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

Introduce composed tree version of leftPositionOf()

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

This patch also introduces |createVisiblePosition()| for
|PositionInComposdTreeWithAffinity| and templaizes
|honorEditingBoundaryAtOrAfter()| and |leftVisuallyDistinctCandidate()| used
by |leftPositionOf()|.

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/1326313002

git-svn-id: svn://svn.chromium.org/blink/trunk@201954 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent db80dcf4
...@@ -93,6 +93,11 @@ VisiblePositionInComposedTree createVisiblePosition(const PositionInComposedTree ...@@ -93,6 +93,11 @@ VisiblePositionInComposedTree createVisiblePosition(const PositionInComposedTree
return VisiblePositionInComposedTree::create(PositionInComposedTreeWithAffinity(position, affinity)); return VisiblePositionInComposedTree::create(PositionInComposedTreeWithAffinity(position, affinity));
} }
VisiblePositionInComposedTree createVisiblePosition(const PositionInComposedTreeWithAffinity& positionWithAffinity)
{
return VisiblePositionInComposedTree::create(positionWithAffinity);
}
VisiblePosition createVisiblePositionInDOMTree(const Position& position, TextAffinity affinity) VisiblePosition createVisiblePositionInDOMTree(const Position& position, TextAffinity affinity)
{ {
return createVisiblePosition(position, affinity); return createVisiblePosition(position, affinity);
......
...@@ -119,6 +119,7 @@ using VisiblePositionInComposedTree = VisiblePositionTemplate<EditingInComposedT ...@@ -119,6 +119,7 @@ using VisiblePositionInComposedTree = VisiblePositionTemplate<EditingInComposedT
CORE_EXPORT VisiblePosition createVisiblePosition(const Position&, TextAffinity = VP_DEFAULT_AFFINITY); CORE_EXPORT VisiblePosition createVisiblePosition(const Position&, TextAffinity = VP_DEFAULT_AFFINITY);
CORE_EXPORT VisiblePosition createVisiblePosition(const PositionWithAffinity&); CORE_EXPORT VisiblePosition createVisiblePosition(const PositionWithAffinity&);
CORE_EXPORT VisiblePositionInComposedTree createVisiblePosition(const PositionInComposedTree&, TextAffinity = VP_DEFAULT_AFFINITY); CORE_EXPORT VisiblePositionInComposedTree createVisiblePosition(const PositionInComposedTree&, TextAffinity = VP_DEFAULT_AFFINITY);
CORE_EXPORT VisiblePositionInComposedTree createVisiblePosition(const PositionInComposedTreeWithAffinity&);
// TODO(yosin) Once we have composed tree version of VisibleUnits, we should not // TODO(yosin) Once we have composed tree version of VisibleUnits, we should not
// use |createVisiblePositionInDOMTree()|. // use |createVisiblePositionInDOMTree()|.
......
...@@ -162,7 +162,7 @@ PositionInComposedTree canonicalPositionOf(const PositionInComposedTree& positio ...@@ -162,7 +162,7 @@ PositionInComposedTree canonicalPositionOf(const PositionInComposedTree& positio
} }
template <typename Strategy> template <typename Strategy>
static PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBeforeAlgorithm(const PositionWithAffinityTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor) static PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBefore(const PositionWithAffinityTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor)
{ {
if (pos.isNull()) if (pos.isNull())
return pos; return pos;
...@@ -193,19 +193,10 @@ static PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBeforeAlgo ...@@ -193,19 +193,10 @@ static PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBeforeAlgo
return lastEditablePositionBeforePositionInRoot(pos.position(), highestRoot); return lastEditablePositionBeforePositionInRoot(pos.position(), highestRoot);
} }
static PositionWithAffinity honorEditingBoundaryAtOrBeforeOf(const PositionWithAffinity& pos, const Position& anchor) template <typename Strategy>
{ static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrBefore(const VisiblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor)
return honorEditingBoundaryAtOrBeforeAlgorithm(pos, anchor);
}
static PositionInComposedTreeWithAffinity honorEditingBoundaryAtOrBeforeOf(const PositionInComposedTreeWithAffinity& pos, const PositionInComposedTree& anchor)
{
return honorEditingBoundaryAtOrBeforeAlgorithm(pos, anchor);
}
static VisiblePosition honorEditingBoundaryAtOrBefore(const VisiblePosition& pos, const Position& anchor)
{ {
return createVisiblePosition(honorEditingBoundaryAtOrBeforeOf(pos.toPositionWithAffinity(), anchor)); return createVisiblePosition(honorEditingBoundaryAtOrBefore(pos.toPositionWithAffinity(), anchor));
} }
template <typename Strategy> template <typename Strategy>
...@@ -961,7 +952,7 @@ static PositionWithAffinityTemplate<Strategy> startOfLine(const PositionWithAffi ...@@ -961,7 +952,7 @@ static PositionWithAffinityTemplate<Strategy> startOfLine(const PositionWithAffi
} }
} }
return honorEditingBoundaryAtOrBeforeOf(visPos, c.position()); return honorEditingBoundaryAtOrBefore(visPos, c.position());
} }
static PositionWithAffinity startOfLine(const PositionWithAffinity& currentPosition) static PositionWithAffinity startOfLine(const PositionWithAffinity& currentPosition)
...@@ -2597,14 +2588,16 @@ UChar32 characterBefore(const VisiblePosition& visiblePosition) ...@@ -2597,14 +2588,16 @@ UChar32 characterBefore(const VisiblePosition& visiblePosition)
return characterAfter(previousPositionOf(visiblePosition)); return characterAfter(previousPositionOf(visiblePosition));
} }
static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosition) template <typename Strategy>
static PositionAlgorithm<Strategy> leftVisuallyDistinctCandidate(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();
...@@ -2642,13 +2635,13 @@ static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi ...@@ -2642,13 +2635,13 @@ static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi
// Overshot to the left. // Overshot to the left.
InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
if (!prevBox) { if (!prevBox) {
Position positionOnLeft = primaryDirection == LTR ? previousVisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition); PositionAlgorithm<Strategy> positionOnLeft = primaryDirection == LTR ? previousVisuallyDistinctCandidate(visiblePosition.deepEquivalent()) : nextVisuallyDistinctCandidate(visiblePosition.deepEquivalent());
if (positionOnLeft.isNull()) if (positionOnLeft.isNull())
return Position(); return PositionAlgorithm<Strategy>();
InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLeft, affinity, primaryDirection).inlineBox; InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLeft, affinity, primaryDirection).inlineBox;
if (boxOnLeft && boxOnLeft->root() == box->root()) if (boxOnLeft && boxOnLeft->root() == box->root())
return Position(); return PositionAlgorithm<Strategy>();
return positionOnLeft; return positionOnLeft;
} }
...@@ -2712,7 +2705,8 @@ static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi ...@@ -2712,7 +2705,8 @@ static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi
continue; continue;
} }
} else { } else {
// Trailing edge of a secondary run. Set to the leading edge of the entire run. // Trailing edge of a secondary run. Set to the leading edge of
// the entire run.
while (true) { while (true) {
while (InlineBox* nextBox = box->nextLeafChild()) { while (InlineBox* nextBox = box->nextLeafChild()) {
if (nextBox->bidiLevel() < level) if (nextBox->bidiLevel() < level)
...@@ -2737,7 +2731,7 @@ static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi ...@@ -2737,7 +2731,7 @@ static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi
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;
...@@ -2746,19 +2740,30 @@ static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi ...@@ -2746,19 +2740,30 @@ static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi
} }
} }
VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) template <typename Strategy>
VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition)
{ {
const Position pos = leftVisuallyDistinctCandidate(visiblePosition); const PositionAlgorithm<Strategy> pos = leftVisuallyDistinctCandidate(visiblePosition);
// TODO(yosin) Why can't we move left from the last position in a tree? // TODO(yosin) 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 left = createVisiblePosition(pos); const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos);
ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent()); ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent());
return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditingBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBoundaryAtOrAfter(left, visiblePosition.deepEquivalent()); return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditingBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBoundaryAtOrAfter(left, visiblePosition.deepEquivalent());
} }
VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition)
{
return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition);
}
VisiblePositionInComposedTree leftPositionOf(const VisiblePositionInComposedTree& visiblePosition)
{
return leftPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePosition);
}
static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePosition) static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePosition)
{ {
const Position deepPosition = visiblePosition.deepEquivalent(); const Position deepPosition = visiblePosition.deepEquivalent();
......
...@@ -96,7 +96,11 @@ CORE_EXPORT UChar32 characterAfter(const VisiblePosition&); ...@@ -96,7 +96,11 @@ CORE_EXPORT UChar32 characterAfter(const VisiblePosition&);
CORE_EXPORT UChar32 characterAfter(const VisiblePositionInComposedTree&); CORE_EXPORT UChar32 characterAfter(const VisiblePositionInComposedTree&);
UChar32 characterBefore(const VisiblePosition&); UChar32 characterBefore(const VisiblePosition&);
VisiblePosition leftPositionOf(const VisiblePosition&); // TODO(yosin) Since return value of |leftPositionOf()| with |VisiblePosition|
// isn't defined well on composed tree, we should not use it for a position in
// composed tree.
CORE_EXPORT VisiblePosition leftPositionOf(const VisiblePosition&);
CORE_EXPORT VisiblePositionInComposedTree leftPositionOf(const VisiblePositionInComposedTree&);
VisiblePosition rightPositionOf(const VisiblePosition&); VisiblePosition rightPositionOf(const VisiblePosition&);
CORE_EXPORT VisiblePosition nextPositionOf(const VisiblePosition&, EditingBoundaryCrossingRule = CanCrossEditingBoundary); CORE_EXPORT VisiblePosition nextPositionOf(const VisiblePosition&, EditingBoundaryCrossingRule = CanCrossEditingBoundary);
......
...@@ -128,6 +128,30 @@ TEST_F(VisibleUnitsTest, inSameLine) ...@@ -128,6 +128,30 @@ TEST_F(VisibleUnitsTest, inSameLine)
EXPECT_TRUE(inSameLine(createVisiblePositionInComposedTree(*two->firstChild(), 0), createVisiblePositionInComposedTree(*four->firstChild(), 0))); EXPECT_TRUE(inSameLine(createVisiblePositionInComposedTree(*two->firstChild(), 0), createVisiblePositionInComposedTree(*four->firstChild(), 0)));
} }
TEST_F(VisibleUnitsTest, leftPositionOf)
{
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 = "<b id=four>4444</b><content select=#two></content><content select=#one></content><b id=five>55555</b>";
setBodyContent(bodyContent);
RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");
updateLayoutAndStyleForPainting();
Element* one = document().getElementById("one");
Element* two = document().getElementById("two");
Element* three = document().getElementById("three");
Element* four = shadowRoot->getElementById("four");
Element* five = shadowRoot->getElementById("five");
EXPECT_EQ(Position(two->firstChild(), 1), leftPositionOf(createVisiblePosition(Position(one, 0))).deepEquivalent());
EXPECT_EQ(PositionInComposedTree(two->firstChild(), 1), leftPositionOf(createVisiblePosition(PositionInComposedTree(one, 0))).deepEquivalent());
EXPECT_EQ(Position(one->firstChild(), 0), leftPositionOf(createVisiblePosition(Position(two, 0))).deepEquivalent());
EXPECT_EQ(PositionInComposedTree(four->firstChild(), 3), leftPositionOf(createVisiblePosition(PositionInComposedTree(two, 0))).deepEquivalent());
EXPECT_EQ(Position(two->firstChild(), 2), leftPositionOf(createVisiblePosition(Position(three, 0))).deepEquivalent());
EXPECT_EQ(PositionInComposedTree(five->firstChild(), 5), leftPositionOf(createVisiblePosition(PositionInComposedTree(three, 0))).deepEquivalent());
}
TEST_F(VisibleUnitsTest, localCaretRectOfPosition) TEST_F(VisibleUnitsTest, localCaretRectOfPosition)
{ {
const char* bodyContent = "<p id='host'><b id='one'>1</b></p><b id='two'>22</b>"; const char* bodyContent = "<p id='host'><b id='one'>1</b></p><b id='two'>22</b>";
......
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