Преглед изворни кода

fix(invisible notes): invisible rests formatting fixed by adding ghost notes

main changes:
VexFlowMeasure: adding Ghost note
MusicSheetCalculator: don't skip voice entries with invisible notes for handleVoiceEntry(), causes problems
adds some handling (skipping) of invisible notes in places like beams, tuplets and voice entry handling.

this commit was done copying the changes from the fix/invisibleRestNotesFormatting branch to develop,
because that branch was created from the fingering feature branch and shows irrelevant changes in the PR.
sschmidTU пре 6 година
родитељ
комит
3b0e19de00

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

@@ -1122,21 +1122,11 @@ export abstract class MusicSheetCalculator {
                                openTuplets: Tuplet[], openBeams: Beam[],
                                octaveShiftValue: OctaveEnum, linkedNotes: Note[] = undefined,
                                sourceStaffEntry: SourceStaffEntry = undefined): OctaveEnum {
-        let voiceEntryHasPrintableNotes: boolean = false;
-        for (const note of voiceEntry.Notes) {
-            if (note.PrintObject) {
-                voiceEntryHasPrintableNotes = true;
-                break;
-            }
-        }
-        if (!voiceEntryHasPrintableNotes) {
-            return; // do not create a GraphicalVoiceEntry without graphical notes in it, will cause problems
-        }
         this.calculateStemDirectionFromVoices(voiceEntry);
         const gve: GraphicalVoiceEntry = graphicalStaffEntry.findOrCreateGraphicalVoiceEntry(voiceEntry);
         for (let idx: number = 0, len: number = voiceEntry.Notes.length; idx < len; ++idx) {
             const note: Note = voiceEntry.Notes[idx];
-            if (note === undefined || !note.PrintObject) {
+            if (note === undefined) {
                 continue;
             }
             if (sourceStaffEntry !== undefined && sourceStaffEntry.Link !== undefined && linkedNotes !== undefined && linkedNotes.indexOf(note) > -1) {
@@ -1155,10 +1145,10 @@ export abstract class MusicSheetCalculator {
             graphicalStaffEntry.addGraphicalNoteToListAtCorrectYPosition(gve, graphicalNote);
             graphicalNote.PositionAndShape.calculateBoundingBox();
             if (!this.leadSheet) {
-                if (note.NoteBeam !== undefined) {
+                if (note.NoteBeam !== undefined && note.PrintObject) {
                     this.handleBeam(graphicalNote, note.NoteBeam, openBeams);
                 }
-                if (note.NoteTuplet !== undefined) {
+                if (note.NoteTuplet !== undefined && note.PrintObject) {
                     this.handleTuplet(graphicalNote, note.NoteTuplet, openTuplets);
                 }
             }
@@ -1451,6 +1441,9 @@ export abstract class MusicSheetCalculator {
             endGse = this.graphicalMusicSheet.GetGraphicalFromSourceStaffEntry(tie.Notes[i].ParentStaffEntry);
             endNote = endGse.findEndTieGraphicalNoteFromNote(tie.Notes[i]);
             if (startNote !== undefined && endNote !== undefined && endGse !== undefined) {
+                if (!startNote.sourceNote.PrintObject || !endNote.sourceNote.PrintObject) {
+                    continue;
+                }
                 const graphicalTie: GraphicalTie = this.createGraphicalTie(tie, startGse, endGse, startNote, endNote);
                 startGse.GraphicalTies.push(graphicalTie);
                 if (this.staffEntriesWithGraphicalTies.indexOf(startGse) >= 0) {

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

@@ -182,7 +182,6 @@ export class VexFlowConverter {
     }
 
     public static GhostNote(frac: Fraction): Vex.Flow.GhostNote {
-        // const frac: Fraction = notes[0].graphicalNoteLength;
         return new Vex.Flow.GhostNote({
             duration: VexFlowConverter.duration(frac, false),
         });

+ 7 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -434,7 +434,6 @@ export class VexFlowMeasure extends GraphicalMeasure {
 
             // check if this voice has just been found the first time:
             if (latestVoiceTimestamp === undefined) {
-
                 // if this voice is new, check for a gap from measure start to the start of the current voice entry:
                 const gapFromMeasureStart: Fraction = Fraction.minus(gNotesStartTimestamp, this.parentSourceMeasure.AbsoluteTimestamp);
                 if (gapFromMeasureStart.RealValue > 0) {
@@ -651,6 +650,8 @@ export class VexFlowMeasure extends GraphicalMeasure {
                 if (gve.notes[0].sourceNote.PrintObject) {
                     (gve as VexFlowVoiceEntry).vfStaveNote = VexFlowConverter.StaveNote(gve);
                 } else {
+                    // don't render note. add ghost note, otherwise Vexflow can have issues with layouting when voices not complete.
+                    (gve as VexFlowVoiceEntry).vfStaveNote = VexFlowConverter.GhostNote(gve.notes[0].sourceNote.Length);
                     graceGVoiceEntriesBefore = []; // if note is not rendered, its grace notes might need to be removed
                     continue;
                 }
@@ -665,7 +666,6 @@ export class VexFlowMeasure extends GraphicalMeasure {
                         }
                     }
                     const graceNoteGroup: Vex.Flow.GraceNoteGroup = new Vex.Flow.GraceNoteGroup(graceNotes, graceSlur);
-                    // (gve as VexFlowVoiceEntry).vfStaveNote.addModifier(0, graceNoteGroup.beamNotes()); // beams in handleBeam now
                     (gve as VexFlowVoiceEntry).vfStaveNote.addModifier(0, graceNoteGroup);
                     graceGVoiceEntriesBefore = [];
                 }
@@ -707,6 +707,11 @@ export class VexFlowMeasure extends GraphicalMeasure {
                 }
 
                 const vexFlowVoiceEntry: VexFlowVoiceEntry = voiceEntry as VexFlowVoiceEntry;
+                if (voiceEntry.notes.length === 0 || !voiceEntry.notes[0] || !voiceEntry.notes[0].sourceNote.PrintObject) {
+                    // GhostNote, don't add modifiers like in-measure clefs
+                    this.vfVoices[voice.VoiceId].addTickable(vexFlowVoiceEntry.vfStaveNote);
+                    continue;
+                }
 
                 // check for in-measure clefs:
                 // only add clefs in main voice (to not add them twice)

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

@@ -390,14 +390,14 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
 
     let vfStartNote: Vex.Flow.StaveNote = undefined;
     let startNoteIndexInTie: number = 0;
-    if (startNote !== undefined) {
+    if (startNote !== undefined && startNote.vfnote !== undefined && startNote.vfnote.length >= 2) {
       vfStartNote = startNote.vfnote[0];
       startNoteIndexInTie = startNote.vfnote[1];
     }
 
     let vfEndNote: Vex.Flow.StaveNote = undefined;
     let endNoteIndexInTie: number = 0;
-    if (endNote !== undefined) {
+    if (endNote !== undefined && endNote.vfnote !== undefined && endNote.vfnote.length >= 2) {
       vfEndNote = endNote.vfnote[0];
       endNoteIndexInTie = endNote.vfnote[1];
     }

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

@@ -29,7 +29,7 @@ export class VexFlowStaffEntry extends GraphicalStaffEntry {
         for (const gve of this.graphicalVoiceEntries as VexFlowVoiceEntry[]) {
             if (gve.vfStaveNote) {
                 gve.vfStaveNote.setStave(stave);
-                if (!gve.vfStaveNote.preFormatted) {
+                if (!gve.vfStaveNote.preFormatted || gve.vfStaveNote.getBoundingBox() === null) {
                     continue;
                 }
                 gve.applyBordersFromVexflow();

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

@@ -12,6 +12,9 @@ export class VexFlowVoiceEntry extends GraphicalVoiceEntry {
 
     public applyBordersFromVexflow(): void {
         const staveNote: any = (this.vfStaveNote as any);
+        if (!staveNote.getNoteHeadBeginX) {
+            return;
+        }
         const boundingBox: any = staveNote.getBoundingBox();
         const modifierWidth: number = staveNote.getNoteHeadBeginX() - boundingBox.x;