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)
current_item_(other.current_item_),
fragment_items_(other.fragment_items_),
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 {
if (root_paint_fragment_) {
......@@ -137,6 +138,12 @@ bool NGInlineCursor::IsHiddenForPaint() const {
return false;
}
bool NGInlineCursor::IsInclusiveDescendantOf(
const LayoutObject& layout_object) const {
return CurrentLayoutObject() &&
CurrentLayoutObject()->IsDescendantOf(&layout_object);
}
bool NGInlineCursor::IsLastLineInInlineBlock() const {
DCHECK(IsLineBox());
if (!GetLayoutBlockFlow()->IsAtomicInlineLevel())
......@@ -313,7 +320,7 @@ void NGInlineCursor::MakeNull() {
NOTREACHED();
}
void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
void NGInlineCursor::InternalMoveTo(const LayoutObject& layout_object) {
DCHECK(layout_object.IsInLayoutNGInlineFormattingContext());
if (root_paint_fragment_) {
const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
......@@ -327,6 +334,19 @@ void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
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) {
DCHECK(root_paint_fragment_);
DCHECK(paint_fragment.IsDescendantOfNotSelf(*root_paint_fragment_))
......@@ -349,6 +369,18 @@ void NGInlineCursor::MoveToContainingLine() {
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() {
DCHECK(CanHaveChildren());
if (!TryToMoveToFirstChild())
......@@ -363,8 +395,8 @@ void NGInlineCursor::MoveToLastChild() {
void NGInlineCursor::MoveToLastLogicalLeaf() {
DCHECK(IsLineBox());
// TODO(yosin): This isn't correct for mixed Bidi. Fix it. Besides, we should
// compute and store it during layout.
// TODO(yosin): This isn't correct for mixed Bidi. Fix it. Besides, we
// should compute and store it during layout.
// TODO(yosin): We should check direction of each container instead of line
// box. See also |NGPhysicalLineBoxFragment::LastLogicalLeaf()|.
if (IsLtr(CurrentStyle().Direction())) {
......@@ -383,6 +415,13 @@ void NGInlineCursor::MoveToNext() {
}
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 (auto* paint_fragment =
current_paint_fragment_->NextForSameLayoutObject())
......
......@@ -13,8 +13,9 @@
namespace blink {
class ComputedStyle;
class LayoutObject;
class LayoutBlockFlow;
class LayoutInline;
class LayoutObject;
class NGFragmentItem;
class NGFragmentItems;
class NGPaintFragment;
......@@ -175,6 +176,10 @@ class CORE_EXPORT NGInlineCursor {
// we'll call it "void cursor" instead of "null cursor".
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
// to call at end or the current position is not line.
bool IsLastLineInInlineBlock() const;
......@@ -183,6 +188,12 @@ class CORE_EXPORT NGInlineCursor {
// fragment, cursor moves to first/last child to parent has no children.
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(ItemsSpan items);
void SetRoot(const NGPaintFragment& root_paint_fragment);
......@@ -205,6 +216,9 @@ class CORE_EXPORT NGInlineCursor {
const NGPaintFragment* root_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&);
......
......@@ -82,12 +82,13 @@ TEST_P(NGInlineCursorTest, ContainingLine) {
cursor.MoveToContainingLine();
EXPECT_EQ(line1, cursor);
const LayoutObject& target = *GetLayoutObjectByElementId("target");
const LayoutInline& target =
ToLayoutInline(*GetLayoutObjectByElementId("target"));
cursor.MoveTo(target);
cursor.MoveToContainingLine();
EXPECT_EQ(line1, cursor);
cursor.MoveTo(*target.SlowFirstChild());
cursor.MoveTo(*target.FirstChild());
cursor.MoveToContainingLine();
EXPECT_EQ(line1, cursor);
......@@ -96,6 +97,20 @@ TEST_P(NGInlineCursorTest, ContainingLine) {
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) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
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