From 356bddbdbb774cf86dd77d2a54a6fddccf82767e Mon Sep 17 00:00:00 2001 From: Edwin Hoksberg Date: Sun, 21 Jul 2024 16:21:28 +0200 Subject: [PATCH] LibWeb: Support percentage values in SVG text positioning element --- .../svg-text-with-percentage-values.txt | 29 +++++++++++++++++++ .../svg-text-with-percentage-values.html | 20 +++++++++++++ .../LibWeb/Layout/SVGFormattingContext.cpp | 2 +- .../LibWeb/SVG/SVGTextPositioningElement.cpp | 20 +++++++++---- .../LibWeb/SVG/SVGTextPositioningElement.h | 10 +++---- 5 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/svg-text-with-percentage-values.txt create mode 100644 Tests/LibWeb/Layout/input/svg-text-with-percentage-values.html diff --git a/Tests/LibWeb/Layout/expected/svg-text-with-percentage-values.txt b/Tests/LibWeb/Layout/expected/svg-text-with-percentage-values.txt new file mode 100644 index 00000000000..787a80bcd1a --- /dev/null +++ b/Tests/LibWeb/Layout/expected/svg-text-with-percentage-values.txt @@ -0,0 +1,29 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x261.328125 children: inline + frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 784x261.328125] baseline: 261.328125 + SVGSVGBox at (8,8) content-size 784x261.328125 [SVG] children: inline + TextNode <#text> + TextNode <#text> + SVGTextBox at (86.40625,65.5) content-size 48.109375x37.484375 children: inline + TextNode <#text> + TextNode <#text> + SVGTextBox at (141.28125,21.078125) content-size 148.234375x79.71875 children: inline + TextNode <#text> + TextNode <#text> + SVGTextBox at (204,117.765625) content-size 34.59375x34.703125 children: inline + TextNode <#text> + TextNode <#text> + SVGTextBox at (243.1875,47.21875) content-size 519.34375x115.359375 children: inline + TextNode <#text> + TextNode <#text> + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x600] + PaintableWithLines (BlockContainer) [8,8 784x261.328125] + SVGSVGPaintable (SVGSVGBox) [8,8 784x261.328125] + SVGPathPaintable (SVGTextBox.small) [86.40625,65.5 48.109375x37.484375] + SVGPathPaintable (SVGTextBox.heavy) [141.28125,21.078125 148.234375x79.71875] + SVGPathPaintable (SVGTextBox.small) [204,117.765625 34.59375x34.703125] + SVGPathPaintable (SVGTextBox.Rrrrr) [243.1875,47.21875 519.34375x115.359375] diff --git a/Tests/LibWeb/Layout/input/svg-text-with-percentage-values.html b/Tests/LibWeb/Layout/input/svg-text-with-percentage-values.html new file mode 100644 index 00000000000..6f2a7fa867b --- /dev/null +++ b/Tests/LibWeb/Layout/input/svg-text-with-percentage-values.html @@ -0,0 +1,20 @@ + + + + My + cat + is + Grumpy! + diff --git a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp index a04e8317e92..74d84ee1916 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp @@ -308,7 +308,7 @@ Gfx::Path SVGFormattingContext::compute_path_for_text(SVGTextBox const& text_box auto text_contents = text_element.text_contents(); Utf8View text_utf8 { text_contents }; auto text_width = font.width(text_utf8); - auto text_offset = text_element.get_offset(); + auto text_offset = text_element.get_offset(m_viewport_size); // https://svgwg.org/svg2-draft/text.html#TextAnchoringProperties switch (text_element.text_anchor().value_or(SVG::TextAnchor::Start)) { diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.cpp index eecc53929fb..12209c8e6e7 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.cpp @@ -34,19 +34,27 @@ void SVGTextPositioningElement::attribute_changed(FlyString const& name, Optiona SVGGraphicsElement::attribute_changed(name, old_value, value); if (name == SVG::AttributeNames::x) { - m_x = AttributeParser::parse_coordinate(value.value_or(String {})).value_or(m_x); + m_x = AttributeParser::parse_number_percentage(value.value_or(String {})); } else if (name == SVG::AttributeNames::y) { - m_y = AttributeParser::parse_coordinate(value.value_or(String {})).value_or(m_y); + m_y = AttributeParser::parse_number_percentage(value.value_or(String {})); } else if (name == SVG::AttributeNames::dx) { - m_dx = AttributeParser::parse_coordinate(value.value_or(String {})).value_or(m_dx); + m_dx = AttributeParser::parse_number_percentage(value.value_or(String {})); } else if (name == SVG::AttributeNames::dy) { - m_dy = AttributeParser::parse_coordinate(value.value_or(String {})).value_or(m_dy); + m_dy = AttributeParser::parse_number_percentage(value.value_or(String {})); } } -Gfx::FloatPoint SVGTextPositioningElement::get_offset() const +Gfx::FloatPoint SVGTextPositioningElement::get_offset(CSSPixelSize const& viewport_size) const { - return { m_x + m_dx, m_y + m_dy }; + auto const viewport_width = viewport_size.width().to_float(); + auto const viewport_height = viewport_size.height().to_float(); + + float const x = m_x.value_or({ 0, false }).resolve_relative_to(viewport_width); + float const y = m_y.value_or({ 0, false }).resolve_relative_to(viewport_height); + float const dx = m_dx.value_or({ 0, false }).resolve_relative_to(viewport_width); + float const dy = m_dy.value_or({ 0, false }).resolve_relative_to(viewport_height); + + return { x + dx, y + dy }; } } diff --git a/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.h b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.h index 61e86d00224..c944fe0cae2 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGTextPositioningElement.h @@ -18,7 +18,7 @@ class SVGTextPositioningElement : public SVGTextContentElement { public: virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) override; - Gfx::FloatPoint get_offset() const; + Gfx::FloatPoint get_offset(CSSPixelSize const& viewport_size) const; JS::NonnullGCPtr x() const; JS::NonnullGCPtr y() const; @@ -31,10 +31,10 @@ protected: virtual void initialize(JS::Realm&) override; private: - float m_x { 0 }; - float m_y { 0 }; - float m_dx { 0 }; - float m_dy { 0 }; + Optional m_x; + Optional m_y; + Optional m_dx; + Optional m_dy; }; }