Bug 1541021 - Should take CSS transform into account when calculating getBoundingClientRect() r=longsonr

We should use nsLayoutUtils::GetTransformToAncestor instead of
nsSVGUtils::GetUserToCanvasTM to get the transform matrix. Because the former
will also take CSS transform into account while the latter won't.

Differential Revision: https://phabricator.services.mozilla.com/D26441

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-04-08 04:39:23 +00:00
Родитель fcff024573
Коммит c0ca7d5cac
3 изменённых файлов: 49 добавлений и 5 удалений

Просмотреть файл

@ -3,6 +3,7 @@
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<style type="text/css">
text { font: 20px monospace; }
#css-trans-rect-2 { transform: scaleX(2) }
</style>
<g id="g">
@ -71,5 +72,7 @@ text { font: 20px monospace; }
<line id="rotatedLine1" x1="160" y1="150" x2="180" y2="170"
stroke="darkmagenta" stroke-width="10"
transform="rotate(-45 160 150)" />
<rect id="css-trans-rect-2" x="5" y="5" width="6" height="6"></rect>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 3.6 KiB

После

Ширина:  |  Высота:  |  Размер: 3.7 KiB

Просмотреть файл

@ -7,6 +7,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=463934
<title>Test for Bug 463934</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style>
#css-trans-rect-1 {
transform: scaleX(2)
}
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=463934">Mozilla Bug 463934</a>
@ -22,6 +27,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=463934
<svg id="outer-4" xmlns="http://www.w3.org/2000/svg" width="30" height="30"
style="border: 10px solid black; padding: 10px">
</svg>
<svg id="outer-5" xmlns="http://www.w3.org/2000/svg" width="30" height="30">
<rect id="css-trans-rect-1" width="6" height="6"></rect>
</svg>
</div>
<iframe id="svg" src="bounds-helper.svg"></iframe>
@ -67,6 +75,10 @@ function runTest() {
is(bounds.width, 70, "outer-svg 4 getBoundingClientRect().width");
is(bounds.height, 70, "outer-svg 4 getBoundingClientRect().height");
bounds = document.getElementById("css-trans-rect-1").getBoundingClientRect();
is(bounds.width, 12, "css-trans-rect getBoundingClientRect().width");
is(bounds.height, 6, "css-trans-rect getBoundingClientRect().height");
var doc = $("svg").contentWindow.document;
var svg1Bounds = doc.getElementById("svg1").getBoundingClientRect();
@ -279,6 +291,13 @@ function runTest() {
isWithAbsTolerance(rotatedLine1Bounds.height, 10, 0.1,
"rotatedLine1Bounds.height");
var cssTransRect2Bounds =
doc.getElementById("css-trans-rect-2").getBoundingClientRect();
is(cssTransRect2Bounds.left, 10, "cssTransRect2Bounds.left");
is(cssTransRect2Bounds.top, 5, "cssTransRect2Bounds.top");
is(cssTransRect2Bounds.width, 12, "cssTransRect2Bounds.width");
is(cssTransRect2Bounds.height, 6, "cssTransRect2Bounds.height");
SimpleTest.finish();
}

Просмотреть файл

@ -321,12 +321,34 @@ nsIFrame* nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(nsIFrame* aFrame,
uint32_t flags =
nsSVGUtils::eForGetClientRects | nsSVGUtils::eBBoxIncludeFill |
nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIncludeMarkers;
gfxMatrix m = nsSVGUtils::GetUserToCanvasTM(aFrame);
auto ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, outer);
float initPositionX = NSAppUnitsToFloatPixels(aFrame->GetPosition().x,
AppUnitsPerCSSPixel()),
initPositionY = NSAppUnitsToFloatPixels(aFrame->GetPosition().y,
AppUnitsPerCSSPixel());
Matrix mm;
ctm.ProjectTo2D();
ctm.CanDraw2D(&mm);
gfxMatrix m = ThebesMatrix(mm);
float appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
float devPixelPerCSSPixel =
1.0 * AppUnitsPerCSSPixel() / appUnitsPerDevPixel;
// The matrix that GetBBox accepts should operate on "user space",
// i.e. with CSS pixel unit.
m = m.PreScale(devPixelPerCSSPixel, devPixelPerCSSPixel);
// Both nsSVGUtils::GetBBox and nsLayoutUtils::GetTransformToAncestor
// will count this displacement, we should remove it here to avoid
// double-counting.
m = m.PreTranslate(-initPositionX, -initPositionY);
SVGBBox bbox = nsSVGUtils::GetBBox(aFrame, flags, &m);
nsRect bounds = nsLayoutUtils::RoundGfxRectToAppRect(
bbox, aFrame->PresContext()->AppUnitsPerDevPixel());
nsMargin bp = outer->GetUsedBorderAndPadding();
*aRect = bounds + nsPoint(bp.left, bp.top);
*aRect = nsLayoutUtils::RoundGfxRectToAppRect(bbox, appUnitsPerDevPixel);
}
return outer;