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

Side by Side Diff: third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.cpp

Issue 2208463003: First step of PaintInvalidator implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: - Created 4 years, 4 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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.
4
5 #include "core/paint/ObjectPaintInvalidator.h"
6
7 #include "core/layout/LayoutBlockFlow.h"
8 #include "core/paint/PaintInvalidator.h"
9 #include "core/paint/PaintLayer.h"
10
11 namespace blink {
12
13 typedef HashMap<const LayoutObject*, LayoutRect> SelectionPaintInvalidationMap;
14 static SelectionPaintInvalidationMap& selectionPaintInvalidationMap()
15 {
16 DEFINE_STATIC_LOCAL(SelectionPaintInvalidationMap, map, ());
17 return map;
18 }
19
20 static void setPreviousSelectionPaintInvalidationRect(const LayoutObject& object , const LayoutRect& rect)
21 {
22 if (rect.isEmpty())
23 selectionPaintInvalidationMap().remove(&object);
24 else
25 selectionPaintInvalidationMap().set(&object, rect);
26 }
27
28 void ObjectPaintInvalidator::objectWillBeDestroyed(const LayoutObject& object)
29 {
30 selectionPaintInvalidationMap().remove(&object);
31 }
32
33 void ObjectPaintInvalidator::incrementallyInvalidatePaint()
34 {
35 const LayoutRect& oldBounds = m_context.oldBounds;
36 const LayoutRect& newBounds = m_context.newBounds;
37
38 DCHECK(oldBounds.location() == newBounds.location());
39
40 LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
41 if (deltaRight > 0) {
42 LayoutRect invalidationRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height());
43 m_object.invalidatePaintUsingContainer(*m_context.paintInvalidationConta iner, invalidationRect, PaintInvalidationIncremental);
44 } else if (deltaRight < 0) {
45 LayoutRect invalidationRect(newBounds.maxX(), oldBounds.y(), -deltaRight , oldBounds.height());
46 m_object.invalidatePaintUsingContainer(*m_context.paintInvalidationConta iner, invalidationRect, PaintInvalidationIncremental);
47 }
48
49 LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
50 if (deltaBottom > 0) {
51 LayoutRect invalidationRect(newBounds.x(), oldBounds.maxY(), newBounds.w idth(), deltaBottom);
52 m_object.invalidatePaintUsingContainer(*m_context.paintInvalidationConta iner, invalidationRect, PaintInvalidationIncremental);
53 } else if (deltaBottom < 0) {
54 LayoutRect invalidationRect(oldBounds.x(), newBounds.maxY(), oldBounds.w idth(), -deltaBottom);
55 m_object.invalidatePaintUsingContainer(*m_context.paintInvalidationConta iner, invalidationRect, PaintInvalidationIncremental);
56 }
57 }
58
59 void ObjectPaintInvalidator::fullyInvalidatePaint(PaintInvalidationReason reason , const LayoutRect& oldBounds, const LayoutRect& newBounds)
60 {
61 // The following logic avoids invalidating twice if one set of bounds contai ns the other.
62 if (!newBounds.contains(oldBounds)) {
63 LayoutRect invalidationRect = oldBounds;
64 m_object.invalidatePaintUsingContainer(*m_context.paintInvalidationConta iner, invalidationRect, reason);
65
66 if (invalidationRect.contains(newBounds))
67 return;
68 }
69
70 m_object.invalidatePaintUsingContainer(*m_context.paintInvalidationContainer , newBounds, reason);
71 }
72
73 PaintInvalidationReason ObjectPaintInvalidator::computePaintInvalidationReason()
74 {
75 // This is before any early return to ensure the background obscuration stat us is saved.
76 bool backgroundObscurationChanged = false;
77 bool backgroundObscured = m_object.backgroundIsKnownToBeObscured();
78 if (backgroundObscured != m_object.previousBackgroundObscured()) {
79 m_object.getMutableForPainting().setPreviousBackgroundObscured(backgroun dObscured);
80 backgroundObscurationChanged = true;
81 }
82
83 if (m_context.forcedSubtreeInvalidationFlags & PaintInvalidatorContext::Forc edSubtreeFullInvalidation)
84 return PaintInvalidationSubtree;
85
86 if (m_object.shouldDoFullPaintInvalidation())
87 return m_object.fullPaintInvalidationReason();
88
89 if (backgroundObscurationChanged)
90 return PaintInvalidationBackgroundObscurationChange;
91
92 if (m_object.paintedOutputOfObjectHasNoEffect())
93 return PaintInvalidationNone;
94
95 const ComputedStyle& style = m_object.styleRef();
96
97 // The outline may change shape because of position change of descendants. F or simplicity,
98 // just force full paint invalidation if this object is marked for checking paint invalidation
99 // for any reason.
100 // TODO(wangxianzhu): Optimize this.
101 if (style.hasOutline())
102 return PaintInvalidationOutline;
103
104 bool locationChanged = m_context.newLocation != m_context.oldLocation;
105
106 // If the bounds are the same then we know that none of the statements below
107 // can match, so we can early out.
108 if (m_context.oldBounds == m_context.newBounds)
109 return locationChanged && !m_context.oldBounds.isEmpty() ? PaintInvalida tionLocationChange : PaintInvalidationNone;
110
111 // If we shifted, we don't know the exact reason so we are conservative and trigger a full invalidation. Shifting could
112 // be caused by some layout property (left / top) or some in-flow layoutObje ct inserted / removed before us in the tree.
113 if (m_context.newBounds.location() != m_context.oldBounds.location())
114 return PaintInvalidationBoundsChange;
115
116 // If the size is zero on one of our bounds then we know we're going to have
117 // to do a full invalidation of either old bounds or new bounds.
118 if (m_context.oldBounds.isEmpty())
119 return PaintInvalidationBecameVisible;
120 if (m_context.newBounds.isEmpty())
121 return PaintInvalidationBecameInvisible;
122
123 if (locationChanged)
124 return PaintInvalidationLocationChange;
125
126 return PaintInvalidationIncremental;
127 }
128
129 void ObjectPaintInvalidator::invalidateSelectionIfNeeded(PaintInvalidationReason reason)
130 {
131 // Update selection rect when we are doing full invalidation (in case that t he object is moved,
132 // composite status changed, etc.) or shouldInvalidationSelection is set (in case that the
133 // selection itself changed).
134 bool fullInvalidation = isFullPaintInvalidationReason(reason);
135 if (!fullInvalidation && !m_object.shouldInvalidateSelection())
136 return;
137
138 LayoutRect oldSelectionRect = selectionPaintInvalidationMap().get(&m_object) ;
139 LayoutRect newSelectionRect = m_object.localSelectionRect();
140 if (!newSelectionRect.isEmpty())
141 m_context.mapLocalRectToPaintInvalidationBacking(m_object, newSelectionR ect);
142
143 newSelectionRect.move(m_object.scrollAdjustmentForPaintInvalidation(*m_conte xt.paintInvalidationContainer));
144
145 setPreviousSelectionPaintInvalidationRect(m_object, newSelectionRect);
146
147 if (!fullInvalidation) {
148 fullyInvalidatePaint(PaintInvalidationSelection, oldSelectionRect, newSe lectionRect);
149 m_context.paintingLayer->setNeedsRepaint();
150 m_object.invalidateDisplayItemClients(PaintInvalidationSelection);
151 }
152 }
153
154 PaintInvalidationReason ObjectPaintInvalidator::invalidatePaintIfNeededWithCompu tedReason(PaintInvalidationReason reason)
155 {
156 // We need to invalidate the selection before checking for whether we are do ing a full invalidation.
157 // This is because we need to update the previous selection rect regardless.
158 invalidateSelectionIfNeeded(reason);
159
160 switch (reason) {
161 case PaintInvalidationNone:
162 // TODO(trchen): Currently we don't keep track of paint offset of layout objects.
163 // There are corner cases that the display items need to be invalidated for paint offset
164 // mutation, but incurs no pixel difference (i.e. bounds stay the same) so no rect-based
165 // invalidation is issued. See crbug.com/508383 and crbug.com/515977.
166 // This is a workaround to force display items to update paint offset.
167 if (m_context.forcedSubtreeInvalidationFlags & PaintInvalidatorContext:: ForcedSubtreeInvalidationChecking) {
168 reason = PaintInvalidationLocationChange;
169 break;
170 }
171 return PaintInvalidationNone;
172 case PaintInvalidationIncremental:
173 incrementallyInvalidatePaint();
174 break;
175 case PaintInvalidationDelayedFull:
176 return PaintInvalidationDelayedFull;
177 default:
178 DCHECK(isFullPaintInvalidationReason(reason));
179 fullyInvalidatePaint(reason, m_context.oldBounds, m_context.newBounds);
180 }
181
182 m_context.paintingLayer->setNeedsRepaint();
183 m_object.invalidateDisplayItemClients(reason);
184 return reason;
185 }
186
187 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698