Commit 2c7e0331 authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

RubyNG: Implement default text-align behavior of RubyBase and RubyText

This CL ports TextAlignmentForLine() and
AdjustInlineDirectionLineBounds() of LayoutRubyBase and LayoutRubyText
to LayoutNG.

This CL doesn't affect production because new behavior is behind a
disabled runtime flag.

Bug: 1069817
Change-Id: I5e09f0a46ff505f15daccea11f13c66444dc9876
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2214589
Commit-Queue: Kent Tamura <tkent@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771710}
parent 71f5c719
......@@ -33,16 +33,31 @@ void NGLineInfo::SetLineStyle(const NGInlineNode& node,
bool use_first_line_style) {
use_first_line_style_ = use_first_line_style;
items_data_ = &items_data;
line_style_ = node.GetLayoutBox()->Style(use_first_line_style_);
const LayoutBox* box = node.GetLayoutBox();
line_style_ = box->Style(use_first_line_style_);
needs_accurate_end_position_ = ComputeNeedsAccurateEndPosition();
is_ruby_base_ = box->IsRubyBase();
is_ruby_text_ = box->IsRubyText();
}
ETextAlign NGLineInfo::GetTextAlign(bool is_last_line) const {
// See LayoutRubyBase::TextAlignmentForLine().
if (is_ruby_base_)
return ETextAlign::kJustify;
// See LayoutRubyText::TextAlignmentForLine().
if (is_ruby_text_ && LineStyle().GetTextAlign() ==
ComputedStyleInitialValues::InitialTextAlign())
return ETextAlign::kJustify;
return LineStyle().GetTextAlign(is_last_line);
}
bool NGLineInfo::ComputeNeedsAccurateEndPosition() const {
// Some 'text-align' values need accurate end position. At this point, we
// don't know if this is the last line or not, and thus we don't know whether
// 'text-align' is used or 'text-align-last' is used.
const ComputedStyle& line_style = LineStyle();
switch (line_style.GetTextAlign()) {
switch (GetTextAlign()) {
case ETextAlign::kStart:
break;
case ETextAlign::kEnd:
......@@ -61,7 +76,16 @@ bool NGLineInfo::ComputeNeedsAccurateEndPosition() const {
return true;
break;
}
switch (line_style.TextAlignLast()) {
ETextAlignLast align_last = LineStyle().TextAlignLast();
if (is_ruby_base_) {
// See LayoutRubyBase::TextAlignmentForLine().
align_last = ETextAlignLast::kJustify;
} else if (is_ruby_text_ &&
align_last == ComputedStyleInitialValues::InitialTextAlignLast()) {
// See LayoutRubyText::TextAlignmentForLine().
align_last = ETextAlignLast::kJustify;
}
switch (align_last) {
case ETextAlignLast::kStart:
case ETextAlignLast::kAuto:
return false;
......@@ -133,7 +157,7 @@ bool NGLineInfo::ShouldHangTrailingSpaces() const {
}
void NGLineInfo::UpdateTextAlign() {
text_align_ = line_style_->GetTextAlign(IsLastLine());
text_align_ = GetTextAlign(IsLastLine());
if (HasTrailingSpaces() && ShouldHangTrailingSpaces()) {
hang_width_ = ComputeTrailingSpaceWidth(&end_offset_for_justify_);
......
......@@ -253,6 +253,7 @@ class CORE_EXPORT NGLineInfo {
bool NeedsAccurateEndPosition() const { return needs_accurate_end_position_; }
private:
ETextAlign GetTextAlign(bool is_last_line = false) const;
bool ComputeNeedsAccurateEndPosition() const;
// The width of preserved trailing spaces.
......@@ -283,6 +284,8 @@ class CORE_EXPORT NGLineInfo {
bool has_overflow_ = false;
bool has_trailing_spaces_ = false;
bool needs_accurate_end_position_ = false;
bool is_ruby_base_ = false;
bool is_ruby_text_ = false;
};
} // namespace blink
......
......@@ -702,22 +702,23 @@ void NGInlineLayoutAlgorithm::PlaceListMarker(const NGInlineItem& item,
// Justify the line. This changes the size of items by adding spacing.
// Returns false if justification failed and should fall back to start-aligned.
bool NGInlineLayoutAlgorithm::ApplyJustify(LayoutUnit space,
NGLineInfo* line_info) {
base::Optional<LayoutUnit> NGInlineLayoutAlgorithm::ApplyJustify(
LayoutUnit space,
NGLineInfo* line_info) {
// Empty lines should align to start.
if (line_info->IsEmptyLine())
return false;
return base::nullopt;
// Justify the end of visible text, ignoring preserved trailing spaces.
unsigned end_offset = line_info->EndOffsetForJustify();
// If this line overflows, fallback to 'text-align: start'.
if (space <= 0)
return false;
return base::nullopt;
// Can't justify an empty string.
if (end_offset == line_info->StartOffset())
return false;
return base::nullopt;
// Construct the line text to compute spacing for.
StringBuilder line_text_builder;
......@@ -740,8 +741,24 @@ bool NGInlineLayoutAlgorithm::ApplyJustify(LayoutUnit space,
ShapeResultSpacing<String> spacing(line_text);
spacing.SetExpansion(space, line_info->BaseDirection(),
line_info->LineStyle().GetTextJustify());
if (!spacing.HasExpansion())
return false; // no expansion opportunities exist.
const LayoutObject* box = Node().GetLayoutBox();
if (!spacing.HasExpansion()) {
// See AdjustInlineDirectionLineBounds() of LayoutRubyBase and
// LayoutRubyText.
if (box && (box->IsRubyText() || box->IsRubyBase()))
return space / 2;
return base::nullopt;
}
LayoutUnit inset;
// See AdjustInlineDirectionLineBounds() of LayoutRubyBase and
// LayoutRubyText.
if (box && (box->IsRubyText() || box->IsRubyBase())) {
inset = space / (spacing.ExpansionOppotunityCount() + 1);
inset = std::min(LayoutUnit(2 * line_info->LineStyle().FontSize()), inset);
spacing.SetExpansion(space - inset, line_info->BaseDirection(),
line_info->LineStyle().GetTextJustify());
}
for (NGInlineItemResult& item_result : *line_info->MutableResults()) {
if (item_result.has_only_trailing_spaces)
......@@ -771,7 +788,7 @@ bool NGInlineLayoutAlgorithm::ApplyJustify(LayoutUnit space,
DCHECK_EQ(offset, 0.f);
}
}
return true;
return inset / 2;
}
// Apply the 'text-align' property to |line_info|. Returns the amount to move
......@@ -785,10 +802,9 @@ LayoutUnit NGInlineLayoutAlgorithm::ApplyTextAlign(NGLineInfo* line_info) {
ETextAlign text_align = line_info->TextAlign();
if (text_align == ETextAlign::kJustify) {
// If justification succeeds, no offset is needed. Expansions are set to
// each |NGInlineItemResult| in |line_info|.
if (ApplyJustify(space, line_info))
return LayoutUnit();
base::Optional<LayoutUnit> offset = ApplyJustify(space, line_info);
if (offset)
return *offset;
// If justification fails, fallback to 'text-align: start'.
text_align = ETextAlign::kStart;
......
......@@ -105,7 +105,7 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
const NGLineInfo&);
LayoutUnit ApplyTextAlign(NGLineInfo*);
bool ApplyJustify(LayoutUnit space, NGLineInfo*);
base::Optional<LayoutUnit> ApplyJustify(LayoutUnit space, NGLineInfo*);
LayoutUnit ComputeContentSize(const NGLineInfo&,
const NGExclusionSpace&,
......
......@@ -38,6 +38,9 @@ class PLATFORM_EXPORT ShapeResultSpacing final {
float WordSpacing() const { return has_spacing_ ? word_spacing_ : .0f; }
bool HasSpacing() const { return has_spacing_; }
bool HasExpansion() const { return expansion_opportunity_count_; }
unsigned ExpansionOppotunityCount() const {
return expansion_opportunity_count_;
}
// Set letter-spacing and word-spacing.
bool SetSpacing(const FontDescription&);
......
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