canvas: Add initial support of ImageBitmapRenderingContext (#37998)

Add support of the ImageBitmapRenderingContext as "bitmaprenderer"
canvas context mode to RenderingContext/OffscreenRenderingContext
https://html.spec.whatwg.org/multipage/#imagebitmaprenderingcontext

It is initial implementation with public interface API but without
any display presentation support for HTMLCanvasElement.

Testing: Improvements in the following tests:
-
html/canvas/element/manual/imagebitmap/createImageBitmap-origin.sub.html
- html/canvas/offscreen/manual/text/canvas.2d.offscreen*
-
html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.nocrash.html
- imagebitmap-renderingcontext/*

Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
This commit is contained in:
Andrei Volykhin 2025-07-15 11:03:49 +03:00 committed by GitHub
parent ccc902eb7a
commit c817d7b9ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 365 additions and 82 deletions

View file

@ -51,6 +51,7 @@ use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers};
#[cfg(not(feature = "webgpu"))]
use crate::dom::gpucanvascontext::GPUCanvasContext;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::imagebitmaprenderingcontext::ImageBitmapRenderingContext;
use crate::dom::mediastream::MediaStream;
use crate::dom::mediastreamtrack::MediaStreamTrack;
use crate::dom::node::{Node, NodeTraits};
@ -164,6 +165,9 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<'_, HTMLCanvasElement> {
Some(RenderingContext::Context2d(context)) => {
context.to_layout().canvas_data_source()
},
Some(RenderingContext::BitmapRenderer(context)) => {
context.to_layout().canvas_data_source()
},
Some(RenderingContext::WebGL(context)) => context.to_layout().canvas_data_source(),
Some(RenderingContext::WebGL2(context)) => context.to_layout().canvas_data_source(),
#[cfg(feature = "webgpu")]
@ -207,6 +211,37 @@ impl HTMLCanvasElement {
Some(context)
}
/// <https://html.spec.whatwg.org/multipage/#canvas-context-bitmaprenderer>
fn get_or_init_bitmaprenderer_context(
&self,
can_gc: CanGc,
) -> Option<DomRoot<ImageBitmapRenderingContext>> {
// Return the same object as was returned the last time the method was
// invoked with this same first argument.
if let Some(ctx) = self.context() {
return match *ctx {
RenderingContext::BitmapRenderer(ref ctx) => Some(DomRoot::from_ref(ctx)),
_ => None,
};
}
// Step 1. Let context be the result of running the
// ImageBitmapRenderingContext creation algorithm given this and
// options.
let context = ImageBitmapRenderingContext::new(
&self.owner_global(),
HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(DomRoot::from_ref(self)),
can_gc,
);
// Step 2. Set this's context mode to bitmaprenderer.
*self.context_mode.borrow_mut() =
Some(RenderingContext::BitmapRenderer(Dom::from_ref(&*context)));
// Step 3. Return context.
Some(context)
}
fn get_or_init_webgl_context(
&self,
cx: JSContext,
@ -410,6 +445,9 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement {
"2d" => self
.get_or_init_2d_context(can_gc)
.map(RootedRenderingContext::CanvasRenderingContext2D),
"bitmaprenderer" => self
.get_or_init_bitmaprenderer_context(can_gc)
.map(RootedRenderingContext::ImageBitmapRenderingContext),
"webgl" | "experimental-webgl" => self
.get_or_init_webgl_context(cx, options, can_gc)
.map(RootedRenderingContext::WebGLRenderingContext),