Chromium Code Reviews| 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" |
| 11 #include "core/layout/LayoutBlockFlow.h" | 11 #include "core/layout/LayoutBlockFlow.h" |
| 12 #include "core/layout/LayoutObject.h" | 12 #include "core/layout/LayoutObject.h" |
| 13 #include "core/layout/LayoutTable.h" | 13 #include "core/layout/LayoutTable.h" |
| 14 #include "core/layout/LayoutView.h" | 14 #include "core/layout/LayoutView.h" |
| 15 #include "core/layout/svg/SVGLayoutSupport.h" | 15 #include "core/layout/svg/SVGLayoutSupport.h" |
| 16 #include "core/paint/ObjectPaintProperties.h" | 16 #include "core/paint/ObjectPaintProperties.h" |
| 17 #include "core/paint/PaintLayer.h" | 17 #include "core/paint/PaintLayer.h" |
| 18 #include "core/paint/PaintLayerScrollableArea.h" | 18 #include "core/paint/PaintLayerScrollableArea.h" |
| 19 #include "core/paint/PaintPropertyTreeBuilder.h" | 19 #include "core/paint/PaintPropertyTreeBuilder.h" |
| 20 | 20 |
| 21 namespace blink { | 21 namespace blink { |
| 22 | 22 |
| 23 static LayoutRect slowMapToVisualRectInAncestorSpace( | 23 static LayoutRect slowMapToVisualRectInAncestorSpace( |
| 24 const LayoutObject& object, | 24 const LayoutObject& object, |
| 25 const LayoutBoxModelObject& ancestor, | 25 const LayoutBoxModelObject& ancestor, |
| 26 const FloatRect& rect) { | 26 const LayoutRect& rect) { |
| 27 if (object.isSVGChild()) { | 27 if (object.isSVGChild()) { |
| 28 LayoutRect result; | 28 LayoutRect result; |
| 29 SVGLayoutSupport::mapToVisualRectInAncestorSpace(object, &ancestor, rect, | 29 SVGLayoutSupport::mapToVisualRectInAncestorSpace(object, &ancestor, |
| 30 result); | 30 FloatRect(rect), result); |
| 31 return result; | 31 return result; |
| 32 } | 32 } |
| 33 | 33 |
| 34 LayoutRect result(rect); | 34 LayoutRect result(rect); |
|
pdr.
2017/01/18 02:31:19
(Just curious, not needed for this patch)
Do these
Xianzhu
2017/01/18 06:23:02
Tested and found that "LayoutRect&" is better than
| |
| 35 if (object.isLayoutView()) | 35 if (object.isLayoutView()) |
| 36 toLayoutView(object).mapToVisualRectInAncestorSpace( | 36 toLayoutView(object).mapToVisualRectInAncestorSpace( |
| 37 &ancestor, result, InputIsInFrameCoordinates, DefaultVisualRectFlags); | 37 &ancestor, result, InputIsInFrameCoordinates, DefaultVisualRectFlags); |
| 38 else | 38 else |
| 39 object.mapToVisualRectInAncestorSpace(&ancestor, result); | 39 object.mapToVisualRectInAncestorSpace(&ancestor, result); |
| 40 return result; | 40 return result; |
| 41 } | 41 } |
| 42 | 42 |
| 43 template <typename Rect> | |
| 44 static LayoutRect mapLocalRectToPaintInvalidationContainerUsingPaintProperties( | |
|
pdr.
2017/01/18 02:31:18
Nit: does "UsingPaintProperties" add information?
| |
| 45 GeometryMapper& geometryMapper, | |
| 46 const Rect& localRect, | |
| 47 const PaintInvalidatorContext& context) { | |
| 48 const auto* containerContentsProperties = | |
| 49 context.paintInvalidationContainer->paintProperties() | |
| 50 ->contentsProperties(); | |
| 51 LayoutRect result; | |
| 52 if (context.treeBuilderContext.current.transform == | |
| 53 containerContentsProperties->transform() && | |
| 54 context.treeBuilderContext.current.clip == | |
| 55 containerContentsProperties->clip()) { | |
| 56 result = LayoutRect(localRect); | |
| 57 } else { | |
| 58 PropertyTreeState currentTreeState( | |
| 59 context.treeBuilderContext.current.transform, | |
| 60 context.treeBuilderContext.current.clip, nullptr, nullptr); | |
| 61 result = LayoutRect(geometryMapper.sourceToDestinationVisualRect( | |
| 62 FloatRect(localRect), currentTreeState, *containerContentsProperties)); | |
| 63 } | |
| 64 | |
| 65 // Convert the result into the container's contents space. | |
| 66 result.moveBy(-context.paintInvalidationContainer->paintOffset()); | |
| 67 return result; | |
| 68 } | |
| 69 | |
| 43 // TODO(wangxianzhu): Combine this into | 70 // TODO(wangxianzhu): Combine this into |
| 44 // PaintInvalidator::mapLocalRectToBacking() when removing | 71 // PaintInvalidator::mapLocalRectToBacking() when removing |
| 45 // PaintInvalidationState. | 72 // PaintInvalidationState. |
| 46 static LayoutRect mapLocalRectToPaintInvalidationBacking( | 73 static LayoutRect mapLocalRectToPaintInvalidationBacking( |
| 47 GeometryMapper& geometryMapper, | 74 GeometryMapper& geometryMapper, |
| 48 const LayoutObject& object, | 75 const LayoutObject& object, |
| 49 const FloatRect& localRect, | 76 const LayoutRect& localRect, |
| 50 const PaintInvalidatorContext& context) { | 77 const PaintInvalidatorContext& context) { |
| 78 // SVG children may use this path when mapping selection rects. | |
| 51 bool isSVGChild = object.isSVGChild(); | 79 bool isSVGChild = object.isSVGChild(); |
| 52 | 80 |
| 53 // TODO(wkorman): The flip below is required because visual rects are | 81 // TODO(wkorman): The flip below is required because visual rects are |
| 54 // currently in "physical coordinates with flipped block-flow direction" | 82 // currently in "physical coordinates with flipped block-flow direction" |
| 55 // (see LayoutBoxModelObject.h) but we need them to be in physical | 83 // (see LayoutBoxModelObject.h) but we need them to be in physical |
| 56 // coordinates. | 84 // coordinates. |
| 57 FloatRect rect = localRect; | 85 LayoutRect rect = localRect; |
| 58 // Writing-mode flipping doesn't apply to non-root SVG. | 86 // Writing-mode flipping doesn't apply to non-root SVG. |
| 59 if (!isSVGChild) { | 87 if (!isSVGChild) { |
| 60 if (object.isBox()) { | 88 if (object.isBox()) { |
| 61 toLayoutBox(object).flipForWritingMode(rect); | 89 toLayoutBox(object).flipForWritingMode(rect); |
| 62 } else if (!(context.forcedSubtreeInvalidationFlags & | 90 } else if (!(context.forcedSubtreeInvalidationFlags & |
| 63 PaintInvalidatorContext::ForcedSubtreeSlowPathRect)) { | 91 PaintInvalidatorContext::ForcedSubtreeSlowPathRect)) { |
| 64 // For SPv2 and the GeometryMapper path, we also need to convert the rect | 92 // For SPv2 and the GeometryMapper path, we also need to convert the rect |
| 65 // for non-boxes into physical coordinates before applying paint offset. | 93 // for non-boxes into physical coordinates before applying paint offset. |
| 66 // (Otherwise we'll call mapToVisualrectInAncestorSpace() which requires | 94 // (Otherwise we'll call mapToVisualrectInAncestorSpace() which requires |
| 67 // physical coordinates for boxes, but "physical coordinates with flipped | 95 // physical coordinates for boxes, but "physical coordinates with flipped |
| 68 // block-flow direction" for non-boxes for which we don't need to flip.) | 96 // block-flow direction" for non-boxes for which we don't need to flip.) |
| 69 // TODO(wangxianzhu): Avoid containingBlock(). | 97 // TODO(wangxianzhu): Avoid containingBlock(). |
| 70 object.containingBlock()->flipForWritingMode(rect); | 98 object.containingBlock()->flipForWritingMode(rect); |
| 71 } | 99 } |
| 72 } | 100 } |
| 73 | 101 |
| 74 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 102 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 75 // In SPv2, visual rects are in the space of their local transform node. | 103 // In SPv2, visual rects are in the space of their local transform node. |
| 76 // For SVG, the input rect is in local SVG coordinates in which paint | 104 // For SVG, the input rect is in local SVG coordinates in which paint |
| 77 // offset doesn't apply. | 105 // offset doesn't apply. |
| 78 if (!isSVGChild) | 106 if (!isSVGChild) |
| 79 rect.moveBy(FloatPoint(object.paintOffset())); | 107 rect.moveBy(object.paintOffset()); |
| 80 // Use enclosingIntRect to ensure the final visual rect will cover the | 108 // Use enclosingIntRect to ensure the final visual rect will cover the |
| 81 // rect in source coordinates no matter if the painting will use pixel | 109 // rect in source coordinates no matter if the painting will use pixel |
| 82 // snapping. | 110 // snapping. |
| 83 return LayoutRect(enclosingIntRect(rect)); | 111 return LayoutRect(enclosingIntRect(rect)); |
| 84 } | 112 } |
| 85 | 113 |
| 86 LayoutRect result; | 114 LayoutRect result; |
| 87 if (context.forcedSubtreeInvalidationFlags & | 115 if (context.forcedSubtreeInvalidationFlags & |
| 88 PaintInvalidatorContext::ForcedSubtreeSlowPathRect) { | 116 PaintInvalidatorContext::ForcedSubtreeSlowPathRect) { |
| 89 result = slowMapToVisualRectInAncestorSpace( | 117 result = slowMapToVisualRectInAncestorSpace( |
| 90 object, *context.paintInvalidationContainer, rect); | 118 object, *context.paintInvalidationContainer, rect); |
| 91 } else if (object == context.paintInvalidationContainer) { | 119 } else if (object == context.paintInvalidationContainer) { |
| 92 result = LayoutRect(rect); | 120 result = LayoutRect(rect); |
| 93 } else { | 121 } else { |
| 94 // For non-root SVG, the input rect is in local SVG coordinates in which | 122 // For non-root SVG, the input rect is in local SVG coordinates in which |
| 95 // paint offset doesn't apply. | 123 // paint offset doesn't apply. |
| 96 if (!isSVGChild) { | 124 if (!isSVGChild) { |
| 97 rect.moveBy(FloatPoint(object.paintOffset())); | 125 rect.moveBy(object.paintOffset()); |
| 98 // Use enclosingIntRect to ensure the final visual rect will cover the | 126 // Use enclosingIntRect to ensure the final visual rect will cover the |
| 99 // rect in source coordinates no matter if the painting will use pixel | 127 // rect in source coordinates no matter if the painting will use pixel |
| 100 // snapping. | 128 // snapping. |
| 101 rect = enclosingIntRect(rect); | 129 rect = LayoutRect(enclosingIntRect(rect)); |
| 102 } | 130 } |
| 103 | 131 |
| 104 const auto* containerContentsProperties = | 132 result = mapLocalRectToPaintInvalidationContainerUsingPaintProperties( |
| 105 context.paintInvalidationContainer->paintProperties() | 133 geometryMapper, rect, context); |
| 106 ->contentsProperties(); | |
| 107 if (context.treeBuilderContext.current.transform == | |
| 108 containerContentsProperties->transform() && | |
| 109 context.treeBuilderContext.current.clip == | |
| 110 containerContentsProperties->clip()) { | |
| 111 result = LayoutRect(rect); | |
| 112 } else { | |
| 113 PropertyTreeState currentTreeState( | |
| 114 context.treeBuilderContext.current.transform, | |
| 115 context.treeBuilderContext.current.clip, nullptr, nullptr); | |
| 116 result = LayoutRect(geometryMapper.sourceToDestinationVisualRect( | |
| 117 rect, currentTreeState, *containerContentsProperties)); | |
| 118 } | |
| 119 | |
| 120 // Convert the result to the container's contents space. | |
| 121 result.moveBy(-context.paintInvalidationContainer->paintOffset()); | |
| 122 } | 134 } |
| 123 | 135 |
| 124 object.adjustVisualRectForRasterEffects(result); | 136 object.adjustVisualRectForRasterEffects(result); |
| 137 | |
| 138 PaintLayer::mapRectInPaintInvalidationContainerToBacking( | |
| 139 *context.paintInvalidationContainer, result); | |
| 140 return result; | |
| 141 } | |
| 142 | |
| 143 // TODO(wangxianzhu): Combine this into | |
| 144 // PaintInvalidator::mapLocalRectToBacking() when removing | |
| 145 // PaintInvalidationState. | |
| 146 static LayoutRect mapSVGLocalRectToPaintInvalidationBacking( | |
|
pdr.
2017/01/18 02:31:19
I like the perf benefit here, but I don't like how
Xianzhu
2017/01/18 06:23:02
Good idea. Done.
| |
| 147 GeometryMapper& geometryMapper, | |
| 148 const LayoutObject& object, | |
| 149 const FloatRect& localRect, | |
| 150 const PaintInvalidatorContext& context) { | |
| 151 DCHECK(object.isSVGChild()); | |
| 152 | |
| 153 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | |
| 154 // In SPv2, visual rects are in the space of their local transform node. | |
| 155 // Use enclosingIntRect to ensure the final visual rect will cover the | |
| 156 // rect in source coordinates no matter if the painting will use pixel | |
| 157 // snapping. | |
| 158 return LayoutRect(enclosingIntRect(localRect)); | |
| 159 } | |
| 160 | |
| 161 LayoutRect result; | |
| 162 if (context.forcedSubtreeInvalidationFlags & | |
| 163 PaintInvalidatorContext::ForcedSubtreeSlowPathRect) { | |
| 164 SVGLayoutSupport::mapToVisualRectInAncestorSpace( | |
| 165 object, context.paintInvalidationContainer, localRect, result); | |
| 166 } else if (object == context.paintInvalidationContainer) { | |
| 167 result = LayoutRect(localRect); | |
| 168 } else { | |
| 169 result = mapLocalRectToPaintInvalidationContainerUsingPaintProperties( | |
| 170 geometryMapper, localRect, context); | |
| 171 } | |
| 172 | |
| 173 object.adjustVisualRectForRasterEffects(result); | |
| 125 | 174 |
| 126 PaintLayer::mapRectInPaintInvalidationContainerToBacking( | 175 PaintLayer::mapRectInPaintInvalidationContainerToBacking( |
| 127 *context.paintInvalidationContainer, result); | 176 *context.paintInvalidationContainer, result); |
| 128 | 177 |
| 129 return result; | 178 return result; |
| 130 } | 179 } |
| 131 | 180 |
| 132 void PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking( | 181 void PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking( |
| 133 const LayoutObject& object, | 182 const LayoutObject& object, |
| 134 LayoutRect& rect) const { | 183 LayoutRect& rect) const { |
| 135 GeometryMapper geometryMapper; | 184 GeometryMapper geometryMapper; |
| 136 rect = blink::mapLocalRectToPaintInvalidationBacking(geometryMapper, object, | 185 rect = blink::mapLocalRectToPaintInvalidationBacking(geometryMapper, object, |
| 137 FloatRect(rect), *this); | 186 rect, *this); |
| 138 } | |
| 139 | |
| 140 LayoutRect PaintInvalidator::mapLocalRectToPaintInvalidationBacking( | |
| 141 const LayoutObject& object, | |
| 142 const FloatRect& localRect, | |
| 143 const PaintInvalidatorContext& context) { | |
| 144 return blink::mapLocalRectToPaintInvalidationBacking(m_geometryMapper, object, | |
| 145 localRect, context); | |
| 146 } | 187 } |
| 147 | 188 |
| 148 LayoutRect PaintInvalidator::computeVisualRectInBacking( | 189 LayoutRect PaintInvalidator::computeVisualRectInBacking( |
| 149 const LayoutObject& object, | 190 const LayoutObject& object, |
| 150 const PaintInvalidatorContext& context) { | 191 const PaintInvalidatorContext& context) { |
| 151 FloatRect localRect; | 192 if (object.isSVGChild()) { |
| 152 if (object.isSVGChild()) | 193 return mapSVGLocalRectToPaintInvalidationBacking( |
| 153 localRect = SVGLayoutSupport::localVisualRect(object); | 194 m_geometryMapper, object, SVGLayoutSupport::localVisualRect(object), |
| 154 else | 195 context); |
| 155 localRect = FloatRect(object.localVisualRect()); | 196 } |
| 156 | 197 return mapLocalRectToPaintInvalidationBacking( |
| 157 return mapLocalRectToPaintInvalidationBacking(object, localRect, context); | 198 m_geometryMapper, object, object.localVisualRect(), context); |
| 158 } | 199 } |
| 159 | 200 |
| 160 LayoutPoint PaintInvalidator::computeLocationInBacking( | 201 LayoutPoint PaintInvalidator::computeLocationInBacking( |
| 161 const LayoutObject& object, | 202 const LayoutObject& object, |
| 162 const PaintInvalidatorContext& context) { | 203 const PaintInvalidatorContext& context) { |
| 163 // Use visual rect location for LayoutTexts because it suffices to check | 204 // Use visual rect location for LayoutTexts because it suffices to check |
| 164 // visual rect change for layout caused invalidation. | 205 // visual rect change for layout caused invalidation. |
| 165 if (object.isText()) | 206 if (object.isText()) |
| 166 return context.newVisualRect.location(); | 207 return context.newVisualRect.location(); |
| 167 | 208 |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; | 493 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; |
| 453 } | 494 } |
| 454 | 495 |
| 455 void PaintInvalidator::processPendingDelayedPaintInvalidations() { | 496 void PaintInvalidator::processPendingDelayedPaintInvalidations() { |
| 456 for (auto target : m_pendingDelayedPaintInvalidations) | 497 for (auto target : m_pendingDelayedPaintInvalidations) |
| 457 target->getMutableForPainting().setShouldDoFullPaintInvalidation( | 498 target->getMutableForPainting().setShouldDoFullPaintInvalidation( |
| 458 PaintInvalidationDelayedFull); | 499 PaintInvalidationDelayedFull); |
| 459 } | 500 } |
| 460 | 501 |
| 461 } // namespace blink | 502 } // namespace blink |
| OLD | NEW |