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

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

Issue 2865903002: [LayoutNG] Inline margin/border/padding, inter-item breaking, and tests (Closed)
Patch Set: ikilpatrick review Created 3 years, 7 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/inline/ng_line_breaker.cc
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
index d464a038527e453fe395bcae591ee9444b65ff27..4656455ad8dca35170336bde27cd74b2a8b99a5b 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
@@ -17,7 +17,6 @@
#include "core/style/ComputedStyle.h"
#include "platform/fonts/shaping/HarfBuzzShaper.h"
#include "platform/fonts/shaping/ShapingLineBreaker.h"
-#include "platform/text/TextBreakIterator.h"
namespace blink {
@@ -28,19 +27,7 @@ namespace {
#if defined(MOCK_SHAPE_LINE)
// The mock for ShapingLineBreaker::ShapeLine().
-// Given the design of ShapingLineBreaker, expected semantics are:
-// - The returned offset is always > item.StartOffset().
-// - offset < item.EndOffset():
-// - width <= available_width: the break opportunity to fit is found.
-// - width > available_width: the first break opportunity did not fit.
-// - offset == item.EndOffset():
-// - width <= available_width: the break opportunity at the end of the item
-// fits.
-// - width > available_width: the first break opportunity is at the end of
-// the item and it does not fit.
-// - offset > item.EndOffset():, the first break opportunity is beyond the
-// end of item and thus cannot measure. In this case, inline_size shows the
-// width until the end of the item. It may fit or may not.
+// See BreakText() for the expected semantics.
std::pair<unsigned, LayoutUnit> ShapeLineMock(
const NGInlineItem& item,
unsigned offset,
@@ -67,23 +54,16 @@ std::pair<unsigned, LayoutUnit> ShapeLineMock(
}
#endif
-LineBreakType GetLineBreakType(const ComputedStyle& style) {
- if (style.AutoWrap()) {
- if (style.WordBreak() == EWordBreak::kBreakAll ||
- style.WordBreak() == EWordBreak::kBreakWord)
- return LineBreakType::kBreakAll;
- if (style.WordBreak() == EWordBreak::kKeepAll)
- return LineBreakType::kKeepAll;
- }
- return LineBreakType::kNormal;
-}
-
} // namespace
NGLineBreaker::NGLineBreaker(NGInlineNode* node,
const NGConstraintSpace* space,
NGInlineBreakToken* break_token)
- : node_(node), constraint_space_(space), item_index_(0), offset_(0) {
+ : node_(node),
+ constraint_space_(space),
+ item_index_(0),
+ offset_(0),
+ break_iterator_(node->Text()) {
if (break_token) {
item_index_ = break_token->ItemIndex();
offset_ = break_token->TextOffset();
@@ -106,130 +86,169 @@ void NGLineBreaker::BreakLine(NGInlineItemResults* item_results,
NGInlineLayoutAlgorithm* algorithm) {
DCHECK(item_results->IsEmpty());
const Vector<NGInlineItem>& items = node_->Items();
- const String& text = node_->Text();
const ComputedStyle& style = node_->Style();
- LazyLineBreakIterator break_iterator(text, style.LocaleForLineBreakIterator(),
- GetLineBreakType(style));
+ UpdateBreakIterator(style);
#if !defined(MOCK_SHAPE_LINE)
+ // TODO(kojii): Instantiate in the constructor.
HarfBuzzShaper shaper(text.Characters16(), text.length());
#endif
- LayoutUnit available_width = algorithm->AvailableWidth();
- LayoutUnit position;
+ available_width_ = algorithm->AvailableWidth();
+ position_ = LayoutUnit(0);
+ LineBreakState state = LineBreakState::kNotBreakable;
+
while (item_index_ < items.size()) {
+ // CloseTag prohibits to break before.
const NGInlineItem& item = items[item_index_];
+ if (item.Type() == NGInlineItem::kCloseTag) {
+ item_results->push_back(
+ NGInlineItemResult(item_index_, offset_, item.EndOffset()));
+ HandleCloseTag(item, &item_results->back());
+ continue;
+ }
+
+ if (state == LineBreakState::kBreakAfterTrailings)
+ return;
+ if (state == LineBreakState::kIsBreakable && position_ > available_width_)
+ return HandleOverflow(item_results);
+
item_results->push_back(
NGInlineItemResult(item_index_, offset_, item.EndOffset()));
NGInlineItemResult* item_result = &item_results->back();
+ if (item.Type() == NGInlineItem::kText) {
+ state = HandleText(item, item_result);
+ } else if (item.Type() == NGInlineItem::kAtomicInline) {
+ state = HandleAtomicInline(item, item_result);
+ } else if (item.Type() == NGInlineItem::kControl) {
+ state = HandleControlItem(item, item_result);
+ if (state == LineBreakState::kForcedBreak)
+ return;
+ } else if (item.Type() == NGInlineItem::kOpenTag) {
+ HandleOpenTag(item, item_result);
+ state = LineBreakState::kNotBreakable;
+ } else if (item.Type() == NGInlineItem::kFloating) {
+ HandleFloat(item, item_results, algorithm);
+ } else {
+ MoveToNextOf(item);
+ }
+ }
+ if (state == LineBreakState::kIsBreakable && position_ > available_width_)
+ return HandleOverflow(item_results);
+}
- // If the start offset is at the item boundary, try to add the entire item.
- if (offset_ == item.StartOffset()) {
- if (item.Type() == NGInlineItem::kText) {
- item_result->inline_size = item.InlineSize();
- } else if (item.Type() == NGInlineItem::kAtomicInline) {
- LayoutAtomicInline(item, item_result);
- } else if (item.Type() == NGInlineItem::kControl) {
- if (HandleControlItem(item, text, item_result, position)) {
- MoveToNextOf(item);
- break;
- }
- } else if (item.Type() == NGInlineItem::kFloating) {
- algorithm->LayoutAndPositionFloat(position, item.GetLayoutObject());
- // Floats may change the available width if they fit.
- available_width = algorithm->AvailableWidth();
- // Floats are already positioned in the container_builder.
- item_results->pop_back();
- MoveToNextOf(item);
- continue;
- } else {
- MoveToNextOf(item);
- continue;
- }
- LayoutUnit next_position = position + item_result->inline_size;
- if (next_position <= available_width) {
- MoveToNextOf(item);
- position = next_position;
- continue;
- }
+NGLineBreaker::LineBreakState NGLineBreaker::HandleText(
+ const NGInlineItem& item,
+ NGInlineItemResult* item_result) {
+ DCHECK_EQ(item.Type(), NGInlineItem::kText);
+
+ // If the start offset is at the item boundary, try to add the entire item.
+ if (offset_ == item.StartOffset()) {
+ item_result->inline_size = item.InlineSize();
+ LayoutUnit next_position = position_ + item_result->inline_size;
+ if (!auto_wrap_ || next_position <= available_width_) {
+ position_ = next_position;
+ MoveToNextOf(item);
+ if (auto_wrap_ && break_iterator_.IsBreakable(item.EndOffset()))
+ return LineBreakState::kIsBreakable;
+ item_result->prohibit_break_after = true;
+ return LineBreakState::kNotBreakable;
+ }
+ }
- // The entire item does not fit. Handle non-text items as overflow,
- // since only text item is breakable.
- if (item.Type() != NGInlineItem::kText) {
- MoveToNextOf(item);
- return HandleOverflow(item_results, break_iterator);
- }
+ if (auto_wrap_) {
+ // Try to break inside of this text item.
+ BreakText(item_result, item, available_width_ - position_);
+ position_ += item_result->inline_size;
+
+ bool is_overflow = position_ > available_width_;
+ item_result->no_break_opportunities_inside = is_overflow;
+ if (item_result->end_offset < item.EndOffset()) {
+ offset_ = item_result->end_offset;
+ return is_overflow ? LineBreakState::kIsBreakable
+ : LineBreakState::kBreakAfterTrailings;
}
+ MoveToNextOf(item);
+ return item_result->prohibit_break_after ? LineBreakState::kNotBreakable
+ : LineBreakState::kIsBreakable;
+ }
+
+ // Add the rest of the item if !auto_wrap.
+ // Because the start position may need to reshape, run ShapingLineBreaker
+ // with max available width.
+ DCHECK_NE(offset_, item.StartOffset());
+ BreakText(item_result, item, LayoutUnit::Max());
+ DCHECK_EQ(item_result->end_offset, item.EndOffset());
+ item_result->no_break_opportunities_inside = true;
+ item_result->prohibit_break_after = true;
+ position_ += item_result->inline_size;
+ MoveToNextOf(item);
+ return LineBreakState::kNotBreakable;
+}
+
+void NGLineBreaker::BreakText(NGInlineItemResult* item_result,
+ const NGInlineItem& item,
+ LayoutUnit available_width) {
+ DCHECK_EQ(item.Type(), NGInlineItem::kText);
+ item.AssertOffset(item_result->start_offset);
- // Either the start or the break is in the mid of a text item.
- DCHECK_EQ(item.Type(), NGInlineItem::kText);
- DCHECK_LT(offset_, item.EndOffset());
- break_iterator.SetLocale(item.Style()->LocaleForLineBreakIterator());
- break_iterator.SetBreakType(GetLineBreakType(*item.Style()));
#if defined(MOCK_SHAPE_LINE)
- unsigned break_offset;
- std::tie(break_offset, item_result->inline_size) = ShapeLineMock(
- item, offset_, available_width - position, break_iterator);
+ std::tie(item_result->end_offset, item_result->inline_size) = ShapeLineMock(
+ item, item_result->start_offset, available_width, break_iterator_);
#else
- // TODO(kojii): We need to instantiate ShapingLineBreaker here because it
- // has item-specific info as context. Should they be part of ShapeLine() to
- // instantiate once, or is this just fine since instatiation is not
- // expensive?
- DCHECK_EQ(item.TextShapeResult()->StartIndexForResult(),
- item.StartOffset());
- DCHECK_EQ(item.TextShapeResult()->EndIndexForResult(), item.EndOffset());
- ShapingLineBreaker breaker(&shaper, &item.Style()->GetFont(),
- item.TextShapeResult(), &break_iterator);
- unsigned break_offset;
- item_result->shape_result =
- breaker.ShapeLine(offset_, available_width - position, &break_offset);
- item_result->inline_size = item_result->shape_result->SnappedWidth();
+ // TODO(kojii): We need to instantiate ShapingLineBreaker here because it
+ // has item-specific info as context. Should they be part of ShapeLine() to
+ // instantiate once, or is this just fine since instatiation is not
+ // expensive?
+ DCHECK_EQ(item.TextShapeResult()->StartIndexForResult(), item.StartOffset());
+ DCHECK_EQ(item.TextShapeResult()->EndIndexForResult(), item.EndOffset());
+ ShapingLineBreaker breaker(&shaper, &item.Style()->GetFont(),
+ item.TextShapeResult(), break_iterator_);
+ item_result->shape_result = breaker.ShapeLine(
+ item_result->start_offset, available_width, &item_result->end_offset);
+ item_result->inline_size = item_result->shape_result->SnappedWidth();
#endif
- DCHECK_GT(break_offset, offset_);
- position += item_result->inline_size;
-
- // If the break found within the item, break here.
- if (break_offset < item.EndOffset()) {
- offset_ = item_result->end_offset = break_offset;
- if (position <= available_width)
- break;
- // The first break opportunity of the item does not fit.
- } else {
- // No break opporunity in the item, or the first break opportunity is at
- // the end of the item. If it fits, continue to the next item.
- item_result->end_offset = item.EndOffset();
- MoveToNextOf(item);
- if (position <= available_width)
- continue;
- }
-
- // We need to look at next item if we're overflowing, and the break
- // opportunity is beyond this item.
- if (break_offset > item.EndOffset())
- continue;
- return HandleOverflow(item_results, break_iterator);
+ DCHECK_GT(item_result->end_offset, item_result->start_offset);
+ // * If width <= available_width:
+ // * If offset < item.EndOffset(): the break opportunity to fit is found.
+ // * If offset == item.EndOffset(): the break opportunity at the end fits.
+ // There may be room for more characters.
+ // * If offset > item.EndOffset(): the first break opportunity is beyond
+ // the end. There may be room for more characters.
+ // * If width > available_width: The first break opporunity does not fit.
+ // offset is the first break opportunity, either inside, at the end, or
+ // beyond the end.
+ if (item_result->end_offset <= item.EndOffset()) {
+ item_result->prohibit_break_after = false;
+ } else {
+ item_result->prohibit_break_after = true;
+ item_result->end_offset = item.EndOffset();
}
}
// Measure control items; new lines and tab, that are similar to text, affect
// layout, but do not need shaping/painting.
-bool NGLineBreaker::HandleControlItem(const NGInlineItem& item,
- const String& text,
- NGInlineItemResult* item_result,
- LayoutUnit position) {
+NGLineBreaker::LineBreakState NGLineBreaker::HandleControlItem(
+ const NGInlineItem& item,
+ NGInlineItemResult* item_result) {
DCHECK_EQ(item.Length(), 1u);
- UChar character = text[item.StartOffset()];
- if (character == kNewlineCharacter)
- return true;
-
+ UChar character = node_->Text()[item.StartOffset()];
+ if (character == kNewlineCharacter) {
+ MoveToNextOf(item);
+ return LineBreakState::kForcedBreak;
+ }
DCHECK_EQ(character, kTabulationCharacter);
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
const Font& font = style.GetFont();
- item_result->inline_size = font.TabWidth(style.GetTabSize(), position);
- return false;
+ item_result->inline_size = font.TabWidth(style.GetTabSize(), position_);
+ position_ += item_result->inline_size;
+ MoveToNextOf(item);
+ // TODO(kojii): Implement break around the tab character.
+ return LineBreakState::kIsBreakable;
}
-void NGLineBreaker::LayoutAtomicInline(const NGInlineItem& item,
- NGInlineItemResult* item_result) {
+NGLineBreaker::LineBreakState NGLineBreaker::HandleAtomicInline(
+ const NGInlineItem& item,
+ NGInlineItemResult* item_result) {
DCHECK_EQ(item.Type(), NGInlineItem::kAtomicInline);
NGBlockNode* node = new NGBlockNode(item.GetLayoutObject());
const ComputedStyle& style = node->Style();
@@ -251,65 +270,158 @@ void NGLineBreaker::LayoutAtomicInline(const NGInlineItem& item,
ComputeMargins(*constraint_space_, style,
constraint_space_->WritingMode(), style.Direction());
item_result->inline_size += item_result->margins.InlineSum();
+
+ position_ += item_result->inline_size;
+ MoveToNextOf(item);
+ if (auto_wrap_)
+ return LineBreakState::kIsBreakable;
+ item_result->prohibit_break_after = true;
+ return LineBreakState::kNotBreakable;
+}
+
+void NGLineBreaker::HandleFloat(const NGInlineItem& item,
+ NGInlineItemResults* item_results,
+ NGInlineLayoutAlgorithm* algorithm) {
+ algorithm->LayoutAndPositionFloat(position_, item.GetLayoutObject());
+ // Floats may change the available width if they fit.
+ available_width_ = algorithm->AvailableWidth();
+ // Floats are already positioned in the container_builder.
+ item_results->pop_back();
+ MoveToNextOf(item);
+}
+
+void NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
+ NGInlineItemResult* item_result) {
+ if (item.HasStartEdge()) {
+ DCHECK(item.Style());
+ // TODO(kojii): We compute 16 values and discard 12 out of that, and do it 3
+ // times per element. We may want to cache this. crrev.com/2865903002/#msg14
+ NGBoxStrut margins = ComputeMargins(*constraint_space_, *item.Style(),
+ constraint_space_->WritingMode(),
+ constraint_space_->Direction());
+ NGBoxStrut borders = ComputeBorders(*constraint_space_, *item.Style());
+ NGBoxStrut paddings = ComputePadding(*constraint_space_, *item.Style());
+ item_result->inline_size =
+ margins.inline_start + borders.inline_start + paddings.inline_start;
+ position_ += item_result->inline_size;
+ }
+ UpdateBreakIterator(*item.Style());
+ MoveToNextOf(item);
+}
+
+void NGLineBreaker::HandleCloseTag(const NGInlineItem& item,
+ NGInlineItemResult* item_result) {
+ if (item.HasEndEdge()) {
+ DCHECK(item.Style());
+ NGBoxStrut margins = ComputeMargins(*constraint_space_, *item.Style(),
+ constraint_space_->WritingMode(),
+ constraint_space_->Direction());
+ NGBoxStrut borders = ComputeBorders(*constraint_space_, *item.Style());
+ NGBoxStrut paddings = ComputePadding(*constraint_space_, *item.Style());
+ item_result->inline_size =
+ margins.inline_end + borders.inline_end + paddings.inline_end;
+ position_ += item_result->inline_size;
+ }
+ DCHECK(item.GetLayoutObject() && item.GetLayoutObject()->Parent());
+ UpdateBreakIterator(item.GetLayoutObject()->Parent()->StyleRef());
+ MoveToNextOf(item);
}
// Handles when the last item overflows.
// At this point, item_results does not fit into the current line, and there
// are no break opportunities in item_results.back().
-void NGLineBreaker::HandleOverflow(
- NGInlineItemResults* item_results,
- const LazyLineBreakIterator& break_iterator) {
- DCHECK_GT(offset_, 0u);
-
- // Find the last break opportunity. If none, let this line overflow.
- unsigned line_start_offset = item_results->front().start_offset;
- unsigned break_offset =
- break_iterator.PreviousBreakOpportunity(offset_ - 1, line_start_offset);
- if (!break_offset || break_offset <= line_start_offset) {
- AppendCloseTags(item_results);
- return;
- }
-
- // Truncate the end of the line to the break opportunity.
+void NGLineBreaker::HandleOverflow(NGInlineItemResults* item_results) {
const Vector<NGInlineItem>& items = node_->Items();
- unsigned new_end = item_results->size();
- while (true) {
- NGInlineItemResult* item_result = &(*item_results)[--new_end];
- if (item_result->start_offset < break_offset) {
- // The break is at the mid of the item. Adjust the end_offset to the new
- // break offset.
- const NGInlineItem& item = items[item_result->item_index];
- item.AssertEndOffset(break_offset);
- DCHECK_EQ(item.Type(), NGInlineItem::kText);
- DCHECK_NE(item_result->end_offset, break_offset);
- item_result->end_offset = break_offset;
- item_result->inline_size =
- item.InlineSize(item_result->start_offset, item_result->end_offset);
- // TODO(kojii): May need to reshape. Add to ShapingLineBreaker?
- new_end++;
- break;
- }
- if (item_result->start_offset == break_offset) {
- // The new break offset is at the item boundary. Remove items up to the
- // new break offset.
- // TODO(kojii): Remove open tags as well.
- break;
+ LayoutUnit rewind_width = available_width_ - position_;
+ DCHECK_LT(rewind_width, 0);
+
+ // Search for a break opportunity that can fit.
+ // Also keep track of the first break opportunity in case of overflow.
+ unsigned break_before = 0;
+ unsigned break_before_if_before_allow = 0;
+ LayoutUnit rewind_width_if_before_allow;
+ bool last_item_prohibits_break_before = true;
+ for (unsigned i = item_results->size(); i;) {
+ NGInlineItemResult* item_result = &(*item_results)[--i];
+ const NGInlineItem& item = items[item_result->item_index];
+ rewind_width += item_result->inline_size;
+ if (item.Type() == NGInlineItem::kText ||
+ item.Type() == NGInlineItem::kAtomicInline) {
+ // Try to break inside of this item.
+ if (item.Type() == NGInlineItem::kText && rewind_width >= 0 &&
+ !item_result->no_break_opportunities_inside) {
+ // When the text fits but its right margin does not, the break point
+ // must not be at the end.
+ LayoutUnit item_available_width =
+ std::min(rewind_width, item_result->inline_size - 1);
+ BreakText(item_result, item, item_available_width);
+ if (item_result->inline_size <= item_available_width) {
+ DCHECK_LT(item_result->end_offset, item.EndOffset());
+ DCHECK(!item_result->prohibit_break_after);
+ return Rewind(item_results, i + 1);
+ }
+ if (!item_result->prohibit_break_after &&
+ !last_item_prohibits_break_before) {
+ break_before = i + 1;
+ }
+ }
+
+ // Try to break after this item.
+ if (break_before_if_before_allow && !item_result->prohibit_break_after) {
+ if (rewind_width_if_before_allow >= 0)
+ return Rewind(item_results, break_before_if_before_allow);
+ break_before = break_before_if_before_allow;
+ }
+
+ // Otherwise, before this item is a possible break point.
+ break_before_if_before_allow = i;
+ rewind_width_if_before_allow = rewind_width;
+ last_item_prohibits_break_before = false;
+ } else if (item.Type() == NGInlineItem::kCloseTag) {
+ last_item_prohibits_break_before = true;
+ } else {
+ if (i + 1 == break_before_if_before_allow) {
+ break_before_if_before_allow = i;
+ rewind_width_if_before_allow = rewind_width;
+ }
+ last_item_prohibits_break_before = false;
}
}
- DCHECK_GT(new_end, 0u);
+ // The rewind point did not found, let this line overflow.
+ // If there was a break opporunity, the overflow should stop there.
+ if (break_before)
+ Rewind(item_results, break_before);
+}
+
+void NGLineBreaker::Rewind(NGInlineItemResults* item_results,
+ unsigned new_end) {
// TODO(kojii): Should we keep results for the next line? We don't need to
// re-layout atomic inlines.
// TODO(kojii): Removing processed floats is likely a problematic. Keep
// floats in this line, or keep it for the next line.
item_results->Shrink(new_end);
- // Update the current item index and offset to the new break point.
- const NGInlineItemResult& last_item_result = item_results->back();
- offset_ = last_item_result.end_offset;
- item_index_ = last_item_result.item_index;
- if (items[item_index_].EndOffset() == offset_)
- item_index_++;
+ MoveToNextOf(item_results->back());
+}
+
+void NGLineBreaker::UpdateBreakIterator(const ComputedStyle& style) {
+ auto_wrap_ = style.AutoWrap();
+
+ if (auto_wrap_) {
+ break_iterator_.SetLocale(style.LocaleForLineBreakIterator());
+
+ if (style.WordBreak() == EWordBreak::kBreakAll ||
+ style.WordBreak() == EWordBreak::kBreakWord) {
+ break_iterator_.SetBreakType(LineBreakType::kBreakAll);
+ } else if (style.WordBreak() == EWordBreak::kKeepAll) {
+ break_iterator_.SetBreakType(LineBreakType::kKeepAll);
+ } else {
+ break_iterator_.SetBreakType(LineBreakType::kNormal);
+ }
+
+ // TODO(kojii): Implement word-wrap/overflow-wrap property
+ }
}
void NGLineBreaker::MoveToNextOf(const NGInlineItem& item) {
@@ -318,6 +430,14 @@ void NGLineBreaker::MoveToNextOf(const NGInlineItem& item) {
item_index_++;
}
+void NGLineBreaker::MoveToNextOf(const NGInlineItemResult& item_result) {
+ offset_ = item_result.end_offset;
+ item_index_ = item_result.item_index;
+ const NGInlineItem& item = node_->Items()[item_result.item_index];
+ if (offset_ == item.EndOffset())
+ item_index_++;
+}
+
void NGLineBreaker::SkipCollapsibleWhitespaces() {
const Vector<NGInlineItem>& items = node_->Items();
if (item_index_ >= items.size())
@@ -336,17 +456,6 @@ void NGLineBreaker::SkipCollapsibleWhitespaces() {
}
}
-void NGLineBreaker::AppendCloseTags(NGInlineItemResults* item_results) {
- const Vector<NGInlineItem>& items = node_->Items();
- for (; item_index_ < items.size(); item_index_++) {
- const NGInlineItem& item = items[item_index_];
- if (item.Type() != NGInlineItem::kCloseTag)
- break;
- DCHECK_EQ(offset_, item.EndOffset());
- item_results->push_back(NGInlineItemResult(item_index_, offset_, offset_));
- }
-}
-
RefPtr<NGInlineBreakToken> NGLineBreaker::CreateBreakToken() const {
const Vector<NGInlineItem>& items = node_->Items();
if (item_index_ >= items.size())

Powered by Google App Engine
This is Rietveld 408576698