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

📄 bidi.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                        else if( bidi.status.eor == QChar::DirL ||
                                 (bidi.status.eor == QChar::DirEN && bidi.status.lastStrong == QChar::DirL)) {
                            bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
                        } else {
                            // numbers on both sides, neutrals get right to left direction
                            if(dir != QChar::DirL) {
                                appendRun( bidi );
                                bidi.eor = bidi.last;
                                dir = QChar::DirR;
                                appendRun( bidi );
                                dir = QChar::DirEN;
                                bidi.status.eor = QChar::DirEN;
                            } else {
                                bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
                            }
                        }
                    default:
                        break;
                    }
                break;
            }
        case QChar::DirAN:
            dirCurrent = QChar::DirAN;
            if(dir == QChar::DirON) dir = QChar::DirAN;
            switch(bidi.status.last)
                {
                case QChar::DirL:
                case QChar::DirAN:
                    bidi.eor = bidi.current; bidi.status.eor = QChar::DirAN; break;
                case QChar::DirR:
                case QChar::DirAL:
                case QChar::DirEN:
                    appendRun( bidi );
                    dir = QChar::DirAN; bidi.status.eor = QChar::DirAN;
                    break;
                case QChar::DirCS:
                    if(bidi.status.eor == QChar::DirAN) {
                        bidi.eor = bidi.current; bidi.status.eor = QChar::DirR; break;
                    }
                case QChar::DirES:
                case QChar::DirET:
                case QChar::DirBN:
                case QChar::DirB:
                case QChar::DirS:
                case QChar::DirWS:
                case QChar::DirON:
                    if(bidi.status.eor == QChar::DirR) {
                        // neutrals go to R
                        bidi.eor = bidi.last;
                        appendRun( bidi );
                        dir = QChar::DirAN;
                        bidi.status.eor = QChar::DirAN;
                    } else if( bidi.status.eor == QChar::DirL ||
                               (bidi.status.eor == QChar::DirEN && bidi.status.lastStrong == QChar::DirL)) {
                        bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
                    } else {
                        // numbers on both sides, neutrals get right to left direction
                        if(dir != QChar::DirL) {
                            appendRun( bidi );
                            bidi.eor = bidi.last;
                            dir = QChar::DirR;
                            appendRun( bidi );
                            dir = QChar::DirAN;
                            bidi.status.eor = QChar::DirAN;
                        } else {
                            bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
                        }
                    }
                default:
                    break;
                }
            break;
        case QChar::DirES:
        case QChar::DirCS:
            break;
        case QChar::DirET:
            if(bidi.status.last == QChar::DirEN) {
                dirCurrent = QChar::DirEN;
                bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
                break;
            }
            break;

        // boundary neutrals should be ignored
        case QChar::DirBN:
            break;
            // neutrals
        case QChar::DirB:
            // ### what do we do with newline and paragraph seperators that come to here?
            break;
        case QChar::DirS:
            // ### implement rule L1
            break;
        case QChar::DirWS:
            break;
        case QChar::DirON:
            break;
        default:
            break;
        }

        //cout << "     after: dir=" << //        dir << " current=" << dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << context->dir << endl;

        if(bidi.current.atEnd()) break;

        // set status.last as needed.
        switch(dirCurrent)
            {
            case QChar::DirET:
            case QChar::DirES:
            case QChar::DirCS:
            case QChar::DirS:
            case QChar::DirWS:
            case QChar::DirON:
                switch(bidi.status.last)
                    {
                    case QChar::DirL:
                    case QChar::DirR:
                    case QChar::DirAL:
                    case QChar::DirEN:
                    case QChar::DirAN:
                        bidi.status.last = dirCurrent;
                        break;
                    default:
                        bidi.status.last = QChar::DirON;
                    }
                break;
            case QChar::DirNSM:
            case QChar::DirBN:
                // ignore these
                break;
            case QChar::DirEN:
                if ( bidi.status.last == QChar::DirL ) {
                    bidi.status.last = QChar::DirL;
                    break;
                }
                // fall through
            default:
                bidi.status.last = dirCurrent;
            }
#endif

	if ( atEnd ) break;
        bidi.last = bidi.current;

	if ( emptyRun ) {
	    bidi.sor = bidi.current;
	    bidi.eor = bidi.current;
	    emptyRun = false;
	}

	// this causes the operator ++ to open and close embedding levels as needed
	// for the CSS unicode-bidi property
	adjustEmbedding = true;
        bidi.current.increment( bidi );
	adjustEmbedding = false;

	if ( bidi.current == end ) {
	    if ( emptyRun )
		break;
	    atEnd = true;
	}
    }

#if BIDI_DEBUG > 0
    kdDebug(6041) << "reached end of line current=" << current.obj << "/" << current.pos
		  << ", eor=" << eor.obj << "/" << eor.pos << endl;
#endif
    if ( !emptyRun && bidi.sor != bidi.current ) {
	    bidi.eor = bidi.last;
	    appendRun( bidi );
    }

    // reorder line according to run structure...

    // first find highest and lowest levels
    uchar levelLow = 128;
    uchar levelHigh = 0;
    BidiRun *r = sFirstBidiRun;
    while ( r ) {
        if ( r->level > levelHigh )
            levelHigh = r->level;
        if ( r->level < levelLow )
            levelLow = r->level;
        r = r->nextRun;
    }

    // implements reordering of the line (L2 according to Bidi spec):
    // L2. From the highest level found in the text to the lowest odd level on each line,
    // reverse any contiguous sequence of characters that are at that level or higher.

    // reversing is only done up to the lowest odd level
    if( !(levelLow%2) ) levelLow++;

#if BIDI_DEBUG > 0
    kdDebug(6041) << "lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh << endl;
    kdDebug(6041) << "logical order is:" << endl;
    QPtrListIterator<BidiRun> it2(runs);
    BidiRun *r2;
    for ( ; (r2 = it2.current()); ++it2 )
        kdDebug(6041) << "    " << r2 << "  start=" << r2->start << "  stop=" << r2->stop << "  level=" << (uint)r2->level << endl;
#endif

    int count = sBidiRunCount - 1;

    // do not reverse for visually ordered web sites
    if(!style()->visuallyOrdered()) {
        while(levelHigh >= levelLow) {
            int i = 0;
            BidiRun* currRun = sFirstBidiRun;
            while ( i < count ) {
                while(i < count && currRun && currRun->level < levelHigh) {
                    i++;
                    currRun = currRun->nextRun;
                }
                int start = i;
                while(i <= count && currRun && currRun->level >= levelHigh) {
                    i++;
                    currRun = currRun->nextRun;
                }
                int end = i-1;
                reverseRuns(start, end);
                i++;
                if(i >= count) break;
            }
            levelHigh--;
        }
    }

#if BIDI_DEBUG > 0
    kdDebug(6041) << "visual order is:" << endl;
    for (BidiRun* curr = sFirstRun; curr; curr = curr->nextRun)
        kdDebug(6041) << "    " << curr << endl;
#endif
}

static void buildCompactRuns(RenderObject* compactObj, BidiState &bidi)
{
    sBuildingCompactRuns = true;
    if (!compactObj->isRenderBlock()) {
        // Just append a run for our object.
        isLineEmpty = false;
        addRun(new (compactObj->renderArena()) BidiRun(0, compactObj->length(), compactObj, bidi.context, dir));
    }
    else {
        // Format the compact like it is its own single line.  We build up all the runs for
        // the little compact and then reorder them for bidi.
        RenderBlock* compactBlock = static_cast<RenderBlock*>(compactObj);
        adjustEmbedding = true;
        BidiIterator start(compactBlock, first(compactBlock, bidi), 0);
        adjustEmbedding = false;
        BidiIterator end = start;

        betweenMidpoints = false;
        isLineEmpty = true;
        previousLineBrokeCleanly = true;

        end = compactBlock->findNextLineBreak(start, bidi);
        if (!isLineEmpty)
            compactBlock->bidiReorderLine(start, end, bidi);
    }


    sCompactFirstBidiRun = sFirstBidiRun;
    sCompactLastBidiRun = sLastBidiRun;
    sCompactBidiRunCount = sBidiRunCount;

    sNumMidpoints = 0;
    sCurrMidpoint = 0;
    betweenMidpoints = false;
    sBuildingCompactRuns = false;
}

QRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
{
    BidiState bidi;

    bool useRepaintRect = false;
    QRect repaintRect(0,0,0,0);

    m_overflowHeight = 0;

    invalidateVerticalPositions();
#ifdef DEBUG_LAYOUT
    QTime qt;
    qt.start();
    kdDebug( 6040 ) << renderName() << " layoutInlineChildren( " << this <<" )" << endl;
#endif
#if BIDI_DEBUG > 1 || defined( DEBUG_LINEBREAKS )
    kdDebug(6041) << " ------- bidi start " << this << " -------" << endl;
#endif

    m_height = borderTop() + paddingTop();
    int toAdd = borderBottom() + paddingBottom();
    if (includeScrollbarSize())
        toAdd += m_layer->horizontalScrollbarHeight();

    // Figure out if we should clear out our line boxes.
    // FIXME: Handle resize eventually!
    // FIXME: Do something better when floats are present.
    bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren || containsFloats();
    if (fullLayout)
        deleteLineBoxes();

    // Text truncation only kicks in if your overflow isn't visible and your text-overflow-mode isn't
    // clip.
    // FIXME: CSS3 says that descendants that are clipped must also know how to truncate.  This is insanely
    // difficult to figure out (especially in the middle of doing layout), and is really an esoteric pile of nonsense
    // anyway, so we won't worry about following the draft here.
    bool hasTextOverflow = style()->textOverflow() && hasOverflowClip();

    // Walk all the lines and delete our ellipsis line boxes if they exist.
    if (hasTextOverflow)
         deleteEllipsisLineBoxes();

    int oldLineBottom = lastRootBox() ? lastRootBox()->bottomOverflow() : m_height;
    int startLineBottom = 0;

    if (firstChild()) {
        // layout replaced elements
        bool endOfInline = false;
        RenderObject *o = first(this, bidi, false);
        bool hasFloat = false;
        while (o) {
            if (o->isReplaced() || o->isFloating() || o->isPositioned()) {
                if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent())
                    o->setChildNeedsLayout(true, false);
                if (o->isPositioned())
                    o->containingBlock()->insertPositionedObject(o);
                else {
                    if (o->isFloating())
                        hasFloat = true;
                    else if (fullLayout || o->needsLayout()) // Replaced elements
                        o->dirtyLineBoxes(fullLayout);
                    o->layoutIfNeeded();
                }
            }
            else if (o->isText() || (o->isInlineFlow() && !endOfInline)) {
                if (fullLayout || o->selfNeedsLayout())
                    o->dirtyLineBoxes(fullLayout);
                o->setNeedsLayout(false);
            }
            o = Bidinext( this, o, bidi, false, &endOfInline);
        }

        if (hasFloat)
            fullLayout = true; // FIXME: Will need to find a way to optimize floats some day.

        if (fullLayout && !selfNeedsLayout()) {
            setNeedsLayout(true, false);  // Mark ourselves as needing a full layout. This way we'll repaint like
                                          // we're supposed to.
            if (!document()->view()->needsFullRepaint() && m_layer) {
                // Because we waited until we were already inside layout to discover
                // that the block really needed a full layout, we missed our chance to repaint the layer
                // before layout started.  Luckily the layer has cached the repaint rect for its original
                // position and size, and so we can use that to make a repaint happen now.
                RenderCanvas* c = canvas();
                if (c && !c->printingMode())
                    c->repaintViewRectangle(m_layer->repaintRect());
            }
        }

⌨️ 快捷键说明

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