diff --git a/Tests/LibWeb/Layout/expected/svg-preserve-aspect-ratio.txt b/Tests/LibWeb/Layout/expected/svg-preserve-aspect-ratio.txt index 5374a27c16..c3c133045d 100644 --- a/Tests/LibWeb/Layout/expected/svg-preserve-aspect-ratio.txt +++ b/Tests/LibWeb/Layout/expected/svg-preserve-aspect-ratio.txt @@ -98,7 +98,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline TextNode <#text> SVGSVGBox at (249,201) content-size 160x60 [SVG] children: inline TextNode <#text> - SVGGeometryBox at (299,201) content-size 60x60 children: not-inline + SVGGeometryBox at (249,201) content-size 160x60 children: not-inline TextNode <#text> TextNode <#text> @@ -141,4 +141,4 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] SVGPathPaintable (SVGGeometryBox) [114,136 125x125] TextPaintable (TextNode<#text>) SVGSVGPaintable (SVGSVGBox) [248,200 162x62] - SVGPathPaintable (SVGGeometryBox) [299,201 60x60] + SVGPathPaintable (SVGGeometryBox) [249,201 160x60] diff --git a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp index 2986807712..76dafe8dc7 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp @@ -46,7 +46,8 @@ CSSPixels SVGFormattingContext::automatic_content_height() const struct ViewBoxTransform { CSSPixelPoint offset; - double scale_factor; + double scale_factor_x; + double scale_factor_y; }; // https://svgwg.org/svg2-draft/coords.html#PreserveAspectRatioAttribute @@ -55,20 +56,27 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio { ViewBoxTransform viewbox_transform {}; + if (preserve_aspect_ratio.align == SVG::PreserveAspectRatio::Align::None) { + viewbox_transform.scale_factor_x = viewbox_scale.width(); + viewbox_transform.scale_factor_y = viewbox_scale.height(); + viewbox_transform.offset = {}; + return viewbox_transform; + } + switch (preserve_aspect_ratio.meet_or_slice) { case SVG::PreserveAspectRatio::MeetOrSlice::Meet: // meet (the default) - Scale the graphic such that: // - aspect ratio is preserved // - the entire ‘viewBox’ is visible within the SVG viewport // - the ‘viewBox’ is scaled up as much as possible, while still meeting the other criteria - viewbox_transform.scale_factor = min(viewbox_scale.width(), viewbox_scale.height()); + viewbox_transform.scale_factor_x = viewbox_transform.scale_factor_y = min(viewbox_scale.width(), viewbox_scale.height()); break; case SVG::PreserveAspectRatio::MeetOrSlice::Slice: // slice - Scale the graphic such that: // aspect ratio is preserved // the entire SVG viewport is covered by the ‘viewBox’ // the ‘viewBox’ is scaled down as much as possible, while still meeting the other criteria - viewbox_transform.scale_factor = max(viewbox_scale.width(), viewbox_scale.height()); + viewbox_transform.scale_factor_x = viewbox_transform.scale_factor_y = max(viewbox_scale.width(), viewbox_scale.height()); break; default: VERIFY_NOT_REACHED(); @@ -93,13 +101,13 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio case SVG::PreserveAspectRatio::Align::xMidYMid: case SVG::PreserveAspectRatio::Align::xMidYMax: // Align the midpoint X value of the element's ‘viewBox’ with the midpoint X value of the SVG viewport. - viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor)) / 2, 0); + viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor_x)) / 2, 0); break; case SVG::PreserveAspectRatio::Align::xMaxYMin: case SVG::PreserveAspectRatio::Align::xMaxYMid: case SVG::PreserveAspectRatio::Align::xMaxYMax: // Align the + of the element's ‘viewBox’ with the maximum X value of the SVG viewport. - viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor)), 0); + viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor_x)), 0); break; default: VERIFY_NOT_REACHED(); @@ -124,13 +132,13 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio case SVG::PreserveAspectRatio::Align::xMidYMid: case SVG::PreserveAspectRatio::Align::xMaxYMid: // Align the midpoint Y value of the element's ‘viewBox’ with the midpoint Y value of the SVG viewport. - viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor)) / 2); + viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor_y)) / 2); break; case SVG::PreserveAspectRatio::Align::xMinYMax: case SVG::PreserveAspectRatio::Align::xMidYMax: case SVG::PreserveAspectRatio::Align::xMaxYMax: // Align the + of the element's ‘viewBox’ with the maximum Y value of the SVG viewport. - viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor))); + viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor_y))); break; default: VERIFY_NOT_REACHED(); @@ -232,7 +240,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available CSSPixelPoint offset = viewbox_offset_and_scale.offset; return Gfx::AffineTransform { m_parent_viewbox_transform }.multiply(Gfx::AffineTransform {} .translate(offset.to_type()) - .scale(viewbox_offset_and_scale.scale_factor, viewbox_offset_and_scale.scale_factor) + .scale(viewbox_offset_and_scale.scale_factor_x, viewbox_offset_and_scale.scale_factor_y) .translate({ -viewbox->min_x, -viewbox->min_y })); }();