import Vex from "vexflow" ; import { VexFlowBackend } from "./VexFlowBackend" ; import { FontStyles } from "../../../Common/Enums/FontStyles" ; import { Fonts } from "../../../Common/Enums/Fonts" ; import { RectangleF2D } from "../../../Common/DataObjects/RectangleF2D" ; import { PointF2D } from "../../../Common/DataObjects/PointF2D" ; import { VexFlowConverter } from "./VexFlowConverter" ; import { BackendType } from "../../../OpenSheetMusicDisplay/OSMDOptions" ; import { EngravingRules } from "../EngravingRules" ; import { GraphicalMusicPage } from "../GraphicalMusicPage" ; export class CanvasVexFlowBackend extends VexFlowBackend { private zoom : number ; constructor ( rules ) { super ( ) ; this . rules = rules ; } public getVexflowBackendType ( ) { return Vex . Flow . Renderer . Backends . CANVAS ; } public getOSMDBackendType ( ) { return BackendType . Canvas ; } public getCanvasSize ( ) { return document . getElementById ( "osmdCanvasPage" + this . graphicalMusicPage . PageNumber ) ?. offsetHeight ; } public initialize ( container , zoom ) { this . zoom = zoom ; this . canvas = document . createElement ( "canvas" ) ; if ( ! this . graphicalMusicPage ) { this . graphicalMusicPage = new GraphicalMusicPage ( undefined ) ; this . graphicalMusicPage . PageNumber = 1 ; } this . canvas . id = "osmdCanvasVexFlowBackendCanvas" + this . graphicalMusicPage . PageNumber ; this . inner = document . createElement ( "div" ) ; this . inner . id = "osmdCanvasPage" + this . graphicalMusicPage . PageNumber ; this . inner . style . position = "relative" ; this . canvas . style . zIndex = "0" ; this . inner . appendChild ( this . canvas ) ; container . appendChild ( this . inner ) ; this . renderer = new Vex . Flow . Renderer ( this . canvas , this . getVexflowBackendType ( ) ) ; this . ctx = < Vex . Flow . CanvasContext > this . renderer . getContext ( ) ; } param width param height public initializeHeadless ( width = 300 , height = 300 ) { if ( ! this . graphicalMusicPage ) { this . graphicalMusicPage = new GraphicalMusicPage ( undefined ) ; this . graphicalMusicPage . PageNumber = 1 ; } this . canvas = document . createElement ( "canvas" ) ; ( this . canvas as any ) . width = width ; ( this . canvas as any ) . height = height ; this . renderer = new Vex . Flow . Renderer ( this . canvas , this . getVexflowBackendType ( ) ) ; this . ctx = < Vex . Flow . CanvasContext > this . renderer . getContext ( ) ; } public getContext ( ) { return this . ctx ; } public clear ( ) { ( < any > this . ctx ) . clearRect ( 0 , 0 , ( < any > this . canvas ) . width , ( < any > this . canvas ) . height ) ; if ( this . rules . PageBackgroundColor ) { this . ctx . save ( ) ; this . ctx . setFillStyle ( this . rules . PageBackgroundColor ) ; this . zoom = 1 ; this . ctx . fillRect ( 0 , 0 , ( this . canvas as any ) . width / this . zoom , ( this . canvas as any ) . height / this . zoom ) ; this . ctx . restore ( ) ; } } public scale ( k ) { this . ctx . scale ( k , k ) ; } public translate ( x , y ) { this . CanvasRenderingCtx . translate ( x , y ) ; } public renderText ( fontHeight , fontStyle , font , text , heightInPixel , screenPosition , color = undefined , fontFamily = undefined ) { const old = this . CanvasRenderingCtx . font ; this . CanvasRenderingCtx . save ( ) ; this . CanvasRenderingCtx . font = VexFlowConverter . font ( fontHeight , fontStyle , font , this . rules , fontFamily ) ; this . CanvasRenderingCtx . fillStyle = color ; this . CanvasRenderingCtx . strokeStyle = color ; this . CanvasRenderingCtx . fillText ( text , screenPosition . x , screenPosition . y + heightInPixel ) ; this . CanvasRenderingCtx . restore ( ) ; this . CanvasRenderingCtx . font = old ; return undefined ; } public renderRectangle ( rectangle , styleId , colorHex , alpha = 1 ) { const old = this . CanvasRenderingCtx . fillStyle ; if ( colorHex ) { this . CanvasRenderingCtx . fillStyle = colorHex ; } else { this . CanvasRenderingCtx . fillStyle = VexFlowConverter . style ( styleId ) ; } this . CanvasRenderingCtx . globalAlpha = alpha ; this . ctx . fillRect ( rectangle . x , rectangle . y , rectangle . width , rectangle . height ) ; this . CanvasRenderingCtx . fillStyle = old ; this . CanvasRenderingCtx . globalAlpha = 1 ; return undefined ; } public renderLine ( start , stop , color = "#FF0000FF" , lineWidth = 2 ) { const oldStyle = this . CanvasRenderingCtx . strokeStyle ; this . CanvasRenderingCtx . strokeStyle = color ; this . CanvasRenderingCtx . beginPath ( ) ; this . CanvasRenderingCtx . moveTo ( start . x , start . y ) ; this . CanvasRenderingCtx . lineTo ( stop . x , stop . y ) ; this . CanvasRenderingCtx . stroke ( ) ; this . CanvasRenderingCtx . strokeStyle = oldStyle ; return undefined ; } public renderCurve ( points ) { this . ctx . beginPath ( ) ; this . ctx . moveTo ( points [ 0 ] . x , points [ 0 ] . y ) ; this . ctx . bezierCurveTo ( points [ 1 ] . x , points [ 1 ] . y , points [ 2 ] . x , points [ 2 ] . y , points [ 3 ] . x , points [ 3 ] . y ) ; this . ctx . lineTo ( points [ 7 ] . x , points [ 7 ] . y ) ; this . ctx . bezierCurveTo ( points [ 6 ] . x , points [ 6 ] . y , points [ 5 ] . x , points [ 5 ] . y , points [ 4 ] . x , points [ 4 ] . y ) ; this . ctx . lineTo ( points [ 0 ] . x , points [ 0 ] . y ) ; this . ctx . closePath ( ) ; this . ctx . fill ( ) ; return undefined ; } private ctx : Vex . Flow . CanvasContext ; public get CanvasRenderingCtx ( ) : CanvasRenderingContext2D { return < CanvasRenderingContext2D > ( this . ctx as any ) . vexFlowCanvasContext ; } }