OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/paint/BoxPaintInvalidator.h" | 5 #include "core/paint/BoxPaintInvalidator.h" |
6 | 6 |
7 #include "core/frame/Settings.h" | 7 #include "core/frame/Settings.h" |
8 #include "core/layout/LayoutView.h" | 8 #include "core/layout/LayoutView.h" |
9 #include "core/layout/compositing/CompositedLayerMapping.h" | 9 #include "core/layout/compositing/CompositedLayerMapping.h" |
10 #include "core/paint/ObjectPaintInvalidator.h" | 10 #include "core/paint/ObjectPaintInvalidator.h" |
11 #include "core/paint/PaintInvalidator.h" | 11 #include "core/paint/PaintInvalidator.h" |
12 #include "core/paint/PaintLayer.h" | 12 #include "core/paint/PaintLayer.h" |
13 #include "core/paint/PaintLayerScrollableArea.h" | 13 #include "core/paint/PaintLayerScrollableArea.h" |
14 #include "platform/geometry/LayoutRect.h" | 14 #include "platform/geometry/LayoutRect.h" |
15 | 15 |
16 namespace blink { | 16 namespace blink { |
17 | 17 |
18 struct PreviousBoxGeometries { | |
19 LayoutRect contentBoxRect; | |
20 LayoutRect layoutOverflowRect; | |
21 }; | |
22 | |
23 typedef HashMap<const LayoutBox*, PreviousBoxGeometries> | |
24 PreviousBoxGeometriesMap; | |
25 static PreviousBoxGeometriesMap& previousBoxGeometriesMap() { | |
26 DEFINE_STATIC_LOCAL(PreviousBoxGeometriesMap, map, ()); | |
27 return map; | |
28 } | |
29 | |
30 void BoxPaintInvalidator::boxWillBeDestroyed(const LayoutBox& box) { | |
31 DCHECK(box.hasPreviousBoxGeometries() == | |
32 previousBoxGeometriesMap().contains(&box)); | |
33 if (box.hasPreviousBoxGeometries()) | |
34 previousBoxGeometriesMap().erase(&box); | |
35 } | |
36 | |
37 static LayoutRect computeRightDelta(const LayoutPoint& location, | 18 static LayoutRect computeRightDelta(const LayoutPoint& location, |
38 const LayoutSize& oldSize, | 19 const LayoutSize& oldSize, |
39 const LayoutSize& newSize, | 20 const LayoutSize& newSize, |
40 const LayoutUnit& extraWidth) { | 21 const LayoutUnit& extraWidth) { |
41 LayoutUnit delta = newSize.width() - oldSize.width(); | 22 LayoutUnit delta = newSize.width() - oldSize.width(); |
42 if (delta > 0) { | 23 if (delta > 0) { |
43 return LayoutRect(location.x() + oldSize.width() - extraWidth, location.y(), | 24 return LayoutRect(location.x() + oldSize.width() - extraWidth, location.y(), |
44 delta + extraWidth, newSize.height()); | 25 delta + extraWidth, newSize.height()); |
45 } | 26 } |
46 if (delta < 0) { | 27 if (delta < 0) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 // can safely exit here. | 92 // can safely exit here. |
112 if (layoutView.usesCompositing() && | 93 if (layoutView.usesCompositing() && |
113 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) | 94 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) |
114 return reason; | 95 return reason; |
115 } | 96 } |
116 | 97 |
117 const ComputedStyle& style = m_box.styleRef(); | 98 const ComputedStyle& style = m_box.styleRef(); |
118 | 99 |
119 if ((style.backgroundLayers().thisOrNextLayersUseContentBox() || | 100 if ((style.backgroundLayers().thisOrNextLayersUseContentBox() || |
120 style.maskLayers().thisOrNextLayersUseContentBox()) && | 101 style.maskLayers().thisOrNextLayersUseContentBox()) && |
121 previousContentBoxRect() != m_box.contentBoxRect()) | 102 m_box.previousContentBoxSize() != m_box.contentBoxRect().size()) |
122 return PaintInvalidationContentBoxChange; | 103 return PaintInvalidationContentBoxChange; |
123 | 104 |
124 LayoutSize oldBorderBoxSize = m_box.previousSize(); | 105 LayoutSize oldBorderBoxSize = m_box.previousSize(); |
125 LayoutSize newBorderBoxSize = m_box.size(); | 106 LayoutSize newBorderBoxSize = m_box.size(); |
126 bool borderBoxChanged = oldBorderBoxSize != newBorderBoxSize; | 107 bool borderBoxChanged = oldBorderBoxSize != newBorderBoxSize; |
127 if (!borderBoxChanged && m_context.oldVisualRect == m_context.newVisualRect) | 108 if (!borderBoxChanged && m_context.oldVisualRect == m_context.newVisualRect) |
128 return PaintInvalidationNone; | 109 return PaintInvalidationNone; |
129 | 110 |
130 // If either border box changed or bounds changed, and old or new border box | 111 // If either border box changed or bounds changed, and old or new border box |
131 // doesn't equal old or new bounds, incremental invalidation is not | 112 // doesn't equal old or new bounds, incremental invalidation is not |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 return false; | 191 return false; |
211 } | 192 } |
212 | 193 |
213 void BoxPaintInvalidator::invalidateScrollingContentsBackgroundIfNeeded() { | 194 void BoxPaintInvalidator::invalidateScrollingContentsBackgroundIfNeeded() { |
214 bool paintsOntoScrollingContentsLayer = | 195 bool paintsOntoScrollingContentsLayer = |
215 backgroundPaintsOntoScrollingContentsLayer(); | 196 backgroundPaintsOntoScrollingContentsLayer(); |
216 if (!paintsOntoScrollingContentsLayer && | 197 if (!paintsOntoScrollingContentsLayer && |
217 !backgroundGeometryDependsOnLayoutOverflowRect()) | 198 !backgroundGeometryDependsOnLayoutOverflowRect()) |
218 return; | 199 return; |
219 | 200 |
220 const LayoutRect& oldLayoutOverflow = previousLayoutOverflowRect(); | 201 const LayoutRect& oldLayoutOverflow = m_box.previousLayoutOverflowRect(); |
221 LayoutRect newLayoutOverflow = m_box.layoutOverflowRect(); | 202 LayoutRect newLayoutOverflow = m_box.layoutOverflowRect(); |
222 | 203 |
223 bool shouldFullyInvalidateOnScrollingContentsLayer = false; | 204 bool shouldFullyInvalidateOnScrollingContentsLayer = false; |
224 if (m_box.backgroundChangedSinceLastPaintInvalidation()) { | 205 if (m_box.backgroundChangedSinceLastPaintInvalidation()) { |
225 if (!paintsOntoScrollingContentsLayer) { | 206 if (!paintsOntoScrollingContentsLayer) { |
226 // The box should have been set needing full invalidation on style change. | 207 // The box should have been set needing full invalidation on style change. |
227 DCHECK(m_box.shouldDoFullPaintInvalidation()); | 208 DCHECK(m_box.shouldDoFullPaintInvalidation()); |
228 return; | 209 return; |
229 } | 210 } |
230 shouldFullyInvalidateOnScrollingContentsLayer = true; | 211 shouldFullyInvalidateOnScrollingContentsLayer = true; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 | 281 |
301 if (PaintLayerScrollableArea* area = m_box.getScrollableArea()) | 282 if (PaintLayerScrollableArea* area = m_box.getScrollableArea()) |
302 area->invalidatePaintOfScrollControlsIfNeeded(m_context); | 283 area->invalidatePaintOfScrollControlsIfNeeded(m_context); |
303 | 284 |
304 // This is for the next invalidatePaintIfNeeded so must be at the end. | 285 // This is for the next invalidatePaintIfNeeded so must be at the end. |
305 savePreviousBoxGeometriesIfNeeded(); | 286 savePreviousBoxGeometriesIfNeeded(); |
306 | 287 |
307 return reason; | 288 return reason; |
308 } | 289 } |
309 | 290 |
310 bool BoxPaintInvalidator::needsToSavePreviousBoxGeometries() { | 291 bool BoxPaintInvalidator:: |
| 292 needsToSavePreviousContentBoxSizeOrLayoutOverflowRect() { |
311 // Don't save old box geometries if the paint rect is empty because we'll | 293 // Don't save old box geometries if the paint rect is empty because we'll |
312 // fully invalidate once the paint rect becomes non-empty. | 294 // fully invalidate once the paint rect becomes non-empty. |
313 if (m_context.newVisualRect.isEmpty()) | 295 if (m_context.newVisualRect.isEmpty()) |
314 return false; | 296 return false; |
315 | 297 |
316 if (m_box.paintedOutputOfObjectHasNoEffectRegardlessOfSize()) | 298 if (m_box.paintedOutputOfObjectHasNoEffectRegardlessOfSize()) |
317 return false; | 299 return false; |
318 | 300 |
319 const ComputedStyle& style = m_box.styleRef(); | 301 const ComputedStyle& style = m_box.styleRef(); |
320 | 302 |
321 // Background and mask layers can depend on other boxes than border box. See | 303 // Background and mask layers can depend on other boxes than border box. See |
322 // crbug.com/490533 | 304 // crbug.com/490533 |
323 if (style.backgroundLayers().thisOrNextLayersUseContentBox() || | 305 if ((style.backgroundLayers().thisOrNextLayersUseContentBox() || |
324 style.maskLayers().thisOrNextLayersUseContentBox() || | 306 style.maskLayers().thisOrNextLayersUseContentBox()) && |
325 backgroundGeometryDependsOnLayoutOverflowRect() || | 307 m_box.contentBoxRect().size() != m_box.size()) |
326 backgroundPaintsOntoScrollingContentsLayer()) | 308 return true; |
| 309 if ((backgroundGeometryDependsOnLayoutOverflowRect() || |
| 310 backgroundPaintsOntoScrollingContentsLayer()) && |
| 311 m_box.layoutOverflowRect() != m_box.borderBoxRect()) |
327 return true; | 312 return true; |
328 | 313 |
329 return false; | 314 return false; |
330 } | 315 } |
331 | 316 |
332 void BoxPaintInvalidator::savePreviousBoxGeometriesIfNeeded() { | 317 void BoxPaintInvalidator::savePreviousBoxGeometriesIfNeeded() { |
333 m_box.getMutableForPainting().setPreviousSize(m_box.size()); | 318 m_box.getMutableForPainting().savePreviousSize(); |
334 | 319 |
335 DCHECK(m_box.hasPreviousBoxGeometries() == | 320 if (needsToSavePreviousContentBoxSizeOrLayoutOverflowRect()) { |
336 previousBoxGeometriesMap().contains(&m_box)); | 321 m_box.getMutableForPainting() |
337 if (!needsToSavePreviousBoxGeometries()) { | 322 .savePreviousContentBoxSizeAndLayoutOverflowRect(); |
338 if (m_box.hasPreviousBoxGeometries()) { | 323 } else { |
339 previousBoxGeometriesMap().erase(&m_box); | 324 m_box.getMutableForPainting() |
340 m_box.getMutableForPainting().setHasPreviousBoxGeometries(false); | 325 .clearPreviousContentBoxSizeAndLayoutOverflowRect(); |
341 } | |
342 return; | |
343 } | 326 } |
344 | |
345 PreviousBoxGeometries geometries = {m_box.contentBoxRect(), | |
346 m_box.layoutOverflowRect()}; | |
347 previousBoxGeometriesMap().set(&m_box, geometries); | |
348 m_box.getMutableForPainting().setHasPreviousBoxGeometries(true); | |
349 } | |
350 | |
351 LayoutRect BoxPaintInvalidator::previousContentBoxRect() { | |
352 DCHECK(m_box.hasPreviousBoxGeometries() == | |
353 previousBoxGeometriesMap().contains(&m_box)); | |
354 return m_box.hasPreviousBoxGeometries() | |
355 ? previousBoxGeometriesMap().get(&m_box).contentBoxRect | |
356 : LayoutRect(LayoutPoint(), m_box.previousSize()); | |
357 } | |
358 | |
359 LayoutRect BoxPaintInvalidator::previousLayoutOverflowRect() { | |
360 DCHECK(m_box.hasPreviousBoxGeometries() == | |
361 previousBoxGeometriesMap().contains(&m_box)); | |
362 return m_box.hasPreviousBoxGeometries() | |
363 ? previousBoxGeometriesMap().get(&m_box).layoutOverflowRect | |
364 : LayoutRect(LayoutPoint(), m_box.previousSize()); | |
365 } | 327 } |
366 | 328 |
367 } // namespace blink | 329 } // namespace blink |
OLD | NEW |