Commit 330aad68 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Change NGLineTruncator to work on NGLogicalLineItem

|NGLineTruncator| was originally designed to compute and
trunate |NGPhysicalTextFragment|. This patch changes it to
work on |NGLogicalLineItem| instead.

This is yet another effort to reduce the usage of
|NGPhysicalTextFragment|, following r778837 and r779021.
This saves creating intermediate |NGPhysicalTextFragment|
when FragmentItem is enabled, and reduces dependency on
|NGPhysicalTextFragment| for the removal when the switch
to FragmentItem was completed.

Bug: 982194
Change-Id: I3742fa1ea33648e2151f7d3cbf83e977928c6715
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2230583
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#779756}
parent 5a9c7e42
...@@ -64,14 +64,15 @@ NGFragmentItem::NGFragmentItem( ...@@ -64,14 +64,15 @@ NGFragmentItem::NGFragmentItem(
const NGInlineItem& inline_item, const NGInlineItem& inline_item,
scoped_refptr<const ShapeResultView> shape_result, scoped_refptr<const ShapeResultView> shape_result,
const NGTextOffset& text_offset, const NGTextOffset& text_offset,
const PhysicalSize& size) const PhysicalSize& size,
bool is_hidden_for_paint)
: layout_object_(inline_item.GetLayoutObject()), : layout_object_(inline_item.GetLayoutObject()),
text_({std::move(shape_result), text_offset}), text_({std::move(shape_result), text_offset}),
rect_({PhysicalOffset(), size}), rect_({PhysicalOffset(), size}),
type_(kText), type_(kText),
sub_type_(static_cast<unsigned>(inline_item.TextType())), sub_type_(static_cast<unsigned>(inline_item.TextType())),
style_variant_(static_cast<unsigned>(inline_item.StyleVariant())), style_variant_(static_cast<unsigned>(inline_item.StyleVariant())),
is_hidden_for_paint_(false), // TODO(kojii): not supported yet. is_hidden_for_paint_(is_hidden_for_paint),
text_direction_(static_cast<unsigned>(inline_item.Direction())), text_direction_(static_cast<unsigned>(inline_item.Direction())),
ink_overflow_computed_(false), ink_overflow_computed_(false),
is_dirty_(false), is_dirty_(false),
...@@ -90,14 +91,15 @@ NGFragmentItem::NGFragmentItem( ...@@ -90,14 +91,15 @@ NGFragmentItem::NGFragmentItem(
const NGInlineItem& inline_item, const NGInlineItem& inline_item,
scoped_refptr<const ShapeResultView> shape_result, scoped_refptr<const ShapeResultView> shape_result,
const String& text_content, const String& text_content,
const PhysicalSize& size) const PhysicalSize& size,
bool is_hidden_for_paint)
: layout_object_(inline_item.GetLayoutObject()), : layout_object_(inline_item.GetLayoutObject()),
generated_text_({std::move(shape_result), text_content}), generated_text_({std::move(shape_result), text_content}),
rect_({PhysicalOffset(), size}), rect_({PhysicalOffset(), size}),
type_(kGeneratedText), type_(kGeneratedText),
sub_type_(static_cast<unsigned>(inline_item.TextType())), sub_type_(static_cast<unsigned>(inline_item.TextType())),
style_variant_(static_cast<unsigned>(inline_item.StyleVariant())), style_variant_(static_cast<unsigned>(inline_item.StyleVariant())),
is_hidden_for_paint_(false), // TODO(kojii): not supported yet. is_hidden_for_paint_(is_hidden_for_paint),
text_direction_(static_cast<unsigned>(inline_item.Direction())), text_direction_(static_cast<unsigned>(inline_item.Direction())),
ink_overflow_computed_(false), ink_overflow_computed_(false),
is_dirty_(false), is_dirty_(false),
...@@ -156,14 +158,16 @@ NGFragmentItem::NGFragmentItem(NGLogicalLineItem&& line_item, ...@@ -156,14 +158,16 @@ NGFragmentItem::NGFragmentItem(NGLogicalLineItem&& line_item,
new (this) NGFragmentItem( new (this) NGFragmentItem(
*line_item.inline_item, std::move(line_item.shape_result), *line_item.inline_item, std::move(line_item.shape_result),
line_item.text_content, line_item.text_content,
ToPhysicalSize(line_item.MarginSize(), writing_mode)); ToPhysicalSize(line_item.MarginSize(), writing_mode),
line_item.is_hidden_for_paint);
return; return;
} }
new (this) new (this)
NGFragmentItem(*line_item.inline_item, NGFragmentItem(*line_item.inline_item,
std::move(line_item.shape_result), line_item.text_offset, std::move(line_item.shape_result), line_item.text_offset,
ToPhysicalSize(line_item.MarginSize(), writing_mode)); ToPhysicalSize(line_item.MarginSize(), writing_mode),
line_item.is_hidden_for_paint);
return; return;
} }
......
...@@ -375,12 +375,14 @@ class CORE_EXPORT NGFragmentItem { ...@@ -375,12 +375,14 @@ class CORE_EXPORT NGFragmentItem {
NGFragmentItem(const NGInlineItem& inline_item, NGFragmentItem(const NGInlineItem& inline_item,
scoped_refptr<const ShapeResultView> shape_result, scoped_refptr<const ShapeResultView> shape_result,
const NGTextOffset& text_offset, const NGTextOffset& text_offset,
const PhysicalSize& size); const PhysicalSize& size,
bool is_hidden_for_paint);
// Create a generated text item. // Create a generated text item.
NGFragmentItem(const NGInlineItem& inline_item, NGFragmentItem(const NGInlineItem& inline_item,
scoped_refptr<const ShapeResultView> shape_result, scoped_refptr<const ShapeResultView> shape_result,
const String& text_content, const String& text_content,
const PhysicalSize& size); const PhysicalSize& size,
bool is_hidden_for_paint);
const LayoutBox* InkOverflowOwnerBox() const; const LayoutBox* InkOverflowOwnerBox() const;
LayoutBox* MutableInkOverflowOwnerBox(); LayoutBox* MutableInkOverflowOwnerBox();
......
...@@ -324,13 +324,6 @@ void NGInlineLayoutAlgorithm::CreateLine( ...@@ -324,13 +324,6 @@ void NGInlineLayoutAlgorithm::CreateLine(
line_info->AvailableWidth() - line_info->TextIndent() && line_info->AvailableWidth() - line_info->TextIndent() &&
node_.GetLayoutBlockFlow()->ShouldTruncateOverflowingText()) || node_.GetLayoutBlockFlow()->ShouldTruncateOverflowingText()) ||
ConstraintSpace().LinesUntilClamp() == 1)) { ConstraintSpace().LinesUntilClamp() == 1)) {
// TODO(kojii): |NGLineTruncator| does not support |Child|-based truncation
// yet, so create |NGPhysicalTextFragment| first.
if (has_logical_text_items) {
line_box_.CreateTextFragments(ConstraintSpace().GetWritingMode(),
line_info->ItemsData().text_content);
has_logical_text_items = false;
}
NGLineTruncator truncator(*line_info); NGLineTruncator truncator(*line_info);
auto* input = auto* input =
DynamicTo<HTMLInputElement>(node_.GetLayoutBlockFlow()->GetNode()); DynamicTo<HTMLInputElement>(node_.GetLayoutBlockFlow()->GetNode());
......
...@@ -64,7 +64,7 @@ LayoutUnit NGLineTruncator::PlaceEllipsisNextTo( ...@@ -64,7 +64,7 @@ LayoutUnit NGLineTruncator::PlaceEllipsisNextTo(
// Create the ellipsis, associating it with the ellipsized child. // Create the ellipsis, associating it with the ellipsized child.
DCHECK(ellipsized_child->HasInFlowFragment()); DCHECK(ellipsized_child->HasInFlowFragment());
LayoutObject* ellipsized_layout_object = LayoutObject* ellipsized_layout_object =
ellipsized_child->PhysicalFragment()->GetMutableLayoutObject(); ellipsized_child->GetMutableLayoutObject();
DCHECK(ellipsized_layout_object); DCHECK(ellipsized_layout_object);
DCHECK(ellipsized_layout_object->IsInline()); DCHECK(ellipsized_layout_object->IsInline());
DCHECK(ellipsized_layout_object->IsText() || DCHECK(ellipsized_layout_object->IsText() ||
...@@ -104,9 +104,10 @@ wtf_size_t NGLineTruncator::AddTruncatedChild( ...@@ -104,9 +104,10 @@ wtf_size_t NGLineTruncator::AddTruncatedChild(
NGLogicalLineItems* line_box, NGLogicalLineItems* line_box,
NGInlineLayoutStateStack* box_states) { NGInlineLayoutStateStack* box_states) {
NGLogicalLineItems& line = *line_box; NGLogicalLineItems& line = *line_box;
const NGLogicalLineItem& source_item = line[source_index];
DCHECK(source_item.shape_result);
scoped_refptr<ShapeResult> shape_result = scoped_refptr<ShapeResult> shape_result =
line[source_index].fragment->TextShapeResult()->CreateShapeResult(); source_item.shape_result->CreateShapeResult();
unsigned text_offset = shape_result->OffsetToFit(position, edge); unsigned text_offset = shape_result->OffsetToFit(position, edge);
if (IsLtr(edge) ? IsLeftMostOffset(*shape_result, text_offset) if (IsLtr(edge) ? IsLeftMostOffset(*shape_result, text_offset)
: IsRightMostOffset(*shape_result, text_offset)) { : IsRightMostOffset(*shape_result, text_offset)) {
...@@ -120,27 +121,18 @@ wtf_size_t NGLineTruncator::AddTruncatedChild( ...@@ -120,27 +121,18 @@ wtf_size_t NGLineTruncator::AddTruncatedChild(
edge); edge);
} }
const auto& fragment = line[source_index].fragment; const wtf_size_t new_index = line.size();
const bool keep_start = edge == fragment->ResolvedDirection(); line.AddChild(TruncateText(source_item, *shape_result, text_offset, edge));
scoped_refptr<const NGPhysicalTextFragment> truncated_fragment =
keep_start ? fragment->TrimText(fragment->StartOffset(),
fragment->StartOffset() + text_offset)
: fragment->TrimText(fragment->StartOffset() + text_offset,
fragment->EndOffset());
wtf_size_t new_index = line.size();
line.AddChild();
box_states->ChildInserted(new_index); box_states->ChildInserted(new_index);
line[new_index] = line[source_index];
line[new_index].inline_size = line_style_->IsHorizontalWritingMode()
? truncated_fragment->Size().width
: truncated_fragment->Size().height;
line[new_index].fragment = std::move(truncated_fragment);
return new_index; return new_index;
} }
LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width, LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width,
NGLogicalLineItems* line_box, NGLogicalLineItems* line_box,
NGInlineLayoutStateStack* box_states) { NGInlineLayoutStateStack* box_states) {
DCHECK(std::all_of(line_box->begin(), line_box->end(),
[](const auto& item) { return !item.fragment; }));
// Shape the ellipsis and compute its inline size. // Shape the ellipsis and compute its inline size.
SetupEllipsis(); SetupEllipsis();
...@@ -148,13 +140,13 @@ LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width, ...@@ -148,13 +140,13 @@ LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width,
// 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
// process. // process.
NGLogicalLineItem* ellipsized_child = nullptr; NGLogicalLineItem* ellipsized_child = nullptr;
scoped_refptr<const NGPhysicalTextFragment> truncated_fragment; base::Optional<NGLogicalLineItem> truncated_child;
if (IsLtr(line_direction_)) { if (IsLtr(line_direction_)) {
NGLogicalLineItem* first_child = line_box->FirstInFlowChild(); NGLogicalLineItem* 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_child)) {
ellipsized_child = &child; ellipsized_child = &child;
break; break;
} }
...@@ -163,7 +155,7 @@ LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width, ...@@ -163,7 +155,7 @@ LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width,
NGLogicalLineItem* first_child = line_box->LastInFlowChild(); NGLogicalLineItem* 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_child)) {
ellipsized_child = &child; ellipsized_child = &child;
break; break;
} }
...@@ -175,28 +167,23 @@ LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width, ...@@ -175,28 +167,23 @@ LayoutUnit NGLineTruncator::TruncateLine(LayoutUnit line_width,
return line_width; return line_width;
// Truncate the text fragment if needed. // Truncate the text fragment if needed.
if (truncated_fragment) { if (truncated_child) {
DCHECK(ellipsized_child->fragment);
// In order to preserve layout information before truncated, hide the // In order to preserve layout information before truncated, hide the
// original fragment and insert a truncated one. // original fragment and insert a truncated one.
size_t child_index_to_truncate = ellipsized_child - line_box->begin(); size_t child_index_to_truncate = ellipsized_child - line_box->begin();
line_box->InsertChild(child_index_to_truncate + 1); line_box->InsertChild(child_index_to_truncate + 1,
std::move(*truncated_child));
box_states->ChildInserted(child_index_to_truncate + 1); box_states->ChildInserted(child_index_to_truncate + 1);
NGLogicalLineItem* child_to_truncate = NGLogicalLineItem* child_to_truncate =
&(*line_box)[child_index_to_truncate]; &(*line_box)[child_index_to_truncate];
ellipsized_child = std::next(child_to_truncate); ellipsized_child = std::next(child_to_truncate);
*ellipsized_child = *child_to_truncate;
HideChild(child_to_truncate); HideChild(child_to_truncate);
LayoutUnit new_inline_size = line_style_->IsHorizontalWritingMode() DCHECK_LE(ellipsized_child->inline_size, child_to_truncate->inline_size);
? truncated_fragment->Size().width
: truncated_fragment->Size().height;
DCHECK_LE(new_inline_size, ellipsized_child->inline_size);
if (UNLIKELY(IsRtl(line_direction_))) { if (UNLIKELY(IsRtl(line_direction_))) {
ellipsized_child->rect.offset.inline_offset += ellipsized_child->rect.offset.inline_offset +=
ellipsized_child->inline_size - new_inline_size; child_to_truncate->inline_size - ellipsized_child->inline_size;
} }
ellipsized_child->inline_size = new_inline_size;
ellipsized_child->fragment = std::move(truncated_fragment);
} }
// Create the ellipsis, associating it with the ellipsized child. // Create the ellipsis, associating it with the ellipsized child.
...@@ -225,16 +212,15 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle( ...@@ -225,16 +212,15 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle(
wtf_size_t initial_index_right = kNotFound; wtf_size_t initial_index_right = kNotFound;
for (wtf_size_t i = 0; i < line_box->size(); ++i) { for (wtf_size_t i = 0; i < line_box->size(); ++i) {
auto& child = line[i]; auto& child = line[i];
if (!child.fragment && child.IsPlaceholder()) if (child.IsPlaceholder())
continue; continue;
if (child.HasOutOfFlowFragment() || !child.fragment || if (!child.shape_result) {
!child.fragment->TextShapeResult()) {
if (initial_index_right != kNotFound) if (initial_index_right != kNotFound)
break; break;
continue; continue;
} }
// Skip pseudo elements like ::before. // Skip pseudo elements like ::before.
if (!child.fragment->GetNode()) if (!child.GetNode())
continue; continue;
if (initial_index_left == kNotFound) if (initial_index_left == kNotFound)
...@@ -404,6 +390,11 @@ void NGLineTruncator::HideChild(NGLogicalLineItem* child) { ...@@ -404,6 +390,11 @@ void NGLineTruncator::HideChild(NGLogicalLineItem* child) {
return; return;
} }
if (child->inline_item) {
child->is_hidden_for_paint = true;
return;
}
NOTREACHED(); NOTREACHED();
} }
...@@ -415,8 +406,8 @@ bool NGLineTruncator::EllipsizeChild( ...@@ -415,8 +406,8 @@ bool NGLineTruncator::EllipsizeChild(
LayoutUnit ellipsis_width, LayoutUnit ellipsis_width,
bool is_first_child, bool is_first_child,
NGLogicalLineItem* child, NGLogicalLineItem* child,
scoped_refptr<const NGPhysicalTextFragment>* truncated_fragment) { base::Optional<NGLogicalLineItem>* truncated_child) {
DCHECK(truncated_fragment && !*truncated_fragment); DCHECK(truncated_child && !*truncated_child);
// Leave out-of-flow children as is. // Leave out-of-flow children as is.
if (!child->HasInFlowFragment()) if (!child->HasInFlowFragment())
...@@ -424,8 +415,7 @@ bool NGLineTruncator::EllipsizeChild( ...@@ -424,8 +415,7 @@ bool NGLineTruncator::EllipsizeChild(
// Inline boxes should not be ellipsized. Usually they will be created in the // Inline boxes should not be ellipsized. Usually they will be created in the
// later phase, but empty inline box are already created. // later phase, but empty inline box are already created.
if (child->layout_result && if (child->IsInlineBox())
child->layout_result->PhysicalFragment().IsInlineBox())
return false; return false;
// Can't place ellipsis if this child is completely outside of the box. // Can't place ellipsis if this child is completely outside of the box.
...@@ -444,19 +434,20 @@ bool NGLineTruncator::EllipsizeChild( ...@@ -444,19 +434,20 @@ bool NGLineTruncator::EllipsizeChild(
} }
// At least part of this child is in the box. // At least part of this child is in the box.
// If not all of this child can fit, try to truncate. // If |child| can fit in the space, truncate this line at the end of |child|.
space_for_child -= ellipsis_width; space_for_child -= ellipsis_width;
if (space_for_child < child->inline_size && if (space_for_child >= child->inline_size)
!TruncateChild(space_for_child, is_first_child, *child, return true;
truncated_fragment)) {
// This child is partially in the box, but it should not be visible because
// earlier sibling will be truncated and ellipsized.
if (!is_first_child)
HideChild(child);
return false;
}
return true; // If not all of this child can fit, try to truncate.
if (TruncateChild(space_for_child, is_first_child, *child, truncated_child))
return true;
// This child is partially in the box, but it can't be truncated to fit. It
// should not be visible because earlier sibling will be truncated.
if (!is_first_child)
HideChild(child);
return false;
} }
// Truncate the specified child. Returns true if truncated successfully, false // Truncate the specified child. Returns true if truncated successfully, false
...@@ -470,49 +461,52 @@ bool NGLineTruncator::TruncateChild( ...@@ -470,49 +461,52 @@ bool NGLineTruncator::TruncateChild(
LayoutUnit space_for_child, LayoutUnit space_for_child,
bool is_first_child, bool is_first_child,
const NGLogicalLineItem& child, const NGLogicalLineItem& child,
scoped_refptr<const NGPhysicalTextFragment>* truncated_fragment) { base::Optional<NGLogicalLineItem>* truncated_child) {
DCHECK(truncated_fragment && !*truncated_fragment); DCHECK(truncated_child && !*truncated_child);
DCHECK(!child.fragment);
// If the space is not enough, try the next child. // If the space is not enough, try the next child.
if (space_for_child <= 0 && !is_first_child) if (space_for_child <= 0 && !is_first_child)
return false; return false;
// Only text fragments can be truncated. // Only text fragments can be truncated.
if (!child.fragment) if (!child.shape_result)
return is_first_child;
auto& fragment = To<NGPhysicalTextFragment>(*child.fragment);
// No need to truncate empty results.
if (!fragment.TextShapeResult())
return is_first_child; return is_first_child;
// TODO(layout-dev): Add support for OffsetToFit to ShapeResultView to avoid // TODO(layout-dev): Add support for OffsetToFit to ShapeResultView to avoid
// this copy. // this copy.
scoped_refptr<blink::ShapeResult> shape_result = scoped_refptr<ShapeResult> shape_result =
fragment.TextShapeResult()->CreateShapeResult(); child.shape_result->CreateShapeResult();
if (!shape_result) DCHECK(shape_result);
return is_first_child; const NGTextOffset original_offset = child.text_offset;
// Compute the offset to truncate. // Compute the offset to truncate.
unsigned new_length = shape_result->OffsetToFit( unsigned offset_to_fit = shape_result->OffsetToFit(
IsLtr(line_direction_) ? space_for_child IsLtr(line_direction_) ? space_for_child
: shape_result->Width() - space_for_child, : shape_result->Width() - space_for_child,
line_direction_); line_direction_);
DCHECK_LE(new_length, fragment.TextLength()); DCHECK_LE(offset_to_fit, original_offset.Length());
if (!new_length || new_length == fragment.TextLength()) { if (!offset_to_fit || offset_to_fit == original_offset.Length()) {
if (!is_first_child) if (!is_first_child)
return false; return false;
new_length = !new_length ? 1 : new_length - 1; offset_to_fit = !offset_to_fit ? 1 : offset_to_fit - 1;
} }
*truncated_child =
// Truncate the text fragment. TruncateText(child, *shape_result, offset_to_fit, line_direction_);
*truncated_fragment =
line_direction_ == shape_result->Direction()
? fragment.TrimText(fragment.StartOffset(),
fragment.StartOffset() + new_length)
: fragment.TrimText(fragment.StartOffset() + new_length,
fragment.EndOffset());
return true; return true;
} }
NGLogicalLineItem NGLineTruncator::TruncateText(const NGLogicalLineItem& item,
const ShapeResult& shape_result,
unsigned offset_to_fit,
TextDirection direction) {
const NGTextOffset new_text_offset =
direction == shape_result.Direction()
? NGTextOffset(item.StartOffset(), item.StartOffset() + offset_to_fit)
: NGTextOffset(item.StartOffset() + offset_to_fit, item.EndOffset());
scoped_refptr<ShapeResultView> new_shape_result = ShapeResultView::Create(
&shape_result, new_text_offset.start, new_text_offset.end);
DCHECK(item.inline_item);
return NGLogicalLineItem(item, std::move(new_shape_result), new_text_offset);
}
} // namespace blink } // namespace blink
...@@ -67,17 +67,22 @@ class CORE_EXPORT NGLineTruncator final { ...@@ -67,17 +67,22 @@ class CORE_EXPORT NGLineTruncator final {
TextDirection edge, TextDirection edge,
NGLogicalLineItems* line_box, NGLogicalLineItems* line_box,
NGInlineLayoutStateStack* box_states); NGInlineLayoutStateStack* box_states);
bool EllipsizeChild( bool EllipsizeChild(LayoutUnit line_width,
LayoutUnit line_width, LayoutUnit ellipsis_width,
LayoutUnit ellipsis_width, bool is_first_child,
bool is_first_child, NGLogicalLineItem*,
NGLogicalLineItem*, base::Optional<NGLogicalLineItem>* truncated_child);
scoped_refptr<const NGPhysicalTextFragment>* truncated_fragment); bool TruncateChild(LayoutUnit space_for_this_child,
bool TruncateChild( bool is_first_child,
LayoutUnit space_for_this_child, const NGLogicalLineItem& child,
bool is_first_child, base::Optional<NGLogicalLineItem>* truncated_child);
const NGLogicalLineItem& child, // Create |NGLogicalLineItem| by truncating text |item| at |offset_to_fit|.
scoped_refptr<const NGPhysicalTextFragment>* truncated_fragment); // |direction| specifies which side of the text is trimmed; if |kLtr|, it
// keeps the left end and trims the right end.
NGLogicalLineItem TruncateText(const NGLogicalLineItem& item,
const ShapeResult& shape_result,
unsigned offset_to_fit,
TextDirection direction);
void HideChild(NGLogicalLineItem* child); void HideChild(NGLogicalLineItem* child);
scoped_refptr<const ComputedStyle> line_style_; scoped_refptr<const ComputedStyle> line_style_;
......
...@@ -9,6 +9,28 @@ ...@@ -9,6 +9,28 @@
namespace blink { namespace blink {
const LayoutObject* NGLogicalLineItem::GetLayoutObject() const {
if (inline_item)
return inline_item->GetLayoutObject();
if (const NGPhysicalFragment* fragment = PhysicalFragment())
return fragment->GetLayoutObject();
return nullptr;
}
LayoutObject* NGLogicalLineItem::GetMutableLayoutObject() const {
if (inline_item)
return inline_item->GetLayoutObject();
if (const NGPhysicalFragment* fragment = PhysicalFragment())
return fragment->GetMutableLayoutObject();
return nullptr;
}
const Node* NGLogicalLineItem::GetNode() const {
if (const LayoutObject* layout_object = GetLayoutObject())
return layout_object->GetNode();
return nullptr;
}
const ComputedStyle* NGLogicalLineItem::Style() const { const ComputedStyle* NGLogicalLineItem::Style() const {
if (const auto* fragment = PhysicalFragment()) if (const auto* fragment = PhysicalFragment())
return &fragment->Style(); return &fragment->Style();
...@@ -37,6 +59,7 @@ void NGLogicalLineItems::CreateTextFragments(WritingMode writing_mode, ...@@ -37,6 +59,7 @@ void NGLogicalLineItems::CreateTextFragments(WritingMode writing_mode,
std::move(child.shape_result), child.text_offset, std::move(child.shape_result), child.text_offset,
child.MarginSize()); child.MarginSize());
} }
text_builder.SetIsHiddenForPaint(child.is_hidden_for_paint);
DCHECK(!child.fragment); DCHECK(!child.fragment);
child.fragment = text_builder.ToTextFragment(); child.fragment = text_builder.ToTextFragment();
} }
...@@ -71,11 +94,6 @@ void NGLogicalLineItems::WillInsertChild(unsigned insert_before) { ...@@ -71,11 +94,6 @@ void NGLogicalLineItems::WillInsertChild(unsigned insert_before) {
} }
} }
void NGLogicalLineItems::InsertChild(unsigned index) {
WillInsertChild(index);
children_.insert(index, NGLogicalLineItem());
}
void NGLogicalLineItems::MoveInInlineDirection(LayoutUnit delta) { void NGLogicalLineItems::MoveInInlineDirection(LayoutUnit delta) {
for (auto& child : children_) for (auto& child : children_)
child.rect.offset.inline_offset += delta; child.rect.offset.inline_offset += delta;
......
...@@ -75,6 +75,16 @@ struct NGLogicalLineItem { ...@@ -75,6 +75,16 @@ struct NGLogicalLineItem {
rect(LayoutUnit(), block_offset, LayoutUnit(), text_height), rect(LayoutUnit(), block_offset, LayoutUnit(), text_height),
inline_size(inline_size), inline_size(inline_size),
bidi_level(bidi_level) {} bidi_level(bidi_level) {}
NGLogicalLineItem(const NGLogicalLineItem& source_item,
scoped_refptr<const ShapeResultView> shape_result,
const NGTextOffset& text_offset)
: inline_item(source_item.inline_item),
shape_result(std::move(shape_result)),
text_offset(text_offset),
text_content(source_item.text_content),
rect(source_item.rect),
inline_size(this->shape_result->SnappedWidth()),
bidi_level(source_item.bidi_level) {}
NGLogicalLineItem(scoped_refptr<const NGPhysicalTextFragment> fragment, NGLogicalLineItem(scoped_refptr<const NGPhysicalTextFragment> fragment,
LogicalOffset offset, LogicalOffset offset,
LayoutUnit inline_size, LayoutUnit inline_size,
...@@ -109,6 +119,9 @@ struct NGLogicalLineItem { ...@@ -109,6 +119,9 @@ struct NGLogicalLineItem {
bfc_offset(bfc_offset), bfc_offset(bfc_offset),
bidi_level(bidi_level) {} bidi_level(bidi_level) {}
bool IsInlineBox() const {
return layout_result && layout_result->PhysicalFragment().IsInlineBox();
}
bool HasInFlowFragment() const { bool HasInFlowFragment() const {
return fragment || inline_item || return fragment || inline_item ||
(layout_result && !layout_result->PhysicalFragment().IsFloating()); (layout_result && !layout_result->PhysicalFragment().IsFloating());
...@@ -147,21 +160,27 @@ struct NGLogicalLineItem { ...@@ -147,21 +160,27 @@ struct NGLogicalLineItem {
LayoutUnit BlockEndOffset() const { return rect.BlockEndOffset(); } LayoutUnit BlockEndOffset() const { return rect.BlockEndOffset(); }
const LogicalSize& Size() const { return rect.size; } const LogicalSize& Size() const { return rect.size; }
LogicalSize MarginSize() const { return {inline_size, Size().block_size}; } LogicalSize MarginSize() const { return {inline_size, Size().block_size}; }
const NGPhysicalFragment* PhysicalFragment() const { const NGPhysicalFragment* PhysicalFragment() const {
if (layout_result) if (layout_result)
return &layout_result->PhysicalFragment(); return &layout_result->PhysicalFragment();
return fragment.get(); return fragment.get();
} }
const LayoutObject* GetLayoutObject() const;
LayoutObject* GetMutableLayoutObject() const;
const Node* GetNode() const;
const ComputedStyle* Style() const;
unsigned StartOffset() const { return text_offset.start; }
unsigned EndOffset() const { return text_offset.end; }
TextDirection ResolvedDirection() const { TextDirection ResolvedDirection() const {
// Inline boxes are not leaves that they don't have directions. // Inline boxes are not leaves that they don't have directions.
DCHECK(HasBidiLevel() || layout_result->PhysicalFragment().IsInlineBox()); DCHECK(HasBidiLevel() || IsInlineBox());
return HasBidiLevel() ? DirectionFromLevel(bidi_level) return HasBidiLevel() ? DirectionFromLevel(bidi_level)
: TextDirection::kLtr; : TextDirection::kLtr;
} }
const ComputedStyle* Style() const;
scoped_refptr<const NGLayoutResult> layout_result; scoped_refptr<const NGLayoutResult> layout_result;
scoped_refptr<const NGPhysicalTextFragment> fragment; scoped_refptr<const NGPhysicalTextFragment> fragment;
...@@ -194,6 +213,8 @@ struct NGLogicalLineItem { ...@@ -194,6 +213,8 @@ struct NGLogicalLineItem {
UBiDiLevel bidi_level = 0xff; UBiDiLevel bidi_level = 0xff;
// The current text direction for OOF positioned items. // The current text direction for OOF positioned items.
TextDirection container_direction = TextDirection::kLtr; TextDirection container_direction = TextDirection::kLtr;
bool is_hidden_for_paint = false;
}; };
// A vector of Child. // A vector of Child.
...@@ -243,7 +264,10 @@ class NGLogicalLineItems { ...@@ -243,7 +264,10 @@ class NGLogicalLineItems {
void AddChild(Args&&... args) { void AddChild(Args&&... args) {
children_.emplace_back(std::forward<Args>(args)...); children_.emplace_back(std::forward<Args>(args)...);
} }
void InsertChild(unsigned index); void InsertChild(unsigned index, NGLogicalLineItem&& item) {
WillInsertChild(index);
children_.insert(index, item);
}
void InsertChild(unsigned index, void InsertChild(unsigned index,
scoped_refptr<const NGLayoutResult> layout_result, scoped_refptr<const NGLayoutResult> layout_result,
const LogicalRect& rect, const LogicalRect& rect,
......
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