Index: third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp |
diff --git a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp |
index 7ddbe084eec9ffa5b0c7b11d7d7a46a66a4259c0..b24b6b17b3adc873e6df810c311043612b5c20c5 100644 |
--- a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp |
+++ b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp |
@@ -12,8 +12,9 @@ |
namespace blink { |
-PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vector<LayoutObject*>& pendingDelayedPaintInvalidations, PaintInvalidationState* ownerPaintInvalidationState) |
- : m_clipped(false) |
+PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vector<LayoutObject*>& pendingDelayedPaintInvalidations, const PaintInvalidationState* ownerPaintInvalidationState) |
+ : m_currentObject(layoutView) |
+ , m_clipped(false) |
, m_cachedOffsetsEnabled(true) |
, m_forcedSubtreeInvalidationWithinContainer(false) |
, m_forcedSubtreeInvalidationRectUpdateWithinContainer(false) |
@@ -21,7 +22,12 @@ PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vec |
, m_paintInvalidationContainer(layoutView.containerForPaintInvalidation()) |
, m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations) |
, m_enclosingSelfPaintingLayer(*layoutView.layer()) |
+#if ENABLE(ASSERT) |
+ , m_didUpdatePaintOffsetAndClipForChildren(true) |
+#endif |
{ |
+ ASSERT(!ownerPaintInvalidationState || ownerPaintInvalidationState->m_didUpdatePaintOffsetAndClipForChildren); |
+ |
bool establishesPaintInvalidationContainer = layoutView == m_paintInvalidationContainer; |
if (!establishesPaintInvalidationContainer) { |
if ((ownerPaintInvalidationState && !ownerPaintInvalidationState->m_cachedOffsetsEnabled) |
@@ -39,21 +45,70 @@ PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vec |
m_clipped = true; |
} |
-PaintInvalidationState::PaintInvalidationState(PaintInvalidationState& next, LayoutBoxModelObject& layoutObject, const LayoutBoxModelObject& paintInvalidationContainer) |
- : m_clipped(false) |
- , m_cachedOffsetsEnabled(true) |
- , m_forcedSubtreeInvalidationWithinContainer(next.m_forcedSubtreeInvalidationWithinContainer) |
- , m_forcedSubtreeInvalidationRectUpdateWithinContainer(next.m_forcedSubtreeInvalidationRectUpdateWithinContainer) |
+// TODO(wangxianzhu): This is temporary for positioned object whose paintInvalidationContainer is different from |
+// the one we find during tree walk. Remove this after we fix the issue with tree walk in DOM-order. |
+PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& parentState, const LayoutBoxModelObject& currentObject, const LayoutBoxModelObject& paintInvalidationContainer) |
+ : m_currentObject(currentObject) |
+ , m_clipped(parentState.m_clipped) |
+ , m_cachedOffsetsEnabled(parentState.m_cachedOffsetsEnabled) |
+ , m_forcedSubtreeInvalidationWithinContainer(parentState.m_forcedSubtreeInvalidationWithinContainer) |
+ , m_forcedSubtreeInvalidationRectUpdateWithinContainer(parentState.m_forcedSubtreeInvalidationRectUpdateWithinContainer) |
, m_viewClippingAndScrollOffsetDisabled(false) |
+ , m_clipRect(parentState.m_clipRect) |
+ , m_paintOffset(parentState.m_paintOffset) |
, m_paintInvalidationContainer(paintInvalidationContainer) |
- , m_pendingDelayedPaintInvalidations(next.pendingDelayedPaintInvalidationTargets()) |
- , m_enclosingSelfPaintingLayer(next.enclosingSelfPaintingLayer(layoutObject)) |
+ , m_svgTransform(parentState.m_svgTransform) |
+ , m_pendingDelayedPaintInvalidations(parentState.pendingDelayedPaintInvalidationTargets()) |
+ , m_enclosingSelfPaintingLayer(parentState.enclosingSelfPaintingLayer(currentObject)) |
+#if ENABLE(ASSERT) |
+ , m_didUpdatePaintOffsetAndClipForChildren(true) |
+#endif |
+{ |
+ ASSERT(parentState.m_didUpdatePaintOffsetAndClipForChildren); |
+ ASSERT(!m_cachedOffsetsEnabled); |
+} |
+ |
+PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& parentState, const LayoutObject& currentObject) |
+ : m_currentObject(currentObject) |
+ , m_clipped(parentState.m_clipped) |
+ , m_cachedOffsetsEnabled(parentState.m_cachedOffsetsEnabled) |
+ , m_forcedSubtreeInvalidationWithinContainer(parentState.m_forcedSubtreeInvalidationWithinContainer) |
+ , m_forcedSubtreeInvalidationRectUpdateWithinContainer(parentState.m_forcedSubtreeInvalidationRectUpdateWithinContainer) |
+ , m_viewClippingAndScrollOffsetDisabled(false) |
+ , m_clipRect(parentState.m_clipRect) |
+ , m_paintOffset(parentState.m_paintOffset) |
+ , m_paintInvalidationContainer(currentObject.isPaintInvalidationContainer() ? toLayoutBoxModelObject(currentObject) : parentState.m_paintInvalidationContainer) |
+ , m_svgTransform(parentState.m_svgTransform) |
+ , m_pendingDelayedPaintInvalidations(parentState.pendingDelayedPaintInvalidationTargets()) |
+ , m_enclosingSelfPaintingLayer(parentState.enclosingSelfPaintingLayer(currentObject)) |
+#if ENABLE(ASSERT) |
+ , m_didUpdatePaintOffsetAndClipForChildren(false) |
+#endif |
+{ |
+ ASSERT(parentState.m_didUpdatePaintOffsetAndClipForChildren); |
+} |
+ |
+void PaintInvalidationState::updatePaintOffsetAndClipForChildren() |
{ |
- // FIXME: SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054 |
- bool establishesPaintInvalidationContainer = layoutObject == m_paintInvalidationContainer; |
- bool fixed = layoutObject.style()->position() == FixedPosition; |
+#if ENABLE(ASSERT) |
+ ASSERT(!m_didUpdatePaintOffsetAndClipForChildren); |
+ m_didUpdatePaintOffsetAndClipForChildren = true; |
+#endif |
+ |
+ bool establishesPaintInvalidationContainer = m_currentObject == m_paintInvalidationContainer; |
+ |
+ if (!m_currentObject.isBoxModelObject()) { |
+ // TODO(wangxianzhu): SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054. |
+ ASSERT(m_currentObject.isSVG()); |
+ ASSERT(!establishesPaintInvalidationContainer); |
+ if (m_cachedOffsetsEnabled) |
+ m_svgTransform = AffineTransform(m_svgTransform * m_currentObject.localToParentTransform()); |
+ return; |
+ } |
+ |
+ bool fixed = m_currentObject.style()->position() == FixedPosition; |
- if (!layoutObject.supportsPaintInvalidationStateCachedOffsets() || !next.m_cachedOffsetsEnabled) |
+ if (!m_currentObject.supportsPaintInvalidationStateCachedOffsets()) |
m_cachedOffsetsEnabled = false; |
if (establishesPaintInvalidationContainer) { |
// When we hit a new paint invalidation container, we don't need to |
@@ -61,62 +116,46 @@ PaintInvalidationState::PaintInvalidationState(PaintInvalidationState& next, Lay |
// descending into a different invalidation container. (For instance if |
// our parents were moved, the entire container will just move.) |
m_forcedSubtreeInvalidationWithinContainer = false; |
+ m_forcedSubtreeInvalidationRectUpdateWithinContainer = false; |
+ |
+ m_clipped = false; // Will be updated in applyClipIfNeeded(). |
+ m_paintOffset = LayoutSize(); |
} else { |
if (m_cachedOffsetsEnabled) { |
if (fixed) { |
- FloatPoint fixedOffset = layoutObject.localToAncestorPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries); |
+ FloatPoint fixedOffset = m_currentObject.localToAncestorPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries); |
m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()); |
- } else { |
- LayoutSize offset = layoutObject.isBox() && !layoutObject.isTableRow() ? toLayoutBox(layoutObject).locationOffset() : LayoutSize(); |
- m_paintOffset = next.m_paintOffset + offset; |
+ } else if (m_currentObject.isBox() && !m_currentObject.isTableRow()) { |
+ // We don't add locationOffset of table row because the child cells' location offsets include the row's location offset. |
+ m_paintOffset += toLayoutBox(m_currentObject).locationOffset(); |
} |
- if (layoutObject.isOutOfFlowPositioned() && !fixed) { |
- if (LayoutObject* container = layoutObject.container()) { |
+ if (m_currentObject.isOutOfFlowPositioned() && !fixed) { |
+ if (LayoutObject* container = m_currentObject.container()) { |
if (container->isInFlowPositioned() && container->isLayoutInline()) |
- m_paintOffset += toLayoutInline(container)->offsetForInFlowPositionedInline(toLayoutBox(layoutObject)); |
+ m_paintOffset += toLayoutInline(container)->offsetForInFlowPositionedInline(toLayoutBox(m_currentObject)); |
} |
} |
- if (layoutObject.isInFlowPositioned() && layoutObject.hasLayer()) |
- m_paintOffset += layoutObject.layer()->offsetForInFlowPosition(); |
+ if (m_currentObject.isInFlowPositioned() && m_currentObject.hasLayer()) |
+ m_paintOffset += toLayoutBoxModelObject(m_currentObject).layer()->offsetForInFlowPosition(); |
} |
- m_clipped = !fixed && next.m_clipped; |
- if (m_clipped) |
- m_clipRect = next.m_clipRect; |
+ m_clipped = !fixed && m_clipped; |
} |
- if (m_cachedOffsetsEnabled && layoutObject.isSVGRoot()) { |
- const LayoutSVGRoot& svgRoot = toLayoutSVGRoot(layoutObject); |
+ if (m_cachedOffsetsEnabled && m_currentObject.isSVGRoot()) { |
+ const LayoutSVGRoot& svgRoot = toLayoutSVGRoot(m_currentObject); |
m_svgTransform = AffineTransform(svgRoot.localToBorderBoxTransform()); |
if (svgRoot.shouldApplyViewportClip()) |
addClipRectRelativeToPaintOffset(LayoutSize(svgRoot.pixelSnappedSize())); |
} |
- applyClipIfNeeded(layoutObject); |
+ applyClipIfNeeded(); |
// FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present. |
} |
-PaintInvalidationState::PaintInvalidationState(PaintInvalidationState& next, const LayoutSVGModelObject& layoutObject) |
- : m_clipped(next.m_clipped) |
- , m_cachedOffsetsEnabled(next.m_cachedOffsetsEnabled) |
- , m_forcedSubtreeInvalidationWithinContainer(next.m_forcedSubtreeInvalidationWithinContainer) |
- , m_forcedSubtreeInvalidationRectUpdateWithinContainer(next.m_forcedSubtreeInvalidationRectUpdateWithinContainer) |
- , m_viewClippingAndScrollOffsetDisabled(false) |
- , m_clipRect(next.m_clipRect) |
- , m_paintOffset(next.m_paintOffset) |
- , m_paintInvalidationContainer(next.m_paintInvalidationContainer) |
- , m_pendingDelayedPaintInvalidations(next.pendingDelayedPaintInvalidationTargets()) |
- , m_enclosingSelfPaintingLayer(next.enclosingSelfPaintingLayer(layoutObject)) |
-{ |
- ASSERT(layoutObject != m_paintInvalidationContainer); |
- |
- if (m_cachedOffsetsEnabled) |
- m_svgTransform = AffineTransform(next.svgTransform() * layoutObject.localToParentTransform()); |
-} |
- |
void PaintInvalidationState::mapObjectRectToAncestor(const LayoutObject& object, const LayoutBoxModelObject* ancestor, LayoutRect& rect) const |
{ |
ASSERT(canMapToAncestor(ancestor)); |
@@ -155,12 +194,12 @@ void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutSize& |
} |
} |
-void PaintInvalidationState::applyClipIfNeeded(const LayoutObject& layoutObject) |
+void PaintInvalidationState::applyClipIfNeeded() |
{ |
- if (!layoutObject.hasOverflowClip()) |
+ if (!m_currentObject.hasOverflowClip()) |
return; |
- const LayoutBox& box = toLayoutBox(layoutObject); |
+ const LayoutBox& box = toLayoutBox(m_currentObject); |
// Do not clip scroll layer contents because the compositor expects the whole layer |
// to be always invalidated in-time. |