Bug 1890198 - Account for transform when applying padding r=dholbert

Differential Revision: https://phabricator.services.mozilla.com/D241763
This commit is contained in:
longsonr
2025-03-19 17:02:47 +00:00
parent 4d3e396107
commit f81c4009de
2 changed files with 84 additions and 2 deletions

View File

@@ -499,8 +499,26 @@ static gfx::Matrix GetCTMInternal(SVGElement* aElement, CTMType aCTMType,
if (frame->IsSVGOuterSVGFrame()) {
nsMargin bp = frame->GetUsedBorderAndPadding();
int32_t appUnitsPerCSSPixel = AppUnitsPerCSSPixel();
tm.PostTranslate(NSAppUnitsToFloatPixels(bp.left, appUnitsPerCSSPixel),
NSAppUnitsToFloatPixels(bp.top, appUnitsPerCSSPixel));
float xOffset = NSAppUnitsToFloatPixels(bp.left, appUnitsPerCSSPixel);
float yOffset = NSAppUnitsToFloatPixels(bp.top, appUnitsPerCSSPixel);
// See
// https://drafts.csswg.org/css-transforms/#valdef-transform-box-fill-box
// For elements with associated CSS layout box, the used value for fill-box
// is content-box and for stroke-box and view-box is border-box.
switch (frame->StyleDisplay()->mTransformBox) {
case StyleTransformBox::FillBox:
case StyleTransformBox::ContentBox:
// Apply border/padding separate from the rest of the transform.
// i.e. after it's been transformed
tm.PostTranslate(xOffset, yOffset);
break;
case StyleTransformBox::StrokeBox:
case StyleTransformBox::ViewBox:
case StyleTransformBox::BorderBox:
// Apply border/padding before we transform the surface.
tm.PreTranslate(xOffset, yOffset);
break;
}
}
if (!ancestor || !ancestor->IsElement()) {

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:h="http://www.w3.org/1999/xhtml">
<title>SVGGraphicsElement with padding</title>
<metadata>
<h:link rel="help" href="https://svgwg.org/svg2-draft/types.html#InterfaceSVGGraphicsElement"/>
</metadata>
<h:script src="/resources/testharness.js"/>
<h:script src="/resources/testharnessreport.js"/>
<foreignObject width="100px" height="100px">
<svg id="svg" width="100px" height="100px">
<circle cx="50" cy="0" r="44"
fill="blue"></circle>
</svg>
</foreignObject>
<script><![CDATA[
test(function() {
let svg = document.getElementById("svg");
svg.setAttribute("style", "padding-left: 12px; transform: rotate(180deg);");
let ctm = svg.getScreenCTM();
let pt = DOMPoint.fromPoint({x: 50, y: 50});
let transformedPoint = pt.matrixTransform(ctm.inverse());
svg.removeAttribute("style");
assert_equals(transformedPoint.x, pt.x);
assert_equals(transformedPoint.y, pt.y);
}, 'getScreenCTM with padding-left and rotation');
test(function() {
let svg = document.getElementById("svg");
svg.setAttribute("style", "padding-top: 12px; transform: rotate(180deg);");
let ctm = svg.getScreenCTM();
let pt = DOMPoint.fromPoint({x: 50, y: 50});
let transformedPoint = pt.matrixTransform(ctm.inverse());
svg.removeAttribute("style");
assert_equals(transformedPoint.x, pt.x);
assert_equals(transformedPoint.y, pt.y);
}, 'getScreenCTM with padding-top and rotation');
test(function() {
let svg = document.getElementById("svg");
svg.setAttribute("style", "padding-right: 12px; transform: rotate(180deg);");
let ctm = svg.getScreenCTM();
let pt = DOMPoint.fromPoint({x: 50, y: 50});
let transformedPoint = pt.matrixTransform(ctm.inverse());
svg.removeAttribute("style");
assert_equals(transformedPoint.x, pt.x + 12);
assert_equals(transformedPoint.y, pt.y);
}, 'getScreenCTM with padding-right and rotation');
test(function() {
let svg = document.getElementById("svg");
svg.setAttribute("style", "padding-left: 12px; transform: rotate(180deg); transform-box: content-box");
let ctm = svg.getScreenCTM();
let pt = DOMPoint.fromPoint({x: 50, y: 50});
let transformedPoint = pt.matrixTransform(ctm.inverse());
svg.removeAttribute("style");
assert_equals(transformedPoint.x, pt.x + 12);
assert_equals(transformedPoint.y, pt.y);
}, 'getScreenCTM with padding-left, rotation and content-box');
]]></script>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB