Просмотр исходного кода

Merge develop for 0.6.1 release

Release 0.6.0
sschmidTU 6 лет назад
Родитель
Сommit
3681315e14

+ 30 - 0
CHANGELOG.md

@@ -1,3 +1,33 @@
+<a name="0.6.0"></a>
+# [0.6.0](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/compare/0.5.1...0.6.0) (2018-10-18)
+
+
+### Bug Fixes
+
+* **accidentalOctaveShift:** place notes with octave brackets correctly ([#424](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/424)) ([43f13d5](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/43f13d5))
+* **ChordSymbolReader:** replace old <AccidentalEnum> conversions. fixes chord symbol reading (e.g. Ab). ([b8d41de](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/b8d41de)), closes [#418](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/418)
+* **ChordSymbols:** add y spacing so stems don't collide ([78cd2ed](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/78cd2ed))
+* **cue notes:** add as VF.GraceNote instead of VF.StaveNote ([8d1371f](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/8d1371f))
+* **grace notes:** can be at end of measure, after main note ([37f145d](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/37f145d))
+* **grace notes:** grace note beams handled like other beams now, can have any grace note beams ([94cc6b5](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/94cc6b5))
+* **invisible notes:** invisible rests formatting partly fixed by adding ghost notes ([3b0e19d](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/3b0e19d))
+* **resize:** handling, set autoResize at runtime, add osmd.clear(), demo null checks ([#428](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/428)) ([cf2111e](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/cf2111e)), closes [#403](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/403) [#387](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/387)
+* **stemDirection:** fix beam with grace note in middle bug ([#413](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/413)) ([a71496c](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/a71496c))
+* **tests:** fix null pointer in setStemDirection (Haydn test fail) ([ad89d96](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/ad89d96))
+* **VexFlowUpdate:** update to 1.2.87, fixes npm audit vulnerabilities
+
+### Features
+
+* **Expressions/Dynamics:** Add Crescendo wedges, texts, spacing, etc. ([#410](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/pull/410))
+* **Arpeggios:** Display arpeggios ([#411](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/411)) ([90ae82f](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/90ae82f))
+* **autoBeam:** add option to automatically beam notes ([09170a2](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/09170a2))
+* **cue notes: add cue notes as smaller notes.** grace notes can have articulations ([0094f1f](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/0094f1f)), closes [#349](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/349)
+* **fingering:** add fingerings to right, above, below, auto ([#406](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/406)) ([0e50f89](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/0e50f89)), closes [#350](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/350)
+* **fingering:** draw fingering using Vexflow, can be disabled by option ([628562b](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/628562b))
+* **NoteHeadShapes:** add square, rectangle note head ([b6a15ef](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/b6a15ef)), closes [#404](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/404)
+* **options:** Options now settable during runtime: public setOptions() ([76bd9bf](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/76bd9bf)), closes [#407](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/407)
+* **stemDirection:** use xml stem direction. (optionally) ([6373d58](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/commit/6373d58)), closes [#415](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/415)
+
 <a name="0.5.1"></a>
 ## [0.5.1](https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/compare/0.5.0...0.5.1) (2018-09-26)
 

+ 2 - 0
demo/index.js

@@ -24,6 +24,7 @@ import { OpenSheetMusicDisplay } from '../src/OpenSheetMusicDisplay/OpenSheetMus
         "OSMD Function Test - All": "OSMD_function_test_all.xml",
         "OSMD Function Test - Autobeam": "OSMD_function_test_autobeam.musicxml",
         "OSMD Function Test - Accidentals": "OSMD_function_test_accidentals.musicxml",
+        "OSMD Function Test - Color": "OSMD_function_test_color.musicxml",
         "OSMD Function Test - Drumset": "OSMD_function_test_drumset.musicxml",
         "OSMD Function Test - Expressions": "OSMD_function_test_expressions.musicxml",
         "OSMD Function Test - Expressions Overlap": "OSMD_function_test_expressions_overlap.musicxml",
@@ -143,6 +144,7 @@ import { OpenSheetMusicDisplay } from '../src/OpenSheetMusicDisplay/OpenSheetMus
         openSheetMusicDisplay = new OpenSheetMusicDisplay(canvas, {
             autoResize: true,
             backend: backendSelect.value,
+            coloringEnabled: true,
             disableCursor: false,
             drawingParameters: "default", // try compact (instead of default)
             drawPartNames: true, // try false

+ 13 - 1
external/vexflow/vexflow.d.ts

@@ -121,11 +121,18 @@ declare namespace Vex {
 
             public addAnnotation(index: number, annotation: Annotation): StaveNote;
 
+            public addDotToAll(): void;
+
             public addModifier(index: number, modifier: Modifier): StaveNote;
 
             public setStyle(style: any): void;
+            public setStemStyle(style: any): void;
+            public setFlagStyle(style: any): void;
 
-            public addDotToAll(): void;
+            // temp solution until noteheadStyles PR is through
+            public note_heads: any; // NoteHead[]; 
+            public flag: Element;
+            public beam: Beam;
         }
 
         export class GraceNote extends StaveNote {
@@ -314,6 +321,10 @@ declare namespace Vex {
             setUpperAccidental(acc: string): void;
             setLowerAccidental(acc: string): void;
         }
+
+        export class Tremolo extends Modifier {
+            constructor(numberOfSlashes: number);
+        }
         
         export class Beam {
             constructor(notes: StaveNote[], auto_stem: boolean);
@@ -321,6 +332,7 @@ declare namespace Vex {
             public setContext(ctx: RenderContext): Beam;
             public draw(): void;
             public static generateBeams(notes: Vex.Flow.StemmableNote[], optionsObject?: any): Beam[];
+            public setStyle(style: any): void;
         }
 
         export class Fraction { // Vex.Flow.Fraction, used for generateBeams

+ 1 - 1
package.json

@@ -91,7 +91,7 @@
     "tsify": "^4.0.0",
     "tslint": "^5.8.0",
     "tslint-loader": "^3.5.3",
-    "typedoc": "^0.12.0",
+    "typedoc": "^0.13.0",
     "typescript": "^2.6.1",
     "uglifyjs-webpack-plugin": "^2.0.0",
     "underscore-template-loader": "^1.0.0",

+ 25 - 0
src/MusicalScore/Graphical/EngravingRules.ts

@@ -173,6 +173,10 @@ export class EngravingRules {
     private noteDistancesScalingFactors: number[] = [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0];
     private durationDistanceDict: {[_: number]: number; } = {};
     private durationScalingDistanceDict: {[_: number]: number; } = {};
+
+    private coloringEnabled: boolean;
+    private colorFlags: boolean;
+    private colorBeams: boolean;
     /** Whether to render a label for the composer of the piece at the top of the sheet. */
     private renderComposer: boolean;
     private renderTitle: boolean;
@@ -376,6 +380,9 @@ export class EngravingRules {
         this.wholeRestXShiftVexflow = -2.5; // VexFlow draws rest notes too far to the right
 
         // Render options (whether to render specific or invisible elements)
+        this.coloringEnabled = true;
+        this.colorBeams = true;
+        this.colorFlags = true;
         this.renderComposer = true;
         this.renderTitle = true;
         this.renderSubtitle = true;
@@ -1295,6 +1302,24 @@ export class EngravingRules {
     public get DurationScalingDistanceDict(): {[_: number]: number; } {
         return this.durationScalingDistanceDict;
     }
+    public get ColoringEnabled(): boolean {
+        return this.coloringEnabled;
+    }
+    public set ColoringEnabled(value: boolean) {
+        this.coloringEnabled = value;
+    }
+    public get ColorFlags(): boolean {
+        return this.colorFlags;
+    }
+    public set ColorFlags(value: boolean) {
+        this.colorFlags = value;
+    }
+    public get ColorBeams(): boolean {
+        return this.colorBeams;
+    }
+    public set ColorBeams(value: boolean) {
+        this.colorBeams = value;
+    }
     public get RenderComposer(): boolean {
         return this.renderComposer;
     }

+ 3 - 3
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -1486,10 +1486,10 @@ export abstract class MusicSheetCalculator {
                                openTuplets: Tuplet[], openBeams: Beam[],
                                octaveShiftValue: OctaveEnum, linkedNotes: Note[] = undefined,
                                sourceStaffEntry: SourceStaffEntry = undefined): OctaveEnum {
-        if (voiceEntry.WantedStemDirectionXml !== StemDirectionType.Undefined &&
+        if (voiceEntry.StemDirectionXml !== StemDirectionType.Undefined &&
             EngravingRules.Rules.SetWantedStemDirectionByXml &&
-            voiceEntry.WantedStemDirectionXml !== undefined) {
-                voiceEntry.WantedStemDirection = voiceEntry.WantedStemDirectionXml;
+            voiceEntry.StemDirectionXml !== undefined) {
+                voiceEntry.WantedStemDirection = voiceEntry.StemDirectionXml;
         } else {
             this.calculateStemDirectionFromVoices(voiceEntry);
         }

+ 48 - 8
src/MusicalScore/Graphical/VexFlow/VexFlowConverter.ts

@@ -216,17 +216,23 @@ export class VexFlowConverter {
         let alignCenter: boolean = false;
         let xShift: number = 0;
         let slashNoteHead: boolean = false;
+        const noteheadStyles: any = [];
+        const stemColor: string = gve.parentVoiceEntry.StemColorXml;
+        const stemStyle: Object = { fillStyle: stemColor, strokeStyle: stemColor };
         for (const note of notes) {
             if (numDots < note.numberOfDots) {
                 numDots = note.numberOfDots;
             }
-            if (note.sourceNote.NoteHead) {
-                if (note.sourceNote.NoteHead.Shape === NoteHeadShape.SLASH) {
-                    slashNoteHead = true;
-                    // if we have slash heads and other heads in the voice entry, this will create the same head for all.
-                    // same problem with numDots. The slash case should be extremely rare though.
+
+            if (EngravingRules.Rules.ColoringEnabled) {
+                const noteheadColor: string = note.sourceNote.NoteheadColorXml;
+                if (noteheadColor) {
+                    noteheadStyles.push({fillStyle: noteheadColor, strokeStyle: noteheadColor});
+                } else {
+                    noteheadStyles.push(undefined);
                 }
             }
+
             // if it is a rest:
             if (note.sourceNote.isRest()) {
                 keys = ["b/4"];
@@ -245,6 +251,15 @@ export class VexFlowConverter {
                 duration += "r";
                 break;
             }
+
+            if (note.sourceNote.NoteHead) {
+                if (note.sourceNote.NoteHead.Shape === NoteHeadShape.SLASH) {
+                    slashNoteHead = true;
+                    // if we have slash heads and other heads in the voice entry, this will create the same head for all.
+                    // same problem with numDots. The slash case should be extremely rare though.
+                }
+            }
+
             const pitch: [string, string, ClefInstruction] = (note as VexFlowGraphicalNote).vfpitch;
             keys.push(pitch[0]);
             accidentals.push(pitch[1]);
@@ -262,15 +277,19 @@ export class VexFlowConverter {
         }
 
         let vfnote: Vex.Flow.StaveNote;
+
         const vfnoteStruct: Object = {
             align_center: alignCenter,
             auto_stem: true,
             clef: vfClefType,
             duration: duration,
             keys: keys,
+            noteheadStyles: noteheadStyles,
             slash: gve.parentVoiceEntry.GraceNoteSlash,
         };
-
+        if (stemColor && EngravingRules.Rules.ColoringEnabled) {
+            (<any>vfnoteStruct).stemStyle = stemStyle;
+        }
         if (gve.notes[0].sourceNote.IsCueNote) {
             (<any>vfnoteStruct).glyph_font_scale = Vex.Flow.DEFAULT_NOTATION_FONT_SCALE * Vex.Flow.GraceNote.SCALE;
             (<any>vfnoteStruct).stroke_px = Vex.Flow.GraceNote.LEDGER_LINE_OFFSET;
@@ -282,8 +301,29 @@ export class VexFlowConverter {
             vfnote = new Vex.Flow.StaveNote(vfnoteStruct);
         }
 
+        if (EngravingRules.Rules.ColoringEnabled) {
+            // TODO temporary fix until Vexflow PR is through (should be set by vfnotestruct.stem/noteheadStyles)
+            if (stemColor) {
+                vfnote.setStemStyle(stemStyle);
+            }
+            if (vfnote.flag && EngravingRules.Rules.ColorFlags) {
+                vfnote.setFlagStyle(stemStyle);
+            }
+            for (let i: number = 0; i < noteheadStyles.length; i++) {
+                const style: string = noteheadStyles[i];
+                if (style) {
+                    vfnote.note_heads[i].setStyle(style);
+                }
+            }
+        }
+
         vfnote.x_shift = xShift;
 
+        if (gve.parentVoiceEntry.IsGrace && gve.notes[0].sourceNote.NoteBeam) {
+            // Vexflow seems to have issues with wanted stem direction for beamed grace notes,
+            // when the stem is connected to a beamed main note (e.g. Haydn Concertante bar 57)
+            gve.parentVoiceEntry.WantedStemDirection = gve.notes[0].sourceNote.NoteBeam.Notes[0].ParentVoiceEntry.WantedStemDirection;
+        }
         if (gve.parentVoiceEntry !== undefined) {
             const wantedStemDirection: StemDirectionType = gve.parentVoiceEntry.WantedStemDirection;
             switch (wantedStemDirection) {
@@ -320,8 +360,8 @@ export class VexFlowConverter {
     }
 
     public static generateArticulations(vfnote: Vex.Flow.StemmableNote, articulations: ArticulationEnum[]): void {
-        if (vfnote === undefined) {
-            return; // needed because grace notes after main note currently not implemented. maybe safer in any case
+        if (vfnote === undefined || vfnote.getAttribute("type") === "GhostNote") {
+            return;
         }
         // Articulations:
         let vfArtPosition: number = Vex.Flow.Modifier.Position.ABOVE;

+ 2 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowInstrumentBracket.ts

@@ -1,6 +1,6 @@
 import Vex = require("vexflow");
-import {GraphicalObject} from "../GraphicalObject";
-import {VexFlowStaffLine} from "./VexFlowStaffLine";
+import { GraphicalObject } from "../GraphicalObject";
+import { VexFlowStaffLine } from "./VexFlowStaffLine";
 import { BoundingBox } from "../BoundingBox";
 import { VexFlowMeasure } from "./VexFlowMeasure";
 import { unitInPixels } from "./VexFlowMusicSheetDrawer";

+ 17 - 4
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -334,7 +334,9 @@ export class VexFlowMeasure extends GraphicalMeasure {
         // Draw all voices
         for (const voiceID in this.vfVoices) {
             if (this.vfVoices.hasOwnProperty(voiceID)) {
+                ctx.save();
                 this.vfVoices[voiceID].draw(ctx, this.stave);
+                ctx.restore();
                 // this.vfVoices[voiceID].tickables.forEach(t => t.getBoundingBox().draw(ctx));
                 // this.vfVoices[voiceID].tickables.forEach(t => t.getBoundingBox().draw(ctx));
             }
@@ -571,6 +573,8 @@ export class VexFlowMeasure extends GraphicalMeasure {
                     }
 
                     let isGraceBeam: boolean = false;
+                    let beamColor: string;
+                    const stemColorsXml: string[] = [];
                     for (const entry of voiceEntries) {
                         const note: Vex.Flow.StaveNote = ((<VexFlowVoiceEntry>entry).vfStaveNote as StaveNote);
                         if (note !== undefined) {
@@ -580,6 +584,9 @@ export class VexFlowMeasure extends GraphicalMeasure {
                         if (entry.parentVoiceEntry.IsGrace) {
                             isGraceBeam = true;
                         }
+                        if (entry.parentVoiceEntry.StemColorXml && EngravingRules.Rules.ColoringEnabled) {
+                            stemColorsXml.push(entry.parentVoiceEntry.StemColorXml);
+                        }
                     }
                     if (notes.length > 1) {
                         const vfBeam: Vex.Flow.Beam = new Vex.Flow.Beam(notes, autoStemBeam);
@@ -588,11 +595,17 @@ export class VexFlowMeasure extends GraphicalMeasure {
                             (<any>vfBeam).render_options.beam_width = 3;
                             (<any>vfBeam).render_options.partial_beam_length = 4;
                         }
+                        if (stemColorsXml.length >= 2 && EngravingRules.Rules.ColorBeams) {
+                            beamColor = stemColorsXml[0];
+                            for (const stemColor of stemColorsXml) {
+                                if (stemColor !== beamColor) {
+                                    beamColor = undefined;
+                                    break;
+                                }
+                            }
+                            vfBeam.setStyle({ fillStyle: beamColor, strokeStyle: beamColor });
+                        }
                         vfbeams.push(vfBeam);
-                        // just a test for coloring the notes:
-                        // for (let note of notes) {
-                        //     (<Vex.Flow.StaveNote> note).setStyle({fillStyle: "green", strokeStyle: "green"});
-                        // }
                     } else {
                         log.debug("Warning! Beam with no notes!");
                     }

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

@@ -465,7 +465,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
       } else if (graphicalContinuousDynamic.IsVerbal) {
         this.calculateGraphicalVerbalContinuousDynamic(graphicalContinuousDynamic, dynamicStartPosition);
       } else {
-        log.warn("This continous dynamic is not covered");
+        log.warn("This continuous dynamic is not covered");
       }
     }
   }

+ 5 - 4
src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.ts

@@ -1,7 +1,8 @@
-import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
-import {VexFlowMeasure} from "./VexFlowMeasure";
-import {SourceStaffEntry} from "../../VoiceData/SourceStaffEntry";
-import {unitInPixels} from "./VexFlowMusicSheetDrawer";
+import Vex = require("vexflow");
+import { GraphicalStaffEntry } from "../GraphicalStaffEntry";
+import { VexFlowMeasure } from "./VexFlowMeasure";
+import { SourceStaffEntry } from "../../VoiceData/SourceStaffEntry";
+import { unitInPixels } from "./VexFlowMusicSheetDrawer";
 import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
 import { Note } from "../../VoiceData/Note";
 import { EngravingRules } from "../EngravingRules";

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

@@ -1,3 +1,4 @@
+import Vex = require("vexflow");
 import { VoiceEntry } from "../../VoiceData/VoiceEntry";
 import { GraphicalVoiceEntry } from "../GraphicalVoiceEntry";
 import { GraphicalStaffEntry } from "../GraphicalStaffEntry";

+ 48 - 1
src/MusicalScore/ScoreIO/InstrumentReader.ts

@@ -214,6 +214,11 @@ export class InstrumentReader {
 
           // check for cue note
           let isCueNote: boolean = false;
+          const cueNode: IXmlElement = xmlNode.element("cue");
+          if (cueNode !== undefined) {
+            isCueNote = true;
+          }
+          // alternative: check for <type size="cue">
           const typeNode: IXmlElement = xmlNode.element("type");
           if (typeNode !== undefined) {
             const sizeAttr: Attr = typeNode.attribute("size");
@@ -226,6 +231,7 @@ export class InstrumentReader {
 
           // check stem element
           let stemDirectionXml: StemDirectionType = StemDirectionType.Undefined;
+          let stemColorXml: string;
           const stemNode: IXmlElement = xmlNode.element("stem");
           if (stemNode !== undefined) {
             switch (stemNode.value) {
@@ -244,6 +250,46 @@ export class InstrumentReader {
               default:
                 stemDirectionXml = StemDirectionType.Undefined;
             }
+
+            const stemColorAttr: Attr = stemNode.attribute("color");
+            if (stemColorAttr) { // can be null, maybe also undefined
+              const stemColorValue: string = stemColorAttr.value;
+              if (stemColorValue.length === 7) { // #RGB hexa
+                stemColorXml = stemColorValue;
+              } else if (stemColorValue.length === 9) { // #ARGB hexa, first part alpha channel
+                stemColorXml = stemColorValue.substr(2);
+              }
+            }
+          }
+
+          // check notehead/color
+          let noteheadColorXml: string;
+          const noteheadNode: IXmlElement = xmlNode.element("notehead");
+          if (noteheadNode) {
+            const colorAttr: Attr = noteheadNode.attribute("color");
+            const colorValue: string = colorAttr.value;
+            if (colorValue.length === 7) { // #RGB hexa
+              noteheadColorXml = colorValue;
+            } else if (colorValue.length === 9) { // #ARGB hexa, first part alpha channel
+              noteheadColorXml = colorValue.substr(2);
+            }
+          }
+
+          let noteColorXml: string;
+          const noteColorAttr: Attr = xmlNode.attribute("color");
+          if (noteColorAttr) {
+            const noteColorValue: string = noteColorAttr.value;
+            if (noteColorValue.length === 7) { // #RGB hexa
+              noteColorXml = noteColorValue;
+            } else if (noteColorValue.length === 9) { // #ARGB hexa, first part alpha channel
+              noteColorXml = noteColorValue.substr(2);
+            }
+            if (noteheadColorXml === undefined) {
+              noteheadColorXml = noteColorXml;
+            }
+            if (stemColorXml === undefined) {
+              stemColorXml = noteColorXml;
+            }
           }
 
           let musicTimestamp: Fraction = currentFraction.clone();
@@ -299,7 +345,8 @@ export class InstrumentReader {
             xmlNode, noteDuration, restNote,
             this.currentStaffEntry, this.currentMeasure,
             measureStartAbsoluteTimestamp,
-            this.maxTieNoteFraction, isChord, guitarPro, printObject, isCueNote, stemDirectionXml
+            this.maxTieNoteFraction, isChord, guitarPro,
+            printObject, isCueNote, stemDirectionXml, stemColorXml, noteheadColorXml
           );
 
           const notationsNode: IXmlElement = xmlNode.element("notations");

+ 15 - 7
src/MusicalScore/ScoreIO/VoiceGenerator.ts

@@ -106,14 +106,16 @@ export class VoiceGenerator {
   public read(noteNode: IXmlElement, noteDuration: Fraction, restNote: boolean,
               parentStaffEntry: SourceStaffEntry, parentMeasure: SourceMeasure,
               measureStartAbsoluteTimestamp: Fraction, maxTieNoteFraction: Fraction, chord: boolean, guitarPro: boolean,
-              printObject: boolean, isCueNote: boolean, stemDirectionXml: StemDirectionType): Note {
+              printObject: boolean, isCueNote: boolean, stemDirectionXml: StemDirectionType,
+              stemColorXml: string, noteheadColorXml: string): Note {
     this.currentStaffEntry = parentStaffEntry;
     this.currentMeasure = parentMeasure;
     //log.debug("read called:", restNote);
     try {
       this.currentNote = restNote
-        ? this.addRestNote(noteDuration, printObject, isCueNote)
-        : this.addSingleNote(noteNode, noteDuration, chord, guitarPro, printObject, isCueNote, stemDirectionXml);
+        ? this.addRestNote(noteDuration, printObject, isCueNote, noteheadColorXml)
+        : this.addSingleNote(noteNode, noteDuration, chord, guitarPro,
+                             printObject, isCueNote, stemDirectionXml, stemColorXml, noteheadColorXml);
       // read lyrics
       const lyricElements: IXmlElement[] = noteNode.elements("lyric");
       if (this.lyricsReader !== undefined && lyricElements !== undefined) {
@@ -321,7 +323,8 @@ export class VoiceGenerator {
    * @returns {Note}
    */
   private addSingleNote(node: IXmlElement, noteDuration: Fraction, chord: boolean, guitarPro: boolean,
-                        printObject: boolean, isCueNote: boolean, stemDirectionXml: StemDirectionType): Note {
+                        printObject: boolean, isCueNote: boolean, stemDirectionXml: StemDirectionType,
+                        stemColorXml: string, noteheadColorXml: string): Note {
     //log.debug("addSingleNote called");
     let noteAlter: number = 0;
     let noteAccidental: AccidentalEnum = AccidentalEnum.NONE;
@@ -416,13 +419,17 @@ export class VoiceGenerator {
     const note: Note = new Note(this.currentVoiceEntry, this.currentStaffEntry, noteLength, pitch);
     note.PrintObject = printObject;
     note.IsCueNote = isCueNote;
-    note.StemDirectionXml = stemDirectionXml;
+    note.StemDirectionXml = stemDirectionXml; // maybe unnecessary, also in VoiceEntry
+    note.NoteheadColorXml = noteheadColorXml;
     note.PlaybackInstrumentId = playbackInstrumentId;
     if (noteHeadShapeXml !== undefined && noteHeadShapeXml !== "normal") {
       note.NoteHead = new NoteHead(note, noteHeadShapeXml, noteHeadFilledXml);
     } // if normal, leave note head undefined to save processing/runtime
     this.currentVoiceEntry.Notes.push(note);
-    this.currentVoiceEntry.WantedStemDirectionXml = stemDirectionXml;
+    this.currentVoiceEntry.StemDirectionXml = stemDirectionXml;
+    if (stemColorXml) {
+      this.currentVoiceEntry.StemColorXml = stemColorXml;
+    }
     if (node.elements("beam") && !chord) {
       this.createBeam(node, note);
     }
@@ -435,11 +442,12 @@ export class VoiceGenerator {
    * @param divisions
    * @returns {Note}
    */
-  private addRestNote(noteDuration: Fraction, printObject: boolean = true, isCueNote: boolean = false): Note {
+  private addRestNote(noteDuration: Fraction, printObject: boolean, isCueNote: boolean, noteheadColorXml: string): Note {
     const restFraction: Fraction = Fraction.createFromFraction(noteDuration);
     const restNote: Note = new Note(this.currentVoiceEntry, this.currentStaffEntry, restFraction, undefined);
     restNote.PrintObject = printObject;
     restNote.IsCueNote = isCueNote;
+    restNote.NoteheadColorXml = noteheadColorXml;
     this.currentVoiceEntry.Notes.push(restNote);
     if (this.openBeam !== undefined) {
       this.openBeam.ExtendedNoteList.push(restNote);

+ 16 - 0
src/MusicalScore/VoiceData/Note.ts

@@ -54,6 +54,10 @@ export class Note {
     private isCueNote: boolean;
     /** The stem direction asked for in XML. Not necessarily final or wanted stem direction. */
     private stemDirectionXml: StemDirectionType;
+    /** Color of the stem given in the XML Stem tag. RGB Hexadecimal, like #00FF00. */
+    private stemColorXml: string;
+    /** Color of the note given in the XML Notehead tag. RGB Hexadecimal, like #00FF00. */
+    private noteheadColorXml: string;
 
     public get ParentVoiceEntry(): VoiceEntry {
         return this.voiceEntry;
@@ -136,6 +140,18 @@ export class Note {
     public set StemDirectionXml(value: StemDirectionType) {
         this.stemDirectionXml = value;
     }
+    public get StemColorXml(): string {
+        return this.stemColorXml;
+    }
+    public set StemColorXml(value: string) {
+        this.stemColorXml = value;
+    }
+    public get NoteheadColorXml(): string {
+        return this.noteheadColorXml;
+    }
+    public set NoteheadColorXml(value: string) {
+        this.noteheadColorXml = value;
+    }
 
     public isRest(): boolean {
         return this.Pitch === undefined;

+ 12 - 5
src/MusicalScore/VoiceData/VoiceEntry.ts

@@ -52,8 +52,9 @@ export class VoiceEntry {
     private ornamentContainer: OrnamentContainer;
     private wantedStemDirection: StemDirectionType = StemDirectionType.Undefined;
     /** Stem direction specified in the xml stem element. */
-    private wantedStemDirectionXml: StemDirectionType = StemDirectionType.Undefined;
+    private stemDirectionXml: StemDirectionType = StemDirectionType.Undefined;
     private stemDirection: StemDirectionType = StemDirectionType.Undefined;
+    private stemColorXml: string;
 
     public get ParentSourceStaffEntry(): SourceStaffEntry {
         return this.parentSourceStaffEntry;
@@ -124,11 +125,11 @@ export class VoiceEntry {
     public get WantedStemDirection(): StemDirectionType {
         return this.wantedStemDirection;
     }
-    public set WantedStemDirectionXml(value: StemDirectionType) {
-        this.wantedStemDirectionXml = value;
+    public set StemDirectionXml(value: StemDirectionType) {
+        this.stemDirectionXml = value;
     }
-    public get WantedStemDirectionXml(): StemDirectionType {
-        return this.wantedStemDirectionXml;
+    public get StemDirectionXml(): StemDirectionType {
+        return this.stemDirectionXml;
     }
     // StemDirection holds the actual value of the stem
     public set StemDirection(value: StemDirectionType) {
@@ -137,6 +138,12 @@ export class VoiceEntry {
     public get StemDirection(): StemDirectionType {
         return this.stemDirection;
     }
+    public get StemColorXml(): string {
+        return this.stemColorXml;
+    }
+    public set StemColorXml(value: string) {
+        this.stemColorXml = value;
+    }
 
     public static isSupportedArticulation(articulation: ArticulationEnum): boolean {
         switch (articulation) {

+ 2 - 0
src/OpenSheetMusicDisplay/OSMDOptions.ts

@@ -12,6 +12,8 @@ export interface IOSMDOptions {
     autoStem?: boolean;
     /** Render Backend, will be SVG if given undefined, SVG or svg, otherwise Canvas. */
     backend?: string;
+    /** Whether to enable coloring noteheads and stems by their XML color attribute. */
+    coloringEnabled?: boolean;
     /** Don't show/load cursor. Will override disableCursor in drawingParameters. */
     disableCursor?: boolean;
     /** Broad Parameters like compact or preview mode. */

+ 3 - 0
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -237,6 +237,9 @@ export class OpenSheetMusicDisplay {
                 }
             }
         }
+        if (options.coloringEnabled !== undefined) {
+            EngravingRules.Rules.ColoringEnabled = options.coloringEnabled;
+        }
         if (options.disableCursor) {
             this.drawingParameters.drawCursors = false;
             this.enableOrDisableCursor(this.drawingParameters.drawCursors);

+ 3 - 3
test/data/JosephHaydn_ConcertanteCello.xml

@@ -4788,8 +4788,8 @@
         <voice>1</voice>
         <type>16th</type>
         <stem>up</stem>
-        <beam number="1">begin</beam>
         <beam number="2">begin</beam>
+        <beam number="3">begin</beam>
         <notations>
           <slur number="1" type="start"/>
         </notations>
@@ -4804,8 +4804,8 @@
         <voice>1</voice>
         <type>16th</type>
         <stem>up</stem>
-        <beam number="1">continue</beam>
         <beam number="2">continue</beam>
+        <beam number="3">continue</beam>
       </note>
       <note>
         <grace/>
@@ -4816,8 +4816,8 @@
         <voice>1</voice>
         <type>16th</type>
         <stem>up</stem>
-        <beam number="1">end</beam>
         <beam number="2">end</beam>
+        <beam number="3">end</beam>
       </note>
       <note>
         <pitch>

+ 791 - 0
test/data/OSMD_function_test_color.musicxml

@@ -0,0 +1,791 @@
+<?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>OSMD Function Test - Color</work-title>
+    </work>
+  <identification>
+    <rights>Copyright © 2002 Recordare LLC</rights>
+    <encoding>
+      <software>MuseScore 2.3.2</software>
+      <encoding-date>2018-10-23</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.35</millimeters>
+      <tenths>40</tenths>
+      </scaling>
+    <page-layout>
+      <page-height>1760</page-height>
+      <page-width>1360</page-width>
+      <page-margins type="both">
+        <left-margin>80</left-margin>
+        <right-margin>80</right-margin>
+        <top-margin>80</top-margin>
+        <bottom-margin>80</bottom-margin>
+        </page-margins>
+      </page-layout>
+    <word-font font-family="Times New Roman" font-size="9"/>
+    <lyric-font font-family="Times New Roman" font-size="10"/>
+    </defaults>
+  <credit page="1">
+    <credit-words default-x="80" default-y="1522" justify="left" valign="bottom" font-size="12">Aloys Jeitteles</credit-words>
+    </credit>
+  <credit page="1">
+    <credit-words default-x="1280" default-y="1522" justify="right" valign="bottom" font-size="12">Ludwig van Beethoven</credit-words>
+    </credit>
+  <credit page="1">
+    <credit-words default-x="680" default-y="1680" justify="center" valign="top" font-size="24">An die ferne Geliebte</credit-words>
+    </credit>
+  <credit page="1">
+    <credit-words default-x="680" default-y="80" justify="center" valign="bottom" font-size="8">Copyright © 2002 Recordare LLC</credit-words>
+    </credit>
+  <part-list>
+    <score-part id="P1">
+      <part-name>Voice</part-name>
+      <score-instrument id="P1-I1">
+        <instrument-name>Voice</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>53</midi-program>
+        <volume>79.5276</volume>
+        <pan>0</pan>
+        </midi-instrument>
+      </score-part>
+    <score-part id="P2">
+      <part-name>Piano</part-name>
+      <score-instrument id="P2-I1">
+        <instrument-name>Acoustic Grand Piano</instrument-name>
+        </score-instrument>
+      <midi-device id="P2-I1" port="1"></midi-device>
+      <midi-instrument id="P2-I1">
+        <midi-channel>2</midi-channel>
+        <midi-program>1</midi-program>
+        <volume>79.5276</volume>
+        <pan>0</pan>
+        </midi-instrument>
+      </score-part>
+    </part-list>
+  <part id="P1">
+    <measure number="1" width="415.74">
+      <print>
+        <system-layout>
+          <system-margins>
+            <left-margin>71.49</left-margin>
+            <right-margin>0.00</right-margin>
+            </system-margins>
+          <top-system-distance>228.00</top-system-distance>
+          </system-layout>
+        </print>
+      <attributes>
+        <divisions>2</divisions>
+        <key>
+          <fifths>-3</fifths>
+          <mode>major</mode>
+          </key>
+        <time>
+          <beats>3</beats>
+          <beat-type>4</beat-type>
+          </time>
+        <clef>
+          <sign>G</sign>
+          <line>2</line>
+          </clef>
+        </attributes>
+      <direction placement="above">
+        <direction-type>
+          <words default-x="-34.44" default-y="26.00" font-weight="bold" font-size="11">Ziemlich langsam und mit Ausdruck</words>
+          </direction-type>
+        <sound tempo="60"/>
+        </direction>
+      <direction placement="above">
+        <direction-type>
+          <words default-y="60.00" font-weight="bold" font-size="16">No. 1</words>
+          </direction-type>
+        </direction>
+      <note color="#0000BB">
+        <rest/>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        </note>
+      <note default-x="209.64" default-y="-20.00">
+        <pitch>
+          <step>B</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem color="#EE00EE">down</stem>
+        <notehead color="#0000FF">normal</notehead>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>single</syllabic>
+          <text>Auf</text>
+          </lyric>
+        </note>
+      <note default-x="311.89" default-y="-20.00">
+        <pitch>
+          <step>B</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>down</stem>
+        <notehead color="#AA0000">normal</notehead>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>single</syllabic>
+          <text>dem</text>
+          </lyric>
+        </note>
+      </measure>
+    <measure number="2" width="363.33">
+      <note default-x="17.64" default-y="-20.00">
+        <pitch>
+          <step>B</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>3</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <dot/>
+        <stem>down</stem>
+        <notehead color="#0000FF">normal</notehead>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>begin</syllabic>
+          <text>Hü</text>
+          </lyric>
+        </note>
+      <note default-x="177.40" default-y="-15.00">
+        <pitch>
+          <step>C</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem color="#AA5500">down</stem>
+        <notehead color="#AA5500">normal</notehead>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>end</syllabic>
+          <text>gel</text>
+          </lyric>
+        </note>
+      <note default-x="238.84" default-y="-10.00">
+        <pitch>
+          <step>D</step>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem color="#005500">down</stem>
+        <notehead color="#005500">normal</notehead>
+        <beam number="1">begin</beam>
+        <lyric number="1" default-x="8.81" default-y="-80.00">
+          <syllabic>single</syllabic>
+          <text>sitz’</text>
+          </lyric>
+        </note>
+      <note default-x="300.29" default-y="-5.00">
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>5</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>down</stem>
+        <notehead color="#FF00FF">normal</notehead>
+        <beam number="1">end</beam>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>single</syllabic>
+          <text>ich</text>
+          </lyric>
+        </note>
+      </measure>
+    <measure number="3" width="349.44">
+      <note default-x="18.74" default-y="-5.00">
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>5</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>down</stem>
+        <notehead color="#FFFF00">normal</notehead>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>begin</syllabic>
+          <text>spä</text>
+          </lyric>
+        </note>
+      <note default-x="112.77" default-y="-30.00">
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>up</stem>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>end</syllabic>
+          <text>hend</text>
+          </lyric>
+        </note>
+      <note>
+        <rest/>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        </note>
+      <note default-x="230.30" default-y="-25.00">
+        <pitch>
+          <step>A</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem color="#EE0000">up</stem>
+        <notehead color="#EE0000">normal</notehead>
+        <beam number="1">begin</beam>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>single</syllabic>
+          <text>in</text>
+          </lyric>
+        </note>
+      <note default-x="289.07" default-y="-30.00">
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem color="#EE0000">up</stem>
+        <notehead color="#EE0000">normal</notehead>
+        <beam number="1">end</beam>
+        <lyric number="1" default-x="6.58" default-y="-80.00">
+          <syllabic>single</syllabic>
+          <text>das</text>
+          </lyric>
+        </note>
+      </measure>
+    </part>
+  <part id="P2">
+    <measure number="1" width="415.74">
+      <print>
+        <staff-layout number="1">
+          <staff-distance>101.00</staff-distance>
+          </staff-layout>
+        <staff-layout number="2">
+          <staff-distance>65.00</staff-distance>
+          </staff-layout>
+        </print>
+      <attributes>
+        <divisions>2</divisions>
+        <key>
+          <fifths>-3</fifths>
+          <mode>major</mode>
+          </key>
+        <time>
+          <beats>3</beats>
+          <beat-type>4</beat-type>
+          </time>
+        <staves>2</staves>
+        <clef number="1">
+          <sign>G</sign>
+          <line>2</line>
+          </clef>
+        <clef number="2">
+          <sign>F</sign>
+          <line>4</line>
+          </clef>
+        </attributes>
+      <direction placement="below">
+        <direction-type>
+          <dynamics default-x="6.58" default-y="-81.00" relative-y="6.67">
+            <p/>
+            </dynamics>
+          </direction-type>
+        <staff>1</staff>
+        <sound dynamics="54.44"/>
+        </direction>
+      <note default-x="107.39" default-y="-196.00">
+        <pitch>
+          <step>B</step>
+          <alter>-1</alter>
+          <octave>3</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem color="#EE0000">up</stem>
+        <notehead color="#00FF7F">normal</notehead>
+        <staff>1</staff>
+        </note>
+      <note default-x="107.39" default-y="-181.00">
+        <chord/>
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note default-x="107.39" default-y="-171.00">
+        <chord/>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <notehead color="#5500FF">normal</notehead>
+        <staff>1</staff>
+        </note>
+      <note default-x="107.39" default-y="-161.00">
+        <chord/>
+        <pitch>
+          <step>B</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note default-x="209.64" default-y="-161.00">
+        <pitch>
+          <step>B</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>down</stem>
+        <staff>1</staff>
+        <notations>
+          <slur type="start" placement="above" number="1"/>
+          </notations>
+        </note>
+      <note default-x="311.89" default-y="-166.00">
+        <pitch>
+          <step>A</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        <notations>
+          <slur type="stop" number="1"/>
+          </notations>
+        </note>
+      <backup>
+        <duration>6</duration>
+        </backup>
+      <direction placement="below">
+        <direction-type>
+          <pedal type="start" relative-y="-80.00"/>
+          </direction-type>
+        <staff>2</staff>
+        </direction>
+      <note default-x="107.39" default-y="-296.00">
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>2</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem color="#EEBB00">up</stem>
+        <staff>2</staff>
+        </note>
+      <note default-x="107.39" default-y="-261.00">
+        <chord/>
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>3</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <notehead color="#FFAA7F">normal</notehead>
+        <staff>2</staff>
+        </note>
+      <attributes>
+        <clef number="2">
+          <sign>G</sign>
+          <line>2</line>
+          </clef>
+        </attributes>
+      <direction placement="below">
+        <direction-type>
+          <pedal type="stop" relative-y="-80.00"/>
+          </direction-type>
+        <staff>2</staff>
+        </direction>
+      <note default-x="209.64" default-y="-276.00">
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        <notations>
+          <slur type="start" number="1"/>
+          </notations>
+        </note>
+      <note default-x="311.89" default-y="-281.00">
+        <pitch>
+          <step>F</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        <notations>
+          <slur type="stop" number="1"/>
+          </notations>
+        </note>
+      </measure>
+    <measure number="2" width="363.33">
+      <note default-x="17.64" default-y="-171.00">
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note default-x="115.95" default-y="-206.00">
+        <pitch>
+          <step>G</step>
+          <octave>3</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <notehead color="#55AA00">normal</notehead>
+        <staff>1</staff>
+        </note>
+      <note default-x="115.95" default-y="-181.00">
+        <chord/>
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <notehead color="#FFFF00">normal</notehead>
+        <staff>1</staff>
+        </note>
+      <note default-x="115.95" default-y="-171.00">
+        <chord/>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <notehead color="#AA5500">normal</notehead>
+        <staff>1</staff>
+        </note>
+      <note>
+        <rest/>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <staff>1</staff>
+        </note>
+      <backup>
+        <duration>6</duration>
+        </backup>
+      <note default-x="17.64" default-y="-286.00">
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        </note>
+      <attributes>
+        <clef number="2">
+          <sign>F</sign>
+          <line>4</line>
+          </clef>
+        </attributes>
+      <direction placement="below">
+        <direction-type>
+          <pedal type="start" relative-y="-80.00"/>
+          </direction-type>
+        <staff>2</staff>
+        </direction>
+      <note default-x="115.95" default-y="-296.00">
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>2</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        </note>
+      <note default-x="115.95" default-y="-261.00">
+        <chord/>
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>3</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        </note>
+      <direction placement="below">
+        <direction-type>
+          <pedal type="stop" relative-y="-80.00"/>
+          </direction-type>
+        <staff>2</staff>
+        </direction>
+      <note>
+        <rest/>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <staff>2</staff>
+        </note>
+      </measure>
+    <measure number="3" width="349.44">
+      <note>
+        <rest/>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <staff>1</staff>
+        </note>
+      <note default-x="112.77" default-y="-206.00">
+        <pitch>
+          <step>G</step>
+          <octave>3</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note default-x="112.77" default-y="-191.00">
+        <chord/>
+        <pitch>
+          <step>C</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note default-x="112.77" default-y="-181.00">
+        <chord/>
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note default-x="112.77" default-y="-171.00">
+        <chord/>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note>
+        <rest/>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <staff>1</staff>
+        </note>
+      <note default-x="289.07" default-y="-206.00">
+        <pitch>
+          <step>G</step>
+          <octave>3</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note default-x="289.07" default-y="-181.00">
+        <chord/>
+        <pitch>
+          <step>E</step>
+          <alter>-1</alter>
+          <octave>4</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <note default-x="289.07" default-y="-171.00">
+        <chord/>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+        <stem>up</stem>
+        <staff>1</staff>
+        </note>
+      <backup>
+        <duration>6</duration>
+        </backup>
+      <note>
+        <rest/>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <staff>2</staff>
+        </note>
+      <direction placement="below">
+        <direction-type>
+          <pedal type="start" relative-y="-80.00"/>
+          </direction-type>
+        <staff>2</staff>
+        </direction>
+      <note default-x="112.77" default-y="-306.00">
+        <pitch>
+          <step>C</step>
+          <octave>2</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        </note>
+      <note default-x="112.77" default-y="-271.00">
+        <chord/>
+        <pitch>
+          <step>C</step>
+          <octave>3</octave>
+          </pitch>
+        <duration>2</duration>
+        <voice>5</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        </note>
+      <direction placement="below">
+        <direction-type>
+          <pedal type="stop" relative-y="-80.00"/>
+          </direction-type>
+        <staff>2</staff>
+        </direction>
+      <note>
+        <rest/>
+        <duration>1</duration>
+        <voice>5</voice>
+        <type>eighth</type>
+        <staff>2</staff>
+        </note>
+      <note default-x="289.07" default-y="-311.00">
+        <pitch>
+          <step>B</step>
+          <alter>-1</alter>
+          <octave>1</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>5</voice>
+        <type>eighth</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        </note>
+      <note default-x="289.07" default-y="-276.00">
+        <chord/>
+        <pitch>
+          <step>B</step>
+          <alter>-1</alter>
+          <octave>2</octave>
+          </pitch>
+        <duration>1</duration>
+        <voice>5</voice>
+        <type>eighth</type>
+        <stem>up</stem>
+        <staff>2</staff>
+        </note>
+      </measure>
+    </part>
+  </score-partwise>