| 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" |
| 11 #include "core/layout/ng/layout_ng_block_flow.h" | 11 #include "core/layout/ng/layout_ng_block_flow.h" |
| 12 #include "core/layout/ng/ng_bidi_paragraph.h" | 12 #include "core/layout/ng/ng_bidi_paragraph.h" |
| 13 #include "core/layout/ng/ng_block_layout_algorithm.h" | 13 #include "core/layout/ng/ng_block_layout_algorithm.h" |
| 14 #include "core/layout/ng/ng_box_fragment.h" | 14 #include "core/layout/ng/ng_box_fragment.h" |
| 15 #include "core/layout/ng/ng_constraint_space.h" | 15 #include "core/layout/ng/ng_constraint_space.h" |
| 16 #include "core/layout/ng/ng_constraint_space_builder.h" | 16 #include "core/layout/ng/ng_constraint_space_builder.h" |
| 17 #include "core/layout/ng/ng_floating_object.h" | 17 #include "core/layout/ng/ng_floating_object.h" |
| 18 #include "core/layout/ng/ng_floats_utils.h" | 18 #include "core/layout/ng/ng_floats_utils.h" |
| 19 #include "core/layout/ng/ng_fragment_builder.h" | 19 #include "core/layout/ng/ng_fragment_builder.h" |
| 20 #include "core/layout/ng/ng_inline_node.h" | 20 #include "core/layout/ng/ng_inline_node.h" |
| 21 #include "core/layout/ng/ng_length_utils.h" | 21 #include "core/layout/ng/ng_length_utils.h" |
| 22 #include "core/layout/ng/ng_line_box_fragment.h" |
| 23 #include "core/layout/ng/ng_line_box_fragment_builder.h" |
| 22 #include "core/layout/ng/ng_space_utils.h" | 24 #include "core/layout/ng/ng_space_utils.h" |
| 23 #include "core/layout/ng/ng_text_fragment.h" | 25 #include "core/layout/ng/ng_text_fragment.h" |
| 26 #include "core/layout/ng/ng_text_fragment_builder.h" |
| 24 #include "core/style/ComputedStyle.h" | 27 #include "core/style/ComputedStyle.h" |
| 25 #include "platform/text/BidiRunList.h" | 28 #include "platform/text/BidiRunList.h" |
| 26 | 29 |
| 27 namespace blink { | 30 namespace blink { |
| 28 namespace { | 31 namespace { |
| 29 | 32 |
| 30 RefPtr<NGConstraintSpace> CreateConstraintSpaceForFloat( | 33 RefPtr<NGConstraintSpace> CreateConstraintSpaceForFloat( |
| 31 const ComputedStyle& style, | 34 const ComputedStyle& style, |
| 32 const NGConstraintSpace& parent_space, | 35 const NGConstraintSpace& parent_space, |
| 33 NGConstraintSpaceBuilder* space_builder) { | 36 NGConstraintSpaceBuilder* space_builder) { |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 PositionFloat(origin_point, constraint_space_->BfcOffset(), | 343 PositionFloat(origin_point, constraint_space_->BfcOffset(), |
| 341 floating_object.get(), constraint_space_); | 344 floating_object.get(), constraint_space_); |
| 342 container_builder_.AddFloatingObject(floating_object, offset); | 345 container_builder_.AddFloatingObject(floating_object, offset); |
| 343 FindNextLayoutOpportunity(); | 346 FindNextLayoutOpportunity(); |
| 344 } | 347 } |
| 345 } | 348 } |
| 346 | 349 |
| 347 void NGLineBuilder::PlaceItems( | 350 void NGLineBuilder::PlaceItems( |
| 348 const Vector<LineItemChunk, 32>& line_item_chunks) { | 351 const Vector<LineItemChunk, 32>& line_item_chunks) { |
| 349 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 352 const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
| 350 const unsigned fragment_start_index = container_builder_.Children().size(); | |
| 351 | 353 |
| 352 NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText, | 354 NGLineBoxFragmentBuilder line_box(inline_box_); |
| 353 inline_box_); | 355 NGTextFragmentBuilder text_builder(inline_box_); |
| 354 text_builder.SetWritingMode(ConstraintSpace().WritingMode()); | |
| 355 line_box_data_list_.grow(line_box_data_list_.size() + 1); | |
| 356 LineBoxData& line_box_data = line_box_data_list_.back(); | |
| 357 | 356 |
| 358 // Accumulate a "strut"; a zero-width inline box with the element's font and | 357 // Accumulate a "strut"; a zero-width inline box with the element's font and |
| 359 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut | 358 // line height properties. https://drafts.csswg.org/css2/visudet.html#strut |
| 360 const ComputedStyle* block_style = inline_box_->BlockStyle(); | 359 const ComputedStyle* block_style = inline_box_->BlockStyle(); |
| 361 InlineItemMetrics block_metrics(*block_style, baseline_type_); | 360 NGLineHeightMetrics block_metrics(*block_style, baseline_type_); |
| 362 line_box_data.UpdateMaxAscentAndDescent(block_metrics); | 361 line_box.UniteMetrics(block_metrics); |
| 363 | 362 |
| 364 // Use the block style to compute the estimated baseline position because the | 363 // Use the block style to compute the estimated baseline position because the |
| 365 // baseline position is not known until we know the maximum ascent and leading | 364 // baseline position is not known until we know the maximum ascent and leading |
| 366 // of the line. Items are placed on this baseline, then adjusted later if the | 365 // of the line. Items are placed on this baseline, then adjusted later if the |
| 367 // estimation turned out to be different. | 366 // estimation turned out to be different. |
| 368 LayoutUnit estimated_baseline = | 367 LayoutUnit estimated_baseline = |
| 369 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); | 368 content_size_ + LayoutUnit(block_metrics.ascent_and_leading); |
| 370 | 369 |
| 370 LayoutUnit inline_size; |
| 371 for (const auto& line_item_chunk : line_item_chunks) { | 371 for (const auto& line_item_chunk : line_item_chunks) { |
| 372 const NGLayoutInlineItem& item = items[line_item_chunk.index]; | 372 const NGLayoutInlineItem& item = items[line_item_chunk.index]; |
| 373 // Skip bidi controls. | 373 // Skip bidi controls. |
| 374 if (!item.GetLayoutObject()) | 374 if (!item.GetLayoutObject()) |
| 375 continue; | 375 continue; |
| 376 | 376 |
| 377 LayoutUnit block_start; | 377 LayoutUnit block_start; |
| 378 if (item.Type() == NGLayoutInlineItem::kText) { | 378 if (item.Type() == NGLayoutInlineItem::kText) { |
| 379 DCHECK(item.GetLayoutObject()->isText()); | 379 DCHECK(item.GetLayoutObject()->isText()); |
| 380 const ComputedStyle* style = item.Style(); | 380 const ComputedStyle* style = item.Style(); |
| 381 // The direction of a fragment is the CSS direction to resolve logical |
| 382 // properties, not the resolved bidi direction. |
| 383 text_builder.SetDirection(style->direction()) |
| 384 .SetInlineSize(line_item_chunk.inline_size); |
| 385 |
| 381 // |InlineTextBoxPainter| sets the baseline at |top + | 386 // |InlineTextBoxPainter| sets the baseline at |top + |
| 382 // ascent-of-primary-font|. Compute |top| to match. | 387 // ascent-of-primary-font|. Compute |top| to match. |
| 383 InlineItemMetrics metrics(*style, baseline_type_); | 388 NGLineHeightMetrics metrics(*style, baseline_type_); |
| 384 block_start = estimated_baseline - LayoutUnit(metrics.ascent); | 389 block_start = estimated_baseline - LayoutUnit(metrics.ascent); |
| 385 LayoutUnit line_height = LayoutUnit(metrics.ascent + metrics.descent); | 390 text_builder.SetBlockSize(metrics.LineHeight()); |
| 386 line_box_data.UpdateMaxAscentAndDescent(metrics); | 391 line_box.UniteMetrics(metrics); |
| 387 | 392 |
| 388 // Take all used fonts into account if 'line-height: normal'. | 393 // Take all used fonts into account if 'line-height: normal'. |
| 389 if (style->lineHeight().isNegative()) | 394 if (style->lineHeight().isNegative()) |
| 390 AccumulateUsedFonts(item, line_item_chunk, &line_box_data); | 395 AccumulateUsedFonts(item, line_item_chunk, &line_box); |
| 391 | |
| 392 // The direction of a fragment is the CSS direction to resolve logical | |
| 393 // properties, not the resolved bidi direction. | |
| 394 text_builder.SetDirection(style->direction()) | |
| 395 .SetInlineSize(line_item_chunk.inline_size) | |
| 396 .SetInlineOverflow(line_item_chunk.inline_size) | |
| 397 .SetBlockSize(line_height) | |
| 398 .SetBlockOverflow(line_height); | |
| 399 } else if (item.Type() == NGLayoutInlineItem::kAtomicInline) { | 396 } else if (item.Type() == NGLayoutInlineItem::kAtomicInline) { |
| 400 block_start = PlaceAtomicInline(item, estimated_baseline, &line_box_data, | 397 block_start = |
| 401 &text_builder); | 398 PlaceAtomicInline(item, estimated_baseline, &line_box, &text_builder); |
| 402 } else if (item.Type() == NGLayoutInlineItem::kOutOfFlowPositioned) { | 399 } else if (item.Type() == NGLayoutInlineItem::kOutOfFlowPositioned) { |
| 403 // TODO(layout-dev): Report the correct static position for the out of | 400 // TODO(layout-dev): Report the correct static position for the out of |
| 404 // flow descendant. We can't do this here yet as it doesn't know the | 401 // flow descendant. We can't do this here yet as it doesn't know the |
| 405 // size of the line box. | 402 // size of the line box. |
| 406 container_builder_.AddOutOfFlowDescendant( | 403 container_builder_.AddOutOfFlowDescendant( |
| 407 // Absolute positioning blockifies the box's display type. | 404 // Absolute positioning blockifies the box's display type. |
| 408 // https://drafts.csswg.org/css-display/#transformations | 405 // https://drafts.csswg.org/css-display/#transformations |
| 409 new NGBlockNode(item.GetLayoutObject()), | 406 new NGBlockNode(item.GetLayoutObject()), |
| 410 NGStaticPosition::Create(ConstraintSpace().WritingMode(), | 407 NGStaticPosition::Create(ConstraintSpace().WritingMode(), |
| 411 ConstraintSpace().Direction(), | 408 ConstraintSpace().Direction(), |
| 412 NGPhysicalOffset())); | 409 NGPhysicalOffset())); |
| 413 continue; | 410 continue; |
| 414 } else { | 411 } else { |
| 415 continue; | 412 continue; |
| 416 } | 413 } |
| 417 | 414 |
| 418 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( | 415 RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment( |
| 419 line_item_chunk.index, line_item_chunk.start_offset, | 416 line_item_chunk.index, line_item_chunk.start_offset, |
| 420 line_item_chunk.end_offset); | 417 line_item_chunk.end_offset); |
| 421 | 418 |
| 422 NGLogicalOffset logical_offset( | 419 NGLogicalOffset logical_offset( |
| 423 line_box_data.inline_size + current_opportunity_.InlineStartOffset() - | 420 inline_size + current_opportunity_.InlineStartOffset() - |
| 424 ConstraintSpace().BfcOffset().inline_offset, | 421 ConstraintSpace().BfcOffset().inline_offset, |
| 425 block_start); | 422 block_start); |
| 426 container_builder_.AddChild(std::move(text_fragment), logical_offset); | 423 line_box.AddChild(std::move(text_fragment), logical_offset); |
| 427 line_box_data.inline_size += line_item_chunk.inline_size; | 424 inline_size += line_item_chunk.inline_size; |
| 428 } | 425 } |
| 429 | 426 |
| 430 if (fragment_start_index == container_builder_.Children().size()) { | 427 if (line_box.Children().isEmpty()) { |
| 431 // The line was empty. Remove the LineBoxData. | 428 // The line was empty. |
| 432 line_box_data_list_.shrink(line_box_data_list_.size() - 1); | |
| 433 return; | 429 return; |
| 434 } | 430 } |
| 435 | 431 |
| 436 // If the estimated baseline position was not the actual position, move all | 432 // If the estimated baseline position was not the actual position, move all |
| 437 // fragments in the block direction. | 433 // fragments in the block direction. |
| 438 if (block_metrics.ascent_and_leading != | 434 LayoutUnit adjust_baseline(line_box.Metrics().ascent_and_leading - |
| 439 line_box_data.max_ascent_and_leading) { | 435 block_metrics.ascent_and_leading); |
| 440 LayoutUnit adjust_top(line_box_data.max_ascent_and_leading - | 436 if (adjust_baseline) |
| 441 block_metrics.ascent_and_leading); | 437 line_box.MoveChildrenInBlockDirection(adjust_baseline); |
| 442 auto& offsets = container_builder_.MutableOffsets(); | |
| 443 for (unsigned i = fragment_start_index; i < offsets.size(); i++) | |
| 444 offsets[i].block_offset += adjust_top; | |
| 445 } | |
| 446 | 438 |
| 447 line_box_data.fragment_end = container_builder_.Children().size(); | 439 line_box.SetInlineSize(inline_size); |
| 448 line_box_data.top_with_leading = content_size_; | 440 NGLogicalOffset offset(LayoutUnit(), content_size_); |
| 449 max_inline_size_ = std::max(max_inline_size_, line_box_data.inline_size); | 441 container_builder_.AddChild(line_box.ToLineBoxFragment(), offset); |
| 450 content_size_ += LayoutUnit(line_box_data.max_ascent_and_leading + | 442 max_inline_size_ = std::max(max_inline_size_, inline_size); |
| 451 line_box_data.max_descent_and_leading); | 443 content_size_ += line_box.Metrics().LineHeight(); |
| 452 } | |
| 453 | |
| 454 NGLineBuilder::InlineItemMetrics::InlineItemMetrics( | |
| 455 const ComputedStyle& style, | |
| 456 FontBaseline baseline_type) { | |
| 457 const SimpleFontData* font_data = style.font().primaryFont(); | |
| 458 DCHECK(font_data); | |
| 459 Initialize(font_data->getFontMetrics(), baseline_type, | |
| 460 style.computedLineHeightInFloat()); | |
| 461 } | |
| 462 | |
| 463 NGLineBuilder::InlineItemMetrics::InlineItemMetrics( | |
| 464 const FontMetrics& font_metrics, | |
| 465 FontBaseline baseline_type) { | |
| 466 Initialize(font_metrics, baseline_type, font_metrics.floatLineSpacing()); | |
| 467 } | |
| 468 | |
| 469 void NGLineBuilder::InlineItemMetrics::Initialize( | |
| 470 const FontMetrics& font_metrics, | |
| 471 FontBaseline baseline_type, | |
| 472 float line_height) { | |
| 473 ascent = font_metrics.floatAscent(baseline_type); | |
| 474 descent = font_metrics.floatDescent(baseline_type); | |
| 475 float half_leading = (line_height - (ascent + descent)) / 2; | |
| 476 // Ensure the top and the baseline is snapped to CSS pixel. | |
| 477 // TODO(kojii): How to handle fractional ascent isn't determined yet. Should | |
| 478 // we snap top or baseline? If baseline, top needs fractional. If top, | |
| 479 // baseline may not align across fonts. | |
| 480 ascent_and_leading = ascent + floor(half_leading); | |
| 481 descent_and_leading = line_height - ascent_and_leading; | |
| 482 } | |
| 483 | |
| 484 void NGLineBuilder::LineBoxData::UpdateMaxAscentAndDescent( | |
| 485 const NGLineBuilder::InlineItemMetrics& metrics) { | |
| 486 max_ascent = std::max(max_ascent, metrics.ascent); | |
| 487 max_descent = std::max(max_descent, metrics.descent); | |
| 488 max_ascent_and_leading = | |
| 489 std::max(max_ascent_and_leading, metrics.ascent_and_leading); | |
| 490 max_descent_and_leading = | |
| 491 std::max(max_descent_and_leading, metrics.descent_and_leading); | |
| 492 } | 444 } |
| 493 | 445 |
| 494 void NGLineBuilder::AccumulateUsedFonts(const NGLayoutInlineItem& item, | 446 void NGLineBuilder::AccumulateUsedFonts(const NGLayoutInlineItem& item, |
| 495 const LineItemChunk& line_item_chunk, | 447 const LineItemChunk& line_item_chunk, |
| 496 LineBoxData* line_box_data) { | 448 NGLineBoxFragmentBuilder* line_box) { |
| 497 HashSet<const SimpleFontData*> fallback_fonts; | 449 HashSet<const SimpleFontData*> fallback_fonts; |
| 498 item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset, | 450 item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset, |
| 499 line_item_chunk.end_offset); | 451 line_item_chunk.end_offset); |
| 500 for (const auto& fallback_font : fallback_fonts) { | 452 for (const auto& fallback_font : fallback_fonts) { |
| 501 InlineItemMetrics fallback_font_metrics(fallback_font->getFontMetrics(), | 453 NGLineHeightMetrics metrics(fallback_font->getFontMetrics(), |
| 502 baseline_type_); | 454 baseline_type_); |
| 503 line_box_data->UpdateMaxAscentAndDescent(fallback_font_metrics); | 455 line_box->UniteMetrics(metrics); |
| 504 } | 456 } |
| 505 } | 457 } |
| 506 | 458 |
| 507 LayoutUnit NGLineBuilder::PlaceAtomicInline(const NGLayoutInlineItem& item, | 459 LayoutUnit NGLineBuilder::PlaceAtomicInline( |
| 508 LayoutUnit estimated_baseline, | 460 const NGLayoutInlineItem& item, |
| 509 LineBoxData* line_box_data, | 461 LayoutUnit estimated_baseline, |
| 510 NGFragmentBuilder* text_builder) { | 462 NGLineBoxFragmentBuilder* line_box, |
| 463 NGTextFragmentBuilder* text_builder) { |
| 511 NGBoxFragment fragment( | 464 NGBoxFragment fragment( |
| 512 ConstraintSpace().WritingMode(), | 465 ConstraintSpace().WritingMode(), |
| 513 toNGPhysicalBoxFragment(LayoutItem(item)->PhysicalFragment().get())); | 466 toNGPhysicalBoxFragment(LayoutItem(item)->PhysicalFragment().get())); |
| 514 // TODO(kojii): Margin and border in block progression not implemented yet. | 467 // TODO(kojii): Margin and border in block progression not implemented yet. |
| 515 LayoutUnit block_size = fragment.BlockSize(); | 468 LayoutUnit block_size = fragment.BlockSize(); |
| 516 | 469 |
| 517 // TODO(kojii): Try to eliminate the wrapping text fragment and use the | 470 // TODO(kojii): Try to eliminate the wrapping text fragment and use the |
| 518 // |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow| | 471 // |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow| |
| 519 // requires a text fragment. | 472 // requires a text fragment. |
| 520 text_builder->SetInlineSize(fragment.InlineSize()) | 473 text_builder->SetInlineSize(fragment.InlineSize()).SetBlockSize(block_size); |
| 521 .SetInlineOverflow(fragment.InlineOverflow()) | |
| 522 .SetBlockSize(block_size) | |
| 523 .SetBlockOverflow(fragment.BlockOverflow()); | |
| 524 | 474 |
| 525 // TODO(kojii): Add baseline position to NGPhysicalFragment. | 475 // TODO(kojii): Add baseline position to NGPhysicalFragment. |
| 526 LayoutBox* box = toLayoutBox(item.GetLayoutObject()); | 476 LayoutBox* box = toLayoutBox(item.GetLayoutObject()); |
| 527 LineDirectionMode line_direction_mode = | 477 LineDirectionMode line_direction_mode = |
| 528 IsHorizontalWritingMode() ? LineDirectionMode::HorizontalLine | 478 IsHorizontalWritingMode() ? LineDirectionMode::HorizontalLine |
| 529 : LineDirectionMode::VerticalLine; | 479 : LineDirectionMode::VerticalLine; |
| 530 bool is_first_line = line_box_data_list_.size() == 1; | 480 bool is_first_line = container_builder_.Children().isEmpty(); |
| 531 int baseline_offset = | 481 int baseline_offset = |
| 532 box->baselinePosition(baseline_type_, is_first_line, line_direction_mode); | 482 box->baselinePosition(baseline_type_, is_first_line, line_direction_mode); |
| 533 LayoutUnit block_start = estimated_baseline - baseline_offset; | 483 LayoutUnit block_start = estimated_baseline - baseline_offset; |
| 534 | 484 |
| 535 line_box_data->max_ascent_and_leading = | 485 NGLineHeightMetrics metrics; |
| 536 std::max<float>(baseline_offset, line_box_data->max_ascent_and_leading); | 486 metrics.ascent_and_leading = baseline_offset; |
| 537 line_box_data->max_descent_and_leading = std::max<float>( | 487 metrics.descent_and_leading = block_size - baseline_offset; |
| 538 block_size - baseline_offset, line_box_data->max_descent_and_leading); | 488 line_box->UniteMetrics(metrics); |
| 539 | 489 |
| 540 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. | 490 // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. |
| 541 // Floats are ok because atomic inlines are BFC? | 491 // Floats are ok because atomic inlines are BFC? |
| 542 | 492 |
| 543 return block_start; | 493 return block_start; |
| 544 } | 494 } |
| 545 | 495 |
| 546 void NGLineBuilder::FindNextLayoutOpportunity() { | 496 void NGLineBuilder::FindNextLayoutOpportunity() { |
| 547 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); | 497 NGLogicalOffset iter_offset = constraint_space_->BfcOffset(); |
| 548 iter_offset.block_offset += content_size_; | 498 iter_offset.block_offset += content_size_; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 571 block->deleteLineBoxTree(); | 521 block->deleteLineBoxTree(); |
| 572 | 522 |
| 573 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); | 523 Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
| 574 Vector<unsigned, 32> text_offsets(items.size()); | 524 Vector<unsigned, 32> text_offsets(items.size()); |
| 575 inline_box_->GetLayoutTextOffsets(&text_offsets); | 525 inline_box_->GetLayoutTextOffsets(&text_offsets); |
| 576 | 526 |
| 577 Vector<const NGPhysicalFragment*, 32> fragments_for_bidi_runs; | 527 Vector<const NGPhysicalFragment*, 32> fragments_for_bidi_runs; |
| 578 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); | 528 fragments_for_bidi_runs.reserveInitialCapacity(items.size()); |
| 579 BidiRunList<BidiRun> bidi_runs; | 529 BidiRunList<BidiRun> bidi_runs; |
| 580 LineInfo line_info; | 530 LineInfo line_info; |
| 581 unsigned fragment_index = 0; | |
| 582 NGPhysicalBoxFragment* box_fragment = toNGPhysicalBoxFragment( | 531 NGPhysicalBoxFragment* box_fragment = toNGPhysicalBoxFragment( |
| 583 container_layout_result_->PhysicalFragment().get()); | 532 container_layout_result_->PhysicalFragment().get()); |
| 584 for (const auto& line_box_data : line_box_data_list_) { | 533 for (const auto& container_child : box_fragment->Children()) { |
| 534 NGPhysicalLineBoxFragment* physical_line_box = |
| 535 toNGPhysicalLineBoxFragment(container_child.get()); |
| 585 // Create a BidiRunList for this line. | 536 // Create a BidiRunList for this line. |
| 586 for (; fragment_index < line_box_data.fragment_end; fragment_index++) { | 537 for (const auto& line_child : physical_line_box->Children()) { |
| 587 const NGPhysicalFragment* fragment = | 538 const auto* text_fragment = toNGPhysicalTextFragment(line_child.get()); |
| 588 box_fragment->Children()[fragment_index].get(); | |
| 589 if (!fragment->IsText()) | |
| 590 continue; | |
| 591 const auto* text_fragment = toNGPhysicalTextFragment(fragment); | |
| 592 const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()]; | 539 const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()]; |
| 593 LayoutObject* layout_object = item.GetLayoutObject(); | |
| 594 if (!layout_object) // Skip bidi controls. | |
| 595 continue; | |
| 596 BidiRun* run; | 540 BidiRun* run; |
| 597 if (layout_object->isText()) { | 541 if (item.Type() == NGLayoutInlineItem::kText) { |
| 542 LayoutObject* layout_object = item.GetLayoutObject(); |
| 543 DCHECK(layout_object->isText()); |
| 598 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; | 544 unsigned text_offset = text_offsets[text_fragment->ItemIndex()]; |
| 599 run = new BidiRun(text_fragment->StartOffset() - text_offset, | 545 run = new BidiRun(text_fragment->StartOffset() - text_offset, |
| 600 text_fragment->EndOffset() - text_offset, | 546 text_fragment->EndOffset() - text_offset, |
| 601 item.BidiLevel(), LineLayoutItem(layout_object)); | 547 item.BidiLevel(), LineLayoutItem(layout_object)); |
| 602 layout_object->clearNeedsLayout(); | 548 layout_object->clearNeedsLayout(); |
| 603 } else { | 549 } else if (item.Type() == NGLayoutInlineItem::kAtomicInline) { |
| 550 LayoutObject* layout_object = item.GetLayoutObject(); |
| 604 DCHECK(layout_object->isAtomicInlineLevel()); | 551 DCHECK(layout_object->isAtomicInlineLevel()); |
| 605 run = | 552 run = |
| 606 new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object)); | 553 new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object)); |
| 554 } else { |
| 555 continue; |
| 607 } | 556 } |
| 608 bidi_runs.addRun(run); | 557 bidi_runs.addRun(run); |
| 609 fragments_for_bidi_runs.push_back(text_fragment); | 558 fragments_for_bidi_runs.push_back(text_fragment); |
| 610 } | 559 } |
| 611 // TODO(kojii): bidi needs to find the logical last run. | 560 // TODO(kojii): bidi needs to find the logical last run. |
| 612 bidi_runs.setLogicallyLastRun(bidi_runs.lastRun()); | 561 bidi_runs.setLogicallyLastRun(bidi_runs.lastRun()); |
| 613 | 562 |
| 614 // Create a RootInlineBox from BidiRunList. InlineBoxes created for the | 563 // Create a RootInlineBox from BidiRunList. InlineBoxes created for the |
| 615 // RootInlineBox are set to Bidirun::m_box. | 564 // RootInlineBox are set to Bidirun::m_box. |
| 616 line_info.setEmpty(false); | 565 line_info.setEmpty(false); |
| 617 // TODO(kojii): Implement setFirstLine, LastLine, etc. | 566 // TODO(kojii): Implement setFirstLine, LastLine, etc. |
| 618 RootInlineBox* line_box = block->constructLine(bidi_runs, line_info); | 567 RootInlineBox* root_line_box = block->constructLine(bidi_runs, line_info); |
| 619 | 568 |
| 620 // Copy fragments data to InlineBoxes. | 569 // Copy fragments data to InlineBoxes. |
| 621 DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount()); | 570 DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount()); |
| 622 BidiRun* run = bidi_runs.firstRun(); | 571 BidiRun* run = bidi_runs.firstRun(); |
| 623 for (auto* physical_fragment : fragments_for_bidi_runs) { | 572 for (auto* physical_fragment : fragments_for_bidi_runs) { |
| 624 DCHECK(run); | 573 DCHECK(run); |
| 625 NGTextFragment fragment(ConstraintSpace().WritingMode(), | 574 NGTextFragment fragment(ConstraintSpace().WritingMode(), |
| 626 toNGPhysicalTextFragment(physical_fragment)); | 575 toNGPhysicalTextFragment(physical_fragment)); |
| 627 InlineBox* inline_box = run->m_box; | 576 InlineBox* inline_box = run->m_box; |
| 628 inline_box->setLogicalWidth(fragment.InlineSize()); | 577 inline_box->setLogicalWidth(fragment.InlineSize()); |
| 629 inline_box->setLogicalLeft(fragment.InlineOffset()); | 578 inline_box->setLogicalLeft(fragment.InlineOffset()); |
| 630 inline_box->setLogicalTop(fragment.BlockOffset()); | 579 inline_box->setLogicalTop(fragment.BlockOffset()); |
| 631 if (inline_box->getLineLayoutItem().isBox()) { | 580 if (inline_box->getLineLayoutItem().isBox()) { |
| 632 LineLayoutBox box(inline_box->getLineLayoutItem()); | 581 LineLayoutBox box(inline_box->getLineLayoutItem()); |
| 633 box.setLocation(inline_box->location()); | 582 box.setLocation(inline_box->location()); |
| 634 } | 583 } |
| 635 run = run->next(); | 584 run = run->next(); |
| 636 } | 585 } |
| 637 DCHECK(!run); | 586 DCHECK(!run); |
| 638 | 587 |
| 639 // Copy LineBoxData to RootInlineBox. | 588 // Copy to RootInlineBox. |
| 640 line_box->setLogicalWidth(line_box_data.inline_size); | 589 NGLineBoxFragment line_box(ConstraintSpace().WritingMode(), |
| 641 line_box->setLogicalTop(line_box_data.top_with_leading); | 590 physical_line_box); |
| 642 LayoutUnit baseline_position = | 591 root_line_box->setLogicalWidth(line_box.InlineSize()); |
| 643 line_box_data.top_with_leading + | 592 LayoutUnit line_top_with_leading = line_box.BlockOffset(); |
| 644 LayoutUnit(line_box_data.max_ascent_and_leading); | 593 root_line_box->setLogicalTop(line_top_with_leading); |
| 645 line_box->setLineTopBottomPositions( | 594 const NGLineHeightMetrics& metrics = physical_line_box->Metrics(); |
| 646 baseline_position - LayoutUnit(line_box_data.max_ascent), | 595 LayoutUnit baseline = |
| 647 baseline_position + LayoutUnit(line_box_data.max_descent), | 596 line_top_with_leading + LayoutUnit(metrics.ascent_and_leading); |
| 648 line_box_data.top_with_leading, | 597 root_line_box->setLineTopBottomPositions( |
| 649 baseline_position + LayoutUnit(line_box_data.max_descent_and_leading)); | 598 baseline - LayoutUnit(metrics.ascent), |
| 599 baseline + LayoutUnit(metrics.descent), line_top_with_leading, |
| 600 baseline + LayoutUnit(metrics.descent_and_leading)); |
| 650 | 601 |
| 651 bidi_runs.deleteRuns(); | 602 bidi_runs.deleteRuns(); |
| 652 fragments_for_bidi_runs.clear(); | 603 fragments_for_bidi_runs.clear(); |
| 653 } | 604 } |
| 654 } | 605 } |
| 655 } // namespace blink | 606 } // namespace blink |
| OLD | NEW |