Ver código fonte

Further pedal fixes
Allow null end staff entry (use end of measure)
Set brackets in same staffline to same height
Use set line for pedal marking vs. using the stave bottom text

Justin Litten 3 anos atrás
pai
commit
23070bf103

+ 100 - 71
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -1044,9 +1044,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
 
       if (endStaffLine !== startStaffLine) {
         if(graphicalPedal.pedalSymbol === MusicSymbol.PEDAL_SYMBOL){
-          if(!graphicalPedal.setEndNote(endStaffEntry)){
-            return;
-          }
+          graphicalPedal.setEndNote(endStaffEntry);
           graphicalPedal.setEndMeasure(endMeasure);
           graphicalPedal.ReleaseText = " ";
           graphicalPedal.CalculateBoundingBox();
@@ -1056,9 +1054,10 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
           // pedal starts on the first measure
           const nextPedal: VexFlowPedal = new VexFlowPedal(pedal, nextPedalFirstMeasure.PositionAndShape);
           const firstNote: GraphicalStaffEntry = nextPedalFirstMeasure.staffEntries[0];
-          if(!nextPedal.setStartNote(firstNote) || !nextPedal.setEndNote(endStaffEntry)){
+          if(!nextPedal.setStartNote(firstNote)){
             return;
-          }
+        }
+          nextPedal.setEndNote(endStaffEntry);
           graphicalPedal.setEndMeasure(endMeasure);
           endStaffLine.Pedals.push(nextPedal);
           nextPedal.CalculateBoundingBox();
@@ -1070,9 +1069,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
             lastMeasureOfFirstShift = endMeasure;
           }
           const lastNoteOfFirstShift: GraphicalStaffEntry = lastMeasureOfFirstShift.staffEntries[lastMeasureOfFirstShift.staffEntries.length - 1];
-          if(!graphicalPedal.setEndNote(lastNoteOfFirstShift)){
-            return;
-          }
+          graphicalPedal.setEndNote(lastNoteOfFirstShift);
           graphicalPedal.setEndMeasure(endMeasure);
 
           const systemsInBetweenCount: number = endStaffLine.ParentMusicSystem.Id - startStaffLine.ParentMusicSystem.Id;
@@ -1100,9 +1097,10 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
                 nextPedalLastMeasure = endMeasure;
                 lastNote = endStaffEntry;
               }
-              if(!nextPedal.setStartNote(firstNote) || !nextPedal.setEndNote(lastNote)){
+              if(!nextPedal.setStartNote(firstNote)){
                 break;
               }
+              nextPedal.setEndNote(lastNote);
               graphicalPedal.setEndMeasure(endMeasure);
               nextPedalStaffline.Pedals.push(nextPedal);
               nextPedal.CalculateBoundingBox();
@@ -1113,9 +1111,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
           this.calculatePedalSkyBottomLine(graphicalPedal.startVfVoiceEntry, graphicalPedal.endVfVoiceEntry, graphicalPedal, startStaffLine);
         }
       } else {
-        if(!graphicalPedal.setEndNote(endStaffEntry)){
-          return;
-        }
+        graphicalPedal.setEndNote(endStaffEntry);
         graphicalPedal.setEndMeasure(endMeasure);
         graphicalPedal.CalculateBoundingBox();
         this.calculatePedalSkyBottomLine(graphicalPedal.startVfVoiceEntry, graphicalPedal.endVfVoiceEntry, graphicalPedal, startStaffLine);
@@ -1310,8 +1306,9 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
       //Just for shorthand. Easier readability below
       const PEDAL_STYLES_ENUM: any = Vex.Flow.PedalMarking.Styles;
       const pedalMarking: any = vfPedal.getPedalMarking();
-      //VF adds 3 to the line that is set for rendering pedal
-      const bottomLineYOffset: number = (pedalMarking.line + 3);
+      //VF adds 3 lines to whatever the pedal line is set to.
+      //VF also measures from the bottom line, whereas our bottom line is from the top staff line
+      const yLineForPedalMarking: number = (pedalMarking.line + 3 + (parentStaffline.StaffLines.length - 1));
       //VF Uses a margin offset for rendering. Take this into account
       const pedalMarkingMarginXOffset: number = pedalMarking.render_options.text_margin_right / 10;
       //TODO: Most of this should be in the bounding box calculation
@@ -1324,39 +1321,55 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
         startX -= 1;
       }
       let stopX: number = undefined;
+      let footroom: number = (parentStaffline.StaffLines.length - 1);
+      //Find the highest foot room in our staffline
+      for (const otherPedal of parentStaffline.Pedals) {
+        const vfOtherPedal: VexFlowPedal = otherPedal as VexFlowPedal;
+        const otherPedalMarking: any = vfOtherPedal.getPedalMarking();
+        const yLineForOtherPedalMarking: number = (otherPedalMarking.line + 3 + (parentStaffline.StaffLines.length - 1));
+        footroom = Math.max(yLineForOtherPedalMarking, footroom);
+      }
       //We have the two seperate symbols, with two bounding boxes
       if (vfPedal.EndSymbolPositionAndShape) {
+        const symbolHalfHeight: number = pedalMarking.render_options.glyph_point_size / 20;
         //Width of the Ped. symbol
         stopX = startX + 3.4;
         const startX2: number = endBbox.AbsolutePosition.x - pedalMarkingMarginXOffset;
         //Width of * symbol
         const stopX2: number = startX2 + 1.5;
 
-        let footroom: number = parentStaffline.SkyBottomLineCalculator.getBottomLineMaxInRange(startX, stopX);
-        footroom = Math.max((vfPedal.startNote.getStave().options as any).bottom_text_position, footroom);
+        footroom = Math.max(parentStaffline.SkyBottomLineCalculator.getBottomLineMaxInRange(startX, stopX), footroom);
+        footroom = Math.max(yLineForPedalMarking + symbolHalfHeight * 2, footroom);
         const footroom2: number = parentStaffline.SkyBottomLineCalculator.getBottomLineMaxInRange(startX2, stopX2);
         //If Depress text is set, means we are not rendering the begin label (we are just rendering the end one)
         if (!vfPedal.DepressText) {
           footroom = Math.max(footroom, footroom2);
         }
-        if (startVfVoiceEntry.parentStaffEntry.parentMeasure !== endVfVoiceEntry.parentStaffEntry.parentMeasure && vfPedal.endNote) {
-          //TODO: look into using the vexflow setLine instead of modifying the whole stave if possible
-          footroom = Math.max((vfPedal.endNote.getStave().options as any).bottom_text_position, footroom);
-          (vfPedal.endNote.getStave().options as any).bottom_text_position = footroom;
-        }
-        (vfPedal.startNote.getStave().options as any).bottom_text_position = footroom;
-        parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(startX, stopX, footroom + bottomLineYOffset);
-        parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(startX2, stopX2, footroom + bottomLineYOffset);
+        vfPedal.setLine(footroom - 3 - (parentStaffline.StaffLines.length - 1));
+        parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(startX, stopX, footroom + symbolHalfHeight);
+        parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(startX2, stopX2, footroom + symbolHalfHeight);
       } else {
-        switch (pedalMarking.style) {
-          case PEDAL_STYLES_ENUM.BRACKET_OPEN_END:
-          case PEDAL_STYLES_ENUM.BRACKET_OPEN_BOTH:
-          case PEDAL_STYLES_ENUM.MIXED_OPEN_END:
-            stopX = endBbox.AbsolutePosition.x + endBbox.BorderRight - pedalMarkingMarginXOffset;
-          break;
-          default:
-            stopX = endBbox.AbsolutePosition.x + endBbox.BorderLeft - pedalMarkingMarginXOffset;
-          break;
+        const bracketHeight: number = pedalMarking.render_options.bracket_height / 10;
+
+        if(pedalMarking.EndsStave){
+          if(endVfVoiceEntry){
+            stopX = endVfVoiceEntry.parentStaffEntry.parentMeasure.PositionAndShape.AbsolutePosition.x +
+              endVfVoiceEntry.parentStaffEntry.parentMeasure.PositionAndShape.Size.width - pedalMarkingMarginXOffset;
+
+          } else {
+            stopX = endBbox.AbsolutePosition.x + endBbox.Size.width;
+          }
+        } else {
+          switch (pedalMarking.style) {
+            case PEDAL_STYLES_ENUM.BRACKET_OPEN_END:
+            case PEDAL_STYLES_ENUM.BRACKET_OPEN_BOTH:
+            case PEDAL_STYLES_ENUM.MIXED_OPEN_END:
+              stopX = endBbox.AbsolutePosition.x + endBbox.BorderRight - pedalMarkingMarginXOffset;
+            break;
+            default:
+              stopX = endBbox.AbsolutePosition.x + endBbox.BorderLeft - pedalMarkingMarginXOffset;
+            break;
+          }
         }
         //Take into account in-staff clefs associated with the staff entry (they modify the bounding box position)
         const vfClefBefore: Vex.Flow.ClefNote = (endVfVoiceEntry?.parentStaffEntry as VexFlowStaffEntry)?.vfClefBefore;
@@ -1365,57 +1378,73 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
           stopX += clefWidth;
         }
 
-        let footroom: number = parentStaffline.SkyBottomLineCalculator.getBottomLineMaxInRange(startX, stopX);
+        footroom = Math.max(parentStaffline.SkyBottomLineCalculator.getBottomLineMaxInRange(startX, stopX), footroom);
         if (footroom === Infinity) { // will cause Vexflow error
           return;
         }
         //Whatever is currently lower - the set render height of the begin vf stave, the set render height of the end vf stave,
         //or the bottom line. Use that as the render height of both staves
-        footroom = Math.max(footroom, (vfPedal.startNote.getStave().options as any).bottom_text_position);
-        if (startVfVoiceEntry.parentStaffEntry.parentMeasure !== endVfVoiceEntry?.parentStaffEntry.parentMeasure && vfPedal.endNote) {
-          footroom = Math.max(footroom, (vfPedal.endNote.getStave().options as any).bottom_text_position);
-          (vfPedal.endNote.getStave().options as any).bottom_text_position = footroom;
-        }
-        (vfPedal.startNote.getStave().options as any).bottom_text_position = footroom;
+        footroom = Math.max(footroom, yLineForPedalMarking + bracketHeight);
+        vfPedal.setLine(footroom - 3 - (parentStaffline.StaffLines.length - 1));
         if (startX > stopX) { // TODO hotfix for skybottomlinecalculator after pedal no endNote fix
           const newStart: number = stopX;
           stopX = startX;
           startX = newStart;
         }
-        parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(startX, stopX, footroom + bottomLineYOffset);
-        //This list will contain only previously processed Pedals - aka, those previous in the sheet music
-        for (const otherPedal of parentStaffline.Pedals) {
-          const vfOtherPedal: VexFlowPedal = otherPedal as VexFlowPedal;
-          //If there is a pedal that ends on our begin measure, we need to update its begin measure to render at the new height
-          //So we don't get lopsided pedal brackets
-          if (vfOtherPedal.endVfVoiceEntry?.parentStaffEntry.parentMeasure === startVfVoiceEntry.parentStaffEntry.parentMeasure) {
-            //Since we've already checked for max height for this stave above, we are certain that this pedal will not render higher than it should
-            //(e.g. colliding with stuff)
-            (vfOtherPedal.startNote.getStave().options as any).bottom_text_position = footroom;
-            const otherPedalMarking: any = vfOtherPedal.getPedalMarking();
-            const otherPedalMarkingMarginXOffset: number = otherPedalMarking.render_options.text_margin_right / 10;
-            const otherPedalStartX: number = vfOtherPedal.startVfVoiceEntry.PositionAndShape.AbsolutePosition.x - otherPedalMarkingMarginXOffset;
-            let otherPedalStopX: number = undefined;
-            switch (otherPedalMarking.style) {
-              case PEDAL_STYLES_ENUM.BRACKET_OPEN_END:
-              case PEDAL_STYLES_ENUM.BRACKET_OPEN_BOTH:
-              case PEDAL_STYLES_ENUM.MIXED_OPEN_END:
-                otherPedalStopX = vfOtherPedal.endVfVoiceEntry.PositionAndShape.AbsolutePosition.x +
-                                  vfOtherPedal.endVfVoiceEntry.PositionAndShape.BorderRight - otherPedalMarkingMarginXOffset;
-              break;
-              default:
-                otherPedalStopX = vfOtherPedal.endVfVoiceEntry.PositionAndShape.AbsolutePosition.x +
-                vfOtherPedal.endVfVoiceEntry.PositionAndShape.BorderLeft - otherPedalMarkingMarginXOffset;
-              break;
+        parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(startX, stopX, footroom + bracketHeight);
+      }
+      //If our current pedal is below the other pedals in this staffline, set them all to this height
+      for (const otherPedal of parentStaffline.Pedals) {
+        const vfOtherPedal: VexFlowPedal = otherPedal as VexFlowPedal;
+        const otherPedalMarking: any = vfOtherPedal.getPedalMarking();
+        const yLineForOtherPedalMarking: number = (otherPedalMarking.line + 3 + (parentStaffline.StaffLines.length - 1));
+        //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 otherPedalStopX: number = undefined;
+          vfOtherPedal.setLine(footroom - 3 - (parentStaffline.StaffLines.length - 1));
+
+          if (vfOtherPedal.EndSymbolPositionAndShape) {
+            const otherSymbolHalfHeight: number = pedalMarking.render_options.glyph_point_size / 20;
+            //Width of the Ped. symbol
+            otherPedalStopX = otherPedalStartX + 3.4;
+            const otherPedalStartX2: number = endBbox.AbsolutePosition.x - pedalMarkingMarginXOffset;
+            //Width of * symbol
+            const otherPedalStopX2: number = otherPedalStartX2 + 1.5;
+            parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(startX, stopX, footroom + otherSymbolHalfHeight);
+            parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(otherPedalStartX2, otherPedalStopX2, footroom + otherSymbolHalfHeight);
+          } else {
+            const otherPedalBracketHeight: number = pedalMarking.render_options.bracket_height / 10;
+
+            if(pedalMarking.EndsStave){
+              if(vfOtherPedal.endVfVoiceEntry){
+                otherPedalStopX = vfOtherPedal.endVfVoiceEntry.parentStaffEntry.parentMeasure.PositionAndShape.AbsolutePosition.x +
+                  vfOtherPedal.endVfVoiceEntry.parentStaffEntry.parentMeasure.PositionAndShape.Size.width - pedalMarkingMarginXOffset;
+              } else {
+                otherPedalStopX = vfOtherPedal.endMeasure.PositionAndShape.AbsolutePosition.x + vfOtherPedal.endMeasure.PositionAndShape.Size.width;
+              }
+            } else {
+              switch (pedalMarking.style) {
+                case PEDAL_STYLES_ENUM.BRACKET_OPEN_END:
+                case PEDAL_STYLES_ENUM.BRACKET_OPEN_BOTH:
+                case PEDAL_STYLES_ENUM.MIXED_OPEN_END:
+                  otherPedalStopX = vfOtherPedal.endVfVoiceEntry.PositionAndShape.AbsolutePosition.x +
+                    vfOtherPedal.endVfVoiceEntry.PositionAndShape.BorderRight - pedalMarkingMarginXOffset;
+                break;
+                default:
+                  otherPedalStopX = vfOtherPedal.endVfVoiceEntry.PositionAndShape.AbsolutePosition.x +
+                    vfOtherPedal.endVfVoiceEntry.PositionAndShape.BorderLeft - pedalMarkingMarginXOffset;
+                break;
+              }
             }
             //Take into account in-staff clefs associated with the staff entry (they modify the bounding box position)
-            const otherPedalVfClefBefore: Vex.Flow.ClefNote = (vfOtherPedal.endVfVoiceEntry.parentStaffEntry as VexFlowStaffEntry).vfClefBefore;
-            if (otherPedalVfClefBefore) {
-              const clefWidth: number = otherPedalVfClefBefore.getWidth() / 10;
-              stopX += clefWidth;
+            const vfOtherClefBefore: Vex.Flow.ClefNote = (vfOtherPedal.endVfVoiceEntry?.parentStaffEntry as VexFlowStaffEntry)?.vfClefBefore;
+            if (vfOtherClefBefore) {
+              const otherClefWidth: number = vfOtherClefBefore.getWidth() / 10;
+              otherPedalStopX += otherClefWidth;
             }
-            const otherPedalBottomLineYOffset: number = (pedalMarking.line + 3);
-            parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(otherPedalStartX, otherPedalStopX, footroom + otherPedalBottomLineYOffset);
+            parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(otherPedalStartX, otherPedalStopX, footroom + otherPedalBracketHeight);
           }
         }
       }

+ 6 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowPedal.ts

@@ -21,6 +21,7 @@ export class VexFlowPedal extends GraphicalPedal {
     public startVfVoiceEntry: VexFlowVoiceEntry;
     public endVfVoiceEntry: VexFlowVoiceEntry;
     public endMeasure: GraphicalMeasure;
+    private line: number = -3;
 
     public EndSymbolPositionAndShape: BoundingBox = undefined;
     /**
@@ -105,6 +106,10 @@ export class VexFlowPedal extends GraphicalPedal {
     public CalculateBoundingBox(): void {
         //TODO?
     }
+
+    public setLine(line: number): void {
+        this.line = line;
+    }
     /**
      * Get the actual vexflow Pedal Marking used for drawing
      */
@@ -114,7 +119,7 @@ export class VexFlowPedal extends GraphicalPedal {
             (pedalMarking as any).setEndStave((this.endMeasure as VexFlowMeasure).getVFStave());
         }
         pedalMarking.setStyle(this.vfStyle);
-        pedalMarking.setLine(-1);
+        pedalMarking.setLine(this.line);
         pedalMarking.setCustomText(this.DepressText, this.ReleaseText);
         //If our end note is at the end of a stave, set that value
         if(this.endVfVoiceEntry?.parentStaffEntry?.parentMeasure?.parentSourceMeasure?.VerticalSourceStaffEntryContainers?.last() ===

+ 11 - 2
src/VexFlowPatch/src/pedalmarking.js

@@ -120,6 +120,8 @@ export class PedalMarking extends Element {
   setEndStave(stave) {
     this.endStave = stave;
     this.endStaveAddedWidth = 0;
+    this.startMargin = 0;
+    this.endMargin = 0;
     if(Array.isArray(this.endStave.modifiers)){
       for(let i = 0; i < this.endStave.modifiers.length; i++){
         let nextMod = this.endStave.modifiers[i];
@@ -168,7 +170,7 @@ export class PedalMarking extends Element {
         //default to note head begin
         x = note.getNoteHeadBeginX();
       } else {
-        x = note.getStave().end_x + this.endStaveAddedWidth;
+        x = this.endStave.end_x + this.endStaveAddedWidth;
       }
 
       //If this pedal doesn't end a stave...
@@ -183,6 +185,7 @@ export class PedalMarking extends Element {
             break;
             default:
               x = note.getNoteHeadBeginX() - pedal.render_options.text_margin_right;
+              this.startMargin = -pedal.render_options.text_margin_right;
             break;
           }
         }
@@ -190,7 +193,13 @@ export class PedalMarking extends Element {
         //pedal across a single note or just the end note
         if(!is_pedal_depressed){
           //IF we are the end, set the end to the stave end
-          x = note.getStave().end_x + this.endStaveAddedWidth - pedal.render_options.text_margin_right;
+          if(note){
+            x = note.getStave().end_x + this.endStaveAddedWidth - pedal.render_options.text_margin_right;
+          } else {
+            x = this.endStave.end_x + this.endStaveAddedWidth - pedal.render_options.text_margin_right;
+          }
+          
+          this.endMargin = -pedal.render_options.text_margin_right;
         }
       }