Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / RenderBox.cpp
index f50c867..cbf845e 100644 (file)
@@ -40,6 +40,8 @@
 #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>
 
@@ -146,7 +146,7 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle& newStyl
         // 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();
@@ -157,7 +157,7 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle& newStyl
         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())
@@ -166,7 +166,7 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle& newStyl
     // 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);
@@ -182,17 +182,9 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle
     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);
@@ -294,9 +286,6 @@ void RenderBox::updateFromStyle()
         // 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);
@@ -468,14 +457,10 @@ void RenderBox::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignmen
         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);
@@ -538,7 +523,7 @@ void RenderBox::updateLayerTransformAfterLayout()
 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));
 }
@@ -546,7 +531,7 @@ LayoutUnit RenderBox::constrainLogicalWidthByMinMax(LayoutUnit logicalWidth, Lay
 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);
@@ -557,7 +542,7 @@ LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, L
 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);
@@ -580,10 +565,10 @@ FloatQuad RenderBox::absoluteContentQuad() const
     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
@@ -874,7 +859,7 @@ IntSize RenderBox::scrolledContentOffset() const
     return layer()->scrollableArea()->scrollOffset();
 }
 
-void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const
+void RenderBox::applyCachedClipAndScrollOffsetForPaintInvalidation(LayoutRect& paintRect) const
 {
     ASSERT(hasLayer());
     ASSERT(hasOverflowClip());
@@ -890,7 +875,7 @@ void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect)
     }
 
     // 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);
@@ -1084,125 +1069,19 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
     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());
@@ -1219,7 +1098,7 @@ bool RenderBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent) const
     }
 
     BackgroundImageGeometry geometry;
-    calculateBackgroundImageGeometry(0, style()->backgroundLayers(), backgroundRect, geometry);
+    BoxPainter::calculateBackgroundImageGeometry(*this, 0, style()->backgroundLayers(), backgroundRect, geometry);
     if (geometry.hasNonLocalGeometry())
         return false;
     paintedExtent = geometry.destRect();
@@ -1364,107 +1243,12 @@ bool RenderBox::backgroundHasOpaqueTopLayer() const
 
 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*)
@@ -1476,7 +1260,7 @@ 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;
     }
 
@@ -1486,56 +1270,16 @@ void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
         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;
@@ -1543,13 +1287,6 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer
 
 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.
@@ -1560,8 +1297,11 @@ InvalidationReason RenderBox::invalidatePaintIfNeeded(const PaintInvalidationSta
                 && 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();
 
@@ -1715,15 +1455,23 @@ static LayoutUnit portionOfMarginNotConsumedByFloat(LayoutUnit childMargin, Layo
 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;
 }
 
@@ -1778,12 +1526,12 @@ LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
     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();
@@ -1792,7 +1540,7 @@ void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContain
     }
 
     bool containerSkipped;
-    RenderObject* o = container(repaintContainer, &containerSkipped);
+    RenderObject* o = container(paintInvalidationContainer, &containerSkipped);
     if (!o)
         return;
 
@@ -1819,16 +1567,16 @@ void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContain
         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
@@ -1974,25 +1722,29 @@ LayoutRect RenderBox::clippedOverflowRectForPaintInvalidation(const RenderLayerM
     }
 
     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));
@@ -2008,9 +1760,6 @@ void RenderBox::mapRectToPaintInvalidationBacking(const RenderLayerModelObject*
         return;
     }
 
-    if (hasReflection())
-        rect.unite(reflectedRect(rect));
-
     if (paintInvalidationContainer == this) {
         if (paintInvalidationContainer->style()->isFlippedBlocksWritingMode())
             flipForWritingMode(rect);
@@ -2047,18 +1796,18 @@ void RenderBox::mapRectToPaintInvalidationBacking(const RenderLayerModelObject*
     }
 
     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;
     }
@@ -2070,8 +1819,19 @@ void RenderBox::mapRectToPaintInvalidationBacking(const RenderLayerModelObject*
         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)
@@ -2267,14 +2027,17 @@ LayoutUnit RenderBox::computeLogicalWidthUsing(SizeType widthType, const Length&
     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);
 }
 
@@ -2285,7 +2048,7 @@ static bool isStretchingColumnFlexItem(const RenderObject* flexitem)
         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;
 }
@@ -2318,7 +2081,7 @@ bool RenderBox::sizesLogicalWidthToFitContent(const Length& logicalWidth) const
         // 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;
     }
 
@@ -2622,11 +2385,13 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) const
 
     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
@@ -2698,8 +2463,8 @@ LayoutUnit RenderBox::computeReplacedLogicalWidth(ShouldComputePreferred shouldC
 
 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));
 }
 
@@ -2734,7 +2499,7 @@ LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(const Length& logicalWidt
         case Intrinsic:
         case MinIntrinsic:
         case Auto:
-        case Undefined:
+        case MaxSizeNone:
             return intrinsicLogicalWidth();
         case ExtendToZoom:
         case DeviceWidth:
@@ -3116,7 +2881,7 @@ void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& compu
                                        computedValues);
 
     // Calculate constraint equation values for 'max-width' case.
-    if (!style()->logicalMaxWidth().isUndefined()) {
+    if (!style()->logicalMaxWidth().isMaxSizeNone()) {
         LogicalExtentComputedValues maxValues;
 
         computePositionedLogicalWidthUsing(style()->logicalMaxWidth(), containerBlock, containerDirection,
@@ -3325,7 +3090,7 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
             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);
@@ -3428,7 +3193,7 @@ void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& comp
     // 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,
@@ -4080,32 +3845,102 @@ InvalidationReason RenderBox::getPaintInvalidationReason(const RenderLayerModelO
     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)
@@ -4154,21 +3989,20 @@ LayoutBoxExtent RenderBox::computeVisualEffectOverflowExtent() const
         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);
@@ -4344,7 +4178,7 @@ bool RenderBox::hasUnsplittableScrollingOverflow() const
     // 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)));
 }
 
@@ -4496,17 +4330,6 @@ LayoutRect RenderBox::noOverflowRect() const
     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();
@@ -4641,7 +4464,7 @@ RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChil
             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());
@@ -4699,13 +4522,16 @@ void RenderBox::savePreviousBorderBoxSizeIfNeeded()
     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