Skip to content

Commit

Permalink
blink: Ensure correct intrinsic sizing for transition elements.
Browse files Browse the repository at this point in the history
The intrinsic size of the replaced elements created for
DocumentTransition is the post page zoom size of an element. Apply the
page zoom factor to ensure this.

Also adds tests for the following cases:
- An element with a transform.
- Using object-view-box to display a subset of the element.

R=vmpstr@chromium.org

Bug: 1303102
Change-Id: Ib8fb3b391a481dd59bbe4e1c54c06532efd74444
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3579292
Auto-Submit: Khushal Sagar <khushalsagar@chromium.org>
Reviewed-by: Vladimir Levin <vmpstr@chromium.org>
Commit-Queue: Vladimir Levin <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#990709}
  • Loading branch information
khushalsagar authored and Chromium LUCI CQ committed Apr 9, 2022
1 parent 4e83984 commit 8c50f01
Show file tree
Hide file tree
Showing 13 changed files with 355 additions and 20 deletions.
16 changes: 9 additions & 7 deletions components/viz/service/transitions/surface_animation_manager.cc
Expand Up @@ -169,13 +169,15 @@ void ReplaceSharedElementWithRenderPass(
target_render_pass->CreateAndAppendSharedQuadState();
*copied_quad_state = *shared_element_quad.shared_quad_state;

copied_quad_state->quad_to_target_transform.PostTranslate(
-shared_pass_output_rect.x(), -shared_pass_output_rect.y());
copied_quad_state->quad_to_target_transform.PostScale(
shared_element_quad.rect.width() /
static_cast<SkScalar>(shared_pass_output_rect.width()),
shared_element_quad.rect.height() /
static_cast<SkScalar>(shared_pass_output_rect.height()));
gfx::Transform transform;
transform.Scale(shared_element_quad.rect.width() /
static_cast<SkScalar>(shared_pass_output_rect.width()),
shared_element_quad.rect.height() /
static_cast<SkScalar>(shared_pass_output_rect.height()));
transform.Translate(-shared_pass_output_rect.x(),
-shared_pass_output_rect.y());

copied_quad_state->quad_to_target_transform.PreconcatTransform(transform);

auto* render_pass_quad =
target_render_pass
Expand Down
4 changes: 4 additions & 0 deletions third_party/blink/renderer/core/css/transition.css
Expand Up @@ -19,6 +19,10 @@ html::page-transition-container(*) {
top: 0;
left: 0;
will-change: transform;

/* The transform applied to the container includes any translation necessary
for the original element's transform-origin. */
transform-origin: top left;
}

html::page-transition-container(root) {
Expand Down
Expand Up @@ -336,6 +336,7 @@ void DocumentTransitionStyleTracker::CaptureResolved() {
element_data->target_element = nullptr;
element_data->cached_border_box_size = element_data->border_box_size;
element_data->cached_viewport_matrix = element_data->viewport_matrix;
element_data->cached_device_pixel_ratio = element_data->device_pixel_ratio;
element_data->effect_node = nullptr;
}
root_effect_node_ = nullptr;
Expand Down Expand Up @@ -493,10 +494,10 @@ PseudoElement* DocumentTransitionStyleTracker::CreatePseudoElement(
document_->GetLayoutView()->GetLayoutSize(kIncludeScrollbars));
snapshot_id = old_root_snapshot_id_;
} else {
// If live data is tracking new elements then use the cached size for
// If live data is tracking new elements then use the cached data for
// the pseudo element displaying snapshot of old element.
size = HasLiveNewContent() ? element_data->border_box_size
: element_data->cached_border_box_size;
bool use_cached_data = HasLiveNewContent();
size = element_data->GetIntrinsicSize(use_cached_data);
snapshot_id = element_data->old_snapshot_id;
}
// Note that we say that this layer is not a live content
Expand All @@ -523,7 +524,8 @@ PseudoElement* DocumentTransitionStyleTracker::CreatePseudoElement(
document_->GetLayoutView()->GetLayoutSize(kIncludeScrollbars));
snapshot_id = new_root_snapshot_id_;
} else {
size = element_data->border_box_size;
bool use_cached_data = false;
size = element_data->GetIntrinsicSize(use_cached_data);
snapshot_id = element_data->new_snapshot_id;
}
auto* pseudo_element =
Expand Down Expand Up @@ -565,9 +567,10 @@ void DocumentTransitionStyleTracker::RunPostPrePaintSteps() {
continue;
}

float device_pixel_ratio = document_->DevicePixelRatio();
TransformationMatrix viewport_matrix =
layout_object->LocalToAbsoluteTransform();
viewport_matrix.Zoom(1.0 / document_->DevicePixelRatio());
viewport_matrix.Zoom(1.0 / device_pixel_ratio);

// ResizeObserverEntry is created to reuse the logic for parsing object size
// for different types of LayoutObjects.
Expand All @@ -582,12 +585,14 @@ void DocumentTransitionStyleTracker::RunPostPrePaintSteps() {
LayoutUnit(entry_size->inlineSize()));

if (viewport_matrix == element_data->viewport_matrix &&
border_box_size == element_data->border_box_size) {
border_box_size == element_data->border_box_size &&
device_pixel_ratio == element_data->device_pixel_ratio) {
continue;
}

element_data->viewport_matrix = viewport_matrix;
element_data->border_box_size = border_box_size;
element_data->device_pixel_ratio = device_pixel_ratio;

PseudoId live_content_element = HasLiveNewContent()
? kPseudoIdPageTransitionIncomingImage
Expand All @@ -597,8 +602,10 @@ void DocumentTransitionStyleTracker::RunPostPrePaintSteps() {
live_content_element, entry.key)) {
// A pseudo element of type |tansition*content| must be created using
// DocumentTransitionContentElement.
bool use_cached_data = false;
LayoutSize size = element_data->GetIntrinsicSize(use_cached_data);
static_cast<DocumentTransitionContentElement*>(pseudo_element)
->SetIntrinsicSize(border_box_size);
->SetIntrinsicSize(size);
}

needs_style_invalidation = true;
Expand Down Expand Up @@ -871,4 +878,15 @@ void DocumentTransitionStyleTracker::ElementData::Trace(
visitor->Trace(target_element);
}

LayoutSize DocumentTransitionStyleTracker::ElementData::GetIntrinsicSize(
bool use_cached_data) {
LayoutSize box_size =
use_cached_data ? cached_border_box_size : border_box_size;
float ratio =
use_cached_data ? cached_device_pixel_ratio : device_pixel_ratio;

box_size.Scale(ratio);
return box_size;
}

} // namespace blink
Expand Up @@ -7,6 +7,7 @@

#include "components/viz/common/shared_element_resource_id.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
#include "third_party/blink/renderer/platform/graphics/document_transition_shared_element_id.h"
Expand Down Expand Up @@ -127,6 +128,8 @@ class DocumentTransitionStyleTracker
struct ElementData : public GarbageCollected<ElementData> {
void Trace(Visitor* visitor) const;

LayoutSize GetIntrinsicSize(bool use_cached_data);

// The element in the current DOM whose state is being tracked and mirrored
// into the corresponding container pseudo element.
Member<Element> target_element;
Expand All @@ -135,10 +138,12 @@ class DocumentTransitionStyleTracker
// |target_element|. This information is mirrored into the UA stylesheet.
LayoutSize border_box_size;
TransformationMatrix viewport_matrix;
float device_pixel_ratio = 1.f;

// Computed info cached before the DOM switches to the new state.
LayoutSize cached_border_box_size;
TransformationMatrix cached_viewport_matrix;
float cached_device_pixel_ratio = 1.f;

// Valid if there is an element in the old DOM generating a snapshot.
viz::SharedElementResourceId old_snapshot_id;
Expand Down
Expand Up @@ -9,6 +9,7 @@
#include "cc/layers/document_transition_content_layer.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/document_transition/document_transition_content_element.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_replaced.h"

namespace blink {
Expand All @@ -26,7 +27,7 @@ class CORE_EXPORT LayoutDocumentTransitionContent : public LayoutReplaced {

protected:
PaintLayerType LayerTypeRequired() const override;

void IntrinsicSizeChanged() override { NOT_DESTROYED(); }
void PaintReplaced(const PaintInfo&,
const PhysicalOffset& paint_offset) const override;

Expand Down
Expand Up @@ -700,6 +700,7 @@
{
name: "CSSObjectViewBoxAndOverflow",
status: "experimental",
implied_by: ["DocumentTransition"],
},
{
name: "CSSOffsetPathRay",
Expand Down
7 changes: 2 additions & 5 deletions third_party/blink/web_tests/FlagExpectations/highdpi
Expand Up @@ -460,12 +460,9 @@ crbug.com/1295280 virtual/document-transition/wpt_internal/document-transition/c
crbug.com/1295280 virtual/document-transition/wpt_internal/document-transition/old-content-captures-opacity.html [ Failure ]
crbug.com/1295281 virtual/document-transition/wpt_internal/document-transition/new-content-captures-different-size.html [ Failure ]
crbug.com/1295281 virtual/document-transition/wpt_internal/document-transition/old-content-captures-different-size.html [ Failure ]
crbug.com/1295280 virtual/document-transition/wpt_internal/document-transition/content-with-clip.html [ Failure ]
crbug.com/1311421 virtual/document-transition/wpt_internal/document-transition/content-with-clip-max-texture-size.html [ Failure ]
crbug.com/1311421 virtual/document-transition/wpt_internal/document-transition/new-content-object-fit-none.html [ Failure ]
crbug.com/1311421 virtual/document-transition/wpt_internal/document-transition/old-content-object-fit-none.html [ Failure ]
crbug.com/1311421 virtual/document-transition/wpt_internal/document-transition/old-content-object-fit-fill.html [ Failure ]
crbug.com/1311421 virtual/document-transition/wpt_internal/document-transition/new-content-object-fit-fill.html [ Failure ]
crbug.com/1295281 virtual/document-transition/wpt_internal/document-transition/old-content-object-fit-fill.html [ Failure ]
crbug.com/1295281 virtual/document-transition/wpt_internal/document-transition/new-content-object-fit-fill.html [ Failure ]

crbug.com/1179544 compositing/canvas-with-object-fit-contain-in-composited-layer.html [ Failure ]
crbug.com/1179544 compositing/composited-replaced-subpixel-location.html [ Failure ]
Expand Down
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html class=reftest-wait>
<title>Shared transitions: object-view-box</title>
<link rel="help" href="https://github.com/WICG/shared-element-transitions">
<link rel="author" href="mailto:khushalsagar@chromium.org">
<link rel="match" href="content-with-transform-ref.html">

<script src="/common/reftest-wait.js"></script>
<style>
.target {
contain: paint;
width: 100px;
height: 100px;
transform: scale(2.0, 3.0);
}

.embedded {
width: 100px;
height: 50px;
}

.hidden {
contain: paint;
width: 10px;
height: 10px;
background: grey;
}

html::page-transition-container(hidden) { animation-duration: 300s; }
html::page-transition-image-wrapper(hidden) { animation: unset; opacity: 0; }

html::page-transition-incoming-image(target) {
animation: unset;
opacity: 1;
}
html::page-transition-outgoing-image(target) { animation: unset; opacity: 0; }

</style>

<div id="target" class="target">
<div class="embedded" style="background: green;">Shared</div>
<div class="embedded" style="background: blue">Element</div>
</div>
<div id=hidden class=hidden></div>

<script>
async function runTest() {
let t = document.createDocumentTransition();
t.setElement(hidden, "hidden");
t.setElement(target, "target");
t.start(() => {
t.setElement(hidden, "hidden");
t.setElement(target, "target");

requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
});
}
onload = () => requestAnimationFrame(runTest);
</script>

@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html class=reftest-wait>
<title>Shared transitions: object-view-box</title>
<link rel="help" href="https://github.com/WICG/shared-element-transitions">
<link rel="author" href="mailto:khushalsagar@chromium.org">
<link rel="match" href="content-with-transform-ref.html">

<script src="/common/reftest-wait.js"></script>
<style>
.target {
contain: paint;
width: 100px;
height: 100px;
transform: scale(2.0, 3.0);
}

.embedded {
width: 100px;
height: 50px;
}

.hidden {
contain: paint;
width: 10px;
height: 10px;
background: grey;
}

html::page-transition-container(hidden) { animation-duration: 300s; }
html::page-transition-image-wrapper(hidden) { animation: unset; opacity: 0; }

html::page-transition-outgoing-image(target) {
animation: unset;
opacity: 1;
}
html::page-transition-incoming-image(target) { animation: unset; opacity: 0; }

</style>

<div id="target" class="target">
<div class="embedded" style="background: green;">Shared</div>
<div class="embedded" style="background: blue">Element</div>
</div>
<div id=hidden class=hidden></div>

<script>
async function runTest() {
let t = document.createDocumentTransition();
t.setElement(hidden, "hidden");
t.setElement(target, "target");
t.start(() => {
t.setElement(hidden, "hidden");
t.setElement(target, "target");

requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
});
}
onload = () => requestAnimationFrame(runTest);
</script>

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<title>Shared transitions: object-view-box (ref)</title>
<link rel="help" href="https://github.com/WICG/shared-element-transitions">
<link rel="author" href="mailto:vmpstr@chromium.org">
<style>
.target {
contain: paint;
width: 100px;
height: 100px;
transform: scale(2.0, 3.0);
}

.embedded {
width: 100px;
height: 50px;
}

</style>
<div id="target" class="target">
<div class="embedded" style="background: green;">Shared</div>
<div class="embedded" style="background: blue">Element</div>
</div>
</div>

0 comments on commit 8c50f01

Please sign in to comment.