#include "core/page/AutoscrollController.h"
#include "core/page/EventHandler.h"
#include "core/page/Page.h"
+#include "core/paint/BackgroundImageGeometry.h"
+#include "core/paint/BoxPainter.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderDeprecatedFlexibleBox.h"
#include "core/rendering/RenderListBox.h"
#include "core/rendering/RenderListMarker.h"
#include "core/rendering/RenderTableCell.h"
-#include "core/rendering/RenderTheme.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "platform/LengthFunctions.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/TransformState.h"
-#include "platform/graphics/GraphicsContextStateSaver.h"
#include <algorithm>
#include <math.h>
// the canvas. Just dirty the entire canvas when our style changes substantially.
if ((diff.needsPaintInvalidation() || diff.needsLayout()) && node()
&& (isHTMLHtmlElement(*node()) || isHTMLBodyElement(*node()))) {
- view()->paintInvalidationForWholeRenderer();
+ view()->setShouldDoFullPaintInvalidation(true);
if (oldStyle->hasEntirelyFixedBackground() != newStyle.hasEntirelyFixedBackground())
view()->compositor()->setNeedsUpdateFixedBackground();
if (diff.needsFullLayout() && parent() && oldStyle->position() != newStyle.position()) {
markContainingBlocksForLayout();
if (oldStyle->position() == StaticPosition)
- paintInvalidationForWholeRenderer();
+ setShouldDoFullPaintInvalidation(true);
else if (newStyle.hasOutOfFlowPosition())
parent()->setChildNeedsLayout();
if (isFloating() && !isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition())
// FIXME: This branch runs when !oldStyle, which means that layout was never called
// so what's the point in invalidating the whole view that we never painted?
} else if (isBody()) {
- view()->paintInvalidationForWholeRenderer();
+ view()->setShouldDoFullPaintInvalidation(true);
}
RenderBoxModelObject::styleWillChange(diff, newStyle);
RenderBoxModelObject::styleDidChange(diff, oldStyle);
RenderStyle* newStyle = style();
- if (needsLayout() && oldStyle) {
+ if (needsLayout() && oldStyle)
RenderBlock::removePercentHeightDescendantIfNeeded(this);
- // Normally we can do optimized positioning layout for absolute/fixed positioned objects. There is one special case, however, which is
- // when the positioned object's margin-before is changed. In this case the parent has to get a layout in order to run margin collapsing
- // to determine the new static position.
- if (isOutOfFlowPositioned() && newStyle->hasStaticBlockPosition(isHorizontalWritingMode()) && oldStyle->marginBefore() != newStyle->marginBefore()
- && parent() && !parent()->normalChildNeedsLayout())
- parent()->setChildNeedsLayout();
- }
-
if (RenderBlock::hasPercentHeightContainerMap() && slowFirstChild()
&& oldHorizontalWritingMode != isHorizontalWritingMode())
RenderBlock::clearPercentHeightDescendantsFrom(this);
// generated by positioned children or self painting layers. crbug.com/345403
for (RenderObject* child = slowFirstChild(); child; child = child->nextSibling())
child->setShouldDoFullPaintInvalidationIfSelfPaintingLayer(true);
-
- if (isRenderBlock())
- toRenderBlock(this)->invalidatePositionedObjectsAffectedByOverflowClip();
}
setHasOverflowClip(boxHasOverflowClip);
newRect = layer()->scrollableArea()->exposeRect(rect, alignX, alignY);
} else if (!parentBox && canBeProgramaticallyScrolled()) {
if (FrameView* frameView = this->frameView()) {
- Element* ownerElement = document().ownerElement();
+ HTMLFrameOwnerElement* ownerElement = document().ownerElement();
if (ownerElement && ownerElement->renderer()) {
- HTMLFrameElementBase* frameElementBase = 0;
-
- if (isHTMLFrameElement(*ownerElement) || isHTMLIFrameElement(*ownerElement))
- frameElementBase = toHTMLFrameElementBase(ownerElement);
-
+ HTMLFrameElementBase* frameElementBase = isHTMLFrameElementBase(*ownerElement) ? toHTMLFrameElementBase(ownerElement) : 0;
if (frameElementAndViewPermitScroll(frameElementBase, frameView)) {
LayoutRect viewRect = frameView->visibleContentRect();
LayoutRect exposeRect = ScrollAlignment::getRectToExpose(viewRect, rect, alignX, alignY);
LayoutUnit RenderBox::constrainLogicalWidthByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb) const
{
RenderStyle* styleToUse = style();
- if (!styleToUse->logicalMaxWidth().isUndefined())
+ if (!styleToUse->logicalMaxWidth().isMaxSizeNone())
logicalWidth = std::min(logicalWidth, computeLogicalWidthUsing(MaxSize, styleToUse->logicalMaxWidth(), availableWidth, cb));
return std::max(logicalWidth, computeLogicalWidthUsing(MinSize, styleToUse->logicalMinWidth(), availableWidth, cb));
}
LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const
{
RenderStyle* styleToUse = style();
- if (!styleToUse->logicalMaxHeight().isUndefined()) {
+ if (!styleToUse->logicalMaxHeight().isMaxSizeNone()) {
LayoutUnit maxH = computeLogicalHeightUsing(styleToUse->logicalMaxHeight(), intrinsicContentHeight);
if (maxH != -1)
logicalHeight = std::min(logicalHeight, maxH);
LayoutUnit RenderBox::constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const
{
RenderStyle* styleToUse = style();
- if (!styleToUse->logicalMaxHeight().isUndefined()) {
+ if (!styleToUse->logicalMaxHeight().isMaxSizeNone()) {
LayoutUnit maxH = computeContentLogicalHeight(styleToUse->logicalMaxHeight(), intrinsicContentHeight);
if (maxH != -1)
logicalHeight = std::min(logicalHeight, maxH);
return localToAbsoluteQuad(FloatRect(rect));
}
-void RenderBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) const
+void RenderBox::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) const
{
if (!size().isEmpty())
- rects.append(pixelSnappedIntRect(additionalOffset, size()));
+ rects.append(LayoutRect(additionalOffset, size()));
}
bool RenderBox::canResize() const
return layer()->scrollableArea()->scrollOffset();
}
-void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const
+void RenderBox::applyCachedClipAndScrollOffsetForPaintInvalidation(LayoutRect& paintRect) const
{
ASSERT(hasLayer());
ASSERT(hasOverflowClip());
}
// height() is inaccurate if we're in the middle of a layout of this RenderBox, so use the
- // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
+ // layer's size instead. Even if the layer's size is wrong, the layer itself will issue paint invalidations
// anyway if its size does change.
LayoutRect clipRect(LayoutPoint(), layer()->size());
paintRect = intersection(paintRect, clipRect);
return false;
}
-// --------------------- painting stuff -------------------------------
-
void RenderBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- LayoutPoint adjustedPaintOffset = paintOffset + location();
- // default implementation. Just pass paint through to the children
- PaintInfo childInfo(paintInfo);
- childInfo.updatePaintingRootForChildren(this);
- for (RenderObject* child = slowFirstChild(); child; child = child->nextSibling())
- child->paint(childInfo, adjustedPaintOffset);
+ BoxPainter(*this).paint(paintInfo, paintOffset);
}
-void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
-{
- if (paintInfo.skipRootBackground())
- return;
-
- RenderObject* rootBackgroundRenderer = rendererForRootBackground();
-
- const FillLayer& bgLayer = rootBackgroundRenderer->style()->backgroundLayers();
- Color bgColor = rootBackgroundRenderer->resolveColor(CSSPropertyBackgroundColor);
-
- paintFillLayers(paintInfo, bgColor, bgLayer, view()->backgroundRect(this), BackgroundBleedNone, CompositeSourceOver, rootBackgroundRenderer);
-}
-
-BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsContext* context, const BoxDecorationData& boxDecorationData) const
-{
- if (!boxDecorationData.hasBackground || !boxDecorationData.hasBorder || !style()->hasBorderRadius() || canRenderBorderImage())
- return BackgroundBleedNone;
-
- // FIXME: See crbug.com/382491. getCTM does not accurately reflect the scale at the time content is
- // rasterized, and should not be relied on to make decisions about bleeding.
- AffineTransform ctm = context->getCTM();
- FloatSize contextScaling(static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()));
-
- // Because RoundedRect uses IntRect internally the inset applied by the
- // BackgroundBleedShrinkBackground strategy cannot be less than one integer
- // layout coordinate, even with subpixel layout enabled. To take that into
- // account, we clamp the contextScaling to 1.0 for the following test so
- // that borderObscuresBackgroundEdge can only return true if the border
- // widths are greater than 2 in both layout coordinates and screen
- // coordinates.
- // This precaution will become obsolete if RoundedRect is ever promoted to
- // a sub-pixel representation.
- if (contextScaling.width() > 1)
- contextScaling.setWidth(1);
- if (contextScaling.height() > 1)
- contextScaling.setHeight(1);
-
- if (borderObscuresBackgroundEdge(contextScaling))
- return BackgroundBleedShrinkBackground;
- if (!boxDecorationData.hasAppearance && borderObscuresBackground() && backgroundHasOpaqueTopLayer())
- return BackgroundBleedBackgroundOverBorder;
-
- return BackgroundBleedClipBackground;
-}
void RenderBox::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(this))
- return;
-
- LayoutRect paintRect = borderBoxRect();
- paintRect.moveBy(paintOffset);
- paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect);
+ BoxPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset);
}
-void RenderBox::paintBoxDecorationBackgroundWithRect(PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutRect& paintRect)
-{
- RenderStyle* style = this->style();
- BoxDecorationData boxDecorationData(*style);
- BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context, boxDecorationData);
-
- // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
- // custom shadows of their own.
- if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
- paintBoxShadow(paintInfo, paintRect, style, Normal);
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
- if (bleedAvoidance == BackgroundBleedClipBackground) {
- stateSaver.save();
- RoundedRect border = style->getRoundedBorderFor(paintRect);
- paintInfo.context->clipRoundedRect(border);
- }
-
- // If we have a native theme appearance, paint that before painting our background.
- // The theme will tell us whether or not we should also paint the CSS background.
- IntRect snappedPaintRect(pixelSnappedIntRect(paintRect));
- bool themePainted = boxDecorationData.hasAppearance && !RenderTheme::theme().paint(this, paintInfo, snappedPaintRect);
- if (!themePainted) {
- if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
- paintBorder(paintInfo, paintRect, style, bleedAvoidance);
- paintBackground(paintInfo, paintRect, boxDecorationData.backgroundColor, bleedAvoidance);
-
- if (boxDecorationData.hasAppearance)
- RenderTheme::theme().paintDecorations(this, paintInfo, snappedPaintRect);
- }
- paintBoxShadow(paintInfo, paintRect, style, Inset);
-
- // The theme will tell us whether or not we should also paint the CSS border.
- if (boxDecorationData.hasBorder && bleedAvoidance != BackgroundBleedBackgroundOverBorder && (!boxDecorationData.hasAppearance || (!themePainted && RenderTheme::theme().paintBorderOnly(this, paintInfo, snappedPaintRect))) && !(isTable() && toRenderTable(this)->collapseBorders()))
- paintBorder(paintInfo, paintRect, style, bleedAvoidance);
-}
-
-void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, const Color& backgroundColor, BackgroundBleedAvoidance bleedAvoidance)
-{
- if (isDocumentElement()) {
- paintRootBoxFillLayers(paintInfo);
- return;
- }
- if (isBody() && skipBodyBackground(this))
- return;
- if (boxDecorationBackgroundIsKnownToBeObscured())
- return;
- paintFillLayers(paintInfo, backgroundColor, style()->backgroundLayers(), paintRect, bleedAvoidance);
-}
-
-bool RenderBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent) const
+bool RenderBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent)
{
ASSERT(hasBackground());
LayoutRect backgroundRect = pixelSnappedIntRect(borderBoxRect());
}
BackgroundImageGeometry geometry;
- calculateBackgroundImageGeometry(0, style()->backgroundLayers(), backgroundRect, geometry);
+ BoxPainter::calculateBackgroundImageGeometry(*this, 0, style()->backgroundLayers(), backgroundRect, geometry);
if (geometry.hasNonLocalGeometry())
return false;
paintedExtent = geometry.destRect();
void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
- return;
-
- LayoutRect paintRect = LayoutRect(paintOffset, size());
- paintMaskImages(paintInfo, paintRect);
+ BoxPainter(*this).paintMask(paintInfo, paintOffset);
}
void RenderBox::paintClippingMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseClippingMask)
- return;
-
- if (!layer() || layer()->compositingState() != PaintsIntoOwnBacking)
- return;
-
- // We should never have this state in this function. A layer with a mask
- // should have always created its own backing if it became composited.
- ASSERT(layer()->compositingState() != HasOwnBackingButPaintsIntoAncestor);
-
- LayoutRect paintRect = LayoutRect(paintOffset, size());
- paintInfo.context->fillRect(pixelSnappedIntRect(paintRect), Color::black);
-}
-
-void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& paintRect)
-{
- // Figure out if we need to push a transparency layer to render our mask.
- bool pushTransparencyLayer = false;
- bool compositedMask = hasLayer() && layer()->hasCompositedMask();
- bool flattenCompositingLayers = view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
- CompositeOperator compositeOp = CompositeSourceOver;
-
- bool allMaskImagesLoaded = true;
-
- if (!compositedMask || flattenCompositingLayers) {
- pushTransparencyLayer = true;
- StyleImage* maskBoxImage = style()->maskBoxImage().image();
- const FillLayer& maskLayers = style()->maskLayers();
-
- // Don't render a masked element until all the mask images have loaded, to prevent a flash of unmasked content.
- if (maskBoxImage)
- allMaskImagesLoaded &= maskBoxImage->isLoaded();
-
- allMaskImagesLoaded &= maskLayers.imagesAreLoaded();
-
- paintInfo.context->setCompositeOperation(CompositeDestinationIn);
- paintInfo.context->beginTransparencyLayer(1);
- compositeOp = CompositeSourceOver;
- }
-
- if (allMaskImagesLoaded) {
- paintFillLayers(paintInfo, Color::transparent, style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
- paintNinePieceImage(paintInfo.context, paintRect, style(), style()->maskBoxImage(), compositeOp);
- }
-
- if (pushTransparencyLayer)
- paintInfo.context->endLayer();
-}
-
-void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect,
- BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
-{
- Vector<const FillLayer*, 8> layers;
- const FillLayer* curLayer = &fillLayer;
- bool shouldDrawBackgroundInSeparateBuffer = false;
- while (curLayer) {
- layers.append(curLayer);
- // Stop traversal when an opaque layer is encountered.
- // FIXME : It would be possible for the following occlusion culling test to be more aggressive
- // on layers with no repeat by testing whether the image covers the layout rect.
- // Testing that here would imply duplicating a lot of calculations that are currently done in
- // RenderBoxModelObject::paintFillLayerExtended. A more efficient solution might be to move
- // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
- // and pass it down.
-
- if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != WebBlendModeNormal)
- shouldDrawBackgroundInSeparateBuffer = true;
-
- // The clipOccludesNextLayers condition must be evaluated first to avoid short-circuiting.
- if (curLayer->clipOccludesNextLayers(curLayer == &fillLayer) && curLayer->hasOpaqueImage(this) && curLayer->image()->canRender(*this, style()->effectiveZoom()) && curLayer->hasRepeatXY() && curLayer->blendMode() == WebBlendModeNormal && !boxShadowShouldBeAppliedToBackground(bleedAvoidance))
- break;
- curLayer = curLayer->next();
- }
-
- GraphicsContext* context = paintInfo.context;
- if (!context)
- shouldDrawBackgroundInSeparateBuffer = false;
- if (shouldDrawBackgroundInSeparateBuffer)
- context->beginTransparencyLayer(1);
-
- Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
- for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
- paintFillLayer(paintInfo, c, **it, rect, bleedAvoidance, op, backgroundObject);
-
- if (shouldDrawBackgroundInSeparateBuffer)
- context->endLayer();
-}
-
-void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect,
- BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
-{
- paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, 0, LayoutSize(), op, backgroundObject);
+ BoxPainter(*this).paintClippingMask(paintInfo, paintOffset);
}
void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
if ((style()->borderImage().image() && style()->borderImage().image()->data() == image) ||
(style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image)) {
- paintInvalidationForWholeRenderer();
+ setShouldDoFullPaintInvalidation(true);
return;
}
markShapeOutsideDependentsForLayout();
}
- bool didFullRepaint = repaintLayerRectsForImage(image, style()->backgroundLayers(), true);
- if (!didFullRepaint)
- repaintLayerRectsForImage(image, style()->maskLayers(), false);
+ if (!paintInvalidationLayerRectsForImage(image, style()->backgroundLayers(), true))
+ paintInvalidationLayerRectsForImage(image, style()->maskLayers(), false);
}
-bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer& layers, bool drawingBackground)
+bool RenderBox::paintInvalidationLayerRectsForImage(WrappedImagePtr image, const FillLayer& layers, bool drawingBackground)
{
- LayoutRect rendererRect;
- RenderBox* layerRenderer = 0;
-
for (const FillLayer* curLayer = &layers; curLayer; curLayer = curLayer->next()) {
if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(*this, style()->effectiveZoom())) {
- // Now that we know this image is being used, compute the renderer and the rect if we haven't already.
- if (!layerRenderer) {
- bool drawingRootBackground = drawingBackground && (isDocumentElement() || (isBody() && !document().documentElement()->renderer()->hasBackground()));
- if (drawingRootBackground) {
- layerRenderer = view();
-
- LayoutUnit rw;
- LayoutUnit rh;
-
- if (FrameView* frameView = toRenderView(layerRenderer)->frameView()) {
- rw = frameView->contentsWidth();
- rh = frameView->contentsHeight();
- } else {
- rw = layerRenderer->width();
- rh = layerRenderer->height();
- }
- rendererRect = LayoutRect(-layerRenderer->marginLeft(),
- -layerRenderer->marginTop(),
- std::max(layerRenderer->width() + layerRenderer->marginWidth() + layerRenderer->borderLeft() + layerRenderer->borderRight(), rw),
- std::max(layerRenderer->height() + layerRenderer->marginHeight() + layerRenderer->borderTop() + layerRenderer->borderBottom(), rh));
- } else {
- layerRenderer = this;
- rendererRect = borderBoxRect();
- }
- }
-
- BackgroundImageGeometry geometry;
- layerRenderer->calculateBackgroundImageGeometry(0, *curLayer, rendererRect, geometry);
- if (geometry.hasNonLocalGeometry()) {
- // Rather than incur the costs of computing the paintContainer for renderers with fixed backgrounds
- // in order to get the right destRect, just repaint the entire renderer.
- layerRenderer->paintInvalidationForWholeRenderer();
- return true;
- }
-
- layerRenderer->invalidatePaintRectangle(geometry.destRect());
- if (geometry.destRect() == rendererRect)
- return true;
+ setShouldDoFullPaintInvalidation(true);
+ return true;
}
}
return false;
InvalidationReason RenderBox::invalidatePaintIfNeeded(const PaintInvalidationState& paintInvalidationState, const RenderLayerModelObject& newPaintInvalidationContainer)
{
- const LayoutRect oldPaintInvalidationRect = previousPaintInvalidationRect();
- const LayoutPoint oldPositionFromPaintInvalidationContainer = previousPositionFromPaintInvalidationContainer();
- setPreviousPaintInvalidationRect(boundsRectForPaintInvalidation(&newPaintInvalidationContainer, &paintInvalidationState));
- setPreviousPositionFromPaintInvalidationContainer(RenderLayer::positionFromPaintInvalidationContainer(this, &newPaintInvalidationContainer, &paintInvalidationState));
-
- InvalidationReason reason = InvalidationNone;
-
// If we are set to do a full paint invalidation that means the RenderView will be
// issue paint invalidations. We can then skip issuing of paint invalidations for the child
// renderers as they'll be covered by the RenderView.
&& layer()->isSelfPaintingLayer())) {
setShouldDoFullPaintInvalidation(true, MarkOnlyThis);
}
+ }
- reason = RenderObject::invalidatePaintIfNeeded(newPaintInvalidationContainer, oldPaintInvalidationRect, oldPositionFromPaintInvalidationContainer, paintInvalidationState);
+ InvalidationReason reason = RenderBoxModelObject::invalidatePaintIfNeeded(paintInvalidationState, newPaintInvalidationContainer);
+
+ if (!view()->doingFullPaintInvalidation()) {
if (reason == InvalidationNone || reason == InvalidationIncremental)
invalidatePaintForOverflowIfNeeded();
LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlockFlow* cb) const
{
LayoutUnit logicalTopPosition = logicalTop();
- LayoutUnit width = cb->availableLogicalWidthForLine(logicalTopPosition, false) - std::max<LayoutUnit>(0, childMarginStart) - std::max<LayoutUnit>(0, childMarginEnd);
+ LayoutUnit startOffsetForContent = cb->startOffsetForContent();
+ LayoutUnit endOffsetForContent = cb->endOffsetForContent();
+ LayoutUnit startOffsetForLine = cb->startOffsetForLine(logicalTopPosition, false);
+ LayoutUnit endOffsetForLine = cb->endOffsetForLine(logicalTopPosition, false);
+ // If there aren't any floats constraining us then allow the margins to shrink/expand the width as much as they want.
+ if (startOffsetForContent == startOffsetForLine && endOffsetForContent == endOffsetForLine)
+ return cb->availableLogicalWidthForLine(logicalTopPosition, false) - childMarginStart - childMarginEnd;
+
+ LayoutUnit width = cb->availableLogicalWidthForLine(logicalTopPosition, false) - std::max<LayoutUnit>(0, childMarginStart) - std::max<LayoutUnit>(0, childMarginEnd);
// We need to see if margins on either the start side or the end side can contain the floats in question. If they can,
// then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line
// offset at all, but can instead push all the way to the content edge of the containing block. In the case where the float
// doesn't fit, we can use the line offset, but we need to grow it by the margin to reflect the fact that the margin was
// "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them.
- width += portionOfMarginNotConsumedByFloat(childMarginStart, cb->startOffsetForContent(), cb->startOffsetForLine(logicalTopPosition, false));
- width += portionOfMarginNotConsumedByFloat(childMarginEnd, cb->endOffsetForContent(), cb->endOffsetForLine(logicalTopPosition, false));
+ width += portionOfMarginNotConsumedByFloat(childMarginStart, startOffsetForContent, startOffsetForLine);
+ width += portionOfMarginNotConsumedByFloat(childMarginEnd, endOffsetForContent, endOffsetForLine);
return width;
}
return cb->adjustContentBoxLogicalHeightForBoxSizing(logicalHeightLength.value());
}
-void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const
+void RenderBox::mapLocalToContainer(const RenderLayerModelObject* paintInvalidationContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const
{
- if (repaintContainer == this)
+ if (paintInvalidationContainer == this)
return;
- if (paintInvalidationState && paintInvalidationState->canMapToContainer(repaintContainer)) {
+ if (paintInvalidationState && paintInvalidationState->canMapToContainer(paintInvalidationContainer)) {
LayoutSize offset = paintInvalidationState->paintOffset() + locationOffset();
if (style()->hasInFlowPosition() && layer())
offset += layer()->offsetForInFlowPosition();
}
bool containerSkipped;
- RenderObject* o = container(repaintContainer, &containerSkipped);
+ RenderObject* o = container(paintInvalidationContainer, &containerSkipped);
if (!o)
return;
transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
if (containerSkipped) {
- // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
- // to just subtract the delta between the repaintContainer and o.
- LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
+ // There can't be a transform between paintInvalidationContainer and o, because transforms create containers, so it should be safe
+ // to just subtract the delta between the paintInvalidationContainer and o.
+ LayoutSize containerOffset = paintInvalidationContainer->offsetFromAncestorContainer(o);
transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
return;
}
mode &= ~ApplyContainerFlip;
- o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
+ o->mapLocalToContainer(paintInvalidationContainer, transformState, mode, wasFixed);
}
void RenderBox::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
}
LayoutRect r = visualOverflowRect();
- ViewportConstrainedPosition viewportConstraint = style()->position() == FixedPosition ? IsFixedPosition : IsNotFixedPosition;
- mapRectToPaintInvalidationBacking(paintInvalidationContainer, r, viewportConstraint, paintInvalidationState);
+ mapRectToPaintInvalidationBacking(paintInvalidationContainer, r, paintInvalidationState);
return r;
}
-void RenderBox::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, ViewportConstrainedPosition, const PaintInvalidationState* paintInvalidationState) const
+void RenderBox::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState) const
{
// The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space.
// Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more appropriate
- // offset corner for the enclosing container). This allows for a fully RL or BT document to repaint
+ // offset corner for the enclosing container). This allows for a fully RL or BT document to issue paint invalidations
// properly even during layout, since the rect remains flipped all the way until the end.
//
- // RenderView::computeRectForRepaint then converts the rect to physical coordinates. We also convert to
+ // RenderView::computeRectForPaintInvalidation then converts the rect to physical coordinates. We also convert to
// physical when we hit a paintInvalidationContainer boundary. Therefore the final rect returned is always in the
// physical coordinate space of the paintInvalidationContainer.
RenderStyle* styleToUse = style();
EPosition position = styleToUse->position();
+ // We need to inflate the paint invalidation rect before we use paintInvalidationState,
+ // else we would forget to inflate it for the current renderer. FIXME: If these were
+ // included into the visual overflow for repaint, we wouldn't have this issue.
+ inflatePaintInvalidationRectForReflectionAndFilter(rect);
+
if (paintInvalidationState && paintInvalidationState->canMapToContainer(paintInvalidationContainer) && position != FixedPosition) {
if (layer() && layer()->transform())
rect = layer()->transform()->mapRect(pixelSnappedIntRect(rect));
return;
}
- if (hasReflection())
- rect.unite(reflectedRect(rect));
-
if (paintInvalidationContainer == this) {
if (paintInvalidationContainer->style()->isFlippedBlocksWritingMode())
flipForWritingMode(rect);
}
if (position != AbsolutePosition && position != FixedPosition && o->hasColumns() && o->isRenderBlockFlow()) {
- LayoutRect repaintRect(topLeft, rect.size());
- toRenderBlock(o)->adjustRectForColumns(repaintRect);
- topLeft = repaintRect.location();
- rect = repaintRect;
+ LayoutRect paintInvalidationRect(topLeft, rect.size());
+ toRenderBlock(o)->adjustRectForColumns(paintInvalidationRect);
+ topLeft = paintInvalidationRect.location();
+ rect = paintInvalidationRect;
}
// 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.
rect.setLocation(topLeft);
- if (o->hasOverflowClip() && !shouldDoFullPaintInvalidationIfSelfPaintingLayer()) {
+ if (o->hasOverflowClip()) {
RenderBox* containerBox = toRenderBox(o);
- containerBox->applyCachedClipAndScrollOffsetForRepaint(rect);
+ containerBox->applyCachedClipAndScrollOffsetForPaintInvalidation(rect);
if (rect.isEmpty())
return;
}
return;
}
- ViewportConstrainedPosition viewportConstraint = position == FixedPosition ? IsFixedPosition : IsNotFixedPosition;
- o->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, viewportConstraint, paintInvalidationState);
+ if (o->isRenderView())
+ toRenderView(o)->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, position == FixedPosition ? RenderView::IsFixedPosition : RenderView::IsNotFixedPosition, paintInvalidationState);
+ else
+ o->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, paintInvalidationState);
+}
+
+void RenderBox::inflatePaintInvalidationRectForReflectionAndFilter(LayoutRect& paintInvalidationRect) const
+{
+ if (hasReflection())
+ paintInvalidationRect.unite(reflectedRect(paintInvalidationRect));
+
+ if (style()->hasFilter())
+ style()->filterOutsets().expandRect(paintInvalidationRect);
}
void RenderBox::invalidatePaintForOverhangingFloats(bool)
return logicalWidthResult;
}
-static bool columnFlexItemHasStretchAlignment(const RenderObject* flexitem)
+static bool flexItemHasStretchAlignment(const RenderObject* flexitem)
{
RenderObject* parent = flexitem->parent();
- // auto margins mean we don't stretch. Note that this function will only be used for
- // widths, so we don't have to check marginBefore/marginAfter.
- ASSERT(parent->style()->isColumnFlexDirection());
- if (flexitem->style()->marginStart().isAuto() || flexitem->style()->marginEnd().isAuto())
- return false;
+ // auto margins mean we don't stretch.
+ if (parent->style()->isColumnFlexDirection()) {
+ if (flexitem->style()->marginStart().isAuto() || flexitem->style()->marginEnd().isAuto())
+ return false;
+ } else {
+ if (flexitem->style()->marginBefore().isAuto() || flexitem->style()->marginAfter().isAuto())
+ return false;
+ }
return flexitem->style()->alignSelf() == ItemPositionStretch || (flexitem->style()->alignSelf() == ItemPositionAuto && parent->style()->alignItems() == ItemPositionStretch);
}
return true;
// We don't stretch multiline flexboxes because they need to apply line spacing (align-content) first.
- if (parent->isFlexibleBox() && parent->style()->flexWrap() == FlexNoWrap && parent->style()->isColumnFlexDirection() && columnFlexItemHasStretchAlignment(flexitem))
+ if (parent->isFlexibleBox() && parent->style()->flexWrap() == FlexNoWrap && parent->style()->isColumnFlexDirection() && flexItemHasStretchAlignment(flexitem))
return true;
return false;
}
// For multiline columns, we need to apply align-content first, so we can't stretch now.
if (!parent()->style()->isColumnFlexDirection() || parent()->style()->flexWrap() != FlexNoWrap)
return true;
- if (!columnFlexItemHasStretchAlignment(this))
+ if (!flexItemHasStretchAlignment(this))
return true;
}
bool includeBorderPadding = isTable();
- if (isHorizontalWritingMode() != cb->isHorizontalWritingMode())
+ if (isHorizontalWritingMode() != cb->isHorizontalWritingMode()) {
availableHeight = containingBlockChild->containingBlockLogicalWidthForContent();
- else if (hasOverrideContainingBlockLogicalHeight())
+ } else if (hasOverrideContainingBlockLogicalHeight()) {
availableHeight = overrideContainingBlockContentLogicalHeight();
- else if (cb->isTableCell()) {
+ } else if (cb->isFlexItem() && flexItemHasStretchAlignment(cb) && cb->hasOverrideHeight()) {
+ availableHeight = cb->overrideLogicalContentHeight();
+ } else if (cb->isTableCell()) {
if (!skippedAutoHeightContainingBlock) {
// Table cells violate what the CSS spec says to do with heights. Basically we
// don't care if the cell specified a height or not. We just always make ourselves
LayoutUnit RenderBox::computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, ShouldComputePreferred shouldComputePreferred) const
{
- LayoutUnit minLogicalWidth = (shouldComputePreferred == ComputePreferred && style()->logicalMinWidth().isPercent()) || style()->logicalMinWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMinWidth());
- LayoutUnit maxLogicalWidth = (shouldComputePreferred == ComputePreferred && style()->logicalMaxWidth().isPercent()) || style()->logicalMaxWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMaxWidth());
+ LayoutUnit minLogicalWidth = (shouldComputePreferred == ComputePreferred && style()->logicalMinWidth().isPercent()) || style()->logicalMinWidth().isMaxSizeNone() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMinWidth());
+ LayoutUnit maxLogicalWidth = (shouldComputePreferred == ComputePreferred && style()->logicalMaxWidth().isPercent()) || style()->logicalMaxWidth().isMaxSizeNone() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMaxWidth());
return std::max(minLogicalWidth, std::min(logicalWidth, maxLogicalWidth));
}
case Intrinsic:
case MinIntrinsic:
case Auto:
- case Undefined:
+ case MaxSizeNone:
return intrinsicLogicalWidth();
case ExtendToZoom:
case DeviceWidth:
computedValues);
// Calculate constraint equation values for 'max-width' case.
- if (!style()->logicalMaxWidth().isUndefined()) {
+ if (!style()->logicalMaxWidth().isMaxSizeNone()) {
LogicalExtentComputedValues maxValues;
computePositionedLogicalWidthUsing(style()->logicalMaxWidth(), containerBlock, containerDirection,
if (autoWidthShouldFitContent())
shrinkToFitWidth(availableSpace, logicalLeftValue, bordersPlusPadding, computedValues);
else
- computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth));
+ computedValues.m_extent = std::max<LayoutUnit>(0, availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth)));
} else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 6: (no need solve for right)
logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
// see FIXME 2
// Calculate constraint equation values for 'max-height' case.
- if (!styleToUse->logicalMaxHeight().isUndefined()) {
+ if (!styleToUse->logicalMaxHeight().isMaxSizeNone()) {
LogicalExtentComputedValues maxValues;
computePositionedLogicalHeightUsing(styleToUse->logicalMaxHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalHeight,
if (!style()->hasBackground() && !style()->hasBoxDecorations())
return invalidationReason;
- LayoutSize oldBorderBoxSize;
- if (m_rareData && m_rareData->m_previousBorderBoxSize.width() != -1) {
- oldBorderBoxSize = m_rareData->m_previousBorderBoxSize;
- } else {
- // We didn't save the old border box size because it was the same as the size of oldBounds.
- oldBorderBoxSize = oldBounds.size();
- }
-
+ LayoutSize oldBorderBoxSize = computePreviousBorderBoxSize(oldBounds.size());
LayoutSize newBorderBoxSize = size();
if (oldBorderBoxSize == newBorderBoxSize)
return invalidationReason;
+ // FIXME: Implement correct incremental invalidation for visual overflowing effects.
+ if (style()->hasVisualOverflowingEffect() || style()->hasAppearance() || style()->hasFilter())
+ return InvalidationBorderBoxChange;
+
+ if (style()->hasBorderRadius()) {
+ // If a border-radius exists and width/height is smaller than radius width/height,
+ // we need to fully invalidate to cover the changed radius.
+ RoundedRect oldRoundedRect = style()->getRoundedBorderFor(LayoutRect(LayoutPoint(0, 0), oldBorderBoxSize));
+ RoundedRect newRoundedRect = style()->getRoundedBorderFor(LayoutRect(LayoutPoint(0, 0), newBorderBoxSize));
+ if (oldRoundedRect.radii() != newRoundedRect.radii())
+ return InvalidationBorderBoxChange;
+ }
+
if (oldBorderBoxSize.width() != newBorderBoxSize.width() && mustInvalidateBackgroundOrBorderPaintOnWidthChange())
return InvalidationBorderBoxChange;
if (oldBorderBoxSize.height() != newBorderBoxSize.height() && mustInvalidateBackgroundOrBorderPaintOnHeightChange())
return InvalidationBorderBoxChange;
- // If size of repaint rect equals to size of border box, RenderObject::incrementallyInvalidatePaint()
+ return InvalidationIncremental;
+}
+
+void RenderBox::incrementallyInvalidatePaint(const RenderLayerModelObject& paintInvalidationContainer, const LayoutRect& oldBounds, const LayoutRect& newBounds, const LayoutPoint& positionFromPaintInvalidationBacking)
+{
+ RenderObject::incrementallyInvalidatePaint(paintInvalidationContainer, oldBounds, newBounds, positionFromPaintInvalidationBacking);
+
+ bool hasBoxDecorations = style()->hasBoxDecorations();
+ if (!style()->hasBackground() && !hasBoxDecorations)
+ return;
+
+ LayoutSize oldBorderBoxSize = computePreviousBorderBoxSize(oldBounds.size());
+ LayoutSize newBorderBoxSize = size();
+
+ // If border box size didn't change, RenderObject's incrementallyInvalidatePaint() is good.
+ if (oldBorderBoxSize == newBorderBoxSize)
+ return;
+
+ // If size of the paint invalidation rect equals to size of border box, RenderObject::incrementallyInvalidatePaint()
// is good for boxes having background without box decorations.
- if (oldBorderBoxSize == oldBounds.size() && newBorderBoxSize == newBounds.size() && !style()->hasBoxDecorations())
- return invalidationReason;
+ ASSERT(oldBounds.location() == newBounds.location()); // Otherwise we won't do incremental invalidation.
+ if (!hasBoxDecorations
+ && positionFromPaintInvalidationBacking == newBounds.location()
+ && oldBorderBoxSize == oldBounds.size()
+ && newBorderBoxSize == newBounds.size())
+ return;
- // FIXME: Since we have accurate old border box size, we could do more accurate
- // incremental invalidation instead of full invalidation.
- return InvalidationBorderBoxChange;
+ // Invalidate the right delta part and the right border of the old or new box which has smaller width.
+ LayoutUnit deltaWidth = absoluteValue(oldBorderBoxSize.width() - newBorderBoxSize.width());
+ if (deltaWidth) {
+ LayoutUnit smallerWidth = std::min(oldBorderBoxSize.width(), newBorderBoxSize.width());
+ LayoutUnit borderTopRightRadiusWidth = valueForLength(style()->borderTopRightRadius().width(), smallerWidth);
+ LayoutUnit borderBottomRightRadiusWidth = valueForLength(style()->borderBottomRightRadius().width(), smallerWidth);
+ LayoutUnit borderWidth = std::max<LayoutUnit>(borderRight(), std::max(borderTopRightRadiusWidth, borderBottomRightRadiusWidth));
+ LayoutRect rightDeltaRect(positionFromPaintInvalidationBacking.x() + smallerWidth - borderWidth,
+ positionFromPaintInvalidationBacking.y(),
+ deltaWidth + borderWidth,
+ std::max(oldBorderBoxSize.height(), newBorderBoxSize.height()));
+ invalidatePaintRectClippedByOldAndNewBounds(paintInvalidationContainer, rightDeltaRect, oldBounds, newBounds);
+ }
+
+ // Invalidate the bottom delta part and the bottom border of the old or new box which has smaller height.
+ LayoutUnit deltaHeight = absoluteValue(oldBorderBoxSize.height() - newBorderBoxSize.height());
+ if (deltaHeight) {
+ LayoutUnit smallerHeight = std::min(oldBorderBoxSize.height(), newBorderBoxSize.height());
+ LayoutUnit borderBottomLeftRadiusHeight = valueForLength(style()->borderBottomLeftRadius().height(), smallerHeight);
+ LayoutUnit borderBottomRightRadiusHeight = valueForLength(style()->borderBottomRightRadius().height(), smallerHeight);
+ LayoutUnit borderHeight = std::max<LayoutUnit>(borderBottom(), std::max(borderBottomLeftRadiusHeight, borderBottomRightRadiusHeight));
+ LayoutRect bottomDeltaRect(positionFromPaintInvalidationBacking.x(),
+ positionFromPaintInvalidationBacking.y() + smallerHeight - borderHeight,
+ std::max(oldBorderBoxSize.width(), newBorderBoxSize.width()),
+ deltaHeight + borderHeight);
+ invalidatePaintRectClippedByOldAndNewBounds(paintInvalidationContainer, bottomDeltaRect, oldBounds, newBounds);
+ }
+}
+
+void RenderBox::invalidatePaintRectClippedByOldAndNewBounds(const RenderLayerModelObject& paintInvalidationContainer, const LayoutRect& rect, const LayoutRect& oldBounds, const LayoutRect& newBounds)
+{
+ if (rect.isEmpty())
+ return;
+ LayoutRect rectClippedByOldBounds = intersection(rect, oldBounds);
+ LayoutRect rectClippedByNewBounds = intersection(rect, newBounds);
+ // Invalidate only once if the clipped rects equal.
+ if (rectClippedByOldBounds == rectClippedByNewBounds) {
+ invalidatePaintUsingContainer(&paintInvalidationContainer, rectClippedByOldBounds, InvalidationIncremental);
+ return;
+ }
+ // Invalidate the bigger one if one contains another. Otherwise invalidate both.
+ if (!rectClippedByNewBounds.contains(rectClippedByOldBounds))
+ invalidatePaintUsingContainer(&paintInvalidationContainer, rectClippedByOldBounds, InvalidationIncremental);
+ if (!rectClippedByOldBounds.contains(rectClippedByNewBounds))
+ invalidatePaintUsingContainer(&paintInvalidationContainer, rectClippedByNewBounds, InvalidationIncremental);
}
void RenderBox::markForPaginationRelayoutIfNeeded(SubtreeLayoutScope& layoutScope)
left = std::max(left, borderOutsets.left());
}
- RenderStyle* outlineStyle = this->outlineStyle();
- if (outlineStyle->hasOutline()) {
- if (outlineStyle->outlineStyleIsAuto()) {
+ if (style()->hasOutline()) {
+ if (style()->outlineStyleIsAuto()) {
// The result focus ring rects are in coordinates of this object's border box.
- Vector<IntRect> focusRingRects;
+ Vector<LayoutRect> focusRingRects;
addFocusRingRects(focusRingRects, LayoutPoint(), this);
- IntRect rect = unionRect(focusRingRects);
+ LayoutRect rect = unionRect(focusRingRects);
- int outlineSize = GraphicsContext::focusRingOutsetExtent(outlineStyle->outlineOffset(), outlineStyle->outlineWidth());
- top = std::max<LayoutUnit>(top, -rect.y() + outlineSize);
- right = std::max<LayoutUnit>(right, rect.maxX() - width() + outlineSize);
- bottom = std::max<LayoutUnit>(bottom, rect.maxY() - height() + outlineSize);
- left = std::max<LayoutUnit>(left, -rect.x() + outlineSize);
+ int outlineSize = GraphicsContext::focusRingOutsetExtent(style()->outlineOffset(), style()->outlineWidth());
+ top = std::max(top, -rect.y() + outlineSize);
+ right = std::max(right, rect.maxX() - width() + outlineSize);
+ bottom = std::max(bottom, rect.maxY() - height() + outlineSize);
+ left = std::max(left, -rect.x() + outlineSize);
} else {
- LayoutUnit outlineSize = outlineStyle->outlineSize();
+ LayoutUnit outlineSize = style()->outlineSize();
top = std::max(top, outlineSize);
right = std::max(right, outlineSize);
bottom = std::max(bottom, outlineSize);
// conditions, but it should work out to be good enough for common cases. Paginating overflow
// with scrollbars present is not the end of the world and is what we used to do in the old model anyway.
return !style()->logicalHeight().isIntrinsicOrAuto()
- || (!style()->logicalMaxHeight().isIntrinsicOrAuto() && !style()->logicalMaxHeight().isUndefined() && (!style()->logicalMaxHeight().isPercent() || percentageLogicalHeightIsResolvable(this)))
+ || (!style()->logicalMaxHeight().isIntrinsicOrAuto() && !style()->logicalMaxHeight().isMaxSizeNone() && (!style()->logicalMaxHeight().isPercent() || percentageLogicalHeightIsResolvable(this)))
|| (!style()->logicalMinHeight().isIntrinsicOrAuto() && style()->logicalMinHeight().isPositive() && (!style()->logicalMinHeight().isPercent() || percentageLogicalHeightIsResolvable(this)));
}
return rect;
}
-LayoutRect RenderBox::overflowRectForPaintRejection() const
-{
- LayoutRect overflowRect = visualOverflowRect();
- if (!m_overflow || !usesCompositedScrolling())
- return overflowRect;
-
- overflowRect.unite(layoutOverflowRect());
- overflowRect.move(-scrolledContentOffset());
- return overflowRect;
-}
-
LayoutUnit RenderBox::offsetLeft() const
{
return adjustedPositionRelativeToOffsetParent(topLeftLocation()).x();
postBox->setChildrenInline(boxToSplit->childrenInline());
RenderBox* parentBox = toRenderBox(boxToSplit->parent());
// We need to invalidate the |parentBox| before inserting the new node
- // so that the table repainting logic knows the structure is dirty.
+ // so that the table paint invalidation logic knows the structure is dirty.
// See for example RenderTableCell:clippedOverflowRectForPaintInvalidation.
markBoxForRelayoutAfterSplit(parentBox);
parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling());
ensureRareData().m_previousBorderBoxSize = size();
}
-RenderBox::BoxDecorationData::BoxDecorationData(const RenderStyle& style)
+LayoutSize RenderBox::computePreviousBorderBoxSize(const LayoutSize& previousBoundsSize) const
{
- backgroundColor = style.visitedDependentColor(CSSPropertyBackgroundColor);
- hasBackground = backgroundColor.alpha() || style.hasBackgroundImage();
- ASSERT(hasBackground == style.hasBackground());
- hasBorder = style.hasBorder();
- hasAppearance = style.hasAppearance();
+ // PreviousBorderBoxSize is only valid when there is background or box decorations.
+ ASSERT(style()->hasBackground() || style()->hasBoxDecorations());
+
+ if (m_rareData && m_rareData->m_previousBorderBoxSize.width() != -1)
+ return m_rareData->m_previousBorderBoxSize;
+
+ // We didn't save the old border box size because it was the same as the size of oldBounds.
+ return previousBoundsSize;
}
} // namespace blink