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 ef44ef005f795955d0a7ba02f4a930578fdb4953..d464a038527e453fe395bcae591ee9444b65ff27 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 |
@@ -127,24 +127,26 @@ void NGLineBreaker::BreakLine(NGInlineItemResults* item_results, |
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(); |
- offset_ = item.EndOffset(); |
- item_index_++; |
+ MoveToNextOf(item); |
continue; |
} else { |
- offset_ = item.EndOffset(); |
- item_index_++; |
+ MoveToNextOf(item); |
continue; |
} |
LayoutUnit next_position = position + item_result->inline_size; |
if (next_position <= available_width) { |
- offset_ = item.EndOffset(); |
- item_index_++; |
+ MoveToNextOf(item); |
position = next_position; |
continue; |
} |
@@ -152,8 +154,7 @@ void NGLineBreaker::BreakLine(NGInlineItemResults* item_results, |
// The entire item does not fit. Handle non-text items as overflow, |
// since only text item is breakable. |
if (item.Type() != NGInlineItem::kText) { |
- offset_ = item.EndOffset(); |
- item_index_++; |
+ MoveToNextOf(item); |
return HandleOverflow(item_results, break_iterator); |
} |
} |
@@ -194,8 +195,8 @@ void NGLineBreaker::BreakLine(NGInlineItemResults* item_results, |
} 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. |
- offset_ = item_result->end_offset = item.EndOffset(); |
- item_index_++; |
+ item_result->end_offset = item.EndOffset(); |
+ MoveToNextOf(item); |
if (position <= available_width) |
continue; |
} |
@@ -208,6 +209,25 @@ void NGLineBreaker::BreakLine(NGInlineItemResults* item_results, |
} |
} |
+// 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) { |
+ DCHECK_EQ(item.Length(), 1u); |
+ UChar character = text[item.StartOffset()]; |
+ if (character == kNewlineCharacter) |
+ return true; |
+ |
+ 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; |
+} |
+ |
void NGLineBreaker::LayoutAtomicInline(const NGInlineItem& item, |
NGInlineItemResult* item_result) { |
DCHECK_EQ(item.Type(), NGInlineItem::kAtomicInline); |
@@ -292,6 +312,12 @@ void NGLineBreaker::HandleOverflow( |
item_index_++; |
} |
+void NGLineBreaker::MoveToNextOf(const NGInlineItem& item) { |
+ DCHECK_EQ(&item, &node_->Items()[item_index_]); |
+ offset_ = item.EndOffset(); |
+ item_index_++; |
+} |
+ |
void NGLineBreaker::SkipCollapsibleWhitespaces() { |
const Vector<NGInlineItem>& items = node_->Items(); |
if (item_index_ >= items.size()) |