📄 bidi.cpp
字号:
// Now we position all of our text runs horizontally. computeHorizontalPositionsForLine(lineBox, bidi); // Now position our text runs vertically. computeVerticalPositionsForLine(lineBox); deleteBidiRuns(renderArena()); } } if (end == start || (!previousLineBrokeCleanly && end.obj && end.obj->style()->whiteSpace() == PRE && end.current() == QChar('\n'))) { adjustEmbedding = true; end.increment(bidi); adjustEmbedding = false; } if (lineBox) lineBox->setLineBreakInfo(end.obj, end.pos); m_firstLine = false; newLine(); } sNumMidpoints = 0; sCurrMidpoint = 0; sCompactFirstBidiRun = sCompactLastBidiRun = 0; sCompactBidiRunCount = 0; } startEmbed->deref(); //embed->deref(); if (endLine) { if (endLineMatched) { // Attach all the remaining lines, and then adjust their y-positions as needed. for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) line->attachLine(); // Now apply the offset to each line if needed. int delta = m_height - endLineYPos; if (delta) for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) line->adjustPosition(0, delta); // Now set our height and check for overflow. int currYPos = m_height; m_height = lastRootBox()->blockHeight(); m_overflowHeight = kMax(m_height, m_overflowHeight); int bottomOfLine = lastRootBox()->bottomOverflow(); if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight) m_overflowHeight = bottomOfLine; if (delta) repaintRect.setHeight(kMax(m_overflowHeight-delta, m_overflowHeight) - repaintRect.y()); else repaintRect.setHeight(currYPos - repaintRect.y()); } else { // Delete all the remaining lines. m_overflowHeight = kMax(m_height, m_overflowHeight); InlineRunBox* line = endLine; RenderArena* arena = renderArena(); while (line) { InlineRunBox* next = line->nextLineBox(); if (!next) repaintRect.setHeight(kMax(m_overflowHeight, line->bottomOverflow()) - repaintRect.y()); line->deleteLine(arena); line = next; } } } } sNumMidpoints = 0; sCurrMidpoint = 0; // 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. m_overflowHeight = kMax(m_height, m_overflowHeight); if (useRepaintRect) { repaintRect.setWidth(kMax((int)m_width, m_overflowWidth)); if (repaintRect.height() == 0) repaintRect.setHeight(m_overflowHeight - repaintRect.y()); } setLinesAppended(false); if (!firstLineBox() && element() && element()->isContentEditable() && element()->rootEditableElement() == element()) { m_height += lineHeight(true); } // See if we have any lines that spill out of our block. If we do, then we will possibly need to // truncate text. if (hasTextOverflow) checkLinesForTextOverflow(); return repaintRect;#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;}RootInlineBox* RenderBlock::determineStartPosition(bool fullLayout, BidiIterator& start, BidiState& bidi){ RootInlineBox* curr = 0; RootInlineBox* last = 0; RenderObject* startObj = 0; int pos = 0; if (fullLayout) { // Nuke all our lines. if (firstRootBox()) { RenderArena* arena = renderArena(); curr = firstRootBox(); while (curr) { RootInlineBox* next = curr->nextRootBox(); curr->deleteLine(arena); curr = next; } KHTMLAssert(!m_firstLineBox && !m_lastLineBox); } } else { for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()); if (curr) { // We have a dirty line. if (curr->prevRootBox()) { // We have a previous line. if (!curr->prevRootBox()->endsWithBreak()) curr = curr->prevRootBox(); // The previous line didn't break cleanly, so treat it as dirty also. } } else { // No dirty lines were found. // If the last line didn't break cleanly, treat it as dirty. if (lastRootBox() && !lastRootBox()->endsWithBreak()) curr = lastRootBox(); } // If we have no dirty lines, then last is just the last root box. last = curr ? curr->prevRootBox() : lastRootBox(); } m_firstLine = !last; previousLineBrokeCleanly = !last || last->endsWithBreak(); if (last) { m_height = last->blockHeight(); int bottomOfLine = last->bottomOverflow(); if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight) m_overflowHeight = bottomOfLine; startObj = last->lineBreakObj(); pos = last->lineBreakPos(); } else startObj = first(this, bidi, 0); adjustEmbedding = true; start = BidiIterator(this, startObj, pos); adjustEmbedding = false; return curr;}RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiIterator& cleanLineStart, int& yPos){ RootInlineBox* last = 0; if (m_linesAppended) last = 0; else { for (RootInlineBox* curr = startLine; curr; curr = curr->nextRootBox()) if (curr->isDirty() && curr->nextRootBox() && !curr->nextRootBox()->isDirty()) last = curr->nextRootBox(); } if (!last) return 0; cleanLineStart = BidiIterator(this, last->prevRootBox()->lineBreakObj(), last->prevRootBox()->lineBreakPos()); yPos = last->prevRootBox()->blockHeight(); for (RootInlineBox* line = last; line; line = line->nextRootBox()) line->extractLine(); // Disconnect all line boxes from their render objects while preserving // their connections to one another. return last;}bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiIterator& endLineStart, RootInlineBox*& endLine, int& endYPos){ if (start == endLineStart) return true; // The common case. All the data we already have is correct. else { // The first clean line doesn't match, but we can check a handful of following lines to try // to match back up. static int numLines = 8; // The # of lines we're willing to match against. RootInlineBox* line = endLine; for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) { if (line->lineBreakObj() == start.obj && line->lineBreakPos() == start.pos) { // We have a match. RootInlineBox* result = line->nextRootBox(); // Set our yPos to be the block height of endLine. if (result) endYPos = line->blockHeight(); // Now delete the lines that we failed to sync. RootInlineBox* boxToDelete = endLine; RenderArena* arena = renderArena(); while (boxToDelete && boxToDelete != result) { RootInlineBox* next = boxToDelete->nextRootBox(); boxToDelete->deleteLine(arena); boxToDelete = next; } endLine = result; return result; } } } return false;}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 // 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()->whiteSpace() != PRE && !start.obj->isBR() && (start.current() == ' ' || start.current() == '\n' || start.obj->isFloatingOrPositioned())))) { 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->isPositioned()) { if (o->hasStaticX()) o->setStaticX(style()->direction() == LTR ? borderLeft()+paddingLeft() : borderRight()+paddingRight()); if (o->hasStaticY()) o->setStaticY(m_height); } } adjustEmbedding = true; start.increment(bidi); adjustEmbedding = false; } if ( start.atEnd() ){ 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 = previousLineBrokeCleanly; previousLineBrokeCleanly = 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; lBreak.increment(bidi); // 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; previousLineBrokeCleanly = 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()) { // If our original display wasn't an inline type, then we can // go ahead and determine our static x position now. bool isInlineType = o->style()->isOriginalDisplayInlineType(); bool needToSetStaticX = o->hasStaticX(); if (o->hasStaticX() && !isInlineType) { o->setStaticX(o->parent()->style()->direction() == LTR ? borderLeft()+paddingLeft() : borderRight()+paddingRight()); needToSetStaticX = false; } // If our original display was an INLINE type, then we can go ahead // and determine our static y position now. bool needToSetStaticY = o->hasStaticY(); if (o->hasStaticY() && isInlineType) { o->setStaticY(m_height); needToSetStaticY = false; } // 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. } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -