📄 render_line.cpp
字号:
void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject){ // All boxes start off open. They will not apply any margins/border/padding on // any side. bool includeLeftEdge = false; bool includeRightEdge = false; RenderFlow* flow = static_cast<RenderFlow*>(object()); if (!flow->firstChild()) includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines. else if (parent()) { // The root inline box never has borders/margins/padding. bool ltr = flow->style()->direction() == LTR; // Check to see if all initial lines are unconstructed. If so, then // we know the inline began on this line. if (!flow->firstLineBox()->isConstructed()) { if (ltr && flow->firstLineBox() == this) includeLeftEdge = true; else if (!ltr && flow->lastLineBox() == this) includeRightEdge = true; } // In order to determine if the inline ends on this line, we check three things: // (1) If we are the last line and we don't have a continuation(), then we can // close up. // (2) If the last line box for the flow has an object following it on the line (ltr, // reverse for rtl), then the inline has closed. // (3) The line may end on the inline. If we are the last child (climbing up // the end object's chain), then we just closed as well. if (!flow->lastLineBox()->isConstructed()) { if (ltr) { if (!nextLineBox() && ((lastLine && !object()->continuation()) || nextOnLineExists() || onEndChain(endObject))) includeRightEdge = true; } else { if ((!prevLineBox() || !prevLineBox()->isConstructed()) && ((lastLine && !object()->continuation()) || prevOnLineExists() || onEndChain(endObject))) includeLeftEdge = true; } } } setEdges(includeLeftEdge, includeRightEdge); // Recur into our children. for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) { if (currChild->isInlineFlowBox()) { InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild); currFlow->determineSpacingForFlowBoxes(lastLine, endObject); } }}int InlineFlowBox::placeBoxesHorizontally(int x){ // Set our x position. setXPos(x); int startX = x; x += borderLeft() + paddingLeft(); for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->object()->isText()) { InlineTextBox* text = static_cast<InlineTextBox*>(curr); text->setXPos(x); x += text->width(); } else { if (curr->object()->isPositioned()) { if (curr->object()->parent()->style()->direction() == LTR) curr->setXPos(x); else { // Our offset that we cache needs to be from the edge of the right border box and // not the left border box. We have to subtract |x| from the width of the block // (which can be obtained by walking up to the root line box). InlineBox* root = this; while (!root->isRootInlineBox()) root = root->parent(); curr->setXPos(root->object()->width()-x); } continue; // The positioned object has no effect on the width. } if (curr->object()->isInlineFlow()) { InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr); if (curr->object()->isCompact()) { int ignoredX = x; flow->placeBoxesHorizontally(ignoredX); } else { x += flow->marginLeft(); x = flow->placeBoxesHorizontally(x); x += flow->marginRight(); } } else if (!curr->object()->isCompact()) { x += curr->object()->marginLeft(); curr->setXPos(x); x += curr->width() + curr->object()->marginRight(); } } } x += borderRight() + paddingRight(); setWidth(x-startX); return x;}void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock){ int maxPositionTop = 0; int maxPositionBottom = 0; int maxAscent = 0; int maxDescent = 0; // Figure out if we're in strict mode. Note that we can't simply use !style()->htmlHacks(), // because that would match almost strict mode as well. RenderObject* curr = object(); while (curr && !curr->element()) curr = curr->container(); bool strictMode = (curr && curr->element()->getDocument()->inStrictMode()); computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode); if (maxAscent + maxDescent < kMax(maxPositionTop, maxPositionBottom)) adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom); int maxHeight = maxAscent + maxDescent; int topPosition = heightOfBlock; int bottomPosition = heightOfBlock; placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, topPosition, bottomPosition); setOverflowPositions(topPosition, bottomPosition); // Shrink boxes with no text children in quirks and almost strict mode. if (!strictMode) 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 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, true)); bool isTableCell = object()->isTableCell(); if (isTableCell) { RenderTableCell* tableCell = static_cast<RenderTableCell*>(object()); setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine, true)); } else setBaseline(object()->baselinePosition(m_firstLine, true)); 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. 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 ); newBaseline = fm.ascent(); newY += curr->baseline() - newBaseline; newHeight = newBaseline+fm.descent(); 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 ); setHeight(fm.ascent()+fm.descent()); setYPos(yPos() + baseline() - fm.ascent()); setBaseline(fm.ascent()); 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::paintBackgroundAndBorder(RenderObject::PaintInfo& i, 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, i.r.y()); int mh; if (_ty < i.r.y()) mh= kMax(0, h - (i.r.y() - _ty)); else mh = kMin(i.r.height(), h); QPainter* p = i.p; // 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())) { CachedImage* bg = styleToUse->backgroundImage(); bool hasBackgroundImage = bg && (bg->pixmap_size() == bg->valid_rect().size()) && !bg->isTransparent() && !bg->isErrorImage(); if (!hasBackgroundImage || (!prevLineBox() && !nextLineBox()) || !parent()) object()->paintBackgroundExtended(p, styleToUse->backgroundColor(),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -