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 * 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 Loading... |
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 Loading... |
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 |
OLD | NEW |