|
@@ -21,7 +21,7 @@ import { Tuplet } from "../VoiceData/Tuplet";
|
|
import { MusicSystem } from "./MusicSystem";
|
|
import { MusicSystem } from "./MusicSystem";
|
|
import { GraphicalTie } from "./GraphicalTie";
|
|
import { GraphicalTie } from "./GraphicalTie";
|
|
import { RepetitionInstruction } from "../VoiceData/Instructions/RepetitionInstruction";
|
|
import { RepetitionInstruction } from "../VoiceData/Instructions/RepetitionInstruction";
|
|
-import { MultiExpression } from "../VoiceData/Expressions/MultiExpression";
|
|
|
|
|
|
+import { MultiExpression, MultiExpressionEntry } from "../VoiceData/Expressions/MultiExpression";
|
|
import { StaffEntryLink } from "../VoiceData/StaffEntryLink";
|
|
import { StaffEntryLink } from "../VoiceData/StaffEntryLink";
|
|
import { MusicSystemBuilder } from "./MusicSystemBuilder";
|
|
import { MusicSystemBuilder } from "./MusicSystemBuilder";
|
|
import { MultiTempoExpression } from "../VoiceData/Expressions/MultiTempoExpression";
|
|
import { MultiTempoExpression } from "../VoiceData/Expressions/MultiTempoExpression";
|
|
@@ -67,6 +67,8 @@ import { GraphicalInstantaneousDynamicExpression } from "./GraphicalInstantaneou
|
|
import { ContDynamicEnum } from "../VoiceData/Expressions/ContinuousExpressions/ContinuousDynamicExpression";
|
|
import { ContDynamicEnum } from "../VoiceData/Expressions/ContinuousExpressions/ContinuousDynamicExpression";
|
|
import { GraphicalContinuousDynamicExpression } from "./GraphicalContinuousDynamicExpression";
|
|
import { GraphicalContinuousDynamicExpression } from "./GraphicalContinuousDynamicExpression";
|
|
import { FillEmptyMeasuresWithWholeRests } from "../../OpenSheetMusicDisplay/OSMDOptions";
|
|
import { FillEmptyMeasuresWithWholeRests } from "../../OpenSheetMusicDisplay/OSMDOptions";
|
|
|
|
+import { IStafflineNoteCalculator } from "../Interfaces/IStafflineNoteCalculator";
|
|
|
|
+import { GraphicalUnknownExpression } from "./GraphicalUnknownExpression";
|
|
|
|
|
|
/**
|
|
/**
|
|
* Class used to do all the calculations in a MusicSheet, which in the end populates a GraphicalMusicSheet.
|
|
* Class used to do all the calculations in a MusicSheet, which in the end populates a GraphicalMusicSheet.
|
|
@@ -74,6 +76,7 @@ import { FillEmptyMeasuresWithWholeRests } from "../../OpenSheetMusicDisplay/OSM
|
|
export abstract class MusicSheetCalculator {
|
|
export abstract class MusicSheetCalculator {
|
|
public static symbolFactory: IGraphicalSymbolFactory;
|
|
public static symbolFactory: IGraphicalSymbolFactory;
|
|
public static transposeCalculator: ITransposeCalculator;
|
|
public static transposeCalculator: ITransposeCalculator;
|
|
|
|
+ public static stafflineNoteCalculator: IStafflineNoteCalculator;
|
|
protected static textMeasurer: ITextMeasurer;
|
|
protected static textMeasurer: ITextMeasurer;
|
|
|
|
|
|
protected staffEntriesWithGraphicalTies: GraphicalStaffEntry[] = [];
|
|
protected staffEntriesWithGraphicalTies: GraphicalStaffEntry[] = [];
|
|
@@ -543,7 +546,53 @@ export abstract class MusicSheetCalculator {
|
|
* @param staffIndex
|
|
* @param staffIndex
|
|
*/
|
|
*/
|
|
protected calculateMoodAndUnknownExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
|
|
protected calculateMoodAndUnknownExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
|
|
- throw new Error("abstract, not implemented");
|
|
|
|
|
|
+ // calculate absolute Timestamp
|
|
|
|
+ const absoluteTimestamp: Fraction = multiExpression.AbsoluteTimestamp;
|
|
|
|
+ const measures: GraphicalMeasure[] = this.graphicalMusicSheet.MeasureList[measureIndex];
|
|
|
|
+ let relative: PointF2D = new PointF2D();
|
|
|
|
+
|
|
|
|
+ if ((multiExpression.MoodList.length > 0) || (multiExpression.UnknownList.length > 0)) {
|
|
|
|
+ let combinedExprString: string = "";
|
|
|
|
+ for (let idx: number = 0, len: number = multiExpression.EntriesList.length; idx < len; ++idx) {
|
|
|
|
+ const entry: MultiExpressionEntry = multiExpression.EntriesList[idx];
|
|
|
|
+ if (entry.prefix !== "") {
|
|
|
|
+ if (combinedExprString === "") {
|
|
|
|
+ combinedExprString += entry.prefix;
|
|
|
|
+ } else {
|
|
|
|
+ combinedExprString += " " + entry.prefix;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (combinedExprString === "") {
|
|
|
|
+ combinedExprString += entry.label;
|
|
|
|
+ } else {
|
|
|
|
+ combinedExprString += " " + entry.label;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ const staffLine: StaffLine = measures[staffIndex].ParentStaffLine;
|
|
|
|
+ if (!staffLine) {
|
|
|
|
+ log.debug("MusicSheetCalculator.calculateMoodAndUnknownExpression: staffLine undefined. Returning.");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ relative = this.getRelativePositionInStaffLineFromTimestamp(absoluteTimestamp, staffIndex, staffLine, staffLine?.isPartOfMultiStaffInstrument());
|
|
|
|
+
|
|
|
|
+ if (Math.abs(relative.x - 0) < 0.0001) {
|
|
|
|
+ relative.x = measures[staffIndex].beginInstructionsWidth + this.rules.RhythmRightMargin;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const fontHeight: number = this.rules.UnknownTextHeight;
|
|
|
|
+
|
|
|
|
+ const graphLabel: GraphicalLabel = this.calculateLabel(staffLine,
|
|
|
|
+ relative, combinedExprString,
|
|
|
|
+ multiExpression.getFontstyleOfFirstEntry(),
|
|
|
|
+ multiExpression.getPlacementOfFirstEntry(),
|
|
|
|
+ fontHeight);
|
|
|
|
+
|
|
|
|
+ const gue: GraphicalUnknownExpression = new GraphicalUnknownExpression(
|
|
|
|
+ staffLine, graphLabel, measures[staffIndex]?.parentSourceMeasure, multiExpression);
|
|
|
|
+ // multiExpression); // TODO would be nice to hand over and save reference to original expression,
|
|
|
|
+ // but MultiExpression is not an AbstractExpression.
|
|
|
|
+ staffLine.AbstractExpressions.push(gue);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -879,7 +928,7 @@ export abstract class MusicSheetCalculator {
|
|
const endMeasure: GraphicalMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(
|
|
const endMeasure: GraphicalMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(
|
|
graphicalContinuousDynamic.ContinuousDynamic.EndMultiExpression.SourceMeasureParent, staffIndex);
|
|
graphicalContinuousDynamic.ContinuousDynamic.EndMultiExpression.SourceMeasureParent, staffIndex);
|
|
if (!endMeasure) {
|
|
if (!endMeasure) {
|
|
- log.warn("Not working");
|
|
|
|
|
|
+ log.warn("MusicSheetCalculator.calculateGraphicalContinuousDynamic: No endMeasure found");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -892,9 +941,9 @@ export abstract class MusicSheetCalculator {
|
|
|
|
|
|
let isPartOfMultiStaffInstrument: boolean = false;
|
|
let isPartOfMultiStaffInstrument: boolean = false;
|
|
if (endStaffLine) { // unfortunately we can't do something like (endStaffLine?.check() || staffLine?.check()) in this typescript version
|
|
if (endStaffLine) { // unfortunately we can't do something like (endStaffLine?.check() || staffLine?.check()) in this typescript version
|
|
- isPartOfMultiStaffInstrument = endStaffLine.isPartOfMultiStaffInstrument();
|
|
|
|
|
|
+ isPartOfMultiStaffInstrument = endStaffLine?.isPartOfMultiStaffInstrument();
|
|
} else if (staffLine) {
|
|
} else if (staffLine) {
|
|
- isPartOfMultiStaffInstrument = staffLine.isPartOfMultiStaffInstrument();
|
|
|
|
|
|
+ isPartOfMultiStaffInstrument = staffLine?.isPartOfMultiStaffInstrument();
|
|
}
|
|
}
|
|
|
|
|
|
const endAbsoluteTimestamp: Fraction = Fraction.createFromFraction(graphicalContinuousDynamic.ContinuousDynamic.EndMultiExpression.AbsoluteTimestamp);
|
|
const endAbsoluteTimestamp: Fraction = Fraction.createFromFraction(graphicalContinuousDynamic.ContinuousDynamic.EndMultiExpression.AbsoluteTimestamp);
|
|
@@ -931,7 +980,8 @@ export abstract class MusicSheetCalculator {
|
|
lowerEndX = endPosInStaffLine.x;
|
|
lowerEndX = endPosInStaffLine.x;
|
|
|
|
|
|
// must create a new Wedge
|
|
// must create a new Wedge
|
|
- secondGraphicalContinuousDynamic = new GraphicalContinuousDynamicExpression(graphicalContinuousDynamic.ContinuousDynamic, endStaffLine);
|
|
|
|
|
|
+ secondGraphicalContinuousDynamic = new GraphicalContinuousDynamicExpression(
|
|
|
|
+ graphicalContinuousDynamic.ContinuousDynamic, endStaffLine, endMeasure.parentSourceMeasure);
|
|
secondGraphicalContinuousDynamic.IsSplittedPart = true;
|
|
secondGraphicalContinuousDynamic.IsSplittedPart = true;
|
|
graphicalContinuousDynamic.IsSplittedPart = true;
|
|
graphicalContinuousDynamic.IsSplittedPart = true;
|
|
} else {
|
|
} else {
|
|
@@ -1159,6 +1209,9 @@ export abstract class MusicSheetCalculator {
|
|
startPosInStaffline: PointF2D): void {
|
|
startPosInStaffline: PointF2D): void {
|
|
// get Margin Dimensions
|
|
// get Margin Dimensions
|
|
const staffLine: StaffLine = graphicalInstantaneousDynamic.ParentStaffLine;
|
|
const staffLine: StaffLine = graphicalInstantaneousDynamic.ParentStaffLine;
|
|
|
|
+ if (!staffLine) {
|
|
|
|
+ return; // TODO can happen when drawing range modified (osmd.setOptions({drawFromMeasureNumber...}))
|
|
|
|
+ }
|
|
const left: number = startPosInStaffline.x + graphicalInstantaneousDynamic.PositionAndShape.BorderMarginLeft;
|
|
const left: number = startPosInStaffline.x + graphicalInstantaneousDynamic.PositionAndShape.BorderMarginLeft;
|
|
const right: number = startPosInStaffline.x + graphicalInstantaneousDynamic.PositionAndShape.BorderMarginRight;
|
|
const right: number = startPosInStaffline.x + graphicalInstantaneousDynamic.PositionAndShape.BorderMarginRight;
|
|
const skyBottomLineCalculator: SkyBottomLineCalculator = staffLine.SkyBottomLineCalculator;
|
|
const skyBottomLineCalculator: SkyBottomLineCalculator = staffLine.SkyBottomLineCalculator;
|
|
@@ -1485,6 +1538,8 @@ export abstract class MusicSheetCalculator {
|
|
graphicalNote = MusicSheetCalculator.symbolFactory.createGraceNote(note, gve, activeClef, octaveShiftValue);
|
|
graphicalNote = MusicSheetCalculator.symbolFactory.createGraceNote(note, gve, activeClef, octaveShiftValue);
|
|
} else {
|
|
} else {
|
|
graphicalNote = MusicSheetCalculator.symbolFactory.createNote(note, gve, activeClef, octaveShiftValue, undefined);
|
|
graphicalNote = MusicSheetCalculator.symbolFactory.createNote(note, gve, activeClef, octaveShiftValue, undefined);
|
|
|
|
+ const staffLineCount: number = voiceEntry.ParentSourceStaffEntry.ParentStaff.StafflineCount;
|
|
|
|
+ graphicalNote = MusicSheetCalculator.stafflineNoteCalculator.positionNote(graphicalNote, activeClef, staffLineCount);
|
|
}
|
|
}
|
|
if (note.Pitch !== undefined) {
|
|
if (note.Pitch !== undefined) {
|
|
this.checkNoteForAccidental(graphicalNote, accidentalCalculator, activeClef, octaveShiftValue);
|
|
this.checkNoteForAccidental(graphicalNote, accidentalCalculator, activeClef, octaveShiftValue);
|
|
@@ -1928,6 +1983,17 @@ export abstract class MusicSheetCalculator {
|
|
staffEntryLinks: StaffEntryLink[]): GraphicalMeasure {
|
|
staffEntryLinks: StaffEntryLink[]): GraphicalMeasure {
|
|
const staff: Staff = this.graphicalMusicSheet.ParentMusicSheet.getStaffFromIndex(staffIndex);
|
|
const staff: Staff = this.graphicalMusicSheet.ParentMusicSheet.getStaffFromIndex(staffIndex);
|
|
let measure: GraphicalMeasure = undefined;
|
|
let measure: GraphicalMeasure = undefined;
|
|
|
|
+ //This property is active...
|
|
|
|
+ if (this.rules.PercussionOneLineCutoff !== undefined && this.rules.PercussionOneLineCutoff !== 0) {
|
|
|
|
+ //We have a percussion clef, check to see if this property applies...
|
|
|
|
+ if (activeClefs[staffIndex].ClefType === ClefEnum.percussion) {
|
|
|
|
+ //-1 means always trigger, or we are under the cutoff number specified
|
|
|
|
+ if (this.rules.PercussionOneLineCutoff === -1 ||
|
|
|
|
+ staff.ParentInstrument.SubInstruments.length < this.rules.PercussionOneLineCutoff) {
|
|
|
|
+ staff.StafflineCount = 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
if (activeClefs[staffIndex].ClefType === ClefEnum.TAB) {
|
|
if (activeClefs[staffIndex].ClefType === ClefEnum.TAB) {
|
|
staff.isTab = true;
|
|
staff.isTab = true;
|
|
measure = MusicSheetCalculator.symbolFactory.createTabStaffMeasure(sourceMeasure, staff);
|
|
measure = MusicSheetCalculator.symbolFactory.createTabStaffMeasure(sourceMeasure, staff);
|
|
@@ -2070,10 +2136,12 @@ export abstract class MusicSheetCalculator {
|
|
graphicalStaffEntry.relInMeasureTimestamp = voiceEntry.Timestamp;
|
|
graphicalStaffEntry.relInMeasureTimestamp = voiceEntry.Timestamp;
|
|
const gve: GraphicalVoiceEntry = MusicSheetCalculator.symbolFactory.createVoiceEntry(voiceEntry, graphicalStaffEntry);
|
|
const gve: GraphicalVoiceEntry = MusicSheetCalculator.symbolFactory.createVoiceEntry(voiceEntry, graphicalStaffEntry);
|
|
graphicalStaffEntry.graphicalVoiceEntries.push(gve);
|
|
graphicalStaffEntry.graphicalVoiceEntries.push(gve);
|
|
- const graphicalNote: GraphicalNote = MusicSheetCalculator.symbolFactory.createNote(note,
|
|
|
|
- gve,
|
|
|
|
- new ClefInstruction(),
|
|
|
|
- OctaveEnum.NONE, undefined);
|
|
|
|
|
|
+ let graphicalNote: GraphicalNote = MusicSheetCalculator.symbolFactory.createNote(note,
|
|
|
|
+ gve,
|
|
|
|
+ new ClefInstruction(),
|
|
|
|
+ OctaveEnum.NONE, undefined);
|
|
|
|
+ const staffLineCount: number = voiceEntry.ParentSourceStaffEntry.ParentStaff.StafflineCount;
|
|
|
|
+ graphicalNote = MusicSheetCalculator.stafflineNoteCalculator.positionNote(graphicalNote, activeClefs[staffIndex], staffLineCount);
|
|
gve.notes.push(graphicalNote);
|
|
gve.notes.push(graphicalNote);
|
|
}
|
|
}
|
|
}
|
|
}
|