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

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

Issue 1303173002: Move computeInlineBoxPosition() to VisibleUnits.{cpp,h} from Position.{cpp,h} and VisiblePosition.h (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 2015-08-21T13:45:14 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 13d9ae5c497294c5cbd774f84df8bf78f73c9519..b3cab4afb4220392778ecdaa274ac5b0ed691fae 100644
--- a/Source/core/editing/VisibleUnits.cpp
+++ b/Source/core/editing/VisibleUnits.cpp
@@ -1456,6 +1456,261 @@ VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection dire
return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
}
+static bool isNonTextLeafChild(LayoutObject* object)
+{
+ if (object->slowFirstChild())
+ return false;
+ if (object->isText())
+ return false;
+ return true;
+}
+
+static InlineTextBox* searchAheadForBetterMatch(LayoutObject* layoutObject)
+{
+ LayoutBlock* container = layoutObject->containingBlock();
+ for (LayoutObject* next = layoutObject->nextInPreOrder(container); next; next = next->nextInPreOrder(container)) {
+ if (next->isLayoutBlock())
+ return 0;
+ if (next->isBR())
+ return 0;
+ if (isNonTextLeafChild(next))
+ return 0;
+ if (next->isText()) {
+ InlineTextBox* match = 0;
+ int minOffset = INT_MAX;
+ for (InlineTextBox* box = toLayoutText(next)->firstTextBox(); box; box = box->nextTextBox()) {
+ int caretMinOffset = box->caretMinOffset();
+ if (caretMinOffset < minOffset) {
+ match = box;
+ minOffset = caretMinOffset;
+ }
+ }
+ if (match)
+ return match;
+ }
+ }
+ return 0;
+}
+
+template <typename Strategy>
+PositionAlgorithm<Strategy> downstreamIgnoringEditingBoundaries(PositionAlgorithm<Strategy> position)
+{
+ PositionAlgorithm<Strategy> lastPosition;
+ while (position != lastPosition) {
+ lastPosition = position;
+ position = position.downstream(CanCrossEditingBoundary);
+ }
+ return position;
+}
+
+template <typename Strategy>
+PositionAlgorithm<Strategy> upstreamIgnoringEditingBoundaries(PositionAlgorithm<Strategy> position)
+{
+ PositionAlgorithm<Strategy> lastPosition;
+ while (position != lastPosition) {
+ lastPosition = position;
+ position = position.upstream(CanCrossEditingBoundary);
+ }
+ return position;
+}
+
+template <typename Strategy>
+static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorithm<Strategy>& position, TextAffinity affinity, TextDirection primaryDirection)
+{
+ InlineBox* inlineBox = nullptr;
+ int caretOffset = position.computeEditingOffset();
+ Node* const anchorNode = position.anchorNode();
+ LayoutObject* layoutObject = anchorNode->isShadowRoot() ? toShadowRoot(anchorNode)->host()->layoutObject() : anchorNode->layoutObject();
+
+ if (!layoutObject->isText()) {
+ inlineBox = 0;
+ if (canHaveChildrenForEditing(anchorNode) && layoutObject->isLayoutBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) {
+ // Try a visually equivalent position with possibly opposite
+ // editability. This helps in case |this| is in an editable block
+ // but surrounded by non-editable positions. It acts to negate the
+ // logic at the beginning of LayoutObject::createVisiblePosition().
+ PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBoundaries(position);
+ if (equivalent == position) {
+ equivalent = upstreamIgnoringEditingBoundaries(position);
+ if (equivalent == position || downstreamIgnoringEditingBoundaries(equivalent) == position)
+ return InlineBoxPosition(inlineBox, caretOffset);
+ }
+
+ return computeInlineBoxPosition(equivalent, TextAffinity::Upstream, primaryDirection);
+ }
+ if (layoutObject->isBox()) {
+ inlineBox = toLayoutBox(layoutObject)->inlineBoxWrapper();
+ if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
+ return InlineBoxPosition(inlineBox, caretOffset);
+ }
+ } else {
+ LayoutText* textLayoutObject = toLayoutText(layoutObject);
+
+ InlineTextBox* box;
+ InlineTextBox* candidate = 0;
+
+ for (box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) {
+ int caretMinOffset = box->caretMinOffset();
+ int caretMaxOffset = box->caretMaxOffset();
+
+ if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
+ continue;
+
+ if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset)
+ return InlineBoxPosition(box, caretOffset);
+
+ if (((caretOffset == caretMaxOffset) ^ (affinity == TextAffinity::Downstream))
+ || ((caretOffset == caretMinOffset) ^ (affinity == TextAffinity::Upstream))
+ || (caretOffset == caretMaxOffset && box->nextLeafChild() && box->nextLeafChild()->isLineBreak()))
+ break;
+
+ candidate = box;
+ }
+ if (candidate && candidate == textLayoutObject->lastTextBox() && affinity == TextAffinity::Downstream) {
+ box = searchAheadForBetterMatch(textLayoutObject);
+ if (box)
+ caretOffset = box->caretMinOffset();
+ }
+ inlineBox = box ? box : candidate;
+ }
+
+ if (!inlineBox)
+ return InlineBoxPosition(inlineBox, caretOffset);
+
+ unsigned char level = inlineBox->bidiLevel();
+
+ if (inlineBox->direction() == primaryDirection) {
+ if (caretOffset == inlineBox->caretRightmostOffset()) {
+ InlineBox* nextBox = inlineBox->nextLeafChild();
+ if (!nextBox || nextBox->bidiLevel() >= level)
+ return InlineBoxPosition(inlineBox, caretOffset);
+
+ level = nextBox->bidiLevel();
+ InlineBox* prevBox = inlineBox;
+ do {
+ prevBox = prevBox->prevLeafChild();
+ } while (prevBox && prevBox->bidiLevel() > level);
+
+ // For example, abc FED 123 ^ CBA
+ if (prevBox && prevBox->bidiLevel() == level)
+ return InlineBoxPosition(inlineBox, caretOffset);
+
+ // For example, abc 123 ^ CBA
+ while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
+ if (nextBox->bidiLevel() < level)
+ break;
+ inlineBox = nextBox;
+ }
+ return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
+ }
+
+ InlineBox* prevBox = inlineBox->prevLeafChild();
+ if (!prevBox || prevBox->bidiLevel() >= level)
+ return InlineBoxPosition(inlineBox, caretOffset);
+
+ level = prevBox->bidiLevel();
+ InlineBox* nextBox = inlineBox;
+ do {
+ nextBox = nextBox->nextLeafChild();
+ } while (nextBox && nextBox->bidiLevel() > level);
+
+ if (nextBox && nextBox->bidiLevel() == level)
+ return InlineBoxPosition(inlineBox, caretOffset);
+
+ while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
+ if (prevBox->bidiLevel() < level)
+ break;
+ inlineBox = prevBox;
+ }
+ return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
+ }
+
+ if (caretOffset == inlineBox->caretLeftmostOffset()) {
+ InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
+ if (!prevBox || prevBox->bidiLevel() < level) {
+ // Left edge of a secondary run. Set to the right edge of the entire
+ // run.
+ while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
+ if (nextBox->bidiLevel() < level)
+ break;
+ inlineBox = nextBox;
+ }
+ return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
+ }
+
+ if (prevBox->bidiLevel() > level) {
+ // Right edge of a "tertiary" run. Set to the left edge of that run.
+ while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
+ if (tertiaryBox->bidiLevel() <= level)
+ break;
+ inlineBox = tertiaryBox;
+ }
+ return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
+ }
+ return InlineBoxPosition(inlineBox, caretOffset);
+ }
+
+ if (layoutObject && layoutObject->style()->unicodeBidi() == Plaintext) {
+ if (inlineBox->bidiLevel() < level)
+ return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
+ return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
+ }
+
+ InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
+ if (!nextBox || nextBox->bidiLevel() < level) {
+ // Right edge of a secondary run. Set to the left edge of the entire
+ // run.
+ while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
+ if (prevBox->bidiLevel() < level)
+ break;
+ inlineBox = prevBox;
+ }
+ return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
+ }
+
+ if (nextBox->bidiLevel() <= level)
+ return InlineBoxPosition(inlineBox, caretOffset);
+
+ // Left edge of a "tertiary" run. Set to the right edge of that run.
+ while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
+ if (tertiaryBox->bidiLevel() <= level)
+ break;
+ inlineBox = tertiaryBox;
+ }
+ return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
+}
+
+template <typename Strategy>
+static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorithm<Strategy>& position, TextAffinity affinity)
+{
+ return computeInlineBoxPositionAlgorithm<Strategy>(position, affinity, primaryDirectionOf(*position.anchorNode()));
+}
+
+InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinity affinity)
+{
+ return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity);
+}
+
+InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& position, TextAffinity affinity)
+{
+ return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(position, affinity);
+}
+
+InlineBoxPosition computeInlineBoxPosition(const VisiblePosition& position)
+{
+ return computeInlineBoxPosition(position.deepEquivalent(), position.affinity());
+}
+
+InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinity affinity, TextDirection primaryDirection)
+{
+ return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity, primaryDirection);
+}
+
+InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& position, TextAffinity affinity, TextDirection primaryDirection)
+{
+ return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(position, affinity, primaryDirection);
+}
+
LayoutRect localCaretRectOfPosition(const PositionWithAffinity& position, LayoutObject*& layoutObject)
{
if (position.position().isNull()) {
« 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