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

📄 bidi.cpp

📁 最新Nokia手机浏览器全套源代码完美版。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    bool lastLine = !end.obj;
    if (end.obj && end.pos == 0)
        endObject = end.obj;
    lastLineBox()->determineSpacingForFlowBoxes(lastLine, endObject);

    // Now mark the line boxes as being constructed.
    lastLineBox()->setConstructed();

    // Return the last line.
    return lastRootBox();
}

// usage: tw - (xpos % tw);
int RenderBlock::tabWidth(bool isWhitespacePre)
{
    if (!isWhitespacePre)
        return 0;

    if (!m_tabWidth) {
        QChar   spaceChar(' ');
        const Font& font = style()->htmlFont();
        int spaceWidth = font.width(&spaceChar, 1, 0, 0);
        m_tabWidth = spaceWidth * 8;
        assert(m_tabWidth != 0);
    }

    return m_tabWidth;
}

void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiState &bidi)
{
    // First determine our total width.
    int availableWidth = lineWidth(m_height);
    int totWidth = lineBox->getFlowSpacingWidth();
    BidiRun* r = 0;
    for (r = sFirstBidiRun; r; r = r->nextRun) {
        if (!r->box || r->obj->isPositioned())
            continue; // Positioned objects are only participating to figure out their
                      // correct static x position.  They have no effect on the width.
        if (r->obj->isText()) {
            int textWidth = static_cast<RenderText *>(r->obj)->width(r->start, r->stop-r->start, totWidth, m_firstLine);
            if (!r->compact) {
                RenderStyle *style = r->obj->style();
                if (style->whiteSpace() == NORMAL && style->khtmlLineBreak() == AFTER_WHITE_SPACE) {
                    // shrink the box as needed to keep the line from overflowing the available width
                    textWidth = kMin(textWidth, availableWidth - totWidth + style->borderLeftWidth());
                }
            }
            r->box->setWidth(textWidth);
        }
        else if (!r->obj->isInlineFlow()) {
            r->obj->calcWidth();
            r->box->setWidth(r->obj->width());
            if (!r->compact)
                totWidth += r->obj->marginLeft() + r->obj->marginRight();
        }

        // Compacts don't contribute to the width of the line, since they are placed in the margin.
        if (!r->compact)
            totWidth += r->box->width();
    }

    // Armed with the total width of the line (without justification),
    // we now examine our text-align property in order to determine where to position the
    // objects horizontally.  The total width of the line can be increased if we end up
    // justifying text.
    int x = leftOffset(m_height);
    switch(style()->textAlign()) {
        case LEFT:
        case KHTML_LEFT:
            // The direction of the block should determine what happens with wide lines.  In
            // particular with RTL blocks, wide lines should still spill out to the left.
            if (style()->direction() == RTL && totWidth > availableWidth)
                x -= (totWidth - availableWidth);
            numSpaces = 0;
            break;
        case JUSTIFY:
            if (numSpaces != 0 && !bidi.current.atEnd() && !lineBox->endsWithBreak())
                break;
            // fall through
        case TAAUTO:
            numSpaces = 0;
            // for right to left fall through to right aligned
            if (bidi.context->basicDir == QChar::DirL)
                break;
        case RIGHT:
        case KHTML_RIGHT:
            // Wide lines spill out of the block based off direction.
            // So even if text-align is right, if direction is LTR, wide lines should overflow out of the right
            // side of the block.
            if (style()->direction() == RTL || totWidth < availableWidth)
                x += availableWidth - totWidth;
            numSpaces = 0;
            break;
        case CENTER:
        case KHTML_CENTER:
            int xd = (availableWidth - totWidth)/2;
            x += xd >0 ? xd : 0;
            numSpaces = 0;
            break;
    }

    if (numSpaces > 0) {
        for (r = sFirstBidiRun; r; r = r->nextRun) {
            if (!r->box) continue;

            int spaceAdd = 0;
            if (numSpaces > 0 && r->obj->isText() && !r->compact) {
                // get the number of spaces in the run
                int spaces = 0;
                for ( int i = r->start; i < r->stop; i++ ) {
                    const QChar c = static_cast<RenderText *>(r->obj)->text()[i];
                    if (c == ' ' || c == '\n' || c == '\t')
                        spaces++;
                }

                KHTMLAssert(spaces <= numSpaces);

                // Only justify text with white-space: normal.
                if (r->obj->style()->whiteSpace() != PRE) {

#if NOKIA_CHANGES
                    RenderCanvas* c = canvas();
                    if(c) {
                       if(c->view()) {
                           int bidiWidth = c->view()->maxBidiWidth();
                           bidiWidth = QMAX(bidiWidth - leftOffset(m_height),0);
                           availableWidth = QMIN(availableWidth,bidiWidth);
                       }
                    }
#endif
                    spaceAdd = (availableWidth - totWidth)*spaces/numSpaces;
                    static_cast<InlineTextBox*>(r->box)->setSpaceAdd(spaceAdd);
                    totWidth += spaceAdd;
                }
                numSpaces -= spaces;
            }
        }
    }
    
    // The widths of all runs are now known.  We can now place every inline box (and
    // compute accurate widths for the inline flow boxes).
    int leftPosition = x;
    int rightPosition = x;
    lineBox->placeBoxesHorizontally(x, leftPosition, rightPosition);
    lineBox->setHorizontalOverflowPositions(leftPosition, rightPosition);
}

void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox)
{
    lineBox->verticallyAlignBoxes(m_height);
    lineBox->setBlockHeight(m_height);

    // See if the line spilled out.  If so set overflow height accordingly.
    int bottomOfLine = lineBox->bottomOverflow();
    if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
        m_overflowHeight = bottomOfLine;
        
    // Now make sure we place replaced render objects correctly.
    for (BidiRun* r = sFirstBidiRun; r; r = r->nextRun) {
        if (!r->box) continue; // Skip runs with no line boxes.

        // Align positioned boxes with the top of the line box.  This is
        // a reasonable approximation of an appropriate y position.
        if (r->obj->isPositioned())
            r->box->setYPos(m_height);

        // Position is used to properly position both replaced elements and
        // to update the static normal flow x/y of positioned elements.
        r->obj->position(r->box, r->start, r->stop - r->start, r->level%2);
    }
}

// collects one line of the paragraph and transforms it to visual order
void RenderBlock::bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi)
{
    if ( start == end ) {
        if ( start.current() == '\n' ) {
            m_height += lineHeight( m_firstLine, true );
        }
        return;
    }

#if BIDI_DEBUG > 1
    kdDebug(6041) << "reordering Line from " << start.obj << "/" << start.pos << " to " << end.obj << "/" << end.pos << endl;
#endif

    sFirstBidiRun = 0;
    sLastBidiRun = 0;
    sBidiRunCount = 0;
    
    //    context->ref();

    dir = bidi.context->dir;

    emptyRun = true;
    bidi.eor.obj = 0;

    numSpaces = 0;

    bidi.current = start;
    bidi.last = bidi.current;
    bool atEnd = false;

    while( 1 ) {

        QChar::Direction dirCurrent;
        if (atEnd) {
            //kdDebug(6041) << "atEnd" << endl;
            BidiContext *c = bidi.context;
            if ( bidi.current.atEnd())
                while ( c->parent )
                    c = c->parent;
            dirCurrent = c->dir;
        } else {
            dirCurrent = bidi.current.direction();
        }

#ifndef QT_NO_UNICODETABLES

#if BIDI_DEBUG > 1
        kdDebug(6041) << "directions: dir=" << (int)dir << " current=" << (int)dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << (int)context->dir << " level =" << (int)context->level << endl;
#endif

        switch(dirCurrent) {

            // embedding and overrides (X1-X9 in the Bidi specs)
        case QChar::DirRLE:
        case QChar::DirLRE:
        case QChar::DirRLO:
        case QChar::DirLRO:
        case QChar::DirPDF:
            embed( dirCurrent, bidi );
            break;

            // strong types
        case QChar::DirL:
            if(dir == QChar::DirON)
                dir = QChar::DirL;
            switch(bidi.status.last)
                {
                case QChar::DirR:
                case QChar::DirAL:
                case QChar::DirEN:
                case QChar::DirAN:
                    if (bidi.status.last != QChar::DirEN || bidi.status.lastStrong != QChar::DirL)
                        appendRun( bidi );
                    dir = QChar::DirL;
                    // fall through
                case QChar::DirL:
                    bidi.eor = bidi.current;
                    bidi.status.eor = QChar::DirL;
                    break;
                case QChar::DirES:
                case QChar::DirET:
                case QChar::DirCS:
                case QChar::DirBN:
                case QChar::DirB:
                case QChar::DirS:
                case QChar::DirWS:
                case QChar::DirON:
                    if (bidi.status.eor == QChar::DirEN) {
                        if (bidi.status.lastStrong != QChar::DirL) {
                            // the numbers need to be on a higher embedding level, so let's close that run
                            dir = QChar::DirEN;
                            appendRun(bidi);
                            if (bidi.context->dir != QChar::DirL) {
                                // the neutrals take the embedding direction, which is R
                                bidi.eor = bidi.last;
                                dir = QChar::DirR;
                                appendRun(bidi);
                            }
                        }
                    } else if (bidi.status.eor == QChar::DirAN) {
                        // Arabic numbers are always on a higher embedding level, so let's close that run
                        dir = QChar::DirAN;
                        appendRun(bidi);
                        if (bidi.context->dir != QChar::DirL) {
                            // the neutrals take the embedding direction, which is R
                            bidi.eor = bidi.last;
                            dir = QChar::DirR;
                            appendRun(bidi);
                        }
                    } else if(bidi.status.eor != QChar::DirL) {
                        //last stuff takes embedding dir
                        if(bidi.context->dir == QChar::DirL || bidi.status.lastStrong == QChar::DirL) { 
                            if (bidi.status.eor != QChar::DirON) 
                            appendRun( bidi );
                        } else {
                            dir = QChar::DirR; 
                            bidi.eor = bidi.last; 
                            appendRun( bidi ); 
                        }
                    }
                    bidi.eor = bidi.current;
                    bidi.status.eor = QChar::DirL;
                    dir = QChar::DirL;
                default:
                    break;
                }
            bidi.status.lastStrong = QChar::DirL;
            break;
        case QChar::DirAL:
        case QChar::DirR:
            if(dir == QChar::DirON) dir = QChar::DirR;
            switch(bidi.status.last)
                {
                case QChar::DirR:
                case QChar::DirAL:
                    bidi.eor = bidi.current; bidi.status.eor = QChar::DirR; break;
                case QChar::DirL:
                case QChar::DirEN:
                case QChar::DirAN:
                    appendRun( bidi );
		    dir = QChar::DirR;
		    bidi.eor = bidi.current;
		    bidi.status.eor = QChar::DirR;
                    break;
                case QChar::DirES:
                case QChar::DirET:
                case QChar::DirCS:
                case QChar::DirBN:
                case QChar::DirB:
                case QChar::DirS:
                case QChar::DirWS:
                case QChar::DirON:
                    if( !(bidi.status.eor == QChar::DirR) && !(bidi.status.eor == QChar::DirAL) ) {
                        //last stuff takes embedding dir
                        if(bidi.context->dir == QChar::DirR || bidi.status.lastStrong == QChar::DirR 
                            || bidi.status.lastStrong == QChar::DirAL) { 
                            appendRun( bidi );
                            dir = QChar::DirR;
                            bidi.eor = bidi.current;
			    bidi.status.eor = QChar::DirR;
                        } else {
                            dir = QChar::DirL; 
                            bidi.eor = bidi.last;
                            appendRun( bidi );
                            dir = QChar::DirR;
			    bidi.status.eor = QChar::DirR;
                        }
                    } else {
                        bidi.eor = bidi.current; bidi.status.eor = QChar::DirR;
                    }
                default:
                    break;
                }
            bidi.status.lastStrong = dirCurrent;
            break;

            // weak types:

        case QChar::DirNSM:
            // ### if @sor, set dir to dirSor
            break;
        case QChar::DirEN:
            if(!(bidi.status.lastStrong == QChar::DirAL)) {

⌨️ 快捷键说明

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