LibWeb: Support percentage values in SVG text positioning element

This commit is contained in:
Edwin Hoksberg 2024-07-21 16:21:28 +02:00 committed by Andreas Kling
parent 4795b9206c
commit 356bddbdbb
Notes: github-actions[bot] 2024-07-21 17:57:31 +00:00
5 changed files with 69 additions and 12 deletions

View File

@ -0,0 +1,29 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
BlockContainer <body> 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 <svg> at (8,8) content-size 784x261.328125 [SVG] children: inline
TextNode <#text>
TextNode <#text>
SVGTextBox <text.small> at (86.40625,65.5) content-size 48.109375x37.484375 children: inline
TextNode <#text>
TextNode <#text>
SVGTextBox <text.heavy> at (141.28125,21.078125) content-size 148.234375x79.71875 children: inline
TextNode <#text>
TextNode <#text>
SVGTextBox <text.small> at (204,117.765625) content-size 34.59375x34.703125 children: inline
TextNode <#text>
TextNode <#text>
SVGTextBox <text.Rrrrr> 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<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x261.328125]
SVGSVGPaintable (SVGSVGBox<svg>) [8,8 784x261.328125]
SVGPathPaintable (SVGTextBox<text>.small) [86.40625,65.5 48.109375x37.484375]
SVGPathPaintable (SVGTextBox<text>.heavy) [141.28125,21.078125 148.234375x79.71875]
SVGPathPaintable (SVGTextBox<text>.small) [204,117.765625 34.59375x34.703125]
SVGPathPaintable (SVGTextBox<text>.Rrrrr) [243.1875,47.21875 519.34375x115.359375]

View File

@ -0,0 +1,20 @@
<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
<style>
.small {
font: italic 13px sans-serif;
}
.heavy {
font: bold 30px sans-serif;
}
.Rrrrr {
font: italic 40px serif;
fill: red;
}
</style>
<text x="10%" y="35%" class="small">My</text>
<text x="17%" y="35%" class="heavy">cat</text>
<text x="25%" y="55%" class="small">is</text>
<text x="30%" y="55%" class="Rrrrr">Grumpy!</text>
</svg>

After

Width:  |  Height:  |  Size: 465 B

View File

@ -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)) {

View File

@ -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 };
}
}

View File

@ -18,7 +18,7 @@ class SVGTextPositioningElement : public SVGTextContentElement {
public:
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value) override;
Gfx::FloatPoint get_offset() const;
Gfx::FloatPoint get_offset(CSSPixelSize const& viewport_size) const;
JS::NonnullGCPtr<SVGAnimatedLength> x() const;
JS::NonnullGCPtr<SVGAnimatedLength> 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<NumberPercentage> m_x;
Optional<NumberPercentage> m_y;
Optional<NumberPercentage> m_dx;
Optional<NumberPercentage> m_dy;
};
}