📄 bidi.cpp
字号:
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; 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 ) { 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); } levelHigh--; } }#if BIDI_DEBUG > 0 kdDebug(6041) << "visual order is:" << endl; for (BidiRun* curr = sFirstRun; curr; curr = curr->nextRun) kdDebug(6041) << " " << curr << endl;#endif}#ifdef APPLE_CHANGES // KDE handles compact blocks differentlystatic 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; previousLineBrokeAtBR = 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;}#endifvoid RenderBlock::layoutInlineChildren(bool relayoutChildren, int breakBeforeLine){ BidiState bidi; 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 (m_layer && style()->scrollsOverflow() && style()->height().isVariable()) toAdd += m_layer->horizontalScrollbarHeight(); // Clear out our line boxes. deleteInlineBoxes(); if (firstChild()) { // layout replaced elements RenderObject *o = first( this, bidi, false ); while ( o ) { if (o->markedForRepaint()) { o->repaintDuringLayout(); o->setMarkedForRepaint(false); } if (o->isReplaced() || o->isFloating() || o->isPositioned()) { // clear the placeHolderBox if (o->isBox()) static_cast<RenderBox*>(o)->RenderBox::deleteInlineBoxes(); //kdDebug(6041) << "layouting replaced or floating child" << endl; if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent()) o->setChildNeedsLayout(true, false); if (o->isPositioned()) o->containingBlock()->insertPositionedObject(o); else o->layoutIfNeeded(); } else { o->deleteInlineBoxes(); o->setNeedsLayout(false); } o = Bidinext( this, o, bidi, false ); } 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; adjustEmbedding = true; BidiIterator start(this, first(this, bidi), 0); adjustEmbedding = false; BidiIterator end = start; m_firstLine = true; if (!smidpoints) smidpoints = new QMemArray<BidiIterator>; sNumMidpoints = 0; sCurrMidpoint = 0; sCompactFirstBidiRun = sCompactLastBidiRun = 0; sCompactBidiRunCount = 0; previousLineBrokeAtBR = true; int lineCount = 0; bool pagebreakHint = false; int oldPos = 0; BidiIterator oldStart; BidiState oldBidi; const bool pagedMode = canvas()->pagedMode();// while( !end.atEnd() ) { start = end; lineCount++; betweenMidpoints = false; isLineEmpty = true; pagebreakHint = false; if (pagedMode) { oldPos = m_height; oldStart = start; oldBidi = bidi; }#ifdef APPLE_CHANGES // KDE handles compact blocks differently if (m_firstLine && firstChild() && firstChild()->isCompact()) { buildCompactRuns(firstChild(), bidi); start.obj = firstChild()->nextSibling(); end = start; }#endif if (lineCount == breakBeforeLine) { m_height = pageTopAfter(oldPos); pagebreakHint = true; }redo_linebreak: 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.#ifdef APPLE_CHANGES // KDE handles compact blocks differently 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -