From c6d4c73c8a8c23ce102918fc0342cf33d2986711 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 30 Aug 2017 14:50:07 -0700 Subject: [PATCH] Initial prototype --- src/Interfaces.ts | 2 ++ src/Renderer.ts | 76 ++++++++++++++++++++++++++++++++++++++++++++++- src/Terminal.ts | 13 ++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/Interfaces.ts b/src/Interfaces.ts index fb66f4d7..b643de45 100644 --- a/src/Interfaces.ts +++ b/src/Interfaces.ts @@ -21,6 +21,8 @@ export interface ITerminal extends IEventEmitter { element: HTMLElement; rowContainer: HTMLElement; selectionContainer: HTMLElement; + canvasElement: HTMLCanvasElement; + canvasContext: CanvasRenderingContext2D; selectionManager: ISelectionManager; charMeasure: ICharMeasure; textarea: HTMLTextAreaElement; diff --git a/src/Renderer.ts b/src/Renderer.ts index b51a9ff9..1586d8fe 100644 --- a/src/Renderer.ts +++ b/src/Renderer.ts @@ -97,7 +97,8 @@ export class Renderer { } this._refreshRowsQueue = []; this._refreshAnimationFrame = null; - this._refresh(start, end); + // this._refresh(start, end); + this._canvasRender(start, end); } /** @@ -323,6 +324,79 @@ export class Renderer { this._terminal.emit('refresh', {start, end}); }; + private _imageDataCache = {}; + private _colors = [ + // dark: + '#2e3436', + '#cc0000', + '#4e9a06', + '#c4a000', + '#3465a4', + '#75507b', + '#06989a', + '#d3d7cf', + // bright: + '#555753', + '#ef2929', + '#8ae234', + '#fce94f', + '#729fcf', + '#ad7fa8', + '#34e2e2', + '#eeeeec' + ]; + + private _canvasRender(start: number, end: number): void { + const charWidth = Math.ceil(this._terminal.charMeasure.width); + const charHeight = Math.ceil(this._terminal.charMeasure.height); + const ctx = this._terminal.canvasContext; + ctx.font = '16px Hack'; + ctx.fillStyle = '#000000'; + // console.log('fill', start, end); + // console.log('fill', start * charHeight, (end - start + 1) * charHeight); + ctx.fillRect(0, start * charHeight, charWidth * this._terminal.cols, (end - start + 1) * charHeight); + ctx.fillStyle = 'rgb(255, 255, 255)'; + ctx.textBaseline = 'top'; + + for (let y = start; y <= end; y++) { + let row = y + this._terminal.buffer.ydisp; + let line = this._terminal.buffer.lines.get(row); + for (let x = 0; x < this._terminal.cols; x++) { + let data: any = line[x][0]; + const ch = line[x][CHAR_DATA_CHAR_INDEX]; + + // if (ch === ' ') { + // continue; + // } + + let bg = data & 0x1ff; + let fg = (data >> 9) & 0x1ff; + let flags = data >> 18; + + // if (bg < 16) { + // } + + if (fg < 16) { + ctx.fillStyle = this._colors[fg]; + } + + // let imageData; + // let key = ch + fg; + // if (key in this._imageDataCache) { + // imageData = this._imageDataCache[key]; + // } else { + ctx.fillText(ch, x * charWidth, y * charHeight); + // imageData = ctx.getImageData(x * charWidth, y * charHeight, charWidth, charHeight); + // this._imageDataCache[key] = imageData; + // } + + // ctx.fillText(ch, x * charWidth, y * charHeight); + // ctx.putImageData(imageData, x * charWidth, y * charHeight); + } + } + this._imageDataCache = {}; + } + /** * Refreshes the selection in the DOM. * @param start The selection start. diff --git a/src/Terminal.ts b/src/Terminal.ts index 827273ff..0bb00ecf 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -175,6 +175,8 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT private body: HTMLBodyElement; private viewportScrollArea: HTMLElement; private viewportElement: HTMLElement; + public canvasElement: HTMLCanvasElement; + public canvasContext: CanvasRenderingContext2D; public selectionContainer: HTMLElement; private helperContainer: HTMLElement; private compositionView: HTMLElement; @@ -703,6 +705,12 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT this.selectionContainer.classList.add('xterm-selection'); this.element.appendChild(this.selectionContainer); + + this.canvasElement = document.createElement('canvas'); + this.canvasContext = this.canvasElement.getContext('2d'); + this.element.appendChild(this.canvasElement); + + // Create the container that will hold the lines of the terminal and then // produce the lines the lines. this.rowContainer = document.createElement('div'); @@ -746,6 +754,11 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT }); this.charMeasure.measure(); + this.charMeasure.on('charsizechanged', () => { + this.canvasElement.setAttribute('width', `${Math.ceil(this.charMeasure.width) * this.cols}px`); + this.canvasElement.setAttribute('height', `${Math.ceil(this.charMeasure.height) * this.rows}px`); + }); + this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure); this.renderer = new Renderer(this); this.selectionManager = new SelectionManager(this, this.buffer, this.rowContainer, this.charMeasure);