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/layout/ng/ng_block_layout_algorithm.h" | 5 #include "core/layout/ng/ng_block_layout_algorithm.h" |
6 | 6 |
7 #include "core/layout/ng/ng_break_token.h" | 7 #include "core/layout/ng/ng_break_token.h" |
8 #include "core/layout/ng/ng_constraint_space.h" | 8 #include "core/layout/ng/ng_constraint_space.h" |
9 #include "core/layout/ng/ng_constraint_space_builder.h" | 9 #include "core/layout/ng/ng_constraint_space_builder.h" |
10 #include "core/layout/ng/ng_fragment_base.h" | 10 #include "core/layout/ng/ng_fragment_base.h" |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 } | 174 } |
175 | 175 |
176 } // namespace | 176 } // namespace |
177 | 177 |
178 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( | 178 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm( |
179 PassRefPtr<const ComputedStyle> style, | 179 PassRefPtr<const ComputedStyle> style, |
180 NGBlockNode* first_child, | 180 NGBlockNode* first_child, |
181 NGConstraintSpace* constraint_space, | 181 NGConstraintSpace* constraint_space, |
182 NGBreakToken* break_token) | 182 NGBreakToken* break_token) |
183 : NGLayoutAlgorithm(kBlockLayoutAlgorithm), | 183 : NGLayoutAlgorithm(kBlockLayoutAlgorithm), |
184 state_(kStateInit), | 184 layout_state_(kStateInit), |
| 185 compute_minmax_state_(kStateInit), |
185 style_(style), | 186 style_(style), |
186 first_child_(first_child), | 187 first_child_(first_child), |
187 constraint_space_(constraint_space), | 188 constraint_space_(constraint_space), |
188 break_token_(break_token), | 189 break_token_(break_token), |
189 is_fragment_margin_strut_block_start_updated_(false) { | 190 is_fragment_margin_strut_block_start_updated_(false) { |
190 DCHECK(style_); | 191 DCHECK(style_); |
191 } | 192 } |
192 | 193 |
| 194 NGLayoutAlgorithm::MinAndMaxState |
| 195 NGBlockLayoutAlgorithm::ComputeMinAndMaxContentSizes( |
| 196 MinAndMaxContentSizes* sizes) { |
| 197 switch (compute_minmax_state_) { |
| 198 case kStateInit: |
| 199 pending_minmax_sizes_.min_content = pending_minmax_sizes_.max_content = |
| 200 LayoutUnit(); |
| 201 // Size-contained elements don't consider their contents for intrinsic |
| 202 // sizing. |
| 203 if (style_->containsSize()) |
| 204 return kSuccess; |
| 205 current_minmax_child_ = first_child_; |
| 206 compute_minmax_state_ = kStateChildLayout; |
| 207 case kStateChildLayout: |
| 208 // TODO: handle floats & orthogonal children |
| 209 if (current_minmax_child_) { |
| 210 Optional<MinAndMaxContentSizes> child_minmax; |
| 211 if (NeedMinAndMaxContentSizesForContentContribution( |
| 212 *current_minmax_child_->Style())) { |
| 213 child_minmax = MinAndMaxContentSizes(); |
| 214 if (!current_minmax_child_->ComputeMinAndMaxContentSizes( |
| 215 &*child_minmax)) |
| 216 return kPending; |
| 217 } |
| 218 MinAndMaxContentSizes child_sizes = ComputeMinAndMaxContentContribution( |
| 219 *current_minmax_child_->Style(), child_minmax); |
| 220 pending_minmax_sizes_.min_content = std::max( |
| 221 pending_minmax_sizes_.min_content, child_sizes.min_content); |
| 222 pending_minmax_sizes_.max_content = std::max( |
| 223 pending_minmax_sizes_.max_content, child_sizes.max_content); |
| 224 |
| 225 current_minmax_child_ = current_minmax_child_->NextSibling(); |
| 226 if (current_minmax_child_) |
| 227 return kPending; |
| 228 } |
| 229 |
| 230 *sizes = pending_minmax_sizes_; |
| 231 sizes->max_content = std::max(sizes->min_content, sizes->max_content); |
| 232 compute_minmax_state_ = kStateInit; |
| 233 return kSuccess; |
| 234 default: |
| 235 NOTREACHED(); |
| 236 return kSuccess; |
| 237 }; |
| 238 } |
| 239 |
193 NGLayoutStatus NGBlockLayoutAlgorithm::Layout( | 240 NGLayoutStatus NGBlockLayoutAlgorithm::Layout( |
194 NGPhysicalFragmentBase* child_fragment, | 241 NGPhysicalFragmentBase* child_fragment, |
195 NGPhysicalFragmentBase** fragment_out, | 242 NGPhysicalFragmentBase** fragment_out, |
196 NGLayoutAlgorithm** algorithm_out) { | 243 NGLayoutAlgorithm** algorithm_out) { |
197 switch (state_) { | 244 switch (layout_state_) { |
198 case kStateInit: { | 245 case kStateInit: { |
| 246 WTF::Optional<MinAndMaxContentSizes> sizes; |
| 247 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) { |
| 248 sizes = MinAndMaxContentSizes(); |
| 249 if (ComputeMinAndMaxContentSizes(&*sizes) == kPending) |
| 250 return kNotFinished; |
| 251 } |
| 252 |
199 border_and_padding_ = | 253 border_and_padding_ = |
200 ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style()); | 254 ComputeBorders(Style()) + ComputePadding(ConstraintSpace(), Style()); |
201 | 255 |
202 WTF::Optional<MinAndMaxContentSizes> sizes; | |
203 if (NeedMinAndMaxContentSizes(ConstraintSpace(), Style())) { | |
204 // TODOO(layout-ng): Implement | |
205 sizes = MinAndMaxContentSizes(); | |
206 } | |
207 LayoutUnit inline_size = | 256 LayoutUnit inline_size = |
208 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); | 257 ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes); |
209 LayoutUnit adjusted_inline_size = | 258 LayoutUnit adjusted_inline_size = |
210 inline_size - border_and_padding_.InlineSum(); | 259 inline_size - border_and_padding_.InlineSum(); |
211 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of | 260 // TODO(layout-ng): For quirks mode, should we pass blockSize instead of |
212 // -1? | 261 // -1? |
213 LayoutUnit block_size = ComputeBlockSizeForFragment( | 262 LayoutUnit block_size = ComputeBlockSizeForFragment( |
214 ConstraintSpace(), Style(), NGSizeIndefinite); | 263 ConstraintSpace(), Style(), NGSizeIndefinite); |
215 LayoutUnit adjusted_block_size(block_size); | 264 LayoutUnit adjusted_block_size(block_size); |
216 // Our calculated block-axis size may be indefinite at this point. | 265 // Our calculated block-axis size may be indefinite at this point. |
(...skipping 14 matching lines...) Expand all Loading... |
231 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); | 280 NGLogicalSize(adjusted_inline_size, adjusted_block_size)); |
232 | 281 |
233 content_size_ = border_and_padding_.block_start; | 282 content_size_ = border_and_padding_.block_start; |
234 | 283 |
235 builder_ = new NGFragmentBuilder(NGPhysicalFragmentBase::kFragmentBox); | 284 builder_ = new NGFragmentBuilder(NGPhysicalFragmentBase::kFragmentBox); |
236 builder_->SetDirection(constraint_space_->Direction()); | 285 builder_->SetDirection(constraint_space_->Direction()); |
237 builder_->SetWritingMode(constraint_space_->WritingMode()); | 286 builder_->SetWritingMode(constraint_space_->WritingMode()); |
238 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); | 287 builder_->SetInlineSize(inline_size).SetBlockSize(block_size); |
239 | 288 |
240 current_child_ = first_child_; | 289 current_child_ = first_child_; |
241 state_ = kStatePrepareForChildLayout; | 290 layout_state_ = kStatePrepareForChildLayout; |
242 return kNotFinished; | 291 return kNotFinished; |
243 } | 292 } |
244 case kStatePrepareForChildLayout: { | 293 case kStatePrepareForChildLayout: { |
245 if (current_child_) { | 294 if (current_child_) { |
246 // TODO(atotic): uncomment this code when implementing oof layout. | 295 // TODO(atotic): uncomment this code when implementing oof layout. |
247 // This code cannot be turned on because it prevents layout of | 296 // This code cannot be turned on because it prevents layout of |
248 // oof children, and non-layedout objects trigger a DCHECK. | 297 // oof children, and non-layedout objects trigger a DCHECK. |
249 // EPosition position = current_child_->Style()->position(); | 298 // EPosition position = current_child_->Style()->position(); |
250 // if ((position == AbsolutePosition || position == FixedPosition)) { | 299 // if ((position == AbsolutePosition || position == FixedPosition)) { |
251 // builder_->AddOutOfFlowCandidateChild(current_child_, | 300 // builder_->AddOutOfFlowCandidateChild(current_child_, |
252 // GetChildSpaceOffset()); | 301 // GetChildSpaceOffset()); |
253 // } | 302 // } |
254 // else | 303 // else |
255 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); | 304 space_for_current_child_ = CreateConstraintSpaceForCurrentChild(); |
256 *algorithm_out = NGLayoutInputNode::AlgorithmForInputNode( | 305 *algorithm_out = NGLayoutInputNode::AlgorithmForInputNode( |
257 current_child_, space_for_current_child_); | 306 current_child_, space_for_current_child_); |
258 state_ = kStateChildLayout; | 307 layout_state_ = kStateChildLayout; |
259 return kChildAlgorithmRequired; | 308 return kChildAlgorithmRequired; |
260 } | 309 } |
261 | 310 |
262 state_ = kStateFinalize; | 311 layout_state_ = kStateFinalize; |
263 return kNotFinished; | 312 return kNotFinished; |
264 } | 313 } |
265 case kStateChildLayout: { | 314 case kStateChildLayout: { |
266 DCHECK(current_child_); | 315 DCHECK(current_child_); |
267 DCHECK(child_fragment); | 316 DCHECK(child_fragment); |
268 | 317 |
269 // TODO(layout_ng): Seems like a giant hack to call this here. | 318 // TODO(layout_ng): Seems like a giant hack to call this here. |
270 current_child_->UpdateLayoutBox(toNGPhysicalFragment(child_fragment), | 319 current_child_->UpdateLayoutBox(toNGPhysicalFragment(child_fragment), |
271 space_for_current_child_); | 320 space_for_current_child_); |
272 | 321 |
273 FinishCurrentChildLayout(new NGFragment( | 322 FinishCurrentChildLayout(new NGFragment( |
274 ConstraintSpace().WritingMode(), ConstraintSpace().Direction(), | 323 ConstraintSpace().WritingMode(), ConstraintSpace().Direction(), |
275 toNGPhysicalFragment(child_fragment))); | 324 toNGPhysicalFragment(child_fragment))); |
276 current_child_ = current_child_->NextSibling(); | 325 current_child_ = current_child_->NextSibling(); |
277 state_ = kStatePrepareForChildLayout; | 326 layout_state_ = kStatePrepareForChildLayout; |
278 return kNotFinished; | 327 return kNotFinished; |
279 } | 328 } |
280 case kStateFinalize: { | 329 case kStateFinalize: { |
281 content_size_ += border_and_padding_.block_end; | 330 content_size_ += border_and_padding_.block_end; |
282 | 331 |
283 // Recompute the block-axis size now that we know our content size. | 332 // Recompute the block-axis size now that we know our content size. |
284 LayoutUnit block_size = ComputeBlockSizeForFragment( | 333 LayoutUnit block_size = ComputeBlockSizeForFragment( |
285 ConstraintSpace(), Style(), content_size_); | 334 ConstraintSpace(), Style(), content_size_); |
286 | 335 |
287 builder_->SetBlockSize(block_size) | 336 builder_->SetBlockSize(block_size) |
288 .SetInlineOverflow(max_inline_size_) | 337 .SetInlineOverflow(max_inline_size_) |
289 .SetBlockOverflow(content_size_); | 338 .SetBlockOverflow(content_size_); |
290 *fragment_out = builder_->ToFragment(); | 339 *fragment_out = builder_->ToFragment(); |
291 state_ = kStateInit; | 340 layout_state_ = kStateInit; |
292 return kNewFragment; | 341 return kNewFragment; |
293 } | 342 } |
294 }; | 343 }; |
295 NOTREACHED(); | 344 NOTREACHED(); |
296 *fragment_out = nullptr; | 345 *fragment_out = nullptr; |
297 return kNewFragment; | 346 return kNewFragment; |
298 } | 347 } |
299 | 348 |
300 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( | 349 void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( |
301 NGFragmentBase* fragment) { | 350 NGFragmentBase* fragment) { |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 } | 488 } |
440 builder_->SetMarginStrutBlockEnd(from); | 489 builder_->SetMarginStrutBlockEnd(from); |
441 } | 490 } |
442 | 491 |
443 NGConstraintSpace* | 492 NGConstraintSpace* |
444 NGBlockLayoutAlgorithm::CreateConstraintSpaceForCurrentChild() const { | 493 NGBlockLayoutAlgorithm::CreateConstraintSpaceForCurrentChild() const { |
445 // TODO(layout-ng): Orthogonal children should also shrink to fit (in *their* | 494 // TODO(layout-ng): Orthogonal children should also shrink to fit (in *their* |
446 // inline axis) | 495 // inline axis) |
447 // We have to keep this commented out for now until we correctly compute | 496 // We have to keep this commented out for now until we correctly compute |
448 // min/max content sizes in Layout(). | 497 // min/max content sizes in Layout(). |
449 // bool shrink_to_fit = CurrentChildStyle().display() == EDisplay::InlineBlock | 498 bool shrink_to_fit = CurrentChildStyle().display() == EDisplay::InlineBlock || |
450 // || CurrentChildStyle().isFloating(); | 499 CurrentChildStyle().isFloating(); |
451 bool shrink_to_fit = false; | |
452 DCHECK(current_child_); | 500 DCHECK(current_child_); |
453 space_builder_ | 501 space_builder_ |
454 ->SetIsNewFormattingContext( | 502 ->SetIsNewFormattingContext( |
455 IsNewFormattingContextForInFlowBlockLevelChild(ConstraintSpace(), | 503 IsNewFormattingContextForInFlowBlockLevelChild(ConstraintSpace(), |
456 CurrentChildStyle())) | 504 CurrentChildStyle())) |
457 .SetIsShrinkToFit(shrink_to_fit) | 505 .SetIsShrinkToFit(shrink_to_fit) |
458 .SetWritingMode( | 506 .SetWritingMode( |
459 FromPlatformWritingMode(CurrentChildStyle().getWritingMode())) | 507 FromPlatformWritingMode(CurrentChildStyle().getWritingMode())) |
460 .SetTextDirection(CurrentChildStyle().direction()); | 508 .SetTextDirection(CurrentChildStyle().direction()); |
461 NGConstraintSpace* child_space = space_builder_->ToConstraintSpace(); | 509 NGConstraintSpace* child_space = space_builder_->ToConstraintSpace(); |
462 | 510 |
463 // TODO(layout-ng): Set offset through the space builder. | 511 // TODO(layout-ng): Set offset through the space builder. |
464 child_space->SetOffset(GetChildSpaceOffset()); | 512 child_space->SetOffset(GetChildSpaceOffset()); |
465 return child_space; | 513 return child_space; |
466 } | 514 } |
467 | 515 |
468 DEFINE_TRACE(NGBlockLayoutAlgorithm) { | 516 DEFINE_TRACE(NGBlockLayoutAlgorithm) { |
469 NGLayoutAlgorithm::trace(visitor); | 517 NGLayoutAlgorithm::trace(visitor); |
470 visitor->trace(first_child_); | 518 visitor->trace(first_child_); |
471 visitor->trace(constraint_space_); | 519 visitor->trace(constraint_space_); |
472 visitor->trace(break_token_); | 520 visitor->trace(break_token_); |
473 visitor->trace(builder_); | 521 visitor->trace(builder_); |
474 visitor->trace(space_builder_); | 522 visitor->trace(space_builder_); |
475 visitor->trace(space_for_current_child_); | 523 visitor->trace(space_for_current_child_); |
476 visitor->trace(current_child_); | 524 visitor->trace(current_child_); |
| 525 visitor->trace(current_minmax_child_); |
477 } | 526 } |
478 | 527 |
479 } // namespace blink | 528 } // namespace blink |
OLD | NEW |