📄 bidi.cpp
字号:
break; } if (numSpaces > 0) { for (r = sFirstBidiRun; r; r = r->nextRun) { int spaceAdd = 0; if (numSpaces > 0 && r->obj->isText()) { // 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.category() == QChar::Separator_Space || c == '\n') spaces++; } KHTMLAssert(spaces <= numSpaces); // Only justify text with white-space: normal. if (r->obj->style()->whiteSpace() == NORMAL) { 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 rightPos = lineBox->placeBoxesHorizontally(x); if (rightPos > m_overflowWidth) m_overflowWidth = rightPos; // FIXME: Work for rtl overflow also.}void RenderBlock::computeVerticalPositionsForLine(InlineFlowBox* lineBox){ lineBox->verticallyAlignBoxes(m_height);// lineBox->setBlockHeight(m_height); // Check for page-breaks if (canvas()->pagedMode() && !lineBox->afterPageBreak()) // If we get a page-break we might need to redo the line-break if (clearLineOfPageBreaks(lineBox) && hasFloats()) return; // 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) { // 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); }}bool RenderBlock::clearLineOfPageBreaks(InlineFlowBox* lineBox){ bool doPageBreak = false; // Check for physical page-breaks int xpage = crossesPageBreak(lineBox->topOverflow(), lineBox->bottomOverflow()); if (xpage) {#ifdef PAGE_DEBUG kdDebug(6040) << renderName() << " Line crosses to page " << xpage << endl; kdDebug(6040) << renderName() << " at pos " << lineBox->yPos() << " height " << lineBox->height() << endl;#endif doPageBreak = true; // check page-break-inside if (!style()->pageBreakInside()) { if (parent()->canClear(this, PageBreakNormal)) { setNeedsPageClear(true); doPageBreak = false; }#ifdef PAGE_DEBUG else kdDebug(6040) << "Ignoring page-break-inside: avoid" << endl;#endif } // check orphans int orphans = 0; InlineRunBox* box = lineBox->prevLineBox(); while (box && orphans < style()->orphans()) { orphans++; box = box->prevLineBox(); } if (orphans == 0) { setNeedsPageClear(true); doPageBreak = false; } else if (orphans < style()->orphans() ) {#ifdef PAGE_DEBUG kdDebug(6040) << "Orphans: " << orphans << endl;#endif // Orphans is a level 2 page-break rule and can be broken only // if the break is physically required. if (parent()->canClear(this, PageBreakHarder)) { // move block instead setNeedsPageClear(true); doPageBreak = false; }#ifdef PAGE_DEBUG else kdDebug(6040) << "Ignoring violated orphans" << endl;#endif } if (doPageBreak) { int oldYPos = lineBox->yPos(); int pTop = pageTopAfter(lineBox->yPos()); m_height = pTop; lineBox->setAfterPageBreak(true); lineBox->verticallyAlignBoxes(m_height); if (lineBox->yPos() < pTop) { // ### serious crap. render_line is sometimes placing lines too high kdDebug(6040) << "page top overflow by repositioned line" << endl; int heightIncrease = pTop - lineBox->yPos(); m_height = pTop + heightIncrease; lineBox->verticallyAlignBoxes(m_height); }#ifdef PAGE_DEBUG kdDebug(6040) << "Cleared line " << lineBox->yPos() - oldYPos << "px" << endl;#endif setContainsPageBreak(true); } } return doPageBreak;}// collects one line of the paragraph and transforms it to visual ordervoid RenderBlock::bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi){ if ( start == end ) { if ( start.current() == '\n' ) { m_height += lineHeight( m_firstLine ); } 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 = QChar::DirON; emptyRun = true; 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::DirL: bidi.eor = bidi.current; bidi.status.eor = QChar::DirL; break; case QChar::DirR: case QChar::DirAL: case QChar::DirEN: case QChar::DirAN: appendRun( bidi ); 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::DirL ) { //last stuff takes embedding dir if(bidi.context->dir == QChar::DirL || bidi.status.lastStrong == QChar::DirL) { if ( bidi.status.eor != QChar::DirEN && bidi.status.eor != QChar::DirAN && bidi.status.eor != QChar::DirON ) appendRun( bidi ); dir = QChar::DirL; bidi.eor = bidi.current; bidi.status.eor = QChar::DirL; } else { if ( bidi.status.eor == QChar::DirEN || bidi.status.eor == QChar::DirAN ) { dir = bidi.status.eor; appendRun( bidi ); } dir = QChar::DirR; bidi.eor = bidi.last; appendRun( bidi ); dir = QChar::DirL; bidi.status.eor = QChar::DirL; } } else { bidi.eor = bidi.current; bidi.status.eor = 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)) { // 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -