Skip to content

Commit

Permalink
Bug 1565557: ResizeObserver for SVG elements with CSS layout boxes us…
Browse files Browse the repository at this point in the history
…e the layout boxes. r=emilio

As per the CSSWG resolution here: w3c/csswg-drafts#4032
Previously, any and all SVG elements used its SVG object bounding box. Now, SVG
elements that have their own CSS layout box use them. These match the following
CSS rules: `svg:root, *:not(svg|*) > svg, svg|foreignObject > svg`

Differential Revision: https://phabricator.services.mozilla.com/D154246
  • Loading branch information
dshin-moz committed Aug 11, 2022
1 parent 26bd199 commit 2ba3e10
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 5 deletions.
11 changes: 6 additions & 5 deletions dom/base/ResizeObserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ static nsSize GetContentRectSize(const nsIFrame& aFrame) {

/**
* Returns |aTarget|'s size in the form of gfx::Size (in pixels).
* If the target is SVG, width and height are determined from bounding box.
* If the target is an SVG that does not participate in CSS layout,
* its width and height are determined from bounding box.
*
* https://www.w3.org/TR/resize-observer-1/#calculate-box-size
*/
Expand All @@ -81,10 +82,10 @@ static gfx::Size CalculateBoxSize(Element* aTarget,
return size;
}

if (aTarget->IsSVGElement()) {
// Per the spec, SVG size is always its bounding box size no matter what
// box option you choose, because SVG elements do not use standard CSS box
// model.
if (frame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) {
// Per the spec, this target's SVG size is always its bounding box size no
// matter what box option you choose, because SVG elements do not use
// standard CSS box model.
const gfxRect bbox = SVGUtils::GetBBox(frame);
size.width = static_cast<float>(bbox.width);
size.height = static_cast<float>(bbox.height);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!doctype html>
<title>ResizeObserver for SVG elements with CSS box.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./resources/resizeTestHelper.js"></script>
<div id="container" style="width: 500px; height: 500px;">
<svg id="svg" width="100%" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="45" style="fill:orange;stroke:black;stroke-width:1" />
<foreignObject id="foreign" x="0" y="0" width="100" height="100">
<svg xmlns="http://www.w3.org/2000/svg"
width="100%" height="100%"
viewBox="0 0 100 100"
id="foreign-svg">
<circle cx="50" cy="50" r="45" style="fill:orange;stroke:black;stroke-width:1" />
</svg>
</foreignObject>
</svg>
<script>
'use strict';

function test0() {
let targetWidth = 150;
let target = document.getElementById('foreign-svg');
let container = document.getElementById('foreign');
let helper = new ResizeTestHelper(
"test0: observe `foreignObject` SVG in HTML document",
[
{
setup: observer => {
observer.observe(target);
},
notify: (entries, observer) => {
return true; // Delay next step
}
},
{
setup: observer => {
target.setAttribute('width', targetWidth);
},
notify: entries => {
assert_equals(entries.length, 1);
const entry = entries[0];
assert_equals(entry.target, target);
assert_equals(entry.contentBoxSize[0].inlineSize, targetWidth);
},
}
]);
return helper.start();
}

function test1() {
let targetWidth = 400;
let target = document.getElementById('svg');
let container = document.getElementById('container');
let helper = new ResizeTestHelper(
"test1: observe inline SVG in HTML",
[
{
setup: observer => {
observer.observe(target);
},
notify: (entries, observer) => {
return true; // Delay next step
}
},
{
setup: observer => {
target.style.width = targetWidth + 'px';
},
notify: (entries, observer) => {
assert_equals(entries.length, 1);
const entry = entries[0];
assert_equals(entry.target, target);
assert_equals(entry.contentBoxSize[0].inlineSize, targetWidth);
}
}
]);
return helper.start();
}

let guard;
test(_ => {
assert_implements(window.ResizeObserver);
guard = async_test('guard');
}, "ResizeObserver implemented")

test0()
.then(() => { test1(); })
.then(() => { guard.done(); });

</script>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2ba3e10

Please sign in to comment.