Bladeren bron

feat(Text): can set the fontStyle of a label, e.g. Bold (1) or BoldItalic (3). new option defaultFontStyle (#739)

fix #739

instead of setting label.fontStyle every time we create a label, one could give EngravingRules in the label constructor.
this would be a better solution if it turns out we need to set more settings from EngravingRules in Label in the future.
sschmid 5 jaren geleden
bovenliggende
commit
894868b051

+ 9 - 1
src/MusicalScore/Graphical/EngravingRules.ts

@@ -6,7 +6,7 @@ import { PlacementEnum } from "../VoiceData/Expressions/AbstractExpression";
 import { AutoBeamOptions, AlignRestOption, FillEmptyMeasuresWithWholeRests } from "../../OpenSheetMusicDisplay/OSMDOptions";
 import { ColoringModes as ColoringMode } from "./DrawingParameters";
 import { Dictionary } from "typescript-collections";
-import { NoteEnum } from "../..";
+import { NoteEnum, FontStyles } from "../..";
 
 export class EngravingRules {
     /** A unit of distance. 1.0 is the distance between lines of a stave for OSMD, which is 10 pixels in Vexflow. */
@@ -197,6 +197,7 @@ export class EngravingRules {
     private defaultColorLabel: string;
     private defaultColorTitle: string;
     private defaultFontFamily: string;
+    private defaultFontStyle: FontStyles;
     private maxMeasureToDrawIndex: number;
     private minMeasureToDrawIndex: number;
     /** Whether to render a label for the composer of the piece at the top of the sheet. */
@@ -433,6 +434,7 @@ export class EngravingRules {
         this.defaultColorLabel = this.defaultColorNotehead;
         this.defaultColorTitle = this.defaultColorNotehead;
         this.defaultFontFamily = "Times New Roman"; // what OSMD was initially optimized for
+        this.defaultFontStyle = FontStyles.Regular;
         this.maxMeasureToDrawIndex = Number.MAX_VALUE;
         this.minMeasureToDrawIndex = 0;
         this.renderComposer = true;
@@ -1497,6 +1499,12 @@ export class EngravingRules {
     public set DefaultFontFamily(value: string) {
         this.defaultFontFamily = value;
     }
+    public get DefaultFontStyle(): FontStyles {
+        return this.defaultFontStyle;
+    }
+    public set DefaultFontStyle(value: FontStyles) {
+        this.defaultFontStyle = value;
+    }
     public get MaxMeasureToDrawIndex(): number {
         return this.maxMeasureToDrawIndex;
     }

+ 3 - 1
src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts

@@ -28,7 +28,9 @@ 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.rules, this.boundingBox);
+        const label: Label = new Label(text);
+        label.fontStyle = this.rules.DefaultFontStyle;
+        this.graphicalLabel = new GraphicalLabel(label, textHeight, TextAlignmentEnum.CenterBottom, this.rules, this.boundingBox);
         this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0.0, 0.0);
     }
 }

+ 4 - 2
src/MusicalScore/Graphical/GraphicalLyricEntry.ts

@@ -4,7 +4,7 @@ import {GraphicalLabel} from "./GraphicalLabel";
 import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
 import {Label} from "../Label";
 import {PointF2D} from "../../Common/DataObjects/PointF2D";
-import { TextAlignmentEnum } from "../../Common/Enums/TextAlignment";
+import {TextAlignmentEnum} from "../../Common/Enums/TextAlignment";
 
 /**
  * The graphical counterpart of a [[LyricsEntry]]
@@ -26,8 +26,10 @@ export class GraphicalLyricEntry {
             && lyricsTextAlignment === TextAlignmentEnum.LeftBottom) {
             // lyricsTextAlignment = TextAlignmentAndPlacement.CenterBottom;
         }
+        const label: Label = new Label(lyricsEntry.Text);
+        label.fontStyle = this.graphicalStaffEntry.parentMeasure.parentSourceMeasure.Rules.DefaultFontStyle;
         this.graphicalLabel = new GraphicalLabel(
-            new Label(lyricsEntry.Text),
+            label,
             lyricsHeight,
             lyricsTextAlignment,
             this.graphicalStaffEntry.parentMeasure.parentSourceMeasure.Rules,

+ 1 - 1
src/MusicalScore/Graphical/GraphicalVoiceEntry.ts

@@ -4,7 +4,7 @@ import { BoundingBox } from "./BoundingBox";
 import { GraphicalNote } from "./GraphicalNote";
 import { GraphicalStaffEntry } from "./GraphicalStaffEntry";
 import { OctaveEnum } from "../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
-import { EngravingRules } from ".";
+import { EngravingRules } from "./EngravingRules";
 
 /**
  * The graphical counterpart of a [[VoiceEntry]].

+ 16 - 4
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -349,7 +349,10 @@ export abstract class MusicSheetCalculator {
     /// <param name="musicSystem"></param>
     private calculateSingleMeasureNumberPlacement(measure: GraphicalMeasure, staffLine: StaffLine, musicSystem: MusicSystem): void {
         const labelNumber: string = measure.MeasureNumber.toString();
-        const graphicalLabel: GraphicalLabel = new GraphicalLabel(new Label(labelNumber), this.rules.MeasureNumberLabelHeight,
+        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);
 
         const skyBottomLineCalculator: SkyBottomLineCalculator = staffLine.SkyBottomLineCalculator;
@@ -1234,6 +1237,7 @@ export abstract class MusicSheetCalculator {
                              fontHeight: number,
                              textAlignment: TextAlignmentEnum = TextAlignmentEnum.CenterBottom): GraphicalLabel {
         const label: Label = new Label(combinedString, textAlignment);
+        label.fontStyle = this.rules.DefaultFontStyle;
         label.fontHeight = fontHeight;
 
         // TODO_RR: TextHeight from first Entry
@@ -1558,6 +1562,7 @@ 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);
@@ -2449,8 +2454,10 @@ export abstract class MusicSheetCalculator {
      * @param {number} y
      */
     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(
-            new Label("-"), this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
+            label, this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
         dash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(dash);
         if (this.staffLinesWithLyricWords.indexOf(staffLine) === -1) {
@@ -2564,8 +2571,10 @@ export abstract class MusicSheetCalculator {
      * @returns {number}
      */
     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(
-            new Label("-"), this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
+            leftLabel, this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
         leftDash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(leftDash);
         if (this.staffLinesWithLyricWords.indexOf(staffLine) === -1) {
@@ -2574,8 +2583,11 @@ export abstract class MusicSheetCalculator {
         leftDash.PositionAndShape.Parent = staffLine.PositionAndShape;
         const leftDashRelative: PointF2D = new PointF2D(startX, y);
         leftDash.PositionAndShape.RelativePosition = leftDashRelative;
+
+        const rightLabel: Label = new Label("-");
+        rightLabel.fontStyle = this.rules.DefaultFontStyle;
         const rightDash: GraphicalLabel = new GraphicalLabel(
-            new Label("-"), this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
+            rightLabel, this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom, this.rules);
         rightDash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(rightDash);
         rightDash.PositionAndShape.Parent = staffLine.PositionAndShape;

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

@@ -25,6 +25,7 @@ import {MusicSymbolDrawingStyle, PhonicScoreModes} from "./DrawingMode";
 import {GraphicalObject} from "./GraphicalObject";
 import { GraphicalInstantaneousDynamicExpression } from "./GraphicalInstantaneousDynamicExpression";
 import { GraphicalContinuousDynamicExpression } from "./GraphicalContinuousDynamicExpression";
+// import { FontStyles } from "../../Common/Enums/FontStyles";
 
 /**
  * Draw a [[GraphicalMusicSheet]] (through the .drawSheet method)
@@ -520,7 +521,9 @@ export abstract class MusicSheetDrawer {
 
             tmpRect = this.applyScreenTransformationForRect(tmpRect);
             this.renderRectangle(tmpRect, <number>GraphicalLayers.Background, layer, 0.5);
-            this.renderLabel(new GraphicalLabel(new Label(dataObjectString), 0.8, TextAlignmentEnum.CenterCenter, this.rules),
+            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));
         }
         layer++;

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

@@ -296,6 +296,7 @@ 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 {
@@ -309,6 +310,7 @@ 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

+ 20 - 0
src/MusicalScore/Graphical/VexFlow/SvgVexFlowBackend.ts

@@ -87,6 +87,26 @@ export class SvgVexFlowBackend extends VexFlowBackend {
         // 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`;
+        let fontWeightVexflow: string = "normal";
+        let fontStyleVexflow: string = "normal";
+        switch (fontStyle) {
+            case FontStyles.Bold:
+                fontWeightVexflow = "bold";
+                break;
+            case FontStyles.Italic:
+                fontStyleVexflow = "italic";
+                break;
+            case FontStyles.BoldItalic:
+                fontWeightVexflow = "bold";
+                fontStyleVexflow = "italic";
+                break;
+            default:
+                fontWeightVexflow = "normal";
+        }
+        this.ctx.attributes["font-weight"] = fontWeightVexflow;
+        this.ctx.state["font-weight"] = fontWeightVexflow;
+        this.ctx.attributes["font-style"] = fontStyleVexflow;
+        this.ctx.state["font-style"] = fontStyleVexflow;
         this.ctx.fillText(text, screenPosition.x, screenPosition.y + heightInPixel);
         this.ctx.restore();
     }

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

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

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

@@ -11,7 +11,9 @@ export class VexFlowInstantaneousDynamicExpression extends GraphicalInstantaneou
     constructor(instantaneousDynamicExpression: InstantaneousDynamicExpression, staffLine: StaffLine, measure: GraphicalMeasure) {
         super(instantaneousDynamicExpression, staffLine, measure);
 
-        this.label = new GraphicalLabel(new Label(this.Expression),
+        const sourceLabel: Label = new Label(this.Expression);
+        sourceLabel.fontStyle = this.rules.DefaultFontStyle;
+        this.label = new GraphicalLabel(sourceLabel,
                                         this.rules.ContinuousDynamicTextHeight,
                                         TextAlignmentEnum.CenterCenter,
                                         this.rules,

+ 1 - 0
src/MusicalScore/Instrument.ts

@@ -13,6 +13,7 @@ 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;

+ 4 - 1
src/MusicalScore/Label.ts

@@ -9,10 +9,13 @@ import {FontStyles} from "../Common/Enums/FontStyles";
  */
 export class Label {
 
-    constructor(text: string = "", alignment: TextAlignmentEnum = TextAlignmentEnum.CenterBottom, font: Fonts = Fonts.TimesNewRoman) {
+    constructor(text: string = "", alignment: TextAlignmentEnum = TextAlignmentEnum.CenterBottom,
+                font: Fonts = Fonts.TimesNewRoman, fontStyle: FontStyles = FontStyles.Regular) {
         this.text = text;
         this.textAlignment = alignment;
         this.font = font;
+        this.fontStyle = FontStyles.Bold; // debug
+        // maybe give EngravingRules as argument, to set FontStyle and potentially further style settings
     }
 
     public text: string;

+ 11 - 1
src/MusicalScore/ScoreIO/MusicSheetReader.ts

@@ -21,7 +21,7 @@ import {MusicSymbolModuleFactory} from "./MusicSymbolModuleFactory";
 import {IAfterSheetReadingModule} from "../Interfaces/IAfterSheetReadingModule";
 import {RepetitionInstructionReader} from "./MusicSymbolModules/RepetitionInstructionReader";
 import {RepetitionCalculator} from "./MusicSymbolModules/RepetitionCalculator";
-import { EngravingRules } from "../Graphical";
+import {EngravingRules} from "../Graphical";
 
 export class MusicSheetReader /*implements IMusicSheetReader*/ {
 
@@ -510,6 +510,7 @@ 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);
@@ -535,10 +536,12 @@ 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;
                     }
                 }
             }
@@ -597,9 +600,11 @@ 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;
@@ -611,9 +616,11 @@ 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;
         }
     }
 
@@ -674,6 +681,7 @@ 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");
@@ -681,6 +689,7 @@ 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);
             }
@@ -701,6 +710,7 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
         if (finalSubTitle
         ) {
             this.musicSheet.Subtitle = new Label(finalSubTitle);
+            this.musicSheet.Subtitle.fontStyle = this.rules.DefaultFontStyle;
         }
     }
 

+ 3 - 0
src/OpenSheetMusicDisplay/OSMDOptions.ts

@@ -1,4 +1,5 @@
 import { DrawingParametersEnum, ColoringModes } from "../MusicalScore/Graphical/DrawingParameters";
+import { FontStyles } from "../Common/Enums/FontStyles";
 
 /** Possible options for the OpenSheetMusicDisplay constructor and osmd.setOptions(). None are mandatory.
  *  Note that after using setOptions(), you have to call osmd.render() again to make changes visible.
@@ -50,6 +51,8 @@ export interface IOSMDOptions {
      * Valid options are CSS font families available in the browser used for rendering, e.g. Times New Roman, Helvetica.
      */
     defaultFontFamily?: string;
+    /** Default font style, e.g. FontStyles.Bold (1). Default Regular (0). */
+    defaultFontStyle?: FontStyles;
     /** Don't show/load cursor. Will override disableCursor in drawingParameters. */
     disableCursor?: boolean;
     /** Follow Cursor: Scroll the page when cursor.next() is called and the cursor moves into a new system outside of the current view frame. */

+ 4 - 1
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -117,7 +117,7 @@ export class OpenSheetMusicDisplay {
                 // Parse the string representing an xml file
                 const parser: DOMParser = new DOMParser();
                 content = parser.parseFromString(str, "application/xml");
-            } else if (str.length < 2083) {
+            } else if (str.length < 2083) { // TODO do proper URL format check
                 log.debug("[OSMD] Retrieve the file at the given URL: " + str);
                 // Assume now "str" is a URL
                 // Retrieve the file at the given URL
@@ -478,6 +478,9 @@ export class OpenSheetMusicDisplay {
         if (options.defaultFontFamily) {
             this.rules.DefaultFontFamily = options.defaultFontFamily; // default "Times New Roman", also used if font family not found
         }
+        if (options.defaultFontStyle) {
+            this.rules.DefaultFontStyle = options.defaultFontStyle; // e.g. FontStyles.Bold
+        }
         if (options.drawUpToMeasureNumber) {
             this.rules.MaxMeasureToDrawIndex = options.drawUpToMeasureNumber - 1;
         }