Преглед на файлове

merge osmd-public 1.5.8 (fix bounding boxes and margins for renderSingeHorizontalStaffline, ignore brackets by default)

sschmidTU преди 2 години
родител
ревизия
af8f6ff22f

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "osmd-extended",
-  "version": "1.5.7",
+  "version": "1.5.8",
   "description": "Private / sponsor exclusive OSMD mirror/audio player.",
   "main": "build/opensheetmusicdisplay.min.js",
   "types": "build/dist/src/index.d.ts",

+ 2 - 9
src/MusicalScore/Graphical/BoundingBox.ts

@@ -3,10 +3,8 @@ import {ArgumentOutOfRangeException} from "../Exceptions";
 import {PointF2D} from "../../Common/DataObjects/PointF2D";
 import {SizeF2D} from "../../Common/DataObjects/SizeF2D";
 import {RectangleF2D} from "../../Common/DataObjects/RectangleF2D";
-import { StaffLineActivitySymbol } from "./StaffLineActivitySymbol";
-import { EngravingRules } from "./EngravingRules";
-import { Clickable } from "./Clickable";
 import { GraphicalObject } from "./GraphicalObject";
+import { Clickable } from "./Clickable";
 
 /**
  * A bounding box delimits an area on the 2D plane.
@@ -380,12 +378,7 @@ export class BoundingBox {
         for (let idx: number = 0, len: number = this.ChildElements.length; idx < len; ++idx) {
             const childElement: BoundingBox = this.ChildElements[idx];
             minTop = Math.min(minTop, childElement.relativePosition.y + childElement.borderTop);
-            if (!EngravingRules.FixStafflineBoundingBox || !(childElement.dataObject instanceof StaffLineActivitySymbol)) {
-                maxBottom = Math.max(maxBottom, childElement.relativePosition.y + childElement.borderBottom);
-                // TODO there's a problem with the bottom bounding box of many stafflines, often caused by StaffLineActivitySymbol,
-                // often leading to the page SVG canvas being unnecessarily long in y-direction. This seems to be remedied by this workaround.
-                // see #643
-            }
+            maxBottom = Math.max(maxBottom, childElement.relativePosition.y + childElement.borderBottom);
             minMarginTop = Math.min(minMarginTop, childElement.relativePosition.y + childElement.borderMarginTop);
             maxMarginBottom = Math.max(maxMarginBottom, childElement.relativePosition.y + childElement.borderMarginBottom);
         }

+ 5 - 4
src/MusicalScore/Graphical/EngravingRules.ts

@@ -352,14 +352,16 @@ export class EngravingRules {
     public RenderSingleHorizontalStaffline: boolean;
     public RestoreCursorAfterRerender: boolean;
     public StretchLastSystemLine: boolean;
+    /** Ignore brackets - e.g. `( )` - that were supposed to be around a note,
+     * but were inserted as a words element in the MusicXML, which can't be matched to the note anymore,
+     * and would otherwise just be placed somewhere else. See OSMD Issue 1251. */
+    public IgnoreBracketsWords: boolean;
     public SpacingBetweenTextLines: number;
 
     public NoteToGraphicalNoteMap: Dictionary<number, GraphicalNote>;
     // this is basically a WeakMap, except we save the id in the Note instead of using a WeakMap.
     public NoteToGraphicalNoteMapObjectCount: number = 0;
 
-    public static FixStafflineBoundingBox: boolean; // TODO temporary workaround
-
     /** The skyline and bottom-line batch calculation algorithm to use.
      *  Note that this can be overridden if AlwaysSetPreferredSkyBottomLineBackendAutomatically is true (which is the default).
      */
@@ -723,8 +725,7 @@ export class EngravingRules {
         this.NewPageAtXMLNewPageAttribute = false;
         this.RestoreCursorAfterRerender = true;
         this.StretchLastSystemLine = false;
-
-        EngravingRules.FixStafflineBoundingBox = false; // TODO temporary workaround
+        this.IgnoreBracketsWords = true;
 
         this.UseJustifiedBuilder = true;
         this.PageFormat = PageFormat.UndefinedPageFormat; // default: undefined / 'infinite' height page, using the canvas'/container's width and height

+ 13 - 11
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -962,13 +962,14 @@ export abstract class MusicSheetCalculator {
                 musicSystem.PositionAndShape.RelativePosition =
                     new PointF2D(musicSystem.PositionAndShape.RelativePosition.x, musicSystem.PositionAndShape.RelativePosition.y - distance);
             }
-            for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
-                const musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
-                for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
-                    const staffLine: StaffLine = musicSystem.StaffLines[idx3];
-                    staffLine.addActivitySymbolClickArea();
-                }
-            }
+            // add ActivitySymbolClickArea - currently unused, extends boundingbox of MusicSystem unnecessarily -> PageRightMargin 0 impossible
+            // for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
+            //     const musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+            //     for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
+            //         const staffLine: StaffLine = musicSystem.StaffLines[idx3];
+            //         staffLine.addActivitySymbolClickArea();
+            //     }
+            // }
 
             // calculate TopBottom Borders for all elements recursively
             //   necessary for composer label (page labels) for high notes in first system
@@ -2136,6 +2137,7 @@ export abstract class MusicSheetCalculator {
     protected calculatePageLabels(page: GraphicalMusicPage): void {
         if (this.rules.RenderSingleHorizontalStaffline) {
             page.PositionAndShape.BorderRight = page.PositionAndShape.Size.width;
+            //page.PositionAndShape.BorderRight = page.PositionAndShape.Size.width + this.rules.PageRightMargin;
             page.PositionAndShape.calculateBoundingBox();
             this.graphicalMusicSheet.ParentMusicSheet.pageWidth = page.PositionAndShape.Size.width;
         }
@@ -2147,7 +2149,7 @@ export abstract class MusicSheetCalculator {
             firstSystemAbsoluteTopMargin = firstMusicSystem.PositionAndShape.RelativePosition.y + firstMusicSystem.PositionAndShape.BorderTop;
         }
         //const firstStaffLine: StaffLine = this.graphicalMusicSheet.MusicPages[0].MusicSystems[0].StaffLines[0];
-        if (this.graphicalMusicSheet.Title) {
+        if (this.graphicalMusicSheet.Title && this.rules.RenderTitle) {
             const title: GraphicalLabel = this.graphicalMusicSheet.Title;
             title.PositionAndShape.Parent = page.PositionAndShape;
             //title.PositionAndShape.Parent = firstStaffLine.PositionAndShape;
@@ -2158,7 +2160,7 @@ export abstract class MusicSheetCalculator {
             title.PositionAndShape.RelativePosition = relative;
             page.Labels.push(title);
         }
-        if (this.graphicalMusicSheet.Subtitle) {
+        if (this.graphicalMusicSheet.Subtitle && this.rules.RenderTitle && this.rules.RenderSubtitle) {
             const subtitle: GraphicalLabel = this.graphicalMusicSheet.Subtitle;
             //subtitle.PositionAndShape.Parent = firstStaffLine.PositionAndShape;
             subtitle.PositionAndShape.Parent = page.PositionAndShape;
@@ -2175,7 +2177,7 @@ export abstract class MusicSheetCalculator {
         //   we don't need a skybottomcalculator currently, labels are put above system skyline anyways.
         const composer: GraphicalLabel = this.graphicalMusicSheet.Composer;
         let composerRelativeY: number;
-        if (composer) {
+        if (composer && this.rules.RenderComposer) {
             composer.PositionAndShape.Parent = page.PositionAndShape; // if using pageWidth. (which can currently be too wide) TODO fix pageWidth (#578)
             //composer.PositionAndShape.Parent = topStaffline.PositionAndShape; // if using firstStaffLine...width.
             //      y-collision problems, harder to y-align with lyrics
@@ -2217,7 +2219,7 @@ export abstract class MusicSheetCalculator {
             page.Labels.push(composer);
         }
         const lyricist: GraphicalLabel = this.graphicalMusicSheet.Lyricist;
-        if (lyricist) {
+        if (lyricist && this.rules.RenderLyricist) {
             lyricist.PositionAndShape.Parent = page.PositionAndShape;
             lyricist.setLabelPositionAndShapeBorders();
             const relative: PointF2D = new PointF2D();

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

@@ -556,6 +556,11 @@ export abstract class MusicSheetDrawer {
             // } else if (type === "VexFlowContinuousDynamicExpression") {
             //     typeMatch = startBox.DataObject instanceof VexFlowContinuousDynamicExpression;
             // }
+            // else if (type === "MusicSystem") {
+            //     typeMatch = startBox.DataObject instanceof MusicSystem;
+            // } else if (type === "GraphicalMusicPage") {
+            //     typeMatch = startBox.DataObject instanceof GraphicalMusicPage;
+            // }
         }
         if (typeMatch || dataObjectString === type) {
             this.drawBoundingBox(startBox, undefined, true, dataObjectString, layer);

+ 4 - 2
src/MusicalScore/Graphical/MusicSystem.ts

@@ -134,8 +134,10 @@ export abstract class MusicSystem extends GraphicalObject {
         leftSystemLine.PositionAndShape.RelativePosition = new PointF2D(xPosition, 0);
         leftSystemLine.PositionAndShape.BorderLeft = 0;
         leftSystemLine.PositionAndShape.BorderRight = lineWidth;
-        leftSystemLine.PositionAndShape.BorderTop = 0;
-        leftSystemLine.PositionAndShape.BorderBottom = this.boundingBox.Size.height;
+        leftSystemLine.PositionAndShape.BorderTop = leftSystemLine.PositionAndShape.Parent.BorderTop;
+        leftSystemLine.PositionAndShape.BorderBottom = leftSystemLine.PositionAndShape.Parent.BorderBottom;
+        // TODO this is arguably still too large for the systemline bbox, but at least not larger than the MusicSystem anymore.
+        //   see https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/1245
         this.createLinesForSystemLine(leftSystemLine);
     }
 

+ 1 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -692,7 +692,7 @@ export class VexFlowMeasure extends GraphicalMeasure {
                     // if (note.isRest()) // TODO somehow there are never rest notes in ve.Notes
                     // TODO also, grace notes are not included here, need to be fixed as well. (and a few triple beamed notes in Bach Air)
                     let relPosY: number = 0;
-                    if (gNote.parentVoiceEntry.parentVoiceEntry.StemDirection === StemDirectionType.Up) {
+                    if (gNote.parentVoiceEntry.parentVoiceEntry.StemDirection === StemDirectionType.Up && gNote.vfnote[0].getDuration() !== "w") {
                         relPosY += 3.5; // about 3.5 lines too high. this seems to be related to the default stem height, not actual stem height.
                         // alternate calculation using actual stem height: somehow wildly varying.
                         // if (ve.Notes.length > 1) {

+ 1 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSystem.ts

@@ -25,6 +25,7 @@ export class VexFlowMusicSystem extends MusicSystem {
         const width: number = this.calcBracketsWidth();
         this.boundingBox.BorderLeft = -width;
         this.boundingBox.BorderMarginLeft = -width;
+        //this.boundingBox.BorderRight = this.rules.SystemRightMargin;
         this.boundingBox.XBordersHaveBeenSet = true;
 
         const topSkyBottomLineCalculator: SkyBottomLineCalculator = this.staffLines[0].SkyBottomLineCalculator;

+ 3 - 0
src/MusicalScore/ScoreIO/MusicSymbolModules/ExpressionReader.ts

@@ -532,6 +532,9 @@ export class ExpressionReader {
     }
     private interpretWords(wordsNode: IXmlElement, currentMeasure: SourceMeasure, inSourceMeasureCurrentFraction: Fraction): void {
         const text: string = wordsNode.value;
+        if (currentMeasure.Rules.IgnoreBracketsWords && /^\(\s*\)$/.test(text)) { // regex: brackets with arbitrary white space in-between
+            return;
+        }
         let fontStyle: FontStyles;
         const fontStyleAttr: Attr = wordsNode.attribute("font-style");
         if (fontStyleAttr) {

+ 14 - 3
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -35,7 +35,7 @@ import { DynamicsCalculator } from "../MusicalScore/ScoreIO/MusicSymbolModules/D
  * After the constructor, use load() and render() to load and render a MusicXML file.
  */
 export class OpenSheetMusicDisplay {
-    private version: string = "1.5.7-audio-extended"; // getter: this.Version
+    private version: string = "1.5.8-audio-extended"; // getter: this.Version
     // at release, bump version and change to -release, afterwards to -dev again
 
     /**
@@ -372,7 +372,8 @@ export class OpenSheetMusicDisplay {
         // Set page width
         let width: number = this.container.offsetWidth;
         if (this.rules.RenderSingleHorizontalStaffline) {
-            width = this.graphic.MusicPages[0].PositionAndShape.Size.width * 10 * this.zoom;
+            width = (this.EngravingRules.PageLeftMargin + this.graphic.MusicPages[0].PositionAndShape.Size.width + this.EngravingRules.PageRightMargin)
+                * 10 * this.zoom;
             // this.container.style.width = width + "px";
             // console.log("width: " + width)
         }
@@ -399,7 +400,17 @@ export class OpenSheetMusicDisplay {
             } else {
                 height = page.PositionAndShape.Size.height;
                 height += this.rules.PageBottomMargin;
-                height += this.rules.CompactMode ? this.rules.PageTopMarginNarrow : this.rules.PageTopMargin;
+                if (backend.getOSMDBackendType() === BackendType.Canvas) {
+                    height += 0.1; // Canvas bug: cuts off bottom pixel with PageBottomMargin = 0. Doesn't happen with SVG.
+                    //  we could only add 0.1 if PageBottomMargin === 0, but that would mean a margin of 0.1 has no effect compared to 0.
+                }
+                //height += this.rules.CompactMode ? this.rules.PageTopMarginNarrow : this.rules.PageTopMargin;
+                // adding the PageTopMargin with a composer label leads to the margin also added to the bottom of the page
+                height += page.PositionAndShape.BorderTop;
+                // try to respect elements like composer cut off: this gets messy.
+                // if (page.PositionAndShape.BorderTop < 0 && this.rules.PageTopMargin === 0) {
+                //     height += page.PositionAndShape.BorderTop + this.rules.PageTopMargin;
+                // }
                 if (this.rules.RenderTitle) {
                     height += this.rules.TitleTopDistance;
                 }

+ 5 - 0
test/Util/generateImages_browserless.mjs

@@ -320,6 +320,8 @@ async function generateSampleImage (sampleFilename, directory, osmdInstance, osm
         const defaultOrCompactTightMode = sampleFilename.startsWith("OSMD_Function_Test_Container_height") ? "compacttight" : "default";
         const isTestFlatBeams = sampleFilename.startsWith("test_drum_tuplet_beams");
         const isTestEndClefStaffEntryBboxes = sampleFilename.startsWith("test_end_measure_clefs_staffentry_bbox");
+        const isTestPageBottomMargin0 = sampleFilename.includes("PageBottomMargin0");
+        osmdInstance.EngravingRules.loadDefaultValues();
         if (isTestEndClefStaffEntryBboxes) {
             drawBoundingBoxString = "VexFlowStaffEntry";
         } else {
@@ -353,6 +355,9 @@ async function generateSampleImage (sampleFilename, directory, osmdInstance, osm
         } else {
             osmdInstance.EngravingRules.FlatBeams = false;
         }
+        if (isTestPageBottomMargin0) {
+            osmdInstance.EngravingRules.PageBottomMargin = 0;
+        }
     }
 
     try {

+ 106 - 0
test/data/test_PageBottomMargin0.musicxml

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="3.1">
+  <work>
+    <work-title>test_PageBottomMargin0</work-title>
+    </work>
+  <identification>
+    <creator type="composer">Composer</creator>
+    <encoding>
+      <software>MuseScore 3.6.2</software>
+      <encoding-date>2022-09-30</encoding-date>
+      <supports element="accidental" type="yes"/>
+      <supports element="beam" type="yes"/>
+      <supports element="print" attribute="new-page" type="yes" value="yes"/>
+      <supports element="print" attribute="new-system" type="yes" value="yes"/>
+      <supports element="stem" type="yes"/>
+      </encoding>
+    </identification>
+  <defaults>
+    <scaling>
+      <millimeters>6.99911</millimeters>
+      <tenths>40</tenths>
+      </scaling>
+    <page-layout>
+      <page-height>1596.77</page-height>
+      <page-width>1233.87</page-width>
+      <page-margins type="even">
+        <left-margin>85.7252</left-margin>
+        <right-margin>85.7252</right-margin>
+        <top-margin>85.7252</top-margin>
+        <bottom-margin>85.7252</bottom-margin>
+        </page-margins>
+      <page-margins type="odd">
+        <left-margin>85.7252</left-margin>
+        <right-margin>85.7252</right-margin>
+        <top-margin>85.7252</top-margin>
+        <bottom-margin>85.7252</bottom-margin>
+        </page-margins>
+      </page-layout>
+    <word-font font-family="Edwin" font-size="10"/>
+    <lyric-font font-family="Edwin" font-size="10"/>
+    </defaults>
+  <credit page="1">
+    <credit-type>title</credit-type>
+    <credit-words default-x="616.935" default-y="1511.05" justify="center" valign="top" font-size="22">Title</credit-words>
+    </credit>
+  <credit page="1">
+    <credit-type>composer</credit-type>
+    <credit-words default-x="1148.15" default-y="1411.05" justify="right" valign="bottom">Composer</credit-words>
+    </credit>
+  <part-list>
+    <score-part id="P1">
+      <part-name>Piano</part-name>
+      <part-abbreviation>Pno.</part-abbreviation>
+      <score-instrument id="P1-I1">
+        <instrument-name>Piano</instrument-name>
+        </score-instrument>
+      <midi-device id="P1-I1" port="1"></midi-device>
+      <midi-instrument id="P1-I1">
+        <midi-channel>1</midi-channel>
+        <midi-program>1</midi-program>
+        <volume>78.7402</volume>
+        <pan>0</pan>
+        </midi-instrument>
+      </score-part>
+    </part-list>
+  <part id="P1">
+    <measure number="1" width="313.47">
+      <print>
+        <system-layout>
+          <system-margins>
+            <left-margin>50.00</left-margin>
+            <right-margin>665.23</right-margin>
+            </system-margins>
+          <top-system-distance>170.00</top-system-distance>
+          </system-layout>
+        </print>
+      <attributes>
+        <divisions>1</divisions>
+        <key>
+          <fifths>0</fifths>
+          </key>
+        <time>
+          <beats>4</beats>
+          <beat-type>4</beat-type>
+          </time>
+        <clef>
+          <sign>G</sign>
+          <line>2</line>
+          </clef>
+        </attributes>
+      <note default-x="84.22" default-y="-80.00">
+        <pitch>
+          <step>D</step>
+          <octave>3</octave>
+          </pitch>
+        <duration>4</duration>
+        <voice>1</voice>
+        <type>whole</type>
+        </note>
+      <barline location="right">
+        <bar-style>light-heavy</bar-style>
+        </barline>
+      </measure>
+    </part>
+  </score-partwise>

+ 135 - 0
test/data/test_ignore_note_brackets.musicxml

@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="3.1">
+  <work>
+    <work-title>test_ignore_note_brackets</work-title>
+    </work>
+  <identification>
+    <encoding>
+      <software>MuseScore 3.6.2</software>
+      <encoding-date>2022-10-14</encoding-date>
+      <supports element="accidental" type="yes"/>
+      <supports element="beam" type="yes"/>
+      <supports element="print" attribute="new-page" type="yes" value="yes"/>
+      <supports element="print" attribute="new-system" type="yes" value="yes"/>
+      <supports element="stem" type="yes"/>
+      </encoding>
+    </identification>
+  <defaults>
+    <scaling>
+      <millimeters>6.99911</millimeters>
+      <tenths>40</tenths>
+      </scaling>
+    <page-layout>
+      <page-height>1596.77</page-height>
+      <page-width>1233.87</page-width>
+      <page-margins type="even">
+        <left-margin>85.7252</left-margin>
+        <right-margin>85.7252</right-margin>
+        <top-margin>85.7252</top-margin>
+        <bottom-margin>85.7252</bottom-margin>
+        </page-margins>
+      <page-margins type="odd">
+        <left-margin>85.7252</left-margin>
+        <right-margin>85.7252</right-margin>
+        <top-margin>85.7252</top-margin>
+        <bottom-margin>85.7252</bottom-margin>
+        </page-margins>
+      </page-layout>
+    <word-font font-family="Edwin" font-size="10"/>
+    <lyric-font font-family="Edwin" font-size="10"/>
+    </defaults>
+  <credit page="1">
+    <credit-type>title</credit-type>
+    <credit-words default-x="616.935" default-y="1511.05" justify="center" valign="top" font-size="22">test_ignore_note_brackets</credit-words>
+    </credit>
+  <part-list>
+    <score-part id="P1">
+      <part-name>Piano</part-name>
+      <part-abbreviation>Pno.</part-abbreviation>
+      <score-instrument id="P1-I1">
+        <instrument-name>Piano</instrument-name>
+        </score-instrument>
+      <midi-device id="P1-I1" port="1"></midi-device>
+      <midi-instrument id="P1-I1">
+        <midi-channel>1</midi-channel>
+        <midi-program>1</midi-program>
+        <volume>78.7402</volume>
+        <pan>0</pan>
+        </midi-instrument>
+      </score-part>
+    </part-list>
+  <part id="P1">
+    <measure number="1" width="335.93">
+      <print>
+        <system-layout>
+          <system-margins>
+            <left-margin>50.00</left-margin>
+            <right-margin>642.77</right-margin>
+            </system-margins>
+          <top-system-distance>170.00</top-system-distance>
+          </system-layout>
+        </print>
+      <attributes>
+        <divisions>1</divisions>
+        <key>
+          <fifths>0</fifths>
+          </key>
+        <time>
+          <beats>4</beats>
+          <beat-type>4</beat-type>
+          </time>
+        <clef>
+          <sign>G</sign>
+          <line>2</line>
+          </clef>
+        </attributes>
+      <direction placement="above">
+        <direction-type>
+          <words relative-x="-8.50" relative-y="-29.10">(   )</words>
+          </direction-type>
+        </direction>
+      <note default-x="80.72" default-y="-30.00">
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>half</type>
+        <stem>down</stem>
+        </note>
+      <note default-x="80.72" default-y="-20.00">
+        <chord/>
+        <pitch>
+          <step>B</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>half</type>
+        <stem>down</stem>
+        </note>
+      <note default-x="80.72" default-y="-10.00">
+        <chord/>
+        <pitch>
+          <step>D</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>half</type>
+        <stem>down</stem>
+        </note>
+      <note>
+        <rest/>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>half</type>
+        </note>
+      <barline location="right">
+        <bar-style>light-heavy</bar-style>
+        </barline>
+      </measure>
+    </part>
+  </score-partwise>