LibWeb: Add OffscreenCanvas to IDL types

Add OffscreenCanvas to TexImageSource and CanvasImageSource.
Implement all the necessary features to make it work in all cases where
these types are used.
This commit is contained in:
Totto16 2025-03-06 23:41:31 +01:00
parent 2cc38111be
commit 23b003f729
No known key found for this signature in database
GPG key ID: AE3227CAF0EB3573
8 changed files with 35 additions and 9 deletions

View file

@ -42,6 +42,12 @@ static void default_source_size(CanvasImageSource const& image, float& source_wi
source_height = source->video_height();
}
},
[&source_width, &source_height](GC::Root<OffscreenCanvas> const& source) {
auto const bitmap = source->bitmap();
source_width = bitmap->width();
source_height = bitmap->height();
},
[&source_width, &source_height](GC::Root<HTMLCanvasElement> const& source) {
if (source->surface()) {
source_width = source->surface()->size().width();

View file

@ -10,13 +10,14 @@
#include <LibWeb/HTML/HTMLCanvasElement.h>
#include <LibWeb/HTML/HTMLImageElement.h>
#include <LibWeb/HTML/HTMLVideoElement.h>
#include <LibWeb/HTML/OffscreenCanvas.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/canvas.html#canvasimagesource
// NOTE: This is the Variant created by the IDL wrapper generator, and needs to be updated accordingly.
using CanvasImageSource = Variant<GC::Root<HTMLImageElement>, GC::Root<SVG::SVGImageElement>, GC::Root<HTMLCanvasElement>, GC::Root<ImageBitmap>, GC::Root<HTMLVideoElement>>;
using CanvasImageSource = Variant<GC::Root<HTMLImageElement>, GC::Root<SVG::SVGImageElement>, GC::Root<HTMLCanvasElement>, GC::Root<ImageBitmap>, GC::Root<OffscreenCanvas>, GC::Root<HTMLVideoElement>>;
// https://html.spec.whatwg.org/multipage/canvas.html#canvasdrawimage
class CanvasDrawImage {

View file

@ -1,6 +1,7 @@
#import <HTML/HTMLCanvasElement.idl>
#import <HTML/HTMLImageElement.idl>
#import <HTML/HTMLVideoElement.idl>
#import <HTML/Canvas/OffscreenCanvasBase.idl>
#import <HTML/ImageBitmap.idl>
#import <SVG/SVGImageElement.idl>
@ -9,8 +10,8 @@ typedef (HTMLImageElement or
// FIXME: We should use HTMLOrSVGImageElement instead of HTMLImageElement
HTMLVideoElement or
HTMLCanvasElement or
ImageBitmap
// FIXME: OffscreenCanvas
ImageBitmap or
OffscreenCanvas
// FIXME: VideoFrame
) CanvasImageSource;

View file

@ -17,6 +17,7 @@ namespace Web::HTML {
GC_DEFINE_ALLOCATOR(CanvasPattern);
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvaspattern-settransform
void CanvasPatternPaintStyle::paint(Gfx::IntRect physical_bounding_box, PaintFunction paint) const
{
// 1. Create an infinite transparent black bitmap.
@ -50,6 +51,7 @@ void CanvasPatternPaintStyle::paint(Gfx::IntRect physical_bounding_box, PaintFun
auto bitmap = m_image.visit(
[](GC::Root<HTMLImageElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> { return source->immutable_bitmap(); },
[](GC::Root<SVG::SVGImageElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> { return source->current_image_bitmap(); },
[](GC::Root<OffscreenCanvas> const& source) -> RefPtr<Gfx::ImmutableBitmap> { return Gfx::ImmutableBitmap::create(*source->bitmap()); },
[](GC::Root<HTMLCanvasElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> { return Gfx::ImmutableBitmap::create_snapshot_from_painting_surface(*source->surface()); },
[](GC::Root<HTMLVideoElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> { return Gfx::ImmutableBitmap::create(*source->bitmap()); },
[](GC::Root<ImageBitmap> const& source) -> RefPtr<Gfx::ImmutableBitmap> { return Gfx::ImmutableBitmap::create(*source->bitmap()); });

View file

@ -132,6 +132,7 @@ WebIDL::ExceptionOr<void> CanvasRenderingContext2D::draw_image_internal(CanvasIm
[](GC::Root<SVG::SVGImageElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
return source->current_image_bitmap();
},
[](GC::Root<OffscreenCanvas> const& source) -> RefPtr<Gfx::ImmutableBitmap> { return Gfx::ImmutableBitmap::create(*source->bitmap()); },
[](GC::Root<HTMLCanvasElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
auto surface = source->surface();
if (!surface)
@ -702,8 +703,14 @@ WebIDL::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasI
return Optional<CanvasImageSourceUsability> {};
},
// OffscreenCanvas
[](GC::Root<OffscreenCanvas> const& offscreen_canvas) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
// If image has either a horizontal dimension or a vertical dimension equal to zero, then throw an "InvalidStateError" DOMException.
if (offscreen_canvas->width() == 0 || offscreen_canvas->height() == 0)
return WebIDL::InvalidStateError::create(offscreen_canvas->realm(), "OffscreenCanvas width or height is zero"_string);
return Optional<CanvasImageSourceUsability> {};
},
// HTMLCanvasElement
// FIXME: OffscreenCanvas
[](GC::Root<HTMLCanvasElement> const& canvas_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
// If image has either a horizontal dimension or a vertical dimension equal to zero, then throw an "InvalidStateError" DOMException.
if (canvas_element->width() == 0 || canvas_element->height() == 0)
@ -743,8 +750,8 @@ bool image_is_not_origin_clean(CanvasImageSource const& image)
// FIXME: image's media data is CORS-cross-origin.
return false;
},
// HTMLCanvasElement
[](OneOf<GC::Root<HTMLCanvasElement>, GC::Root<ImageBitmap>> auto const&) {
// HTMLCanvasElement, ImageBitmap or OffscreenCanvas
[](OneOf<GC::Root<HTMLCanvasElement>, GC::Root<ImageBitmap>, GC::Root<OffscreenCanvas>> auto const&) {
// FIXME: image's bitmap's origin-clean flag is false.
return false;
});

View file

@ -6,8 +6,14 @@
#pragma once
#include <LibWeb/Forward.h>
#include <LibWeb/WebIDL/Types.h>
namespace Web::WebGL {
// NOTE: This is the Variant created by the IDL wrapper generator, and needs to be updated accordingly.
using TexImageSource = Variant<GC::Root<HTML::ImageBitmap>, GC::Root<HTML::ImageData>, GC::Root<HTML::HTMLImageElement>, GC::Root<HTML::HTMLCanvasElement>, GC::Root<HTML::OffscreenCanvas>, GC::Root<HTML::HTMLVideoElement>>;
// FIXME: This object should inherit from Bindings::PlatformObject and implement the WebGLRenderingContextBase IDL interface.
// We should make WebGL code generator to produce implementation for this interface.
class WebGLRenderingContextBase {

View file

@ -4,8 +4,8 @@ typedef (ImageBitmap or
ImageData or
HTMLImageElement or
HTMLCanvasElement or
HTMLVideoElement
// FIXME: OffscreenCanvas or
HTMLVideoElement or
OffscreenCanvas
// FIXME: VideoFrame
) TexImageSource;

View file

@ -730,7 +730,7 @@ struct ConvertedTexture {
int height { 0 };
};
static Optional<ConvertedTexture> read_and_pixel_convert_texture_image_source(Variant<GC::Root<ImageBitmap>, GC::Root<ImageData>, GC::Root<HTMLImageElement>, GC::Root<HTMLCanvasElement>, GC::Root<HTMLVideoElement>> const& source, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, Optional<int> destination_width = OptionalNone {}, Optional<int> destination_height = OptionalNone {})
static Optional<ConvertedTexture> read_and_pixel_convert_texture_image_source(TexImageSource const& source, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, Optional<int> destination_width = OptionalNone {}, Optional<int> destination_height = OptionalNone {})
{
// FIXME: If this function is called with an ImageData whose data attribute has been neutered,
// an INVALID_VALUE error is generated.
@ -753,6 +753,9 @@ static Optional<ConvertedTexture> read_and_pixel_convert_texture_image_source(Va
surface->read_into_bitmap(*bitmap);
return Gfx::ImmutableBitmap::create(*bitmap);
},
[](GC::Root<OffscreenCanvas> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
return Gfx::ImmutableBitmap::create(*source->bitmap());
},
[](GC::Root<HTMLVideoElement> const& source) -> RefPtr<Gfx::ImmutableBitmap> {
return Gfx::ImmutableBitmap::create(*source->bitmap());
},