📄 renderbox.cpp
字号:
void RenderBox::positionLineBox(InlineBox* box){ if (isPositioned()) { // Cache the x position only if we were an INLINE type originally. bool wasInline = style()->isOriginalDisplayInlineType(); if (wasInline && style()->hasStaticX()) { // The value is cached in the xPos of the box. We only need this value if // our object was inline originally, since otherwise it would have ended up underneath // the inlines. layer()->setStaticX(box->x()); setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly. } else if (!wasInline && style()->hasStaticY()) { // Our object was a block originally, so we make our normal flow position be // just below the line box (as though all the inlines that came before us got // wrapped in an anonymous block, which is what would have happened had we been // in flow). This value was cached in the y() of the box. layer()->setStaticY(box->y()); setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly. } // Nuke the box. box->remove(); box->destroy(renderArena()); } else if (isReplaced()) { setLocation(box->x(), box->y()); m_inlineBoxWrapper = box; }}void RenderBox::deleteLineBoxWrapper(){ if (m_inlineBoxWrapper) { if (!documentBeingDestroyed()) m_inlineBoxWrapper->remove(); m_inlineBoxWrapper->destroy(renderArena()); m_inlineBoxWrapper = 0; }}IntRect RenderBox::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer){ if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return IntRect(); IntRect r = overflowRect(false); RenderView* v = view(); if (v) { // FIXME: layoutDelta needs to be applied in parts before/after transforms and // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308 r.move(v->layoutDelta()); } if (style()) { if (style()->hasAppearance()) // The theme may wish to inflate the rect used when repainting. theme()->adjustRepaintRect(this, r); // We have to use maximalOutlineSize() because a child might have an outline // that projects outside of our overflowRect. if (v) { ASSERT(style()->outlineSize() <= v->maximalOutlineSize()); r.inflate(v->maximalOutlineSize()); } } computeRectForRepaint(repaintContainer, r); return r;}void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed){ if (RenderView* v = view()) { // LayoutState is only valid for root-relative repainting if (v->layoutStateEnabled() && !repaintContainer) { LayoutState* layoutState = v->layoutState(); if (style()->position() == RelativePosition && layer()) rect.move(layer()->relativePositionOffset()); rect.move(x(), y()); rect.move(layoutState->m_offset); if (layoutState->m_clipped) rect.intersect(layoutState->m_clipRect); return; } } if (hasReflection()) rect.unite(reflectedRect(rect)); if (repaintContainer == this) return; RenderObject* o = container(); if (!o) return; IntPoint topLeft = rect.location(); topLeft.move(x(), y()); if (style()->position() == FixedPosition) fixed = true; if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) { RenderBlock* cb = toRenderBlock(o); if (cb->hasColumns()) { IntRect repaintRect(topLeft, rect.size()); cb->adjustRectForColumns(repaintRect); topLeft = repaintRect.location(); rect = repaintRect; } } // We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box // in the parent's coordinate space that encloses us. if (layer() && layer()->transform()) { fixed = false; rect = layer()->transform()->mapRect(rect); // FIXME: this clobbers topLeft adjustment done for multicol above topLeft = rect.location(); topLeft.move(x(), y()); } if (style()->position() == AbsolutePosition && o->isRelPositioned() && o->isRenderInline()) topLeft += toRenderInline(o)->relativePositionedInlineOffset(this); else if (style()->position() == RelativePosition && layer()) { // Apply the relative position offset when invalidating a rectangle. The layer // is translated, but the render box isn't, so we need to do this to get the // right dirty rect. Since this is called from RenderObject::setStyle, the relative position // flag on the RenderObject has been cleared, so use the one on the style(). topLeft += layer()->relativePositionOffset(); } // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout, // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer. if (o->hasOverflowClip()) { RenderBox* containerBox = toRenderBox(o); // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. topLeft -= containerBox->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden. IntRect repaintRect(topLeft, rect.size()); IntRect boxRect(0, 0, containerBox->layer()->width(), containerBox->layer()->height()); rect = intersection(repaintRect, boxRect); if (rect.isEmpty()) return; } else rect.setLocation(topLeft); o->computeRectForRepaint(repaintContainer, rect, fixed);}void RenderBox::repaintDuringLayoutIfMoved(const IntRect& rect){ int newX = x(); int newY = y(); int newWidth = width(); int newHeight = height(); if (rect.x() != newX || rect.y() != newY) { // The child moved. Invalidate the object's old and new positions. We have to do this // since the object may not have gotten a layout. m_frameRect = rect; repaint(); repaintOverhangingFloats(true); m_frameRect = IntRect(newX, newY, newWidth, newHeight); repaint(); repaintOverhangingFloats(true); }}void RenderBox::calcWidth(){ if (isPositioned()) { calcAbsoluteHorizontal(); return; } // If layout is limited to a subtree, the subtree root's width does not change. if (node() && view()->frameView() && view()->frameView()->layoutRoot(true) == this) return; // The parent box is flexing us, so it has increased or decreased our // width. Use the width from the style context. if (hasOverrideSize() && parent()->style()->boxOrient() == HORIZONTAL && parent()->isFlexibleBox() && parent()->isFlexingChildren()) { setWidth(overrideSize()); return; } bool inVerticalBox = parent()->isFlexibleBox() && (parent()->style()->boxOrient() == VERTICAL); bool stretching = (parent()->style()->boxAlign() == BSTRETCH); bool treatAsReplaced = shouldCalculateSizeAsReplaced() && (!inVerticalBox || !stretching); Length w = (treatAsReplaced) ? Length(calcReplacedWidth(), Fixed) : style()->width(); RenderBlock* cb = containingBlock(); int containerWidth = max(0, containingBlockWidthForContent()); Length marginLeft = style()->marginLeft(); Length marginRight = style()->marginRight(); if (isInline() && !isInlineBlockOrInlineTable()) { // just calculate margins m_marginLeft = marginLeft.calcMinValue(containerWidth); m_marginRight = marginRight.calcMinValue(containerWidth); if (treatAsReplaced) setWidth(max(w.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight(), minPrefWidth())); return; } // Width calculations if (treatAsReplaced) setWidth(w.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight()); else { // Calculate Width setWidth(calcWidthUsing(Width, containerWidth)); // Calculate MaxWidth if (!style()->maxWidth().isUndefined()) { int maxW = calcWidthUsing(MaxWidth, containerWidth); if (width() > maxW) { setWidth(maxW); w = style()->maxWidth(); } } // Calculate MinWidth int minW = calcWidthUsing(MinWidth, containerWidth); if (width() < minW) { setWidth(minW); w = style()->minWidth(); } } if (stretchesToMinIntrinsicWidth()) { setWidth(max(width(), minPrefWidth())); w = Length(width(), Fixed); } // Margin calculations if (w.isAuto()) { m_marginLeft = marginLeft.calcMinValue(containerWidth); m_marginRight = marginRight.calcMinValue(containerWidth); } else { m_marginLeft = 0; m_marginRight = 0; calcHorizontalMargins(marginLeft, marginRight, containerWidth); } if (containerWidth && containerWidth != (width() + m_marginLeft + m_marginRight) && !isFloating() && !isInline() && !cb->isFlexibleBox()) { if (cb->style()->direction() == LTR) m_marginRight = containerWidth - width() - m_marginLeft; else m_marginLeft = containerWidth - width() - m_marginRight; }}int RenderBox::calcWidthUsing(WidthType widthType, int cw){ int widthResult = width(); Length w; if (widthType == Width) w = style()->width(); else if (widthType == MinWidth) w = style()->minWidth(); else w = style()->maxWidth(); if (w.isIntrinsicOrAuto()) { int marginLeft = style()->marginLeft().calcMinValue(cw); int marginRight = style()->marginRight().calcMinValue(cw); if (cw) widthResult = cw - marginLeft - marginRight; if (sizesToIntrinsicWidth(widthType)) { widthResult = max(widthResult, minPrefWidth()); widthResult = min(widthResult, maxPrefWidth()); } } else widthResult = calcBorderBoxWidth(w.calcValue(cw)); return widthResult;}bool RenderBox::sizesToIntrinsicWidth(WidthType widthType) const{ // Marquees in WinIE are like a mixture of blocks and inline-blocks. They size as though they're blocks, // but they allow text to sit on the same line as the marquee. if (isFloating() || (isInlineBlockOrInlineTable() && !isHTMLMarquee())) return true; // This code may look a bit strange. Basically width:intrinsic should clamp the size when testing both // min-width and width. max-width is only clamped if it is also intrinsic. Length width = (widthType == MaxWidth) ? style()->maxWidth() : style()->width(); if (width.type() == Intrinsic) return true; // Children of a horizontal marquee do not fill the container by default. // FIXME: Need to deal with MAUTO value properly. It could be vertical. if (parent()->style()->overflowX() == OMARQUEE) { EMarqueeDirection dir = parent()->style()->marqueeDirection(); if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT) return true; } // Flexible horizontal boxes lay out children at their intrinsic widths. Also vertical boxes // that don't stretch their kids lay out their children at their intrinsic widths. if (parent()->isFlexibleBox() && (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH)) return true; return false;}void RenderBox::calcHorizontalMargins(const Length& marginLeft, const Length& marginRight, int containerWidth){ if (isFloating() || isInline()) { // Inline blocks/tables and floats don't have their margins increased. m_marginLeft = marginLeft.calcMinValue(containerWidth); m_marginRight = marginRight.calcMinValue(containerWidth); return; } if ((marginLeft.isAuto() && marginRight.isAuto() && width() < containerWidth) || (!marginLeft.isAuto() && !marginRight.isAuto() && containingBlock()->style()->textAlign() == WEBKIT_CENTER)) { m_marginLeft = max(0, (containerWidth - width()) / 2); m_marginRight = containerWidth - width() - m_marginLeft; } else if ((marginRight.isAuto() && width() < containerWidth) || (!marginLeft.isAuto() && containingBlock()->style()->direction() == RTL && containingBlock()->style()->textAlign() == WEBKIT_LEFT)) { m_marginLeft = marginLeft.calcValue(containerWidth); m_marginRight = containerWidth - width() - m_marginLeft; } else if ((marginLeft.isAuto() && width() < containerWidth) || (!marginRight.isAuto() && containingBlock()->style()->direction() == LTR && containingBlock()->style()->textAlign() == WEBKIT_RIGHT)) { m_marginRight = marginRight.calcValue(containerWidth); m_marginLeft = containerWidth - width() - m_marginRight; } else { // This makes auto margins 0 if we failed a width() < containerWidth test above (css2.1, 10.3.3). m_marginLeft = marginLeft.calcMinValue(containerWidth); m_marginRight = marginRight.calcMinValue(containerWidth); }}void RenderBox::calcHeight(){ // Cell height is managed by the table and inline non-replaced elements do not support a height property.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -