📄 bidi.cpp
字号:
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 + -