📄 bidi.cpp
字号:
sBidiRunCount += sCompactBidiRunCount; }#endif if (sBidiRunCount) { InlineFlowBox* lineBox = constructLine(start, end); if (lineBox) { if (pagebreakHint) lineBox->setAfterPageBreak(true); // Now we position all of our text runs horizontally. computeHorizontalPositionsForLine(lineBox, bidi); // Now position our text runs vertically. computeVerticalPositionsForLine(lineBox); deleteBidiRuns(renderArena()); if (lineBox->afterPageBreak() && hasFloats() && !pagebreakHint) { start = end = oldStart; bidi = oldBidi; m_height = pageTopAfter(oldPos); deleteLastLineBox(renderArena()); pagebreakHint = true; goto redo_linebreak; } } } if( end == start || (end.obj && end.obj->isBR() && !start.obj->isBR() ) ) { adjustEmbedding = true; end.increment(bidi); adjustEmbedding = false; } else if (end.obj && end.obj->style()->preserveLF() && end.current() == QChar('\n')) { adjustEmbedding = true; end.increment(bidi); adjustEmbedding = false; } m_firstLine = false; newLine(); } sNumMidpoints = 0; sCurrMidpoint = 0; sCompactFirstBidiRun = sCompactLastBidiRun = 0; sCompactBidiRunCount = 0; } startEmbed->deref(); //embed->deref(); } sNumMidpoints = 0; sCurrMidpoint = 0; // If we violate widows page-breaking rules, we set a hint and relayout. // Note that the widows rule might still be violated afterwards if the lines have become wider if (canvas()->pagedMode() && containsPageBreak() && breakBeforeLine == 0) { int orphans = 0; int widows = 0; // find breaking line InlineRunBox* lineBox = firstLineBox(); while (lineBox) { if (lineBox->isInlineFlowBox()) { InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(lineBox); if (flowBox->afterPageBreak()) break; } orphans++; lineBox = lineBox->nextLineBox(); } InlineFlowBox* pageBreaker = static_cast<InlineFlowBox*>(lineBox); if (!pageBreaker) goto no_break; // count widows while (lineBox && widows < style()->widows()) { if (lineBox->hasTextChildren()) widows++; lineBox = lineBox->nextLineBox(); } // Widows rule broken and more orphans left to use if (widows < style()->widows() && orphans > 0) { kdDebug( 6040 ) << "Widows: " << widows << endl; // Check if we have enough orphans after respecting widows count int newOrphans = orphans - (style()->widows() - widows); if (newOrphans < style()->orphans() && parent()->canClear(this,PageBreakHarder)) { // Relayout to remove incorrect page-break setNeedsPageClear(true); setContainsPageBreak(false); layoutInlineChildren(relayoutChildren, -1); return; } else { // Set hint and try again layoutInlineChildren(relayoutChildren, newOrphans+1); return; } } } no_break: // in case we have a float on the last line, it might not be positioned up to now. // This has to be done before adding in the bottom border/padding, or the float will // include the padding incorrectly. -dwh positionNewFloats(); // Now add in the bottom border/padding. m_height += toAdd; // Always make sure this is at least our height. if (m_overflowHeight < m_height) m_overflowHeight = m_height;#if BIDI_DEBUG > 1 kdDebug(6041) << " ------- bidi end " << this << " -------" << endl;#endif //kdDebug() << "RenderBlock::layoutInlineChildren time used " << qt.elapsed() << endl; //kdDebug(6040) << "height = " << m_height <<endl;}static void setStaticPosition( RenderBlock* p, RenderObject *o, bool *needToSetStaticX = 0, bool *needToSetStaticY = 0 ){ // If our original display wasn't an inline type, then we can // determine our static x position now. bool nssx, nssy; bool isInlineType = o->style()->isOriginalDisplayInlineType(); nssx = o->hasStaticX(); if (nssx && !isInlineType && o->isBox()) { static_cast<RenderBox*>(o)->setStaticX(o->parent()->style()->direction() == LTR ? p->borderLeft()+p->paddingLeft() : p->borderRight()+p->paddingRight()); nssx = false; } // If our original display was an INLINE type, then we can // determine our static y position now. nssy = o->hasStaticY(); if (nssy && o->isBox()) { static_cast<RenderBox*>(o)->setStaticY(p->height()); nssy = !isInlineType; } if (needToSetStaticX) *needToSetStaticX = nssx; if (needToSetStaticY) *needToSetStaticY = nssy;}BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi){ int width = lineWidth(m_height); int w = 0; int tmpW = 0;#ifdef DEBUG_LINEBREAKS kdDebug(6041) << "findNextLineBreak: line at " << m_height << " line width " << width << endl; kdDebug(6041) << "sol: " << start.obj << " " << start.pos << endl;#endif BidiIterator posStart = start; bool hadPosStart = false; // eliminate spaces at beginning of line // remove leading spaces. Any inline flows we encounter will be empty and should also // be skipped. while (!start.atEnd() && (start.obj->isInlineFlow() || (!start.obj->style()->preserveWS() && !start.obj->isBR() &&#ifndef QT_NO_UNICODETABLES ( (start.current().unicode() == (ushort)0x0020) || // ASCII space (start.current().unicode() == (ushort)0x0009) || // ASCII tab (start.current().unicode() == (ushort)0x000A) || // ASCII line feed (start.current().unicode() == (ushort)0x000C) || // ASCII form feed (start.current().unicode() == (ushort)0x200B) || // Zero-width space start.obj->isFloatingOrPositioned() )#else ( start.current() == ' ' || start.current() == '\n' || start.obj->isFloatingOrPositioned() )#endif ))) { if( start.obj->isFloatingOrPositioned() ) { RenderObject *o = start.obj; // add to special objects... if (o->isFloating()) { insertFloatingObject(o); positionNewFloats(); width = lineWidth(m_height); } else if (o->isBox() && o->isPositioned()) { if (!hadPosStart) { hadPosStart = true; posStart = start; // end addMidpoint(BidiIterator(0, o, 0)); } else { // start/end addMidpoint(BidiIterator(0, o, 0)); addMidpoint(BidiIterator(0, o, 0)); } setStaticPosition(this, o); } } adjustEmbedding = true; start.increment(bidi); adjustEmbedding = false; } if (hadPosStart && !start.atEnd()) addMidpoint(start); if ( start.atEnd() ){ if (hadPosStart) { start = posStart; posStart.increment(bidi); return posStart; } return start; } // This variable is used only if whitespace isn't set to PRE, and it tells us whether // or not we are currently ignoring whitespace. bool ignoringSpaces = false; BidiIterator ignoreStart; // This variable tracks whether the very last character we saw was a space. We use // this to detect when we encounter a second space so we know we have to terminate // a run. bool currentCharacterIsSpace = false; RenderObject* trailingSpaceObject = 0; BidiIterator lBreak = start; RenderObject *o = start.obj; RenderObject *last = o; int pos = start.pos; bool prevLineBrokeCleanly = previousLineBrokeAtBR; previousLineBrokeAtBR = false; while( o ) {#ifdef DEBUG_LINEBREAKS kdDebug(6041) << "new object "<< o <<" width = " << w <<" tmpw = " << tmpW << endl;#endif if(o->isBR()) { if( w + tmpW <= width ) { lBreak.obj = o; lBreak.pos = 0; // A <br> always breaks a line, so don't let the line be collapsed // away. Also, the space at the end of a line with a <br> does not // get collapsed away. It only does this if the previous line broke // cleanly. Otherwise the <br> has no effect on whether the line is // empty or not. if (prevLineBrokeCleanly) isLineEmpty = false; trailingSpaceObject = 0; previousLineBrokeAtBR = true; if (!isLineEmpty) { // only check the clear status for non-empty lines. EClear clear = o->style()->clear(); if(clear != CNONE) m_clearStatus = (EClear) (m_clearStatus | clear); } } goto end; } if( o->isFloatingOrPositioned() ) { // add to special objects... if(o->isFloating()) { insertFloatingObject(o); // check if it fits in the current line. // If it does, position it now, otherwise, position // it after moving to next line (in newLine() func) if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) { positionNewFloats(); width = lineWidth(m_height); } } else if (o->isPositioned()) { bool needToSetStaticX; bool needToSetStaticY; setStaticPosition(this, o, &needToSetStaticX, &needToSetStaticY); // If we're ignoring spaces, we have to stop and include this object and // then start ignoring spaces again. if (needToSetStaticX || needToSetStaticY) { trailingSpaceObject = 0; ignoreStart.obj = o; ignoreStart.pos = 0; if (ignoringSpaces) { addMidpoint(ignoreStart); // Stop ignoring spaces. addMidpoint(ignoreStart); // Start ignoring again. } } } } else if (o->isInlineFlow()) { // Only empty inlines matter. We treat those similarly to replaced elements. KHTMLAssert(!o->firstChild()); tmpW += o->marginLeft()+o->borderLeft()+o->paddingLeft()+ o->marginRight()+o->borderRight()+o->paddingRight(); } else if ( o->isReplaced() ) { EWhiteSpace currWS = o->style()->whiteSpace(); EWhiteSpace lastWS = last->style()->whiteSpace(); // WinIE marquees have different whitespace characteristics by default when viewed from // the outside vs. the inside. Text inside is NOWRAP, and so we altered the marquee's // style to reflect this, but we now have to get back to the original whitespace value // for the marquee when checking for line breaking. if (o->isHTMLMarquee() && o->layer() && o->layer()->marquee()) currWS = o->layer()->marquee()->whiteSpace(); if (last->isHTMLMarquee() && last->layer() && last->layer()->marquee()) lastWS = last->layer()->marquee()->whiteSpace(); // Break on replaced elements if either has normal white-space. if (currWS == NORMAL || lastWS == NORMAL) { w += tmpW; tmpW = 0; lBreak.obj = o; lBreak.pos = 0; } tmpW += o->width()+o->marginLeft()+o->marginRight()+inlineWidth(o); if (ignoringSpaces) { BidiIterator startMid( 0, o, 0 ); addMidpoint(startMid); } isLineEmpty = false; ignoringSpaces = false; currentCharacterIsSpace = false; trailingSpaceObject = 0; if (o->isListMarker() && o->style()->listStylePosition() == OUTSIDE) { // The marker must not have an effect on whitespace at the start // of the line. We start ignoring spaces to make sure that any additional // spaces we see will be discarded. // // Optimize for a common case. If we can't find whitespace after the list // item, then this is all moot. -dwh RenderObject* next = Bidinext( start.par, o, bidi ); if (!m_pre && next && next->isText() && static_cast<RenderText*>(next)->stringLength() > 0 && (static_cast<RenderText*>(next)->text()[0].category() == QChar::Separator_Space || static_cast<RenderText*>(next)->text()[0] == '\n')) { currentCharacterIsSpace = true; ignoringSpaces = true; BidiIterator endMid( 0, o, 0 ); addMidpoint(endMid); } } } else if ( o->isText() ) { RenderText *t = static_cast<RenderText *>(o); int strlen = t->stringLength(); int len = strlen - pos; QChar *str = t->text(); const Font *f = t->htmlFont( m_firstLine ); // proportional font, needs a bit more work. int lastSpace = pos; bool autoWrap = o->style()->autoWrap(); bool preserveWS = o->style()->preserveWS(); bool preserveLF = o->style()->preserveLF();#ifdef APPLE_CHANGES int wordSpacing = o->style()->wordSpacing();#endif bool appliedStartWidth = pos > 0; // If the span originated on a previous line, // then assume the start width has been applied. bool appliedEndWidth = false; bool nextIsSoftBreakable = false; while(len) { bool previousCharacterIsSpace = currentCharacterIsSpace; bool isSoftBreakable = nextIsSoftBreakable; nextIsSoftBreakable = false; const QChar c = str[pos]; currentCharacterIsSpace = c == ' '; if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -