Chromium Code Reviews| OLD | NEW |
|---|---|
| 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( |
|
chrishtr
2017/07/27 15:13:39
Not going to look at code changes here, since flac
smcgruer
2017/07/28 17:35:57
Acknowledged.
| |
| 11 const FloatRect& viewport_rect, | 11 const FloatRect& overflow_clip_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. a nested inline parent. | |
| 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 = overflow_clip_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; |
| 44 | 54 |
| 45 box_rect.Move(right_delta, 0); | 55 box_rect.Move(right_delta, 0); |
| 46 } | 56 } |
| 47 | 57 |
| 48 if (HasAnchorEdge(kAnchorEdgeLeft)) { | 58 if (HasAnchorEdge(kAnchorEdgeLeft)) { |
| 49 float left_limit = viewport_rect.X() + left_offset_; | 59 float left_limit = overflow_clip_rect.X() + left_offset_; |
| 50 float left_delta = std::max<float>(0, left_limit - sticky_box_rect.X()); | 60 float left_delta = std::max<float>(0, left_limit - sticky_box_rect.X()); |
| 51 float available_space = std::max<float>( | 61 float available_space = std::max<float>( |
| 52 0, containing_block_rect.MaxX() - sticky_box_rect.MaxX()); | 62 0, containing_block_rect.MaxX() - sticky_box_rect.MaxX()); |
| 53 if (left_delta > available_space) | 63 if (left_delta > available_space) |
| 54 left_delta = available_space; | 64 left_delta = available_space; |
| 55 | 65 |
| 56 box_rect.Move(left_delta, 0); | 66 box_rect.Move(left_delta, 0); |
| 57 } | 67 } |
| 58 | 68 |
| 59 if (HasAnchorEdge(kAnchorEdgeBottom)) { | 69 if (HasAnchorEdge(kAnchorEdgeBottom)) { |
| 60 float bottom_limit = viewport_rect.MaxY() - bottom_offset_; | 70 float bottom_limit = overflow_clip_rect.MaxY() - bottom_offset_; |
| 61 float bottom_delta = | 71 float bottom_delta = |
| 62 std::min<float>(0, bottom_limit - sticky_box_rect.MaxY()); | 72 std::min<float>(0, bottom_limit - sticky_box_rect.MaxY()); |
| 63 float available_space = | 73 float available_space = |
| 64 std::min<float>(0, containing_block_rect.Y() - sticky_box_rect.Y()); | 74 std::min<float>(0, containing_block_rect.Y() - sticky_box_rect.Y()); |
| 65 if (bottom_delta < available_space) | 75 if (bottom_delta < available_space) |
| 66 bottom_delta = available_space; | 76 bottom_delta = available_space; |
| 67 | 77 |
| 68 box_rect.Move(0, bottom_delta); | 78 box_rect.Move(0, bottom_delta); |
| 69 } | 79 } |
| 70 | 80 |
| 71 if (HasAnchorEdge(kAnchorEdgeTop)) { | 81 if (HasAnchorEdge(kAnchorEdgeTop)) { |
| 72 float top_limit = viewport_rect.Y() + top_offset_; | 82 float top_limit = overflow_clip_rect.Y() + top_offset_; |
| 73 float top_delta = std::max<float>(0, top_limit - sticky_box_rect.Y()); | 83 float top_delta = std::max<float>(0, top_limit - sticky_box_rect.Y()); |
| 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 // Now that we have computed our current sticky offset, update the cached | |
| 95 // accumulated sticky offsets. | |
| 84 total_sticky_box_sticky_offset_ = ancestor_sticky_box_offset + sticky_offset; | 96 total_sticky_box_sticky_offset_ = ancestor_sticky_box_offset + sticky_offset; |
| 85 total_containing_block_sticky_offset_ = ancestor_sticky_box_offset + | 97 total_containing_block_sticky_offset_ = ancestor_sticky_box_offset + |
| 86 ancestor_containing_block_offset + | 98 ancestor_containing_block_offset + |
| 87 sticky_offset; | 99 sticky_offset; |
| 88 | 100 |
| 89 return sticky_offset; | 101 return sticky_offset; |
| 90 } | 102 } |
| 91 | 103 |
| 92 FloatSize StickyPositionScrollingConstraints::GetOffsetForStickyPosition( | 104 FloatSize StickyPositionScrollingConstraints::GetOffsetForStickyPosition( |
| 93 const StickyConstraintsMap& constraints_map) const { | 105 const StickyConstraintsMap& constraints_map) const { |
| 94 FloatSize nearest_sticky_box_shifting_sticky_box_constraints_offset; | 106 FloatSize nearest_sticky_layer_shifting_sticky_box_constraints_offset; |
| 95 if (nearest_sticky_box_shifting_sticky_box_) { | 107 if (nearest_sticky_layer_shifting_sticky_box_) { |
| 96 nearest_sticky_box_shifting_sticky_box_constraints_offset = | 108 nearest_sticky_layer_shifting_sticky_box_constraints_offset = |
| 97 constraints_map.at(nearest_sticky_box_shifting_sticky_box_->Layer()) | 109 constraints_map.at(nearest_sticky_layer_shifting_sticky_box_) |
| 98 .GetTotalStickyBoxStickyOffset(); | 110 .total_sticky_box_sticky_offset_; |
| 99 } | 111 } |
| 100 return total_sticky_box_sticky_offset_ - | 112 return total_sticky_box_sticky_offset_ - |
| 101 nearest_sticky_box_shifting_sticky_box_constraints_offset; | 113 nearest_sticky_layer_shifting_sticky_box_constraints_offset; |
| 114 } | |
| 115 | |
| 116 FloatSize StickyPositionScrollingConstraints::AncestorStickyBoxOffset( | |
| 117 const StickyConstraintsMap& constraints_map) { | |
| 118 if (!nearest_sticky_layer_shifting_sticky_box_) | |
| 119 return FloatSize(); | |
| 120 DCHECK(constraints_map.Contains(nearest_sticky_layer_shifting_sticky_box_)); | |
| 121 return constraints_map.at(nearest_sticky_layer_shifting_sticky_box_) | |
| 122 .total_sticky_box_sticky_offset_; | |
| 123 } | |
| 124 | |
| 125 FloatSize StickyPositionScrollingConstraints::AncestorContainingBlockOffset( | |
| 126 const StickyConstraintsMap& constraints_map) { | |
| 127 if (!nearest_sticky_layer_shifting_containing_block_) { | |
| 128 return FloatSize(); | |
| 129 } | |
| 130 DCHECK(constraints_map.Contains( | |
| 131 nearest_sticky_layer_shifting_containing_block_)); | |
| 132 return constraints_map.at(nearest_sticky_layer_shifting_containing_block_) | |
| 133 .total_containing_block_sticky_offset_; | |
| 102 } | 134 } |
| 103 | 135 |
| 104 } // namespace blink | 136 } // namespace blink |
| OLD | NEW |