Bug 1903352 - SVG attribute values should not be zoomed r=emilio a=RyanVM

Differential Revision: https://phabricator.services.mozilla.com/D214286
This commit is contained in:
longsonr 2024-06-20 14:56:29 +00:00
parent af63ccdbeb
commit dbf44bb672
15 changed files with 119 additions and 70 deletions

View file

@ -376,31 +376,37 @@ float UserSpaceMetricsWithSize::GetAxisLength(uint8_t aCtxType) const {
float SVGAnimatedLength::GetPixelsPerUnit(const SVGElement* aSVGElement, float SVGAnimatedLength::GetPixelsPerUnit(const SVGElement* aSVGElement,
uint8_t aUnitType) const { uint8_t aUnitType) const {
return SVGLength::GetPixelsPerUnit(SVGElementMetrics(aSVGElement), aUnitType, return SVGLength::GetPixelsPerUnit(SVGElementMetrics(aSVGElement), aUnitType,
mCtxType); mCtxType, false);
} }
float SVGAnimatedLength::GetPixelsPerUnit(const SVGViewportElement* aCtx, float SVGAnimatedLength::GetPixelsPerUnitWithZoom(const SVGElement* aSVGElement,
uint8_t aUnitType) const { 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, return SVGLength::GetPixelsPerUnit(SVGElementMetrics(aCtx, aCtx), aUnitType,
mCtxType); mCtxType, true);
} }
float SVGAnimatedLength::GetPixelsPerUnit(nsIFrame* aFrame, float SVGAnimatedLength::GetPixelsPerUnitWithZoom(nsIFrame* aFrame,
uint8_t aUnitType) const { uint8_t aUnitType) const {
const nsIContent* content = aFrame->GetContent(); const nsIContent* content = aFrame->GetContent();
MOZ_ASSERT(!content->IsText(), "Not expecting text content"); MOZ_ASSERT(!content->IsText(), "Not expecting text content");
if (content->IsSVGElement()) { if (content->IsSVGElement()) {
return SVGLength::GetPixelsPerUnit( return SVGLength::GetPixelsPerUnit(
SVGElementMetrics(static_cast<const SVGElement*>(content)), aUnitType, SVGElementMetrics(static_cast<const SVGElement*>(content)), aUnitType,
mCtxType); mCtxType, true);
} }
return SVGLength::GetPixelsPerUnit(NonSVGFrameUserSpaceMetrics(aFrame), return SVGLength::GetPixelsPerUnit(NonSVGFrameUserSpaceMetrics(aFrame),
aUnitType, mCtxType); aUnitType, mCtxType, true);
} }
float SVGAnimatedLength::GetPixelsPerUnit(const UserSpaceMetrics& aMetrics, float SVGAnimatedLength::GetPixelsPerUnitWithZoom(
uint8_t aUnitType) const { const UserSpaceMetrics& aMetrics, uint8_t aUnitType) const {
return SVGLength::GetPixelsPerUnit(aMetrics, aUnitType, mCtxType); return SVGLength::GetPixelsPerUnit(aMetrics, aUnitType, mCtxType, true);
} }
void SVGAnimatedLength::SetBaseValueInSpecifiedUnits(float aValue, void SVGAnimatedLength::SetBaseValueInSpecifiedUnits(float aValue,
@ -653,7 +659,7 @@ float SVGLengthAndInfo::ConvertUnits(const SVGLengthAndInfo& aTo) const {
float SVGLengthAndInfo::ValueInPixels(const UserSpaceMetrics& aMetrics) const { float SVGLengthAndInfo::ValueInPixels(const UserSpaceMetrics& aMetrics) const {
return mValue == 0.0f ? 0.0f return mValue == 0.0f ? 0.0f
: mValue * SVGLength::GetPixelsPerUnit( : mValue * SVGLength::GetPixelsPerUnit(
aMetrics, mUnitType, mCtxType); aMetrics, mUnitType, mCtxType, false);
} }
void SVGLengthAndInfo::Add(const SVGLengthAndInfo& aValueToAdd, void SVGLengthAndInfo::Add(const SVGLengthAndInfo& aValueToAdd,
@ -673,7 +679,7 @@ void SVGLengthAndInfo::Add(const SVGLengthAndInfo& aValueToAdd,
mUnitType = aValueToAdd.mUnitType; mUnitType = aValueToAdd.mUnitType;
mCtxType = aValueToAdd.mCtxType; mCtxType = aValueToAdd.mCtxType;
mValue = (currentLength + lengthToAdd) / mValue = (currentLength + lengthToAdd) /
SVGLength::GetPixelsPerUnit(metrics, mUnitType, mCtxType); SVGLength::GetPixelsPerUnit(metrics, mUnitType, mCtxType, false);
} }
void SVGLengthAndInfo::Interpolate(const SVGLengthAndInfo& aStart, void SVGLengthAndInfo::Interpolate(const SVGLengthAndInfo& aStart,

View file

@ -151,14 +151,17 @@ class SVGAnimatedLength {
float GetAnimValue(const SVGElement* aSVGElement) const { float GetAnimValue(const SVGElement* aSVGElement) const {
return mAnimVal * GetPixelsPerUnit(aSVGElement, mAnimUnitType); return mAnimVal * GetPixelsPerUnit(aSVGElement, mAnimUnitType);
} }
float GetAnimValue(nsIFrame* aFrame) const { float GetAnimValueWithZoom(const SVGElement* aSVGElement) const {
return mAnimVal * GetPixelsPerUnit(aFrame, mAnimUnitType); return mAnimVal * GetPixelsPerUnitWithZoom(aSVGElement, mAnimUnitType);
} }
float GetAnimValue(const SVGViewportElement* aCtx) const { float GetAnimValueWithZoom(nsIFrame* aFrame) const {
return mAnimVal * GetPixelsPerUnit(aCtx, mAnimUnitType); return mAnimVal * GetPixelsPerUnitWithZoom(aFrame, mAnimUnitType);
} }
float GetAnimValue(const UserSpaceMetrics& aMetrics) const { float GetAnimValueWithZoom(const SVGViewportElement* aCtx) const {
return mAnimVal * GetPixelsPerUnit(aMetrics, mAnimUnitType); return mAnimVal * GetPixelsPerUnitWithZoom(aCtx, mAnimUnitType);
}
float GetAnimValueWithZoom(const UserSpaceMetrics& aMetrics) const {
return mAnimVal * GetPixelsPerUnitWithZoom(aMetrics, mAnimUnitType);
} }
uint8_t GetCtxType() const { return mCtxType; } 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 // These APIs returns the number of user-unit pixels per unit of the
// given type, in a given context (frame/element/etc). // 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, float GetPixelsPerUnit(const SVGElement* aSVGElement,
uint8_t aUnitType) const; uint8_t aUnitType) const;
float GetPixelsPerUnit(const SVGViewportElement* aCtx, float GetPixelsPerUnitWithZoom(nsIFrame* aFrame, uint8_t aUnitType) const;
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 // 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 // if unit conversion fails e.g. conversion to ex or em units where the

View file

@ -1559,7 +1559,7 @@ void SVGElement::GetAnimatedLengthValues(float* aFirst, ...) {
va_start(args, aFirst); va_start(args, aFirst);
while (f && i < info.mCount) { while (f && i < info.mCount) {
*f = info.mValues[i++].GetAnimValue(metrics); *f = info.mValues[i++].GetAnimValueWithZoom(metrics);
f = va_arg(args, float*); f = va_arg(args, float*);
} }

View file

@ -165,7 +165,8 @@ enum class ZoomType { Self, SelfFromRoot, None };
/*static*/ /*static*/
float SVGLength::GetPixelsPerUnit(const UserSpaceMetrics& aMetrics, float SVGLength::GetPixelsPerUnit(const UserSpaceMetrics& aMetrics,
uint8_t aUnitType, uint8_t aAxis) { uint8_t aUnitType, uint8_t aAxis,
bool aApplyZoom) {
auto zoomType = ZoomType::Self; auto zoomType = ZoomType::Self;
float value = [&]() -> float { float value = [&]() -> float {
switch (aUnitType) { switch (aUnitType) {
@ -216,15 +217,17 @@ float SVGLength::GetPixelsPerUnit(const UserSpaceMetrics& aMetrics,
return GetAbsUnitsPerAbsUnit(SVG_LENGTHTYPE_PX, aUnitType); return GetAbsUnitsPerAbsUnit(SVG_LENGTHTYPE_PX, aUnitType);
} }
}(); }();
switch (zoomType) { if (aApplyZoom) {
case ZoomType::None: switch (zoomType) {
break; case ZoomType::None:
case ZoomType::Self: break;
value *= aMetrics.GetZoom(); case ZoomType::Self:
break; value *= aMetrics.GetZoom();
case ZoomType::SelfFromRoot: break;
value *= aMetrics.GetZoom() / aMetrics.GetRootZoom(); case ZoomType::SelfFromRoot:
break; value *= aMetrics.GetZoom() / aMetrics.GetRootZoom();
break;
}
} }
return value; return value;
} }

View file

@ -93,9 +93,14 @@ class SVGLength {
bool IsPercentage() const { return IsPercentageUnit(mUnit); } 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, float GetPixelsPerUnit(const dom::UserSpaceMetrics& aMetrics,
uint8_t aAxis) const { uint8_t aAxis) const {
return GetPixelsPerUnit(aMetrics, mUnit, aAxis); return GetPixelsPerUnit(aMetrics, mUnit, aAxis, false);
} }
static bool IsValidUnitType(uint16_t aUnitType) { static bool IsValidUnitType(uint16_t aUnitType) {
@ -123,7 +128,8 @@ class SVGLength {
* Returns the number of pixels per given unit. * Returns the number of pixels per given unit.
*/ */
static float GetPixelsPerUnit(const dom::UserSpaceMetrics& aMetrics, static float GetPixelsPerUnit(const dom::UserSpaceMetrics& aMetrics,
uint8_t aUnitType, uint8_t aAxis); uint8_t aUnitType, uint8_t aAxis,
bool aApplyZoom);
private: private:
float mValue; float mValue;

View file

@ -180,17 +180,17 @@ SVGViewBox SVGMarkerElement::GetViewBox() {
if (mViewBox.HasRect()) { if (mViewBox.HasRect()) {
return mViewBox.GetAnimValue(); return mViewBox.GetAnimValue();
} }
return SVGViewBox(0, 0, return SVGViewBox(
mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx), 0, 0, mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx),
mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx)); mLengthAttributes[MARKERHEIGHT].GetAnimValueWithZoom(mCoordCtx));
} }
gfx::Matrix SVGMarkerElement::GetViewBoxTransform() { gfx::Matrix SVGMarkerElement::GetViewBoxTransform() {
if (!mViewBoxToViewportTransform) { if (!mViewBoxToViewportTransform) {
float viewportWidth = float viewportWidth =
mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx); mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx);
float viewportHeight = float viewportHeight =
mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx); mLengthAttributes[MARKERHEIGHT].GetAnimValueWithZoom(mCoordCtx);
SVGViewBox viewbox = GetViewBox(); SVGViewBox viewbox = GetViewBox();
@ -201,8 +201,8 @@ gfx::Matrix SVGMarkerElement::GetViewBoxTransform() {
viewportWidth, viewportHeight, viewbox.x, viewbox.y, viewbox.width, viewportWidth, viewportHeight, viewbox.x, viewbox.y, viewbox.width,
viewbox.height, mPreserveAspectRatio); viewbox.height, mPreserveAspectRatio);
float refX = mLengthAttributes[REFX].GetAnimValue(mCoordCtx); float refX = mLengthAttributes[REFX].GetAnimValueWithZoom(mCoordCtx);
float refY = mLengthAttributes[REFY].GetAnimValue(mCoordCtx); float refY = mLengthAttributes[REFY].GetAnimValueWithZoom(mCoordCtx);
gfx::Point ref = viewBoxTM.TransformPoint(gfx::Point(refX, refY)); gfx::Point ref = viewBoxTM.TransformPoint(gfx::Point(refX, refY));

View file

@ -396,7 +396,7 @@ LengthPercentage SVGSVGElement::GetIntrinsicWidthOrHeight(int aAttr) {
// that uses the passed argument as the context, but that's fine since we // 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 // 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). // 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); return LengthPercentage::FromPixels(rawSize);
} }

View file

@ -105,7 +105,7 @@ inline float ComputeSynthesizedViewBoxDimension(
return aViewportLength * aLength.GetAnimValInSpecifiedUnits() / 100.0f; 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; float viewportWidth, viewportHeight;
if (IsInner()) { if (IsInner()) {
SVGElementMetrics metrics(this); SVGElementMetrics metrics(this);
viewportWidth = mLengthAttributes[ATTR_WIDTH].GetAnimValue(metrics); viewportWidth = mLengthAttributes[ATTR_WIDTH].GetAnimValueWithZoom(metrics);
viewportHeight = mLengthAttributes[ATTR_HEIGHT].GetAnimValue(metrics); viewportHeight =
mLengthAttributes[ATTR_HEIGHT].GetAnimValueWithZoom(metrics);
} else { } else {
viewportWidth = mViewportSize.width; viewportWidth = mViewportSize.width;
viewportHeight = mViewportSize.height; viewportHeight = mViewportSize.height;
@ -201,10 +202,10 @@ float SVGViewportElement::GetLength(uint8_t aCtxType) const {
// of GetAnimValue(). // of GetAnimValue().
SVGElementMetrics metrics(this); SVGElementMetrics metrics(this);
if (shouldComputeWidth) { if (shouldComputeWidth) {
w = mLengthAttributes[ATTR_WIDTH].GetAnimValue(metrics); w = mLengthAttributes[ATTR_WIDTH].GetAnimValueWithZoom(metrics);
} }
if (shouldComputeHeight) { if (shouldComputeHeight) {
h = mLengthAttributes[ATTR_HEIGHT].GetAnimValue(metrics); h = mLengthAttributes[ATTR_HEIGHT].GetAnimValueWithZoom(metrics);
} }
} else if (ShouldSynthesizeViewBox()) { } else if (ShouldSynthesizeViewBox()) {
if (shouldComputeWidth) { if (shouldComputeWidth) {

View file

@ -20,6 +20,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=342513
<svg font-size="10" width="20em" height="20em"> <svg font-size="10" width="20em" height="20em">
<rect id="r1" x="5em" y="6em" width="20%" height="30%" /> <rect id="r1" x="5em" y="6em" width="20%" height="30%" />
</svg> </svg>
<div style="zoom: 2;">
<svg width="40" height="40">
<rect id="r2" width="25" height="20" />
</svg>
</div>
</svg> </svg>
</div> </div>
@ -34,7 +39,7 @@ function run() {
var divElem = document.getElementById("div"); var divElem = document.getElementById("div");
var expectedWidth = divElem.clientWidth; var expectedWidth = divElem.clientWidth;
// test for the pixel width of the svg // 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 // set the SVG width to ~50% in pixels
svgDoc.width.baseVal.newValueSpecifiedUnits(svgDoc.width.baseVal.SVG_LENGTHTYPE_PX, Math.floor(expectedWidth / 2)); 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 <svg> should be resolved against the inner <svg>"); is(r1.width.baseVal.value, 40, "width in em for elements inside inner <svg> should be resolved against the inner <svg>");
is(r1.height.baseVal.value, 60, "height in em for elements inside inner <svg> should be resolved against the inner <svg>"); is(r1.height.baseVal.value, 60, "height in em for elements inside inner <svg> should be resolved against the inner <svg>");
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(); SimpleTest.finish();
} }

View file

@ -455,7 +455,7 @@ float SVGLinearGradientFrame::GetLengthValue(uint32_t aIndex) {
NS_ASSERTION(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, NS_ASSERTION(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX,
"Unknown gradientUnits type"); "Unknown gradientUnits type");
return length.GetAnimValue(static_cast<SVGViewportElement*>(nullptr)); return length.GetAnimValueWithZoom(static_cast<SVGViewportElement*>(nullptr));
} }
dom::SVGLinearGradientElement* dom::SVGLinearGradientElement*
@ -557,7 +557,7 @@ float SVGRadialGradientFrame::GetLengthValueFromElement(
NS_ASSERTION(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, NS_ASSERTION(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX,
"Unknown gradientUnits type"); "Unknown gradientUnits type");
return length.GetAnimValue(static_cast<SVGViewportElement*>(nullptr)); return length.GetAnimValueWithZoom(static_cast<SVGViewportElement*>(nullptr));
} }
dom::SVGRadialGradientElement* dom::SVGRadialGradientElement*

View file

@ -158,7 +158,8 @@ nscoord SVGOuterSVGFrame::GetPrefISize(gfxContext* aRenderingContext) {
result = nscoord(0); result = nscoord(0);
} }
} else { } else {
result = nsPresContext::CSSPixelsToAppUnits(isize.GetAnimValue(svg)); result =
nsPresContext::CSSPixelsToAppUnits(isize.GetAnimValueWithZoom(svg));
if (result < 0) { if (result < 0) {
result = nscoord(0); result = nscoord(0);
} }
@ -189,13 +190,13 @@ IntrinsicSize SVGOuterSVGFrame::GetIntrinsicSize() {
if (!width.IsPercentage()) { if (!width.IsPercentage()) {
nscoord val = nscoord val =
nsPresContext::CSSPixelsToAppUnits(width.GetAnimValue(content)); nsPresContext::CSSPixelsToAppUnits(width.GetAnimValueWithZoom(content));
intrinsicSize.width.emplace(std::max(val, 0)); intrinsicSize.width.emplace(std::max(val, 0));
} }
if (!height.IsPercentage()) { if (!height.IsPercentage()) {
nscoord val = nscoord val = nsPresContext::CSSPixelsToAppUnits(
nsPresContext::CSSPixelsToAppUnits(height.GetAnimValue(content)); height.GetAnimValueWithZoom(content));
intrinsicSize.height.emplace(std::max(val, 0)); intrinsicSize.height.emplace(std::max(val, 0));
} }

View file

@ -644,16 +644,16 @@ gfxMatrix SVGPatternFrame::ConstructCTM(const SVGAnimatedViewBox& aViewBox,
// If we're dealing with an SVG target only retrieve the context once. // If we're dealing with an SVG target only retrieve the context once.
// Calling the nsIFrame* variant of GetAnimValue would look it up on // Calling the nsIFrame* variant of GetAnimValue would look it up on
// every call. // every call.
viewportWidth = viewportWidth = GetLengthValue(SVGPatternElement::ATTR_WIDTH)
GetLengthValue(SVGPatternElement::ATTR_WIDTH)->GetAnimValue(ctx); ->GetAnimValueWithZoom(ctx);
viewportHeight = viewportHeight = GetLengthValue(SVGPatternElement::ATTR_HEIGHT)
GetLengthValue(SVGPatternElement::ATTR_HEIGHT)->GetAnimValue(ctx); ->GetAnimValueWithZoom(ctx);
} else { } else {
// No SVG target, call the nsIFrame* variant of GetAnimValue. // No SVG target, call the nsIFrame* variant of GetAnimValue.
viewportWidth = viewportWidth = GetLengthValue(SVGPatternElement::ATTR_WIDTH)
GetLengthValue(SVGPatternElement::ATTR_WIDTH)->GetAnimValue(aTarget); ->GetAnimValueWithZoom(aTarget);
viewportHeight = viewportHeight = GetLengthValue(SVGPatternElement::ATTR_HEIGHT)
GetLengthValue(SVGPatternElement::ATTR_HEIGHT)->GetAnimValue(aTarget); ->GetAnimValueWithZoom(aTarget);
} }
if (viewportWidth <= 0.0f || viewportHeight <= 0.0f) { if (viewportWidth <= 0.0f || viewportHeight <= 0.0f) {

View file

@ -4570,7 +4570,7 @@ gfxFloat SVGTextFrame::GetStartOffset(nsIFrame* aTextPathFrame) {
100.0 100.0
: 0.0; : 0.0;
} }
float lengthValue = length->GetAnimValue(tp); float lengthValue = length->GetAnimValueWithZoom(tp);
// If offsetScale is infinity we want to return 0 not NaN // If offsetScale is infinity we want to return 0 not NaN
return lengthValue == 0 ? 0.0 : lengthValue * GetOffsetScale(aTextPathFrame); return lengthValue == 0 ? 0.0 : lengthValue * GetOffsetScale(aTextPathFrame);
} }
@ -4808,7 +4808,7 @@ void SVGTextFrame::DoGlyphPositioning() {
element->EnumAttributes()[SVGTextContentElement::LENGTHADJUST] element->EnumAttributes()[SVGTextContentElement::LENGTHADJUST]
.GetAnimValue(); .GetAnimValue();
bool adjustingTextLength = textLengthAttr->IsExplicitlySet(); bool adjustingTextLength = textLengthAttr->IsExplicitlySet();
float expectedTextLength = textLengthAttr->GetAnimValue(element); float expectedTextLength = textLengthAttr->GetAnimValueWithZoom(element);
if (adjustingTextLength && if (adjustingTextLength &&
(expectedTextLength < 0.0f || lengthAdjust == LENGTHADJUST_UNKNOWN)) { (expectedTextLength < 0.0f || lengthAdjust == LENGTHADJUST_UNKNOWN)) {

View file

@ -254,19 +254,20 @@ float SVGUtils::ObjectSpace(const gfxRect& aRect,
// Multiply first to avoid precision errors: // Multiply first to avoid precision errors:
return axis * aLength->GetAnimValInSpecifiedUnits() / 100; return axis * aLength->GetAnimValInSpecifiedUnits() / 100;
} }
return aLength->GetAnimValue(static_cast<SVGViewportElement*>(nullptr)) * return aLength->GetAnimValueWithZoom(
static_cast<SVGViewportElement*>(nullptr)) *
axis; axis;
} }
float SVGUtils::UserSpace(nsIFrame* aNonSVGContext, float SVGUtils::UserSpace(nsIFrame* aNonSVGContext,
const SVGAnimatedLength* aLength) { const SVGAnimatedLength* aLength) {
MOZ_ASSERT(!aNonSVGContext->IsTextFrame(), "Not expecting text content"); MOZ_ASSERT(!aNonSVGContext->IsTextFrame(), "Not expecting text content");
return aLength->GetAnimValue(aNonSVGContext); return aLength->GetAnimValueWithZoom(aNonSVGContext);
} }
float SVGUtils::UserSpace(const UserSpaceMetrics& aMetrics, float SVGUtils::UserSpace(const UserSpaceMetrics& aMetrics,
const SVGAnimatedLength* aLength) { const SVGAnimatedLength* aLength) {
return aLength->GetAnimValue(aMetrics); return aLength->GetAnimValueWithZoom(aMetrics);
} }
SVGOuterSVGFrame* SVGUtils::GetOuterSVGFrame(nsIFrame* aFrame) { SVGOuterSVGFrame* SVGUtils::GetOuterSVGFrame(nsIFrame* aFrame) {

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<title>SVGLength in zoomed div</title>
<link rel="help" href="https://www.w3.org/TR/SVG/types.html#InterfaceSVGLength">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div style="zoom: 2;">
<svg>
<rect id="rect" width="100" height="100"/>
</svg>
</div>
<script>
const rect = document.getElementById("rect");
test(() => {
assert_approx_equals(rect.width.baseVal.value, 100, 0.1);
}, "SVGLength in zoomed div should be unchanged");
</script>