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/PaintInvalidator.h" | 5 #include "core/paint/PaintInvalidator.h" |
6 | 6 |
7 #include "core/editing/FrameSelection.h" | 7 #include "core/editing/FrameSelection.h" |
8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
9 #include "core/frame/LocalFrame.h" | 9 #include "core/frame/LocalFrame.h" |
10 #include "core/frame/Settings.h" | 10 #include "core/frame/Settings.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 // PaintInvalidator::mapLocalRectToBacking() when removing | 45 // PaintInvalidator::mapLocalRectToBacking() when removing |
46 // PaintInvalidationState. | 46 // PaintInvalidationState. |
47 // This function is templatized to avoid FloatRect<->LayoutRect conversions | 47 // This function is templatized to avoid FloatRect<->LayoutRect conversions |
48 // which affect performance. | 48 // which affect performance. |
49 template <typename Rect, typename Point> | 49 template <typename Rect, typename Point> |
50 static LayoutRect mapLocalRectToPaintInvalidationBacking( | 50 static LayoutRect mapLocalRectToPaintInvalidationBacking( |
51 const LayoutObject& object, | 51 const LayoutObject& object, |
52 const Rect& localRect, | 52 const Rect& localRect, |
53 const PaintInvalidatorContext& context, | 53 const PaintInvalidatorContext& context, |
54 GeometryMapper& geometryMapper) { | 54 GeometryMapper& geometryMapper) { |
| 55 if (localRect.isEmpty()) |
| 56 return LayoutRect(); |
| 57 |
55 bool isSVGChild = object.isSVGChild(); | 58 bool isSVGChild = object.isSVGChild(); |
56 | 59 |
57 // TODO(wkorman): The flip below is required because visual rects are | 60 // TODO(wkorman): The flip below is required because visual rects are |
58 // currently in "physical coordinates with flipped block-flow direction" | 61 // currently in "physical coordinates with flipped block-flow direction" |
59 // (see LayoutBoxModelObject.h) but we need them to be in physical | 62 // (see LayoutBoxModelObject.h) but we need them to be in physical |
60 // coordinates. | 63 // coordinates. |
61 Rect rect = localRect; | 64 Rect rect = localRect; |
62 // Writing-mode flipping doesn't apply to non-root SVG. | 65 // Writing-mode flipping doesn't apply to non-root SVG. |
63 if (!isSVGChild) { | 66 if (!isSVGChild) { |
64 if (object.isBox()) { | 67 if (object.isBox()) { |
(...skipping 25 matching lines...) Expand all Loading... |
90 LayoutRect result; | 93 LayoutRect result; |
91 if (context.forcedSubtreeInvalidationFlags & | 94 if (context.forcedSubtreeInvalidationFlags & |
92 PaintInvalidatorContext::ForcedSubtreeSlowPathRect) { | 95 PaintInvalidatorContext::ForcedSubtreeSlowPathRect) { |
93 result = slowMapToVisualRectInAncestorSpace( | 96 result = slowMapToVisualRectInAncestorSpace( |
94 object, *context.paintInvalidationContainer, rect); | 97 object, *context.paintInvalidationContainer, rect); |
95 } else if (object == context.paintInvalidationContainer) { | 98 } else if (object == context.paintInvalidationContainer) { |
96 result = LayoutRect(rect); | 99 result = LayoutRect(rect); |
97 } else { | 100 } else { |
98 // For non-root SVG, the input rect is in local SVG coordinates in which | 101 // For non-root SVG, the input rect is in local SVG coordinates in which |
99 // paint offset doesn't apply. | 102 // paint offset doesn't apply. |
100 if (!isSVGChild) { | 103 if (!isSVGChild) |
101 rect.moveBy(Point(object.paintOffset())); | 104 rect.moveBy(Point(object.paintOffset())); |
102 // Use enclosingIntRect to ensure the final visual rect will cover the | |
103 // rect in source coordinates no matter if the painting will use pixel | |
104 // snapping. | |
105 rect = Rect(enclosingIntRect(rect)); | |
106 } | |
107 | 105 |
108 const auto* containerContentsProperties = | 106 const auto* containerContentsProperties = |
109 context.paintInvalidationContainer->paintProperties() | 107 context.paintInvalidationContainer->paintProperties() |
110 ->contentsProperties(); | 108 ->contentsProperties(); |
| 109 |
111 if (context.treeBuilderContext.current.transform == | 110 if (context.treeBuilderContext.current.transform == |
112 containerContentsProperties->transform() && | 111 containerContentsProperties->transform() && |
113 context.treeBuilderContext.current.clip == | 112 context.treeBuilderContext.current.clip == |
114 containerContentsProperties->clip()) { | 113 containerContentsProperties->clip()) { |
115 result = LayoutRect(rect); | 114 result = LayoutRect(rect); |
116 } else { | 115 } else { |
| 116 // Use enclosingIntRect to ensure the final visual rect will cover the |
| 117 // rect in source coordinates no matter if the painting will use pixel |
| 118 // snapping, when transforms are applied. If there is no transform, |
| 119 // enclosingIntRect is applied in the last step of paint invalidation |
| 120 // (see CompositedLayerMapping::setContentsNeedDisplayInRect()). |
| 121 if (!isSVGChild && |
| 122 context.treeBuilderContext.current.transform != |
| 123 containerContentsProperties->transform()) |
| 124 rect = Rect(enclosingIntRect(rect)); |
| 125 |
117 PropertyTreeState currentTreeState( | 126 PropertyTreeState currentTreeState( |
118 context.treeBuilderContext.current.transform, | 127 context.treeBuilderContext.current.transform, |
119 context.treeBuilderContext.current.clip, nullptr); | 128 context.treeBuilderContext.current.clip, nullptr); |
120 result = LayoutRect( | 129 result = LayoutRect( |
121 geometryMapper | 130 geometryMapper |
122 .sourceToDestinationVisualRect(FloatRect(rect), currentTreeState, | 131 .sourceToDestinationVisualRect(FloatRect(rect), currentTreeState, |
123 *containerContentsProperties) | 132 *containerContentsProperties) |
124 .rect()); | 133 .rect()); |
125 } | 134 } |
126 | 135 |
(...skipping 25 matching lines...) Expand all Loading... |
152 return mapLocalRectToPaintInvalidationBacking<FloatRect, FloatPoint>( | 161 return mapLocalRectToPaintInvalidationBacking<FloatRect, FloatPoint>( |
153 object, localRect, context, m_geometryMapper); | 162 object, localRect, context, m_geometryMapper); |
154 } | 163 } |
155 return mapLocalRectToPaintInvalidationBacking<LayoutRect, LayoutPoint>( | 164 return mapLocalRectToPaintInvalidationBacking<LayoutRect, LayoutPoint>( |
156 object, object.localVisualRect(), context, m_geometryMapper); | 165 object, object.localVisualRect(), context, m_geometryMapper); |
157 } | 166 } |
158 | 167 |
159 LayoutPoint PaintInvalidator::computeLocationInBacking( | 168 LayoutPoint PaintInvalidator::computeLocationInBacking( |
160 const LayoutObject& object, | 169 const LayoutObject& object, |
161 const PaintInvalidatorContext& context) { | 170 const PaintInvalidatorContext& context) { |
162 // Use visual rect location for LayoutTexts because it suffices to check | |
163 // visual rect change for layout caused invalidation. | |
164 if (object.isText()) | |
165 return context.newVisualRect.location(); | |
166 | |
167 LayoutPoint point; | 171 LayoutPoint point; |
168 if (object != context.paintInvalidationContainer) { | 172 if (object != context.paintInvalidationContainer) { |
169 point.moveBy(object.paintOffset()); | 173 point.moveBy(object.paintOffset()); |
170 | 174 |
171 const auto* containerTransform = | 175 const auto* containerTransform = |
172 context.paintInvalidationContainer->paintProperties() | 176 context.paintInvalidationContainer->paintProperties() |
173 ->contentsProperties() | 177 ->contentsProperties() |
174 ->transform(); | 178 ->transform(); |
175 if (context.treeBuilderContext.current.transform != containerTransform) { | 179 if (context.treeBuilderContext.current.transform != containerTransform) { |
176 point = LayoutPoint(m_geometryMapper | 180 point = LayoutPoint(m_geometryMapper |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 // geometry effects, after skia optimizes filter's mapRect operation. | 343 // geometry effects, after skia optimizes filter's mapRect operation. |
340 // TODO(crbug.com/648274): This is a workaround for multi-column contents. | 344 // TODO(crbug.com/648274): This is a workaround for multi-column contents. |
341 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) { | 345 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) { |
342 context.forcedSubtreeInvalidationFlags |= | 346 context.forcedSubtreeInvalidationFlags |= |
343 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; | 347 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; |
344 } | 348 } |
345 | 349 |
346 ObjectPaintInvalidator objectPaintInvalidator(object); | 350 ObjectPaintInvalidator objectPaintInvalidator(object); |
347 context.oldVisualRect = object.previousVisualRect(); | 351 context.oldVisualRect = object.previousVisualRect(); |
348 context.oldLocation = objectPaintInvalidator.previousLocationInBacking(); | 352 context.oldLocation = objectPaintInvalidator.previousLocationInBacking(); |
349 context.newVisualRect = computeVisualRectInBacking(object, context); | |
350 context.newLocation = computeLocationInBacking(object, context); | |
351 | 353 |
352 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation( | 354 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation( |
353 *context.paintInvalidationContainer); | 355 *context.paintInvalidationContainer); |
354 context.newLocation.move(adjustment); | 356 context.newVisualRect = computeVisualRectInBacking(object, context); |
355 context.newVisualRect.move(adjustment); | 357 context.newVisualRect.move(adjustment); |
356 | 358 |
| 359 if (object.isText()) { |
| 360 // Use visual rect location for LayoutTexts because it suffices to check |
| 361 // whether a visual rect changes for layout caused invalidation. |
| 362 context.newLocation = context.newVisualRect.location(); |
| 363 } else { |
| 364 context.newLocation = computeLocationInBacking(object, context); |
| 365 context.newLocation.move(adjustment); |
| 366 |
| 367 // Location of empty visual rect doesn't affect paint invalidation. Set it |
| 368 // to newLocation to avoid saving the previous location separately in |
| 369 // ObjectPaintInvalidator. |
| 370 if (context.newVisualRect.isEmpty()) |
| 371 context.newVisualRect.setLocation(context.newLocation); |
| 372 } |
| 373 |
357 object.getMutableForPainting().setPreviousVisualRect(context.newVisualRect); | 374 object.getMutableForPainting().setPreviousVisualRect(context.newVisualRect); |
358 objectPaintInvalidator.setPreviousLocationInBacking(context.newLocation); | 375 objectPaintInvalidator.setPreviousLocationInBacking(context.newLocation); |
359 } | 376 } |
360 | 377 |
361 void PaintInvalidator::invalidatePaintIfNeeded( | 378 void PaintInvalidator::invalidatePaintIfNeeded( |
362 FrameView& frameView, | 379 FrameView& frameView, |
363 PaintInvalidatorContext& context) { | 380 PaintInvalidatorContext& context) { |
364 LayoutView* layoutView = frameView.layoutView(); | 381 LayoutView* layoutView = frameView.layoutView(); |
365 CHECK(layoutView); | 382 CHECK(layoutView); |
366 | 383 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; | 464 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; |
448 } | 465 } |
449 | 466 |
450 void PaintInvalidator::processPendingDelayedPaintInvalidations() { | 467 void PaintInvalidator::processPendingDelayedPaintInvalidations() { |
451 for (auto target : m_pendingDelayedPaintInvalidations) | 468 for (auto target : m_pendingDelayedPaintInvalidations) |
452 target->getMutableForPainting().setShouldDoFullPaintInvalidation( | 469 target->getMutableForPainting().setShouldDoFullPaintInvalidation( |
453 PaintInvalidationDelayedFull); | 470 PaintInvalidationDelayedFull); |
454 } | 471 } |
455 | 472 |
456 } // namespace blink | 473 } // namespace blink |
OLD | NEW |