Commit 155aa5fb authored by Yoshifumi Inoue's avatar Yoshifumi Inoue Committed by Commit Bot

Utilize NGInlineCursor for inline box traversal

This patch changes "inline_box_traversal.cc" to utilize |NGInlineCursor| instead
of |NGPaintFragment| for preparation of migraing |NGFragmentItem|.

This patch will reduces 1000+ failed web_tests in |LayoutNGFragmentItem| flag.

Bug: 982194
Change-Id: I7f889755ff44beaa63e83f47db415b65969394d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1888242
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Auto-Submit: Yoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712949}
parent ee5f0d37
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/editing/inline_box_traversal.h" #include "third_party/blink/renderer/core/editing/inline_box_traversal.h"
#include <unicode/ubidi.h>
#include "third_party/blink/renderer/core/editing/inline_box_position.h" #include "third_party/blink/renderer/core/editing/inline_box_position.h"
#include "third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h" #include "third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h"
#include "third_party/blink/renderer/core/editing/selection_template.h" #include "third_party/blink/renderer/core/editing/selection_template.h"
...@@ -12,10 +14,6 @@ ...@@ -12,10 +14,6 @@
#include "third_party/blink/renderer/core/layout/line/inline_box.h" #include "third_party/blink/renderer/core/layout/line/inline_box.h"
#include "third_party/blink/renderer/core/layout/line/root_inline_box.h" #include "third_party/blink/renderer/core/layout/line/root_inline_box.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h"
#include "third_party/blink/renderer/platform/text/text_direction.h" #include "third_party/blink/renderer/platform/text/text_direction.h"
// TODO(xiaochengh): Rename this file to |bidi_adjustment.cc| // TODO(xiaochengh): Rename this file to |bidi_adjustment.cc|
...@@ -35,10 +33,9 @@ class AbstractInlineBox { ...@@ -35,10 +33,9 @@ class AbstractInlineBox {
explicit AbstractInlineBox(const InlineBox& box) explicit AbstractInlineBox(const InlineBox& box)
: type_(InstanceType::kOldLayout), inline_box_(&box) {} : type_(InstanceType::kOldLayout), inline_box_(&box) {}
explicit AbstractInlineBox(const NGPaintFragment& paint_fragment) explicit AbstractInlineBox(const NGInlineCursor& cursor)
: AbstractInlineBox( : type_(InstanceType::kNG),
NGPaintFragmentTraversal(*paint_fragment.ContainerLineBox(), line_cursor_(CreateLineRootedCursor(cursor)) {}
paint_fragment)) {}
bool IsNotNull() const { return type_ != InstanceType::kNull; } bool IsNotNull() const { return type_ != InstanceType::kNull; }
bool IsNull() const { return !IsNotNull(); } bool IsNull() const { return !IsNotNull(); }
...@@ -54,35 +51,36 @@ class AbstractInlineBox { ...@@ -54,35 +51,36 @@ class AbstractInlineBox {
case InstanceType::kOldLayout: case InstanceType::kOldLayout:
return inline_box_ == other.inline_box_; return inline_box_ == other.inline_box_;
case InstanceType::kNG: case InstanceType::kNG:
return paint_fragment_.get() == other.paint_fragment_.get(); return line_cursor_ == other.line_cursor_;
} }
NOTREACHED(); NOTREACHED();
return false; return false;
} }
// Returns containing block rooted cursor instead of line rooted cursor for
// ease of handling, e.g. equiality check, move to next/previous line, etc.
NGInlineCursor GetCursor() const {
NGInlineCursor cursor;
cursor.MoveTo(line_cursor_);
return cursor;
}
const InlineBox& GetInlineBox() const { const InlineBox& GetInlineBox() const {
DCHECK(IsOldLayout()); DCHECK(IsOldLayout());
DCHECK(inline_box_); DCHECK(inline_box_);
return *inline_box_; return *inline_box_;
} }
const NGPaintFragment& GetNGPaintFragment() const {
DCHECK(IsNG());
DCHECK(!paint_fragment_.IsAtEnd());
return *paint_fragment_;
}
UBiDiLevel BidiLevel() const { UBiDiLevel BidiLevel() const {
DCHECK(IsNotNull()); DCHECK(IsNotNull());
return IsOldLayout() ? GetInlineBox().BidiLevel() return IsOldLayout() ? GetInlineBox().BidiLevel()
: GetNGPaintFragment().PhysicalFragment().BidiLevel(); : line_cursor_.CurrentBidiLevel();
} }
TextDirection Direction() const { TextDirection Direction() const {
DCHECK(IsNotNull()); DCHECK(IsNotNull());
return IsOldLayout() return IsOldLayout() ? GetInlineBox().Direction()
? GetInlineBox().Direction() : line_cursor_.CurrentResolvedDirection();
: GetNGPaintFragment().PhysicalFragment().ResolvedDirection();
} }
AbstractInlineBox PrevLeafChild() const { AbstractInlineBox PrevLeafChild() const {
...@@ -91,10 +89,9 @@ class AbstractInlineBox { ...@@ -91,10 +89,9 @@ class AbstractInlineBox {
const InlineBox* result = GetInlineBox().PrevLeafChild(); const InlineBox* result = GetInlineBox().PrevLeafChild();
return result ? AbstractInlineBox(*result) : AbstractInlineBox(); return result ? AbstractInlineBox(*result) : AbstractInlineBox();
} }
NGPaintFragmentTraversal result(paint_fragment_); NGInlineCursor cursor(line_cursor_);
result.MoveToPreviousInlineLeaf(); cursor.MoveToPreviousInlineLeaf();
return result.IsAtEnd() ? AbstractInlineBox() return cursor ? AbstractInlineBox(cursor) : AbstractInlineBox();
: AbstractInlineBox(std::move(result));
} }
AbstractInlineBox PrevLeafChildIgnoringLineBreak() const { AbstractInlineBox PrevLeafChildIgnoringLineBreak() const {
...@@ -103,10 +100,9 @@ class AbstractInlineBox { ...@@ -103,10 +100,9 @@ class AbstractInlineBox {
const InlineBox* result = GetInlineBox().PrevLeafChildIgnoringLineBreak(); const InlineBox* result = GetInlineBox().PrevLeafChildIgnoringLineBreak();
return result ? AbstractInlineBox(*result) : AbstractInlineBox(); return result ? AbstractInlineBox(*result) : AbstractInlineBox();
} }
NGPaintFragmentTraversal result(paint_fragment_); NGInlineCursor cursor(line_cursor_);
result.MoveToPreviousInlineLeafIgnoringLineBreak(); cursor.MoveToPreviousInlineLeafIgnoringLineBreak();
return result.IsAtEnd() ? AbstractInlineBox() return cursor ? AbstractInlineBox(cursor) : AbstractInlineBox();
: AbstractInlineBox(std::move(result));
} }
AbstractInlineBox NextLeafChild() const { AbstractInlineBox NextLeafChild() const {
...@@ -115,10 +111,9 @@ class AbstractInlineBox { ...@@ -115,10 +111,9 @@ class AbstractInlineBox {
const InlineBox* result = GetInlineBox().NextLeafChild(); const InlineBox* result = GetInlineBox().NextLeafChild();
return result ? AbstractInlineBox(*result) : AbstractInlineBox(); return result ? AbstractInlineBox(*result) : AbstractInlineBox();
} }
NGPaintFragmentTraversal result(paint_fragment_); NGInlineCursor cursor(line_cursor_);
result.MoveToNextInlineLeaf(); cursor.MoveToNextInlineLeaf();
return result.IsAtEnd() ? AbstractInlineBox() return cursor ? AbstractInlineBox(cursor) : AbstractInlineBox();
: AbstractInlineBox(std::move(result));
} }
AbstractInlineBox NextLeafChildIgnoringLineBreak() const { AbstractInlineBox NextLeafChildIgnoringLineBreak() const {
...@@ -127,30 +122,45 @@ class AbstractInlineBox { ...@@ -127,30 +122,45 @@ class AbstractInlineBox {
const InlineBox* result = GetInlineBox().NextLeafChildIgnoringLineBreak(); const InlineBox* result = GetInlineBox().NextLeafChildIgnoringLineBreak();
return result ? AbstractInlineBox(*result) : AbstractInlineBox(); return result ? AbstractInlineBox(*result) : AbstractInlineBox();
} }
NGPaintFragmentTraversal result(paint_fragment_); NGInlineCursor cursor(line_cursor_);
result.MoveToNextInlineLeafIgnoringLineBreak(); cursor.MoveToNextInlineLeafIgnoringLineBreak();
return result.IsAtEnd() ? AbstractInlineBox() return cursor ? AbstractInlineBox(cursor) : AbstractInlineBox();
: AbstractInlineBox(std::move(result));
} }
TextDirection ParagraphDirection() const { TextDirection ParagraphDirection() const {
DCHECK(IsNotNull()); DCHECK(IsNotNull());
if (IsOldLayout()) if (IsOldLayout())
return ParagraphDirectionOf(GetInlineBox()); return ParagraphDirectionOf(GetInlineBox());
return ParagraphDirectionOf(GetNGPaintFragment()); return GetLineBox(line_cursor_).CurrentBaseDirection();
} }
private: private:
explicit AbstractInlineBox(NGPaintFragmentTraversal&& fragment) static NGInlineCursor CreateLineRootedCursor(const NGInlineCursor& cursor) {
: type_(InstanceType::kNG), paint_fragment_(std::move(fragment)) {} NGInlineCursor line_cursor = GetLineBox(cursor).CursorForDescendants();
line_cursor.MoveTo(cursor);
return line_cursor;
}
// Returns containing line box of |cursor| even if |cursor| is scoped inside
// line.
static NGInlineCursor GetLineBox(const NGInlineCursor& cursor) {
NGInlineCursor line_box;
line_box.MoveTo(cursor);
line_box.MoveToContainingLine();
return line_box;
}
enum class InstanceType { kNull, kOldLayout, kNG }; enum class InstanceType { kNull, kOldLayout, kNG };
InstanceType type_; InstanceType type_;
// Only one of |inline_box_| or |paint_fragment_| is used, but we cannot make // Only one of |inline_box_| or |line_cursor_| is used, but we cannot make
// them union because of non-trivial destructor. // them union because of non-trivial destructor.
const InlineBox* inline_box_; const InlineBox* inline_box_;
NGPaintFragmentTraversal paint_fragment_;
// Because of |MoveToContainingLine()| isn't cheap and we avoid to call each
// |MoveTo{Next,Previous}InlineLeaf()|, we hold containing line rooted cursor
// instead of containing block rooted cursor.
NGInlineCursor line_cursor_;
}; };
// |SideAffinity| represents the left or right side of a leaf inline // |SideAffinity| represents the left or right side of a leaf inline
...@@ -177,10 +187,9 @@ bool IsAtFragmentStart(const NGCaretPosition& caret_position) { ...@@ -177,10 +187,9 @@ bool IsAtFragmentStart(const NGCaretPosition& caret_position) {
case NGCaretPositionType::kAfterBox: case NGCaretPositionType::kAfterBox:
return false; return false;
case NGCaretPositionType::kAtTextOffset: case NGCaretPositionType::kAtTextOffset:
const auto& text_fragment = To<NGPhysicalTextFragment>(
caret_position.PaintFragment()->PhysicalFragment());
DCHECK(caret_position.text_offset.has_value()); DCHECK(caret_position.text_offset.has_value());
return *caret_position.text_offset == text_fragment.StartOffset(); return *caret_position.text_offset ==
caret_position.cursor.CurrentTextStartOffset();
} }
NOTREACHED(); NOTREACHED();
return false; return false;
...@@ -194,10 +203,9 @@ bool IsAtFragmentEnd(const NGCaretPosition& caret_position) { ...@@ -194,10 +203,9 @@ bool IsAtFragmentEnd(const NGCaretPosition& caret_position) {
case NGCaretPositionType::kAfterBox: case NGCaretPositionType::kAfterBox:
return true; return true;
case NGCaretPositionType::kAtTextOffset: case NGCaretPositionType::kAtTextOffset:
const auto& text_fragment = To<NGPhysicalTextFragment>(
caret_position.PaintFragment()->PhysicalFragment());
DCHECK(caret_position.text_offset.has_value()); DCHECK(caret_position.text_offset.has_value());
return *caret_position.text_offset == text_fragment.EndOffset(); return *caret_position.text_offset ==
caret_position.cursor.CurrentTextEndOffset();
} }
NOTREACHED(); NOTREACHED();
return false; return false;
...@@ -205,13 +213,11 @@ bool IsAtFragmentEnd(const NGCaretPosition& caret_position) { ...@@ -205,13 +213,11 @@ bool IsAtFragmentEnd(const NGCaretPosition& caret_position) {
// Returns whether |caret_position| is at the left or right side of fragment. // Returns whether |caret_position| is at the left or right side of fragment.
SideAffinity GetSideAffinity(const NGCaretPosition& caret_position) { SideAffinity GetSideAffinity(const NGCaretPosition& caret_position) {
DCHECK(caret_position.PaintFragment()); DCHECK(!caret_position.IsNull());
DCHECK(IsAtFragmentStart(caret_position) || IsAtFragmentEnd(caret_position)); DCHECK(IsAtFragmentStart(caret_position) || IsAtFragmentEnd(caret_position));
const bool is_at_start = IsAtFragmentStart(caret_position); const bool is_at_start = IsAtFragmentStart(caret_position);
const bool is_at_left_side = const bool is_at_left_side =
is_at_start == IsLtr(caret_position.PaintFragment() is_at_start == IsLtr(caret_position.cursor.CurrentResolvedDirection());
->PhysicalFragment()
.ResolvedDirection());
return is_at_left_side ? SideAffinity::kLeft : SideAffinity::kRight; return is_at_left_side ? SideAffinity::kLeft : SideAffinity::kRight;
} }
...@@ -236,9 +242,8 @@ class AbstractInlineBoxAndSideAffinity { ...@@ -236,9 +242,8 @@ class AbstractInlineBoxAndSideAffinity {
explicit AbstractInlineBoxAndSideAffinity( explicit AbstractInlineBoxAndSideAffinity(
const NGCaretPosition& caret_position) const NGCaretPosition& caret_position)
: box_(*caret_position.PaintFragment()), : box_(caret_position.cursor), side_(GetSideAffinity(caret_position)) {
side_(GetSideAffinity(caret_position)) { DCHECK(!caret_position.IsNull());
DCHECK(caret_position.PaintFragment());
} }
InlineBoxPosition ToInlineBoxPosition() const { InlineBoxPosition ToInlineBoxPosition() const {
...@@ -253,23 +258,18 @@ class AbstractInlineBoxAndSideAffinity { ...@@ -253,23 +258,18 @@ class AbstractInlineBoxAndSideAffinity {
NGCaretPosition ToNGCaretPosition() const { NGCaretPosition ToNGCaretPosition() const {
DCHECK(box_.IsNG()); DCHECK(box_.IsNG());
const bool is_at_start = IsLtr(box_.Direction()) == AtLeftSide(); const bool is_at_start = IsLtr(box_.Direction()) == AtLeftSide();
const NGPaintFragment& fragment = box_.GetNGPaintFragment(); NGInlineCursor cursor(box_.GetCursor());
const NGPhysicalFragment& physical_fragment = fragment.PhysicalFragment();
DCHECK(physical_fragment.IsInline());
NGInlineCursor cursor;
cursor.MoveTo(fragment);
if (physical_fragment.IsBox()) { if (!cursor.IsText()) {
return {cursor, return {cursor,
is_at_start ? NGCaretPositionType::kBeforeBox is_at_start ? NGCaretPositionType::kBeforeBox
: NGCaretPositionType::kAfterBox, : NGCaretPositionType::kAfterBox,
base::nullopt}; base::nullopt};
} }
const auto& text_fragment = To<NGPhysicalTextFragment>(physical_fragment); return {cursor, NGCaretPositionType::kAtTextOffset,
return { is_at_start ? cursor.CurrentTextStartOffset()
cursor, NGCaretPositionType::kAtTextOffset, : cursor.CurrentTextEndOffset()};
is_at_start ? text_fragment.StartOffset() : text_fragment.EndOffset()};
} }
PositionInFlatTree GetPosition() const { PositionInFlatTree GetPosition() const {
...@@ -734,9 +734,8 @@ class RangeSelectionAdjuster { ...@@ -734,9 +734,8 @@ class RangeSelectionAdjuster {
const NGCaretPosition caret_position = ComputeNGCaretPosition(adjusted); const NGCaretPosition caret_position = ComputeNGCaretPosition(adjusted);
if (caret_position.IsNull()) if (caret_position.IsNull())
return RenderedPosition(); return RenderedPosition();
return RenderedPosition( return RenderedPosition(AbstractInlineBox(caret_position.cursor),
AbstractInlineBox(*caret_position.PaintFragment()), GetPotentialBidiBoundaryType(caret_position));
GetPotentialBidiBoundaryType(caret_position));
} }
const InlineBoxPosition box_position = ComputeInlineBoxPosition(adjusted); const InlineBoxPosition box_position = ComputeInlineBoxPosition(adjusted);
...@@ -874,11 +873,4 @@ TextDirection ParagraphDirectionOf(const InlineBox& box) { ...@@ -874,11 +873,4 @@ TextDirection ParagraphDirectionOf(const InlineBox& box) {
return DirectionFromLevel(min_level); return DirectionFromLevel(min_level);
} }
// TODO(xiaochengh): Move this function to a better place
TextDirection ParagraphDirectionOf(const NGPaintFragment& fragment) {
const auto& line_box = To<NGPhysicalLineBoxFragment>(
fragment.ContainerLineBox()->PhysicalFragment());
return line_box.BaseDirection();
}
} // namespace blink } // namespace blink
...@@ -650,6 +650,25 @@ void NGInlineCursor::MoveTo(const LayoutObject& layout_object) { ...@@ -650,6 +650,25 @@ void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
MoveToNext(); MoveToNext();
} }
void NGInlineCursor::MoveTo(const NGInlineCursor& cursor) {
if (const NGPaintFragment* paint_fragment = cursor.CurrentPaintFragment()) {
MoveTo(*paint_fragment);
return;
}
if (cursor.current_item_) {
if (!fragment_items_)
SetRoot(*cursor.fragment_items_);
// Note: We use address instead of iterato because we can't compare
// iterators in different span. See |base::CheckedContiguousIterator<T>|.
const ptrdiff_t index = &*cursor.item_iter_ - &*items_.begin();
DCHECK_GE(index, 0);
DCHECK_LT(static_cast<size_t>(index), items_.size());
MoveToItem(items_.begin() + index);
return;
}
*this = cursor;
}
void NGInlineCursor::MoveTo(const NGPaintFragment& paint_fragment) { void NGInlineCursor::MoveTo(const NGPaintFragment& paint_fragment) {
DCHECK(!fragment_items_); DCHECK(!fragment_items_);
if (!root_paint_fragment_) if (!root_paint_fragment_)
......
...@@ -210,6 +210,11 @@ class CORE_EXPORT NGInlineCursor { ...@@ -210,6 +210,11 @@ class CORE_EXPORT NGInlineCursor {
// Functions to move the current position. // Functions to move the current position.
// //
// Move the current position at |cursor|. Unlinke copy constrcutr, this
// function doesn't copy root. Note: The current position in |cursor|
// should be part of |this| cursor.
void MoveTo(const NGInlineCursor& cursor);
// Move the current posint at |paint_fragment|. // Move the current posint at |paint_fragment|.
void MoveTo(const NGPaintFragment& paint_fragment); void MoveTo(const NGPaintFragment& paint_fragment);
......
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