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

[LayoutNG] Introduce NGPaintFragmentTraversal::MoveToParent() and MoveToPrevious()

This patch inttroduces |MoveToParent()| and |MoveToPrevious()| in
|NGPaintFragmentTraversal| class for the patch[1], which uses |MoveToPrevious()|
to find text fragment in same line.

This patch also utilize |MoveToParent()| in |MoveToNext()| to share code for
improving code health.

[1] http://crrev.com/c/1104082 [LayoutNG] Adapt accessibility module to
LayoutNG;

Bug: 774229
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng;luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: If65e3015b8f4ed768325c0e13df121c0bc378580
Reviewed-on: https://chromium-review.googlesource.com/1109609Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569199}
parent 289afd80
...@@ -201,33 +201,53 @@ void NGPaintFragmentTraversal::MoveToNext() { ...@@ -201,33 +201,53 @@ void NGPaintFragmentTraversal::MoveToNext() {
} }
void NGPaintFragmentTraversal::MoveToNextSiblingOrAncestor() { void NGPaintFragmentTraversal::MoveToNextSiblingOrAncestor() {
if (IsAtEnd()) while (!IsAtEnd()) {
return;
while (true) {
// Check if we have a next sibling. // Check if we have a next sibling.
auto& stack_top = stack_.back(); auto& stack_top = stack_.back();
if (++stack_top.index < stack_top.parent->Children().size()) { if (++stack_top.index < stack_top.parent->Children().size()) {
current_ = stack_top.parent->Children()[stack_top.index].get(); current_ = stack_top.parent->Children()[stack_top.index].get();
return; return;
} }
MoveToParent();
}
}
// Check the next parent in the stack. If the stack is not empty, traverse void NGPaintFragmentTraversal::MoveToParent() {
// its next sibiling. if (IsAtEnd())
stack_.pop_back(); return;
if (!stack_.IsEmpty()) DCHECK(!stack_.IsEmpty());
continue; const NGPaintFragment& parent = *stack_.back().parent;
stack_.pop_back();
if (&parent == &root_) {
DCHECK(stack_.IsEmpty());
current_ = nullptr;
return;
}
if (stack_.IsEmpty()) {
// We might have started with |MoveTo()|, and thus computing parent stack // We might have started with |MoveTo()|, and thus computing parent stack
// was deferred. Check parents until we reach the |root_|. // was deferred.
const NGPaintFragment* parent = current_->Parent(); Push(parent);
DCHECK(parent); return;
if (parent == &root_) { }
current_ = nullptr; DCHECK_EQ(&parent,
return; stack_.back().parent->Children()[stack_.back().index].get());
} current_ = &parent;
Push(*parent); }
void NGPaintFragmentTraversal::MoveToPrevious() {
if (IsAtEnd())
return;
DCHECK(!stack_.IsEmpty());
auto& stack_top = stack_.back();
if (stack_top.index == 0) {
// There is no previous sibling of |current_|. We move to parent.
MoveToParent();
return;
} }
--stack_top.index;
current_ = stack_top.parent->Children()[stack_top.index].get();
while (!current_->Children().IsEmpty())
Push(*current_, current_->Children().size() - 1);
} }
Vector<NGPaintFragmentWithContainerOffset> Vector<NGPaintFragmentWithContainerOffset>
......
...@@ -73,12 +73,24 @@ class CORE_EXPORT NGPaintFragmentTraversal { ...@@ -73,12 +73,24 @@ class CORE_EXPORT NGPaintFragmentTraversal {
void MoveTo(const NGPaintFragment& fragment); void MoveTo(const NGPaintFragment& fragment);
// Move to the next node using the pre-order depth-first-search. // Move to the next node using the pre-order depth-first-search.
// Note: When |IsAtEnd()| is true, this function does nothing.
void MoveToNext(); void MoveToNext();
// Move to the next sibling, or next ancestor node using the pre-order // Move to the next sibling, or next ancestor node using the pre-order
// depth-first-search, skipping children of the current node. // depth-first-search, skipping children of the current node.
void MoveToNextSiblingOrAncestor(); void MoveToNextSiblingOrAncestor();
// Move to the parent of current fragment. When |current_| is a child of
// |root_|, this function makes |IsAtEnd()| to true.
// Note: When |IsAtEnd()| is true, this function does nothing.
void MoveToParent();
// Move to the previous node using the pre-order depth-first-search. When
// |current_| is the first child of |root_|, this function makes |IsAtEnd()|
// to true.
// Note: When |IsAtEnd()| is true, this function does nothing.
void MoveToPrevious();
// //
// Following functions are static, similar to DOM traversal utilities. // Following functions are static, similar to DOM traversal utilities.
// //
...@@ -119,7 +131,12 @@ class CORE_EXPORT NGPaintFragmentTraversal { ...@@ -119,7 +131,12 @@ class CORE_EXPORT NGPaintFragmentTraversal {
void Push(const NGPaintFragment& parent, unsigned index); void Push(const NGPaintFragment& parent, unsigned index);
void Push(const NGPaintFragment& fragment); void Push(const NGPaintFragment& fragment);
// |current_| holds a |NGPaintFragment| specified by |index|th child of
// |parent| of the last element of |stack_|.
const NGPaintFragment* current_ = nullptr; const NGPaintFragment* current_ = nullptr;
// The root of subtree where traversing is taken place. |root_| is excluded
// from traversal. |current_| can't |root_|.
const NGPaintFragment& root_; const NGPaintFragment& root_;
// The stack of parent and its child index up to the root. Each stack entry // The stack of parent and its child index up to the root. Each stack entry
......
...@@ -41,6 +41,16 @@ class NGPaintFragmentTraversalTest : public RenderingTest, ...@@ -41,6 +41,16 @@ class NGPaintFragmentTraversalTest : public RenderingTest,
return results; return results;
} }
Vector<const NGPaintFragment*> ToReverseDepthFirstList(
NGPaintFragmentTraversal* traversal) const {
Vector<const NGPaintFragment*> results;
for (; *traversal; traversal->MoveToPrevious()) {
const NGPaintFragment& fragment = **traversal;
results.push_back(&fragment);
}
return results;
}
LayoutBlockFlow* layout_block_flow_; LayoutBlockFlow* layout_block_flow_;
NGPaintFragment* root_fragment_; NGPaintFragment* root_fragment_;
}; };
...@@ -83,6 +93,46 @@ TEST_F(NGPaintFragmentTraversalTest, MoveToNextWithRoot) { ...@@ -83,6 +93,46 @@ TEST_F(NGPaintFragmentTraversalTest, MoveToNextWithRoot) {
span->Children()[0].get(), br})); span->Children()[0].get(), br}));
} }
TEST_F(NGPaintFragmentTraversalTest, MoveToPrevious) {
SetUpHtml("t", R"HTML(
<div id=t>
line0
<span style="background: red">red</span>
<br>
line1
</div>
)HTML");
NGPaintFragmentTraversal traversal(*root_fragment_);
NGPaintFragment* line0 = root_fragment_->Children()[0].get();
NGPaintFragment* line1 = root_fragment_->Children()[1].get();
NGPaintFragment* span = line0->Children()[1].get();
NGPaintFragment* br = line0->Children()[2].get();
traversal.MoveTo(*line1->Children()[0].get());
EXPECT_THAT(ToReverseDepthFirstList(&traversal),
ElementsAreArray({line1->Children()[0].get(), line1, br,
span->Children()[0].get(), span,
line0->Children()[0].get(), line0}));
}
TEST_F(NGPaintFragmentTraversalTest, MoveToPreviousWithRoot) {
SetUpHtml("t", R"HTML(
<div id=t>
line0
<span style="background: red">red</span>
<br>
line1
</div>
)HTML");
NGPaintFragment* line0 = root_fragment_->Children()[0].get();
NGPaintFragment* span = line0->Children()[1].get();
NGPaintFragment* br = line0->Children()[2].get();
NGPaintFragmentTraversal traversal(*line0);
traversal.MoveTo(*br);
EXPECT_THAT(ToReverseDepthFirstList(&traversal),
ElementsAreArray({br, span->Children()[0].get(), span,
line0->Children()[0].get()}));
}
TEST_F(NGPaintFragmentTraversalTest, MoveTo) { TEST_F(NGPaintFragmentTraversalTest, MoveTo) {
SetUpHtml("t", R"HTML( SetUpHtml("t", R"HTML(
<div id=t> <div id=t>
......
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