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

📄 bidi.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:

        BidiContext *startEmbed;
        if( style()->direction() == LTR ) {
            startEmbed = new BidiContext( 0, QChar::DirL );
            bidi.status.eor = QChar::DirL;
        } else {
            startEmbed = new BidiContext( 1, QChar::DirR );
            bidi.status.eor = QChar::DirR;
        }
        startEmbed->ref();

	bidi.status.lastStrong = QChar::DirON;
	bidi.status.last = QChar::DirON;
        bidi.context = startEmbed;

        if (!smidpoints)
            smidpoints = new QMemArray<BidiIterator>;

        sNumMidpoints = 0;
        sCurrMidpoint = 0;
        sCompactFirstBidiRun = sCompactLastBidiRun = 0;
        sCompactBidiRunCount = 0;

        // We want to skip ahead to the first dirty line
        BidiIterator start;
        RootInlineBox* startLine = determineStartPosition(fullLayout, start, bidi);

        // We also find the first clean line and extract these lines.  We will add them back
        // if we determine that we're able to synchronize after handling all our dirty lines.
        BidiIterator cleanLineStart;
        int endLineYPos;
        RootInlineBox* endLine = (fullLayout || !startLine) ?
                                 0 : determineEndPosition(startLine, cleanLineStart, endLineYPos);
        if (startLine) {
            useRepaintRect = true;
            startLineBottom = startLine->bottomOverflow();
            repaintRect.setY(kMin(m_height, startLine->topOverflow()));
            RenderArena* arena = renderArena();
            RootInlineBox* box = startLine;
            while (box) {
                RootInlineBox* next = box->nextRootBox();
                box->deleteLine(arena);
                box = next;
            }
            startLine = 0;
        }

        BidiIterator end = start;

        bool endLineMatched = false;
        while (!end.atEnd()) {
            start = end;
            if (endLine && (endLineMatched = matchedEndLine(start, cleanLineStart, endLine, endLineYPos)))
                break;

            betweenMidpoints = false;
            isLineEmpty = true;
            if (m_firstLine && firstChild() && firstChild()->isCompact() && firstChild()->isRenderBlock()) {
                buildCompactRuns(firstChild(), bidi);
                start.obj = firstChild()->nextSibling();
                end = start;
            }
            end = findNextLineBreak(start, bidi);
            if( start.atEnd() ) break;
            if (!isLineEmpty) {
                bidiReorderLine(start, end, bidi);

                // Now that the runs have been ordered, we create the line boxes.
                // At the same time we figure out where border/padding/margin should be applied for
                // inline flow boxes.
                if (sCompactFirstBidiRun) {
                    // We have a compact line sharing this line.  Link the compact runs
                    // to our runs to create a single line of runs.
                    sCompactLastBidiRun->nextRun = sFirstBidiRun;
                    sFirstBidiRun = sCompactFirstBidiRun;
                    sBidiRunCount += sCompactBidiRunCount;
                }

                RootInlineBox* lineBox = 0;
                if (sBidiRunCount) {
                    lineBox = constructLine(start, end);
                    if (lineBox) {
                        lineBox->setEndsWithBreak(previousLineBrokeCleanly);

                        // Now we position all of our text runs horizontally.
                        computeHorizontalPositionsForLine(lineBox, bidi);

                        // Now position our text runs vertically.
                        computeVerticalPositionsForLine(lineBox);

                        deleteBidiRuns(renderArena());
                    }
                }

                if (end == start || (!previousLineBrokeCleanly && end.obj && end.obj->style()->whiteSpace() == PRE && end.current() == QChar('\n'))) {
                    adjustEmbedding = true;
                    end.increment(bidi);
                    adjustEmbedding = false;
                }

                if (lineBox)
                    lineBox->setLineBreakInfo(end.obj, end.pos);

                m_firstLine = false;
                newLine();
            }

            sNumMidpoints = 0;
            sCurrMidpoint = 0;
            sCompactFirstBidiRun = sCompactLastBidiRun = 0;
            sCompactBidiRunCount = 0;
        }
        startEmbed->deref();
        //embed->deref();

        if (endLine) {
            if (endLineMatched) {
                // Note our current y-position for correct repainting when no lines move.  If no lines move, we still have to
                // repaint up to the maximum of the bottom overflow of the old start line or the bottom overflow of the new last line.
                int currYPos = kMax(startLineBottom, m_height);
                if (lastRootBox())
                    currYPos = kMax(currYPos, lastRootBox()->bottomOverflow());

                // Attach all the remaining lines, and then adjust their y-positions as needed.
                for (RootInlineBox* line = endLine; line; line = line->nextRootBox())
                    line->attachLine();

                // Now apply the offset to each line if needed.
                int delta = m_height - endLineYPos;
                if (delta)
                    for (RootInlineBox* line = endLine; line; line = line->nextRootBox())
                        line->adjustPosition(0, delta);
                m_height = lastRootBox()->blockHeight();
                m_overflowHeight = kMax(m_height, m_overflowHeight);
                int bottomOfLine = lastRootBox()->bottomOverflow();
                if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
                    m_overflowHeight = bottomOfLine;
                if (delta)
                    repaintRect.setHeight(kMax(m_overflowHeight-delta, m_overflowHeight) - repaintRect.y());
                else
                    repaintRect.setHeight(currYPos - repaintRect.y());
            }
            else {
                // Delete all the remaining lines.
                m_overflowHeight = kMax(m_height, m_overflowHeight);
                InlineRunBox* line = endLine;
                RenderArena* arena = renderArena();
                while (line) {
                    InlineRunBox* next = line->nextLineBox();
                    if (!next)
                        repaintRect.setHeight(kMax(m_overflowHeight, line->bottomOverflow()) - repaintRect.y());
                    line->deleteLine(arena);
                    line = next;
                }
            }
        }
    }

    sNumMidpoints = 0;
    sCurrMidpoint = 0;

    // in case we have a float on the last line, it might not be positioned up to now.
    // This has to be done before adding in the bottom border/padding, or the float will
    // include the padding incorrectly. -dwh
    positionNewFloats();

    // Now add in the bottom border/padding.
    m_height += toAdd;

    // Always make sure this is at least our height.
    m_overflowHeight = kMax(m_height, m_overflowHeight);

    // See if any lines spill out of the block.  If so, we need to update our overflow width.
    checkLinesForOverflow();

    if (useRepaintRect) {
        repaintRect.setWidth(kMax((int)m_width, m_overflowWidth));
        if (repaintRect.height() == 0)
            repaintRect.setHeight(kMax(oldLineBottom, m_overflowHeight) - repaintRect.y());
    }

    if (!firstLineBox() && element() && element()->isContentEditable() && element()->rootEditableElement() == element())
        m_height += lineHeight(true);

    // See if we have any lines that spill out of our block.  If we do, then we will possibly need to
    // truncate text.
    if (hasTextOverflow)
        checkLinesForTextOverflow();

    return repaintRect;

#if BIDI_DEBUG > 1
    kdDebug(6041) << " ------- bidi end " << this << " -------" << endl;
#endif
    //kdDebug() << "RenderBlock::layoutInlineChildren time used " << qt.elapsed() << endl;
    //kdDebug(6040) << "height = " << m_height <<endl;
}

RootInlineBox* RenderBlock::determineStartPosition(bool fullLayout, BidiIterator& start, BidiState& bidi)
{
    RootInlineBox* curr = 0;
    RootInlineBox* last = 0;
    RenderObject* startObj = 0;
    int pos = 0;

    if (fullLayout) {
        // Nuke all our lines.
        if (firstRootBox()) {
            RenderArena* arena = renderArena();
            curr = firstRootBox();
            while (curr) {
                RootInlineBox* next = curr->nextRootBox();
                curr->deleteLine(arena);
                curr = next;
            }
            KHTMLAssert(!m_firstLineBox && !m_lastLineBox);
        }
    }
    else {
        for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox());
        if (curr) {
            // We have a dirty line.
            if (curr->prevRootBox()) {
                // We have a previous line.
                if (!curr->prevRootBox()->endsWithBreak())
                    curr = curr->prevRootBox();  // The previous line didn't break cleanly, so treat it as dirty also.
            }
        }
        else {
            // No dirty lines were found.
            // If the last line didn't break cleanly, treat it as dirty.
            if (lastRootBox() && !lastRootBox()->endsWithBreak())
                curr = lastRootBox();
        }

        // If we have no dirty lines, then last is just the last root box.
        last = curr ? curr->prevRootBox() : lastRootBox();
    }

    m_firstLine = !last;
    previousLineBrokeCleanly = !last || last->endsWithBreak();
    if (last) {
        m_height = last->blockHeight();
        int bottomOfLine = last->bottomOverflow();
        if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
            m_overflowHeight = bottomOfLine;
        startObj = last->lineBreakObj();
        pos = last->lineBreakPos();
    }
    else
        startObj = first(this, bidi, 0);

    adjustEmbedding = true;
    start = BidiIterator(this, startObj, pos);

    adjustEmbedding = false;

    return curr;
}

RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiIterator& cleanLineStart,
                                                 int& yPos)
{
    RootInlineBox* last = 0;
    if (!startLine)
        last = 0;
    else {
        for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) {
            if (curr->isDirty())
                last = 0;
            else if (!last)
                last = curr;
        }
    }

    if (!last)
        return 0;

    cleanLineStart = BidiIterator(this, last->prevRootBox()->lineBreakObj(), last->prevRootBox()->lineBreakPos());
    yPos = last->prevRootBox()->blockHeight();

    for (RootInlineBox* line = last; line; line = line->nextRootBox())
        line->extractLine(); // Disconnect all line boxes from their render objects while preserving
                             // their connections to one another.

    return last;
}

bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiIterator& endLineStart,
                                 RootInlineBox*& endLine, int& endYPos)
{
    if (start == endLineStart) {
        // Need to return false in case the first "clean" line is indirectly dirty from
        // line wrap changes (i.e. could need to shift this line left or right in
        // response to changes on the previous line).
        return false;
    } else {
        // The first clean line doesn't match, but we can check a handful of following lines to try
        // to match back up.
        static int numLines = 8; // The # of lines we're willing to match against.
        RootInlineBox* line = endLine;
        for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
            if (line->lineBreakObj() == start.obj && line->lineBreakPos() == start.pos) {
                // We have a match.
                RootInlineBox* result = line->nextRootBox();

                // Set our yPos to be the block height of endLine.
                if (result)
                    endYPos = line->blockHeight();

                // Now delete the lines that we failed to sync.
                RootInlineBox* boxToDelete = endLine;
                RenderArena* arena = renderArena();
                while (boxToDelete && boxToDelete != result) {
                    RootInlineBox* next = boxToDelete->nextRootBox();
                    boxToDelete->deleteLine(arena);
                    boxToDelete = next;
                }

                endLine = result;
                return result;
            }
        }
    }
    return false;
}

static const ushort nonBreakingSpace = 0xa0;

inline bool RenderBlock::skipNonBreakingSpace(BidiIterator &it)
{
    if (it.obj->style()->nbspMode() != SPACE || it.current().unicode() != nonBreakingSpace)
        return false;

    // Do not skip a non-breaking space if it is the first character
    // on the first line of a block.
    if (m_firstLine && isLineEmpty)
        return false;

    // Do not skip a non-breaking space if it is the first character
    // on a line after a clean line break.
    if (!m_firstLine && isLineEmpty && previousLineBrokeCleanly)
        return false;

    return true;
}

int RenderBlock::skipWhitespace(BidiIterator &it, BidiState &bidi)
{
    // FIXME: The entire concept of the skipWhitespace function is flawed, since we really need to be building
    // line boxes even for containers that may ultimately collapse away.  Otherwise we'll never get positioned
    // elements quite right.  In other words, we need to build this function's work into the normal line
    // object iteration process.
    int w = lineWidth(m_height);
    while (!it.atEnd() && (it.obj->isInlineFlow() || (it.obj->style()->whiteSpace() != PRE && !it.obj->isBR() &&
          (it.current() == ' ' || it.current() == '\n' ||
           skipNonBreakingSpace(it) || it.obj->isFloatingOrPositioned())))) {
        if (it.obj->isFlo

⌨️ 快捷键说明

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