mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 15:38:10 +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
|
@ -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 <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;
|
||||
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 <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;
|
||||
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<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 }));
|
||||
}();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue