Browse Source

fix(Pedals): fix pedal lines across score (#50), faulty xml pedals with 2x start in a row etc. improved (#107)

fix #50

* openPedal: check for IsLine (prevent Ped. overlapping * at end of Dichterliebe)

* fix error with pedals when startX > stopX, fix cursor error
sschmidTU 3 years ago
parent
commit
258a1bbcd6

+ 17 - 3
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -1009,6 +1009,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
       endMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(pedal.ParentEndMultiExpression.SourceMeasureParent,
                                                                                           staffIndex);
     } else {
+      //return; // also possible: don't handle faulty pedal without end
       endMeasure = this.graphicalMusicSheet.getLastGraphicalMeasureFromIndex(staffIndex, true); // get last rendered measure
     }
     if (endMeasure.MeasureNumber > maxMeasureToDrawIndex + 1) { //  ends in measure not rendered
@@ -1017,9 +1018,15 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
     let startMeasure: GraphicalMeasure = undefined;
     if (pedal.ParentEndMultiExpression) {
       startMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(pedal.ParentStartMultiExpression.SourceMeasureParent,
-                                                                                            staffIndex);
+        staffIndex);
     } else {
-      startMeasure = this.graphicalMusicSheet.MeasureList[minMeasureToDrawIndex][staffIndex]; // first rendered measure
+      startMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(
+        pedal.ParentStartMultiExpression.SourceMeasureParent,
+        staffIndex);
+      if (!startMeasure) {
+        startMeasure = this.graphicalMusicSheet.MeasureList[minMeasureToDrawIndex][staffIndex]; // first rendered measure
+      }
+      //console.log("no end multi expression for start measure " + startMeasure.MeasureNumber);
     }
     if (startMeasure.MeasureNumber < minMeasureToDrawIndex + 1) { //  starts before range of measures selected to render
       startMeasure = this.graphicalMusicSheet.MeasureList[minMeasureToDrawIndex][staffIndex]; // first rendered measure
@@ -1426,7 +1433,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
         //Only do these changes if current footroom is higher
         if(footroom > yLineForOtherPedalMarking) {
           const otherPedalMarkingMarginXOffset: number = otherPedalMarking.render_options.text_margin_right / 10;
-          const otherPedalStartX: number = vfOtherPedal.startVfVoiceEntry.PositionAndShape.AbsolutePosition.x - otherPedalMarkingMarginXOffset;
+          let otherPedalStartX: number = vfOtherPedal.startVfVoiceEntry.PositionAndShape.AbsolutePosition.x - otherPedalMarkingMarginXOffset;
           let otherPedalStopX: number = undefined;
           vfOtherPedal.setLine(footroom - 3 - (parentStaffline.StaffLines.length - 1));
           let otherPedalEndBBox: BoundingBox = vfOtherPedal.endVfVoiceEntry?.PositionAndShape;
@@ -1465,6 +1472,13 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
               const otherClefWidth: number = vfOtherClefBefore.getWidth() / 10;
               otherPedalStopX += otherClefWidth;
             }
+            if (otherPedalStartX > otherPedalStopX) {
+              // TODO this shouldn't happen, though this fixes the SkyBottomLineCalculator error for now (startIndex needs to be <= endIndex)
+              // switch startX and stopX
+              const otherStartX: number = otherPedalStartX;
+              otherPedalStartX = otherPedalStopX;
+              otherPedalStopX = otherStartX;
+            }
             parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(otherPedalStartX, otherPedalStopX, footroom + otherPedalBracketHeight);
           }
         }

+ 16 - 7
src/MusicalScore/ScoreIO/MusicSymbolModules/ExpressionReader.ts

@@ -354,20 +354,23 @@ export class ExpressionReader {
                     }
                     switch (pedalNode.attribute("type").value) {
                         case "start":
-                            //ignore duplicate tags
-                            if (!this.openPedal || !this.openPedal.ParentStartMultiExpression.AbsoluteTimestamp.Equals(endTimestamp)) {
-                                this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
+                            //ignore duplicate tags (causes issues when pedals aren't terminated)
+                            // if (!this.openPedal || !this.openPedal.ParentStartMultiExpression.AbsoluteTimestamp.Equals(endTimestamp)) {
+                            //     this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
+                            // }
+                            // instead, just end open pedal if there already was one, and create new one
+                            if (this.openPedal && this.openPedal.IsLine) {
+                                // if we don't check IsLine, the Ped. at the end of Dichterliebe overlaps with a *
+                                this.endOpenPedal(currentMeasure);
                             }
+                            this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
                             this.openPedal = new Pedal(line, sign);
                             this.getMultiExpression.PedalStart = this.openPedal;
                             this.openPedal.ParentStartMultiExpression = this.getMultiExpression;
                         break;
                         case "stop":
                             if (this.openPedal) {
-                                this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
-                                this.getMultiExpression.PedalEnd = this.openPedal;
-                                this.openPedal.ParentEndMultiExpression = this.getMultiExpression;
-                                this.openPedal = undefined;
+                                this.endOpenPedal(currentMeasure);
                             }
                         break;
                         case "change":
@@ -398,6 +401,12 @@ export class ExpressionReader {
             }
         }
     }
+    private endOpenPedal(currentMeasure: SourceMeasure): void {
+        this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
+        this.getMultiExpression.PedalEnd = this.openPedal;
+        this.openPedal.ParentEndMultiExpression = this.getMultiExpression;
+        this.openPedal = undefined;
+    }
     public addWavyLine(wavyLineNode: IXmlElement, currentMeasure: SourceMeasure, currentTimestamp: Fraction, previousTimestamp: Fraction): void {
         if (wavyLineNode && wavyLineNode.hasAttributes) {
             try {

+ 1 - 1
src/OpenSheetMusicDisplay/Cursor.ts

@@ -451,7 +451,7 @@ export class Cursor implements IPlaybackListener {
   }
 
   public updateCurrentPageFromSystem(system: MusicSystem): number {
-    if (system !== undefined) {
+    if (system?.Parent) {
       const newPageNumber: number = system.Parent.PageNumber;
       if (newPageNumber !== this.currentPageNumber) {
         this.container.removeChild(this.cursorElement);