Skip to content

Commit

Permalink
feat(options): instances of osmd don't share static options/Engraving…
Browse files Browse the repository at this point in the history
…Rules anymore

Merge pull request #721 from opensheetmusicdisplay/dnlfrst-fix/entangled-engraving-rules

make EngravingRules nonstatic, allowing multiple instances of osmd
on the same page in the browser to have their own options.
previously, a static EngravingRules instance meant changing options
for one osmd object changed it for another on the same page as well.

fix #559, close #647 

initial work done by @dnlfirst in #647
  • Loading branch information
sschmidTU authored Apr 15, 2020
2 parents 52e4ada + c1d7979 commit fc095ad
Show file tree
Hide file tree
Showing 42 changed files with 414 additions and 272 deletions.
3 changes: 2 additions & 1 deletion src/MusicalScore/Graphical/AbstractGraphicalExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ export abstract class AbstractGraphicalExpression extends GraphicalObject {
/** Internal cache of read expression */
protected expression: AbstractExpression;
/** EngravingRules for positioning */
protected rules: EngravingRules = EngravingRules.Rules;
protected rules: EngravingRules;

constructor(parentStaffline: StaffLine, expression: AbstractExpression) {
super();
this.expression = expression;
this.boundingBox = new BoundingBox(this, parentStaffline.PositionAndShape);
this.parentStaffLine = parentStaffline;
this.parentStaffLine.AbstractExpressions.push(this);
this.rules = parentStaffline.ParentMusicSystem.rules;
}

/** Graphical label of the expression if available */
Expand Down
2 changes: 1 addition & 1 deletion src/MusicalScore/Graphical/BoundingBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export class BoundingBox {
for (let idx: number = 0, len: number = this.ChildElements.length; idx < len; ++idx) {
const childElement: BoundingBox = this.ChildElements[idx];
minTop = Math.min(minTop, childElement.relativePosition.y + childElement.borderTop);
if (!EngravingRules.Rules.FixStafflineBoundingBox || !(childElement.dataObject instanceof StaffLineActivitySymbol)) {
if (!EngravingRules.FixStafflineBoundingBox || !(childElement.dataObject instanceof StaffLineActivitySymbol)) {
maxBottom = Math.max(maxBottom, childElement.relativePosition.y + childElement.borderBottom);
// TODO there's a problem with the bottom bounding box of many stafflines, often caused by StaffLineActivitySymbol,
// often leading to the page SVG canvas being unnecessarily long in y-direction. This seems to be remedied by this workaround.
Expand Down
25 changes: 17 additions & 8 deletions src/MusicalScore/Graphical/DrawingParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export enum DrawingParametersEnum {
export class DrawingParameters {
/** will set other settings if changed with set method */
private drawingParametersEnum: DrawingParametersEnum;
private rules: EngravingRules = new EngravingRules();
public drawHighlights: boolean;
public drawErrors: boolean;
public drawSelectionStartSymbol: boolean;
Expand Down Expand Up @@ -87,7 +88,7 @@ export class DrawingParameters {
this.drawCredits = true;
this.DrawPartNames = true;
this.drawHiddenNotes = true;
EngravingRules.Rules.CompactMode = false;
this.rules.CompactMode = false;
}

public setForDefault(): void {
Expand All @@ -110,7 +111,7 @@ export class DrawingParameters {

public setForCompactMode(): void {
this.setForDefault();
EngravingRules.Rules.CompactMode = true;
this.rules.CompactMode = true;
this.DrawCredits = false; // sets DrawComposer, DrawTitle, DrawLyricist to false
// this.DrawPartNames = true; // unnecessary
this.drawHiddenNotes = false;
Expand Down Expand Up @@ -152,7 +153,7 @@ export class DrawingParameters {
/** Enable or disable drawing the Title of the piece. If disabled, will disable drawing Subtitle as well. */
public set DrawTitle(value: boolean) {
this.drawTitle = value;
EngravingRules.Rules.RenderTitle = value;
this.rules.RenderTitle = value;
if (!value) { // don't draw subtitle if title isn't drawn
this.DrawSubtitle = false;
}
Expand All @@ -165,7 +166,7 @@ export class DrawingParameters {
/** Enable or disable drawing the Subtitle of the piece. If enabled, will enable drawing Title as well. */
public set DrawSubtitle(value: boolean) {
this.drawSubtitle = value;
EngravingRules.Rules.RenderSubtitle = value;
this.rules.RenderSubtitle = value;
if (value) {
this.DrawTitle = true; // if subtitle is drawn, title needs to be drawn as well
}
Expand All @@ -178,7 +179,7 @@ export class DrawingParameters {
/** Enable or disable drawing a label for the Composer of the piece. */
public set DrawComposer(value: boolean) {
this.drawComposer = value;
EngravingRules.Rules.RenderComposer = value;
this.rules.RenderComposer = value;
}

public get DrawLyricist(): boolean {
Expand All @@ -187,7 +188,7 @@ export class DrawingParameters {

public set DrawLyricist(value: boolean) {
this.drawLyricist = value;
EngravingRules.Rules.RenderLyricist = value;
this.rules.RenderLyricist = value;
}

public get DrawPartNames(): boolean {
Expand All @@ -196,7 +197,7 @@ export class DrawingParameters {

public set DrawPartNames(value: boolean) {
this.drawPartNames = value;
EngravingRules.Rules.RenderPartNames = value;
this.rules.RenderPartNames = value;
}

public get FingeringPosition(): PlacementEnum {
Expand All @@ -205,6 +206,14 @@ export class DrawingParameters {

public set FingeringPosition(value: PlacementEnum) {
this.fingeringPosition = value;
EngravingRules.Rules.FingeringPosition = value;
this.rules.FingeringPosition = value;
}

public get Rules(): EngravingRules {
return this.rules;
}

public set Rules(value: EngravingRules) {
this.rules = value;
}
}
20 changes: 8 additions & 12 deletions src/MusicalScore/Graphical/EngravingRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { Dictionary } from "typescript-collections";
import { NoteEnum } from "../..";

export class EngravingRules {
private static rules: EngravingRules;
/** A unit of distance. 1.0 is the distance between lines of a stave for OSMD, which is 10 pixels in Vexflow. */
private static unit: number = 1.0;
private samplingUnit: number;
Expand Down Expand Up @@ -218,7 +217,7 @@ export class EngravingRules {
private pageBackgroundColor: string; // vexflow-color-string (#FFFFFF). Default undefined/transparent.
private renderSingleHorizontalStaffline: boolean;

private fixStafflineBoundingBox: boolean; // TODO temporary workaround
private static fixStafflineBoundingBox: boolean; // TODO temporary workaround

constructor() {
// global variables
Expand Down Expand Up @@ -443,7 +442,7 @@ export class EngravingRules {
this.fingeringPosition = PlacementEnum.Left; // easier to get bounding box, and safer for vertical layout
this.fingeringInsideStafflines = false;

this.fixStafflineBoundingBox = false; // TODO temporary workaround
EngravingRules.FixStafflineBoundingBox = false; // TODO temporary workaround

this.pageFormat = PageFormat.UndefinedPageFormat; // default: undefined / 'infinite' height page, using the canvas'/container's width and height
this.pageBackgroundColor = undefined; // default: transparent. half-transparent white: #FFFFFF88"
Expand All @@ -460,10 +459,14 @@ export class EngravingRules {
} catch (ex) {
log.info("EngravingRules()", ex);
}
}

// these two need to be static so that we can avoid passing EngravingRules to BoundingBox in lots of code
public static get FixStafflineBoundingBox(): boolean {
return EngravingRules.fixStafflineBoundingBox;
}
public static get Rules(): EngravingRules {
return EngravingRules.rules !== undefined ? EngravingRules.rules : (EngravingRules.rules = new EngravingRules());
public static set FixStafflineBoundingBox(value: boolean) {
EngravingRules.fixStafflineBoundingBox = value;
}
public get SamplingUnit(): number {
return this.samplingUnit;
Expand Down Expand Up @@ -1558,13 +1561,6 @@ export class EngravingRules {
public set FingeringInsideStafflines(value: boolean) {
this.fingeringInsideStafflines = value;
}
public set FixStafflineBoundingBox(value: boolean) { // TODO temporary workaround
this.fixStafflineBoundingBox = value;
}
public get FixStafflineBoundingBox(): boolean {
return this.fixStafflineBoundingBox;
}

public get PageFormat(): PageFormat {
return this.pageFormat;
}
Expand Down
9 changes: 7 additions & 2 deletions src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@ import {ChordSymbolContainer} from "../VoiceData/ChordSymbolContainer";
import {BoundingBox} from "./BoundingBox";
import {GraphicalObject} from "./GraphicalObject";
import {PointF2D} from "../../Common/DataObjects/PointF2D";
import {EngravingRules} from "./EngravingRules";

export class GraphicalChordSymbolContainer extends GraphicalObject {
private chordSymbolContainer: ChordSymbolContainer;
private graphicalLabel: GraphicalLabel;
constructor(chordSymbolContainer: ChordSymbolContainer, parent: BoundingBox, textHeight: number, transposeHalftones: number) {
private rules: EngravingRules;

constructor(chordSymbolContainer: ChordSymbolContainer, parent: BoundingBox, textHeight: number,
transposeHalftones: number, rules: EngravingRules) {
super();
this.chordSymbolContainer = chordSymbolContainer;
this.boundingBox = new BoundingBox(this, parent);
this.calculateLabel(textHeight, transposeHalftones);
this.rules = rules;
}
public get GetChordSymbolContainer(): ChordSymbolContainer {
return this.chordSymbolContainer;
Expand All @@ -23,7 +28,7 @@ export class GraphicalChordSymbolContainer extends GraphicalObject {
}
private calculateLabel(textHeight: number, transposeHalftones: number): void {
const text: string = ChordSymbolContainer.calculateChordText(this.chordSymbolContainer, transposeHalftones);
this.graphicalLabel = new GraphicalLabel(new Label(text), textHeight, TextAlignmentEnum.CenterBottom, this.boundingBox);
this.graphicalLabel = new GraphicalLabel(new Label(text), textHeight, TextAlignmentEnum.CenterBottom, this.rules, this.boundingBox);
this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0.0, 0.0);
}
}
7 changes: 5 additions & 2 deletions src/MusicalScore/Graphical/GraphicalLabel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { MusicSheetCalculator } from "./MusicSheetCalculator";
*/
export class GraphicalLabel extends Clickable {
private label: Label;
private rules: EngravingRules;

/**
* Creates a new GraphicalLabel from a Label
Expand All @@ -18,12 +19,14 @@ export class GraphicalLabel extends Clickable {
* @param alignment Alignement like left, right, top, ...
* @param parent Parent Bounding Box where the label is attached to
*/
constructor(label: Label, textHeight: number, alignment: TextAlignmentEnum, parent: BoundingBox = undefined) {
constructor(label: Label, textHeight: number, alignment: TextAlignmentEnum, rules: EngravingRules,
parent: BoundingBox = undefined, ) {
super();
this.label = label;
this.boundingBox = new BoundingBox(this, parent);
this.label.fontHeight = textHeight;
this.label.textAlignment = alignment;
this.rules = rules;
}

public get Label(): Label {
Expand All @@ -41,7 +44,7 @@ export class GraphicalLabel extends Clickable {
if (this.Label.text.trim() === "") {
return;
}
const labelMarginBorderFactor: number = EngravingRules.Rules.LabelMarginBorderFactor;
const labelMarginBorderFactor: number = this.rules?.LabelMarginBorderFactor ?? 0.1;

const widthToHeightRatio: number =
MusicSheetCalculator.TextMeasurer.computeTextWidthToHeightRatio(this.Label.text, this.Label.font, this.Label.fontStyle);
Expand Down
6 changes: 3 additions & 3 deletions src/MusicalScore/Graphical/GraphicalLyricEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {GraphicalLabel} from "./GraphicalLabel";
import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
import {Label} from "../Label";
import {PointF2D} from "../../Common/DataObjects/PointF2D";
import { EngravingRules } from "./EngravingRules";
import { TextAlignmentEnum } from "../../Common/Enums/TextAlignment";

/**
Expand All @@ -19,7 +18,7 @@ export class GraphicalLyricEntry {
constructor(lyricsEntry: LyricsEntry, graphicalStaffEntry: GraphicalStaffEntry, lyricsHeight: number, staffHeight: number) {
this.lyricsEntry = lyricsEntry;
this.graphicalStaffEntry = graphicalStaffEntry;
const lyricsTextAlignment: TextAlignmentEnum = EngravingRules.Rules.LyricsAlignmentStandard;
const lyricsTextAlignment: TextAlignmentEnum = graphicalStaffEntry.parentMeasure.parentSourceMeasure.Rules.LyricsAlignmentStandard;
// for small notes with long text, use center alignment
// TODO use this, fix center+left alignment combination spacing
if (lyricsEntry.Text.length >= 4
Expand All @@ -31,7 +30,8 @@ export class GraphicalLyricEntry {
new Label(lyricsEntry.Text),
lyricsHeight,
lyricsTextAlignment,
graphicalStaffEntry.PositionAndShape
this.graphicalStaffEntry.parentMeasure.parentSourceMeasure.Rules,
graphicalStaffEntry.PositionAndShape,
);
this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0, staffHeight);
if (lyricsTextAlignment === TextAlignmentEnum.LeftBottom) {
Expand Down
5 changes: 2 additions & 3 deletions src/MusicalScore/Graphical/GraphicalMusicSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {CollectionUtil} from "../../Util/CollectionUtil";
import {SelectionStartSymbol} from "./SelectionStartSymbol";
import {SelectionEndSymbol} from "./SelectionEndSymbol";
import {OutlineAndFillStyleEnum} from "./DrawingEnums";
import {EngravingRules} from "./EngravingRules";

/**
* The graphical counterpart of a [[MusicSheet]]
Expand Down Expand Up @@ -165,7 +164,7 @@ export class GraphicalMusicSheet {
*/
public static transformRelativeToAbsolutePosition(graphicalMusicSheet: GraphicalMusicSheet): void {
for (let i: number = 0; i < graphicalMusicSheet.MusicPages.length; i++) {
const pageAbsolute: PointF2D = graphicalMusicSheet.MusicPages[i].setMusicPageAbsolutePosition(i, graphicalMusicSheet.ParentMusicSheet.rules);
const pageAbsolute: PointF2D = graphicalMusicSheet.MusicPages[i].setMusicPageAbsolutePosition(i, graphicalMusicSheet.ParentMusicSheet.Rules);
const page: GraphicalMusicPage = graphicalMusicSheet.MusicPages[i];
page.PositionAndShape.calculateAbsolutePositionsRecursive(pageAbsolute.x, pageAbsolute.y);
}
Expand Down Expand Up @@ -463,7 +462,7 @@ export class GraphicalMusicSheet {
public getLastGraphicalMeasureFromIndex(staffIndex: number, lastRendered: boolean = true): GraphicalMeasure {
let measureIndex: number = this.measureList.length - 1;
if (lastRendered) {
measureIndex = EngravingRules.Rules.MaxMeasureToDrawIndex;
measureIndex = this.musicSheet.Rules.MaxMeasureToDrawIndex;
}
return this.measureList[measureIndex][staffIndex];
}
Expand Down
4 changes: 4 additions & 0 deletions src/MusicalScore/Graphical/GraphicalVoiceEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BoundingBox } from "./BoundingBox";
import { GraphicalNote } from "./GraphicalNote";
import { GraphicalStaffEntry } from "./GraphicalStaffEntry";
import { OctaveEnum } from "../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
import { EngravingRules } from ".";

/**
* The graphical counterpart of a [[VoiceEntry]].
Expand All @@ -15,13 +16,16 @@ export class GraphicalVoiceEntry extends GraphicalObject {
this.parentStaffEntry = parentStaffEntry;
this.PositionAndShape = new BoundingBox(this, parentStaffEntry ? parentStaffEntry.PositionAndShape : undefined, true);
this.notes = [];
this.rules = parentStaffEntry ?
parentStaffEntry.parentMeasure.parentSourceMeasure.Rules : new EngravingRules();
}

public parentVoiceEntry: VoiceEntry;
public parentStaffEntry: GraphicalStaffEntry;
public notes: GraphicalNote[];
/** Contains octave shifts affecting this voice entry, caused by octave brackets. */
public octaveShiftValue: OctaveEnum;
protected rules: EngravingRules;

/** Sort this entry's notes by pitch.
* Notes need to be sorted for Vexflow StaveNote creation.
Expand Down
Loading

0 comments on commit fc095ad

Please sign in to comment.