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

Unified Diff: Source/core/editing/Position.cpp

Issue 1299323006: [Editing][CodeHealth] Move Position::up/downstream implementation to VisibleUnit.cpp (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/editing/Position.h ('k') | Source/core/editing/VisibleUnits.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/editing/Position.cpp
diff --git a/Source/core/editing/Position.cpp b/Source/core/editing/Position.cpp
index 6716f960a70ab8033c29ccc9d94401ea67a8e9c0..9733c7a295ee7e49e5f5b2481d0f5c5d8ac8abaf 100644
--- a/Source/core/editing/Position.cpp
+++ b/Source/core/editing/Position.cpp
@@ -515,301 +515,16 @@ bool PositionAlgorithm<Strategy>::atEndOfTree() const
return !Strategy::parent(*anchorNode()) && m_offset >= EditingStrategy::lastOffsetForEditing(anchorNode());
}
-// Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions.
-// If true, adjacent candidates are visually distinct.
-// FIXME: Disregard nodes with layoutObjects that have no height, as we do in isCandidate.
-// FIXME: Share code with isCandidate, if possible.
-static bool endsOfNodeAreVisuallyDistinctPositions(Node* node)
-{
- if (!node || !node->layoutObject())
- return false;
-
- if (!node->layoutObject()->isInline())
- return true;
-
- // Don't include inline tables.
- if (isHTMLTableElement(*node))
- return false;
-
- // A Marquee elements are moving so we should assume their ends are always
- // visibily distinct.
- if (isHTMLMarqueeElement(*node))
- return true;
-
- // There is a VisiblePosition inside an empty inline-block container.
- return node->layoutObject()->isReplaced() && canHaveChildrenForEditing(node) && toLayoutBox(node->layoutObject())->size().height() != 0 && !node->hasChildren();
-}
-
-template <typename Strategy>
-static Node* enclosingVisualBoundary(Node* node)
-{
- while (node && !endsOfNodeAreVisuallyDistinctPositions(node))
- node = Strategy::parent(*node);
-
- return node;
-}
-
-// upstream() and downstream() want to return positions that are either in a
-// text node or at just before a non-text node. This method checks for that.
-template <typename Strategy>
-static bool isStreamer(const PositionIteratorAlgorithm<Strategy>& pos)
-{
- if (!pos.node())
- return true;
-
- if (isAtomicNode(pos.node()))
- return true;
-
- return pos.atStartOfNode();
-}
-
-// This function and downstream() are used for moving back and forth between visually equivalent candidates.
-// For example, for the text node "foo bar" where whitespace is collapsible, there are two candidates
-// that map to the VisiblePosition between 'b' and the space. This function will return the left candidate
-// and downstream() will return the right one.
-// Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate
-// in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true.
template <typename Strategy>
PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::upstream(EditingBoundaryCrossingRule rule) const
{
- TRACE_EVENT0("blink", "Position::upstream");
-
- Node* startNode = anchorNode();
- if (!startNode)
- return PositionAlgorithm<Strategy>();
-
- // iterate backward from there, looking for a qualified position
- Node* boundary = enclosingVisualBoundary<Strategy>(startNode);
- // FIXME: PositionIterator should respect Before and After positions.
- PositionIteratorAlgorithm<Strategy> lastVisible(isAfterAnchor() ? editingPositionOf(m_anchorNode.get(), Strategy::caretMaxOffset(*m_anchorNode)) : PositionAlgorithm<Strategy>(*this));
- PositionIteratorAlgorithm<Strategy> currentPos = lastVisible;
- bool startEditable = startNode->hasEditableStyle();
- Node* lastNode = startNode;
- bool boundaryCrossed = false;
- for (; !currentPos.atStart(); currentPos.decrement()) {
- Node* currentNode = currentPos.node();
- // Don't check for an editability change if we haven't moved to a different node,
- // to avoid the expense of computing hasEditableStyle().
- if (currentNode != lastNode) {
- // Don't change editability.
- bool currentEditable = currentNode->hasEditableStyle();
- if (startEditable != currentEditable) {
- if (rule == CannotCrossEditingBoundary)
- break;
- boundaryCrossed = true;
- }
- lastNode = currentNode;
- }
-
- // If we've moved to a position that is visually distinct, return the last saved position. There
- // is code below that terminates early if we're *about* to move to a visually distinct position.
- if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
- return lastVisible.deprecatedComputePosition();
-
- // skip position in non-laid out or invisible node
- LayoutObject* layoutObject = currentNode->layoutObject();
- if (!layoutObject || layoutObject->style()->visibility() != VISIBLE)
- continue;
-
- if (rule == CanCrossEditingBoundary && boundaryCrossed) {
- lastVisible = currentPos;
- break;
- }
-
- // track last visible streamer position
- if (isStreamer<Strategy>(currentPos))
- lastVisible = currentPos;
-
- // Don't move past a position that is visually distinct. We could rely on code above to terminate and
- // return lastVisible on the next iteration, but we terminate early to avoid doing a nodeIndex() call.
- if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.atStartOfNode())
- return lastVisible.deprecatedComputePosition();
-
- // Return position after tables and nodes which have content that can be ignored.
- if (Strategy::editingIgnoresContent(currentNode) || isRenderedHTMLTableElement(currentNode)) {
- if (currentPos.atEndOfNode())
- return afterNode(currentNode);
- continue;
- }
-
- // return current position if it is in laid out text
- if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox()) {
- if (currentNode != startNode) {
- // This assertion fires in layout tests in the case-transform.html test because
- // of a mix-up between offsets in the text in the DOM tree with text in the
- // layout tree which can have a different length due to case transformation.
- // Until we resolve that, disable this so we can run the layout tests!
- // ASSERT(currentOffset >= layoutObject->caretMaxOffset());
- return PositionAlgorithm<Strategy>(currentNode, layoutObject->caretMaxOffset());
- }
-
- unsigned textOffset = currentPos.offsetInLeafNode();
- LayoutText* textLayoutObject = toLayoutText(layoutObject);
- InlineTextBox* lastTextBox = textLayoutObject->lastTextBox();
- for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) {
- if (textOffset <= box->start() + box->len()) {
- if (textOffset > box->start())
- return currentPos.computePosition();
- continue;
- }
-
- if (box == lastTextBox || textOffset != box->start() + box->len() + 1)
- continue;
-
- // The text continues on the next line only if the last text box is not on this line and
- // none of the boxes on this line have a larger start offset.
-
- bool continuesOnNextLine = true;
- InlineBox* otherBox = box;
- while (continuesOnNextLine) {
- otherBox = otherBox->nextLeafChild();
- if (!otherBox)
- break;
- if (otherBox == lastTextBox || (otherBox->layoutObject() == textLayoutObject && toInlineTextBox(otherBox)->start() > textOffset))
- continuesOnNextLine = false;
- }
-
- otherBox = box;
- while (continuesOnNextLine) {
- otherBox = otherBox->prevLeafChild();
- if (!otherBox)
- break;
- if (otherBox == lastTextBox || (otherBox->layoutObject() == textLayoutObject && toInlineTextBox(otherBox)->start() > textOffset))
- continuesOnNextLine = false;
- }
-
- if (continuesOnNextLine)
- return currentPos.computePosition();
- }
- }
- }
- return lastVisible.deprecatedComputePosition();
+ return mostForwardCaretPosition(*this, rule);
}
-// This function and upstream() are used for moving back and forth between visually equivalent candidates.
-// For example, for the text node "foo bar" where whitespace is collapsible, there are two candidates
-// that map to the VisiblePosition between 'b' and the space. This function will return the right candidate
-// and upstream() will return the left one.
-// Also, downstream() will return the last position in the last atomic node in boundary for all of the positions
-// in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPositions(boundary).
-// FIXME: This function should never be called when the line box tree is dirty. See https://bugs.webkit.org/show_bug.cgi?id=97264
template <typename Strategy>
PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::downstream(EditingBoundaryCrossingRule rule) const
{
- TRACE_EVENT0("blink", "Position::downstream");
-
- Node* startNode = anchorNode();
- if (!startNode)
- return PositionAlgorithm<Strategy>();
-
- // iterate forward from there, looking for a qualified position
- Node* boundary = enclosingVisualBoundary<Strategy>(startNode);
- // FIXME: PositionIterator should respect Before and After positions.
- PositionIteratorAlgorithm<Strategy> lastVisible(isAfterAnchor() ? editingPositionOf(m_anchorNode.get(), Strategy::caretMaxOffset(*m_anchorNode)) : PositionAlgorithm<Strategy>(*this));
- PositionIteratorAlgorithm<Strategy> currentPos = lastVisible;
- bool startEditable = startNode->hasEditableStyle();
- Node* lastNode = startNode;
- bool boundaryCrossed = false;
- for (; !currentPos.atEnd(); currentPos.increment()) {
- Node* currentNode = currentPos.node();
- // Don't check for an editability change if we haven't moved to a different node,
- // to avoid the expense of computing hasEditableStyle().
- if (currentNode != lastNode) {
- // Don't change editability.
- bool currentEditable = currentNode->hasEditableStyle();
- if (startEditable != currentEditable) {
- if (rule == CannotCrossEditingBoundary)
- break;
- boundaryCrossed = true;
- }
-
- lastNode = currentNode;
- }
-
- // stop before going above the body, up into the head
- // return the last visible streamer position
- if (isHTMLBodyElement(*currentNode) && currentPos.atEndOfNode())
- break;
-
- // Do not move to a visually distinct position.
- if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
- return lastVisible.deprecatedComputePosition();
- // Do not move past a visually disinct position.
- // Note: The first position after the last in a node whose ends are visually distinct
- // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1].
- if (boundary && Strategy::parent(*boundary) == currentNode)
- return lastVisible.deprecatedComputePosition();
-
- // skip position in non-laid out or invisible node
- LayoutObject* layoutObject = currentNode->layoutObject();
- if (!layoutObject || layoutObject->style()->visibility() != VISIBLE)
- continue;
-
- if (rule == CanCrossEditingBoundary && boundaryCrossed) {
- lastVisible = currentPos;
- break;
- }
-
- // track last visible streamer position
- if (isStreamer<Strategy>(currentPos))
- lastVisible = currentPos;
-
- // Return position before tables and nodes which have content that can be ignored.
- if (Strategy::editingIgnoresContent(currentNode) || isRenderedHTMLTableElement(currentNode)) {
- if (currentPos.offsetInLeafNode() <= layoutObject->caretMinOffset())
- return editingPositionOf(currentNode, layoutObject->caretMinOffset());
- continue;
- }
-
- // return current position if it is in laid out text
- if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox()) {
- if (currentNode != startNode) {
- ASSERT(currentPos.atStartOfNode());
- return PositionAlgorithm<Strategy>(currentNode, layoutObject->caretMinOffset());
- }
-
- unsigned textOffset = currentPos.offsetInLeafNode();
- LayoutText* textLayoutObject = toLayoutText(layoutObject);
- InlineTextBox* lastTextBox = textLayoutObject->lastTextBox();
- for (InlineTextBox* box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) {
- if (textOffset <= box->end()) {
- if (textOffset >= box->start())
- return currentPos.computePosition();
- continue;
- }
-
- if (box == lastTextBox || textOffset != box->start() + box->len())
- continue;
-
- // The text continues on the next line only if the last text box is not on this line and
- // none of the boxes on this line have a larger start offset.
-
- bool continuesOnNextLine = true;
- InlineBox* otherBox = box;
- while (continuesOnNextLine) {
- otherBox = otherBox->nextLeafChild();
- if (!otherBox)
- break;
- if (otherBox == lastTextBox || (otherBox->layoutObject() == textLayoutObject && toInlineTextBox(otherBox)->start() >= textOffset))
- continuesOnNextLine = false;
- }
-
- otherBox = box;
- while (continuesOnNextLine) {
- otherBox = otherBox->prevLeafChild();
- if (!otherBox)
- break;
- if (otherBox == lastTextBox || (otherBox->layoutObject() == textLayoutObject && toInlineTextBox(otherBox)->start() >= textOffset))
- continuesOnNextLine = false;
- }
-
- if (continuesOnNextLine)
- return currentPos.computePosition();
- }
- }
- }
-
- return lastVisible.deprecatedComputePosition();
+ return mostBackwardCaretPosition(*this, rule);
}
static int boundingBoxLogicalHeight(LayoutObject *o, const IntRect &rect)
« no previous file with comments | « Source/core/editing/Position.h ('k') | Source/core/editing/VisibleUnits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698