Commit 08436a6b authored by David Bokan's avatar David Bokan Committed by Commit Bot

Convert sticky to layout units

Sticky constraints should use layout units like the rest of the layout
system. They should only be converted to float when passed to the
compositor.

Bug: 882075,1010961a
Change-Id: I34f54702c0918238171981fcd97a621dbe9bbdef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1943339
Commit-Queue: David Bokan <bokan@chromium.org>
Auto-Submit: David Bokan <bokan@chromium.org>
Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720336}
parent 5a4bbf1a
......@@ -144,7 +144,7 @@ class CORE_EXPORT LayoutBoxModelObject : public LayoutObject {
// Populates StickyPositionConstraints, setting the sticky box rect,
// containing block rect and updating the constraint offsets according to the
// available space.
FloatRect ComputeStickyConstrainingRect() const;
PhysicalRect ComputeStickyConstrainingRect() const;
void UpdateStickyPositionConstraints() const;
PhysicalOffset StickyPositionOffset() const;
bool IsSlowRepaintConstrainedObject() const;
......
......@@ -421,8 +421,7 @@ TEST_F(LayoutBoxModelObjectTest, StickyPositionConstraintInvalidation) {
scrollable_area->GetStickyConstraintsMap().Contains(sticky->Layer()));
EXPECT_EQ(25.f, scrollable_area->GetStickyConstraintsMap()
.at(sticky->Layer())
.scroll_container_relative_sticky_box_rect.Location()
.X());
.scroll_container_relative_sticky_box_rect.X());
To<HTMLElement>(target->GetNode())->classList().Add("hide");
GetDocument().View()->UpdateLifecycleToLayoutClean();
// Layout should invalidate the sticky constraints of the sticky element and
......@@ -435,8 +434,7 @@ TEST_F(LayoutBoxModelObjectTest, StickyPositionConstraintInvalidation) {
UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(50.f, scrollable_area->GetStickyConstraintsMap()
.at(sticky->Layer())
.scroll_container_relative_sticky_box_rect.Location()
.X());
.scroll_container_relative_sticky_box_rect.X());
}
// Verifies that the correct sticky-box shifting ancestor is found when
......
......@@ -4,18 +4,19 @@
#include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
namespace blink {
FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
const FloatRect& content_box_rect,
PhysicalOffset StickyPositionScrollingConstraints::ComputeStickyOffset(
const PhysicalRect& content_box_rect,
const StickyConstraintsMap& constraints_map) {
FloatRect sticky_box_rect = scroll_container_relative_sticky_box_rect;
FloatRect containing_block_rect =
PhysicalRect sticky_box_rect = scroll_container_relative_sticky_box_rect;
PhysicalRect containing_block_rect =
scroll_container_relative_containing_block_rect;
FloatSize ancestor_sticky_box_offset =
PhysicalOffset ancestor_sticky_box_offset =
AncestorStickyBoxOffset(constraints_map);
FloatSize ancestor_containing_block_offset =
PhysicalOffset ancestor_containing_block_offset =
AncestorContainingBlockOffset(constraints_map);
// Adjust the cached rect locations for any sticky ancestor elements. The
......@@ -41,55 +42,69 @@ FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
// shifting produces the final sticky offset below.
//
// As per the spec, 'left' overrides 'right' and 'top' overrides 'bottom'.
FloatRect box_rect = sticky_box_rect;
PhysicalRect box_rect = sticky_box_rect;
if (is_anchored_right) {
float right_limit = content_box_rect.MaxX() - right_offset;
float right_delta =
std::min<float>(0, right_limit - sticky_box_rect.MaxX());
float available_space =
std::min<float>(0, containing_block_rect.X() - sticky_box_rect.X());
LayoutUnit right_limit = content_box_rect.Right() - right_offset;
LayoutUnit right_delta = right_limit - sticky_box_rect.Right();
LayoutUnit available_space =
containing_block_rect.X() - sticky_box_rect.X();
right_delta = right_delta.ClampPositiveToZero();
available_space = available_space.ClampPositiveToZero();
if (right_delta < available_space)
right_delta = available_space;
box_rect.Move(right_delta, 0);
box_rect.Move(PhysicalOffset(right_delta, LayoutUnit()));
}
if (is_anchored_left) {
float left_limit = content_box_rect.X() + left_offset;
float left_delta = std::max<float>(0, left_limit - sticky_box_rect.X());
float available_space = std::max<float>(
0, containing_block_rect.MaxX() - sticky_box_rect.MaxX());
LayoutUnit left_limit = content_box_rect.X() + left_offset;
LayoutUnit left_delta = left_limit - sticky_box_rect.X();
LayoutUnit available_space =
containing_block_rect.Right() - sticky_box_rect.Right();
left_delta = left_delta.ClampNegativeToZero();
available_space = available_space.ClampNegativeToZero();
if (left_delta > available_space)
left_delta = available_space;
box_rect.Move(left_delta, 0);
box_rect.Move(PhysicalOffset(left_delta, LayoutUnit()));
}
if (is_anchored_bottom) {
float bottom_limit = content_box_rect.MaxY() - bottom_offset;
float bottom_delta =
std::min<float>(0, bottom_limit - sticky_box_rect.MaxY());
float available_space =
std::min<float>(0, containing_block_rect.Y() - sticky_box_rect.Y());
LayoutUnit bottom_limit = content_box_rect.Bottom() - bottom_offset;
LayoutUnit bottom_delta = bottom_limit - sticky_box_rect.Bottom();
LayoutUnit available_space =
containing_block_rect.Y() - sticky_box_rect.Y();
bottom_delta = bottom_delta.ClampPositiveToZero();
available_space = available_space.ClampPositiveToZero();
if (bottom_delta < available_space)
bottom_delta = available_space;
box_rect.Move(0, bottom_delta);
box_rect.Move(PhysicalOffset(LayoutUnit(), bottom_delta));
}
if (is_anchored_top) {
float top_limit = content_box_rect.Y() + top_offset;
float top_delta = std::max<float>(0, top_limit - sticky_box_rect.Y());
float available_space = std::max<float>(
0, containing_block_rect.MaxY() - sticky_box_rect.MaxY());
LayoutUnit top_limit = content_box_rect.Y() + top_offset;
LayoutUnit top_delta = top_limit - sticky_box_rect.Y();
LayoutUnit available_space =
containing_block_rect.Bottom() - sticky_box_rect.Bottom();
top_delta = top_delta.ClampNegativeToZero();
available_space = available_space.ClampNegativeToZero();
if (top_delta > available_space)
top_delta = available_space;
box_rect.Move(0, top_delta);
box_rect.Move(PhysicalOffset(LayoutUnit(), top_delta));
}
FloatSize sticky_offset = box_rect.Location() - sticky_box_rect.Location();
PhysicalOffset sticky_offset = box_rect.offset - sticky_box_rect.offset;
// Now that we have computed our current sticky offset, update the cached
// accumulated sticky offsets.
......@@ -101,25 +116,26 @@ FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
return sticky_offset;
}
FloatSize StickyPositionScrollingConstraints::GetOffsetForStickyPosition(
PhysicalOffset StickyPositionScrollingConstraints::GetOffsetForStickyPosition(
const StickyConstraintsMap& constraints_map) const {
return total_sticky_box_sticky_offset -
AncestorStickyBoxOffset(constraints_map);
}
FloatSize StickyPositionScrollingConstraints::AncestorStickyBoxOffset(
PhysicalOffset StickyPositionScrollingConstraints::AncestorStickyBoxOffset(
const StickyConstraintsMap& constraints_map) const {
if (!nearest_sticky_layer_shifting_sticky_box)
return FloatSize();
return PhysicalOffset();
DCHECK(constraints_map.Contains(nearest_sticky_layer_shifting_sticky_box));
return constraints_map.at(nearest_sticky_layer_shifting_sticky_box)
.total_sticky_box_sticky_offset;
}
FloatSize StickyPositionScrollingConstraints::AncestorContainingBlockOffset(
PhysicalOffset
StickyPositionScrollingConstraints::AncestorContainingBlockOffset(
const StickyConstraintsMap& constraints_map) const {
if (!nearest_sticky_layer_shifting_containing_block) {
return FloatSize();
return PhysicalOffset();
}
DCHECK(
constraints_map.Contains(nearest_sticky_layer_shifting_containing_block));
......
......@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_STICKY_POSITION_SCROLLING_CONSTRAINTS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_STICKY_POSITION_SCROLLING_CONSTRAINTS_H_
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
......@@ -85,8 +85,8 @@ struct StickyPositionScrollingConstraints final {
//
// This method is non-const as we cache internal state for performance; see
// documentation in the implementation for details.
FloatSize ComputeStickyOffset(const FloatRect& content_box_rect,
const StickyConstraintsMap&);
PhysicalOffset ComputeStickyOffset(const PhysicalRect& content_box_rect,
const StickyConstraintsMap&);
// Returns the last-computed offset of the sticky box from its original
// position before scroll.
......@@ -94,17 +94,17 @@ struct StickyPositionScrollingConstraints final {
// This method exists for performance (to avoid recomputing the sticky offset)
// and must only be called when compositing inputs are clean for the sticky
// element. (Or after prepaint for CompositeAfterPaint).
FloatSize GetOffsetForStickyPosition(const StickyConstraintsMap&) const;
PhysicalOffset GetOffsetForStickyPosition(const StickyConstraintsMap&) const;
bool is_anchored_left : 1;
bool is_anchored_right : 1;
bool is_anchored_top : 1;
bool is_anchored_bottom : 1;
float left_offset = 0.f;
float right_offset = 0.f;
float top_offset = 0.f;
float bottom_offset = 0.f;
LayoutUnit left_offset;
LayoutUnit right_offset;
LayoutUnit top_offset;
LayoutUnit bottom_offset;
// The containing block rect and sticky box rect are the basic components
// for calculating the sticky offset to apply after a scroll. Consider the
......@@ -119,12 +119,12 @@ struct StickyPositionScrollingConstraints final {
// The layout position of the containing block relative to the scroll
// container. When calculating the sticky offset it is used to ensure the
// sticky element stays bounded by its containing block.
FloatRect scroll_container_relative_containing_block_rect;
PhysicalRect scroll_container_relative_containing_block_rect;
// The layout position of the sticky element relative to the scroll container.
// When calculating the sticky offset it is used to determine how large the
// offset needs to be to satisfy the sticky constraints.
FloatRect scroll_container_relative_sticky_box_rect;
PhysicalRect scroll_container_relative_sticky_box_rect;
// In the case of nested sticky elements the layout position of the sticky
// element and its containing block are not accurate (as they are affected by
......@@ -158,16 +158,17 @@ struct StickyPositionScrollingConstraints final {
//
// In the above example, both outerInline and innerInline have the same
// containing block - the outermost <div>.
FloatSize total_sticky_box_sticky_offset;
PhysicalOffset total_sticky_box_sticky_offset;
// The containing block offset accumulates all sticky-related offsets between
// this element and the ancestor scroller. If this element is a containing
// block shifting ancestor for some descendant, it shifts the descendant's
// constraint rects by its entire offset.
FloatSize total_containing_block_sticky_offset;
PhysicalOffset total_containing_block_sticky_offset;
FloatSize AncestorStickyBoxOffset(const StickyConstraintsMap&) const;
FloatSize AncestorContainingBlockOffset(const StickyConstraintsMap&) const;
PhysicalOffset AncestorStickyBoxOffset(const StickyConstraintsMap&) const;
PhysicalOffset AncestorContainingBlockOffset(
const StickyConstraintsMap&) const;
};
} // namespace blink
......
......@@ -560,17 +560,19 @@ void FragmentPaintPropertyTreeBuilder::UpdateStickyTranslation() {
constraint->is_anchored_right = layout_constraint.is_anchored_right;
constraint->is_anchored_top = layout_constraint.is_anchored_top;
constraint->is_anchored_bottom = layout_constraint.is_anchored_bottom;
constraint->left_offset = layout_constraint.left_offset;
constraint->right_offset = layout_constraint.right_offset;
constraint->top_offset = layout_constraint.top_offset;
constraint->bottom_offset = layout_constraint.bottom_offset;
constraint->left_offset = layout_constraint.left_offset.ToFloat();
constraint->right_offset = layout_constraint.right_offset.ToFloat();
constraint->top_offset = layout_constraint.top_offset.ToFloat();
constraint->bottom_offset = layout_constraint.bottom_offset.ToFloat();
constraint->constraint_box_rect =
RoundedIntRect(box_model.ComputeStickyConstrainingRect());
constraint->scroll_container_relative_sticky_box_rect = RoundedIntRect(
layout_constraint.scroll_container_relative_sticky_box_rect);
constraint
->scroll_container_relative_containing_block_rect = RoundedIntRect(
layout_constraint.scroll_container_relative_containing_block_rect);
PixelSnappedIntRect(box_model.ComputeStickyConstrainingRect());
constraint->scroll_container_relative_sticky_box_rect =
PixelSnappedIntRect(
layout_constraint.scroll_container_relative_sticky_box_rect);
constraint->scroll_container_relative_containing_block_rect =
PixelSnappedIntRect(
layout_constraint
.scroll_container_relative_containing_block_rect);
if (PaintLayer* sticky_box_shifting_ancestor =
layout_constraint.nearest_sticky_layer_shifting_sticky_box) {
constraint->nearest_element_shifting_sticky_box =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment