📄 render_line.cpp
字号:
shrinkBoxesWithNoTextChildren(topPosition, bottomPosition); heightOfBlock += maxHeight;}void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom){ for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { // The computed lineheight needs to be extended for the // positioned elements // see khtmltests/rendering/html_align.html if (curr->object()->isPositioned()) continue; // Positioned placeholders don't affect calculations. if (curr->yPos() == PositionTop || curr->yPos() == PositionBottom) { if (curr->yPos() == PositionTop) { if (maxAscent + maxDescent < curr->height()) maxDescent = curr->height() - maxAscent; } else { if (maxAscent + maxDescent < curr->height()) maxAscent = curr->height() - maxDescent; } if ( maxAscent + maxDescent >= kMax( maxPositionTop, maxPositionBottom ) ) break; } if (curr->isInlineFlowBox()) static_cast<InlineFlowBox*>(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom); }}void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom, int& maxAscent, int& maxDescent, bool strictMode){ if (isRootInlineBox()) { // Examine our root box. setHeight(object()->lineHeight(m_firstLine)); bool isTableCell = object()->isTableCell(); if (isTableCell) { RenderTableCell* tableCell = static_cast<RenderTableCell*>(object()); setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine)); } else setBaseline(object()->baselinePosition(m_firstLine)); if (hasTextChildren() || strictMode) { int ascent = baseline(); int descent = height() - ascent; if (maxAscent < ascent) maxAscent = ascent; if (maxDescent < descent) maxDescent = descent; } } for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->object()->isPositioned()) continue; // Positioned placeholders don't affect calculations. curr->setHeight(curr->object()->lineHeight(m_firstLine)); curr->setBaseline(curr->object()->baselinePosition(m_firstLine)); curr->setYPos(curr->object()->verticalPositionHint(m_firstLine)); if (curr->yPos() == PositionTop) { if (maxPositionTop < curr->height()) maxPositionTop = curr->height(); } else if (curr->yPos() == PositionBottom) { if (maxPositionBottom < curr->height()) maxPositionBottom = curr->height(); } else if (curr->hasTextChildren() || strictMode) { int ascent = curr->baseline() - curr->yPos(); int descent = curr->height() - ascent; if (maxAscent < ascent) maxAscent = ascent; if (maxDescent < descent) maxDescent = descent; } if (curr->isInlineFlowBox()) static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode); }}void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode, int& topPosition, int& bottomPosition){ if (isRootInlineBox()) { setYPos(y + maxAscent - baseline());// Place our root box. // CSS2: 10.8.1 - line-height on the block level element specifies the *minimum* // height of the generated line box if (hasTextChildren() && maxHeight < object()->lineHeight(m_firstLine)) maxHeight = object()->lineHeight(m_firstLine); } for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->object()->isPositioned()) continue; // Positioned placeholders don't affect calculations. // Adjust boxes to use their real box y/height and not the logical height (as dictated by // line-height). if (curr->isInlineFlowBox()) static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode, topPosition, bottomPosition); bool childAffectsTopBottomPos = true; if (curr->yPos() == PositionTop) curr->setYPos(y); else if (curr->yPos() == PositionBottom) curr->setYPos(y + maxHeight - curr->height()); else { if (!curr->hasTextChildren() && !strictMode) childAffectsTopBottomPos = false; curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline()); } int newY = curr->yPos(); int newHeight = curr->height(); int newBaseline = curr->baseline(); if (curr->isInlineTextBox() || curr->isInlineFlowBox()) { const QFontMetrics &fm = curr->object()->fontMetrics( m_firstLine );#ifdef APPLE_CHANGES newBaseline = fm.ascent(); newY += curr->baseline() - newBaseline; newHeight = newBaseline+fm.descent();#else // only adjust if the leading delta is superior to the font's natural leading if ( kAbs(fm.ascent() - curr->baseline()) > fm.leading()/2 ) { int ascent = fm.ascent()+fm.leading()/2; newBaseline = ascent; newY += curr->baseline() - newBaseline; newHeight = fm.lineSpacing(); }#endif if (curr->isInlineFlowBox()) { newHeight += curr->object()->borderTop() + curr->object()->paddingTop() + curr->object()->borderBottom() + curr->object()->paddingBottom(); newY -= curr->object()->borderTop() + curr->object()->paddingTop(); newBaseline += curr->object()->borderTop() + curr->object()->paddingTop(); } } else { newY += curr->object()->marginTop(); newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom()); } curr->setYPos(newY); curr->setHeight(newHeight); curr->setBaseline(newBaseline); if (childAffectsTopBottomPos) { if (newY < topPosition) topPosition = newY; if (newY + newHeight > bottomPosition) bottomPosition = newY + newHeight; } } if (isRootInlineBox()) { const QFontMetrics &fm = object()->fontMetrics( m_firstLine );#ifdef APPLE_CHANGES setHeight(fm.ascent()+fm.descent()); setYPos(yPos() + baseline() - fm.ascent()); setBaseline(fm.ascent());#else if ( kAbs(fm.ascent() - baseline()) > fm.leading()/2 ) { int ascent = fm.ascent()+fm.leading()/2; setHeight(fm.lineSpacing()); setYPos(yPos() + baseline() - ascent); setBaseline(ascent); }#endif if (hasTextChildren() || strictMode) { if (yPos() < topPosition) topPosition = yPos(); if (yPos() + height() > bottomPosition) bottomPosition = yPos() + height(); } }}void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos){ // First shrink our kids. for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->object()->isPositioned()) continue; // Positioned placeholders don't affect calculations. if (curr->isInlineFlowBox()) static_cast<InlineFlowBox*>(curr)->shrinkBoxesWithNoTextChildren(topPos, bottomPos); } // See if we have text children. If not, then we need to shrink ourselves to fit on the line. if (!hasTextChildren()) { if (yPos() < topPos) setYPos(topPos); if (yPos() + height() > bottomPos) setHeight(bottomPos - yPos()); if (baseline() > height()) setBaseline(height()); }}void InlineFlowBox::paintBackgrounds(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer, int my, int mh, int _tx, int _ty, int w, int h, int xoff){ if (!bgLayer) return; paintBackgrounds(p, c, bgLayer->next(), my, mh, _tx, _ty, w, h, xoff); paintBackground(p, c, bgLayer, my, mh, _tx, _ty, w, h, xoff);}void InlineFlowBox::paintBackground(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer, int my, int mh, int _tx, int _ty, int w, int h, int xOffsetOnLine){ CachedImage* bg = bgLayer->backgroundImage(); bool hasBackgroundImage = bg && (bg->pixmap_size() == bg->valid_rect().size()) && !bg->isTransparent() && !bg->isErrorImage(); if (!hasBackgroundImage || (!prevLineBox() && !nextLineBox()) || !parent()) object()->paintBackgroundExtended(p, c, bgLayer, my, mh, _tx, _ty, w, h, borderLeft(), borderRight()); else { // We have a background image that spans multiple lines. // We need to adjust _tx and _ty by the width of all previous lines. // Think of background painting on inlines as though you had one long line, a single continuous // strip. Even though that strip has been broken up across multiple lines, you still paint it // as though you had one single line. This means each line has to pick up the background where // the previous line left off. int startX = _tx - xOffsetOnLine; int totalWidth = xOffsetOnLine; for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox()) totalWidth += curr->width(); QRect clipRect(_tx, _ty, width(), height()); clipRect = p->xForm(clipRect); p->save(); p->setClipRect( clipRect ); object()->paintBackgroundExtended(p, c, bgLayer, my, mh, startX, _ty, totalWidth, h, borderLeft(), borderRight()); p->restore(); }}void InlineFlowBox::paintBackgroundAndBorder(RenderObject::PaintInfo& pI, int _tx, int _ty, int xOffsetOnLine){ // Move x/y to our coordinates. _tx += m_x; _ty += m_y; int w = width(); int h = height(); int my = kMax(_ty, pI.r.y()); int mh; if (_ty<pI.r.y()) mh= kMax(0,h-(pI.r.y()-_ty)); else mh = kMin(pI.r.height(),h); // You can use p::first-line to specify a background. If so, the root line boxes for // a line may actually have to paint a background. RenderStyle* styleToUse = object()->style(m_firstLine); if ((!parent() && m_firstLine && styleToUse != object()->style()) || (parent() && object()->shouldPaintBackgroundOrBorder())) { QColor c = styleToUse->backgroundColor(); paintBackgrounds(pI.p, c, styleToUse->backgroundLayers(), my, mh, _tx, _ty, w, h, xOffsetOnLine); // :first-line cannot be used to put borders on a line. Always paint borders with our // non-first-line style. if (parent() && object()->style()->hasBorder()) object()->paintBorder(pI.p, _tx, _ty, w, h, object()->style(), includeLeftEdge(), includeRightEdge()); }}static bool shouldDrawDecoration(RenderObject* obj){ bool shouldDraw = false; for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling()) { if (curr->isInlineFlow()) { shouldDraw = true; break; } else if (curr->isText() && !curr->isBR() && (curr->style()->preserveWS() || !curr->element() || !curr->element()->containsOnlyWhitespace())) { shouldDraw = true; break; } } return shouldDraw;}void InlineFlowBox::paintDecorations(RenderObject::PaintInfo& pI, int _tx, int _ty){ // Now paint our text decorations. We only do this if we aren't in quirks mode (i.e., in // almost-strict mode or strict mode). _tx += m_x; _ty += m_y; RenderStyle* styleToUse = object()->style(m_firstLine); int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect(); if (deco != TDNONE && shouldDrawDecoration(object())) { // We must have child boxes and have decorations defined. _tx += borderLeft() + paddingLeft(); int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());// kdDebug() << k_funcinfo << "w: " << w << " deco: " << deco << endl; if ( !w ) return; const QFontMetrics &fm = object()->fontMetrics( m_firstLine ); // thick lines on small fonts look ugly int thickness = fm.height() > 20 ? fm.lineWidth() : 1; QColor underline, overline, linethrough; underline = overline = linethrough = styleToUse->color(); if (!parent()) object()->getTextDecorationColors(deco, underline, overline, linethrough); if (deco & UNDERLINE) { int underlineOffset = ( fm.height() + m_baseline ) / 2; if (underlineOffset <= m_baseline) underlineOffset = m_baseline+1; pI.p->fillRect(_tx, _ty + underlineOffset, w, thickness, underline ); } if (deco & OVERLINE) { pI.p->fillRect(_tx, _ty, w, thickness, overline ); } if (deco & LINE_THROUGH) { pI.p->fillRect(_tx, _ty + 2*m_baseline/3, w, thickness, linethrough ); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -