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() {
}
void NGPaintFragmentTraversal::MoveToNextSiblingOrAncestor() {
if (IsAtEnd())
return;
while (true) {
while (!IsAtEnd()) {
// Check if we have a next sibling.
auto& stack_top = stack_.back();
if (++stack_top.index < stack_top.parent->Children().size()) {
current_ = stack_top.parent->Children()[stack_top.index].get();
return;
}
MoveToParent();
}
}
// Check the next parent in the stack. If the stack is not empty, traverse
// its next sibiling.
stack_.pop_back();
if (!stack_.IsEmpty())
continue;
void NGPaintFragmentTraversal::MoveToParent() {
if (IsAtEnd())
return;
DCHECK(!stack_.IsEmpty());
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
// was deferred. Check parents until we reach the |root_|.
const NGPaintFragment* parent = current_->Parent();
DCHECK(parent);
if (parent == &root_) {
current_ = nullptr;
return;
}
Push(*parent);
// was deferred.
Push(parent);
return;
}
DCHECK_EQ(&parent,
stack_.back().parent->Children()[stack_.back().index].get());
current_ = &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>
......
......@@ -73,12 +73,24 @@ class CORE_EXPORT NGPaintFragmentTraversal {
void MoveTo(const NGPaintFragment& fragment);
// Move to the next node using the pre-order depth-first-search.
// Note: When |IsAtEnd()| is true, this function does nothing.
void MoveToNext();
// Move to the next sibling, or next ancestor node using the pre-order
// depth-first-search, skipping children of the current node.
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.
//
......@@ -119,7 +131,12 @@ class CORE_EXPORT NGPaintFragmentTraversal {
void Push(const NGPaintFragment& parent, unsigned index);
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;
// The root of subtree where traversing is taken place. |root_| is excluded
// from traversal. |current_| can't |root_|.
const NGPaintFragment& root_;
// The stack of parent and its child index up to the root. Each stack entry
......
......@@ -41,6 +41,16 @@ class NGPaintFragmentTraversalTest : public RenderingTest,
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_;
NGPaintFragment* root_fragment_;
};
......@@ -83,6 +93,46 @@ TEST_F(NGPaintFragmentTraversalTest, MoveToNextWithRoot) {
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) {
SetUpHtml("t", R"HTML(
<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