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 |