MusicSheetCalculator.ts 98 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749
  1. import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
  2. import {StaffLine} from "./StaffLine";
  3. import {GraphicalMusicSheet} from "./GraphicalMusicSheet";
  4. import {EngravingRules} from "./EngravingRules";
  5. import {Tie} from "../VoiceData/Tie";
  6. import {Fraction} from "../../Common/DataObjects/Fraction";
  7. import {Note} from "../VoiceData/Note";
  8. import {MusicSheet} from "../MusicSheet";
  9. import {StaffMeasure} from "./StaffMeasure";
  10. import {ClefInstruction} from "../VoiceData/Instructions/ClefInstruction";
  11. import {LyricWord} from "../VoiceData/Lyrics/LyricsWord";
  12. import {SourceMeasure} from "../VoiceData/SourceMeasure";
  13. import {GraphicalMusicPage} from "./GraphicalMusicPage";
  14. import {GraphicalNote} from "./GraphicalNote";
  15. import {Beam} from "../VoiceData/Beam";
  16. import {OctaveEnum} from "../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
  17. import {LyricsEntry} from "../VoiceData/Lyrics/LyricsEntry";
  18. import {VoiceEntry} from "../VoiceData/VoiceEntry";
  19. import {OrnamentContainer} from "../VoiceData/OrnamentContainer";
  20. import {ArticulationEnum} from "../VoiceData/VoiceEntry";
  21. import {Tuplet} from "../VoiceData/Tuplet";
  22. import {MusicSystem} from "./MusicSystem";
  23. import {GraphicalTie} from "./GraphicalTie";
  24. import {RepetitionInstruction} from "../VoiceData/Instructions/RepetitionInstruction";
  25. import {MultiExpression} from "../VoiceData/Expressions/MultiExpression";
  26. import {StaffEntryLink} from "../VoiceData/StaffEntryLink";
  27. import {MusicSystemBuilder} from "./MusicSystemBuilder";
  28. import {MultiTempoExpression} from "../VoiceData/Expressions/MultiTempoExpression";
  29. import {Repetition} from "../MusicSource/Repetition";
  30. import {PointF2D} from "../../Common/DataObjects/PointF2D";
  31. import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
  32. import {BoundingBox} from "./BoundingBox";
  33. import {Instrument} from "../Instrument";
  34. import {GraphicalLabel} from "./GraphicalLabel";
  35. import {TextAlignment} from "../../Common/Enums/TextAlignment";
  36. import {VerticalGraphicalStaffEntryContainer} from "./VerticalGraphicalStaffEntryContainer";
  37. import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
  38. import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
  39. import {TechnicalInstruction} from "../VoiceData/Instructions/TechnicalInstruction";
  40. import {Pitch} from "../../Common/DataObjects/Pitch";
  41. import {LinkedVoice} from "../VoiceData/LinkedVoice";
  42. import {ColDirEnum} from "./BoundingBox";
  43. import {IGraphicalSymbolFactory} from "../Interfaces/IGraphicalSymbolFactory";
  44. import {ITextMeasurer} from "../Interfaces/ITextMeasurer";
  45. import {ITransposeCalculator} from "../Interfaces/ITransposeCalculator";
  46. import {OctaveShiftParams} from "./OctaveShiftParams";
  47. import {AccidentalCalculator} from "./AccidentalCalculator";
  48. import {MidiInstrument} from "../VoiceData/Instructions/ClefInstruction";
  49. import {Staff} from "../VoiceData/Staff";
  50. import {OctaveShift} from "../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
  51. import {Logging} from "../../Common/Logging";
  52. import Dictionary from "typescript-collections/dist/lib/Dictionary";
  53. import {CollectionUtil} from "../../Util/CollectionUtil";
  54. /**
  55. * Class used to do all the calculations in a MusicSheet, which in the end populates a GraphicalMusicSheet.
  56. */
  57. export abstract class MusicSheetCalculator {
  58. public static transposeCalculator: ITransposeCalculator;
  59. protected static textMeasurer: ITextMeasurer;
  60. protected staffEntriesWithGraphicalTies: GraphicalStaffEntry[] = [];
  61. protected staffEntriesWithOrnaments: GraphicalStaffEntry[] = [];
  62. protected staffEntriesWithChordSymbols: GraphicalStaffEntry[] = [];
  63. protected staffLinesWithLyricWords: StaffLine[] = [];
  64. protected staffLinesWithGraphicalExpressions: StaffLine[] = [];
  65. protected graphicalMusicSheet: GraphicalMusicSheet;
  66. protected rules: EngravingRules;
  67. protected symbolFactory: IGraphicalSymbolFactory;
  68. constructor(symbolFactory: IGraphicalSymbolFactory) {
  69. this.symbolFactory = symbolFactory;
  70. }
  71. public static get TextMeasurer(): ITextMeasurer {
  72. return MusicSheetCalculator.textMeasurer;
  73. }
  74. public static set TextMeasurer(value: ITextMeasurer) {
  75. MusicSheetCalculator.textMeasurer = value;
  76. }
  77. protected get leadSheet(): boolean {
  78. return this.graphicalMusicSheet.LeadSheet;
  79. }
  80. private static addTieToTieTimestampsDict(tieTimestampListDict: Dictionary<Tie, Fraction[]>, note: Note): void {
  81. note.NoteTie.initializeBoolList();
  82. let tieTimestampList: Fraction[] = [];
  83. for (let m: number = 0; m < note.NoteTie.Fractions.length; m++) {
  84. let musicTimestamp: Fraction;
  85. if (m === 0) {
  86. musicTimestamp = Fraction.plus(note.calculateNoteLengthWithoutTie(), note.getAbsoluteTimestamp());
  87. } else {
  88. musicTimestamp = Fraction.plus(tieTimestampList[m - 1], note.NoteTie.Fractions[m - 1]);
  89. }
  90. tieTimestampList.push(musicTimestamp);
  91. }
  92. tieTimestampListDict.setValue(note.NoteTie, tieTimestampList);
  93. }
  94. private static setMeasuresMinStaffEntriesWidth(measures: StaffMeasure[], minimumStaffEntriesWidth: number): void {
  95. for (let idx: number = 0, len: number = measures.length; idx < len; ++idx) {
  96. let measure: StaffMeasure = measures[idx];
  97. measure.minimumStaffEntriesWidth = minimumStaffEntriesWidth;
  98. }
  99. }
  100. public initialize(graphicalMusicSheet: GraphicalMusicSheet): void {
  101. this.graphicalMusicSheet = graphicalMusicSheet;
  102. this.rules = graphicalMusicSheet.ParentMusicSheet.rules;
  103. this.prepareGraphicalMusicSheet();
  104. //this.calculate();
  105. }
  106. /**
  107. * Build the 2D [[GraphicalMeasure]] ist needed for the [[MusicSheetCalculator]].
  108. * Internally it creates [[GraphicalMeasure]]s, [[GraphicalStaffEntry]]'s and [[GraphicalNote]]s.
  109. */
  110. public prepareGraphicalMusicSheet(): void {
  111. // Clear the stored system images dict - all systems have to be redrawn.
  112. // Not necessary now. TODO Check
  113. // this.graphicalMusicSheet.SystemImages.length = 0;
  114. let musicSheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
  115. this.staffEntriesWithGraphicalTies = [];
  116. this.staffEntriesWithOrnaments = [];
  117. this.staffEntriesWithChordSymbols = [];
  118. this.staffLinesWithLyricWords = [];
  119. this.staffLinesWithGraphicalExpressions = [];
  120. this.graphicalMusicSheet.Initialize();
  121. let measureList: StaffMeasure[][] = this.graphicalMusicSheet.MeasureList;
  122. // one AccidentalCalculator for each Staff (regardless of Instrument)
  123. let accidentalCalculators: AccidentalCalculator[] = this.createAccidentalCalculators();
  124. // List of Active ClefInstructions
  125. let activeClefs: ClefInstruction[] = this.graphicalMusicSheet.initializeActiveClefs();
  126. // LyricWord - GraphicalLyricWord Lists
  127. let lyricWords: LyricWord[] = [];
  128. let completeNumberOfStaves: number = musicSheet.getCompleteNumberOfStaves();
  129. // Octave Shifts List
  130. let openOctaveShifts: OctaveShiftParams[] = [];
  131. // TieList - timestampsArray
  132. let tieTimestampListDictList: Dictionary<Tie, Fraction[]>[] = [];
  133. for (let i: number = 0; i < completeNumberOfStaves; i++) {
  134. let tieTimestampListDict: Dictionary<Tie, Fraction[]> = new Dictionary<Tie, Fraction[]>();
  135. tieTimestampListDictList.push(tieTimestampListDict);
  136. openOctaveShifts.push(undefined);
  137. }
  138. // go through all SourceMeasures (taking into account normal SourceMusicParts and Repetitions)
  139. for (let idx: number = 0, len: number = musicSheet.SourceMeasures.length; idx < len; ++idx) {
  140. let sourceMeasure: SourceMeasure = musicSheet.SourceMeasures[idx];
  141. let graphicalMeasures: StaffMeasure[] = this.createGraphicalMeasuresForSourceMeasure(
  142. sourceMeasure,
  143. accidentalCalculators,
  144. lyricWords,
  145. tieTimestampListDictList,
  146. openOctaveShifts,
  147. activeClefs
  148. );
  149. measureList.push(graphicalMeasures);
  150. }
  151. this.handleStaffEntries();
  152. this.calculateVerticalContainersList();
  153. this.setIndecesToVerticalGraphicalContainers();
  154. }
  155. /**
  156. * The main method for the Calculator.
  157. */
  158. public calculate(): void {
  159. this.clearSystemsAndMeasures();
  160. // delete graphicalObjects that will be recalculated and create the GraphicalObjects that strech over a single StaffEntry new.
  161. this.clearRecreatedObjects();
  162. this.createGraphicalTies();
  163. // calculate SheetLabelBoundingBoxes
  164. this.calculateSheetLabelBoundingBoxes();
  165. this.calculateXLayout(this.graphicalMusicSheet, this.maxInstrNameLabelLength());
  166. // create List<MusicPage>
  167. this.graphicalMusicSheet.MusicPages.length = 0;
  168. // create new MusicSystems and StaffLines (as many as necessary) and populate them with Measures from measureList
  169. this.calculateMusicSystems();
  170. // Add some white space at the end of the piece:
  171. this.graphicalMusicSheet.MusicPages[0].PositionAndShape.BorderMarginBottom += 9;
  172. // transform Relative to Absolute Positions
  173. GraphicalMusicSheet.transformRelativeToAbsolutePosition(this.graphicalMusicSheet);
  174. }
  175. public calculateXLayout(graphicalMusicSheet: GraphicalMusicSheet, maxInstrNameLabelLength: number): void {
  176. // for each inner List in big Measure List calculate new Positions for the StaffEntries
  177. // and adjust Measures sizes
  178. // calculate max measure length for maximum zoom in.
  179. let minLength: number = 0;
  180. let maxInstructionsLength: number = this.rules.MaxInstructionsConstValue;
  181. if (this.graphicalMusicSheet.MeasureList.length > 0) {
  182. let measures: StaffMeasure[] = this.graphicalMusicSheet.MeasureList[0];
  183. let minimumStaffEntriesWidth: number = this.calculateMeasureXLayout(measures);
  184. MusicSheetCalculator.setMeasuresMinStaffEntriesWidth(measures, minimumStaffEntriesWidth);
  185. minLength = minimumStaffEntriesWidth * 1.2 + maxInstrNameLabelLength + maxInstructionsLength;
  186. for (let i: number = 1; i < this.graphicalMusicSheet.MeasureList.length; i++) {
  187. measures = this.graphicalMusicSheet.MeasureList[i];
  188. minimumStaffEntriesWidth = this.calculateMeasureXLayout(measures);
  189. MusicSheetCalculator.setMeasuresMinStaffEntriesWidth(measures, minimumStaffEntriesWidth);
  190. minLength = Math.max(minLength, minimumStaffEntriesWidth * 1.2 + maxInstructionsLength);
  191. }
  192. }
  193. this.graphicalMusicSheet.MinAllowedSystemWidth = minLength;
  194. }
  195. /**
  196. * Calculates the x layout of the staff entries within the staff measures belonging to one source measure.
  197. * All staff entries are x-aligned throughout all the measures.
  198. * @param measures - The minimum required x width of the source measure
  199. */
  200. protected calculateMeasureXLayout(measures: StaffMeasure[]): number {
  201. throw new Error("abstract, not implemented");
  202. }
  203. protected calculateSystemYLayout(): void {
  204. throw new Error("abstract, not implemented");
  205. }
  206. /**
  207. * Called for every source measure when generating the list of staff measures for it.
  208. */
  209. protected initStaffMeasuresCreation(): void {
  210. throw new Error("abstract, not implemented");
  211. }
  212. protected handleBeam(graphicalNote: GraphicalNote, beam: Beam, openBeams: Beam[]): void {
  213. throw new Error("abstract, not implemented");
  214. }
  215. /**
  216. * Check if the tied graphical note belongs to any beams or tuplets and react accordingly.
  217. * @param tiedGraphicalNote
  218. * @param beams
  219. * @param activeClef
  220. * @param octaveShiftValue
  221. * @param graphicalStaffEntry
  222. * @param duration
  223. * @param openTie
  224. * @param isLastTieNote
  225. */
  226. protected handleTiedGraphicalNote(tiedGraphicalNote: GraphicalNote, beams: Beam[], activeClef: ClefInstruction,
  227. octaveShiftValue: OctaveEnum, graphicalStaffEntry: GraphicalStaffEntry, duration: Fraction,
  228. openTie: Tie, isLastTieNote: boolean): void {
  229. throw new Error("abstract, not implemented");
  230. }
  231. protected handleVoiceEntryLyrics(lyricsEntries: Dictionary<number, LyricsEntry>, voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry,
  232. openLyricWords: LyricWord[]): void {
  233. throw new Error("abstract, not implemented");
  234. }
  235. protected handleVoiceEntryOrnaments(ornamentContainer: OrnamentContainer, voiceEntry: VoiceEntry,
  236. graphicalStaffEntry: GraphicalStaffEntry): void {
  237. throw new Error("abstract, not implemented");
  238. }
  239. protected handleVoiceEntryArticulations(articulations: ArticulationEnum[],
  240. voiceEntry: VoiceEntry,
  241. graphicalStaffEntry: GraphicalStaffEntry): void {
  242. throw new Error("abstract, not implemented");
  243. }
  244. protected handleTuplet(graphicalNote: GraphicalNote, tuplet: Tuplet, openTuplets: Tuplet[]): void {
  245. throw new Error("abstract, not implemented");
  246. }
  247. protected layoutVoiceEntry(voiceEntry: VoiceEntry, graphicalNotes: GraphicalNote[],
  248. graphicalStaffEntry: GraphicalStaffEntry, hasPitchedNote: boolean, isGraceStaffEntry: boolean): void {
  249. throw new Error("abstract, not implemented");
  250. }
  251. protected layoutStaffEntry(graphicalStaffEntry: GraphicalStaffEntry): void {
  252. throw new Error("abstract, not implemented");
  253. }
  254. protected createGraphicalTie(tie: Tie, startGse: GraphicalStaffEntry, endGse: GraphicalStaffEntry, startNote: GraphicalNote,
  255. endNote: GraphicalNote): GraphicalTie {
  256. throw new Error("abstract, not implemented");
  257. }
  258. protected updateStaffLineBorders(staffLine: StaffLine): void {
  259. throw new Error("abstract, not implemented");
  260. }
  261. /**
  262. * Iterate through all Measures and calculates the MeasureNumberLabels.
  263. * @param musicSystem
  264. */
  265. protected calculateMeasureNumberPlacement(musicSystem: MusicSystem): void {
  266. throw new Error("abstract, not implemented");
  267. }
  268. /**
  269. * Calculate the shape (Bézier curve) for this tie.
  270. * @param tie
  271. * @param tieIsAtSystemBreak
  272. */
  273. protected layoutGraphicalTie(tie: GraphicalTie, tieIsAtSystemBreak: boolean): void {
  274. throw new Error("abstract, not implemented");
  275. }
  276. /**
  277. * Calculate the Lyrics YPositions for a single [[StaffLine]].
  278. * @param staffLine
  279. * @param lyricVersesNumber
  280. */
  281. protected calculateSingleStaffLineLyricsPosition(staffLine: StaffLine, lyricVersesNumber: number[]): void {
  282. throw new Error("abstract, not implemented");
  283. }
  284. /**
  285. * Calculate a single OctaveShift for a [[MultiExpression]].
  286. * @param sourceMeasure
  287. * @param multiExpression
  288. * @param measureIndex
  289. * @param staffIndex
  290. */
  291. protected calculateSingleOctaveShift(sourceMeasure: SourceMeasure, multiExpression: MultiExpression,
  292. measureIndex: number, staffIndex: number): void {
  293. throw new Error("abstract, not implemented");
  294. }
  295. /**
  296. * Calculate all the [[RepetitionInstruction]]s for a single [[SourceMeasure]].
  297. * @param repetitionInstruction
  298. * @param measureIndex
  299. */
  300. protected calculateWordRepetitionInstruction(repetitionInstruction: RepetitionInstruction,
  301. measureIndex: number): void {
  302. throw new Error("abstract, not implemented");
  303. }
  304. /**
  305. * Calculate all the Mood and Unknown Expressions for a single [[MultiExpression]].
  306. * @param multiExpression
  307. * @param measureIndex
  308. * @param staffIndex
  309. */
  310. protected calculateMoodAndUnknownExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
  311. throw new Error("abstract, not implemented");
  312. }
  313. /**
  314. * Delete all Objects that must be recalculated.
  315. * If graphicalMusicSheet.reCalculate has been called, then this method will be called to reset or remove all flexible
  316. * graphical music symbols (e.g. Ornaments, Lyrics, Slurs) graphicalMusicSheet will have MusicPages, they will have MusicSystems etc...
  317. */
  318. protected clearRecreatedObjects(): void {
  319. // Clear StaffEntries with GraphicalTies
  320. for (let idx: number = 0, len: number = this.staffEntriesWithGraphicalTies.length; idx < len; ++idx) {
  321. let staffEntriesWithGraphicalTie: GraphicalStaffEntry = this.staffEntriesWithGraphicalTies[idx];
  322. staffEntriesWithGraphicalTie.GraphicalTies.length = 0;
  323. }
  324. this.staffEntriesWithGraphicalTies.length = 0;
  325. return;
  326. }
  327. /**
  328. * This method handles a [[StaffEntryLink]].
  329. * @param graphicalStaffEntry
  330. * @param staffEntryLinks
  331. */
  332. protected handleStaffEntryLink(graphicalStaffEntry: GraphicalStaffEntry,
  333. staffEntryLinks: StaffEntryLink[]): void {
  334. Logging.debug("handleStaffEntryLink not implemented");
  335. }
  336. /**
  337. * Store the newly computed [[Measure]]s in newly created [[MusicSystem]]s.
  338. */
  339. protected calculateMusicSystems(): void {
  340. if (this.graphicalMusicSheet.MeasureList === undefined) {
  341. return;
  342. }
  343. let allMeasures: StaffMeasure[][] = this.graphicalMusicSheet.MeasureList;
  344. if (allMeasures === undefined) {
  345. return;
  346. }
  347. // visible 2D-MeasureList
  348. let visibleMeasureList: StaffMeasure[][] = [];
  349. for (let idx: number = 0, len: number = allMeasures.length; idx < len; ++idx) {
  350. let staffMeasures: StaffMeasure[] = allMeasures[idx];
  351. let visibleStaffMeasures: StaffMeasure[] = [];
  352. for (let idx2: number = 0, len2: number = staffMeasures.length; idx2 < len2; ++idx2) {
  353. let staffMeasure: StaffMeasure = allMeasures[idx][idx2];
  354. if (staffMeasure.isVisible()) {
  355. visibleStaffMeasures.push(staffMeasure);
  356. }
  357. }
  358. visibleMeasureList.push(visibleStaffMeasures);
  359. }
  360. // find out how many StaffLine Instances we need
  361. let numberOfStaffLines: number = 0;
  362. for (let idx: number = 0, len: number = visibleMeasureList.length; idx < len; ++idx) {
  363. let gmlist: StaffMeasure[] = visibleMeasureList[idx];
  364. numberOfStaffLines = Math.max(gmlist.length, numberOfStaffLines);
  365. break;
  366. }
  367. if (numberOfStaffLines === 0) {
  368. return;
  369. }
  370. // build the MusicSystems
  371. let musicSystemBuilder: MusicSystemBuilder = new MusicSystemBuilder();
  372. musicSystemBuilder.initialize(this.graphicalMusicSheet, visibleMeasureList, numberOfStaffLines, this.symbolFactory);
  373. musicSystemBuilder.buildMusicSystems();
  374. // check for Measures with only WholeRestNotes and correct their X-Position (middle of Measure)
  375. this.checkMeasuresForWholeRestNotes();
  376. if (!this.leadSheet) {
  377. // calculate Beam Placement
  378. this.calculateBeams();
  379. // possible Displacement of RestNotes
  380. this.optimizeRestPlacement();
  381. // possible Displacement of RestNotes
  382. this.calculateStaffEntryArticulationMarks();
  383. // calculate Ties
  384. this.calculateTieCurves();
  385. }
  386. // calculate Sky- and BottomLine
  387. // will have reasonable values only between ObjectsBorders (eg StaffEntries)
  388. this.calculateSkyBottomLines();
  389. // calculate TupletsNumbers
  390. this.calculateTupletNumbers();
  391. // calculate MeasureNumbers
  392. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  393. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  394. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  395. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  396. this.calculateMeasureNumberPlacement(musicSystem);
  397. }
  398. }
  399. // calculate Slurs
  400. if (!this.leadSheet) {
  401. this.calculateSlurs();
  402. }
  403. // calculate StaffEntry Ornaments
  404. // (must come after Slurs)
  405. if (!this.leadSheet) {
  406. this.calculateOrnaments();
  407. }
  408. // update Sky- and BottomLine with borderValues 0.0 and 4.0 respectively
  409. // (must also come after Slurs)
  410. this.updateSkyBottomLines();
  411. // calculate StaffEntry ChordSymbols
  412. this.calculateChordSymbols();
  413. if (!this.leadSheet) {
  414. // calculate all Instantanious/Continuous Dynamics Expressions
  415. this.calculateDynamicExpressions();
  416. // place neighbouring DynamicExpressions at the same height
  417. this.optimizeStaffLineDynamicExpressionsPositions();
  418. // calculate all Mood and Unknown Expression
  419. this.calculateMoodAndUnknownExpressions();
  420. // calculate all OctaveShifts
  421. this.calculateOctaveShifts();
  422. // calucalte RepetitionInstructions (Dal Segno, Coda, etc)
  423. this.calculateWordRepetitionInstructions();
  424. }
  425. // calculate endings last, so they appear above measure numbers
  426. this.calculateRepetitionEndings();
  427. // calcualte all Tempo Expressions
  428. if (!this.leadSheet) {
  429. this.calculateTempoExpressions();
  430. }
  431. // calculate all LyricWords Positions
  432. this.calculateLyricsPosition();
  433. // update all StaffLine's Borders
  434. // create temporary Object, just to call the methods (in order to avoid declaring them static)
  435. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  436. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  437. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  438. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  439. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  440. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  441. this.updateStaffLineBorders(staffLine);
  442. }
  443. }
  444. }
  445. // calculate Comments for each Staffline
  446. this.calculateComments();
  447. // Y-spacing
  448. this.calculateSystemYLayout();
  449. // calculate marked Areas for Systems
  450. this.calculateMarkedAreas();
  451. // the following must be done after Y-spacing, when the MusicSystems's final Dimensions are set
  452. // set the final yPositions of Objects such as SystemLabels and SystemLinesContainers,
  453. // create all System Lines, Brackets and MeasureNumbers (for all systems and for all pages)
  454. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  455. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  456. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  457. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  458. musicSystem.setMusicSystemLabelsYPosition();
  459. if (!this.leadSheet) {
  460. musicSystem.setYPositionsToVerticalLineObjectsAndCreateLines(this.rules);
  461. musicSystem.createSystemLeftLine(this.rules.SystemThinLineWidth, this.rules.SystemLabelsRightMargin);
  462. musicSystem.createInstrumentBrackets(this.graphicalMusicSheet.ParentMusicSheet.Instruments, this.rules.StaffHeight);
  463. musicSystem.createGroupBrackets(this.graphicalMusicSheet.ParentMusicSheet.InstrumentalGroups, this.rules.StaffHeight, 0);
  464. musicSystem.alignBeginInstructions();
  465. } else if (musicSystem === musicSystem.Parent.MusicSystems[0]) {
  466. musicSystem.createSystemLeftLine(this.rules.SystemThinLineWidth, this.rules.SystemLabelsRightMargin);
  467. }
  468. musicSystem.calculateBorders(this.rules);
  469. }
  470. let distance: number = graphicalMusicPage.MusicSystems[0].PositionAndShape.BorderTop;
  471. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  472. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  473. // let newPosition: PointF2D = new PointF2D(musicSystem.PositionAndShape.RelativePosition.x,
  474. // musicSystem.PositionAndShape.RelativePosition.y - distance);
  475. musicSystem.PositionAndShape.RelativePosition =
  476. new PointF2D(musicSystem.PositionAndShape.RelativePosition.x, musicSystem.PositionAndShape.RelativePosition.y - distance);
  477. }
  478. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  479. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  480. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  481. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  482. staffLine.addActivitySymbolClickArea();
  483. }
  484. }
  485. // calculate all Labels's Positions for the first Page
  486. if (graphicalMusicPage === this.graphicalMusicSheet.MusicPages[0]) {
  487. this.calculatePageLabels(graphicalMusicPage);
  488. }
  489. // calculate TopBottom Borders for all elements recursively
  490. graphicalMusicPage.PositionAndShape.calculateTopBottomBorders();
  491. }
  492. }
  493. protected updateSkyBottomLine(staffLine: StaffLine): void {
  494. //Logging.debug("updateSkyBottomLine not implemented");
  495. return;
  496. }
  497. protected calculateSkyBottomLine(staffLine: StaffLine): void {
  498. //Logging.debug("calculateSkyBottomLine not implemented");
  499. return;
  500. }
  501. protected calculateMarkedAreas(): void {
  502. //Logging.debug("calculateMarkedAreas not implemented");
  503. return;
  504. }
  505. protected calculateComments(): void {
  506. //Logging.debug("calculateComments not implemented");
  507. return;
  508. }
  509. /**
  510. * Iterate through all the [[StaffLine]]s in order to check for possible optimizations in the placement of the [[GraphicalExpression]]s.
  511. */
  512. protected optimizeStaffLineDynamicExpressionsPositions(): void {
  513. return;
  514. }
  515. protected calculateChordSymbols(): void {
  516. return;
  517. }
  518. /**
  519. * Do layout on staff measures with only consist of a full rest.
  520. * @param rest
  521. * @param gse
  522. * @param measure
  523. */
  524. protected layoutMeasureWithWholeRest(rest: GraphicalNote, gse: GraphicalStaffEntry,
  525. measure: StaffMeasure): void {
  526. return;
  527. }
  528. protected layoutBeams(staffEntry: GraphicalStaffEntry): void {
  529. return;
  530. }
  531. protected layoutArticulationMarks(articulations: ArticulationEnum[], voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry): void {
  532. return;
  533. }
  534. protected layoutOrnament(ornaments: OrnamentContainer, voiceEntry: VoiceEntry,
  535. graphicalStaffEntry: GraphicalStaffEntry): void {
  536. return;
  537. }
  538. protected calculateRestNotePlacementWithinGraphicalBeam(graphicalStaffEntry: GraphicalStaffEntry,
  539. restNote: GraphicalNote,
  540. previousNote: GraphicalNote,
  541. nextStaffEntry: GraphicalStaffEntry,
  542. nextNote: GraphicalNote): void {
  543. return;
  544. }
  545. protected calculateTupletNumbers(): void {
  546. return;
  547. }
  548. protected calculateSlurs(): void {
  549. return;
  550. }
  551. protected calculateDynamicExpressionsForSingleMultiExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
  552. return;
  553. }
  554. protected calcGraphicalRepetitionEndingsRecursively(repetition: Repetition): void {
  555. return;
  556. }
  557. /**
  558. * Calculate a single GraphicalRepetition.
  559. * @param start
  560. * @param end
  561. * @param numberText
  562. * @param offset
  563. * @param leftOpen
  564. * @param rightOpen
  565. */
  566. protected layoutSingleRepetitionEnding(start: StaffMeasure, end: StaffMeasure, numberText: string,
  567. offset: number, leftOpen: boolean, rightOpen: boolean): void {
  568. return;
  569. }
  570. protected calculateTempoExpressionsForSingleMultiTempoExpression(sourceMeasure: SourceMeasure, multiTempoExpression: MultiTempoExpression,
  571. measureIndex: number): void {
  572. return;
  573. }
  574. protected staffMeasureCreatedCalculations(measure: StaffMeasure): void {
  575. return;
  576. }
  577. protected clearSystemsAndMeasures(): void {
  578. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  579. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  580. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  581. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  582. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  583. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  584. for (let idx4: number = 0, len4: number = staffLine.Measures.length; idx4 < len4; ++idx4) {
  585. let graphicalMeasure: StaffMeasure = staffLine.Measures[idx4];
  586. if (graphicalMeasure.FirstInstructionStaffEntry !== undefined) {
  587. let index: number = graphicalMeasure.PositionAndShape.ChildElements.indexOf(
  588. graphicalMeasure.FirstInstructionStaffEntry.PositionAndShape
  589. );
  590. if (index > -1) {
  591. graphicalMeasure.PositionAndShape.ChildElements.splice(index, 1);
  592. }
  593. graphicalMeasure.FirstInstructionStaffEntry = undefined;
  594. graphicalMeasure.beginInstructionsWidth = 0.0;
  595. }
  596. if (graphicalMeasure.LastInstructionStaffEntry !== undefined) {
  597. let index: number = graphicalMeasure.PositionAndShape.ChildElements.indexOf(
  598. graphicalMeasure.LastInstructionStaffEntry.PositionAndShape
  599. );
  600. if (index > -1) {
  601. graphicalMeasure.PositionAndShape.ChildElements.splice(index, 1);
  602. }
  603. graphicalMeasure.LastInstructionStaffEntry = undefined;
  604. graphicalMeasure.endInstructionsWidth = 0.0;
  605. }
  606. }
  607. staffLine.Measures = [];
  608. staffLine.PositionAndShape.ChildElements = [];
  609. }
  610. musicSystem.StaffLines.length = 0;
  611. musicSystem.PositionAndShape.ChildElements = [];
  612. }
  613. graphicalMusicPage.MusicSystems = [];
  614. graphicalMusicPage.PositionAndShape.ChildElements = [];
  615. }
  616. this.graphicalMusicSheet.MusicPages = [];
  617. }
  618. protected handleVoiceEntry(voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry,
  619. accidentalCalculator: AccidentalCalculator, openLyricWords: LyricWord[],
  620. tieTimestampListDict: Dictionary<Tie, Fraction[]>, activeClef: ClefInstruction,
  621. openTuplets: Tuplet[], openBeams: Beam[],
  622. octaveShiftValue: OctaveEnum, grace: boolean = false, linkedNotes: Note[] = undefined,
  623. sourceStaffEntry: SourceStaffEntry = undefined): OctaveEnum {
  624. let graphicalNotes: GraphicalNote[] = graphicalStaffEntry.findOrCreateGraphicalNotesListFromVoiceEntry(voiceEntry);
  625. for (let idx: number = 0, len: number = voiceEntry.Notes.length; idx < len; ++idx) {
  626. let note: Note = voiceEntry.Notes[idx];
  627. if (sourceStaffEntry !== undefined && sourceStaffEntry.Link !== undefined && linkedNotes !== undefined && linkedNotes.indexOf(note) > -1) {
  628. continue;
  629. }
  630. let graphicalNote: GraphicalNote;
  631. if (grace) {
  632. graphicalNote = this.symbolFactory.createGraceNote(note, graphicalStaffEntry, activeClef, octaveShiftValue);
  633. } else {
  634. graphicalNote = this.symbolFactory.createNote(note, graphicalStaffEntry, activeClef, octaveShiftValue, undefined);
  635. }
  636. if (note.NoteTie !== undefined) {
  637. MusicSheetCalculator.addTieToTieTimestampsDict(tieTimestampListDict, note);
  638. }
  639. if (note.Pitch !== undefined) {
  640. this.checkNoteForAccidental(graphicalNote, accidentalCalculator, activeClef, octaveShiftValue, grace);
  641. }
  642. this.resetYPositionForLeadSheet(graphicalNote.PositionAndShape);
  643. graphicalStaffEntry.addGraphicalNoteToListAtCorrectYPosition(graphicalNotes, graphicalNote);
  644. graphicalStaffEntry.PositionAndShape.ChildElements.push(graphicalNote.PositionAndShape);
  645. graphicalNote.PositionAndShape.calculateBoundingBox();
  646. if (!this.leadSheet) {
  647. if (note.NoteBeam !== undefined) {
  648. this.handleBeam(graphicalNote, note.NoteBeam, openBeams);
  649. }
  650. if (note.NoteTuplet !== undefined) {
  651. this.handleTuplet(graphicalNote, note.NoteTuplet, openTuplets);
  652. }
  653. }
  654. }
  655. if (voiceEntry.Articulations.length > 0) {
  656. this.handleVoiceEntryArticulations(voiceEntry.Articulations, voiceEntry, graphicalStaffEntry);
  657. }
  658. if (voiceEntry.TechnicalInstructions.length > 0) {
  659. this.checkVoiceEntriesForTechnicalInstructions(voiceEntry, graphicalStaffEntry);
  660. }
  661. if (voiceEntry.LyricsEntries.size() > 0) {
  662. this.handleVoiceEntryLyrics(voiceEntry.LyricsEntries, voiceEntry, graphicalStaffEntry, openLyricWords);
  663. }
  664. if (voiceEntry.OrnamentContainer !== undefined) {
  665. this.handleVoiceEntryOrnaments(voiceEntry.OrnamentContainer, voiceEntry, graphicalStaffEntry);
  666. }
  667. return octaveShiftValue;
  668. }
  669. protected handleVoiceEntryGraceNotes(graceEntries: VoiceEntry[], graphicalGraceEntries: GraphicalStaffEntry[], graphicalStaffEntry: GraphicalStaffEntry,
  670. accidentalCalculator: AccidentalCalculator, activeClef: ClefInstruction,
  671. octaveShiftValue: OctaveEnum, lyricWords: LyricWord[],
  672. tieTimestampListDict: Dictionary<Tie, Fraction[]>,
  673. tuplets: Tuplet[], beams: Beam[]): void {
  674. if (graceEntries !== undefined) {
  675. for (let idx: number = 0, len: number = graceEntries.length; idx < len; ++idx) {
  676. let graceVoiceEntry: VoiceEntry = graceEntries[idx];
  677. let graceStaffEntry: GraphicalStaffEntry = this.symbolFactory.createGraceStaffEntry(
  678. graphicalStaffEntry,
  679. graphicalStaffEntry.parentMeasure
  680. );
  681. graphicalGraceEntries.push(graceStaffEntry);
  682. graphicalStaffEntry.PositionAndShape.ChildElements.push(graceStaffEntry.PositionAndShape);
  683. this.handleVoiceEntry(
  684. graceVoiceEntry, graceStaffEntry, accidentalCalculator, lyricWords,
  685. tieTimestampListDict, activeClef, tuplets,
  686. beams, octaveShiftValue, true
  687. );
  688. }
  689. }
  690. }
  691. protected handleOpenTies(measure: StaffMeasure, beams: Beam[], tieTimestampListDict: Dictionary<Tie, Fraction[]>,
  692. activeClef: ClefInstruction, octaveShiftParams: OctaveShiftParams): void {
  693. CollectionUtil.removeDictElementIfTrue( this, tieTimestampListDict,
  694. function (thisPointer: MusicSheetCalculator, openTie: Tie, tieTimestamps: Fraction[]): boolean {
  695. // for (let m: number = tieTimestampListDict.size() - 1; m >= 0; m--) {
  696. // let keyValuePair: KeyValuePair<Tie, Fraction[]> = tieTimestampListDict.ElementAt(m);
  697. // let openTie: Tie = keyValuePair.Key;
  698. // let tieTimestamps: Fraction[] = keyValuePair.Value;
  699. let absoluteTimestamp: Fraction = undefined;
  700. let removeTie: boolean = false;
  701. for (let k: number = 0; k < tieTimestamps.length; k++) {
  702. if (!openTie.NoteHasBeenCreated[k]) {
  703. absoluteTimestamp = tieTimestamps[k];
  704. if (Fraction.plus(measure.parentSourceMeasure.AbsoluteTimestamp, measure.parentSourceMeasure.Duration).lte(absoluteTimestamp)) {
  705. continue;
  706. }
  707. let graphicalStaffEntry: GraphicalStaffEntry = undefined;
  708. if (absoluteTimestamp !== undefined) {
  709. for (let idx: number = 0, len: number = measure.staffEntries.length; idx < len; ++idx) {
  710. let gse: GraphicalStaffEntry = measure.staffEntries[idx];
  711. if (gse.getAbsoluteTimestamp().Equals(absoluteTimestamp)) {
  712. graphicalStaffEntry = gse;
  713. break;
  714. }
  715. }
  716. if (graphicalStaffEntry === undefined) {
  717. graphicalStaffEntry = thisPointer.createStaffEntryForTieNote(measure, absoluteTimestamp, openTie);
  718. }
  719. }
  720. if (graphicalStaffEntry !== undefined) {
  721. let octaveShiftValue: OctaveEnum = OctaveEnum.NONE;
  722. if (octaveShiftParams !== undefined) {
  723. if (octaveShiftParams.getAbsoluteStartTimestamp.lte(graphicalStaffEntry.getAbsoluteTimestamp()) &&
  724. graphicalStaffEntry.getAbsoluteTimestamp().lte(octaveShiftParams.getAbsoluteEndTimestamp)) {
  725. octaveShiftValue = octaveShiftParams.getOpenOctaveShift.Type;
  726. }
  727. }
  728. let isLastTieNote: boolean = k === tieTimestamps.length - 1;
  729. let tieFraction: Fraction = openTie.Fractions[k];
  730. // GraphicalNote points to tieStartNote, but must get the correct Length (eg the correct Fraction of tieStartNote's Length)
  731. let tiedGraphicalNote: GraphicalNote = thisPointer.symbolFactory.createNote(openTie.Start, graphicalStaffEntry, activeClef,
  732. octaveShiftValue, tieFraction);
  733. let graphicalNotes: GraphicalNote[] =
  734. graphicalStaffEntry.findOrCreateGraphicalNotesListFromGraphicalNote(tiedGraphicalNote);
  735. graphicalStaffEntry.addGraphicalNoteToListAtCorrectYPosition(graphicalNotes, tiedGraphicalNote);
  736. graphicalStaffEntry.PositionAndShape.ChildElements.push(tiedGraphicalNote.PositionAndShape);
  737. thisPointer.handleTiedGraphicalNote(tiedGraphicalNote, beams, activeClef, octaveShiftValue, graphicalStaffEntry, tieFraction,
  738. openTie, isLastTieNote);
  739. let tieStartNote: Note = openTie.Start;
  740. if (isLastTieNote && tieStartNote.ParentVoiceEntry.Articulations.length === 1 &&
  741. tieStartNote.ParentVoiceEntry.Articulations[0] === ArticulationEnum.fermata) {
  742. thisPointer.symbolFactory.addFermataAtTiedEndNote(tieStartNote, graphicalStaffEntry);
  743. }
  744. openTie.NoteHasBeenCreated[k] = true;
  745. if (openTie.allGraphicalNotesHaveBeenCreated()) {
  746. removeTie = true;
  747. //tieTimestampListDict.remove(openTie);
  748. }
  749. }
  750. }
  751. }
  752. return removeTie;
  753. });
  754. }
  755. protected resetYPositionForLeadSheet(psi: BoundingBox): void {
  756. if (this.leadSheet) {
  757. psi.RelativePosition = new PointF2D(psi.RelativePosition.x, 0.0);
  758. }
  759. }
  760. protected layoutVoiceEntries(graphicalStaffEntry: GraphicalStaffEntry): void {
  761. graphicalStaffEntry.PositionAndShape.RelativePosition = new PointF2D(0.0, 0.0);
  762. let isGraceStaffEntry: boolean = graphicalStaffEntry.staffEntryParent !== undefined;
  763. if (!this.leadSheet) {
  764. let graphicalStaffEntryNotes: GraphicalNote[][] = graphicalStaffEntry.notes;
  765. for (let idx4: number = 0, len4: number = graphicalStaffEntryNotes.length; idx4 < len4; ++idx4) {
  766. let graphicalNotes: GraphicalNote[] = graphicalStaffEntryNotes[idx4];
  767. if (graphicalNotes.length === 0) {
  768. continue;
  769. }
  770. let voiceEntry: VoiceEntry = graphicalNotes[0].sourceNote.ParentVoiceEntry;
  771. let hasPitchedNote: boolean = graphicalNotes[0].sourceNote.Pitch !== undefined;
  772. this.layoutVoiceEntry(voiceEntry, graphicalNotes, graphicalStaffEntry, hasPitchedNote, isGraceStaffEntry);
  773. }
  774. }
  775. }
  776. protected maxInstrNameLabelLength(): number {
  777. let maxLabelLength: number = 0.0;
  778. for (let instrument of this.graphicalMusicSheet.ParentMusicSheet.Instruments) {
  779. if (instrument.Voices.length > 0 && instrument.Voices[0].Visible) {
  780. let graphicalLabel: GraphicalLabel = new GraphicalLabel(instrument.NameLabel, this.rules.InstrumentLabelTextHeight, TextAlignment.LeftCenter);
  781. graphicalLabel.setLabelPositionAndShapeBorders();
  782. maxLabelLength = Math.max(maxLabelLength, graphicalLabel.PositionAndShape.MarginSize.width);
  783. }
  784. }
  785. return maxLabelLength;
  786. }
  787. protected calculateSheetLabelBoundingBoxes(): void {
  788. let musicSheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
  789. if (musicSheet.Title !== undefined) {
  790. let title: GraphicalLabel = new GraphicalLabel(musicSheet.Title, this.rules.SheetTitleHeight, TextAlignment.CenterBottom);
  791. this.graphicalMusicSheet.Title = title;
  792. title.setLabelPositionAndShapeBorders();
  793. }
  794. if (musicSheet.Subtitle !== undefined) {
  795. let subtitle: GraphicalLabel = new GraphicalLabel(musicSheet.Subtitle, this.rules.SheetSubtitleHeight, TextAlignment.CenterCenter);
  796. this.graphicalMusicSheet.Subtitle = subtitle;
  797. subtitle.setLabelPositionAndShapeBorders();
  798. }
  799. if (musicSheet.Composer !== undefined) {
  800. let composer: GraphicalLabel = new GraphicalLabel(musicSheet.Composer, this.rules.SheetComposerHeight, TextAlignment.RightCenter);
  801. this.graphicalMusicSheet.Composer = composer;
  802. composer.setLabelPositionAndShapeBorders();
  803. }
  804. if (musicSheet.Lyricist !== undefined) {
  805. let lyricist: GraphicalLabel = new GraphicalLabel(musicSheet.Lyricist, this.rules.SheetAuthorHeight, TextAlignment.LeftCenter);
  806. this.graphicalMusicSheet.Lyricist = lyricist;
  807. lyricist.setLabelPositionAndShapeBorders();
  808. }
  809. }
  810. protected checkMeasuresForWholeRestNotes(): void {
  811. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  812. let musicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  813. for (let idx2: number = 0, len2: number = musicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  814. let musicSystem: MusicSystem = musicPage.MusicSystems[idx2];
  815. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  816. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  817. for (let idx4: number = 0, len4: number = staffLine.Measures.length; idx4 < len4; ++idx4) {
  818. let measure: StaffMeasure = staffLine.Measures[idx4];
  819. if (measure.staffEntries.length === 1) {
  820. let gse: GraphicalStaffEntry = measure.staffEntries[0];
  821. if (gse.notes.length > 0 && gse.notes[0].length > 0) {
  822. let graphicalNote: GraphicalNote = gse.notes[0][0];
  823. if (graphicalNote.sourceNote.Pitch === undefined && (new Fraction(1, 2)).lt(graphicalNote.sourceNote.Length)) {
  824. this.layoutMeasureWithWholeRest(graphicalNote, gse, measure);
  825. }
  826. }
  827. }
  828. }
  829. }
  830. }
  831. }
  832. }
  833. protected optimizeRestNotePlacement(graphicalStaffEntry: GraphicalStaffEntry, measure: StaffMeasure): void {
  834. if (graphicalStaffEntry.notes.length === 0) {
  835. return;
  836. }
  837. let voice1Notes: GraphicalNote[] = graphicalStaffEntry.notes[0];
  838. if (voice1Notes.length === 0) {
  839. return;
  840. }
  841. let voice1Note1: GraphicalNote = voice1Notes[0];
  842. let voice1Note1IsRest: boolean = voice1Note1.sourceNote.Pitch === undefined;
  843. if (graphicalStaffEntry.notes.length === 2) {
  844. let voice2Note1IsRest: boolean = false;
  845. let voice2Notes: GraphicalNote[] = graphicalStaffEntry.notes[1];
  846. if (voice2Notes.length > 0) {
  847. let voice2Note1: GraphicalNote = voice2Notes[0];
  848. voice2Note1IsRest = voice2Note1.sourceNote.Pitch === undefined;
  849. }
  850. if (voice1Note1IsRest && voice2Note1IsRest) {
  851. this.calculateTwoRestNotesPlacementWithCollisionDetection(graphicalStaffEntry);
  852. } else if (voice1Note1IsRest || voice2Note1IsRest) {
  853. this.calculateRestNotePlacementWithCollisionDetectionFromGraphicalNote(graphicalStaffEntry);
  854. }
  855. } else if (voice1Note1IsRest && graphicalStaffEntry !== measure.staffEntries[0] &&
  856. graphicalStaffEntry !== measure.staffEntries[measure.staffEntries.length - 1]) {
  857. let staffEntryIndex: number = measure.staffEntries.indexOf(graphicalStaffEntry);
  858. let previousStaffEntry: GraphicalStaffEntry = measure.staffEntries[staffEntryIndex - 1];
  859. let nextStaffEntry: GraphicalStaffEntry = measure.staffEntries[staffEntryIndex + 1];
  860. if (previousStaffEntry.notes.length === 1) {
  861. let previousNote: GraphicalNote = previousStaffEntry.notes[0][0];
  862. if (previousNote.sourceNote.NoteBeam !== undefined && nextStaffEntry.notes.length === 1) {
  863. let nextNote: GraphicalNote = nextStaffEntry.notes[0][0];
  864. if (nextNote.sourceNote.NoteBeam !== undefined && previousNote.sourceNote.NoteBeam === nextNote.sourceNote.NoteBeam) {
  865. this.calculateRestNotePlacementWithinGraphicalBeam(
  866. graphicalStaffEntry, voice1Note1, previousNote,
  867. nextStaffEntry, nextNote
  868. );
  869. graphicalStaffEntry.PositionAndShape.calculateBoundingBox();
  870. }
  871. }
  872. }
  873. }
  874. }
  875. protected getRelativePositionInStaffLineFromTimestamp(timestamp: Fraction, verticalIndex: number, staffLine: StaffLine,
  876. multiStaffInstrument: boolean, firstVisibleMeasureRelativeX: number = 0.0): PointF2D {
  877. let relative: PointF2D = new PointF2D();
  878. let leftStaffEntry: GraphicalStaffEntry = undefined;
  879. let rightStaffEntry: GraphicalStaffEntry = undefined;
  880. let numEntries: number = this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers.length;
  881. let index: number = this.graphicalMusicSheet.GetInterpolatedIndexInVerticalContainers(timestamp);
  882. let leftIndex: number = <number>Math.min(Math.floor(index), numEntries - 1);
  883. let rightIndex: number = <number>Math.min(Math.ceil(index), numEntries - 1);
  884. if (leftIndex < 0 || verticalIndex < 0) {
  885. return relative;
  886. }
  887. leftStaffEntry = this.getFirstLeftNotNullStaffEntryFromContainer(leftIndex, verticalIndex, multiStaffInstrument);
  888. rightStaffEntry = this.getFirstRightNotNullStaffEntryFromContainer(rightIndex, verticalIndex, multiStaffInstrument);
  889. if (leftStaffEntry !== undefined && rightStaffEntry !== undefined) {
  890. let measureRelativeX: number = leftStaffEntry.parentMeasure.PositionAndShape.RelativePosition.x;
  891. if (firstVisibleMeasureRelativeX > 0) {
  892. measureRelativeX = firstVisibleMeasureRelativeX;
  893. }
  894. let leftX: number = leftStaffEntry.PositionAndShape.RelativePosition.x + measureRelativeX;
  895. let rightX: number = rightStaffEntry.PositionAndShape.RelativePosition.x + rightStaffEntry.parentMeasure.PositionAndShape.RelativePosition.x;
  896. if (firstVisibleMeasureRelativeX > 0) {
  897. rightX = rightStaffEntry.PositionAndShape.RelativePosition.x + measureRelativeX;
  898. }
  899. let timestampQuotient: number = 0.0;
  900. if (leftStaffEntry !== rightStaffEntry) {
  901. let leftTimestamp: Fraction = leftStaffEntry.getAbsoluteTimestamp();
  902. let rightTimestamp: Fraction = rightStaffEntry.getAbsoluteTimestamp();
  903. let leftDifference: Fraction = Fraction.minus(timestamp, leftTimestamp);
  904. timestampQuotient = leftDifference.RealValue / Fraction.minus(rightTimestamp, leftTimestamp).RealValue;
  905. }
  906. if (leftStaffEntry.parentMeasure.ParentStaffLine !== rightStaffEntry.parentMeasure.ParentStaffLine) {
  907. if (leftStaffEntry.parentMeasure.ParentStaffLine === staffLine) {
  908. rightX = staffLine.PositionAndShape.Size.width;
  909. } else {
  910. leftX = staffLine.PositionAndShape.RelativePosition.x;
  911. }
  912. }
  913. relative = new PointF2D(leftX + (rightX - leftX) * timestampQuotient, 0.0);
  914. }
  915. return relative;
  916. }
  917. protected getRelativeXPositionFromTimestamp(timestamp: Fraction): number {
  918. let numEntries: number = this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers.length;
  919. let index: number = this.graphicalMusicSheet.GetInterpolatedIndexInVerticalContainers(timestamp);
  920. let discreteIndex: number = <number>Math.max(0, Math.min(Math.round(index), numEntries - 1));
  921. let gse: GraphicalStaffEntry = this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[discreteIndex].getFirstNonNullStaffEntry();
  922. let posX: number = gse.PositionAndShape.RelativePosition.x + gse.parentMeasure.PositionAndShape.RelativePosition.x;
  923. return posX;
  924. }
  925. protected calculatePageLabels(page: GraphicalMusicPage): void {
  926. let firstSystemAbsoluteTopMargin: number = 10;
  927. if (page.MusicSystems.length > 0) {
  928. let firstMusicSystem: MusicSystem = page.MusicSystems[0];
  929. firstSystemAbsoluteTopMargin = firstMusicSystem.PositionAndShape.RelativePosition.y + firstMusicSystem.PositionAndShape.BorderTop;
  930. }
  931. if (this.graphicalMusicSheet.Title !== undefined) {
  932. let title: GraphicalLabel = this.graphicalMusicSheet.Title;
  933. title.PositionAndShape.Parent = page.PositionAndShape;
  934. page.PositionAndShape.ChildElements.push(title.PositionAndShape);
  935. let relative: PointF2D = new PointF2D();
  936. relative.x = this.graphicalMusicSheet.ParentMusicSheet.pageWidth / 2;
  937. relative.y = this.rules.TitleTopDistance + this.rules.SheetTitleHeight;
  938. title.PositionAndShape.RelativePosition = relative;
  939. page.Labels.push(title);
  940. }
  941. if (this.graphicalMusicSheet.Subtitle !== undefined) {
  942. let subtitle: GraphicalLabel = this.graphicalMusicSheet.Subtitle;
  943. subtitle.PositionAndShape.Parent = page.PositionAndShape;
  944. page.PositionAndShape.ChildElements.push(subtitle.PositionAndShape);
  945. let relative: PointF2D = new PointF2D();
  946. relative.x = this.graphicalMusicSheet.ParentMusicSheet.pageWidth / 2;
  947. relative.y = this.rules.TitleTopDistance + this.rules.SheetTitleHeight + this.rules.SheetMinimumDistanceBetweenTitleAndSubtitle;
  948. subtitle.PositionAndShape.RelativePosition = relative;
  949. page.Labels.push(subtitle);
  950. }
  951. if (this.graphicalMusicSheet.Composer !== undefined) {
  952. let composer: GraphicalLabel = this.graphicalMusicSheet.Composer;
  953. composer.PositionAndShape.Parent = page.PositionAndShape;
  954. page.PositionAndShape.ChildElements.push(composer.PositionAndShape);
  955. composer.setLabelPositionAndShapeBorders();
  956. let relative: PointF2D = new PointF2D();
  957. relative.x = this.graphicalMusicSheet.ParentMusicSheet.pageWidth - this.rules.PageRightMargin;
  958. relative.y = firstSystemAbsoluteTopMargin - this.rules.SystemComposerDistance;
  959. composer.PositionAndShape.RelativePosition = relative;
  960. page.Labels.push(composer);
  961. }
  962. if (this.graphicalMusicSheet.Lyricist !== undefined) {
  963. let lyricist: GraphicalLabel = this.graphicalMusicSheet.Lyricist;
  964. lyricist.PositionAndShape.Parent = page.PositionAndShape;
  965. page.PositionAndShape.ChildElements.push(lyricist.PositionAndShape);
  966. lyricist.setLabelPositionAndShapeBorders();
  967. let relative: PointF2D = new PointF2D();
  968. relative.x = this.rules.PageLeftMargin;
  969. relative.y = firstSystemAbsoluteTopMargin - this.rules.SystemComposerDistance;
  970. lyricist.PositionAndShape.RelativePosition = relative;
  971. page.Labels.push(lyricist);
  972. }
  973. }
  974. protected createGraphicalTies(): void {
  975. for (let measureIndex: number = 0; measureIndex < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.length; measureIndex++) {
  976. let sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[measureIndex];
  977. for (let staffIndex: number = 0; staffIndex < sourceMeasure.CompleteNumberOfStaves; staffIndex++) {
  978. for (let j: number = 0; j < sourceMeasure.VerticalSourceStaffEntryContainers.length; j++) {
  979. let sourceStaffEntry: SourceStaffEntry = sourceMeasure.VerticalSourceStaffEntryContainers[j].StaffEntries[staffIndex];
  980. if (sourceStaffEntry !== undefined) {
  981. let startStaffEntry: GraphicalStaffEntry = this.graphicalMusicSheet.findGraphicalStaffEntryFromMeasureList(
  982. staffIndex, measureIndex, sourceStaffEntry
  983. );
  984. for (let idx: number = 0, len: number = sourceStaffEntry.VoiceEntries.length; idx < len; ++idx) {
  985. let voiceEntry: VoiceEntry = sourceStaffEntry.VoiceEntries[idx];
  986. for (let idx2: number = 0, len2: number = voiceEntry.Notes.length; idx2 < len2; ++idx2) {
  987. let note: Note = voiceEntry.Notes[idx2];
  988. if (note.NoteTie !== undefined) {
  989. let tie: Tie = note.NoteTie;
  990. this.handleTie(tie, startStaffEntry, staffIndex, measureIndex);
  991. }
  992. }
  993. }
  994. }
  995. }
  996. }
  997. }
  998. }
  999. private handleTie(tie: Tie, startGraphicalStaffEntry: GraphicalStaffEntry, staffIndex: number, measureIndex: number): void {
  1000. let startGse: GraphicalStaffEntry = startGraphicalStaffEntry;
  1001. let endGse: GraphicalStaffEntry = undefined;
  1002. let startNote: GraphicalNote = undefined;
  1003. let endNote: GraphicalNote = undefined;
  1004. for (let i: number = 0; i < tie.Fractions.length; i++) {
  1005. let verticalGraphicalStaffEntryContainer: VerticalGraphicalStaffEntryContainer;
  1006. let endTimestamp: Fraction;
  1007. let startContainerIndex: number = startGraphicalStaffEntry.parentVerticalContainer.Index;
  1008. if (i === 0) {
  1009. endTimestamp = Fraction.plus(startGraphicalStaffEntry.getAbsoluteTimestamp(), tie.Start.calculateNoteLengthWithoutTie());
  1010. } else {
  1011. endTimestamp = Fraction.plus(startGse.getAbsoluteTimestamp(), tie.Fractions[i - 1]);
  1012. }
  1013. verticalGraphicalStaffEntryContainer = this.graphicalMusicSheet.GetVerticalContainerFromTimestamp(endTimestamp, startContainerIndex + 1);
  1014. if (verticalGraphicalStaffEntryContainer !== undefined) {
  1015. endGse = verticalGraphicalStaffEntryContainer.StaffEntries[staffIndex];
  1016. startNote = startGse.findEndTieGraphicalNoteFromNote(tie.Start);
  1017. if (endGse !== undefined) {
  1018. endNote = endGse.findEndTieGraphicalNoteFromNote(tie.Start);
  1019. }
  1020. }
  1021. if (startNote !== undefined && endNote !== undefined && endGse !== undefined) {
  1022. let graphicalTie: GraphicalTie = this.createGraphicalTie(tie, startGse, endGse, startNote, endNote);
  1023. startGse.GraphicalTies.push(graphicalTie);
  1024. if (this.staffEntriesWithGraphicalTies.indexOf(startGse) >= 0) {
  1025. this.staffEntriesWithGraphicalTies.push(startGse);
  1026. }
  1027. }
  1028. if (endGse !== undefined) {
  1029. if (endGse.parentMeasure !== startGse.parentMeasure) {
  1030. measureIndex++;
  1031. }
  1032. startGse = endGse;
  1033. endGse = this.graphicalMusicSheet.findNextGraphicalStaffEntry(staffIndex, measureIndex, startGse);
  1034. }
  1035. }
  1036. }
  1037. private createAccidentalCalculators(): AccidentalCalculator[] {
  1038. let accidentalCalculators: AccidentalCalculator[] = [];
  1039. let firstSourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.getFirstSourceMeasure();
  1040. if (firstSourceMeasure !== undefined) {
  1041. for (let i: number = 0; i < firstSourceMeasure.CompleteNumberOfStaves; i++) {
  1042. let accidentalCalculator: AccidentalCalculator = new AccidentalCalculator(this.symbolFactory);
  1043. accidentalCalculators.push(accidentalCalculator);
  1044. if (firstSourceMeasure.FirstInstructionsStaffEntries[i] !== undefined) {
  1045. for (let idx: number = 0, len: number = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions.length; idx < len; ++idx) {
  1046. let abstractNotationInstruction: AbstractNotationInstruction = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions[idx];
  1047. if (abstractNotationInstruction instanceof KeyInstruction) {
  1048. let keyInstruction: KeyInstruction = <KeyInstruction>abstractNotationInstruction;
  1049. accidentalCalculator.ActiveKeyInstruction = keyInstruction;
  1050. }
  1051. }
  1052. }
  1053. }
  1054. }
  1055. return accidentalCalculators;
  1056. }
  1057. private calculateVerticalContainersList(): void {
  1058. let numberOfEntries: number = this.graphicalMusicSheet.MeasureList[0].length;
  1059. for (let i: number = 0; i < this.graphicalMusicSheet.MeasureList.length; i++) {
  1060. for (let j: number = 0; j < numberOfEntries; j++) {
  1061. let measure: StaffMeasure = this.graphicalMusicSheet.MeasureList[i][j];
  1062. for (let idx: number = 0, len: number = measure.staffEntries.length; idx < len; ++idx) {
  1063. let graphicalStaffEntry: GraphicalStaffEntry = measure.staffEntries[idx];
  1064. let verticalContainer: VerticalGraphicalStaffEntryContainer =
  1065. this.graphicalMusicSheet.getOrCreateVerticalContainer(graphicalStaffEntry.getAbsoluteTimestamp());
  1066. if (verticalContainer !== undefined) {
  1067. verticalContainer.StaffEntries[j] = graphicalStaffEntry;
  1068. graphicalStaffEntry.parentVerticalContainer = verticalContainer;
  1069. } else {
  1070. // TODO ?
  1071. }
  1072. }
  1073. }
  1074. }
  1075. }
  1076. private setIndecesToVerticalGraphicalContainers(): void {
  1077. for (let i: number = 0; i < this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers.length; i++) {
  1078. this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].Index = i;
  1079. }
  1080. }
  1081. private createGraphicalMeasuresForSourceMeasure(sourceMeasure: SourceMeasure, accidentalCalculators: AccidentalCalculator[],
  1082. openLyricWords: LyricWord[],
  1083. tieTimestampListDictList: Dictionary<Tie, Fraction[]>[],
  1084. openOctaveShifts: OctaveShiftParams[], activeClefs: ClefInstruction[]): StaffMeasure[] {
  1085. this.initStaffMeasuresCreation();
  1086. let verticalMeasureList: StaffMeasure[] = [];
  1087. let openBeams: Beam[] = [];
  1088. let openTuplets: Tuplet[] = [];
  1089. let staffEntryLinks: StaffEntryLink[] = [];
  1090. for (let staffIndex: number = 0; staffIndex < sourceMeasure.CompleteNumberOfStaves; staffIndex++) {
  1091. let measure: StaffMeasure = this.createGraphicalMeasure(
  1092. sourceMeasure, tieTimestampListDictList[staffIndex], openTuplets, openBeams,
  1093. accidentalCalculators[staffIndex], activeClefs, openOctaveShifts, openLyricWords, staffIndex, staffEntryLinks
  1094. );
  1095. this.staffMeasureCreatedCalculations(measure);
  1096. verticalMeasureList.push(measure);
  1097. }
  1098. this.graphicalMusicSheet.sourceToGraphicalMeasureLinks.setValue(sourceMeasure, verticalMeasureList);
  1099. return verticalMeasureList;
  1100. }
  1101. private createGraphicalMeasure(sourceMeasure: SourceMeasure, tieTimestampListDict: Dictionary<Tie, Fraction[]>, openTuplets: Tuplet[], openBeams: Beam[],
  1102. accidentalCalculator: AccidentalCalculator, activeClefs: ClefInstruction[],
  1103. openOctaveShifts: OctaveShiftParams[], openLyricWords: LyricWord[], staffIndex: number,
  1104. staffEntryLinks: StaffEntryLink[]): StaffMeasure {
  1105. let staff: Staff = this.graphicalMusicSheet.ParentMusicSheet.getStaffFromIndex(staffIndex);
  1106. let measure: StaffMeasure = this.symbolFactory.createStaffMeasure(sourceMeasure, staff);
  1107. measure.hasError = sourceMeasure.getErrorInMeasure(staffIndex);
  1108. if (sourceMeasure.FirstInstructionsStaffEntries[staffIndex] !== undefined) {
  1109. for (let idx: number = 0, len: number = sourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions.length; idx < len; ++idx) {
  1110. let instruction: AbstractNotationInstruction = sourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions[idx];
  1111. if (instruction instanceof KeyInstruction) {
  1112. let key: KeyInstruction = KeyInstruction.copy(instruction);
  1113. if (this.graphicalMusicSheet.ParentMusicSheet.Transpose !== 0 &&
  1114. measure.ParentStaff.ParentInstrument.MidiInstrumentId !== MidiInstrument.Percussion &&
  1115. MusicSheetCalculator.transposeCalculator !== undefined) {
  1116. MusicSheetCalculator.transposeCalculator.transposeKey(
  1117. key, this.graphicalMusicSheet.ParentMusicSheet.Transpose
  1118. );
  1119. }
  1120. accidentalCalculator.ActiveKeyInstruction = key;
  1121. }
  1122. }
  1123. }
  1124. for (let idx: number = 0, len: number = sourceMeasure.StaffLinkedExpressions[staffIndex].length; idx < len; ++idx) {
  1125. let multiExpression: MultiExpression = sourceMeasure.StaffLinkedExpressions[staffIndex][idx];
  1126. if (multiExpression.OctaveShiftStart !== undefined) {
  1127. let openOctaveShift: OctaveShift = multiExpression.OctaveShiftStart;
  1128. openOctaveShifts[staffIndex] = new OctaveShiftParams(
  1129. openOctaveShift, multiExpression.AbsoluteTimestamp,
  1130. openOctaveShift.ParentEndMultiExpression.AbsoluteTimestamp
  1131. );
  1132. }
  1133. }
  1134. for (let entryIndex: number = 0; entryIndex < sourceMeasure.VerticalSourceStaffEntryContainers.length; entryIndex++) {
  1135. let sourceStaffEntry: SourceStaffEntry = sourceMeasure.VerticalSourceStaffEntryContainers[entryIndex].StaffEntries[staffIndex];
  1136. if (sourceStaffEntry !== undefined) {
  1137. for (let idx: number = 0, len: number = sourceStaffEntry.Instructions.length; idx < len; ++idx) {
  1138. let abstractNotationInstruction: AbstractNotationInstruction = sourceStaffEntry.Instructions[idx];
  1139. if (abstractNotationInstruction instanceof ClefInstruction) {
  1140. activeClefs[staffIndex] = <ClefInstruction>abstractNotationInstruction;
  1141. }
  1142. }
  1143. let graphicalStaffEntry: GraphicalStaffEntry = this.symbolFactory.createStaffEntry(sourceStaffEntry, measure);
  1144. if (measure.staffEntries.length > entryIndex) {
  1145. measure.addGraphicalStaffEntryAtTimestamp(graphicalStaffEntry);
  1146. } else {
  1147. measure.addGraphicalStaffEntry(graphicalStaffEntry);
  1148. }
  1149. let linkedNotes: Note[] = [];
  1150. if (sourceStaffEntry.Link !== undefined) {
  1151. sourceStaffEntry.findLinkedNotes(linkedNotes);
  1152. this.handleStaffEntryLink(graphicalStaffEntry, staffEntryLinks);
  1153. }
  1154. let octaveShiftValue: OctaveEnum = OctaveEnum.NONE;
  1155. if (openOctaveShifts[staffIndex] !== undefined) {
  1156. let octaveShiftParams: OctaveShiftParams = openOctaveShifts[staffIndex];
  1157. if (octaveShiftParams.getAbsoluteStartTimestamp.lte(sourceStaffEntry.AbsoluteTimestamp) &&
  1158. sourceStaffEntry.AbsoluteTimestamp.lte(octaveShiftParams.getAbsoluteEndTimestamp)) {
  1159. octaveShiftValue = octaveShiftParams.getOpenOctaveShift.Type;
  1160. }
  1161. }
  1162. for (let idx: number = 0, len: number = sourceStaffEntry.VoiceEntries.length; idx < len; ++idx) {
  1163. let voiceEntry: VoiceEntry = sourceStaffEntry.VoiceEntries[idx];
  1164. this.handleVoiceEntryGraceNotes(
  1165. voiceEntry.graceVoiceEntriesBefore, graphicalStaffEntry.graceStaffEntriesBefore, graphicalStaffEntry,
  1166. accidentalCalculator, activeClefs[staffIndex], octaveShiftValue, openLyricWords,
  1167. tieTimestampListDict, openTuplets, openBeams
  1168. );
  1169. octaveShiftValue = this.handleVoiceEntry(
  1170. voiceEntry, graphicalStaffEntry,
  1171. accidentalCalculator, openLyricWords,
  1172. tieTimestampListDict,
  1173. activeClefs[staffIndex], openTuplets,
  1174. openBeams, octaveShiftValue, false, linkedNotes,
  1175. sourceStaffEntry
  1176. );
  1177. this.handleVoiceEntryGraceNotes(
  1178. voiceEntry.graceVoiceEntriesAfter, graphicalStaffEntry.graceStaffEntriesAfter, graphicalStaffEntry,
  1179. accidentalCalculator, activeClefs[staffIndex], octaveShiftValue, openLyricWords,
  1180. tieTimestampListDict, openTuplets, openBeams
  1181. );
  1182. }
  1183. if (sourceStaffEntry.Instructions.length > 0) {
  1184. let clefInstruction: ClefInstruction = <ClefInstruction>sourceStaffEntry.Instructions[0];
  1185. this.symbolFactory.createInStaffClef(graphicalStaffEntry, clefInstruction);
  1186. }
  1187. if (sourceStaffEntry.ChordContainer !== undefined) {
  1188. sourceStaffEntry.ParentStaff.ParentInstrument.HasChordSymbols = true;
  1189. this.symbolFactory.createChordSymbol(sourceStaffEntry, graphicalStaffEntry, this.graphicalMusicSheet.ParentMusicSheet.Transpose);
  1190. }
  1191. }
  1192. }
  1193. if (tieTimestampListDict.size() > 0) {
  1194. this.handleOpenTies(
  1195. measure, openBeams,
  1196. tieTimestampListDict, activeClefs[staffIndex], openOctaveShifts[staffIndex]
  1197. );
  1198. }
  1199. accidentalCalculator.doCalculationsAtEndOfMeasure();
  1200. if (sourceMeasure.LastInstructionsStaffEntries[staffIndex] !== undefined) {
  1201. let lastStaffEntry: SourceStaffEntry = sourceMeasure.LastInstructionsStaffEntries[staffIndex];
  1202. for (let idx: number = 0, len: number = lastStaffEntry.Instructions.length; idx < len; ++idx) {
  1203. let abstractNotationInstruction: AbstractNotationInstruction = lastStaffEntry.Instructions[idx];
  1204. if (abstractNotationInstruction instanceof ClefInstruction) {
  1205. activeClefs[staffIndex] = <ClefInstruction>abstractNotationInstruction;
  1206. }
  1207. }
  1208. }
  1209. for (let idx: number = 0, len: number = sourceMeasure.StaffLinkedExpressions[staffIndex].length; idx < len; ++idx) {
  1210. let multiExpression: MultiExpression = sourceMeasure.StaffLinkedExpressions[staffIndex][idx];
  1211. if (multiExpression.OctaveShiftEnd !== undefined && openOctaveShifts[staffIndex] !== undefined &&
  1212. multiExpression.OctaveShiftEnd === openOctaveShifts[staffIndex].getOpenOctaveShift) {
  1213. openOctaveShifts[staffIndex] = undefined;
  1214. }
  1215. }
  1216. if (measure.staffEntries.length === 0) {
  1217. let sourceStaffEntry: SourceStaffEntry = new SourceStaffEntry(undefined, staff);
  1218. let note: Note = new Note(undefined, sourceStaffEntry, Fraction.createFromFraction(sourceMeasure.Duration), undefined);
  1219. let graphicalStaffEntry: GraphicalStaffEntry = this.symbolFactory.createStaffEntry(sourceStaffEntry, measure);
  1220. measure.addGraphicalStaffEntry(graphicalStaffEntry);
  1221. graphicalStaffEntry.relInMeasureTimestamp = new Fraction(0, 1);
  1222. let graphicalNotes: GraphicalNote[] = [];
  1223. graphicalStaffEntry.notes.push(graphicalNotes);
  1224. let graphicalNote: GraphicalNote = this.symbolFactory.createNote( note,
  1225. graphicalStaffEntry,
  1226. new ClefInstruction(),
  1227. OctaveEnum.NONE, undefined);
  1228. graphicalNotes.push(graphicalNote);
  1229. graphicalStaffEntry.PositionAndShape.ChildElements.push(graphicalNote.PositionAndShape);
  1230. }
  1231. return measure;
  1232. }
  1233. private checkVoiceEntriesForTechnicalInstructions(voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry): void {
  1234. for (let idx: number = 0, len: number = voiceEntry.TechnicalInstructions.length; idx < len; ++idx) {
  1235. let technicalInstruction: TechnicalInstruction = voiceEntry.TechnicalInstructions[idx];
  1236. this.symbolFactory.createGraphicalTechnicalInstruction(technicalInstruction, graphicalStaffEntry);
  1237. }
  1238. }
  1239. private checkNoteForAccidental(graphicalNote: GraphicalNote, accidentalCalculator: AccidentalCalculator, activeClef: ClefInstruction,
  1240. octaveEnum: OctaveEnum, grace: boolean = false): void {
  1241. let pitch: Pitch = graphicalNote.sourceNote.Pitch;
  1242. let transpose: number = this.graphicalMusicSheet.ParentMusicSheet.Transpose;
  1243. if (transpose !== 0 && graphicalNote.sourceNote.ParentStaffEntry.ParentStaff.ParentInstrument.MidiInstrumentId !== MidiInstrument.Percussion) {
  1244. pitch = graphicalNote.Transpose(
  1245. accidentalCalculator.ActiveKeyInstruction, activeClef, transpose, octaveEnum
  1246. );
  1247. if (graphicalNote.sourceNote.NoteTie !== undefined) {
  1248. graphicalNote.sourceNote.NoteTie.BaseNoteYPosition = graphicalNote.PositionAndShape.RelativePosition.y;
  1249. }
  1250. }
  1251. graphicalNote.sourceNote.halfTone = pitch.getHalfTone();
  1252. let scalingFactor: number = 1.0;
  1253. if (grace) {
  1254. scalingFactor = this.rules.GraceNoteScalingFactor;
  1255. }
  1256. accidentalCalculator.checkAccidental(graphicalNote, pitch, grace, scalingFactor);
  1257. }
  1258. // needed to disable linter, as it doesn't recognize the existing usage of this method.
  1259. // ToDo: check if a newer version doesn't have the problem.
  1260. /* tslint:disable:no-unused-variable */
  1261. private createStaffEntryForTieNote(measure: StaffMeasure, absoluteTimestamp: Fraction, openTie: Tie): GraphicalStaffEntry {
  1262. /* tslint:enable:no-unused-variable */
  1263. let graphicalStaffEntry: GraphicalStaffEntry;
  1264. graphicalStaffEntry = this.symbolFactory.createStaffEntry(openTie.Start.ParentStaffEntry, measure);
  1265. graphicalStaffEntry.relInMeasureTimestamp = Fraction.minus(absoluteTimestamp, measure.parentSourceMeasure.AbsoluteTimestamp);
  1266. this.resetYPositionForLeadSheet(graphicalStaffEntry.PositionAndShape);
  1267. measure.addGraphicalStaffEntryAtTimestamp(graphicalStaffEntry);
  1268. return graphicalStaffEntry;
  1269. }
  1270. private updateSkyBottomLines(): void {
  1271. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1272. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1273. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  1274. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  1275. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  1276. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  1277. this.updateSkyBottomLine(staffLine);
  1278. }
  1279. }
  1280. }
  1281. }
  1282. private handleStaffEntries(): void {
  1283. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MeasureList.length; idx < len; ++idx) {
  1284. let measures: StaffMeasure[] = this.graphicalMusicSheet.MeasureList[idx];
  1285. for (let idx2: number = 0, len2: number = measures.length; idx2 < len2; ++idx2) {
  1286. let measure: StaffMeasure = measures[idx2];
  1287. for (let idx3: number = 0, len3: number = measure.staffEntries.length; idx3 < len3; ++idx3) {
  1288. let graphicalStaffEntry: GraphicalStaffEntry = measure.staffEntries[idx3];
  1289. if (graphicalStaffEntry.parentMeasure !== undefined && graphicalStaffEntry.notes.length > 0 && graphicalStaffEntry.notes[0].length > 0) {
  1290. this.layoutVoiceEntries(graphicalStaffEntry);
  1291. this.layoutStaffEntry(graphicalStaffEntry);
  1292. }
  1293. }
  1294. }
  1295. }
  1296. }
  1297. private calculateSkyBottomLines(): void {
  1298. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1299. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1300. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  1301. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  1302. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  1303. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  1304. this.calculateSkyBottomLine(staffLine);
  1305. }
  1306. }
  1307. }
  1308. }
  1309. private calculateBeams(): void {
  1310. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1311. let musicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1312. for (let idx2: number = 0, len2: number = musicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  1313. let musicSystem: MusicSystem = musicPage.MusicSystems[idx2];
  1314. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  1315. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  1316. for (let idx4: number = 0, len4: number = staffLine.Measures.length; idx4 < len4; ++idx4) {
  1317. let measure: StaffMeasure = staffLine.Measures[idx4];
  1318. for (let idx5: number = 0, len5: number = measure.staffEntries.length; idx5 < len5; ++idx5) {
  1319. let staffEntry: GraphicalStaffEntry = measure.staffEntries[idx5];
  1320. this.layoutBeams(staffEntry);
  1321. }
  1322. }
  1323. }
  1324. }
  1325. }
  1326. }
  1327. private calculateStaffEntryArticulationMarks(): void {
  1328. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1329. let page: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1330. for (let idx2: number = 0, len2: number = page.MusicSystems.length; idx2 < len2; ++idx2) {
  1331. let system: MusicSystem = page.MusicSystems[idx2];
  1332. for (let idx3: number = 0, len3: number = system.StaffLines.length; idx3 < len3; ++idx3) {
  1333. let line: StaffLine = system.StaffLines[idx3];
  1334. for (let idx4: number = 0, len4: number = line.Measures.length; idx4 < len4; ++idx4) {
  1335. let measure: StaffMeasure = line.Measures[idx4];
  1336. for (let idx5: number = 0, len5: number = measure.staffEntries.length; idx5 < len5; ++idx5) {
  1337. let graphicalStaffEntry: GraphicalStaffEntry = measure.staffEntries[idx5];
  1338. for (let idx6: number = 0, len6: number = graphicalStaffEntry.sourceStaffEntry.VoiceEntries.length; idx6 < len6; ++idx6) {
  1339. let voiceEntry: VoiceEntry = graphicalStaffEntry.sourceStaffEntry.VoiceEntries[idx6];
  1340. if (voiceEntry.Articulations.length > 0) {
  1341. this.layoutArticulationMarks(voiceEntry.Articulations, voiceEntry, graphicalStaffEntry);
  1342. }
  1343. }
  1344. }
  1345. }
  1346. }
  1347. }
  1348. }
  1349. }
  1350. private calculateOrnaments(): void {
  1351. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1352. let page: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1353. for (let idx2: number = 0, len2: number = page.MusicSystems.length; idx2 < len2; ++idx2) {
  1354. let system: MusicSystem = page.MusicSystems[idx2];
  1355. for (let idx3: number = 0, len3: number = system.StaffLines.length; idx3 < len3; ++idx3) {
  1356. let line: StaffLine = system.StaffLines[idx3];
  1357. for (let idx4: number = 0, len4: number = line.Measures.length; idx4 < len4; ++idx4) {
  1358. let measure: StaffMeasure = line.Measures[idx4];
  1359. for (let idx5: number = 0, len5: number = measure.staffEntries.length; idx5 < len5; ++idx5) {
  1360. let graphicalStaffEntry: GraphicalStaffEntry = measure.staffEntries[idx5];
  1361. for (let idx6: number = 0, len6: number = graphicalStaffEntry.sourceStaffEntry.VoiceEntries.length; idx6 < len6; ++idx6) {
  1362. let voiceEntry: VoiceEntry = graphicalStaffEntry.sourceStaffEntry.VoiceEntries[idx6];
  1363. if (voiceEntry.OrnamentContainer !== undefined) {
  1364. if (voiceEntry.hasTie() && !graphicalStaffEntry.relInMeasureTimestamp.Equals(voiceEntry.Timestamp)) {
  1365. continue;
  1366. }
  1367. this.layoutOrnament(voiceEntry.OrnamentContainer, voiceEntry, graphicalStaffEntry);
  1368. if (!(this.staffEntriesWithOrnaments.indexOf(graphicalStaffEntry) !== -1)) {
  1369. this.staffEntriesWithOrnaments.push(graphicalStaffEntry);
  1370. }
  1371. }
  1372. }
  1373. }
  1374. }
  1375. }
  1376. }
  1377. }
  1378. }
  1379. private optimizeRestPlacement(): void {
  1380. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1381. let page: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1382. for (let idx2: number = 0, len2: number = page.MusicSystems.length; idx2 < len2; ++idx2) {
  1383. let system: MusicSystem = page.MusicSystems[idx2];
  1384. for (let idx3: number = 0, len3: number = system.StaffLines.length; idx3 < len3; ++idx3) {
  1385. let line: StaffLine = system.StaffLines[idx3];
  1386. for (let idx4: number = 0, len4: number = line.Measures.length; idx4 < len4; ++idx4) {
  1387. let measure: StaffMeasure = line.Measures[idx4];
  1388. for (let idx5: number = 0, len5: number = measure.staffEntries.length; idx5 < len5; ++idx5) {
  1389. let graphicalStaffEntry: GraphicalStaffEntry = measure.staffEntries[idx5];
  1390. this.optimizeRestNotePlacement(graphicalStaffEntry, measure);
  1391. }
  1392. }
  1393. }
  1394. }
  1395. }
  1396. }
  1397. private calculateTwoRestNotesPlacementWithCollisionDetection(graphicalStaffEntry: GraphicalStaffEntry): void {
  1398. let firstRestNote: GraphicalNote = graphicalStaffEntry.notes[0][0];
  1399. let secondRestNote: GraphicalNote = graphicalStaffEntry.notes[1][0];
  1400. secondRestNote.PositionAndShape.RelativePosition = new PointF2D(0.0, 2.5);
  1401. graphicalStaffEntry.PositionAndShape.calculateAbsolutePositionsRecursiveWithoutTopelement();
  1402. firstRestNote.PositionAndShape.computeNonOverlappingPositionWithMargin(
  1403. graphicalStaffEntry.PositionAndShape, ColDirEnum.Up,
  1404. new PointF2D(0.0, secondRestNote.PositionAndShape.RelativePosition.y)
  1405. );
  1406. let relative: PointF2D = firstRestNote.PositionAndShape.RelativePosition;
  1407. relative.y -= 1.0;
  1408. firstRestNote.PositionAndShape.RelativePosition = relative;
  1409. graphicalStaffEntry.PositionAndShape.calculateBoundingBox();
  1410. }
  1411. private calculateRestNotePlacementWithCollisionDetectionFromGraphicalNote(graphicalStaffEntry: GraphicalStaffEntry): void {
  1412. let restNote: GraphicalNote;
  1413. let graphicalNotes: GraphicalNote[];
  1414. if (graphicalStaffEntry.notes[0][0].sourceNote.Pitch === undefined) {
  1415. restNote = graphicalStaffEntry.notes[0][0];
  1416. graphicalNotes = graphicalStaffEntry.notes[1];
  1417. } else {
  1418. graphicalNotes = graphicalStaffEntry.notes[0];
  1419. restNote = graphicalStaffEntry.notes[1][0];
  1420. }
  1421. let collision: boolean = false;
  1422. graphicalStaffEntry.PositionAndShape.calculateAbsolutePositionsRecursiveWithoutTopelement();
  1423. for (let idx: number = 0, len: number = graphicalNotes.length; idx < len; ++idx) {
  1424. let graphicalNote: GraphicalNote = graphicalNotes[idx];
  1425. if (restNote.PositionAndShape.marginCollisionDetection(graphicalNote.PositionAndShape)) {
  1426. collision = true;
  1427. break;
  1428. }
  1429. }
  1430. if (collision) {
  1431. if (restNote.sourceNote.ParentVoiceEntry.ParentVoice instanceof LinkedVoice) {
  1432. let bottomBorder: number = graphicalNotes[0].PositionAndShape.BorderMarginBottom + graphicalNotes[0].PositionAndShape.RelativePosition.y;
  1433. restNote.PositionAndShape.RelativePosition = new PointF2D(0.0, bottomBorder - restNote.PositionAndShape.BorderMarginTop + 0.5);
  1434. } else {
  1435. let last: GraphicalNote = graphicalNotes[graphicalNotes.length - 1];
  1436. let topBorder: number = last.PositionAndShape.BorderMarginTop + last.PositionAndShape.RelativePosition.y;
  1437. if (graphicalNotes[0].sourceNote.ParentVoiceEntry.ParentVoice instanceof LinkedVoice) {
  1438. restNote.PositionAndShape.RelativePosition = new PointF2D(0.0, topBorder - restNote.PositionAndShape.BorderMarginBottom - 0.5);
  1439. } else {
  1440. let bottomBorder: number = graphicalNotes[0].PositionAndShape.BorderMarginBottom + graphicalNotes[0].PositionAndShape.RelativePosition.y;
  1441. if (bottomBorder < 2.0) {
  1442. restNote.PositionAndShape.RelativePosition = new PointF2D(0.0, bottomBorder - restNote.PositionAndShape.BorderMarginTop + 0.5);
  1443. } else {
  1444. restNote.PositionAndShape.RelativePosition = new PointF2D(0.0, topBorder - restNote.PositionAndShape.BorderMarginBottom - 0.0);
  1445. }
  1446. }
  1447. }
  1448. }
  1449. graphicalStaffEntry.PositionAndShape.calculateBoundingBox();
  1450. }
  1451. private calculateTieCurves(): void {
  1452. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1453. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1454. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  1455. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  1456. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  1457. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  1458. for (let idx4: number = 0, len5: number = staffLine.Measures.length; idx4 < len5; ++idx4) {
  1459. let measure: StaffMeasure = staffLine.Measures[idx4];
  1460. for (let idx6: number = 0, len6: number = measure.staffEntries.length; idx6 < len6; ++idx6) {
  1461. let staffEntry: GraphicalStaffEntry = measure.staffEntries[idx6];
  1462. let graphicalTies: GraphicalTie[] = staffEntry.GraphicalTies;
  1463. for (let idx7: number = 0, len7: number = graphicalTies.length; idx7 < len7; ++idx7) {
  1464. let graphicalTie: GraphicalTie = graphicalTies[idx7];
  1465. if (graphicalTie.StartNote !== undefined && graphicalTie.StartNote.parentStaffEntry === staffEntry) {
  1466. let tieIsAtSystemBreak: boolean = (
  1467. graphicalTie.StartNote.parentStaffEntry.parentMeasure.ParentStaffLine !==
  1468. graphicalTie.EndNote.parentStaffEntry.parentMeasure.ParentStaffLine
  1469. );
  1470. this.layoutGraphicalTie(graphicalTie, tieIsAtSystemBreak);
  1471. }
  1472. }
  1473. }
  1474. }
  1475. }
  1476. }
  1477. }
  1478. }
  1479. // Commented because unused:
  1480. //private calculateFingering(): void {
  1481. // for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1482. // let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1483. // for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  1484. // let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  1485. // for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  1486. // let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  1487. // let skyBottomLineCalculator: SkyBottomLineCalculator = new SkyBottomLineCalculator(this.rules);
  1488. // for (let idx4: number = 0, len4: number = staffLine.Measures.length; idx4 < len4; ++idx4) {
  1489. // let measure: StaffMeasure = staffLine.Measures[idx4];
  1490. // let measureRelativePosition: PointF2D = measure.PositionAndShape.RelativePosition;
  1491. // for (let idx5: number = 0, len5: number = measure.staffEntries.length; idx5 < len5; ++idx5) {
  1492. // let staffEntry: GraphicalStaffEntry = measure.staffEntries[idx5];
  1493. // let hasTechnicalInstruction: boolean = false;
  1494. // for (let idx6: number = 0, len6: number = staffEntry.sourceStaffEntry.VoiceEntries.length; idx6 < len6; ++idx6) {
  1495. // let ve: VoiceEntry = staffEntry.sourceStaffEntry.VoiceEntries[idx6];
  1496. // if (ve.TechnicalInstructions.length > 0) {
  1497. // hasTechnicalInstruction = true;
  1498. // break;
  1499. // }
  1500. // }
  1501. // if (hasTechnicalInstruction) {
  1502. // this.layoutFingering(staffLine, skyBottomLineCalculator, staffEntry, measureRelativePosition);
  1503. // }
  1504. // }
  1505. // }
  1506. // }
  1507. // }
  1508. // }
  1509. //}
  1510. private calculateLyricsPosition(): void {
  1511. for (let idx: number = 0, len: number = this.graphicalMusicSheet.ParentMusicSheet.Instruments.length; idx < len; ++idx) {
  1512. let instrument: Instrument = this.graphicalMusicSheet.ParentMusicSheet.Instruments[idx];
  1513. if (instrument.HasLyrics && instrument.LyricVersesNumbers.length > 0) {
  1514. instrument.LyricVersesNumbers.sort();
  1515. }
  1516. }
  1517. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  1518. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  1519. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  1520. let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  1521. for (let idx3: number = 0, len3: number = musicSystem.StaffLines.length; idx3 < len3; ++idx3) {
  1522. let staffLine: StaffLine = musicSystem.StaffLines[idx3];
  1523. this.calculateSingleStaffLineLyricsPosition(staffLine, staffLine.ParentStaff.ParentInstrument.LyricVersesNumbers);
  1524. }
  1525. }
  1526. }
  1527. }
  1528. private calculateDynamicExpressions(): void {
  1529. for (let i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.length; i++) {
  1530. let sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
  1531. for (let j: number = 0; j < sourceMeasure.StaffLinkedExpressions.length; j++) {
  1532. if (this.graphicalMusicSheet.MeasureList[i][j].ParentStaff.ParentInstrument.Visible) {
  1533. for (let k: number = 0; k < sourceMeasure.StaffLinkedExpressions[j].length; k++) {
  1534. if (sourceMeasure.StaffLinkedExpressions[j][k].InstantaniousDynamic !== undefined ||
  1535. (sourceMeasure.StaffLinkedExpressions[j][k].StartingContinuousDynamic !== undefined &&
  1536. sourceMeasure.StaffLinkedExpressions[j][k].StartingContinuousDynamic.StartMultiExpression ===
  1537. sourceMeasure.StaffLinkedExpressions[j][k] && sourceMeasure.StaffLinkedExpressions[j][k].UnknownList.length === 0)
  1538. ) {
  1539. this.calculateDynamicExpressionsForSingleMultiExpression(sourceMeasure.StaffLinkedExpressions[j][k], i, j);
  1540. }
  1541. }
  1542. }
  1543. }
  1544. }
  1545. }
  1546. private calculateOctaveShifts(): void {
  1547. for (let i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.length; i++) {
  1548. let sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
  1549. for (let j: number = 0; j < sourceMeasure.StaffLinkedExpressions.length; j++) {
  1550. if (this.graphicalMusicSheet.MeasureList[i][j].ParentStaff.ParentInstrument.Visible) {
  1551. for (let k: number = 0; k < sourceMeasure.StaffLinkedExpressions[j].length; k++) {
  1552. if ((sourceMeasure.StaffLinkedExpressions[j][k].OctaveShiftStart !== undefined)) {
  1553. this.calculateSingleOctaveShift(sourceMeasure, sourceMeasure.StaffLinkedExpressions[j][k], i, j);
  1554. }
  1555. }
  1556. }
  1557. }
  1558. }
  1559. }
  1560. private getFirstLeftNotNullStaffEntryFromContainer(horizontalIndex: number, verticalIndex: number, multiStaffInstrument: boolean): GraphicalStaffEntry {
  1561. if (this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[horizontalIndex].StaffEntries[verticalIndex] !== undefined) {
  1562. return this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[horizontalIndex].StaffEntries[verticalIndex];
  1563. }
  1564. for (let i: number = horizontalIndex - 1; i >= 0; i--) {
  1565. if (this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].StaffEntries[verticalIndex] !== undefined) {
  1566. return this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].StaffEntries[verticalIndex];
  1567. }
  1568. }
  1569. return undefined;
  1570. }
  1571. private getFirstRightNotNullStaffEntryFromContainer(horizontalIndex: number, verticalIndex: number, multiStaffInstrument: boolean): GraphicalStaffEntry {
  1572. if (this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[horizontalIndex].StaffEntries[verticalIndex] !== undefined) {
  1573. return this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[horizontalIndex].StaffEntries[verticalIndex];
  1574. }
  1575. for (let i: number = horizontalIndex + 1; i < this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers.length; i++) {
  1576. if (this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].StaffEntries[verticalIndex] !== undefined) {
  1577. return this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].StaffEntries[verticalIndex];
  1578. }
  1579. }
  1580. return undefined;
  1581. }
  1582. private calculateWordRepetitionInstructions(): void {
  1583. for (let i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.length; i++) {
  1584. let sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
  1585. for (let idx: number = 0, len: number = sourceMeasure.FirstRepetitionInstructions.length; idx < len; ++idx) {
  1586. let instruction: RepetitionInstruction = sourceMeasure.FirstRepetitionInstructions[idx];
  1587. this.calculateWordRepetitionInstruction(instruction, i);
  1588. }
  1589. for (let idx: number = 0, len: number = sourceMeasure.LastRepetitionInstructions.length; idx < len; ++idx) {
  1590. let instruction: RepetitionInstruction = sourceMeasure.LastRepetitionInstructions[idx];
  1591. this.calculateWordRepetitionInstruction(instruction, i);
  1592. }
  1593. }
  1594. }
  1595. private calculateRepetitionEndings(): void {
  1596. let musicsheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
  1597. for (let idx: number = 0, len: number = musicsheet.Repetitions.length; idx < len; ++idx) {
  1598. let partListEntry: Repetition = musicsheet.Repetitions[idx];
  1599. this.calcGraphicalRepetitionEndingsRecursively(partListEntry);
  1600. }
  1601. }
  1602. private calculateTempoExpressions(): void {
  1603. for (let i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.length; i++) {
  1604. let sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
  1605. for (let j: number = 0; j < sourceMeasure.TempoExpressions.length; j++) {
  1606. this.calculateTempoExpressionsForSingleMultiTempoExpression(sourceMeasure, sourceMeasure.TempoExpressions[j], i);
  1607. }
  1608. }
  1609. }
  1610. private calculateMoodAndUnknownExpressions(): void {
  1611. for (let i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.length; i++) {
  1612. let sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
  1613. for (let j: number = 0; j < sourceMeasure.StaffLinkedExpressions.length; j++) {
  1614. if (this.graphicalMusicSheet.MeasureList[i][j].ParentStaff.ParentInstrument.Visible) {
  1615. for (let k: number = 0; k < sourceMeasure.StaffLinkedExpressions[j].length; k++) {
  1616. if ((sourceMeasure.StaffLinkedExpressions[j][k].MoodList.length > 0) ||
  1617. (sourceMeasure.StaffLinkedExpressions[j][k].UnknownList.length > 0)) {
  1618. this.calculateMoodAndUnknownExpression(sourceMeasure.StaffLinkedExpressions[j][k], i, j);
  1619. }
  1620. }
  1621. }
  1622. }
  1623. }
  1624. }
  1625. }