0

[text-wrap-pretty] Add NGLineBreaker::OverrideAvailableWidth

When asking `NGLineBreaker` to layout within a specified
available width, instead of passing a artificially modified
`line_opportunity`, this patch adds `OverrideAvailableWidth`.

The `line_opportunity` has effects other than available width,
such as BFC offsets, floating objects, and when it's copied to
`NGLineInfo`, the line width to apply `text-align`. The last
one was fixed in crrev.com/c/4304620 by saving and restoring
the `line_opportunity`.

To make the intention clearer and allow `NGLineBreaker` to
behave differently in that situation, `OverrideAvailableWidth`
tells that callsites want to use different available width
than the `line_opportunity`, only for computing line wrapping
purposes.

Bug: 1432798
Change-Id: I610afa1722de1bb60e49d86abc36b53c64eb3dca
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4533817
Auto-Submit: Koji Ishii <kojii@chromium.org>
Reviewed-by: Kent Tamura <tkent@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1144578}
This commit is contained in:
Koji Ishii
2023-05-16 08:11:38 +00:00
committed by Chromium LUCI CQ
parent a6dc0beca2
commit fa2d839111
6 changed files with 35 additions and 45 deletions

@ -1321,7 +1321,6 @@ const NGLayoutResult* NGInlineLayoutAlgorithm::Layout() {
Node(), ConstraintSpace(), line_opportunity));
}
absl::optional<NGLineLayoutOpportunity> saved_line_opportunity;
bool is_line_info_cached = false;
NGLineInfo& line_info =
context_->GetLineInfo(break_token, is_line_info_cached);
@ -1330,17 +1329,14 @@ const NGLayoutResult* NGInlineLayoutAlgorithm::Layout() {
// `line_info` was cached.
line_info.SetBfcBlockOffset(line_opportunity.bfc_block_offset);
} else {
if (const absl::optional<LayoutUnit>& balanced_available_width =
context_->BalancedAvailableWidth()) {
saved_line_opportunity = line_opportunity;
NGParagraphLineBreaker::PrepareForNextLine(*balanced_available_width,
&line_opportunity);
}
NGLineBreaker line_breaker(
Node(), NGLineBreakerMode::kContent, ConstraintSpace(),
line_opportunity, leading_floats, handled_leading_floats_index,
break_token, column_spanner_path_, &ExclusionSpace());
if (const absl::optional<LayoutUnit>& balanced_available_width =
context_->BalancedAvailableWidth()) {
line_breaker.OverrideAvailableWidth(*balanced_available_width);
}
line_breaker.NextLine(&line_info);
}
@ -1425,12 +1421,6 @@ const NGLayoutResult* NGInlineLayoutAlgorithm::Layout() {
// to overflow in that case.
}
if (saved_line_opportunity) {
// Restore `line_opportunity` if `NGParagraphLineBreaker` updated it.
line_opportunity = *saved_line_opportunity;
line_info.SetAvailableWidth(line_opportunity.AvailableInlineSize());
}
PrepareBoxStates(line_info, break_token);
CreateLine(line_opportunity, &line_info, line_box);

@ -328,8 +328,13 @@ inline bool NGLineBreaker::ShouldAutoWrap(const ComputedStyle& style) const {
return style.ShouldWrapLine();
}
LayoutUnit NGLineBreaker::ComputeAvailableWidth() const {
LayoutUnit available_width = line_opportunity_.AvailableInlineSize();
void NGLineBreaker::UpdateAvailableWidth() {
LayoutUnit available_width;
if (UNLIKELY(override_available_width_)) {
available_width = override_available_width_;
} else {
available_width = line_opportunity_.AvailableInlineSize();
}
// Make sure it's at least the initial size, which is usually 0 but not so
// when `box-decoration-break: clone`.
available_width =
@ -337,7 +342,7 @@ LayoutUnit NGLineBreaker::ComputeAvailableWidth() const {
// Available width must be smaller than |LayoutUnit::Max()| so that the
// position can be larger.
available_width = std::min(available_width, LayoutUnit::NearlyMax());
return available_width;
available_width_ = available_width;
}
NGLineBreaker::NGLineBreaker(NGInlineNode node,
@ -377,7 +382,7 @@ NGLineBreaker::NGLineBreaker(NGInlineNode node,
leading_floats_(leading_floats),
handled_leading_floats_index_(handled_leading_floats_index),
base_direction_(node_.BaseDirection()) {
available_width_ = ComputeAvailableWidth();
UpdateAvailableWidth();
break_iterator_.SetBreakSpace(BreakSpaceType::kAfterSpaceRun);
if (is_svg_text_) {
const auto& char_data_list = node_.SvgCharacterDataList();
@ -421,6 +426,12 @@ NGLineBreaker::NGLineBreaker(NGInlineNode node,
NGLineBreaker::~NGLineBreaker() = default;
void NGLineBreaker::OverrideAvailableWidth(LayoutUnit available_width) {
DCHECK(available_width);
override_available_width_ = available_width;
UpdateAvailableWidth();
}
inline NGInlineItemResult* NGLineBreaker::AddItem(const NGInlineItem& item,
unsigned end_offset,
NGLineInfo* line_info) {
@ -545,7 +556,7 @@ void NGLineBreaker::RecalcClonedBoxDecorations() {
// accommodate cloned box decorations.
position_ += cloned_box_decorations_initial_size_;
// |cloned_box_decorations_initial_size_| may affect available width.
available_width_ = ComputeAvailableWidth();
UpdateAvailableWidth();
DCHECK_GE(available_width_, cloned_box_decorations_initial_size_);
}
@ -721,6 +732,12 @@ void NGLineBreaker::NextLine(NGLineInfo* line_info) {
if (trailing_whitespace_ == WhitespaceState::kPreserved)
line_info->SetHasTrailingSpaces();
if (UNLIKELY(override_available_width_)) {
// Clear the overridden available width so that `line_info` has the original
// available width for aligning.
override_available_width_ = LayoutUnit();
UpdateAvailableWidth();
}
ComputeLineLocation(line_info);
if (mode_ == NGLineBreakerMode::kContent) {
line_info->SetBreakToken(CreateBreakToken(*line_info));
@ -2701,7 +2718,7 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
line_opportunity_ = opportunity.ComputeLineLayoutOpportunity(
constraint_space_, line_opportunity_.line_block_size, LayoutUnit());
available_width_ = ComputeAvailableWidth();
UpdateAvailableWidth();
DCHECK_GE(AvailableWidth(), LayoutUnit());
}

@ -61,6 +61,10 @@ class CORE_EXPORT NGLineBreaker {
bool IsFinished() const { return current_.item_index >= Items().size(); }
// Override the available width to compute line breaks. This is reset after
// each `NextLine`.
void OverrideAvailableWidth(LayoutUnit available_width);
// Computing |NGLineBreakerMode::kMinContent| with |MaxSizeCache| caches
// information that can help computing |kMaxContent|. It is recommended to set
// this when computing both |kMinContent| and |kMaxContent|.
@ -216,10 +220,7 @@ class CORE_EXPORT NGLineBreaker {
void ComputeBaseDirection();
void RecalcClonedBoxDecorations();
LayoutUnit AvailableWidth() const {
DCHECK_EQ(available_width_, ComputeAvailableWidth());
return available_width_;
}
LayoutUnit AvailableWidth() const { return available_width_; }
LayoutUnit AvailableWidthToFit() const {
return AvailableWidth().AddEpsilon();
}
@ -227,7 +228,7 @@ class CORE_EXPORT NGLineBreaker {
return AvailableWidthToFit() - position_;
}
bool CanFitOnLine() const { return position_ <= AvailableWidthToFit(); }
LayoutUnit ComputeAvailableWidth() const;
void UpdateAvailableWidth();
// True if the current line is hyphenated.
bool HasHyphen() const { return hyphen_index_.has_value(); }
@ -349,6 +350,8 @@ class CORE_EXPORT NGLineBreaker {
};
absl::optional<TrailingCollapsibleSpace> trailing_collapsible_space_;
LayoutUnit override_available_width_;
// Keep track of handled float items. See HandleFloat().
const NGPositionedFloatVector& leading_floats_;
unsigned leading_floats_index_ = 0u;

@ -150,9 +150,6 @@ class CORE_EXPORT NGLineInfo {
void SetBfcBlockOffset(LayoutUnit block_offset) {
bfc_offset_.block_offset = block_offset;
}
void SetAvailableWidth(LayoutUnit available_width) {
available_width_ = available_width;
}
void SetWidth(LayoutUnit available_width, LayoutUnit width) {
available_width_ = available_width;
width_ = width;

@ -227,18 +227,4 @@ NGParagraphLineBreaker::AttemptParagraphBalancingCore(
normal_lines.BreakToken());
}
// static
void NGParagraphLineBreaker::PrepareForNextLine(
LayoutUnit balanced_available_width,
NGLineLayoutOpportunity* line_opportunity) {
DCHECK_GE(line_opportunity->line_right_offset,
line_opportunity->line_left_offset);
DCHECK_EQ(line_opportunity->line_left_offset,
line_opportunity->float_line_left_offset);
DCHECK_EQ(line_opportunity->line_right_offset,
line_opportunity->float_line_right_offset);
line_opportunity->line_right_offset =
line_opportunity->line_left_offset + balanced_available_width;
}
} // namespace blink

@ -23,9 +23,6 @@ class CORE_EXPORT NGParagraphLineBreaker {
const NGConstraintSpace& space,
const NGLineLayoutOpportunity& line_opportunity);
static void PrepareForNextLine(LayoutUnit balanced_available_width,
NGLineLayoutOpportunity* line_opportunity);
private:
static absl::optional<LayoutUnit> AttemptParagraphBalancingCore(
const NGInlineNode& node,