Skip to content

Improve canvas text#841

Open
jfboeve wants to merge 5 commits into
mainfrom
fix/improve-canvas-text
Open

Improve canvas text#841
jfboeve wants to merge 5 commits into
mainfrom
fix/improve-canvas-text

Conversation

@jfboeve

@jfboeve jfboeve commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

This pull request refactors the text rendering pipeline to improve performance and flexibility by allowing the use of ImageBitmap and HTMLCanvasElement as texture sources, in addition to ImageData. The changes optimize how text is rendered and transferred to GPU textures, reduce unnecessary pixel readbacks and copies, and add support for offscreen and onscreen canvas workflows. The most important changes are grouped below:

Text rendering pipeline improvements

  • The text renderer now uses ImageBitmap (for OffscreenCanvas) or a dedicated HTMLCanvasElement (for onscreen rendering) as the texture source, instead of always using ImageData. This enables zero-copy transfers to the GPU and avoids unnecessary pixel readbacks. (src/core/text-rendering/CanvasTextRenderer.ts, src/core/text-rendering/TextRenderer.ts) [1] [2] [3]
  • The renderer distinguishes between offscreen and onscreen canvases, using transferToImageBitmap() for OffscreenCanvas and allocating a new HTMLCanvasElement per text node otherwise. (src/core/text-rendering/CanvasTextRenderer.ts) [1] [2] [3]

Texture and image source handling

  • The ImageTexture and TextureData types now support ImageBitmap and HTMLCanvasElement as valid texture sources, in addition to ImageData. (src/core/textures/ImageTexture.ts, src/core/textures/Texture.ts) [1] [2] [3]
  • The texture uploaders in both Canvas and WebGL renderers are updated to handle HTMLCanvasElement as a valid image source for textures. (src/core/renderers/canvas/CanvasTexture.ts, src/core/renderers/webgl/WebGlCtxTexture.ts, src/core/renderers/webgl/WebGlCtxSubTexture.ts) [1] [2] [3]

Platform and canvas management

  • The platform abstraction is updated to provide both createCanvas() (for onscreen) and createOffscreenCanvas() (for offscreen or worker rendering), and the web platform implements both methods. The renderer now uses these appropriately. (src/core/platforms/Platform.ts, src/core/platforms/web/WebPlatform.ts) [1] [2]

These changes collectively make the text rendering pipeline more efficient, flexible, and compatible with modern browser features.

jorge-graca-sky and others added 3 commits July 14, 2026 15:44
Use bitmap/canvas instead of ImageData
`getImageData` forces the browser to copy the pixels drawn by the canvas
to JS world. By using ImageBitmap instead the pixels can be drawn on the
GPU and stay there.
@jfboeve jfboeve requested a review from wouterlucas July 15, 2026 12:29
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ jfboeve
❌ jorge-graca-sky
You have signed the CLA already but the status is still pending? Let us recheck it.

Comment thread src/core/platforms/web/WebPlatform.ts
Comment on lines +68 to +73
canvas = stage.platform.createOffscreenCanvas();
isOffscreen =
typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas;
if (canvas === null) {
canvas = stage.platform.createCanvas();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
canvas = stage.platform.createOffscreenCanvas();
isOffscreen =
typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas;
if (canvas === null) {
canvas = stage.platform.createCanvas();
}
canvas = stage.platform.createOffscreenCanvas();
if (canvas) {
isOffscreen = true;
} else {
isOffscreen = false;
canvas = stage.platform.createCanvas();
}


// If a canvas was provided in the settings, use it. Otherwise, create a new one.
this.canvas = settings.canvas || this.createCanvas();
this.canvas = settings.canvas || document.createElement('canvas');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
this.canvas = settings.canvas || document.createElement('canvas');
this.canvas = settings.canvas || this.createCanvas();


/**
* Creates a new canvas element.
* Creates a new canvas.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Creates a new canvas.
* Creates a new canvas element.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants