| 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 57e63b8c70237352fe1f0e45d7c41050a90e010c..6696cd7080cc2c835850f06134ffa1822b108523 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
|
| @@ -77,7 +77,8 @@ NGLineBreaker::NGLineBreaker(NGInlineNode node,
|
|
|
| bool NGLineBreaker::NextLine(NGLineInfo* line_info,
|
| const NGLogicalOffset& content_offset) {
|
| - BreakLine(line_info, content_offset);
|
| + content_offset_ = content_offset;
|
| + BreakLine(line_info);
|
|
|
| // TODO(kojii): When editing, or caret is enabled, trailing spaces at wrap
|
| // point should not be removed. For other cases, we can a) remove, b) leave
|
| @@ -88,21 +89,22 @@ bool NGLineBreaker::NextLine(NGLineInfo* line_info,
|
| return !line_info->Results().IsEmpty();
|
| }
|
|
|
| -void NGLineBreaker::BreakLine(NGLineInfo* line_info,
|
| - const NGLogicalOffset& content_offset) {
|
| +void NGLineBreaker::BreakLine(NGLineInfo* line_info) {
|
| NGInlineItemResults* item_results = &line_info->Results();
|
| item_results->clear();
|
| const Vector<NGInlineItem>& items = node_.Items();
|
| line_info->SetLineStyle(node_, !item_index_ && !offset_);
|
| SetCurrentStyle(line_info->LineStyle());
|
| position_ = LayoutUnit(0);
|
| + should_create_line_box_ = false;
|
| LineBreakState state = LineBreakState::kNotBreakable;
|
|
|
| // We are only able to calculate our available_width if our container has
|
| // been positioned in the BFC coordinate space yet.
|
| - WTF::Optional<LayoutUnit> available_width;
|
| if (container_builder_->BfcOffset())
|
| - available_width = ComputeAvailableWidth(content_offset);
|
| + UpdateAvailableWidth();
|
| + else
|
| + available_width_.reset();
|
|
|
| while (item_index_ < items.size()) {
|
| // CloseTag prohibits to break before.
|
| @@ -118,32 +120,15 @@ void NGLineBreaker::BreakLine(NGLineInfo* line_info,
|
| line_info->SetIsLastLine(false);
|
| return;
|
| }
|
| - if (state == LineBreakState::kIsBreakable && available_width &&
|
| - position_ > available_width.value())
|
| - return HandleOverflow(available_width.value(), line_info);
|
| -
|
| - // We resolve the BFC-offset of the container if this line has an item with
|
| - // inline-size. Floats, and tags do not allow us to resolve the BFC-offset.
|
| - //
|
| - // If this line just has a float we place it in the unpositioned float list
|
| - // which will be positioned later.
|
| - bool should_resolve_bfc_offset =
|
| - !container_builder_->BfcOffset() &&
|
| - (item.Type() == NGInlineItem::kText ||
|
| - item.Type() == NGInlineItem::kAtomicInline ||
|
| - item.Type() == NGInlineItem::kControl);
|
| -
|
| - if (should_resolve_bfc_offset) {
|
| - ResolveBFCOffset();
|
| - available_width = ComputeAvailableWidth(content_offset);
|
| - }
|
| + if (state == LineBreakState::kIsBreakable && HasAvailableWidth() &&
|
| + position_ > AvailableWidth())
|
| + return HandleOverflow(line_info);
|
|
|
| item_results->push_back(
|
| NGInlineItemResult(item_index_, offset_, item.EndOffset()));
|
| NGInlineItemResult* item_result = &item_results->back();
|
| if (item.Type() == NGInlineItem::kText) {
|
| - DCHECK(available_width);
|
| - state = HandleText(item, available_width.value(), item_result);
|
| + state = HandleText(item, item_result);
|
| } else if (item.Type() == NGInlineItem::kAtomicInline) {
|
| state = HandleAtomicInline(item, item_result);
|
| } else if (item.Type() == NGInlineItem::kControl) {
|
| @@ -156,47 +141,38 @@ void NGLineBreaker::BreakLine(NGLineInfo* line_info,
|
| HandleOpenTag(item, item_result);
|
| state = LineBreakState::kNotBreakable;
|
| } else if (item.Type() == NGInlineItem::kFloating) {
|
| - HandleFloat(item, content_offset, &available_width, item_results);
|
| + HandleFloat(item, item_results);
|
| } else {
|
| MoveToNextOf(item);
|
| }
|
| }
|
| - if (state == LineBreakState::kIsBreakable && available_width &&
|
| - position_ > available_width.value())
|
| - return HandleOverflow(available_width.value(), line_info);
|
| + if (state == LineBreakState::kIsBreakable && HasAvailableWidth() &&
|
| + position_ > AvailableWidth())
|
| + return HandleOverflow(line_info);
|
| line_info->SetIsLastLine(true);
|
| }
|
|
|
| -// Resolves the BFC offset for the container, and positions any pending floats.
|
| -void NGLineBreaker::ResolveBFCOffset() {
|
| - LayoutUnit container_bfc_block_offset =
|
| - constraint_space_->BfcOffset().block_offset +
|
| - constraint_space_->MarginStrut().Sum();
|
| - MaybeUpdateFragmentBfcOffset(*constraint_space_, container_bfc_block_offset,
|
| - container_builder_);
|
| - PositionPendingFloats(container_bfc_block_offset, container_builder_,
|
| - constraint_space_);
|
| -}
|
| -
|
| -// Returns the inline size of the first layout opportunity from the given
|
| +// Update the inline size of the first layout opportunity from the given
|
| // content_offset.
|
| -LayoutUnit NGLineBreaker::ComputeAvailableWidth(
|
| - const NGLogicalOffset& content_offset) const {
|
| +void NGLineBreaker::UpdateAvailableWidth() {
|
| NGLogicalOffset offset = container_builder_->BfcOffset().value();
|
| - offset += content_offset;
|
| + offset += content_offset_;
|
|
|
| NGLayoutOpportunityIterator iter(constraint_space_->Exclusions().get(),
|
| constraint_space_->AvailableSize(), offset);
|
| NGLayoutOpportunity opportunity = iter.Next();
|
| - return opportunity.InlineSize();
|
| -};
|
| + available_width_ = opportunity.InlineSize();
|
| +}
|
|
|
| NGLineBreaker::LineBreakState NGLineBreaker::HandleText(
|
| const NGInlineItem& item,
|
| - LayoutUnit available_width,
|
| NGInlineItemResult* item_result) {
|
| DCHECK_EQ(item.Type(), NGInlineItem::kText);
|
|
|
| + if (!should_create_line_box_)
|
| + SetShouldCreateLineBox();
|
| + LayoutUnit available_width = AvailableWidth();
|
| +
|
| // 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();
|
| @@ -289,6 +265,10 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleControlItem(
|
| const NGInlineItem& item,
|
| NGInlineItemResult* item_result) {
|
| DCHECK_EQ(item.Length(), 1u);
|
| +
|
| + if (!should_create_line_box_)
|
| + SetShouldCreateLineBox();
|
| +
|
| UChar character = node_.Text()[item.StartOffset()];
|
| if (character == kNewlineCharacter) {
|
| MoveToNextOf(item);
|
| @@ -309,6 +289,10 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleAtomicInline(
|
| const NGInlineItem& item,
|
| NGInlineItemResult* item_result) {
|
| DCHECK_EQ(item.Type(), NGInlineItem::kAtomicInline);
|
| +
|
| + if (!should_create_line_box_)
|
| + SetShouldCreateLineBox();
|
| +
|
| NGBlockNode node = NGBlockNode(ToLayoutBox(item.GetLayoutObject()));
|
| const ComputedStyle& style = node.Style();
|
| NGConstraintSpaceBuilder constraint_space_builder(constraint_space_);
|
| @@ -355,8 +339,6 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleAtomicInline(
|
| //
|
| // TODO(glebl): Add the support of clearance for inline floats.
|
| void NGLineBreaker::HandleFloat(const NGInlineItem& item,
|
| - const NGLogicalOffset& content_offset,
|
| - WTF::Optional<LayoutUnit>* available_width,
|
| NGInlineItemResults* item_results) {
|
| NGBlockNode node(ToLayoutBox(item.GetLayoutObject()));
|
|
|
| @@ -380,8 +362,8 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
|
| // I.e. we may not have come across any text yet, in order to be able to
|
| // resolve the BFC position.
|
| bool float_does_not_fit =
|
| - !available_width->has_value() ||
|
| - position_ + inline_size + margins.InlineSum() > available_width->value();
|
| + !HasAvailableWidth() ||
|
| + position_ + inline_size + margins.InlineSum() > AvailableWidth();
|
|
|
| // Check if we already have a pending float. That's because a float cannot be
|
| // higher than any block or floated box generated before.
|
| @@ -391,7 +373,7 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
|
| } else {
|
| NGLogicalOffset container_bfc_offset =
|
| container_builder_->BfcOffset().value();
|
| - unpositioned_float->origin_offset = container_bfc_offset + content_offset;
|
| + unpositioned_float->origin_offset = container_bfc_offset + content_offset_;
|
| unpositioned_float->from_offset.block_offset =
|
| container_bfc_offset.block_offset;
|
| unpositioned_float->parent_bfc_block_offset =
|
| @@ -402,7 +384,7 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
|
|
|
| // We need to recalculate the available_width as the float probably
|
| // consumed space on the line.
|
| - *available_width = ComputeAvailableWidth(content_offset);
|
| + UpdateAvailableWidth();
|
| }
|
|
|
| // Floats are already positioned in the container_builder.
|
| @@ -414,6 +396,7 @@ void NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
|
| NGInlineItemResult* item_result) {
|
| DCHECK(item.Style());
|
| const ComputedStyle& style = *item.Style();
|
| + item_result->needs_box_when_empty = false;
|
| if (style.HasBorder() || style.HasPadding() ||
|
| (style.HasMargin() && item.HasStartEdge())) {
|
| NGBoxStrut borders = ComputeBorders(*constraint_space_, style);
|
| @@ -429,6 +412,11 @@ void NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
|
| item_result->inline_size = item_result->margins.inline_start +
|
| borders.inline_start + paddings.inline_start;
|
| position_ += item_result->inline_size;
|
| +
|
| + item_result->needs_box_when_empty =
|
| + item_result->inline_size || item_result->margins.inline_start;
|
| + if (item_result->needs_box_when_empty && !should_create_line_box_)
|
| + SetShouldCreateLineBox();
|
| }
|
| }
|
| SetCurrentStyle(style);
|
| @@ -437,16 +425,23 @@ void NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
|
|
|
| void NGLineBreaker::HandleCloseTag(const NGInlineItem& item,
|
| NGInlineItemResult* item_result) {
|
| + item_result->needs_box_when_empty = false;
|
| if (item.HasEndEdge()) {
|
| DCHECK(item.Style());
|
| - item_result->margins = ComputeMargins(*constraint_space_, *item.Style(),
|
| + const ComputedStyle& style = *item.Style();
|
| + item_result->margins = ComputeMargins(*constraint_space_, style,
|
| constraint_space_->WritingMode(),
|
| constraint_space_->Direction());
|
| - NGBoxStrut borders = ComputeBorders(*constraint_space_, *item.Style());
|
| - NGBoxStrut paddings = ComputePadding(*constraint_space_, *item.Style());
|
| + NGBoxStrut borders = ComputeBorders(*constraint_space_, style);
|
| + NGBoxStrut paddings = ComputePadding(*constraint_space_, style);
|
| item_result->inline_size = item_result->margins.inline_end +
|
| borders.inline_end + paddings.inline_end;
|
| position_ += item_result->inline_size;
|
| +
|
| + item_result->needs_box_when_empty =
|
| + item_result->inline_size || item_result->margins.inline_end;
|
| + if (item_result->needs_box_when_empty && !should_create_line_box_)
|
| + SetShouldCreateLineBox();
|
| }
|
| DCHECK(item.GetLayoutObject() && item.GetLayoutObject()->Parent());
|
| SetCurrentStyle(item.GetLayoutObject()->Parent()->StyleRef());
|
| @@ -456,10 +451,10 @@ void NGLineBreaker::HandleCloseTag(const NGInlineItem& 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(LayoutUnit available_width,
|
| - NGLineInfo* line_info) {
|
| +void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
|
| NGInlineItemResults* item_results = &line_info->Results();
|
| const Vector<NGInlineItem>& items = node_.Items();
|
| + LayoutUnit available_width = AvailableWidth();
|
| LayoutUnit rewind_width = available_width - position_;
|
| DCHECK_LT(rewind_width, 0);
|
|
|
| @@ -537,6 +532,28 @@ void NGLineBreaker::Rewind(NGLineInfo* line_info, unsigned new_end) {
|
| line_info->SetIsLastLine(false);
|
| }
|
|
|
| +void NGLineBreaker::SetShouldCreateLineBox() {
|
| + DCHECK(!should_create_line_box_);
|
| + should_create_line_box_ = true;
|
| +
|
| + // We resolve the BFC-offset of the container if this line has a line box.
|
| + // A line box prevents collapsing margins between boxes before and after,
|
| + // but not all lines create line boxes.
|
| + //
|
| + // If this line just has a float we place it in the unpositioned float list
|
| + // which will be positioned later.
|
| + if (!container_builder_->BfcOffset()) {
|
| + LayoutUnit container_bfc_block_offset =
|
| + constraint_space_->BfcOffset().block_offset +
|
| + constraint_space_->MarginStrut().Sum();
|
| + MaybeUpdateFragmentBfcOffset(*constraint_space_, container_bfc_block_offset,
|
| + container_builder_);
|
| + PositionPendingFloats(container_bfc_block_offset, container_builder_,
|
| + constraint_space_);
|
| + UpdateAvailableWidth();
|
| + }
|
| +}
|
| +
|
| void NGLineBreaker::SetCurrentStyle(const ComputedStyle& style) {
|
| auto_wrap_ = style.AutoWrap();
|
|
|
|
|