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

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 bool boxDecorationBackgroundObscurationChanged = false;
chrishtr 2016/08/09 23:47:31 75-80 are new code?
Xianzhu 2016/08/10 16:25:01 They are previously in LayoutObject::invalidatePai
76 bool boxDecorationBackgroundObscured = m_object.boxDecorationBackgroundIsKno wnToBeObscured();
77 if (boxDecorationBackgroundObscured != m_object.previousBoxDecorationBackgro undObscured()) {
78 m_object.getMutableForPainting().setPreviousBoxDecorationBackgroundObscu red(boxDecorationBackgroundObscured);
79 boxDecorationBackgroundObscurationChanged = true;
80 }
81
82 if (m_context.forcedSubtreeInvalidationFlags & PaintInvalidatorContext::Forc edSubtreeFullInvalidation)
83 return PaintInvalidationSubtree;
84
85 if (m_object.shouldDoFullPaintInvalidation())
86 return m_object.fullPaintInvalidationReason();
87
88 if (boxDecorationBackgroundObscurationChanged)
89 return PaintInvalidationBackgroundObscurationChange;
90
91 if (m_object.paintedOutputOfObjectHasNoEffect())
92 return PaintInvalidationNone;
93
94 const ComputedStyle& style = m_object.styleRef();
95
96 // The outline may change shape because of position change of descendants. F or simplicity,
97 // just force full paint invalidation if this object is marked for checking paint invalidation
98 // for any reason.
99 // TODO(wangxianzhu): Optimize this.
100 if (style.hasOutline())
101 return PaintInvalidationOutline;
102
103 bool locationChanged = m_context.newLocation != m_context.oldLocation;
104
105 // If the bounds are the same then we know that none of the statements below
106 // can match, so we can early out.
107 if (m_context.oldBounds == m_context.newBounds)
108 return locationChanged && !m_context.oldBounds.isEmpty() ? PaintInvalida tionLocationChange : PaintInvalidationNone;
109
110 // If we shifted, we don't know the exact reason so we are conservative and trigger a full invalidation. Shifting could
111 // be caused by some layout property (left / top) or some in-flow layoutObje ct inserted / removed before us in the tree.
112 if (m_context.newBounds.location() != m_context.oldBounds.location())
113 return PaintInvalidationBoundsChange;
114
115 // If the size is zero on one of our bounds then we know we're going to have
116 // to do a full invalidation of either old bounds or new bounds.
117 if (m_context.oldBounds.isEmpty())
118 return PaintInvalidationBecameVisible;
119 if (m_context.newBounds.isEmpty())
120 return PaintInvalidationBecameInvisible;
121
122 if (locationChanged)
123 return PaintInvalidationLocationChange;
124
125 return PaintInvalidationIncremental;
126 }
127
128 void ObjectPaintInvalidator::invalidateSelectionIfNeeded(PaintInvalidationReason reason)
129 {
130 // Update selection rect when we are doing full invalidation (in case that t he object is moved,
131 // composite status changed, etc.) or shouldInvalidationSelection is set (in case that the
132 // selection itself changed).
133 bool fullInvalidation = isFullPaintInvalidationReason(reason);
134 if (!fullInvalidation && !m_object.shouldInvalidateSelection())
135 return;
136
137 LayoutRect oldSelectionRect = selectionPaintInvalidationMap().get(&m_object) ;
138 LayoutRect newSelectionRect = m_object.localSelectionRect();
139 if (!newSelectionRect.isEmpty())
140 m_context.mapLocalRectToPaintInvalidationBacking(m_object, newSelectionR ect);
141
142 newSelectionRect.move(m_object.scrollAdjustmentForPaintInvalidation(*m_conte xt.paintInvalidationContainer));
143
144 setPreviousSelectionPaintInvalidationRect(m_object, newSelectionRect);
145
146 if (!fullInvalidation) {
147 fullyInvalidatePaint(PaintInvalidationSelection, oldSelectionRect, newSe lectionRect);
148 m_context.paintingLayer->setNeedsRepaint();
149 m_object.invalidateDisplayItemClients(PaintInvalidationSelection);
150 }
151 }
152
153 PaintInvalidationReason ObjectPaintInvalidator::invalidatePaintIfNeededWithCompu tedReason(PaintInvalidationReason reason)
154 {
155 // We need to invalidate the selection before checking for whether we are do ing a full invalidation.
156 // This is because we need to update the previous selection rect regardless.
157 invalidateSelectionIfNeeded(reason);
158
159 switch (reason) {
160 case PaintInvalidationNone:
161 // TODO(trchen): Currently we don't keep track of paint offset of layout objects.
162 // There are corner cases that the display items need to be invalidated for paint offset
163 // mutation, but incurs no pixel difference (i.e. bounds stay the same) so no rect-based
164 // invalidation is issued. See crbug.com/508383 and crbug.com/515977.
165 // This is a workaround to force display items to update paint offset.
166 if (m_context.forcedSubtreeInvalidationFlags & PaintInvalidatorContext:: ForcedSubtreeInvalidationChecking) {
167 reason = PaintInvalidationLocationChange;
168 break;
169 }
170 return PaintInvalidationNone;
171 case PaintInvalidationIncremental:
172 incrementallyInvalidatePaint();
173 break;
174 case PaintInvalidationDelayedFull:
175 return PaintInvalidationDelayedFull;
176 default:
177 DCHECK(isFullPaintInvalidationReason(reason));
178 fullyInvalidatePaint(reason, m_context.oldBounds, m_context.newBounds);
179 }
180
181 m_context.paintingLayer->setNeedsRepaint();
182 m_object.invalidateDisplayItemClients(reason);
183 return reason;
184 }
185
186 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698