Skip to content

Commit

Permalink
Restore behavior (hit testing, layout shifts) from before splitting o…
Browse files Browse the repository at this point in the history
…f nodes for individual transform properties.

This restores FragmentData::PreTransform and related code to its
behavior prior to the splitting of transform nodes for individual
transform properties.  (For the parts involving layout shift
calculations, some of the "related code" is rather distant.)

All of the added tests in css/css-transforms/transform-hit-testing.html
fail without the change (though I'm actually not sure why the one
testing 'transform' does).

This adds four tests to layout-instability/, all slight modifications
of existing tests:
* local-shift-without-viewport-shift-2.html based on
  local-shift-without-viewport-shift.html
* shift-with-counter-scroll-and-translate.html based on
  shift-with-counter-scroll-and-transform.html
* translate-change.html based on transform-change.html
* translate-counter-layout-shift.html based on
  transform-counter-layout-shift.html

Of those four added tests, two of them are not affected by this change,
and two of them (shift-with-counter-scroll-and-translate.html and
translate-counter-layout-shift.html) fail prior to this change and pass
with it.

This also adds a pair of tests in wpt_internal that attempt to exercise
the unspecified "layout shift root" concept.  (These tests have a bit of
error tolerance which is well within the difference between using
Math.round() on the pixel values and using Math.floor() on the pixel
values.)

Fixed: 1349111
Bug: 696374, 1278452
Change-Id: Ic5a3328571d8d53d372dd4649d42e176d0cc7e9a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3810679
Commit-Queue: David Baron <dbaron@chromium.org>
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1034551}
  • Loading branch information
dbaron authored and chromium-wpt-export-bot committed Aug 12, 2022
1 parent be2067b commit 631ec10
Show file tree
Hide file tree
Showing 5 changed files with 316 additions and 0 deletions.
153 changes: 153 additions & 0 deletions css/css-transforms/transform-hit-testing.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<!DOCTYPE HTML>
<title>CSS Test (Transforms): Hit Testing</title>
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Google" href="http://www.google.com/">
<link rel="help" href="https://www.w3.org/TR/css-transforms-1/#transform-property">
<link rel="help" href="https://www.w3.org/TR/css-transforms-2/#individual-transforms">
<meta name="flags" content="dom">
<style>

html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
border: none;
}

body { margin: 50px; }

</style>
<script>

let body_x_margin = 50;
let body_y_margin = 50;

</script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<body>
<script>

class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}

let simple_tests = [
// In this list of tests, test_points_inside and test_points_outside
// are relative to the element's untransformed origin (top, left).
{
description: "rectangle with 'translate' and 'rotate'",
styles: "width: 100px; height: 50px; translate: 30px; rotate: 20deg;",
test_points_inside: [
new Point(28, 32),
new Point(44, -10),
new Point(133, 22),
new Point(117, 64),
new Point(65, 27),
],
test_points_outside: [
new Point(30, 5),
new Point(28, 37),
new Point(100, 2),
new Point(124, 58),
],
},
{
description: "rectangle with 'transform'",
styles: "width: 100px; height: 50px; transform: translate(30px) rotate(20deg);",
test_points_inside: [
new Point(28, 32),
new Point(44, -10),
new Point(133, 22),
new Point(117, 64),
new Point(65, 27),
],
test_points_outside: [
new Point(30, 5),
new Point(28, 37),
new Point(100, 2),
new Point(124, 58),
],
},
{
description: "rectangle with 'translate' and 'rotate' and 'scale' and 'transform'",
styles: "width: 100px; height: 50px; translate: 30px; rotate: 40deg; scale: 2; transform: rotate(-20deg) scale(0.5)",
test_points_inside: [
new Point(28, 32),
new Point(44, -10),
new Point(133, 22),
new Point(117, 64),
new Point(65, 27),
],
test_points_outside: [
new Point(30, 5),
new Point(28, 37),
new Point(100, 2),
new Point(124, 58),
],
},
{
description: "square with 'rotate'",
styles: "width: 10px; height: 10px; rotate: 90deg; transform-origin: 0 10px",
test_points_inside: [
new Point(1, 11),
new Point(9, 11),
new Point(1, 19),
new Point(9, 19),
],
test_points_outside: [
new Point(1, 9),
new Point(9, 9),
],
},
{
description: "square with 'scale'",
styles: "width: 10px; height: 10px; scale: 0.2;",
test_points_inside: [
new Point(4, 4),
new Point(5, 4),
new Point(4, 5),
new Point(5, 5),
],
test_points_outside: [
new Point(3, 3),
new Point(3, 5),
new Point(3, 6),
new Point(5, 3),
new Point(5, 6),
new Point(6, 3),
new Point(6, 5),
new Point(6, 6),
],
},
];

for (let t of simple_tests) {
test(function() {
let e = document.createElement("div");
e.setAttribute("style", t.styles);
document.body.appendChild(e);

for (let p of t.test_points_inside) {
let res = document.elementFromPoint(p.x + body_x_margin,
p.y + body_y_margin);
assert_equals(res, e,
`point (${p.x}, ${p.y}) is inside element`);
}

for (let p of t.test_points_outside) {
let res = document.elementFromPoint(p.x + body_x_margin,
p.y + body_y_margin);
assert_equals(res, document.body,
`point (${p.x}, ${p.y}) is outside element`);
}

e.remove();
}, `hit testing of ${t.description}`);
}
</script>
32 changes: 32 additions & 0 deletions layout-instability/local-shift-without-viewport-shift-2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<title>Layout Instability: local shift without viewport shift</title>
<link rel="help" href="https://wicg.github.io/layout-instability/" />
<style>

#c { position: relative; width: 300px; height: 100px; scale: 0.1; }
#j { position: relative; width: 100px; height: 10px; background: blue; }

</style>
<div id='c'>
<div id='j'></div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/util.js"></script>
<script>

promise_test(async () => {
const watcher = new ScoreWatcher;

// Wait for the initial render to complete.
await waitForAnimationFrames(2);

document.querySelector("#j").style.top = "4px";

// Make sure no shift score is reported, since the element didn't move in the
// viewport.
await waitForAnimationFrames(3);
assert_equals(watcher.score, 0);
}, "Local shift without viewport shift.");

</script>
62 changes: 62 additions & 0 deletions layout-instability/shift-with-counter-scroll-and-translate.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<!DOCTYPE html>
<title>Layout Instability: shift with counter scroll and translate not counted</title>
<link rel="help" href="https://wicg.github.io/layout-instability/" />
<style>
.scroller {
overflow: scroll;
position: absolute;
left: 20px;
top: 20px;
width: 200px;
height: 200px;
}
.content {
width: 600px;
height: 600px;
}
.changer {
position: relative;
background: yellow;
left: 10px;
top: 100px;
width: 150px;
height: 150px;
}

</style>
<div id="scroller1" class="scroller">
<div class="content">
<div id="changer1" class="changer"></div>
</div>
</div>
<div id="scroller2" class="scroller">
<div class="content">
<div id="changer2" class="changer"></div>
</div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/util.js"></script>
<script>

promise_test(async () => {
const watcher = new ScoreWatcher;

// Wait for the initial render to complete.
await waitForAnimationFrames(2);

changer1.style.top = "250px";
changer1.style.translate = "0 -50px";
// 250 - 50 = 200; old position is 100; hence scrollTop to counter is 100.
scroller1.scrollTop = 100;

changer2.style.left = "220px";
changer2.style.translate = "80px 0";
// 220 + 80 = 300; old position is 10; hence scrollTop to counter is 290.
scroller2.scrollLeft = 290;

await waitForAnimationFrames(3);
assert_equals(watcher.score, 0);
}, "Shift with counter scroll and translate not counted.");

</script>
33 changes: 33 additions & 0 deletions layout-instability/translate-change.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<title>Layout Instability: no layout shift for change of individual transform property</title>
<link rel="help" href="https://wicg.github.io/layout-instability/" />
<style>
body { margin: 0; }
#transformed { position: relative; translate: 20px 0; width: 100px; height: 100px; background: blue; }
#child { width: 400px; height: 400px; }
</style>
<div id="transformed">
<div id="child"></div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/util.js"></script>
<script>

promise_test(async () => {
const watcher = new ScoreWatcher;

// Wait for the initial render to complete.
await waitForAnimationFrames(2);

// Modify the transform, for which no shift should be reported.
document.querySelector("#transformed").style = "translate: 0 100px";
// Change size of child, for which no shift should be reported, either.
document.querySelector("#child").style = "width: 300px";

await waitForAnimationFrames(2);
// No shift should be reported.
assert_equals(watcher.score, 0);
}, 'no layout shift for transform change');

</script>
36 changes: 36 additions & 0 deletions layout-instability/translate-counter-layout-shift.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<title>Layout Instability: no layout shift if translate change counters location change</title>
<link rel="help" href="https://wicg.github.io/layout-instability/" />
<style>
body { margin: 0; }
#transformed { position: relative; translate: 20px 0; width: 100px; height: 100px; background: blue; }
#child { width: 400px; height: 400px; }
</style>
<div id="transformed">
<div id="child"></div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/util.js"></script>
<script>

promise_test(async () => {
const watcher = new ScoreWatcher;

// Wait for the initial render to complete.
await waitForAnimationFrames(2);

// Modify the transform and the location at the same time, and the values
// cancel each other visually, for which no shift should be reported.
transformed.style.translate = '0 100px';
transformed.style.top = '-100px';
transformed.style.left = '20px';
// Change size of child, for which no shift should be reported, either.
child.style.width = '300px';

await waitForAnimationFrames(2);
// No shift should be reported.
assert_equals(watcher.score, 0);
}, 'no layout shift if translate change counters location change');

</script>

0 comments on commit 631ec10

Please sign in to comment.