mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-23 04:55:15 +00:00
LibWeb: Scale SVG stroke-width based on viewbox
This fixes the clipping of strokes in quite a few cases and now fixes the Gartic Phone logo :^) (Layout test updated but no visible changes there)
This commit is contained in:
parent
cb79c6bc2f
commit
f9c61e3ba7
Notes:
sideshowbarker
2024-07-17 07:11:12 +09:00
Author: https://github.com/MacDue Commit: https://github.com/SerenityOS/serenity/commit/f9c61e3ba7 Pull-request: https://github.com/SerenityOS/serenity/pull/18388
5 changed files with 33 additions and 21 deletions
|
@ -23,7 +23,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
TextNode <#text>
|
||||
SVGGraphicsBox <g> children: inline
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <path> at (45.193222,199.330932) content-size 119.782173x48.453796 children: not-inline
|
||||
SVGGeometryBox <path> at (45.693222,199.830932) content-size 118.782173x47.453796 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGraphicsBox <g> children: inline
|
||||
|
@ -34,63 +34,63 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
|||
TextNode <#text>
|
||||
SVGSVGBox <svg> at (258,50) content-size 200x200 children: inline
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (267.5,59.5) content-size 31x21 children: not-inline
|
||||
SVGGeometryBox <rect> at (268,60) content-size 30x20 children: not-inline
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (287.5,129.5) content-size 111x91 children: not-inline
|
||||
SVGGeometryBox <rect> at (288,130) content-size 110x90 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGSVGBox <svg> at (466,50) content-size 200x200 children: inline
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (505.5,89.5) content-size 121x121 children: not-inline
|
||||
SVGGeometryBox <rect> at (506,90) content-size 120x120 children: not-inline
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (470.858978,89.5) content-size 190.282043x121 children: not-inline
|
||||
SVGGeometryBox <rect> at (471.358978,90) content-size 189.282043x120 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGSVGBox <svg> at (50,250) content-size 200x200 children: inline
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (120.088233,320.088256) content-size 59.823524x59.823528 children: not-inline
|
||||
SVGGeometryBox <rect> at (120.588233,320.588256) content-size 58.823524x58.823528 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (51.943771,309.873626) content-size 69.144462x69.144454 children: not-inline
|
||||
SVGGeometryBox <rect> at (52.443771,310.373626) content-size 68.144462x68.144454 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (178.911773,320.981903) content-size 69.14447x69.144462 children: not-inline
|
||||
SVGGeometryBox <rect> at (179.411773,321.481903) content-size 68.14447x68.144462 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGSVGBox <svg> at (258,250) content-size 200x200 children: inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <circle> at (277.5,269.5) content-size 161x161 children: not-inline
|
||||
SVGGeometryBox <circle> at (278,270) content-size 160x160 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <circle> at (337.5,269.5) content-size 41x161 children: not-inline
|
||||
SVGGeometryBox <circle> at (338,270) content-size 40x160 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <circle> at (277.5,329.5) content-size 161x41 children: not-inline
|
||||
SVGGeometryBox <circle> at (278,330) content-size 160x40 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <circle> at (337.5,329.5) content-size 41x41 children: not-inline
|
||||
SVGGeometryBox <circle> at (338,330) content-size 40x40 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGSVGBox <svg> at (466,250) content-size 200x200 children: inline
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (505.5,289.5) content-size 121x121 children: not-inline
|
||||
SVGGeometryBox <rect> at (506,290) content-size 120x120 children: not-inline
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (505.5,254.858978) content-size 121x190.282043 children: not-inline
|
||||
SVGGeometryBox <rect> at (506,255.358978) content-size 120x189.282043 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGSVGBox <svg> at (50,450) content-size 200x200 children: inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (59.5,459.5) content-size 81x81 children: not-inline
|
||||
SVGGeometryBox <rect> at (60,460) content-size 80x80 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (159.5,459.5) content-size 81x81 children: not-inline
|
||||
SVGGeometryBox <rect> at (160,460) content-size 80x80 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (59.5,559.5) content-size 81x81 children: not-inline
|
||||
SVGGeometryBox <rect> at (60,560) content-size 80x80 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
SVGGeometryBox <rect> at (159.5,559.5) content-size 81x81 children: not-inline
|
||||
SVGGeometryBox <rect> at (160,560) content-size 80x80 children: not-inline
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
|
|
|
@ -87,7 +87,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode, [[maybe_unused]] Avai
|
|||
|
||||
// Stroke increases the path's size by stroke_width/2 per side.
|
||||
auto path_bounding_box = transform.map(path.bounding_box()).to_type<CSSPixels>();
|
||||
CSSPixels stroke_width = geometry_box.dom_node().stroke_width().value_or(0);
|
||||
CSSPixels stroke_width = geometry_box.dom_node().visible_stroke_width() * viewbox_scale;
|
||||
path_bounding_box.inflate(stroke_width, stroke_width);
|
||||
geometry_box_state.set_content_offset(path_bounding_box.top_left() + offset);
|
||||
geometry_box_state.set_content_width(path_bounding_box.width());
|
||||
|
|
|
@ -38,6 +38,8 @@ Optional<Gfx::AffineTransform> SVGGeometryBox::layout_transform() const
|
|||
// we now have to derive what it was from the original bounding box size.
|
||||
// FIXME: It would be nice if we could store the transform from layout somewhere, so we don't have to solve for it here.
|
||||
auto original_bounding_box = Gfx::AffineTransform {}.translate(-origin).multiply(transform).map(const_cast<SVG::SVGGeometryElement&>(geometry_element).get_path().bounding_box());
|
||||
float stroke_width = geometry_element.visible_stroke_width();
|
||||
original_bounding_box.inflate(stroke_width, stroke_width);
|
||||
// If the transform (or path) results in a empty box we can't display this.
|
||||
if (original_bounding_box.is_empty())
|
||||
return {};
|
||||
|
|
|
@ -71,7 +71,9 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const
|
|||
auto transform = layout_box().layout_transform();
|
||||
if (!transform.has_value())
|
||||
return;
|
||||
Gfx::Path path = const_cast<SVG::SVGGeometryElement&>(geometry_element).get_path().copy_transformed(Gfx::AffineTransform {}.scale(css_scale, css_scale).multiply(*transform));
|
||||
|
||||
auto paint_transform = Gfx::AffineTransform {}.scale(css_scale, css_scale).multiply(*transform);
|
||||
Gfx::Path path = const_cast<SVG::SVGGeometryElement&>(geometry_element).get_path().copy_transformed(paint_transform);
|
||||
|
||||
if (auto fill_color = geometry_element.fill_color().value_or(svg_context.fill_color()); fill_color.alpha() > 0) {
|
||||
// We need to fill the path before applying the stroke, however the filled
|
||||
|
@ -91,7 +93,8 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const
|
|||
painter.stroke_path(
|
||||
path,
|
||||
stroke_color,
|
||||
geometry_element.stroke_width().value_or(svg_context.stroke_width()) * context.device_pixels_per_css_pixel());
|
||||
// Note: This is assuming .x_scale() == .y_scale() (which it does currently).
|
||||
geometry_element.stroke_width().value_or(svg_context.stroke_width()) * paint_transform.x_scale());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,13 @@ public:
|
|||
Optional<Gfx::Color> stroke_color() const;
|
||||
Optional<float> stroke_width() const;
|
||||
|
||||
float visible_stroke_width() const
|
||||
{
|
||||
if (auto color = stroke_color(); color.has_value() && color->alpha() > 0)
|
||||
return stroke_width().value_or(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Gfx::AffineTransform get_transform() const;
|
||||
|
||||
protected:
|
||||
|
|
Loading…
Add table
Reference in a new issue