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

Side by Side Diff: Source/core/editing/VisibleUnits.cpp

Issue 1326313002: Introduce composed tree version of leftPositionOf() (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 2015-09-08T16:21:19 Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 }
200 201
201 static PositionInComposedTreeWithAffinity honorEditingBoundaryAtOrBeforeOf(const PositionInComposedTreeWithAffinity& pos, const PositionInComposedTree& anchor) 202 template <typename Strategy>
202 { 203 static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrAfter(const Vis iblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor)
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 }
210
211 static VisiblePosition honorEditingBoundaryAtOrAfter(const VisiblePosition& pos, const Position& anchor)
212 { 204 {
213 if (pos.isNull()) 205 if (pos.isNull())
214 return pos; 206 return pos;
215 207
216 ContainerNode* highestRoot = highestEditableRoot(anchor); 208 ContainerNode* highestRoot = highestEditableRoot(anchor);
217 209
218 // Return empty position if |pos| is not somewhere inside the editable 210 // Return empty position if |pos| is not somewhere inside the editable
219 // region // containing this position 211 // region containing this position
220 if (highestRoot && !pos.deepEquivalent().anchorNode()->isDescendantOf(highes tRoot)) 212 if (highestRoot && !pos.deepEquivalent().anchorNode()->isDescendantOf(highes tRoot))
221 return VisiblePosition(); 213 return VisiblePositionTemplate<Strategy>();
222 214
223 // Return |pos| itself if the two are from the very same editable region, or 215 // Return |pos| itself if the two are from the very same editable region, or
224 // both are non-editable 216 // both are non-editable
225 // TODO(yosin) In the non-editable case, just because the new position is 217 // TODO(yosin) In the non-editable case, just because the new position is
226 // non-editable doesn't mean movement to it is allowed. 218 // non-editable doesn't mean movement to it is allowed.
227 // |VisibleSelection::adjustForEditableContent()| has this problem too. 219 // |VisibleSelection::adjustForEditableContent()| has this problem too.
228 if (highestEditableRoot(pos.deepEquivalent()) == highestRoot) 220 if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
229 return pos; 221 return pos;
230 222
231 // Return empty position if this position is non-editable, but |pos| is 223 // Return empty position if this position is non-editable, but |pos| is
232 // editable 224 // editable.
233 // TODO(yosin) Move to the next non-editable region. 225 // TODO(yosin) Move to the next non-editable region.
234 if (!highestRoot) 226 if (!highestRoot)
235 return VisiblePosition(); 227 return VisiblePositionTemplate<Strategy>();
236 228
237 // Return the next position after |pos| that is in the same editable region 229 // Return the next position after |pos| that is in the same editable region
238 // as this position 230 // as this position
239 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot); 231 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot);
240 } 232 }
241 233
242 static Node* previousLeafWithSameEditability(Node* node, EditableType editableTy pe) 234 static Node* previousLeafWithSameEditability(Node* node, EditableType editableTy pe)
243 { 235 {
244 bool editable = node->hasEditableStyle(editableType); 236 bool editable = node->hasEditableStyle(editableType);
245 node = previousAtomicLeafNode(*node); 237 node = previousAtomicLeafNode(*node);
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 // 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.
954 PositionWithAffinityTemplate<Strategy> visPos = startPositionForLine(c, mode ); 946 PositionWithAffinityTemplate<Strategy> visPos = startPositionForLine(c, mode );
955 947
956 if (mode == UseLogicalOrdering) { 948 if (mode == UseLogicalOrdering) {
957 if (ContainerNode* editableRoot = highestEditableRoot(c.position())) { 949 if (ContainerNode* editableRoot = highestEditableRoot(c.position())) {
958 if (!editableRoot->contains(visPos.position().computeContainerNode() )) 950 if (!editableRoot->contains(visPos.position().computeContainerNode() ))
959 return PositionWithAffinityTemplate<Strategy>(PositionAlgorithm< Strategy>::firstPositionInNode(editableRoot)); 951 return PositionWithAffinityTemplate<Strategy>(PositionAlgorithm< Strategy>::firstPositionInNode(editableRoot));
960 } 952 }
961 } 953 }
962 954
963 return honorEditingBoundaryAtOrBeforeOf(visPos, c.position()); 955 return honorEditingBoundaryAtOrBefore(visPos, c.position());
964 } 956 }
965 957
966 static PositionWithAffinity startOfLine(const PositionWithAffinity& currentPosit ion) 958 static PositionWithAffinity startOfLine(const PositionWithAffinity& currentPosit ion)
967 { 959 {
968 return startOfLine(currentPosition, UseInlineBoxOrdering); 960 return startOfLine(currentPosition, UseInlineBoxOrdering);
969 } 961 }
970 962
971 static PositionInComposedTreeWithAffinity startOfLine(const PositionInComposedTr eeWithAffinity& currentPosition) 963 static PositionInComposedTreeWithAffinity startOfLine(const PositionInComposedTr eeWithAffinity& currentPosition)
972 { 964 {
973 return startOfLine(currentPosition, UseInlineBoxOrdering); 965 return startOfLine(currentPosition, UseInlineBoxOrdering);
(...skipping 1603 matching lines...) Expand 10 before | Expand all | Expand 10 after
2577 UChar32 characterAfter(const VisiblePositionInComposedTree& visiblePosition) 2569 UChar32 characterAfter(const VisiblePositionInComposedTree& visiblePosition)
2578 { 2570 {
2579 return characterAfterAlgorithm<EditingInComposedTreeStrategy>(visiblePositio n); 2571 return characterAfterAlgorithm<EditingInComposedTreeStrategy>(visiblePositio n);
2580 } 2572 }
2581 2573
2582 UChar32 characterBefore(const VisiblePosition& visiblePosition) 2574 UChar32 characterBefore(const VisiblePosition& visiblePosition)
2583 { 2575 {
2584 return characterAfter(previousPositionOf(visiblePosition)); 2576 return characterAfter(previousPositionOf(visiblePosition));
2585 } 2577 }
2586 2578
2587 static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi tion) 2579 template <typename Strategy>
2580 static PositionAlgorithm<Strategy> leftVisuallyDistinctCandidate(const VisiblePo sitionTemplate<Strategy>& visiblePosition)
2588 { 2581 {
2589 const Position deepPosition = visiblePosition.deepEquivalent(); 2582 const PositionAlgorithm<Strategy> deepPosition = visiblePosition.deepEquival ent();
2590 Position p = deepPosition; 2583 PositionAlgorithm<Strategy> p = deepPosition;
2584
2591 if (p.isNull()) 2585 if (p.isNull())
2592 return Position(); 2586 return PositionAlgorithm<Strategy>();
2593 2587
2594 Position downstreamStart = mostForwardCaretPosition(p); 2588 const PositionAlgorithm<Strategy> downstreamStart = mostForwardCaretPosition (p);
2595 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); 2589 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
2596 const TextAffinity affinity = visiblePosition.affinity(); 2590 const TextAffinity affinity = visiblePosition.affinity();
2597 2591
2598 while (true) { 2592 while (true) {
2599 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, pr imaryDirection); 2593 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, pr imaryDirection);
2600 InlineBox* box = boxPosition.inlineBox; 2594 InlineBox* box = boxPosition.inlineBox;
2601 int offset = boxPosition.offsetInBox; 2595 int offset = boxPosition.offsetInBox;
2602 if (!box) 2596 if (!box)
2603 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(d eepPosition) : nextVisuallyDistinctCandidate(deepPosition); 2597 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(d eepPosition) : nextVisuallyDistinctCandidate(deepPosition);
2604 2598
(...skipping 17 matching lines...) Expand all
2622 int caretMinOffset = box->caretMinOffset(); 2616 int caretMinOffset = box->caretMinOffset();
2623 int caretMaxOffset = box->caretMaxOffset(); 2617 int caretMaxOffset = box->caretMaxOffset();
2624 2618
2625 if (offset > caretMinOffset && offset < caretMaxOffset) 2619 if (offset > caretMinOffset && offset < caretMaxOffset)
2626 break; 2620 break;
2627 2621
2628 if (box->isLeftToRightDirection() ? offset < caretMinOffset : offset > caretMaxOffset) { 2622 if (box->isLeftToRightDirection() ? offset < caretMinOffset : offset > caretMaxOffset) {
2629 // Overshot to the left. 2623 // Overshot to the left.
2630 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); 2624 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
2631 if (!prevBox) { 2625 if (!prevBox) {
2632 Position positionOnLeft = primaryDirection == LTR ? previous VisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosi tion); 2626 PositionAlgorithm<Strategy> positionOnLeft = primaryDirectio n == LTR ? previousVisuallyDistinctCandidate(visiblePosition.deepEquivalent()) : nextVisuallyDistinctCandidate(visiblePosition.deepEquivalent());
2633 if (positionOnLeft.isNull()) 2627 if (positionOnLeft.isNull())
2634 return Position(); 2628 return PositionAlgorithm<Strategy>();
2635 2629
2636 InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLe ft, affinity, primaryDirection).inlineBox; 2630 InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLe ft, affinity, primaryDirection).inlineBox;
2637 if (boxOnLeft && boxOnLeft->root() == box->root()) 2631 if (boxOnLeft && boxOnLeft->root() == box->root())
2638 return Position(); 2632 return PositionAlgorithm<Strategy>();
2639 return positionOnLeft; 2633 return positionOnLeft;
2640 } 2634 }
2641 2635
2642 // Reposition at the other logical position corresponding to our 2636 // Reposition at the other logical position corresponding to our
2643 // edge's visual position and go for another round. 2637 // edge's visual position and go for another round.
2644 box = prevBox; 2638 box = prevBox;
2645 layoutObject = &box->layoutObject(); 2639 layoutObject = &box->layoutObject();
2646 offset = prevBox->caretRightmostOffset(); 2640 offset = prevBox->caretRightmostOffset();
2647 continue; 2641 continue;
2648 } 2642 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2692 offset = box->caretRightmostOffset(); 2686 offset = box->caretRightmostOffset();
2693 if (box->bidiLevel() > level) { 2687 if (box->bidiLevel() > level) {
2694 do { 2688 do {
2695 prevBox = prevBox->prevLeafChild(); 2689 prevBox = prevBox->prevLeafChild();
2696 } while (prevBox && prevBox->bidiLevel() > level); 2690 } while (prevBox && prevBox->bidiLevel() > level);
2697 2691
2698 if (!prevBox || prevBox->bidiLevel() < level) 2692 if (!prevBox || prevBox->bidiLevel() < level)
2699 continue; 2693 continue;
2700 } 2694 }
2701 } else { 2695 } else {
2702 // Trailing edge of a secondary run. Set to the leading edge of the entire run. 2696 // Trailing edge of a secondary run. Set to the leading edge of
2697 // the entire run.
2703 while (true) { 2698 while (true) {
2704 while (InlineBox* nextBox = box->nextLeafChild()) { 2699 while (InlineBox* nextBox = box->nextLeafChild()) {
2705 if (nextBox->bidiLevel() < level) 2700 if (nextBox->bidiLevel() < level)
2706 break; 2701 break;
2707 box = nextBox; 2702 box = nextBox;
2708 } 2703 }
2709 if (box->bidiLevel() == level) 2704 if (box->bidiLevel() == level)
2710 break; 2705 break;
2711 level = box->bidiLevel(); 2706 level = box->bidiLevel();
2712 while (InlineBox* prevBox = box->prevLeafChild()) { 2707 while (InlineBox* prevBox = box->prevLeafChild()) {
2713 if (prevBox->bidiLevel() < level) 2708 if (prevBox->bidiLevel() < level)
2714 break; 2709 break;
2715 box = prevBox; 2710 box = prevBox;
2716 } 2711 }
2717 if (box->bidiLevel() == level) 2712 if (box->bidiLevel() == level)
2718 break; 2713 break;
2719 level = box->bidiLevel(); 2714 level = box->bidiLevel();
2720 } 2715 }
2721 layoutObject = &box->layoutObject(); 2716 layoutObject = &box->layoutObject();
2722 offset = primaryDirection == LTR ? box->caretMinOffset() : box-> caretMaxOffset(); 2717 offset = primaryDirection == LTR ? box->caretMinOffset() : box-> caretMaxOffset();
2723 } 2718 }
2724 break; 2719 break;
2725 } 2720 }
2726 2721
2727 p = Position::editingPositionOf(layoutObject->node(), offset); 2722 p = PositionAlgorithm<Strategy>::editingPositionOf(layoutObject->node(), offset);
2728 2723
2729 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) 2724 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
2730 return p; 2725 return p;
2731 2726
2732 ASSERT(p != deepPosition); 2727 ASSERT(p != deepPosition);
2733 } 2728 }
2734 } 2729 }
2735 2730
2736 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) 2731 template <typename Strategy>
2732 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm(const VisiblePositionT emplate<Strategy>& visiblePosition)
2737 { 2733 {
2738 const Position pos = leftVisuallyDistinctCandidate(visiblePosition); 2734 const PositionAlgorithm<Strategy> pos = leftVisuallyDistinctCandidate(visibl ePosition);
2739 // TODO(yosin) Why can't we move left from the last position in a tree? 2735 // TODO(yosin) Why can't we move left from the last position in a tree?
2740 if (pos.atStartOfTree() || pos.atEndOfTree()) 2736 if (pos.atStartOfTree() || pos.atEndOfTree())
2741 return VisiblePosition(); 2737 return VisiblePositionTemplate<Strategy>();
2742 2738
2743 VisiblePosition left = createVisiblePosition(pos); 2739 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos);
2744 ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent()); 2740 ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent());
2745 2741
2746 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda ryAtOrAfter(left, visiblePosition.deepEquivalent()); 2742 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda ryAtOrAfter(left, visiblePosition.deepEquivalent());
2747 } 2743 }
2748 2744
2745 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition)
2746 {
2747 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition);
2748 }
2749
2750 VisiblePositionInComposedTree leftPositionOf(const VisiblePositionInComposedTree & visiblePosition)
2751 {
2752 return leftPositionOfAlgorithm<EditingInComposedTreeStrategy>(visiblePositio n);
2753 }
2754
2749 static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos ition) 2755 static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos ition)
2750 { 2756 {
2751 const Position deepPosition = visiblePosition.deepEquivalent(); 2757 const Position deepPosition = visiblePosition.deepEquivalent();
2752 Position p = deepPosition; 2758 Position p = deepPosition;
2753 if (p.isNull()) 2759 if (p.isNull())
2754 return Position(); 2760 return Position();
2755 2761
2756 Position downstreamStart = mostForwardCaretPosition(p); 2762 Position downstreamStart = mostForwardCaretPosition(p);
2757 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); 2763 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
2758 const TextAffinity affinity = visiblePosition.affinity(); 2764 const TextAffinity affinity = visiblePosition.affinity();
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
2979 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale nt()); 2985 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale nt());
2980 case CanSkipOverEditingBoundary: 2986 case CanSkipOverEditingBoundary:
2981 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent ()); 2987 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent ());
2982 } 2988 }
2983 2989
2984 ASSERT_NOT_REACHED(); 2990 ASSERT_NOT_REACHED();
2985 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent() ); 2991 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent() );
2986 } 2992 }
2987 2993
2988 } // namespace blink 2994 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698