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

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

Issue 1310953005: Move {left,right}PositionOf() for VisiblePosition to VisibleUnits.cpp (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 2015-09-01T21:47:52 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
« no previous file with comments | « Source/core/editing/VisiblePosition.h ('k') | Source/core/editing/VisibleUnits.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 * Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights reserved. 3 * Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 } 57 }
58 58
59 VisiblePosition VisiblePosition::createWithoutCanonicalization(const PositionWit hAffinity& canonicalized) 59 VisiblePosition VisiblePosition::createWithoutCanonicalization(const PositionWit hAffinity& canonicalized)
60 { 60 {
61 VisiblePosition visiblePosition; 61 VisiblePosition visiblePosition;
62 visiblePosition.m_deepPosition = canonicalized.position(); 62 visiblePosition.m_deepPosition = canonicalized.position();
63 visiblePosition.m_affinity = canonicalized.affinity(); 63 visiblePosition.m_affinity = canonicalized.affinity();
64 return visiblePosition; 64 return visiblePosition;
65 } 65 }
66 66
67 // TODO(yosin) We should move |rightVisuallyDistinctCandidate()| with
68 // |rightPositionOf()| to "VisibleUnits.cpp".
69 static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi tion)
70 {
71 const Position deepPosition = visiblePosition.deepEquivalent();
72 Position p = deepPosition;
73 if (p.isNull())
74 return Position();
75
76 Position downstreamStart = mostForwardCaretPosition(p);
77 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
78 const TextAffinity affinity = visiblePosition.affinity();
79
80 while (true) {
81 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, pr imaryDirection);
82 InlineBox* box = boxPosition.inlineBox;
83 int offset = boxPosition.offsetInBox;
84 if (!box)
85 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(d eepPosition) : nextVisuallyDistinctCandidate(deepPosition);
86
87 LayoutObject* layoutObject = &box->layoutObject();
88
89 while (true) {
90 if ((layoutObject->isReplaced() || layoutObject->isBR()) && offset = = box->caretRightmostOffset())
91 return box->isLeftToRightDirection() ? previousVisuallyDistinctC andidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition);
92
93 if (!layoutObject->node()) {
94 box = box->prevLeafChild();
95 if (!box)
96 return primaryDirection == LTR ? previousVisuallyDistinctCan didate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition);
97 layoutObject = &box->layoutObject();
98 offset = box->caretRightmostOffset();
99 continue;
100 }
101
102 offset = box->isLeftToRightDirection() ? layoutObject->previousOffse t(offset) : layoutObject->nextOffset(offset);
103
104 int caretMinOffset = box->caretMinOffset();
105 int caretMaxOffset = box->caretMaxOffset();
106
107 if (offset > caretMinOffset && offset < caretMaxOffset)
108 break;
109
110 if (box->isLeftToRightDirection() ? offset < caretMinOffset : offset > caretMaxOffset) {
111 // Overshot to the left.
112 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
113 if (!prevBox) {
114 Position positionOnLeft = primaryDirection == LTR ? previous VisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosi tion);
115 if (positionOnLeft.isNull())
116 return Position();
117
118 InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLe ft, affinity, primaryDirection).inlineBox;
119 if (boxOnLeft && boxOnLeft->root() == box->root())
120 return Position();
121 return positionOnLeft;
122 }
123
124 // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
125 box = prevBox;
126 layoutObject = &box->layoutObject();
127 offset = prevBox->caretRightmostOffset();
128 continue;
129 }
130
131 ASSERT(offset == box->caretLeftmostOffset());
132
133 unsigned char level = box->bidiLevel();
134 InlineBox* prevBox = box->prevLeafChild();
135
136 if (box->direction() == primaryDirection) {
137 if (!prevBox) {
138 InlineBox* logicalStart = 0;
139 if (primaryDirection == LTR ? box->root().getLogicalStartBox WithNode(logicalStart) : box->root().getLogicalEndBoxWithNode(logicalStart)) {
140 box = logicalStart;
141 layoutObject = &box->layoutObject();
142 offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset();
143 }
144 break;
145 }
146 if (prevBox->bidiLevel() >= level)
147 break;
148
149 level = prevBox->bidiLevel();
150
151 InlineBox* nextBox = box;
152 do {
153 nextBox = nextBox->nextLeafChild();
154 } while (nextBox && nextBox->bidiLevel() > level);
155
156 if (nextBox && nextBox->bidiLevel() == level)
157 break;
158
159 box = prevBox;
160 layoutObject = &box->layoutObject();
161 offset = box->caretRightmostOffset();
162 if (box->direction() == primaryDirection)
163 break;
164 continue;
165 }
166
167 while (prevBox && !prevBox->layoutObject().node())
168 prevBox = prevBox->prevLeafChild();
169
170 if (prevBox) {
171 box = prevBox;
172 layoutObject = &box->layoutObject();
173 offset = box->caretRightmostOffset();
174 if (box->bidiLevel() > level) {
175 do {
176 prevBox = prevBox->prevLeafChild();
177 } while (prevBox && prevBox->bidiLevel() > level);
178
179 if (!prevBox || prevBox->bidiLevel() < level)
180 continue;
181 }
182 } else {
183 // Trailing edge of a secondary run. Set to the leading edge of the entire run.
184 while (true) {
185 while (InlineBox* nextBox = box->nextLeafChild()) {
186 if (nextBox->bidiLevel() < level)
187 break;
188 box = nextBox;
189 }
190 if (box->bidiLevel() == level)
191 break;
192 level = box->bidiLevel();
193 while (InlineBox* prevBox = box->prevLeafChild()) {
194 if (prevBox->bidiLevel() < level)
195 break;
196 box = prevBox;
197 }
198 if (box->bidiLevel() == level)
199 break;
200 level = box->bidiLevel();
201 }
202 layoutObject = &box->layoutObject();
203 offset = primaryDirection == LTR ? box->caretMinOffset() : box-> caretMaxOffset();
204 }
205 break;
206 }
207
208 p = Position::editingPositionOf(layoutObject->node(), offset);
209
210 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
211 return p;
212
213 ASSERT(p != deepPosition);
214 }
215 }
216
217 // TODO(yosin) We should move |leftPositionOf()| to "VisibleUnits.cpp".
218 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition)
219 {
220 const Position pos = leftVisuallyDistinctCandidate(visiblePosition);
221 // TODO(yosin) Why can't we move left from the last position in a tree?
222 if (pos.atStartOfTree() || pos.atEndOfTree())
223 return VisiblePosition();
224
225 VisiblePosition left = VisiblePosition(pos);
226 ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent());
227
228 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda ryAtOrAfter(left, visiblePosition.deepEquivalent());
229 }
230
231 // TODO(yosin) We should move |rightVisuallyDistinctCandidate()| with
232 // |rightPositionOf()| to "VisibleUnits.cpp".
233 static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos ition)
234 {
235 const Position deepPosition = visiblePosition.deepEquivalent();
236 Position p = deepPosition;
237 if (p.isNull())
238 return Position();
239
240 Position downstreamStart = mostForwardCaretPosition(p);
241 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
242 const TextAffinity affinity = visiblePosition.affinity();
243
244 while (true) {
245 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, pr imaryDirection);
246 InlineBox* box = boxPosition.inlineBox;
247 int offset = boxPosition.offsetInBox;
248 if (!box)
249 return primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepP osition) : previousVisuallyDistinctCandidate(deepPosition);
250
251 LayoutObject* layoutObject = &box->layoutObject();
252
253 while (true) {
254 if ((layoutObject->isReplaced() || layoutObject->isBR()) && offset = = box->caretLeftmostOffset())
255 return box->isLeftToRightDirection() ? nextVisuallyDistinctCandi date(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
256
257 if (!layoutObject->node()) {
258 box = box->nextLeafChild();
259 if (!box)
260 return primaryDirection == LTR ? nextVisuallyDistinctCandida te(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
261 layoutObject = &box->layoutObject();
262 offset = box->caretLeftmostOffset();
263 continue;
264 }
265
266 offset = box->isLeftToRightDirection() ? layoutObject->nextOffset(of fset) : layoutObject->previousOffset(offset);
267
268 int caretMinOffset = box->caretMinOffset();
269 int caretMaxOffset = box->caretMaxOffset();
270
271 if (offset > caretMinOffset && offset < caretMaxOffset)
272 break;
273
274 if (box->isLeftToRightDirection() ? offset > caretMaxOffset : offset < caretMinOffset) {
275 // Overshot to the right.
276 InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();
277 if (!nextBox) {
278 Position positionOnRight = primaryDirection == LTR ? nextVis uallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPos ition);
279 if (positionOnRight.isNull())
280 return Position();
281
282 InlineBox* boxOnRight = computeInlineBoxPosition(positionOnR ight, affinity, primaryDirection).inlineBox;
283 if (boxOnRight && boxOnRight->root() == box->root())
284 return Position();
285 return positionOnRight;
286 }
287
288 // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
289 box = nextBox;
290 layoutObject = &box->layoutObject();
291 offset = nextBox->caretLeftmostOffset();
292 continue;
293 }
294
295 ASSERT(offset == box->caretRightmostOffset());
296
297 unsigned char level = box->bidiLevel();
298 InlineBox* nextBox = box->nextLeafChild();
299
300 if (box->direction() == primaryDirection) {
301 if (!nextBox) {
302 InlineBox* logicalEnd = 0;
303 if (primaryDirection == LTR ? box->root().getLogicalEndBoxWi thNode(logicalEnd) : box->root().getLogicalStartBoxWithNode(logicalEnd)) {
304 box = logicalEnd;
305 layoutObject = &box->layoutObject();
306 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset();
307 }
308 break;
309 }
310
311 if (nextBox->bidiLevel() >= level)
312 break;
313
314 level = nextBox->bidiLevel();
315
316 InlineBox* prevBox = box;
317 do {
318 prevBox = prevBox->prevLeafChild();
319 } while (prevBox && prevBox->bidiLevel() > level);
320
321 if (prevBox && prevBox->bidiLevel() == level) // For example, ab c FED 123 ^ CBA
322 break;
323
324 // For example, abc 123 ^ CBA or 123 ^ CBA abc
325 box = nextBox;
326 layoutObject = &box->layoutObject();
327 offset = box->caretLeftmostOffset();
328 if (box->direction() == primaryDirection)
329 break;
330 continue;
331 }
332
333 while (nextBox && !nextBox->layoutObject().node())
334 nextBox = nextBox->nextLeafChild();
335
336 if (nextBox) {
337 box = nextBox;
338 layoutObject = &box->layoutObject();
339 offset = box->caretLeftmostOffset();
340
341 if (box->bidiLevel() > level) {
342 do {
343 nextBox = nextBox->nextLeafChild();
344 } while (nextBox && nextBox->bidiLevel() > level);
345
346 if (!nextBox || nextBox->bidiLevel() < level)
347 continue;
348 }
349 } else {
350 // Trailing edge of a secondary run. Set to the leading edge of the entire run.
351 while (true) {
352 while (InlineBox* prevBox = box->prevLeafChild()) {
353 if (prevBox->bidiLevel() < level)
354 break;
355 box = prevBox;
356 }
357 if (box->bidiLevel() == level)
358 break;
359 level = box->bidiLevel();
360 while (InlineBox* nextBox = box->nextLeafChild()) {
361 if (nextBox->bidiLevel() < level)
362 break;
363 box = nextBox;
364 }
365 if (box->bidiLevel() == level)
366 break;
367 level = box->bidiLevel();
368 }
369 layoutObject = &box->layoutObject();
370 offset = primaryDirection == LTR ? box->caretMaxOffset() : box-> caretMinOffset();
371 }
372 break;
373 }
374
375 p = Position::editingPositionOf(layoutObject->node(), offset);
376
377 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
378 return p;
379
380 ASSERT(p != deepPosition);
381 }
382 }
383
384 // TODO(yosin) We should move |rightPositionOf()| to "VisibleUnits.cpp".
385 VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition)
386 {
387 const Position pos = rightVisuallyDistinctCandidate(visiblePosition);
388 // TODO(yosin) Why can't we move left from the last position in a tree?
389 if (pos.atStartOfTree() || pos.atEndOfTree())
390 return VisiblePosition();
391
392 VisiblePosition right = VisiblePosition(pos);
393 ASSERT(right.deepEquivalent() != visiblePosition.deepEquivalent());
394
395 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditi ngBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBound aryAtOrBefore(right, visiblePosition.deepEquivalent());
396 }
397
398 template <typename Strategy> 67 template <typename Strategy>
399 PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBeforeAlgorithm(c onst PositionWithAffinityTemplate<Strategy>& pos, const PositionAlgorithm<Strate gy>& anchor) 68 PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBeforeAlgorithm(c onst PositionWithAffinityTemplate<Strategy>& pos, const PositionAlgorithm<Strate gy>& anchor)
400 { 69 {
401 if (pos.isNull()) 70 if (pos.isNull())
402 return pos; 71 return pos;
403 72
404 ContainerNode* highestRoot = highestEditableRoot(anchor); 73 ContainerNode* highestRoot = highestEditableRoot(anchor);
405 74
406 // Return empty position if pos is not somewhere inside the editable region containing this position 75 // Return empty position if pos is not somewhere inside the editable region containing this position
407 if (highestRoot && !pos.position().anchorNode()->isDescendantOf(highestRoot) ) 76 if (highestRoot && !pos.position().anchorNode()->isDescendantOf(highestRoot) )
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 else 203 else
535 fprintf(stderr, "Cannot showTree for (nil) VisiblePosition.\n"); 204 fprintf(stderr, "Cannot showTree for (nil) VisiblePosition.\n");
536 } 205 }
537 206
538 void showTree(const blink::VisiblePosition& vpos) 207 void showTree(const blink::VisiblePosition& vpos)
539 { 208 {
540 vpos.showTreeForThis(); 209 vpos.showTreeForThis();
541 } 210 }
542 211
543 #endif 212 #endif
OLDNEW
« no previous file with comments | « Source/core/editing/VisiblePosition.h ('k') | Source/core/editing/VisibleUnits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698