From b8732a25a3a9b3560454ded301bdd2f92009fea5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 2 Sep 2017 10:37:51 -0700 Subject: [PATCH] Support Safari Safari lacks support for window.createImageBitmap, fallback to HTMLCanvasElement in thi case. --- src/renderer/BaseRenderLayer.ts | 15 ++++++++++++--- src/renderer/CharAtlas.ts | 18 +++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 2650af3ac..20768c8ad 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -14,7 +14,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { // TODO: This should be shared between terminals, but not for static as some // terminals may have different styles - private _charAtlas: ImageBitmap; + private _charAtlas: HTMLCanvasElement | ImageBitmap; constructor( container: HTMLElement, @@ -39,8 +39,17 @@ export abstract class BaseRenderLayer implements IRenderLayer { public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void {} public onThemeChanged(terminal: ITerminal, colorSet: IColorSet): void { + this._refreshCharAtlas(terminal, colorSet); + } + + private _refreshCharAtlas(terminal: ITerminal, colorSet: IColorSet): void { this._charAtlas = null; - acquireCharAtlas(terminal, this.colors).then(bitmap => this._charAtlas = bitmap); + const result = acquireCharAtlas(terminal, this.colors); + if (result instanceof HTMLCanvasElement) { + this._charAtlas = result; + } else { + result.then(bitmap => this._charAtlas = bitmap); + } } public resize(terminal: ITerminal, canvasWidth: number, canvasHeight: number, charSizeChanged: boolean): void { @@ -52,7 +61,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { this._canvas.style.height = `${canvasHeight}px`; if (charSizeChanged) { - acquireCharAtlas(terminal, this.colors).then(bitmap => this._charAtlas = bitmap); + this._refreshCharAtlas(terminal, this.colors); } } diff --git a/src/renderer/CharAtlas.ts b/src/renderer/CharAtlas.ts index a9fe8bd30..d25520d11 100644 --- a/src/renderer/CharAtlas.ts +++ b/src/renderer/CharAtlas.ts @@ -12,14 +12,14 @@ interface ICharAtlasConfig { } interface ICharAtlasCacheEntry { - bitmap: Promise; + bitmap: HTMLCanvasElement | Promise; config: ICharAtlasConfig; ownedBy: ITerminal[]; } let charAtlasCache: ICharAtlasCacheEntry[] = []; -export function acquireCharAtlas(terminal: ITerminal, colors: IColorSet): Promise { +export function acquireCharAtlas(terminal: ITerminal, colors: IColorSet): HTMLCanvasElement | Promise { const scaledCharWidth = terminal.charMeasure.width * window.devicePixelRatio; const scaledCharHeight = terminal.charMeasure.height * window.devicePixelRatio; const newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors); @@ -101,7 +101,7 @@ class CharAtlasGenerator { this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); } - public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, foreground: string, ansiColors: string[]): Promise { + public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, foreground: string, ansiColors: string[]): HTMLCanvasElement | Promise { const cellWidth = scaledCharWidth + CHAR_ATLAS_CELL_SPACING; const cellHeight = scaledCharHeight + CHAR_ATLAS_CELL_SPACING; this._canvas.width = 255 * cellWidth; @@ -133,6 +133,18 @@ class CharAtlasGenerator { this._ctx.restore(); const charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height); + + // Support is patchy for createImageBitmap at the moment, pass a canvas back + // if support is lacking as drawImage works there too. + if (!('createImageBitmap' in window)) { + // Regenerate canvas and context as they are now owned by the char atlas + const result = this._canvas; + this._canvas = document.createElement('canvas'); + this._ctx = this._canvas.getContext('2d'); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + return result; + } + const promise = window.createImageBitmap(charAtlasImageData); // Clear the rect while the promise is in progress this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);