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

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

Issue 1303173002: Move computeInlineBoxPosition() to VisibleUnits.{cpp,h} from Position.{cpp,h} and VisiblePosition.h (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 2015-08-21T13:45:14 Created 5 years, 4 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/Position.h ('k') | Source/core/editing/RenderedPosition.cpp » ('j') | 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, 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
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 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 { 593 {
594 return inRenderedTextAlgorithm<EditingStrategy>(position); 594 return inRenderedTextAlgorithm<EditingStrategy>(position);
595 } 595 }
596 596
597 bool inRenderedText(const PositionInComposedTree& position) 597 bool inRenderedText(const PositionInComposedTree& position)
598 { 598 {
599 return inRenderedTextAlgorithm<EditingInComposedTreeStrategy>(position); 599 return inRenderedTextAlgorithm<EditingInComposedTreeStrategy>(position);
600 } 600 }
601 601
602 template <typename Strategy> 602 template <typename Strategy>
603 static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorit hm<Strategy>& position, TextAffinity affinity)
604 {
605 return computeInlineBoxPositionAlgorithm<Strategy>(position, affinity, prima ryDirectionOf(*position.anchorNode()));
606 }
607
608 InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinit y affinity)
609 {
610 return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity );
611 }
612
613 InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& positio n, TextAffinity affinity)
614 {
615 return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(posi tion, affinity);
616 }
617
618 static bool isNonTextLeafChild(LayoutObject* object)
619 {
620 if (object->slowFirstChild())
621 return false;
622 if (object->isText())
623 return false;
624 return true;
625 }
626
627 static InlineTextBox* searchAheadForBetterMatch(LayoutObject* layoutObject)
628 {
629 LayoutBlock* container = layoutObject->containingBlock();
630 for (LayoutObject* next = layoutObject->nextInPreOrder(container); next; nex t = next->nextInPreOrder(container)) {
631 if (next->isLayoutBlock())
632 return 0;
633 if (next->isBR())
634 return 0;
635 if (isNonTextLeafChild(next))
636 return 0;
637 if (next->isText()) {
638 InlineTextBox* match = 0;
639 int minOffset = INT_MAX;
640 for (InlineTextBox* box = toLayoutText(next)->firstTextBox(); box; b ox = box->nextTextBox()) {
641 int caretMinOffset = box->caretMinOffset();
642 if (caretMinOffset < minOffset) {
643 match = box;
644 minOffset = caretMinOffset;
645 }
646 }
647 if (match)
648 return match;
649 }
650 }
651 return 0;
652 }
653
654 template <typename Strategy>
655 PositionAlgorithm<Strategy> downstreamIgnoringEditingBoundaries(PositionAlgorith m<Strategy> position)
656 {
657 PositionAlgorithm<Strategy> lastPosition;
658 while (position != lastPosition) {
659 lastPosition = position;
660 position = position.downstream(CanCrossEditingBoundary);
661 }
662 return position;
663 }
664
665 template <typename Strategy>
666 PositionAlgorithm<Strategy> upstreamIgnoringEditingBoundaries(PositionAlgorithm< Strategy> position)
667 {
668 PositionAlgorithm<Strategy> lastPosition;
669 while (position != lastPosition) {
670 lastPosition = position;
671 position = position.upstream(CanCrossEditingBoundary);
672 }
673 return position;
674 }
675
676 template <typename Strategy>
677 static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorit hm<Strategy>& position, TextAffinity affinity, TextDirection primaryDirection)
678 {
679 InlineBox* inlineBox = nullptr;
680 int caretOffset = position.computeEditingOffset();
681 Node* const anchorNode = position.anchorNode();
682 LayoutObject* layoutObject = anchorNode->isShadowRoot() ? toShadowRoot(ancho rNode)->host()->layoutObject() : anchorNode->layoutObject();
683
684 if (!layoutObject->isText()) {
685 inlineBox = 0;
686 if (canHaveChildrenForEditing(anchorNode) && layoutObject->isLayoutBlock Flow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) {
687 // Try a visually equivalent position with possibly opposite
688 // editability. This helps in case |this| is in an editable block
689 // but surrounded by non-editable positions. It acts to negate the
690 // logic at the beginning of LayoutObject::createVisiblePosition().
691 PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBo undaries(position);
692 if (equivalent == position) {
693 equivalent = upstreamIgnoringEditingBoundaries(position);
694 if (equivalent == position || downstreamIgnoringEditingBoundarie s(equivalent) == position)
695 return InlineBoxPosition(inlineBox, caretOffset);
696 }
697
698 return computeInlineBoxPosition(equivalent, TextAffinity::Upstream, primaryDirection);
699 }
700 if (layoutObject->isBox()) {
701 inlineBox = toLayoutBox(layoutObject)->inlineBoxWrapper();
702 if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && care tOffset < inlineBox->caretMaxOffset()))
703 return InlineBoxPosition(inlineBox, caretOffset);
704 }
705 } else {
706 LayoutText* textLayoutObject = toLayoutText(layoutObject);
707
708 InlineTextBox* box;
709 InlineTextBox* candidate = 0;
710
711 for (box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox ()) {
712 int caretMinOffset = box->caretMinOffset();
713 int caretMaxOffset = box->caretMaxOffset();
714
715 if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
716 continue;
717
718 if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset)
719 return InlineBoxPosition(box, caretOffset);
720
721 if (((caretOffset == caretMaxOffset) ^ (affinity == TextAffinity::Do wnstream))
722 || ((caretOffset == caretMinOffset) ^ (affinity == TextAffinity: :Upstream))
723 || (caretOffset == caretMaxOffset && box->nextLeafChild() && box ->nextLeafChild()->isLineBreak()))
724 break;
725
726 candidate = box;
727 }
728 if (candidate && candidate == textLayoutObject->lastTextBox() && affinit y == TextAffinity::Downstream) {
729 box = searchAheadForBetterMatch(textLayoutObject);
730 if (box)
731 caretOffset = box->caretMinOffset();
732 }
733 inlineBox = box ? box : candidate;
734 }
735
736 if (!inlineBox)
737 return InlineBoxPosition(inlineBox, caretOffset);
738
739 unsigned char level = inlineBox->bidiLevel();
740
741 if (inlineBox->direction() == primaryDirection) {
742 if (caretOffset == inlineBox->caretRightmostOffset()) {
743 InlineBox* nextBox = inlineBox->nextLeafChild();
744 if (!nextBox || nextBox->bidiLevel() >= level)
745 return InlineBoxPosition(inlineBox, caretOffset);
746
747 level = nextBox->bidiLevel();
748 InlineBox* prevBox = inlineBox;
749 do {
750 prevBox = prevBox->prevLeafChild();
751 } while (prevBox && prevBox->bidiLevel() > level);
752
753 // For example, abc FED 123 ^ CBA
754 if (prevBox && prevBox->bidiLevel() == level)
755 return InlineBoxPosition(inlineBox, caretOffset);
756
757 // For example, abc 123 ^ CBA
758 while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
759 if (nextBox->bidiLevel() < level)
760 break;
761 inlineBox = nextBox;
762 }
763 return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset( ));
764 }
765
766 InlineBox* prevBox = inlineBox->prevLeafChild();
767 if (!prevBox || prevBox->bidiLevel() >= level)
768 return InlineBoxPosition(inlineBox, caretOffset);
769
770 level = prevBox->bidiLevel();
771 InlineBox* nextBox = inlineBox;
772 do {
773 nextBox = nextBox->nextLeafChild();
774 } while (nextBox && nextBox->bidiLevel() > level);
775
776 if (nextBox && nextBox->bidiLevel() == level)
777 return InlineBoxPosition(inlineBox, caretOffset);
778
779 while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
780 if (prevBox->bidiLevel() < level)
781 break;
782 inlineBox = prevBox;
783 }
784 return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
785 }
786
787 if (caretOffset == inlineBox->caretLeftmostOffset()) {
788 InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
789 if (!prevBox || prevBox->bidiLevel() < level) {
790 // Left edge of a secondary run. Set to the right edge of the entire
791 // run.
792 while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBrea k()) {
793 if (nextBox->bidiLevel() < level)
794 break;
795 inlineBox = nextBox;
796 }
797 return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset( ));
798 }
799
800 if (prevBox->bidiLevel() > level) {
801 // Right edge of a "tertiary" run. Set to the left edge of that run.
802 while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLine Break()) {
803 if (tertiaryBox->bidiLevel() <= level)
804 break;
805 inlineBox = tertiaryBox;
806 }
807 return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset() );
808 }
809 return InlineBoxPosition(inlineBox, caretOffset);
810 }
811
812 if (layoutObject && layoutObject->style()->unicodeBidi() == Plaintext) {
813 if (inlineBox->bidiLevel() < level)
814 return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset() );
815 return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
816 }
817
818 InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
819 if (!nextBox || nextBox->bidiLevel() < level) {
820 // Right edge of a secondary run. Set to the left edge of the entire
821 // run.
822 while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
823 if (prevBox->bidiLevel() < level)
824 break;
825 inlineBox = prevBox;
826 }
827 return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
828 }
829
830 if (nextBox->bidiLevel() <= level)
831 return InlineBoxPosition(inlineBox, caretOffset);
832
833 // Left edge of a "tertiary" run. Set to the right edge of that run.
834 while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
835 if (tertiaryBox->bidiLevel() <= level)
836 break;
837 inlineBox = tertiaryBox;
838 }
839 return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
840 }
841
842 InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinit y affinity, TextDirection primaryDirection)
843 {
844 return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity , primaryDirection);
845 }
846
847 InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& positio n, TextAffinity affinity, TextDirection primaryDirection)
848 {
849 return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(posi tion, affinity, primaryDirection);
850 }
851
852 template <typename Strategy>
853 void PositionAlgorithm<Strategy>::debugPosition(const char* msg) const 603 void PositionAlgorithm<Strategy>::debugPosition(const char* msg) const
854 { 604 {
855 static const char* const anchorTypes[] = { 605 static const char* const anchorTypes[] = {
856 "OffsetInAnchor", 606 "OffsetInAnchor",
857 "BeforeAnchor", 607 "BeforeAnchor",
858 "AfterAnchor", 608 "AfterAnchor",
859 "BeforeChildren", 609 "BeforeChildren",
860 "AfterChildren", 610 "AfterChildren",
861 "Invalid", 611 "Invalid",
862 }; 612 };
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 775
1026 void showTree(const blink::Position* pos) 776 void showTree(const blink::Position* pos)
1027 { 777 {
1028 if (pos) 778 if (pos)
1029 pos->showTreeForThis(); 779 pos->showTreeForThis();
1030 else 780 else
1031 fprintf(stderr, "Cannot showTree for (nil)\n"); 781 fprintf(stderr, "Cannot showTree for (nil)\n");
1032 } 782 }
1033 783
1034 #endif 784 #endif
OLDNEW
« no previous file with comments | « Source/core/editing/Position.h ('k') | Source/core/editing/RenderedPosition.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698