Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(683)

Unified Diff: third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc

Issue 2764753007: [LayoutNG] Add NGLineBoxFragment (Closed)
Patch Set: Rebase again as other CLs landed faster Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
index 4bb239f596d26b44643673aa8a265a8fd07e6ed0..be639f41da13b93bc0d9f8a3458f3f0f5cd322c5 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
@@ -19,8 +19,11 @@
#include "core/layout/ng/ng_fragment_builder.h"
#include "core/layout/ng/ng_inline_node.h"
#include "core/layout/ng/ng_length_utils.h"
+#include "core/layout/ng/ng_line_box_fragment.h"
+#include "core/layout/ng/ng_line_box_fragment_builder.h"
#include "core/layout/ng/ng_space_utils.h"
#include "core/layout/ng/ng_text_fragment.h"
+#include "core/layout/ng/ng_text_fragment_builder.h"
#include "core/style/ComputedStyle.h"
#include "platform/text/BidiRunList.h"
@@ -347,19 +350,15 @@ void NGLineBuilder::LayoutAndPositionFloat(LayoutUnit end_position,
void NGLineBuilder::PlaceItems(
const Vector<LineItemChunk, 32>& line_item_chunks) {
const Vector<NGLayoutInlineItem>& items = inline_box_->Items();
- const unsigned fragment_start_index = container_builder_.Children().size();
- NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText,
- inline_box_);
- text_builder.SetWritingMode(ConstraintSpace().WritingMode());
- line_box_data_list_.grow(line_box_data_list_.size() + 1);
- LineBoxData& line_box_data = line_box_data_list_.back();
+ NGLineBoxFragmentBuilder line_box(inline_box_);
+ NGTextFragmentBuilder text_builder(inline_box_);
// Accumulate a "strut"; a zero-width inline box with the element's font and
// line height properties. https://drafts.csswg.org/css2/visudet.html#strut
const ComputedStyle* block_style = inline_box_->BlockStyle();
- InlineItemMetrics block_metrics(*block_style, baseline_type_);
- line_box_data.UpdateMaxAscentAndDescent(block_metrics);
+ NGLineHeightMetrics block_metrics(*block_style, baseline_type_);
+ line_box.UniteMetrics(block_metrics);
// Use the block style to compute the estimated baseline position because the
// baseline position is not known until we know the maximum ascent and leading
@@ -368,6 +367,7 @@ void NGLineBuilder::PlaceItems(
LayoutUnit estimated_baseline =
content_size_ + LayoutUnit(block_metrics.ascent_and_leading);
+ LayoutUnit inline_size;
for (const auto& line_item_chunk : line_item_chunks) {
const NGLayoutInlineItem& item = items[line_item_chunk.index];
// Skip bidi controls.
@@ -378,27 +378,24 @@ void NGLineBuilder::PlaceItems(
if (item.Type() == NGLayoutInlineItem::kText) {
DCHECK(item.GetLayoutObject()->isText());
const ComputedStyle* style = item.Style();
+ // The direction of a fragment is the CSS direction to resolve logical
+ // properties, not the resolved bidi direction.
+ text_builder.SetDirection(style->direction())
+ .SetInlineSize(line_item_chunk.inline_size);
+
// |InlineTextBoxPainter| sets the baseline at |top +
// ascent-of-primary-font|. Compute |top| to match.
- InlineItemMetrics metrics(*style, baseline_type_);
+ NGLineHeightMetrics metrics(*style, baseline_type_);
block_start = estimated_baseline - LayoutUnit(metrics.ascent);
- LayoutUnit line_height = LayoutUnit(metrics.ascent + metrics.descent);
- line_box_data.UpdateMaxAscentAndDescent(metrics);
+ text_builder.SetBlockSize(metrics.LineHeight());
+ line_box.UniteMetrics(metrics);
// Take all used fonts into account if 'line-height: normal'.
if (style->lineHeight().isNegative())
- AccumulateUsedFonts(item, line_item_chunk, &line_box_data);
-
- // The direction of a fragment is the CSS direction to resolve logical
- // properties, not the resolved bidi direction.
- text_builder.SetDirection(style->direction())
- .SetInlineSize(line_item_chunk.inline_size)
- .SetInlineOverflow(line_item_chunk.inline_size)
- .SetBlockSize(line_height)
- .SetBlockOverflow(line_height);
+ AccumulateUsedFonts(item, line_item_chunk, &line_box);
} else if (item.Type() == NGLayoutInlineItem::kAtomicInline) {
- block_start = PlaceAtomicInline(item, estimated_baseline, &line_box_data,
- &text_builder);
+ block_start =
+ PlaceAtomicInline(item, estimated_baseline, &line_box, &text_builder);
} else if (item.Type() == NGLayoutInlineItem::kOutOfFlowPositioned) {
// TODO(layout-dev): Report the correct static position for the out of
// flow descendant. We can't do this here yet as it doesn't know the
@@ -420,94 +417,50 @@ void NGLineBuilder::PlaceItems(
line_item_chunk.end_offset);
NGLogicalOffset logical_offset(
- line_box_data.inline_size + current_opportunity_.InlineStartOffset() -
+ inline_size + current_opportunity_.InlineStartOffset() -
ConstraintSpace().BfcOffset().inline_offset,
block_start);
- container_builder_.AddChild(std::move(text_fragment), logical_offset);
- line_box_data.inline_size += line_item_chunk.inline_size;
+ line_box.AddChild(std::move(text_fragment), logical_offset);
+ inline_size += line_item_chunk.inline_size;
}
- if (fragment_start_index == container_builder_.Children().size()) {
- // The line was empty. Remove the LineBoxData.
- line_box_data_list_.shrink(line_box_data_list_.size() - 1);
+ if (line_box.Children().isEmpty()) {
+ // The line was empty.
return;
}
// If the estimated baseline position was not the actual position, move all
// fragments in the block direction.
- if (block_metrics.ascent_and_leading !=
- line_box_data.max_ascent_and_leading) {
- LayoutUnit adjust_top(line_box_data.max_ascent_and_leading -
- block_metrics.ascent_and_leading);
- auto& offsets = container_builder_.MutableOffsets();
- for (unsigned i = fragment_start_index; i < offsets.size(); i++)
- offsets[i].block_offset += adjust_top;
- }
-
- line_box_data.fragment_end = container_builder_.Children().size();
- line_box_data.top_with_leading = content_size_;
- max_inline_size_ = std::max(max_inline_size_, line_box_data.inline_size);
- content_size_ += LayoutUnit(line_box_data.max_ascent_and_leading +
- line_box_data.max_descent_and_leading);
-}
-
-NGLineBuilder::InlineItemMetrics::InlineItemMetrics(
- const ComputedStyle& style,
- FontBaseline baseline_type) {
- const SimpleFontData* font_data = style.font().primaryFont();
- DCHECK(font_data);
- Initialize(font_data->getFontMetrics(), baseline_type,
- style.computedLineHeightInFloat());
-}
-
-NGLineBuilder::InlineItemMetrics::InlineItemMetrics(
- const FontMetrics& font_metrics,
- FontBaseline baseline_type) {
- Initialize(font_metrics, baseline_type, font_metrics.floatLineSpacing());
-}
-
-void NGLineBuilder::InlineItemMetrics::Initialize(
- const FontMetrics& font_metrics,
- FontBaseline baseline_type,
- float line_height) {
- ascent = font_metrics.floatAscent(baseline_type);
- descent = font_metrics.floatDescent(baseline_type);
- float half_leading = (line_height - (ascent + descent)) / 2;
- // Ensure the top and the baseline is snapped to CSS pixel.
- // TODO(kojii): How to handle fractional ascent isn't determined yet. Should
- // we snap top or baseline? If baseline, top needs fractional. If top,
- // baseline may not align across fonts.
- ascent_and_leading = ascent + floor(half_leading);
- descent_and_leading = line_height - ascent_and_leading;
-}
-
-void NGLineBuilder::LineBoxData::UpdateMaxAscentAndDescent(
- const NGLineBuilder::InlineItemMetrics& metrics) {
- max_ascent = std::max(max_ascent, metrics.ascent);
- max_descent = std::max(max_descent, metrics.descent);
- max_ascent_and_leading =
- std::max(max_ascent_and_leading, metrics.ascent_and_leading);
- max_descent_and_leading =
- std::max(max_descent_and_leading, metrics.descent_and_leading);
+ LayoutUnit adjust_baseline(line_box.Metrics().ascent_and_leading -
+ block_metrics.ascent_and_leading);
+ if (adjust_baseline)
+ line_box.MoveChildrenInBlockDirection(adjust_baseline);
+
+ line_box.SetInlineSize(inline_size);
+ NGLogicalOffset offset(LayoutUnit(), content_size_);
+ container_builder_.AddChild(line_box.ToLineBoxFragment(), offset);
+ max_inline_size_ = std::max(max_inline_size_, inline_size);
+ content_size_ += line_box.Metrics().LineHeight();
}
void NGLineBuilder::AccumulateUsedFonts(const NGLayoutInlineItem& item,
const LineItemChunk& line_item_chunk,
- LineBoxData* line_box_data) {
+ NGLineBoxFragmentBuilder* line_box) {
HashSet<const SimpleFontData*> fallback_fonts;
item.GetFallbackFonts(&fallback_fonts, line_item_chunk.start_offset,
line_item_chunk.end_offset);
for (const auto& fallback_font : fallback_fonts) {
- InlineItemMetrics fallback_font_metrics(fallback_font->getFontMetrics(),
- baseline_type_);
- line_box_data->UpdateMaxAscentAndDescent(fallback_font_metrics);
+ NGLineHeightMetrics metrics(fallback_font->getFontMetrics(),
+ baseline_type_);
+ line_box->UniteMetrics(metrics);
}
}
-LayoutUnit NGLineBuilder::PlaceAtomicInline(const NGLayoutInlineItem& item,
- LayoutUnit estimated_baseline,
- LineBoxData* line_box_data,
- NGFragmentBuilder* text_builder) {
+LayoutUnit NGLineBuilder::PlaceAtomicInline(
+ const NGLayoutInlineItem& item,
+ LayoutUnit estimated_baseline,
+ NGLineBoxFragmentBuilder* line_box,
+ NGTextFragmentBuilder* text_builder) {
NGBoxFragment fragment(
ConstraintSpace().WritingMode(),
toNGPhysicalBoxFragment(LayoutItem(item)->PhysicalFragment().get()));
@@ -517,25 +470,22 @@ LayoutUnit NGLineBuilder::PlaceAtomicInline(const NGLayoutInlineItem& item,
// TODO(kojii): Try to eliminate the wrapping text fragment and use the
// |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow|
// requires a text fragment.
- text_builder->SetInlineSize(fragment.InlineSize())
- .SetInlineOverflow(fragment.InlineOverflow())
- .SetBlockSize(block_size)
- .SetBlockOverflow(fragment.BlockOverflow());
+ text_builder->SetInlineSize(fragment.InlineSize()).SetBlockSize(block_size);
// TODO(kojii): Add baseline position to NGPhysicalFragment.
LayoutBox* box = toLayoutBox(item.GetLayoutObject());
LineDirectionMode line_direction_mode =
IsHorizontalWritingMode() ? LineDirectionMode::HorizontalLine
: LineDirectionMode::VerticalLine;
- bool is_first_line = line_box_data_list_.size() == 1;
+ bool is_first_line = container_builder_.Children().isEmpty();
int baseline_offset =
box->baselinePosition(baseline_type_, is_first_line, line_direction_mode);
LayoutUnit block_start = estimated_baseline - baseline_offset;
- line_box_data->max_ascent_and_leading =
- std::max<float>(baseline_offset, line_box_data->max_ascent_and_leading);
- line_box_data->max_descent_and_leading = std::max<float>(
- block_size - baseline_offset, line_box_data->max_descent_and_leading);
+ NGLineHeightMetrics metrics;
+ metrics.ascent_and_leading = baseline_offset;
+ metrics.descent_and_leading = block_size - baseline_offset;
+ line_box->UniteMetrics(metrics);
// TODO(kojii): Figure out what to do with OOF in NGLayoutResult.
// Floats are ok because atomic inlines are BFC?
@@ -578,32 +528,31 @@ void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() {
fragments_for_bidi_runs.reserveInitialCapacity(items.size());
BidiRunList<BidiRun> bidi_runs;
LineInfo line_info;
- unsigned fragment_index = 0;
NGPhysicalBoxFragment* box_fragment = toNGPhysicalBoxFragment(
container_layout_result_->PhysicalFragment().get());
- for (const auto& line_box_data : line_box_data_list_) {
+ for (const auto& container_child : box_fragment->Children()) {
+ NGPhysicalLineBoxFragment* physical_line_box =
+ toNGPhysicalLineBoxFragment(container_child.get());
// Create a BidiRunList for this line.
- for (; fragment_index < line_box_data.fragment_end; fragment_index++) {
- const NGPhysicalFragment* fragment =
- box_fragment->Children()[fragment_index].get();
- if (!fragment->IsText())
- continue;
- const auto* text_fragment = toNGPhysicalTextFragment(fragment);
+ for (const auto& line_child : physical_line_box->Children()) {
+ const auto* text_fragment = toNGPhysicalTextFragment(line_child.get());
const NGLayoutInlineItem& item = items[text_fragment->ItemIndex()];
- LayoutObject* layout_object = item.GetLayoutObject();
- if (!layout_object) // Skip bidi controls.
- continue;
BidiRun* run;
- if (layout_object->isText()) {
+ if (item.Type() == NGLayoutInlineItem::kText) {
+ LayoutObject* layout_object = item.GetLayoutObject();
+ DCHECK(layout_object->isText());
unsigned text_offset = text_offsets[text_fragment->ItemIndex()];
run = new BidiRun(text_fragment->StartOffset() - text_offset,
text_fragment->EndOffset() - text_offset,
item.BidiLevel(), LineLayoutItem(layout_object));
layout_object->clearNeedsLayout();
- } else {
+ } else if (item.Type() == NGLayoutInlineItem::kAtomicInline) {
+ LayoutObject* layout_object = item.GetLayoutObject();
DCHECK(layout_object->isAtomicInlineLevel());
run =
new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object));
+ } else {
+ continue;
}
bidi_runs.addRun(run);
fragments_for_bidi_runs.push_back(text_fragment);
@@ -615,7 +564,7 @@ void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() {
// RootInlineBox are set to Bidirun::m_box.
line_info.setEmpty(false);
// TODO(kojii): Implement setFirstLine, LastLine, etc.
- RootInlineBox* line_box = block->constructLine(bidi_runs, line_info);
+ RootInlineBox* root_line_box = block->constructLine(bidi_runs, line_info);
// Copy fragments data to InlineBoxes.
DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount());
@@ -636,17 +585,19 @@ void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() {
}
DCHECK(!run);
- // Copy LineBoxData to RootInlineBox.
- line_box->setLogicalWidth(line_box_data.inline_size);
- line_box->setLogicalTop(line_box_data.top_with_leading);
- LayoutUnit baseline_position =
- line_box_data.top_with_leading +
- LayoutUnit(line_box_data.max_ascent_and_leading);
- line_box->setLineTopBottomPositions(
- baseline_position - LayoutUnit(line_box_data.max_ascent),
- baseline_position + LayoutUnit(line_box_data.max_descent),
- line_box_data.top_with_leading,
- baseline_position + LayoutUnit(line_box_data.max_descent_and_leading));
+ // Copy to RootInlineBox.
+ NGLineBoxFragment line_box(ConstraintSpace().WritingMode(),
+ physical_line_box);
+ root_line_box->setLogicalWidth(line_box.InlineSize());
+ LayoutUnit line_top_with_leading = line_box.BlockOffset();
+ root_line_box->setLogicalTop(line_top_with_leading);
+ const NGLineHeightMetrics& metrics = physical_line_box->Metrics();
+ LayoutUnit baseline =
+ line_top_with_leading + LayoutUnit(metrics.ascent_and_leading);
+ root_line_box->setLineTopBottomPositions(
+ baseline - LayoutUnit(metrics.ascent),
+ baseline + LayoutUnit(metrics.descent), line_top_with_leading,
+ baseline + LayoutUnit(metrics.descent_and_leading));
bidi_runs.deleteRuns();
fragments_for_bidi_runs.clear();

Powered by Google App Engine
This is Rietveld 408576698