import { TypeContext , TypeBoardSizeOptions } from '@idraw/types' ; type Options = { width : number ; height : number ; contextWidth : number ; contextHeight : number ; devicePixelRatio : number ; } ; type Transform = { scale ? : number ; scrollX ? : number ; scrollY ? : number ; } ; type PrivateTransform = { scale : number ; scrollX : number ; scrollY : number ; } ; class Context implements TypeContext { private _opts : Options ; private _ctx : CanvasRenderingContext2D ; private _transform : PrivateTransform ; constructor ( ctx , opts ) { this . _opts = opts ; this . _ctx = ctx ; this . _transform = { scale : 1 , scrollX : 0 , scrollY : 0 , } ; } getContext ( ) { return this . _ctx ; } resetSize ( opts ) { this . _opts = { ... this . _opts , ... opts } ; } calcDeviceNum ( num ) { return num * this . _opts . devicePixelRatio ; } calcScreenNum ( num ) { return num / this . _opts . devicePixelRatio ; } getSize ( ) { return { width : this . _opts . width , height : this . _opts . height , contextWidth : this . _opts . contextWidth , contextHeight : this . _opts . contextHeight , devicePixelRatio : this . _opts . devicePixelRatio , } ; } setTransform ( config ) { this . _transform = { ... this . _transform , ... config } ; } getTransform ( ) { return { scale : this . _transform . scale , scrollX : this . _transform . scrollX , scrollY : this . _transform . scrollY , } ; } setFillStyle ( color ) { this . _ctx . fillStyle = color ; } fill ( fillRule ? ) { return this . _ctx . fill ( fillRule || 'nonzero' ) ; } arc ( x , y , radius , startAngle , endAngle , anticlockwise ? ) { return this . _ctx . arc ( this . _doSize ( x ) , this . _doSize ( y ) , this . _doSize ( radius ) , startAngle , endAngle , anticlockwise ) ; } rect ( x , y , w , h ) { return this . _ctx . rect ( this . _doSize ( x ) , this . _doSize ( y ) , this . _doSize ( w ) , this . _doSize ( h ) ) ; } fillRect ( x , y , w , h ) { return this . _ctx . fillRect ( this . _doSize ( x ) , this . _doSize ( y ) , this . _doSize ( w ) , this . _doSize ( h ) ) ; } clearRect ( x , y , w , h ) { return this . _ctx . clearRect ( this . _doSize ( x ) , this . _doSize ( y ) , this . _doSize ( w ) , this . _doSize ( h ) ) ; } beginPath ( ) { return this . _ctx . beginPath ( ) ; } closePath ( ) { return this . _ctx . closePath ( ) ; } lineTo ( x , y ) { return this . _ctx . lineTo ( this . _doSize ( x ) , this . _doSize ( y ) ) ; } moveTo ( x , y ) { return this . _ctx . moveTo ( this . _doSize ( x ) , this . _doSize ( y ) ) ; } arcTo ( x1 , y1 , x2 , y2 , radius ) { return this . _ctx . arcTo ( this . _doSize ( x1 ) , this . _doSize ( y1 ) , this . _doSize ( x2 ) , this . _doSize ( y2 ) , this . _doSize ( radius ) ) ; } setLineWidth ( w ) { return this . _ctx . lineWidth = this . _doSize ( w ) ; } setLineDash ( nums ) { return this . _ctx . setLineDash ( nums . map ( n => this . _doSize ( n ) ) ) ; } isPointInPath ( x , y ) { return this . _ctx . isPointInPath ( this . _doX ( x ) , this . _doY ( y ) ) ; } isPointInPathWithoutScroll ( x , y ) { return this . _ctx . isPointInPath ( this . _doSize ( x ) , this . _doSize ( y ) ) ; } setStrokeStyle ( color ) { this . _ctx . strokeStyle = color ; } stroke ( ) { return this . _ctx . stroke ( ) ; } translate ( x , y ) { return this . _ctx . translate ( this . _doSize ( x ) , this . _doSize ( y ) ) ; } rotate ( angle ) { return this . _ctx . rotate ( angle ) ; } drawImage ( ... args ) { const image = args [ 0 ] ; const sx = args [ 1 ] ; const sy = args [ 2 ] ; const sw = args [ 3 ] ; const sh = args [ 4 ] ; const dx = args [ args . length - 4 ] ; const dy = args [ args . length - 3 ] ; const dw = args [ args . length - 2 ] ; const dh = args [ args . length - 1 ] ; if ( args . length === 9 ) { return this . _ctx . drawImage ( image , this . _doSize ( sx ) , this . _doSize ( sy ) , this . _doSize ( sw ) , this . _doSize ( sh ) , this . _doSize ( dx ) , this . _doSize ( dy ) , this . _doSize ( dw ) , this . _doSize ( dh ) ) ; } else { return this . _ctx . drawImage ( image , this . _doSize ( dx ) , this . _doSize ( dy ) , this . _doSize ( dw ) , this . _doSize ( dh ) ) ; } } createPattern ( image , repetition ) { return this . _ctx . createPattern ( image , repetition ) ; } measureText ( text ) { return this . _ctx . measureText ( text ) ; } setTextAlign ( align ) { this . _ctx . textAlign = align ; } fillText ( text , x , y , maxWidth ? ) { if ( maxWidth !== undefined ) { return this . _ctx . fillText ( text , this . _doSize ( x ) , this . _doSize ( y ) , this . _doSize ( maxWidth ) ) ; } else { return this . _ctx . fillText ( text , this . _doSize ( x ) , this . _doSize ( y ) ) ; } } strokeText ( text , x , y , maxWidth ? ) { if ( maxWidth !== undefined ) { return this . _ctx . strokeText ( text , this . _doSize ( x ) , this . _doSize ( y ) , this . _doSize ( maxWidth ) ) ; } else { return this . _ctx . strokeText ( text , this . _doSize ( x ) , this . _doSize ( y ) ) ; } } setFont ( opts ) { const strList = [ ] ; if ( opts . fontWeight === 'bold' ) { strList . push ( `${ opts . fontWeight }` ) ; } strList . push ( `${ this . _doSize ( opts . fontSize || 12 ) }px` ) ; strList . push ( `${ opts . fontFamily || 'sans-serif' }` ) ; this . _ctx . font = `${ strList . join ( ' ' ) }` ; } setTextBaseline ( baseline ) { this . _ctx . textBaseline = baseline ; } setGlobalAlpha ( alpha ) { this . _ctx . globalAlpha = alpha ; } save ( ) { this . _ctx . save ( ) ; } restore ( ) { this . _ctx . restore ( ) ; } scale ( ratioX , ratioY ) { this . _ctx . scale ( ratioX , ratioY ) ; } setShadowColor ( color ) { this . _ctx . shadowColor = color ; } setShadowOffsetX ( offsetX ) { this . _ctx . shadowOffsetX = this . _doSize ( offsetX ) ; } setShadowOffsetY ( offsetY ) { this . _ctx . shadowOffsetY = this . _doSize ( offsetY ) ; } setShadowBlur ( blur ) { this . _ctx . shadowBlur = this . _doSize ( blur ) ; } ellipse ( x , y , radiusX , radiusY , rotation , startAngle , endAngle , counterclockwise ? ) { this . _ctx . ellipse ( this . _doSize ( x ) , this . _doSize ( y ) , this . _doSize ( radiusX ) , this . _doSize ( radiusY ) , rotation , startAngle , endAngle , counterclockwise ) ; } private _doSize ( num ) { return this . _opts . devicePixelRatio * num ; } private _doX ( x ) { const { scale , scrollX } = this . _transform ; const _x = ( x - scrollX ) / scale ; return this . _doSize ( _x ) ; } private _doY ( y ) { const { scale , scrollY } = this . _transform ; const _y = ( y - scrollY ) / scale ; return this . _doSize ( _y ) ; } } export default Context ;