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

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc

Issue 2805283003: Inline algorithm should take into account the wrapper's clearance line. (Closed)
Patch Set: git rebase-update Created 3 years, 8 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
« no previous file with comments | « third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/layout/ng/ng_block_layout_algorithm.h" 5 #include "core/layout/ng/ng_block_layout_algorithm.h"
6 6
7 #include "core/layout/ng/inline/ng_inline_node.h" 7 #include "core/layout/ng/inline/ng_inline_node.h"
8 #include "core/layout/ng/ng_absolute_utils.h" 8 #include "core/layout/ng/ng_absolute_utils.h"
9 #include "core/layout/ng/ng_block_child_iterator.h" 9 #include "core/layout/ng/ng_block_child_iterator.h"
10 #include "core/layout/ng/ng_box_fragment.h" 10 #include "core/layout/ng/ng_box_fragment.h"
11 #include "core/layout/ng/ng_constraint_space.h" 11 #include "core/layout/ng/ng_constraint_space.h"
12 #include "core/layout/ng/ng_constraint_space_builder.h" 12 #include "core/layout/ng/ng_constraint_space_builder.h"
13 #include "core/layout/ng/ng_floats_utils.h" 13 #include "core/layout/ng/ng_floats_utils.h"
14 #include "core/layout/ng/ng_fragment.h" 14 #include "core/layout/ng/ng_fragment.h"
15 #include "core/layout/ng/ng_fragment_builder.h" 15 #include "core/layout/ng/ng_fragment_builder.h"
16 #include "core/layout/ng/ng_layout_opportunity_iterator.h" 16 #include "core/layout/ng/ng_layout_opportunity_iterator.h"
17 #include "core/layout/ng/ng_length_utils.h" 17 #include "core/layout/ng/ng_length_utils.h"
18 #include "core/layout/ng/ng_out_of_flow_layout_part.h" 18 #include "core/layout/ng/ng_out_of_flow_layout_part.h"
19 #include "core/layout/ng/ng_space_utils.h" 19 #include "core/layout/ng/ng_space_utils.h"
20 #include "core/style/ComputedStyle.h" 20 #include "core/style/ComputedStyle.h"
21 #include "platform/LengthFunctions.h" 21 #include "platform/LengthFunctions.h"
22 #include "wtf/Optional.h" 22 #include "wtf/Optional.h"
23 23
24 namespace blink { 24 namespace blink {
25 namespace { 25 namespace {
26 26
27 // Adjusts {@code offset} to the clearance line.
28 void AdjustToClearance(const WTF::Optional<LayoutUnit>& clearance_offset,
29 NGLogicalOffset* offset) {
30 DCHECK(offset);
31 if (clearance_offset) {
32 offset->block_offset =
33 std::max(clearance_offset.value(), offset->block_offset);
34 }
35 }
36
27 // Returns if a child may be affected by its clear property. I.e. it will 37 // Returns if a child may be affected by its clear property. I.e. it will
28 // actually clear a float. 38 // actually clear a float.
29 bool ClearanceMayAffectLayout( 39 bool ClearanceMayAffectLayout(
30 const NGConstraintSpace& space, 40 const NGConstraintSpace& space,
31 const Vector<RefPtr<NGFloatingObject>>& unpositioned_floats, 41 const Vector<RefPtr<NGFloatingObject>>& unpositioned_floats,
32 const ComputedStyle& child_style) { 42 const ComputedStyle& child_style) {
33 const NGExclusions& exclusions = *space.Exclusions(); 43 const NGExclusions& exclusions = *space.Exclusions();
34 EClear clear = child_style.Clear(); 44 EClear clear = child_style.Clear();
35 bool should_clear_left = (clear == EClear::kBoth || clear == EClear::kLeft); 45 bool should_clear_left = (clear == EClear::kBoth || clear == EClear::kLeft);
36 bool should_clear_right = (clear == EClear::kBoth || clear == EClear::kRight); 46 bool should_clear_right = (clear == EClear::kBoth || clear == EClear::kRight);
(...skipping 19 matching lines...) Expand all
56 66
57 // Whether we've run out of space in this flow. If so, there will be no work 67 // Whether we've run out of space in this flow. If so, there will be no work
58 // left to do for this block in this fragmentainer. 68 // left to do for this block in this fragmentainer.
59 bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) { 69 bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) {
60 return space.HasBlockFragmentation() && 70 return space.HasBlockFragmentation() &&
61 content_size >= space.FragmentainerSpaceAvailable(); 71 content_size >= space.FragmentainerSpaceAvailable();
62 } 72 }
63 73
64 } // namespace 74 } // namespace
65 75
76 void MaybeUpdateFragmentBfcOffset(const NGConstraintSpace& space,
77 const NGLogicalOffset& offset,
78 NGFragmentBuilder* builder) {
79 DCHECK(builder);
80 if (!builder->BfcOffset()) {
81 NGLogicalOffset mutable_offset(offset);
82 AdjustToClearance(space.ClearanceOffset(), &mutable_offset);
83 builder->SetBfcOffset(mutable_offset);
84 }
85 }
86
66 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node, 87 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node,
67 NGConstraintSpace* space, 88 NGConstraintSpace* space,
68 NGBlockBreakToken* break_token) 89 NGBlockBreakToken* break_token)
69 : NGLayoutAlgorithm(node, space, break_token), 90 : NGLayoutAlgorithm(node, space, break_token),
70 builder_(NGPhysicalFragment::kFragmentBox, node), 91 builder_(NGPhysicalFragment::kFragmentBox, node),
71 space_builder_(constraint_space_) {} 92 space_builder_(constraint_space_) {}
72 93
73 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize() 94 Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize()
74 const { 95 const {
75 MinMaxContentSize sizes; 96 MinMaxContentSize sizes;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 LayoutUnit inline_offset = 134 LayoutUnit inline_offset =
114 border_and_padding_.inline_start + curr_child_margins_.inline_start; 135 border_and_padding_.inline_start + curr_child_margins_.inline_start;
115 LayoutUnit block_offset = content_size_; 136 LayoutUnit block_offset = content_size_;
116 if (known_fragment_offset) { 137 if (known_fragment_offset) {
117 block_offset = known_fragment_offset.value().block_offset - 138 block_offset = known_fragment_offset.value().block_offset -
118 builder_.BfcOffset().value().block_offset; 139 builder_.BfcOffset().value().block_offset;
119 } 140 }
120 return {inline_offset, block_offset}; 141 return {inline_offset, block_offset};
121 } 142 }
122 143
123 void NGBlockLayoutAlgorithm::UpdateFragmentBfcOffset(
124 const NGLogicalOffset& offset) {
125 if (!builder_.BfcOffset()) {
126 NGLogicalOffset bfc_offset = offset;
127 if (ConstraintSpace().ClearanceOffset()) {
128 bfc_offset.block_offset = std::max(
129 ConstraintSpace().ClearanceOffset().value(), offset.block_offset);
130 }
131 builder_.SetBfcOffset(bfc_offset);
132 }
133 }
134
135 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() { 144 RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
136 WTF::Optional<MinMaxContentSize> min_max_size; 145 WTF::Optional<MinMaxContentSize> min_max_size;
137 if (NeedMinMaxContentSize(ConstraintSpace(), Style())) 146 if (NeedMinMaxContentSize(ConstraintSpace(), Style()))
138 min_max_size = ComputeMinMaxContentSize(); 147 min_max_size = ComputeMinMaxContentSize();
139 148
140 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + 149 border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) +
141 ComputePadding(ConstraintSpace(), Style()); 150 ComputePadding(ConstraintSpace(), Style());
142 151
143 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of -1? 152 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of -1?
144 NGLogicalSize size( 153 NGLogicalSize size(
(...skipping 27 matching lines...) Expand all
172 content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start; 181 content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start;
173 182
174 curr_margin_strut_ = ConstraintSpace().MarginStrut(); 183 curr_margin_strut_ = ConstraintSpace().MarginStrut();
175 curr_bfc_offset_ = ConstraintSpace().BfcOffset(); 184 curr_bfc_offset_ = ConstraintSpace().BfcOffset();
176 185
177 // Margins collapsing: 186 // Margins collapsing:
178 // Do not collapse margins between parent and its child if there is 187 // Do not collapse margins between parent and its child if there is
179 // border/padding between them. 188 // border/padding between them.
180 if (border_and_padding_.block_start) { 189 if (border_and_padding_.block_start) {
181 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 190 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
182 UpdateFragmentBfcOffset(curr_bfc_offset_); 191 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
192 &builder_);
183 curr_margin_strut_ = NGMarginStrut(); 193 curr_margin_strut_ = NGMarginStrut();
184 } 194 }
185 195
186 // If a new formatting context hits the if branch above then the BFC offset is 196 // If a new formatting context hits the if branch above then the BFC offset is
187 // still {} as the margin strut from the constraint space must also be empty. 197 // still {} as the margin strut from the constraint space must also be empty.
188 if (ConstraintSpace().IsNewFormattingContext()) { 198 if (ConstraintSpace().IsNewFormattingContext()) {
189 UpdateFragmentBfcOffset(curr_bfc_offset_); 199 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
200 &builder_);
190 DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); 201 DCHECK_EQ(curr_margin_strut_, NGMarginStrut());
191 DCHECK_EQ(builder_.BfcOffset().value(), NGLogicalOffset()); 202 DCHECK_EQ(builder_.BfcOffset().value(), NGLogicalOffset());
192 curr_bfc_offset_ = {}; 203 curr_bfc_offset_ = {};
193 } 204 }
194 205
195 curr_bfc_offset_.block_offset += content_size_; 206 curr_bfc_offset_.block_offset += content_size_;
196 207
197 while (child) { 208 while (child) {
198 if (child->IsBlock()) { 209 if (child->IsBlock()) {
199 EPosition position = child->Style().GetPosition(); 210 EPosition position = child->Style().GetPosition();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 size.block_size = 252 size.block_size =
242 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); 253 ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
243 builder_.SetBlockSize(size.block_size); 254 builder_.SetBlockSize(size.block_size);
244 255
245 // Layout our absolute and fixed positioned children. 256 // Layout our absolute and fixed positioned children.
246 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &builder_).Run(); 257 NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &builder_).Run();
247 258
248 // Non-empty blocks always know their position in space: 259 // Non-empty blocks always know their position in space:
249 if (size.block_size) { 260 if (size.block_size) {
250 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 261 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
251 UpdateFragmentBfcOffset(curr_bfc_offset_); 262 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
263 &builder_);
252 PositionPendingFloats(curr_bfc_offset_.block_offset, 264 PositionPendingFloats(curr_bfc_offset_.block_offset,
253 MutableConstraintSpace(), &builder_); 265 MutableConstraintSpace(), &builder_);
254 } 266 }
255 267
256 // Margins collapsing: 268 // Margins collapsing:
257 // Do not collapse margins between the last in-flow child and bottom margin 269 // Do not collapse margins between the last in-flow child and bottom margin
258 // of its parent if the parent has height != auto() 270 // of its parent if the parent has height != auto()
259 if (!Style().LogicalHeight().IsAuto()) { 271 if (!Style().LogicalHeight().IsAuto()) {
260 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight. 272 // TODO(glebl): handle minLogicalHeight, maxLogicalHeight.
261 curr_margin_strut_ = NGMarginStrut(); 273 curr_margin_strut_ = NGMarginStrut();
(...skipping 28 matching lines...) Expand all
290 child->IsBlock() && !is_floating && 302 child->IsBlock() && !is_floating &&
291 !IsNewFormattingContextForBlockLevelChild(Style(), *child) && 303 !IsNewFormattingContextForBlockLevelChild(Style(), *child) &&
292 ClearanceMayAffectLayout(ConstraintSpace(), builder_.UnpositionedFloats(), 304 ClearanceMayAffectLayout(ConstraintSpace(), builder_.UnpositionedFloats(),
293 child->Style()); 305 child->Style());
294 306
295 // Children which may clear a float need to force all the pending floats to 307 // Children which may clear a float need to force all the pending floats to
296 // be positioned before layout. This also resolves the fragment's bfc offset. 308 // be positioned before layout. This also resolves the fragment's bfc offset.
297 if (should_position_pending_floats) { 309 if (should_position_pending_floats) {
298 LayoutUnit origin_point_block_offset = 310 LayoutUnit origin_point_block_offset =
299 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum(); 311 curr_bfc_offset_.block_offset + curr_margin_strut_.Sum();
300 UpdateFragmentBfcOffset( 312 MaybeUpdateFragmentBfcOffset(
301 {curr_bfc_offset_.inline_offset, origin_point_block_offset}); 313 ConstraintSpace(),
314 {curr_bfc_offset_.inline_offset, origin_point_block_offset}, &builder_);
302 PositionPendingFloats(origin_point_block_offset, MutableConstraintSpace(), 315 PositionPendingFloats(origin_point_block_offset, MutableConstraintSpace(),
303 &builder_); 316 &builder_);
304 } 317 }
305 318
306 bool is_inflow = child->IsInline() || !is_floating; 319 bool is_inflow = child->IsInline() || !is_floating;
307 320
308 // Only inflow children (e.g. not floats) are included in the child's margin 321 // Only inflow children (e.g. not floats) are included in the child's margin
309 // strut as they do not participate in margin collapsing. 322 // strut as they do not participate in margin collapsing.
310 if (is_inflow) { 323 if (is_inflow) {
311 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; 324 curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start;
(...skipping 12 matching lines...) Expand all
324 bool should_collapse_margins = 337 bool should_collapse_margins =
325 child->IsInline() || 338 child->IsInline() ||
326 (!is_floating && 339 (!is_floating &&
327 IsNewFormattingContextForBlockLevelChild(Style(), *child)); 340 IsNewFormattingContextForBlockLevelChild(Style(), *child));
328 341
329 // Inline children or children which establish a block formatting context 342 // Inline children or children which establish a block formatting context
330 // collapse margins and position themselves immediately as they need to know 343 // collapse margins and position themselves immediately as they need to know
331 // their BFC offset for fragmentation purposes. 344 // their BFC offset for fragmentation purposes.
332 if (should_collapse_margins) { 345 if (should_collapse_margins) {
333 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); 346 curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
334 UpdateFragmentBfcOffset(curr_bfc_offset_); 347 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
348 &builder_);
335 PositionPendingFloats(curr_bfc_offset_.block_offset, 349 PositionPendingFloats(curr_bfc_offset_.block_offset,
336 MutableConstraintSpace(), &builder_); 350 MutableConstraintSpace(), &builder_);
337 curr_margin_strut_ = {}; 351 curr_margin_strut_ = {};
338 } 352 }
339 } 353 }
340 354
341 void NGBlockLayoutAlgorithm::FinishChildLayout( 355 void NGBlockLayoutAlgorithm::FinishChildLayout(
342 NGLayoutInputNode* child, 356 NGLayoutInputNode* child,
343 NGConstraintSpace* child_space, 357 NGConstraintSpace* child_space,
344 RefPtr<NGLayoutResult> layout_result) { 358 RefPtr<NGLayoutResult> layout_result) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 390
377 // Determine the fragment's position in the parent space either by using 391 // Determine the fragment's position in the parent space either by using
378 // content_size_ or known fragment's BFC offset. 392 // content_size_ or known fragment's BFC offset.
379 WTF::Optional<NGLogicalOffset> bfc_offset; 393 WTF::Optional<NGLogicalOffset> bfc_offset;
380 if (child_space->IsNewFormattingContext()) { 394 if (child_space->IsNewFormattingContext()) {
381 DCHECK(builder_.BfcOffset()); 395 DCHECK(builder_.BfcOffset());
382 bfc_offset = curr_bfc_offset_; 396 bfc_offset = curr_bfc_offset_;
383 } else if (fragment.BfcOffset()) { 397 } else if (fragment.BfcOffset()) {
384 // Fragment that knows its offset can be used to set parent's BFC position. 398 // Fragment that knows its offset can be used to set parent's BFC position.
385 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; 399 curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset;
386 UpdateFragmentBfcOffset(curr_bfc_offset_); 400 MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
401 &builder_);
387 PositionPendingFloats(curr_bfc_offset_.block_offset, 402 PositionPendingFloats(curr_bfc_offset_.block_offset,
388 MutableConstraintSpace(), &builder_); 403 MutableConstraintSpace(), &builder_);
389 bfc_offset = curr_bfc_offset_; 404 bfc_offset = curr_bfc_offset_;
390 } else if (builder_.BfcOffset()) { 405 } else if (builder_.BfcOffset()) {
391 // Fragment doesn't know its offset but we can still calculate its BFC 406 // Fragment doesn't know its offset but we can still calculate its BFC
392 // position because the parent fragment's BFC is known. 407 // position because the parent fragment's BFC is known.
393 // Example: 408 // Example:
394 // BFC Offset is known here because of the padding. 409 // BFC Offset is known here because of the padding.
395 // <div style="padding: 1px"> 410 // <div style="padding: 1px">
396 // <div id="empty-div" style="margins: 1px"></div> 411 // <div id="empty-div" style="margins: 1px"></div>
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 NGLayoutInputNode* child) { 499 NGLayoutInputNode* child) {
485 DCHECK(child); 500 DCHECK(child);
486 501
487 const ComputedStyle& child_style = child->Style(); 502 const ComputedStyle& child_style = child->Style();
488 bool is_new_bfc = IsNewFormattingContextForBlockLevelChild(Style(), *child); 503 bool is_new_bfc = IsNewFormattingContextForBlockLevelChild(Style(), *child);
489 space_builder_.SetIsNewFormattingContext(is_new_bfc) 504 space_builder_.SetIsNewFormattingContext(is_new_bfc)
490 .SetBfcOffset(curr_bfc_offset_); 505 .SetBfcOffset(curr_bfc_offset_);
491 506
492 if (child->IsInline()) { 507 if (child->IsInline()) {
493 // TODO(kojii): Setup space_builder_ appropriately for inline child. 508 // TODO(kojii): Setup space_builder_ appropriately for inline child.
494 space_builder_.SetBfcOffset(curr_bfc_offset_); 509 space_builder_.SetBfcOffset(curr_bfc_offset_)
510 .SetClearanceOffset(ConstraintSpace().ClearanceOffset());
495 return space_builder_.ToConstraintSpace( 511 return space_builder_.ToConstraintSpace(
496 FromPlatformWritingMode(Style().GetWritingMode())); 512 FromPlatformWritingMode(Style().GetWritingMode()));
497 } 513 }
498 514
499 space_builder_ 515 space_builder_
500 .SetClearanceOffset( 516 .SetClearanceOffset(
501 GetClearanceOffset(constraint_space_->Exclusions(), child_style)) 517 GetClearanceOffset(constraint_space_->Exclusions(), child_style))
502 .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style)) 518 .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style))
503 .SetTextDirection(child_style.Direction()); 519 .SetTextDirection(child_style.Direction());
504 520
(...skipping 13 matching lines...) Expand all
518 DCHECK(builder_.BfcOffset()); 534 DCHECK(builder_.BfcOffset());
519 space_available -= curr_bfc_offset_.block_offset; 535 space_available -= curr_bfc_offset_.block_offset;
520 } 536 }
521 } 537 }
522 space_builder_.SetFragmentainerSpaceAvailable(space_available); 538 space_builder_.SetFragmentainerSpaceAvailable(space_available);
523 539
524 return space_builder_.ToConstraintSpace( 540 return space_builder_.ToConstraintSpace(
525 FromPlatformWritingMode(child_style.GetWritingMode())); 541 FromPlatformWritingMode(child_style.GetWritingMode()));
526 } 542 }
527 } // namespace blink 543 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698