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

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

Issue 20681004: Make first-letter style to work with editing Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: 2013-08-08T13:29:08 Created 7 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/dom/Position.h ('k') | Source/core/dom/PositionIterator.h » ('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 24 matching lines...) Expand all
35 #include "core/editing/VisiblePosition.h" 35 #include "core/editing/VisiblePosition.h"
36 #include "core/editing/VisibleUnits.h" 36 #include "core/editing/VisibleUnits.h"
37 #include "core/editing/htmlediting.h" 37 #include "core/editing/htmlediting.h"
38 #include "core/html/HTMLHtmlElement.h" 38 #include "core/html/HTMLHtmlElement.h"
39 #include "core/html/HTMLTableElement.h" 39 #include "core/html/HTMLTableElement.h"
40 #include "core/platform/Logging.h" 40 #include "core/platform/Logging.h"
41 #include "core/rendering/InlineIterator.h" 41 #include "core/rendering/InlineIterator.h"
42 #include "core/rendering/InlineTextBox.h" 42 #include "core/rendering/InlineTextBox.h"
43 #include "core/rendering/RenderBlock.h" 43 #include "core/rendering/RenderBlock.h"
44 #include "core/rendering/RenderInline.h" 44 #include "core/rendering/RenderInline.h"
45 #include "core/rendering/RenderText.h" 45 #include "core/rendering/RenderTextFragment.h"
46 #include "wtf/text/CString.h" 46 #include "wtf/text/CString.h"
47 #include "wtf/unicode/CharacterNames.h" 47 #include "wtf/unicode/CharacterNames.h"
48 48
49 namespace WebCore { 49 namespace WebCore {
50 50
51 using namespace HTMLNames; 51 using namespace HTMLNames;
52 52
53 static Node* nextRenderedEditable(Node* node) 53 static Node* nextRenderedEditable(Node* node)
54 { 54 {
55 while ((node = node->nextLeafNode())) { 55 while ((node = node->nextLeafNode())) {
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 return !findParent(deprecatedNode()) && m_offset <= 0; 450 return !findParent(deprecatedNode()) && m_offset <= 0;
451 } 451 }
452 452
453 bool Position::atEndOfTree() const 453 bool Position::atEndOfTree() const
454 { 454 {
455 if (isNull()) 455 if (isNull())
456 return true; 456 return true;
457 return !findParent(deprecatedNode()) && m_offset >= lastOffsetForEditing(dep recatedNode()); 457 return !findParent(deprecatedNode()) && m_offset >= lastOffsetForEditing(dep recatedNode());
458 } 458 }
459 459
460 RenderObject* Position::renderer() const
461 {
462 if (!m_anchorNode)
463 return 0;
464 RenderObject* renderer = m_anchorNode->renderer();
eseidel 2013/09/09 20:28:27 Positions can be relative to anchor nodes other th
yosin_UTC9 2013/09/20 09:30:26 This function is replacement of Position.anchorNod
465 if (!renderer || !renderer->isText() || !toRenderText(renderer)->isTextFragm ent())
466 return renderer;
467 if (m_offset >= static_cast<int>(toRenderTextFragment(renderer)->textStartOf fset()))
468 return renderer;
469 return toRenderTextFragment(renderer)->firstRenderTextInFirstLetter();
470 }
471
472 int Position::offsetInRenderer() const
473 {
474 switch (m_isLegacyEditingPosition ? PositionIsOffsetInAnchor : m_anchorType) {
475 case PositionIsBeforeChildren:
476 case PositionIsBeforeAnchor:
eseidel 2013/09/09 20:28:27 Wouldn't this possibly have a different renderer d
yosin_UTC9 2013/09/20 09:30:26 This function does as same as deprecatedEditingOff
477 case PositionIsOffsetInAnchor: {
478 RenderObject* renderer = this->renderer();
479 if (!renderer || !renderer->isText())
480 return m_offset;
481 return m_offset - toRenderText(renderer)->textStartOffset();
482 }
483 case PositionIsAfterChildren:
484 case PositionIsAfterAnchor:
485 return offsetForPositionAfterAnchor();
486 }
487 ASSERT_NOT_REACHED();
488 return m_offset;
489 }
490
460 int Position::renderedOffset() const 491 int Position::renderedOffset() const
461 { 492 {
462 if (!deprecatedNode()->isTextNode()) 493 RenderObject* renderer = this->renderer();
494 if (!renderer || !renderer->isText())
463 return m_offset; 495 return m_offset;
464 496
465 if (!deprecatedNode()->renderer()) 497 RenderText* textRenderer = toRenderText(renderer);
466 return m_offset; 498 int result = textRenderer->textStartOffset();
467
468 int result = 0;
469 RenderText* textRenderer = toRenderText(deprecatedNode()->renderer());
470 for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->next TextBox()) { 499 for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->next TextBox()) {
471 int start = box->start(); 500 int start = box->start();
472 int end = box->start() + box->len(); 501 int end = box->start() + box->len();
473 if (m_offset < start) 502 if (m_offset < start)
474 return result; 503 return result;
475 if (m_offset <= end) { 504 if (m_offset <= end) {
476 result += m_offset - start; 505 result += m_offset - start;
477 return result; 506 return result;
478 } 507 }
479 result += box->len(); 508 result += box->len();
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 Node* startNode = deprecatedNode(); 618 Node* startNode = deprecatedNode();
590 if (!startNode) 619 if (!startNode)
591 return Position(); 620 return Position();
592 621
593 // iterate backward from there, looking for a qualified position 622 // iterate backward from there, looking for a qualified position
594 Node* boundary = enclosingVisualBoundary(startNode); 623 Node* boundary = enclosingVisualBoundary(startNode);
595 // FIXME: PositionIterator should respect Before and After positions. 624 // FIXME: PositionIterator should respect Before and After positions.
596 PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? creat eLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this; 625 PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? creat eLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
597 PositionIterator currentPos = lastVisible; 626 PositionIterator currentPos = lastVisible;
598 bool startEditable = startNode->rendererIsEditable(); 627 bool startEditable = startNode->rendererIsEditable();
628 RenderObject* startRenderer = renderer();
599 Node* lastNode = startNode; 629 Node* lastNode = startNode;
630 RenderObject* lastRenderer = startRenderer;
600 bool boundaryCrossed = false; 631 bool boundaryCrossed = false;
601 for (; !currentPos.atStart(); currentPos.decrement()) { 632 for (; !currentPos.atStart(); currentPos.decrement()) {
602 Node* currentNode = currentPos.node(); 633 Node* currentNode = currentPos.node();
634 RenderObject* currentRenderer = currentPos.renderer();
603 635
604 // Don't check for an editability change if we haven't moved to a differ ent node, 636 // Don't check for an editability change if we haven't moved to a differ ent node,
605 // to avoid the expense of computing rendererIsEditable(). 637 // to avoid the expense of computing rendererIsEditable().
606 if (currentNode != lastNode) { 638 if (currentRenderer != lastRenderer) {
607 // Don't change editability. 639 // Don't change editability.
608 bool currentEditable = currentNode->rendererIsEditable(); 640 bool currentEditable = currentNode->rendererIsEditable();
609 if (startEditable != currentEditable) { 641 if (startEditable != currentEditable) {
610 if (rule == CannotCrossEditingBoundary) 642 if (rule == CannotCrossEditingBoundary)
611 break; 643 break;
612 boundaryCrossed = true; 644 boundaryCrossed = true;
613 } 645 }
614 lastNode = currentNode; 646 lastNode = currentNode;
647 lastRenderer = currentPos.renderer();
615 } 648 }
616 649
617 // If we've moved to a position that is visually distinct, return the la st saved position. There 650 // If we've moved to a position that is visually distinct, return the la st saved position. There
618 // is code below that terminates early if we're *about* to move to a vis ually distinct position. 651 // is code below that terminates early if we're *about* to move to a vis ually distinct position.
619 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode ! = boundary) 652 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode ! = boundary)
620 return lastVisible; 653 return lastVisible;
621 654
622 // skip position in unrendered or invisible node 655 // skip position in unrendered or invisible node
623 RenderObject* renderer = currentNode->renderer(); 656 if (!currentRenderer || currentRenderer->style()->visibility() != VISIBL E)
624 if (!renderer || renderer->style()->visibility() != VISIBLE)
625 continue; 657 continue;
626 658
627 if (rule == CanCrossEditingBoundary && boundaryCrossed) { 659 if (rule == CanCrossEditingBoundary && boundaryCrossed) {
628 lastVisible = currentPos; 660 lastVisible = currentPos;
629 break; 661 break;
630 } 662 }
631 663
632 // track last visible streamer position 664 // track last visible streamer position
633 if (isStreamer(currentPos)) 665 if (isStreamer(currentPos))
634 lastVisible = currentPos; 666 lastVisible = currentPos;
635 667
636 // Don't move past a position that is visually distinct. We could rely on code above to terminate and 668 // Don't move past a position that is visually distinct. We could rely on code above to terminate and
637 // return lastVisible on the next iteration, but we terminate early to a void doing a nodeIndex() call. 669 // return lastVisible on the next iteration, but we terminate early to a void doing a nodeIndex() call.
638 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.at StartOfNode()) 670 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.at StartOfNode())
639 return lastVisible; 671 return lastVisible;
640 672
641 // Return position after tables and nodes which have content that can be ignored. 673 // Return position after tables and nodes which have content that can be ignored.
642 if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) { 674 if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
643 if (currentPos.atEndOfNode()) 675 if (currentPos.atEndOfNode())
644 return positionAfterNode(currentNode); 676 return positionAfterNode(currentNode);
645 continue; 677 continue;
646 } 678 }
647 679
648 // return current position if it is in rendered text 680 // return current position if it is in rendered text
649 if (renderer->isText() && toRenderText(renderer)->firstTextBox()) { 681 if (currentRenderer->isText() && toRenderText(currentRenderer)->firstTex tBox()) {
650 if (currentNode != startNode) { 682 RenderText* textRenderer = toRenderText(currentRenderer);
651 // This assertion fires in layout tests in the case-transform.ht ml test because 683 if (currentRenderer != startRenderer)
652 // of a mix-up between offsets in the text in the DOM tree with text in the 684 return createLegacyEditingPosition(currentNode, textRenderer->ca retMaxOffset() + textRenderer->textStartOffset());
653 // render tree which can have a different length due to case tra nsformation.
654 // Until we resolve that, disable this so we can run the layout tests!
655 //ASSERT(currentOffset >= renderer->caretMaxOffset());
656 return createLegacyEditingPosition(currentNode, renderer->caretM axOffset());
657 }
658 685
659 unsigned textOffset = currentPos.offsetInLeafNode(); 686 unsigned textOffset = currentPos.offsetInLeafNode() - textRenderer-> textStartOffset();
660 RenderText* textRenderer = toRenderText(renderer);
661 InlineTextBox* lastTextBox = textRenderer->lastTextBox(); 687 InlineTextBox* lastTextBox = textRenderer->lastTextBox();
662 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = b ox->nextTextBox()) { 688 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = b ox->nextTextBox()) {
663 if (textOffset <= box->start() + box->len()) { 689 if (textOffset <= box->start() + box->len()) {
664 if (textOffset > box->start()) 690 if (textOffset > box->start())
665 return currentPos; 691 return currentPos;
666 continue; 692 continue;
667 } 693 }
668 694
669 if (box == lastTextBox || textOffset != box->start() + box->len( ) + 1) 695 if (box == lastTextBox || textOffset != box->start() + box->len( ) + 1)
670 continue; 696 continue;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 Node* startNode = deprecatedNode(); 738 Node* startNode = deprecatedNode();
713 if (!startNode) 739 if (!startNode)
714 return Position(); 740 return Position();
715 741
716 // iterate forward from there, looking for a qualified position 742 // iterate forward from there, looking for a qualified position
717 Node* boundary = enclosingVisualBoundary(startNode); 743 Node* boundary = enclosingVisualBoundary(startNode);
718 // FIXME: PositionIterator should respect Before and After positions. 744 // FIXME: PositionIterator should respect Before and After positions.
719 PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? creat eLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this; 745 PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? creat eLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
720 PositionIterator currentPos = lastVisible; 746 PositionIterator currentPos = lastVisible;
721 bool startEditable = startNode->rendererIsEditable(); 747 bool startEditable = startNode->rendererIsEditable();
748 RenderObject* startRenderer = renderer();
722 Node* lastNode = startNode; 749 Node* lastNode = startNode;
750 RenderObject* lastRenderer = startRenderer;
723 bool boundaryCrossed = false; 751 bool boundaryCrossed = false;
724 for (; !currentPos.atEnd(); currentPos.increment()) { 752 for (; !currentPos.atEnd(); currentPos.increment()) {
725 Node* currentNode = currentPos.node(); 753 Node* currentNode = currentPos.node();
754 RenderObject* currentRenderer = currentPos.renderer();
726 755
727 // Don't check for an editability change if we haven't moved to a differ ent node, 756 // Don't check for an editability change if we haven't moved to a differ ent node,
728 // to avoid the expense of computing rendererIsEditable(). 757 // to avoid the expense of computing rendererIsEditable().
729 if (currentNode != lastNode) { 758 if (currentRenderer!= lastRenderer) {
730 // Don't change editability. 759 // Don't change editability.
731 bool currentEditable = currentNode->rendererIsEditable(); 760 bool currentEditable = currentNode->rendererIsEditable();
732 if (startEditable != currentEditable) { 761 if (startEditable != currentEditable) {
733 if (rule == CannotCrossEditingBoundary) 762 if (rule == CannotCrossEditingBoundary)
734 break; 763 break;
735 boundaryCrossed = true; 764 boundaryCrossed = true;
736 } 765 }
737 766
738 lastNode = currentNode; 767 lastNode = currentNode;
768 lastRenderer = currentRenderer;
739 } 769 }
740 770
741 // stop before going above the body, up into the head 771 // stop before going above the body, up into the head
742 // return the last visible streamer position 772 // return the last visible streamer position
743 if (currentNode->hasTagName(bodyTag) && currentPos.atEndOfNode()) 773 if (currentNode->hasTagName(bodyTag) && currentPos.atEndOfNode())
744 break; 774 break;
745 775
746 // Do not move to a visually distinct position. 776 // Do not move to a visually distinct position.
747 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode ! = boundary) 777 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode ! = boundary)
748 return lastVisible; 778 return lastVisible;
749 // Do not move past a visually disinct position. 779 // Do not move past a visually disinct position.
750 // Note: The first position after the last in a node whose ends are visu ally distinct 780 // Note: The first position after the last in a node whose ends are visu ally distinct
751 // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1]. 781 // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1].
752 if (boundary && boundary->parentNode() == currentNode) 782 if (boundary && boundary->parentNode() == currentNode)
753 return lastVisible; 783 return lastVisible;
754 784
755 // skip position in unrendered or invisible node 785 // skip position in unrendered or invisible node
756 RenderObject* renderer = currentNode->renderer(); 786 if (!currentRenderer || currentRenderer->style()->visibility() != VISIBL E)
757 if (!renderer || renderer->style()->visibility() != VISIBLE)
758 continue; 787 continue;
759 788
760 if (rule == CanCrossEditingBoundary && boundaryCrossed) { 789 if (rule == CanCrossEditingBoundary && boundaryCrossed) {
761 lastVisible = currentPos; 790 lastVisible = currentPos;
762 break; 791 break;
763 } 792 }
764 793
765 // track last visible streamer position 794 // track last visible streamer position
766 if (isStreamer(currentPos)) 795 if (isStreamer(currentPos))
767 lastVisible = currentPos; 796 lastVisible = currentPos;
768 797
769 // Return position before tables and nodes which have content that can b e ignored. 798 // Return position before tables and nodes which have content that can b e ignored.
770 if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) { 799 if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
771 if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset()) 800 if (currentPos.offsetInLeafNode() <= currentRenderer->caretMinOffset ())
772 return createLegacyEditingPosition(currentNode, renderer->caretM inOffset()); 801 return createLegacyEditingPosition(currentNode, currentRenderer- >caretMinOffset());
773 continue; 802 continue;
774 } 803 }
775 804
776 // return current position if it is in rendered text 805 // return current position if it is in rendered text
777 if (renderer->isText() && toRenderText(renderer)->firstTextBox()) { 806 if (currentRenderer->isText() && toRenderText(currentRenderer)->firstTex tBox()) {
778 if (currentNode != startNode) { 807 RenderText* textRenderer = toRenderText(currentRenderer);
779 ASSERT(currentPos.atStartOfNode()); 808 if (currentRenderer != startRenderer)
780 return createLegacyEditingPosition(currentNode, renderer->caretM inOffset()); 809 return createLegacyEditingPosition(currentNode, textRenderer->ca retMinOffset() + textRenderer->textStartOffset());
781 }
782 810
783 unsigned textOffset = currentPos.offsetInLeafNode(); 811 unsigned textOffset = currentPos.offsetInLeafNode() - textRenderer-> textStartOffset();
784 RenderText* textRenderer = toRenderText(renderer);
785 InlineTextBox* lastTextBox = textRenderer->lastTextBox(); 812 InlineTextBox* lastTextBox = textRenderer->lastTextBox();
786 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = b ox->nextTextBox()) { 813 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = b ox->nextTextBox()) {
787 if (textOffset <= box->end()) { 814 if (textOffset <= box->end()) {
788 if (textOffset >= box->start()) 815 if (textOffset >= box->start())
789 return currentPos; 816 return currentPos;
790 continue; 817 continue;
791 } 818 }
792 819
793 if (box == lastTextBox || textOffset != box->start() + box->len( )) 820 if (box == lastTextBox || textOffset != box->start() + box->len( ))
794 continue; 821 continue;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextIn PreOrder()) 862 for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextIn PreOrder())
836 if (o->nonPseudoNode()) { 863 if (o->nonPseudoNode()) {
837 if ((o->isText() && boundingBoxLogicalHeight(o, toRenderText(o)->lin esBoundingBox())) 864 if ((o->isText() && boundingBoxLogicalHeight(o, toRenderText(o)->lin esBoundingBox()))
838 || (o->isBox() && toRenderBox(o)->pixelSnappedLogicalHeight()) 865 || (o->isBox() && toRenderBox(o)->pixelSnappedLogicalHeight())
839 || (o->isRenderInline() && isEmptyInline(o) && boundingBoxLogica lHeight(o, toRenderInline(o)->linesBoundingBox()))) 866 || (o->isRenderInline() && isEmptyInline(o) && boundingBoxLogica lHeight(o, toRenderInline(o)->linesBoundingBox())))
840 return true; 867 return true;
841 } 868 }
842 return false; 869 return false;
843 } 870 }
844 871
872 // FIXME: Caller of nodeIsUserSelectNode() should consider first letter and
873 // remaining text have different user-select CSS property.
845 bool Position::nodeIsUserSelectNone(Node* node) 874 bool Position::nodeIsUserSelectNone(Node* node)
846 { 875 {
847 return node && node->renderer() && node->renderer()->style()->userSelect() = = SELECT_NONE && node->renderer()->style()->userModify() == READ_ONLY; 876 return node && rendererIsUserSelectNone(node->renderer());
877 }
878
879 bool Position::rendererIsUserSelectNone(RenderObject* renderer)
880 {
881 return renderer && renderer->style()->userSelect() == SELECT_NONE && rendere r->style()->userModify() == READ_ONLY;
848 } 882 }
849 883
850 ContainerNode* Position::findParent(const Node* node) 884 ContainerNode* Position::findParent(const Node* node)
851 { 885 {
852 return node->parentNode(); 886 return node->parentNode();
853 } 887 }
854 888
855 #if ENABLE(USERSELECT_ALL) 889 #if ENABLE(USERSELECT_ALL)
856 bool Position::nodeIsUserSelectAll(const Node* node) 890 bool Position::nodeIsUserSelectAll(const Node* node)
857 { 891 {
(...skipping 18 matching lines...) Expand all
876 break; 910 break;
877 candidateRoot = parent; 911 candidateRoot = parent;
878 parent = candidateRoot->parentNode(); 912 parent = candidateRoot->parentNode();
879 } 913 }
880 return candidateRoot; 914 return candidateRoot;
881 } 915 }
882 #endif 916 #endif
883 917
884 bool Position::isCandidate() const 918 bool Position::isCandidate() const
885 { 919 {
886 if (isNull()) 920 RenderObject* renderer = this->renderer();
887 return false;
888
889 RenderObject* renderer = deprecatedNode()->renderer();
890 if (!renderer) 921 if (!renderer)
891 return false; 922 return false;
892 923
893 if (renderer->style()->visibility() != VISIBLE) 924 if (renderer->style()->visibility() != VISIBLE)
894 return false; 925 return false;
895 926
896 if (renderer->isBR()) 927 if (renderer->isBR())
897 // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor , but for now we still need to support legacy positions. 928 // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor , but for now we still need to support legacy positions.
898 return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUser SelectNone(deprecatedNode()->parentNode()); 929 return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUser SelectNone(deprecatedNode()->parentNode());
899 930
900 if (renderer->isText()) 931 if (renderer->isText())
901 return !nodeIsUserSelectNone(deprecatedNode()) && inRenderedText(); 932 return !rendererIsUserSelectNone(renderer) && inRenderedText();
902 933
903 if (isTableElement(deprecatedNode()) || editingIgnoresContent(deprecatedNode ())) 934 if (isTableElement(deprecatedNode()) || editingIgnoresContent(deprecatedNode ()))
904 return (atFirstEditingPositionForNode() || atLastEditingPositionForNode( )) && !nodeIsUserSelectNone(deprecatedNode()->parentNode()); 935 return (atFirstEditingPositionForNode() || atLastEditingPositionForNode( )) && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
905 936
906 if (isHTMLHtmlElement(m_anchorNode.get())) 937 if (isHTMLHtmlElement(m_anchorNode.get()))
907 return false; 938 return false;
908 939
909 if (renderer->isBlockFlow()) { 940 if (renderer->isBlockFlow()) {
910 if (toRenderBlock(renderer)->logicalHeight() || m_anchorNode->hasTagName (bodyTag)) { 941 if (toRenderBlock(renderer)->logicalHeight() || m_anchorNode->hasTagName (bodyTag)) {
911 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer )) 942 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer ))
912 return atFirstEditingPositionForNode() && !Position::nodeIsUserS electNone(deprecatedNode()); 943 return atFirstEditingPositionForNode() && !Position::nodeIsUserS electNone(deprecatedNode());
913 return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSe lectNone(deprecatedNode()) && atEditingBoundary(); 944 return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSe lectNone(deprecatedNode()) && atEditingBoundary();
914 } 945 }
915 } else 946 } else
916 return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelect None(deprecatedNode()) && atEditingBoundary(); 947 return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelect None(deprecatedNode()) && atEditingBoundary();
917 948
918 return false; 949 return false;
919 } 950 }
920 951
921 bool Position::inRenderedText() const 952 bool Position::inRenderedText() const
922 { 953 {
923 if (isNull() || !deprecatedNode()->isTextNode()) 954 RenderObject* renderer = this->renderer();
955 if (!renderer || !renderer->isText())
924 return false; 956 return false;
925 957
926 RenderObject* renderer = deprecatedNode()->renderer(); 958 RenderText* textRenderer = toRenderText(renderer);
927 if (!renderer) 959 int offset = m_offset - textRenderer->textStartOffset();
928 return false;
929
930 RenderText *textRenderer = toRenderText(renderer);
931 for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->next TextBox()) { 960 for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->next TextBox()) {
932 if (m_offset < static_cast<int>(box->start()) && !textRenderer->contains ReversedText()) { 961 if (offset < static_cast<int>(box->start()) && !textRenderer->containsRe versedText()) {
933 // The offset we're looking for is before this node 962 // The offset we're looking for is before this node
934 // this means the offset must be in content that is 963 // this means the offset must be in content that is
935 // not rendered. Return false. 964 // not rendered. Return false.
936 return false; 965 return false;
937 } 966 }
938 if (box->containsCaretOffset(m_offset)) 967 if (box->containsCaretOffset(offset)) {
939 // Return false for offsets inside composed characters. 968 // Return false for offsets inside composed characters.
940 return m_offset == 0 || m_offset == textRenderer->nextOffset(textRen derer->previousOffset(m_offset)); 969 return !offset || offset == textRenderer->nextOffset(textRenderer->p reviousOffset(offset));
970 }
941 } 971 }
942 972
943 return false; 973 return false;
944 } 974 }
945 975
946 bool Position::isRenderedCharacter() const 976 bool Position::isRenderedCharacter() const
947 { 977 {
948 if (isNull() || !deprecatedNode()->isTextNode()) 978 RenderObject* renderer = this->renderer();
949 return false; 979 if (!renderer || !renderer->isText())
950
951 RenderObject* renderer = deprecatedNode()->renderer();
952 if (!renderer)
953 return false; 980 return false;
954 981
955 RenderText* textRenderer = toRenderText(renderer); 982 RenderText* textRenderer = toRenderText(renderer);
983 int offset = m_offset - textRenderer->textStartOffset();
956 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->next TextBox()) { 984 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->next TextBox()) {
957 if (m_offset < static_cast<int>(box->start()) && !textRenderer->contains ReversedText()) { 985 if (offset < static_cast<int>(box->start()) && !textRenderer->containsRe versedText()) {
958 // The offset we're looking for is before this node 986 // The offset we're looking for is before this node
959 // this means the offset must be in content that is 987 // this means the offset must be in content that is
960 // not rendered. Return false. 988 // not rendered. Return false.
961 return false; 989 return false;
962 } 990 }
963 if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast <int>(box->start() + box->len())) 991 if (offset >= static_cast<int>(box->start()) && offset < static_cast<int >(box->start() + box->len()))
964 return true; 992 return true;
965 } 993 }
966 994
967 return false; 995 return false;
968 } 996 }
969 997
970 bool Position::rendersInDifferentPosition(const Position &pos) const 998 bool Position::rendersInDifferentPosition(const Position &pos) const
971 { 999 {
972 if (isNull() || pos.isNull()) 1000 RenderObject* renderer = this->renderer();
973 return false;
974
975 RenderObject* renderer = deprecatedNode()->renderer();
976 if (!renderer) 1001 if (!renderer)
977 return false; 1002 return false;
978 1003
979 RenderObject* posRenderer = pos.deprecatedNode()->renderer(); 1004 RenderObject* posRenderer = pos.renderer();
980 if (!posRenderer) 1005 if (!posRenderer)
981 return false; 1006 return false;
982 1007
983 if (renderer->style()->visibility() != VISIBLE || 1008 if (renderer->style()->visibility() != VISIBLE ||
984 posRenderer->style()->visibility() != VISIBLE) 1009 posRenderer->style()->visibility() != VISIBLE)
985 return false; 1010 return false;
986 1011
987 if (deprecatedNode() == pos.deprecatedNode()) { 1012 if (deprecatedNode() == pos.deprecatedNode()) {
988 if (deprecatedNode()->hasTagName(brTag)) 1013 if (deprecatedNode()->hasTagName(brTag))
989 return false; 1014 return false;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 while (position != lastPosition) { 1175 while (position != lastPosition) {
1151 lastPosition = position; 1176 lastPosition = position;
1152 position = position.upstream(CanCrossEditingBoundary); 1177 position = position.upstream(CanCrossEditingBoundary);
1153 } 1178 }
1154 return position; 1179 return position;
1155 } 1180 }
1156 1181
1157 void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi rection, InlineBox*& inlineBox, int& caretOffset) const 1182 void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi rection, InlineBox*& inlineBox, int& caretOffset) const
1158 { 1183 {
1159 caretOffset = deprecatedEditingOffset(); 1184 caretOffset = deprecatedEditingOffset();
1160 RenderObject* renderer = deprecatedNode()->renderer(); 1185 RenderObject* renderer = this->renderer();
1161 1186
1162 if (!renderer->isText()) { 1187 if (!renderer->isText()) {
1163 inlineBox = 0; 1188 inlineBox = 0;
1164 if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isBlockFlow () && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) { 1189 if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isBlockFlow () && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) {
1165 // Try a visually equivalent position with possibly opposite editabi lity. This helps in case |this| is in 1190 // Try a visually equivalent position with possibly opposite editabi lity. This helps in case |this| is in
1166 // an editable block but surrounded by non-editable positions. It ac ts to negate the logic at the beginning 1191 // an editable block but surrounded by non-editable positions. It ac ts to negate the logic at the beginning
1167 // of RenderObject::createVisiblePosition(). 1192 // of RenderObject::createVisiblePosition().
1168 Position equivalent = downstreamIgnoringEditingBoundaries(*this); 1193 Position equivalent = downstreamIgnoringEditingBoundaries(*this);
1169 if (equivalent == *this) { 1194 if (equivalent == *this) {
1170 equivalent = upstreamIgnoringEditingBoundaries(*this); 1195 equivalent = upstreamIgnoringEditingBoundaries(*this);
1171 if (equivalent == *this || downstreamIgnoringEditingBoundaries(e quivalent) == *this) 1196 if (equivalent == *this || downstreamIgnoringEditingBoundaries(e quivalent) == *this)
1172 return; 1197 return;
1173 } 1198 }
1174 1199
1175 equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineB ox, caretOffset); 1200 equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineB ox, caretOffset);
1176 return; 1201 return;
1177 } 1202 }
1178 if (renderer->isBox()) { 1203 if (renderer->isBox()) {
1179 inlineBox = toRenderBox(renderer)->inlineBoxWrapper(); 1204 inlineBox = toRenderBox(renderer)->inlineBoxWrapper();
1180 if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && care tOffset < inlineBox->caretMaxOffset())) 1205 if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && care tOffset < inlineBox->caretMaxOffset()))
1181 return; 1206 return;
1182 } 1207 }
1183 } else { 1208 } else {
1184 RenderText* textRenderer = toRenderText(renderer); 1209 RenderText* textRenderer = toRenderText(renderer);
1185 1210
1186 InlineTextBox* box; 1211 InlineTextBox* box;
1187 InlineTextBox* candidate = 0; 1212 InlineTextBox* candidate = 0;
1188 1213
1214 if (textRenderer->isTextFragment() && toRenderTextFragment(textRenderer) ->firstLetter()) {
1215 if (caretOffset) {
1216 caretOffset -= textRenderer->textStartOffset();
1217 } else {
1218 textRenderer = toRenderTextFragment(textRenderer)->firstRenderTe xtInFirstLetter();
1219 if (!textRenderer)
1220 return;
1221 }
1222 }
1223
1189 for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { 1224 for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
1190 int caretMinOffset = box->caretMinOffset(); 1225 int caretMinOffset = box->caretMinOffset();
1191 int caretMaxOffset = box->caretMaxOffset(); 1226 int caretMaxOffset = box->caretMaxOffset();
1192 1227
1193 if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak())) 1228 if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
1194 continue; 1229 continue;
1195 1230
1196 if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) { 1231 if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) {
1197 inlineBox = box; 1232 inlineBox = box;
1198 return; 1233 return;
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1392 pos.showTreeForThis(); 1427 pos.showTreeForThis();
1393 } 1428 }
1394 1429
1395 void showTree(const WebCore::Position* pos) 1430 void showTree(const WebCore::Position* pos)
1396 { 1431 {
1397 if (pos) 1432 if (pos)
1398 pos->showTreeForThis(); 1433 pos->showTreeForThis();
1399 } 1434 }
1400 1435
1401 #endif 1436 #endif
OLDNEW
« no previous file with comments | « Source/core/dom/Position.h ('k') | Source/core/dom/PositionIterator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698