Skip to content

Commit

Permalink
LibWeb/SVG: Implement SVGImageElement
Browse files Browse the repository at this point in the history
  • Loading branch information
tcl3 committed Aug 26, 2024
1 parent 471885e commit 945b229
Show file tree
Hide file tree
Showing 14 changed files with 396 additions and 8 deletions.
1 change: 1 addition & 0 deletions Tests/LibWeb/Text/expected/all-window-properties.txt
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ SVGGElement
SVGGeometryElement
SVGGradientElement
SVGGraphicsElement
SVGImageElement
SVGLength
SVGLineElement
SVGLinearGradientElement
Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibWeb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ set(SOURCES
Layout/SVGForeignObjectBox.cpp
Layout/SVGGeometryBox.cpp
Layout/SVGGraphicsBox.cpp
Layout/SVGImageBox.cpp
Layout/SVGSVGBox.cpp
Layout/SVGMaskBox.cpp
Layout/SVGClipBox.cpp
Expand Down Expand Up @@ -659,6 +660,7 @@ set(SOURCES
SVG/SVGGeometryElement.cpp
SVG/SVGGraphicsElement.cpp
SVG/SVGGradientElement.cpp
SVG/SVGImageElement.cpp
SVG/SVGPathElement.cpp
SVG/SVGCircleElement.cpp
SVG/SVGEllipseElement.cpp
Expand Down
3 changes: 3 additions & 0 deletions Userland/Libraries/LibWeb/DOM/ElementFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
#include <LibWeb/SVG/SVGEllipseElement.h>
#include <LibWeb/SVG/SVGForeignObjectElement.h>
#include <LibWeb/SVG/SVGGElement.h>
#include <LibWeb/SVG/SVGImageElement.h>
#include <LibWeb/SVG/SVGLineElement.h>
#include <LibWeb/SVG/SVGLinearGradientElement.h>
#include <LibWeb/SVG/SVGMaskElement.h>
Expand Down Expand Up @@ -488,6 +489,8 @@ static JS::GCPtr<SVG::SVGElement> create_svg_element(JS::Realm& realm, Document&
return realm.heap().allocate<SVG::SVGScriptElement>(realm, document, move(qualified_name));
if (local_name == SVG::TagNames::a)
return realm.heap().allocate<SVG::SVGAElement>(realm, document, move(qualified_name));
if (local_name == SVG::TagNames::image)
return realm.heap().allocate<SVG::SVGImageElement>(realm, document, move(qualified_name));

return nullptr;
}
Expand Down
16 changes: 16 additions & 0 deletions Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
#include <LibWeb/Layout/SVGClipBox.h>
#include <LibWeb/Layout/SVGFormattingContext.h>
#include <LibWeb/Layout/SVGGeometryBox.h>
#include <LibWeb/Layout/SVGImageBox.h>
#include <LibWeb/Layout/SVGMaskBox.h>
#include <LibWeb/SVG/SVGAElement.h>
#include <LibWeb/SVG/SVGClipPathElement.h>
#include <LibWeb/SVG/SVGForeignObjectElement.h>
#include <LibWeb/SVG/SVGGElement.h>
#include <LibWeb/SVG/SVGImageElement.h>
#include <LibWeb/SVG/SVGMaskElement.h>
#include <LibWeb/SVG/SVGSVGElement.h>
#include <LibWeb/SVG/SVGSymbolElement.h>
Expand Down Expand Up @@ -405,6 +407,8 @@ void SVGFormattingContext::layout_graphics_element(SVGGraphicsBox const& graphic
// 5.2. Grouping: the ‘g’ element
// The ‘g’ element is a container element for grouping together related graphics elements.
layout_container_element(graphics_box);
} else if (is<SVGImageBox>(graphics_box)) {
layout_image_element(static_cast<SVGImageBox const&>(graphics_box));
} else {
// Assume this is a path-like element.
layout_path_like_element(graphics_box);
Expand All @@ -417,6 +421,18 @@ void SVGFormattingContext::layout_graphics_element(SVGGraphicsBox const& graphic
layout_mask_or_clip(*clip_box);
}

void SVGFormattingContext::layout_image_element(SVGImageBox const& image_box)
{
auto& box_state = m_state.get_mutable(image_box);
auto bounding_box = const_cast<SVG::SVGImageElement&>(image_box.dom_node()).bounding_box();
box_state.set_content_x(bounding_box.x());
box_state.set_content_y(bounding_box.y());
box_state.set_content_width(bounding_box.width());
box_state.set_content_height(bounding_box.height());
box_state.set_has_definite_width(true);
box_state.set_has_definite_height(true);
}

void SVGFormattingContext::layout_mask_or_clip(SVGBox const& mask_or_clip)
{
SVG::SVGUnits content_units {};
Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <LibGfx/DeprecatedPath.h>
#include <LibWeb/Forward.h>
#include <LibWeb/Layout/FormattingContext.h>
#include <LibWeb/Layout/SVGImageBox.h>
#include <LibWeb/Layout/SVGSVGBox.h>
#include <LibWeb/Layout/SVGTextBox.h>
#include <LibWeb/Layout/SVGTextPathBox.h>
Expand All @@ -31,6 +32,7 @@ class SVGFormattingContext : public FormattingContext {
void layout_graphics_element(SVGGraphicsBox const&);
void layout_path_like_element(SVGGraphicsBox const&);
void layout_mask_or_clip(SVGBox const&);
void layout_image_element(SVGImageBox const& image_box);

[[nodiscard]] Gfx::Path compute_path_for_text(SVGTextBox const&);
[[nodiscard]] Gfx::Path compute_path_for_text_path(SVGTextPathBox const&);
Expand Down
24 changes: 24 additions & 0 deletions Userland/Libraries/LibWeb/Layout/SVGImageBox.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2024, Tim Ledbetter <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <LibWeb/Layout/SVGImageBox.h>
#include <LibWeb/Painting/ImagePaintable.h>
#include <LibWeb/Painting/SVGGraphicsPaintable.h>
#include <LibWeb/Painting/StackingContext.h>

namespace Web::Layout {

SVGImageBox::SVGImageBox(DOM::Document& document, SVG::SVGGraphicsElement& element, NonnullRefPtr<CSS::StyleProperties> properties)
: SVGGraphicsBox(document, element, properties)
{
}

JS::GCPtr<Painting::Paintable> SVGImageBox::create_paintable() const
{
return Painting::ImagePaintable::create(*this);
}

}
28 changes: 28 additions & 0 deletions Userland/Libraries/LibWeb/Layout/SVGImageBox.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2024, Tim Ledbetter <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <LibJS/Heap/GCPtr.h>
#include <LibWeb/Layout/SVGGraphicsBox.h>
#include <LibWeb/SVG/SVGImageElement.h>

namespace Web::Layout {

class SVGImageBox : public SVGGraphicsBox {
JS_CELL(SVGImageBox, SVGGraphicsBox);

public:
SVGImageBox(DOM::Document&, SVG::SVGGraphicsElement&, NonnullRefPtr<CSS::StyleProperties>);
virtual ~SVGImageBox() override = default;

SVG::SVGImageElement& dom_node() { return static_cast<SVG::SVGImageElement&>(SVGGraphicsBox::dom_node()); }
SVG::SVGImageElement const& dom_node() const { return static_cast<SVG::SVGImageElement const&>(SVGGraphicsBox::dom_node()); }

virtual JS::GCPtr<Painting::Paintable> create_paintable() const override;
};

}
18 changes: 12 additions & 6 deletions Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <LibWeb/HTML/DecodedImageData.h>
#include <LibWeb/HTML/HTMLImageElement.h>
#include <LibWeb/HTML/ImageRequest.h>
#include <LibWeb/Layout/ImageBox.h>
#include <LibWeb/Painting/BorderRadiusCornerClipper.h>
#include <LibWeb/Painting/ImagePaintable.h>
#include <LibWeb/Platform/FontPlugin.h>
Expand All @@ -19,17 +18,23 @@ namespace Web::Painting {

JS_DEFINE_ALLOCATOR(ImagePaintable);

JS::NonnullGCPtr<ImagePaintable> ImagePaintable::create(Layout::SVGImageBox const& layout_box)
{
return layout_box.heap().allocate_without_realm<ImagePaintable>(layout_box, layout_box.dom_node(), false, String {}, true);
}

JS::NonnullGCPtr<ImagePaintable> ImagePaintable::create(Layout::ImageBox const& layout_box)
{
auto alt = layout_box.dom_node().get_attribute_value(HTML::AttributeNames::alt);
return layout_box.heap().allocate_without_realm<ImagePaintable>(layout_box, move(alt));
return layout_box.heap().allocate_without_realm<ImagePaintable>(layout_box, layout_box.image_provider(), layout_box.renders_as_alt_text(), move(alt), false);
}

ImagePaintable::ImagePaintable(Layout::ImageBox const& layout_box, String alt_text)
ImagePaintable::ImagePaintable(Layout::Box const& layout_box, Layout::ImageProvider const& image_provider, bool renders_as_alt_text, String alt_text, bool is_svg)
: PaintableBox(layout_box)
, m_renders_as_alt_text(layout_box.renders_as_alt_text())
, m_renders_as_alt_text(renders_as_alt_text)
, m_alt_text(move(alt_text))
, m_image_provider(layout_box.image_provider())
, m_image_provider(image_provider)
, m_is_svg(is_svg)
{
const_cast<DOM::Document&>(layout_box.document()).register_viewport_client(*this);
}
Expand Down Expand Up @@ -74,7 +79,8 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const
auto scale_y = 0.0f;
Gfx::IntRect bitmap_intersect = bitmap_rect;

switch (computed_values().object_fit()) {
auto object_fit = m_is_svg ? CSS::ObjectFit::Contain : computed_values().object_fit();
switch (object_fit) {
case CSS::ObjectFit::Fill:
scale_x = (float)image_int_rect.width() / bitmap_rect.width();
scale_y = (float)image_int_rect.height() / bitmap_rect.height();
Expand Down
8 changes: 6 additions & 2 deletions Userland/Libraries/LibWeb/Painting/ImagePaintable.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma once

#include <LibWeb/Layout/ImageBox.h>
#include <LibWeb/Layout/SVGImageBox.h>
#include <LibWeb/Painting/PaintableBox.h>

namespace Web::Painting {
Expand All @@ -18,7 +19,8 @@ class ImagePaintable final
JS_DECLARE_ALLOCATOR(ImagePaintable);

public:
static JS::NonnullGCPtr<ImagePaintable> create(Layout::ImageBox const&);
static JS::NonnullGCPtr<ImagePaintable> create(Layout::ImageBox const& layout_box);
static JS::NonnullGCPtr<ImagePaintable> create(Layout::SVGImageBox const& layout_box);

virtual void paint(PaintContext&, PaintPhase) const override;

Expand All @@ -30,12 +32,14 @@ class ImagePaintable final
// ^Document::ViewportClient
virtual void did_set_viewport_rect(CSSPixelRect const&) final;

ImagePaintable(Layout::ImageBox const&, String alt_text);
ImagePaintable(Layout::Box const& layout_box, Layout::ImageProvider const& image_provider, bool renders_as_alt_text, String alt_text, bool is_svg);

bool m_renders_as_alt_text { false };
String m_alt_text;

Layout::ImageProvider const& m_image_provider;

bool m_is_svg { false };
};

}
Loading

0 comments on commit 945b229

Please sign in to comment.