Commit 1a09455d authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

Refactor NGLineTruncator

Add two functions for the beginning and the end of TruncateLine().
These functions will be used by 'middle-ellipsis' feature.

This CL has no behavior changes.

Bug: 1060022
Change-Id: I87146ccad6637f18f297066cfb67e49abfccdfbd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2094919Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748547}
parent e67af5a8
...@@ -19,25 +19,64 @@ NGLineTruncator::NGLineTruncator(const NGLineInfo& line_info) ...@@ -19,25 +19,64 @@ NGLineTruncator::NGLineTruncator(const NGLineInfo& line_info)
available_width_(line_info.AvailableWidth() - line_info.TextIndent()), available_width_(line_info.AvailableWidth() - line_info.TextIndent()),
line_direction_(line_info.BaseDirection()) {} line_direction_(line_info.BaseDirection()) {}
LayoutUnit NGLineTruncator::TruncateLine( const ComputedStyle& NGLineTruncator::EllipsisStyle() const {
LayoutUnit line_width,
NGLineBoxFragmentBuilder::ChildList* line_box,
NGInlineLayoutStateStack* box_states) {
// Shape the ellipsis and compute its inline size.
// The ellipsis is styled according to the line style. // The ellipsis is styled according to the line style.
// https://drafts.csswg.org/css-ui/#ellipsing-details // https://drafts.csswg.org/css-ui/#ellipsing-details
const ComputedStyle* ellipsis_style = line_style_.get(); return *line_style_;
const Font& font = ellipsis_style->GetFont(); }
const SimpleFontData* font_data = font.PrimaryFont();
DCHECK(font_data); void NGLineTruncator::SetupEllipsis() {
String ellipsis_text = const Font& font = EllipsisStyle().GetFont();
font_data && font_data->GlyphForCharacter(kHorizontalEllipsisCharacter) ellipsis_font_data_ = font.PrimaryFont();
DCHECK(ellipsis_font_data_);
ellipsis_text_ =
ellipsis_font_data_ && ellipsis_font_data_->GlyphForCharacter(
kHorizontalEllipsisCharacter)
? String(&kHorizontalEllipsisCharacter, 1) ? String(&kHorizontalEllipsisCharacter, 1)
: String(u"..."); : String(u"...");
HarfBuzzShaper shaper(ellipsis_text); HarfBuzzShaper shaper(ellipsis_text_);
scoped_refptr<ShapeResultView> ellipsis_shape_result = ellipsis_shape_result_ =
ShapeResultView::Create(shaper.Shape(&font, line_direction_).get()); ShapeResultView::Create(shaper.Shape(&font, line_direction_).get());
LayoutUnit ellipsis_width = ellipsis_shape_result->SnappedWidth(); ellipsis_width_ = ellipsis_shape_result_->SnappedWidth();
}
LayoutUnit NGLineTruncator::PlaceEllipsisNextTo(
NGLineBoxFragmentBuilder::ChildList* line_box,
NGLineBoxFragmentBuilder::Child* ellipsized_child) {
// Create the ellipsis, associating it with the ellipsized child.
LayoutObject* ellipsized_layout_object =
ellipsized_child->PhysicalFragment()->GetMutableLayoutObject();
DCHECK(ellipsized_layout_object);
DCHECK(ellipsized_layout_object->IsInline());
DCHECK(ellipsized_layout_object->IsText() ||
ellipsized_layout_object->IsAtomicInlineLevel());
NGTextFragmentBuilder builder(line_style_->GetWritingMode());
builder.SetText(ellipsized_layout_object, ellipsis_text_, &EllipsisStyle(),
true /* is_ellipsis_style */,
std::move(ellipsis_shape_result_));
// Now the offset of the ellpisis is determined. Place the ellpisis into the
// line box.
LayoutUnit ellipsis_inline_offset =
IsLtr(line_direction_)
? ellipsized_child->InlineOffset() + ellipsized_child->inline_size
: ellipsized_child->InlineOffset() - ellipsis_width_;
FontBaseline baseline_type = line_style_->GetFontBaseline();
NGLineHeightMetrics ellipsis_metrics(ellipsis_font_data_->GetFontMetrics(),
baseline_type);
line_box->AddChild(
builder.ToTextFragment(),
LogicalOffset{ellipsis_inline_offset, -ellipsis_metrics.ascent},
ellipsis_width_, 0);
return ellipsis_inline_offset;
}
LayoutUnit NGLineTruncator::TruncateLine(
LayoutUnit line_width,
NGLineBoxFragmentBuilder::ChildList* line_box,
NGInlineLayoutStateStack* box_states) {
// Shape the ellipsis and compute its inline size.
SetupEllipsis();
// Loop children from the logical last to the logical first to determine where // Loop children from the logical last to the logical first to determine where
// to place the ellipsis. Children maybe truncated or moved as part of the // to place the ellipsis. Children maybe truncated or moved as part of the
...@@ -48,7 +87,7 @@ LayoutUnit NGLineTruncator::TruncateLine( ...@@ -48,7 +87,7 @@ LayoutUnit NGLineTruncator::TruncateLine(
NGLineBoxFragmentBuilder::Child* first_child = line_box->FirstInFlowChild(); NGLineBoxFragmentBuilder::Child* first_child = line_box->FirstInFlowChild();
for (auto it = line_box->rbegin(); it != line_box->rend(); it++) { for (auto it = line_box->rbegin(); it != line_box->rend(); it++) {
auto& child = *it; auto& child = *it;
if (EllipsizeChild(line_width, ellipsis_width, &child == first_child, if (EllipsizeChild(line_width, ellipsis_width_, &child == first_child,
&child, &truncated_fragment)) { &child, &truncated_fragment)) {
ellipsized_child = &child; ellipsized_child = &child;
break; break;
...@@ -57,7 +96,7 @@ LayoutUnit NGLineTruncator::TruncateLine( ...@@ -57,7 +96,7 @@ LayoutUnit NGLineTruncator::TruncateLine(
} else { } else {
NGLineBoxFragmentBuilder::Child* first_child = line_box->LastInFlowChild(); NGLineBoxFragmentBuilder::Child* first_child = line_box->LastInFlowChild();
for (auto& child : *line_box) { for (auto& child : *line_box) {
if (EllipsizeChild(line_width, ellipsis_width, &child == first_child, if (EllipsizeChild(line_width, ellipsis_width_, &child == first_child,
&child, &truncated_fragment)) { &child, &truncated_fragment)) {
ellipsized_child = &child; ellipsized_child = &child;
break; break;
...@@ -95,30 +134,9 @@ LayoutUnit NGLineTruncator::TruncateLine( ...@@ -95,30 +134,9 @@ LayoutUnit NGLineTruncator::TruncateLine(
} }
// Create the ellipsis, associating it with the ellipsized child. // Create the ellipsis, associating it with the ellipsized child.
LayoutObject* ellipsized_layout_object =
ellipsized_child->PhysicalFragment()->GetMutableLayoutObject();
DCHECK(ellipsized_layout_object && ellipsized_layout_object->IsInline() &&
(ellipsized_layout_object->IsText() ||
ellipsized_layout_object->IsAtomicInlineLevel()));
NGTextFragmentBuilder builder(line_style_->GetWritingMode());
builder.SetText(ellipsized_layout_object, ellipsis_text, ellipsis_style,
true /* is_ellipsis_style */,
std::move(ellipsis_shape_result));
// Now the offset of the ellpisis is determined. Place the ellpisis into the
// line box.
LayoutUnit ellipsis_inline_offset = LayoutUnit ellipsis_inline_offset =
IsLtr(line_direction_) PlaceEllipsisNextTo(line_box, ellipsized_child);
? ellipsized_child->InlineOffset() + ellipsized_child->inline_size return std::max(ellipsis_inline_offset + ellipsis_width_, line_width);
: ellipsized_child->InlineOffset() - ellipsis_width;
FontBaseline baseline_type = line_style_->GetFontBaseline();
NGLineHeightMetrics ellipsis_metrics(font_data->GetFontMetrics(),
baseline_type);
line_box->AddChild(
builder.ToTextFragment(),
LogicalOffset{ellipsis_inline_offset, -ellipsis_metrics.ascent},
ellipsis_width, 0);
return std::max(ellipsis_inline_offset + ellipsis_width, line_width);
} }
// Hide this child from being painted. Leaves a hidden fragment so that layout // Hide this child from being painted. Leaves a hidden fragment so that layout
......
...@@ -34,6 +34,16 @@ class CORE_EXPORT NGLineTruncator final { ...@@ -34,6 +34,16 @@ class CORE_EXPORT NGLineTruncator final {
NGInlineLayoutStateStack* box_states); NGInlineLayoutStateStack* box_states);
private: private:
const ComputedStyle& EllipsisStyle() const;
// Initialize four ellipsis_*_ data members.
void SetupEllipsis();
// Add a child for ellipsis next to |ellipsized_child|.
LayoutUnit PlaceEllipsisNextTo(
NGLineBoxFragmentBuilder::ChildList* line_box,
NGLineBoxFragmentBuilder::Child* ellipsized_child);
bool EllipsizeChild( bool EllipsizeChild(
LayoutUnit line_width, LayoutUnit line_width,
LayoutUnit ellipsis_width, LayoutUnit ellipsis_width,
...@@ -50,6 +60,15 @@ class CORE_EXPORT NGLineTruncator final { ...@@ -50,6 +60,15 @@ class CORE_EXPORT NGLineTruncator final {
scoped_refptr<const ComputedStyle> line_style_; scoped_refptr<const ComputedStyle> line_style_;
LayoutUnit available_width_; LayoutUnit available_width_;
TextDirection line_direction_; TextDirection line_direction_;
// The following 3 data members are available after SetupEllipsis().
const SimpleFontData* ellipsis_font_data_;
String ellipsis_text_;
LayoutUnit ellipsis_width_;
// This data member is available between SetupEllipsis() and
// PlaceEllipsisNextTo().
scoped_refptr<ShapeResultView> ellipsis_shape_result_;
}; };
} // namespace blink } // namespace blink
......
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