From 4073a20191512c023032ff164c90a5b69ee37ee0 Mon Sep 17 00:00:00 2001 From: longsonr Date: Wed, 3 Jul 2024 15:42:09 +0000 Subject: [PATCH] Bug 1905023 - viewBox values need to be adjusted in the presence of CSS zoom r=emilio Differential Revision: https://phabricator.services.mozilla.com/D215300 --- dom/svg/SVGAnimatedViewBox.h | 3 +++ dom/svg/SVGMarkerElement.cpp | 3 ++- dom/svg/SVGViewportElement.cpp | 19 ++++++++++--------- layout/svg/SVGOuterSVGFrame.cpp | 9 ++++++--- layout/svg/SVGPatternFrame.cpp | 3 ++- .../css-viewport/zoom/svg-viewBox-ref.html | 7 +++++++ .../css/css-viewport/zoom/svg-viewBox.html | 10 ++++++++++ 7 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 testing/web-platform/tests/css/css-viewport/zoom/svg-viewBox-ref.html create mode 100644 testing/web-platform/tests/css/css-viewport/zoom/svg-viewBox.html diff --git a/dom/svg/SVGAnimatedViewBox.h b/dom/svg/SVGAnimatedViewBox.h index ad550b6462e6..97c09b956270 100644 --- a/dom/svg/SVGAnimatedViewBox.h +++ b/dom/svg/SVGAnimatedViewBox.h @@ -34,6 +34,9 @@ struct SVGViewBox { SVGViewBox(float aX, float aY, float aWidth, float aHeight) : x(aX), y(aY), width(aWidth), height(aHeight), none(false) {} bool operator==(const SVGViewBox& aOther) const; + SVGViewBox operator*(const float m) const { + return SVGViewBox(x * m, y * m, width * m, height * m); + } static nsresult FromString(const nsAString& aStr, SVGViewBox* aViewBox); }; diff --git a/dom/svg/SVGMarkerElement.cpp b/dom/svg/SVGMarkerElement.cpp index 96b471faceae..4cd876da0a39 100644 --- a/dom/svg/SVGMarkerElement.cpp +++ b/dom/svg/SVGMarkerElement.cpp @@ -178,7 +178,8 @@ gfx::Matrix SVGMarkerElement::GetMarkerTransform(float aStrokeWidth, SVGViewBox SVGMarkerElement::GetViewBox() { if (mViewBox.HasRect()) { - return mViewBox.GetAnimValue(); + float zoom = UserSpaceMetrics::GetZoom(this); + return mViewBox.GetAnimValue() * zoom; } return SVGViewBox( 0, 0, mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx), diff --git a/dom/svg/SVGViewportElement.cpp b/dom/svg/SVGViewportElement.cpp index 52322abde9c5..bbc8823dc3a1 100644 --- a/dom/svg/SVGViewportElement.cpp +++ b/dom/svg/SVGViewportElement.cpp @@ -183,19 +183,18 @@ gfx::Matrix SVGViewportElement::GetViewBoxTransform() const { // SVGViewportElement float SVGViewportElement::GetLength(uint8_t aCtxType) const { - const SVGViewBox* viewbox = GetViewBoxInternal().HasRect() - ? &GetViewBoxInternal().GetAnimValue() - : nullptr; - + const auto& animatedViewBox = GetViewBoxInternal(); float h = 0.0f, w = 0.0f; bool shouldComputeWidth = (aCtxType == SVGContentUtils::X || aCtxType == SVGContentUtils::XY), shouldComputeHeight = (aCtxType == SVGContentUtils::Y || aCtxType == SVGContentUtils::XY); - if (viewbox) { - w = viewbox->width; - h = viewbox->height; + if (animatedViewBox.HasRect()) { + float zoom = UserSpaceMetrics::GetZoom(this); + const auto& viewbox = animatedViewBox.GetAnimValue() * zoom; + w = viewbox.width; + h = viewbox.height; } else if (IsInner()) { // Resolving length for inner is exactly the same as other // ordinary element. We shouldn't use the SVGViewportElement overload @@ -317,8 +316,10 @@ bool SVGViewportElement::ShouldSynthesizeViewBox() const { SVGViewBox SVGViewportElement::GetViewBoxWithSynthesis( float aViewportWidth, float aViewportHeight) const { - if (GetViewBoxInternal().HasRect()) { - return GetViewBoxInternal().GetAnimValue(); + const auto& animatedViewBox = GetViewBoxInternal(); + if (animatedViewBox.HasRect()) { + float zoom = UserSpaceMetrics::GetZoom(this); + return animatedViewBox.GetAnimValue() * zoom; } if (ShouldSynthesizeViewBox()) { diff --git a/layout/svg/SVGOuterSVGFrame.cpp b/layout/svg/SVGOuterSVGFrame.cpp index 432719291f06..c9c29162e800 100644 --- a/layout/svg/SVGOuterSVGFrame.cpp +++ b/layout/svg/SVGOuterSVGFrame.cpp @@ -222,8 +222,10 @@ AspectRatio SVGOuterSVGFrame::GetIntrinsicRatio() const { // 2. width and height are non-negative numbers. // Otherwise, we use the viewbox rect. // https://github.com/w3c/csswg-drafts/issues/6286 - const float w = width.GetAnimValue(content); - const float h = height.GetAnimValue(content); + // Note width/height may have different units and therefore be + // affected by zoom in different ways. + const float w = width.GetAnimValueWithZoom(content); + const float h = height.GetAnimValueWithZoom(content); if (w > 0.0f && h > 0.0f) { return AspectRatio::FromSize(w, h); } @@ -231,7 +233,8 @@ AspectRatio SVGOuterSVGFrame::GetIntrinsicRatio() const { const auto& viewBox = content->GetViewBoxInternal(); if (viewBox.HasRect()) { - const auto& anim = viewBox.GetAnimValue(); + float zoom = Style()->EffectiveZoom().ToFloat(); + const auto& anim = viewBox.GetAnimValue() * zoom; return AspectRatio::FromSize(anim.width, anim.height); } diff --git a/layout/svg/SVGPatternFrame.cpp b/layout/svg/SVGPatternFrame.cpp index 80a6b7f6e308..4d80fa3d8bd4 100644 --- a/layout/svg/SVGPatternFrame.cpp +++ b/layout/svg/SVGPatternFrame.cpp @@ -633,7 +633,8 @@ gfxMatrix SVGPatternFrame::ConstructCTM(const SVGAnimatedViewBox& aViewBox, if (!aViewBox.IsExplicitlySet()) { return gfxMatrix(scaleX, 0.0, 0.0, scaleY, 0.0, 0.0); } - const SVGViewBox& viewBox = aViewBox.GetAnimValue(); + const SVGViewBox& viewBox = + aViewBox.GetAnimValue() * Style()->EffectiveZoom().ToFloat(); if (viewBox.height <= 0.0f || viewBox.width <= 0.0f) { return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular diff --git a/testing/web-platform/tests/css/css-viewport/zoom/svg-viewBox-ref.html b/testing/web-platform/tests/css/css-viewport/zoom/svg-viewBox-ref.html new file mode 100644 index 000000000000..b58eb47a23c4 --- /dev/null +++ b/testing/web-platform/tests/css/css-viewport/zoom/svg-viewBox-ref.html @@ -0,0 +1,7 @@ + +
+ + + + +
diff --git a/testing/web-platform/tests/css/css-viewport/zoom/svg-viewBox.html b/testing/web-platform/tests/css/css-viewport/zoom/svg-viewBox.html new file mode 100644 index 000000000000..d5c2336bdd04 --- /dev/null +++ b/testing/web-platform/tests/css/css-viewport/zoom/svg-viewBox.html @@ -0,0 +1,10 @@ + + + + + + + + + +