ソースを参照

fix(Skyline): Accomodate multiline octave (octava)

Merge pull request #775 from opensheetmusicdisplay/fix/skyline/ottava

Calculate sky and bottom lines for octave marking
Simon 5 年 前
コミット
222a558858

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

@@ -362,7 +362,6 @@ export abstract class MusicSheetDrawer {
                 this.drawDashes(staffLine.LyricsDashes);
             }
         }
-
         this.drawOctaveShifts(staffLine);
 
         this.drawExpressions(staffLine);

+ 30 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -663,14 +663,44 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
         const firstNote: GraphicalStaffEntry = firstMeasure.staffEntries[0];
         remainingOctaveShift.setStartNote(firstNote);
         remainingOctaveShift.setEndNote(endStaffEntry);
+        this.calculateOctaveShiftSkyBottomLine(startStaffEntry, lastNote, graphicalOctaveShift, startStaffLine);
+        this.calculateOctaveShiftSkyBottomLine(firstNote, endStaffEntry, remainingOctaveShift, endStaffLine);
       } else {
         graphicalOctaveShift.setEndNote(endStaffEntry);
+        this.calculateOctaveShiftSkyBottomLine(startStaffEntry, endStaffEntry, graphicalOctaveShift, startStaffLine);
       }
     } else {
       log.warn("End measure or staffLines for octave shift are undefined! This should not happen!");
     }
   }
 
+  private calculateOctaveShiftSkyBottomLine(startStaffEntry: GraphicalStaffEntry, endStaffEntry: GraphicalStaffEntry,
+                                            vfOctaveShift: VexFlowOctaveShift, parentStaffline: StaffLine): void {
+
+    const startX: number = startStaffEntry.PositionAndShape.AbsolutePosition.x - startStaffEntry.PositionAndShape.Size.width / 2;
+    const stopX: number = endStaffEntry.PositionAndShape.AbsolutePosition.x + endStaffEntry.PositionAndShape.Size.width / 2;
+    vfOctaveShift.PositionAndShape.Size.width = startX - stopX;
+    const textBracket: Vex.Flow.TextBracket = vfOctaveShift.getTextBracket();
+    const fontSize: number = (textBracket as any).font.size / 10;
+
+    if ((<any>textBracket).position === Vex.Flow.TextBracket.Positions.TOP) {
+      const headroom: number = Math.ceil(parentStaffline.SkyBottomLineCalculator.getSkyLineMinInRange(startX, stopX));
+      if (headroom === Infinity) { // will cause Vexflow error
+          return;
+      }
+      (textBracket.start.getStave().options as any).top_text_position = Math.abs(headroom);
+      parentStaffline.SkyBottomLineCalculator.updateSkyLineInRange(startX, stopX, headroom - fontSize * 2);
+    } else {
+        const footroom: number = parentStaffline.SkyBottomLineCalculator.getBottomLineMaxInRange(startX, stopX);
+        if (footroom === Infinity) { // will cause Vexflow error
+            return;
+        }
+        (textBracket.start.getStave().options as any).bottom_text_position = footroom;
+        //Vexflow positions top vs. bottom text in a slightly inconsistent way it seems
+        parentStaffline.SkyBottomLineCalculator.updateBottomLineInRange(startX, stopX, footroom + fontSize * 1.5);
+    }
+  }
+
   /**
    * Calculate all the textual and symbolic [[RepetitionInstruction]]s (e.g. dal segno) for a single [[SourceMeasure]].
    * @param repetitionInstruction

+ 2 - 16
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -316,24 +316,10 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
     protected drawOctaveShifts(staffLine: StaffLine): void {
         for (const graphicalOctaveShift of staffLine.OctaveShifts) {
             if (graphicalOctaveShift) {
+                const vexFlowOctaveShift: VexFlowOctaveShift = graphicalOctaveShift as VexFlowOctaveShift;
                 const ctx: Vex.IRenderContext = this.backend.getContext();
-                const textBracket: Vex.Flow.TextBracket = (graphicalOctaveShift as VexFlowOctaveShift).getTextBracket();
+                const textBracket: Vex.Flow.TextBracket = vexFlowOctaveShift.getTextBracket();
                 textBracket.setContext(ctx);
-                const startX: number = staffLine.PositionAndShape.AbsolutePosition.x + textBracket.start.getX() / 10;
-                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();
             }
         }