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

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

Issue 2745973002: [LayoutNG] Implement atomic inlines for LayoutNGInline (Closed)
Patch Set: 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 d5b2d8c5e74873d6cea1953ae31ab5e2c0fa9a34..5ec108bd9c42c27956e487079b239bfeb5ae813c 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
@@ -25,15 +25,15 @@ NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box,
: inline_box_(inline_box),
constraint_space_(constraint_space),
containing_block_builder_(containing_block_builder),
- baseline_type_(constraint_space->WritingMode() ==
- NGWritingMode::kHorizontalTopBottom
- ? FontBaseline::AlphabeticBaseline
- : FontBaseline::IdeographicBaseline)
+ is_horizontal_writing_mode_(
+ blink::IsHorizontalWritingMode(constraint_space->WritingMode()))
#if DCHECK_IS_ON()
,
is_bidi_reordered_(false)
#endif
{
+ if (!is_horizontal_writing_mode_)
+ baseline_type_ = FontBaseline::IdeographicBaseline;
}
bool NGLineBuilder::CanFitOnLine() const {
@@ -76,17 +76,17 @@ void NGLineBuilder::SetEnd(unsigned new_end_offset) {
if (new_end_offset > item->EndOffset()) {
if (end_offset_ < item->EndOffset()) {
SetEnd(item->EndOffset(),
- item->InlineSize(end_offset_, item->EndOffset()));
+ InlineSize(*item, end_offset_, item->EndOffset()));
}
item = &items[++last_index];
while (new_end_offset > item->EndOffset()) {
- SetEnd(item->EndOffset(), item->InlineSize());
+ SetEnd(item->EndOffset(), InlineSize(*item));
item = &items[++last_index];
}
}
- SetEnd(new_end_offset, item->InlineSize(end_offset_, new_end_offset));
+ SetEnd(new_end_offset, InlineSize(*item, end_offset_, new_end_offset));
}
void NGLineBuilder::SetEnd(unsigned new_end_offset,
@@ -125,6 +125,40 @@ void NGLineBuilder::SetStartOfHangables(unsigned offset) {
// TODO(kojii): Implement.
}
+LayoutUnit NGLineBuilder::InlineSize(const NGLayoutInlineItem& item) {
+ if (item.IsAtomicInlineLevel())
+ return InlineSizeFromLayout(item);
+ return item.InlineSize();
+}
+
+LayoutUnit NGLineBuilder::InlineSize(const NGLayoutInlineItem& item,
+ unsigned start_offset,
+ unsigned end_offset) {
+ if (item.StartOffset() == start_offset && item.EndOffset() == end_offset &&
+ item.IsAtomicInlineLevel())
+ return InlineSizeFromLayout(item);
+ return item.InlineSize(start_offset, end_offset);
+}
+
+LayoutUnit NGLineBuilder::InlineSizeFromLayout(const NGLayoutInlineItem& item) {
+ const RefPtr<NGLayoutResult>& layout_result = LayoutItem(item);
+ return IsHorizontalWritingMode()
ikilpatrick 2017/03/16 16:15:40 instead of this can you stack allocate a NGBoxFrag
kojii 2017/03/16 16:48:45 Done. I didn't know I can pass parent's writing-mo
+ ? layout_result->PhysicalFragment()->Width()
+ : layout_result->PhysicalFragment()->Height();
+}
+
+RefPtr<NGLayoutResult>& NGLineBuilder::LayoutItem(
+ const NGLayoutInlineItem& item) {
+ const Vector<NGLayoutInlineItem>& items = inline_box_->Items();
+ if (layout_results_.isEmpty())
+ layout_results_.resize(items.size());
+ unsigned index = std::distance(items.begin(), &item);
+ RefPtr<NGLayoutResult>& layout_result = layout_results_[index];
+ if (!layout_result)
+ layout_result = item.Layout(ConstraintSpace());
ikilpatrick 2017/03/16 16:15:41 We'll need to fix this constraint space, this migh
ikilpatrick 2017/03/16 16:15:41 on this is not a NGLayoutInputNode, hmmm... i foun
kojii 2017/03/16 16:48:45 Understood, moved the layout code here.
+ return layout_result;
ikilpatrick 2017/03/16 16:15:40 do we need to assign back to the layout_results_ v
kojii 2017/03/16 16:48:45 |layout_result| here is a reference to the vector.
+}
+
void NGLineBuilder::CreateLine() {
if (HasItemsAfterLastBreakOpportunity())
SetBreakOpportunity();
@@ -145,7 +179,7 @@ void NGLineBuilder::CreateLineUpToLastBreakOpportunity() {
std::min(item.EndOffset(), last_break_opportunity_offset_);
line_item_chunks.push_back(
LineItemChunk{i, start_offset, end_offset,
- item.InlineSize(start_offset, end_offset)});
+ InlineSize(item, start_offset, end_offset)});
start_offset = end_offset;
}
@@ -233,19 +267,28 @@ void NGLineBuilder::PlaceItems(
if (!item.GetLayoutObject())
continue;
- LayoutUnit top, height;
+ LayoutUnit top;
const ComputedStyle* style = item.Style();
if (style) {
+ DCHECK(item.GetLayoutObject()->isText());
// |InlineTextBoxPainter| sets the baseline at |top +
// ascent-of-primary-font|. Compute |top| to match.
InlineItemMetrics metrics(*style, baseline_type_);
top = estimated_baseline - LayoutUnit(metrics.ascent);
- height = LayoutUnit(metrics.ascent + metrics.descent);
+ LayoutUnit height = LayoutUnit(metrics.ascent + metrics.descent);
line_box_data.UpdateMaxAscentAndDescent(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(height)
+ .SetBlockOverflow(height);
} else {
LayoutObject* layout_object = item.GetLayoutObject();
if (layout_object->isOutOfFlowPositioned()) {
@@ -264,19 +307,10 @@ void NGLineBuilder::PlaceItems(
layout_object->clearNeedsLayout();
continue;
}
- DCHECK(layout_object->isAtomicInlineLevel());
- // TODO(kojii): Implement atomic inline.
- style = layout_object->style();
- top = content_size_;
+ top = PlaceAtomicInline(item, estimated_baseline, &line_box_data,
+ &text_builder);
}
- // 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(height)
- .SetBlockOverflow(height);
RefPtr<NGPhysicalTextFragment> text_fragment = text_builder.ToTextFragment(
line_item_chunk.index, line_item_chunk.start_offset,
line_item_chunk.end_offset);
@@ -367,6 +401,52 @@ void NGLineBuilder::AccumulateUsedFonts(const NGLayoutInlineItem& item,
}
}
+LayoutUnit NGLineBuilder::PlaceAtomicInline(const NGLayoutInlineItem& item,
+ LayoutUnit estimated_baseline,
+ LineBoxData* line_box_data,
+ NGFragmentBuilder* text_builder) {
+ const RefPtr<NGLayoutResult>& layout_result = LayoutItem(item);
+ RefPtr<NGPhysicalFragment> fragment = layout_result->PhysicalFragment();
+ LayoutUnit height;
+ // TODO(kojii): Try to eliminate the text fragment and use the |fragment|
+ // directly. Currently |CopyFragmentDataToLayoutBlockFlow| requires a text
+ // fragment.
+ // TODO(kojii): Margin and border in block progression not implemented yet.
+ if (IsHorizontalWritingMode()) {
+ height = fragment->Height();
+ text_builder->SetInlineSize(fragment->Width())
+ .SetInlineOverflow(fragment->WidthOverflow())
+ .SetBlockSize(height)
+ .SetBlockOverflow(fragment->HeightOverflow());
+ } else {
+ height = fragment->Width();
+ text_builder->SetInlineSize(fragment->Height())
+ .SetInlineOverflow(fragment->HeightOverflow())
+ .SetBlockSize(height)
+ .SetBlockOverflow(fragment->WidthOverflow());
+ }
+
+ // 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;
+ int baseline_offset =
+ box->baselinePosition(baseline_type_, is_first_line, line_direction_mode);
+ LayoutUnit top = 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>(
+ height - baseline_offset, line_box_data->max_descent_and_leading);
+
+ // TODO(kojii): Figure out what to do with OOF in NGLayoutResult.
+ // Floats are ok because atomic inlines are BFC?
+
+ return top;
+}
+
void NGLineBuilder::FindNextLayoutOpportunity() {
NGLogicalOffset iter_offset = constraint_space_->BfcOffset();
iter_offset.block_offset += content_size_;
@@ -432,8 +512,6 @@ void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() {
DCHECK(layout_object->isAtomicInlineLevel());
run =
new BidiRun(0, 1, item.BidiLevel(), LineLayoutItem(layout_object));
- // TODO(kojii): Temporarily clearNeedsLayout() for not to assert.
- layout_object->clearNeedsLayout();
}
bidi_runs.addRun(run);
fragments_for_bidi_runs.push_back(text_fragment);
@@ -458,12 +536,17 @@ void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() {
inline_box->setLogicalWidth(fragment.InlineSize());
inline_box->setLogicalLeft(fragment.InlineOffset());
inline_box->setLogicalTop(fragment.BlockOffset());
+ if (inline_box->getLineLayoutItem().isBox()) {
+ LineLayoutBox box(inline_box->getLineLayoutItem());
+ box.setLocation(inline_box->location());
+ }
run = run->next();
}
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);

Powered by Google App Engine
This is Rietveld 408576698