فهرست منبع

fix(OctaveShift): fix occasional error when no start or end note found (#860)

fix #860
sschmid 4 سال پیش
والد
کامیت
f91e5d0b9a

+ 28 - 4
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -703,11 +703,35 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
     if (endMeasure && startStaffLine && endStaffLine) {
       // calculate GraphicalOctaveShift and RelativePositions
       const graphicalOctaveShift: VexFlowOctaveShift = new VexFlowOctaveShift(octaveShift, startStaffLine.PositionAndShape);
-      if (!graphicalOctaveShift.getStartNote()) { // fix for rendering range set
-        graphicalOctaveShift.setStartNote(startMeasure.staffEntries[0]);
+      if (!graphicalOctaveShift.startNote) { // fix for rendering range set
+        let startGse: GraphicalStaffEntry;
+        for (const gve of startMeasure.staffEntries) {
+          if (gve) {
+            startGse = gve;
+            break;
+          }
+        }
+        if (!startGse) {
+          return; // couldn't find a start staffentry, don't draw the octave shift
+        }
+        graphicalOctaveShift.setStartNote(startGse);
+        if (!graphicalOctaveShift.startNote) {
+          return; // couldn't find a start note, don't draw the octave shift
+        }
       }
-      if (!graphicalOctaveShift.getStartNote()) { // fix for rendering range set
-        graphicalOctaveShift.setEndNote(endMeasure.staffEntries.last());
+      if (!graphicalOctaveShift.endNote) { // fix for rendering range set
+        let endGse: GraphicalStaffEntry;
+        for (let i: number = endMeasure.staffEntries.length - 1; i >= 0; i++) {
+          // search backwards from end of measure
+          if (endMeasure.staffEntries[i]) {
+            endGse = endMeasure.staffEntries[i];
+            break;
+          }
+        }
+        graphicalOctaveShift.setEndNote(endGse);
+        if (!graphicalOctaveShift.endNote) {
+          return;
+        }
       }
       startStaffLine.OctaveShifts.push(graphicalOctaveShift);
 

+ 21 - 14
src/MusicalScore/Graphical/VexFlow/VexFlowOctaveShift.ts

@@ -12,9 +12,9 @@ import log from "loglevel";
 export class VexFlowOctaveShift extends GraphicalOctaveShift {
 
     /** Defines the note where the octave shift starts */
-    private startNote: Vex.Flow.StemmableNote;
+    public startNote: Vex.Flow.StemmableNote;
     /** Defines the note where the octave shift ends */
-    private endNote: Vex.Flow.StemmableNote;
+    public endNote: Vex.Flow.StemmableNote;
     /** Top or bottom of the staffline */
     private position: Vex.Flow.TextBracket.Positions;
     /** Supscript is a smaller text after the regular text (e.g. va after 8) */
@@ -60,24 +60,31 @@ export class VexFlowOctaveShift extends GraphicalOctaveShift {
      * Set a start note using a staff entry
      * @param graphicalStaffEntry the staff entry that holds the start note
      */
-    public setStartNote(graphicalStaffEntry: GraphicalStaffEntry): void {
-        this.startNote = (graphicalStaffEntry.graphicalVoiceEntries[0] as VexFlowVoiceEntry).vfStaveNote;
+    public setStartNote(graphicalStaffEntry: GraphicalStaffEntry): boolean {
+        for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
+            const vve: VexFlowVoiceEntry = (gve as VexFlowVoiceEntry);
+            if (vve?.vfStaveNote) {
+                this.startNote = vve.vfStaveNote;
+                return true;
+            }
+        }
+        return false; // couldn't find a startNote
     }
 
     /**
      * Set an end note using a staff entry
      * @param graphicalStaffEntry the staff entry that holds the end note
      */
-    public setEndNote(graphicalStaffEntry: GraphicalStaffEntry): void {
-        this.endNote = (graphicalStaffEntry.graphicalVoiceEntries[0] as VexFlowVoiceEntry).vfStaveNote;
-    }
-
-    public getStartNote(): Vex.Flow.StemmableNote {
-        return this.startNote;
-    }
-
-    public getEndNote(): Vex.Flow.StemmableNote {
-        return this.endNote;
+    public setEndNote(graphicalStaffEntry: GraphicalStaffEntry): boolean {
+        // this is duplicate code from setStartNote, but if we make one general method, we add a lot of branching.
+        for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
+            const vve: VexFlowVoiceEntry = (gve as VexFlowVoiceEntry);
+            if (vve?.vfStaveNote) {
+                this.endNote = vve.vfStaveNote;
+                return true;
+            }
+        }
+        return false; // couldn't find an endNote
     }
 
     /**