Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(880)

Unified Diff: Source/core/layout/LayoutBox.cpp

Issue 1145993002: Refactor root element background painting (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: make invalidation more robust. also improve incremental invalidation for some common cases Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/layout/LayoutBox.cpp
diff --git a/Source/core/layout/LayoutBox.cpp b/Source/core/layout/LayoutBox.cpp
index c5df9eae4bd658aa70c98a73235a9ffde4457e82..6f6ad20081f9adc363a66f834ccfaa6c949777fc 100644
--- a/Source/core/layout/LayoutBox.cpp
+++ b/Source/core/layout/LayoutBox.cpp
@@ -89,17 +89,6 @@ static OverrideSizeMap* gExtraBlockOffsetMap = 0;
static const int autoscrollBeltSize = 20;
static const unsigned backgroundObscurationTestMaxDepth = 4;
-static bool skipBodyBackground(const LayoutBox* bodyElementLayoutObject)
-{
- ASSERT(bodyElementLayoutObject->isBody());
- // The <body> only paints its background if the root element has defined a background independent of the body,
- // or if the <body>'s parent is not the document element's layoutObject (e.g. inside SVG foreignObject).
- LayoutObject* documentElementLayoutObject = bodyElementLayoutObject->document().documentElement()->layoutObject();
- return documentElementLayoutObject
- && !documentElementLayoutObject->hasBackground()
- && (documentElementLayoutObject == bodyElementLayoutObject->parent());
-}
-
LayoutBox::LayoutBox(ContainerNode* node)
: LayoutBoxModelObject(node)
, m_intrinsicContentLogicalHeight(-1)
@@ -177,16 +166,6 @@ void LayoutBox::styleWillChange(StyleDifference diff, const ComputedStyle& newSt
{
const ComputedStyle* oldStyle = style();
if (oldStyle) {
- // The background of the root element or the body element could propagate up to
- // the canvas. Just dirty the entire canvas when our style changes substantially.
- if ((diff.needsPaintInvalidation() || diff.needsLayout()) && node()
- && (isHTMLHtmlElement(*node()) || isHTMLBodyElement(*node()))) {
- view()->setShouldDoFullPaintInvalidation();
-
- if (oldStyle->hasEntirelyFixedBackground() != newStyle.hasEntirelyFixedBackground())
- view()->compositor()->setNeedsUpdateFixedBackground();
- }
-
// When a layout hint happens and an object's position style changes, we have to do a layout
// to dirty the layout tree using the old position value now.
if (diff.needsFullLayout() && parent() && oldStyle->position() != newStyle.position()) {
@@ -304,12 +283,11 @@ void LayoutBox::updateFromStyle()
LayoutBoxModelObject::updateFromStyle();
const ComputedStyle& styleToUse = styleRef();
- bool isRootObject = isDocumentElement();
bool isViewObject = isLayoutView();
bool rootLayerScrolls = document().settings() && document().settings()->rootLayerScrolls();
- // The root and the LayoutView always paint their backgrounds/borders.
- if (isRootObject || isViewObject)
+ // LayoutView of the main frame is resposible from painting base background.
+ if (isViewObject && !document().ownerElement())
setHasBoxDecorationBackground(true);
setFloating(!isOutOfFlowPositioned() && styleToUse.isFloating());
@@ -1180,7 +1158,7 @@ bool LayoutBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent)
bool LayoutBox::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
{
- if (isBody() && skipBodyBackground(this))
+ if (isDocumentElement() || backgroundStolenForBeingBody())
return false;
Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
@@ -1321,9 +1299,6 @@ void LayoutBox::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOf
void LayoutBox::imageChanged(WrappedImagePtr image, const IntRect*)
{
- if (!parent())
- return;
-
// TODO(chrishtr): support PaintInvalidationDelayedFull for animated border images.
if ((style()->borderImage().image() && style()->borderImage().image()->data() == image)
|| (style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image)) {
@@ -1340,35 +1315,21 @@ void LayoutBox::imageChanged(WrappedImagePtr image, const IntRect*)
}
}
- if (!paintInvalidationLayerRectsForImage(image, style()->backgroundLayers(), true))
- paintInvalidationLayerRectsForImage(image, style()->maskLayers(), false);
+ if (!invalidatePaintOfLayerRectsForImage(image, style()->backgroundLayers(), true))
+ invalidatePaintOfLayerRectsForImage(image, style()->maskLayers(), false);
}
-bool LayoutBox::paintInvalidationLayerRectsForImage(WrappedImagePtr image, const FillLayer& layers, bool drawingBackground)
+bool LayoutBox::invalidatePaintOfLayerRectsForImage(WrappedImagePtr image, const FillLayer& layers, bool drawingBackground)
{
- Vector<LayoutObject*> layerLayoutObjects;
-
- // A background of the body or document must extend to the total visible size of the document. This means the union of the
- // view and document bounds, since it can be the case that the view is larger than the document and vice-versa.
- // http://dev.w3.org/csswg/css-backgrounds/#the-background
- if (drawingBackground && (isDocumentElement() || (isBody() && !document().documentElement()->layoutObject()->hasBackground()))) {
- layerLayoutObjects.append(document().documentElement()->layoutObject());
- layerLayoutObjects.append(view());
- if (view()->frameView())
- view()->frameView()->setNeedsFullPaintInvalidation();
- } else {
- layerLayoutObjects.append(this);
- }
+ if (drawingBackground && (isDocumentElement() || backgroundStolenForBeingBody()))
+ return false;
for (const FillLayer* curLayer = &layers; curLayer; curLayer = curLayer->next()) {
- if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(*this, style()->effectiveZoom())) {
- for (LayoutObject* layerLayoutObject : layerLayoutObjects) {
- // For now, only support delayed paint invalidation for animated background images.
- bool maybeAnimated = curLayer->image()->cachedImage() && curLayer->image()->cachedImage()->image() && curLayer->image()->cachedImage()->image()->maybeAnimated();
- if (maybeAnimated && drawingBackground)
- layerLayoutObject->setShouldDoFullPaintInvalidation(PaintInvalidationDelayedFull);
- else
- layerLayoutObject->setShouldDoFullPaintInvalidation(PaintInvalidationFull);
- }
+ if (curLayer->image() && image == curLayer->image()->data()) {
+ bool maybeAnimated = curLayer->image()->cachedImage() && curLayer->image()->cachedImage()->image() && curLayer->image()->cachedImage()->image()->maybeAnimated();
+ if (maybeAnimated && drawingBackground)
+ setShouldDoFullPaintInvalidation(PaintInvalidationDelayedFull);
+ else
+ setShouldDoFullPaintInvalidation();
return true;
}
}
@@ -3954,7 +3915,8 @@ PaintInvalidationReason LayoutBox::paintInvalidationReason(const LayoutBoxModelO
&& hasLayer() && layer()->transform() && !layer()->transform()->isIdentityOrTranslation())
return PaintInvalidationBoundsChange;
- if (!style()->hasBackground() && !style()->hasBoxDecorations()) {
+ bool paintsBackground = style()->hasBackground() && !isDocumentElement() && !backgroundStolenForBeingBody();
+ if (!paintsBackground && !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())
@@ -3962,18 +3924,26 @@ PaintInvalidationReason LayoutBox::paintInvalidationReason(const LayoutBoxModelO
return invalidationReason;
}
- if (style()->backgroundLayers().thisOrNextLayersUseContentBox() || style()->maskLayers().thisOrNextLayersUseContentBox()) {
+ if (paintsBackground && (style()->backgroundLayers().thisOrNextLayersUseContentBox() || style()->maskLayers().thisOrNextLayersUseContentBox())) {
LayoutRect oldContentBoxRect = m_rareData ? m_rareData->m_previousContentBoxRect : LayoutRect();
LayoutRect newContentBoxRect = contentBoxRect();
if (oldContentBoxRect != newContentBoxRect)
return PaintInvalidationContentBoxChange;
}
- if (style()->backgroundLayers().thisOrNextLayersHaveLocalAttachment()) {
+ if (paintsBackground && style()->backgroundLayers().thisOrNextLayersHaveLocalAttachment()) {
LayoutRect oldLayoutOverflowRect = m_rareData ? m_rareData->m_previousLayoutOverflowRect : LayoutRect();
LayoutRect newLayoutOverflowRect = layoutOverflowRect();
- if (oldLayoutOverflowRect != newLayoutOverflowRect)
- return PaintInvalidationLayoutOverflowBoxChange;
+ if (oldLayoutOverflowRect != newLayoutOverflowRect) {
Xianzhu 2015/06/05 00:52:46 We could keep these lines as-is. The change increa
+ // Background positioning for the LayoutView are based on the box of the root element.
+ // Whether full invalidation is needed will be checked with special logic in
+ // LayoutView::invalidatePaintIfNeeded. Here we only need to guarantee incremental
+ // painting is done for newly expanded area.
+ if (!isLayoutView())
+ return PaintInvalidationLayoutOverflowBoxChange;
+ if (invalidationReason < PaintInvalidationIncremental)
+ invalidationReason = PaintInvalidationIncremental;
+ }
}
LayoutSize oldBorderBoxSize = computePreviousBorderBoxSize(oldBounds.size());
@@ -3998,11 +3968,13 @@ PaintInvalidationReason LayoutBox::paintInvalidationReason(const LayoutBoxModelO
return PaintInvalidationBorderBoxChange;
}
+ if (!paintsBackground)
+ return invalidationReason;
+
if (oldBorderBoxSize.width() != newBorderBoxSize.width() && mustInvalidateBackgroundOrBorderPaintOnWidthChange())
return PaintInvalidationBorderBoxChange;
if (oldBorderBoxSize.height() != newBorderBoxSize.height() && mustInvalidateBackgroundOrBorderPaintOnHeightChange())
return PaintInvalidationBorderBoxChange;
-
return PaintInvalidationIncremental;
}
@@ -4713,7 +4685,7 @@ void LayoutBox::logicalExtentAfterUpdatingLogicalWidth(const LayoutUnit& newLogi
setMarginRight(oldMarginRight);
}
-inline bool LayoutBox::mustInvalidateFillLayersPaintOnWidthChange(const FillLayer& layer) const
+bool LayoutBox::mustInvalidateFillLayersPaintOnWidthChange(const FillLayer& layer) const
{
// Nobody will use multiple layers without wanting fancy positioning.
if (layer.next())

Powered by Google App Engine
This is Rietveld 408576698