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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 { | 155 { |
156 return canonicalPosition(position); | 156 return canonicalPosition(position); |
157 } | 157 } |
158 | 158 |
159 PositionInComposedTree canonicalPositionOf(const PositionInComposedTree& positio
n) | 159 PositionInComposedTree canonicalPositionOf(const PositionInComposedTree& positio
n) |
160 { | 160 { |
161 return canonicalPosition(position); | 161 return canonicalPosition(position); |
162 } | 162 } |
163 | 163 |
164 template <typename Strategy> | 164 template <typename Strategy> |
165 static PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBeforeAlgo
rithm(const PositionWithAffinityTemplate<Strategy>& pos, const PositionAlgorithm
<Strategy>& anchor) | 165 static PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBefore(con
st PositionWithAffinityTemplate<Strategy>& pos, const PositionAlgorithm<Strategy
>& anchor) |
166 { | 166 { |
167 if (pos.isNull()) | 167 if (pos.isNull()) |
168 return pos; | 168 return pos; |
169 | 169 |
170 ContainerNode* highestRoot = highestEditableRoot(anchor); | 170 ContainerNode* highestRoot = highestEditableRoot(anchor); |
171 | 171 |
172 // Return empty position if |pos| is not somewhere inside the editable | 172 // Return empty position if |pos| is not somewhere inside the editable |
173 // region containing this position | 173 // region containing this position |
174 if (highestRoot && !pos.position().anchorNode()->isDescendantOf(highestRoot)
) | 174 if (highestRoot && !pos.position().anchorNode()->isDescendantOf(highestRoot)
) |
175 return PositionWithAffinityTemplate<Strategy>(); | 175 return PositionWithAffinityTemplate<Strategy>(); |
(...skipping 10 matching lines...) Expand all Loading... |
186 // editable. | 186 // editable. |
187 // TODO(yosin) Move to the previous non-editable region. | 187 // TODO(yosin) Move to the previous non-editable region. |
188 if (!highestRoot) | 188 if (!highestRoot) |
189 return PositionWithAffinityTemplate<Strategy>(); | 189 return PositionWithAffinityTemplate<Strategy>(); |
190 | 190 |
191 // Return the last position before |pos| that is in the same editable region | 191 // Return the last position before |pos| that is in the same editable region |
192 // as this position | 192 // as this position |
193 return lastEditablePositionBeforePositionInRoot(pos.position(), highestRoot)
; | 193 return lastEditablePositionBeforePositionInRoot(pos.position(), highestRoot)
; |
194 } | 194 } |
195 | 195 |
196 static PositionWithAffinity honorEditingBoundaryAtOrBeforeOf(const PositionWithA
ffinity& pos, const Position& anchor) | 196 template <typename Strategy> |
| 197 static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrBefore(const Vi
siblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor) |
197 { | 198 { |
198 return honorEditingBoundaryAtOrBeforeAlgorithm(pos, anchor); | 199 return createVisiblePosition(honorEditingBoundaryAtOrBefore(pos.toPositionWi
thAffinity(), anchor)); |
199 } | |
200 | |
201 static PositionInComposedTreeWithAffinity honorEditingBoundaryAtOrBeforeOf(const
PositionInComposedTreeWithAffinity& pos, const PositionInComposedTree& anchor) | |
202 { | |
203 return honorEditingBoundaryAtOrBeforeAlgorithm(pos, anchor); | |
204 } | |
205 | |
206 static VisiblePosition honorEditingBoundaryAtOrBefore(const VisiblePosition& pos
, const Position& anchor) | |
207 { | |
208 return createVisiblePosition(honorEditingBoundaryAtOrBeforeOf(pos.toPosition
WithAffinity(), anchor)); | |
209 } | 200 } |
210 | 201 |
211 template <typename Strategy> | 202 template <typename Strategy> |
212 static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrAfter(const Vis
iblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor) | 203 static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrAfter(const Vis
iblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor) |
213 { | 204 { |
214 if (pos.isNull()) | 205 if (pos.isNull()) |
215 return pos; | 206 return pos; |
216 | 207 |
217 ContainerNode* highestRoot = highestEditableRoot(anchor); | 208 ContainerNode* highestRoot = highestEditableRoot(anchor); |
218 | 209 |
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. | 945 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. |
955 PositionWithAffinityTemplate<Strategy> visPos = startPositionForLine(c, mode
); | 946 PositionWithAffinityTemplate<Strategy> visPos = startPositionForLine(c, mode
); |
956 | 947 |
957 if (mode == UseLogicalOrdering) { | 948 if (mode == UseLogicalOrdering) { |
958 if (ContainerNode* editableRoot = highestEditableRoot(c.position())) { | 949 if (ContainerNode* editableRoot = highestEditableRoot(c.position())) { |
959 if (!editableRoot->contains(visPos.position().computeContainerNode()
)) | 950 if (!editableRoot->contains(visPos.position().computeContainerNode()
)) |
960 return PositionWithAffinityTemplate<Strategy>(PositionAlgorithm<
Strategy>::firstPositionInNode(editableRoot)); | 951 return PositionWithAffinityTemplate<Strategy>(PositionAlgorithm<
Strategy>::firstPositionInNode(editableRoot)); |
961 } | 952 } |
962 } | 953 } |
963 | 954 |
964 return honorEditingBoundaryAtOrBeforeOf(visPos, c.position()); | 955 return honorEditingBoundaryAtOrBefore(visPos, c.position()); |
965 } | 956 } |
966 | 957 |
967 static PositionWithAffinity startOfLine(const PositionWithAffinity& currentPosit
ion) | 958 static PositionWithAffinity startOfLine(const PositionWithAffinity& currentPosit
ion) |
968 { | 959 { |
969 return startOfLine(currentPosition, UseInlineBoxOrdering); | 960 return startOfLine(currentPosition, UseInlineBoxOrdering); |
970 } | 961 } |
971 | 962 |
972 static PositionInComposedTreeWithAffinity startOfLine(const PositionInComposedTr
eeWithAffinity& currentPosition) | 963 static PositionInComposedTreeWithAffinity startOfLine(const PositionInComposedTr
eeWithAffinity& currentPosition) |
973 { | 964 { |
974 return startOfLine(currentPosition, UseInlineBoxOrdering); | 965 return startOfLine(currentPosition, UseInlineBoxOrdering); |
(...skipping 1615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2590 UChar32 characterAfter(const VisiblePositionInComposedTree& visiblePosition) | 2581 UChar32 characterAfter(const VisiblePositionInComposedTree& visiblePosition) |
2591 { | 2582 { |
2592 return characterAfterAlgorithm<EditingInComposedTreeStrategy>(visiblePositio
n); | 2583 return characterAfterAlgorithm<EditingInComposedTreeStrategy>(visiblePositio
n); |
2593 } | 2584 } |
2594 | 2585 |
2595 UChar32 characterBefore(const VisiblePosition& visiblePosition) | 2586 UChar32 characterBefore(const VisiblePosition& visiblePosition) |
2596 { | 2587 { |
2597 return characterAfter(previousPositionOf(visiblePosition)); | 2588 return characterAfter(previousPositionOf(visiblePosition)); |
2598 } | 2589 } |
2599 | 2590 |
2600 static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi
tion) | 2591 template <typename Strategy> |
| 2592 static PositionAlgorithm<Strategy> leftVisuallyDistinctCandidate(const VisiblePo
sitionTemplate<Strategy>& visiblePosition) |
2601 { | 2593 { |
2602 const Position deepPosition = visiblePosition.deepEquivalent(); | 2594 const PositionAlgorithm<Strategy> deepPosition = visiblePosition.deepEquival
ent(); |
2603 Position p = deepPosition; | 2595 PositionAlgorithm<Strategy> p = deepPosition; |
| 2596 |
2604 if (p.isNull()) | 2597 if (p.isNull()) |
2605 return Position(); | 2598 return PositionAlgorithm<Strategy>(); |
2606 | 2599 |
2607 Position downstreamStart = mostForwardCaretPosition(p); | 2600 const PositionAlgorithm<Strategy> downstreamStart = mostForwardCaretPosition
(p); |
2608 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); | 2601 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
2609 const TextAffinity affinity = visiblePosition.affinity(); | 2602 const TextAffinity affinity = visiblePosition.affinity(); |
2610 | 2603 |
2611 while (true) { | 2604 while (true) { |
2612 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, pr
imaryDirection); | 2605 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, pr
imaryDirection); |
2613 InlineBox* box = boxPosition.inlineBox; | 2606 InlineBox* box = boxPosition.inlineBox; |
2614 int offset = boxPosition.offsetInBox; | 2607 int offset = boxPosition.offsetInBox; |
2615 if (!box) | 2608 if (!box) |
2616 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(d
eepPosition) : nextVisuallyDistinctCandidate(deepPosition); | 2609 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(d
eepPosition) : nextVisuallyDistinctCandidate(deepPosition); |
2617 | 2610 |
(...skipping 17 matching lines...) Expand all Loading... |
2635 int caretMinOffset = box->caretMinOffset(); | 2628 int caretMinOffset = box->caretMinOffset(); |
2636 int caretMaxOffset = box->caretMaxOffset(); | 2629 int caretMaxOffset = box->caretMaxOffset(); |
2637 | 2630 |
2638 if (offset > caretMinOffset && offset < caretMaxOffset) | 2631 if (offset > caretMinOffset && offset < caretMaxOffset) |
2639 break; | 2632 break; |
2640 | 2633 |
2641 if (box->isLeftToRightDirection() ? offset < caretMinOffset : offset
> caretMaxOffset) { | 2634 if (box->isLeftToRightDirection() ? offset < caretMinOffset : offset
> caretMaxOffset) { |
2642 // Overshot to the left. | 2635 // Overshot to the left. |
2643 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); | 2636 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); |
2644 if (!prevBox) { | 2637 if (!prevBox) { |
2645 Position positionOnLeft = primaryDirection == LTR ? previous
VisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosi
tion); | 2638 PositionAlgorithm<Strategy> positionOnLeft = primaryDirectio
n == LTR ? previousVisuallyDistinctCandidate(visiblePosition.deepEquivalent()) :
nextVisuallyDistinctCandidate(visiblePosition.deepEquivalent()); |
2646 if (positionOnLeft.isNull()) | 2639 if (positionOnLeft.isNull()) |
2647 return Position(); | 2640 return PositionAlgorithm<Strategy>(); |
2648 | 2641 |
2649 InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLe
ft, affinity, primaryDirection).inlineBox; | 2642 InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLe
ft, affinity, primaryDirection).inlineBox; |
2650 if (boxOnLeft && boxOnLeft->root() == box->root()) | 2643 if (boxOnLeft && boxOnLeft->root() == box->root()) |
2651 return Position(); | 2644 return PositionAlgorithm<Strategy>(); |
2652 return positionOnLeft; | 2645 return positionOnLeft; |
2653 } | 2646 } |
2654 | 2647 |
2655 // Reposition at the other logical position corresponding to our | 2648 // Reposition at the other logical position corresponding to our |
2656 // edge's visual position and go for another round. | 2649 // edge's visual position and go for another round. |
2657 box = prevBox; | 2650 box = prevBox; |
2658 layoutObject = &box->layoutObject(); | 2651 layoutObject = &box->layoutObject(); |
2659 offset = prevBox->caretRightmostOffset(); | 2652 offset = prevBox->caretRightmostOffset(); |
2660 continue; | 2653 continue; |
2661 } | 2654 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2705 offset = box->caretRightmostOffset(); | 2698 offset = box->caretRightmostOffset(); |
2706 if (box->bidiLevel() > level) { | 2699 if (box->bidiLevel() > level) { |
2707 do { | 2700 do { |
2708 prevBox = prevBox->prevLeafChild(); | 2701 prevBox = prevBox->prevLeafChild(); |
2709 } while (prevBox && prevBox->bidiLevel() > level); | 2702 } while (prevBox && prevBox->bidiLevel() > level); |
2710 | 2703 |
2711 if (!prevBox || prevBox->bidiLevel() < level) | 2704 if (!prevBox || prevBox->bidiLevel() < level) |
2712 continue; | 2705 continue; |
2713 } | 2706 } |
2714 } else { | 2707 } else { |
2715 // Trailing edge of a secondary run. Set to the leading edge of
the entire run. | 2708 // Trailing edge of a secondary run. Set to the leading edge of |
| 2709 // the entire run. |
2716 while (true) { | 2710 while (true) { |
2717 while (InlineBox* nextBox = box->nextLeafChild()) { | 2711 while (InlineBox* nextBox = box->nextLeafChild()) { |
2718 if (nextBox->bidiLevel() < level) | 2712 if (nextBox->bidiLevel() < level) |
2719 break; | 2713 break; |
2720 box = nextBox; | 2714 box = nextBox; |
2721 } | 2715 } |
2722 if (box->bidiLevel() == level) | 2716 if (box->bidiLevel() == level) |
2723 break; | 2717 break; |
2724 level = box->bidiLevel(); | 2718 level = box->bidiLevel(); |
2725 while (InlineBox* prevBox = box->prevLeafChild()) { | 2719 while (InlineBox* prevBox = box->prevLeafChild()) { |
2726 if (prevBox->bidiLevel() < level) | 2720 if (prevBox->bidiLevel() < level) |
2727 break; | 2721 break; |
2728 box = prevBox; | 2722 box = prevBox; |
2729 } | 2723 } |
2730 if (box->bidiLevel() == level) | 2724 if (box->bidiLevel() == level) |
2731 break; | 2725 break; |
2732 level = box->bidiLevel(); | 2726 level = box->bidiLevel(); |
2733 } | 2727 } |
2734 layoutObject = &box->layoutObject(); | 2728 layoutObject = &box->layoutObject(); |
2735 offset = primaryDirection == LTR ? box->caretMinOffset() : box->
caretMaxOffset(); | 2729 offset = primaryDirection == LTR ? box->caretMinOffset() : box->
caretMaxOffset(); |
2736 } | 2730 } |
2737 break; | 2731 break; |
2738 } | 2732 } |
2739 | 2733 |
2740 p = Position::editingPositionOf(layoutObject->node(), offset); | 2734 p = PositionAlgorithm<Strategy>::editingPositionOf(layoutObject->node(),
offset); |
2741 | 2735 |
2742 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) | 2736 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) |
2743 return p; | 2737 return p; |
2744 | 2738 |
2745 ASSERT(p != deepPosition); | 2739 ASSERT(p != deepPosition); |
2746 } | 2740 } |
2747 } | 2741 } |
2748 | 2742 |
2749 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) | 2743 template <typename Strategy> |
| 2744 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm(const VisiblePositionT
emplate<Strategy>& visiblePosition) |
2750 { | 2745 { |
2751 const Position pos = leftVisuallyDistinctCandidate(visiblePosition); | 2746 const PositionAlgorithm<Strategy> pos = leftVisuallyDistinctCandidate(visibl
ePosition); |
2752 // TODO(yosin) Why can't we move left from the last position in a tree? | 2747 // TODO(yosin) Why can't we move left from the last position in a tree? |
2753 if (pos.atStartOfTree() || pos.atEndOfTree()) | 2748 if (pos.atStartOfTree() || pos.atEndOfTree()) |
2754 return VisiblePosition(); | 2749 return VisiblePositionTemplate<Strategy>(); |
2755 | 2750 |
2756 VisiblePosition left = createVisiblePosition(pos); | 2751 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos); |
2757 ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent()); | 2752 ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent()); |
2758 | 2753 |
2759 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin
gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda
ryAtOrAfter(left, visiblePosition.deepEquivalent()); | 2754 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin
gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda
ryAtOrAfter(left, visiblePosition.deepEquivalent()); |
2760 } | 2755 } |
2761 | 2756 |
| 2757 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) |
| 2758 { |
| 2759 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition); |
| 2760 } |
| 2761 |
| 2762 VisiblePositionInComposedTree leftPositionOf(const VisiblePositionInComposedTree
& visiblePosition) |
| 2763 { |
| 2764 return leftPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePositio
n); |
| 2765 } |
| 2766 |
2762 static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos
ition) | 2767 static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos
ition) |
2763 { | 2768 { |
2764 const Position deepPosition = visiblePosition.deepEquivalent(); | 2769 const Position deepPosition = visiblePosition.deepEquivalent(); |
2765 Position p = deepPosition; | 2770 Position p = deepPosition; |
2766 if (p.isNull()) | 2771 if (p.isNull()) |
2767 return Position(); | 2772 return Position(); |
2768 | 2773 |
2769 Position downstreamStart = mostForwardCaretPosition(p); | 2774 Position downstreamStart = mostForwardCaretPosition(p); |
2770 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); | 2775 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
2771 const TextAffinity affinity = visiblePosition.affinity(); | 2776 const TextAffinity affinity = visiblePosition.affinity(); |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3003 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale
nt()); | 3008 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale
nt()); |
3004 case CanSkipOverEditingBoundary: | 3009 case CanSkipOverEditingBoundary: |
3005 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent
()); | 3010 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent
()); |
3006 } | 3011 } |
3007 | 3012 |
3008 ASSERT_NOT_REACHED(); | 3013 ASSERT_NOT_REACHED(); |
3009 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent()
); | 3014 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent()
); |
3010 } | 3015 } |
3011 | 3016 |
3012 } // namespace blink | 3017 } // namespace blink |
OLD | NEW |