Browse Source

vexflow 3.x: set softmax factor (note spacing), default font (gonville instead of bravura)

currently vexflow is still not updated to 3.0.9 though because the formatter still has issues.
(layout is cramped and/or overflowing the measure)

further input for the vexflow version comparisons in #706
sschmid 5 years ago
parent
commit
3797652182

+ 2 - 2
package.json

@@ -27,10 +27,10 @@
     "generatePNG:paged:single": "node ./test/Util/generateImages_browserless.js ../../build ./test/data ./export 0 0 ^Beethoven",
     "generate:current": "node ./test/Util/generateImages_browserless.js ../../build ./test/data ./visual_regression/current 0 0 allSmall --osmdtesting",
     "generate:current:debug": "node ./test/Util/generateImages_browserless.js ../../build ./test/data ./visual_regression/current 0 0 allSmall --debugosmdtesting",
-    "generate:current:singletest": "node test/Util/generateImages_browserless.js ../../build ./test/data ./visual_regression/current 0 0 .*function_test_all.* --osmdtesting",
+    "generate:current:singletest": "node test/Util/generateImages_browserless.js ../../build ./test/data ./visual_regression/current 0 0 ^Beethoven --osmdtesting",
     "generate:blessed": "node ./test/Util/generateImages_browserless.js ../../build ./test/data ./visual_regression/blessed 0 0 allSmall --osmdtesting",
     "test:visual": "sh ./test/Util/visual_regression.sh ./visual_regression",
-    "test:visual:singletest": "sh ./test/Util/visual_regression.sh ./visual_regression OSMD_function_test_all",
+    "test:visual:singletest": "sh ./test/Util/visual_regression.sh ./visual_regression Beethoven",
     "fix-memory-limit": "cross-env NODE_OPTIONS=--max_old_space_size=4096"
   },
   "pre-commit": [

+ 16 - 0
src/MusicalScore/Graphical/EngravingRules.ts

@@ -184,6 +184,7 @@ export class EngravingRules {
     private metronomeMarksDrawn: boolean;
     private metronomeMarkXShift: number;
     private metronomeMarkYShift: number;
+    private softmaxFactorVexFlow: number;
     private maxInstructionsConstValue: number;
     private noteDistances: number[] = [1.0, 1.0, 1.3, 1.6, 2.0, 2.5, 3.0, 4.0];
     private noteDistancesScalingFactors: number[] = [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0];
@@ -208,6 +209,7 @@ export class EngravingRules {
     private defaultColorTitle: string;
     private defaultFontFamily: string;
     private defaultFontStyle: FontStyles;
+    private defaultVexFlowNoteFont: string;
     private maxMeasureToDrawIndex: number;
     private minMeasureToDrawIndex: number;
     /** Whether to render a label for the composer of the piece at the top of the sheet. */
@@ -441,6 +443,7 @@ export class EngravingRules {
         this.metronomeMarksDrawn = true;
         this.metronomeMarkXShift = -6; // our unit, is taken * unitInPixels
         this.metronomeMarkYShift = -0.5;
+        this.softmaxFactorVexFlow = 5;
 
         // Render options (whether to render specific or invisible elements)
         this.alignRests = AlignRestOption.Never; // 0 = false, 1 = true, 2 = auto
@@ -460,6 +463,7 @@ export class EngravingRules {
         this.defaultColorTitle = this.defaultColorNotehead;
         this.defaultFontFamily = "Times New Roman"; // what OSMD was initially optimized for
         this.defaultFontStyle = FontStyles.Regular;
+        this.defaultVexFlowNoteFont = "gonville"; // was the default vexflow font up to vexflow 1.2.93, now it's Bravura, which is more cursive/bold
         this.maxMeasureToDrawIndex = Number.MAX_VALUE;
         this.minMeasureToDrawIndex = 0;
         this.renderComposer = true;
@@ -1452,6 +1456,12 @@ export class EngravingRules {
     public set MetronomeMarkYShift(value: number) {
         this.metronomeMarkYShift = value;
     }
+    public get SoftmaxFactorVexFlow(): number {
+        return this.softmaxFactorVexFlow;
+    }
+    public set SoftmaxFactorVexFlow(value: number) {
+        this.softmaxFactorVexFlow = value;
+    }
     public get MaxInstructionsConstValue(): number {
         return this.maxInstructionsConstValue;
     }
@@ -1585,6 +1595,12 @@ export class EngravingRules {
     public set DefaultFontStyle(value: FontStyles) {
         this.defaultFontStyle = value;
     }
+    public get DefaultVexFlowNoteFont(): string {
+        return this.defaultVexFlowNoteFont;
+    }
+    public set DefaultVexFlowNoteFont(value: string) {
+        this.defaultVexFlowNoteFont = value;
+    }
     public get MaxMeasureToDrawIndex(): number {
         return this.maxMeasureToDrawIndex;
     }

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

@@ -58,6 +58,7 @@ export abstract class MusicSheetDrawer {
         this.textMeasurer = textMeasurer;
         this.splitScreenLineColor = -1;
         this.drawingParameters = drawingParameters;
+        this.rules = drawingParameters.Rules;
     }
 
     public set Mode(value: PhonicScoreModes) {

+ 7 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -61,6 +61,12 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
     MusicSheetCalculator.symbolFactory = new VexFlowGraphicalSymbolFactory();
     MusicSheetCalculator.TextMeasurer = new VexFlowTextMeasurer(this.rules);
     MusicSheetCalculator.stafflineNoteCalculator = new VexflowStafflineNoteCalculator(this.rules);
+
+    // prepare Vexflow font (doesn't affect Vexflow 1.x). It seems like this has to be done here for now, otherwise it's too slow for the generateImages script.
+    //   (first image will have the non-updated font, in this case the Vexflow default Bravura, while we want Gonville here)
+    if (this.rules.DefaultVexFlowNoteFont === "gonville") {
+      (Vex.Flow as any).DEFAULT_FONT_STACK = [(Vex.Flow as any).Fonts?.Gonville, (Vex.Flow as any).Fonts?.Bravura, (Vex.Flow as any).Fonts?.Custom];
+    } // else keep new vexflow default Bravura (more cursive, bold)
   }
 
   protected clearRecreatedObjects(): void {
@@ -123,7 +129,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
 
     // Format the voices
     const allVoices: Vex.Flow.Voice[] = [];
-    const formatter: Vex.Flow.Formatter = new Vex.Flow.Formatter();
+    const formatter: Vex.Flow.Formatter = new Vex.Flow.Formatter({softmaxFactor: this.rules.SoftmaxFactorVexFlow});
 
     for (const measure of measures) {
       if (!measure) {

+ 5 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -51,6 +51,11 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
     }
 
     public drawSheet(graphicalMusicSheet: GraphicalMusicSheet): void {
+        // vexflow 3.x: change default font
+        if (this.rules.DefaultVexFlowNoteFont === "gonville") {
+            (Vex.Flow as any).DEFAULT_FONT_STACK = [(Vex.Flow as any).Fonts?.Gonville, (Vex.Flow as any).Fonts?.Bravura, (Vex.Flow as any).Fonts?.Custom];
+        } // else keep new vexflow default Bravura (more cursive, bold).
+
         this.pageIdx = 0;
         for (const graphicalMusicPage of graphicalMusicSheet.MusicPages) {
             const backend: VexFlowBackend = this.backends[this.pageIdx];

+ 7 - 0
src/OpenSheetMusicDisplay/OSMDOptions.ts

@@ -194,6 +194,13 @@ export interface IOSMDOptions {
      *  IF this value is -1, it will render all percussion clef voices on the single line.
      */
     percussionForceVoicesOneLineCutoff?: number;
+    /** The softmaxFactor for Vexflow's formatter. Default is 5, default in Vexflow is 100 (voice.js).
+     *  Lowering this factor makes the spacing between individual notes smaller (especially from one half note to the next).
+     *  So, to get more compact scores, try lowering this value (or set osmd.zoom, which simply scales),
+     *  or try 100 for a more expansive layout.
+     *  Setting this is the same as setting osmd.EngravingRules.SoftmaxFactorVexFlow.
+     */
+    spacingFactorSoftmax?: number;
 }
 
 export enum AlignRestOption {

+ 3 - 0
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -518,6 +518,9 @@ export class OpenSheetMusicDisplay {
         if (options.renderSingleHorizontalStaffline !== undefined) {
             this.rules.RenderSingleHorizontalStaffline = options.renderSingleHorizontalStaffline;
         }
+        if (options.spacingFactorSoftmax !== undefined) {
+            this.rules.SoftmaxFactorVexFlow = options.spacingFactorSoftmax;
+        }
     }
 
     public setColoringMode(options: IOSMDOptions): void {