| 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_line_builder.h" | 5 #include "core/layout/ng/ng_line_builder.h" |
| 6 | 6 |
| 7 #include "core/layout/BidiRun.h" | 7 #include "core/layout/BidiRun.h" |
| 8 #include "core/layout/LayoutBlockFlow.h" | 8 #include "core/layout/LayoutBlockFlow.h" |
| 9 #include "core/layout/line/LineInfo.h" | 9 #include "core/layout/line/LineInfo.h" |
| 10 #include "core/layout/line/RootInlineBox.h" | 10 #include "core/layout/line/RootInlineBox.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, | 22 NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, |
| 23 NGConstraintSpace* constraint_space, | 23 NGConstraintSpace* constraint_space, |
| 24 NGFragmentBuilder* containing_block_builder) | 24 NGFragmentBuilder* containing_block_builder) |
| 25 : inline_box_(inline_box), | 25 : inline_box_(inline_box), |
| 26 constraint_space_(constraint_space), | 26 constraint_space_(constraint_space), |
| 27 containing_block_builder_(containing_block_builder), | 27 containing_block_builder_(containing_block_builder), |
| 28 baseline_type_(constraint_space->WritingMode() == | 28 baseline_type_(constraint_space->WritingMode() == |
| 29 NGWritingMode::kHorizontalTopBottom | 29 NGWritingMode::kHorizontalTopBottom |
| 30 ? FontBaseline::AlphabeticBaseline | 30 ? FontBaseline::AlphabeticBaseline |
| 31 : FontBaseline::IdeographicBaseline) | 31 : FontBaseline::IdeographicBaseline), |
| 32 container_builder_(NGPhysicalFragment::kFragmentBox, inline_box_), |
| 33 container_layout_result_(nullptr) |
| 32 #if DCHECK_IS_ON() | 34 #if DCHECK_IS_ON() |
| 33 , | 35 , |
| 34 is_bidi_reordered_(false) | 36 is_bidi_reordered_(false) |
| 35 #endif | 37 #endif |
| 36 { | 38 { |
| 37 } | 39 } |
| 38 | 40 |
| 39 bool NGLineBuilder::CanFitOnLine() const { | 41 bool NGLineBuilder::CanFitOnLine() const { |
| 40 LayoutUnit available_size = current_opportunity_.InlineSize(); | 42 LayoutUnit available_size = current_opportunity_.InlineSize(); |
| 41 if (available_size == NGSizeIndefinite) | 43 if (available_size == NGSizeIndefinite) |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 unsigned logical_index = indices_in_visual_order[visual_index]; | 201 unsigned logical_index = indices_in_visual_order[visual_index]; |
| 200 line_item_chunks_in_visual_order[visual_index] = | 202 line_item_chunks_in_visual_order[visual_index] = |
| 201 (*line_item_chunks)[logical_index]; | 203 (*line_item_chunks)[logical_index]; |
| 202 } | 204 } |
| 203 line_item_chunks->swap(line_item_chunks_in_visual_order); | 205 line_item_chunks->swap(line_item_chunks_in_visual_order); |
| 204 } | 206 } |
| 205 | 207 |
| 206 void NGLineBuilder::PlaceItems( | 208 void NGLineBuilder::PlaceItems( |
| 207 const Vector<LineItemChunk, 32>& line_item_chunks) { | 209 const Vector<LineItemChunk, 32>& line_item_chunks) { |
| 208 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 210 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
| 209 const unsigned fragment_start_index = fragments_.size(); | 211 const unsigned fragment_start_index = container_builder_.Children().size(); |
| 210 | 212 |
| 211 NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText, | 213 NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText, |
| 212 inline_box_); | 214 inline_box_); |
| 213 text_builder.SetWritingMode(ConstraintSpace().WritingMode()); | 215 text_builder.SetWritingMode(ConstraintSpace().WritingMode()); |
| 214 line_box_data_list_.grow(line_box_data_list_.size() + 1); | 216 line_box_data_list_.grow(line_box_data_list_.size() + 1); |
| 215 LineBoxData& line_box_data = line_box_data_list_.back(); | 217 LineBoxData& line_box_data = line_box_data_list_.back(); |
| 216 | 218 |
| 217 // Accumulate a "strut"; a zero-width inline box with the element's font and | 219 // Accumulate a "strut"; a zero-width inline box with the element's font and |
| 218 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut | 220 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut |
| 219 const ComputedStyle* block_style = inline_box_->BlockStyle(); | 221 const ComputedStyle* block_style = inline_box_->BlockStyle(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 // The direction of a fragment is the CSS direction to resolve logical | 275 // The direction of a fragment is the CSS direction to resolve logical |
| 274 // properties, not the resolved bidi direction. | 276 // properties, not the resolved bidi direction. |
| 275 text_builder.SetDirection(style->direction()) | 277 text_builder.SetDirection(style->direction()) |
| 276 .SetInlineSize(line_item_chunk.inline_size) | 278 .SetInlineSize(line_item_chunk.inline_size) |
| 277 .SetInlineOverflow(line_item_chunk.inline_size) | 279 .SetInlineOverflow(line_item_chunk.inline_size) |
| 278 .SetBlockSize(height) | 280 .SetBlockSize(height) |
| 279 .SetBlockOverflow(height); | 281 .SetBlockOverflow(height); |
| 280 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( | 282 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( |
| 281 line_item_chunk.index, line_item_chunk.start_offset, | 283 line_item_chunk.index, line_item_chunk.start_offset, |
| 282 line_item_chunk.end_offset); | 284 line_item_chunk.end_offset); |
| 283 fragments_.push_back(std::move(text_fragment)); | |
| 284 | 285 |
| 285 NGLogicalOffset logical_offset( | 286 NGLogicalOffset logical_offset( |
| 286 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - | 287 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - |
| 287 ConstraintSpace().BfcOffset().inline_offset, | 288 ConstraintSpace().BfcOffset().inline_offset, |
| 288 top); | 289 top); |
| 289 offsets_.push_back(logical_offset); | 290 container_builder_.AddChild(std::move(text_fragment), logical_offset); |
| 290 line_box_data.inline_size += line_item_chunk.inline_size; | 291 line_box_data.inline_size += line_item_chunk.inline_size; |
| 291 } | 292 } |
| 292 DCHECK_EQ(fragments_.size(), offsets_.size()); | |
| 293 | 293 |
| 294 if (fragment_start_index == fragments_.size()) { | 294 if (fragment_start_index == container_builder_.Children().size()) { |
| 295 // The line was empty. Remove the LineBoxData. | 295 // The line was empty. Remove the LineBoxData. |
| 296 line_box_data_list_.shrink(line_box_data_list_.size() - 1); | 296 line_box_data_list_.shrink(line_box_data_list_.size() - 1); |
| 297 return; | 297 return; |
| 298 } | 298 } |
| 299 | 299 |
| 300 // If the estimated baseline position was not the actual position, move all | 300 // If the estimated baseline position was not the actual position, move all |
| 301 // fragments in the block direction. | 301 // fragments in the block direction. |
| 302 if (block_metrics.ascent_and_leading != | 302 if (block_metrics.ascent_and_leading != |
| 303 line_box_data.max_ascent_and_leading) { | 303 line_box_data.max_ascent_and_leading) { |
| 304 LayoutUnit adjust_top(line_box_data.max_ascent_and_leading - | 304 LayoutUnit adjust_top(line_box_data.max_ascent_and_leading - |
| 305 block_metrics.ascent_and_leading); | 305 block_metrics.ascent_and_leading); |
| 306 for (unsigned i = fragment_start_index; i < offsets_.size(); i++) | 306 auto& offsets = container_builder_.MutableOffsets(); |
| 307 offsets_[i].block_offset += adjust_top; | 307 for (unsigned i = fragment_start_index; i < offsets.size(); i++) |
| 308 offsets[i].block_offset += adjust_top; |
| 308 } | 309 } |
| 309 | 310 |
| 310 line_box_data.fragment_end = fragments_.size(); | 311 line_box_data.fragment_end = container_builder_.Children().size(); |
| 311 line_box_data.top_with_leading = content_size_; | 312 line_box_data.top_with_leading = content_size_; |
| 312 max_inline_size_ = std::max(max_inline_size_, line_box_data.inline_size); | 313 max_inline_size_ = std::max(max_inline_size_, line_box_data.inline_size); |
| 313 content_size_ += LayoutUnit(line_box_data.max_ascent_and_leading + | 314 content_size_ += LayoutUnit(line_box_data.max_ascent_and_leading + |
| 314 line_box_data.max_descent_and_leading); | 315 line_box_data.max_descent_and_leading); |
| 315 } | 316 } |
| 316 | 317 |
| 317 NGLineBuilder::InlineItemMetrics::InlineItemMetrics( | 318 NGLineBuilder::InlineItemMetrics::InlineItemMetrics( |
| 318 const ComputedStyle& style, | 319 const ComputedStyle& style, |
| 319 FontBaseline baseline_type) { | 320 FontBaseline baseline_type) { |
| 320 const SimpleFontData* font_data = style.font().primaryFont(); | 321 const SimpleFontData* font_data = style.font().primaryFont(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); | 372 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); |
| 372 iter_offset.block_offset += content_size_; | 373 iter_offset.block_offset += content_size_; |
| 373 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset); | 374 auto* iter = constraint_space_->LayoutOpportunityIterator(iter_offset); |
| 374 NGLayoutOpportunity opportunity = iter->Next(); | 375 NGLayoutOpportunity opportunity = iter->Next(); |
| 375 if (!opportunity.IsEmpty()) | 376 if (!opportunity.IsEmpty()) |
| 376 current_opportunity_ = opportunity; | 377 current_opportunity_ = opportunity; |
| 377 } | 378 } |
| 378 | 379 |
| 379 RefPtr<NGLayoutResult> NGLineBuilder::CreateFragments() { | 380 RefPtr<NGLayoutResult> NGLineBuilder::CreateFragments() { |
| 380 DCHECK(!HasItems()) << "Must call CreateLine()"; | 381 DCHECK(!HasItems()) << "Must call CreateLine()"; |
| 381 DCHECK_EQ(fragments_.size(), offsets_.size()); | |
| 382 | |
| 383 NGFragmentBuilder container_builder(NGPhysicalFragment::kFragmentBox, | |
| 384 inline_box_); | |
| 385 | |
| 386 for (unsigned i = 0; i < fragments_.size(); i++) { | |
| 387 // TODO(layout-dev): This should really be a std::move but | |
| 388 // CopyFragmentDataToLayoutBlockFlow also uses the fragments. | |
| 389 container_builder.AddChild(fragments_[i].get(), offsets_[i]); | |
| 390 } | |
| 391 | 382 |
| 392 // TODO(kojii): Check if the line box width should be content or available. | 383 // TODO(kojii): Check if the line box width should be content or available. |
| 393 // TODO(kojii): Need to take constraint_space into account. | 384 // TODO(kojii): Need to take constraint_space into account. |
| 394 container_builder.SetInlineSize(max_inline_size_) | 385 container_builder_.SetInlineSize(max_inline_size_) |
| 395 .SetInlineOverflow(max_inline_size_) | 386 .SetInlineOverflow(max_inline_size_) |
| 396 .SetBlockSize(content_size_) | 387 .SetBlockSize(content_size_) |
| 397 .SetBlockOverflow(content_size_); | 388 .SetBlockOverflow(content_size_); |
| 398 | 389 |
| 399 return container_builder.ToBoxFragment(); | 390 container_layout_result_ = container_builder_.ToBoxFragment(); |
| 391 return container_layout_result_; |
| 400 } | 392 } |
| 401 | 393 |
| 402 void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() { | 394 void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() { |
| 403 LayoutBlockFlow* block = inline_box_->GetLayoutBlockFlow(); | 395 LayoutBlockFlow* block = inline_box_->GetLayoutBlockFlow(); |
| 404 block->deleteLineBoxTree(); | 396 block->deleteLineBoxTree(); |
| 405 | 397 |
| 406 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 398 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
| 407 Vector<unsigned, 32> text_offsets(items.size()); | 399 Vector<unsigned, 32> text_offsets(items.size()); |
| 408 inline_box_->GetLayoutTextOffsets(&text_offsets); | 400 inline_box_->GetLayoutTextOffsets(&text_offsets); |
| 409 | 401 |
| 410 Vector<NGPhysicalFragment*, 32> fragments_for_bidi_runs; | 402 Vector<const NGPhysicalFragment*, 32> fragments_for_bidi_runs; |
| 411 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); | 403 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); |
| 412 BidiRunList<BidiRun> bidi_runs; | 404 BidiRunList<BidiRun> bidi_runs; |
| 413 LineInfo line_info; | 405 LineInfo line_info; |
| 414 unsigned fragment_index = 0; | 406 unsigned fragment_index = 0; |
| 407 NGPhysicalBoxFragment* box_fragment = toNGPhysicalBoxFragment( |
| 408 container_layout_result_->PhysicalFragment().get()); |
| 415 for (const auto& line_box_data : line_box_data_list_) { | 409 for (const auto& line_box_data : line_box_data_list_) { |
| 416 // Create a BidiRunList for this line. | 410 // Create a BidiRunList for this line. |
| 417 for (; fragment_index < line_box_data.fragment_end; fragment_index++) { | 411 for (; fragment_index < line_box_data.fragment_end; fragment_index++) { |
| 418 NGPhysicalTextFragment* text_fragment = | 412 const NGPhysicalFragment* fragment = |
| 419 toNGPhysicalTextFragment(fragments_[fragment_index].get()); | 413 box_fragment->Children()[fragment_index].get(); |
| 414 if (!fragment->IsText()) |
| 415 continue; |
| 416 const auto* text_fragment = toNGPhysicalTextFragment(fragment); |
| 420 const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()]; | 417 const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()]; |
| 421 LayoutObject* layout_object = item.GetLayoutObject(); | 418 LayoutObject* layout_object = item.GetLayoutObject(); |
| 422 if (!layout_object) // Skip bidi controls. | 419 if (!layout_object) // Skip bidi controls. |
| 423 continue; | 420 continue; |
| 424 BidiRun* run; | 421 BidiRun* run; |
| 425 if (layout_object->isText()) { | 422 if (layout_object->isText()) { |
| 426 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; | 423 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; |
| 427 run = new BidiRun(text_fragment->StartOffset() - text_offset, | 424 run = new BidiRun(text_fragment->StartOffset() - text_offset, |
| 428 text_fragment->EndOffset() - text_offset, | 425 text_fragment->EndOffset() - text_offset, |
| 429 item.BidiLevel(), LineLayoutItem(layout_object)); | 426 item.BidiLevel(), LineLayoutItem(layout_object)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 baseline_position - LayoutUnit(line_box_data.max_ascent), | 468 baseline_position - LayoutUnit(line_box_data.max_ascent), |
| 472 baseline_position + LayoutUnit(line_box_data.max_descent), | 469 baseline_position + LayoutUnit(line_box_data.max_descent), |
| 473 line_box_data.top_with_leading, | 470 line_box_data.top_with_leading, |
| 474 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); | 471 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); |
| 475 | 472 |
| 476 bidi_runs.deleteRuns(); | 473 bidi_runs.deleteRuns(); |
| 477 fragments_for_bidi_runs.clear(); | 474 fragments_for_bidi_runs.clear(); |
| 478 } | 475 } |
| 479 } | 476 } |
| 480 } // namespace blink | 477 } // namespace blink |
| OLD | NEW |