diff --git a/dom/svg/SVGAnimatedLength.cpp b/dom/svg/SVGAnimatedLength.cpp index 16069bfdaf7a..b31f739282a6 100644 --- a/dom/svg/SVGAnimatedLength.cpp +++ b/dom/svg/SVGAnimatedLength.cpp @@ -376,31 +376,37 @@ float UserSpaceMetricsWithSize::GetAxisLength(uint8_t aCtxType) const { float SVGAnimatedLength::GetPixelsPerUnit(const SVGElement* aSVGElement, uint8_t aUnitType) const { return SVGLength::GetPixelsPerUnit(SVGElementMetrics(aSVGElement), aUnitType, - mCtxType); + mCtxType, false); } -float SVGAnimatedLength::GetPixelsPerUnit(const SVGViewportElement* aCtx, - uint8_t aUnitType) const { +float SVGAnimatedLength::GetPixelsPerUnitWithZoom(const SVGElement* aSVGElement, + uint8_t aUnitType) const { + return SVGLength::GetPixelsPerUnit(SVGElementMetrics(aSVGElement), aUnitType, + mCtxType, true); +} + +float SVGAnimatedLength::GetPixelsPerUnitWithZoom( + const SVGViewportElement* aCtx, uint8_t aUnitType) const { return SVGLength::GetPixelsPerUnit(SVGElementMetrics(aCtx, aCtx), aUnitType, - mCtxType); + mCtxType, true); } -float SVGAnimatedLength::GetPixelsPerUnit(nsIFrame* aFrame, - uint8_t aUnitType) const { +float SVGAnimatedLength::GetPixelsPerUnitWithZoom(nsIFrame* aFrame, + uint8_t aUnitType) const { const nsIContent* content = aFrame->GetContent(); MOZ_ASSERT(!content->IsText(), "Not expecting text content"); if (content->IsSVGElement()) { return SVGLength::GetPixelsPerUnit( SVGElementMetrics(static_cast(content)), aUnitType, - mCtxType); + mCtxType, true); } return SVGLength::GetPixelsPerUnit(NonSVGFrameUserSpaceMetrics(aFrame), - aUnitType, mCtxType); + aUnitType, mCtxType, true); } -float SVGAnimatedLength::GetPixelsPerUnit(const UserSpaceMetrics& aMetrics, - uint8_t aUnitType) const { - return SVGLength::GetPixelsPerUnit(aMetrics, aUnitType, mCtxType); +float SVGAnimatedLength::GetPixelsPerUnitWithZoom( + const UserSpaceMetrics& aMetrics, uint8_t aUnitType) const { + return SVGLength::GetPixelsPerUnit(aMetrics, aUnitType, mCtxType, true); } void SVGAnimatedLength::SetBaseValueInSpecifiedUnits(float aValue, @@ -653,7 +659,7 @@ float SVGLengthAndInfo::ConvertUnits(const SVGLengthAndInfo& aTo) const { float SVGLengthAndInfo::ValueInPixels(const UserSpaceMetrics& aMetrics) const { return mValue == 0.0f ? 0.0f : mValue * SVGLength::GetPixelsPerUnit( - aMetrics, mUnitType, mCtxType); + aMetrics, mUnitType, mCtxType, false); } void SVGLengthAndInfo::Add(const SVGLengthAndInfo& aValueToAdd, @@ -673,7 +679,7 @@ void SVGLengthAndInfo::Add(const SVGLengthAndInfo& aValueToAdd, mUnitType = aValueToAdd.mUnitType; mCtxType = aValueToAdd.mCtxType; mValue = (currentLength + lengthToAdd) / - SVGLength::GetPixelsPerUnit(metrics, mUnitType, mCtxType); + SVGLength::GetPixelsPerUnit(metrics, mUnitType, mCtxType, false); } void SVGLengthAndInfo::Interpolate(const SVGLengthAndInfo& aStart, diff --git a/dom/svg/SVGAnimatedLength.h b/dom/svg/SVGAnimatedLength.h index f6e55d598cf5..0c33298b8127 100644 --- a/dom/svg/SVGAnimatedLength.h +++ b/dom/svg/SVGAnimatedLength.h @@ -151,14 +151,17 @@ class SVGAnimatedLength { float GetAnimValue(const SVGElement* aSVGElement) const { return mAnimVal * GetPixelsPerUnit(aSVGElement, mAnimUnitType); } - float GetAnimValue(nsIFrame* aFrame) const { - return mAnimVal * GetPixelsPerUnit(aFrame, mAnimUnitType); + float GetAnimValueWithZoom(const SVGElement* aSVGElement) const { + return mAnimVal * GetPixelsPerUnitWithZoom(aSVGElement, mAnimUnitType); } - float GetAnimValue(const SVGViewportElement* aCtx) const { - return mAnimVal * GetPixelsPerUnit(aCtx, mAnimUnitType); + float GetAnimValueWithZoom(nsIFrame* aFrame) const { + return mAnimVal * GetPixelsPerUnitWithZoom(aFrame, mAnimUnitType); } - float GetAnimValue(const UserSpaceMetrics& aMetrics) const { - return mAnimVal * GetPixelsPerUnit(aMetrics, mAnimUnitType); + float GetAnimValueWithZoom(const SVGViewportElement* aCtx) const { + return mAnimVal * GetPixelsPerUnitWithZoom(aCtx, mAnimUnitType); + } + float GetAnimValueWithZoom(const UserSpaceMetrics& aMetrics) const { + return mAnimVal * GetPixelsPerUnitWithZoom(aMetrics, mAnimUnitType); } uint8_t GetCtxType() const { return mCtxType; } @@ -197,13 +200,15 @@ class SVGAnimatedLength { // These APIs returns the number of user-unit pixels per unit of the // given type, in a given context (frame/element/etc). - float GetPixelsPerUnit(nsIFrame* aFrame, uint8_t aUnitType) const; - float GetPixelsPerUnit(const UserSpaceMetrics& aMetrics, - uint8_t aUnitType) const; float GetPixelsPerUnit(const SVGElement* aSVGElement, uint8_t aUnitType) const; - float GetPixelsPerUnit(const SVGViewportElement* aCtx, - uint8_t aUnitType) const; + float GetPixelsPerUnitWithZoom(nsIFrame* aFrame, uint8_t aUnitType) const; + float GetPixelsPerUnitWithZoom(const UserSpaceMetrics& aMetrics, + uint8_t aUnitType) const; + float GetPixelsPerUnitWithZoom(const SVGElement* aSVGElement, + uint8_t aUnitType) const; + float GetPixelsPerUnitWithZoom(const SVGViewportElement* aCtx, + uint8_t aUnitType) const; // SetBaseValue and SetAnimValue set the value in user units. This may fail // if unit conversion fails e.g. conversion to ex or em units where the diff --git a/dom/svg/SVGElement.cpp b/dom/svg/SVGElement.cpp index 213bc6be0e4d..4662d28bbf67 100644 --- a/dom/svg/SVGElement.cpp +++ b/dom/svg/SVGElement.cpp @@ -1559,7 +1559,7 @@ void SVGElement::GetAnimatedLengthValues(float* aFirst, ...) { va_start(args, aFirst); while (f && i < info.mCount) { - *f = info.mValues[i++].GetAnimValue(metrics); + *f = info.mValues[i++].GetAnimValueWithZoom(metrics); f = va_arg(args, float*); } diff --git a/dom/svg/SVGLength.cpp b/dom/svg/SVGLength.cpp index ec3c4dc9861e..d61d4439b935 100644 --- a/dom/svg/SVGLength.cpp +++ b/dom/svg/SVGLength.cpp @@ -165,7 +165,8 @@ enum class ZoomType { Self, SelfFromRoot, None }; /*static*/ float SVGLength::GetPixelsPerUnit(const UserSpaceMetrics& aMetrics, - uint8_t aUnitType, uint8_t aAxis) { + uint8_t aUnitType, uint8_t aAxis, + bool aApplyZoom) { auto zoomType = ZoomType::Self; float value = [&]() -> float { switch (aUnitType) { @@ -216,15 +217,17 @@ float SVGLength::GetPixelsPerUnit(const UserSpaceMetrics& aMetrics, return GetAbsUnitsPerAbsUnit(SVG_LENGTHTYPE_PX, aUnitType); } }(); - switch (zoomType) { - case ZoomType::None: - break; - case ZoomType::Self: - value *= aMetrics.GetZoom(); - break; - case ZoomType::SelfFromRoot: - value *= aMetrics.GetZoom() / aMetrics.GetRootZoom(); - break; + if (aApplyZoom) { + switch (zoomType) { + case ZoomType::None: + break; + case ZoomType::Self: + value *= aMetrics.GetZoom(); + break; + case ZoomType::SelfFromRoot: + value *= aMetrics.GetZoom() / aMetrics.GetRootZoom(); + break; + } } return value; } diff --git a/dom/svg/SVGLength.h b/dom/svg/SVGLength.h index f2b06315488f..d9826a0ed91c 100644 --- a/dom/svg/SVGLength.h +++ b/dom/svg/SVGLength.h @@ -93,9 +93,14 @@ class SVGLength { bool IsPercentage() const { return IsPercentageUnit(mUnit); } + float GetPixelsPerUnitWithZoom(const dom::UserSpaceMetrics& aMetrics, + uint8_t aAxis) const { + return GetPixelsPerUnit(aMetrics, mUnit, aAxis, true); + } + float GetPixelsPerUnit(const dom::UserSpaceMetrics& aMetrics, uint8_t aAxis) const { - return GetPixelsPerUnit(aMetrics, mUnit, aAxis); + return GetPixelsPerUnit(aMetrics, mUnit, aAxis, false); } static bool IsValidUnitType(uint16_t aUnitType) { @@ -123,7 +128,8 @@ class SVGLength { * Returns the number of pixels per given unit. */ static float GetPixelsPerUnit(const dom::UserSpaceMetrics& aMetrics, - uint8_t aUnitType, uint8_t aAxis); + uint8_t aUnitType, uint8_t aAxis, + bool aApplyZoom); private: float mValue; diff --git a/dom/svg/SVGMarkerElement.cpp b/dom/svg/SVGMarkerElement.cpp index 5467c4ac11cb..96b471faceae 100644 --- a/dom/svg/SVGMarkerElement.cpp +++ b/dom/svg/SVGMarkerElement.cpp @@ -180,17 +180,17 @@ SVGViewBox SVGMarkerElement::GetViewBox() { if (mViewBox.HasRect()) { return mViewBox.GetAnimValue(); } - return SVGViewBox(0, 0, - mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx), - mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx)); + return SVGViewBox( + 0, 0, mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx), + mLengthAttributes[MARKERHEIGHT].GetAnimValueWithZoom(mCoordCtx)); } gfx::Matrix SVGMarkerElement::GetViewBoxTransform() { if (!mViewBoxToViewportTransform) { float viewportWidth = - mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx); + mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx); float viewportHeight = - mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx); + mLengthAttributes[MARKERHEIGHT].GetAnimValueWithZoom(mCoordCtx); SVGViewBox viewbox = GetViewBox(); @@ -201,8 +201,8 @@ gfx::Matrix SVGMarkerElement::GetViewBoxTransform() { viewportWidth, viewportHeight, viewbox.x, viewbox.y, viewbox.width, viewbox.height, mPreserveAspectRatio); - float refX = mLengthAttributes[REFX].GetAnimValue(mCoordCtx); - float refY = mLengthAttributes[REFY].GetAnimValue(mCoordCtx); + float refX = mLengthAttributes[REFX].GetAnimValueWithZoom(mCoordCtx); + float refY = mLengthAttributes[REFY].GetAnimValueWithZoom(mCoordCtx); gfx::Point ref = viewBoxTM.TransformPoint(gfx::Point(refX, refY)); diff --git a/dom/svg/SVGSVGElement.cpp b/dom/svg/SVGSVGElement.cpp index 04f5b8662e43..a44c974ccc76 100644 --- a/dom/svg/SVGSVGElement.cpp +++ b/dom/svg/SVGSVGElement.cpp @@ -396,7 +396,7 @@ LengthPercentage SVGSVGElement::GetIntrinsicWidthOrHeight(int aAttr) { // that uses the passed argument as the context, but that's fine since we // know the length isn't a percentage so the context won't be used (and we // need to pass the element to be able to resolve em/ex units). - float rawSize = mLengthAttributes[aAttr].GetAnimValue(this); + float rawSize = mLengthAttributes[aAttr].GetAnimValueWithZoom(this); return LengthPercentage::FromPixels(rawSize); } diff --git a/dom/svg/SVGViewportElement.cpp b/dom/svg/SVGViewportElement.cpp index a98c7fb44310..52322abde9c5 100644 --- a/dom/svg/SVGViewportElement.cpp +++ b/dom/svg/SVGViewportElement.cpp @@ -105,7 +105,7 @@ inline float ComputeSynthesizedViewBoxDimension( return aViewportLength * aLength.GetAnimValInSpecifiedUnits() / 100.0f; } - return aLength.GetAnimValue(aSelf); + return aLength.GetAnimValueWithZoom(aSelf); } //---------------------------------------------------------------------- @@ -155,8 +155,9 @@ gfx::Matrix SVGViewportElement::GetViewBoxTransform() const { float viewportWidth, viewportHeight; if (IsInner()) { SVGElementMetrics metrics(this); - viewportWidth = mLengthAttributes[ATTR_WIDTH].GetAnimValue(metrics); - viewportHeight = mLengthAttributes[ATTR_HEIGHT].GetAnimValue(metrics); + viewportWidth = mLengthAttributes[ATTR_WIDTH].GetAnimValueWithZoom(metrics); + viewportHeight = + mLengthAttributes[ATTR_HEIGHT].GetAnimValueWithZoom(metrics); } else { viewportWidth = mViewportSize.width; viewportHeight = mViewportSize.height; @@ -201,10 +202,10 @@ float SVGViewportElement::GetLength(uint8_t aCtxType) const { // of GetAnimValue(). SVGElementMetrics metrics(this); if (shouldComputeWidth) { - w = mLengthAttributes[ATTR_WIDTH].GetAnimValue(metrics); + w = mLengthAttributes[ATTR_WIDTH].GetAnimValueWithZoom(metrics); } if (shouldComputeHeight) { - h = mLengthAttributes[ATTR_HEIGHT].GetAnimValue(metrics); + h = mLengthAttributes[ATTR_HEIGHT].GetAnimValueWithZoom(metrics); } } else if (ShouldSynthesizeViewBox()) { if (shouldComputeWidth) { diff --git a/dom/svg/test/test_length.xhtml b/dom/svg/test/test_length.xhtml index 513c65cbb213..34ea69424686 100644 --- a/dom/svg/test/test_length.xhtml +++ b/dom/svg/test/test_length.xhtml @@ -20,6 +20,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=342513 +
+ + + +
@@ -34,7 +39,7 @@ function run() { var divElem = document.getElementById("div"); var expectedWidth = divElem.clientWidth; // test for the pixel width of the svg - is(svgDoc.width.baseVal.value, expectedWidth, "svgDoc.width.baseVal.value"); + isfuzzy(svgDoc.width.baseVal.value, expectedWidth, 0.01, "svgDoc.width.baseVal.value"); // set the SVG width to ~50% in pixels svgDoc.width.baseVal.newValueSpecifiedUnits(svgDoc.width.baseVal.SVG_LENGTHTYPE_PX, Math.floor(expectedWidth / 2)); @@ -46,6 +51,10 @@ function run() { is(r1.width.baseVal.value, 40, "width in em for elements inside inner should be resolved against the inner "); is(r1.height.baseVal.value, 60, "height in em for elements inside inner should be resolved against the inner "); + let r2 = document.getElementById("r2"); + is(r2.width.baseVal.value, 25, "width in px for elements in zoomed div should be the same as unzoomed"); + is(r2.height.baseVal.value, 20, "height in px for elements inside zoomed div should be the same as unzoomed"); + SimpleTest.finish(); } diff --git a/layout/svg/SVGGradientFrame.cpp b/layout/svg/SVGGradientFrame.cpp index be6f395cda79..8b847ad177dd 100644 --- a/layout/svg/SVGGradientFrame.cpp +++ b/layout/svg/SVGGradientFrame.cpp @@ -455,7 +455,7 @@ float SVGLinearGradientFrame::GetLengthValue(uint32_t aIndex) { NS_ASSERTION(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, "Unknown gradientUnits type"); - return length.GetAnimValue(static_cast(nullptr)); + return length.GetAnimValueWithZoom(static_cast(nullptr)); } dom::SVGLinearGradientElement* @@ -557,7 +557,7 @@ float SVGRadialGradientFrame::GetLengthValueFromElement( NS_ASSERTION(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, "Unknown gradientUnits type"); - return length.GetAnimValue(static_cast(nullptr)); + return length.GetAnimValueWithZoom(static_cast(nullptr)); } dom::SVGRadialGradientElement* diff --git a/layout/svg/SVGOuterSVGFrame.cpp b/layout/svg/SVGOuterSVGFrame.cpp index 00d766390138..e054c3c6e9da 100644 --- a/layout/svg/SVGOuterSVGFrame.cpp +++ b/layout/svg/SVGOuterSVGFrame.cpp @@ -158,7 +158,8 @@ nscoord SVGOuterSVGFrame::GetPrefISize(gfxContext* aRenderingContext) { result = nscoord(0); } } else { - result = nsPresContext::CSSPixelsToAppUnits(isize.GetAnimValue(svg)); + result = + nsPresContext::CSSPixelsToAppUnits(isize.GetAnimValueWithZoom(svg)); if (result < 0) { result = nscoord(0); } @@ -189,13 +190,13 @@ IntrinsicSize SVGOuterSVGFrame::GetIntrinsicSize() { if (!width.IsPercentage()) { nscoord val = - nsPresContext::CSSPixelsToAppUnits(width.GetAnimValue(content)); + nsPresContext::CSSPixelsToAppUnits(width.GetAnimValueWithZoom(content)); intrinsicSize.width.emplace(std::max(val, 0)); } if (!height.IsPercentage()) { - nscoord val = - nsPresContext::CSSPixelsToAppUnits(height.GetAnimValue(content)); + nscoord val = nsPresContext::CSSPixelsToAppUnits( + height.GetAnimValueWithZoom(content)); intrinsicSize.height.emplace(std::max(val, 0)); } diff --git a/layout/svg/SVGPatternFrame.cpp b/layout/svg/SVGPatternFrame.cpp index da7d0ce592fd..80a6b7f6e308 100644 --- a/layout/svg/SVGPatternFrame.cpp +++ b/layout/svg/SVGPatternFrame.cpp @@ -644,16 +644,16 @@ gfxMatrix SVGPatternFrame::ConstructCTM(const SVGAnimatedViewBox& aViewBox, // If we're dealing with an SVG target only retrieve the context once. // Calling the nsIFrame* variant of GetAnimValue would look it up on // every call. - viewportWidth = - GetLengthValue(SVGPatternElement::ATTR_WIDTH)->GetAnimValue(ctx); - viewportHeight = - GetLengthValue(SVGPatternElement::ATTR_HEIGHT)->GetAnimValue(ctx); + viewportWidth = GetLengthValue(SVGPatternElement::ATTR_WIDTH) + ->GetAnimValueWithZoom(ctx); + viewportHeight = GetLengthValue(SVGPatternElement::ATTR_HEIGHT) + ->GetAnimValueWithZoom(ctx); } else { // No SVG target, call the nsIFrame* variant of GetAnimValue. - viewportWidth = - GetLengthValue(SVGPatternElement::ATTR_WIDTH)->GetAnimValue(aTarget); - viewportHeight = - GetLengthValue(SVGPatternElement::ATTR_HEIGHT)->GetAnimValue(aTarget); + viewportWidth = GetLengthValue(SVGPatternElement::ATTR_WIDTH) + ->GetAnimValueWithZoom(aTarget); + viewportHeight = GetLengthValue(SVGPatternElement::ATTR_HEIGHT) + ->GetAnimValueWithZoom(aTarget); } if (viewportWidth <= 0.0f || viewportHeight <= 0.0f) { diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index 09ed2c704320..2b14d55b01ec 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -4570,7 +4570,7 @@ gfxFloat SVGTextFrame::GetStartOffset(nsIFrame* aTextPathFrame) { 100.0 : 0.0; } - float lengthValue = length->GetAnimValue(tp); + float lengthValue = length->GetAnimValueWithZoom(tp); // If offsetScale is infinity we want to return 0 not NaN return lengthValue == 0 ? 0.0 : lengthValue * GetOffsetScale(aTextPathFrame); } @@ -4808,7 +4808,7 @@ void SVGTextFrame::DoGlyphPositioning() { element->EnumAttributes()[SVGTextContentElement::LENGTHADJUST] .GetAnimValue(); bool adjustingTextLength = textLengthAttr->IsExplicitlySet(); - float expectedTextLength = textLengthAttr->GetAnimValue(element); + float expectedTextLength = textLengthAttr->GetAnimValueWithZoom(element); if (adjustingTextLength && (expectedTextLength < 0.0f || lengthAdjust == LENGTHADJUST_UNKNOWN)) { diff --git a/layout/svg/SVGUtils.cpp b/layout/svg/SVGUtils.cpp index 727bf26a051d..11c9028fb58f 100644 --- a/layout/svg/SVGUtils.cpp +++ b/layout/svg/SVGUtils.cpp @@ -254,19 +254,20 @@ float SVGUtils::ObjectSpace(const gfxRect& aRect, // Multiply first to avoid precision errors: return axis * aLength->GetAnimValInSpecifiedUnits() / 100; } - return aLength->GetAnimValue(static_cast(nullptr)) * + return aLength->GetAnimValueWithZoom( + static_cast(nullptr)) * axis; } float SVGUtils::UserSpace(nsIFrame* aNonSVGContext, const SVGAnimatedLength* aLength) { MOZ_ASSERT(!aNonSVGContext->IsTextFrame(), "Not expecting text content"); - return aLength->GetAnimValue(aNonSVGContext); + return aLength->GetAnimValueWithZoom(aNonSVGContext); } float SVGUtils::UserSpace(const UserSpaceMetrics& aMetrics, const SVGAnimatedLength* aLength) { - return aLength->GetAnimValue(aMetrics); + return aLength->GetAnimValueWithZoom(aMetrics); } SVGOuterSVGFrame* SVGUtils::GetOuterSVGFrame(nsIFrame* aFrame) { diff --git a/testing/web-platform/tests/svg/types/scripted/SVGLength-zoom.html b/testing/web-platform/tests/svg/types/scripted/SVGLength-zoom.html new file mode 100644 index 000000000000..5b8cb16b94f3 --- /dev/null +++ b/testing/web-platform/tests/svg/types/scripted/SVGLength-zoom.html @@ -0,0 +1,17 @@ + +SVGLength in zoomed div + + + +
+ + + +
+