1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/layout/PaintInvalidationState.h"
8 #include "core/layout/LayoutInline.h"
9 #include "core/layout/LayoutView.h"
10 #include "core/layout/svg/LayoutSVGModelObject.h"
11 #include "core/layout/svg/LayoutSVGRoot.h"
12 #include "core/paint/DeprecatedPaintLayer.h"
16 PaintInvalidationState::PaintInvalidationState(const LayoutView
& layoutView
, Vector
<LayoutObject
*>& pendingDelayedPaintInvalidations
, PaintInvalidationState
* ownerPaintInvalidationState
)
18 , m_cachedOffsetsEnabled(true)
19 , m_forcedSubtreeInvalidationWithinContainer(false)
20 , m_paintInvalidationContainer(*layoutView
.containerForPaintInvalidation())
21 , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations
)
23 bool establishesPaintInvalidationContainer
= layoutView
== m_paintInvalidationContainer
;
24 if (!establishesPaintInvalidationContainer
) {
25 if ((ownerPaintInvalidationState
&& !ownerPaintInvalidationState
->m_cachedOffsetsEnabled
)
26 || !layoutView
.supportsPaintInvalidationStateCachedOffsets()) {
27 m_cachedOffsetsEnabled
= false;
30 if (ownerPaintInvalidationState
&& ownerPaintInvalidationState
->m_forcedSubtreeInvalidationWithinContainer
)
31 m_forcedSubtreeInvalidationWithinContainer
= true;
32 FloatPoint point
= layoutView
.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer
, TraverseDocumentBoundaries
);
33 m_paintOffset
= LayoutSize(point
.x(), point
.y());
35 m_clipRect
= layoutView
.viewRect();
36 m_clipRect
.move(m_paintOffset
);
40 PaintInvalidationState::PaintInvalidationState(PaintInvalidationState
& next
, LayoutBoxModelObject
& layoutObject
, const LayoutBoxModelObject
& paintInvalidationContainer
)
42 , m_cachedOffsetsEnabled(true)
43 , m_forcedSubtreeInvalidationWithinContainer(next
.m_forcedSubtreeInvalidationWithinContainer
)
44 , m_paintInvalidationContainer(paintInvalidationContainer
)
45 , m_pendingDelayedPaintInvalidations(next
.pendingDelayedPaintInvalidationTargets())
47 // FIXME: SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054
48 bool establishesPaintInvalidationContainer
= layoutObject
== m_paintInvalidationContainer
;
49 bool fixed
= layoutObject
.style()->position() == FixedPosition
;
51 if (!layoutObject
.supportsPaintInvalidationStateCachedOffsets() || !next
.m_cachedOffsetsEnabled
)
52 m_cachedOffsetsEnabled
= false;
53 if (establishesPaintInvalidationContainer
) {
54 // When we hit a new paint invalidation container, we don't need to
55 // continue forcing a check for paint invalidation, since we're
56 // descending into a different invalidation container. (For instance if
57 // our parents were moved, the entire container will just move.)
58 m_forcedSubtreeInvalidationWithinContainer
= false;
60 if (m_cachedOffsetsEnabled
) {
62 FloatPoint fixedOffset
= layoutObject
.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer
, TraverseDocumentBoundaries
);
63 m_paintOffset
= LayoutSize(fixedOffset
.x(), fixedOffset
.y());
65 LayoutSize offset
= layoutObject
.isBox() && !layoutObject
.isTableRow() ? toLayoutBox(layoutObject
).locationOffset() : LayoutSize();
66 m_paintOffset
= next
.m_paintOffset
+ offset
;
69 if (layoutObject
.isOutOfFlowPositioned() && !fixed
) {
70 if (LayoutObject
* container
= layoutObject
.container()) {
71 if (container
->style()->hasInFlowPosition() && container
->isLayoutInline())
72 m_paintOffset
+= toLayoutInline(container
)->offsetForInFlowPositionedInline(toLayoutBox(layoutObject
));
76 if (layoutObject
.style()->hasInFlowPosition() && layoutObject
.hasLayer())
77 m_paintOffset
+= layoutObject
.layer()->offsetForInFlowPosition();
80 m_clipped
= !fixed
&& next
.m_clipped
;
82 m_clipRect
= next
.m_clipRect
;
85 if (m_cachedOffsetsEnabled
&& layoutObject
.isSVGRoot()) {
86 const LayoutSVGRoot
& svgRoot
= toLayoutSVGRoot(layoutObject
);
87 m_svgTransform
= adoptPtr(new AffineTransform(svgRoot
.localToBorderBoxTransform()));
88 if (svgRoot
.shouldApplyViewportClip())
89 addClipRectRelativeToPaintOffset(LayoutSize(svgRoot
.pixelSnappedSize()));
92 applyClipIfNeeded(layoutObject
);
94 // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
97 PaintInvalidationState::PaintInvalidationState(PaintInvalidationState
& next
, const LayoutSVGModelObject
& layoutObject
)
98 : m_clipped(next
.m_clipped
)
99 , m_cachedOffsetsEnabled(next
.m_cachedOffsetsEnabled
)
100 , m_forcedSubtreeInvalidationWithinContainer(next
.m_forcedSubtreeInvalidationWithinContainer
)
101 , m_clipRect(next
.m_clipRect
)
102 , m_paintOffset(next
.m_paintOffset
)
103 , m_paintInvalidationContainer(next
.m_paintInvalidationContainer
)
104 , m_pendingDelayedPaintInvalidations(next
.pendingDelayedPaintInvalidationTargets())
106 ASSERT(layoutObject
!= m_paintInvalidationContainer
);
108 if (m_cachedOffsetsEnabled
)
109 m_svgTransform
= adoptPtr(new AffineTransform(next
.svgTransform() * layoutObject
.localToParentTransform()));
112 void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutSize
& clipSize
)
114 LayoutRect
clipRect(toPoint(m_paintOffset
), clipSize
);
116 m_clipRect
.intersect(clipRect
);
118 m_clipRect
= clipRect
;
123 void PaintInvalidationState::applyClipIfNeeded(const LayoutObject
& layoutObject
)
125 if (!layoutObject
.hasOverflowClip())
128 const LayoutBox
& box
= toLayoutBox(layoutObject
);
130 // Do not clip scroll layer contents because the compositor expects the whole layer
131 // to be always invalidated in-time.
132 if (box
.usesCompositedScrolling())
133 ASSERT(!m_clipped
); // The box should establish paint invalidation container, so no m_clipped inherited.
135 addClipRectRelativeToPaintOffset(LayoutSize(box
.layer()->size()));
137 m_paintOffset
-= box
.scrolledContentOffset();