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

Introduce NGInlineCursor::MoveTo{Next,Previous}InlineLeaf{,IgnoringLineBreak}()

This patch introduces member functions to |NGInlineCursor| for preparation of
the patch[1]:
 - MoveToNextInlineLeaf()
 - MoveToNextInlineLeafIgnoringLineBreak()
 - MoveToPreviousInlineLeaf()
 - MoveToPreviousInlineLeafIgnoringLineBreak()
along with helper functions:
 - MoveToPrevious()
  * MoveToPreviousPaintFragment()
  * MoveToPreviousSiblingPaintFragment()
used in |AbstractInlineBox|, |AXInlineTextBox| and |AXLayoutObject|.

Note: These functions are similar to |NGPaintFragmentTraversal|, but these
functions doesn't skip adjacent inline leaf when starting from non-inline
leaf fragment.
 PFT |<b>abc</b><b>def</b> => next =>|<b>abc</b><b>|def</b>
 IC  |<b>abc</b><b>def</b> => next => <b>|abc</b><b>|def</b>

This change affects only |{Next,Previous}OnLineInlineNG()| for |AXLayoutObject|.

[1] http://crrev.com/c/1888242 Utilize NGInlineCursor for inline box traversal

Bug: 982194
Change-Id: I0eac23fde8e4eb1028c98c76c17bc584d4e86bd2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1895258
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Auto-Submit: Yoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712056}
parent 95fdfd8d
...@@ -712,6 +712,19 @@ void NGInlineCursor::MoveToNextForSameLayoutObject() { ...@@ -712,6 +712,19 @@ void NGInlineCursor::MoveToNextForSameLayoutObject() {
} }
} }
void NGInlineCursor::MoveToNextInlineLeaf() {
if (IsNotNull() && IsInlineLeaf())
MoveToNext();
while (IsNotNull() && !IsInlineLeaf())
MoveToNext();
}
void NGInlineCursor::MoveToNextInlineLeafIgnoringLineBreak() {
do {
MoveToNextInlineLeaf();
} while (IsNotNull() && IsLineBreak());
}
void NGInlineCursor::MoveToNextLine() { void NGInlineCursor::MoveToNextLine() {
DCHECK(IsLineBox()); DCHECK(IsLineBox());
if (current_paint_fragment_) { if (current_paint_fragment_) {
...@@ -740,6 +753,25 @@ void NGInlineCursor::MoveToNextSkippingChildren() { ...@@ -740,6 +753,25 @@ void NGInlineCursor::MoveToNextSkippingChildren() {
MoveToNextItemSkippingChildren(); MoveToNextItemSkippingChildren();
} }
void NGInlineCursor::MoveToPrevious() {
if (root_paint_fragment_)
return MoveToPreviousPaintFragment();
MoveToPreviousItem();
}
void NGInlineCursor::MoveToPreviousInlineLeaf() {
if (IsNotNull() && IsInlineLeaf())
MoveToPrevious();
while (IsNotNull() && !IsInlineLeaf())
MoveToPrevious();
}
void NGInlineCursor::MoveToPreviousInlineLeafIgnoringLineBreak() {
do {
MoveToPreviousInlineLeaf();
} while (IsNotNull() && IsLineBreak());
}
void NGInlineCursor::MoveToPreviousLine() { void NGInlineCursor::MoveToPreviousLine() {
DCHECK(IsLineBox()); DCHECK(IsLineBox());
if (current_paint_fragment_) { if (current_paint_fragment_) {
...@@ -866,6 +898,30 @@ void NGInlineCursor::MoveToNextPaintFragmentSkippingChildren() { ...@@ -866,6 +898,30 @@ void NGInlineCursor::MoveToNextPaintFragmentSkippingChildren() {
} }
} }
void NGInlineCursor::MoveToPreviousPaintFragment() {
DCHECK(IsPaintFragmentCursor() && current_paint_fragment_);
const NGPaintFragment* const parent = current_paint_fragment_->Parent();
MoveToPreviousSiblingPaintFragment();
if (current_paint_fragment_) {
while (TryToMoveToLastChild())
continue;
return;
}
current_paint_fragment_ = parent == root_paint_fragment_ ? nullptr : parent;
}
void NGInlineCursor::MoveToPreviousSiblingPaintFragment() {
DCHECK(IsPaintFragmentCursor() && current_paint_fragment_);
const NGPaintFragment* const current = current_paint_fragment_;
current_paint_fragment_ = nullptr;
for (auto* sibling : current->Parent()->Children()) {
if (sibling == current)
return;
current_paint_fragment_ = sibling;
}
NOTREACHED();
}
std::ostream& operator<<(std::ostream& ostream, const NGInlineCursor& cursor) { std::ostream& operator<<(std::ostream& ostream, const NGInlineCursor& cursor) {
if (cursor.IsNull()) if (cursor.IsNull())
return ostream << "NGInlineCursor()"; return ostream << "NGInlineCursor()";
......
...@@ -248,6 +248,15 @@ class CORE_EXPORT NGInlineCursor { ...@@ -248,6 +248,15 @@ class CORE_EXPORT NGInlineCursor {
// Same as |MoveToNext| except that this skips children even if they exist. // Same as |MoveToNext| except that this skips children even if they exist.
void MoveToNextSkippingChildren(); void MoveToNextSkippingChildren();
// Move the current to next/previous inline leaf.
void MoveToNextInlineLeaf();
void MoveToNextInlineLeafIgnoringLineBreak();
void MoveToPreviousInlineLeaf();
void MoveToPreviousInlineLeafIgnoringLineBreak();
// Move the cursor position to previous fragment in pre-order DFS.
void MoveToPrevious();
// Move the current position to previous line. It is error to call other than // Move the current position to previous line. It is error to call other than
// line box. // line box.
void MoveToPreviousLine(); void MoveToPreviousLine();
...@@ -299,6 +308,8 @@ class CORE_EXPORT NGInlineCursor { ...@@ -299,6 +308,8 @@ class CORE_EXPORT NGInlineCursor {
void MoveToNextSiblingPaintFragment(); void MoveToNextSiblingPaintFragment();
void MoveToNextPaintFragmentSkippingChildren(); void MoveToNextPaintFragmentSkippingChildren();
void MoveToPreviousPaintFragment();
void MoveToPreviousSiblingPaintFragment();
ItemsSpan items_; ItemsSpan items_;
ItemsSpan::iterator item_iter_; ItemsSpan::iterator item_iter_;
const NGFragmentItem* current_item_ = nullptr; const NGFragmentItem* current_item_ = nullptr;
......
...@@ -288,6 +288,32 @@ TEST_P(NGInlineCursorTest, Next) { ...@@ -288,6 +288,32 @@ TEST_P(NGInlineCursorTest, Next) {
"#span2", "text3", "text4", "text5")); "#span2", "text3", "text4", "text5"));
} }
TEST_P(NGInlineCursorTest, NextInlineLeaf) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor =
SetupCursor("<div id=root>abc<b>DEF</b><br>xyz</div>");
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextInlineLeaf();
}
EXPECT_THAT(list, ElementsAre("#linebox", "abc", "DEF", "", "xyz"));
}
TEST_P(NGInlineCursorTest, NextInlineLeafIgnoringLineBreak) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor =
SetupCursor("<div id=root>abc<b>DEF</b><br>xyz</div>");
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextInlineLeafIgnoringLineBreak();
}
EXPECT_THAT(list, ElementsAre("#linebox", "abc", "DEF", "xyz"));
}
TEST_P(NGInlineCursorTest, NextLine) { TEST_P(NGInlineCursorTest, NextLine) {
NGInlineCursor cursor = SetupCursor("<div id=root>abc<br>xyz</div>"); NGInlineCursor cursor = SetupCursor("<div id=root>abc<br>xyz</div>");
NGInlineCursor line1(cursor); NGInlineCursor line1(cursor);
...@@ -410,6 +436,73 @@ TEST_P(NGInlineCursorTest, EmptyOutOfFlow) { ...@@ -410,6 +436,73 @@ TEST_P(NGInlineCursorTest, EmptyOutOfFlow) {
EXPECT_THAT(list, ElementsAre()); EXPECT_THAT(list, ElementsAre());
} }
TEST_P(NGInlineCursorTest, Previous) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor =
SetupCursor("<div id=root>abc<b>DEF</b><br>xyz</div>");
// TDOO(yosin): We'll use |MoveTo(*cursor.GetLayoutBlockFlow()->LastChild())|
// once |MoveTo()| works with rootless cursor.
while (cursor) {
NGInlineCursor next(cursor);
next.MoveToNext();
if (!next)
break;
cursor = next;
}
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToPrevious();
}
EXPECT_THAT(list, ElementsAre("xyz", "#linebox", "", "DEF", "LayoutInline B",
"abc", "#linebox"));
}
TEST_P(NGInlineCursorTest, PreviousInlineLeaf) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor =
SetupCursor("<div id=root>abc<b>DEF</b><br>xyz</div>");
// TDOO(yosin): We'll use |MoveTo(*cursor.GetLayoutBlockFlow()->LastChild())|
// once |MoveTo()| works with rootless cursor.
while (cursor) {
NGInlineCursor next(cursor);
next.MoveToNext();
if (!next)
break;
cursor = next;
}
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToPreviousInlineLeaf();
}
EXPECT_THAT(list, ElementsAre("xyz", "", "DEF", "abc"));
}
TEST_P(NGInlineCursorTest, PreviousInlineLeafIgnoringLineBreak) {
// TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
InsertStyleElement("b { background: gray; }");
NGInlineCursor cursor =
SetupCursor("<div id=root>abc<b>DEF</b><br>xyz</div>");
// TDOO(yosin): We'll use |MoveTo(*cursor.GetLayoutBlockFlow()->LastChild())|
// once |MoveTo()| works with rootless cursor.
while (cursor) {
NGInlineCursor next(cursor);
next.MoveToNext();
if (!next)
break;
cursor = next;
}
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToPreviousInlineLeafIgnoringLineBreak();
}
EXPECT_THAT(list, ElementsAre("xyz", "DEF", "abc"));
}
TEST_P(NGInlineCursorTest, PreviousLine) { TEST_P(NGInlineCursorTest, PreviousLine) {
NGInlineCursor cursor = SetupCursor("<div id=root>abc<br>xyz</div>"); NGInlineCursor cursor = SetupCursor("<div id=root>abc<br>xyz</div>");
NGInlineCursor line1(cursor); NGInlineCursor line1(cursor);
......
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