VexFlowBackend.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import Vex from "vexflow";
  2. import {FontStyles} from "../../../Common/Enums/FontStyles";
  3. import {Fonts} from "../../../Common/Enums/Fonts";
  4. import {RectangleF2D} from "../../../Common/DataObjects/RectangleF2D";
  5. import {PointF2D} from "../../../Common/DataObjects/PointF2D";
  6. import {BackendType} from "../../../OpenSheetMusicDisplay/OSMDOptions";
  7. import {GraphicalMusicPage} from "../GraphicalMusicPage";
  8. import {EngravingRules} from "../EngravingRules";
  9. export class VexFlowBackends {
  10. public static CANVAS: 0;
  11. public static RAPHAEL: 1; // this is currently unused in OSMD, and outdated in Vexflow.
  12. // maybe SVG should be 1? but this could be a breaking change if people use numbers (2) instead of names (.SVG).
  13. public static SVG: 2;
  14. public static VML: 3; // this is currently unused in OSMD, and outdated in Vexflow
  15. }
  16. export abstract class VexFlowBackend {
  17. /** The GraphicalMusicPage the backend is drawing from. Each backend only renders one GraphicalMusicPage, to which the coordinates are relative. */
  18. public graphicalMusicPage: GraphicalMusicPage;
  19. protected rules: EngravingRules;
  20. public width: number; // read-only
  21. public height: number; // read-only
  22. public abstract initialize(container: HTMLElement, zoom: number): void;
  23. public getInnerElement(): HTMLElement {
  24. return this.inner;
  25. }
  26. public getCanvas(): HTMLElement {
  27. return this.canvas;
  28. }
  29. public abstract getCanvasSize(): number;
  30. public getRenderElement(): HTMLElement {
  31. //console.log("backend type: " + this.getVexflowBackendType());
  32. let renderingHtmlElement: HTMLElement = this.canvas; // for SVGBackend
  33. if (this.getVexflowBackendType() === Vex.Flow.Renderer.Backends.CANVAS) {
  34. renderingHtmlElement = this.inner;
  35. // usage in removeFromContainer:
  36. // for SVG, this.canvas === this.inner, but for Canvas, removing this.canvas causes an error because it's not a child of container,
  37. // so we have to remove this.inner instead.
  38. }
  39. return renderingHtmlElement;
  40. }
  41. public getRenderer(): Vex.Flow.Renderer {
  42. return this.renderer;
  43. }
  44. public removeAllChildrenFromContainer(container: HTMLElement): void {
  45. while (container.children.length !== 0) {
  46. container.removeChild(container.children.item(0));
  47. }
  48. }
  49. // note: removing single children to remove all is error-prone, because sometimes a random SVG-child remains.
  50. public removeFromContainer(container: HTMLElement): void {
  51. const htmlElementToRemove: HTMLElement = this.getRenderElement();
  52. // only remove child if the container has this child, otherwise it will throw an error.
  53. for (let i: number = 0; i < container.children.length; i++) {
  54. if (container.children.item(i) === htmlElementToRemove) {
  55. container.removeChild(htmlElementToRemove);
  56. break;
  57. }
  58. }
  59. // there is unfortunately no built-in container.hasChild(child) method.
  60. }
  61. public abstract getContext(): Vex.IRenderContext;
  62. // public abstract setWidth(width: number): void;
  63. // public abstract setHeight(height: number): void;
  64. public abstract scale(k: number): void;
  65. public resize(width: number, height: number): void {
  66. this.renderer.resize(width, height);
  67. this.width = width;
  68. this.height = height;
  69. }
  70. public abstract clear(): void;
  71. public abstract translate(x: number, y: number): void;
  72. public abstract renderText(fontHeight: number, fontStyle: FontStyles, font: Fonts, text: string,
  73. heightInPixel: number, screenPosition: PointF2D,
  74. color?: string, fontFamily?: string): Node;
  75. /**
  76. * Renders a rectangle with the given style to the screen.
  77. * It is given in screen coordinates.
  78. * @param rectangle the rect in screen coordinates
  79. * @param layer is the current rendering layer. There are many layers on top of each other to which can be rendered. Not needed for now.
  80. * @param styleId the style id
  81. * @param alpha alpha value between 0 and 1
  82. */
  83. public abstract renderRectangle(rectangle: RectangleF2D, styleId: number, colorHex: string, alpha: number): Node;
  84. public abstract renderLine(start: PointF2D, stop: PointF2D, color: string, lineWidth: number): Node;
  85. public abstract renderCurve(points: PointF2D[]): void;
  86. public abstract getVexflowBackendType(): Vex.Flow.Renderer.Backends;
  87. /** The general type of backend: Canvas or SVG.
  88. * This is not used for now (only VexflowBackendType used), but it may be useful when we don't want to use a Vexflow class.
  89. */
  90. public abstract getOSMDBackendType(): BackendType;
  91. protected renderer: Vex.Flow.Renderer;
  92. protected inner: HTMLElement;
  93. protected canvas: HTMLElement;
  94. }