Title: [89683] trunk/Source/WebCore
Revision
89683
Author
[email protected]
Date
2011-06-24 10:45:00 -0700 (Fri, 24 Jun 2011)

Log Message

2011-06-24  Ryosuke Niwa  <[email protected]>

        Reviewed by Enrica Casucci.

        Add BeforeChildren and AfterChildren to the Position's anchor types
        https://bugs.webkit.org/show_bug.cgi?id=63100

        Added PositionIsBeforeChildren and PositionIsAfterChildren to Position::AnchorType and deployed them in
        firstPositionInNode and lastPositionInNode.

        These new types of positions will let us express the first and the last positions in a non-text node in O(1).

        No new tests because there is no new behavior or feature exposed.

        * dom/Position.cpp:
        (WebCore::Position::Position): Assert that the anchor type is not BeforeChildren and AfterChildren for text nodes.
        (WebCore::Position::containerNode): For BeforeChildren and AfterChildren, the anchor node is the container node.
        (WebCore::Position::computeOffsetInContainerNode): The offset in the container node is 0 for BeforeChildren and
        the offset in the anchor node for AfterChildren.
        (WebCore::Position::offsetForPositionAfterAnchor): Called by deprecatedNode; the anchor type could be AfterChildren.
        (WebCore::Position::parentAnchoredEquivalent): If the anchor node is before or after children, then do the trick
        for table and ignored contents like before or after anchor.
        (WebCore::Position::computeNodeBeforePosition): Returns null for BeforeChildren and returns the last child of
        the anchor node for AfterChildren.
        (WebCore::Position::computeNodeAfterPosition): Returns the first child of the anchor node for BeforeChildren
        (WebCore::Position::atFirstEditingPositionForNode): A position is at the last editing position if the anchor type
        is BeforeChildren, or the anchor type is AfterChildren or AfterAnchor and the anchor doesn't have any children.
        (WebCore::Position::atLastEditingPositionForNode): A position is at the last editing position if the anchor type
        is AfterChildren.
        (WebCore::Position::showAnchorTypeAndOffset): Supports BeforeChildren and AfterChildren.
        * dom/Position.h:
        (WebCore::Position::deprecatedEditingOffset): Returns m_offset if the anchor type is BeforeChildren.
        (WebCore::firstPositionInNode): Returns a position in offset for a text node. Otherwise returns BeforeChildren.
        (WebCore::lastPositionInNode): Returns a position in offset for a text node. Otherwise returns AfterChildren.
        * editing/CompositeEditCommand.cpp:
        (WebCore::CompositeEditCommand::positionOutsideTabSpan): Since the anchor node was a text node,
        the anchor type shouldn't be BeforeChildren or AfterChildren.
        * editing/DeleteSelectionCommand.cpp:
        (WebCore::updatePositionForNodeRemoval): Supports BeforeChildren and AfterChildren.
        (WebCore::DeleteSelectionCommand::handleGeneralDelete): Calls updatePositionForNodeRemoval on m_downstremEnd
        when its anchor node is removed instead of manually updating the offset; also avoid calling moveToOffset
        on BeforeChildren or AfterChildren position.
        * editing/FormatBlockCommand.cpp:
        (WebCore::FormatBlockCommand::formatRange): Since lastParagraphInBlockNode is used to insert a placeholder
        after paragraphs below the block is moved into, it needs to be the position after the current last child in
        the block instead of after children in the block; otherwise the position will move to the end of block.
        * editing/VisiblePosition.cpp:
        (WebCore::VisiblePosition::characterAfter): Since the container node is never a text for position before/after
        children or before/after anchor, just return null for these anchor types.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (89682 => 89683)


--- trunk/Source/WebCore/ChangeLog	2011-06-24 17:37:51 UTC (rev 89682)
+++ trunk/Source/WebCore/ChangeLog	2011-06-24 17:45:00 UTC (rev 89683)
@@ -1,3 +1,53 @@
+2011-06-24  Ryosuke Niwa  <[email protected]>
+
+        Reviewed by Enrica Casucci.
+
+        Add BeforeChildren and AfterChildren to the Position's anchor types
+        https://bugs.webkit.org/show_bug.cgi?id=63100
+
+        Added PositionIsBeforeChildren and PositionIsAfterChildren to Position::AnchorType and deployed them in
+        firstPositionInNode and lastPositionInNode.
+
+        These new types of positions will let us express the first and the last positions in a non-text node in O(1).
+
+        No new tests because there is no new behavior or feature exposed.
+
+        * dom/Position.cpp:
+        (WebCore::Position::Position): Assert that the anchor type is not BeforeChildren and AfterChildren for text nodes.
+        (WebCore::Position::containerNode): For BeforeChildren and AfterChildren, the anchor node is the container node.
+        (WebCore::Position::computeOffsetInContainerNode): The offset in the container node is 0 for BeforeChildren and
+        the offset in the anchor node for AfterChildren.
+        (WebCore::Position::offsetForPositionAfterAnchor): Called by deprecatedNode; the anchor type could be AfterChildren.
+        (WebCore::Position::parentAnchoredEquivalent): If the anchor node is before or after children, then do the trick
+        for table and ignored contents like before or after anchor.
+        (WebCore::Position::computeNodeBeforePosition): Returns null for BeforeChildren and returns the last child of
+        the anchor node for AfterChildren.
+        (WebCore::Position::computeNodeAfterPosition): Returns the first child of the anchor node for BeforeChildren
+        (WebCore::Position::atFirstEditingPositionForNode): A position is at the last editing position if the anchor type
+        is BeforeChildren, or the anchor type is AfterChildren or AfterAnchor and the anchor doesn't have any children.
+        (WebCore::Position::atLastEditingPositionForNode): A position is at the last editing position if the anchor type
+        is AfterChildren.
+        (WebCore::Position::showAnchorTypeAndOffset): Supports BeforeChildren and AfterChildren.
+        * dom/Position.h:
+        (WebCore::Position::deprecatedEditingOffset): Returns m_offset if the anchor type is BeforeChildren.
+        (WebCore::firstPositionInNode): Returns a position in offset for a text node. Otherwise returns BeforeChildren.
+        (WebCore::lastPositionInNode): Returns a position in offset for a text node. Otherwise returns AfterChildren.
+        * editing/CompositeEditCommand.cpp:
+        (WebCore::CompositeEditCommand::positionOutsideTabSpan): Since the anchor node was a text node,
+        the anchor type shouldn't be BeforeChildren or AfterChildren.
+        * editing/DeleteSelectionCommand.cpp:
+        (WebCore::updatePositionForNodeRemoval): Supports BeforeChildren and AfterChildren.
+        (WebCore::DeleteSelectionCommand::handleGeneralDelete): Calls updatePositionForNodeRemoval on m_downstremEnd
+        when its anchor node is removed instead of manually updating the offset; also avoid calling moveToOffset
+        on BeforeChildren or AfterChildren position.
+        * editing/FormatBlockCommand.cpp:
+        (WebCore::FormatBlockCommand::formatRange): Since lastParagraphInBlockNode is used to insert a placeholder
+        after paragraphs below the block is moved into, it needs to be the position after the current last child in
+        the block instead of after children in the block; otherwise the position will move to the end of block.
+        * editing/VisiblePosition.cpp:
+        (WebCore::VisiblePosition::characterAfter): Since the container node is never a text for position before/after
+        children or before/after anchor, just return null for these anchor types.
+
 2011-06-24  Dominic Cooney  <[email protected]>
 
         Reviewed by Dimitri Glazkov.

Modified: trunk/Source/WebCore/dom/Position.cpp (89682 => 89683)


--- trunk/Source/WebCore/dom/Position.cpp	2011-06-24 17:37:51 UTC (rev 89682)
+++ trunk/Source/WebCore/dom/Position.cpp	2011-06-24 17:45:00 UTC (rev 89683)
@@ -91,6 +91,7 @@
 {
     ASSERT(!m_anchorNode || !m_anchorNode->isShadowRoot());
     ASSERT(anchorType != PositionIsOffsetInAnchor);
+    ASSERT(!((anchorType == PositionIsBeforeChildren || anchorType == PositionIsAfterChildren) && m_anchorNode->isTextNode()));
 }
 
 Position::Position(PassRefPtr<Node> anchorNode, int offset, AnchorType anchorType)
@@ -135,6 +136,8 @@
         return 0;
 
     switch (anchorType()) {
+    case PositionIsBeforeChildren:
+    case PositionIsAfterChildren:
     case PositionIsOffsetInAnchor:
         return m_anchorNode.get();
     case PositionIsBeforeAnchor:
@@ -151,6 +154,10 @@
         return 0;
 
     switch (anchorType()) {
+    case PositionIsBeforeChildren:
+        return 0;
+    case PositionIsAfterChildren:
+        return lastOffsetInNode(m_anchorNode.get());
     case PositionIsOffsetInAnchor:
         return std::min(lastOffsetInNode(m_anchorNode.get()), m_offset);
     case PositionIsBeforeAnchor:
@@ -164,7 +171,7 @@
 
 int Position::offsetForPositionAfterAnchor() const
 {
-    ASSERT(m_anchorType == PositionIsAfterAnchor);
+    ASSERT(m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren);
     ASSERT(!m_isLegacyEditingPosition);
     return lastOffsetForEditing(m_anchorNode.get());
 }
@@ -177,12 +184,13 @@
         return Position();
     
     // FIXME: This should only be necessary for legacy positions, but is also needed for positions before and after Tables
-    if (m_offset <= 0 && m_anchorType != PositionIsAfterAnchor) {
+    if (m_offset <= 0 && (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren)) {
         if (m_anchorNode->nonShadowBoundaryParentNode() && (editingIgnoresContent(m_anchorNode.get()) || isTableElement(m_anchorNode.get())))
             return positionInParentBeforeNode(m_anchorNode.get());
-        return firstPositionInOrBeforeNode(m_anchorNode.get());
+        return Position(m_anchorNode.get(), 0, PositionIsOffsetInAnchor);
     }
-    if (!m_anchorNode->offsetInCharacters() && (m_anchorType == PositionIsAfterAnchor || static_cast<unsigned>(m_offset) == m_anchorNode->childNodeCount())
+    if (!m_anchorNode->offsetInCharacters()
+        && (m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || static_cast<unsigned>(m_offset) == m_anchorNode->childNodeCount())
         && (editingIgnoresContent(m_anchorNode.get()) || isTableElement(m_anchorNode.get()))
         && containerNode()) {
         return positionInParentAfterNode(m_anchorNode.get());
@@ -197,6 +205,10 @@
         return 0;
 
     switch (anchorType()) {
+    case PositionIsBeforeChildren:
+        return 0;
+    case PositionIsAfterChildren:
+        return m_anchorNode->lastChild();
     case PositionIsOffsetInAnchor:
         return m_anchorNode->childNode(m_offset - 1); // -1 converts to childNode((unsigned)-1) and returns null.
     case PositionIsBeforeAnchor:
@@ -214,6 +226,10 @@
         return 0;
 
     switch (anchorType()) {
+    case PositionIsBeforeChildren:
+        return m_anchorNode->firstChild();
+    case PositionIsAfterChildren:
+        return 0;
     case PositionIsOffsetInAnchor:
         return m_anchorNode->childNode(m_offset);
     case PositionIsBeforeAnchor:
@@ -340,14 +356,29 @@
 {
     if (isNull())
         return true;
-    return m_anchorType == PositionIsBeforeAnchor || m_offset <= 0;
+    // FIXME: Position before anchor shouldn't be considered as at the first editing position for node
+    // since that position resides outside of the node.
+    switch (m_anchorType) {
+    case PositionIsOffsetInAnchor:
+        return m_offset <= 0;
+    case PositionIsBeforeChildren:
+    case PositionIsBeforeAnchor:
+        return true;
+    case PositionIsAfterChildren:
+    case PositionIsAfterAnchor:
+        return !lastOffsetForEditing(deprecatedNode());
+    }
+    ASSERT_NOT_REACHED();
+    return false;
 }
 
 bool Position::atLastEditingPositionForNode() const
 {
     if (isNull())
         return true;
-    return m_anchorType == PositionIsAfterAnchor || m_offset >= lastOffsetForEditing(deprecatedNode());
+    // FIXME: Position after anchor shouldn't be considered as at the first editing position for node
+    // since that position resides outside of the node.
+    return m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || m_offset >= lastOffsetForEditing(deprecatedNode());
 }
 
 // A position is considered at editing boundary if one of the following is true:
@@ -1269,12 +1300,18 @@
     case PositionIsOffsetInAnchor:
         fputs("offset", stderr);
         break;
-    case PositionIsAfterAnchor:
-        fputs("after", stderr);
+    case PositionIsBeforeChildren:
+        fputs("beforeChildren", stderr);
         break;
+    case PositionIsAfterChildren:
+        fputs("afterChildren", stderr);
+        break;
     case PositionIsBeforeAnchor:
         fputs("before", stderr);
         break;
+    case PositionIsAfterAnchor:
+        fputs("after", stderr);
+        break;
     }
     fprintf(stderr, ", offset:%d\n", m_offset);
 }

Modified: trunk/Source/WebCore/dom/Position.h (89682 => 89683)


--- trunk/Source/WebCore/dom/Position.h	2011-06-24 17:37:51 UTC (rev 89682)
+++ trunk/Source/WebCore/dom/Position.h	2011-06-24 17:45:00 UTC (rev 89683)
@@ -54,8 +54,10 @@
 public:
     enum AnchorType {
         PositionIsOffsetInAnchor,
+        PositionIsBeforeAnchor,
         PositionIsAfterAnchor,
-        PositionIsBeforeAnchor
+        PositionIsBeforeChildren,
+        PositionIsAfterChildren,
     };
 
     Position()
@@ -107,7 +109,7 @@
     // New code should not use this function.
     int deprecatedEditingOffset() const
     {
-        if (m_isLegacyEditingPosition || m_anchorType != PositionIsAfterAnchor)
+        if (m_isLegacyEditingPosition || (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren))
             return m_offset;
         return offsetForPositionAfterAnchor();
     }
@@ -204,7 +206,7 @@
     // returns true, then other places in editing will treat m_offset == 0 as "before the anchor"
     // and m_offset > 0 as "after the anchor node".  See parentAnchoredEquivalent for more info.
     int m_offset;
-    unsigned m_anchorType : 2;
+    unsigned m_anchorType : 3;
     bool m_isLegacyEditingPosition : 1;
 };
 
@@ -265,12 +267,16 @@
 // firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to childNodeCount()
 inline Position firstPositionInNode(Node* anchorNode)
 {
-    return Position(anchorNode, 0, Position::PositionIsOffsetInAnchor);
+    if (anchorNode->isTextNode())
+        return Position(anchorNode, 0, Position::PositionIsOffsetInAnchor);
+    return Position(anchorNode, Position::PositionIsBeforeChildren);
 }
 
 inline Position lastPositionInNode(Node* anchorNode)
 {
-    return Position(anchorNode, lastOffsetInNode(anchorNode), Position::PositionIsOffsetInAnchor);
+    if (anchorNode->isTextNode())
+        return Position(anchorNode, lastOffsetInNode(anchorNode), Position::PositionIsOffsetInAnchor);
+    return Position(anchorNode, Position::PositionIsAfterChildren);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/editing/CompositeEditCommand.cpp (89682 => 89683)


--- trunk/Source/WebCore/editing/CompositeEditCommand.cpp	2011-06-24 17:37:51 UTC (rev 89682)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.cpp	2011-06-24 17:45:00 UTC (rev 89683)
@@ -373,10 +373,18 @@
     if (!isTabSpanTextNode(pos.anchorNode()))
         return pos;
 
-    if (pos.anchorType() == Position::PositionIsAfterAnchor)
+    switch (pos.anchorType()) {
+    case Position::PositionIsBeforeChildren:
+    case Position::PositionIsAfterChildren:
+        ASSERT_NOT_REACHED();
+        return pos;
+    case Position::PositionIsOffsetInAnchor:
+        break;
+    case Position::PositionIsBeforeAnchor:
+        return positionInParentBeforeNode(pos.anchorNode());
+    case Position::PositionIsAfterAnchor:
         return positionInParentAfterNode(pos.anchorNode());
-    if (pos.anchorType() == Position::PositionIsBeforeAnchor)
-        return positionInParentBeforeNode(pos.anchorNode());
+    }
 
     Node* tabSpan = tabSpanNode(pos.containerNode());
 

Modified: trunk/Source/WebCore/editing/DeleteSelectionCommand.cpp (89682 => 89683)


--- trunk/Source/WebCore/editing/DeleteSelectionCommand.cpp	2011-06-24 17:37:51 UTC (rev 89682)
+++ trunk/Source/WebCore/editing/DeleteSelectionCommand.cpp	2011-06-24 17:45:00 UTC (rev 89683)
@@ -319,6 +319,14 @@
     if (position.isNull())
         return;
     switch (position.anchorType()) {
+    case Position::PositionIsBeforeChildren:
+        if (position.containerNode() == node)
+            position = positionInParentBeforeNode(node);
+        break;
+    case Position::PositionIsAfterChildren:
+        if (position.containerNode() == node)
+            position = positionInParentAfterNode(node);
+        break;
     case Position::PositionIsOffsetInAnchor:
         if (position.containerNode() == node->parentNode() && static_cast<unsigned>(position.offsetInContainerNode()) > node->nodeIndex())
             position.moveToOffset(position.offsetInContainerNode() - 1);
@@ -498,11 +506,7 @@
                 RefPtr<Node> nextNode = node->traverseNextSibling();
                 // if we just removed a node from the end container, update end position so the
                 // check above will work
-                if (node->parentNode() == m_downstreamEnd.deprecatedNode()) {
-                    ASSERT(m_downstreamEnd.deprecatedEditingOffset());
-                    ASSERT(node->nodeIndex() < (unsigned)m_downstreamEnd.deprecatedEditingOffset());
-                    m_downstreamEnd.moveToOffset(m_downstreamEnd.deprecatedEditingOffset() - 1);
-                }
+                updatePositionForNodeRemoval(node.get(), m_downstreamEnd);
                 removeNode(node.get());
                 node = nextNode.get();
             } else {
@@ -542,7 +546,7 @@
                             offset = n->nodeIndex() + 1;
                     }
                     removeChildrenInRange(m_downstreamEnd.deprecatedNode(), offset, m_downstreamEnd.deprecatedEditingOffset());
-                    m_downstreamEnd.moveToOffset(offset);
+                    m_downstreamEnd = createLegacyEditingPosition(m_downstreamEnd.deprecatedNode(), offset);
                 }
             }
         }

Modified: trunk/Source/WebCore/editing/FormatBlockCommand.cpp (89682 => 89683)


--- trunk/Source/WebCore/editing/FormatBlockCommand.cpp	2011-06-24 17:37:51 UTC (rev 89682)
+++ trunk/Source/WebCore/editing/FormatBlockCommand.cpp	2011-06-24 17:45:00 UTC (rev 89683)
@@ -86,7 +86,7 @@
         insertNodeBefore(blockNode, nodeAfterInsertionPosition);
     }
 
-    Position lastParagraphInBlockNode = lastPositionInNode(blockNode.get());
+    Position lastParagraphInBlockNode = blockNode->lastChild() ? positionAfterNode(blockNode->lastChild()) : Position();
     bool wasEndOfParagraph = isEndOfParagraph(lastParagraphInBlockNode);
 
     moveParagraphWithClones(start, end, blockNode.get(), outerBlock.get());

Modified: trunk/Source/WebCore/editing/VisiblePosition.cpp (89682 => 89683)


--- trunk/Source/WebCore/editing/VisiblePosition.cpp	2011-06-24 17:37:51 UTC (rev 89682)
+++ trunk/Source/WebCore/editing/VisiblePosition.cpp	2011-06-24 17:45:00 UTC (rev 89683)
@@ -541,10 +541,17 @@
     // We canonicalize to the first of two equivalent candidates, but the second of the two candidates
     // is the one that will be inside the text node containing the character after this visible position.
     Position pos = m_deepPosition.downstream();
-    Node* node = pos.containerNode();
-    if (!node || !node->isTextNode() || pos.anchorType() == Position::PositionIsAfterAnchor)
+    if (!pos.containerNode() || !pos.containerNode()->isTextNode())
         return 0;
-    ASSERT(pos.anchorType() == Position::PositionIsBeforeAnchor || pos.anchorType() == Position::PositionIsOffsetInAnchor);
+    switch (pos.anchorType()) {
+    case Position::PositionIsAfterChildren:
+    case Position::PositionIsAfterAnchor:
+    case Position::PositionIsBeforeAnchor:
+    case Position::PositionIsBeforeChildren:
+        return 0;
+    case Position::PositionIsOffsetInAnchor:
+        break;
+    }
     Text* textNode = static_cast<Text*>(pos.containerNode());
     unsigned offset = pos.anchorType() == Position::PositionIsOffsetInAnchor ? pos.offsetInContainerNode() : 0;
     unsigned length = textNode->length();
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to