📄 visible_units.cpp
字号:
VisiblePosition visPos = VisiblePosition(startNode, startOffset, DOWNSTREAM); return positionAvoidingFirstPositionInTable(visPos);}VisiblePosition startOfLine(const VisiblePosition& c){ VisiblePosition visPos = startPositionForLine(c); if (visPos.isNotNull()) { // Make sure the start of line is not greater than the given input position. Else use the previous position to // obtain start of line. This condition happens when the input position is before the space character at the end // of a soft-wrapped non-editable line. In this scenario, startPositionForLine would incorrectly hand back a position // greater than the input position. This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space // style versus lines without that style, which would break before a space by default. Position p = visPos.deepEquivalent(); if (p.offset() > c.deepEquivalent().offset() && p.node()->isSameNode(c.deepEquivalent().node())) { visPos = c.previous(); if (visPos.isNull()) return VisiblePosition(); visPos = startPositionForLine(visPos); } } return c.honorEditableBoundaryAtOrAfter(visPos);}static VisiblePosition endPositionForLine(const VisiblePosition& c){ if (c.isNull()) return VisiblePosition(); RootInlineBox *rootBox = rootBoxForLine(c); if (!rootBox) { // There are VisiblePositions at offset 0 in blocks without // RootInlineBoxes, like empty editable blocks and bordered blocks. Position p = c.deepEquivalent(); if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.offset() == 0) return c; return VisiblePosition(); } // Generated content (e.g. list markers and CSS :before and :after // pseudoelements) have no corresponding DOM element, and so cannot be // represented by a VisiblePosition. Use whatever precedes instead. Node *endNode; InlineBox *endBox = rootBox->lastLeafChild(); while (1) { if (!endBox) return VisiblePosition(); RenderObject *endRenderer = endBox->renderer(); if (!endRenderer) return VisiblePosition(); endNode = endRenderer->node(); if (endNode) break; endBox = endBox->prevLeafChild(); } int endOffset = 1; if (endNode->hasTagName(brTag)) { endOffset = 0; } else if (endBox->isInlineTextBox()) { InlineTextBox *endTextBox = static_cast<InlineTextBox *>(endBox); endOffset = endTextBox->start(); if (!endTextBox->isLineBreak()) endOffset += endTextBox->len(); } return VisiblePosition(endNode, endOffset, VP_UPSTREAM_IF_POSSIBLE);}VisiblePosition endOfLine(const VisiblePosition& c){ VisiblePosition visPos = endPositionForLine(c); // Make sure the end of line is at the same line as the given input position. Else use the previous position to // obtain end of line. This condition happens when the input position is before the space character at the end // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position // in the next line instead. This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space style // versus lines without that style, which would break before a space by default. if (!inSameLine(c, visPos)) { visPos = c.previous(); if (visPos.isNull()) return VisiblePosition(); visPos = endPositionForLine(visPos); } return c.honorEditableBoundaryAtOrBefore(visPos);}bool inSameLine(const VisiblePosition &a, const VisiblePosition &b){ return a.isNotNull() && startOfLine(a) == startOfLine(b);}bool isStartOfLine(const VisiblePosition &p){ return p.isNotNull() && p == startOfLine(p);}bool isEndOfLine(const VisiblePosition &p){ return p.isNotNull() && p == endOfLine(p);}// The first leaf before node that has the same editability as node.static Node* previousLeafWithSameEditability(Node* node){ bool editable = node->isContentEditable(); Node* n = node->previousLeafNode(); while (n) { if (editable == n->isContentEditable()) return n; n = n->previousLeafNode(); } return 0;}VisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int x){ Position p = visiblePosition.deepEquivalent(); Node *node = p.node(); Node* highestRoot = highestEditableRoot(p); if (!node) return VisiblePosition(); node->document()->updateLayoutIgnorePendingStylesheets(); RenderObject *renderer = node->renderer(); if (!renderer) return VisiblePosition(); RenderBlock *containingBlock = 0; RootInlineBox *root = 0; InlineBox* box; int ignoredCaretOffset; visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset); if (box) { root = box->root()->prevRootBox(); if (root) containingBlock = renderer->containingBlock(); } if (!root) { // This containing editable block does not have a previous line. // Need to move back to previous containing editable block in this root editable // block and find the last root line box in that block. Node* startBlock = enclosingBlock(node); Node* n = previousLeafWithSameEditability(node); while (n && startBlock == enclosingBlock(n)) n = previousLeafWithSameEditability(n); while (n) { if (highestEditableRoot(Position(n, 0)) != highestRoot) break; Position pos(n, caretMinOffset(n)); if (pos.isCandidate()) { ASSERT(n->renderer()); Position maxPos(n, caretMaxOffset(n)); maxPos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset); if (box) { // previous root line box found root = box->root(); containingBlock = n->renderer()->containingBlock(); break; } return VisiblePosition(pos, DOWNSTREAM); } n = previousLeafWithSameEditability(n); } } if (root) { // FIXME: Can be wrong for multi-column layout and with transforms. FloatPoint absPos = containingBlock->localToAbsolute(FloatPoint()); if (containingBlock->hasOverflowClip()) absPos -= containingBlock->layer()->scrolledContentOffset(); RenderObject* renderer = root->closestLeafChildForXPos(x - absPos.x(), isEditablePosition(p))->renderer(); Node* node = renderer->node(); if (editingIgnoresContent(node)) return Position(node->parent(), node->nodeIndex()); return renderer->positionForCoordinates(x - absPos.x(), root->topOverflow()); } // Could not find a previous line. This means we must already be on the first line. // Move to the start of the content in this block, which effectively moves us // to the start of the line we're on. Node* rootElement = node->isContentEditable() ? node->rootEditableElement() : node->document()->documentElement(); return VisiblePosition(rootElement, 0, DOWNSTREAM);}static Node* nextLeafWithSameEditability(Node* node, int offset){ bool editable = node->isContentEditable(); ASSERT(offset >= 0); Node* child = node->childNode(offset); Node* n = child ? child->nextLeafNode() : node->nextLeafNode(); while (n) { if (editable == n->isContentEditable()) return n; n = n->nextLeafNode(); } return 0;}static Node* nextLeafWithSameEditability(Node* node){ if (!node) return 0; bool editable = node->isContentEditable(); Node* n = node->nextLeafNode(); while (n) { if (editable == n->isContentEditable()) return n; n = n->nextLeafNode(); } return 0;}VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x){ Position p = visiblePosition.deepEquivalent(); Node *node = p.node(); Node* highestRoot = highestEditableRoot(p); if (!node) return VisiblePosition(); node->document()->updateLayoutIgnorePendingStylesheets(); RenderObject *renderer = node->renderer(); if (!renderer) return VisiblePosition(); RenderBlock *containingBlock = 0; RootInlineBox *root = 0; InlineBox* box; int ignoredCaretOffset; visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset); if (box) { root = box->root()->nextRootBox(); if (root) containingBlock = renderer->containingBlock(); } if (!root) { // This containing editable block does not have a next line. // Need to move forward to next containing editable block in this root editable // block and find the first root line box in that block. Node* startBlock = enclosingBlock(node); Node* n = nextLeafWithSameEditability(node, p.offset()); while (n && startBlock == enclosingBlock(n)) n = nextLeafWithSameEditability(n); while (n) { if (highestEditableRoot(Position(n, 0)) != highestRoot) break; Position pos(n, caretMinOffset(n)); if (pos.isCandidate()) { ASSERT(n->renderer()); pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset); if (box) { // next root line box found root = box->root(); containingBlock = n->renderer()->containingBlock(); break; } return VisiblePosition(pos, DOWNSTREAM); } n = nextLeafWithSameEditability(n); } } if (root) { // FIXME: Can be wrong for multi-column layout and with transforms. FloatPoint absPos = containingBlock->localToAbsolute(FloatPoint()); if (containingBlock->hasOverflowClip()) absPos -= containingBlock->layer()->scrolledContentOffset(); RenderObject* renderer = root->closestLeafChildForXPos(x - absPos.x(), isEditablePosition(p))->renderer(); Node* node = renderer->node(); if (editingIgnoresContent(node)) return Position(node->parent(), node->nodeIndex()); return renderer->positionForCoordinates(x - absPos.x(), root->topOverflow()); } // Could not find a next line. This means we must already be on the last line. // Move to the end of the content in this block, which effectively moves us // to the end of the line we're on. Element* rootElement = node->isContentEditable() ? node->rootEditableElement() : node->document()->documentElement(); return VisiblePosition(rootElement, rootElement ? rootElement->childNodeCount() : 0, DOWNSTREAM);}// ---------static unsigned startSentenceBoundary(const UChar* characters, unsigned length){ TextBreakIterator* iterator = sentenceBreakIterator(characters, length); // FIXME: The following function can return -1; we don't handle that. return textBreakPreceding(iterator, length);}VisiblePosition startOfSentence(const VisiblePosition &c){ return previousBoundary(c, startSentenceBoundary);}static unsigned endSentenceBoundary(const UChar* characters, unsigned length){ TextBreakIterator* iterator = sentenceBreakIterator(characters, length); return textBreakNext(iterator);}// FIXME: This includes the space after the punctuation that marks the end of the sentence.VisiblePosition endOfSentence(const VisiblePosition &c){ return nextBoundary(c, endSentenceBoundary);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -