| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights |
| 3 * reserved. | 3 * 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 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 } | 699 } |
| 700 | 700 |
| 701 if (!iter) | 701 if (!iter) |
| 702 break; | 702 break; |
| 703 | 703 |
| 704 iter->first(); | 704 iter->first(); |
| 705 int offsetInIterator = offsetInBox - textBox->start() + previousBoxLength; | 705 int offsetInIterator = offsetInBox - textBox->start() + previousBoxLength; |
| 706 | 706 |
| 707 bool isWordBreak; | 707 bool isWordBreak; |
| 708 bool boxHasSameDirectionalityAsBlock = box->direction() == blockDirection; | 708 bool boxHasSameDirectionalityAsBlock = box->direction() == blockDirection; |
| 709 bool movingBackward = (direction == MoveLeft && box->direction() == LTR) || | 709 bool movingBackward = |
| 710 (direction == MoveRight && box->direction() == RTL); | 710 (direction == MoveLeft && box->direction() == TextDirection::Ltr) || |
| 711 (direction == MoveRight && box->direction() == TextDirection::Rtl); |
| 711 if ((skipsSpaceWhenMovingRight && boxHasSameDirectionalityAsBlock) || | 712 if ((skipsSpaceWhenMovingRight && boxHasSameDirectionalityAsBlock) || |
| 712 (!skipsSpaceWhenMovingRight && movingBackward)) { | 713 (!skipsSpaceWhenMovingRight && movingBackward)) { |
| 713 bool logicalStartInLayoutObject = | 714 bool logicalStartInLayoutObject = |
| 714 offsetInBox == static_cast<int>(textBox->start()) && | 715 offsetInBox == static_cast<int>(textBox->start()) && |
| 715 previousBoxInDifferentBlock; | 716 previousBoxInDifferentBlock; |
| 716 isWordBreak = isLogicalStartOfWord(iter, offsetInIterator, | 717 isWordBreak = isLogicalStartOfWord(iter, offsetInIterator, |
| 717 logicalStartInLayoutObject); | 718 logicalStartInLayoutObject); |
| 718 } else { | 719 } else { |
| 719 bool logicalEndInLayoutObject = | 720 bool logicalEndInLayoutObject = |
| 720 offsetInBox == static_cast<int>(textBox->start() + textBox->len()) && | 721 offsetInBox == static_cast<int>(textBox->start() + textBox->len()) && |
| (...skipping 16 matching lines...) Expand all Loading... |
| 737 VisiblePosition leftWordBreak = | 738 VisiblePosition leftWordBreak = |
| 738 visualWordPosition(visiblePosition, MoveLeft, skipsSpaceWhenMovingRight); | 739 visualWordPosition(visiblePosition, MoveLeft, skipsSpaceWhenMovingRight); |
| 739 leftWordBreak = honorEditingBoundaryAtOrBefore( | 740 leftWordBreak = honorEditingBoundaryAtOrBefore( |
| 740 leftWordBreak, visiblePosition.deepEquivalent()); | 741 leftWordBreak, visiblePosition.deepEquivalent()); |
| 741 | 742 |
| 742 // FIXME: How should we handle a non-editable position? | 743 // FIXME: How should we handle a non-editable position? |
| 743 if (leftWordBreak.isNull() && | 744 if (leftWordBreak.isNull() && |
| 744 isEditablePosition(visiblePosition.deepEquivalent())) { | 745 isEditablePosition(visiblePosition.deepEquivalent())) { |
| 745 TextDirection blockDirection = | 746 TextDirection blockDirection = |
| 746 directionOfEnclosingBlock(visiblePosition.deepEquivalent()); | 747 directionOfEnclosingBlock(visiblePosition.deepEquivalent()); |
| 747 leftWordBreak = blockDirection == LTR | 748 leftWordBreak = blockDirection == TextDirection::Ltr |
| 748 ? startOfEditableContent(visiblePosition) | 749 ? startOfEditableContent(visiblePosition) |
| 749 : endOfEditableContent(visiblePosition); | 750 : endOfEditableContent(visiblePosition); |
| 750 } | 751 } |
| 751 return leftWordBreak; | 752 return leftWordBreak; |
| 752 } | 753 } |
| 753 | 754 |
| 754 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, | 755 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, |
| 755 bool skipsSpaceWhenMovingRight) { | 756 bool skipsSpaceWhenMovingRight) { |
| 756 DCHECK(visiblePosition.isValid()) << visiblePosition; | 757 DCHECK(visiblePosition.isValid()) << visiblePosition; |
| 757 VisiblePosition rightWordBreak = | 758 VisiblePosition rightWordBreak = |
| 758 visualWordPosition(visiblePosition, MoveRight, skipsSpaceWhenMovingRight); | 759 visualWordPosition(visiblePosition, MoveRight, skipsSpaceWhenMovingRight); |
| 759 rightWordBreak = honorEditingBoundaryAtOrBefore( | 760 rightWordBreak = honorEditingBoundaryAtOrBefore( |
| 760 rightWordBreak, visiblePosition.deepEquivalent()); | 761 rightWordBreak, visiblePosition.deepEquivalent()); |
| 761 | 762 |
| 762 // FIXME: How should we handle a non-editable position? | 763 // FIXME: How should we handle a non-editable position? |
| 763 if (rightWordBreak.isNull() && | 764 if (rightWordBreak.isNull() && |
| 764 isEditablePosition(visiblePosition.deepEquivalent())) { | 765 isEditablePosition(visiblePosition.deepEquivalent())) { |
| 765 TextDirection blockDirection = | 766 TextDirection blockDirection = |
| 766 directionOfEnclosingBlock(visiblePosition.deepEquivalent()); | 767 directionOfEnclosingBlock(visiblePosition.deepEquivalent()); |
| 767 rightWordBreak = blockDirection == LTR | 768 rightWordBreak = blockDirection == TextDirection::Ltr |
| 768 ? endOfEditableContent(visiblePosition) | 769 ? endOfEditableContent(visiblePosition) |
| 769 : startOfEditableContent(visiblePosition); | 770 : startOfEditableContent(visiblePosition); |
| 770 } | 771 } |
| 771 return rightWordBreak; | 772 return rightWordBreak; |
| 772 } | 773 } |
| 773 | 774 |
| 774 template <typename Strategy> | 775 template <typename Strategy> |
| 775 static ContainerNode* nonShadowBoundaryParentNode(Node* node) { | 776 static ContainerNode* nonShadowBoundaryParentNode(Node* node) { |
| 776 ContainerNode* parent = Strategy::parent(*node); | 777 ContainerNode* parent = Strategy::parent(*node); |
| 777 return parent && !parent->isShadowRoot() ? parent : nullptr; | 778 return parent && !parent->isShadowRoot() ? parent : nullptr; |
| (...skipping 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2205 // of INPUT/TEXTAREA element, by |nextPosition().isNull()|, because of | 2206 // of INPUT/TEXTAREA element, by |nextPosition().isNull()|, because of |
| 2206 // an inner editor is an only leaf node. | 2207 // an inner editor is an only leaf node. |
| 2207 if (!nextPosition.deepEquivalent().isAfterAnchor()) | 2208 if (!nextPosition.deepEquivalent().isAfterAnchor()) |
| 2208 return false; | 2209 return false; |
| 2209 return isTextControlElement(nextPosition.deepEquivalent().anchorNode()); | 2210 return isTextControlElement(nextPosition.deepEquivalent().anchorNode()); |
| 2210 } | 2211 } |
| 2211 | 2212 |
| 2212 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, | 2213 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, |
| 2213 TextDirection direction) { | 2214 TextDirection direction) { |
| 2214 DCHECK(c.isValid()) << c; | 2215 DCHECK(c.isValid()) << c; |
| 2215 return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c); | 2216 return direction == TextDirection::Ltr ? logicalStartOfLine(c) |
| 2217 : logicalEndOfLine(c); |
| 2216 } | 2218 } |
| 2217 | 2219 |
| 2218 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, | 2220 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, |
| 2219 TextDirection direction) { | 2221 TextDirection direction) { |
| 2220 DCHECK(c.isValid()) << c; | 2222 DCHECK(c.isValid()) << c; |
| 2221 return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c); | 2223 return direction == TextDirection::Ltr ? logicalEndOfLine(c) |
| 2224 : logicalStartOfLine(c); |
| 2222 } | 2225 } |
| 2223 | 2226 |
| 2224 static bool isNonTextLeafChild(LayoutObject* object) { | 2227 static bool isNonTextLeafChild(LayoutObject* object) { |
| 2225 if (object->slowFirstChild()) | 2228 if (object->slowFirstChild()) |
| 2226 return false; | 2229 return false; |
| 2227 if (object->isText()) | 2230 if (object->isText()) |
| 2228 return false; | 2231 return false; |
| 2229 return true; | 2232 return true; |
| 2230 } | 2233 } |
| 2231 | 2234 |
| (...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3325 mostForwardCaretPosition(p); | 3328 mostForwardCaretPosition(p); |
| 3326 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); | 3329 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
| 3327 const TextAffinity affinity = visiblePosition.affinity(); | 3330 const TextAffinity affinity = visiblePosition.affinity(); |
| 3328 | 3331 |
| 3329 while (true) { | 3332 while (true) { |
| 3330 InlineBoxPosition boxPosition = | 3333 InlineBoxPosition boxPosition = |
| 3331 computeInlineBoxPosition(p, affinity, primaryDirection); | 3334 computeInlineBoxPosition(p, affinity, primaryDirection); |
| 3332 InlineBox* box = boxPosition.inlineBox; | 3335 InlineBox* box = boxPosition.inlineBox; |
| 3333 int offset = boxPosition.offsetInBox; | 3336 int offset = boxPosition.offsetInBox; |
| 3334 if (!box) | 3337 if (!box) |
| 3335 return primaryDirection == LTR | 3338 return primaryDirection == TextDirection::Ltr |
| 3336 ? previousVisuallyDistinctCandidate(deepPosition) | 3339 ? previousVisuallyDistinctCandidate(deepPosition) |
| 3337 : nextVisuallyDistinctCandidate(deepPosition); | 3340 : nextVisuallyDistinctCandidate(deepPosition); |
| 3338 | 3341 |
| 3339 LineLayoutItem lineLayoutItem = box->getLineLayoutItem(); | 3342 LineLayoutItem lineLayoutItem = box->getLineLayoutItem(); |
| 3340 | 3343 |
| 3341 while (true) { | 3344 while (true) { |
| 3342 if ((lineLayoutItem.isAtomicInlineLevel() || lineLayoutItem.isBR()) && | 3345 if ((lineLayoutItem.isAtomicInlineLevel() || lineLayoutItem.isBR()) && |
| 3343 offset == box->caretRightmostOffset()) | 3346 offset == box->caretRightmostOffset()) |
| 3344 return box->isLeftToRightDirection() | 3347 return box->isLeftToRightDirection() |
| 3345 ? previousVisuallyDistinctCandidate(deepPosition) | 3348 ? previousVisuallyDistinctCandidate(deepPosition) |
| 3346 : nextVisuallyDistinctCandidate(deepPosition); | 3349 : nextVisuallyDistinctCandidate(deepPosition); |
| 3347 | 3350 |
| 3348 if (!lineLayoutItem.node()) { | 3351 if (!lineLayoutItem.node()) { |
| 3349 box = box->prevLeafChild(); | 3352 box = box->prevLeafChild(); |
| 3350 if (!box) | 3353 if (!box) |
| 3351 return primaryDirection == LTR | 3354 return primaryDirection == TextDirection::Ltr |
| 3352 ? previousVisuallyDistinctCandidate(deepPosition) | 3355 ? previousVisuallyDistinctCandidate(deepPosition) |
| 3353 : nextVisuallyDistinctCandidate(deepPosition); | 3356 : nextVisuallyDistinctCandidate(deepPosition); |
| 3354 lineLayoutItem = box->getLineLayoutItem(); | 3357 lineLayoutItem = box->getLineLayoutItem(); |
| 3355 offset = box->caretRightmostOffset(); | 3358 offset = box->caretRightmostOffset(); |
| 3356 continue; | 3359 continue; |
| 3357 } | 3360 } |
| 3358 | 3361 |
| 3359 offset = box->isLeftToRightDirection() | 3362 offset = box->isLeftToRightDirection() |
| 3360 ? previousGraphemeBoundaryOf(lineLayoutItem.node(), offset) | 3363 ? previousGraphemeBoundaryOf(lineLayoutItem.node(), offset) |
| 3361 : nextGraphemeBoundaryOf(lineLayoutItem.node(), offset); | 3364 : nextGraphemeBoundaryOf(lineLayoutItem.node(), offset); |
| 3362 | 3365 |
| 3363 int caretMinOffset = box->caretMinOffset(); | 3366 int caretMinOffset = box->caretMinOffset(); |
| 3364 int caretMaxOffset = box->caretMaxOffset(); | 3367 int caretMaxOffset = box->caretMaxOffset(); |
| 3365 | 3368 |
| 3366 if (offset > caretMinOffset && offset < caretMaxOffset) | 3369 if (offset > caretMinOffset && offset < caretMaxOffset) |
| 3367 break; | 3370 break; |
| 3368 | 3371 |
| 3369 if (box->isLeftToRightDirection() ? offset < caretMinOffset | 3372 if (box->isLeftToRightDirection() ? offset < caretMinOffset |
| 3370 : offset > caretMaxOffset) { | 3373 : offset > caretMaxOffset) { |
| 3371 // Overshot to the left. | 3374 // Overshot to the left. |
| 3372 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); | 3375 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); |
| 3373 if (!prevBox) { | 3376 if (!prevBox) { |
| 3374 PositionTemplate<Strategy> positionOnLeft = | 3377 PositionTemplate<Strategy> positionOnLeft = |
| 3375 primaryDirection == LTR ? previousVisuallyDistinctCandidate( | 3378 primaryDirection == TextDirection::Ltr |
| 3376 visiblePosition.deepEquivalent()) | 3379 ? previousVisuallyDistinctCandidate( |
| 3377 : nextVisuallyDistinctCandidate( | 3380 visiblePosition.deepEquivalent()) |
| 3378 visiblePosition.deepEquivalent()); | 3381 : nextVisuallyDistinctCandidate( |
| 3382 visiblePosition.deepEquivalent()); |
| 3379 if (positionOnLeft.isNull()) | 3383 if (positionOnLeft.isNull()) |
| 3380 return PositionTemplate<Strategy>(); | 3384 return PositionTemplate<Strategy>(); |
| 3381 | 3385 |
| 3382 InlineBox* boxOnLeft = computeInlineBoxPosition( | 3386 InlineBox* boxOnLeft = computeInlineBoxPosition( |
| 3383 positionOnLeft, affinity, primaryDirection) | 3387 positionOnLeft, affinity, primaryDirection) |
| 3384 .inlineBox; | 3388 .inlineBox; |
| 3385 if (boxOnLeft && boxOnLeft->root() == box->root()) | 3389 if (boxOnLeft && boxOnLeft->root() == box->root()) |
| 3386 return PositionTemplate<Strategy>(); | 3390 return PositionTemplate<Strategy>(); |
| 3387 return positionOnLeft; | 3391 return positionOnLeft; |
| 3388 } | 3392 } |
| 3389 | 3393 |
| 3390 // Reposition at the other logical position corresponding to our | 3394 // Reposition at the other logical position corresponding to our |
| 3391 // edge's visual position and go for another round. | 3395 // edge's visual position and go for another round. |
| 3392 box = prevBox; | 3396 box = prevBox; |
| 3393 lineLayoutItem = box->getLineLayoutItem(); | 3397 lineLayoutItem = box->getLineLayoutItem(); |
| 3394 offset = prevBox->caretRightmostOffset(); | 3398 offset = prevBox->caretRightmostOffset(); |
| 3395 continue; | 3399 continue; |
| 3396 } | 3400 } |
| 3397 | 3401 |
| 3398 DCHECK_EQ(offset, box->caretLeftmostOffset()); | 3402 DCHECK_EQ(offset, box->caretLeftmostOffset()); |
| 3399 | 3403 |
| 3400 unsigned char level = box->bidiLevel(); | 3404 unsigned char level = box->bidiLevel(); |
| 3401 InlineBox* prevBox = box->prevLeafChild(); | 3405 InlineBox* prevBox = box->prevLeafChild(); |
| 3402 | 3406 |
| 3403 if (box->direction() == primaryDirection) { | 3407 if (box->direction() == primaryDirection) { |
| 3404 if (!prevBox) { | 3408 if (!prevBox) { |
| 3405 InlineBox* logicalStart = 0; | 3409 InlineBox* logicalStart = 0; |
| 3406 if (primaryDirection == LTR | 3410 if (primaryDirection == TextDirection::Ltr |
| 3407 ? box->root().getLogicalStartBoxWithNode(logicalStart) | 3411 ? box->root().getLogicalStartBoxWithNode(logicalStart) |
| 3408 : box->root().getLogicalEndBoxWithNode(logicalStart)) { | 3412 : box->root().getLogicalEndBoxWithNode(logicalStart)) { |
| 3409 box = logicalStart; | 3413 box = logicalStart; |
| 3410 lineLayoutItem = box->getLineLayoutItem(); | 3414 lineLayoutItem = box->getLineLayoutItem(); |
| 3411 offset = primaryDirection == LTR ? box->caretMinOffset() | 3415 offset = primaryDirection == TextDirection::Ltr |
| 3412 : box->caretMaxOffset(); | 3416 ? box->caretMinOffset() |
| 3417 : box->caretMaxOffset(); |
| 3413 } | 3418 } |
| 3414 break; | 3419 break; |
| 3415 } | 3420 } |
| 3416 if (prevBox->bidiLevel() >= level) | 3421 if (prevBox->bidiLevel() >= level) |
| 3417 break; | 3422 break; |
| 3418 | 3423 |
| 3419 level = prevBox->bidiLevel(); | 3424 level = prevBox->bidiLevel(); |
| 3420 | 3425 |
| 3421 InlineBox* nextBox = box; | 3426 InlineBox* nextBox = box; |
| 3422 do { | 3427 do { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3464 while (InlineBox* prevBox = box->prevLeafChild()) { | 3469 while (InlineBox* prevBox = box->prevLeafChild()) { |
| 3465 if (prevBox->bidiLevel() < level) | 3470 if (prevBox->bidiLevel() < level) |
| 3466 break; | 3471 break; |
| 3467 box = prevBox; | 3472 box = prevBox; |
| 3468 } | 3473 } |
| 3469 if (box->bidiLevel() == level) | 3474 if (box->bidiLevel() == level) |
| 3470 break; | 3475 break; |
| 3471 level = box->bidiLevel(); | 3476 level = box->bidiLevel(); |
| 3472 } | 3477 } |
| 3473 lineLayoutItem = box->getLineLayoutItem(); | 3478 lineLayoutItem = box->getLineLayoutItem(); |
| 3474 offset = primaryDirection == LTR ? box->caretMinOffset() | 3479 offset = primaryDirection == TextDirection::Ltr ? box->caretMinOffset() |
| 3475 : box->caretMaxOffset(); | 3480 : box->caretMaxOffset(); |
| 3476 } | 3481 } |
| 3477 break; | 3482 break; |
| 3478 } | 3483 } |
| 3479 | 3484 |
| 3480 p = PositionTemplate<Strategy>::editingPositionOf(lineLayoutItem.node(), | 3485 p = PositionTemplate<Strategy>::editingPositionOf(lineLayoutItem.node(), |
| 3481 offset); | 3486 offset); |
| 3482 | 3487 |
| 3483 if ((isVisuallyEquivalentCandidate(p) && | 3488 if ((isVisuallyEquivalentCandidate(p) && |
| 3484 mostForwardCaretPosition(p) != downstreamStart) || | 3489 mostForwardCaretPosition(p) != downstreamStart) || |
| 3485 p.atStartOfTree() || p.atEndOfTree()) | 3490 p.atStartOfTree() || p.atEndOfTree()) |
| 3486 return p; | 3491 return p; |
| 3487 | 3492 |
| 3488 DCHECK_NE(p, deepPosition); | 3493 DCHECK_NE(p, deepPosition); |
| 3489 } | 3494 } |
| 3490 } | 3495 } |
| 3491 | 3496 |
| 3492 template <typename Strategy> | 3497 template <typename Strategy> |
| 3493 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm( | 3498 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm( |
| 3494 const VisiblePositionTemplate<Strategy>& visiblePosition) { | 3499 const VisiblePositionTemplate<Strategy>& visiblePosition) { |
| 3495 DCHECK(visiblePosition.isValid()) << visiblePosition; | 3500 DCHECK(visiblePosition.isValid()) << visiblePosition; |
| 3496 const PositionTemplate<Strategy> pos = | 3501 const PositionTemplate<Strategy> pos = |
| 3497 leftVisuallyDistinctCandidate(visiblePosition); | 3502 leftVisuallyDistinctCandidate(visiblePosition); |
| 3498 // TODO(yosin) Why can't we move left from the last position in a tree? | 3503 // TODO(yosin) Why can't we move left from the last position in a tree? |
| 3499 if (pos.atStartOfTree() || pos.atEndOfTree()) | 3504 if (pos.atStartOfTree() || pos.atEndOfTree()) |
| 3500 return VisiblePositionTemplate<Strategy>(); | 3505 return VisiblePositionTemplate<Strategy>(); |
| 3501 | 3506 |
| 3502 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos); | 3507 const VisiblePositionTemplate<Strategy> left = createVisiblePosition(pos); |
| 3503 DCHECK_NE(left.deepEquivalent(), visiblePosition.deepEquivalent()); | 3508 DCHECK_NE(left.deepEquivalent(), visiblePosition.deepEquivalent()); |
| 3504 | 3509 |
| 3505 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR | 3510 return directionOfEnclosingBlock(left.deepEquivalent()) == TextDirection::Ltr |
| 3506 ? honorEditingBoundaryAtOrBefore(left, | 3511 ? honorEditingBoundaryAtOrBefore(left, |
| 3507 visiblePosition.deepEquivalent()) | 3512 visiblePosition.deepEquivalent()) |
| 3508 : honorEditingBoundaryAtOrAfter(left, | 3513 : honorEditingBoundaryAtOrAfter(left, |
| 3509 visiblePosition.deepEquivalent()); | 3514 visiblePosition.deepEquivalent()); |
| 3510 } | 3515 } |
| 3511 | 3516 |
| 3512 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) { | 3517 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) { |
| 3513 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition); | 3518 return leftPositionOfAlgorithm<EditingStrategy>(visiblePosition); |
| 3514 } | 3519 } |
| 3515 | 3520 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3532 mostForwardCaretPosition(p); | 3537 mostForwardCaretPosition(p); |
| 3533 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); | 3538 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
| 3534 const TextAffinity affinity = visiblePosition.affinity(); | 3539 const TextAffinity affinity = visiblePosition.affinity(); |
| 3535 | 3540 |
| 3536 while (true) { | 3541 while (true) { |
| 3537 InlineBoxPosition boxPosition = | 3542 InlineBoxPosition boxPosition = |
| 3538 computeInlineBoxPosition(p, affinity, primaryDirection); | 3543 computeInlineBoxPosition(p, affinity, primaryDirection); |
| 3539 InlineBox* box = boxPosition.inlineBox; | 3544 InlineBox* box = boxPosition.inlineBox; |
| 3540 int offset = boxPosition.offsetInBox; | 3545 int offset = boxPosition.offsetInBox; |
| 3541 if (!box) | 3546 if (!box) |
| 3542 return primaryDirection == LTR | 3547 return primaryDirection == TextDirection::Ltr |
| 3543 ? nextVisuallyDistinctCandidate(deepPosition) | 3548 ? nextVisuallyDistinctCandidate(deepPosition) |
| 3544 : previousVisuallyDistinctCandidate(deepPosition); | 3549 : previousVisuallyDistinctCandidate(deepPosition); |
| 3545 | 3550 |
| 3546 LayoutObject* layoutObject = | 3551 LayoutObject* layoutObject = |
| 3547 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); | 3552 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); |
| 3548 | 3553 |
| 3549 while (true) { | 3554 while (true) { |
| 3550 if ((layoutObject->isAtomicInlineLevel() || layoutObject->isBR()) && | 3555 if ((layoutObject->isAtomicInlineLevel() || layoutObject->isBR()) && |
| 3551 offset == box->caretLeftmostOffset()) | 3556 offset == box->caretLeftmostOffset()) |
| 3552 return box->isLeftToRightDirection() | 3557 return box->isLeftToRightDirection() |
| 3553 ? nextVisuallyDistinctCandidate(deepPosition) | 3558 ? nextVisuallyDistinctCandidate(deepPosition) |
| 3554 : previousVisuallyDistinctCandidate(deepPosition); | 3559 : previousVisuallyDistinctCandidate(deepPosition); |
| 3555 | 3560 |
| 3556 if (!layoutObject->node()) { | 3561 if (!layoutObject->node()) { |
| 3557 box = box->nextLeafChild(); | 3562 box = box->nextLeafChild(); |
| 3558 if (!box) | 3563 if (!box) |
| 3559 return primaryDirection == LTR | 3564 return primaryDirection == TextDirection::Ltr |
| 3560 ? nextVisuallyDistinctCandidate(deepPosition) | 3565 ? nextVisuallyDistinctCandidate(deepPosition) |
| 3561 : previousVisuallyDistinctCandidate(deepPosition); | 3566 : previousVisuallyDistinctCandidate(deepPosition); |
| 3562 layoutObject = | 3567 layoutObject = |
| 3563 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); | 3568 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); |
| 3564 offset = box->caretLeftmostOffset(); | 3569 offset = box->caretLeftmostOffset(); |
| 3565 continue; | 3570 continue; |
| 3566 } | 3571 } |
| 3567 | 3572 |
| 3568 offset = box->isLeftToRightDirection() | 3573 offset = box->isLeftToRightDirection() |
| 3569 ? nextGraphemeBoundaryOf(layoutObject->node(), offset) | 3574 ? nextGraphemeBoundaryOf(layoutObject->node(), offset) |
| 3570 : previousGraphemeBoundaryOf(layoutObject->node(), offset); | 3575 : previousGraphemeBoundaryOf(layoutObject->node(), offset); |
| 3571 | 3576 |
| 3572 int caretMinOffset = box->caretMinOffset(); | 3577 int caretMinOffset = box->caretMinOffset(); |
| 3573 int caretMaxOffset = box->caretMaxOffset(); | 3578 int caretMaxOffset = box->caretMaxOffset(); |
| 3574 | 3579 |
| 3575 if (offset > caretMinOffset && offset < caretMaxOffset) | 3580 if (offset > caretMinOffset && offset < caretMaxOffset) |
| 3576 break; | 3581 break; |
| 3577 | 3582 |
| 3578 if (box->isLeftToRightDirection() ? offset > caretMaxOffset | 3583 if (box->isLeftToRightDirection() ? offset > caretMaxOffset |
| 3579 : offset < caretMinOffset) { | 3584 : offset < caretMinOffset) { |
| 3580 // Overshot to the right. | 3585 // Overshot to the right. |
| 3581 InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); | 3586 InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); |
| 3582 if (!nextBox) { | 3587 if (!nextBox) { |
| 3583 PositionTemplate<Strategy> positionOnRight = | 3588 PositionTemplate<Strategy> positionOnRight = |
| 3584 primaryDirection == LTR | 3589 primaryDirection == TextDirection::Ltr |
| 3585 ? nextVisuallyDistinctCandidate(deepPosition) | 3590 ? nextVisuallyDistinctCandidate(deepPosition) |
| 3586 : previousVisuallyDistinctCandidate(deepPosition); | 3591 : previousVisuallyDistinctCandidate(deepPosition); |
| 3587 if (positionOnRight.isNull()) | 3592 if (positionOnRight.isNull()) |
| 3588 return PositionTemplate<Strategy>(); | 3593 return PositionTemplate<Strategy>(); |
| 3589 | 3594 |
| 3590 InlineBox* boxOnRight = | 3595 InlineBox* boxOnRight = |
| 3591 computeInlineBoxPosition(positionOnRight, affinity, | 3596 computeInlineBoxPosition(positionOnRight, affinity, |
| 3592 primaryDirection) | 3597 primaryDirection) |
| 3593 .inlineBox; | 3598 .inlineBox; |
| 3594 if (boxOnRight && boxOnRight->root() == box->root()) | 3599 if (boxOnRight && boxOnRight->root() == box->root()) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3606 } | 3611 } |
| 3607 | 3612 |
| 3608 DCHECK_EQ(offset, box->caretRightmostOffset()); | 3613 DCHECK_EQ(offset, box->caretRightmostOffset()); |
| 3609 | 3614 |
| 3610 unsigned char level = box->bidiLevel(); | 3615 unsigned char level = box->bidiLevel(); |
| 3611 InlineBox* nextBox = box->nextLeafChild(); | 3616 InlineBox* nextBox = box->nextLeafChild(); |
| 3612 | 3617 |
| 3613 if (box->direction() == primaryDirection) { | 3618 if (box->direction() == primaryDirection) { |
| 3614 if (!nextBox) { | 3619 if (!nextBox) { |
| 3615 InlineBox* logicalEnd = 0; | 3620 InlineBox* logicalEnd = 0; |
| 3616 if (primaryDirection == LTR | 3621 if (primaryDirection == TextDirection::Ltr |
| 3617 ? box->root().getLogicalEndBoxWithNode(logicalEnd) | 3622 ? box->root().getLogicalEndBoxWithNode(logicalEnd) |
| 3618 : box->root().getLogicalStartBoxWithNode(logicalEnd)) { | 3623 : box->root().getLogicalStartBoxWithNode(logicalEnd)) { |
| 3619 box = logicalEnd; | 3624 box = logicalEnd; |
| 3620 layoutObject = | 3625 layoutObject = |
| 3621 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); | 3626 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); |
| 3622 offset = primaryDirection == LTR ? box->caretMaxOffset() | 3627 offset = primaryDirection == TextDirection::Ltr |
| 3623 : box->caretMinOffset(); | 3628 ? box->caretMaxOffset() |
| 3629 : box->caretMinOffset(); |
| 3624 } | 3630 } |
| 3625 break; | 3631 break; |
| 3626 } | 3632 } |
| 3627 | 3633 |
| 3628 if (nextBox->bidiLevel() >= level) | 3634 if (nextBox->bidiLevel() >= level) |
| 3629 break; | 3635 break; |
| 3630 | 3636 |
| 3631 level = nextBox->bidiLevel(); | 3637 level = nextBox->bidiLevel(); |
| 3632 | 3638 |
| 3633 InlineBox* prevBox = box; | 3639 InlineBox* prevBox = box; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3682 if (nextBox->bidiLevel() < level) | 3688 if (nextBox->bidiLevel() < level) |
| 3683 break; | 3689 break; |
| 3684 box = nextBox; | 3690 box = nextBox; |
| 3685 } | 3691 } |
| 3686 if (box->bidiLevel() == level) | 3692 if (box->bidiLevel() == level) |
| 3687 break; | 3693 break; |
| 3688 level = box->bidiLevel(); | 3694 level = box->bidiLevel(); |
| 3689 } | 3695 } |
| 3690 layoutObject = | 3696 layoutObject = |
| 3691 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); | 3697 LineLayoutAPIShim::layoutObjectFrom(box->getLineLayoutItem()); |
| 3692 offset = primaryDirection == LTR ? box->caretMaxOffset() | 3698 offset = primaryDirection == TextDirection::Ltr ? box->caretMaxOffset() |
| 3693 : box->caretMinOffset(); | 3699 : box->caretMinOffset(); |
| 3694 } | 3700 } |
| 3695 break; | 3701 break; |
| 3696 } | 3702 } |
| 3697 | 3703 |
| 3698 p = PositionTemplate<Strategy>::editingPositionOf(layoutObject->node(), | 3704 p = PositionTemplate<Strategy>::editingPositionOf(layoutObject->node(), |
| 3699 offset); | 3705 offset); |
| 3700 | 3706 |
| 3701 if ((isVisuallyEquivalentCandidate(p) && | 3707 if ((isVisuallyEquivalentCandidate(p) && |
| 3702 mostForwardCaretPosition(p) != downstreamStart) || | 3708 mostForwardCaretPosition(p) != downstreamStart) || |
| 3703 p.atStartOfTree() || p.atEndOfTree()) | 3709 p.atStartOfTree() || p.atEndOfTree()) |
| 3704 return p; | 3710 return p; |
| 3705 | 3711 |
| 3706 DCHECK_NE(p, deepPosition); | 3712 DCHECK_NE(p, deepPosition); |
| 3707 } | 3713 } |
| 3708 } | 3714 } |
| 3709 | 3715 |
| 3710 template <typename Strategy> | 3716 template <typename Strategy> |
| 3711 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm( | 3717 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm( |
| 3712 const VisiblePositionTemplate<Strategy>& visiblePosition) { | 3718 const VisiblePositionTemplate<Strategy>& visiblePosition) { |
| 3713 DCHECK(visiblePosition.isValid()) << visiblePosition; | 3719 DCHECK(visiblePosition.isValid()) << visiblePosition; |
| 3714 const PositionTemplate<Strategy> pos = | 3720 const PositionTemplate<Strategy> pos = |
| 3715 rightVisuallyDistinctCandidate(visiblePosition); | 3721 rightVisuallyDistinctCandidate(visiblePosition); |
| 3716 // FIXME: Why can't we move left from the last position in a tree? | 3722 // FIXME: Why can't we move left from the last position in a tree? |
| 3717 if (pos.atStartOfTree() || pos.atEndOfTree()) | 3723 if (pos.atStartOfTree() || pos.atEndOfTree()) |
| 3718 return VisiblePositionTemplate<Strategy>(); | 3724 return VisiblePositionTemplate<Strategy>(); |
| 3719 | 3725 |
| 3720 const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos); | 3726 const VisiblePositionTemplate<Strategy> right = createVisiblePosition(pos); |
| 3721 DCHECK_NE(right.deepEquivalent(), visiblePosition.deepEquivalent()); | 3727 DCHECK_NE(right.deepEquivalent(), visiblePosition.deepEquivalent()); |
| 3722 | 3728 |
| 3723 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR | 3729 return directionOfEnclosingBlock(right.deepEquivalent()) == TextDirection::Ltr |
| 3724 ? honorEditingBoundaryAtOrAfter(right, | 3730 ? honorEditingBoundaryAtOrAfter(right, |
| 3725 visiblePosition.deepEquivalent()) | 3731 visiblePosition.deepEquivalent()) |
| 3726 : honorEditingBoundaryAtOrBefore(right, | 3732 : honorEditingBoundaryAtOrBefore(right, |
| 3727 visiblePosition.deepEquivalent()); | 3733 visiblePosition.deepEquivalent()); |
| 3728 } | 3734 } |
| 3729 | 3735 |
| 3730 VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition) { | 3736 VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition) { |
| 3731 return rightPositionOfAlgorithm<EditingStrategy>(visiblePosition); | 3737 return rightPositionOfAlgorithm<EditingStrategy>(visiblePosition); |
| 3732 } | 3738 } |
| 3733 | 3739 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3842 | 3848 |
| 3843 VisiblePositionInFlatTree previousPositionOf( | 3849 VisiblePositionInFlatTree previousPositionOf( |
| 3844 const VisiblePositionInFlatTree& visiblePosition, | 3850 const VisiblePositionInFlatTree& visiblePosition, |
| 3845 EditingBoundaryCrossingRule rule) { | 3851 EditingBoundaryCrossingRule rule) { |
| 3846 DCHECK(visiblePosition.isValid()) << visiblePosition; | 3852 DCHECK(visiblePosition.isValid()) << visiblePosition; |
| 3847 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>( | 3853 return previousPositionOfAlgorithm<EditingInFlatTreeStrategy>( |
| 3848 visiblePosition.deepEquivalent(), rule); | 3854 visiblePosition.deepEquivalent(), rule); |
| 3849 } | 3855 } |
| 3850 | 3856 |
| 3851 } // namespace blink | 3857 } // namespace blink |
| OLD | NEW |