OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights |
3 * reserved. | 3 * reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 | 700 |
701 if (!iter) | 701 if (!iter) |
702 break; | 702 break; |
703 | 703 |
704 iter->first(); | 704 iter->first(); |
705 int offsetInIterator = offsetInBox - textBox->start() + previousBoxLength; | 705 int offsetInIterator = offsetInBox - textBox->start() + previousBoxLength; |
706 | 706 |
707 bool isWordBreak; | 707 bool isWordBreak; |
708 bool boxHasSameDirectionalityAsBlock = box->direction() == blockDirection; | 708 bool boxHasSameDirectionalityAsBlock = box->direction() == blockDirection; |
709 bool movingBackward = | 709 bool movingBackward = |
710 (direction == MoveLeft && box->direction() == TextDirection::Ltr) || | 710 (direction == MoveLeft && box->direction() == TextDirection::kLtr) || |
711 (direction == MoveRight && box->direction() == TextDirection::Rtl); | 711 (direction == MoveRight && box->direction() == TextDirection::kRtl); |
712 if ((skipsSpaceWhenMovingRight && boxHasSameDirectionalityAsBlock) || | 712 if ((skipsSpaceWhenMovingRight && boxHasSameDirectionalityAsBlock) || |
713 (!skipsSpaceWhenMovingRight && movingBackward)) { | 713 (!skipsSpaceWhenMovingRight && movingBackward)) { |
714 bool logicalStartInLayoutObject = | 714 bool logicalStartInLayoutObject = |
715 offsetInBox == static_cast<int>(textBox->start()) && | 715 offsetInBox == static_cast<int>(textBox->start()) && |
716 previousBoxInDifferentBlock; | 716 previousBoxInDifferentBlock; |
717 isWordBreak = isLogicalStartOfWord(iter, offsetInIterator, | 717 isWordBreak = isLogicalStartOfWord(iter, offsetInIterator, |
718 logicalStartInLayoutObject); | 718 logicalStartInLayoutObject); |
719 } else { | 719 } else { |
720 bool logicalEndInLayoutObject = | 720 bool logicalEndInLayoutObject = |
721 offsetInBox == static_cast<int>(textBox->start() + textBox->len()) && | 721 offsetInBox == static_cast<int>(textBox->start() + textBox->len()) && |
(...skipping 16 matching lines...) Expand all Loading... |
738 VisiblePosition leftWordBreak = | 738 VisiblePosition leftWordBreak = |
739 visualWordPosition(visiblePosition, MoveLeft, skipsSpaceWhenMovingRight); | 739 visualWordPosition(visiblePosition, MoveLeft, skipsSpaceWhenMovingRight); |
740 leftWordBreak = honorEditingBoundaryAtOrBefore( | 740 leftWordBreak = honorEditingBoundaryAtOrBefore( |
741 leftWordBreak, visiblePosition.deepEquivalent()); | 741 leftWordBreak, visiblePosition.deepEquivalent()); |
742 | 742 |
743 // FIXME: How should we handle a non-editable position? | 743 // FIXME: How should we handle a non-editable position? |
744 if (leftWordBreak.isNull() && | 744 if (leftWordBreak.isNull() && |
745 isEditablePosition(visiblePosition.deepEquivalent())) { | 745 isEditablePosition(visiblePosition.deepEquivalent())) { |
746 TextDirection blockDirection = | 746 TextDirection blockDirection = |
747 directionOfEnclosingBlock(visiblePosition.deepEquivalent()); | 747 directionOfEnclosingBlock(visiblePosition.deepEquivalent()); |
748 leftWordBreak = blockDirection == TextDirection::Ltr | 748 leftWordBreak = blockDirection == TextDirection::kLtr |
749 ? startOfEditableContent(visiblePosition) | 749 ? startOfEditableContent(visiblePosition) |
750 : endOfEditableContent(visiblePosition); | 750 : endOfEditableContent(visiblePosition); |
751 } | 751 } |
752 return leftWordBreak; | 752 return leftWordBreak; |
753 } | 753 } |
754 | 754 |
755 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, | 755 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, |
756 bool skipsSpaceWhenMovingRight) { | 756 bool skipsSpaceWhenMovingRight) { |
757 DCHECK(visiblePosition.isValid()) << visiblePosition; | 757 DCHECK(visiblePosition.isValid()) << visiblePosition; |
758 VisiblePosition rightWordBreak = | 758 VisiblePosition rightWordBreak = |
759 visualWordPosition(visiblePosition, MoveRight, skipsSpaceWhenMovingRight); | 759 visualWordPosition(visiblePosition, MoveRight, skipsSpaceWhenMovingRight); |
760 rightWordBreak = honorEditingBoundaryAtOrBefore( | 760 rightWordBreak = honorEditingBoundaryAtOrBefore( |
761 rightWordBreak, visiblePosition.deepEquivalent()); | 761 rightWordBreak, visiblePosition.deepEquivalent()); |
762 | 762 |
763 // FIXME: How should we handle a non-editable position? | 763 // FIXME: How should we handle a non-editable position? |
764 if (rightWordBreak.isNull() && | 764 if (rightWordBreak.isNull() && |
765 isEditablePosition(visiblePosition.deepEquivalent())) { | 765 isEditablePosition(visiblePosition.deepEquivalent())) { |
766 TextDirection blockDirection = | 766 TextDirection blockDirection = |
767 directionOfEnclosingBlock(visiblePosition.deepEquivalent()); | 767 directionOfEnclosingBlock(visiblePosition.deepEquivalent()); |
768 rightWordBreak = blockDirection == TextDirection::Ltr | 768 rightWordBreak = blockDirection == TextDirection::kLtr |
769 ? endOfEditableContent(visiblePosition) | 769 ? endOfEditableContent(visiblePosition) |
770 : startOfEditableContent(visiblePosition); | 770 : startOfEditableContent(visiblePosition); |
771 } | 771 } |
772 return rightWordBreak; | 772 return rightWordBreak; |
773 } | 773 } |
774 | 774 |
775 template <typename Strategy> | 775 template <typename Strategy> |
776 static ContainerNode* nonShadowBoundaryParentNode(Node* node) { | 776 static ContainerNode* nonShadowBoundaryParentNode(Node* node) { |
777 ContainerNode* parent = Strategy::parent(*node); | 777 ContainerNode* parent = Strategy::parent(*node); |
778 return parent && !parent->isShadowRoot() ? parent : nullptr; | 778 return parent && !parent->isShadowRoot() ? parent : nullptr; |
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1782 } | 1782 } |
1783 | 1783 |
1784 const LayoutItem layoutItem = | 1784 const LayoutItem layoutItem = |
1785 LayoutItem(prevousNodeIterator->layoutObject()); | 1785 LayoutItem(prevousNodeIterator->layoutObject()); |
1786 if (layoutItem.isNull()) { | 1786 if (layoutItem.isNull()) { |
1787 prevousNodeIterator = | 1787 prevousNodeIterator = |
1788 Strategy::previousPostOrder(*prevousNodeIterator, startBlock); | 1788 Strategy::previousPostOrder(*prevousNodeIterator, startBlock); |
1789 continue; | 1789 continue; |
1790 } | 1790 } |
1791 const ComputedStyle& style = layoutItem.styleRef(); | 1791 const ComputedStyle& style = layoutItem.styleRef(); |
1792 if (style.visibility() != EVisibility::Visible) { | 1792 if (style.visibility() != EVisibility::kVisible) { |
1793 prevousNodeIterator = | 1793 prevousNodeIterator = |
1794 Strategy::previousPostOrder(*prevousNodeIterator, startBlock); | 1794 Strategy::previousPostOrder(*prevousNodeIterator, startBlock); |
1795 continue; | 1795 continue; |
1796 } | 1796 } |
1797 | 1797 |
1798 if (layoutItem.isBR() || isEnclosingBlock(prevousNodeIterator)) | 1798 if (layoutItem.isBR() || isEnclosingBlock(prevousNodeIterator)) |
1799 break; | 1799 break; |
1800 | 1800 |
1801 if (layoutItem.isText() && | 1801 if (layoutItem.isText() && |
1802 toLayoutText(prevousNodeIterator->layoutObject()) | 1802 toLayoutText(prevousNodeIterator->layoutObject()) |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 if (!nextNodeItreator || !nextNodeItreator->isDescendantOf(highestRoot)) | 1895 if (!nextNodeItreator || !nextNodeItreator->isDescendantOf(highestRoot)) |
1896 break; | 1896 break; |
1897 } | 1897 } |
1898 | 1898 |
1899 LayoutObject* const layoutObject = nextNodeItreator->layoutObject(); | 1899 LayoutObject* const layoutObject = nextNodeItreator->layoutObject(); |
1900 if (!layoutObject) { | 1900 if (!layoutObject) { |
1901 nextNodeItreator = Strategy::next(*nextNodeItreator, startBlock); | 1901 nextNodeItreator = Strategy::next(*nextNodeItreator, startBlock); |
1902 continue; | 1902 continue; |
1903 } | 1903 } |
1904 const ComputedStyle& style = layoutObject->styleRef(); | 1904 const ComputedStyle& style = layoutObject->styleRef(); |
1905 if (style.visibility() != EVisibility::Visible) { | 1905 if (style.visibility() != EVisibility::kVisible) { |
1906 nextNodeItreator = Strategy::next(*nextNodeItreator, startBlock); | 1906 nextNodeItreator = Strategy::next(*nextNodeItreator, startBlock); |
1907 continue; | 1907 continue; |
1908 } | 1908 } |
1909 | 1909 |
1910 if (layoutObject->isBR() || isEnclosingBlock(nextNodeItreator)) | 1910 if (layoutObject->isBR() || isEnclosingBlock(nextNodeItreator)) |
1911 break; | 1911 break; |
1912 | 1912 |
1913 // FIXME: We avoid returning a position where the layoutObject can't accept | 1913 // FIXME: We avoid returning a position where the layoutObject can't accept |
1914 // the caret. | 1914 // the caret. |
1915 if (layoutObject->isText() && | 1915 if (layoutObject->isText() && |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2206 // of INPUT/TEXTAREA element, by |nextPosition().isNull()|, because of | 2206 // of INPUT/TEXTAREA element, by |nextPosition().isNull()|, because of |
2207 // an inner editor is an only leaf node. | 2207 // an inner editor is an only leaf node. |
2208 if (!nextPosition.deepEquivalent().isAfterAnchor()) | 2208 if (!nextPosition.deepEquivalent().isAfterAnchor()) |
2209 return false; | 2209 return false; |
2210 return isTextControlElement(nextPosition.deepEquivalent().anchorNode()); | 2210 return isTextControlElement(nextPosition.deepEquivalent().anchorNode()); |
2211 } | 2211 } |
2212 | 2212 |
2213 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, | 2213 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, |
2214 TextDirection direction) { | 2214 TextDirection direction) { |
2215 DCHECK(c.isValid()) << c; | 2215 DCHECK(c.isValid()) << c; |
2216 return direction == TextDirection::Ltr ? logicalStartOfLine(c) | 2216 return direction == TextDirection::kLtr ? logicalStartOfLine(c) |
2217 : logicalEndOfLine(c); | 2217 : logicalEndOfLine(c); |
2218 } | 2218 } |
2219 | 2219 |
2220 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, | 2220 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, |
2221 TextDirection direction) { | 2221 TextDirection direction) { |
2222 DCHECK(c.isValid()) << c; | 2222 DCHECK(c.isValid()) << c; |
2223 return direction == TextDirection::Ltr ? logicalEndOfLine(c) | 2223 return direction == TextDirection::kLtr ? logicalEndOfLine(c) |
2224 : logicalStartOfLine(c); | 2224 : logicalStartOfLine(c); |
2225 } | 2225 } |
2226 | 2226 |
2227 static bool isNonTextLeafChild(LayoutObject* object) { | 2227 static bool isNonTextLeafChild(LayoutObject* object) { |
2228 if (object->slowFirstChild()) | 2228 if (object->slowFirstChild()) |
2229 return false; | 2229 return false; |
2230 if (object->isText()) | 2230 if (object->isText()) |
2231 return false; | 2231 return false; |
2232 return true; | 2232 return true; |
2233 } | 2233 } |
2234 | 2234 |
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2821 // saved position. There is code below that terminates early if we're | 2821 // saved position. There is code below that terminates early if we're |
2822 // *about* to move to a visually distinct position. | 2822 // *about* to move to a visually distinct position. |
2823 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && | 2823 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && |
2824 currentNode != boundary) | 2824 currentNode != boundary) |
2825 return lastVisible.deprecatedComputePosition(); | 2825 return lastVisible.deprecatedComputePosition(); |
2826 | 2826 |
2827 // skip position in non-laid out or invisible node | 2827 // skip position in non-laid out or invisible node |
2828 LayoutObject* layoutObject = | 2828 LayoutObject* layoutObject = |
2829 associatedLayoutObjectOf(*currentNode, currentPos.offsetInLeafNode()); | 2829 associatedLayoutObjectOf(*currentNode, currentPos.offsetInLeafNode()); |
2830 if (!layoutObject || | 2830 if (!layoutObject || |
2831 layoutObject->style()->visibility() != EVisibility::Visible) | 2831 layoutObject->style()->visibility() != EVisibility::kVisible) |
2832 continue; | 2832 continue; |
2833 | 2833 |
2834 if (rule == CanCrossEditingBoundary && boundaryCrossed) { | 2834 if (rule == CanCrossEditingBoundary && boundaryCrossed) { |
2835 lastVisible = currentPos; | 2835 lastVisible = currentPos; |
2836 break; | 2836 break; |
2837 } | 2837 } |
2838 | 2838 |
2839 // track last visible streamer position | 2839 // track last visible streamer position |
2840 if (isStreamer<Strategy>(currentPos)) | 2840 if (isStreamer<Strategy>(currentPos)) |
2841 lastVisible = currentPos; | 2841 lastVisible = currentPos; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2885 ->isRemainingTextLayoutObject()) { | 2885 ->isRemainingTextLayoutObject()) { |
2886 // |currentPos| is at start of remaining text of | 2886 // |currentPos| is at start of remaining text of |
2887 // |Text| node with :first-letter. | 2887 // |Text| node with :first-letter. |
2888 DCHECK_GE(currentPos.offsetInLeafNode(), 1); | 2888 DCHECK_GE(currentPos.offsetInLeafNode(), 1); |
2889 LayoutObject* firstLetterLayoutObject = | 2889 LayoutObject* firstLetterLayoutObject = |
2890 toLayoutTextFragment(layoutObject) | 2890 toLayoutTextFragment(layoutObject) |
2891 ->firstLetterPseudoElement() | 2891 ->firstLetterPseudoElement() |
2892 ->layoutObject(); | 2892 ->layoutObject(); |
2893 if (firstLetterLayoutObject && | 2893 if (firstLetterLayoutObject && |
2894 firstLetterLayoutObject->style()->visibility() == | 2894 firstLetterLayoutObject->style()->visibility() == |
2895 EVisibility::Visible) | 2895 EVisibility::kVisible) |
2896 return currentPos.computePosition(); | 2896 return currentPos.computePosition(); |
2897 } | 2897 } |
2898 continue; | 2898 continue; |
2899 } | 2899 } |
2900 if (textOffset <= box->start() + box->len()) { | 2900 if (textOffset <= box->start() + box->len()) { |
2901 if (textOffset > box->start()) | 2901 if (textOffset > box->start()) |
2902 return currentPos.computePosition(); | 2902 return currentPos.computePosition(); |
2903 continue; | 2903 continue; |
2904 } | 2904 } |
2905 | 2905 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3005 // Note: The first position after the last in a node whose ends are visually | 3005 // Note: The first position after the last in a node whose ends are visually |
3006 // distinct positions will be [boundary->parentNode(), | 3006 // distinct positions will be [boundary->parentNode(), |
3007 // originalBlock->nodeIndex() + 1]. | 3007 // originalBlock->nodeIndex() + 1]. |
3008 if (boundary && Strategy::parent(*boundary) == currentNode) | 3008 if (boundary && Strategy::parent(*boundary) == currentNode) |
3009 return lastVisible.deprecatedComputePosition(); | 3009 return lastVisible.deprecatedComputePosition(); |
3010 | 3010 |
3011 // skip position in non-laid out or invisible node | 3011 // skip position in non-laid out or invisible node |
3012 LayoutObject* layoutObject = | 3012 LayoutObject* layoutObject = |
3013 associatedLayoutObjectOf(*currentNode, currentPos.offsetInLeafNode()); | 3013 associatedLayoutObjectOf(*currentNode, currentPos.offsetInLeafNode()); |
3014 if (!layoutObject || | 3014 if (!layoutObject || |
3015 layoutObject->style()->visibility() != EVisibility::Visible) | 3015 layoutObject->style()->visibility() != EVisibility::kVisible) |
3016 continue; | 3016 continue; |
3017 | 3017 |
3018 if (rule == CanCrossEditingBoundary && boundaryCrossed) { | 3018 if (rule == CanCrossEditingBoundary && boundaryCrossed) { |
3019 lastVisible = currentPos; | 3019 lastVisible = currentPos; |
3020 break; | 3020 break; |
3021 } | 3021 } |
3022 | 3022 |
3023 // track last visible streamer position | 3023 // track last visible streamer position |
3024 if (isStreamer<Strategy>(currentPos)) | 3024 if (isStreamer<Strategy>(currentPos)) |
3025 lastVisible = currentPos; | 3025 lastVisible = currentPos; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3142 static bool isVisuallyEquivalentCandidateAlgorithm( | 3142 static bool isVisuallyEquivalentCandidateAlgorithm( |
3143 const PositionTemplate<Strategy>& position) { | 3143 const PositionTemplate<Strategy>& position) { |
3144 Node* const anchorNode = position.anchorNode(); | 3144 Node* const anchorNode = position.anchorNode(); |
3145 if (!anchorNode) | 3145 if (!anchorNode) |
3146 return false; | 3146 return false; |
3147 | 3147 |
3148 LayoutObject* layoutObject = anchorNode->layoutObject(); | 3148 LayoutObject* layoutObject = anchorNode->layoutObject(); |
3149 if (!layoutObject) | 3149 if (!layoutObject) |
3150 return false; | 3150 return false; |
3151 | 3151 |
3152 if (layoutObject->style()->visibility() != EVisibility::Visible) | 3152 if (layoutObject->style()->visibility() != EVisibility::kVisible) |
3153 return false; | 3153 return false; |
3154 | 3154 |
3155 if (layoutObject->isBR()) { | 3155 if (layoutObject->isBR()) { |
3156 // TODO(leviw) The condition should be | 3156 // TODO(leviw) The condition should be |
3157 // m_anchorType == PositionAnchorType::BeforeAnchor, but for now we | 3157 // m_anchorType == PositionAnchorType::BeforeAnchor, but for now we |
3158 // still need to support legacy positions. | 3158 // still need to support legacy positions. |
3159 if (position.isAfterAnchor()) | 3159 if (position.isAfterAnchor()) |
3160 return false; | 3160 return false; |
3161 if (position.computeEditingOffset()) | 3161 if (position.computeEditingOffset()) |
3162 return false; | 3162 return false; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3328 mostForwardCaretPosition(p); | 3328 mostForwardCaretPosition(p); |
3329 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); | 3329 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
3330 const TextAffinity affinity = visiblePosition.affinity(); | 3330 const TextAffinity affinity = visiblePosition.affinity(); |
3331 | 3331 |
3332 while (true) { | 3332 while (true) { |
3333 InlineBoxPosition boxPosition = | 3333 InlineBoxPosition boxPosition = |
3334 computeInlineBoxPosition(p, affinity, primaryDirection); | 3334 computeInlineBoxPosition(p, affinity, primaryDirection); |
3335 InlineBox* box = boxPosition.inlineBox; | 3335 InlineBox* box = boxPosition.inlineBox; |
3336 int offset = boxPosition.offsetInBox; | 3336 int offset = boxPosition.offsetInBox; |
3337 if (!box) | 3337 if (!box) |
3338 return primaryDirection == TextDirection::Ltr | 3338 return primaryDirection == TextDirection::kLtr |
3339 ? previousVisuallyDistinctCandidate(deepPosition) | 3339 ? previousVisuallyDistinctCandidate(deepPosition) |
3340 : nextVisuallyDistinctCandidate(deepPosition); | 3340 : nextVisuallyDistinctCandidate(deepPosition); |
3341 | 3341 |
3342 LineLayoutItem lineLayoutItem = box->getLineLayoutItem(); | 3342 LineLayoutItem lineLayoutItem = box->getLineLayoutItem(); |
3343 | 3343 |
3344 while (true) { | 3344 while (true) { |
3345 if ((lineLayoutItem.isAtomicInlineLevel() || lineLayoutItem.isBR()) && | 3345 if ((lineLayoutItem.isAtomicInlineLevel() || lineLayoutItem.isBR()) && |
3346 offset == box->caretRightmostOffset()) | 3346 offset == box->caretRightmostOffset()) |
3347 return box->isLeftToRightDirection() | 3347 return box->isLeftToRightDirection() |
3348 ? previousVisuallyDistinctCandidate(deepPosition) | 3348 ? previousVisuallyDistinctCandidate(deepPosition) |
3349 : nextVisuallyDistinctCandidate(deepPosition); | 3349 : nextVisuallyDistinctCandidate(deepPosition); |
3350 | 3350 |
3351 if (!lineLayoutItem.node()) { | 3351 if (!lineLayoutItem.node()) { |
3352 box = box->prevLeafChild(); | 3352 box = box->prevLeafChild(); |
3353 if (!box) | 3353 if (!box) |
3354 return primaryDirection == TextDirection::Ltr | 3354 return primaryDirection == TextDirection::kLtr |
3355 ? previousVisuallyDistinctCandidate(deepPosition) | 3355 ? previousVisuallyDistinctCandidate(deepPosition) |
3356 : nextVisuallyDistinctCandidate(deepPosition); | 3356 : nextVisuallyDistinctCandidate(deepPosition); |
3357 lineLayoutItem = box->getLineLayoutItem(); | 3357 lineLayoutItem = box->getLineLayoutItem(); |
3358 offset = box->caretRightmostOffset(); | 3358 offset = box->caretRightmostOffset(); |
3359 continue; | 3359 continue; |
3360 } | 3360 } |
3361 | 3361 |
3362 offset = box->isLeftToRightDirection() | 3362 offset = box->isLeftToRightDirection() |
3363 ? previousGraphemeBoundaryOf(lineLayoutItem.node(), offset) | 3363 ? previousGraphemeBoundaryOf(lineLayoutItem.node(), offset) |
3364 : nextGraphemeBoundaryOf(lineLayoutItem.node(), offset); | 3364 : nextGraphemeBoundaryOf(lineLayoutItem.node(), offset); |
3365 | 3365 |
3366 int caretMinOffset = box->caretMinOffset(); | 3366 int caretMinOffset = box->caretMinOffset(); |
3367 int caretMaxOffset = box->caretMaxOffset(); | 3367 int caretMaxOffset = box->caretMaxOffset(); |
3368 | 3368 |
3369 if (offset > caretMinOffset && offset < caretMaxOffset) | 3369 if (offset > caretMinOffset && offset < caretMaxOffset) |
3370 break; | 3370 break; |
3371 | 3371 |
3372 if (box->isLeftToRightDirection() ? offset < caretMinOffset | 3372 if (box->isLeftToRightDirection() ? offset < caretMinOffset |
3373 : offset > caretMaxOffset) { | 3373 : offset > caretMaxOffset) { |
3374 // Overshot to the left. | 3374 // Overshot to the left. |
3375 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); | 3375 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); |
3376 if (!prevBox) { | 3376 if (!prevBox) { |
3377 PositionTemplate<Strategy> positionOnLeft = | 3377 PositionTemplate<Strategy> positionOnLeft = |
3378 primaryDirection == TextDirection::Ltr | 3378 primaryDirection == TextDirection::kLtr |
3379 ? previousVisuallyDistinctCandidate( | 3379 ? previousVisuallyDistinctCandidate( |
3380 visiblePosition.deepEquivalent()) | 3380 visiblePosition.deepEquivalent()) |
3381 : nextVisuallyDistinctCandidate( | 3381 : nextVisuallyDistinctCandidate( |
3382 visiblePosition.deepEquivalent()); | 3382 visiblePosition.deepEquivalent()); |
3383 if (positionOnLeft.isNull()) | 3383 if (positionOnLeft.isNull()) |
3384 return PositionTemplate<Strategy>(); | 3384 return PositionTemplate<Strategy>(); |
3385 | 3385 |
3386 InlineBox* boxOnLeft = computeInlineBoxPosition( | 3386 InlineBox* boxOnLeft = computeInlineBoxPosition( |
3387 positionOnLeft, affinity, primaryDirection) | 3387 positionOnLeft, affinity, primaryDirection) |
3388 .inlineBox; | 3388 .inlineBox; |
(...skipping 11 matching lines...) Expand all Loading... |
3400 } | 3400 } |
3401 | 3401 |
3402 DCHECK_EQ(offset, box->caretLeftmostOffset()); | 3402 DCHECK_EQ(offset, box->caretLeftmostOffset()); |
3403 | 3403 |
3404 unsigned char level = box->bidiLevel(); | 3404 unsigned char level = box->bidiLevel(); |
3405 InlineBox* prevBox = box->prevLeafChild(); | 3405 InlineBox* prevBox = box->prevLeafChild(); |
3406 | 3406 |
3407 if (box->direction() == primaryDirection) { | 3407 if (box->direction() == primaryDirection) { |
3408 if (!prevBox) { | 3408 if (!prevBox) { |
3409 InlineBox* logicalStart = 0; | 3409 InlineBox* logicalStart = 0; |
3410 if (primaryDirection == TextDirection::Ltr | 3410 if (primaryDirection == TextDirection::kLtr |
3411 ? box->root().getLogicalStartBoxWithNode(logicalStart) | 3411 ? box->root().getLogicalStartBoxWithNode(logicalStart) |
3412 : box->root().getLogicalEndBoxWithNode(logicalStart)) { | 3412 : box->root().getLogicalEndBoxWithNode(logicalStart)) { |
3413 box = logicalStart; | 3413 box = logicalStart; |
3414 lineLayoutItem = box->getLineLayoutItem(); | 3414 lineLayoutItem = box->getLineLayoutItem(); |
3415 offset = primaryDirection == TextDirection::Ltr | 3415 offset = primaryDirection == TextDirection::kLtr |
3416 ? box->caretMinOffset() | 3416 ? box->caretMinOffset() |
3417 : box->caretMaxOffset(); | 3417 : box->caretMaxOffset(); |
3418 } | 3418 } |
3419 break; | 3419 break; |
3420 } | 3420 } |
3421 if (prevBox->bidiLevel() >= level) | 3421 if (prevBox->bidiLevel() >= level) |
3422 break; | 3422 break; |
3423 | 3423 |
3424 level = prevBox->bidiLevel(); | 3424 level = prevBox->bidiLevel(); |
3425 | 3425 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3469 while (InlineBox* prevBox = box->prevLeafChild()) { | 3469 while (InlineBox* prevBox = box->prevLeafChild()) { |
3470 if (prevBox->bidiLevel() < level) | 3470 if (prevBox->bidiLevel() < level) |
3471 break; | 3471 break; |
3472 box = prevBox; | 3472 box = prevBox; |
3473 } | 3473 } |
3474 if (box->bidiLevel() == level) | 3474 if (box->bidiLevel() == level) |
3475 break; | 3475 break; |
3476 level = box->bidiLevel(); | 3476 level = box->bidiLevel(); |
3477 } | 3477 } |
3478 lineLayoutItem = box->getLineLayoutItem(); | 3478 lineLayoutItem = box->getLineLayoutItem(); |
3479 offset = primaryDirection == TextDirection::Ltr ? box->caretMinOffset() | 3479 offset = primaryDirection == TextDirection::kLtr |
3480 : box->caretMaxOffset(); | 3480 ? box->caretMinOffset() |
| 3481 : box->caretMaxOffset(); |
3481 } | 3482 } |
3482 break; | 3483 break; |
3483 } | 3484 } |
3484 | 3485 |
3485 p = PositionTemplate<Strategy>::editingPositionOf(lineLayoutItem.node(), | 3486 p = PositionTemplate<Strategy>::editingPositionOf(lineLayoutItem.node(), |
3486 offset); | 3487 offset); |
3487 | 3488 |
3488 if ((isVisuallyEquivalentCandidate(p) && | 3489 if ((isVisuallyEquivalentCandidate(p) && |
3489 mostForwardCaretPosition(p) != downstreamStart) || | 3490 mostForwardCaretPosition(p) != downstreamStart) || |
3490 p.atStartOfTree() || p.atEndOfTree()) | 3491 p.atStartOfTree() || p.atEndOfTree()) |
3491 return p; | 3492 return p; |
3492 | 3493 |
3493 DCHECK_NE(p, deepPosition); | 3494 DCHECK_NE(p, deepPosition); |
3494 } | 3495 } |
3495 } | 3496 } |
3496 | 3497 |
3497 template <typename Strategy> | 3498 template <typename Strategy> |
3498 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm( | 3499 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm( |
3499 const VisiblePositionTemplate<Strategy>& visiblePosition) { | 3500 const VisiblePositionTemplate<Strategy>& visiblePosition) { |
3500 DCHECK(visiblePosition.isValid()) << visiblePosition; | 3501 DCHECK(visiblePosition.isValid()) << visiblePosition; |
3501 const PositionTemplate<Strategy> pos = | 3502 const PositionTemplate<Strategy> pos = |
3502 leftVisuallyDistinctCandidate(visiblePosition); | 3503 leftVisuallyDistinctCandidate(visiblePosition); |
3503 // TODO(yosin) Why can't we move left from the last position in a tree? | 3504 // TODO(yosin) Why can't we move left from the last position in a tree? |
3504 if (pos.atStartOfTree() || pos.atEndOfTree()) | 3505 if (pos.atStartOfTree() || pos.atEndOfTree()) |
3505 return VisiblePositionTemplate<Strategy>(); | 3506 return VisiblePositionTemplate<Strategy>(); |
3506 | 3507 |
3507 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos); | 3508 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos); |
3508 DCHECK_NE(left.deepEquivalent(), visiblePosition.deepEquivalent()); | 3509 DCHECK_NE(left.deepEquivalent(), visiblePosition.deepEquivalent()); |
3509 | 3510 |
3510 return directionOfEnclosingBlock(left.deepEquivalent()) == TextDirection::Ltr | 3511 return directionOfEnclosingBlock(left.deepEquivalent()) == TextDirection::kLtr |
3511 ? honorEditingBoundaryAtOrBefore(left, | 3512 ? honorEditingBoundaryAtOrBefore(left, |
3512 visiblePosition.deepEquivalent()) | 3513 visiblePosition.deepEquivalent()) |
3513 : honorEditingBoundaryAtOrAfter(left, | 3514 : honorEditingBoundaryAtOrAfter(left, |
3514 visiblePosition.deepEquivalent()); | 3515 visiblePosition.deepEquivalent()); |
3515 } | 3516 } |
3516 | 3517 |
3517 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) { | 3518 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) { |
3518 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition); | 3519 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition); |
3519 } | 3520 } |
3520 | 3521 |
(...skipping 16 matching lines...) Expand all Loading... |
3537 mostForwardCaretPosition(p); | 3538 mostForwardCaretPosition(p); |
3538 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); | 3539 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
3539 const TextAffinity affinity = visiblePosition.affinity(); | 3540 const TextAffinity affinity = visiblePosition.affinity(); |
3540 | 3541 |
3541 while (true) { | 3542 while (true) { |
3542 InlineBoxPosition boxPosition = | 3543 InlineBoxPosition boxPosition = |
3543 computeInlineBoxPosition(p, affinity, primaryDirection); | 3544 computeInlineBoxPosition(p, affinity, primaryDirection); |
3544 InlineBox* box = boxPosition.inlineBox; | 3545 InlineBox* box = boxPosition.inlineBox; |
3545 int offset = boxPosition.offsetInBox; | 3546 int offset = boxPosition.offsetInBox; |
3546 if (!box) | 3547 if (!box) |
3547 return primaryDirection == TextDirection::Ltr | 3548 return primaryDirection == TextDirection::kLtr |
3548 ? nextVisuallyDistinctCandidate(deepPosition) | 3549 ? nextVisuallyDistinctCandidate(deepPosition) |
3549 : previousVisuallyDistinctCandidate(deepPosition); | 3550 : previousVisuallyDistinctCandidate(deepPosition); |
3550 | 3551 |
3551 LayoutObject* layoutObject = | 3552 LayoutObject* layoutObject = |
3552 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); | 3553 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); |
3553 | 3554 |
3554 while (true) { | 3555 while (true) { |
3555 if ((layoutObject->isAtomicInlineLevel() || layoutObject->isBR()) && | 3556 if ((layoutObject->isAtomicInlineLevel() || layoutObject->isBR()) && |
3556 offset == box->caretLeftmostOffset()) | 3557 offset == box->caretLeftmostOffset()) |
3557 return box->isLeftToRightDirection() | 3558 return box->isLeftToRightDirection() |
3558 ? nextVisuallyDistinctCandidate(deepPosition) | 3559 ? nextVisuallyDistinctCandidate(deepPosition) |
3559 : previousVisuallyDistinctCandidate(deepPosition); | 3560 : previousVisuallyDistinctCandidate(deepPosition); |
3560 | 3561 |
3561 if (!layoutObject->node()) { | 3562 if (!layoutObject->node()) { |
3562 box = box->nextLeafChild(); | 3563 box = box->nextLeafChild(); |
3563 if (!box) | 3564 if (!box) |
3564 return primaryDirection == TextDirection::Ltr | 3565 return primaryDirection == TextDirection::kLtr |
3565 ? nextVisuallyDistinctCandidate(deepPosition) | 3566 ? nextVisuallyDistinctCandidate(deepPosition) |
3566 : previousVisuallyDistinctCandidate(deepPosition); | 3567 : previousVisuallyDistinctCandidate(deepPosition); |
3567 layoutObject = | 3568 layoutObject = |
3568 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); | 3569 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); |
3569 offset = box->caretLeftmostOffset(); | 3570 offset = box->caretLeftmostOffset(); |
3570 continue; | 3571 continue; |
3571 } | 3572 } |
3572 | 3573 |
3573 offset = box->isLeftToRightDirection() | 3574 offset = box->isLeftToRightDirection() |
3574 ? nextGraphemeBoundaryOf(layoutObject->node(), offset) | 3575 ? nextGraphemeBoundaryOf(layoutObject->node(), offset) |
3575 : previousGraphemeBoundaryOf(layoutObject->node(), offset); | 3576 : previousGraphemeBoundaryOf(layoutObject->node(), offset); |
3576 | 3577 |
3577 int caretMinOffset = box->caretMinOffset(); | 3578 int caretMinOffset = box->caretMinOffset(); |
3578 int caretMaxOffset = box->caretMaxOffset(); | 3579 int caretMaxOffset = box->caretMaxOffset(); |
3579 | 3580 |
3580 if (offset > caretMinOffset && offset < caretMaxOffset) | 3581 if (offset > caretMinOffset && offset < caretMaxOffset) |
3581 break; | 3582 break; |
3582 | 3583 |
3583 if (box->isLeftToRightDirection() ? offset > caretMaxOffset | 3584 if (box->isLeftToRightDirection() ? offset > caretMaxOffset |
3584 : offset < caretMinOffset) { | 3585 : offset < caretMinOffset) { |
3585 // Overshot to the right. | 3586 // Overshot to the right. |
3586 InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); | 3587 InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); |
3587 if (!nextBox) { | 3588 if (!nextBox) { |
3588 PositionTemplate<Strategy> positionOnRight = | 3589 PositionTemplate<Strategy> positionOnRight = |
3589 primaryDirection == TextDirection::Ltr | 3590 primaryDirection == TextDirection::kLtr |
3590 ? nextVisuallyDistinctCandidate(deepPosition) | 3591 ? nextVisuallyDistinctCandidate(deepPosition) |
3591 : previousVisuallyDistinctCandidate(deepPosition); | 3592 : previousVisuallyDistinctCandidate(deepPosition); |
3592 if (positionOnRight.isNull()) | 3593 if (positionOnRight.isNull()) |
3593 return PositionTemplate<Strategy>(); | 3594 return PositionTemplate<Strategy>(); |
3594 | 3595 |
3595 InlineBox* boxOnRight = | 3596 InlineBox* boxOnRight = |
3596 computeInlineBoxPosition(positionOnRight, affinity, | 3597 computeInlineBoxPosition(positionOnRight, affinity, |
3597 primaryDirection) | 3598 primaryDirection) |
3598 .inlineBox; | 3599 .inlineBox; |
3599 if (boxOnRight && boxOnRight->root() == box->root()) | 3600 if (boxOnRight && boxOnRight->root() == box->root()) |
(...skipping 11 matching lines...) Expand all Loading... |
3611 } | 3612 } |
3612 | 3613 |
3613 DCHECK_EQ(offset, box->caretRightmostOffset()); | 3614 DCHECK_EQ(offset, box->caretRightmostOffset()); |
3614 | 3615 |
3615 unsigned char level = box->bidiLevel(); | 3616 unsigned char level = box->bidiLevel(); |
3616 InlineBox* nextBox = box->nextLeafChild(); | 3617 InlineBox* nextBox = box->nextLeafChild(); |
3617 | 3618 |
3618 if (box->direction() == primaryDirection) { | 3619 if (box->direction() == primaryDirection) { |
3619 if (!nextBox) { | 3620 if (!nextBox) { |
3620 InlineBox* logicalEnd = 0; | 3621 InlineBox* logicalEnd = 0; |
3621 if (primaryDirection == TextDirection::Ltr | 3622 if (primaryDirection == TextDirection::kLtr |
3622 ? box->root().getLogicalEndBoxWithNode(logicalEnd) | 3623 ? box->root().getLogicalEndBoxWithNode(logicalEnd) |
3623 : box->root().getLogicalStartBoxWithNode(logicalEnd)) { | 3624 : box->root().getLogicalStartBoxWithNode(logicalEnd)) { |
3624 box = logicalEnd; | 3625 box = logicalEnd; |
3625 layoutObject = | 3626 layoutObject = |
3626 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); | 3627 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); |
3627 offset = primaryDirection == TextDirection::Ltr | 3628 offset = primaryDirection == TextDirection::kLtr |
3628 ? box->caretMaxOffset() | 3629 ? box->caretMaxOffset() |
3629 : box->caretMinOffset(); | 3630 : box->caretMinOffset(); |
3630 } | 3631 } |
3631 break; | 3632 break; |
3632 } | 3633 } |
3633 | 3634 |
3634 if (nextBox->bidiLevel() >= level) | 3635 if (nextBox->bidiLevel() >= level) |
3635 break; | 3636 break; |
3636 | 3637 |
3637 level = nextBox->bidiLevel(); | 3638 level = nextBox->bidiLevel(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3688 if (nextBox->bidiLevel() < level) | 3689 if (nextBox->bidiLevel() < level) |
3689 break; | 3690 break; |
3690 box = nextBox; | 3691 box = nextBox; |
3691 } | 3692 } |
3692 if (box->bidiLevel() == level) | 3693 if (box->bidiLevel() == level) |
3693 break; | 3694 break; |
3694 level = box->bidiLevel(); | 3695 level = box->bidiLevel(); |
3695 } | 3696 } |
3696 layoutObject = | 3697 layoutObject = |
3697 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); | 3698 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); |
3698 offset = primaryDirection == TextDirection::Ltr ? box->caretMaxOffset() | 3699 offset = primaryDirection == TextDirection::kLtr |
3699 : box->caretMinOffset(); | 3700 ? box->caretMaxOffset() |
| 3701 : box->caretMinOffset(); |
3700 } | 3702 } |
3701 break; | 3703 break; |
3702 } | 3704 } |
3703 | 3705 |
3704 p = PositionTemplate<Strategy>::editingPositionOf(layoutObject->node(), | 3706 p = PositionTemplate<Strategy>::editingPositionOf(layoutObject->node(), |
3705 offset); | 3707 offset); |
3706 | 3708 |
3707 if ((isVisuallyEquivalentCandidate(p) && | 3709 if ((isVisuallyEquivalentCandidate(p) && |
3708 mostForwardCaretPosition(p) != downstreamStart) || | 3710 mostForwardCaretPosition(p) != downstreamStart) || |
3709 p.atStartOfTree() || p.atEndOfTree()) | 3711 p.atStartOfTree() || p.atEndOfTree()) |
3710 return p; | 3712 return p; |
3711 | 3713 |
3712 DCHECK_NE(p, deepPosition); | 3714 DCHECK_NE(p, deepPosition); |
3713 } | 3715 } |
3714 } | 3716 } |
3715 | 3717 |
3716 template <typename Strategy> | 3718 template <typename Strategy> |
3717 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm( | 3719 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm( |
3718 const VisiblePositionTemplate<Strategy>& visiblePosition) { | 3720 const VisiblePositionTemplate<Strategy>& visiblePosition) { |
3719 DCHECK(visiblePosition.isValid()) << visiblePosition; | 3721 DCHECK(visiblePosition.isValid()) << visiblePosition; |
3720 const PositionTemplate<Strategy> pos = | 3722 const PositionTemplate<Strategy> pos = |
3721 rightVisuallyDistinctCandidate(visiblePosition); | 3723 rightVisuallyDistinctCandidate(visiblePosition); |
3722 // FIXME: Why can't we move left from the last position in a tree? | 3724 // FIXME: Why can't we move left from the last position in a tree? |
3723 if (pos.atStartOfTree() || pos.atEndOfTree()) | 3725 if (pos.atStartOfTree() || pos.atEndOfTree()) |
3724 return VisiblePositionTemplate<Strategy>(); | 3726 return VisiblePositionTemplate<Strategy>(); |
3725 | 3727 |
3726 const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos); | 3728 const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos); |
3727 DCHECK_NE(right.deepEquivalent(), visiblePosition.deepEquivalent()); | 3729 DCHECK_NE(right.deepEquivalent(), visiblePosition.deepEquivalent()); |
3728 | 3730 |
3729 return directionOfEnclosingBlock(right.deepEquivalent()) == TextDirection::Ltr | 3731 return directionOfEnclosingBlock(right.deepEquivalent()) == |
| 3732 TextDirection::kLtr |
3730 ? honorEditingBoundaryAtOrAfter(right, | 3733 ? honorEditingBoundaryAtOrAfter(right, |
3731 visiblePosition.deepEquivalent()) | 3734 visiblePosition.deepEquivalent()) |
3732 : honorEditingBoundaryAtOrBefore(right, | 3735 : honorEditingBoundaryAtOrBefore(right, |
3733 visiblePosition.deepEquivalent()); | 3736 visiblePosition.deepEquivalent()); |
3734 } | 3737 } |
3735 | 3738 |
3736 VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition) { | 3739 VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition) { |
3737 return rightPositionOfAlgorithm<EditingStrategy>(visiblePosition); | 3740 return rightPositionOfAlgorithm<EditingStrategy>(visiblePosition); |
3738 } | 3741 } |
3739 | 3742 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3848 | 3851 |
3849 VisiblePositionInFlatTree previousPositionOf( | 3852 VisiblePositionInFlatTree previousPositionOf( |
3850 const VisiblePositionInFlatTree& visiblePosition, | 3853 const VisiblePositionInFlatTree& visiblePosition, |
3851 EditingBoundaryCrossingRule rule) { | 3854 EditingBoundaryCrossingRule rule) { |
3852 DCHECK(visiblePosition.isValid()) << visiblePosition; | 3855 DCHECK(visiblePosition.isValid()) << visiblePosition; |
3853 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>( | 3856 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>( |
3854 visiblePosition.deepEquivalent(), rule); | 3857 visiblePosition.deepEquivalent(), rule); |
3855 } | 3858 } |
3856 | 3859 |
3857 } // namespace blink | 3860 } // namespace blink |
OLD | NEW |