VexFlowGraphicalSymbolFactory.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import Vex from "vexflow";
  2. import {IGraphicalSymbolFactory} from "../../Interfaces/IGraphicalSymbolFactory";
  3. import {MusicSystem} from "../MusicSystem";
  4. import {VexFlowMusicSystem} from "./VexFlowMusicSystem";
  5. import {Staff} from "../../VoiceData/Staff";
  6. import {StaffLine} from "../StaffLine";
  7. import {SourceMeasure} from "../../VoiceData/SourceMeasure";
  8. import {GraphicalMeasure} from "../GraphicalMeasure";
  9. import {VexFlowMeasure} from "./VexFlowMeasure";
  10. import {SourceStaffEntry} from "../../VoiceData/SourceStaffEntry";
  11. import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
  12. import {VexFlowStaffEntry} from "./VexFlowStaffEntry";
  13. import {Note} from "../../VoiceData/Note";
  14. import {ClefInstruction} from "../../VoiceData/Instructions/ClefInstruction";
  15. import {OctaveEnum} from "../../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
  16. import {GraphicalNote} from "../GraphicalNote";
  17. import {Pitch} from "../../../Common/DataObjects/Pitch";
  18. import {VexFlowGraphicalNote} from "./VexFlowGraphicalNote";
  19. import {Fraction} from "../../../Common/DataObjects/Fraction";
  20. import {GraphicalChordSymbolContainer} from "../GraphicalChordSymbolContainer";
  21. import {GraphicalLabel} from "../GraphicalLabel";
  22. import {EngravingRules} from "../EngravingRules";
  23. import { TechnicalInstruction } from "../../VoiceData/Instructions/TechnicalInstruction";
  24. import { GraphicalVoiceEntry } from "../GraphicalVoiceEntry";
  25. import { VoiceEntry } from "../../VoiceData/VoiceEntry";
  26. import { VexFlowVoiceEntry } from "./VexFlowVoiceEntry";
  27. import { VexFlowConverter } from "./VexFlowConverter";
  28. import { VexFlowTabMeasure } from "./VexFlowTabMeasure";
  29. import { VexFlowStaffLine } from "./VexFlowStaffLine";
  30. import { KeyInstruction } from "../../VoiceData/Instructions/KeyInstruction";
  31. import { VexFlowMultiRestMeasure } from "./VexFlowMultiRestMeasure";
  32. export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
  33. /**
  34. * Create a new music system for the given page.
  35. * Currently only one vertically endless page exists where all systems are put to.
  36. * @param page
  37. * @param systemIndex
  38. * @returns {VexFlowMusicSystem}
  39. */
  40. public createMusicSystem(systemIndex: number, rules: EngravingRules): MusicSystem {
  41. return new VexFlowMusicSystem(systemIndex, rules);
  42. }
  43. /**
  44. * Create a staffline object containing all staff measures belonging to a given system and staff.
  45. * @param parentSystem
  46. * @param parentStaff
  47. * @returns {VexFlowStaffLine}
  48. */
  49. public createStaffLine(parentSystem: MusicSystem, parentStaff: Staff): StaffLine {
  50. return new VexFlowStaffLine(parentSystem, parentStaff);
  51. }
  52. /**
  53. * Construct an empty graphicalMeasure from the given source measure and staff.
  54. * @param sourceMeasure
  55. * @param staff
  56. * @returns {VexFlowMeasure}
  57. */
  58. public createGraphicalMeasure(sourceMeasure: SourceMeasure, staff: Staff, isTabMeasure: boolean = false): GraphicalMeasure {
  59. return new VexFlowMeasure(staff, sourceMeasure, undefined);
  60. }
  61. /**
  62. * Construct a MultiRestMeasure from the given source measure and staff.
  63. * @param sourceMeasure
  64. * @param staff
  65. * @returns {VexFlowMultiRestMeasure}
  66. */
  67. public createMultiRestMeasure(sourceMeasure: SourceMeasure, staff: Staff, staffLine?: StaffLine): GraphicalMeasure {
  68. return new VexFlowMultiRestMeasure(staff, sourceMeasure, staffLine);
  69. }
  70. /**
  71. * Construct an empty Tab staffMeasure from the given source measure and staff.
  72. * @param sourceMeasure
  73. * @param staff
  74. * @returns {VexFlowTabMeasure}
  75. */
  76. public createTabStaffMeasure(sourceMeasure: SourceMeasure, staff: Staff): GraphicalMeasure {
  77. return new VexFlowTabMeasure(staff, sourceMeasure);
  78. }
  79. /**
  80. * Create empty measure, which will be used to show key, rhythm changes at the end of the system.
  81. * @param staffLine
  82. * @returns {VexFlowMeasure}
  83. */
  84. public createExtraGraphicalMeasure(staffLine: StaffLine): GraphicalMeasure {
  85. return new VexFlowMeasure(staffLine.ParentStaff, undefined, staffLine);
  86. }
  87. /**
  88. * Create a staffEntry in the given measure for a given sourceStaffEntry.
  89. * @param sourceStaffEntry
  90. * @param measure
  91. * @returns {VexFlowStaffEntry}
  92. */
  93. public createStaffEntry(sourceStaffEntry: SourceStaffEntry, measure: GraphicalMeasure): GraphicalStaffEntry {
  94. return new VexFlowStaffEntry(<VexFlowMeasure>measure, sourceStaffEntry, undefined);
  95. }
  96. public createVoiceEntry(parentVoiceEntry: VoiceEntry, parentStaffEntry: GraphicalStaffEntry): GraphicalVoiceEntry {
  97. return new VexFlowVoiceEntry(parentVoiceEntry, parentStaffEntry);
  98. }
  99. /**
  100. * Create a Graphical Note for given note and clef and as part of graphicalStaffEntry.
  101. * @param note
  102. * @param numberOfDots The number of dots the note has to increase its musical duration.
  103. * @param graphicalStaffEntry
  104. * @param activeClef The currently active clef, needed for positioning the note vertically
  105. * @param octaveShift The currently active octave transposition enum, needed for positioning the note vertically
  106. * @returns {GraphicalNote}
  107. */
  108. public createNote(note: Note, graphicalVoiceEntry: GraphicalVoiceEntry, activeClef: ClefInstruction,
  109. octaveShift: OctaveEnum = OctaveEnum.NONE, rules: EngravingRules,
  110. graphicalNoteLength: Fraction = undefined): GraphicalNote {
  111. return new VexFlowGraphicalNote(note, graphicalVoiceEntry, activeClef, octaveShift, rules, graphicalNoteLength);
  112. }
  113. /**
  114. * Create a Graphical Grace Note (smaller head, stem...) for given note and clef and as part of graphicalStaffEntry.
  115. * @param note
  116. * @param numberOfDots
  117. * @param graphicalVoiceEntry
  118. * @param activeClef
  119. * @param octaveShift
  120. * @returns {GraphicalNote}
  121. */
  122. public createGraceNote(note: Note, graphicalVoiceEntry: GraphicalVoiceEntry,
  123. activeClef: ClefInstruction, rules: EngravingRules,
  124. octaveShift: OctaveEnum = OctaveEnum.NONE): GraphicalNote {
  125. return new VexFlowGraphicalNote(note, graphicalVoiceEntry, activeClef, octaveShift, rules);
  126. }
  127. /**
  128. * Sets a pitch which will be used for rendering the given graphical note (not changing the original pitch of the note!!!).
  129. * Will be only called if the displayed accidental is different from the original (e.g. a C# with C# as key instruction)
  130. * @param graphicalNote
  131. * @param pitch The pitch which will be rendered.
  132. */
  133. public addGraphicalAccidental(graphicalNote: GraphicalNote, pitch: Pitch): void {
  134. const note: VexFlowGraphicalNote = (graphicalNote as VexFlowGraphicalNote);
  135. // accidental is added in setPitch
  136. note.setAccidental(pitch);
  137. }
  138. /**
  139. * Adds a Fermata symbol at the last note of the given tied Note.
  140. * The last graphical note of this tied note is located at the given graphicalStaffEntry.
  141. * A Fermata has to be located at the last tied note.
  142. * @param tiedNote
  143. * @param graphicalStaffEntry
  144. */
  145. public addFermataAtTiedEndNote(tiedNote: Note, graphicalStaffEntry: GraphicalStaffEntry): void {
  146. return;
  147. }
  148. /**
  149. * Adds a clef change within a measure before the given staff entry.
  150. * @param graphicalStaffEntry
  151. * @param clefInstruction
  152. */
  153. public createInStaffClef(graphicalStaffEntry: GraphicalStaffEntry, clefInstruction: ClefInstruction): void {
  154. const se: VexFlowStaffEntry = graphicalStaffEntry as VexFlowStaffEntry;
  155. const vfClefParams: { type: string, size: string, annotation: string } = VexFlowConverter.Clef(clefInstruction, "small");
  156. se.vfClefBefore = new Vex.Flow.ClefNote(vfClefParams.type, vfClefParams.size, vfClefParams.annotation);
  157. return;
  158. }
  159. /**
  160. * Adds a chord symbol at the given staff entry
  161. * @param sourceStaffEntry
  162. * @param graphicalStaffEntry
  163. * @param transposeHalftones
  164. */
  165. public createChordSymbols( sourceStaffEntry: SourceStaffEntry,
  166. graphicalStaffEntry: GraphicalStaffEntry,
  167. keyInstruction: KeyInstruction,
  168. transposeHalftones: number): void {
  169. const rules: EngravingRules = graphicalStaffEntry.parentMeasure.parentSourceMeasure.Rules;
  170. let xShift: number = 0;
  171. const chordSymbolSpacing: number = rules.ChordSymbolXSpacing;
  172. for (const chordSymbolContainer of sourceStaffEntry.ChordContainers) {
  173. const graphicalChordSymbolContainer: GraphicalChordSymbolContainer =
  174. new GraphicalChordSymbolContainer(chordSymbolContainer,
  175. graphicalStaffEntry.PositionAndShape,
  176. rules.ChordSymbolTextHeight,
  177. keyInstruction,
  178. transposeHalftones,
  179. graphicalStaffEntry.parentMeasure.parentSourceMeasure.Rules // TODO undefined sometimes
  180. );
  181. const graphicalLabel: GraphicalLabel = graphicalChordSymbolContainer.GraphicalLabel;
  182. graphicalLabel.PositionAndShape.RelativePosition.y -= rules.ChordSymbolYOffset;
  183. graphicalLabel.PositionAndShape.RelativePosition.x += xShift;
  184. // TODO check for available space until next staffEntry or chord symbol (x direction)
  185. graphicalLabel.setLabelPositionAndShapeBorders();
  186. graphicalChordSymbolContainer.PositionAndShape.calculateBoundingBox();
  187. graphicalStaffEntry.graphicalChordContainers.push(graphicalChordSymbolContainer);
  188. xShift += graphicalLabel.PositionAndShape.Size.width + chordSymbolSpacing;
  189. }
  190. }
  191. /**
  192. * Adds a technical instruction at the given staff entry.
  193. * @param technicalInstruction
  194. * @param graphicalStaffEntry
  195. */
  196. public createGraphicalTechnicalInstruction(technicalInstruction: TechnicalInstruction, graphicalStaffEntry: GraphicalStaffEntry): void {
  197. return;
  198. }
  199. }