Index: third_party/WebKit/Source/core/layout/LayoutBox.cpp |
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp |
index 7e2b702a73f1ba5aaa67065078c5f0207003e606..bfa8daeabf98e24ca0b10994f63097df39737ca2 100644 |
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp |
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp |
@@ -54,6 +54,7 @@ |
#include "core/page/Page.h" |
#include "core/page/scrolling/SnapCoordinator.h" |
#include "core/paint/BackgroundImageGeometry.h" |
+#include "core/paint/BoxPaintInvalidator.h" |
#include "core/paint/BoxPainter.h" |
#include "core/paint/PaintLayer.h" |
#include "core/style/ShadowList.h" |
@@ -132,6 +133,8 @@ void LayoutBox::willBeDestroyed() |
ShapeOutsideInfo::removeInfo(*this); |
+ BoxPaintInvalidator::boxWillBeDestroyed(*this); |
+ |
LayoutBoxModelObject::willBeDestroyed(); |
} |
@@ -1562,14 +1565,12 @@ PaintInvalidationReason LayoutBox::invalidatePaintIfNeeded(const PaintInvalidati |
layer.setNeedsPaintPhaseDescendantBlockBackgrounds(); |
} |
- PaintInvalidationReason reason = LayoutBoxModelObject::invalidatePaintIfNeeded(paintInvalidationState); |
- |
- if (PaintLayerScrollableArea* area = getScrollableArea()) |
- area->invalidatePaintOfScrollControlsIfNeeded(paintInvalidationState); |
+ return LayoutBoxModelObject::invalidatePaintIfNeeded(paintInvalidationState); |
+} |
- // This is for the next invalidatePaintIfNeeded so must be at the end. |
- savePreviousBoxSizesIfNeeded(); |
- return reason; |
+PaintInvalidationReason LayoutBox::invalidatePaintIfNeeded(const PaintInvalidatorContext& context) const |
+{ |
+ return BoxPaintInvalidator(*this, context).invalidatePaintIfNeeded(); |
} |
void LayoutBox::invalidatePaintOfSubtreesIfNeeded(const PaintInvalidationState& childPaintInvalidationState) |
@@ -3966,173 +3967,6 @@ bool LayoutBox::hasNonCompositedScrollbars() const |
return false; |
} |
-PaintInvalidationReason LayoutBox::getPaintInvalidationReason(const PaintInvalidationState& paintInvalidationState, |
- const LayoutRect& oldBounds, const LayoutPoint& oldLocation, const LayoutRect& newBounds, const LayoutPoint& newLocation) const |
-{ |
- PaintInvalidationReason invalidationReason = LayoutBoxModelObject::getPaintInvalidationReason(paintInvalidationState, oldBounds, oldLocation, newBounds, newLocation); |
- |
- if (isFullPaintInvalidationReason(invalidationReason) && invalidationReason != PaintInvalidationDelayedFull) |
- return invalidationReason; |
- |
- if (mayNeedPaintInvalidationAnimatedBackgroundImage() && !backgroundIsKnownToBeObscured()) |
- invalidationReason = PaintInvalidationDelayedFull; |
- |
- // If the current paint invalidation reason is PaintInvalidationDelayedFull, then this paint invalidation can delayed if the |
- // LayoutBox in question is not on-screen. The logic to decide whether this is appropriate exists at the site of the original |
- // paint invalidation that chose PaintInvalidationDelayedFull. |
- if (invalidationReason == PaintInvalidationDelayedFull) { |
- // Do regular full paint invalidation if the object is onscreen. |
- return intersectsVisibleViewport() ? PaintInvalidationFull : PaintInvalidationDelayedFull; |
- } |
- |
- if (isLayoutView()) { |
- const LayoutView* layoutView = toLayoutView(this); |
- // In normal compositing mode, root background doesn't need to be invalidated for |
- // box changes, because the background always covers the whole document rect |
- // and clipping is done by compositor()->m_containerLayer. Also the scrollbars |
- // are always composited. There are no other box decoration on the LayoutView thus |
- // we can safely exit here. |
- if (layoutView->usesCompositing() && (!document().settings() || !document().settings()->rootLayerScrolls())) |
- return invalidationReason; |
- } |
- |
- // If the transform is not identity or translation, incremental invalidation is not applicable |
- // because the difference between oldBounds and newBounds doesn't cover all area needing invalidation. |
- // FIXME: Should also consider ancestor transforms since paintInvalidationContainer. crbug.com/426111. |
- if (invalidationReason == PaintInvalidationIncremental |
- && paintInvalidationState.paintInvalidationContainer() != this |
- && hasLayer() && layer()->transform() && !layer()->transform()->isIdentityOrTranslation()) |
- return PaintInvalidationBoundsChange; |
- |
- if (style()->backgroundLayers().thisOrNextLayersUseContentBox() || style()->maskLayers().thisOrNextLayersUseContentBox() || style()->boxSizing() == BoxSizingBorderBox) { |
- LayoutRect oldContentBoxRect = m_rareData ? m_rareData->m_previousContentBoxRect : LayoutRect(); |
- LayoutRect newContentBoxRect = contentBoxRect(); |
- if (oldContentBoxRect != newContentBoxRect) |
- return PaintInvalidationContentBoxChange; |
- } |
- |
- if (!style()->hasBackground() && !style()->hasBoxDecorations()) { |
- // We could let incremental invalidation cover non-composited scrollbars, but just |
- // do a full invalidation because incremental invalidation will go away with slimming paint. |
- if (invalidationReason == PaintInvalidationIncremental && hasNonCompositedScrollbars()) |
- return PaintInvalidationBorderBoxChange; |
- return invalidationReason; |
- } |
- |
- if (style()->backgroundLayers().thisOrNextLayersHaveLocalAttachment()) { |
- LayoutRect oldLayoutOverflowRect = m_rareData ? m_rareData->m_previousLayoutOverflowRect : LayoutRect(); |
- LayoutRect newLayoutOverflowRect = layoutOverflowRect(); |
- if (oldLayoutOverflowRect != newLayoutOverflowRect) |
- return PaintInvalidationLayoutOverflowBoxChange; |
- } |
- |
- LayoutSize oldBorderBoxSize = computePreviousBorderBoxSize(oldBounds.size()); |
- LayoutSize newBorderBoxSize = size(); |
- |
- if (oldBorderBoxSize == newBorderBoxSize) |
- return invalidationReason; |
- |
- // LayoutBox::incrementallyInvalidatePaint() depends on positionFromPaintInvalidationBacking |
- // which is not available when slimmingPaintOffsetCachingEnabled. |
- if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() && (style()->hasBoxDecorations() || style()->hasBackground())) |
- return PaintInvalidationBorderBoxChange; |
- |
- // TODO(wangxianzhu): Remove incremental invalidation when we remove rect-based paint invalidation. |
- // See another hasNonCompositedScrollbars() callsite above. |
- if (hasNonCompositedScrollbars()) |
- return PaintInvalidationBorderBoxChange; |
- |
- if (style()->hasVisualOverflowingEffect() || style()->hasAppearance() || style()->hasFilterInducingProperty() || style()->resize() != RESIZE_NONE) |
- return PaintInvalidationBorderBoxChange; |
- |
- 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. |
- FloatRoundedRect oldRoundedRect = style()->getRoundedBorderFor(LayoutRect(LayoutPoint(0, 0), oldBorderBoxSize)); |
- FloatRoundedRect newRoundedRect = style()->getRoundedBorderFor(LayoutRect(LayoutPoint(0, 0), newBorderBoxSize)); |
- if (oldRoundedRect.getRadii() != newRoundedRect.getRadii()) |
- return PaintInvalidationBorderBoxChange; |
- } |
- |
- if (oldBorderBoxSize.width() != newBorderBoxSize.width() && mustInvalidateBackgroundOrBorderPaintOnWidthChange()) |
- return PaintInvalidationBorderBoxChange; |
- if (oldBorderBoxSize.height() != newBorderBoxSize.height() && mustInvalidateBackgroundOrBorderPaintOnHeightChange()) |
- return PaintInvalidationBorderBoxChange; |
- |
- return styleRef().hasBackground() || styleRef().hasBoxDecorations() ? PaintInvalidationIncremental : invalidationReason; |
-} |
- |
-void LayoutBox::incrementallyInvalidatePaint(const LayoutBoxModelObject& paintInvalidationContainer, const LayoutRect& oldBounds, const LayoutRect& newBounds, const LayoutPoint& positionFromPaintInvalidationBacking) |
-{ |
- LayoutObject::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, LayoutObject's incrementallyInvalidatePaint() is good. |
- if (oldBorderBoxSize == newBorderBoxSize) |
- return; |
- |
- // If size of the paint invalidation rect equals to size of border box, LayoutObject::incrementallyInvalidatePaint() |
- // is good for boxes having background without box decorations. |
- ASSERT(oldBounds.location() == newBounds.location()); // Otherwise we won't do incremental invalidation. |
- if (!hasBoxDecorations |
- && positionFromPaintInvalidationBacking == newBounds.location() |
- && oldBorderBoxSize == oldBounds.size() |
- && newBorderBoxSize == newBounds.size()) |
- return; |
- |
- // 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 LayoutBox::invalidatePaintRectClippedByOldAndNewBounds(const LayoutBoxModelObject& 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, PaintInvalidationIncremental); |
- return; |
- } |
- // Invalidate the bigger one if one contains another. Otherwise invalidate both. |
- if (!rectClippedByNewBounds.contains(rectClippedByOldBounds)) |
- invalidatePaintUsingContainer(paintInvalidationContainer, rectClippedByOldBounds, PaintInvalidationIncremental); |
- if (!rectClippedByOldBounds.contains(rectClippedByNewBounds)) |
- invalidatePaintUsingContainer(paintInvalidationContainer, rectClippedByNewBounds, PaintInvalidationIncremental); |
-} |
- |
void LayoutBox::markForPaginationRelayoutIfNeeded(SubtreeLayoutScope& layoutScope) |
{ |
ASSERT(!needsLayout()); |
@@ -4655,63 +4489,6 @@ void LayoutBox::setPageLogicalOffset(LayoutUnit offset) |
ensureRareData().m_pageLogicalOffset = offset; |
} |
-bool LayoutBox::needToSavePreviousBoxSizes() |
-{ |
- // If m_rareData is already created, always save. |
- if (m_rareData) |
- return true; |
- |
- LayoutSize paintInvalidationSize = previousPaintInvalidationRectSize(); |
- // Don't save old box sizes if the paint rect is empty because we'll |
- // full invalidate once the paint rect becomes non-empty. |
- if (paintInvalidationSize.isEmpty()) |
- return false; |
- |
- // If we use border-box sizing we need to track changes in the size of the content box. |
- if (style()->boxSizing() == BoxSizingBorderBox) |
- return true; |
- |
- // We need the old box sizes only when the box has background, decorations, or masks. |
- // Main LayoutView paints base background, thus interested in box size. |
- if (!isLayoutView() && !style()->hasBackground() && !style()->hasBoxDecorations() && !style()->hasMask()) |
- return false; |
- |
- // No need to save old border box size if we can use size of the old paint |
- // rect as the old border box size in the next invalidation. |
- if (paintInvalidationSize != size()) |
- return true; |
- |
- // Background and mask layers can depend on other boxes than border box. See crbug.com/490533 |
- if (style()->backgroundLayers().thisOrNextLayersUseContentBox() || style()->backgroundLayers().thisOrNextLayersHaveLocalAttachment() |
- || style()->maskLayers().thisOrNextLayersUseContentBox()) |
- return true; |
- |
- return false; |
-} |
- |
-void LayoutBox::savePreviousBoxSizesIfNeeded() |
-{ |
- if (!needToSavePreviousBoxSizes()) |
- return; |
- |
- LayoutBoxRareData& rareData = ensureRareData(); |
- rareData.m_previousBorderBoxSize = size(); |
- rareData.m_previousContentBoxRect = contentBoxRect(); |
- rareData.m_previousLayoutOverflowRect = layoutOverflowRect(); |
-} |
- |
-LayoutSize LayoutBox::computePreviousBorderBoxSize(const LayoutSize& previousBoundsSize) const |
-{ |
- // 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; |
-} |
- |
void LayoutBox::logicalExtentAfterUpdatingLogicalWidth(const LayoutUnit& newLogicalTop, LayoutBox::LogicalExtentComputedValues& computedValues) |
{ |
// FIXME: None of this is right for perpendicular writing-mode children. |
@@ -4736,7 +4513,7 @@ void LayoutBox::logicalExtentAfterUpdatingLogicalWidth(const LayoutUnit& newLogi |
setMarginRight(oldMarginRight); |
} |
-bool LayoutBox::mustInvalidateFillLayersPaintOnHeightChange(const FillLayer& layer) const |
+bool LayoutBox::mustInvalidateFillLayersPaintOnHeightChange(const FillLayer& layer) |
{ |
// Nobody will use multiple layers without wanting fancy positioning. |
if (layer.next()) |
@@ -4775,7 +4552,7 @@ bool LayoutBox::mustInvalidateFillLayersPaintOnHeightChange(const FillLayer& lay |
return false; |
} |
-bool LayoutBox::mustInvalidateFillLayersPaintOnWidthChange(const FillLayer& layer) const |
+bool LayoutBox::mustInvalidateFillLayersPaintOnWidthChange(const FillLayer& layer) |
{ |
// Nobody will use multiple layers without wanting fancy positioning. |
if (layer.next()) |