Index: Source/core/rendering/RenderObject.h |
diff --git a/Source/core/rendering/RenderObject.h b/Source/core/rendering/RenderObject.h |
index 1975ed16046eecbe6ed469f16e300cd38c25f069..7c9717008de3519e17991f67362e203be307240d 100644 |
--- a/Source/core/rendering/RenderObject.h |
+++ b/Source/core/rendering/RenderObject.h |
@@ -250,6 +250,29 @@ public: |
renderer->assertRendererLaidOut(); |
} |
+ void assertRendererClearedPaintInvalidationState() const |
+ { |
+#ifndef NDEBUG |
+ if (paintInvalidationStateIsDirty()) { |
+ showRenderTreeForThis(); |
+ ASSERT_NOT_REACHED(); |
+ } |
+#endif |
+ } |
+ |
+ void assertSubtreeClearedPaintInvalidationState() const |
+ { |
+ for (const RenderObject* renderer = this; renderer; renderer = renderer->nextInPreOrder()) { |
+ renderer->assertRendererClearedPaintInvalidationState(); |
+ |
+ // Currently we skip some SVG containers for performance (see RenderSVGModelObject::invalidateTreeAfterLayout) |
+ // so we just skip the underlying subtree. This is not strictly the condition in the previous function but |
+ // it makes little sense to cover SVG subtrees if we know they are skipped anyway. |
+ if (renderer->isSVGContainer()) |
+ return; |
+ } |
+ } |
+ |
#endif |
bool skipInvalidationWhenLaidOutChildren() const; |
@@ -1002,11 +1025,24 @@ public: |
void setPreviousPositionFromPaintInvalidationContainer(const LayoutPoint& location) { m_previousPositionFromPaintInvalidationContainer = location; } |
bool shouldDoFullPaintInvalidation() const { return m_bitfields.shouldDoFullPaintInvalidation(); } |
- void setShouldDoFullPaintInvalidation(bool b) { m_bitfields.setShouldDoFullPaintInvalidation(b); } |
+ void setShouldDoFullPaintInvalidation(bool b, MarkingBehavior markBehavior = MarkContainingBlockChain) |
+ { |
+ m_bitfields.setShouldDoFullPaintInvalidation(b); |
+ |
+ if (markBehavior == MarkContainingBlockChain && b) |
+ markContainingBlockChainForPaintInvalidation(); |
+ } |
+ |
bool shouldInvalidateOverflowForPaint() const { return m_bitfields.shouldInvalidateOverflowForPaint(); } |
bool shouldDoFullPaintInvalidationIfSelfPaintingLayer() const { return m_bitfields.shouldDoFullPaintInvalidationIfSelfPaintingLayer(); } |
- void setShouldDoFullPaintInvalidationIfSelfPaintingLayer(bool b) { m_bitfields.setShouldDoFullPaintInvalidationIfSelfPaintingLayer(b); } |
+ void setShouldDoFullPaintInvalidationIfSelfPaintingLayer(bool b) |
+ { |
+ m_bitfields.setShouldDoFullPaintInvalidationIfSelfPaintingLayer(b); |
+ |
+ if (b) |
+ markContainingBlockChainForPaintInvalidation(); |
+ } |
bool onlyNeededPositionedMovementLayout() const { return m_bitfields.onlyNeededPositionedMovementLayout(); } |
void setOnlyNeededPositionedMovementLayout(bool b) { m_bitfields.setOnlyNeededPositionedMovementLayout(b); } |
@@ -1015,17 +1051,17 @@ public: |
// layoutDidGetCalled indicates whether this render object was re-laid-out |
// since the last call to setLayoutDidGetCalled(false) on this object. |
- bool layoutDidGetCalled() { return m_bitfields.layoutDidGetCalled(); } |
+ bool layoutDidGetCalled() const { return m_bitfields.layoutDidGetCalled(); } |
void setLayoutDidGetCalled(bool b) { m_bitfields.setLayoutDidGetCalled(b); } |
- bool mayNeedPaintInvalidation() { return m_bitfields.mayNeedPaintInvalidation(); } |
+ bool mayNeedPaintInvalidation() const { return m_bitfields.mayNeedPaintInvalidation(); } |
void setMayNeedPaintInvalidation(bool b) |
{ |
m_bitfields.setMayNeedPaintInvalidation(b); |
// Make sure our parent is marked as needing invalidation. |
- if (b && parent() && !parent()->mayNeedPaintInvalidation()) |
- parent()->setMayNeedPaintInvalidation(b); |
+ if (b) |
+ markContainingBlockChainForPaintInvalidation(); |
} |
bool neededLayoutBecauseOfChildren() const { return m_bitfields.neededLayoutBecauseOfChildren(); } |
@@ -1033,7 +1069,7 @@ public: |
bool shouldCheckForPaintInvalidation() |
{ |
- return layoutDidGetCalled() || mayNeedPaintInvalidation(); |
+ return layoutDidGetCalled() || mayNeedPaintInvalidation() || shouldDoFullPaintInvalidation() || shouldDoFullPaintInvalidationIfSelfPaintingLayer(); |
} |
bool supportsLayoutStateCachedOffsets() const { return !hasColumns() && !hasTransform() && !hasReflection() && !style()->isFlippedBlocksWritingMode(); } |
@@ -1119,9 +1155,21 @@ private: |
#if ENABLE(ASSERT) |
void checkBlockPositionedObjectsNeedLayout(); |
+ |
+ bool paintInvalidationStateIsDirty() const |
+ { |
+ return layoutDidGetCalled() || shouldDoFullPaintInvalidation() || shouldDoFullPaintInvalidationIfSelfPaintingLayer() |
+ || onlyNeededPositionedMovementLayout() || neededLayoutBecauseOfChildren() || mayNeedPaintInvalidation(); |
+ } |
#endif |
const char* invalidationReasonToString(InvalidationReason) const; |
+ void markContainingBlockChainForPaintInvalidation() |
+ { |
+ for (RenderObject* container = this->container(); container && !container->shouldCheckForPaintInvalidation(); container = container->container()) |
+ container->setMayNeedPaintInvalidation(true); |
+ } |
+ |
static bool isAllowedToModifyRenderTreeStructure(Document&); |
RefPtr<RenderStyle> m_style; |