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. | |
wkorman
2017/02/21 22:54:19
Are transforms the only potential cause of subpixe
Xianzhu
2017/02/21 23:15:59
Yes.
We need to apply enclosingIntRect before ear
| |
119 if (!isSVGChild && | |
120 context.treeBuilderContext.current.transform != | |
121 containerContentsProperties->transform()) | |
122 rect = Rect(enclosingIntRect(rect)); | |
123 | |
117 PropertyTreeState currentTreeState( | 124 PropertyTreeState currentTreeState( |
118 context.treeBuilderContext.current.transform, | 125 context.treeBuilderContext.current.transform, |
119 context.treeBuilderContext.current.clip, nullptr); | 126 context.treeBuilderContext.current.clip, nullptr); |
120 result = LayoutRect( | 127 result = LayoutRect( |
121 geometryMapper | 128 geometryMapper |
122 .sourceToDestinationVisualRect(FloatRect(rect), currentTreeState, | 129 .sourceToDestinationVisualRect(FloatRect(rect), currentTreeState, |
123 *containerContentsProperties) | 130 *containerContentsProperties) |
124 .rect()); | 131 .rect()); |
125 } | 132 } |
126 | 133 |
(...skipping 25 matching lines...) Expand all Loading... | |
152 return mapLocalRectToPaintInvalidationBacking<FloatRect, FloatPoint>( | 159 return mapLocalRectToPaintInvalidationBacking<FloatRect, FloatPoint>( |
153 object, localRect, context, m_geometryMapper); | 160 object, localRect, context, m_geometryMapper); |
154 } | 161 } |
155 return mapLocalRectToPaintInvalidationBacking<LayoutRect, LayoutPoint>( | 162 return mapLocalRectToPaintInvalidationBacking<LayoutRect, LayoutPoint>( |
156 object, object.localVisualRect(), context, m_geometryMapper); | 163 object, object.localVisualRect(), context, m_geometryMapper); |
157 } | 164 } |
158 | 165 |
159 LayoutPoint PaintInvalidator::computeLocationInBacking( | 166 LayoutPoint PaintInvalidator::computeLocationInBacking( |
160 const LayoutObject& object, | 167 const LayoutObject& object, |
161 const PaintInvalidatorContext& context) { | 168 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; | 169 LayoutPoint point; |
168 if (object != context.paintInvalidationContainer) { | 170 if (object != context.paintInvalidationContainer) { |
169 point.moveBy(object.paintOffset()); | 171 point.moveBy(object.paintOffset()); |
170 | 172 |
171 const auto* containerTransform = | 173 const auto* containerTransform = |
172 context.paintInvalidationContainer->paintProperties() | 174 context.paintInvalidationContainer->paintProperties() |
173 ->contentsProperties() | 175 ->contentsProperties() |
174 ->transform(); | 176 ->transform(); |
175 if (context.treeBuilderContext.current.transform != containerTransform) { | 177 if (context.treeBuilderContext.current.transform != containerTransform) { |
176 point = LayoutPoint(m_geometryMapper | 178 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. | 341 // geometry effects, after skia optimizes filter's mapRect operation. |
340 // TODO(crbug.com/648274): This is a workaround for multi-column contents. | 342 // TODO(crbug.com/648274): This is a workaround for multi-column contents. |
341 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) { | 343 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) { |
342 context.forcedSubtreeInvalidationFlags |= | 344 context.forcedSubtreeInvalidationFlags |= |
343 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; | 345 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; |
344 } | 346 } |
345 | 347 |
346 ObjectPaintInvalidator objectPaintInvalidator(object); | 348 ObjectPaintInvalidator objectPaintInvalidator(object); |
347 context.oldVisualRect = object.previousVisualRect(); | 349 context.oldVisualRect = object.previousVisualRect(); |
348 context.oldLocation = objectPaintInvalidator.previousLocationInBacking(); | 350 context.oldLocation = objectPaintInvalidator.previousLocationInBacking(); |
349 context.newVisualRect = computeVisualRectInBacking(object, context); | |
350 context.newLocation = computeLocationInBacking(object, context); | |
351 | 351 |
352 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation( | 352 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation( |
353 *context.paintInvalidationContainer); | 353 *context.paintInvalidationContainer); |
354 context.newLocation.move(adjustment); | 354 context.newVisualRect = computeVisualRectInBacking(object, context); |
355 context.newVisualRect.move(adjustment); | 355 context.newVisualRect.move(adjustment); |
356 | 356 |
357 if (object.isText()) { | |
358 // Use visual rect location for LayoutTexts because it suffices to check | |
359 // visual rect change for layout caused invalidation. | |
wkorman
2017/02/21 22:54:19
insert 'whether a' before 'visual'
Xianzhu
2017/02/21 23:15:59
Done.
| |
360 context.newLocation = context.newVisualRect.location(); | |
361 } else { | |
362 context.newLocation = computeLocationInBacking(object, context); | |
363 context.newLocation.move(adjustment); | |
wkorman
2017/02/21 22:54:19
We don't need this for the text case?
Xianzhu
2017/02/21 23:15:59
No, because context.newVisualRect.location() has a
| |
364 | |
365 // Location of empty visual rect doesn't affect paint invalidation. Set it | |
366 // to newLocation to avoid saving the previous location separately in | |
367 // ObjectPaintInvalidator. | |
368 if (context.newVisualRect.isEmpty()) | |
369 context.newVisualRect.setLocation(context.newLocation); | |
370 } | |
371 | |
357 object.getMutableForPainting().setPreviousVisualRect(context.newVisualRect); | 372 object.getMutableForPainting().setPreviousVisualRect(context.newVisualRect); |
358 objectPaintInvalidator.setPreviousLocationInBacking(context.newLocation); | 373 objectPaintInvalidator.setPreviousLocationInBacking(context.newLocation); |
359 } | 374 } |
360 | 375 |
361 void PaintInvalidator::invalidatePaintIfNeeded( | 376 void PaintInvalidator::invalidatePaintIfNeeded( |
362 FrameView& frameView, | 377 FrameView& frameView, |
363 PaintInvalidatorContext& context) { | 378 PaintInvalidatorContext& context) { |
364 LayoutView* layoutView = frameView.layoutView(); | 379 LayoutView* layoutView = frameView.layoutView(); |
365 CHECK(layoutView); | 380 CHECK(layoutView); |
366 | 381 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; | 462 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; |
448 } | 463 } |
449 | 464 |
450 void PaintInvalidator::processPendingDelayedPaintInvalidations() { | 465 void PaintInvalidator::processPendingDelayedPaintInvalidations() { |
451 for (auto target : m_pendingDelayedPaintInvalidations) | 466 for (auto target : m_pendingDelayedPaintInvalidations) |
452 target->getMutableForPainting().setShouldDoFullPaintInvalidation( | 467 target->getMutableForPainting().setShouldDoFullPaintInvalidation( |
453 PaintInvalidationDelayedFull); | 468 PaintInvalidationDelayedFull); |
454 } | 469 } |
455 | 470 |
456 } // namespace blink | 471 } // namespace blink |
OLD | NEW |