| 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 |