| 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 "platform/graphics/paint/GeometryMapper.h" | 5 #include "platform/graphics/paint/GeometryMapper.h" |
| 6 | 6 |
| 7 #include "platform/RuntimeEnabledFeatures.h" | 7 #include "platform/RuntimeEnabledFeatures.h" |
| 8 #include "platform/geometry/LayoutRect.h" | 8 #include "platform/geometry/LayoutRect.h" |
| 9 | 9 |
| 10 namespace blink { | 10 namespace blink { |
| 11 | 11 |
| 12 FloatRect GeometryMapper::sourceToDestinationVisualRect( | 12 FloatClipRect GeometryMapper::sourceToDestinationVisualRect( |
| 13 const FloatRect& rect, | 13 const FloatRect& rect, |
| 14 const PropertyTreeState& sourceState, | 14 const PropertyTreeState& sourceState, |
| 15 const PropertyTreeState& destinationState) { | 15 const PropertyTreeState& destinationState) { |
| 16 bool success = false; | 16 bool success = false; |
| 17 FloatRect result = sourceToDestinationVisualRectInternal( | 17 FloatClipRect result = sourceToDestinationVisualRectInternal( |
| 18 rect, sourceState, destinationState, success); | 18 rect, sourceState, destinationState, success); |
| 19 DCHECK(success); | 19 DCHECK(success); |
| 20 return result; | 20 return result; |
| 21 } | 21 } |
| 22 | 22 |
| 23 FloatRect GeometryMapper::sourceToDestinationVisualRectInternal( | 23 FloatClipRect GeometryMapper::sourceToDestinationVisualRectInternal( |
| 24 const FloatRect& rect, | 24 const FloatRect& rect, |
| 25 const PropertyTreeState& sourceState, | 25 const PropertyTreeState& sourceState, |
| 26 const PropertyTreeState& destinationState, | 26 const PropertyTreeState& destinationState, |
| 27 bool& success) { | 27 bool& success) { |
| 28 FloatRect result = localToAncestorVisualRectInternal( | 28 FloatClipRect result = localToAncestorVisualRectInternal( |
| 29 rect, sourceState, destinationState, success); | 29 rect, sourceState, destinationState, success); |
| 30 // Success if destinationState is an ancestor state. | 30 // Success if destinationState is an ancestor state. |
| 31 if (success) | 31 if (success) |
| 32 return result; | 32 return result; |
| 33 | 33 |
| 34 // Otherwise first map to the lowest common ancestor, then map to destination. | 34 // Otherwise first map to the lowest common ancestor, then map to destination. |
| 35 const TransformPaintPropertyNode* lcaTransform = lowestCommonAncestor( | 35 const TransformPaintPropertyNode* lcaTransform = lowestCommonAncestor( |
| 36 sourceState.transform(), destinationState.transform()); | 36 sourceState.transform(), destinationState.transform()); |
| 37 DCHECK(lcaTransform); | 37 DCHECK(lcaTransform); |
| 38 | 38 |
| 39 // Assume that the clip of destinationState is an ancestor of the clip of | 39 // Assume that the clip of destinationState is an ancestor of the clip of |
| 40 // sourceState and is under the space of lcaTransform. Otherwise | 40 // sourceState and is under the space of lcaTransform. Otherwise |
| 41 // localToAncestorVisualRect() will fail. | 41 // localToAncestorVisualRect() will fail. |
| 42 PropertyTreeState lcaState = destinationState; | 42 PropertyTreeState lcaState = destinationState; |
| 43 lcaState.setTransform(lcaTransform); | 43 lcaState.setTransform(lcaTransform); |
| 44 | 44 |
| 45 FloatRect lcaVisualRect = | 45 result = |
| 46 localToAncestorVisualRectInternal(rect, sourceState, lcaState, success); | 46 localToAncestorVisualRectInternal(rect, sourceState, lcaState, success); |
| 47 if (!success) | 47 if (!success) |
| 48 return lcaVisualRect; | 48 return result; |
| 49 return ancestorToLocalRect(lcaVisualRect, lcaTransform, | 49 FloatRect final = ancestorToLocalRect(result.rect(), lcaTransform, |
| 50 destinationState.transform()); | 50 destinationState.transform()); |
| 51 result.setRect(final); |
| 52 return result; |
| 51 } | 53 } |
| 52 | 54 |
| 53 FloatRect GeometryMapper::sourceToDestinationRect( | 55 FloatRect GeometryMapper::sourceToDestinationRect( |
| 54 const FloatRect& rect, | 56 const FloatRect& rect, |
| 55 const TransformPaintPropertyNode* sourceTransformNode, | 57 const TransformPaintPropertyNode* sourceTransformNode, |
| 56 const TransformPaintPropertyNode* destinationTransformNode) { | 58 const TransformPaintPropertyNode* destinationTransformNode) { |
| 57 bool success = false; | 59 bool success = false; |
| 58 FloatRect result = localToAncestorRectInternal( | 60 FloatRect result = localToAncestorRectInternal( |
| 59 rect, sourceTransformNode, destinationTransformNode, success); | 61 rect, sourceTransformNode, destinationTransformNode, success); |
| 60 // Success if destinationTransformNode is an ancestor of sourceTransformNode. | 62 // Success if destinationTransformNode is an ancestor of sourceTransformNode. |
| 61 if (success) | 63 if (success) |
| 62 return result; | 64 return result; |
| 63 | 65 |
| 64 // Otherwise first map to the least common ancestor, then map to destination. | 66 // Otherwise first map to the least common ancestor, then map to destination. |
| 65 const TransformPaintPropertyNode* lcaTransform = | 67 const TransformPaintPropertyNode* lcaTransform = |
| 66 lowestCommonAncestor(sourceTransformNode, destinationTransformNode); | 68 lowestCommonAncestor(sourceTransformNode, destinationTransformNode); |
| 67 DCHECK(lcaTransform); | 69 DCHECK(lcaTransform); |
| 68 | 70 |
| 69 FloatRect lcaRect = | 71 FloatRect lcaRect = |
| 70 localToAncestorRect(rect, sourceTransformNode, lcaTransform); | 72 localToAncestorRect(rect, sourceTransformNode, lcaTransform); |
| 71 return ancestorToLocalRect(lcaRect, lcaTransform, destinationTransformNode); | 73 return ancestorToLocalRect(lcaRect, lcaTransform, destinationTransformNode); |
| 72 } | 74 } |
| 73 | 75 |
| 74 FloatRect GeometryMapper::localToAncestorVisualRect( | 76 FloatClipRect GeometryMapper::localToAncestorVisualRect( |
| 75 const FloatRect& rect, | 77 const FloatRect& rect, |
| 76 const PropertyTreeState& localState, | 78 const PropertyTreeState& localState, |
| 77 const PropertyTreeState& ancestorState) { | 79 const PropertyTreeState& ancestorState) { |
| 78 bool success = false; | 80 bool success = false; |
| 79 FloatRect result = localToAncestorVisualRectInternal(rect, localState, | 81 FloatClipRect result = localToAncestorVisualRectInternal( |
| 80 ancestorState, success); | 82 rect, localState, ancestorState, success); |
| 81 DCHECK(success); | 83 DCHECK(success); |
| 82 return result; | 84 return result; |
| 83 } | 85 } |
| 84 | 86 |
| 85 FloatRect GeometryMapper::localToAncestorVisualRectInternal( | 87 FloatClipRect GeometryMapper::localToAncestorVisualRectInternal( |
| 86 const FloatRect& rect, | 88 const FloatRect& rect, |
| 87 const PropertyTreeState& localState, | 89 const PropertyTreeState& localState, |
| 88 const PropertyTreeState& ancestorState, | 90 const PropertyTreeState& ancestorState, |
| 89 bool& success) { | 91 bool& success) { |
| 90 if (localState == ancestorState) { | 92 if (localState == ancestorState) { |
| 91 success = true; | 93 success = true; |
| 92 return rect; | 94 return rect; |
| 93 } | 95 } |
| 94 | 96 |
| 95 const auto& transformMatrix = localToAncestorMatrixInternal( | 97 const auto& transformMatrix = localToAncestorMatrixInternal( |
| 96 localState.transform(), ancestorState.transform(), success); | 98 localState.transform(), ancestorState.transform(), success); |
| 97 if (!success) | 99 if (!success) |
| 98 return rect; | 100 return rect; |
| 99 | 101 |
| 100 FloatRect mappedRect = transformMatrix.mapRect(rect); | 102 FloatRect mappedRect = transformMatrix.mapRect(rect); |
| 101 | 103 |
| 102 const auto clipRect = | 104 FloatClipRect clipRect = |
| 103 localToAncestorClipRectInternal(localState, ancestorState, success); | 105 localToAncestorClipRectInternal(localState, ancestorState, success); |
| 104 | 106 |
| 105 if (success) { | 107 if (success) { |
| 106 mappedRect.intersect(clipRect); | 108 clipRect.intersect(mappedRect); |
| 107 } else if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 109 } else if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 108 // On SPv1 we may fail when the paint invalidation container creates an | 110 // On SPv1 we may fail when the paint invalidation container creates an |
| 109 // overflow clip (in ancestorState) which is not in localState of an | 111 // overflow clip (in ancestorState) which is not in localState of an |
| 110 // out-of-flow positioned descendant. See crbug.com/513108 and layout test | 112 // out-of-flow positioned descendant. See crbug.com/513108 and layout test |
| 111 // compositing/overflow/handle-non-ancestor-clip-parent.html (run with | 113 // compositing/overflow/handle-non-ancestor-clip-parent.html (run with |
| 112 // --enable-prefer-compositing-to-lcd-text) for details. | 114 // --enable-prefer-compositing-to-lcd-text) for details. |
| 113 // Ignore it for SPv1 for now. | 115 // Ignore it for SPv1 for now. |
| 114 success = true; | 116 success = true; |
| 115 } | 117 } |
| 116 | 118 |
| 117 return mappedRect; | 119 return clipRect; |
| 118 } | 120 } |
| 119 | 121 |
| 120 FloatRect GeometryMapper::localToAncestorRect( | 122 FloatRect GeometryMapper::localToAncestorRect( |
| 121 const FloatRect& rect, | 123 const FloatRect& rect, |
| 122 const TransformPaintPropertyNode* localTransformNode, | 124 const TransformPaintPropertyNode* localTransformNode, |
| 123 const TransformPaintPropertyNode* ancestorTransformNode) { | 125 const TransformPaintPropertyNode* ancestorTransformNode) { |
| 124 bool success = false; | 126 bool success = false; |
| 125 FloatRect result = localToAncestorRectInternal( | 127 FloatRect result = localToAncestorRectInternal( |
| 126 rect, localTransformNode, ancestorTransformNode, success); | 128 rect, localTransformNode, ancestorTransformNode, success); |
| 127 DCHECK(success); | 129 DCHECK(success); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 const ClipPaintPropertyNode* clip) { | 180 const ClipPaintPropertyNode* clip) { |
| 179 PrecomputedDataForAncestor& precomputedData = | 181 PrecomputedDataForAncestor& precomputedData = |
| 180 getPrecomputedDataForAncestor(transform); | 182 getPrecomputedDataForAncestor(transform); |
| 181 | 183 |
| 182 auto addResult = precomputedData.precomputedClips.insert(clip, nullptr); | 184 auto addResult = precomputedData.precomputedClips.insert(clip, nullptr); |
| 183 if (addResult.isNewEntry) | 185 if (addResult.isNewEntry) |
| 184 addResult.storedValue->value = WTF::makeUnique<ClipCache>(); | 186 addResult.storedValue->value = WTF::makeUnique<ClipCache>(); |
| 185 return *addResult.storedValue->value; | 187 return *addResult.storedValue->value; |
| 186 } | 188 } |
| 187 | 189 |
| 188 FloatRect GeometryMapper::localToAncestorClipRect( | 190 FloatClipRect GeometryMapper::localToAncestorClipRect( |
| 189 const PropertyTreeState& localState, | 191 const PropertyTreeState& localState, |
| 190 const PropertyTreeState& ancestorState) { | 192 const PropertyTreeState& ancestorState) { |
| 191 bool success = false; | 193 bool success = false; |
| 192 FloatRect result = | 194 FloatClipRect result = |
| 193 localToAncestorClipRectInternal(localState, ancestorState, success); | 195 localToAncestorClipRectInternal(localState, ancestorState, success); |
| 194 DCHECK(success); | 196 DCHECK(success); |
| 195 return result; | 197 return result; |
| 196 } | 198 } |
| 197 | 199 |
| 198 FloatRect GeometryMapper::localToAncestorClipRectInternal( | 200 FloatClipRect GeometryMapper::localToAncestorClipRectInternal( |
| 199 const PropertyTreeState& localState, | 201 const PropertyTreeState& localState, |
| 200 const PropertyTreeState& ancestorState, | 202 const PropertyTreeState& ancestorState, |
| 201 bool& success) { | 203 bool& success) { |
| 202 FloatRect clip(LayoutRect::infiniteIntRect()); | 204 FloatClipRect clip(LayoutRect::infiniteIntRect()); |
| 203 if (localState.clip() == ancestorState.clip()) { | 205 if (localState.clip() == ancestorState.clip()) { |
| 204 success = true; | 206 success = true; |
| 205 return clip; | 207 return clip; |
| 206 } | 208 } |
| 207 | 209 |
| 208 ClipCache& clipCache = | 210 ClipCache& clipCache = |
| 209 getClipCache(ancestorState.transform(), ancestorState.clip()); | 211 getClipCache(ancestorState.transform(), ancestorState.clip()); |
| 210 const ClipPaintPropertyNode* clipNode = localState.clip(); | 212 const ClipPaintPropertyNode* clipNode = localState.clip(); |
| 211 Vector<const ClipPaintPropertyNode*> intermediateNodes; | 213 Vector<const ClipPaintPropertyNode*> intermediateNodes; |
| 212 | 214 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 230 // computing and memoizing clip rects as we go. | 232 // computing and memoizing clip rects as we go. |
| 231 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); | 233 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); |
| 232 ++it) { | 234 ++it) { |
| 233 success = false; | 235 success = false; |
| 234 const TransformationMatrix& transformMatrix = localToAncestorMatrixInternal( | 236 const TransformationMatrix& transformMatrix = localToAncestorMatrixInternal( |
| 235 (*it)->localTransformSpace(), ancestorState.transform(), success); | 237 (*it)->localTransformSpace(), ancestorState.transform(), success); |
| 236 if (!success) | 238 if (!success) |
| 237 return clip; | 239 return clip; |
| 238 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect()); | 240 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect()); |
| 239 clip.intersect(mappedRect); | 241 clip.intersect(mappedRect); |
| 242 if ((*it)->clipRect().isRounded()) |
| 243 clip.setHasRadius(true); |
| 240 clipCache.set(*it, clip); | 244 clipCache.set(*it, clip); |
| 241 } | 245 } |
| 242 | 246 |
| 243 success = true; | 247 success = true; |
| 244 return clipCache.find(localState.clip())->value; | 248 return clipCache.find(localState.clip())->value; |
| 245 } | 249 } |
| 246 | 250 |
| 247 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( | 251 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( |
| 248 const TransformPaintPropertyNode* localTransformNode, | 252 const TransformPaintPropertyNode* localTransformNode, |
| 249 const TransformPaintPropertyNode* ancestorTransformNode) { | 253 const TransformPaintPropertyNode* ancestorTransformNode) { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 const TransformPaintPropertyNode*, | 358 const TransformPaintPropertyNode*, |
| 355 const TransformPaintPropertyNode*); | 359 const TransformPaintPropertyNode*); |
| 356 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor( | 360 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor( |
| 357 const ClipPaintPropertyNode*, | 361 const ClipPaintPropertyNode*, |
| 358 const ClipPaintPropertyNode*); | 362 const ClipPaintPropertyNode*); |
| 359 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor( | 363 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor( |
| 360 const ScrollPaintPropertyNode*, | 364 const ScrollPaintPropertyNode*, |
| 361 const ScrollPaintPropertyNode*); | 365 const ScrollPaintPropertyNode*); |
| 362 | 366 |
| 363 } // namespace blink | 367 } // namespace blink |
| OLD | NEW |