| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 #include "platform/heap/Handle.h" | 66 #include "platform/heap/Handle.h" |
| 67 #include "platform/text/TextBoundaries.h" | 67 #include "platform/text/TextBoundaries.h" |
| 68 | 68 |
| 69 namespace blink { | 69 namespace blink { |
| 70 | 70 |
| 71 template <typename PositionType> | 71 template <typename PositionType> |
| 72 static PositionType canonicalizeCandidate(const PositionType& candidate) | 72 static PositionType canonicalizeCandidate(const PositionType& candidate) |
| 73 { | 73 { |
| 74 if (candidate.isNull()) | 74 if (candidate.isNull()) |
| 75 return PositionType(); | 75 return PositionType(); |
| 76 ASSERT(isVisuallyEquivalentCandidate(candidate)); | 76 DCHECK(isVisuallyEquivalentCandidate(candidate)); |
| 77 PositionType upstream = mostBackwardCaretPosition(candidate); | 77 PositionType upstream = mostBackwardCaretPosition(candidate); |
| 78 if (isVisuallyEquivalentCandidate(upstream)) | 78 if (isVisuallyEquivalentCandidate(upstream)) |
| 79 return upstream; | 79 return upstream; |
| 80 return candidate; | 80 return candidate; |
| 81 } | 81 } |
| 82 | 82 |
| 83 template <typename PositionType> | 83 template <typename PositionType> |
| 84 static PositionType canonicalPosition(const PositionType& passedPosition) | 84 static PositionType canonicalPosition(const PositionType& passedPosition) |
| 85 { | 85 { |
| 86 // Sometimes updating selection positions can be extremely expensive and | 86 // Sometimes updating selection positions can be extremely expensive and |
| 87 // occur frequently. Often calling preventDefault on mousedown events can | 87 // occur frequently. Often calling preventDefault on mousedown events can |
| 88 // avoid doing unnecessary text selection work. http://crbug.com/472258. | 88 // avoid doing unnecessary text selection work. http://crbug.com/472258. |
| 89 TRACE_EVENT0("input", "VisibleUnits::canonicalPosition"); | 89 TRACE_EVENT0("input", "VisibleUnits::canonicalPosition"); |
| 90 | 90 |
| 91 // The updateLayout call below can do so much that even the position passed | 91 // The updateLayout call below can do so much that even the position passed |
| 92 // in to us might get changed as a side effect. Specifically, there are code | 92 // in to us might get changed as a side effect. Specifically, there are code |
| 93 // paths that pass selection endpoints, and updateLayout can change the | 93 // paths that pass selection endpoints, and updateLayout can change the |
| 94 // selection. | 94 // selection. |
| 95 PositionType position = passedPosition; | 95 PositionType position = passedPosition; |
| 96 | 96 |
| 97 // FIXME (9535): Canonicalizing to the leftmost candidate means that if | 97 // FIXME (9535): Canonicalizing to the leftmost candidate means that if |
| 98 // we're at a line wrap, we will ask layoutObjects to paint downstream | 98 // we're at a line wrap, we will ask layoutObjects to paint downstream |
| 99 // carets for other layoutObjects. To fix this, we need to either a) add | 99 // carets for other layoutObjects. To fix this, we need to either a) add |
| 100 // code to all paintCarets to pass the responsibility off to the appropriate | 100 // code to all paintCarets to pass the responsibility off to the appropriate |
| 101 // layoutObject for VisiblePosition's like these, or b) canonicalize to the | 101 // layoutObject for VisiblePosition's like these, or b) canonicalize to the |
| 102 // rightmost candidate unless the affinity is upstream. | 102 // rightmost candidate unless the affinity is upstream. |
| 103 if (position.isNull()) | 103 if (position.isNull()) |
| 104 return PositionType(); | 104 return PositionType(); |
| 105 | 105 |
| 106 ASSERT(position.document()); | 106 DCHECK(position.document()); |
| 107 position.document()->updateLayoutIgnorePendingStylesheets(); | 107 position.document()->updateLayoutIgnorePendingStylesheets(); |
| 108 | 108 |
| 109 Node* node = position.computeContainerNode(); | 109 Node* node = position.computeContainerNode(); |
| 110 | 110 |
| 111 PositionType candidate = mostBackwardCaretPosition(position); | 111 PositionType candidate = mostBackwardCaretPosition(position); |
| 112 if (isVisuallyEquivalentCandidate(candidate)) | 112 if (isVisuallyEquivalentCandidate(candidate)) |
| 113 return candidate; | 113 return candidate; |
| 114 candidate = mostForwardCaretPosition(position); | 114 candidate = mostForwardCaretPosition(position); |
| 115 if (isVisuallyEquivalentCandidate(candidate)) | 115 if (isVisuallyEquivalentCandidate(candidate)) |
| 116 return candidate; | 116 return candidate; |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 next = 0; | 718 next = 0; |
| 719 } | 719 } |
| 720 it.advance(); | 720 it.advance(); |
| 721 } | 721 } |
| 722 if (needMoreContext) { | 722 if (needMoreContext) { |
| 723 // The last search returned the beginning of the buffer and asked for | 723 // The last search returned the beginning of the buffer and asked for |
| 724 // more context, but there is no earlier text. Force a search with | 724 // more context, but there is no earlier text. Force a search with |
| 725 // what's available. | 725 // what's available. |
| 726 // TODO(xiaochengh): Do we have to search the whole string? | 726 // TODO(xiaochengh): Do we have to search the whole string? |
| 727 next = searchFunction(string.data(), string.size(), string.size() - suff
ixLength, DontHaveMoreContext, needMoreContext); | 727 next = searchFunction(string.data(), string.size(), string.size() - suff
ixLength, DontHaveMoreContext, needMoreContext); |
| 728 ASSERT(!needMoreContext); | 728 DCHECK(!needMoreContext); |
| 729 } | 729 } |
| 730 | 730 |
| 731 if (!next) | 731 if (!next) |
| 732 return createVisiblePosition(it.atEnd() ? it.startPosition() : pos); | 732 return createVisiblePosition(it.atEnd() ? it.startPosition() : pos); |
| 733 | 733 |
| 734 Node* node = it.startContainer(); | 734 Node* node = it.startContainer(); |
| 735 int boundaryOffset = remainingLength + next; | 735 int boundaryOffset = remainingLength + next; |
| 736 if (node->isTextNode() && boundaryOffset <= node->maxCharacterOffset()) { | 736 if (node->isTextNode() && boundaryOffset <= node->maxCharacterOffset()) { |
| 737 // The next variable contains a usable index into a text node | 737 // The next variable contains a usable index into a text node |
| 738 return createVisiblePosition(PositionTemplate<Strategy>(node, boundaryOf
fset)); | 738 return createVisiblePosition(PositionTemplate<Strategy>(node, boundaryOf
fset)); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 next = string.size(); | 812 next = string.size(); |
| 813 } | 813 } |
| 814 it.advance(); | 814 it.advance(); |
| 815 } | 815 } |
| 816 if (needMoreContext) { | 816 if (needMoreContext) { |
| 817 // The last search returned the end of the buffer and asked for more | 817 // The last search returned the end of the buffer and asked for more |
| 818 // context, but there is no further text. Force a search with what's | 818 // context, but there is no further text. Force a search with what's |
| 819 // available. | 819 // available. |
| 820 // TODO(xiaochengh): Do we still have to search the whole string? | 820 // TODO(xiaochengh): Do we still have to search the whole string? |
| 821 next = searchFunction(string.data(), string.size(), prefixLength, DontHa
veMoreContext, needMoreContext); | 821 next = searchFunction(string.data(), string.size(), prefixLength, DontHa
veMoreContext, needMoreContext); |
| 822 ASSERT(!needMoreContext); | 822 DCHECK(!needMoreContext); |
| 823 } | 823 } |
| 824 | 824 |
| 825 if (it.atEnd() && next == string.size()) { | 825 if (it.atEnd() && next == string.size()) { |
| 826 pos = it.startPositionInCurrentContainer(); | 826 pos = it.startPositionInCurrentContainer(); |
| 827 } else if (next != invalidOffset && next != prefixLength) { | 827 } else if (next != invalidOffset && next != prefixLength) { |
| 828 // Use the character iterator to translate the next value into a DOM | 828 // Use the character iterator to translate the next value into a DOM |
| 829 // position. | 829 // position. |
| 830 CharacterIteratorAlgorithm<Strategy> charIt(searchStart, searchEnd, Text
IteratorEmitsCharactersBetweenAllVisiblePositions); | 830 CharacterIteratorAlgorithm<Strategy> charIt(searchStart, searchEnd, Text
IteratorEmitsCharactersBetweenAllVisiblePositions); |
| 831 charIt.advance(next - prefixLength - 1); | 831 charIt.advance(next - prefixLength - 1); |
| 832 pos = charIt.endPosition(); | 832 pos = charIt.endPosition(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 845 | 845 |
| 846 // generate VisiblePosition, use TextAffinity::Upstream affinity if possible | 846 // generate VisiblePosition, use TextAffinity::Upstream affinity if possible |
| 847 return createVisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); | 847 return createVisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); |
| 848 } | 848 } |
| 849 | 849 |
| 850 // --------- | 850 // --------- |
| 851 | 851 |
| 852 static unsigned startWordBoundary(const UChar* characters, unsigned length, unsi
gned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMor
eContext) | 852 static unsigned startWordBoundary(const UChar* characters, unsigned length, unsi
gned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMor
eContext) |
| 853 { | 853 { |
| 854 TRACE_EVENT0("blink", "startWordBoundary"); | 854 TRACE_EVENT0("blink", "startWordBoundary"); |
| 855 ASSERT(offset); | 855 DCHECK(offset); |
| 856 if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset
)) { | 856 if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset
)) { |
| 857 needMoreContext = true; | 857 needMoreContext = true; |
| 858 return 0; | 858 return 0; |
| 859 } | 859 } |
| 860 needMoreContext = false; | 860 needMoreContext = false; |
| 861 int start, end; | 861 int start, end; |
| 862 U16_BACK_1(characters, 0, offset); | 862 U16_BACK_1(characters, 0, offset); |
| 863 findWordBoundary(characters, length, offset, &start, &end); | 863 findWordBoundary(characters, length, offset, &start, &end); |
| 864 return start; | 864 return start; |
| 865 } | 865 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 887 return startOfWordAlgorithm<EditingStrategy>(c, side); | 887 return startOfWordAlgorithm<EditingStrategy>(c, side); |
| 888 } | 888 } |
| 889 | 889 |
| 890 VisiblePositionInFlatTree startOfWord(const VisiblePositionInFlatTree& c, EWordS
ide side) | 890 VisiblePositionInFlatTree startOfWord(const VisiblePositionInFlatTree& c, EWordS
ide side) |
| 891 { | 891 { |
| 892 return startOfWordAlgorithm<EditingInFlatTreeStrategy>(c, side); | 892 return startOfWordAlgorithm<EditingInFlatTreeStrategy>(c, side); |
| 893 } | 893 } |
| 894 | 894 |
| 895 static unsigned endWordBoundary(const UChar* characters, unsigned length, unsign
ed offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreC
ontext) | 895 static unsigned endWordBoundary(const UChar* characters, unsigned length, unsign
ed offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreC
ontext) |
| 896 { | 896 { |
| 897 ASSERT(offset <= length); | 897 DCHECK_LE(offset, length); |
| 898 if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset,
length - offset) == static_cast<int>(length - offset)) { | 898 if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset,
length - offset) == static_cast<int>(length - offset)) { |
| 899 needMoreContext = true; | 899 needMoreContext = true; |
| 900 return length; | 900 return length; |
| 901 } | 901 } |
| 902 needMoreContext = false; | 902 needMoreContext = false; |
| 903 return findWordEndBoundary(characters, length, offset); | 903 return findWordEndBoundary(characters, length, offset); |
| 904 } | 904 } |
| 905 | 905 |
| 906 template <typename Strategy> | 906 template <typename Strategy> |
| 907 static VisiblePositionTemplate<Strategy> endOfWordAlgorithm(const VisiblePositio
nTemplate<Strategy>& c, EWordSide side) | 907 static VisiblePositionTemplate<Strategy> endOfWordAlgorithm(const VisiblePositio
nTemplate<Strategy>& c, EWordSide side) |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 return isLogicalEndOfLineAlgorithm<EditingStrategy>(p); | 1275 return isLogicalEndOfLineAlgorithm<EditingStrategy>(p); |
| 1276 } | 1276 } |
| 1277 | 1277 |
| 1278 bool isLogicalEndOfLine(const VisiblePositionInFlatTree& p) | 1278 bool isLogicalEndOfLine(const VisiblePositionInFlatTree& p) |
| 1279 { | 1279 { |
| 1280 return isLogicalEndOfLineAlgorithm<EditingInFlatTreeStrategy>(p); | 1280 return isLogicalEndOfLineAlgorithm<EditingInFlatTreeStrategy>(p); |
| 1281 } | 1281 } |
| 1282 | 1282 |
| 1283 static inline LayoutPoint absoluteLineDirectionPointToLocalPointInBlock(RootInli
neBox* root, LayoutUnit lineDirectionPoint) | 1283 static inline LayoutPoint absoluteLineDirectionPointToLocalPointInBlock(RootInli
neBox* root, LayoutUnit lineDirectionPoint) |
| 1284 { | 1284 { |
| 1285 ASSERT(root); | 1285 DCHECK(root); |
| 1286 LineLayoutBlockFlow containingBlock = root->block(); | 1286 LineLayoutBlockFlow containingBlock = root->block(); |
| 1287 FloatPoint absoluteBlockPoint = containingBlock.localToAbsolute(FloatPoint()
); | 1287 FloatPoint absoluteBlockPoint = containingBlock.localToAbsolute(FloatPoint()
); |
| 1288 if (containingBlock.hasOverflowClip()) | 1288 if (containingBlock.hasOverflowClip()) |
| 1289 absoluteBlockPoint -= FloatSize(containingBlock.scrolledContentOffset())
; | 1289 absoluteBlockPoint -= FloatSize(containingBlock.scrolledContentOffset())
; |
| 1290 | 1290 |
| 1291 if (root->block().isHorizontalWritingMode()) | 1291 if (root->block().isHorizontalWritingMode()) |
| 1292 return LayoutPoint(LayoutUnit(lineDirectionPoint - absoluteBlockPoint.x(
)), root->blockDirectionPointInLine()); | 1292 return LayoutPoint(LayoutUnit(lineDirectionPoint - absoluteBlockPoint.x(
)), root->blockDirectionPointInLine()); |
| 1293 | 1293 |
| 1294 return LayoutPoint(root->blockDirectionPointInLine(), LayoutUnit(lineDirecti
onPoint - absoluteBlockPoint.y())); | 1294 return LayoutPoint(root->blockDirectionPointInLine(), LayoutUnit(lineDirecti
onPoint - absoluteBlockPoint.y())); |
| 1295 } | 1295 } |
| (...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2209 // appeared in layout tree. | 2209 // appeared in layout tree. |
| 2210 // | 2210 // |
| 2211 // When |Text| node contains only first-letter characters and whitespaces, e.g. | 2211 // When |Text| node contains only first-letter characters and whitespaces, e.g. |
| 2212 // "B\n", associated |LayoutTextFragment| is first-letter part instead of | 2212 // "B\n", associated |LayoutTextFragment| is first-letter part instead of |
| 2213 // remaining part. | 2213 // remaining part. |
| 2214 // | 2214 // |
| 2215 // Punctuation characters are considered as first-letter. For "(1)ab", | 2215 // Punctuation characters are considered as first-letter. For "(1)ab", |
| 2216 // "(1)" are first-letter part and "ab" are remaining part. | 2216 // "(1)" are first-letter part and "ab" are remaining part. |
| 2217 LayoutObject* associatedLayoutObjectOf(const Node& node, int offsetInNode) | 2217 LayoutObject* associatedLayoutObjectOf(const Node& node, int offsetInNode) |
| 2218 { | 2218 { |
| 2219 ASSERT(offsetInNode >= 0); | 2219 DCHECK_GE(offsetInNode, 0); |
| 2220 LayoutObject* layoutObject = node.layoutObject(); | 2220 LayoutObject* layoutObject = node.layoutObject(); |
| 2221 if (!node.isTextNode() || !layoutObject || !toLayoutText(layoutObject)->isTe
xtFragment()) | 2221 if (!node.isTextNode() || !layoutObject || !toLayoutText(layoutObject)->isTe
xtFragment()) |
| 2222 return layoutObject; | 2222 return layoutObject; |
| 2223 LayoutTextFragment* layoutTextFragment = toLayoutTextFragment(layoutObject); | 2223 LayoutTextFragment* layoutTextFragment = toLayoutTextFragment(layoutObject); |
| 2224 if (!layoutTextFragment->isRemainingTextLayoutObject()) { | 2224 if (!layoutTextFragment->isRemainingTextLayoutObject()) { |
| 2225 ASSERT(static_cast<unsigned>(offsetInNode) <= layoutTextFragment->start(
) + layoutTextFragment->fragmentLength()); | 2225 DCHECK_LE(static_cast<unsigned>(offsetInNode), layoutTextFragment->start
() + layoutTextFragment->fragmentLength()); |
| 2226 return layoutTextFragment; | 2226 return layoutTextFragment; |
| 2227 } | 2227 } |
| 2228 if (layoutTextFragment->fragmentLength() && static_cast<unsigned>(offsetInNo
de) >= layoutTextFragment->start()) | 2228 if (layoutTextFragment->fragmentLength() && static_cast<unsigned>(offsetInNo
de) >= layoutTextFragment->start()) |
| 2229 return layoutObject; | 2229 return layoutObject; |
| 2230 LayoutObject* firstLetterLayoutObject = layoutTextFragment->firstLetterPseud
oElement()->layoutObject(); | 2230 LayoutObject* firstLetterLayoutObject = layoutTextFragment->firstLetterPseud
oElement()->layoutObject(); |
| 2231 // TODO(yosin): We're not sure when |firstLetterLayoutObject| has | 2231 // TODO(yosin): We're not sure when |firstLetterLayoutObject| has |
| 2232 // multiple child layout object. | 2232 // multiple child layout object. |
| 2233 ASSERT(firstLetterLayoutObject->slowFirstChild() == firstLetterLayoutObject-
>slowLastChild()); | 2233 DCHECK_EQ(firstLetterLayoutObject->slowFirstChild(), firstLetterLayoutObject
->slowLastChild()); |
| 2234 return firstLetterLayoutObject->slowFirstChild(); | 2234 return firstLetterLayoutObject->slowFirstChild(); |
| 2235 } | 2235 } |
| 2236 | 2236 |
| 2237 int caretMinOffset(const Node* node) | 2237 int caretMinOffset(const Node* node) |
| 2238 { | 2238 { |
| 2239 LayoutObject* layoutObject = associatedLayoutObjectOf(*node, 0); | 2239 LayoutObject* layoutObject = associatedLayoutObjectOf(*node, 0); |
| 2240 return layoutObject ? layoutObject->caretMinOffset() : 0; | 2240 return layoutObject ? layoutObject->caretMinOffset() : 0; |
| 2241 } | 2241 } |
| 2242 | 2242 |
| 2243 int caretMaxOffset(const Node* n) | 2243 int caretMaxOffset(const Node* n) |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2418 | 2418 |
| 2419 // return current position if it is in laid out text | 2419 // return current position if it is in laid out text |
| 2420 if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox()
) { | 2420 if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox()
) { |
| 2421 LayoutText* const textLayoutObject = toLayoutText(layoutObject); | 2421 LayoutText* const textLayoutObject = toLayoutText(layoutObject); |
| 2422 const unsigned textStartOffset = textLayoutObject->textStartOffset()
; | 2422 const unsigned textStartOffset = textLayoutObject->textStartOffset()
; |
| 2423 if (currentNode != startNode) { | 2423 if (currentNode != startNode) { |
| 2424 // This assertion fires in layout tests in the case-transform.ht
ml test because | 2424 // This assertion fires in layout tests in the case-transform.ht
ml test because |
| 2425 // of a mix-up between offsets in the text in the DOM tree with
text in the | 2425 // of a mix-up between offsets in the text in the DOM tree with
text in the |
| 2426 // layout tree which can have a different length due to case tra
nsformation. | 2426 // layout tree which can have a different length due to case tra
nsformation. |
| 2427 // Until we resolve that, disable this so we can run the layout
tests! | 2427 // Until we resolve that, disable this so we can run the layout
tests! |
| 2428 // ASSERT(currentOffset >= layoutObject->caretMaxOffset()); | 2428 // DCHECK_GE(currentOffset, layoutObject->caretMaxOffset()); |
| 2429 return PositionTemplate<Strategy>(currentNode, layoutObject->car
etMaxOffset() + textStartOffset); | 2429 return PositionTemplate<Strategy>(currentNode, layoutObject->car
etMaxOffset() + textStartOffset); |
| 2430 } | 2430 } |
| 2431 | 2431 |
| 2432 // Map offset in DOM node to offset in InlineBox. | 2432 // Map offset in DOM node to offset in InlineBox. |
| 2433 ASSERT(currentPos.offsetInLeafNode() >= static_cast<int>(textStartOf
fset)); | 2433 DCHECK_GE(currentPos.offsetInLeafNode(), static_cast<int>(textStartO
ffset)); |
| 2434 const unsigned textOffset = currentPos.offsetInLeafNode() - textStar
tOffset; | 2434 const unsigned textOffset = currentPos.offsetInLeafNode() - textStar
tOffset; |
| 2435 InlineTextBox* lastTextBox = textLayoutObject->lastTextBox(); | 2435 InlineTextBox* lastTextBox = textLayoutObject->lastTextBox(); |
| 2436 for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box
= box->nextTextBox()) { | 2436 for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box
= box->nextTextBox()) { |
| 2437 if (textOffset == box->start()) { | 2437 if (textOffset == box->start()) { |
| 2438 if (textLayoutObject->isTextFragment() && toLayoutTextFragme
nt(layoutObject)->isRemainingTextLayoutObject()) { | 2438 if (textLayoutObject->isTextFragment() && toLayoutTextFragme
nt(layoutObject)->isRemainingTextLayoutObject()) { |
| 2439 // |currentPos| is at start of remaining text of | 2439 // |currentPos| is at start of remaining text of |
| 2440 // |Text| node with :first-letter. | 2440 // |Text| node with :first-letter. |
| 2441 ASSERT(currentPos.offsetInLeafNode() >= 1); | 2441 DCHECK_GE(currentPos.offsetInLeafNode(), 1); |
| 2442 LayoutObject* firstLetterLayoutObject = toLayoutTextFrag
ment(layoutObject)->firstLetterPseudoElement()->layoutObject(); | 2442 LayoutObject* firstLetterLayoutObject = toLayoutTextFrag
ment(layoutObject)->firstLetterPseudoElement()->layoutObject(); |
| 2443 if (firstLetterLayoutObject && firstLetterLayoutObject->
style()->visibility() == VISIBLE) | 2443 if (firstLetterLayoutObject && firstLetterLayoutObject->
style()->visibility() == VISIBLE) |
| 2444 return currentPos.computePosition(); | 2444 return currentPos.computePosition(); |
| 2445 } | 2445 } |
| 2446 continue; | 2446 continue; |
| 2447 } | 2447 } |
| 2448 if (textOffset <= box->start() + box->len()) { | 2448 if (textOffset <= box->start() + box->len()) { |
| 2449 if (textOffset > box->start()) | 2449 if (textOffset > box->start()) |
| 2450 return currentPos.computePosition(); | 2450 return currentPos.computePosition(); |
| 2451 continue; | 2451 continue; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2560 if (currentPos.offsetInLeafNode() <= layoutObject->caretMinOffset()) | 2560 if (currentPos.offsetInLeafNode() <= layoutObject->caretMinOffset()) |
| 2561 return PositionTemplate<Strategy>::editingPositionOf(currentNode
, layoutObject->caretMinOffset()); | 2561 return PositionTemplate<Strategy>::editingPositionOf(currentNode
, layoutObject->caretMinOffset()); |
| 2562 continue; | 2562 continue; |
| 2563 } | 2563 } |
| 2564 | 2564 |
| 2565 // return current position if it is in laid out text | 2565 // return current position if it is in laid out text |
| 2566 if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox()
) { | 2566 if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox()
) { |
| 2567 LayoutText* const textLayoutObject = toLayoutText(layoutObject); | 2567 LayoutText* const textLayoutObject = toLayoutText(layoutObject); |
| 2568 const unsigned textStartOffset = textLayoutObject->textStartOffset()
; | 2568 const unsigned textStartOffset = textLayoutObject->textStartOffset()
; |
| 2569 if (currentNode != startNode) { | 2569 if (currentNode != startNode) { |
| 2570 ASSERT(currentPos.atStartOfNode()); | 2570 DCHECK(currentPos.atStartOfNode()); |
| 2571 return PositionTemplate<Strategy>(currentNode, layoutObject->car
etMinOffset() + textStartOffset); | 2571 return PositionTemplate<Strategy>(currentNode, layoutObject->car
etMinOffset() + textStartOffset); |
| 2572 } | 2572 } |
| 2573 | 2573 |
| 2574 // Map offset in DOM node to offset in InlineBox. | 2574 // Map offset in DOM node to offset in InlineBox. |
| 2575 ASSERT(currentPos.offsetInLeafNode() >= static_cast<int>(textStartOf
fset)); | 2575 DCHECK_GE(currentPos.offsetInLeafNode(), static_cast<int>(textStartO
ffset)); |
| 2576 const unsigned textOffset = currentPos.offsetInLeafNode() - textStar
tOffset; | 2576 const unsigned textOffset = currentPos.offsetInLeafNode() - textStar
tOffset; |
| 2577 InlineTextBox* lastTextBox = textLayoutObject->lastTextBox(); | 2577 InlineTextBox* lastTextBox = textLayoutObject->lastTextBox(); |
| 2578 for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box
= box->nextTextBox()) { | 2578 for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box
= box->nextTextBox()) { |
| 2579 if (textOffset <= box->end()) { | 2579 if (textOffset <= box->end()) { |
| 2580 if (textOffset >= box->start()) | 2580 if (textOffset >= box->start()) |
| 2581 return currentPos.computePosition(); | 2581 return currentPos.computePosition(); |
| 2582 continue; | 2582 continue; |
| 2583 } | 2583 } |
| 2584 | 2584 |
| 2585 if (box == lastTextBox || textOffset != box->start() + box->len(
)) | 2585 if (box == lastTextBox || textOffset != box->start() + box->len(
)) |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2758 // or both are non-editable. | 2758 // or both are non-editable. |
| 2759 if (highestRootOfPos == highestRoot) | 2759 if (highestRootOfPos == highestRoot) |
| 2760 return pos; | 2760 return pos; |
| 2761 | 2761 |
| 2762 // If this is not editable but |pos| has an editable root, skip to the end | 2762 // If this is not editable but |pos| has an editable root, skip to the end |
| 2763 if (!highestRoot && highestRootOfPos) | 2763 if (!highestRoot && highestRootOfPos) |
| 2764 return createVisiblePosition(PositionTemplate<Strategy>(highestRootOfPos
, PositionAnchorType::AfterAnchor).parentAnchoredEquivalent()); | 2764 return createVisiblePosition(PositionTemplate<Strategy>(highestRootOfPos
, PositionAnchorType::AfterAnchor).parentAnchoredEquivalent()); |
| 2765 | 2765 |
| 2766 // That must mean that |pos| is not editable. Return the next position after | 2766 // That must mean that |pos| is not editable. Return the next position after |
| 2767 // |pos| that is in the same editable region as this position | 2767 // |pos| that is in the same editable region as this position |
| 2768 ASSERT(highestRoot); | 2768 DCHECK(highestRoot); |
| 2769 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(),
*highestRoot); | 2769 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(),
*highestRoot); |
| 2770 } | 2770 } |
| 2771 | 2771 |
| 2772 template <typename Strategy> | 2772 template <typename Strategy> |
| 2773 static UChar32 characterAfterAlgorithm(const VisiblePositionTemplate<Strategy>&
visiblePosition) | 2773 static UChar32 characterAfterAlgorithm(const VisiblePositionTemplate<Strategy>&
visiblePosition) |
| 2774 { | 2774 { |
| 2775 // We canonicalize to the first of two equivalent candidates, but the second | 2775 // We canonicalize to the first of two equivalent candidates, but the second |
| 2776 // of the two candidates is the one that will be inside the text node | 2776 // of the two candidates is the one that will be inside the text node |
| 2777 // containing the character after this visible position. | 2777 // containing the character after this visible position. |
| 2778 const PositionTemplate<Strategy> pos = mostForwardCaretPosition(visiblePosit
ion.deepEquivalent()); | 2778 const PositionTemplate<Strategy> pos = mostForwardCaretPosition(visiblePosit
ion.deepEquivalent()); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2874 } | 2874 } |
| 2875 | 2875 |
| 2876 // Reposition at the other logical position corresponding to our | 2876 // Reposition at the other logical position corresponding to our |
| 2877 // edge's visual position and go for another round. | 2877 // edge's visual position and go for another round. |
| 2878 box = prevBox; | 2878 box = prevBox; |
| 2879 lineLayoutItem = box->getLineLayoutItem(); | 2879 lineLayoutItem = box->getLineLayoutItem(); |
| 2880 offset = prevBox->caretRightmostOffset(); | 2880 offset = prevBox->caretRightmostOffset(); |
| 2881 continue; | 2881 continue; |
| 2882 } | 2882 } |
| 2883 | 2883 |
| 2884 ASSERT(offset == box->caretLeftmostOffset()); | 2884 DCHECK_EQ(offset, box->caretLeftmostOffset()); |
| 2885 | 2885 |
| 2886 unsigned char level = box->bidiLevel(); | 2886 unsigned char level = box->bidiLevel(); |
| 2887 InlineBox* prevBox = box->prevLeafChild(); | 2887 InlineBox* prevBox = box->prevLeafChild(); |
| 2888 | 2888 |
| 2889 if (box->direction() == primaryDirection) { | 2889 if (box->direction() == primaryDirection) { |
| 2890 if (!prevBox) { | 2890 if (!prevBox) { |
| 2891 InlineBox* logicalStart = 0; | 2891 InlineBox* logicalStart = 0; |
| 2892 if (primaryDirection == LTR ? box->root().getLogicalStartBox
WithNode(logicalStart) : box->root().getLogicalEndBoxWithNode(logicalStart)) { | 2892 if (primaryDirection == LTR ? box->root().getLogicalStartBox
WithNode(logicalStart) : box->root().getLogicalEndBoxWithNode(logicalStart)) { |
| 2893 box = logicalStart; | 2893 box = logicalStart; |
| 2894 lineLayoutItem = box->getLineLayoutItem(); | 2894 lineLayoutItem = box->getLineLayoutItem(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2957 offset = primaryDirection == LTR ? box->caretMinOffset() : box->
caretMaxOffset(); | 2957 offset = primaryDirection == LTR ? box->caretMinOffset() : box->
caretMaxOffset(); |
| 2958 } | 2958 } |
| 2959 break; | 2959 break; |
| 2960 } | 2960 } |
| 2961 | 2961 |
| 2962 p = PositionTemplate<Strategy>::editingPositionOf(lineLayoutItem.node(),
offset); | 2962 p = PositionTemplate<Strategy>::editingPositionOf(lineLayoutItem.node(),
offset); |
| 2963 | 2963 |
| 2964 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) | 2964 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) |
| 2965 return p; | 2965 return p; |
| 2966 | 2966 |
| 2967 ASSERT(p != deepPosition); | 2967 DCHECK_NE(p, deepPosition); |
| 2968 } | 2968 } |
| 2969 } | 2969 } |
| 2970 | 2970 |
| 2971 template <typename Strategy> | 2971 template <typename Strategy> |
| 2972 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm(const VisiblePositionT
emplate<Strategy>& visiblePosition) | 2972 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm(const VisiblePositionT
emplate<Strategy>& visiblePosition) |
| 2973 { | 2973 { |
| 2974 const PositionTemplate<Strategy> pos = leftVisuallyDistinctCandidate(visible
Position); | 2974 const PositionTemplate<Strategy> pos = leftVisuallyDistinctCandidate(visible
Position); |
| 2975 // TODO(yosin) Why can't we move left from the last position in a tree? | 2975 // TODO(yosin) Why can't we move left from the last position in a tree? |
| 2976 if (pos.atStartOfTree() || pos.atEndOfTree()) | 2976 if (pos.atStartOfTree() || pos.atEndOfTree()) |
| 2977 return VisiblePositionTemplate<Strategy>(); | 2977 return VisiblePositionTemplate<Strategy>(); |
| 2978 | 2978 |
| 2979 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos); | 2979 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos); |
| 2980 ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent()); | 2980 DCHECK_NE(left.deepEquivalent(), visiblePosition.deepEquivalent()); |
| 2981 | 2981 |
| 2982 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin
gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda
ryAtOrAfter(left, visiblePosition.deepEquivalent()); | 2982 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin
gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda
ryAtOrAfter(left, visiblePosition.deepEquivalent()); |
| 2983 } | 2983 } |
| 2984 | 2984 |
| 2985 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) | 2985 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) |
| 2986 { | 2986 { |
| 2987 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition); | 2987 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition); |
| 2988 } | 2988 } |
| 2989 | 2989 |
| 2990 VisiblePositionInFlatTree leftPositionOf(const VisiblePositionInFlatTree& visibl
ePosition) | 2990 VisiblePositionInFlatTree leftPositionOf(const VisiblePositionInFlatTree& visibl
ePosition) |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3049 } | 3049 } |
| 3050 | 3050 |
| 3051 // Reposition at the other logical position corresponding to our | 3051 // Reposition at the other logical position corresponding to our |
| 3052 // edge's visual position and go for another round. | 3052 // edge's visual position and go for another round. |
| 3053 box = nextBox; | 3053 box = nextBox; |
| 3054 layoutObject = LineLayoutAPIShim::layoutObjectFrom(box->getLineL
ayoutItem()); | 3054 layoutObject = LineLayoutAPIShim::layoutObjectFrom(box->getLineL
ayoutItem()); |
| 3055 offset = nextBox->caretLeftmostOffset(); | 3055 offset = nextBox->caretLeftmostOffset(); |
| 3056 continue; | 3056 continue; |
| 3057 } | 3057 } |
| 3058 | 3058 |
| 3059 ASSERT(offset == box->caretRightmostOffset()); | 3059 DCHECK_EQ(offset, box->caretRightmostOffset()); |
| 3060 | 3060 |
| 3061 unsigned char level = box->bidiLevel(); | 3061 unsigned char level = box->bidiLevel(); |
| 3062 InlineBox* nextBox = box->nextLeafChild(); | 3062 InlineBox* nextBox = box->nextLeafChild(); |
| 3063 | 3063 |
| 3064 if (box->direction() == primaryDirection) { | 3064 if (box->direction() == primaryDirection) { |
| 3065 if (!nextBox) { | 3065 if (!nextBox) { |
| 3066 InlineBox* logicalEnd = 0; | 3066 InlineBox* logicalEnd = 0; |
| 3067 if (primaryDirection == LTR ? box->root().getLogicalEndBoxWi
thNode(logicalEnd) : box->root().getLogicalStartBoxWithNode(logicalEnd)) { | 3067 if (primaryDirection == LTR ? box->root().getLogicalEndBoxWi
thNode(logicalEnd) : box->root().getLogicalStartBoxWithNode(logicalEnd)) { |
| 3068 box = logicalEnd; | 3068 box = logicalEnd; |
| 3069 layoutObject = LineLayoutAPIShim::layoutObjectFrom(box->
getLineLayoutItem()); | 3069 layoutObject = LineLayoutAPIShim::layoutObjectFrom(box->
getLineLayoutItem()); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3135 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->
caretMinOffset(); | 3135 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->
caretMinOffset(); |
| 3136 } | 3136 } |
| 3137 break; | 3137 break; |
| 3138 } | 3138 } |
| 3139 | 3139 |
| 3140 p = PositionTemplate<Strategy>::editingPositionOf(layoutObject->node(),
offset); | 3140 p = PositionTemplate<Strategy>::editingPositionOf(layoutObject->node(),
offset); |
| 3141 | 3141 |
| 3142 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) | 3142 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) |
| 3143 return p; | 3143 return p; |
| 3144 | 3144 |
| 3145 ASSERT(p != deepPosition); | 3145 DCHECK_NE(p, deepPosition); |
| 3146 } | 3146 } |
| 3147 } | 3147 } |
| 3148 | 3148 |
| 3149 template <typename Strategy> | 3149 template <typename Strategy> |
| 3150 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm(const VisibleP
ositionTemplate<Strategy>& visiblePosition) | 3150 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm(const VisibleP
ositionTemplate<Strategy>& visiblePosition) |
| 3151 { | 3151 { |
| 3152 const PositionTemplate<Strategy> pos = rightVisuallyDistinctCandidate(visibl
ePosition); | 3152 const PositionTemplate<Strategy> pos = rightVisuallyDistinctCandidate(visibl
ePosition); |
| 3153 // FIXME: Why can't we move left from the last position in a tree? | 3153 // FIXME: Why can't we move left from the last position in a tree? |
| 3154 if (pos.atStartOfTree() || pos.atEndOfTree()) | 3154 if (pos.atStartOfTree() || pos.atEndOfTree()) |
| 3155 return VisiblePositionTemplate<Strategy>(); | 3155 return VisiblePositionTemplate<Strategy>(); |
| 3156 | 3156 |
| 3157 const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos); | 3157 const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos); |
| 3158 ASSERT(right.deepEquivalent() != visiblePosition.deepEquivalent()); | 3158 DCHECK_NE(right.deepEquivalent(), visiblePosition.deepEquivalent()); |
| 3159 | 3159 |
| 3160 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditi
ngBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBound
aryAtOrBefore(right, visiblePosition.deepEquivalent()); | 3160 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditi
ngBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBound
aryAtOrBefore(right, visiblePosition.deepEquivalent()); |
| 3161 } | 3161 } |
| 3162 | 3162 |
| 3163 VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition) | 3163 VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition) |
| 3164 { | 3164 { |
| 3165 return rightPositionOfAlgorithm<EditingStrategy>(visiblePosition); | 3165 return rightPositionOfAlgorithm<EditingStrategy>(visiblePosition); |
| 3166 } | 3166 } |
| 3167 | 3167 |
| 3168 VisiblePositionInFlatTree rightPositionOf(const VisiblePositionInFlatTree& visib
lePosition) | 3168 VisiblePositionInFlatTree rightPositionOf(const VisiblePositionInFlatTree& visib
lePosition) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3210 // both are non-editable. | 3210 // both are non-editable. |
| 3211 if (highestRootOfPos == highestRoot) | 3211 if (highestRootOfPos == highestRoot) |
| 3212 return pos; | 3212 return pos; |
| 3213 | 3213 |
| 3214 // If this is not editable but |pos| has an editable root, skip to the start | 3214 // If this is not editable but |pos| has an editable root, skip to the start |
| 3215 if (!highestRoot && highestRootOfPos) | 3215 if (!highestRoot && highestRootOfPos) |
| 3216 return createVisiblePosition(previousVisuallyDistinctCandidate(PositionT
emplate<Strategy>(highestRootOfPos, PositionAnchorType::BeforeAnchor).parentAnch
oredEquivalent())); | 3216 return createVisiblePosition(previousVisuallyDistinctCandidate(PositionT
emplate<Strategy>(highestRootOfPos, PositionAnchorType::BeforeAnchor).parentAnch
oredEquivalent())); |
| 3217 | 3217 |
| 3218 // That must mean that |pos| is not editable. Return the last position | 3218 // That must mean that |pos| is not editable. Return the last position |
| 3219 // before |pos| that is in the same editable region as this position | 3219 // before |pos| that is in the same editable region as this position |
| 3220 ASSERT(highestRoot); | 3220 DCHECK(highestRoot); |
| 3221 return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(),
*highestRoot); | 3221 return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(),
*highestRoot); |
| 3222 } | 3222 } |
| 3223 | 3223 |
| 3224 template <typename Strategy> | 3224 template <typename Strategy> |
| 3225 static VisiblePositionTemplate<Strategy> previousPositionOfAlgorithm(const Visib
lePositionTemplate<Strategy>& visiblePosition, EditingBoundaryCrossingRule rule) | 3225 static VisiblePositionTemplate<Strategy> previousPositionOfAlgorithm(const Visib
lePositionTemplate<Strategy>& visiblePosition, EditingBoundaryCrossingRule rule) |
| 3226 { | 3226 { |
| 3227 const PositionTemplate<Strategy> pos = previousVisuallyDistinctCandidate(vis
iblePosition.deepEquivalent()); | 3227 const PositionTemplate<Strategy> pos = previousVisuallyDistinctCandidate(vis
iblePosition.deepEquivalent()); |
| 3228 | 3228 |
| 3229 // return null visible position if there is no previous visible position | 3229 // return null visible position if there is no previous visible position |
| 3230 if (pos.atStartOfTree()) | 3230 if (pos.atStartOfTree()) |
| 3231 return VisiblePositionTemplate<Strategy>(); | 3231 return VisiblePositionTemplate<Strategy>(); |
| 3232 | 3232 |
| 3233 // we should always be able to make the affinity |TextAffinity::Downstream|, | 3233 // we should always be able to make the affinity |TextAffinity::Downstream|, |
| 3234 // because going previous from an |TextAffinity::Upstream| position can | 3234 // because going previous from an |TextAffinity::Upstream| position can |
| 3235 // never yield another |TextAffinity::Upstream position| (unless line wrap | 3235 // never yield another |TextAffinity::Upstream position| (unless line wrap |
| 3236 // length is 0!). | 3236 // length is 0!). |
| 3237 const VisiblePositionTemplate<Strategy> prev = createVisiblePosition(pos); | 3237 const VisiblePositionTemplate<Strategy> prev = createVisiblePosition(pos); |
| 3238 ASSERT(prev.deepEquivalent() != visiblePosition.deepEquivalent()); | 3238 DCHECK_NE(prev.deepEquivalent(), visiblePosition.deepEquivalent()); |
| 3239 | 3239 |
| 3240 switch (rule) { | 3240 switch (rule) { |
| 3241 case CanCrossEditingBoundary: | 3241 case CanCrossEditingBoundary: |
| 3242 return prev; | 3242 return prev; |
| 3243 case CannotCrossEditingBoundary: | 3243 case CannotCrossEditingBoundary: |
| 3244 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale
nt()); | 3244 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale
nt()); |
| 3245 case CanSkipOverEditingBoundary: | 3245 case CanSkipOverEditingBoundary: |
| 3246 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent
()); | 3246 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent
()); |
| 3247 } | 3247 } |
| 3248 | 3248 |
| 3249 ASSERT_NOT_REACHED(); | 3249 ASSERT_NOT_REACHED(); |
| 3250 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent()
); | 3250 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent()
); |
| 3251 } | 3251 } |
| 3252 | 3252 |
| 3253 VisiblePosition previousPositionOf(const VisiblePosition& visiblePosition, Editi
ngBoundaryCrossingRule rule) | 3253 VisiblePosition previousPositionOf(const VisiblePosition& visiblePosition, Editi
ngBoundaryCrossingRule rule) |
| 3254 { | 3254 { |
| 3255 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule); | 3255 return previousPositionOfAlgorithm<EditingStrategy>(visiblePosition, rule); |
| 3256 } | 3256 } |
| 3257 | 3257 |
| 3258 VisiblePositionInFlatTree previousPositionOf(const VisiblePositionInFlatTree& vi
siblePosition, EditingBoundaryCrossingRule rule) | 3258 VisiblePositionInFlatTree previousPositionOf(const VisiblePositionInFlatTree& vi
siblePosition, EditingBoundaryCrossingRule rule) |
| 3259 { | 3259 { |
| 3260 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePositio
n, rule); | 3260 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>(visiblePositio
n, rule); |
| 3261 } | 3261 } |
| 3262 | 3262 |
| 3263 } // namespace blink | 3263 } // namespace blink |
| OLD | NEW |