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

📄 textiterator.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                if (renderer->style()->visibility() == VISIBLE && m_offset > 0)                    m_handledNode = handleTextNode();            } else if (renderer && (renderer->isImage() || renderer->isWidget())) {                if (renderer->style()->visibility() == VISIBLE && m_offset > 0)                    m_handledNode = handleReplacedElement();            } else                m_handledNode = handleNonTextNode();            if (m_positionNode)                return;        }        Node* next = m_handledChildren ? 0 : m_node->lastChild();        if (!next) {            // Exit empty containers as we pass over them or containers            // where [container, 0] is where we started iterating.            if (!m_handledNode &&                canHaveChildrenForEditing(m_node) &&                 m_node->parentNode() &&                 (!m_node->lastChild() || m_node == m_endNode && m_endOffset == 0)) {                exitNode();                if (m_positionNode) {                    m_handledNode = true;                    m_handledChildren = true;                    return;                }                        }            // Exit all other containers.            next = m_node->previousSibling();            while (!next) {                if (!m_node->parentNode())                    break;                m_node = m_node->parentNode();                exitNode();                if (m_positionNode) {                    m_handledNode = true;                    m_handledChildren = true;                    return;                }                next = m_node->previousSibling();            }        }                m_node = next;        m_offset = m_node ? caretMaxOffset(m_node) : 0;        m_handledNode = false;        m_handledChildren = false;                if (m_positionNode)            return;    }}bool SimplifiedBackwardsTextIterator::handleTextNode(){    m_lastTextNode = m_node;    RenderText *renderer = toRenderText(m_node->renderer());    String str = renderer->text();    if (!renderer->firstTextBox() && str.length() > 0)        return true;    m_positionEndOffset = m_offset;    m_offset = (m_node == m_startNode) ? m_startOffset : 0;    m_positionNode = m_node;    m_positionStartOffset = m_offset;    m_textLength = m_positionEndOffset - m_positionStartOffset;    m_textCharacters = str.characters() + m_positionStartOffset;    m_lastCharacter = str[m_positionEndOffset - 1];    return true;}bool SimplifiedBackwardsTextIterator::handleReplacedElement(){    unsigned index = m_node->nodeIndex();    // We want replaced elements to behave like punctuation for boundary     // finding, and to simply take up space for the selection preservation     // code in moveParagraphs, so we use a comma.  Unconditionally emit    // here because this iterator is only used for boundary finding.    emitCharacter(',', m_node->parentNode(), index, index + 1);    return true;}bool SimplifiedBackwardsTextIterator::handleNonTextNode(){        // We can use a linefeed in place of a tab because this simple iterator is only used to    // find boundaries, not actual content.  A linefeed breaks words, sentences, and paragraphs.    if (shouldEmitNewlineForNode(m_node) ||        shouldEmitNewlineAfterNode(m_node) ||        shouldEmitTabBeforeNode(m_node)) {        unsigned index = m_node->nodeIndex();        // The start of this emitted range is wrong, ensuring correctness would require        // VisiblePositions and so would be slow.  previousBoundary expects this.        emitCharacter('\n', m_node->parentNode(), index + 1, index + 1);    }        return true;}void SimplifiedBackwardsTextIterator::exitNode(){    if (shouldEmitNewlineForNode(m_node) ||        shouldEmitNewlineBeforeNode(m_node) ||        shouldEmitTabBeforeNode(m_node))        // The start of this emitted range is wrong, ensuring correctness would require        // VisiblePositions and so would be slow.  previousBoundary expects this.        emitCharacter('\n', m_node, 0, 0);}void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node *node, int startOffset, int endOffset){    m_singleCharacterBuffer = c;    m_positionNode = node;    m_positionStartOffset = startOffset;    m_positionEndOffset = endOffset;    m_textCharacters = &m_singleCharacterBuffer;    m_textLength = 1;    m_lastCharacter = c;}PassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const{    if (m_positionNode)        return Range::create(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset);        return Range::create(m_startNode->document(), m_startNode, m_startOffset, m_startNode, m_startOffset);}// --------CharacterIterator::CharacterIterator()    : m_offset(0)    , m_runOffset(0)    , m_atBreak(true){}CharacterIterator::CharacterIterator(const Range *r, bool emitCharactersBetweenAllVisiblePositions, bool enterTextControls)    : m_offset(0)    , m_runOffset(0)    , m_atBreak(true)    , m_textIterator(r, emitCharactersBetweenAllVisiblePositions, enterTextControls){    while (!atEnd() && m_textIterator.length() == 0)        m_textIterator.advance();}PassRefPtr<Range> CharacterIterator::range() const{    RefPtr<Range> r = m_textIterator.range();    if (!m_textIterator.atEnd()) {        if (m_textIterator.length() <= 1) {            ASSERT(m_runOffset == 0);        } else {            Node* n = r->startContainer();            ASSERT(n == r->endContainer());            int offset = r->startOffset() + m_runOffset;            ExceptionCode ec = 0;            r->setStart(n, offset, ec);            r->setEnd(n, offset + 1, ec);            ASSERT(!ec);        }    }    return r.release();}void CharacterIterator::advance(int count){    if (count <= 0) {        ASSERT(count == 0);        return;    }        m_atBreak = false;    // easy if there is enough left in the current m_textIterator run    int remaining = m_textIterator.length() - m_runOffset;    if (count < remaining) {        m_runOffset += count;        m_offset += count;        return;    }    // exhaust the current m_textIterator run    count -= remaining;    m_offset += remaining;        // move to a subsequent m_textIterator run    for (m_textIterator.advance(); !atEnd(); m_textIterator.advance()) {        int runLength = m_textIterator.length();        if (runLength == 0)            m_atBreak = true;        else {            // see whether this is m_textIterator to use            if (count < runLength) {                m_runOffset = count;                m_offset += count;                return;            }                        // exhaust this m_textIterator run            count -= runLength;            m_offset += runLength;        }    }    // ran to the end of the m_textIterator... no more runs left    m_atBreak = true;    m_runOffset = 0;}String CharacterIterator::string(int numChars){    Vector<UChar> result;    result.reserveInitialCapacity(numChars);    while (numChars > 0 && !atEnd()) {        int runSize = min(numChars, length());        result.append(characters(), runSize);        numChars -= runSize;        advance(runSize);    }    return String::adopt(result);}static PassRefPtr<Range> characterSubrange(CharacterIterator& it, int offset, int length){    it.advance(offset);    RefPtr<Range> start = it.range();    if (length > 1)        it.advance(length - 1);    RefPtr<Range> end = it.range();    return Range::create(start->startContainer()->document(),         start->startContainer(), start->startOffset(),         end->endContainer(), end->endOffset());}// --------WordAwareIterator::WordAwareIterator(): m_previousText(0), m_didLookAhead(false){}WordAwareIterator::WordAwareIterator(const Range *r): m_previousText(0), m_didLookAhead(false), m_textIterator(r){    m_didLookAhead = true;  // so we consider the first chunk from the text iterator    advance();              // get in position over the first chunk of text}// We're always in one of these modes:// - The current chunk in the text iterator is our current chunk//      (typically its a piece of whitespace, or text that ended with whitespace)// - The previous chunk in the text iterator is our current chunk//      (we looked ahead to the next chunk and found a word boundary)// - We built up our own chunk of text from many chunks from the text iterator// FIXME: Perf could be bad for huge spans next to each other that don't fall on word boundariesvoid WordAwareIterator::advance(){    m_previousText = 0;    m_buffer.clear();      // toss any old buffer we built up    // If last time we did a look-ahead, start with that looked-ahead chunk now    if (!m_didLookAhead) {        ASSERT(!m_textIterator.atEnd());        m_textIterator.advance();    }    m_didLookAhead = false;    // Go to next non-empty chunk     while (!m_textIterator.atEnd() && m_textIterator.length() == 0)        m_textIterator.advance();    m_range = m_textIterator.range();    if (m_textIterator.atEnd())        return;        while (1) {        // If this chunk ends in whitespace we can just use it as our chunk.        if (isSpaceOrNewline(m_textIterator.characters()[m_textIterator.length() - 1]))            return;        // If this is the first chunk that failed, save it in previousText before look ahead        if (m_buffer.isEmpty()) {            m_previousText = m_textIterator.characters();            m_previousLength = m_textIterator.length();        }        // Look ahead to next chunk.  If it is whitespace or a break, we can use the previous stuff        m_textIterator.advance();        if (m_textIterator.atEnd() || m_textIterator.length() == 0 || isSpaceOrNewline(m_textIterator.characters()[0])) {            m_didLookAhead = true;            return;        }        if (m_buffer.isEmpty()) {            // Start gobbling chunks until we get to a suitable stopping point            m_buffer.append(m_previousText, m_previousLength);            m_previousText = 0;        }        m_buffer.append(m_textIterator.characters(), m_textIterator.length());        int exception = 0;        m_range->setEnd(m_textIterator.range()->endContainer(), m_textIterator.range()->endOffset(), exception);    }}int WordAwareIterator::length() const{    if (!m_buffer.isEmpty())        return m_buffer.size();    if (m_previousText)        return m_previousLength;    return m_textIterator.length();}const UChar* WordAwareIterator::characters() const{    if (!m_buffer.isEmpty())        return m_buffer.data();    if (m_previousText)        return m_previousText;    return m_textIterator.characters();}// --------#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATIONstatic const size_t minimumSearchBufferSize = 8192;#ifndef NDEBUGstatic bool searcherInUse;#endifstatic UStringSearch* createSearcher(){    // Provide a non-empty pattern and non-empty text so usearch_open will not fail,    // but it doesn't matter exactly what it is, since we don't perform any searches    // without setting both the pattern and the text.    // Pass empty string for the locale for now to get the Unicode Collation Algorithm,    // rather than something locale-specific.    UErrorCode status = U_ZERO_ERROR;    UStringSearch* searcher = usearch_open(&newlineCharacter, 1, &newlineCharacter, 1, "", 0, &status);    ASSERT(status == U_ZERO_ERROR);    return searcher;}static UStringSearch* searcher(){    static UStringSearch* searcher = createSearcher();    return searcher;}static inline void lockSearcher(){#ifndef NDEBUG    ASSERT(!searcherInUse);    searcherInUse = true;#endif}static inline void unlockSearcher(){#ifndef NDEBUG    ASSERT(searcherInUse);    searcherInUse = false;#endif}inline SearchBuffer::SearchBuffer(const String& target, bool isCaseSensitive)    : m_target(target)    , m_atBreak(true){    ASSERT(!m_target.isEmpty());    size_t targetLength = target.length();    m_buffer.reserveInitialCapacity(max(targetLength * 8, minimumSearchBufferSize));    m_overlap = m_buffer.capacity() / 4;    // Grab the single global searcher.    // If we ever have a reason to do more than once search buffer at once, we'll have    // to move to multiple searchers.    lockSearcher();    UStringSearch* searcher = WebCore::searcher();    UCollator* collator = usearch_getCollator(searcher);    UCollationStrength strength = isCaseSensitive ? UCOL_TERTIARY : UCOL_PRIMARY;    if (ucol_getStrength(collator) != strength) {        ucol_setStrength(collator, strength);        usearch_reset(searcher);    }    UErrorCode status = U_ZERO_ERROR;    usearch_setPattern(searcher, m_target.characters(), targetLength, &status);    ASSERT(status == U_ZERO_ERROR);}inline SearchBuffer::~SearchBuffer(){    unlockSearcher();}inline size_t SearchBuffer::append(const UChar* characters, size_t length){    ASSERT(length);    if (m_atBreak) {        m_buffer.shrink(0);        m_atBreak = false;    } else if (m_buffer.size() == m_buffer.capacity()) {        memcpy(m_buffer.data(), m_buffer.data() + m_buffer.size() - m_overlap, m_overlap * sizeof(UChar));        m_buffer.shrink(m_overlap);

⌨️ 快捷键说明

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