From 308707ff633f36ba856462a943d0a2da578bc3c2 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 4 Oct 2024 14:39:04 +0200 Subject: [PATCH] LibWeb: Make SVGImageElement part of CanvasImageSource union This is very janky at the moment but it also more correct. :^) (cherry picked from commit cd0e4a49b8a758aca847ceaf57eec0a62cd7b687; amended to add a missing include of LibGfx/ImmutableBitmap.h to SVGImageElement.h that ladybird seems to get transitively somehow) --- .../expected/canvas/pattern-from-image.txt | 3 ++ .../Text/input/canvas/pattern-from-image.html | 12 ++++++++ Userland/Libraries/LibWeb/Forward.h | 1 + .../LibWeb/HTML/Canvas/CanvasDrawImage.cpp | 30 +++++++++++++------ .../LibWeb/HTML/Canvas/CanvasDrawImage.h | 2 +- .../LibWeb/HTML/Canvas/CanvasDrawImage.idl | 2 ++ .../HTML/Canvas/CanvasFillStrokeStyles.idl | 3 +- .../Libraries/LibWeb/HTML/CanvasPattern.cpp | 1 + .../LibWeb/HTML/CanvasRenderingContext2D.cpp | 18 +++++++++++ .../Libraries/LibWeb/SVG/SVGImageElement.h | 10 +++++++ 10 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/canvas/pattern-from-image.txt create mode 100644 Tests/LibWeb/Text/input/canvas/pattern-from-image.html diff --git a/Tests/LibWeb/Text/expected/canvas/pattern-from-image.txt b/Tests/LibWeb/Text/expected/canvas/pattern-from-image.txt new file mode 100644 index 00000000000000..546f2cdabb4859 --- /dev/null +++ b/Tests/LibWeb/Text/expected/canvas/pattern-from-image.txt @@ -0,0 +1,3 @@ +null +null +PASS (didn't throw!) diff --git a/Tests/LibWeb/Text/input/canvas/pattern-from-image.html b/Tests/LibWeb/Text/input/canvas/pattern-from-image.html new file mode 100644 index 00000000000000..7b680d57539aea --- /dev/null +++ b/Tests/LibWeb/Text/input/canvas/pattern-from-image.html @@ -0,0 +1,12 @@ + + diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 81ba53072bc074..b81bbd03003008 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -718,6 +718,7 @@ class SVGEllipseElement; class SVGForeignObjectElement; class SVGGeometryElement; class SVGGraphicsElement; +class SVGImageElement; class SVGLength; class SVGLineElement; class SVGMaskElement; diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp index 5cfe17501ee8e9..3c93d18c52ea17 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp @@ -6,20 +6,32 @@ #include #include +#include namespace Web::HTML { static void default_source_size(CanvasImageSource const& image, float& source_width, float& source_height) { - image.visit([&source_width, &source_height](auto const& source) { - if (source->bitmap()) { - source_width = source->bitmap()->width(); - source_height = source->bitmap()->height(); - } else { - source_width = source->width(); - source_height = source->height(); - } - }); + image.visit( + [&source_width, &source_height](JS::Handle const& source) { + if (source->bitmap()) { + source_width = source->bitmap()->width(); + source_height = source->bitmap()->height(); + } else { + // FIXME: This is very janky and not correct. + source_width = source->width()->anim_val()->value(); + source_height = source->height()->anim_val()->value(); + } + }, + [&source_width, &source_height](auto const& source) { + if (source->bitmap()) { + source_width = source->bitmap()->width(); + source_height = source->bitmap()->height(); + } else { + source_width = source->width(); + source_height = source->height(); + } + }); } WebIDL::ExceptionOr CanvasDrawImage::draw_image(Web::HTML::CanvasImageSource const& image, float destination_x, float destination_y) diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h index b274c490762d0a..cfe4aa0c315d01 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h @@ -15,7 +15,7 @@ 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, JS::Handle, JS::Handle>; +using CanvasImageSource = Variant, JS::Handle, JS::Handle, JS::Handle>; // https://html.spec.whatwg.org/multipage/canvas.html#canvasdrawimage class CanvasDrawImage { diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.idl b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.idl index aef9653c3ec559..f3da18fef4f916 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.idl +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.idl @@ -1,8 +1,10 @@ #import #import #import +#import typedef (HTMLImageElement or + SVGImageElement or // FIXME: We should use HTMLOrSVGImageElement instead of HTMLImageElement // FIXME: HTMLVideoElement or HTMLCanvasElement or diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.idl b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.idl index 149a2334a8bb5e..9b78a2a6e5a476 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.idl +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.idl @@ -10,6 +10,5 @@ interface mixin CanvasFillStrokeStyles { CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1); CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1); CanvasGradient createConicGradient(double startAngle, double x, double y); - // FIXME: 'image' should be a CanvasImageSource - CanvasPattern? createPattern((HTMLImageElement or HTMLCanvasElement) image, [LegacyNullToEmptyString] DOMString repetition); + CanvasPattern? createPattern(CanvasImageSource image, [LegacyNullToEmptyString] DOMString repetition); }; diff --git a/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp b/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp index c58fa97e2e8992..f75351d626abe4 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Web::HTML { diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index 86eabfd68639d7..6301144e3b8a44 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include namespace Web::HTML { @@ -660,6 +661,19 @@ WebIDL::ExceptionOr check_usability_of_image(CanvasI return { CanvasImageSourceUsability::Bad }; return Optional {}; }, + // FIXME: Don't duplicate this for HTMLImageElement and SVGImageElement. + [](JS::Handle const& image_element) -> WebIDL::ExceptionOr> { + // FIXME: If image's current request's state is broken, then throw an "InvalidStateError" DOMException. + + // If image is not fully decodable, then return bad. + if (!image_element->bitmap()) + return { CanvasImageSourceUsability::Bad }; + + // If image has an intrinsic width or intrinsic height (or both) equal to zero, then return bad. + if (image_element->bitmap()->width() == 0 || image_element->bitmap()->height() == 0) + return { CanvasImageSourceUsability::Bad }; + return Optional {}; + }, // FIXME: HTMLVideoElement // If image's readyState attribute is either HAVE_NOTHING or HAVE_METADATA, then return bad. @@ -697,6 +711,10 @@ bool image_is_not_origin_clean(CanvasImageSource const& image) // FIXME: image's current request's image data is CORS-cross-origin. return false; }, + [](JS::Handle const&) { + // FIXME: image's current request's image data is CORS-cross-origin. + return false; + }, // FIXME: HTMLVideoElement // image's media data is CORS-cross-origin. diff --git a/Userland/Libraries/LibWeb/SVG/SVGImageElement.h b/Userland/Libraries/LibWeb/SVG/SVGImageElement.h index e782aa89b73dee..36c4290393a30e 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGImageElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGImageElement.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -29,6 +30,15 @@ class SVGImageElement Gfx::Rect bounding_box() const; + // FIXME: This is a hack for images used as CanvasImageSource. Do something more elegant. + RefPtr bitmap() const + { + auto bitmap = current_image_bitmap(); + if (!bitmap) + return nullptr; + return bitmap->bitmap(); + } + // ^Layout::ImageProvider virtual bool is_image_available() const override; virtual Optional intrinsic_width() const override;