Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(899)

Unified Diff: Source/core/editing/VisibleUnits.cpp

Issue 1310953005: Move {left,right}PositionOf() for VisiblePosition to VisibleUnits.cpp (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 2015-09-01T21:47:52 Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/editing/VisibleUnits.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/editing/VisibleUnits.cpp
diff --git a/Source/core/editing/VisibleUnits.cpp b/Source/core/editing/VisibleUnits.cpp
index 97bb5e9ccdee5cb70cbc8a9cb41c4bf623bd3daa..b69f0bf5ca55a840e0f0e1147544868e26261adb 100644
--- a/Source/core/editing/VisibleUnits.cpp
+++ b/Source/core/editing/VisibleUnits.cpp
@@ -2494,6 +2494,335 @@ UChar32 characterBefore(const VisiblePosition& visiblePosition)
return characterAfter(previousPositionOf(visiblePosition));
}
+static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosition)
+{
+ const Position deepPosition = visiblePosition.deepEquivalent();
+ Position p = deepPosition;
+ if (p.isNull())
+ return Position();
+
+ Position downstreamStart = mostForwardCaretPosition(p);
+ TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
+ const TextAffinity affinity = visiblePosition.affinity();
+
+ while (true) {
+ InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, primaryDirection);
+ InlineBox* box = boxPosition.inlineBox;
+ int offset = boxPosition.offsetInBox;
+ if (!box)
+ return primaryDirection == LTR ? previousVisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition);
+
+ LayoutObject* layoutObject = &box->layoutObject();
+
+ while (true) {
+ if ((layoutObject->isReplaced() || layoutObject->isBR()) && offset == box->caretRightmostOffset())
+ return box->isLeftToRightDirection() ? previousVisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition);
+
+ if (!layoutObject->node()) {
+ box = box->prevLeafChild();
+ if (!box)
+ return primaryDirection == LTR ? previousVisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition);
+ layoutObject = &box->layoutObject();
+ offset = box->caretRightmostOffset();
+ continue;
+ }
+
+ offset = box->isLeftToRightDirection() ? layoutObject->previousOffset(offset) : layoutObject->nextOffset(offset);
+
+ int caretMinOffset = box->caretMinOffset();
+ int caretMaxOffset = box->caretMaxOffset();
+
+ if (offset > caretMinOffset && offset < caretMaxOffset)
+ break;
+
+ if (box->isLeftToRightDirection() ? offset < caretMinOffset : offset > caretMaxOffset) {
+ // Overshot to the left.
+ InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
+ if (!prevBox) {
+ Position positionOnLeft = primaryDirection == LTR ? previousVisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition);
+ if (positionOnLeft.isNull())
+ return Position();
+
+ InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLeft, affinity, primaryDirection).inlineBox;
+ if (boxOnLeft && boxOnLeft->root() == box->root())
+ return Position();
+ return positionOnLeft;
+ }
+
+ // Reposition at the other logical position corresponding to our
+ // edge's visual position and go for another round.
+ box = prevBox;
+ layoutObject = &box->layoutObject();
+ offset = prevBox->caretRightmostOffset();
+ continue;
+ }
+
+ ASSERT(offset == box->caretLeftmostOffset());
+
+ unsigned char level = box->bidiLevel();
+ InlineBox* prevBox = box->prevLeafChild();
+
+ if (box->direction() == primaryDirection) {
+ if (!prevBox) {
+ InlineBox* logicalStart = 0;
+ if (primaryDirection == LTR ? box->root().getLogicalStartBoxWithNode(logicalStart) : box->root().getLogicalEndBoxWithNode(logicalStart)) {
+ box = logicalStart;
+ layoutObject = &box->layoutObject();
+ offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset();
+ }
+ break;
+ }
+ if (prevBox->bidiLevel() >= level)
+ break;
+
+ level = prevBox->bidiLevel();
+
+ InlineBox* nextBox = box;
+ do {
+ nextBox = nextBox->nextLeafChild();
+ } while (nextBox && nextBox->bidiLevel() > level);
+
+ if (nextBox && nextBox->bidiLevel() == level)
+ break;
+
+ box = prevBox;
+ layoutObject = &box->layoutObject();
+ offset = box->caretRightmostOffset();
+ if (box->direction() == primaryDirection)
+ break;
+ continue;
+ }
+
+ while (prevBox && !prevBox->layoutObject().node())
+ prevBox = prevBox->prevLeafChild();
+
+ if (prevBox) {
+ box = prevBox;
+ layoutObject = &box->layoutObject();
+ offset = box->caretRightmostOffset();
+ if (box->bidiLevel() > level) {
+ do {
+ prevBox = prevBox->prevLeafChild();
+ } while (prevBox && prevBox->bidiLevel() > level);
+
+ if (!prevBox || prevBox->bidiLevel() < level)
+ continue;
+ }
+ } else {
+ // Trailing edge of a secondary run. Set to the leading edge of the entire run.
+ while (true) {
+ while (InlineBox* nextBox = box->nextLeafChild()) {
+ if (nextBox->bidiLevel() < level)
+ break;
+ box = nextBox;
+ }
+ if (box->bidiLevel() == level)
+ break;
+ level = box->bidiLevel();
+ while (InlineBox* prevBox = box->prevLeafChild()) {
+ if (prevBox->bidiLevel() < level)
+ break;
+ box = prevBox;
+ }
+ if (box->bidiLevel() == level)
+ break;
+ level = box->bidiLevel();
+ }
+ layoutObject = &box->layoutObject();
+ offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset();
+ }
+ break;
+ }
+
+ p = Position::editingPositionOf(layoutObject->node(), offset);
+
+ if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
+ return p;
+
+ ASSERT(p != deepPosition);
+ }
+}
+
+VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition)
+{
+ const Position pos = leftVisuallyDistinctCandidate(visiblePosition);
+ // TODO(yosin) Why can't we move left from the last position in a tree?
+ if (pos.atStartOfTree() || pos.atEndOfTree())
+ return VisiblePosition();
+
+ VisiblePosition left = createVisiblePosition(pos);
+ ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent());
+
+ return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditingBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBoundaryAtOrAfter(left, visiblePosition.deepEquivalent());
+}
+
+static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePosition)
+{
+ const Position deepPosition = visiblePosition.deepEquivalent();
+ Position p = deepPosition;
+ if (p.isNull())
+ return Position();
+
+ Position downstreamStart = mostForwardCaretPosition(p);
+ TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
+ const TextAffinity affinity = visiblePosition.affinity();
+
+ while (true) {
+ InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, primaryDirection);
+ InlineBox* box = boxPosition.inlineBox;
+ int offset = boxPosition.offsetInBox;
+ if (!box)
+ return primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
+
+ LayoutObject* layoutObject = &box->layoutObject();
+
+ while (true) {
+ if ((layoutObject->isReplaced() || layoutObject->isBR()) && offset == box->caretLeftmostOffset())
+ return box->isLeftToRightDirection() ? nextVisuallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
+
+ if (!layoutObject->node()) {
+ box = box->nextLeafChild();
+ if (!box)
+ return primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
+ layoutObject = &box->layoutObject();
+ offset = box->caretLeftmostOffset();
+ continue;
+ }
+
+ offset = box->isLeftToRightDirection() ? layoutObject->nextOffset(offset) : layoutObject->previousOffset(offset);
+
+ int caretMinOffset = box->caretMinOffset();
+ int caretMaxOffset = box->caretMaxOffset();
+
+ if (offset > caretMinOffset && offset < caretMaxOffset)
+ break;
+
+ if (box->isLeftToRightDirection() ? offset > caretMaxOffset : offset < caretMinOffset) {
+ // Overshot to the right.
+ InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();
+ if (!nextBox) {
+ Position positionOnRight = primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
+ if (positionOnRight.isNull())
+ return Position();
+
+ InlineBox* boxOnRight = computeInlineBoxPosition(positionOnRight, affinity, primaryDirection).inlineBox;
+ if (boxOnRight && boxOnRight->root() == box->root())
+ return Position();
+ return positionOnRight;
+ }
+
+ // Reposition at the other logical position corresponding to our
+ // edge's visual position and go for another round.
+ box = nextBox;
+ layoutObject = &box->layoutObject();
+ offset = nextBox->caretLeftmostOffset();
+ continue;
+ }
+
+ ASSERT(offset == box->caretRightmostOffset());
+
+ unsigned char level = box->bidiLevel();
+ InlineBox* nextBox = box->nextLeafChild();
+
+ if (box->direction() == primaryDirection) {
+ if (!nextBox) {
+ InlineBox* logicalEnd = 0;
+ if (primaryDirection == LTR ? box->root().getLogicalEndBoxWithNode(logicalEnd) : box->root().getLogicalStartBoxWithNode(logicalEnd)) {
+ box = logicalEnd;
+ layoutObject = &box->layoutObject();
+ offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset();
+ }
+ break;
+ }
+
+ if (nextBox->bidiLevel() >= level)
+ break;
+
+ level = nextBox->bidiLevel();
+
+ InlineBox* prevBox = box;
+ do {
+ prevBox = prevBox->prevLeafChild();
+ } while (prevBox && prevBox->bidiLevel() > level);
+
+ // For example, abc FED 123 ^ CBA
+ if (prevBox && prevBox->bidiLevel() == level)
+ break;
+
+ // For example, abc 123 ^ CBA or 123 ^ CBA abc
+ box = nextBox;
+ layoutObject = &box->layoutObject();
+ offset = box->caretLeftmostOffset();
+ if (box->direction() == primaryDirection)
+ break;
+ continue;
+ }
+
+ while (nextBox && !nextBox->layoutObject().node())
+ nextBox = nextBox->nextLeafChild();
+
+ if (nextBox) {
+ box = nextBox;
+ layoutObject = &box->layoutObject();
+ offset = box->caretLeftmostOffset();
+
+ if (box->bidiLevel() > level) {
+ do {
+ nextBox = nextBox->nextLeafChild();
+ } while (nextBox && nextBox->bidiLevel() > level);
+
+ if (!nextBox || nextBox->bidiLevel() < level)
+ continue;
+ }
+ } else {
+ // Trailing edge of a secondary run. Set to the leading edge of
+ // the entire run.
+ while (true) {
+ while (InlineBox* prevBox = box->prevLeafChild()) {
+ if (prevBox->bidiLevel() < level)
+ break;
+ box = prevBox;
+ }
+ if (box->bidiLevel() == level)
+ break;
+ level = box->bidiLevel();
+ while (InlineBox* nextBox = box->nextLeafChild()) {
+ if (nextBox->bidiLevel() < level)
+ break;
+ box = nextBox;
+ }
+ if (box->bidiLevel() == level)
+ break;
+ level = box->bidiLevel();
+ }
+ layoutObject = &box->layoutObject();
+ offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset();
+ }
+ break;
+ }
+
+ p = Position::editingPositionOf(layoutObject->node(), offset);
+
+ if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
+ return p;
+
+ ASSERT(p != deepPosition);
+ }
+}
+
+VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition)
+{
+ const Position pos = rightVisuallyDistinctCandidate(visiblePosition);
+ // TODO(yosin) Why can't we move left from the last position in a tree?
+ if (pos.atStartOfTree() || pos.atEndOfTree())
+ return VisiblePosition();
+
+ VisiblePosition right = createVisiblePosition(pos);
+ ASSERT(right.deepEquivalent() != visiblePosition.deepEquivalent());
+
+ return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditingBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBoundaryAtOrBefore(right, visiblePosition.deepEquivalent());
+}
+
VisiblePosition nextPositionOf(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
{
VisiblePosition next(nextVisuallyDistinctCandidate(visiblePosition.deepEquivalent()), visiblePosition.affinity());
« no previous file with comments | « Source/core/editing/VisibleUnits.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698