Chromium Code Reviews| 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 |