import type { Display } from "./Display" ; /**
 *  Rasterizer 負責處理圖像的點陣化轉換。
  export class Rasterizer { private static readonly _DEBOUNCE = 1000 ; private static readonly _GC_TIME = 5000 ; private readonly _display : Display ; private readonly _img : HTMLImageElement ; constructor ( display , img ) { this . _display = display ; this . _img = img ; window . addEventListener ( "beforeprint" , this . $beforePrint . bind ( this ) ) ; window . addEventListener ( "afterprint" , this . _afterPrint . bind ( this ) ) ; } public $createPngBlob ( ) { let canvas = document . createElement ( "canvas" ) ; let ctx = canvas . getContext ( "2d" ) ! ; let img = this . _img ; return new Promise < Blob > ( resolve => { img . addEventListener ( "load" , ( ) => { canvas . width = img . clientWidth ; canvas . height = img . clientHeight ; ctx . fillStyle = 'white' ; ctx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ; ctx . drawImage ( img , 0 , 0 , img . naturalWidth , img . naturalHeight , 0 , 0 , img . clientWidth , img . clientHeight ) ; this . _printing = false ; canvas . toBlob ( blob => resolve ( blob ! ) ) ; } , { once : true } ) ; this . $beforePrint ( ) ; } ) ; } /** 用來偵測列印事件連續觸發；這個在手機上會發生 */ private _printing : boolean = false ; /** 手機連續觸發的情況中 afterPrint 也會被連續觸發，用這個偵測出最後一次 */ private _debounce : number ; public $beforePrint ( ) { clearTimeout ( this . _debounce ) ; if ( ! this . _printing && document . visibilityState == 'visible' ) { let old = this . _img . src ; setTimeout ( ( ) => URL . revokeObjectURL ( old ) , Rasterizer . _GC_TIME ) ; this . _img . src = URL . createObjectURL ( this . _display . $createSvgBlob ( ) ) ; this . _printing = true ; } } public _afterPrint ( ) { this . _debounce = window . setTimeout ( ( ) => { this . _printing = false ; this . _debounce = NaN ; } , Rasterizer . _DEBOUNCE ) ; } public async $copyPNG ( ) { const blob = await this . $createPngBlob ( ) ; return navigator . clipboard . write ( [ new ClipboardItem ( { 'image/png' : blob } ) , ] ) ; } }