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

@ -20,6 +20,7 @@ use crate::dom::bindings::codegen::Bindings::OffscreenCanvasBinding::{
ImageEncodeOptions, OffscreenCanvasMethods,
OffscreenRenderingContext as RootedOffscreenRenderingContext,
};
use crate::dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object_with_proto};
@ -32,6 +33,7 @@ use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlcanvaselement::HTMLCanvasElement;
use crate::dom::imagebitmap::ImageBitmap;
use crate::dom::imagebitmaprenderingcontext::ImageBitmapRenderingContext;
use crate::dom::offscreencanvasrenderingcontext2d::OffscreenCanvasRenderingContext2D;
use crate::dom::promise::Promise;
use crate::realms::{AlreadyInRealm, InRealm};
@ -140,6 +142,38 @@ impl OffscreenCanvas {
Some(context)
}
/// <https://html.spec.whatwg.org/multipage/#offscreen-context-type-bitmaprenderer>
pub(crate) 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 {
OffscreenRenderingContext::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.global(),
HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(DomRoot::from_ref(self)),
can_gc,
);
// Step 2. Set this's context mode to bitmaprenderer.
*self.context.borrow_mut() = Some(OffscreenRenderingContext::BitmapRenderer(
Dom::from_ref(&*context),
));
// Step 3. Return context.
Some(context)
}
pub(crate) fn placeholder(&self) -> Option<DomRoot<HTMLCanvasElement>> {
self.placeholder
.as_ref()
@ -267,6 +301,9 @@ impl OffscreenCanvasMethods<crate::DomTypeHolder> for OffscreenCanvas {
"2d" => Ok(self
.get_or_init_2d_context(can_gc)
.map(RootedOffscreenRenderingContext::OffscreenCanvasRenderingContext2D)),
"bitmaprenderer" => Ok(self
.get_or_init_bitmaprenderer_context(can_gc)
.map(RootedOffscreenRenderingContext::ImageBitmapRenderingContext)),
/*"webgl" | "experimental-webgl" => self
.get_or_init_webgl_context(cx, options)
.map(OffscreenRenderingContext::WebGLRenderingContext),