Commit 03073473 authored by yosin@chromium.org's avatar yosin@chromium.org

Introduce composed tree version of rightPositionOf()

This patch introduces composed tree version of |rightPositionOf()|
by templatizing original |rightPositionOf()| to work both DOM tree
position and composed tree position version for introducing composed tree
version of |VisibleSelection| class.

This patch also templaizes |rightVisuallyDistinctCandidate()| used by
|rightPositionOf()|.

This patch is a preparation of making selection to handle granularity for web
component, http://crrev.com/1277863002

BUG=513568
TEST=n/a; no behavior changes

Review URL: https://codereview.chromium.org/1311803004

git-svn-id: svn://svn.chromium.org/blink/trunk@201967 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent cb8cb890
...@@ -2782,14 +2782,15 @@ VisiblePositionInComposedTree leftPositionOf(const VisiblePositionInComposedTree ...@@ -2782,14 +2782,15 @@ VisiblePositionInComposedTree leftPositionOf(const VisiblePositionInComposedTree
return leftPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePosition); return leftPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePosition);
} }
static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePosition) template <typename Strategy>
static PositionAlgorithm<Strategy> rightVisuallyDistinctCandidate(const VisiblePositionTemplate<Strategy>& visiblePosition)
{ {
const Position deepPosition = visiblePosition.deepEquivalent(); const PositionAlgorithm<Strategy> deepPosition = visiblePosition.deepEquivalent();
Position p = deepPosition; PositionAlgorithm<Strategy> p = deepPosition;
if (p.isNull()) if (p.isNull())
return Position(); return PositionAlgorithm<Strategy>();
Position downstreamStart = mostForwardCaretPosition(p); const PositionAlgorithm<Strategy> downstreamStart = mostForwardCaretPosition(p);
TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
const TextAffinity affinity = visiblePosition.affinity(); const TextAffinity affinity = visiblePosition.affinity();
...@@ -2827,13 +2828,13 @@ static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos ...@@ -2827,13 +2828,13 @@ static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos
// Overshot to the right. // Overshot to the right.
InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();
if (!nextBox) { if (!nextBox) {
Position positionOnRight = primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPosition); PositionAlgorithm<Strategy> positionOnRight = primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
if (positionOnRight.isNull()) if (positionOnRight.isNull())
return Position(); return PositionAlgorithm<Strategy>();
InlineBox* boxOnRight = computeInlineBoxPosition(positionOnRight, affinity, primaryDirection).inlineBox; InlineBox* boxOnRight = computeInlineBoxPosition(positionOnRight, affinity, primaryDirection).inlineBox;
if (boxOnRight && boxOnRight->root() == box->root()) if (boxOnRight && boxOnRight->root() == box->root())
return Position(); return PositionAlgorithm<Strategy>();
return positionOnRight; return positionOnRight;
} }
...@@ -2901,8 +2902,7 @@ static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos ...@@ -2901,8 +2902,7 @@ static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos
continue; continue;
} }
} else { } else {
// Trailing edge of a secondary run. Set to the leading edge of // Trailing edge of a secondary run. Set to the leading edge of the entire run.
// the entire run.
while (true) { while (true) {
while (InlineBox* prevBox = box->prevLeafChild()) { while (InlineBox* prevBox = box->prevLeafChild()) {
if (prevBox->bidiLevel() < level) if (prevBox->bidiLevel() < level)
...@@ -2927,7 +2927,7 @@ static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos ...@@ -2927,7 +2927,7 @@ static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos
break; break;
} }
p = Position::editingPositionOf(layoutObject->node(), offset); p = PositionAlgorithm<Strategy>::editingPositionOf(layoutObject->node(), offset);
if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
return p; return p;
...@@ -2936,19 +2936,30 @@ static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos ...@@ -2936,19 +2936,30 @@ static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos
} }
} }
VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition) template <typename Strategy>
static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition)
{ {
const Position pos = rightVisuallyDistinctCandidate(visiblePosition); const PositionAlgorithm<Strategy> pos = rightVisuallyDistinctCandidate(visiblePosition);
// TODO(yosin) Why can't we move left from the last position in a tree? // FIXME: Why can't we move left from the last position in a tree?
if (pos.atStartOfTree() || pos.atEndOfTree()) if (pos.atStartOfTree() || pos.atEndOfTree())
return VisiblePosition(); return VisiblePositionTemplate<Strategy>();
VisiblePosition right = createVisiblePosition(pos); const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos);
ASSERT(right.deepEquivalent() != visiblePosition.deepEquivalent()); ASSERT(right.deepEquivalent() != visiblePosition.deepEquivalent());
return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditingBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBoundaryAtOrBefore(right, visiblePosition.deepEquivalent()); return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditingBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBoundaryAtOrBefore(right, visiblePosition.deepEquivalent());
} }
VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition)
{
return rightPositionOfAlgorithm<EditingStrategy>(visiblePosition);
}
VisiblePositionInComposedTree rightPositionOf(const VisiblePositionInComposedTree& visiblePosition)
{
return rightPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePosition);
}
template <typename Strategy> template <typename Strategy>
static VisiblePositionTemplate<Strategy> nextPositionOfAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition, EditingBoundaryCrossingRule rule) static VisiblePositionTemplate<Strategy> nextPositionOfAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition, EditingBoundaryCrossingRule rule)
{ {
......
...@@ -101,7 +101,11 @@ UChar32 characterBefore(const VisiblePosition&); ...@@ -101,7 +101,11 @@ UChar32 characterBefore(const VisiblePosition&);
// composed tree. // composed tree.
CORE_EXPORT VisiblePosition leftPositionOf(const VisiblePosition&); CORE_EXPORT VisiblePosition leftPositionOf(const VisiblePosition&);
CORE_EXPORT VisiblePositionInComposedTree leftPositionOf(const VisiblePositionInComposedTree&); CORE_EXPORT VisiblePositionInComposedTree leftPositionOf(const VisiblePositionInComposedTree&);
VisiblePosition rightPositionOf(const VisiblePosition&); // TODO(yosin) Since return value of |rightPositionOf()| with |VisiblePosition|
// isn't defined well on composed tree, we should not use it for a position in
// composed tree.
CORE_EXPORT VisiblePosition rightPositionOf(const VisiblePosition&);
CORE_EXPORT VisiblePositionInComposedTree rightPositionOf(const VisiblePositionInComposedTree&);
CORE_EXPORT VisiblePosition nextPositionOf(const VisiblePosition&, EditingBoundaryCrossingRule = CanCrossEditingBoundary); CORE_EXPORT VisiblePosition nextPositionOf(const VisiblePosition&, EditingBoundaryCrossingRule = CanCrossEditingBoundary);
CORE_EXPORT VisiblePositionInComposedTree nextPositionOf(const VisiblePositionInComposedTree&, EditingBoundaryCrossingRule = CanCrossEditingBoundary); CORE_EXPORT VisiblePositionInComposedTree nextPositionOf(const VisiblePositionInComposedTree&, EditingBoundaryCrossingRule = CanCrossEditingBoundary);
......
...@@ -332,4 +332,31 @@ TEST_F(VisibleUnitsTest, renderedOffset) ...@@ -332,4 +332,31 @@ TEST_F(VisibleUnitsTest, renderedOffset)
EXPECT_FALSE(rendersInDifferentPosition(Position::lastPositionInNode(sample1->firstChild()), Position(sample2->firstChild(), 0))); EXPECT_FALSE(rendersInDifferentPosition(Position::lastPositionInNode(sample1->firstChild()), Position(sample2->firstChild(), 0)));
} }
TEST_F(VisibleUnitsTest, rightPositionOf)
{
const char* bodyContent = "<b id=zero>0</b><p id=host><b id=one>1</b><b id=two>22</b></p><b id=three>333</b>";
const char* shadowContent = "<p id=four>4444</p><content select=#two></content><content select=#one></content><p id=five>55555</p>";
setBodyContent(bodyContent);
RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");
updateLayoutAndStyleForPainting();
Node* one = document().getElementById("one")->firstChild();
Node* two = document().getElementById("two")->firstChild();
Node* three = document().getElementById("three")->firstChild();
Node* four = shadowRoot->getElementById("four")->firstChild();
Node* five = shadowRoot->getElementById("five")->firstChild();
EXPECT_EQ(Position(), rightPositionOf(createVisiblePosition(Position(one, 1))).deepEquivalent());
EXPECT_EQ(PositionInComposedTree(five, 0), rightPositionOf(createVisiblePosition(PositionInComposedTree(one, 1))).deepEquivalent());
EXPECT_EQ(Position(one, 1), rightPositionOf(createVisiblePosition(Position(two, 2))).deepEquivalent());
EXPECT_EQ(PositionInComposedTree(one, 1), rightPositionOf(createVisiblePosition(PositionInComposedTree(two, 2))).deepEquivalent());
EXPECT_EQ(Position(five, 0), rightPositionOf(createVisiblePosition(Position(four, 4))).deepEquivalent());
EXPECT_EQ(PositionInComposedTree(two, 0), rightPositionOf(createVisiblePosition(PositionInComposedTree(four, 4))).deepEquivalent());
EXPECT_EQ(Position(), rightPositionOf(createVisiblePosition(Position(five, 5))).deepEquivalent());
EXPECT_EQ(PositionInComposedTree(three, 0), rightPositionOf(createVisiblePosition(PositionInComposedTree(five, 5))).deepEquivalent());
}
} // namespace blink } // namespace blink
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