Skip to content

Commit

Permalink
LibWeb: Make SVGImageElement part of CanvasImageSource union
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
awesomekling authored and nico committed Nov 17, 2024
1 parent afbb213 commit abf9980
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 12 deletions.
3 changes: 3 additions & 0 deletions Tests/LibWeb/Text/expected/canvas/pattern-from-image.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
null
null
PASS (didn't throw!)
12 changes: 12 additions & 0 deletions Tests/LibWeb/Text/input/canvas/pattern-from-image.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script src="../include.js"></script>
<script>
test(() => {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = document.createElement("img");
println(ctx.createPattern(img, 'repeat'));
img = document.createElementNS("http://www.w3.org/2000/svg", "image");
println(ctx.createPattern(img, 'repeat'));
println("PASS (didn't throw!)");
});
</script>
1 change: 1 addition & 0 deletions Userland/Libraries/LibWeb/Forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,7 @@ class SVGEllipseElement;
class SVGForeignObjectElement;
class SVGGeometryElement;
class SVGGraphicsElement;
class SVGImageElement;
class SVGLength;
class SVGLineElement;
class SVGMaskElement;
Expand Down
30 changes: 21 additions & 9 deletions Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,32 @@

#include <LibWeb/HTML/Canvas/CanvasDrawImage.h>
#include <LibWeb/HTML/ImageBitmap.h>
#include <LibWeb/SVG/SVGImageElement.h>

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<SVG::SVGImageElement> 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<void> CanvasDrawImage::draw_image(Web::HTML::CanvasImageSource const& image, float destination_x, float destination_y)
Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<HTMLImageElement>, JS::Handle<HTMLCanvasElement>, JS::Handle<ImageBitmap>>;
using CanvasImageSource = Variant<JS::Handle<HTMLImageElement>, JS::Handle<SVG::SVGImageElement>, JS::Handle<HTMLCanvasElement>, JS::Handle<ImageBitmap>>;

// https://html.spec.whatwg.org/multipage/canvas.html#canvasdrawimage
class CanvasDrawImage {
Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.idl
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#import <HTML/HTMLCanvasElement.idl>
#import <HTML/HTMLImageElement.idl>
#import <HTML/ImageBitmap.idl>
#import <SVG/SVGImageElement.idl>

typedef (HTMLImageElement or
SVGImageElement or
// FIXME: We should use HTMLOrSVGImageElement instead of HTMLImageElement
// FIXME: HTMLVideoElement or
HTMLCanvasElement or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
1 change: 1 addition & 0 deletions Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <LibWeb/HTML/CanvasPattern.h>
#include <LibWeb/HTML/CanvasRenderingContext2D.h>
#include <LibWeb/HTML/ImageBitmap.h>
#include <LibWeb/SVG/SVGImageElement.h>

namespace Web::HTML {

Expand Down
18 changes: 18 additions & 0 deletions Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <LibWeb/Layout/TextNode.h>
#include <LibWeb/Painting/Paintable.h>
#include <LibWeb/Platform/FontPlugin.h>
#include <LibWeb/SVG/SVGImageElement.h>
#include <LibWeb/WebIDL/ExceptionOr.h>

namespace Web::HTML {
Expand Down Expand Up @@ -660,6 +661,19 @@ WebIDL::ExceptionOr<CanvasImageSourceUsability> check_usability_of_image(CanvasI
return { CanvasImageSourceUsability::Bad };
return Optional<CanvasImageSourceUsability> {};
},
// FIXME: Don't duplicate this for HTMLImageElement and SVGImageElement.
[](JS::Handle<SVG::SVGImageElement> const& image_element) -> WebIDL::ExceptionOr<Optional<CanvasImageSourceUsability>> {
// 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<CanvasImageSourceUsability> {};
},

// FIXME: HTMLVideoElement
// If image's readyState attribute is either HAVE_NOTHING or HAVE_METADATA, then return bad.
Expand Down Expand Up @@ -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<SVG::SVGImageElement> 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.
Expand Down
10 changes: 10 additions & 0 deletions Userland/Libraries/LibWeb/SVG/SVGImageElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include <LibGfx/ImmutableBitmap.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibWeb/Layout/ImageProvider.h>
#include <LibWeb/SVG/SVGAnimatedLength.h>
Expand All @@ -29,6 +30,15 @@ class SVGImageElement

Gfx::Rect<CSSPixels> bounding_box() const;

// FIXME: This is a hack for images used as CanvasImageSource. Do something more elegant.
RefPtr<Gfx::Bitmap> 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<CSSPixels> intrinsic_width() const override;
Expand Down

0 comments on commit abf9980

Please sign in to comment.