mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:37:46 +00:00
LibWeb: Support preserveAspectRatio=none
for SVGs
This is very easy now all transforms are computed during layout.
This commit is contained in:
parent
190a8f948e
commit
05f42efc06
2 changed files with 18 additions and 10 deletions
|
@ -98,7 +98,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
TextNode <#text>
|
TextNode <#text>
|
||||||
SVGSVGBox <svg> at (249,201) content-size 160x60 [SVG] children: inline
|
SVGSVGBox <svg> at (249,201) content-size 160x60 [SVG] children: inline
|
||||||
TextNode <#text>
|
TextNode <#text>
|
||||||
SVGGeometryBox <circle> at (299,201) content-size 60x60 children: not-inline
|
SVGGeometryBox <circle> at (249,201) content-size 160x60 children: not-inline
|
||||||
TextNode <#text>
|
TextNode <#text>
|
||||||
TextNode <#text>
|
TextNode <#text>
|
||||||
|
|
||||||
|
@ -141,4 +141,4 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
SVGPathPaintable (SVGGeometryBox<circle>) [114,136 125x125]
|
SVGPathPaintable (SVGGeometryBox<circle>) [114,136 125x125]
|
||||||
TextPaintable (TextNode<#text>)
|
TextPaintable (TextNode<#text>)
|
||||||
SVGSVGPaintable (SVGSVGBox<svg>) [248,200 162x62]
|
SVGSVGPaintable (SVGSVGBox<svg>) [248,200 162x62]
|
||||||
SVGPathPaintable (SVGGeometryBox<circle>) [299,201 60x60]
|
SVGPathPaintable (SVGGeometryBox<circle>) [249,201 160x60]
|
||||||
|
|
|
@ -46,7 +46,8 @@ CSSPixels SVGFormattingContext::automatic_content_height() const
|
||||||
|
|
||||||
struct ViewBoxTransform {
|
struct ViewBoxTransform {
|
||||||
CSSPixelPoint offset;
|
CSSPixelPoint offset;
|
||||||
double scale_factor;
|
double scale_factor_x;
|
||||||
|
double scale_factor_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://svgwg.org/svg2-draft/coords.html#PreserveAspectRatioAttribute
|
// https://svgwg.org/svg2-draft/coords.html#PreserveAspectRatioAttribute
|
||||||
|
@ -55,20 +56,27 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio
|
||||||
{
|
{
|
||||||
ViewBoxTransform viewbox_transform {};
|
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) {
|
switch (preserve_aspect_ratio.meet_or_slice) {
|
||||||
case SVG::PreserveAspectRatio::MeetOrSlice::Meet:
|
case SVG::PreserveAspectRatio::MeetOrSlice::Meet:
|
||||||
// meet (the default) - Scale the graphic such that:
|
// meet (the default) - Scale the graphic such that:
|
||||||
// - aspect ratio is preserved
|
// - aspect ratio is preserved
|
||||||
// - the entire ‘viewBox’ is visible within the SVG viewport
|
// - the entire ‘viewBox’ is visible within the SVG viewport
|
||||||
// - the ‘viewBox’ is scaled up as much as possible, while still meeting the other criteria
|
// - 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;
|
break;
|
||||||
case SVG::PreserveAspectRatio::MeetOrSlice::Slice:
|
case SVG::PreserveAspectRatio::MeetOrSlice::Slice:
|
||||||
// slice - Scale the graphic such that:
|
// slice - Scale the graphic such that:
|
||||||
// aspect ratio is preserved
|
// aspect ratio is preserved
|
||||||
// the entire SVG viewport is covered by the ‘viewBox’
|
// the entire SVG viewport is covered by the ‘viewBox’
|
||||||
// the ‘viewBox’ is scaled down as much as possible, while still meeting the other criteria
|
// 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;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
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::xMidYMid:
|
||||||
case SVG::PreserveAspectRatio::Align::xMidYMax:
|
case SVG::PreserveAspectRatio::Align::xMidYMax:
|
||||||
// Align the midpoint X value of the element's ‘viewBox’ with the midpoint X value of the SVG viewport.
|
// 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;
|
break;
|
||||||
case SVG::PreserveAspectRatio::Align::xMaxYMin:
|
case SVG::PreserveAspectRatio::Align::xMaxYMin:
|
||||||
case SVG::PreserveAspectRatio::Align::xMaxYMid:
|
case SVG::PreserveAspectRatio::Align::xMaxYMid:
|
||||||
case SVG::PreserveAspectRatio::Align::xMaxYMax:
|
case SVG::PreserveAspectRatio::Align::xMaxYMax:
|
||||||
// Align the <min-x>+<width> of the element's ‘viewBox’ with the maximum X value of the SVG viewport.
|
// Align the <min-x>+<width> 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;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
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::xMidYMid:
|
||||||
case SVG::PreserveAspectRatio::Align::xMaxYMid:
|
case SVG::PreserveAspectRatio::Align::xMaxYMid:
|
||||||
// Align the midpoint Y value of the element's ‘viewBox’ with the midpoint Y value of the SVG viewport.
|
// 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;
|
break;
|
||||||
case SVG::PreserveAspectRatio::Align::xMinYMax:
|
case SVG::PreserveAspectRatio::Align::xMinYMax:
|
||||||
case SVG::PreserveAspectRatio::Align::xMidYMax:
|
case SVG::PreserveAspectRatio::Align::xMidYMax:
|
||||||
case SVG::PreserveAspectRatio::Align::xMaxYMax:
|
case SVG::PreserveAspectRatio::Align::xMaxYMax:
|
||||||
// Align the <min-y>+<height> of the element's ‘viewBox’ with the maximum Y value of the SVG viewport.
|
// Align the <min-y>+<height> 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;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -232,7 +240,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available
|
||||||
CSSPixelPoint offset = viewbox_offset_and_scale.offset;
|
CSSPixelPoint offset = viewbox_offset_and_scale.offset;
|
||||||
return Gfx::AffineTransform { m_parent_viewbox_transform }.multiply(Gfx::AffineTransform {}
|
return Gfx::AffineTransform { m_parent_viewbox_transform }.multiply(Gfx::AffineTransform {}
|
||||||
.translate(offset.to_type<float>())
|
.translate(offset.to_type<float>())
|
||||||
.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 }));
|
.translate({ -viewbox->min_x, -viewbox->min_y }));
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue