Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: Source/core/editing/VisibleUnits.cpp

Issue 1310953005: Move {left,right}PositionOf() for VisiblePosition to VisibleUnits.cpp (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 2015-09-01T21:47:52 Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/editing/VisibleUnits.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « Source/core/editing/VisibleUnits.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698