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

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

Issue 2931363002: [LayoutNG] More precise checks for empty inline and add test (Closed)
Patch Set: ikilpatrick review Created 3 years, 6 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
« no previous file with comments | « third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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();
« no previous file with comments | « third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698