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 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 2476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2487 return 0; | 2487 return 0; |
2488 | 2488 |
2489 return textNode->data().characterStartingAt(offset); | 2489 return textNode->data().characterStartingAt(offset); |
2490 } | 2490 } |
2491 | 2491 |
2492 UChar32 characterBefore(const VisiblePosition& visiblePosition) | 2492 UChar32 characterBefore(const VisiblePosition& visiblePosition) |
2493 { | 2493 { |
2494 return characterAfter(previousPositionOf(visiblePosition)); | 2494 return characterAfter(previousPositionOf(visiblePosition)); |
2495 } | 2495 } |
2496 | 2496 |
| 2497 static Position leftVisuallyDistinctCandidate(const VisiblePosition& visiblePosi
tion) |
| 2498 { |
| 2499 const Position deepPosition = visiblePosition.deepEquivalent(); |
| 2500 Position p = deepPosition; |
| 2501 if (p.isNull()) |
| 2502 return Position(); |
| 2503 |
| 2504 Position downstreamStart = mostForwardCaretPosition(p); |
| 2505 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
| 2506 const TextAffinity affinity = visiblePosition.affinity(); |
| 2507 |
| 2508 while (true) { |
| 2509 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, pr
imaryDirection); |
| 2510 InlineBox* box = boxPosition.inlineBox; |
| 2511 int offset = boxPosition.offsetInBox; |
| 2512 if (!box) |
| 2513 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(d
eepPosition) : nextVisuallyDistinctCandidate(deepPosition); |
| 2514 |
| 2515 LayoutObject* layoutObject = &box->layoutObject(); |
| 2516 |
| 2517 while (true) { |
| 2518 if ((layoutObject->isReplaced() || layoutObject->isBR()) && offset =
= box->caretRightmostOffset()) |
| 2519 return box->isLeftToRightDirection() ? previousVisuallyDistinctC
andidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition); |
| 2520 |
| 2521 if (!layoutObject->node()) { |
| 2522 box = box->prevLeafChild(); |
| 2523 if (!box) |
| 2524 return primaryDirection == LTR ? previousVisuallyDistinctCan
didate(deepPosition) : nextVisuallyDistinctCandidate(deepPosition); |
| 2525 layoutObject = &box->layoutObject(); |
| 2526 offset = box->caretRightmostOffset(); |
| 2527 continue; |
| 2528 } |
| 2529 |
| 2530 offset = box->isLeftToRightDirection() ? layoutObject->previousOffse
t(offset) : layoutObject->nextOffset(offset); |
| 2531 |
| 2532 int caretMinOffset = box->caretMinOffset(); |
| 2533 int caretMaxOffset = box->caretMaxOffset(); |
| 2534 |
| 2535 if (offset > caretMinOffset && offset < caretMaxOffset) |
| 2536 break; |
| 2537 |
| 2538 if (box->isLeftToRightDirection() ? offset < caretMinOffset : offset
> caretMaxOffset) { |
| 2539 // Overshot to the left. |
| 2540 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); |
| 2541 if (!prevBox) { |
| 2542 Position positionOnLeft = primaryDirection == LTR ? previous
VisuallyDistinctCandidate(deepPosition) : nextVisuallyDistinctCandidate(deepPosi
tion); |
| 2543 if (positionOnLeft.isNull()) |
| 2544 return Position(); |
| 2545 |
| 2546 InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLe
ft, affinity, primaryDirection).inlineBox; |
| 2547 if (boxOnLeft && boxOnLeft->root() == box->root()) |
| 2548 return Position(); |
| 2549 return positionOnLeft; |
| 2550 } |
| 2551 |
| 2552 // Reposition at the other logical position corresponding to our |
| 2553 // edge's visual position and go for another round. |
| 2554 box = prevBox; |
| 2555 layoutObject = &box->layoutObject(); |
| 2556 offset = prevBox->caretRightmostOffset(); |
| 2557 continue; |
| 2558 } |
| 2559 |
| 2560 ASSERT(offset == box->caretLeftmostOffset()); |
| 2561 |
| 2562 unsigned char level = box->bidiLevel(); |
| 2563 InlineBox* prevBox = box->prevLeafChild(); |
| 2564 |
| 2565 if (box->direction() == primaryDirection) { |
| 2566 if (!prevBox) { |
| 2567 InlineBox* logicalStart = 0; |
| 2568 if (primaryDirection == LTR ? box->root().getLogicalStartBox
WithNode(logicalStart) : box->root().getLogicalEndBoxWithNode(logicalStart)) { |
| 2569 box = logicalStart; |
| 2570 layoutObject = &box->layoutObject(); |
| 2571 offset = primaryDirection == LTR ? box->caretMinOffset()
: box->caretMaxOffset(); |
| 2572 } |
| 2573 break; |
| 2574 } |
| 2575 if (prevBox->bidiLevel() >= level) |
| 2576 break; |
| 2577 |
| 2578 level = prevBox->bidiLevel(); |
| 2579 |
| 2580 InlineBox* nextBox = box; |
| 2581 do { |
| 2582 nextBox = nextBox->nextLeafChild(); |
| 2583 } while (nextBox && nextBox->bidiLevel() > level); |
| 2584 |
| 2585 if (nextBox && nextBox->bidiLevel() == level) |
| 2586 break; |
| 2587 |
| 2588 box = prevBox; |
| 2589 layoutObject = &box->layoutObject(); |
| 2590 offset = box->caretRightmostOffset(); |
| 2591 if (box->direction() == primaryDirection) |
| 2592 break; |
| 2593 continue; |
| 2594 } |
| 2595 |
| 2596 while (prevBox && !prevBox->layoutObject().node()) |
| 2597 prevBox = prevBox->prevLeafChild(); |
| 2598 |
| 2599 if (prevBox) { |
| 2600 box = prevBox; |
| 2601 layoutObject = &box->layoutObject(); |
| 2602 offset = box->caretRightmostOffset(); |
| 2603 if (box->bidiLevel() > level) { |
| 2604 do { |
| 2605 prevBox = prevBox->prevLeafChild(); |
| 2606 } while (prevBox && prevBox->bidiLevel() > level); |
| 2607 |
| 2608 if (!prevBox || prevBox->bidiLevel() < level) |
| 2609 continue; |
| 2610 } |
| 2611 } else { |
| 2612 // Trailing edge of a secondary run. Set to the leading edge of
the entire run. |
| 2613 while (true) { |
| 2614 while (InlineBox* nextBox = box->nextLeafChild()) { |
| 2615 if (nextBox->bidiLevel() < level) |
| 2616 break; |
| 2617 box = nextBox; |
| 2618 } |
| 2619 if (box->bidiLevel() == level) |
| 2620 break; |
| 2621 level = box->bidiLevel(); |
| 2622 while (InlineBox* prevBox = box->prevLeafChild()) { |
| 2623 if (prevBox->bidiLevel() < level) |
| 2624 break; |
| 2625 box = prevBox; |
| 2626 } |
| 2627 if (box->bidiLevel() == level) |
| 2628 break; |
| 2629 level = box->bidiLevel(); |
| 2630 } |
| 2631 layoutObject = &box->layoutObject(); |
| 2632 offset = primaryDirection == LTR ? box->caretMinOffset() : box->
caretMaxOffset(); |
| 2633 } |
| 2634 break; |
| 2635 } |
| 2636 |
| 2637 p = Position::editingPositionOf(layoutObject->node(), offset); |
| 2638 |
| 2639 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) |
| 2640 return p; |
| 2641 |
| 2642 ASSERT(p != deepPosition); |
| 2643 } |
| 2644 } |
| 2645 |
| 2646 VisiblePosition leftPositionOf(const VisiblePosition& visiblePosition) |
| 2647 { |
| 2648 const Position pos = leftVisuallyDistinctCandidate(visiblePosition); |
| 2649 // TODO(yosin) Why can't we move left from the last position in a tree? |
| 2650 if (pos.atStartOfTree() || pos.atEndOfTree()) |
| 2651 return VisiblePosition(); |
| 2652 |
| 2653 VisiblePosition left = createVisiblePosition(pos); |
| 2654 ASSERT(left.deepEquivalent() != visiblePosition.deepEquivalent()); |
| 2655 |
| 2656 return directionOfEnclosingBlock(left.deepEquivalent()) == LTR ? honorEditin
gBoundaryAtOrBefore(left, visiblePosition.deepEquivalent()) : honorEditingBounda
ryAtOrAfter(left, visiblePosition.deepEquivalent()); |
| 2657 } |
| 2658 |
| 2659 static Position rightVisuallyDistinctCandidate(const VisiblePosition& visiblePos
ition) |
| 2660 { |
| 2661 const Position deepPosition = visiblePosition.deepEquivalent(); |
| 2662 Position p = deepPosition; |
| 2663 if (p.isNull()) |
| 2664 return Position(); |
| 2665 |
| 2666 Position downstreamStart = mostForwardCaretPosition(p); |
| 2667 TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); |
| 2668 const TextAffinity affinity = visiblePosition.affinity(); |
| 2669 |
| 2670 while (true) { |
| 2671 InlineBoxPosition boxPosition = computeInlineBoxPosition(p, affinity, pr
imaryDirection); |
| 2672 InlineBox* box = boxPosition.inlineBox; |
| 2673 int offset = boxPosition.offsetInBox; |
| 2674 if (!box) |
| 2675 return primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepP
osition) : previousVisuallyDistinctCandidate(deepPosition); |
| 2676 |
| 2677 LayoutObject* layoutObject = &box->layoutObject(); |
| 2678 |
| 2679 while (true) { |
| 2680 if ((layoutObject->isReplaced() || layoutObject->isBR()) && offset =
= box->caretLeftmostOffset()) |
| 2681 return box->isLeftToRightDirection() ? nextVisuallyDistinctCandi
date(deepPosition) : previousVisuallyDistinctCandidate(deepPosition); |
| 2682 |
| 2683 if (!layoutObject->node()) { |
| 2684 box = box->nextLeafChild(); |
| 2685 if (!box) |
| 2686 return primaryDirection == LTR ? nextVisuallyDistinctCandida
te(deepPosition) : previousVisuallyDistinctCandidate(deepPosition); |
| 2687 layoutObject = &box->layoutObject(); |
| 2688 offset = box->caretLeftmostOffset(); |
| 2689 continue; |
| 2690 } |
| 2691 |
| 2692 offset = box->isLeftToRightDirection() ? layoutObject->nextOffset(of
fset) : layoutObject->previousOffset(offset); |
| 2693 |
| 2694 int caretMinOffset = box->caretMinOffset(); |
| 2695 int caretMaxOffset = box->caretMaxOffset(); |
| 2696 |
| 2697 if (offset > caretMinOffset && offset < caretMaxOffset) |
| 2698 break; |
| 2699 |
| 2700 if (box->isLeftToRightDirection() ? offset > caretMaxOffset : offset
< caretMinOffset) { |
| 2701 // Overshot to the right. |
| 2702 InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); |
| 2703 if (!nextBox) { |
| 2704 Position positionOnRight = primaryDirection == LTR ? nextVis
uallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPos
ition); |
| 2705 if (positionOnRight.isNull()) |
| 2706 return Position(); |
| 2707 |
| 2708 InlineBox* boxOnRight = computeInlineBoxPosition(positionOnR
ight, affinity, primaryDirection).inlineBox; |
| 2709 if (boxOnRight && boxOnRight->root() == box->root()) |
| 2710 return Position(); |
| 2711 return positionOnRight; |
| 2712 } |
| 2713 |
| 2714 // Reposition at the other logical position corresponding to our |
| 2715 // edge's visual position and go for another round. |
| 2716 box = nextBox; |
| 2717 layoutObject = &box->layoutObject(); |
| 2718 offset = nextBox->caretLeftmostOffset(); |
| 2719 continue; |
| 2720 } |
| 2721 |
| 2722 ASSERT(offset == box->caretRightmostOffset()); |
| 2723 |
| 2724 unsigned char level = box->bidiLevel(); |
| 2725 InlineBox* nextBox = box->nextLeafChild(); |
| 2726 |
| 2727 if (box->direction() == primaryDirection) { |
| 2728 if (!nextBox) { |
| 2729 InlineBox* logicalEnd = 0; |
| 2730 if (primaryDirection == LTR ? box->root().getLogicalEndBoxWi
thNode(logicalEnd) : box->root().getLogicalStartBoxWithNode(logicalEnd)) { |
| 2731 box = logicalEnd; |
| 2732 layoutObject = &box->layoutObject(); |
| 2733 offset = primaryDirection == LTR ? box->caretMaxOffset()
: box->caretMinOffset(); |
| 2734 } |
| 2735 break; |
| 2736 } |
| 2737 |
| 2738 if (nextBox->bidiLevel() >= level) |
| 2739 break; |
| 2740 |
| 2741 level = nextBox->bidiLevel(); |
| 2742 |
| 2743 InlineBox* prevBox = box; |
| 2744 do { |
| 2745 prevBox = prevBox->prevLeafChild(); |
| 2746 } while (prevBox && prevBox->bidiLevel() > level); |
| 2747 |
| 2748 // For example, abc FED 123 ^ CBA |
| 2749 if (prevBox && prevBox->bidiLevel() == level) |
| 2750 break; |
| 2751 |
| 2752 // For example, abc 123 ^ CBA or 123 ^ CBA abc |
| 2753 box = nextBox; |
| 2754 layoutObject = &box->layoutObject(); |
| 2755 offset = box->caretLeftmostOffset(); |
| 2756 if (box->direction() == primaryDirection) |
| 2757 break; |
| 2758 continue; |
| 2759 } |
| 2760 |
| 2761 while (nextBox && !nextBox->layoutObject().node()) |
| 2762 nextBox = nextBox->nextLeafChild(); |
| 2763 |
| 2764 if (nextBox) { |
| 2765 box = nextBox; |
| 2766 layoutObject = &box->layoutObject(); |
| 2767 offset = box->caretLeftmostOffset(); |
| 2768 |
| 2769 if (box->bidiLevel() > level) { |
| 2770 do { |
| 2771 nextBox = nextBox->nextLeafChild(); |
| 2772 } while (nextBox && nextBox->bidiLevel() > level); |
| 2773 |
| 2774 if (!nextBox || nextBox->bidiLevel() < level) |
| 2775 continue; |
| 2776 } |
| 2777 } else { |
| 2778 // Trailing edge of a secondary run. Set to the leading edge of |
| 2779 // the entire run. |
| 2780 while (true) { |
| 2781 while (InlineBox* prevBox = box->prevLeafChild()) { |
| 2782 if (prevBox->bidiLevel() < level) |
| 2783 break; |
| 2784 box = prevBox; |
| 2785 } |
| 2786 if (box->bidiLevel() == level) |
| 2787 break; |
| 2788 level = box->bidiLevel(); |
| 2789 while (InlineBox* nextBox = box->nextLeafChild()) { |
| 2790 if (nextBox->bidiLevel() < level) |
| 2791 break; |
| 2792 box = nextBox; |
| 2793 } |
| 2794 if (box->bidiLevel() == level) |
| 2795 break; |
| 2796 level = box->bidiLevel(); |
| 2797 } |
| 2798 layoutObject = &box->layoutObject(); |
| 2799 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->
caretMinOffset(); |
| 2800 } |
| 2801 break; |
| 2802 } |
| 2803 |
| 2804 p = Position::editingPositionOf(layoutObject->node(), offset); |
| 2805 |
| 2806 if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) !=
downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) |
| 2807 return p; |
| 2808 |
| 2809 ASSERT(p != deepPosition); |
| 2810 } |
| 2811 } |
| 2812 |
| 2813 VisiblePosition rightPositionOf(const VisiblePosition& visiblePosition) |
| 2814 { |
| 2815 const Position pos = rightVisuallyDistinctCandidate(visiblePosition); |
| 2816 // TODO(yosin) Why can't we move left from the last position in a tree? |
| 2817 if (pos.atStartOfTree() || pos.atEndOfTree()) |
| 2818 return VisiblePosition(); |
| 2819 |
| 2820 VisiblePosition right = createVisiblePosition(pos); |
| 2821 ASSERT(right.deepEquivalent() != visiblePosition.deepEquivalent()); |
| 2822 |
| 2823 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditi
ngBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBound
aryAtOrBefore(right, visiblePosition.deepEquivalent()); |
| 2824 } |
| 2825 |
2497 VisiblePosition nextPositionOf(const VisiblePosition& visiblePosition, EditingBo
undaryCrossingRule rule) | 2826 VisiblePosition nextPositionOf(const VisiblePosition& visiblePosition, EditingBo
undaryCrossingRule rule) |
2498 { | 2827 { |
2499 VisiblePosition next(nextVisuallyDistinctCandidate(visiblePosition.deepEquiv
alent()), visiblePosition.affinity()); | 2828 VisiblePosition next(nextVisuallyDistinctCandidate(visiblePosition.deepEquiv
alent()), visiblePosition.affinity()); |
2500 | 2829 |
2501 switch (rule) { | 2830 switch (rule) { |
2502 case CanCrossEditingBoundary: | 2831 case CanCrossEditingBoundary: |
2503 return next; | 2832 return next; |
2504 case CannotCrossEditingBoundary: | 2833 case CannotCrossEditingBoundary: |
2505 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalen
t()); | 2834 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalen
t()); |
2506 case CanSkipOverEditingBoundary: | 2835 case CanSkipOverEditingBoundary: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2560 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale
nt()); | 2889 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale
nt()); |
2561 case CanSkipOverEditingBoundary: | 2890 case CanSkipOverEditingBoundary: |
2562 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent
()); | 2891 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent
()); |
2563 } | 2892 } |
2564 | 2893 |
2565 ASSERT_NOT_REACHED(); | 2894 ASSERT_NOT_REACHED(); |
2566 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent()
); | 2895 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent()
); |
2567 } | 2896 } |
2568 | 2897 |
2569 } // namespace blink | 2898 } // namespace blink |
OLD | NEW |