From 129633a66d68d5d3cd9f349539342c1e16885c5e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 30 Aug 2017 22:09:25 -0700 Subject: [PATCH] Only draw background when needed --- src/RendererCanvas.ts | 11 +++----- src/renderer/BackgroundRenderLayer.ts | 37 ++++++++++++++++++++------- src/renderer/ForegroundRenderLayer.ts | 4 +-- src/renderer/Interfaces.ts | 2 +- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/RendererCanvas.ts b/src/RendererCanvas.ts index 27832bed9..bca5f70e0 100644 --- a/src/RendererCanvas.ts +++ b/src/RendererCanvas.ts @@ -33,13 +33,10 @@ export class Renderer { } public onResize(cols: number, rows: number): void { - // TODO: This could be triggered immediately after onCharSizeChanged? - const charWidth = this._terminal.charMeasure.width; - const charHeight = this._terminal.charMeasure.height; - const width = Math.ceil(charWidth) * this._terminal.cols; - const height = Math.ceil(charHeight) * this._terminal.rows; + const width = Math.ceil(this._terminal.charMeasure.width) * this._terminal.cols; + const height = Math.ceil(this._terminal.charMeasure.height) * this._terminal.rows; for (let i = 0; i < this._renderLayers.length; i++) { - this._renderLayers[i].resize(width, height, charWidth, charHeight, false); + this._renderLayers[i].resize(this._terminal, width, height, false); } } @@ -47,7 +44,7 @@ export class Renderer { const width = Math.ceil(charWidth) * this._terminal.cols; const height = Math.ceil(charHeight) * this._terminal.rows; for (let i = 0; i < this._renderLayers.length; i++) { - this._renderLayers[i].resize(width, height, charWidth, charHeight, true); + this._renderLayers[i].resize(this._terminal, width, height, true); } } diff --git a/src/renderer/BackgroundRenderLayer.ts b/src/renderer/BackgroundRenderLayer.ts index b283ce158..c1d9eac06 100644 --- a/src/renderer/BackgroundRenderLayer.ts +++ b/src/renderer/BackgroundRenderLayer.ts @@ -6,6 +6,7 @@ import { TANGO_COLORS } from './Color'; export class BackgroundRenderLayer implements IRenderLayer { private _canvas: HTMLCanvasElement; private _ctx: CanvasRenderingContext2D; + private _currentState: number[][]; constructor(container: HTMLElement) { this._canvas = document.createElement('canvas'); @@ -13,13 +14,27 @@ export class BackgroundRenderLayer implements IRenderLayer { this._ctx = this._canvas.getContext('2d'); this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); container.appendChild(this._canvas); + + this._currentState = []; } - public resize(canvasWidth: number, canvasHeight: number, charWidth: number, charHeight: number, charSizeChanged: boolean): void { + public resize(terminal: ITerminal, canvasWidth: number, canvasHeight: number, charSizeChanged: boolean): void { this._canvas.width = canvasWidth * window.devicePixelRatio; this._canvas.height = canvasHeight * window.devicePixelRatio; this._canvas.style.width = `${canvasWidth}px`; this._canvas.style.height = `${canvasHeight}px`; + // Initialize current state grid + this._currentState = []; + for (let y = 0; y < terminal.rows; y++) { + if (this._currentState.length <= y) { + this._currentState.push([]); + } + for (let x = this._currentState[y].length; x < terminal.cols; x++) { + this._currentState[y].push(null); + } + this._currentState[y].length = terminal.cols; + } + this._currentState.length = terminal.rows; } public render(terminal: ITerminal, startRow: number, endRow: number): void { @@ -34,14 +49,18 @@ export class BackgroundRenderLayer implements IRenderLayer { const bg = data & 0x1ff; const flags = data >> 18; - if (bg < 16) { - this._ctx.save(); - this._ctx.fillStyle = TANGO_COLORS[bg]; - this._ctx.fillRect(x * scaledCharWidth, y * scaledCharHeight, scaledCharWidth, scaledCharHeight); - this._ctx.restore(); - } else { - // TODO: Only clear if needed - this._ctx.clearRect(x * scaledCharWidth, y * scaledCharHeight, scaledCharWidth, scaledCharHeight); + const needsRefresh = (bg < 16 && this._currentState[y][x] !== bg) || this._currentState[y][x] !== null; + if (needsRefresh) { + if (bg < 16) { + this._ctx.save(); + this._ctx.fillStyle = TANGO_COLORS[bg]; + this._ctx.fillRect(x * scaledCharWidth, y * scaledCharHeight, scaledCharWidth, scaledCharHeight); + this._ctx.restore(); + this._currentState[y][x] = bg; + } else { + this._ctx.clearRect(x * scaledCharWidth, y * scaledCharHeight, scaledCharWidth, scaledCharHeight); + this._currentState[y][x] = null; + } } } } diff --git a/src/renderer/ForegroundRenderLayer.ts b/src/renderer/ForegroundRenderLayer.ts index d3b1fb058..da0519bda 100644 --- a/src/renderer/ForegroundRenderLayer.ts +++ b/src/renderer/ForegroundRenderLayer.ts @@ -20,14 +20,14 @@ export class ForegroundRenderLayer implements IRenderLayer { this._charAtlasGenerator = new CharAtlasGenerator(); } - public resize(canvasWidth: number, canvasHeight: number, charWidth: number, charHeight: number, charSizeChanged: boolean): void { + public resize(terminal: ITerminal, canvasWidth: number, canvasHeight: number, charSizeChanged: boolean): void { this._canvas.width = canvasWidth * window.devicePixelRatio; this._canvas.height = canvasHeight * window.devicePixelRatio; this._canvas.style.width = `${canvasWidth}px`; this._canvas.style.height = `${canvasHeight}px`; if (charSizeChanged) { this._charAtlas = null; - this._charAtlasGenerator.generate(charWidth, charHeight).then(bitmap => { + this._charAtlasGenerator.generate(terminal.charMeasure.width, terminal.charMeasure.height).then(bitmap => { this._charAtlas = bitmap; }); } diff --git a/src/renderer/Interfaces.ts b/src/renderer/Interfaces.ts index f95725256..4d2753751 100644 --- a/src/renderer/Interfaces.ts +++ b/src/renderer/Interfaces.ts @@ -1,6 +1,6 @@ import { ITerminal } from '../Interfaces'; export interface IRenderLayer { - resize(canvasWidth: number, canvasHeight: number, charWidth: number, charHeight: number, charSizeChanged: boolean): void; + resize(terminal: ITerminal, canvasWidth: number, canvasHeight: number, charSizeChanged: boolean): void; render(terminal: ITerminal, startRow: number, endRow: number): void; }