VexFlowMusicSheetCalculator.ts 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import {MusicSheetCalculator} from "../MusicSheetCalculator";
  2. import {VexFlowGraphicalSymbolFactory} from "./VexFlowGraphicalSymbolFactory";
  3. import {GraphicalMusicSheet} from "../GraphicalMusicSheet";
  4. import {StaffMeasure} from "../StaffMeasure";
  5. import {MusicSystemBuilder} from "../MusicSystemBuilder";
  6. import {StaffLine} from "../StaffLine";
  7. import {VoiceEntry} from "../../VoiceData/VoiceEntry";
  8. import {MusicSystem} from "../MusicSystem";
  9. import {GraphicalNote} from "../GraphicalNote";
  10. import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
  11. import {GraphicalMusicPage} from "../GraphicalMusicPage";
  12. import {GraphicalTie} from "../GraphicalTie";
  13. import {Tie} from "../../VoiceData/Tie";
  14. import {SourceMeasure} from "../../VoiceData/SourceMeasure";
  15. import {MultiExpression} from "../../VoiceData/Expressions/multiExpression";
  16. import {RepetitionInstruction} from "../../VoiceData/Instructions/RepetitionInstruction";
  17. import {Beam} from "../../VoiceData/Beam";
  18. import {ClefInstruction} from "../../VoiceData/Instructions/ClefInstruction";
  19. import {OctaveEnum} from "../../VoiceData/Expressions/ContinuousExpressions/octaveShift";
  20. import {Fraction} from "../../../Common/DataObjects/fraction";
  21. import {LyricsEntry} from "../../VoiceData/Lyrics/LyricsEntry";
  22. import {LyricWord} from "../../VoiceData/Lyrics/LyricsWord";
  23. import {OrnamentContainer} from "../../VoiceData/OrnamentContainer";
  24. import {ArticulationEnum} from "../../VoiceData/VoiceEntry";
  25. import {Tuplet} from "../../VoiceData/Tuplet";
  26. import Dictionary from "typescript-collections/dist/lib/Dictionary";
  27. import {VexFlowMeasure} from "./VexFlowMeasure";
  28. import {VexFlowTextMeasurer} from "./VexFlowTextMeasurer";
  29. //import {VexFlowMeasure} from "./VexFlowMeasure";
  30. export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
  31. constructor() {
  32. super(new VexFlowGraphicalSymbolFactory());
  33. MusicSheetCalculator.TextMeasurer = new VexFlowTextMeasurer();
  34. }
  35. /**
  36. * The main method for the Calculator.
  37. */
  38. public calculate(): void {
  39. this.clearSystemsAndMeasures();
  40. this.clearRecreatedObjects();
  41. this.calculateXLayout(this.graphicalMusicSheet, this.maxInstrNameLabelLength());
  42. this.graphicalMusicSheet.MusicPages.length = 0;
  43. this.calculateMusicSystems();
  44. this.graphicalMusicSheet.MusicPages[0].PositionAndShape.BorderMarginBottom += 9;
  45. GraphicalMusicSheet.transformRelativeToAbsolutePosition(this.graphicalMusicSheet);
  46. }
  47. /**
  48. * Calculates the x layout of the staff entries within the staff measures belonging to one source measure.
  49. * All staff entries are x-aligned throughout all vertically aligned staff measures.
  50. * This method is called within calculateXLayout.
  51. * The staff entries are aligned with minimum needed x distances.
  52. * The MinimumStaffEntriesWidth of every measure will be set - needed for system building.
  53. * @param measures
  54. * @returns the minimum required x width of the source measure (=list of staff measures)
  55. */
  56. protected calculateMeasureXLayout(measures: StaffMeasure[]): number {
  57. // layout the measures in x.
  58. // return the minimum required x width of this vertically aligned measure set:
  59. let allVoices: Vex.Flow.Voice[] = [];
  60. let formatter: Vex.Flow.Formatter = new Vex.Flow.Formatter();
  61. for (let measure of measures) {
  62. let mvoices: { [voiceID: number]: Vex.Flow.Voice; } = (measure as VexFlowMeasure).voices;
  63. let voices: Vex.Flow.Voice[] = [];
  64. for (let voiceID in mvoices) {
  65. if (mvoices.hasOwnProperty(voiceID)) {
  66. voices.push(mvoices[voiceID]);
  67. allVoices.push(mvoices[voiceID]);
  68. }
  69. }
  70. formatter.joinVoices(voices);
  71. }
  72. let width: number = formatter.preCalculateMinTotalWidth(allVoices);
  73. for (let measure of measures) {
  74. measure.minimumStaffEntriesWidth = width;
  75. }
  76. return width;
  77. }
  78. /**
  79. * Creates the music systems and calculates their layout.
  80. */
  81. protected calculateMusicSystems(): void {
  82. let measureList: StaffMeasure[][] = [];
  83. for (let mlist of this.graphicalMusicSheet.MeasureList) {
  84. let list: StaffMeasure[] = [];
  85. for (let m of mlist) {
  86. if (m.isVisible()) {
  87. list.push(m);
  88. }
  89. }
  90. measureList.push(list);
  91. }
  92. let numberOfStaffLines: number = 0;
  93. for (let idx: number = 0, len: number = measureList.length; idx < len; ++idx) {
  94. let gmlist: StaffMeasure[] = measureList[idx];
  95. numberOfStaffLines = Math.max(gmlist.length, numberOfStaffLines);
  96. }
  97. if (numberOfStaffLines === 0) { return; }
  98. let musicSystemBuilder: MusicSystemBuilder = new MusicSystemBuilder();
  99. musicSystemBuilder.initialize(this.graphicalMusicSheet, measureList, numberOfStaffLines, this.symbolFactory);
  100. musicSystemBuilder.buildMusicSystems();
  101. this.checkMeasuresForWholeRestNotes();
  102. }
  103. protected updateStaffLineBorders(staffLine: StaffLine): void {
  104. return;
  105. }
  106. protected calculateMeasureNumberPlacement(musicSystem: MusicSystem): void {
  107. return;
  108. }
  109. /**
  110. * Can be used to calculate stem directions, helper(ledger) lines, and overlapping note x-displacement.
  111. * Is Excecuted per voice entry of a staff entry.
  112. * After that layoutStaffEntry is called.
  113. * @param voiceEntry
  114. * @param graphicalNotes
  115. * @param graphicalStaffEntry
  116. * @param hasPitchedNote
  117. * @param isGraceStaffEntry
  118. */
  119. protected layoutVoiceEntry(voiceEntry: VoiceEntry, graphicalNotes: GraphicalNote[], graphicalStaffEntry: GraphicalStaffEntry,
  120. hasPitchedNote: boolean, isGraceStaffEntry: boolean): void {
  121. return;
  122. }
  123. /**
  124. * Do all layout calculations that have to be done per staff entry, like dots, ornaments, arpeggios....
  125. * This method is called after the voice entries are handled by layoutVoiceEntry().
  126. * @param graphicalStaffEntry
  127. */
  128. protected layoutStaffEntry(graphicalStaffEntry: GraphicalStaffEntry): void {
  129. return;
  130. }
  131. /**
  132. * calculates the y positions of the staff lines within a system and
  133. * furthermore the y positions of the systems themselves.
  134. */
  135. protected calculateSystemYLayout(): void {
  136. for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
  137. let graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
  138. if (!this.leadSheet) {
  139. for (let idx2: number = 0, len2: number = graphicalMusicPage.MusicSystems.length; idx2 < len2; ++idx2) {
  140. //let musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
  141. // calculate y positions of stafflines within system
  142. // ...
  143. }
  144. }
  145. // set y positions of systems using the previous system and a fixed distance.
  146. // ...
  147. }
  148. }
  149. /**
  150. * Is called at the begin of the method for creating the vertically aligned staff measures belonging to one source measure.
  151. */
  152. protected initStaffMeasuresCreation(): void {
  153. return;
  154. }
  155. protected handleTie(tie: Tie, startGraphicalStaffEntry: GraphicalStaffEntry, staffIndex: number, measureIndex: number): void {
  156. return;
  157. }
  158. protected layoutGraphicalTie(tie: GraphicalTie, tieIsAtSystemBreak: boolean): void {
  159. return;
  160. }
  161. protected calculateSingleStaffLineLyricsPosition(staffLine: StaffLine, lyricVersesNumber: number[]): void {
  162. return;
  163. }
  164. protected calculateSingleOctaveShift(sourceMeasure: SourceMeasure, multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
  165. return;
  166. }
  167. protected calculateWordRepetitionInstruction(repetitionInstruction: RepetitionInstruction, measureIndex: number): void {
  168. return;
  169. }
  170. protected calculateMoodAndUnknownExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
  171. return;
  172. }
  173. protected createGraphicalTieNote(beams: Beam[], activeClef: ClefInstruction,
  174. octaveShiftValue: OctaveEnum, graphicalStaffEntry: GraphicalStaffEntry, duration: Fraction, numberOfDots: number,
  175. openTie: Tie, isLastTieNote: boolean): void {
  176. return;
  177. }
  178. /**
  179. * Is called if a note is part of a beam.
  180. * @param graphicalNote
  181. * @param beam
  182. * @param openBeams a list of all currently open beams
  183. */
  184. protected handleBeam(graphicalNote: GraphicalNote, beam: Beam, openBeams: Beam[]): void {
  185. return;
  186. }
  187. protected handleVoiceEntryLyrics(lyricsEntries: Dictionary<number, LyricsEntry>, voiceEntry: VoiceEntry,
  188. graphicalStaffEntry: GraphicalStaffEntry, openLyricWords: LyricWord[]): void {
  189. return;
  190. }
  191. protected handleVoiceEntryOrnaments(ornamentContainer: OrnamentContainer, voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry): void {
  192. return;
  193. }
  194. protected handleVoiceEntryArticulations(articulations: ArticulationEnum[], voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry): void {
  195. return;
  196. }
  197. /**
  198. * Is called if a note is part of a tuplet.
  199. * @param graphicalNote
  200. * @param tuplet
  201. * @param openTuplets a list of all currently open tuplets
  202. */
  203. protected handleTuplet(graphicalNote: GraphicalNote, tuplet: Tuplet, openTuplets: Tuplet[]): void {
  204. return;
  205. }
  206. }