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 "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 const TransformationMatrix& GeometryMapper::identityMatrix() { | 12 const TransformationMatrix& GeometryMapper::identityMatrix() { |
| 13 DEFINE_STATIC_LOCAL(TransformationMatrix, identity, (TransformationMatrix())); | 13 DEFINE_STATIC_LOCAL(TransformationMatrix, identity, (TransformationMatrix())); |
| 14 return identity; | 14 return identity; |
| 15 } | 15 } |
| 16 | 16 |
| 17 const FloatClipRect& GeometryMapper::infiniteClip() { | 17 const FloatClipRect& GeometryMapper::infiniteClip() { |
| 18 DEFINE_STATIC_LOCAL(FloatClipRect, infinite, (FloatClipRect())); | 18 DEFINE_STATIC_LOCAL(FloatClipRect, infinite, (FloatClipRect())); |
| 19 return infinite; | 19 return infinite; |
| 20 } | 20 } |
| 21 | 21 |
| 22 FloatClipRect& GeometryMapper::tempRect() { | 22 FloatClipRect& GeometryMapper::tempRect() { |
| 23 DEFINE_STATIC_LOCAL(FloatClipRect, temp, (FloatClipRect())); | 23 DEFINE_STATIC_LOCAL(FloatClipRect, temp, (FloatClipRect())); |
| 24 return temp; | 24 return temp; |
| 25 } | 25 } |
| 26 | 26 |
| 27 void GeometryMapper::sourceToDestinationVisualRect( | 27 void GeometryMapper::sourceToDestinationVisualRect( |
| 28 const PropertyTreeState& sourceState, | 28 const PropertyTreeState& sourceState, |
| 29 const PropertyTreeState& destinationState, | 29 const PropertyTreeState& destinationState, |
| 30 FloatRect& rect) { | 30 FloatClipRect& rect) { |
| 31 bool success = false; | 31 bool success = false; |
| 32 sourceToDestinationVisualRectInternal(sourceState, destinationState, rect, | 32 sourceToDestinationVisualRectInternal(sourceState, destinationState, rect, |
| 33 success); | 33 success); |
| 34 DCHECK(success); | 34 DCHECK(success); |
| 35 } | 35 } |
| 36 | 36 |
| 37 void GeometryMapper::sourceToDestinationVisualRectInternal( | 37 void GeometryMapper::sourceToDestinationVisualRectInternal( |
| 38 const PropertyTreeState& sourceState, | 38 const PropertyTreeState& sourceState, |
| 39 const PropertyTreeState& destinationState, | 39 const PropertyTreeState& destinationState, |
| 40 FloatRect& mappingRect, | 40 FloatClipRect& mappingRect, |
| 41 bool& success) { | 41 bool& success) { |
| 42 localToAncestorVisualRectInternal(sourceState, destinationState, mappingRect, | 42 localToAncestorVisualRectInternal(sourceState, destinationState, mappingRect, |
| 43 success); | 43 success); |
| 44 // Success if destinationState is an ancestor state. | 44 // Success if destinationState is an ancestor state. |
| 45 if (success) | 45 if (success) |
| 46 return; | 46 return; |
| 47 | 47 |
| 48 // Otherwise first map to the lowest common ancestor, then map to destination. | 48 // Otherwise first map to the lowest common ancestor, then map to destination. |
| 49 const TransformPaintPropertyNode* lcaTransform = lowestCommonAncestor( | 49 const TransformPaintPropertyNode* lcaTransform = lowestCommonAncestor( |
| 50 sourceState.transform(), destinationState.transform()); | 50 sourceState.transform(), destinationState.transform()); |
| 51 DCHECK(lcaTransform); | 51 DCHECK(lcaTransform); |
| 52 | 52 |
| 53 // Assume that the clip of destinationState is an ancestor of the clip of | 53 // Assume that the clip of destinationState is an ancestor of the clip of |
| 54 // sourceState and is under the space of lcaTransform. Otherwise | 54 // sourceState and is under the space of lcaTransform. Otherwise |
| 55 // localToAncestorVisualRect() will fail. | 55 // localToAncestorVisualRect() will fail. |
| 56 PropertyTreeState lcaState = destinationState; | 56 PropertyTreeState lcaState = destinationState; |
| 57 lcaState.setTransform(lcaTransform); | 57 lcaState.setTransform(lcaTransform); |
| 58 | 58 |
| 59 localToAncestorVisualRectInternal(sourceState, lcaState, mappingRect, | 59 localToAncestorVisualRectInternal(sourceState, lcaState, mappingRect, |
| 60 success); | 60 success); |
| 61 if (!success) | 61 if (!success) |
| 62 return; | 62 return; |
| 63 | 63 |
| 64 ancestorToLocalRect(lcaTransform, destinationState.transform(), mappingRect); | 64 ancestorToLocalRect(lcaTransform, destinationState.transform(), |
| 65 mappingRect.rect()); | |
| 65 } | 66 } |
| 66 | 67 |
| 67 void GeometryMapper::sourceToDestinationRect( | 68 void GeometryMapper::sourceToDestinationRect( |
| 68 const TransformPaintPropertyNode* sourceTransformNode, | 69 const TransformPaintPropertyNode* sourceTransformNode, |
| 69 const TransformPaintPropertyNode* destinationTransformNode, | 70 const TransformPaintPropertyNode* destinationTransformNode, |
| 70 FloatRect& mappingRect) { | 71 FloatRect& mappingRect) { |
| 71 bool success = false; | 72 bool success = false; |
| 72 localToAncestorRectInternal(sourceTransformNode, destinationTransformNode, | 73 localToAncestorRectInternal(sourceTransformNode, destinationTransformNode, |
| 73 mappingRect, success); | 74 mappingRect, success); |
| 74 // Success if destinationTransformNode is an ancestor of sourceTransformNode. | 75 // Success if destinationTransformNode is an ancestor of sourceTransformNode. |
| 75 if (success) | 76 if (success) |
| 76 return; | 77 return; |
| 77 | 78 |
| 78 // Otherwise first map to the least common ancestor, then map to destination. | 79 // Otherwise first map to the least common ancestor, then map to destination. |
| 79 const TransformPaintPropertyNode* lcaTransform = | 80 const TransformPaintPropertyNode* lcaTransform = |
| 80 lowestCommonAncestor(sourceTransformNode, destinationTransformNode); | 81 lowestCommonAncestor(sourceTransformNode, destinationTransformNode); |
| 81 DCHECK(lcaTransform); | 82 DCHECK(lcaTransform); |
| 82 | 83 |
| 83 localToAncestorRect(sourceTransformNode, lcaTransform, mappingRect); | 84 localToAncestorRect(sourceTransformNode, lcaTransform, mappingRect); |
| 84 ancestorToLocalRect(lcaTransform, destinationTransformNode, mappingRect); | 85 ancestorToLocalRect(lcaTransform, destinationTransformNode, mappingRect); |
| 85 } | 86 } |
| 86 | 87 |
| 87 void GeometryMapper::localToAncestorVisualRect( | 88 void GeometryMapper::localToAncestorVisualRect( |
| 88 const PropertyTreeState& localState, | 89 const PropertyTreeState& localState, |
| 89 const PropertyTreeState& ancestorState, | 90 const PropertyTreeState& ancestorState, |
| 90 FloatRect& mappingRect) { | 91 FloatClipRect& mappingRect) { |
| 91 bool success = false; | 92 bool success = false; |
| 92 localToAncestorVisualRectInternal(localState, ancestorState, mappingRect, | 93 localToAncestorVisualRectInternal(localState, ancestorState, mappingRect, |
| 93 success); | 94 success); |
| 94 DCHECK(success); | 95 DCHECK(success); |
| 95 } | 96 } |
| 96 | 97 |
| 97 void GeometryMapper::localToAncestorVisualRectInternal( | 98 void GeometryMapper::localToAncestorVisualRectInternal( |
| 98 const PropertyTreeState& localState, | 99 const PropertyTreeState& localState, |
| 99 const PropertyTreeState& ancestorState, | 100 const PropertyTreeState& ancestorState, |
| 100 FloatRect& rectToMap, | 101 FloatClipRect& rectToMap, |
| 101 bool& success) { | 102 bool& success) { |
| 102 if (localState == ancestorState) { | 103 if (localState == ancestorState) { |
| 103 success = true; | 104 success = true; |
| 104 return; | 105 return; |
| 105 } | 106 } |
| 106 | 107 |
| 107 if (localState.effect() != ancestorState.effect()) { | 108 if (localState.effect() != ancestorState.effect()) { |
| 108 slowLocalToAncestorVisualRectWithEffects(localState, ancestorState, | 109 slowLocalToAncestorVisualRectWithEffects(localState, ancestorState, |
| 109 rectToMap, success); | 110 rectToMap, success); |
| 110 return; | 111 return; |
| 111 } | 112 } |
| 112 | 113 |
| 113 const auto& transformMatrix = localToAncestorMatrixInternal( | 114 const auto& transformMatrix = localToAncestorMatrixInternal( |
| 114 localState.transform(), ancestorState.transform(), success); | 115 localState.transform(), ancestorState.transform(), success); |
| 115 if (!success) { | 116 if (!success) { |
| 116 return; | 117 return; |
| 117 } | 118 } |
| 118 | 119 |
| 119 FloatRect mappedRect = transformMatrix.mapRect(rectToMap); | 120 FloatRect mappedRect = transformMatrix.mapRect(rectToMap.rect()); |
| 120 | 121 |
| 121 const FloatClipRect& clipRect = | 122 FloatClipRect clipRect = |
| 122 localToAncestorClipRectInternal(localState.clip(), ancestorState.clip(), | 123 localToAncestorClipRectInternal(localState.clip(), ancestorState.clip(), |
| 123 ancestorState.transform(), success); | 124 ancestorState.transform(), success); |
| 124 | 125 |
| 125 if (success) { | 126 if (success) { |
| 126 rectToMap = clipRect.rect(); | 127 rectToMap = clipRect; |
|
wkorman
2017/04/05 20:06:47
It looks like (but please confirm) this is the cri
chrishtr
2017/04/05 20:22:15
Done.
| |
| 127 rectToMap.intersect(mappedRect); | 128 rectToMap.intersect(mappedRect); |
| 128 } else if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 129 } else if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 129 // On SPv1 we may fail when the paint invalidation container creates an | 130 // On SPv1 we may fail when the paint invalidation container creates an |
| 130 // overflow clip (in ancestorState) which is not in localState of an | 131 // overflow clip (in ancestorState) which is not in localState of an |
| 131 // out-of-flow positioned descendant. See crbug.com/513108 and layout test | 132 // out-of-flow positioned descendant. See crbug.com/513108 and layout test |
| 132 // compositing/overflow/handle-non-ancestor-clip-parent.html (run with | 133 // compositing/overflow/handle-non-ancestor-clip-parent.html (run with |
| 133 // --enable-prefer-compositing-to-lcd-text) for details. | 134 // --enable-prefer-compositing-to-lcd-text) for details. |
| 134 // Ignore it for SPv1 for now. | 135 // Ignore it for SPv1 for now. |
| 135 success = true; | 136 success = true; |
| 136 } | 137 } |
| 137 } | 138 } |
| 138 | 139 |
| 139 void GeometryMapper::slowLocalToAncestorVisualRectWithEffects( | 140 void GeometryMapper::slowLocalToAncestorVisualRectWithEffects( |
| 140 const PropertyTreeState& localState, | 141 const PropertyTreeState& localState, |
| 141 const PropertyTreeState& ancestorState, | 142 const PropertyTreeState& ancestorState, |
| 142 FloatRect& mappingRect, | 143 FloatClipRect& mappingRect, |
| 143 bool& success) { | 144 bool& success) { |
| 144 PropertyTreeState lastTransformAndClipState(localState.transform(), | 145 PropertyTreeState lastTransformAndClipState(localState.transform(), |
| 145 localState.clip(), nullptr); | 146 localState.clip(), nullptr); |
| 146 | 147 |
| 147 for (const auto* effect = localState.effect(); | 148 for (const auto* effect = localState.effect(); |
| 148 effect && effect != ancestorState.effect(); effect = effect->parent()) { | 149 effect && effect != ancestorState.effect(); effect = effect->parent()) { |
| 149 if (!effect->hasFilterThatMovesPixels()) | 150 if (!effect->hasFilterThatMovesPixels()) |
| 150 continue; | 151 continue; |
| 151 | 152 |
| 152 PropertyTreeState transformAndClipState(effect->localTransformSpace(), | 153 PropertyTreeState transformAndClipState(effect->localTransformSpace(), |
| 153 effect->outputClip(), nullptr); | 154 effect->outputClip(), nullptr); |
| 154 sourceToDestinationVisualRectInternal( | 155 sourceToDestinationVisualRectInternal( |
| 155 lastTransformAndClipState, transformAndClipState, mappingRect, success); | 156 lastTransformAndClipState, transformAndClipState, mappingRect, success); |
| 156 if (!success) | 157 if (!success) |
| 157 return; | 158 return; |
| 158 | 159 |
| 159 mappingRect = effect->mapRect(mappingRect); | 160 mappingRect.setRect(effect->mapRect(mappingRect.rect())); |
| 160 lastTransformAndClipState = transformAndClipState; | 161 lastTransformAndClipState = transformAndClipState; |
| 161 } | 162 } |
| 162 | 163 |
| 163 PropertyTreeState finalTransformAndClipState(ancestorState.transform(), | 164 PropertyTreeState finalTransformAndClipState(ancestorState.transform(), |
| 164 ancestorState.clip(), nullptr); | 165 ancestorState.clip(), nullptr); |
| 165 sourceToDestinationVisualRectInternal(lastTransformAndClipState, | 166 sourceToDestinationVisualRectInternal(lastTransformAndClipState, |
| 166 finalTransformAndClipState, mappingRect, | 167 finalTransformAndClipState, mappingRect, |
| 167 success); | 168 success); |
| 168 } | 169 } |
| 169 | 170 |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 const TransformPaintPropertyNode*, | 466 const TransformPaintPropertyNode*, |
| 466 const TransformPaintPropertyNode*); | 467 const TransformPaintPropertyNode*); |
| 467 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor( | 468 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor( |
| 468 const ClipPaintPropertyNode*, | 469 const ClipPaintPropertyNode*, |
| 469 const ClipPaintPropertyNode*); | 470 const ClipPaintPropertyNode*); |
| 470 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor( | 471 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor( |
| 471 const ScrollPaintPropertyNode*, | 472 const ScrollPaintPropertyNode*, |
| 472 const ScrollPaintPropertyNode*); | 473 const ScrollPaintPropertyNode*); |
| 473 | 474 |
| 474 } // namespace blink | 475 } // namespace blink |
| OLD | NEW |