Skip to content

Commit

Permalink
SET: Add support for clip-path object-view-box calculations.
Browse files Browse the repository at this point in the history
This patch adds clip-path support for object-view-box calculations.
This includes tests with both subset and intersecting clip-paths.

R=khushalsagar@chromium.org

Fixed: 1311706
Change-Id: Id62232f92d6628daa44b8fc2fd79742d071d1f82
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3645236
Reviewed-by: Khushal Sagar <khushalsagar@chromium.org>
Commit-Queue: Khushal Sagar <khushalsagar@chromium.org>
Commit-Queue: Vladimir Levin <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1003964}
NOKEYCHECK=True
GitOrigin-RevId: b074e802240c39226401a8f2f8c1f720099d5273
  • Loading branch information
vmpstr authored and Copybara-Service committed May 17, 2022
1 parent 628b287 commit db010ed
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/core/style/shape_clip_path_operation.h"
#include "third_party/blink/renderer/platform/data_resource_helper.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
Expand Down Expand Up @@ -98,12 +99,30 @@ PhysicalRect ComputeVisualOverflowRect(LayoutBox* box) {
child_box->MapToVisualRectInAncestorSpace(box, overflow_rect);
result.Unite(overflow_rect);
}
// Clip self painting descendant overflow by the clipping rect, then add in
// the visual overflow from the own painting layer.
// TODO(vmpstr): After these steps, we should also clip by the clip-path.
// Clip self painting descendant overflow by the overflow clip rect, then add
// in the visual overflow from the own painting layer.
result.Intersect(box->OverflowClipRect(PhysicalOffset()));
result.Unite(box->PhysicalVisualOverflowRectIncludingFilters());
return result;

const ComputedStyle& style = box->StyleRef();
if (!style.HasClipPath())
return result;

ClipPathOperation* clip_path = style.ClipPath();
if (clip_path->GetType() != ClipPathOperation::kShape)
return result;

ShapeClipPathOperation* shape =
static_cast<ShapeClipPathOperation*>(clip_path);
// TODO(vmpstr): Should this by PhysicalBorderBoxRect or Logical?
const Path& path = shape->GetPath(
static_cast<gfx::RectF>(box->BorderBoxRect()), style.EffectiveZoom());

// TODO(vmpstr): This is just the bounds of the clip-path, as opposed to the
// intersection between the clip-path and the border box bounds. This seems
// suboptimal, but that's the rect that we use further down the pipeline to
// generate the texture.
return static_cast<PhysicalRect>(gfx::ToEnclosingRect(path.BoundingRect()));
}

} // namespace
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<title>Shared transitions: object-view-box with larger overflow (ref)</title>
<link rel="help" href="https://github.com/WICG/shared-element-transitions">
<link rel="author" href="mailto:vmpstr@chromium.org">
<style>
.target {
color: red;
width: 100px;
height: 100px;
contain: paint;
position: relative;
top: 50px;
left: 50px;
}
.child {
width: 123px;
height: 150px;
background: lightblue;
position: relative;
top: -10px;
left: -20px;
}
.grandchild {
width: 25px;
height: 25px;
position: relative;
top: 20px;
left: 40px;
background: green;
}
#one { clip-path: inset(10px 12px 20px 28px); }
#two { clip-path: inset(10px -12px 20px -28px); }
body { background: lightpink; }
</style>

<div id=one class=target>
<div class=child>
<div class=grandchild></div>
</div>
</div>
<div style="height: 20px;"></div>
<div id=two class=target>
<div class=child>
<div class=grandchild></div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html class=reftest-wait>
<title>Shared transitions: object-view-box with larger clip-path</title>
<link rel="help" href="https://github.com/WICG/shared-element-transitions">
<link rel="author" href="mailto:vmpstr@chromium.org">
<link rel="match" href="new-content-object-view-box-clip-path-ref.html">
<script src="/common/reftest-wait.js"></script>
<style>
.target {
color: red;
width: 100px;
height: 100px;
contain: paint;
overflow-clip-margin: 1000px;
position: relative;
top: 50px;
left: 50px;
}
.child {
width: 123px;
height: 150px;
background: lightblue;
position: relative;
top: -10px;
left: -20px;
}
.grandchild {
width: 25px;
height: 25px;
position: relative;
top: 20px;
left: 40px;
background: green;
}
#one {
page-transition-tag: target-one;
clip-path: inset(10px 12px 20px 28px);
}
#two {
page-transition-tag: target-two;
clip-path: inset(10px -12px 20px -28px);
}

html::page-transition-container(target-one),
html::page-transition-container(target-two) { animation-duration: 300s; }
html::page-transition-outgoing-image(target-one),
html::page-transition-outgoing-image(target-two) { animation: unset; opacity: 0; }
html::page-transition-incoming-image(target-one),
html::page-transition-incoming-image(target-two) {
animation: unset;
opacity: 1;
/* clip overflow, and verify inner contents only */
overflow: hidden;
}

html::page-transition-container(root) { animation: unset; opacity: 0; }
html::page-transition { background: lightpink; }
</style>

<div id=one class=target>
<div class=child>
<div class=grandchild></div>
</div>
</div>
<div style="height: 20px;"></div>
<div id=two class=target>
<div class=child>
<div class=grandchild></div>
</div>
</div>

<script>
async function runTest() {
document.createDocumentTransition().start(() =>
requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
}
onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
</script>

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<title>Shared transitions: object-view-box with larger overflow (ref)</title>
<link rel="help" href="https://github.com/WICG/shared-element-transitions">
<link rel="author" href="mailto:vmpstr@chromium.org">
<style>
.target {
color: red;
width: 100px;
height: 100px;
contain: paint;
position: relative;
top: 50px;
left: 50px;
}
.child {
width: 123px;
height: 150px;
background: lightblue;
position: relative;
top: -10px;
left: -20px;
}
.grandchild {
width: 25px;
height: 25px;
position: relative;
top: 20px;
left: 40px;
background: green;
}
#one { clip-path: inset(10px 12px 20px 28px); }
#two { clip-path: inset(10px -12px 20px -28px); }
body { background: lightpink; }
</style>

<div id=one class=target>
<div class=child>
<div class=grandchild></div>
</div>
</div>
<div style="height: 20px;"></div>
<div id=two class=target>
<div class=child>
<div class=grandchild></div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html class=reftest-wait>
<title>Shared transitions: object-view-box with larger clip-path</title>
<link rel="help" href="https://github.com/WICG/shared-element-transitions">
<link rel="author" href="mailto:vmpstr@chromium.org">
<link rel="match" href="old-content-object-view-box-clip-path-ref.html">
<script src="/common/reftest-wait.js"></script>
<style>
.target {
color: red;
width: 100px;
height: 100px;
contain: paint;
overflow-clip-margin: 1000px;
position: relative;
top: 50px;
left: 50px;
}
.child {
width: 123px;
height: 150px;
background: lightblue;
position: relative;
top: -10px;
left: -20px;
}
.grandchild {
width: 25px;
height: 25px;
position: relative;
top: 20px;
left: 40px;
background: green;
}
#one {
page-transition-tag: target-one;
clip-path: inset(10px 12px 20px 28px);
}
#two {
page-transition-tag: target-two;
clip-path: inset(10px -12px 20px -28px);
}

html::page-transition-container(target-one),
html::page-transition-container(target-two) { animation-duration: 300s; }
html::page-transition-incoming-image(target-one),
html::page-transition-incoming-image(target-two) { animation: unset; opacity: 0; }
html::page-transition-outgoing-image(target-one),
html::page-transition-outgoing-image(target-two) {
animation: unset;
opacity: 1;
/* clip overflow, and verify inner contents only */
overflow: hidden;
}

html::page-transition-container(root) { animation: unset; opacity: 0; }
html::page-transition { background: lightpink; }
</style>

<div id=one class=target>
<div class=child>
<div class=grandchild></div>
</div>
</div>
<div style="height: 20px;"></div>
<div id=two class=target>
<div class=child>
<div class=grandchild></div>
</div>
</div>

<script>
async function runTest() {
document.createDocumentTransition().start(() =>
requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
}
onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
</script>

0 comments on commit db010ed

Please sign in to comment.