|
@@ -1,38 +1,37 @@
|
|
|
-import {MusicSheetCalculator} from "../MusicSheetCalculator";
|
|
|
-import {VexFlowGraphicalSymbolFactory} from "./VexFlowGraphicalSymbolFactory";
|
|
|
-import {GraphicalMeasure} from "../GraphicalMeasure";
|
|
|
-import {StaffLine} from "../StaffLine";
|
|
|
-import {VoiceEntry} from "../../VoiceData/VoiceEntry";
|
|
|
-import {GraphicalNote} from "../GraphicalNote";
|
|
|
-import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
|
|
|
-import {GraphicalTie} from "../GraphicalTie";
|
|
|
-import {Tie} from "../../VoiceData/Tie";
|
|
|
-import {SourceMeasure} from "../../VoiceData/SourceMeasure";
|
|
|
-import {MultiExpression} from "../../VoiceData/Expressions/MultiExpression";
|
|
|
-import {RepetitionInstruction} from "../../VoiceData/Instructions/RepetitionInstruction";
|
|
|
-import {Beam} from "../../VoiceData/Beam";
|
|
|
-import {ClefInstruction} from "../../VoiceData/Instructions/ClefInstruction";
|
|
|
-import {OctaveEnum, OctaveShift} from "../../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
|
|
|
-import {Fraction} from "../../../Common/DataObjects/Fraction";
|
|
|
-import {LyricWord} from "../../VoiceData/Lyrics/LyricsWord";
|
|
|
-import {OrnamentContainer} from "../../VoiceData/OrnamentContainer";
|
|
|
-import {ArticulationEnum} from "../../VoiceData/VoiceEntry";
|
|
|
-import {Tuplet} from "../../VoiceData/Tuplet";
|
|
|
-import {VexFlowMeasure} from "./VexFlowMeasure";
|
|
|
-import {VexFlowTextMeasurer} from "./VexFlowTextMeasurer";
|
|
|
+import { MusicSheetCalculator } from "../MusicSheetCalculator";
|
|
|
+import { VexFlowGraphicalSymbolFactory } from "./VexFlowGraphicalSymbolFactory";
|
|
|
+import { GraphicalMeasure } from "../GraphicalMeasure";
|
|
|
+import { StaffLine } from "../StaffLine";
|
|
|
+import { VoiceEntry } from "../../VoiceData/VoiceEntry";
|
|
|
+import { GraphicalNote } from "../GraphicalNote";
|
|
|
+import { GraphicalStaffEntry } from "../GraphicalStaffEntry";
|
|
|
+import { GraphicalTie } from "../GraphicalTie";
|
|
|
+import { Tie } from "../../VoiceData/Tie";
|
|
|
+import { SourceMeasure } from "../../VoiceData/SourceMeasure";
|
|
|
+import { MultiExpression } from "../../VoiceData/Expressions/MultiExpression";
|
|
|
+import { RepetitionInstruction } from "../../VoiceData/Instructions/RepetitionInstruction";
|
|
|
+import { Beam } from "../../VoiceData/Beam";
|
|
|
+import { ClefInstruction } from "../../VoiceData/Instructions/ClefInstruction";
|
|
|
+import { OctaveEnum, OctaveShift } from "../../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
|
|
|
+import { Fraction } from "../../../Common/DataObjects/Fraction";
|
|
|
+import { LyricWord } from "../../VoiceData/Lyrics/LyricsWord";
|
|
|
+import { OrnamentContainer } from "../../VoiceData/OrnamentContainer";
|
|
|
+import { ArticulationEnum } from "../../VoiceData/VoiceEntry";
|
|
|
+import { Tuplet } from "../../VoiceData/Tuplet";
|
|
|
+import { VexFlowMeasure } from "./VexFlowMeasure";
|
|
|
+import { VexFlowTextMeasurer } from "./VexFlowTextMeasurer";
|
|
|
import Vex = require("vexflow");
|
|
|
import * as log from "loglevel";
|
|
|
-import {unitInPixels} from "./VexFlowMusicSheetDrawer";
|
|
|
-import {VexFlowGraphicalNote} from "./VexFlowGraphicalNote";
|
|
|
-import {TechnicalInstruction} from "../../VoiceData/Instructions/TechnicalInstruction";
|
|
|
-import {GraphicalLyricEntry} from "../GraphicalLyricEntry";
|
|
|
-import {GraphicalLabel} from "../GraphicalLabel";
|
|
|
-import {LyricsEntry} from "../../VoiceData/Lyrics/LyricsEntry";
|
|
|
-import {GraphicalLyricWord} from "../GraphicalLyricWord";
|
|
|
-import {VexFlowStaffEntry} from "./VexFlowStaffEntry";
|
|
|
+import { unitInPixels } from "./VexFlowMusicSheetDrawer";
|
|
|
+import { VexFlowGraphicalNote } from "./VexFlowGraphicalNote";
|
|
|
+import { TechnicalInstruction } from "../../VoiceData/Instructions/TechnicalInstruction";
|
|
|
+import { GraphicalLyricEntry } from "../GraphicalLyricEntry";
|
|
|
+import { GraphicalLabel } from "../GraphicalLabel";
|
|
|
+import { LyricsEntry } from "../../VoiceData/Lyrics/LyricsEntry";
|
|
|
+import { GraphicalLyricWord } from "../GraphicalLyricWord";
|
|
|
+import { VexFlowStaffEntry } from "./VexFlowStaffEntry";
|
|
|
import { VexFlowOctaveShift } from "./VexFlowOctaveShift";
|
|
|
import { VexFlowInstantaneousDynamicExpression } from "./VexFlowInstantaneousDynamicExpression";
|
|
|
-import {BoundingBox} from "../BoundingBox";
|
|
|
import { Slur } from "../../VoiceData/Expressions/ContinuousExpressions/Slur";
|
|
|
/* VexFlow Version - for later use
|
|
|
// import { VexFlowSlur } from "./VexFlowSlur";
|
|
@@ -40,14 +39,12 @@ import { Slur } from "../../VoiceData/Expressions/ContinuousExpressions/Slur";
|
|
|
// import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
|
|
|
*/
|
|
|
import { EngravingRules } from "../EngravingRules";
|
|
|
-import { InstantaneousDynamicExpression } from "../../VoiceData/Expressions/InstantaneousDynamicExpression";
|
|
|
import { PointF2D } from "../../../Common/DataObjects/PointF2D";
|
|
|
-import { GraphicalInstantaneousDynamicExpression } from "../GraphicalInstantaneousDynamicExpression";
|
|
|
-import { SkyBottomLineCalculator } from "../SkyBottomLineCalculator";
|
|
|
-import { PlacementEnum } from "../../VoiceData/Expressions/AbstractExpression";
|
|
|
-import { Staff } from "../../VoiceData/Staff";
|
|
|
import { TextAlignmentEnum, TextAlignment } from "../../../Common/Enums/TextAlignment";
|
|
|
import { GraphicalSlur } from "../GraphicalSlur";
|
|
|
+import { BoundingBox } from "../BoundingBox";
|
|
|
+import { ContinuousDynamicExpression } from "../../VoiceData/Expressions/ContinuousExpressions/ContinuousDynamicExpression";
|
|
|
+import { VexFlowContinuousDynamicExpression } from "./VexFlowContinuousDynamicExpression";
|
|
|
|
|
|
export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
/** space needed for a dash for lyrics spacing, calculated once */
|
|
@@ -68,17 +65,17 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- protected formatMeasures(): void {
|
|
|
- for (const verticalMeasureList of this.graphicalMusicSheet.MeasureList) {
|
|
|
- const firstMeasure: VexFlowMeasure = verticalMeasureList[0] as VexFlowMeasure;
|
|
|
- // first measure has formatting method as lambda function object, but formats all measures. TODO this could be refactored
|
|
|
- firstMeasure.format();
|
|
|
- for (const measure of verticalMeasureList) {
|
|
|
- for (const staffEntry of measure.staffEntries) {
|
|
|
- (<VexFlowStaffEntry>staffEntry).calculateXPosition();
|
|
|
- }
|
|
|
+ protected formatMeasures(): void {
|
|
|
+ for (const verticalMeasureList of this.graphicalMusicSheet.MeasureList) {
|
|
|
+ const firstMeasure: VexFlowMeasure = verticalMeasureList[0] as VexFlowMeasure;
|
|
|
+ // first measure has formatting method as lambda function object, but formats all measures. TODO this could be refactored
|
|
|
+ firstMeasure.format();
|
|
|
+ for (const measure of verticalMeasureList) {
|
|
|
+ for (const staffEntry of measure.staffEntries) {
|
|
|
+ (<VexFlowStaffEntry>staffEntry).calculateXPosition();
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//protected clearSystemsAndMeasures(): void {
|
|
@@ -109,56 +106,56 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
const formatter: Vex.Flow.Formatter = new Vex.Flow.Formatter();
|
|
|
|
|
|
for (const measure of measures) {
|
|
|
- const mvoices: { [voiceID: number]: Vex.Flow.Voice; } = (measure as VexFlowMeasure).vfVoices;
|
|
|
- const voices: Vex.Flow.Voice[] = [];
|
|
|
- for (const voiceID in mvoices) {
|
|
|
- if (mvoices.hasOwnProperty(voiceID)) {
|
|
|
- voices.push(mvoices[voiceID]);
|
|
|
- allVoices.push(mvoices[voiceID]);
|
|
|
- }
|
|
|
+ const mvoices: { [voiceID: number]: Vex.Flow.Voice; } = (measure as VexFlowMeasure).vfVoices;
|
|
|
+ const voices: Vex.Flow.Voice[] = [];
|
|
|
+ for (const voiceID in mvoices) {
|
|
|
+ if (mvoices.hasOwnProperty(voiceID)) {
|
|
|
+ voices.push(mvoices[voiceID]);
|
|
|
+ allVoices.push(mvoices[voiceID]);
|
|
|
}
|
|
|
- if (voices.length === 0) {
|
|
|
- log.info("Found a measure with no voices. Continuing anyway.", mvoices);
|
|
|
- continue;
|
|
|
- }
|
|
|
- // all voices that belong to one stave are collectively added to create a common context in VexFlow.
|
|
|
- formatter.joinVoices(voices);
|
|
|
+ }
|
|
|
+ if (voices.length === 0) {
|
|
|
+ log.info("Found a measure with no voices. Continuing anyway.", mvoices);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // all voices that belong to one stave are collectively added to create a common context in VexFlow.
|
|
|
+ formatter.joinVoices(voices);
|
|
|
}
|
|
|
|
|
|
let minStaffEntriesWidth: number = 200;
|
|
|
if (allVoices.length > 0) {
|
|
|
- // FIXME: The following ``+ 5.0'' is temporary: it was added as a workaround for
|
|
|
- // FIXME: a more relaxed formatting of voices
|
|
|
- minStaffEntriesWidth = formatter.preCalculateMinTotalWidth(allVoices) / unitInPixels + 5.0;
|
|
|
- // firstMeasure.formatVoices = (w: number) => {
|
|
|
- // formatter.format(allVoices, w);
|
|
|
- // };
|
|
|
- MusicSheetCalculator.setMeasuresMinStaffEntriesWidth(measures, minStaffEntriesWidth);
|
|
|
- for (const measure of measures) {
|
|
|
- if (measure === measures[0]) {
|
|
|
- const vexflowMeasure: VexFlowMeasure = (measure as VexFlowMeasure);
|
|
|
- // prepare format function for voices, will be called later for formatting measure again
|
|
|
- vexflowMeasure.formatVoices = (w: number) => {
|
|
|
- formatter.format(allVoices, w);
|
|
|
- // formatter.format(allVoices, w, {
|
|
|
- // align_rests: false, // TODO
|
|
|
- // // align_rests = true causes a Vexflow Exception for Mozart - An Chloe
|
|
|
- // // align_rests = false still aligns rests with beams according to Vexflow, but doesn't seem to do anything
|
|
|
- // });
|
|
|
- };
|
|
|
- // format now for minimum width, calculateMeasureWidthFromLyrics later
|
|
|
- vexflowMeasure.formatVoices(minStaffEntriesWidth * unitInPixels);
|
|
|
- } else {
|
|
|
- (measure as VexFlowMeasure).formatVoices = undefined;
|
|
|
- }
|
|
|
+ // FIXME: The following ``+ 5.0'' is temporary: it was added as a workaround for
|
|
|
+ // FIXME: a more relaxed formatting of voices
|
|
|
+ minStaffEntriesWidth = formatter.preCalculateMinTotalWidth(allVoices) / unitInPixels + 5.0;
|
|
|
+ // firstMeasure.formatVoices = (w: number) => {
|
|
|
+ // formatter.format(allVoices, w);
|
|
|
+ // };
|
|
|
+ MusicSheetCalculator.setMeasuresMinStaffEntriesWidth(measures, minStaffEntriesWidth);
|
|
|
+ for (const measure of measures) {
|
|
|
+ if (measure === measures[0]) {
|
|
|
+ const vexflowMeasure: VexFlowMeasure = (measure as VexFlowMeasure);
|
|
|
+ // prepare format function for voices, will be called later for formatting measure again
|
|
|
+ vexflowMeasure.formatVoices = (w: number) => {
|
|
|
+ formatter.format(allVoices, w);
|
|
|
+ // formatter.format(allVoices, w, {
|
|
|
+ // align_rests: false, // TODO
|
|
|
+ // // align_rests = true causes a Vexflow Exception for Mozart - An Chloe
|
|
|
+ // // align_rests = false still aligns rests with beams according to Vexflow, but doesn't seem to do anything
|
|
|
+ // });
|
|
|
+ };
|
|
|
+ // format now for minimum width, calculateMeasureWidthFromLyrics later
|
|
|
+ vexflowMeasure.formatVoices(minStaffEntriesWidth * unitInPixels);
|
|
|
+ } else {
|
|
|
+ (measure as VexFlowMeasure).formatVoices = undefined;
|
|
|
}
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
for (const graphicalMeasure of measures) {
|
|
|
for (const staffEntry of graphicalMeasure.staffEntries) {
|
|
|
// here the measure modifiers are not yet set, therefore the begin instruction width will be empty
|
|
|
(<VexFlowStaffEntry>staffEntry).calculateXPosition();
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
// calculateMeasureWidthFromLyrics() will be called from MusicSheetCalculator after this
|
|
|
return minStaffEntriesWidth;
|
|
@@ -314,7 +311,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
|
|
|
|
|
|
protected updateStaffLineBorders(staffLine: StaffLine): void {
|
|
|
- staffLine.SkyBottomLineCalculator.updateStaffLineBorders();
|
|
|
+ staffLine.SkyBottomLineCalculator.updateStaffLineBorders();
|
|
|
}
|
|
|
|
|
|
protected graphicalMeasureCreatedCalculations(measure: GraphicalMeasure): void {
|
|
@@ -350,15 +347,15 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
*/
|
|
|
protected calculateSystemYLayout(): void {
|
|
|
for (const graphicalMusicPage of this.graphicalMusicSheet.MusicPages) {
|
|
|
- for (const musicSystem of graphicalMusicPage.MusicSystems) {
|
|
|
- this.optimizeDistanceBetweenStaffLines(musicSystem);
|
|
|
- }
|
|
|
-
|
|
|
- // set y positions of systems using the previous system and a fixed distance.
|
|
|
- this.calculateMusicSystemsRelativePositions(graphicalMusicPage);
|
|
|
- }
|
|
|
+ for (const musicSystem of graphicalMusicPage.MusicSystems) {
|
|
|
+ this.optimizeDistanceBetweenStaffLines(musicSystem);
|
|
|
}
|
|
|
|
|
|
+ // set y positions of systems using the previous system and a fixed distance.
|
|
|
+ this.calculateMusicSystemsRelativePositions(graphicalMusicPage);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Is called at the begin of the method for creating the vertically aligned staff measures belonging to one source measure.
|
|
|
*/
|
|
@@ -379,25 +376,25 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Calculate the shape (Bezier curve) for this tie.
|
|
|
- * @param tie
|
|
|
- * @param tieIsAtSystemBreak
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * Calculate the shape (Bezier curve) for this tie.
|
|
|
+ * @param tie
|
|
|
+ * @param tieIsAtSystemBreak
|
|
|
+ */
|
|
|
protected layoutGraphicalTie(tie: GraphicalTie, tieIsAtSystemBreak: boolean): void {
|
|
|
const startNote: VexFlowGraphicalNote = (tie.StartNote as VexFlowGraphicalNote);
|
|
|
const endNote: VexFlowGraphicalNote = (tie.EndNote as VexFlowGraphicalNote);
|
|
|
|
|
|
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];
|
|
|
}
|
|
@@ -436,127 +433,50 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
const absoluteTimestamp: Fraction = multiExpression.AbsoluteTimestamp;
|
|
|
const measures: GraphicalMeasure[] = this.graphicalMusicSheet.MeasureList[measureIndex];
|
|
|
const staffLine: StaffLine = measures[staffIndex].ParentStaffLine;
|
|
|
+ const startMeasure: GraphicalMeasure = measures[staffIndex];
|
|
|
|
|
|
- if (multiExpression.InstantaneousDynamic) {
|
|
|
- const instantaneousDynamic: InstantaneousDynamicExpression = multiExpression.InstantaneousDynamic;
|
|
|
-
|
|
|
- const startPosInStaffline: PointF2D = this.getRelativePositionInStaffLineFromTimestamp(
|
|
|
- absoluteTimestamp,
|
|
|
- staffIndex,
|
|
|
- staffLine,
|
|
|
- staffLine.isPartOfMultiStaffInstrument());
|
|
|
- if (Math.abs(startPosInStaffline.x) === 0) {
|
|
|
- startPosInStaffline.x = measures[staffIndex].beginInstructionsWidth + this.rules.RhythmRightMargin;
|
|
|
- }
|
|
|
- const measure: GraphicalMeasure = this.graphicalMusicSheet.MeasureList[measureIndex][staffIndex];
|
|
|
- const graphicalInstantaneousDynamic: VexFlowInstantaneousDynamicExpression = new VexFlowInstantaneousDynamicExpression(
|
|
|
- instantaneousDynamic,
|
|
|
- staffLine,
|
|
|
- measure);
|
|
|
- (measure as VexFlowMeasure).instantaneousDynamics.push(graphicalInstantaneousDynamic);
|
|
|
- this.calculateGraphicalInstantaneousDynamicExpression(graphicalInstantaneousDynamic, staffLine, startPosInStaffline);
|
|
|
- }
|
|
|
- }
|
|
|
+ const startPosInStaffline: PointF2D = this.getRelativePositionInStaffLineFromTimestamp(
|
|
|
+ absoluteTimestamp,
|
|
|
+ staffIndex,
|
|
|
+ staffLine,
|
|
|
+ staffLine.isPartOfMultiStaffInstrument());
|
|
|
|
|
|
- public calculateGraphicalInstantaneousDynamicExpression(graphicalInstantaneousDynamic: VexFlowInstantaneousDynamicExpression,
|
|
|
- staffLine: StaffLine,
|
|
|
- relative: PointF2D): void {
|
|
|
- // // add to StaffLine and set PSI relations
|
|
|
- staffLine.AbstractExpressions.push(graphicalInstantaneousDynamic);
|
|
|
- staffLine.PositionAndShape.ChildElements.push(graphicalInstantaneousDynamic.PositionAndShape);
|
|
|
- if (this.staffLinesWithGraphicalExpressions.indexOf(staffLine) === -1) {
|
|
|
- this.staffLinesWithGraphicalExpressions.push(staffLine);
|
|
|
+ const dynamicStartPosition: PointF2D = startPosInStaffline;
|
|
|
+ if (startPosInStaffline.x <= 0) {
|
|
|
+ dynamicStartPosition.x = startMeasure.beginInstructionsWidth + this.rules.RhythmRightMargin;
|
|
|
}
|
|
|
|
|
|
- // get Margin Dimensions
|
|
|
- const left: number = relative.x + graphicalInstantaneousDynamic.PositionAndShape.BorderMarginLeft;
|
|
|
- const right: number = relative.x + graphicalInstantaneousDynamic.PositionAndShape.BorderMarginRight;
|
|
|
- const skyBottomLineCalculator: SkyBottomLineCalculator = staffLine.SkyBottomLineCalculator;
|
|
|
-
|
|
|
- // get possible previous Dynamic
|
|
|
- let previousExpression: GraphicalInstantaneousDynamicExpression = undefined;
|
|
|
- const expressionIndex: number = staffLine.AbstractExpressions.indexOf(graphicalInstantaneousDynamic);
|
|
|
- if (expressionIndex > 0) {
|
|
|
- previousExpression = (staffLine.AbstractExpressions[expressionIndex - 1] as GraphicalInstantaneousDynamicExpression);
|
|
|
+ if (multiExpression.InstantaneousDynamic) {
|
|
|
+ const graphicalInstantaneousDynamic: VexFlowInstantaneousDynamicExpression = new VexFlowInstantaneousDynamicExpression(
|
|
|
+ multiExpression.InstantaneousDynamic,
|
|
|
+ staffLine,
|
|
|
+ startMeasure);
|
|
|
+ this.calculateGraphicalInstantaneousDynamicExpression(graphicalInstantaneousDynamic, dynamicStartPosition);
|
|
|
}
|
|
|
-
|
|
|
- // TODO: Not yet implemented
|
|
|
- // // is previous a ContinuousDynamic?
|
|
|
- // if (previousExpression && previousExpression instanceof GraphicalContinuousDynamicExpression)
|
|
|
- // {
|
|
|
- // GraphicalContinuousDynamicExpression formerGraphicalContinuousDynamic =
|
|
|
- // (GraphicalContinuousDynamicExpression)previousExpression;
|
|
|
-
|
|
|
- // optimizeFormerContDynamicXPositionForInstDynamic(staffLine, skyBottomLineCalculator,
|
|
|
- // graphicalInstantaneousDynamic,
|
|
|
- // formerGraphicalContinuousDynamic, left, right);
|
|
|
- // }
|
|
|
- // // is previous a instantaneousDynamic?
|
|
|
- // else
|
|
|
- if (previousExpression && previousExpression instanceof GraphicalInstantaneousDynamicExpression) {
|
|
|
- //const formerGraphicalInstantaneousDynamic: GraphicalInstantaneousDynamicExpression = previousExpression;
|
|
|
-
|
|
|
- // optimizeFormerInstDynamicXPositionForInstDynamic(formerGraphicalInstantaneousDynamic,
|
|
|
- // graphicalInstantaneousDynamic, ref relative, ref left, ref right);
|
|
|
- }// End x-positioning overlap check
|
|
|
-
|
|
|
- // calculate yPosition according to Placement
|
|
|
- if (graphicalInstantaneousDynamic.InstantaneousDynamic.Placement === PlacementEnum.Above) {
|
|
|
- const skyLineValue: number = skyBottomLineCalculator.getSkyLineMinInRange(left, right);
|
|
|
- let yPosition: number = 0;
|
|
|
-
|
|
|
- // if StaffLine part of multiStafff Instrument and not the first one, ideal yPosition middle of distance between Staves
|
|
|
- if (staffLine.isPartOfMultiStaffInstrument() && staffLine.ParentStaff !== staffLine.ParentStaff.ParentInstrument.Staves[0]) {
|
|
|
- const formerStaffLine: StaffLine = staffLine.ParentMusicSystem.StaffLines[staffLine.ParentMusicSystem.StaffLines.indexOf(staffLine) - 1];
|
|
|
- const difference: number = staffLine.PositionAndShape.RelativePosition.y -
|
|
|
- formerStaffLine.PositionAndShape.RelativePosition.y - this.rules.StaffHeight;
|
|
|
-
|
|
|
- // take always into account the size of the Dynamic
|
|
|
- if (skyLineValue > -difference / 2) {
|
|
|
- yPosition = -difference / 2;
|
|
|
- } else {
|
|
|
- yPosition = skyLineValue - graphicalInstantaneousDynamic.PositionAndShape.BorderMarginBottom;
|
|
|
- }
|
|
|
- } else {
|
|
|
- yPosition = skyLineValue - graphicalInstantaneousDynamic.PositionAndShape.BorderMarginBottom;
|
|
|
- }
|
|
|
-
|
|
|
- graphicalInstantaneousDynamic.PositionAndShape.RelativePosition = new PointF2D(relative.x, yPosition);
|
|
|
- skyBottomLineCalculator.updateSkyLineInRange(left, right, yPosition + graphicalInstantaneousDynamic.PositionAndShape.BorderMarginTop);
|
|
|
- } else if (graphicalInstantaneousDynamic.InstantaneousDynamic.Placement === PlacementEnum.Below) {
|
|
|
- const bottomLineValue: number = skyBottomLineCalculator.getBottomLineMaxInRange(left, right);
|
|
|
- let yPosition: number = 0;
|
|
|
-
|
|
|
- // if StaffLine part of multiStafff Instrument and not the last one, ideal yPosition middle of distance between Staves
|
|
|
- const lastStaff: Staff = staffLine.ParentStaff.ParentInstrument.Staves[staffLine.ParentStaff.ParentInstrument.Staves.length - 1];
|
|
|
- if (staffLine.isPartOfMultiStaffInstrument() && staffLine.ParentStaff !== lastStaff) {
|
|
|
- const nextStaffLine: StaffLine = staffLine.ParentMusicSystem.StaffLines[staffLine.ParentMusicSystem.StaffLines.indexOf(staffLine) + 1];
|
|
|
- const difference: number = nextStaffLine.PositionAndShape.RelativePosition.y -
|
|
|
- staffLine.PositionAndShape.RelativePosition.y - this.rules.StaffHeight;
|
|
|
- const border: number = graphicalInstantaneousDynamic.PositionAndShape.BorderMarginBottom;
|
|
|
-
|
|
|
- // take always into account the size of the Dynamic
|
|
|
- if (bottomLineValue + border < this.rules.StaffHeight + difference / 2) {
|
|
|
- yPosition = this.rules.StaffHeight + difference / 2;
|
|
|
- } else {
|
|
|
- yPosition = bottomLineValue - graphicalInstantaneousDynamic.PositionAndShape.BorderMarginTop;
|
|
|
- }
|
|
|
- } else {
|
|
|
- yPosition = bottomLineValue - graphicalInstantaneousDynamic.PositionAndShape.BorderMarginTop;
|
|
|
- }
|
|
|
-
|
|
|
- graphicalInstantaneousDynamic.PositionAndShape.RelativePosition = new PointF2D(relative.x, yPosition);
|
|
|
- skyBottomLineCalculator.updateBottomLineInRange(left, right, yPosition + graphicalInstantaneousDynamic.PositionAndShape.BorderMarginBottom);
|
|
|
+ if (multiExpression.StartingContinuousDynamic) {
|
|
|
+ const continuousDynamic: ContinuousDynamicExpression = multiExpression.StartingContinuousDynamic;
|
|
|
+ const graphicalContinuousDynamic: VexFlowContinuousDynamicExpression = new VexFlowContinuousDynamicExpression(
|
|
|
+ multiExpression.StartingContinuousDynamic,
|
|
|
+ staffLine);
|
|
|
+ graphicalContinuousDynamic.StartMeasure = startMeasure;
|
|
|
+
|
|
|
+ if (!graphicalContinuousDynamic.IsVerbal && continuousDynamic.EndMultiExpression) {
|
|
|
+ this.calculateGraphicalContinuousDynamic(graphicalContinuousDynamic, dynamicStartPosition);
|
|
|
+ } else if (graphicalContinuousDynamic.IsVerbal) {
|
|
|
+ this.calculateGraphicalVerbalContinuousDynamic(graphicalContinuousDynamic, dynamicStartPosition);
|
|
|
+ } else {
|
|
|
+ log.warn("This continous dynamic is not covered");
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * Calculate a single OctaveShift for a [[MultiExpression]].
|
|
|
- * @param sourceMeasure
|
|
|
- * @param multiExpression
|
|
|
- * @param measureIndex
|
|
|
- * @param staffIndex
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * Calculate a single OctaveShift for a [[MultiExpression]].
|
|
|
+ * @param sourceMeasure
|
|
|
+ * @param multiExpression
|
|
|
+ * @param measureIndex
|
|
|
+ * @param staffIndex
|
|
|
+ */
|
|
|
protected calculateSingleOctaveShift(sourceMeasure: SourceMeasure, multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
|
|
|
// calculate absolute Timestamp and startStaffLine (and EndStaffLine if needed)
|
|
|
const octaveShift: OctaveShift = multiExpression.OctaveShiftStart;
|
|
@@ -568,9 +488,9 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
|
|
|
let endMeasure: GraphicalMeasure = undefined;
|
|
|
if (octaveShift.ParentEndMultiExpression !== undefined) {
|
|
|
- endMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(octaveShift.ParentEndMultiExpression.SourceMeasureParent,
|
|
|
- staffIndex);
|
|
|
- }
|
|
|
+ endMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(octaveShift.ParentEndMultiExpression.SourceMeasureParent,
|
|
|
+ staffIndex);
|
|
|
+ }
|
|
|
let startMeasure: GraphicalMeasure = undefined;
|
|
|
if (octaveShift.ParentEndMultiExpression !== undefined) {
|
|
|
startMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(octaveShift.ParentStartMultiExpression.SourceMeasureParent,
|
|
@@ -578,76 +498,76 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
}
|
|
|
|
|
|
if (endMeasure !== undefined) {
|
|
|
- // calculate GraphicalOctaveShift and RelativePositions
|
|
|
- const graphicalOctaveShift: VexFlowOctaveShift = new VexFlowOctaveShift(octaveShift, startStaffLine.PositionAndShape);
|
|
|
- startStaffLine.OctaveShifts.push(graphicalOctaveShift);
|
|
|
-
|
|
|
- // calculate RelativePosition and Dashes
|
|
|
- const startStaffEntry: GraphicalStaffEntry = startMeasure.findGraphicalStaffEntryFromTimestamp(startTimeStamp);
|
|
|
- const endStaffEntry: GraphicalStaffEntry = endMeasure.findGraphicalStaffEntryFromTimestamp(endTimeStamp);
|
|
|
-
|
|
|
- graphicalOctaveShift.setStartNote(startStaffEntry);
|
|
|
-
|
|
|
- if (endMeasure.ParentStaffLine !== startMeasure.ParentStaffLine) {
|
|
|
- graphicalOctaveShift.endsOnDifferentStaffLine = true;
|
|
|
- const lastMeasure: GraphicalMeasure = startMeasure.ParentStaffLine.Measures[startMeasure.ParentStaffLine.Measures.length - 1];
|
|
|
- const lastNote: GraphicalStaffEntry = lastMeasure.staffEntries[lastMeasure.staffEntries.length - 1];
|
|
|
- graphicalOctaveShift.setEndNote(lastNote);
|
|
|
-
|
|
|
- // Now finish the shift on the next line
|
|
|
- const remainingOctaveShift: VexFlowOctaveShift = new VexFlowOctaveShift(octaveShift, endMeasure.PositionAndShape);
|
|
|
- endMeasure.ParentStaffLine.OctaveShifts.push(remainingOctaveShift);
|
|
|
- const firstMeasure: GraphicalMeasure = endMeasure.ParentStaffLine.Measures[0];
|
|
|
- const firstNote: GraphicalStaffEntry = firstMeasure.staffEntries[0];
|
|
|
- remainingOctaveShift.setStartNote(firstNote);
|
|
|
- remainingOctaveShift.setEndNote(endStaffEntry);
|
|
|
- } else {
|
|
|
- graphicalOctaveShift.setEndNote(endStaffEntry);
|
|
|
- }
|
|
|
+ // calculate GraphicalOctaveShift and RelativePositions
|
|
|
+ const graphicalOctaveShift: VexFlowOctaveShift = new VexFlowOctaveShift(octaveShift, startStaffLine.PositionAndShape);
|
|
|
+ startStaffLine.OctaveShifts.push(graphicalOctaveShift);
|
|
|
+
|
|
|
+ // calculate RelativePosition and Dashes
|
|
|
+ const startStaffEntry: GraphicalStaffEntry = startMeasure.findGraphicalStaffEntryFromTimestamp(startTimeStamp);
|
|
|
+ const endStaffEntry: GraphicalStaffEntry = endMeasure.findGraphicalStaffEntryFromTimestamp(endTimeStamp);
|
|
|
+
|
|
|
+ graphicalOctaveShift.setStartNote(startStaffEntry);
|
|
|
+
|
|
|
+ if (endMeasure.ParentStaffLine !== startMeasure.ParentStaffLine) {
|
|
|
+ graphicalOctaveShift.endsOnDifferentStaffLine = true;
|
|
|
+ const lastMeasure: GraphicalMeasure = startMeasure.ParentStaffLine.Measures[startMeasure.ParentStaffLine.Measures.length - 1];
|
|
|
+ const lastNote: GraphicalStaffEntry = lastMeasure.staffEntries[lastMeasure.staffEntries.length - 1];
|
|
|
+ graphicalOctaveShift.setEndNote(lastNote);
|
|
|
+
|
|
|
+ // Now finish the shift on the next line
|
|
|
+ const remainingOctaveShift: VexFlowOctaveShift = new VexFlowOctaveShift(octaveShift, endMeasure.PositionAndShape);
|
|
|
+ endMeasure.ParentStaffLine.OctaveShifts.push(remainingOctaveShift);
|
|
|
+ const firstMeasure: GraphicalMeasure = endMeasure.ParentStaffLine.Measures[0];
|
|
|
+ const firstNote: GraphicalStaffEntry = firstMeasure.staffEntries[0];
|
|
|
+ remainingOctaveShift.setStartNote(firstNote);
|
|
|
+ remainingOctaveShift.setEndNote(endStaffEntry);
|
|
|
+ } else {
|
|
|
+ graphicalOctaveShift.setEndNote(endStaffEntry);
|
|
|
+ }
|
|
|
} else {
|
|
|
log.warn("End measure for octave shift is undefined! This should not happen!");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Calculate all the textual and symbolic [[RepetitionInstruction]]s (e.g. dal segno) for a single [[SourceMeasure]].
|
|
|
- * @param repetitionInstruction
|
|
|
- * @param measureIndex
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * Calculate all the textual and symbolic [[RepetitionInstruction]]s (e.g. dal segno) for a single [[SourceMeasure]].
|
|
|
+ * @param repetitionInstruction
|
|
|
+ * @param measureIndex
|
|
|
+ */
|
|
|
protected calculateWordRepetitionInstruction(repetitionInstruction: RepetitionInstruction, measureIndex: number): void {
|
|
|
- // find first visible StaffLine
|
|
|
- let uppermostMeasure: VexFlowMeasure = undefined;
|
|
|
- const measures: VexFlowMeasure[] = <VexFlowMeasure[]>this.graphicalMusicSheet.MeasureList[measureIndex];
|
|
|
- for (let idx: number = 0, len: number = measures.length; idx < len; ++idx) {
|
|
|
- const graphicalMeasure: VexFlowMeasure = measures[idx];
|
|
|
- if (graphicalMeasure.ParentStaffLine !== undefined && graphicalMeasure.ParentStaff.ParentInstrument.Visible) {
|
|
|
- uppermostMeasure = <VexFlowMeasure>graphicalMeasure;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- // ToDo: feature/Repetitions
|
|
|
- // now create corresponding graphical symbol or Text in VexFlow:
|
|
|
- // use top measure and staffline for positioning.
|
|
|
- if (uppermostMeasure !== undefined) {
|
|
|
- uppermostMeasure.addWordRepetition(repetitionInstruction);
|
|
|
+ // find first visible StaffLine
|
|
|
+ let uppermostMeasure: VexFlowMeasure = undefined;
|
|
|
+ const measures: VexFlowMeasure[] = <VexFlowMeasure[]>this.graphicalMusicSheet.MeasureList[measureIndex];
|
|
|
+ for (let idx: number = 0, len: number = measures.length; idx < len; ++idx) {
|
|
|
+ const graphicalMeasure: VexFlowMeasure = measures[idx];
|
|
|
+ if (graphicalMeasure.ParentStaffLine !== undefined && graphicalMeasure.ParentStaff.ParentInstrument.Visible) {
|
|
|
+ uppermostMeasure = <VexFlowMeasure>graphicalMeasure;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
+ // ToDo: feature/Repetitions
|
|
|
+ // now create corresponding graphical symbol or Text in VexFlow:
|
|
|
+ // use top measure and staffline for positioning.
|
|
|
+ if (uppermostMeasure !== undefined) {
|
|
|
+ uppermostMeasure.addWordRepetition(repetitionInstruction);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
protected calculateMoodAndUnknownExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Check if the tied graphical note belongs to any beams or tuplets and react accordingly.
|
|
|
- * @param tiedGraphicalNote
|
|
|
- * @param beams
|
|
|
- * @param activeClef
|
|
|
- * @param octaveShiftValue
|
|
|
- * @param graphicalStaffEntry
|
|
|
- * @param duration
|
|
|
- * @param openTie
|
|
|
- * @param isLastTieNote
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * Check if the tied graphical note belongs to any beams or tuplets and react accordingly.
|
|
|
+ * @param tiedGraphicalNote
|
|
|
+ * @param beams
|
|
|
+ * @param activeClef
|
|
|
+ * @param octaveShiftValue
|
|
|
+ * @param graphicalStaffEntry
|
|
|
+ * @param duration
|
|
|
+ * @param openTie
|
|
|
+ * @param isLastTieNote
|
|
|
+ */
|
|
|
protected handleTiedGraphicalNote(tiedGraphicalNote: GraphicalNote, beams: Beam[], activeClef: ClefInstruction,
|
|
|
octaveShiftValue: OctaveEnum, graphicalStaffEntry: GraphicalStaffEntry, duration: Fraction,
|
|
|
openTie: Tie, isLastTieNote: boolean): void {
|
|
@@ -665,45 +585,45 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
}
|
|
|
|
|
|
protected handleVoiceEntryLyrics(voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry, lyricWords: LyricWord[]): void {
|
|
|
- voiceEntry.LyricsEntries.forEach((key: number, lyricsEntry: LyricsEntry) => {
|
|
|
- const graphicalLyricEntry: GraphicalLyricEntry = new GraphicalLyricEntry(lyricsEntry,
|
|
|
- graphicalStaffEntry,
|
|
|
- this.rules.LyricsHeight,
|
|
|
- this.rules.StaffHeight);
|
|
|
-
|
|
|
- graphicalStaffEntry.LyricsEntries.push(graphicalLyricEntry);
|
|
|
-
|
|
|
- // create corresponding GraphicalLabel
|
|
|
- const graphicalLabel: GraphicalLabel = graphicalLyricEntry.GraphicalLabel;
|
|
|
- graphicalLabel.setLabelPositionAndShapeBorders();
|
|
|
-
|
|
|
- if (lyricsEntry.Word !== undefined) {
|
|
|
- const lyricsEntryIndex: number = lyricsEntry.Word.Syllables.indexOf(lyricsEntry);
|
|
|
- let index: number = lyricWords.indexOf(lyricsEntry.Word);
|
|
|
- if (index === -1) {
|
|
|
- lyricWords.push(lyricsEntry.Word);
|
|
|
- index = lyricWords.indexOf(lyricsEntry.Word);
|
|
|
- }
|
|
|
+ voiceEntry.LyricsEntries.forEach((key: number, lyricsEntry: LyricsEntry) => {
|
|
|
+ const graphicalLyricEntry: GraphicalLyricEntry = new GraphicalLyricEntry(lyricsEntry,
|
|
|
+ graphicalStaffEntry,
|
|
|
+ this.rules.LyricsHeight,
|
|
|
+ this.rules.StaffHeight);
|
|
|
+
|
|
|
+ graphicalStaffEntry.LyricsEntries.push(graphicalLyricEntry);
|
|
|
+
|
|
|
+ // create corresponding GraphicalLabel
|
|
|
+ const graphicalLabel: GraphicalLabel = graphicalLyricEntry.GraphicalLabel;
|
|
|
+ graphicalLabel.setLabelPositionAndShapeBorders();
|
|
|
+
|
|
|
+ if (lyricsEntry.Word !== undefined) {
|
|
|
+ const lyricsEntryIndex: number = lyricsEntry.Word.Syllables.indexOf(lyricsEntry);
|
|
|
+ let index: number = lyricWords.indexOf(lyricsEntry.Word);
|
|
|
+ if (index === -1) {
|
|
|
+ lyricWords.push(lyricsEntry.Word);
|
|
|
+ index = lyricWords.indexOf(lyricsEntry.Word);
|
|
|
+ }
|
|
|
|
|
|
- if (this.graphicalLyricWords.length === 0 || index > this.graphicalLyricWords.length - 1) {
|
|
|
- const graphicalLyricWord: GraphicalLyricWord = new GraphicalLyricWord(lyricsEntry.Word);
|
|
|
+ if (this.graphicalLyricWords.length === 0 || index > this.graphicalLyricWords.length - 1) {
|
|
|
+ const graphicalLyricWord: GraphicalLyricWord = new GraphicalLyricWord(lyricsEntry.Word);
|
|
|
|
|
|
- graphicalLyricEntry.ParentLyricWord = graphicalLyricWord;
|
|
|
- graphicalLyricWord.GraphicalLyricsEntries[lyricsEntryIndex] = graphicalLyricEntry;
|
|
|
- this.graphicalLyricWords.push(graphicalLyricWord);
|
|
|
- } else {
|
|
|
- const graphicalLyricWord: GraphicalLyricWord = this.graphicalLyricWords[index];
|
|
|
+ graphicalLyricEntry.ParentLyricWord = graphicalLyricWord;
|
|
|
+ graphicalLyricWord.GraphicalLyricsEntries[lyricsEntryIndex] = graphicalLyricEntry;
|
|
|
+ this.graphicalLyricWords.push(graphicalLyricWord);
|
|
|
+ } else {
|
|
|
+ const graphicalLyricWord: GraphicalLyricWord = this.graphicalLyricWords[index];
|
|
|
|
|
|
- graphicalLyricEntry.ParentLyricWord = graphicalLyricWord;
|
|
|
- graphicalLyricWord.GraphicalLyricsEntries[lyricsEntryIndex] = graphicalLyricEntry;
|
|
|
+ graphicalLyricEntry.ParentLyricWord = graphicalLyricWord;
|
|
|
+ graphicalLyricWord.GraphicalLyricsEntries[lyricsEntryIndex] = graphicalLyricEntry;
|
|
|
|
|
|
- if (graphicalLyricWord.isFilled()) {
|
|
|
- lyricWords.splice(index, 1);
|
|
|
- this.graphicalLyricWords.splice(this.graphicalLyricWords.indexOf(graphicalLyricWord), 1);
|
|
|
- }
|
|
|
- }
|
|
|
+ if (graphicalLyricWord.isFilled()) {
|
|
|
+ lyricWords.splice(index, 1);
|
|
|
+ this.graphicalLyricWords.splice(this.graphicalLyricWords.indexOf(graphicalLyricWord), 1);
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
protected handleVoiceEntryOrnaments(ornamentContainer: OrnamentContainer, voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry): void {
|
|
@@ -754,9 +674,9 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
*/
|
|
|
public findIndexGraphicalSlurFromSlur(gSlurs: GraphicalSlur[], slur: Slur): number {
|
|
|
for (let slurIndex: number = 0; slurIndex < gSlurs.length; slurIndex++) {
|
|
|
- if (gSlurs[slurIndex].slur === slur) {
|
|
|
- return slurIndex;
|
|
|
- }
|
|
|
+ if (gSlurs[slurIndex].slur === slur) {
|
|
|
+ return slurIndex;
|
|
|
+ }
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
@@ -789,175 +709,177 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
|
|
|
*/
|
|
|
|
|
|
for (const gmPage of this.graphicalMusicSheet.MusicPages) {
|
|
|
- for (const musicSystem of gmPage.MusicSystems) {
|
|
|
- for (const staffLine of musicSystem.StaffLines) {
|
|
|
- // if a graphical slur reaches out of the last musicsystem, we have to create another graphical slur reaching into this musicsystem
|
|
|
- // (one slur needs 2 graphical slurs)
|
|
|
- const openGraphicalSlurs: GraphicalSlur[] = openSlursDict[staffLine.ParentStaff.idInMusicSheet];
|
|
|
- for (let slurIndex: number = 0; slurIndex < openGraphicalSlurs.length; slurIndex++) {
|
|
|
- const oldGSlur: GraphicalSlur = openGraphicalSlurs[slurIndex];
|
|
|
- const newGSlur: GraphicalSlur = new GraphicalSlur(oldGSlur.slur); //Graphicalslur.createFromSlur(oldSlur);
|
|
|
- staffLine.addSlurToStaffline(newGSlur); // every VFSlur is added to the array in the VFStaffline!
|
|
|
- openGraphicalSlurs[slurIndex] = newGSlur;
|
|
|
- }
|
|
|
+ for (const musicSystem of gmPage.MusicSystems) {
|
|
|
+ for (const staffLine of musicSystem.StaffLines) {
|
|
|
+ // if a graphical slur reaches out of the last musicsystem, we have to create another graphical slur reaching into this musicsystem
|
|
|
+ // (one slur needs 2 graphical slurs)
|
|
|
+ const openGraphicalSlurs: GraphicalSlur[] = openSlursDict[staffLine.ParentStaff.idInMusicSheet];
|
|
|
+ for (let slurIndex: number = 0; slurIndex < openGraphicalSlurs.length; slurIndex++) {
|
|
|
+ const oldGSlur: GraphicalSlur = openGraphicalSlurs[slurIndex];
|
|
|
+ const newGSlur: GraphicalSlur = new GraphicalSlur(oldGSlur.slur); //Graphicalslur.createFromSlur(oldSlur);
|
|
|
+ staffLine.addSlurToStaffline(newGSlur); // every VFSlur is added to the array in the VFStaffline!
|
|
|
+ openGraphicalSlurs[slurIndex] = newGSlur;
|
|
|
+ }
|
|
|
|
|
|
- /* VexFlow Version - for later use
|
|
|
- const vfOpenSlurs: VexFlowSlur[] = vfOpenSlursDict[staffLine.ParentStaff.idInMusicSheet];
|
|
|
- const vfStaffLine: VexFlowStaffLine = <VexFlowStaffLine> staffLine;
|
|
|
- for (let slurIndex: number = 0; slurIndex < vfOpenSlurs.length; slurIndex++) {
|
|
|
- const oldVFSlur: VexFlowSlur = vfOpenSlurs[slurIndex];
|
|
|
- const newVFSlur: VexFlowSlur = VexFlowSlur.createFromVexflowSlur(oldVFSlur);
|
|
|
- newVFSlur.vfStartNote = undefined;
|
|
|
- vfStaffLine.addVFSlurToVFStaffline(newVFSlur); // every VFSlur is added to the array in the VFStaffline!
|
|
|
- vfOpenSlurs[slurIndex] = newVFSlur;
|
|
|
- }
|
|
|
- */
|
|
|
-
|
|
|
- // add reference of slur array to the VexFlowStaffline class
|
|
|
- for (const graphicalMeasure of staffLine.Measures) {
|
|
|
- for (const graphicalStaffEntry of graphicalMeasure.staffEntries) {
|
|
|
- // for (var idx5: number = 0, len5 = graphicalStaffEntry.GraceStaffEntriesBefore.Count; idx5 < len5; ++idx5) {
|
|
|
- // var graceStaffEntry: GraphicalStaffEntry = graphicalStaffEntry.GraceStaffEntriesBefore[idx5];
|
|
|
- // if (graceStaffEntry.Notes[0][0].SourceNote.NoteSlurs.Count > 0) {
|
|
|
- // var graceNote: Note = graceStaffEntry.Notes[0][0].SourceNote;
|
|
|
- // graceStaffEntry.RelInMeasureTimestamp = Fraction.createFromFraction(graphicalStaffEntry.RelInMeasureTimestamp);
|
|
|
- // for (var idx6: number = 0, len6 = graceNote.NoteSlurs.Count; idx6 < len6; ++idx6) {
|
|
|
- // var graceNoteSlur: Slur = graceNote.NoteSlurs[idx6];
|
|
|
- // if (graceNoteSlur.StartNote == graceNote) {
|
|
|
- // var vfSlur: VexFlowSlur = new VexFlowSlur(graceNoteSlur);
|
|
|
- // vfSlur.GraceStart = true;
|
|
|
- // staffLine.GraphicalSlurs.Add(vfSlur);
|
|
|
- // openGraphicalSlurs[i].Add(vfSlur);
|
|
|
- // for (var j: number = graphicalStaffEntry.GraceStaffEntriesBefore.IndexOf(graceStaffEntry);
|
|
|
- // j < graphicalStaffEntry.GraceStaffEntriesBefore.Count; j++)
|
|
|
- // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry.GraceStaffEntriesBefore[j]);
|
|
|
- // }
|
|
|
- // if (graceNote == graceNoteSlur.EndNote) {
|
|
|
- // var vfSlur: VexFlowSlur = findGraphicalSlurFromSlur(openGraphicalSlurs[i], graceNoteSlur);
|
|
|
- // if (vfSlur != null) {
|
|
|
- // vfSlur.GraceEnd = true;
|
|
|
- // openGraphicalSlurs[i].Remove(vfSlur);
|
|
|
- // for (var j: number = 0; j <= graphicalStaffEntry.GraceStaffEntriesBefore.IndexOf(graceStaffEntry); j++)
|
|
|
- // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry.GraceStaffEntriesBefore[j]);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
- // loop over "normal" notes (= no gracenotes)
|
|
|
- for (const graphicalVoiceEntry of graphicalStaffEntry.graphicalVoiceEntries) {
|
|
|
- for (const graphicalNote of graphicalVoiceEntry.notes) {
|
|
|
- for (const slur of graphicalNote.sourceNote.NoteSlurs) {
|
|
|
- // extra check for some MusicSheets that have openSlurs (because only the first Page is available -> Recordare files)
|
|
|
- if (slur.EndNote === undefined || slur.StartNote === undefined) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- // add new VexFlowSlur to List
|
|
|
- if (slur.StartNote === graphicalNote.sourceNote) {
|
|
|
- if (graphicalNote.sourceNote.NoteTie !== undefined) {
|
|
|
- if (graphicalNote.parentVoiceEntry.parentStaffEntry.getAbsoluteTimestamp() !==
|
|
|
- graphicalNote.sourceNote.NoteTie.StartNote.getAbsoluteTimestamp()) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Add a Graphical Slur to the staffline, if the recent note is the Startnote of a slur
|
|
|
- const gSlur: GraphicalSlur = new GraphicalSlur(slur);
|
|
|
- openGraphicalSlurs.push(gSlur);
|
|
|
- staffLine.addSlurToStaffline(gSlur);
|
|
|
-
|
|
|
- /* VexFlow Version - for later use
|
|
|
- const vfSlur: VexFlowSlur = new VexFlowSlur(slur);
|
|
|
- vfOpenSlurs.push(vfSlur); //add open... adding / removing is JUST DONE in the open... array
|
|
|
- vfSlur.vfStartNote = (graphicalVoiceEntry as VexFlowVoiceEntry).vfStaveNote;
|
|
|
- vfStaffLine.addVFSlurToVFStaffline(vfSlur); // every VFSlur is added to the array in the VFStaffline!
|
|
|
- */
|
|
|
- }
|
|
|
- if (slur.EndNote === graphicalNote.sourceNote) {
|
|
|
- // Remove the Graphical Slur from the staffline if the note is the Endnote of a slur
|
|
|
- const index: number = this.findIndexGraphicalSlurFromSlur(openGraphicalSlurs, slur);
|
|
|
- if (index >= 0) {
|
|
|
- // save Voice Entry in VFSlur and then remove it from array of open VFSlurs
|
|
|
- const gSlur: GraphicalSlur = openGraphicalSlurs[index];
|
|
|
- if (gSlur.staffEntries.indexOf(graphicalStaffEntry) === -1) {
|
|
|
- gSlur.staffEntries.push(graphicalStaffEntry);
|
|
|
- }
|
|
|
-
|
|
|
- openGraphicalSlurs.splice(index, 1);
|
|
|
- }
|
|
|
-
|
|
|
- /* VexFlow Version - for later use
|
|
|
- const vfIndex: number = this.findIndexVFSlurFromSlur(vfOpenSlurs, slur);
|
|
|
- if (vfIndex !== undefined) {
|
|
|
- // save Voice Entry in VFSlur and then remove it from array of open VFSlurs
|
|
|
- const vfSlur: VexFlowSlur = vfOpenSlurs[vfIndex];
|
|
|
- vfSlur.vfEndNote = (graphicalVoiceEntry as VexFlowVoiceEntry).vfStaveNote;
|
|
|
- vfSlur.createVexFlowCurve();
|
|
|
- vfOpenSlurs.splice(vfIndex, 1);
|
|
|
- }
|
|
|
- */
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ /* VexFlow Version - for later use
|
|
|
+ const vfOpenSlurs: VexFlowSlur[] = vfOpenSlursDict[staffLine.ParentStaff.idInMusicSheet];
|
|
|
+ const vfStaffLine: VexFlowStaffLine = <VexFlowStaffLine> staffLine;
|
|
|
+ for (let slurIndex: number = 0; slurIndex < vfOpenSlurs.length; slurIndex++) {
|
|
|
+ const oldVFSlur: VexFlowSlur = vfOpenSlurs[slurIndex];
|
|
|
+ const newVFSlur: VexFlowSlur = VexFlowSlur.createFromVexflowSlur(oldVFSlur);
|
|
|
+ newVFSlur.vfStartNote = undefined;
|
|
|
+ vfStaffLine.addVFSlurToVFStaffline(newVFSlur); // every VFSlur is added to the array in the VFStaffline!
|
|
|
+ vfOpenSlurs[slurIndex] = newVFSlur;
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ // add reference of slur array to the VexFlowStaffline class
|
|
|
+ for (const graphicalMeasure of staffLine.Measures) {
|
|
|
+ for (const graphicalStaffEntry of graphicalMeasure.staffEntries) {
|
|
|
+ // for (var idx5: number = 0, len5 = graphicalStaffEntry.GraceStaffEntriesBefore.Count; idx5 < len5; ++idx5) {
|
|
|
+ // var graceStaffEntry: GraphicalStaffEntry = graphicalStaffEntry.GraceStaffEntriesBefore[idx5];
|
|
|
+ // if (graceStaffEntry.Notes[0][0].SourceNote.NoteSlurs.Count > 0) {
|
|
|
+ // var graceNote: Note = graceStaffEntry.Notes[0][0].SourceNote;
|
|
|
+ // graceStaffEntry.RelInMeasureTimestamp = Fraction.createFromFraction(graphicalStaffEntry.RelInMeasureTimestamp);
|
|
|
+ // for (var idx6: number = 0, len6 = graceNote.NoteSlurs.Count; idx6 < len6; ++idx6) {
|
|
|
+ // var graceNoteSlur: Slur = graceNote.NoteSlurs[idx6];
|
|
|
+ // if (graceNoteSlur.StartNote == graceNote) {
|
|
|
+ // var vfSlur: VexFlowSlur = new VexFlowSlur(graceNoteSlur);
|
|
|
+ // vfSlur.GraceStart = true;
|
|
|
+ // staffLine.GraphicalSlurs.Add(vfSlur);
|
|
|
+ // openGraphicalSlurs[i].Add(vfSlur);
|
|
|
+ // for (var j: number = graphicalStaffEntry.GraceStaffEntriesBefore.IndexOf(graceStaffEntry);
|
|
|
+ // j < graphicalStaffEntry.GraceStaffEntriesBefore.Count; j++)
|
|
|
+ // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry.GraceStaffEntriesBefore[j]);
|
|
|
+ // }
|
|
|
+ // if (graceNote == graceNoteSlur.EndNote) {
|
|
|
+ // var vfSlur: VexFlowSlur = findGraphicalSlurFromSlur(openGraphicalSlurs[i], graceNoteSlur);
|
|
|
+ // if (vfSlur != null) {
|
|
|
+ // vfSlur.GraceEnd = true;
|
|
|
+ // openGraphicalSlurs[i].Remove(vfSlur);
|
|
|
+ // for (var j: number = 0; j <= graphicalStaffEntry.GraceStaffEntriesBefore.IndexOf(graceStaffEntry); j++)
|
|
|
+ // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry.GraceStaffEntriesBefore[j]);
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // loop over "normal" notes (= no gracenotes)
|
|
|
+ for (const graphicalVoiceEntry of graphicalStaffEntry.graphicalVoiceEntries) {
|
|
|
+ for (const graphicalNote of graphicalVoiceEntry.notes) {
|
|
|
+ for (const slur of graphicalNote.sourceNote.NoteSlurs) {
|
|
|
+ // extra check for some MusicSheets that have openSlurs (because only the first Page is available -> Recordare files)
|
|
|
+ if (slur.EndNote === undefined || slur.StartNote === undefined) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // add new VexFlowSlur to List
|
|
|
+ if (slur.StartNote === graphicalNote.sourceNote) {
|
|
|
+ if (graphicalNote.sourceNote.NoteTie !== undefined) {
|
|
|
+ if (graphicalNote.parentVoiceEntry.parentStaffEntry.getAbsoluteTimestamp() !==
|
|
|
+ graphicalNote.sourceNote.NoteTie.StartNote.getAbsoluteTimestamp()) {
|
|
|
+ break;
|
|
|
}
|
|
|
- // for (var idx5: number = 0, len5 = graphicalStaffEntry.GraceStaffEntriesAfter.Count; idx5 < len5; ++idx5) {
|
|
|
- // var graceStaffEntry: GraphicalStaffEntry = graphicalStaffEntry.GraceStaffEntriesAfter[idx5];
|
|
|
- // if (graceStaffEntry.Notes[0][0].SourceNote.NoteSlurs.Count > 0) {
|
|
|
- // var graceNote: Note = graceStaffEntry.Notes[0][0].SourceNote;
|
|
|
- // graceStaffEntry.RelInMeasureTimestamp = Fraction.createFromFraction(graphicalStaffEntry.RelInMeasureTimestamp);
|
|
|
- // for (var idx6: number = 0, len6 = graceNote.NoteSlurs.Count; idx6 < len6; ++idx6) {
|
|
|
- // var graceNoteSlur: Slur = graceNote.NoteSlurs[idx6];
|
|
|
- // if (graceNoteSlur.StartNote == graceNote) {
|
|
|
- // var vfSlur: VexFlowSlur = new VexFlowSlur(graceNoteSlur);
|
|
|
- // vfSlur.GraceStart = true;
|
|
|
- // staffLine.GraphicalSlurs.Add(vfSlur);
|
|
|
- // openGraphicalSlurs[i].Add(vfSlur);
|
|
|
- // for (var j: number = graphicalStaffEntry.GraceStaffEntriesAfter.IndexOf(graceStaffEntry);
|
|
|
- // j < graphicalStaffEntry.GraceStaffEntriesAfter.Count; j++)
|
|
|
- // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry.GraceStaffEntriesAfter[j]);
|
|
|
- // }
|
|
|
- // if (graceNote == graceNoteSlur.EndNote) {
|
|
|
- // var vfSlur: VexFlowSlur = findGraphicalSlurFromSlur(openGraphicalSlurs[i], graceNoteSlur);
|
|
|
- // if (vfSlur != null) {
|
|
|
- // vfSlur.GraceEnd = true;
|
|
|
- // openGraphicalSlurs[i].Remove(vfSlur);
|
|
|
- // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry);
|
|
|
- // for (var j: number = 0; j <= graphicalStaffEntry.GraceStaffEntriesAfter.IndexOf(graceStaffEntry); j++)
|
|
|
- // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry.GraceStaffEntriesAfter[j]);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- //add the present Staffentry to all open slurs that don't contain this Staffentry already
|
|
|
- for (const gSlur of openGraphicalSlurs) {
|
|
|
- if (gSlur.staffEntries.indexOf(graphicalStaffEntry) === -1) {
|
|
|
- gSlur.staffEntries.push(graphicalStaffEntry);
|
|
|
- }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Add a Graphical Slur to the staffline, if the recent note is the Startnote of a slur
|
|
|
+ const gSlur: GraphicalSlur = new GraphicalSlur(slur);
|
|
|
+ openGraphicalSlurs.push(gSlur);
|
|
|
+ staffLine.addSlurToStaffline(gSlur);
|
|
|
+
|
|
|
+ /* VexFlow Version - for later use
|
|
|
+ const vfSlur: VexFlowSlur = new VexFlowSlur(slur);
|
|
|
+ vfOpenSlurs.push(vfSlur); //add open... adding / removing is JUST DONE in the open... array
|
|
|
+ vfSlur.vfStartNote = (graphicalVoiceEntry as VexFlowVoiceEntry).vfStaveNote;
|
|
|
+ vfStaffLine.addVFSlurToVFStaffline(vfSlur); // every VFSlur is added to the array in the VFStaffline!
|
|
|
+ */
|
|
|
+ }
|
|
|
+ if (slur.EndNote === graphicalNote.sourceNote) {
|
|
|
+ // Remove the Graphical Slur from the staffline if the note is the Endnote of a slur
|
|
|
+ const index: number = this.findIndexGraphicalSlurFromSlur(openGraphicalSlurs, slur);
|
|
|
+ if (index >= 0) {
|
|
|
+ // save Voice Entry in VFSlur and then remove it from array of open VFSlurs
|
|
|
+ const gSlur: GraphicalSlur = openGraphicalSlurs[index];
|
|
|
+ if (gSlur.staffEntries.indexOf(graphicalStaffEntry) === -1) {
|
|
|
+ gSlur.staffEntries.push(graphicalStaffEntry);
|
|
|
}
|
|
|
- } // loop over StaffEntries
|
|
|
- } // loop over Measures
|
|
|
- } // loop over StaffLines
|
|
|
|
|
|
- // Attach vfSlur array to the vfStaffline to be drawn
|
|
|
- //vfStaffLine.SlursInVFStaffLine = vfSlurs;
|
|
|
- } // loop over MusicSystems
|
|
|
+ openGraphicalSlurs.splice(index, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* VexFlow Version - for later use
|
|
|
+ const vfIndex: number = this.findIndexVFSlurFromSlur(vfOpenSlurs, slur);
|
|
|
+ if (vfIndex !== undefined) {
|
|
|
+ // save Voice Entry in VFSlur and then remove it from array of open VFSlurs
|
|
|
+ const vfSlur: VexFlowSlur = vfOpenSlurs[vfIndex];
|
|
|
+ vfSlur.vfEndNote = (graphicalVoiceEntry as VexFlowVoiceEntry).vfStaveNote;
|
|
|
+ vfSlur.createVexFlowCurve();
|
|
|
+ vfOpenSlurs.splice(vfIndex, 1);
|
|
|
+ }
|
|
|
+ */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // for (var idx5: number = 0, len5 = graphicalStaffEntry.GraceStaffEntriesAfter.Count; idx5 < len5; ++idx5) {
|
|
|
+ // var graceStaffEntry: GraphicalStaffEntry = graphicalStaffEntry.GraceStaffEntriesAfter[idx5];
|
|
|
+ // if (graceStaffEntry.Notes[0][0].SourceNote.NoteSlurs.Count > 0) {
|
|
|
+ // var graceNote: Note = graceStaffEntry.Notes[0][0].SourceNote;
|
|
|
+ // graceStaffEntry.RelInMeasureTimestamp = Fraction.createFromFraction(graphicalStaffEntry.RelInMeasureTimestamp);
|
|
|
+ // for (var idx6: number = 0, len6 = graceNote.NoteSlurs.Count; idx6 < len6; ++idx6) {
|
|
|
+ // var graceNoteSlur: Slur = graceNote.NoteSlurs[idx6];
|
|
|
+ // if (graceNoteSlur.StartNote == graceNote) {
|
|
|
+ // var vfSlur: VexFlowSlur = new VexFlowSlur(graceNoteSlur);
|
|
|
+ // vfSlur.GraceStart = true;
|
|
|
+ // staffLine.GraphicalSlurs.Add(vfSlur);
|
|
|
+ // openGraphicalSlurs[i].Add(vfSlur);
|
|
|
+ // for (var j: number = graphicalStaffEntry.GraceStaffEntriesAfter.IndexOf(graceStaffEntry);
|
|
|
+ // j < graphicalStaffEntry.GraceStaffEntriesAfter.Count; j++)
|
|
|
+ // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry.GraceStaffEntriesAfter[j]);
|
|
|
+ // }
|
|
|
+ // if (graceNote == graceNoteSlur.EndNote) {
|
|
|
+ // var vfSlur: VexFlowSlur = findGraphicalSlurFromSlur(openGraphicalSlurs[i], graceNoteSlur);
|
|
|
+ // if (vfSlur != null) {
|
|
|
+ // vfSlur.GraceEnd = true;
|
|
|
+ // openGraphicalSlurs[i].Remove(vfSlur);
|
|
|
+ // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry);
|
|
|
+ // for (var j: number = 0; j <= graphicalStaffEntry.GraceStaffEntriesAfter.IndexOf(graceStaffEntry); j++)
|
|
|
+ // vfSlur.StaffEntries.Add(<PsStaffEntry>graphicalStaffEntry.GraceStaffEntriesAfter[j]);
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ //add the present Staffentry to all open slurs that don't contain this Staffentry already
|
|
|
+ for (const gSlur of openGraphicalSlurs) {
|
|
|
+ if (gSlur.staffEntries.indexOf(graphicalStaffEntry) === -1) {
|
|
|
+ gSlur.staffEntries.push(graphicalStaffEntry);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } // loop over StaffEntries
|
|
|
+ } // loop over Measures
|
|
|
+ } // loop over StaffLines
|
|
|
+
|
|
|
+ // Attach vfSlur array to the vfStaffline to be drawn
|
|
|
+ //vfStaffLine.SlursInVFStaffLine = vfSlurs;
|
|
|
+ } // loop over MusicSystems
|
|
|
} // loop over MusicPages
|
|
|
|
|
|
// order slurs that were saved to the Staffline
|
|
|
for (const graphicalMusicPage of this.graphicalMusicSheet.MusicPages) {
|
|
|
for (const musicSystem of graphicalMusicPage.MusicSystems) {
|
|
|
- for (const staffLine of musicSystem.StaffLines) {
|
|
|
- for (const gSlur of staffLine.GraphicalSlurs) {
|
|
|
- // crossed slurs will be handled later:
|
|
|
- if (gSlur.slur.isCrossed()) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- gSlur.calculateCurve(this.rules);
|
|
|
+ for (const staffLine of musicSystem.StaffLines) {
|
|
|
+ // Sort all gSlurs in the staffline using the Compare function in class GraphicalSlurSorter
|
|
|
+ const sortedGSlurs: GraphicalSlur[] = staffLine.GraphicalSlurs.sort(GraphicalSlur.Compare);
|
|
|
+ for (const gSlur of sortedGSlurs) {
|
|
|
+ // crossed slurs will be handled later:
|
|
|
+ if (gSlur.slur.isCrossed()) {
|
|
|
+ continue;
|
|
|
}
|
|
|
+ gSlur.calculateCurve(this.rules);
|
|
|
}
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
}
|