Commit a6346780 authored by Yoshifumi Inoue's avatar Yoshifumi Inoue Committed by Commit Bot

Make NGInlineCursor to support culled inline

This patch makes |NGInlineCursor| to support culled inline box to repalce
|NGInlineFragmentTraversal::SelfFragmentsOf()| with |NGInlineCursor| for
preparation of migrating |NGFragmentItem|.

Bug: 982194
Change-Id: I86d90dac19780af31defddebc09393a5ae836a3d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1855618
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@{#705852}
parent b69056dc
...@@ -72,7 +72,8 @@ NGInlineCursor::NGInlineCursor(const NGInlineCursor& other) ...@@ -72,7 +72,8 @@ NGInlineCursor::NGInlineCursor(const NGInlineCursor& other)
current_item_(other.current_item_), current_item_(other.current_item_),
fragment_items_(other.fragment_items_), fragment_items_(other.fragment_items_),
root_paint_fragment_(other.root_paint_fragment_), root_paint_fragment_(other.root_paint_fragment_),
current_paint_fragment_(other.current_paint_fragment_) {} current_paint_fragment_(other.current_paint_fragment_),
layout_inline_(other.layout_inline_) {}
bool NGInlineCursor::operator==(const NGInlineCursor& other) const { bool NGInlineCursor::operator==(const NGInlineCursor& other) const {
if (root_paint_fragment_) { if (root_paint_fragment_) {
...@@ -137,6 +138,12 @@ bool NGInlineCursor::IsHiddenForPaint() const { ...@@ -137,6 +138,12 @@ bool NGInlineCursor::IsHiddenForPaint() const {
return false; return false;
} }
bool NGInlineCursor::IsInclusiveDescendantOf(
const LayoutObject& layout_object) const {
return CurrentLayoutObject() &&
CurrentLayoutObject()->IsDescendantOf(&layout_object);
}
bool NGInlineCursor::IsLastLineInInlineBlock() const { bool NGInlineCursor::IsLastLineInInlineBlock() const {
DCHECK(IsLineBox()); DCHECK(IsLineBox());
if (!GetLayoutBlockFlow()->IsAtomicInlineLevel()) if (!GetLayoutBlockFlow()->IsAtomicInlineLevel())
...@@ -313,7 +320,7 @@ void NGInlineCursor::MakeNull() { ...@@ -313,7 +320,7 @@ void NGInlineCursor::MakeNull() {
NOTREACHED(); NOTREACHED();
} }
void NGInlineCursor::MoveTo(const LayoutObject& layout_object) { void NGInlineCursor::InternalMoveTo(const LayoutObject& layout_object) {
DCHECK(layout_object.IsInLayoutNGInlineFormattingContext()); DCHECK(layout_object.IsInLayoutNGInlineFormattingContext());
if (root_paint_fragment_) { if (root_paint_fragment_) {
const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object); const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
...@@ -327,6 +334,19 @@ void NGInlineCursor::MoveTo(const LayoutObject& layout_object) { ...@@ -327,6 +334,19 @@ void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
MoveToNextItem(); MoveToNextItem();
} }
void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
InternalMoveTo(layout_object);
if (IsNotNull() || !layout_object.IsLayoutInline()) {
layout_inline_ = nullptr;
return;
}
// In case of |layout_object| is cullred inline.
layout_inline_ = ToLayoutInline(&layout_object);
MoveToFirst();
while (IsNotNull() && !IsInclusiveDescendantOf(layout_object))
MoveToNext();
}
void NGInlineCursor::MoveTo(const NGPaintFragment& paint_fragment) { void NGInlineCursor::MoveTo(const NGPaintFragment& paint_fragment) {
DCHECK(root_paint_fragment_); DCHECK(root_paint_fragment_);
DCHECK(paint_fragment.IsDescendantOfNotSelf(*root_paint_fragment_)) DCHECK(paint_fragment.IsDescendantOfNotSelf(*root_paint_fragment_))
...@@ -349,6 +369,18 @@ void NGInlineCursor::MoveToContainingLine() { ...@@ -349,6 +369,18 @@ void NGInlineCursor::MoveToContainingLine() {
NOTREACHED(); NOTREACHED();
} }
void NGInlineCursor::MoveToFirst() {
if (root_paint_fragment_) {
current_paint_fragment_ = root_paint_fragment_->FirstChild();
return;
}
if (IsItemCursor()) {
MoveToItem(items_.begin());
return;
}
NOTREACHED();
}
void NGInlineCursor::MoveToFirstChild() { void NGInlineCursor::MoveToFirstChild() {
DCHECK(CanHaveChildren()); DCHECK(CanHaveChildren());
if (!TryToMoveToFirstChild()) if (!TryToMoveToFirstChild())
...@@ -363,8 +395,8 @@ void NGInlineCursor::MoveToLastChild() { ...@@ -363,8 +395,8 @@ void NGInlineCursor::MoveToLastChild() {
void NGInlineCursor::MoveToLastLogicalLeaf() { void NGInlineCursor::MoveToLastLogicalLeaf() {
DCHECK(IsLineBox()); DCHECK(IsLineBox());
// TODO(yosin): This isn't correct for mixed Bidi. Fix it. Besides, we should // TODO(yosin): This isn't correct for mixed Bidi. Fix it. Besides, we
// compute and store it during layout. // should compute and store it during layout.
// TODO(yosin): We should check direction of each container instead of line // TODO(yosin): We should check direction of each container instead of line
// box. See also |NGPhysicalLineBoxFragment::LastLogicalLeaf()|. // box. See also |NGPhysicalLineBoxFragment::LastLogicalLeaf()|.
if (IsLtr(CurrentStyle().Direction())) { if (IsLtr(CurrentStyle().Direction())) {
...@@ -383,6 +415,13 @@ void NGInlineCursor::MoveToNext() { ...@@ -383,6 +415,13 @@ void NGInlineCursor::MoveToNext() {
} }
void NGInlineCursor::MoveToNextForSameLayoutObject() { void NGInlineCursor::MoveToNextForSameLayoutObject() {
if (layout_inline_) {
// Move to next fragment in culled inline box undef |layout_inline_|.
do {
MoveToNext();
} while (IsNotNull() && !IsInclusiveDescendantOf(*layout_inline_));
return;
}
if (current_paint_fragment_) { if (current_paint_fragment_) {
if (auto* paint_fragment = if (auto* paint_fragment =
current_paint_fragment_->NextForSameLayoutObject()) current_paint_fragment_->NextForSameLayoutObject())
......
...@@ -13,8 +13,9 @@ ...@@ -13,8 +13,9 @@
namespace blink { namespace blink {
class ComputedStyle; class ComputedStyle;
class LayoutObject;
class LayoutBlockFlow; class LayoutBlockFlow;
class LayoutInline;
class LayoutObject;
class NGFragmentItem; class NGFragmentItem;
class NGFragmentItems; class NGFragmentItems;
class NGPaintFragment; class NGPaintFragment;
...@@ -175,6 +176,10 @@ class CORE_EXPORT NGInlineCursor { ...@@ -175,6 +176,10 @@ class CORE_EXPORT NGInlineCursor {
// we'll call it "void cursor" instead of "null cursor". // we'll call it "void cursor" instead of "null cursor".
NGInlineCursor() = delete; NGInlineCursor() = delete;
// True if current position is descendant or self of |layout_object|.
// Note: This function is used for moving cursor in culled inline boxes.
bool IsInclusiveDescendantOf(const LayoutObject& layout_object) const;
// True if the current position is a last line in inline block. It is error // True if the current position is a last line in inline block. It is error
// to call at end or the current position is not line. // to call at end or the current position is not line.
bool IsLastLineInInlineBlock() const; bool IsLastLineInInlineBlock() const;
...@@ -183,6 +188,12 @@ class CORE_EXPORT NGInlineCursor { ...@@ -183,6 +188,12 @@ class CORE_EXPORT NGInlineCursor {
// fragment, cursor moves to first/last child to parent has no children. // fragment, cursor moves to first/last child to parent has no children.
void MakeNull(); void MakeNull();
// Move the cursor position to the first fragment in tree.
void MoveToFirst();
// Same as |MoveTo()| but not support culled inline.
void InternalMoveTo(const LayoutObject& layout_object);
void SetRoot(const NGFragmentItems& items); void SetRoot(const NGFragmentItems& items);
void SetRoot(ItemsSpan items); void SetRoot(ItemsSpan items);
void SetRoot(const NGPaintFragment& root_paint_fragment); void SetRoot(const NGPaintFragment& root_paint_fragment);
...@@ -205,6 +216,9 @@ class CORE_EXPORT NGInlineCursor { ...@@ -205,6 +216,9 @@ class CORE_EXPORT NGInlineCursor {
const NGPaintFragment* root_paint_fragment_ = nullptr; const NGPaintFragment* root_paint_fragment_ = nullptr;
const NGPaintFragment* current_paint_fragment_ = nullptr; const NGPaintFragment* current_paint_fragment_ = nullptr;
// Used in |MoveToNextForSameLayoutObject()| to support culled inline.
const LayoutInline* layout_inline_ = nullptr;
}; };
CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGInlineCursor&); CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGInlineCursor&);
......
...@@ -82,12 +82,13 @@ TEST_P(NGInlineCursorTest, ContainingLine) { ...@@ -82,12 +82,13 @@ TEST_P(NGInlineCursorTest, ContainingLine) {
cursor.MoveToContainingLine(); cursor.MoveToContainingLine();
EXPECT_EQ(line1, cursor); EXPECT_EQ(line1, cursor);
const LayoutObject& target = *GetLayoutObjectByElementId("target"); const LayoutInline& target =
ToLayoutInline(*GetLayoutObjectByElementId("target"));
cursor.MoveTo(target); cursor.MoveTo(target);
cursor.MoveToContainingLine(); cursor.MoveToContainingLine();
EXPECT_EQ(line1, cursor); EXPECT_EQ(line1, cursor);
cursor.MoveTo(*target.SlowFirstChild()); cursor.MoveTo(*target.FirstChild());
cursor.MoveToContainingLine(); cursor.MoveToContainingLine();
EXPECT_EQ(line1, cursor); EXPECT_EQ(line1, cursor);
...@@ -96,6 +97,20 @@ TEST_P(NGInlineCursorTest, ContainingLine) { ...@@ -96,6 +97,20 @@ TEST_P(NGInlineCursorTest, ContainingLine) {
EXPECT_EQ(line2, cursor); EXPECT_EQ(line2, cursor);
} }
TEST_P(NGInlineCursorTest, CulledInline) {
NGInlineCursor cursor =
SetupCursor("<div id=root><a><b>abc</b><br><i>xyz</i></a></div>");
const LayoutInline& layout_inline =
ToLayoutInline(*cursor.GetLayoutBlockFlow()->FirstChild());
cursor.MoveTo(layout_inline);
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextForSameLayoutObject();
}
EXPECT_THAT(list, ElementsAre("abc", "", "xyz"));
}
TEST_P(NGInlineCursorTest, FirstChild) { TEST_P(NGInlineCursorTest, FirstChild) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline. // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("a, b { background: gray; }"); InsertStyleElement("a, b { background: gray; }");
......
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