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/rendering/PaintInvalidationState.h"
8 #include "core/rendering/RenderInline.h"
9 #include "core/rendering/RenderLayer.h"
10 #include "core/rendering/RenderView.h"
11 #include "core/rendering/svg/RenderSVGModelObject.h"
12 #include "core/rendering/svg/RenderSVGRoot.h"
13 #include "platform/Partitions.h"
17 PaintInvalidationState::PaintInvalidationState(const RenderView& renderView)
19 , m_cachedOffsetsEnabled(true)
20 , m_forceCheckForPaintInvalidation(false)
21 , m_paintInvalidationContainer(*renderView.containerForPaintInvalidation())
23 bool establishesPaintInvalidationContainer = renderView == m_paintInvalidationContainer;
24 if (!establishesPaintInvalidationContainer) {
25 if (!renderView.supportsPaintInvalidationStateCachedOffsets()) {
26 m_cachedOffsetsEnabled = false;
29 FloatPoint point = renderView.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries);
30 m_paintOffset = LayoutSize(point.x(), point.y());
32 m_clipRect = renderView.viewRect();
33 m_clipRect.move(m_paintOffset);
37 PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& next, RenderLayerModelObject& renderer, const RenderLayerModelObject& paintInvalidationContainer)
39 , m_cachedOffsetsEnabled(true)
40 , m_forceCheckForPaintInvalidation(next.m_forceCheckForPaintInvalidation)
41 , m_paintInvalidationContainer(paintInvalidationContainer)
43 // FIXME: SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054
44 bool establishesPaintInvalidationContainer = renderer == m_paintInvalidationContainer;
45 bool fixed = renderer.style()->position() == FixedPosition;
47 if (establishesPaintInvalidationContainer) {
48 // When we hit a new paint invalidation container, we don't need to
49 // continue forcing a check for paint invalidation because movement
50 // from our parents will just move the whole invalidation container.
51 m_forceCheckForPaintInvalidation = false;
53 if (!renderer.supportsPaintInvalidationStateCachedOffsets() || !next.m_cachedOffsetsEnabled) {
54 m_cachedOffsetsEnabled = false;
57 FloatPoint fixedOffset = renderer.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries);
58 m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y());
60 LayoutSize offset = renderer.isBox() && !renderer.isTableRow() ? toRenderBox(renderer).locationOffset() : LayoutSize();
61 m_paintOffset = next.m_paintOffset + offset;
64 if (renderer.isOutOfFlowPositioned() && !fixed) {
65 if (RenderObject* container = renderer.container()) {
66 if (container->style()->hasInFlowPosition() && container->isRenderInline())
67 m_paintOffset += toRenderInline(container)->offsetForInFlowPositionedInline(toRenderBox(renderer));
71 if (renderer.style()->hasInFlowPosition() && renderer.hasLayer())
72 m_paintOffset += renderer.layer()->offsetForInFlowPosition();
75 m_clipped = !fixed && next.m_clipped;
77 m_clipRect = next.m_clipRect;
80 if (m_cachedOffsetsEnabled && renderer.isSVGRoot()) {
81 const RenderSVGRoot& svgRoot = toRenderSVGRoot(renderer);
82 m_svgTransform = adoptPtr(new AffineTransform(svgRoot.localToBorderBoxTransform()));
83 if (svgRoot.shouldApplyViewportClip())
84 addClipRectRelativeToPaintOffset(svgRoot.pixelSnappedSize());
87 applyClipIfNeeded(renderer);
89 // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
92 PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& next, const RenderSVGModelObject& renderer)
93 : m_clipped(next.m_clipped)
94 , m_cachedOffsetsEnabled(next.m_cachedOffsetsEnabled)
95 , m_forceCheckForPaintInvalidation(next.m_forceCheckForPaintInvalidation)
96 , m_clipRect(next.m_clipRect)
97 , m_paintOffset(next.m_paintOffset)
98 , m_paintInvalidationContainer(next.m_paintInvalidationContainer)
100 ASSERT(renderer != m_paintInvalidationContainer);
102 if (m_cachedOffsetsEnabled)
103 m_svgTransform = adoptPtr(new AffineTransform(next.svgTransform() * renderer.localToParentTransform()));
106 void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutSize& clipSize)
108 LayoutRect clipRect(toPoint(m_paintOffset), clipSize);
110 m_clipRect.intersect(clipRect);
112 m_clipRect = clipRect;
117 void PaintInvalidationState::applyClipIfNeeded(const RenderObject& renderer)
119 if (!renderer.hasOverflowClip())
122 const RenderBox& box = toRenderBox(renderer);
124 // Do not clip scroll layer contents because the compositor expects the whole layer
125 // to be always invalidated in-time.
126 if (box.usesCompositedScrolling())
127 ASSERT(!m_clipped); // The box should establish paint invalidation container, so no m_clipped inherited.
129 addClipRectRelativeToPaintOffset(box.layer()->size());
131 m_paintOffset -= box.scrolledContentOffset();