瀏覽代碼

fix(Expressions): Octaveshift line breaks work now

Octaveshifts that start on one staffline and continue on another are rendered correctly now. Test
files added

#309
Benjamin Giesinger 6 年之前
父節點
當前提交
e2b1780320

+ 1 - 0
demo/index.js

@@ -26,6 +26,7 @@ import { OpenSheetMusicDisplay } from '../src/OpenSheetMusicDisplay/OpenSheetMus
             "OSMD Function Test - Grace Notes": "OSMD_function_test_GraceNotes.xml",
             "OSMD Function Test - Ornaments": "OSMD_function_test_Ornaments.xml",
             "OSMD Function Test - Accidentals": "OSMD_function_test_accidentals.musicxml",
+            "OSMD Function Test - Expressions": "OSMD_function_test_expressions.musicxml",
             "Schubert, F. - An Die Musik": "Schubert_An_die_Musik.xml",
             "Actor, L. - Prelude (Sample)": "ActorPreludeSample.xml",
             "Anonymous - Saltarello": "Saltarello.mxl",

+ 39 - 7
src/MusicalScore/Graphical/SkyBottomLineCalculator.ts

@@ -1,10 +1,11 @@
-import {EngravingRules} from "./EngravingRules";
-import {StaffLine} from "./StaffLine";
-import {PointF2D} from "../../Common/DataObjects/PointF2D";
-import {CanvasVexFlowBackend} from "./VexFlow/CanvasVexFlowBackend";
-import {VexFlowMeasure} from "./VexFlow/VexFlowMeasure";
-import {unitInPixels} from "./VexFlow/VexFlowMusicSheetDrawer";
+import { EngravingRules } from "./EngravingRules";
+import { StaffLine } from "./StaffLine";
+import { PointF2D } from "../../Common/DataObjects/PointF2D";
+import { CanvasVexFlowBackend } from "./VexFlow/CanvasVexFlowBackend";
+import { VexFlowMeasure } from "./VexFlow/VexFlowMeasure";
+import { unitInPixels } from "./VexFlow/VexFlowMusicSheetDrawer";
 import * as log from "loglevel";
+import { BoundingBox } from "./BoundingBox";
 /**
  * This class calculates and holds the skyline and bottom line information.
  * It also has functions to update areas of the two lines if new elements are
@@ -147,7 +148,7 @@ export class SkyBottomLineCalculator {
         const ctx: any = backend.getContext();
         const oldStyle: string = ctx.fillStyle;
         ctx.fillStyle = color;
-        ctx.fillRect( coord.x, coord.y, 2, 2 );
+        ctx.fillRect(coord.x, coord.y, 2, 2);
         ctx.fillStyle = oldStyle;
     }
 
@@ -366,6 +367,37 @@ export class SkyBottomLineCalculator {
         return this.getMaxInRange(this.BottomLine, startIndex, endIndex);
     }
 
+    /**
+     * This method finds the BottomLine's maximum value within a given range.
+     * @param staffLine Staffline to find the max value in
+     * @param startIndex Start index of the range
+     * @param endIndex End index of the range
+     */
+
+
+    /**
+     * This method returns the maximum value of the bottom line around a specific
+     * bounding box. Will return undefined if the bounding box is not valid or inside staffline
+     * @param boundingBox Bounding box where the maximum should be retrieved from
+     * @returns Maximum value inside bounding box boundaries or undefined if not possible
+     */
+    public getBottomLineMaxInBoundingBox(boundingBox: BoundingBox): number {
+        // FIXME: See if this really works as expected!
+        let iteratorBB: BoundingBox = boundingBox;
+        let startIndex: number = boundingBox.BorderLeft;
+        let endIndex: number = boundingBox.BorderRight;
+        let successfull: boolean = false;
+        while (iteratorBB.Parent) {
+            if (iteratorBB === this.mStaffLineParent.PositionAndShape) {
+                successfull = true;
+                break;
+            }
+            startIndex += iteratorBB.BorderLeft;
+            endIndex += iteratorBB.BorderRight;
+            iteratorBB = iteratorBB.Parent;
+        }
+        return successfull ? this.getMaxInRange(this.BottomLine, startIndex, endIndex) : undefined;
+    }
 
     //#region Private methods
 

+ 3 - 3
src/MusicalScore/Graphical/VexFlow/VexFlowInstantaniousDynamicExpression.ts

@@ -22,9 +22,9 @@ export class VexFlowInstantaniousDynamicExpression extends GraphicalInstantaniou
                                          EngravingRules.Rules.ContinuousDynamicTextHeight,
                                          TextAlignment.LeftTop,
                                          staffEntry.PositionAndShape);
-        // FIXME: Add offset when skyline available
-        // const offset: number = staffEntry.parentMeasure.ParentStaffLine.SkyBottomCalculator ...
-        const offset: number = 5.5;
+
+        const offset: number = staffEntry.parentMeasure.ParentStaffLine
+                                       .SkyBottomLineCalculator.getBottomLineMaxInBoundingBox(staffEntry.parentMeasure.PositionAndShape);
         this.mLabel.PositionAndShape.RelativePosition.y += offset;
         this.mLabel.Label.fontStyle = FontStyles.BoldItalic;
     }

+ 21 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -353,7 +353,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
         const measure: GraphicalMeasure = this.graphicalMusicSheet.MeasureList[measureIndex][staffIndex];
         const startStaffEntry: GraphicalStaffEntry = measure.findGraphicalStaffEntryFromTimestamp(timeStamp);
         const idx: VexFlowInstantaniousDynamicExpression = new VexFlowInstantaniousDynamicExpression(multiExpression.InstantaniousDynamic, startStaffEntry);
-        idx.calculcateBottomLine(measure);
+        // idx.calculcateBottomLine(measure);
         (measure as VexFlowMeasure).instantaniousDynamics.push(idx);
     }
   }
@@ -384,6 +384,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
       startMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(octaveShift.ParentStartMultiExpression.SourceMeasureParent,
                                                                                            staffIndex);
     }
+
     if (endMeasure !== undefined) {
         // calculate GraphicalOctaveShift and RelativePositions
         const graphicalOctaveShift: VexFlowOctaveShift = new VexFlowOctaveShift(octaveShift, startStaffLine.PositionAndShape);
@@ -394,7 +395,25 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
         const endStaffEntry: GraphicalStaffEntry = endMeasure.findGraphicalStaffEntryFromTimestamp(endTimeStamp);
 
         graphicalOctaveShift.setStartNote(startStaffEntry);
-        graphicalOctaveShift.setEndNote(endStaffEntry);
+
+        if (endMeasure.ParentStaffLine !== startMeasure.ParentStaffLine) {
+          graphicalOctaveShift.endsOnDifferentStaffLine = true;
+          const lastMeasure: GraphicalMeasure = startMeasure.ParentStaffLine.Measures[startMeasure.ParentStaffLine.Measures.length - 1];
+          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];
+          const firstNote: GraphicalStaffEntry = firstMeasure.staffEntries[0];
+          remainingOctaveShift.setStartNote(firstNote);
+          remainingOctaveShift.setEndNote(endStaffEntry);
+        } else {
+          graphicalOctaveShift.setEndNote(endStaffEntry);
+        }
+    } else {
+      log.warn("End measure for octave shift is undefined! This should not happen!");
     }
   }
 

+ 275 - 51
test/data/Expression_Test.musicxml → test/data/OSMD_function_test_expressions.musicxml

@@ -7,7 +7,7 @@
   <identification>
     <encoding>
       <software>MuseScore 2.2.1</software>
-      <encoding-date>2018-06-04</encoding-date>
+      <encoding-date>2018-08-15</encoding-date>
       <supports element="accidental" type="yes"/>
       <supports element="beam" type="yes"/>
       <supports element="print" attribute="new-page" type="yes" value="yes"/>
@@ -59,18 +59,18 @@
       </score-part>
     </part-list>
   <part id="P1">
-    <measure number="1" width="257.52">
+    <measure number="1" width="259.32">
       <print>
         <system-layout>
           <system-margins>
-            <left-margin>-0.00</left-margin>
+            <left-margin>0.00</left-margin>
             <right-margin>0.00</right-margin>
             </system-margins>
           <top-system-distance>170.00</top-system-distance>
           </system-layout>
         </print>
       <attributes>
-        <divisions>1</divisions>
+        <divisions>2</divisions>
         <key>
           <fifths>0</fifths>
           </key>
@@ -101,17 +101,17 @@
           <step>C</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="120.36" default-y="-45.00">
+      <note default-x="120.81" default-y="-45.00">
         <pitch>
           <step>D</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
@@ -124,28 +124,28 @@
           </direction-type>
         <sound dynamics="54.44"/>
         </direction>
-      <note default-x="165.55" default-y="-40.00">
+      <note default-x="166.45" default-y="-40.00">
         <pitch>
           <step>E</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="210.73" default-y="-35.00">
+      <note default-x="212.08" default-y="-35.00">
         <pitch>
           <step>F</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
       </measure>
-    <measure number="2" width="202.74">
+    <measure number="2" width="204.54">
       <direction placement="below">
         <direction-type>
           <dynamics default-x="6.58" default-y="-80.00">
@@ -159,17 +159,17 @@
           <step>C</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="59.29" default-y="-45.00">
+      <note default-x="59.74" default-y="-45.00">
         <pitch>
           <step>D</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
@@ -182,22 +182,22 @@
           </direction-type>
         <sound dynamics="106.67"/>
         </direction>
-      <note default-x="106.57" default-y="-40.00">
+      <note default-x="107.47" default-y="-40.00">
         <pitch>
           <step>E</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="153.86" default-y="-35.00">
+      <note default-x="155.21" default-y="-35.00">
         <pitch>
           <step>F</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
@@ -208,7 +208,7 @@
           </direction-type>
         </direction>
       </measure>
-    <measure number="3" width="202.74">
+    <measure number="3" width="204.54">
       <direction placement="below">
         <direction-type>
           <octave-shift type="up" size="8" number="1" default-y="-79.41"/>
@@ -219,37 +219,37 @@
           <step>C</step>
           <octave>3</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="59.29" default-y="-45.00">
+      <note default-x="59.74" default-y="-45.00">
         <pitch>
           <step>D</step>
           <octave>3</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="106.57" default-y="-40.00">
+      <note default-x="107.47" default-y="-40.00">
         <pitch>
           <step>E</step>
           <octave>3</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="153.86" default-y="-35.00">
+      <note default-x="155.21" default-y="-35.00">
         <pitch>
           <step>F</step>
           <octave>3</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
@@ -260,7 +260,7 @@
           </direction-type>
         </direction>
       </measure>
-    <measure number="4" width="202.74">
+    <measure number="4" width="204.54">
       <direction placement="below">
         <direction-type>
           <wedge type="diminuendo" number="1" default-y="-75.43" relative-x="-1.43"/>
@@ -271,37 +271,37 @@
           <step>C</step>
           <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>down</stem>
         </note>
-      <note default-x="59.29" default-y="-20.00">
+      <note default-x="59.74" default-y="-20.00">
         <pitch>
           <step>B</step>
           <octave>4</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>down</stem>
         </note>
-      <note default-x="106.57" default-y="-25.00">
+      <note default-x="107.47" default-y="-25.00">
         <pitch>
           <step>A</step>
           <octave>4</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="153.86" default-y="-30.00">
+      <note default-x="155.21" default-y="-30.00">
         <pitch>
           <step>G</step>
           <octave>4</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
@@ -312,51 +312,53 @@
           </direction-type>
         </direction>
       </measure>
-    <measure number="5" width="211.74">
-      <barline location="left">
-        <ending number="1" type="start" default-y="28.57"/>
-        </barline>
+    <measure number="5" width="204.54">
       <direction placement="below">
         <direction-type>
           <wedge type="crescendo" number="1" default-y="-75.00"/>
           </direction-type>
         </direction>
+      <direction placement="above">
+        <direction-type>
+          <octave-shift type="down" size="15" number="1" default-y="30.00"/>
+          </direction-type>
+        </direction>
       <note default-x="12.00" default-y="-15.00">
         <pitch>
           <step>C</step>
-          <octave>5</octave>
+          <octave>6</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>down</stem>
         </note>
-      <note default-x="59.29" default-y="-20.00">
+      <note default-x="59.74" default-y="-20.00">
         <pitch>
           <step>B</step>
-          <octave>4</octave>
+          <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>down</stem>
         </note>
-      <note default-x="106.57" default-y="-25.00">
+      <note default-x="107.47" default-y="-25.00">
         <pitch>
           <step>A</step>
-          <octave>4</octave>
+          <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
         </note>
-      <note default-x="153.86" default-y="-30.00">
+      <note default-x="155.21" default-y="-30.00">
         <pitch>
           <step>G</step>
-          <octave>4</octave>
+          <octave>5</octave>
           </pitch>
-        <duration>1</duration>
+        <duration>2</duration>
         <voice>1</voice>
         <type>quarter</type>
         <stem>up</stem>
@@ -366,9 +368,231 @@
           <wedge type="stop" number="1"/>
           </direction-type>
         </direction>
+      </measure>
+    <measure number="6" width="246.92">
+      <print new-system="yes">
+        <system-layout>
+          <system-margins>
+            <left-margin>0.00</left-margin>
+            <right-margin>0.00</right-margin>
+            </system-margins>
+          <system-distance>150.00</system-distance>
+          </system-layout>
+        </print>
+      <note default-x="49.07" default-y="-15.00">
+        <pitch>
+          <step>C</step>
+          <octave>6</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>down</stem>
+        </note>
+      <note default-x="98.14" default-y="-20.00">
+        <pitch>
+          <step>B</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>down</stem>
+        </note>
+      <note default-x="147.20" default-y="-30.00">
+        <pitch>
+          <step>G</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        </note>
+      <note default-x="196.26" default-y="-10.00">
+        <pitch>
+          <step>D</step>
+          <octave>6</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>down</stem>
+        </note>
+      <direction placement="above">
+        <direction-type>
+          <octave-shift type="stop" size="15" number="1"/>
+          </direction-type>
+        </direction>
+      </measure>
+    <measure number="7" width="284.43">
+      <note default-x="12.00" default-y="-10.00">
+        <pitch>
+          <step>D</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>down</stem>
+        <beam number="1">begin</beam>
+        </note>
+      <note default-x="45.85" default-y="-15.00">
+        <pitch>
+          <step>C</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>down</stem>
+        <beam number="1">continue</beam>
+        </note>
+      <note default-x="45.85" default-y="0.00">
+        <chord/>
+        <pitch>
+          <step>F</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>down</stem>
+        </note>
+      <note default-x="79.71" default-y="-35.00">
+        <pitch>
+          <step>F</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>down</stem>
+        <beam number="1">continue</beam>
+        </note>
+      <note default-x="79.71" default-y="0.00">
+        <chord/>
+        <pitch>
+          <step>F</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>down</stem>
+        </note>
+      <note default-x="113.56" default-y="10.00">
+        <pitch>
+          <step>A</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>down</stem>
+        <beam number="1">end</beam>
+        </note>
+      <direction placement="below">
+        <direction-type>
+          <dynamics default-x="6.58" default-y="-80.00">
+            <ff/>
+            </dynamics>
+          </direction-type>
+        <sound dynamics="124.44"/>
+        </direction>
+      <note default-x="147.41" default-y="-30.00">
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>up</stem>
+        </note>
+      <note>
+        <rest/>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        </note>
+      <note default-x="215.12" default-y="-5.00">
+        <pitch>
+          <step>E</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>down</stem>
+        </note>
+      <note>
+        <rest/>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        </note>
+      </measure>
+    <measure number="8" width="174.57">
+      <note default-x="12.00" default-y="-20.00">
+        <pitch>
+          <step>B</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>8</duration>
+        <voice>1</voice>
+        <type>whole</type>
+        </note>
+      </measure>
+    <measure number="9" width="174.57">
+      <note default-x="12.00" default-y="-15.00">
+        <pitch>
+          <step>C</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>8</duration>
+        <voice>1</voice>
+        <type>whole</type>
+        </note>
+      </measure>
+    <measure number="10" width="197.00">
+      <barline location="left">
+        <ending number="1" type="start" default-y="31.43" relative-x="-1.57"/>
+        </barline>
+      <note default-x="12.00" default-y="-30.00">
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>4</duration>
+        <voice>1</voice>
+        <type>half</type>
+        <stem>down</stem>
+        </note>
+      <note default-x="12.00" default-y="-10.00">
+        <chord/>
+        <pitch>
+          <step>D</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>4</duration>
+        <voice>1</voice>
+        <type>half</type>
+        <stem>down</stem>
+        </note>
+      <note default-x="99.02" default-y="-30.00">
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>4</duration>
+        <voice>1</voice>
+        <type>half</type>
+        <stem>up</stem>
+        </note>
       <barline location="right">
         <bar-style>light-heavy</bar-style>
-        <ending number="1" type="discontinue"/>
+        <ending number="1" type="discontinue" relative-x="-3.41"/>
         </barline>
       </measure>
     </part>