Explorar el Código

feat(Font): can set fontFamily per label (#737), refactor: don't set defaultFontStyle per label

refactor: don't set fontStyle to default for every created label manually:
this was really a stupid idea, causing a lot of duplicated/unnecessary code.

now checking for label.fontStyle, and using default value if undefined,
is the centralized method in SvgVexFlowBackend.renderText() and VexFlowConverter.font().
sschmid hace 5 años
padre
commit
a7af16bb49

+ 0 - 2
src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts

@@ -6,7 +6,6 @@ import {BoundingBox} from "./BoundingBox";
 import {GraphicalObject} from "./GraphicalObject";
 import {PointF2D} from "../../Common/DataObjects/PointF2D";
 import {EngravingRules} from "./EngravingRules";
-import {FontStyles} from "../../Common";
 
 export class GraphicalChordSymbolContainer extends GraphicalObject {
     private chordSymbolContainer: ChordSymbolContainer;
@@ -30,7 +29,6 @@ export class GraphicalChordSymbolContainer extends GraphicalObject {
     private calculateLabel(textHeight: number, transposeHalftones: number): void {
         const text: string = ChordSymbolContainer.calculateChordText(this.chordSymbolContainer, transposeHalftones);
         const label: Label = new Label(text);
-        label.fontStyle = this.rules?.DefaultFontStyle ?? FontStyles.Regular; // TODO seems like rules are undefined sometimes
         this.graphicalLabel = new GraphicalLabel(label, textHeight, TextAlignmentEnum.CenterBottom, this.rules, this.boundingBox);
         this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0.0, 0.0);
     }

+ 2 - 1
src/MusicalScore/Graphical/GraphicalLabel.ts

@@ -47,7 +47,8 @@ export class GraphicalLabel extends Clickable {
         const labelMarginBorderFactor: number = this.rules?.LabelMarginBorderFactor ?? 0.1;
 
         const widthToHeightRatio: number =
-            MusicSheetCalculator.TextMeasurer.computeTextWidthToHeightRatio(this.Label.text, this.Label.font, this.Label.fontStyle);
+            MusicSheetCalculator.TextMeasurer.computeTextWidthToHeightRatio(
+                this.Label.text, this.Label.font, this.Label.fontStyle, this.label.fontFamily);
         const height: number = this.Label.fontHeight;
         const width: number = height * widthToHeightRatio;
         const bbox: BoundingBox = this.PositionAndShape;

+ 0 - 1
src/MusicalScore/Graphical/GraphicalLyricEntry.ts

@@ -27,7 +27,6 @@ export class GraphicalLyricEntry {
             // lyricsTextAlignment = TextAlignmentAndPlacement.CenterBottom;
         }
         const label: Label = new Label(lyricsEntry.Text);
-        label.fontStyle = this.graphicalStaffEntry.parentMeasure.parentSourceMeasure.Rules.DefaultFontStyle;
         this.graphicalLabel = new GraphicalLabel(
             label,
             lyricsHeight,

+ 1 - 7
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -350,7 +350,6 @@ export abstract class MusicSheetCalculator {
     private calculateSingleMeasureNumberPlacement(measure: GraphicalMeasure, staffLine: StaffLine, musicSystem: MusicSystem): void {
         const labelNumber: string = measure.MeasureNumber.toString();
         const label: Label = new Label(labelNumber);
-        label.fontStyle = this.rules.DefaultFontStyle;
         // maybe give rules as argument instead of just setting fontStyle and maybe other settings manually afterwards
         const graphicalLabel: GraphicalLabel = new GraphicalLabel(label, this.rules.MeasureNumberLabelHeight,
                                                                   TextAlignmentEnum.LeftBottom, this.rules);
@@ -1237,12 +1236,11 @@ export abstract class MusicSheetCalculator {
                              fontHeight: number,
                              textAlignment: TextAlignmentEnum = TextAlignmentEnum.CenterBottom): GraphicalLabel {
         const label: Label = new Label(combinedString, textAlignment);
-        label.fontStyle = this.rules.DefaultFontStyle;
+        label.fontStyle = style;
         label.fontHeight = fontHeight;
 
         // TODO_RR: TextHeight from first Entry
         const graphLabel: GraphicalLabel = new GraphicalLabel(label, fontHeight, label.textAlignment, this.rules, staffLine.PositionAndShape);
-        graphLabel.Label.fontStyle = style;
         const marginFactor: number = 1.1;
 
         if (placement === PlacementEnum.Below) {
@@ -1562,7 +1560,6 @@ export abstract class MusicSheetCalculator {
                 let renderedLabel: Label = instrument.NameLabel;
                 if (!this.rules.RenderPartNames) {
                     renderedLabel = new Label("", renderedLabel.textAlignment, renderedLabel.font);
-                    renderedLabel.fontStyle = this.rules.DefaultFontStyle;
                 }
                 const graphicalLabel: GraphicalLabel = new GraphicalLabel(
                     renderedLabel, this.rules.InstrumentLabelTextHeight, TextAlignmentEnum.LeftCenter, this.rules);
@@ -2455,7 +2452,6 @@ export abstract class MusicSheetCalculator {
      */
     private calculateSingleDashForLyricWord(staffLine: StaffLine, startX: number, endX: number, y: number): void {
         const label: Label = new Label("-");
-        label.fontStyle = this.rules.DefaultFontStyle;
         const dash: GraphicalLabel = new GraphicalLabel(
             label, this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
         dash.setLabelPositionAndShapeBorders();
@@ -2572,7 +2568,6 @@ export abstract class MusicSheetCalculator {
      */
     private calculateRightAndLeftDashesForLyricWord(staffLine: StaffLine, startX: number, endX: number, y: number): number {
         const leftLabel: Label = new Label("-");
-        leftLabel.fontStyle = this.rules.DefaultFontStyle;
         const leftDash: GraphicalLabel = new GraphicalLabel(
             leftLabel, this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
         leftDash.setLabelPositionAndShapeBorders();
@@ -2585,7 +2580,6 @@ export abstract class MusicSheetCalculator {
         leftDash.PositionAndShape.RelativePosition = leftDashRelative;
 
         const rightLabel: Label = new Label("-");
-        rightLabel.fontStyle = this.rules.DefaultFontStyle;
         const rightDash: GraphicalLabel = new GraphicalLabel(
             rightLabel, this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
         rightDash.setLabelPositionAndShapeBorders();

+ 0 - 1
src/MusicalScore/Graphical/MusicSheetDrawer.ts

@@ -522,7 +522,6 @@ export abstract class MusicSheetDrawer {
             tmpRect = this.applyScreenTransformationForRect(tmpRect);
             this.renderRectangle(tmpRect, <number>GraphicalLayers.Background, layer, 0.5);
             const label: Label = new Label(dataObjectString);
-            label.fontStyle = this.rules.DefaultFontStyle;
             this.renderLabel(new GraphicalLabel(label, 0.8, TextAlignmentEnum.CenterCenter, this.rules),
                              layer, tmpRect.width, tmpRect.height, tmpRect.height, new PointF2D(tmpRect.x, tmpRect.y + 12));
         }

+ 0 - 2
src/MusicalScore/Graphical/MusicSystem.ts

@@ -296,7 +296,6 @@ export abstract class MusicSystem extends GraphicalObject {
                 instrNameLabel = instrument.NameLabel;
                 if (!this.rules.RenderPartNames) {
                     instrNameLabel = new Label("", instrument.NameLabel.textAlignment, instrument.NameLabel.font);
-                    instrNameLabel.fontStyle = this.rules.DefaultFontStyle;
                     systemLabelsRightMargin = 0; // might affect lyricist/tempo placement. but without this there's still some extra x-spacing.
                 }
             } else {
@@ -310,7 +309,6 @@ export abstract class MusicSystem extends GraphicalObject {
                 const labelText: string = instrument.PartAbbreviation;
                 // const labelText: string = instrument.NameLabel.text[0] + ".";
                 instrNameLabel = new Label(labelText, instrument.NameLabel.textAlignment, instrument.NameLabel.font);
-                instrNameLabel.fontStyle = this.rules.DefaultFontStyle;
             }
             const graphicalLabel: GraphicalLabel = new GraphicalLabel(
                 instrNameLabel, instrumentLabelTextHeight, TextAlignmentEnum.LeftCenter, this.rules, this.boundingBox

+ 4 - 2
src/MusicalScore/Graphical/VexFlow/CanvasVexFlowBackend.ts

@@ -83,14 +83,16 @@ export class CanvasVexFlowBackend extends VexFlowBackend {
         this.CanvasRenderingCtx.translate(x, y);
     }
     public renderText(fontHeight: number, fontStyle: FontStyles, font: Fonts, text: string,
-                      heightInPixel: number, screenPosition: PointF2D, color: string = undefined): void  {
+                      heightInPixel: number, screenPosition: PointF2D,
+                      color: string = undefined, fontFamily: string = undefined): void  {
         const old: string = this.CanvasRenderingCtx.font;
         this.CanvasRenderingCtx.save();
         this.CanvasRenderingCtx.font = VexFlowConverter.font(
             fontHeight,
             fontStyle,
             font,
-            this.rules
+            this.rules,
+            fontFamily
         );
         this.CanvasRenderingCtx.fillStyle = color;
         this.CanvasRenderingCtx.strokeStyle = color;

+ 7 - 2
src/MusicalScore/Graphical/VexFlow/SvgVexFlowBackend.ts

@@ -76,14 +76,19 @@ export class SvgVexFlowBackend extends VexFlowBackend {
         // TODO: implement this
     }
     public renderText(fontHeight: number, fontStyle: FontStyles, font: Fonts, text: string,
-                      heightInPixel: number, screenPosition: PointF2D, color: string = undefined): void {
+                      heightInPixel: number, screenPosition: PointF2D,
+                      color: string = undefined, fontFamily: string = undefined): void {
         this.ctx.save();
 
         if (color) {
             this.ctx.attributes.fill = color;
             this.ctx.attributes.stroke = color;
         }
-        this.ctx.setFont(this.rules.DefaultFontFamily, fontHeight, VexFlowConverter.fontStyle(fontStyle));
+        let fontFamilyVexFlow: string = fontFamily;
+        if (!fontFamily || fontFamily === "default") {
+            fontFamilyVexFlow = this.rules.DefaultFontFamily;
+        }
+        this.ctx.setFont(fontFamilyVexFlow, fontHeight, VexFlowConverter.fontStyle(fontStyle));
         // font size is set by VexFlow in `pt`. This overwrites the font so it's set to px instead
         this.ctx.attributes["font-size"] = `${fontHeight}px`;
         this.ctx.state["font-size"] = `${fontHeight}px`;

+ 2 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowBackend.ts

@@ -82,7 +82,8 @@ public abstract getContext(): Vex.IRenderContext;
 
   public abstract translate(x: number, y: number): void;
   public abstract renderText(fontHeight: number, fontStyle: FontStyles, font: Fonts, text: string,
-                             heightInPixel: number, screenPosition: PointF2D, color?: string): void;
+                             heightInPixel: number, screenPosition: PointF2D,
+                             color?: string, fontFamily?: string): void;
   /**
    * Renders a rectangle with the given style to the screen.
    * It is given in screen coordinates.

+ 0 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowContinuousDynamicExpression.ts

@@ -14,7 +14,6 @@ export class VexFlowContinuousDynamicExpression extends GraphicalContinuousDynam
         super(continuousDynamic, staffLine);
         if (this.IsVerbal) {
             const sourceLabel: Label = new Label(continuousDynamic.Label);
-            sourceLabel.fontStyle = this.rules.DefaultFontStyle;
             this.label = new GraphicalLabel(sourceLabel,
                                             textHeight ? textHeight : this.rules.ContinuousDynamicTextHeight,
                                             TextAlignmentEnum.LeftCenter,

+ 6 - 3
src/MusicalScore/Graphical/VexFlow/VexFlowConverter.ts

@@ -707,10 +707,10 @@ export class VexFlowConverter {
      * @returns {string}
      */
     public static font(fontSize: number, fontStyle: FontStyles = FontStyles.Regular,
-                       font: Fonts = Fonts.TimesNewRoman, rules: EngravingRules): string {
+                       font: Fonts = Fonts.TimesNewRoman, rules: EngravingRules, fontFamily: string = undefined): string {
         let style: string = "normal";
         let weight: string = "normal";
-        const family: string = "'" + rules.DefaultFontFamily + "'"; // default "'Times New Roman'"
+        let family: string = `'${rules.DefaultFontFamily}'`; // default "'Times New Roman'"
 
         switch (fontStyle) {
             case FontStyles.Bold:
@@ -737,8 +737,11 @@ export class VexFlowConverter {
             default:
         }
 
+        if (fontFamily && fontFamily !== "default") {
+            family = `'${fontFamily}'`;
+        }
 
-        return  style + " " + weight + " " + Math.floor(fontSize) + "px " + family;
+        return style + " " + weight + " " + Math.floor(fontSize) + "px " + family;
     }
 
     /**

+ 0 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowInstantaneousDynamicExpression.ts

@@ -12,7 +12,6 @@ export class VexFlowInstantaneousDynamicExpression extends GraphicalInstantaneou
         super(instantaneousDynamicExpression, staffLine, measure);
 
         const sourceLabel: Label = new Label(this.Expression);
-        sourceLabel.fontStyle = this.rules.DefaultFontStyle;
         this.label = new GraphicalLabel(sourceLabel,
                                         this.rules.ContinuousDynamicTextHeight,
                                         TextAlignmentEnum.CenterCenter,

+ 10 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -398,7 +398,7 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
     protected renderLabel(graphicalLabel: GraphicalLabel, layer: number, bitmapWidth: number,
                           bitmapHeight: number, heightInPixel: number, screenPosition: PointF2D): void {
         const height: number = graphicalLabel.Label.fontHeight * unitInPixels;
-        const { fontStyle, font, text } = graphicalLabel.Label;
+        const { font, text } = graphicalLabel.Label;
         let color: string;
         if (this.rules.ColoringEnabled) {
             color = graphicalLabel.Label.colorDefault;
@@ -406,7 +406,15 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
                 color = this.rules.DefaultColorLabel;
             }
         }
-        this.backend.renderText(height, fontStyle, font, text, heightInPixel, screenPosition, color);
+        let { fontStyle, fontFamily } = graphicalLabel.Label;
+        if (!fontStyle) {
+            fontStyle = this.rules.DefaultFontStyle;
+        }
+        if (!fontFamily) {
+            fontFamily = this.rules.DefaultFontFamily;
+        }
+        this.backend.renderText(height, fontStyle, font, text, heightInPixel, screenPosition, color, graphicalLabel.Label.fontFamily);
+        // font currently unused, replaced by fontFamily
     }
 
     /**

+ 4 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowTextMeasurer.ts

@@ -26,8 +26,10 @@ export class VexFlowTextMeasurer implements ITextMeasurer {
      * @param style
      * @returns {number}
      */
-    public computeTextWidthToHeightRatio(text: string, font: Fonts, style: FontStyles, fontSize: number = this.fontSize): number {
-        this.context.font = VexFlowConverter.font(fontSize, style, font, this.rules);
+    public computeTextWidthToHeightRatio(text: string, font: Fonts, style: FontStyles,
+                                         fontFamily: string = undefined,
+                                         fontSize: number = this.fontSize): number {
+        this.context.font = VexFlowConverter.font(fontSize, style, font, this.rules, fontFamily);
         return this.context.measureText(text).width / fontSize;
     }
 

+ 0 - 1
src/MusicalScore/Instrument.ts

@@ -13,7 +13,6 @@ export class Instrument extends InstrumentalGroup {
         this.id = id;
         this.idString = idString;
         this.nameLabel = new Label(idString);
-        this.nameLabel.fontStyle = musicSheet.Rules.DefaultFontStyle;
     }
 
     public transpose: number = 0;

+ 2 - 1
src/MusicalScore/Interfaces/ITextMeasurer.ts

@@ -4,6 +4,7 @@ import {FontStyles} from "../../Common/Enums/FontStyles";
 export interface ITextMeasurer {
     fontSize: number;
     fontSizeStandard: number;
-    computeTextWidthToHeightRatio(text: string, font: Fonts, style: FontStyles): number;
+    computeTextWidthToHeightRatio(text: string, font: Fonts, style: FontStyles,
+                                  fontFamily?: string, fontSize?: number): number;
     setFontSize(fontSize: number): number;
 }

+ 3 - 2
src/MusicalScore/Label.ts

@@ -10,10 +10,11 @@ import {FontStyles} from "../Common/Enums/FontStyles";
 export class Label {
 
     constructor(text: string = "", alignment: TextAlignmentEnum = TextAlignmentEnum.CenterBottom,
-                font: Fonts = Fonts.TimesNewRoman, fontStyle: FontStyles = FontStyles.Regular) {
+                font: Fonts = undefined) {
         this.text = text;
         this.textAlignment = alignment;
         this.font = font;
+        this.fontFamily = undefined; // default value, will use EngravingRules.DefaultFontFamily at rendering
         // maybe give EngravingRules as argument, to set FontStyle and potentially further style settings
     }
 
@@ -21,6 +22,7 @@ export class Label {
     public color: OSMDColor;
     public colorDefault: string; // TODO this is Vexflow format, convert to OSMDColor. for now convenient for default colors.
     public font: Fonts;
+    public fontFamily: string; // default undefined: will use EngravingRules.DefaultFontFamily at rendering
     public fontStyle: FontStyles;
     public fontHeight: number;
     public textAlignment: TextAlignmentEnum;
@@ -28,5 +30,4 @@ export class Label {
     public ToString(): string {
         return this.text;
     }
-
 }

+ 0 - 10
src/MusicalScore/ScoreIO/MusicSheetReader.ts

@@ -510,7 +510,6 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
                 const filename: string = filePath.substr(barI);
                 const filenameSplits: string[] = filename.split(".", 1);
                 this.musicSheet.Title = new Label(filenameSplits[0]);
-                this.musicSheet.Title.fontStyle = this.rules.DefaultFontStyle;
             }
         } catch (ex) {
             log.info("MusicSheetReader.pushSheetLabels", "read title from file name", ex);
@@ -536,12 +535,10 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
                 if (creator.hasAttributes) {
                     if (this.presentAttrsWithValue(creator, "composer")) {
                         this.musicSheet.Composer = new Label(this.trimString(creator.value));
-                        this.musicSheet.Composer.fontStyle = this.rules.DefaultFontStyle;
                         continue;
                     }
                     if (this.presentAttrsWithValue(creator, "lyricist") || this.presentAttrsWithValue(creator, "poet")) {
                         this.musicSheet.Lyricist = new Label(this.trimString(creator.value));
-                        this.musicSheet.Lyricist.fontStyle = this.rules.DefaultFontStyle;
                     }
                 }
             }
@@ -600,11 +597,9 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
                             switch (creditJustify) {
                                 case "right":
                                     this.musicSheet.Composer = new Label(this.trimString(creditChild.value));
-                                    this.musicSheet.Composer.fontStyle = this.rules.DefaultFontStyle;
                                     break;
                                 case "left":
                                     this.musicSheet.Lyricist = new Label(this.trimString(creditChild.value));
-                                    this.musicSheet.Lyricist.fontStyle = this.rules.DefaultFontStyle;
                                     break;
                                 default:
                                     break;
@@ -616,11 +611,9 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
         }
         if (this.musicSheet.Title === undefined && finalTitle) {
             this.musicSheet.Title = new Label(this.trimString(finalTitle));
-            this.musicSheet.Title.fontStyle = this.rules.DefaultFontStyle;
         }
         if (this.musicSheet.Subtitle === undefined && finalSubtitle) {
             this.musicSheet.Subtitle = new Label(this.trimString(finalSubtitle));
-            this.musicSheet.Subtitle.fontStyle = this.rules.DefaultFontStyle;
         }
     }
 
@@ -681,7 +674,6 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
             titleNodeChild = titleNode.element("work-title");
             if (titleNodeChild !== undefined && titleNodeChild.value) {
                 this.musicSheet.Title = new Label(this.trimString(titleNodeChild.value));
-                this.musicSheet.Title.fontStyle = this.rules.DefaultFontStyle;
             }
         }
         const movementNode: IXmlElement = root.element("movement-title");
@@ -689,7 +681,6 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
         if (movementNode !== undefined) {
             if (this.musicSheet.Title === undefined) {
                 this.musicSheet.Title = new Label(this.trimString(movementNode.value));
-                this.musicSheet.Title.fontStyle = this.rules.DefaultFontStyle;
             } else {
                 finalSubTitle = this.trimString(movementNode.value);
             }
@@ -710,7 +701,6 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
         if (finalSubTitle
         ) {
             this.musicSheet.Subtitle = new Label(finalSubTitle);
-            this.musicSheet.Subtitle.fontStyle = this.rules.DefaultFontStyle;
         }
     }