📄 bidi.cpp
字号:
// if last strong was AL change EN to AN
if(dir == QChar::DirON) {
dir = QChar::DirL;
}
switch(bidi.status.last)
{
case QChar::DirET:
if ( bidi.status.lastStrong == QChar::DirR || bidi.status.lastStrong == QChar::DirAL ) {
appendRun( bidi );
dir = QChar::DirEN;
bidi.status.eor = QChar::DirEN;
}
// fall through
case QChar::DirEN:
case QChar::DirL:
bidi.eor = bidi.current;
bidi.status.eor = dirCurrent;
break;
case QChar::DirR:
case QChar::DirAL:
case QChar::DirAN:
appendRun( bidi );
bidi.status.eor = QChar::DirEN;
dir = QChar::DirEN; break;
case QChar::DirES:
case QChar::DirCS:
if(bidi.status.eor == QChar::DirEN) {
bidi.eor = bidi.current; break;
}
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::DirEN;
bidi.status.eor = QChar::DirEN;
}
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; 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 && bidi.status.eor != QChar::DirAL) {
// run of L before neutrals, neutrals take embedding dir (N2)
if(bidi.context->dir == QChar::DirR || bidi.status.lastStrong == QChar::DirR
|| bidi.status.lastStrong == QChar::DirAL) {
// the embedding direction is R
// close the L run
appendRun( bidi );
// neutrals become an R run
bidi.eor = bidi.last;
dir = QChar::DirR;
appendRun( bidi );
bidi.eor = bidi.current;
} else {
// the embedding direction is L
// append neutrals to the L run and close it
dir = QChar::DirL;
bidi.eor = bidi.last;
appendRun(bidi);
}
} else {
bidi.eor = bidi.last;
appendRun(bidi);
bidi.eor = bidi.current;
}
dir = QChar::DirAN;
bidi.status.eor = QChar::DirAN;
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;
} else if ((bidi.status.eor == QChar::DirR || bidi.status.eor == QChar::DirAL || bidi.status.eor == QChar::DirAN || (bidi.status.eor == QChar::DirEN && bidi.status.lastStrong == QChar::DirR)) && bidi.last!=bidi.current) {
// most of the time this is unnecessary, but we need to secure the R run in case
// the ET ends up being neutral and followed by L
if (bidi.status.last!=QChar::DirET) {
dir = bidi.status.eor;
appendRun(bidi);
bidi.eor = bidi.last;
}
bidi.status.eor = QChar::DirR;
dir = QChar::DirR;
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:
if (bidi.status.last != QChar::DirEN)
bidi.status.last = QChar::DirET;
break;
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:
// fall through
default:
bidi.status.last = dirCurrent;
}
#endif
if ( atEnd ) break;
bidi.last = bidi.current;
if ( emptyRun ) {
bidi.sor = 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
}
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -