Przeglądaj źródła

fix(Layout): Widen pickup measure per staffentry accidental (#938)

add GraphicalNote.DrawnAccidental
add StaffEntry.MaxAccidentals
sschmidTU 4 lat temu
rodzic
commit
e1f6277962

+ 2 - 1
src/MusicalScore/Graphical/GraphicalNote.ts

@@ -3,7 +3,7 @@ import {Fraction} from "../../Common/DataObjects/Fraction";
 import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
 import {ClefInstruction} from "../VoiceData/Instructions/ClefInstruction";
 import {OctaveEnum} from "../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
-import {Pitch} from "../../Common/DataObjects/Pitch";
+import {AccidentalEnum, Pitch} from "../../Common/DataObjects/Pitch";
 import {GraphicalObject} from "./GraphicalObject";
 import {MusicSheetCalculator} from "./MusicSheetCalculator";
 import {BoundingBox} from "./BoundingBox";
@@ -29,6 +29,7 @@ export class GraphicalNote extends GraphicalObject {
     }
 
     public sourceNote: Note;
+    public DrawnAccidental: AccidentalEnum = AccidentalEnum.NONE;
     public graphicalNoteLength: Fraction;
     public parentVoiceEntry: GraphicalVoiceEntry;
     public numberOfDots: number;

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

@@ -50,6 +50,7 @@ export abstract class GraphicalStaffEntry extends GraphicalObject {
     public staffEntryParent: GraphicalStaffEntry;
     public parentVerticalContainer: VerticalGraphicalStaffEntryContainer;
     public tabStaffEntry: GraphicalStaffEntry = undefined;
+    public MaxAccidentals: number = 0;
 
     private graphicalInstructions: AbstractGraphicalInstruction[] = [];
     private graphicalTies: GraphicalTie[] = [];

+ 7 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowGraphicalNote.ts

@@ -49,11 +49,17 @@ export class VexFlowGraphicalNote extends GraphicalNote {
         //     }
         // } else {
         // revert octave shift, as the placement of the note is independent of octave brackets
-        const drawPitch: Pitch = OctaveShift.getPitchFromOctaveShift(pitch, this.octaveShift);
+        const drawPitch: Pitch = this.drawPitch(pitch);
         // recalculate the pitch, and this time don't ignore the accidental:
         this.vfpitch = VexFlowConverter.pitch(drawPitch, this.sourceNote.isRest(), this.clef, this.sourceNote.Notehead);
+        this.DrawnAccidental = drawPitch.Accidental;
         //}
     }
+
+    public drawPitch(pitch: Pitch): Pitch {
+        return OctaveShift.getPitchFromOctaveShift(pitch, this.octaveShift);
+    }
+
     public Transpose(keyInstruction: KeyInstruction, activeClef: ClefInstruction, halfTones: number, octaveEnum: OctaveEnum): Pitch {
         const tranposedPitch: Pitch = super.Transpose(keyInstruction, activeClef, halfTones, octaveEnum);
         const drawPitch: Pitch = OctaveShift.getPitchFromOctaveShift(tranposedPitch, this.octaveShift);

+ 10 - 4
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -150,13 +150,19 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
     });
 
     let maxStaffEntries: number = measures[0].staffEntries.length;
+    let maxStaffEntriesPlusAccidentals: number = 1;
     for (const measure of measures) {
       if (!measure) {
         continue;
       }
-      // the if is a TEMP change to show pure diff for pickup measures, should be done for all measures, but increases spacing
+      let measureAccidentals: number = 0;
+      for (const staffEntry of measure.staffEntries) {
+        measureAccidentals += (staffEntry as VexFlowStaffEntry).setMaxAccidentals(); // staffEntryAccidentals
+      }
+      // TODO the if is a TEMP change to show pure diff for pickup measures, should be done for all measures, but increases spacing
       if (measure.parentSourceMeasure.ImplicitMeasure) {
         maxStaffEntries = Math.max(measure.staffEntries.length, maxStaffEntries);
+        maxStaffEntriesPlusAccidentals = Math.max(measure.staffEntries.length + measureAccidentals, maxStaffEntriesPlusAccidentals);
       }
       const mvoices: { [voiceID: number]: Vex.Flow.Voice } = (measure as VexFlowMeasure).vfVoices;
       const voices: Vex.Flow.Voice[] = [];
@@ -186,7 +192,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
       minStaffEntriesWidth = formatter.preCalculateMinTotalWidth(allVoices) / unitInPixels
       * this.rules.VoiceSpacingMultiplierVexflow
       + this.rules.VoiceSpacingAddendVexflow
-      + maxStaffEntries * staffEntryFactor;
+      + maxStaffEntries * staffEntryFactor; // TODO use maxStaffEntriesPlusAccidentals here as well, adjust spacing
       if (parentSourceMeasure?.ImplicitMeasure) {
         // shrink width in the ratio that the pickup measure is shorter compared to a full measure('s time signature):
         minStaffEntriesWidth = parentSourceMeasure.Duration.RealValue / parentSourceMeasure.ActiveTimeSignature.RealValue * minStaffEntriesWidth;
@@ -196,9 +202,9 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
 
         // add more than the original staffEntries scaling again: (removing it above makes it too short)
         if (maxStaffEntries > 1) { // not necessary for only 1 StaffEntry
-          minStaffEntriesWidth += maxStaffEntries * staffEntryFactor; // don't scale this for implicit measures
+          console.log('max: ' + maxStaffEntriesPlusAccidentals);
+          minStaffEntriesWidth += maxStaffEntriesPlusAccidentals * staffEntryFactor * 1.5; // don't scale this for implicit measures
           // in fact overscale it, this needs a lot of space the more staffEntries (and modifiers like accidentals) there are
-          //   TODO idea: count accidentals/other modifiers, count them as another staffentry or half or so
         }
         minStaffEntriesWidth *= this.rules.PickupMeasureWidthMultiplier;
       }

+ 23 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.ts

@@ -5,6 +5,7 @@ import { SourceStaffEntry } from "../../VoiceData/SourceStaffEntry";
 import { unitInPixels } from "./VexFlowMusicSheetDrawer";
 import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
 import { Note } from "../../VoiceData/Note";
+import { AccidentalEnum } from "../../../Common/DataObjects/Pitch";
 
 export class VexFlowStaffEntry extends GraphicalStaffEntry {
     constructor(measure: VexFlowMeasure, sourceStaffEntry: SourceStaffEntry, staffEntryParent: VexFlowStaffEntry) {
@@ -57,4 +58,26 @@ export class VexFlowStaffEntry extends GraphicalStaffEntry {
         this.PositionAndShape.RelativePosition.x -= lastBorderLeft;
         this.PositionAndShape.calculateBoundingBox();
     }
+
+    public setMaxAccidentals(): number {
+        for (const gve of this.graphicalVoiceEntries) {
+            for (const note of gve.notes) {
+                if (note.DrawnAccidental !== AccidentalEnum.NONE) {
+                    //TODO continue checking for double accidentals in other notes?
+                    return this.MaxAccidentals = 1;
+                }
+                // live calculation if the note was changed:
+                // let pitch: Pitch = note.sourceNote.Pitch;
+                // pitch = (note as VexFlowGraphicalNote).drawPitch(pitch);
+                // if (pitch) {
+                //     const accidental: AccidentalEnum = pitch.Accidental;
+                //     if (accidental !== AccidentalEnum.NONE) {
+                //         this.maxAccidentals = 1;
+                //         return this.maxAccidentals;
+                //     }
+                // }
+            }
+        }
+        return this.MaxAccidentals = 0;
+    }
 }

+ 3 - 0
src/MusicalScore/VoiceData/Expressions/ContinuousExpressions/OctaveShift.ts

@@ -57,6 +57,9 @@ export class OctaveShift {
      * @returns New pitch with corrected octave shift
      */
     public static getPitchFromOctaveShift(pitch: Pitch, octaveShiftValue: OctaveEnum): Pitch {
+        if (!pitch) {
+            return undefined;
+        }
         let result: number = pitch.Octave;
         switch (octaveShiftValue) {
             case OctaveEnum.VA8:

BIN
test/data/test_pickup_measure_width_chloe_extended_pickup_many_accidentals.mxl