📄 position.cpp
字号:
} } if (node()->hasTagName(brTag) && pos.isCandidate()) return true; if (pos.node()->hasTagName(brTag) && isCandidate()) return true; if (node()->enclosingBlockFlowElement() != pos.node()->enclosingBlockFlowElement()) return true; if (node()->isTextNode() && !inRenderedText()) return false; if (pos.node()->isTextNode() && !pos.inRenderedText()) return false; int thisRenderedOffset = renderedOffset(); int posRenderedOffset = pos.renderedOffset(); if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset) return false; int ignoredCaretOffset; InlineBox* b1; getInlineBoxAndOffset(DOWNSTREAM, b1, ignoredCaretOffset); InlineBox* b2; pos.getInlineBoxAndOffset(DOWNSTREAM, b2, ignoredCaretOffset); LOG(Editing, "renderer: %p [%p]\n", renderer, b1); LOG(Editing, "thisRenderedOffset: %d\n", thisRenderedOffset); LOG(Editing, "posRenderer: %p [%p]\n", posRenderer, b2); LOG(Editing, "posRenderedOffset: %d\n", posRenderedOffset); LOG(Editing, "node min/max: %d:%d\n", caretMinOffset(node()), caretMaxRenderedOffset(node())); LOG(Editing, "pos node min/max: %d:%d\n", caretMinOffset(pos.node()), caretMaxRenderedOffset(pos.node())); LOG(Editing, "----------------------------------------------------------------------\n"); if (!b1 || !b2) { return false; } if (b1->root() != b2->root()) { return true; } if (nextRenderedEditable(node()) == pos.node() && thisRenderedOffset == (int)caretMaxRenderedOffset(node()) && posRenderedOffset == 0) { return false; } if (previousRenderedEditable(node()) == pos.node() && thisRenderedOffset == 0 && posRenderedOffset == (int)caretMaxRenderedOffset(pos.node())) { return false; } return true;}// This assumes that it starts in editable content.Position Position::leadingWhitespacePosition(EAffinity affinity, bool considerNonCollapsibleWhitespace) const{ ASSERT(isEditablePosition(*this)); if (isNull()) return Position(); if (upstream().node()->hasTagName(brTag)) return Position(); Position prev = previousCharacterPosition(affinity); if (prev != *this && prev.node()->inSameContainingBlockFlowElement(node()) && prev.node()->isTextNode()) { String string = static_cast<Text *>(prev.node())->data(); UChar c = string[prev.offset()]; if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c)) if (isEditablePosition(prev)) return prev; } return Position();}// This assumes that it starts in editable content.Position Position::trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace) const{ ASSERT(isEditablePosition(*this)); if (isNull()) return Position(); VisiblePosition v(*this); UChar c = v.characterAfter(); // The space must not be in another paragraph and it must be editable. if (!isEndOfParagraph(v) && v.next(true).isNotNull()) if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c)) return *this; return Position();}void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const{ TextDirection primaryDirection = LTR; for (RenderObject* r = node()->renderer(); r; r = r->parent()) { if (r->isBlockFlow()) { primaryDirection = r->style()->direction(); break; } } getInlineBoxAndOffset(affinity, primaryDirection, inlineBox, caretOffset);}static bool isNonTextLeafChild(RenderObject* object){ if (object->firstChild()) return false; if (object->isText()) return false; return true;}static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer){ InlineTextBox* match = 0; int minOffset = INT_MAX; RenderBlock* container = renderer->containingBlock(); RenderObject* next = renderer; while ((next = next->nextInPreOrder(container))) { if (next->isRenderBlock()) break; if (next->isBR()) break; if (isNonTextLeafChild(next)) break; if (next->isText()) { for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; box = box->nextTextBox()) { int caretMinOffset = box->caretMinOffset(); if (caretMinOffset < minOffset) { match = box; minOffset = caretMinOffset; } } } } return match;}void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const{ caretOffset = offset(); RenderObject* renderer = node()->renderer(); if (!renderer->isText()) { inlineBox = renderer->isBox() ? toRenderBox(renderer)->inlineBoxWrapper() : 0; if (!inlineBox || caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()) return; } else { RenderText* textRenderer = toRenderText(renderer); InlineTextBox* box; InlineTextBox* candidate = 0; for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { int caretMinOffset = box->caretMinOffset(); int caretMaxOffset = box->caretMaxOffset(); if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || caretOffset == caretMaxOffset && box->isLineBreak()) continue; if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) { inlineBox = box; return; } if ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM)) break; candidate = box; } if (candidate && !box && affinity == DOWNSTREAM) { box = searchAheadForBetterMatch(textRenderer); if (box) caretOffset = box->caretMinOffset(); } inlineBox = box ? box : candidate; } if (!inlineBox) return; unsigned char level = inlineBox->bidiLevel(); if (inlineBox->direction() == primaryDirection) { if (caretOffset == inlineBox->caretRightmostOffset()) { InlineBox* nextBox = inlineBox->nextLeafChild(); if (!nextBox || nextBox->bidiLevel() >= level) return; level = nextBox->bidiLevel(); InlineBox* prevBox = inlineBox; do { prevBox = prevBox->prevLeafChild(); } while (prevBox && prevBox->bidiLevel() > level); if (prevBox && prevBox->bidiLevel() == level) // For example, abc FED 123 ^ CBA return; // For example, abc 123 ^ CBA while (InlineBox* nextBox = inlineBox->nextLeafChild()) { if (nextBox->bidiLevel() < level) break; inlineBox = nextBox; } caretOffset = inlineBox->caretRightmostOffset(); } else { InlineBox* prevBox = inlineBox->prevLeafChild(); if (!prevBox || prevBox->bidiLevel() >= level) return; level = prevBox->bidiLevel(); InlineBox* nextBox = inlineBox; do { nextBox = nextBox->nextLeafChild(); } while (nextBox && nextBox->bidiLevel() > level); if (nextBox && nextBox->bidiLevel() == level) return; while (InlineBox* prevBox = inlineBox->prevLeafChild()) { if (prevBox->bidiLevel() < level) break; inlineBox = prevBox; } caretOffset = inlineBox->caretLeftmostOffset(); } return; } if (caretOffset == inlineBox->caretLeftmostOffset()) { InlineBox* prevBox = inlineBox->prevLeafChild(); if (!prevBox || prevBox->bidiLevel() < level) { // Left edge of a secondary run. Set to the right edge of the entire run. while (InlineBox* nextBox = inlineBox->nextLeafChild()) { if (nextBox->bidiLevel() < level) break; inlineBox = nextBox; } caretOffset = inlineBox->caretRightmostOffset(); } else if (prevBox->bidiLevel() > level) { // Right edge of a "tertiary" run. Set to the left edge of that run. while (InlineBox* tertiaryBox = inlineBox->prevLeafChild()) { if (tertiaryBox->bidiLevel() <= level) break; inlineBox = tertiaryBox; } caretOffset = inlineBox->caretLeftmostOffset(); } } else { InlineBox* nextBox = inlineBox->nextLeafChild(); if (!nextBox || nextBox->bidiLevel() < level) { // Right edge of a secondary run. Set to the left edge of the entire run. while (InlineBox* prevBox = inlineBox->prevLeafChild()) { if (prevBox->bidiLevel() < level) break; inlineBox = prevBox; } caretOffset = inlineBox->caretLeftmostOffset(); } else if (nextBox->bidiLevel() > level) { // Left edge of a "tertiary" run. Set to the right edge of that run. while (InlineBox* tertiaryBox = inlineBox->nextLeafChild()) { if (tertiaryBox->bidiLevel() <= level) break; inlineBox = tertiaryBox; } caretOffset = inlineBox->caretRightmostOffset(); } }}void Position::debugPosition(const char* msg) const{ if (isNull()) fprintf(stderr, "Position [%s]: null\n", msg); else fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, node()->nodeName().utf8().data(), node(), offset());}#ifndef NDEBUGvoid Position::formatForDebugger(char* buffer, unsigned length) const{ String result; if (isNull()) result = "<null>"; else { char s[1024]; result += "offset "; result += String::number(offset()); result += " of "; node()->formatForDebugger(s, sizeof(s)); result += s; } strncpy(buffer, result.utf8().data(), length - 1);}void Position::showTreeForThis() const{ if (node()) node()->showTreeForThis();}#endifPosition startPosition(const Range* r){ return r ? r->startPosition() : Position();}Position endPosition(const Range* r){ return r ? r->endPosition() : Position();}} // namespace WebCore#ifndef NDEBUGvoid showTree(const WebCore::Position& pos){ pos.showTreeForThis();}void showTree(const WebCore::Position* pos){ if (pos) pos->showTreeForThis();}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -