Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defer canvas creation #56

Merged
merged 7 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions overwrite/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"sourceType": "module"
},
"ignorePatterns": [
"**/inwasm-sdks/*",
"**/typings/*.d.ts",
"**/node_modules",
"**/*.js"
Expand Down
2 changes: 1 addition & 1 deletion src/ImageAddon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class ImageAddon implements ITerminalAddon {
this._terminal = terminal;

// internal data structures
this._renderer = new ImageRenderer(terminal, this._opts.showPlaceholder);
this._renderer = new ImageRenderer(terminal);
this._storage = new ImageStorage(terminal, this._renderer, this._opts);

// enable size reports
Expand Down
39 changes: 22 additions & 17 deletions src/ImageRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class ImageRenderer implements IDisposable {
}


constructor(private _terminal: ITerminalExt, private _showPlaceholder: boolean) {
constructor(private _terminal: ITerminalExt) {
this._oldOpen = this._terminal._core.open;
this._terminal._core.open = (parent: HTMLElement): void => {
this._oldOpen?.call(this._terminal._core, parent);
Expand All @@ -79,7 +79,7 @@ export class ImageRenderer implements IDisposable {

public dispose(): void {
this._optionsRefresh?.dispose();
this._removeLayerFromDom();
this.removeLayerFromDom();
if (this._terminal._core && this._oldOpen) {
this._terminal._core.open = this._oldOpen;
this._oldOpen = undefined;
Expand Down Expand Up @@ -220,17 +220,20 @@ export class ImageRenderer implements IDisposable {
* Draw a line with placeholder on the image layer canvas.
*/
public drawPlaceholder(col: number, row: number, count: number = 1): void {
if ((this._placeholderBitmap || this._placeholder) && this._ctx) {
if (this._ctx) {
const { width, height } = this.cellSize;

// Don't try to draw anything, if we cannot get valid renderer metrics.
if (width === -1 || height === -1) {
return;
}

if (height >= this._placeholder!.height) {
if (!this._placeholder) {
this._createPlaceHolder(Math.max(height + 1, PLACEHOLDER_HEIGHT));
} else if (height >= this._placeholder!.height) {
this._createPlaceHolder(height + 1);
}
if (!this._placeholder) return;
this._ctx.drawImage(
this._placeholderBitmap || this._placeholder!,
col * width,
Expand Down Expand Up @@ -294,25 +297,27 @@ export class ImageRenderer implements IDisposable {
this._renderService = this._terminal._core._renderService;
this._oldSetRenderer = this._renderService.setRenderer.bind(this._renderService);
this._renderService.setRenderer = (renderer: any) => {
this._removeLayerFromDom();
this.removeLayerFromDom();
this._oldSetRenderer?.call(this._renderService, renderer);
this._insertLayerToDom();
};
this._insertLayerToDom();
if (this._showPlaceholder) {
this._createPlaceHolder();
}
}

private _insertLayerToDom(): void {
this.canvas = ImageRenderer.createCanvas(this._terminal._core._coreBrowserService.window, this.dimensions?.css.canvas.width || 0, this.dimensions?.css.canvas.height || 0);
this.canvas.classList.add('xterm-image-layer');
this._terminal._core.screenElement?.appendChild(this.canvas);
this._ctx = this.canvas.getContext('2d', { alpha: true, desynchronized: true });
public insertLayerToDom(): void {
if (!this.canvas) {
this.canvas = ImageRenderer.createCanvas(this._terminal._core._coreBrowserService.window, this.dimensions?.css.canvas.width || 0, this.dimensions?.css.canvas.height || 0);
this.canvas.classList.add('xterm-image-layer');
this._terminal._core.screenElement?.appendChild(this.canvas);
this._ctx = this.canvas.getContext('2d', { alpha: true, desynchronized: true });
this.clearAll();
}
}

private _removeLayerFromDom(): void {
this.canvas?.parentNode?.removeChild(this.canvas);
public removeLayerFromDom(): void {
if (this.canvas) {
this._ctx = undefined;
this.canvas.parentNode?.removeChild(this.canvas);
this.canvas = undefined;
}
}

private _createPlaceHolder(height: number = PLACEHOLDER_HEIGHT): void {
Expand Down
13 changes: 10 additions & 3 deletions src/ImageStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,13 @@ export class ImageStorage implements IDisposable {
*/
// TODO: Should we move this to the ImageRenderer?
public render(range: { start: number, end: number }): void {
// exit early if we dont have a canvas
if (!this._renderer.canvas) {
return;
// setup image canvas in case we have none yet, but have images in store
if (!this._renderer.canvas && this._images.size) {
this._renderer.insertLayerToDom();
// safety measure - in case we cannot spawn a canvas at all, just exit
if (!this._renderer.canvas) {
return;
}
}
// rescale if needed
this._renderer.rescaleCanvas();
Expand All @@ -339,6 +343,9 @@ export class ImageStorage implements IDisposable {
this._fullyCleared = true;
this._needsFullClear = false;
}
if (this._renderer.canvas) {
this._renderer.removeLayerFromDom();
}
return;
}

Expand Down