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

📄 visibleposition.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */#include "config.h"#include "VisiblePosition.h"#include "CString.h"#include "Document.h"#include "Element.h"#include "FloatQuad.h"#include "HTMLNames.h"#include "InlineTextBox.h"#include "Logging.h"#include "Range.h"#include "Text.h"#include "htmlediting.h"#include "visible_units.h"#include <stdio.h>namespace WebCore {using namespace HTMLNames;VisiblePosition::VisiblePosition(const Position &pos, EAffinity affinity){    init(pos, affinity);}VisiblePosition::VisiblePosition(Node *node, int offset, EAffinity affinity){    ASSERT(offset >= 0);    init(Position(node, offset), affinity);}void VisiblePosition::init(const Position& position, EAffinity affinity){    m_affinity = affinity;        m_deepPosition = canonicalPosition(position);        // When not at a line wrap, make sure to end up with DOWNSTREAM affinity.    if (m_affinity == UPSTREAM && (isNull() || inSameLine(VisiblePosition(position, DOWNSTREAM), *this)))        m_affinity = DOWNSTREAM;}VisiblePosition VisiblePosition::next(bool stayInEditableContent) const{    VisiblePosition next(nextVisuallyDistinctCandidate(m_deepPosition), m_affinity);        if (!stayInEditableContent)        return next;        return honorEditableBoundaryAtOrAfter(next);}VisiblePosition VisiblePosition::previous(bool stayInEditableContent) const{    // find first previous DOM position that is visible    Position pos = previousVisuallyDistinctCandidate(m_deepPosition);        // return null visible position if there is no previous visible position    if (pos.atStart())        return VisiblePosition();            VisiblePosition prev = VisiblePosition(pos, DOWNSTREAM);    ASSERT(prev != *this);    #ifndef NDEBUG    // we should always be able to make the affinity DOWNSTREAM, because going previous from an    // UPSTREAM position can never yield another UPSTREAM position (unless line wrap length is 0!).    if (prev.isNotNull() && m_affinity == UPSTREAM) {        VisiblePosition temp = prev;        temp.setAffinity(UPSTREAM);        ASSERT(inSameLine(temp, prev));    }#endif    if (!stayInEditableContent)        return prev;        return honorEditableBoundaryAtOrBefore(prev);}Position VisiblePosition::leftVisuallyDistinctCandidate() const{    Position p = m_deepPosition;    if (!p.node())        return Position();    Position downstreamStart = p.downstream();    TextDirection primaryDirection = LTR;    for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) {        if (r->isBlockFlow()) {            primaryDirection = r->style()->direction();            break;        }    }    while (true) {        InlineBox* box;        int offset;        p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset);        if (!box)            return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);        RenderObject* renderer = box->renderer();        while (true) {            if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretRightmostOffset())                return box->direction() == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);            offset = box->direction() == LTR ? renderer->previousOffset(offset) : renderer->nextOffset(offset);            int caretMinOffset = box->caretMinOffset();            int caretMaxOffset = box->caretMaxOffset();            if (offset > caretMinOffset && offset < caretMaxOffset)                break;            if (box->direction() == LTR ? offset < caretMinOffset : offset > caretMaxOffset) {                // Overshot to the left.                InlineBox* prevBox = box->prevLeafChild();                if (!prevBox)                    return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);                // Reposition at the other logical position corresponding to our edge's visual position and go for another round.                box = prevBox;                renderer = box->renderer();                offset = prevBox->caretRightmostOffset();                continue;            }            ASSERT(offset == box->caretLeftmostOffset());            unsigned char level = box->bidiLevel();            InlineBox* prevBox = box->prevLeafChild();            if (box->direction() == primaryDirection) {                if (!prevBox || prevBox->bidiLevel() >= level)                    break;                level = prevBox->bidiLevel();                InlineBox* nextBox = box;                do {                    nextBox = nextBox->nextLeafChild();                } while (nextBox && nextBox->bidiLevel() > level);                if (nextBox && nextBox->bidiLevel() == level)                    break;                while (InlineBox* prevBox = box->prevLeafChild()) {                    if (prevBox->bidiLevel() < level)                        break;                    box = prevBox;                }                renderer = box->renderer();                offset = box->caretRightmostOffset();                if (box->direction() == primaryDirection)                    break;                continue;            }            if (prevBox) {                box = prevBox;                renderer = box->renderer();                offset = box->caretRightmostOffset();                if (box->bidiLevel() > level) {                    do {                        prevBox = box->prevLeafChild();                    } while (prevBox && prevBox->bidiLevel() > level);                    if (!prevBox || prevBox->bidiLevel() < level)                        continue;                }            } else {                // Trailing edge of a secondary run. Set to the leading edge of the entire run.                while (true) {                    while (InlineBox* nextBox = box->nextLeafChild()) {                        if (nextBox->bidiLevel() < level)                            break;                        box = nextBox;                    }                    if (box->bidiLevel() == level)                        break;                    level = box->bidiLevel();                    while (InlineBox* prevBox = box->prevLeafChild()) {                        if (prevBox->bidiLevel() < level)                            break;                        box = prevBox;                    }                    if (box->bidiLevel() == level)                        break;                    level = box->bidiLevel();                }                renderer = box->renderer();                offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset();            }            break;        }        p = Position(renderer->node(), offset);        if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd())            return p;    }}VisiblePosition VisiblePosition::left(bool stayInEditableContent) const{    Position pos = leftVisuallyDistinctCandidate();    if (pos.atStart() || pos.atEnd())        return VisiblePosition();    VisiblePosition left = VisiblePosition(pos, DOWNSTREAM);    ASSERT(left != *this);    if (!stayInEditableContent)        return left;    // FIXME: This may need to do something different from "before".    return honorEditableBoundaryAtOrBefore(left);}Position VisiblePosition::rightVisuallyDistinctCandidate() const{    Position p = m_deepPosition;    if (!p.node())        return Position();    Position downstreamStart = p.downstream();    TextDirection primaryDirection = LTR;    for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) {        if (r->isBlockFlow()) {            primaryDirection = r->style()->direction();            break;        }    }    while (true) {        InlineBox* box;        int offset;        p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset);        if (!box)            return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);        RenderObject* renderer = box->renderer();        while (true) {            if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset())                return box->direction() == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);            offset = box->direction() == LTR ? renderer->nextOffset(offset) : renderer->previousOffset(offset);            int caretMinOffset = box->caretMinOffset();            int caretMaxOffset = box->caretMaxOffset();            if (offset > caretMinOffset && offset < caretMaxOffset)                break;            if (box->direction() == LTR ? offset > caretMaxOffset : offset < caretMinOffset) {                // Overshot to the right.                InlineBox* nextBox = box->nextLeafChild();                if (!nextBox)                    return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);                // Reposition at the other logical position corresponding to our edge's visual position and go for another round.                box = nextBox;                renderer = box->renderer();                offset = nextBox->caretLeftmostOffset();                continue;            }            ASSERT(offset == box->caretRightmostOffset());            unsigned char level = box->bidiLevel();            InlineBox* nextBox = box->nextLeafChild();            if (box->direction() == primaryDirection) {                if (!nextBox || nextBox->bidiLevel() >= level)                    break;                level = nextBox->bidiLevel();                InlineBox* prevBox = box;                do {                    prevBox = prevBox->prevLeafChild();                } while (prevBox && prevBox->bidiLevel() > level);                if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA                    break;                // For example, abc 123 ^ CBA                while (InlineBox* nextBox = box->nextLeafChild()) {                    if (nextBox->bidiLevel() < level)                        break;                    box = nextBox;                }                renderer = box->renderer();                offset = box->caretLeftmostOffset();                if (box->direction() == primaryDirection)                    break;                continue;            }            if (nextBox) {                box = nextBox;                renderer = box->renderer();                offset = box->caretLeftmostOffset();                if (box->bidiLevel() > level) {                    do {                        nextBox = box->nextLeafChild();                    } while (nextBox && nextBox->bidiLevel() > level);                    if (!nextBox || nextBox->bidiLevel() < level)                        continue;                }            } else {                // Trailing edge of a secondary run. Set to the leading edge of the entire run.                while (true) {

⌨️ 快捷键说明

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