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 |