OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
pdr.
2017/03/27 21:15:02
Nice file, I like this.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef FindPaintOffsetAndVisualRectNeedingUpdate_h | |
6 #define FindPaintOffsetAndVisualRectNeedingUpdate_h | |
7 | |
8 #if DCHECK_IS_ON() | |
9 | |
10 #include "core/layout/LayoutObject.h" | |
11 #include "core/paint/FindPropertiesNeedingUpdate.h" | |
12 #include "core/paint/ObjectPaintInvalidator.h" | |
13 #include "core/paint/PaintInvalidator.h" | |
14 #include "core/paint/PaintPropertyTreeBuilder.h" | |
15 | |
16 namespace blink { | |
17 | |
18 // This file contains scope classes for catching cases where paint offset or | |
19 // visual rect needed an update but were not marked as such. If paint offset or | |
20 // any visual rect (including visual rect of the object itself, scroll controls, | |
21 // caret, selection, etc.) will change, the object must be marked as such by | |
22 // LayoutObject::setNeedsPaintOffsetAndVisualRectUpdate() (which is a private | |
23 // function called by several public paint-invalidation-flag setting functions). | |
24 | |
25 class FindPaintOffsetNeedingUpdateScope { | |
26 public: | |
27 FindPaintOffsetNeedingUpdateScope( | |
28 const LayoutObject& object, | |
29 const PaintPropertyTreeBuilderContext& context) | |
30 : m_object(object), | |
31 m_context(context), | |
32 m_oldPaintOffset(object.paintOffset()) { | |
33 if (object.paintProperties() && | |
34 object.paintProperties()->paintOffsetTranslation()) { | |
35 m_oldPaintOffsetTranslation = | |
36 object.paintProperties()->paintOffsetTranslation()->clone(); | |
37 } | |
38 } | |
39 | |
40 ~FindPaintOffsetNeedingUpdateScope() { | |
41 if (m_context.isActuallyNeeded) | |
42 return; | |
43 DCHECK_OBJECT_PROPERTY_EQ(m_object, &m_oldPaintOffset, | |
44 &m_object.paintOffset()); | |
45 const auto* paintOffsetTranslation = | |
46 m_object.paintProperties() | |
47 ? m_object.paintProperties()->paintOffsetTranslation() | |
48 : nullptr; | |
49 DCHECK_OBJECT_PROPERTY_EQ(m_object, m_oldPaintOffsetTranslation.get(), | |
50 paintOffsetTranslation); | |
51 } | |
52 | |
53 private: | |
54 const LayoutObject& m_object; | |
55 const PaintPropertyTreeBuilderContext& m_context; | |
56 LayoutPoint m_oldPaintOffset; | |
57 RefPtr<const TransformPaintPropertyNode> m_oldPaintOffsetTranslation; | |
58 }; | |
59 | |
60 class FindVisualRectNeedingUpdateScopeBase { | |
61 protected: | |
62 FindVisualRectNeedingUpdateScopeBase(const LayoutObject& object, | |
63 const PaintInvalidatorContext& context, | |
64 const LayoutRect& oldVisualRect) | |
65 : m_object(object), | |
66 m_context(context), | |
67 m_oldVisualRect(oldVisualRect), | |
68 m_neededVisualRectUpdate(context.needsVisualRectUpdate(object)) { | |
69 if (m_neededVisualRectUpdate) { | |
70 DCHECK(!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() || | |
71 (context.m_treeBuilderContext && | |
72 context.m_treeBuilderContext->isActuallyNeeded)); | |
73 return; | |
74 } | |
75 context.m_forceVisualRectUpdateForChecking = true; | |
76 DCHECK(context.needsVisualRectUpdate(object)); | |
77 } | |
78 | |
79 ~FindVisualRectNeedingUpdateScopeBase() { | |
80 m_context.m_forceVisualRectUpdateForChecking = false; | |
81 DCHECK_EQ(m_neededVisualRectUpdate, | |
82 m_context.needsVisualRectUpdate(m_object)); | |
83 } | |
84 | |
85 static LayoutRect inflatedRect(const LayoutRect& r) { | |
86 LayoutRect result = r; | |
87 result.inflate(1); | |
88 return result; | |
89 } | |
90 | |
91 void checkVisualRect(const LayoutRect& newVisualRect) { | |
92 if (m_neededVisualRectUpdate) | |
93 return; | |
94 DCHECK((m_oldVisualRect.isEmpty() && newVisualRect.isEmpty()) || | |
95 m_oldVisualRect == newVisualRect || | |
96 // The following check is to tolerate the differences caused by | |
97 // pixel snapping that may happen for one rect but not for another | |
98 // while we need neither paint invalidation nor raster invalidation | |
99 // for the change. This may miss some real subpixel changes of visual | |
100 // rects. TODO(wangxianzhu): Look into whether we can tighten this | |
101 // for SPv2. | |
102 inflatedRect(m_oldVisualRect).contains(newVisualRect) || | |
103 inflatedRect(newVisualRect).contains(m_oldVisualRect)) | |
104 << "Visual rect changed without needing update" | |
105 << " object=" << m_object.debugName() | |
106 << " old=" << m_oldVisualRect.toString() | |
107 << " new=" << newVisualRect.toString(); | |
108 } | |
109 | |
110 const LayoutObject& m_object; | |
111 const PaintInvalidatorContext& m_context; | |
112 LayoutRect m_oldVisualRect; | |
113 bool m_neededVisualRectUpdate; | |
114 }; | |
115 | |
116 // For updates of visual rects (e.g. of scroll controls, caret, selection,etc.) | |
117 // contained by an object. | |
118 class FindVisualRectNeedingUpdateScope : FindVisualRectNeedingUpdateScopeBase { | |
119 public: | |
120 FindVisualRectNeedingUpdateScope(const LayoutObject& object, | |
121 const PaintInvalidatorContext& context, | |
122 const LayoutRect& oldVisualRect, | |
123 // Must be a reference to a rect that | |
124 // outlives this scope. | |
125 const LayoutRect& newVisualRect) | |
126 : FindVisualRectNeedingUpdateScopeBase(object, context, oldVisualRect), | |
127 m_newVisualRectRef(newVisualRect) {} | |
128 | |
129 ~FindVisualRectNeedingUpdateScope() { checkVisualRect(m_newVisualRectRef); } | |
130 | |
131 private: | |
132 const LayoutRect& m_newVisualRectRef; | |
133 }; | |
134 | |
135 // For updates of object visual rect and location. | |
136 class FindObjectVisualRectNeedingUpdateScope | |
137 : FindVisualRectNeedingUpdateScopeBase { | |
138 public: | |
139 FindObjectVisualRectNeedingUpdateScope(const LayoutObject& object, | |
140 const PaintInvalidatorContext& context) | |
141 : FindVisualRectNeedingUpdateScopeBase(object, | |
142 context, | |
143 object.visualRect()), | |
144 m_oldLocation(ObjectPaintInvalidator(object).locationInBacking()) {} | |
145 | |
146 ~FindObjectVisualRectNeedingUpdateScope() { | |
147 checkVisualRect(m_object.visualRect()); | |
148 checkLocation(); | |
149 } | |
150 | |
151 void checkLocation() { | |
152 if (m_neededVisualRectUpdate) | |
153 return; | |
154 LayoutPoint newLocation = | |
155 ObjectPaintInvalidator(m_object).locationInBacking(); | |
156 // Location of LayoutText and non-root SVG is location of the visual rect | |
157 // which have been checked above. | |
158 DCHECK(m_object.isText() || m_object.isSVGChild() || | |
159 newLocation == m_oldLocation || | |
160 // See checkVisualRect for the issue of approximation. | |
161 LayoutRect(-1, -1, 2, 2) | |
162 .contains(LayoutPoint(newLocation - m_oldLocation))) | |
163 << "Location changed without needing update" | |
164 << " object=" << m_object.debugName() | |
165 << " old=" << m_oldLocation.toString() | |
166 << " new=" << newLocation.toString(); | |
167 } | |
168 | |
169 private: | |
170 LayoutPoint m_oldLocation; | |
171 }; | |
172 | |
173 } // namespace blink | |
174 | |
175 #endif // DCHECK_IS_ON() | |
176 | |
177 #endif // FindPaintOffsetAndVisualRectNeedingUpdate_h | |
OLD | NEW |