| 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_inline_node.h" | 5 #include "core/layout/ng/ng_inline_node.h" |
| 6 | 6 |
| 7 #include "core/layout/LayoutBlockFlow.h" | 7 #include "core/layout/LayoutBlockFlow.h" |
| 8 #include "core/layout/LayoutObject.h" | 8 #include "core/layout/LayoutObject.h" |
| 9 #include "core/layout/LayoutText.h" | 9 #include "core/layout/LayoutText.h" |
| 10 #include "core/layout/ng/ng_bidi_paragraph.h" | 10 #include "core/layout/ng/ng_bidi_paragraph.h" |
| 11 #include "core/layout/ng/ng_box_fragment.h" | 11 #include "core/layout/ng/ng_box_fragment.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_fragment_builder.h" | 13 #include "core/layout/ng/ng_fragment_builder.h" |
| 14 #include "core/layout/ng/ng_inline_break_token.h" |
| 15 #include "core/layout/ng/ng_inline_layout_algorithm.h" |
| 14 #include "core/layout/ng/ng_layout_inline_items_builder.h" | 16 #include "core/layout/ng/ng_layout_inline_items_builder.h" |
| 15 #include "core/layout/ng/ng_line_builder.h" | |
| 16 #include "core/layout/ng/ng_physical_box_fragment.h" | 17 #include "core/layout/ng/ng_physical_box_fragment.h" |
| 17 #include "core/layout/ng/ng_physical_text_fragment.h" | 18 #include "core/layout/ng/ng_physical_text_fragment.h" |
| 18 #include "core/layout/ng/ng_text_fragment.h" | 19 #include "core/layout/ng/ng_text_fragment.h" |
| 19 #include "core/layout/ng/ng_text_layout_algorithm.h" | |
| 20 #include "core/style/ComputedStyle.h" | 20 #include "core/style/ComputedStyle.h" |
| 21 #include "platform/fonts/CharacterRange.h" | 21 #include "platform/fonts/CharacterRange.h" |
| 22 #include "platform/fonts/shaping/CachingWordShapeIterator.h" | 22 #include "platform/fonts/shaping/CachingWordShapeIterator.h" |
| 23 #include "platform/fonts/shaping/CachingWordShaper.h" | 23 #include "platform/fonts/shaping/CachingWordShaper.h" |
| 24 #include "platform/fonts/shaping/HarfBuzzShaper.h" | 24 #include "platform/fonts/shaping/HarfBuzzShaper.h" |
| 25 #include "platform/fonts/shaping/ShapeResultBuffer.h" | 25 #include "platform/fonts/shaping/ShapeResultBuffer.h" |
| 26 #include "wtf/text/CharacterNames.h" | 26 #include "wtf/text/CharacterNames.h" |
| 27 | 27 |
| 28 namespace blink { | 28 namespace blink { |
| 29 | 29 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 LayoutObject* node = start; | 86 LayoutObject* node = start; |
| 87 while (node) { | 87 while (node) { |
| 88 if (node->isText()) { | 88 if (node->isText()) { |
| 89 builder->SetIsSVGText(node->isSVGInlineText()); | 89 builder->SetIsSVGText(node->isSVGInlineText()); |
| 90 builder->Append(toLayoutText(node)->text(), node->style(), node); | 90 builder->Append(toLayoutText(node)->text(), node->style(), node); |
| 91 node->clearNeedsLayout(); | 91 node->clearNeedsLayout(); |
| 92 | 92 |
| 93 } else if (node->isFloating()) { | 93 } else if (node->isFloating()) { |
| 94 // Add floats and positioned objects in the same way as atomic inlines. | 94 // Add floats and positioned objects in the same way as atomic inlines. |
| 95 // Because these objects need positions, they will be handled in | 95 // Because these objects need positions, they will be handled in |
| 96 // NGLineBuilder. | 96 // NGInlineLayoutAlgorithm. |
| 97 builder->Append(NGLayoutInlineItem::kFloating, objectReplacementCharacter, | 97 builder->Append(NGLayoutInlineItem::kFloating, objectReplacementCharacter, |
| 98 nullptr, node); | 98 nullptr, node); |
| 99 } else if (node->isOutOfFlowPositioned()) { | 99 } else if (node->isOutOfFlowPositioned()) { |
| 100 builder->Append(NGLayoutInlineItem::kOutOfFlowPositioned, | 100 builder->Append(NGLayoutInlineItem::kOutOfFlowPositioned, |
| 101 objectReplacementCharacter, nullptr, node); | 101 objectReplacementCharacter, nullptr, node); |
| 102 | 102 |
| 103 } else if (!node->isInline()) { | 103 } else if (!node->isInline()) { |
| 104 // A block box found. End inline and transit to block layout. | 104 // A block box found. End inline and transit to block layout. |
| 105 return node; | 105 return node; |
| 106 | 106 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 void NGLayoutInlineItem::SetEndOffset(unsigned end_offset) { | 226 void NGLayoutInlineItem::SetEndOffset(unsigned end_offset) { |
| 227 DCHECK_GE(end_offset, start_offset_); | 227 DCHECK_GE(end_offset, start_offset_); |
| 228 end_offset_ = end_offset; | 228 end_offset_ = end_offset; |
| 229 } | 229 } |
| 230 | 230 |
| 231 LayoutUnit NGLayoutInlineItem::InlineSize() const { | 231 LayoutUnit NGLayoutInlineItem::InlineSize() const { |
| 232 if (Type() == NGLayoutInlineItem::kText) | 232 if (Type() == NGLayoutInlineItem::kText) |
| 233 return LayoutUnit(shape_result_->width()); | 233 return LayoutUnit(shape_result_->width()); |
| 234 | 234 |
| 235 DCHECK(Type() != NGLayoutInlineItem::kAtomicInline) | 235 DCHECK(Type() != NGLayoutInlineItem::kAtomicInline) |
| 236 << "Use NGLineBuilder::InlineSize"; | 236 << "Use NGInlineLayoutAlgorithm::InlineSize"; |
| 237 // Bidi controls and out-of-flow objects do not have in-flow widths. | 237 // Bidi controls and out-of-flow objects do not have in-flow widths. |
| 238 return LayoutUnit(); | 238 return LayoutUnit(); |
| 239 } | 239 } |
| 240 | 240 |
| 241 LayoutUnit NGLayoutInlineItem::InlineSize(unsigned start, unsigned end) const { | 241 LayoutUnit NGLayoutInlineItem::InlineSize(unsigned start, unsigned end) const { |
| 242 DCHECK(start >= StartOffset() && start <= end && end <= EndOffset()); | 242 DCHECK(start >= StartOffset() && start <= end && end <= EndOffset()); |
| 243 | 243 |
| 244 if (start == end) | 244 if (start == end) |
| 245 return LayoutUnit(); | 245 return LayoutUnit(); |
| 246 if (start == start_offset_ && end == end_offset_) | 246 if (start == start_offset_ && end == end_offset_) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 272 for (auto& item : items_) { | 272 for (auto& item : items_) { |
| 273 if (item.Type() != NGLayoutInlineItem::kText) | 273 if (item.Type() != NGLayoutInlineItem::kText) |
| 274 continue; | 274 continue; |
| 275 | 275 |
| 276 item.shape_result_ = shaper.shape(&item.Style()->font(), item.Direction(), | 276 item.shape_result_ = shaper.shape(&item.Style()->font(), item.Direction(), |
| 277 item.StartOffset(), item.EndOffset()); | 277 item.StartOffset(), item.EndOffset()); |
| 278 } | 278 } |
| 279 } | 279 } |
| 280 | 280 |
| 281 RefPtr<NGLayoutResult> NGInlineNode::Layout(NGConstraintSpace* constraint_space, | 281 RefPtr<NGLayoutResult> NGInlineNode::Layout(NGConstraintSpace* constraint_space, |
| 282 NGBreakToken*) { | 282 NGBreakToken* break_token) { |
| 283 // TODO(kojii): Invalidate PrepareLayout() more efficiently. | 283 // TODO(kojii): Invalidate PrepareLayout() more efficiently. |
| 284 InvalidatePrepareLayout(); | 284 InvalidatePrepareLayout(); |
| 285 NGLineBuilder line_builder(this, constraint_space); | 285 PrepareLayout(); |
| 286 Layout(&line_builder); | 286 |
| 287 RefPtr<NGLayoutResult> result = line_builder.CreateFragments(); | 287 NGInlineLayoutAlgorithm algorithm(this, constraint_space, |
| 288 line_builder.CopyFragmentDataToLayoutBlockFlow(); | 288 toNGInlineBreakToken(break_token)); |
| 289 RefPtr<NGLayoutResult> result = algorithm.Layout(); |
| 290 algorithm.CopyFragmentDataToLayoutBlockFlow(result.get()); |
| 289 return result; | 291 return result; |
| 290 } | 292 } |
| 291 | 293 |
| 292 void NGInlineNode::Layout(NGLineBuilder* line_builder) { | 294 MinMaxContentSize NGInlineNode::ComputeMinMaxContentSize() { |
| 293 if (!IsPrepareLayoutFinished()) | 295 if (!IsPrepareLayoutFinished()) |
| 294 PrepareLayout(); | 296 PrepareLayout(); |
| 295 | 297 |
| 296 if (text_content_.isEmpty()) | |
| 297 return; | |
| 298 | |
| 299 NGTextLayoutAlgorithm(this).LayoutInline(line_builder); | |
| 300 } | |
| 301 | |
| 302 MinMaxContentSize NGInlineNode::ComputeMinMaxContentSize() { | |
| 303 // Compute the max of inline sizes of all line boxes with 0 available inline | 298 // Compute the max of inline sizes of all line boxes with 0 available inline |
| 304 // size. This gives the min-content, the width where lines wrap at every break | 299 // size. This gives the min-content, the width where lines wrap at every break |
| 305 // opportunity. | 300 // opportunity. |
| 306 NGWritingMode writing_mode = | 301 NGWritingMode writing_mode = |
| 307 FromPlatformWritingMode(BlockStyle()->getWritingMode()); | 302 FromPlatformWritingMode(BlockStyle()->getWritingMode()); |
| 308 RefPtr<NGConstraintSpace> constraint_space = | 303 RefPtr<NGConstraintSpace> constraint_space = |
| 309 NGConstraintSpaceBuilder(writing_mode) | 304 NGConstraintSpaceBuilder(writing_mode) |
| 310 .SetTextDirection(BlockStyle()->direction()) | 305 .SetTextDirection(BlockStyle()->direction()) |
| 311 .SetAvailableSize({LayoutUnit(), NGSizeIndefinite}) | 306 .SetAvailableSize({LayoutUnit(), NGSizeIndefinite}) |
| 312 .ToConstraintSpace(writing_mode); | 307 .ToConstraintSpace(writing_mode); |
| 313 NGLineBuilder line_builder(this, constraint_space.get()); | 308 NGInlineLayoutAlgorithm algorithm(this, constraint_space.get()); |
| 314 Layout(&line_builder); | 309 return algorithm.ComputeMinMaxContentSizeByLayout(); |
| 315 MinMaxContentSize sizes; | |
| 316 sizes.min_content = line_builder.MaxInlineSize(); | |
| 317 | |
| 318 // max-content is the width without any line wrapping. | |
| 319 // TODO(kojii): Implement hard breaks (<br> etc.) to break. | |
| 320 for (const auto& item : items_) | |
| 321 sizes.max_content += line_builder.InlineSize(item); | |
| 322 | |
| 323 return sizes; | |
| 324 } | 310 } |
| 325 | 311 |
| 326 NGLayoutInputNode* NGInlineNode::NextSibling() { | 312 NGLayoutInputNode* NGInlineNode::NextSibling() { |
| 327 if (!IsPrepareLayoutFinished()) | 313 if (!IsPrepareLayoutFinished()) |
| 328 PrepareLayout(); | 314 PrepareLayout(); |
| 329 return next_sibling_; | 315 return next_sibling_; |
| 330 } | 316 } |
| 331 | 317 |
| 332 LayoutObject* NGInlineNode::GetLayoutObject() { | 318 LayoutObject* NGInlineNode::GetLayoutObject() { |
| 333 return GetLayoutBlockFlow(); | 319 return GetLayoutBlockFlow(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 unsigned start_index, | 364 unsigned start_index, |
| 379 unsigned end_index) | 365 unsigned end_index) |
| 380 : start_item_(&(*items)[start_index]), | 366 : start_item_(&(*items)[start_index]), |
| 381 size_(end_index - start_index), | 367 size_(end_index - start_index), |
| 382 start_index_(start_index) { | 368 start_index_(start_index) { |
| 383 CHECK_LE(start_index, end_index); | 369 CHECK_LE(start_index, end_index); |
| 384 CHECK_LE(end_index, items->size()); | 370 CHECK_LE(end_index, items->size()); |
| 385 } | 371 } |
| 386 | 372 |
| 387 } // namespace blink | 373 } // namespace blink |
| OLD | NEW |