Commit 08f33075 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[LayoutNG] Fix NGInlineNode::ComputeMinMaxSize when hyphenated

This patch changes NGInlineNode::ComputeMinMaxSize to use
NGLineInfo::Width() instead of accumulating the list of
NGInlineItemResult.

This fixes min-/max-content size to include the width of
hyphens.

During the fix, an uninitialized variable was found when
NGLineInfo was re-used across different NextLine(). Re-using
NGLineInfo isn't much gain, this was prohibited to avoid rare
code path. Also a few DCHECK were added to ensure accumulated
with is in sync.

A test for min-content of hyphened line was added. There are
two tests, but both use table to compute it, and that they
may fail to test if table sizing is broken. The new test uses
'min-content' directly.

Bug: 636993
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng
Change-Id: Ibc7a3a2dcbf6a70a06bc974eb69dd47b23ad72fe
Reviewed-on: https://chromium-review.googlesource.com/1111895
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarChristian Biesinger <cbiesinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569954}
parent 65c91617
<!DOCTYPE html>
<style>
div {
width: min-content;
border: 5px blue solid;
}
</style>
<div>0123-<br>45</div>
<!DOCTYPE html>
<style>
div {
width: min-content;
border: 5px blue solid;
}
</style>
<div>0123&shy;45</div>
......@@ -61,6 +61,20 @@ void NGInlineItemResult::CheckConsistency(bool during_line_break) const {
}
#endif
LayoutUnit NGLineInfo::ComputeWidth() const {
LayoutUnit inline_size = TextIndent();
for (const NGInlineItemResult& item_result : Results())
inline_size += item_result.inline_size;
if (UNLIKELY(line_end_fragment_)) {
inline_size += line_end_fragment_->Size()
.ConvertToLogical(LineStyle().GetWritingMode())
.inline_size;
}
return inline_size;
}
void NGLineInfo::SetLineBfcOffset(NGBfcOffset line_bfc_offset,
LayoutUnit available_width,
LayoutUnit width) {
......
......@@ -105,9 +105,6 @@ class CORE_EXPORT NGLineInfo {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
public:
NGLineInfo() = default;
explicit NGLineInfo(size_t capacity) : results_(capacity) {}
const NGInlineItemsData& ItemsData() const {
DCHECK(items_data_);
return *items_data_;
......@@ -152,6 +149,7 @@ class CORE_EXPORT NGLineInfo {
NGBfcOffset LineBfcOffset() const { return line_bfc_offset_; }
LayoutUnit AvailableWidth() const { return available_width_; }
LayoutUnit Width() const { return width_; }
LayoutUnit ComputeWidth() const;
void SetLineBfcOffset(NGBfcOffset line_bfc_offset,
LayoutUnit available_width,
LayoutUnit width);
......
......@@ -670,7 +670,6 @@ static LayoutUnit ComputeContentSize(NGInlineNode node,
Vector<scoped_refptr<NGUnpositionedFloat>> unpositioned_floats;
scoped_refptr<NGInlineBreakToken> break_token;
NGLineInfo line_info;
NGExclusionSpace empty_exclusion_space;
NGLineLayoutOpportunity line_opportunity(available_inline_size);
LayoutUnit result;
......@@ -683,13 +682,13 @@ static LayoutUnit ComputeContentSize(NGInlineNode node,
&unpositioned_floats,
nullptr /* container_builder */,
&empty_exclusion_space, 0u, break_token.get());
NGLineInfo line_info;
if (!line_breaker.NextLine(line_opportunity, &line_info))
break;
break_token = line_breaker.CreateBreakToken(line_info, nullptr);
LayoutUnit inline_size = line_info.TextIndent();
for (const NGInlineItemResult& item_result : line_info.Results())
inline_size += item_result.inline_size;
LayoutUnit inline_size = line_info.Width();
DCHECK_EQ(inline_size, line_info.ComputeWidth().ClampNegativeToZero());
// There should be no positioned floats while determining the min/max sizes.
DCHECK_EQ(positioned_floats.size(), 0u);
......
......@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/core/layout/layout_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
......@@ -161,8 +162,10 @@ void NGLineBreaker::ComputeBaseDirection(const NGLineInfo& line_info) {
void NGLineBreaker::PrepareNextLine(
const NGLineLayoutOpportunity& line_opportunity,
NGLineInfo* line_info) {
NGInlineItemResults* item_results = &line_info->Results();
item_results->clear();
// NGLineInfo is not supposed to be re-used becase it's not much gain and to
// avoid rare code path.
DCHECK(line_info->Results().IsEmpty());
line_info->SetStartOffset(offset_);
line_info->SetLineStyle(
node_, items_data_, constraint_space_, line_.is_first_formatted_line,
......@@ -291,19 +294,20 @@ void NGLineBreaker::BreakLine(NGLineInfo* line_info) {
}
}
// Re-compute the current position from NGInlineItemResults.
// Re-compute the current position from NGLineInfo.
// The current position is usually updated as NGLineBreaker builds
// NGInlineItemResults. This function re-computes it when it was lost.
void NGLineBreaker::UpdatePosition(const NGInlineItemResults& results) {
LayoutUnit position;
for (const NGInlineItemResult& item_result : results)
position += item_result.inline_size;
line_.position = position;
void NGLineBreaker::UpdatePosition(const NGLineInfo& line_info) {
line_.position = line_info.ComputeWidth();
}
void NGLineBreaker::ComputeLineLocation(NGLineInfo* line_info) const {
LayoutUnit bfc_line_offset = line_.line_opportunity.line_left_offset;
LayoutUnit available_width = line_.AvailableWidth();
// TODO(kojii): IsBeforeAfterNonCollapsedLineWrapSpace fails only on Mac
#if !defined(OS_MACOSX)
DCHECK_EQ(line_.position, line_info->ComputeWidth());
#endif
// Negative margins can make the position negative, but the inline size is
// always positive or 0.
......@@ -971,11 +975,7 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleOverflow(
available_width + next_width_to_rewind + item_result->inline_size;
if (line_info->LineEndFragment())
SetLineEndFragment(nullptr, line_info);
#if DCHECK_IS_ON()
LayoutUnit position_fast = line_.position;
UpdatePosition(line_info->Results());
DCHECK_EQ(line_.position, position_fast);
#endif
DCHECK_EQ(line_.position, line_info->ComputeWidth());
item_index_ = item_result->item_index;
offset_ = item_result->end_offset;
items_data_.AssertOffset(item_index_, offset_);
......@@ -1030,7 +1030,7 @@ void NGLineBreaker::Rewind(NGLineInfo* line_info, unsigned new_end) {
item_results->Shrink(new_end);
SetLineEndFragment(nullptr, line_info);
UpdatePosition(line_info->Results());
UpdatePosition(*line_info);
}
// Returns the LayoutObject at the current index/offset.
......
......@@ -117,7 +117,7 @@ class CORE_EXPORT NGLineBreaker {
void PrepareNextLine(const NGLineLayoutOpportunity&, NGLineInfo*);
void UpdatePosition(const NGInlineItemResults&);
void UpdatePosition(const NGLineInfo&);
void ComputeLineLocation(NGLineInfo*) const;
enum class LineBreakState {
......
......@@ -48,12 +48,12 @@ class NGLineBreakerTest : public NGBaseLayoutAlgorithmTest {
Vector<NGInlineItemResults> lines;
NGExclusionSpace exclusion_space;
NGLineLayoutOpportunity line_opportunity(available_width);
NGLineInfo line_info;
while (!break_token || !break_token->IsFinished()) {
NGLineBreaker line_breaker(node, NGLineBreakerMode::kContent, *space,
&positioned_floats, &unpositioned_floats,
/* container_builder */ nullptr,
&exclusion_space, 0u, break_token.get());
NGLineInfo line_info;
if (!line_breaker.NextLine(line_opportunity, &line_info))
break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment