Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.cpp

Issue 2961613002: Slightly refactor StickyPositionScrollingConstraints API and add documentation (Closed)
Patch Set: More documentation, split out ancestor offset calculation Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/page/scrolling/StickyPositionScrollingConstraints.h" 5 #include "core/page/scrolling/StickyPositionScrollingConstraints.h"
6 #include "core/paint/PaintLayer.h" 6 #include "core/paint/PaintLayer.h"
7 7
8 namespace blink { 8 namespace blink {
9 9
10 FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset( 10 FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
11 const FloatRect& viewport_rect, 11 const FloatRect& viewport_rect,
12 const StickyPositionScrollingConstraints* ancestor_sticky_box_constraints, 12 const StickyConstraintsMap& constraints_map) {
13 const StickyPositionScrollingConstraints*
14 ancestor_containing_block_constraints) {
15 // Adjust the constraint rect locations based on our ancestor sticky elements
16 // These adjustments are necessary to avoid double offsetting in the case of
17 // nested sticky elements.
18 FloatSize ancestor_sticky_box_offset =
19 ancestor_sticky_box_constraints
20 ? ancestor_sticky_box_constraints->GetTotalStickyBoxStickyOffset()
21 : FloatSize();
22 FloatSize ancestor_containing_block_offset =
23 ancestor_containing_block_constraints
24 ? ancestor_containing_block_constraints
25 ->GetTotalContainingBlockStickyOffset()
26 : FloatSize();
27 FloatRect sticky_box_rect = scroll_container_relative_sticky_box_rect_; 13 FloatRect sticky_box_rect = scroll_container_relative_sticky_box_rect_;
28 FloatRect containing_block_rect = 14 FloatRect containing_block_rect =
29 scroll_container_relative_containing_block_rect_; 15 scroll_container_relative_containing_block_rect_;
16 FloatSize ancestor_sticky_box_offset =
17 AncestorStickyBoxOffset(constraints_map);
18 FloatSize ancestor_containing_block_offset =
19 AncestorContainingBlockOffset(constraints_map);
20
21 // Adjust the cached rect locations for any sticky ancestor elements. The
22 // sticky offset applied to those ancestors affects us as follows:
23 //
24 // 1. |nearest_sticky_layer_shifting_sticky_box_| is a sticky layer between
25 // ourselves and our containing block, e.g. an inline parent. As such,
smcgruer 2017/06/26 19:18:56 I think this is inaccurate, an inline parent is in
flackr 2017/06/29 15:24:10 Yeah so it needs to be a sticky layer that is not
smcgruer 2017/06/29 18:51:46 Nested inline appears to work, so will likely use
flackr 2017/06/30 02:48:35 Yes, I was thinking it might be related if the rea
smcgruer 2017/07/07 13:51:57 Fixed the comment.
26 // it shifts only the sticky_box_rect, and not the containing_block_rect.
27 // 2. |nearest_sticky_layer_shifting_containing_block_| is a sticky layer
28 // between our containing block (inclusive) and our scroll ancestor
29 // (exclusive). As such, it shifts both the sticky_box_rect and the
30 // containing_block_rect.
31 //
32 // Note that this calculation assumes that |ComputeStickyOffset| is being
33 // called top down, e.g. it has been called on any ancestors we have before
34 // being called on us.
30 sticky_box_rect.Move(ancestor_sticky_box_offset + 35 sticky_box_rect.Move(ancestor_sticky_box_offset +
31 ancestor_containing_block_offset); 36 ancestor_containing_block_offset);
32 containing_block_rect.Move(ancestor_containing_block_offset); 37 containing_block_rect.Move(ancestor_containing_block_offset);
33 38
39 // We now attempt to shift sticky_box_rect to obey the specified sticky
40 // constraints, whilst always staying within our containing block. This
41 // shifting produces the final sticky offset below.
42 //
43 // As per the spec, 'left' overrides 'right' and 'top' overrides 'bottom'.
34 FloatRect box_rect = sticky_box_rect; 44 FloatRect box_rect = sticky_box_rect;
35 45
36 if (HasAnchorEdge(kAnchorEdgeRight)) { 46 if (HasAnchorEdge(kAnchorEdgeRight)) {
37 float right_limit = viewport_rect.MaxX() - right_offset_; 47 float right_limit = viewport_rect.MaxX() - right_offset_;
38 float right_delta = 48 float right_delta =
39 std::min<float>(0, right_limit - sticky_box_rect.MaxX()); 49 std::min<float>(0, right_limit - sticky_box_rect.MaxX());
40 float available_space = 50 float available_space =
41 std::min<float>(0, containing_block_rect.X() - sticky_box_rect.X()); 51 std::min<float>(0, containing_block_rect.X() - sticky_box_rect.X());
42 if (right_delta < available_space) 52 if (right_delta < available_space)
43 right_delta = available_space; 53 right_delta = available_space;
(...skipping 30 matching lines...) Expand all
74 float available_space = std::max<float>( 84 float available_space = std::max<float>(
75 0, containing_block_rect.MaxY() - sticky_box_rect.MaxY()); 85 0, containing_block_rect.MaxY() - sticky_box_rect.MaxY());
76 if (top_delta > available_space) 86 if (top_delta > available_space)
77 top_delta = available_space; 87 top_delta = available_space;
78 88
79 box_rect.Move(0, top_delta); 89 box_rect.Move(0, top_delta);
80 } 90 }
81 91
82 FloatSize sticky_offset = box_rect.Location() - sticky_box_rect.Location(); 92 FloatSize sticky_offset = box_rect.Location() - sticky_box_rect.Location();
83 93
94 // For performance, we cache our accumulated sticky offsets for any descendant
95 // sticky to use in it's own |ComputeStickyOffset| call. If these were not
96 // cached, one would instead need to call |ComputeStickyOffset| on every
97 // sticky ancestor in turn, accumulating the results.
98
99 // TODO(smcgruer): Document why these are calculated like this and why the two
smcgruer 2017/06/26 19:18:56 As per our IM discussion, I am still trying to exp
100 // different members are necessary.
84 total_sticky_box_sticky_offset_ = ancestor_sticky_box_offset + sticky_offset; 101 total_sticky_box_sticky_offset_ = ancestor_sticky_box_offset + sticky_offset;
85 total_containing_block_sticky_offset_ = ancestor_sticky_box_offset + 102 total_containing_block_sticky_offset_ = ancestor_sticky_box_offset +
86 ancestor_containing_block_offset + 103 ancestor_containing_block_offset +
87 sticky_offset; 104 sticky_offset;
88 105
89 return sticky_offset; 106 return sticky_offset;
90 } 107 }
91 108
92 FloatSize StickyPositionScrollingConstraints::GetOffsetForStickyPosition( 109 FloatSize StickyPositionScrollingConstraints::GetOffsetForStickyPosition(
93 const StickyConstraintsMap& constraints_map) const { 110 const StickyConstraintsMap& constraints_map) const {
94 FloatSize nearest_sticky_box_shifting_sticky_box_constraints_offset; 111 FloatSize nearest_sticky_layer_shifting_sticky_box_constraints_offset;
95 if (nearest_sticky_box_shifting_sticky_box_) { 112 if (nearest_sticky_layer_shifting_sticky_box_) {
96 nearest_sticky_box_shifting_sticky_box_constraints_offset = 113 nearest_sticky_layer_shifting_sticky_box_constraints_offset =
97 constraints_map.at(nearest_sticky_box_shifting_sticky_box_->Layer()) 114 constraints_map.at(nearest_sticky_layer_shifting_sticky_box_)
98 .GetTotalStickyBoxStickyOffset(); 115 .total_sticky_box_sticky_offset_;
99 } 116 }
100 return total_sticky_box_sticky_offset_ - 117 return total_sticky_box_sticky_offset_ -
101 nearest_sticky_box_shifting_sticky_box_constraints_offset; 118 nearest_sticky_layer_shifting_sticky_box_constraints_offset;
119 }
120
121 FloatSize StickyPositionScrollingConstraints::AncestorStickyBoxOffset(
122 const StickyConstraintsMap& constraints_map) {
123 if (!nearest_sticky_layer_shifting_sticky_box_)
124 return FloatSize();
125 DCHECK(constraints_map.Contains(nearest_sticky_layer_shifting_sticky_box_));
flackr 2017/06/29 15:24:10 Is this check necessary when we use the constraint
smcgruer 2017/06/29 18:51:46 It's necessary. at() just calls EmptyValue() if it
126 return constraints_map.at(nearest_sticky_layer_shifting_sticky_box_)
127 .total_sticky_box_sticky_offset_;
128 }
129
130 FloatSize StickyPositionScrollingConstraints::AncestorContainingBlockOffset(
131 const StickyConstraintsMap& constraints_map) {
132 if (!nearest_sticky_layer_shifting_containing_block_)
133 return FloatSize();
134 DCHECK(constraints_map.Contains(
135 nearest_sticky_layer_shifting_containing_block_));
136 return constraints_map.at(nearest_sticky_layer_shifting_containing_block_)
137 .total_containing_block_sticky_offset_;
102 } 138 }
103 139
104 } // namespace blink 140 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698