⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 position.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    Node* lastNode = startNode;    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 isContentEditable().        if (currentNode != lastNode) {            // Don't change editability.            bool currentEditable = currentNode->isContentEditable();            if (startEditable != currentEditable)                break;            lastNode = currentNode;        }        // If we've moved to a position that is visually disinct, 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;        // skip position in unrendered or invisible node        RenderObject* renderer = currentNode->renderer();        if (!renderer || renderer->style()->visibility() != VISIBLE)            continue;                         // track last visible streamer position        if (isStreamer(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;        // Return position after tables and nodes which have content that can be ignored.        if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {            if (currentPos.atEndOfNode())                return Position(currentNode, maxDeepOffset(currentNode));            continue;        }        // return current position if it is in rendered text        if (renderer->isText() && toRenderText(renderer)->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                // render 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 >= renderer->caretMaxOffset());                return Position(currentNode, renderer->caretMaxOffset());            }            unsigned textOffset = currentPos.offsetInLeafNode();            RenderText* textRenderer = toRenderText(renderer);            InlineTextBox* lastTextBox = textRenderer->lastTextBox();            for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {                if (textOffset <= box->start() + box->len()) {                    if (textOffset > box->start())                        return currentPos;                    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->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset)                        continuesOnNextLine = false;                }                otherBox = box;                while (continuesOnNextLine) {                    otherBox = otherBox->prevLeafChild();                    if (!otherBox)                        break;                    if (otherBox == lastTextBox || otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset)                        continuesOnNextLine = false;                }                if (continuesOnNextLine)                    return currentPos;            }        }    }    return lastVisible;}// 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).Position Position::downstream() const{    Node* startNode = node();    if (!startNode)        return Position();    // iterate forward from there, looking for a qualified position    Node* boundary = enclosingVisualBoundary(startNode);    PositionIterator lastVisible = *this;    PositionIterator currentPos = lastVisible;    bool startEditable = startNode->isContentEditable();    Node* lastNode = startNode;    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 isContentEditable().        if (currentNode != lastNode) {            // Don't change editability.            bool currentEditable = currentNode->isContentEditable();            if (startEditable != currentEditable)                break;            lastNode = currentNode;        }        // stop before going above the body, up into the head        // return the last visible streamer position        if (currentNode->hasTagName(bodyTag) && currentPos.atEndOfNode())            break;                    // Do not move to a visually distinct position.        if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)            return lastVisible;        // 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 && boundary->parentNode() == currentNode)            return lastVisible;        // skip position in unrendered or invisible node        RenderObject* renderer = currentNode->renderer();        if (!renderer || renderer->style()->visibility() != VISIBLE)            continue;                    // track last visible streamer position        if (isStreamer(currentPos))            lastVisible = currentPos;        // Return position before tables and nodes which have content that can be ignored.        if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {            if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())                return Position(currentNode, renderer->caretMinOffset());            continue;        }        // return current position if it is in rendered text        if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {            if (currentNode != startNode) {                ASSERT(currentPos.atStartOfNode());                return Position(currentNode, renderer->caretMinOffset());            }            unsigned textOffset = currentPos.offsetInLeafNode();            RenderText* textRenderer = toRenderText(renderer);            InlineTextBox* lastTextBox = textRenderer->lastTextBox();            for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {                if (textOffset <= box->end()) {                    if (textOffset >= box->start())                        return currentPos;                    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->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset)                        continuesOnNextLine = false;                }                otherBox = box;                while (continuesOnNextLine) {                    otherBox = otherBox->prevLeafChild();                    if (!otherBox)                        break;                    if (otherBox == lastTextBox || otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset)                        continuesOnNextLine = false;                }                if (continuesOnNextLine)                    return currentPos;            }        }    }        return lastVisible;}bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* renderer){    RenderObject* stop = renderer->nextInPreOrderAfterChildren();    for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder())        if (o->node()) {            if ((o->isText() && toRenderText(o)->linesBoundingBox().height()) ||                (o->isBox() && toRenderBox(o)->borderBoundingBox().height()))                return true;        }    return false;}bool Position::nodeIsUserSelectNone(Node* node){    return node && node->renderer() && node->renderer()->style()->userSelect() == SELECT_NONE;}bool Position::isCandidate() const{    if (isNull())        return false;            RenderObject *renderer = node()->renderer();    if (!renderer)        return false;        if (renderer->style()->visibility() != VISIBLE)        return false;    if (renderer->isBR())        return offset() == 0 && !nodeIsUserSelectNone(node()->parent());    if (renderer->isText())        return inRenderedText() && !nodeIsUserSelectNone(node());    if (isTableElement(node()) || editingIgnoresContent(node()))        return (offset() == 0 || offset() == maxDeepOffset(node())) && !nodeIsUserSelectNone(node()->parent());    if (!node()->hasTagName(htmlTag) && renderer->isBlockFlow() && !hasRenderedNonAnonymousDescendantsWithHeight(renderer) &&       (toRenderBox(renderer)->height() || node()->hasTagName(bodyTag)))        return offset() == 0 && !nodeIsUserSelectNone(node());        return false;}bool Position::inRenderedText() const{    if (isNull() || !node()->isTextNode())        return false;            RenderObject *renderer = node()->renderer();    if (!renderer)        return false;        RenderText *textRenderer = toRenderText(renderer);    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {        if (offset() < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {            // The offset we're looking for is before this node            // this means the offset must be in content that is            // not rendered. Return false.            return false;        }        if (box->containsCaretOffset(offset()))            // Return false for offsets inside composed characters.            return offset() == 0 || offset() == textRenderer->nextOffset(textRenderer->previousOffset(offset()));    }        return false;}static unsigned caretMaxRenderedOffset(const Node* n){    RenderObject* r = n->renderer();    if (r)        return r->caretMaxRenderedOffset();        if (n->isCharacterDataNode())        return static_cast<const CharacterData*>(n)->length();    return 1;}bool Position::isRenderedCharacter() const{    if (isNull() || !node()->isTextNode())        return false;            RenderObject* renderer = node()->renderer();    if (!renderer)        return false;        RenderText* textRenderer = toRenderText(renderer);    for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {        if (offset() < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {            // The offset we're looking for is before this node            // this means the offset must be in content that is            // not rendered. Return false.            return false;        }        if (offset() >= static_cast<int>(box->start()) && offset() < static_cast<int>(box->start() + box->len()))            return true;    }        return false;}bool Position::rendersInDifferentPosition(const Position &pos) const{    if (isNull() || pos.isNull())        return false;    RenderObject *renderer = node()->renderer();    if (!renderer)        return false;        RenderObject *posRenderer = pos.node()->renderer();    if (!posRenderer)        return false;    if (renderer->style()->visibility() != VISIBLE ||        posRenderer->style()->visibility() != VISIBLE)        return false;        if (node() == pos.node()) {        if (node()->hasTagName(brTag))            return false;        if (offset() == pos.offset())            return false;                    if (!node()->isTextNode() && !pos.node()->isTextNode()) {            if (offset() != pos.offset())                return true;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -