Browse Source

fix(octaveShift, drawRange): start and end at within draw range, fix error

part of #586

AbsoluteTimeStamp error not yet fixed, though only occurs with incorrect xmls
Simon Schmid 5 years ago
parent
commit
9f6bb82868

+ 55 - 9
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -513,41 +513,87 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
     const startTimeStamp: Fraction = octaveShift.ParentStartMultiExpression.Timestamp;
     const endTimeStamp: Fraction = octaveShift.ParentEndMultiExpression.Timestamp;
 
-    const startStaffLine: StaffLine = this.graphicalMusicSheet.MeasureList[measureIndex][staffIndex].ParentStaffLine;
+    const minMeasureToDrawIndex: number = EngravingRules.Rules.MinMeasureToDrawIndex;
+    const maxMeasureToDrawIndex: number = EngravingRules.Rules.MaxMeasureToDrawIndex;
+
+    let startStaffLine: StaffLine = this.graphicalMusicSheet.MeasureList[measureIndex][staffIndex].ParentStaffLine;
+    if (startStaffLine === undefined) { // fix for rendering range set. all of these can probably done cleaner.
+      startStaffLine = this.graphicalMusicSheet.MeasureList[minMeasureToDrawIndex][staffIndex].ParentStaffLine;
+    }
 
     let endMeasure: GraphicalMeasure = undefined;
     if (octaveShift.ParentEndMultiExpression !== undefined) {
       endMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(octaveShift.ParentEndMultiExpression.SourceMeasureParent,
                                                                                          staffIndex);
+    } else {
+      endMeasure = this.graphicalMusicSheet.getLastGraphicalMeasureFromIndex(staffIndex, true); // get last rendered measure
+    }
+    if (endMeasure.MeasureNumber > maxMeasureToDrawIndex + 1) { // octaveshift ends in measure not rendered
+      endMeasure = this.graphicalMusicSheet.getLastGraphicalMeasureFromIndex(staffIndex, true);
     }
     let startMeasure: GraphicalMeasure = undefined;
     if (octaveShift.ParentEndMultiExpression !== undefined) {
       startMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(octaveShift.ParentStartMultiExpression.SourceMeasureParent,
                                                                                            staffIndex);
+    } else {
+      startMeasure = this.graphicalMusicSheet.MeasureList[minMeasureToDrawIndex][staffIndex]; // first rendered measure
+    }
+    if (startMeasure.MeasureNumber < minMeasureToDrawIndex + 1) { // octaveshift starts before range of measures selected to render
+      startMeasure = this.graphicalMusicSheet.MeasureList[minMeasureToDrawIndex][staffIndex]; // first rendered measure
+    }
+
+    if (startMeasure.MeasureNumber < minMeasureToDrawIndex + 1 ||
+        startMeasure.MeasureNumber > maxMeasureToDrawIndex + 1 ||
+        endMeasure.MeasureNumber < minMeasureToDrawIndex + 1 ||
+        endMeasure.MeasureNumber > maxMeasureToDrawIndex + 1) {
+      // octave shift completely out of drawing range, don't draw anything
+      return;
     }
 
-    // TODO octave shifts probably need a fix when we only draw measure 1 for example, then stafflines are undefined
-    if (endMeasure !== undefined && startStaffLine !== undefined && endMeasure.ParentStaffLine !== undefined) {
+    let endStaffLine: StaffLine = endMeasure.ParentStaffLine;
+    if (endStaffLine === undefined) {
+      endStaffLine = startStaffLine;
+    }
+
+    if (endMeasure !== undefined && startStaffLine !== undefined && endStaffLine !== undefined) {
       // calculate GraphicalOctaveShift and RelativePositions
       const graphicalOctaveShift: VexFlowOctaveShift = new VexFlowOctaveShift(octaveShift, startStaffLine.PositionAndShape);
+      if (graphicalOctaveShift.getStartNote() === undefined) { // fix for rendering range set
+        graphicalOctaveShift.setStartNote(startMeasure.staffEntries[0]);
+      }
+      if (graphicalOctaveShift.getStartNote() === undefined) { // fix for rendering range set
+        graphicalOctaveShift.setEndNote(endMeasure.staffEntries.last());
+      }
       startStaffLine.OctaveShifts.push(graphicalOctaveShift);
 
       // calculate RelativePosition and Dashes
-      const startStaffEntry: GraphicalStaffEntry = startMeasure.findGraphicalStaffEntryFromTimestamp(startTimeStamp);
-      const endStaffEntry: GraphicalStaffEntry = endMeasure.findGraphicalStaffEntryFromTimestamp(endTimeStamp);
+      let startStaffEntry: GraphicalStaffEntry = startMeasure.findGraphicalStaffEntryFromTimestamp(startTimeStamp);
+      if (startStaffEntry === undefined) { // fix for rendering range set
+        startStaffEntry = startMeasure.staffEntries[0];
+      }
+      let endStaffEntry: GraphicalStaffEntry = endMeasure.findGraphicalStaffEntryFromTimestamp(endTimeStamp);
+      if (endStaffEntry === undefined) { // fix for rendering range set
+        endStaffEntry = endMeasure.staffEntries[endMeasure.staffEntries.length - 1];
+      }
 
       graphicalOctaveShift.setStartNote(startStaffEntry);
 
-      if (endMeasure.ParentStaffLine !== startMeasure.ParentStaffLine) {
+      if (endStaffLine !== startStaffLine) {
         graphicalOctaveShift.endsOnDifferentStaffLine = true;
-        const lastMeasure: GraphicalMeasure = startMeasure.ParentStaffLine.Measures[startMeasure.ParentStaffLine.Measures.length - 1];
+        let lastMeasure: GraphicalMeasure = startStaffLine.Measures[startStaffLine.Measures.length - 1];
+        if (lastMeasure === undefined) { // TODO handle this case correctly (when drawUpToMeasureNumber etc set)
+          lastMeasure = endMeasure;
+        }
         const lastNote: GraphicalStaffEntry = lastMeasure.staffEntries[lastMeasure.staffEntries.length - 1];
         graphicalOctaveShift.setEndNote(lastNote);
 
         // Now finish the shift on the next line
         const remainingOctaveShift: VexFlowOctaveShift = new VexFlowOctaveShift(octaveShift, endMeasure.PositionAndShape);
-        endMeasure.ParentStaffLine.OctaveShifts.push(remainingOctaveShift);
-        const firstMeasure: GraphicalMeasure = endMeasure.ParentStaffLine.Measures[0];
+        endStaffLine.OctaveShifts.push(remainingOctaveShift);
+        let firstMeasure: GraphicalMeasure = endStaffLine.Measures[0];
+        if (firstMeasure === undefined) { // TODO handle this case correctly (when drawUpToMeasureNumber etc set)
+          firstMeasure = startMeasure;
+        }
         const firstNote: GraphicalStaffEntry = firstMeasure.staffEntries[0];
         remainingOctaveShift.setStartNote(firstNote);
         remainingOctaveShift.setEndNote(endStaffEntry);

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

@@ -278,9 +278,15 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
                 const stopX: number = staffLine.PositionAndShape.AbsolutePosition.x + textBracket.stop.getX() / 10;
                 if ((<any>textBracket).position === Vex.Flow.TextBracket.Positions.TOP) {
                     const headroom: number = staffLine.SkyBottomLineCalculator.getSkyLineMinInRange(startX, stopX);
+                    if (headroom === Infinity) { // will cause Vexflow error
+                        return;
+                    }
                     textBracket.start.getStave().options.space_above_staff_ln = headroom;
                 } else {
                     const footroom: number = staffLine.SkyBottomLineCalculator.getBottomLineMaxInRange(startX, stopX);
+                    if (footroom === Infinity) { // will cause Vexflow error
+                        return;
+                    }
                     textBracket.start.getStave().options.space_below_staff_ln = footroom;
                 }
                 textBracket.draw();

+ 8 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowOctaveShift.ts

@@ -72,6 +72,14 @@ export class VexFlowOctaveShift extends GraphicalOctaveShift {
         this.endNote = (graphicalStaffEntry.graphicalVoiceEntries[0] as VexFlowVoiceEntry).vfStaveNote;
     }
 
+    public getStartNote(): Vex.Flow.StemmableNote {
+        return this.startNote;
+    }
+
+    public getEndNote(): Vex.Flow.StemmableNote {
+        return this.endNote;
+    }
+
     /**
      * Get the actual vexflow text bracket used for drawing
      */