| 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/geometry/LayoutRect.h" | 7 #include "platform/geometry/LayoutRect.h" |
| 8 #include "platform/graphics/paint/ClipPaintPropertyNode.h" | |
| 9 #include "platform/graphics/paint/EffectPaintPropertyNode.h" | |
| 10 #include "platform/graphics/paint/TransformPaintPropertyNode.h" | |
| 11 | 8 |
| 12 namespace blink { | 9 namespace blink { |
| 13 | 10 |
| 14 FloatRect GeometryMapper::mapToVisualRectInDestinationSpace( | 11 FloatRect GeometryMapper::mapToVisualRectInDestinationSpace( |
| 15 const FloatRect& rect, | 12 const FloatRect& rect, |
| 16 const GeometryPropertyTreeState& sourceState, | 13 const PropertyTreeState& sourceState, |
| 17 const GeometryPropertyTreeState& destinationState, | 14 const PropertyTreeState& destinationState, |
| 18 bool& success) { | 15 bool& success) { |
| 19 FloatRect result = localToVisualRectInAncestorSpace( | 16 FloatRect result = localToVisualRectInAncestorSpace( |
| 20 rect, sourceState, destinationState, success); | 17 rect, sourceState, destinationState, success); |
| 21 if (success) | 18 if (success) |
| 22 return result; | 19 return result; |
| 23 return slowMapToVisualRectInDestinationSpace(rect, sourceState, | 20 return slowMapToVisualRectInDestinationSpace(rect, sourceState, |
| 24 destinationState, success); | 21 destinationState, success); |
| 25 } | 22 } |
| 26 | 23 |
| 27 FloatRect GeometryMapper::mapRectToDestinationSpace( | 24 FloatRect GeometryMapper::mapRectToDestinationSpace( |
| 28 const FloatRect& rect, | 25 const FloatRect& rect, |
| 29 const GeometryPropertyTreeState& sourceState, | 26 const PropertyTreeState& sourceState, |
| 30 const GeometryPropertyTreeState& destinationState, | 27 const PropertyTreeState& destinationState, |
| 31 bool& success) { | 28 bool& success) { |
| 32 FloatRect result = | 29 FloatRect result = |
| 33 localToAncestorRect(rect, sourceState, destinationState, success); | 30 localToAncestorRect(rect, sourceState, destinationState, success); |
| 34 if (success) | 31 if (success) |
| 35 return result; | 32 return result; |
| 36 return slowMapRectToDestinationSpace(rect, sourceState, destinationState, | 33 return slowMapRectToDestinationSpace(rect, sourceState, destinationState, |
| 37 success); | 34 success); |
| 38 } | 35 } |
| 39 | 36 |
| 40 FloatRect GeometryMapper::slowMapToVisualRectInDestinationSpace( | 37 FloatRect GeometryMapper::slowMapToVisualRectInDestinationSpace( |
| 41 const FloatRect& rect, | 38 const FloatRect& rect, |
| 42 const GeometryPropertyTreeState& sourceState, | 39 const PropertyTreeState& sourceState, |
| 43 const GeometryPropertyTreeState& destinationState, | 40 const PropertyTreeState& destinationState, |
| 44 bool& success) { | 41 bool& success) { |
| 45 const TransformPaintPropertyNode* lcaTransform = leastCommonAncestor( | 42 const TransformPaintPropertyNode* lcaTransform = leastCommonAncestor( |
| 46 sourceState.transform.get(), destinationState.transform.get()); | 43 sourceState.transform(), destinationState.transform()); |
| 47 DCHECK(lcaTransform); | 44 DCHECK(lcaTransform); |
| 48 | 45 |
| 49 // Assume that the clip of destinationState is an ancestor of the clip of sour
ceState | 46 // Assume that the clip of destinationState is an ancestor of the clip of sour
ceState |
| 50 // and is under the space of lcaTransform. Otherwise localToAncestorClipRect()
will fail. | 47 // and is under the space of lcaTransform. Otherwise localToAncestorClipRect()
will fail. |
| 51 GeometryPropertyTreeState lcaState = destinationState; | 48 PropertyTreeState lcaState = destinationState; |
| 52 lcaState.transform = lcaTransform; | 49 lcaState.setTransform(lcaTransform); |
| 53 | 50 |
| 54 const auto clipRect = localToAncestorClipRect(sourceState, lcaState, success); | 51 const auto clipRect = localToAncestorClipRect(sourceState, lcaState, success); |
| 55 if (!success) | 52 if (!success) |
| 56 return rect; | 53 return rect; |
| 57 | 54 |
| 58 FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success); | 55 FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success); |
| 59 DCHECK(success); | 56 DCHECK(success); |
| 60 result.intersect(clipRect); | 57 result.intersect(clipRect); |
| 61 | 58 |
| 62 const TransformationMatrix& destinationToLca = localToAncestorMatrix( | 59 const TransformationMatrix& destinationToLca = |
| 63 destinationState.transform.get(), lcaState, success); | 60 localToAncestorMatrix(destinationState.transform(), lcaState, success); |
| 64 DCHECK(success); | 61 DCHECK(success); |
| 65 if (destinationToLca.isInvertible()) { | 62 if (destinationToLca.isInvertible()) { |
| 66 success = true; | 63 success = true; |
| 67 return destinationToLca.inverse().mapRect(result); | 64 return destinationToLca.inverse().mapRect(result); |
| 68 } | 65 } |
| 69 success = false; | 66 success = false; |
| 70 return rect; | 67 return rect; |
| 71 } | 68 } |
| 72 | 69 |
| 73 FloatRect GeometryMapper::slowMapRectToDestinationSpace( | 70 FloatRect GeometryMapper::slowMapRectToDestinationSpace( |
| 74 const FloatRect& rect, | 71 const FloatRect& rect, |
| 75 const GeometryPropertyTreeState& sourceState, | 72 const PropertyTreeState& sourceState, |
| 76 const GeometryPropertyTreeState& destinationState, | 73 const PropertyTreeState& destinationState, |
| 77 bool& success) { | 74 bool& success) { |
| 78 const TransformPaintPropertyNode* lcaTransform = leastCommonAncestor( | 75 const TransformPaintPropertyNode* lcaTransform = leastCommonAncestor( |
| 79 sourceState.transform.get(), destinationState.transform.get()); | 76 sourceState.transform(), destinationState.transform()); |
| 80 DCHECK(lcaTransform); | 77 DCHECK(lcaTransform); |
| 81 GeometryPropertyTreeState lcaState = sourceState; | 78 PropertyTreeState lcaState = sourceState; |
| 82 lcaState.transform = lcaTransform; | 79 lcaState.setTransform(lcaTransform); |
| 83 | 80 |
| 84 FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success); | 81 FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success); |
| 85 DCHECK(success); | 82 DCHECK(success); |
| 86 | 83 |
| 87 const TransformationMatrix& destinationToLca = localToAncestorMatrix( | 84 const TransformationMatrix& destinationToLca = |
| 88 destinationState.transform.get(), lcaState, success); | 85 localToAncestorMatrix(destinationState.transform(), lcaState, success); |
| 89 DCHECK(success); | 86 DCHECK(success); |
| 90 if (destinationToLca.isInvertible()) { | 87 if (destinationToLca.isInvertible()) { |
| 91 success = true; | 88 success = true; |
| 92 return destinationToLca.inverse().mapRect(result); | 89 return destinationToLca.inverse().mapRect(result); |
| 93 } | 90 } |
| 94 success = false; | 91 success = false; |
| 95 return rect; | 92 return rect; |
| 96 } | 93 } |
| 97 | 94 |
| 98 FloatRect GeometryMapper::localToVisualRectInAncestorSpace( | 95 FloatRect GeometryMapper::localToVisualRectInAncestorSpace( |
| 99 const FloatRect& rect, | 96 const FloatRect& rect, |
| 100 const GeometryPropertyTreeState& localState, | 97 const PropertyTreeState& localState, |
| 101 const GeometryPropertyTreeState& ancestorState, | 98 const PropertyTreeState& ancestorState, |
| 102 bool& success) { | 99 bool& success) { |
| 103 const auto& transformMatrix = | 100 const auto& transformMatrix = |
| 104 localToAncestorMatrix(localState.transform.get(), ancestorState, success); | 101 localToAncestorMatrix(localState.transform(), ancestorState, success); |
| 105 if (!success) | 102 if (!success) |
| 106 return rect; | 103 return rect; |
| 107 | 104 |
| 108 FloatRect mappedRect = transformMatrix.mapRect(rect); | 105 FloatRect mappedRect = transformMatrix.mapRect(rect); |
| 109 | 106 |
| 110 const auto clipRect = | 107 const auto clipRect = |
| 111 localToAncestorClipRect(localState, ancestorState, success); | 108 localToAncestorClipRect(localState, ancestorState, success); |
| 112 DCHECK(success); | 109 DCHECK(success); |
| 113 | 110 |
| 114 mappedRect.intersect(clipRect); | 111 mappedRect.intersect(clipRect); |
| 115 return mappedRect; | 112 return mappedRect; |
| 116 } | 113 } |
| 117 | 114 |
| 118 FloatRect GeometryMapper::localToAncestorRect( | 115 FloatRect GeometryMapper::localToAncestorRect( |
| 119 const FloatRect& rect, | 116 const FloatRect& rect, |
| 120 const GeometryPropertyTreeState& localState, | 117 const PropertyTreeState& localState, |
| 121 const GeometryPropertyTreeState& ancestorState, | 118 const PropertyTreeState& ancestorState, |
| 122 bool& success) { | 119 bool& success) { |
| 123 const auto& transformMatrix = | 120 const auto& transformMatrix = |
| 124 localToAncestorMatrix(localState.transform.get(), ancestorState, success); | 121 localToAncestorMatrix(localState.transform(), ancestorState, success); |
| 125 if (!success) | 122 if (!success) |
| 126 return rect; | 123 return rect; |
| 127 return transformMatrix.mapRect(rect); | 124 return transformMatrix.mapRect(rect); |
| 128 } | 125 } |
| 129 | 126 |
| 130 FloatRect GeometryMapper::ancestorToLocalRect( | 127 FloatRect GeometryMapper::ancestorToLocalRect( |
| 131 const FloatRect& rect, | 128 const FloatRect& rect, |
| 132 const GeometryPropertyTreeState& localState, | 129 const PropertyTreeState& localState, |
| 133 const GeometryPropertyTreeState& ancestorState, | 130 const PropertyTreeState& ancestorState, |
| 134 bool& success) { | 131 bool& success) { |
| 135 const auto& transformMatrix = | 132 const auto& transformMatrix = |
| 136 localToAncestorMatrix(localState.transform.get(), ancestorState, success); | 133 localToAncestorMatrix(localState.transform(), ancestorState, success); |
| 137 if (!success) | 134 if (!success) |
| 138 return rect; | 135 return rect; |
| 139 | 136 |
| 140 if (!transformMatrix.isInvertible()) { | 137 if (!transformMatrix.isInvertible()) { |
| 141 success = false; | 138 success = false; |
| 142 return rect; | 139 return rect; |
| 143 } | 140 } |
| 144 success = true; | 141 success = true; |
| 145 | 142 |
| 146 // TODO(chrishtr): Cache the inverse? | 143 // TODO(chrishtr): Cache the inverse? |
| 147 return transformMatrix.inverse().mapRect(rect); | 144 return transformMatrix.inverse().mapRect(rect); |
| 148 } | 145 } |
| 149 | 146 |
| 150 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor( | 147 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor( |
| 151 const GeometryPropertyTreeState& ancestorState) { | 148 const PropertyTreeState& ancestorState) { |
| 152 auto addResult = m_data.add(ancestorState.transform.get(), nullptr); | 149 auto addResult = m_data.add(ancestorState.transform(), nullptr); |
| 153 if (addResult.isNewEntry) | 150 if (addResult.isNewEntry) |
| 154 addResult.storedValue->value = PrecomputedDataForAncestor::create(); | 151 addResult.storedValue->value = PrecomputedDataForAncestor::create(); |
| 155 return *addResult.storedValue->value; | 152 return *addResult.storedValue->value; |
| 156 } | 153 } |
| 157 | 154 |
| 158 FloatRect GeometryMapper::localToAncestorClipRect( | 155 FloatRect GeometryMapper::localToAncestorClipRect( |
| 159 const GeometryPropertyTreeState& localState, | 156 const PropertyTreeState& localState, |
| 160 const GeometryPropertyTreeState& ancestorState, | 157 const PropertyTreeState& ancestorState, |
| 161 bool& success) { | 158 bool& success) { |
| 162 PrecomputedDataForAncestor& precomputedData = | 159 PrecomputedDataForAncestor& precomputedData = |
| 163 getPrecomputedDataForAncestor(ancestorState); | 160 getPrecomputedDataForAncestor(ancestorState); |
| 164 const ClipPaintPropertyNode* clipNode = localState.clip.get(); | 161 const ClipPaintPropertyNode* clipNode = localState.clip(); |
| 165 Vector<const ClipPaintPropertyNode*> intermediateNodes; | 162 Vector<const ClipPaintPropertyNode*> intermediateNodes; |
| 166 FloatRect clip(LayoutRect::infiniteIntRect()); | 163 FloatRect clip(LayoutRect::infiniteIntRect()); |
| 167 | 164 |
| 168 bool found = false; | 165 bool found = false; |
| 169 // Iterate over the path from localState.clip to ancestorState.clip. Stop if w
e've found a memoized (precomputed) clip | 166 // Iterate over the path from localState.clip to ancestorState.clip. Stop if w
e've found a memoized (precomputed) clip |
| 170 // for any particular node. | 167 // for any particular node. |
| 171 while (clipNode) { | 168 while (clipNode) { |
| 172 auto it = precomputedData.toAncestorClipRects.find(clipNode); | 169 auto it = precomputedData.toAncestorClipRects.find(clipNode); |
| 173 if (it != precomputedData.toAncestorClipRects.end()) { | 170 if (it != precomputedData.toAncestorClipRects.end()) { |
| 174 clip = it->value; | 171 clip = it->value; |
| 175 found = true; | 172 found = true; |
| 176 break; | 173 break; |
| 177 } | 174 } |
| 178 intermediateNodes.append(clipNode); | 175 intermediateNodes.append(clipNode); |
| 179 | 176 |
| 180 if (clipNode == ancestorState.clip) | 177 if (clipNode == ancestorState.clip()) |
| 181 break; | 178 break; |
| 182 | 179 |
| 183 clipNode = clipNode->parent(); | 180 clipNode = clipNode->parent(); |
| 184 } | 181 } |
| 185 if (clipNode != ancestorState.clip && !found) { | 182 if (clipNode != ancestorState.clip() && !found) { |
| 186 success = false; | 183 success = false; |
| 187 return clip; | 184 return clip; |
| 188 } | 185 } |
| 189 | 186 |
| 190 // Iterate down from the top intermediate node found in the previous loop, com
puting and memoizing clip rects as we go. | 187 // Iterate down from the top intermediate node found in the previous loop, com
puting and memoizing clip rects as we go. |
| 191 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); | 188 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); |
| 192 ++it) { | 189 ++it) { |
| 193 if ((*it) != ancestorState.clip) { | 190 if ((*it) != ancestorState.clip()) { |
| 194 success = false; | 191 success = false; |
| 195 const TransformationMatrix& transformMatrix = localToAncestorMatrix( | 192 const TransformationMatrix& transformMatrix = localToAncestorMatrix( |
| 196 (*it)->localTransformSpace(), ancestorState, success); | 193 (*it)->localTransformSpace(), ancestorState, success); |
| 197 if (!success) | 194 if (!success) |
| 198 return clip; | 195 return clip; |
| 199 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect()); | 196 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect()); |
| 200 clip.intersect(mappedRect); | 197 clip.intersect(mappedRect); |
| 201 } | 198 } |
| 202 | 199 |
| 203 precomputedData.toAncestorClipRects.set(*it, clip); | 200 precomputedData.toAncestorClipRects.set(*it, clip); |
| 204 } | 201 } |
| 205 | 202 |
| 206 success = true; | 203 success = true; |
| 207 return precomputedData.toAncestorClipRects.find(localState.clip.get())->value; | 204 return precomputedData.toAncestorClipRects.find(localState.clip())->value; |
| 208 } | 205 } |
| 209 | 206 |
| 210 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( | 207 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( |
| 211 const TransformPaintPropertyNode* localTransformNode, | 208 const TransformPaintPropertyNode* localTransformNode, |
| 212 const GeometryPropertyTreeState& ancestorState, | 209 const PropertyTreeState& ancestorState, |
| 213 bool& success) { | 210 bool& success) { |
| 214 PrecomputedDataForAncestor& precomputedData = | 211 PrecomputedDataForAncestor& precomputedData = |
| 215 getPrecomputedDataForAncestor(ancestorState); | 212 getPrecomputedDataForAncestor(ancestorState); |
| 216 | 213 |
| 217 const TransformPaintPropertyNode* transformNode = localTransformNode; | 214 const TransformPaintPropertyNode* transformNode = localTransformNode; |
| 218 Vector<const TransformPaintPropertyNode*> intermediateNodes; | 215 Vector<const TransformPaintPropertyNode*> intermediateNodes; |
| 219 TransformationMatrix transformMatrix; | 216 TransformationMatrix transformMatrix; |
| 220 | 217 |
| 221 bool found = false; | 218 bool found = false; |
| 222 // Iterate over the path from localTransformNode to ancestorState.transform. S
top if we've found a memoized (precomputed) transform | 219 // Iterate over the path from localTransformNode to ancestorState.transform. S
top if we've found a memoized (precomputed) transform |
| 223 // for any particular node. | 220 // for any particular node. |
| 224 while (transformNode) { | 221 while (transformNode) { |
| 225 auto it = precomputedData.toAncestorTransforms.find(transformNode); | 222 auto it = precomputedData.toAncestorTransforms.find(transformNode); |
| 226 if (it != precomputedData.toAncestorTransforms.end()) { | 223 if (it != precomputedData.toAncestorTransforms.end()) { |
| 227 transformMatrix = it->value; | 224 transformMatrix = it->value; |
| 228 found = true; | 225 found = true; |
| 229 break; | 226 break; |
| 230 } | 227 } |
| 231 | 228 |
| 232 intermediateNodes.append(transformNode); | 229 intermediateNodes.append(transformNode); |
| 233 | 230 |
| 234 if (transformNode == ancestorState.transform) | 231 if (transformNode == ancestorState.transform()) |
| 235 break; | 232 break; |
| 236 | 233 |
| 237 transformNode = transformNode->parent(); | 234 transformNode = transformNode->parent(); |
| 238 } | 235 } |
| 239 if (!found && transformNode != ancestorState.transform) { | 236 if (!found && transformNode != ancestorState.transform()) { |
| 240 success = false; | 237 success = false; |
| 241 return m_identity; | 238 return m_identity; |
| 242 } | 239 } |
| 243 | 240 |
| 244 // Iterate down from the top intermediate node found in the previous loop, com
puting and memoizing transforms as we go. | 241 // Iterate down from the top intermediate node found in the previous loop, com
puting and memoizing transforms as we go. |
| 245 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); | 242 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); |
| 246 it++) { | 243 it++) { |
| 247 if ((*it) != ancestorState.transform) { | 244 if ((*it) != ancestorState.transform()) { |
| 248 TransformationMatrix localTransformMatrix = (*it)->matrix(); | 245 TransformationMatrix localTransformMatrix = (*it)->matrix(); |
| 249 localTransformMatrix.applyTransformOrigin((*it)->origin()); | 246 localTransformMatrix.applyTransformOrigin((*it)->origin()); |
| 250 transformMatrix = transformMatrix * localTransformMatrix; | 247 transformMatrix = transformMatrix * localTransformMatrix; |
| 251 } | 248 } |
| 252 | 249 |
| 253 precomputedData.toAncestorTransforms.set(*it, transformMatrix); | 250 precomputedData.toAncestorTransforms.set(*it, transformMatrix); |
| 254 } | 251 } |
| 255 success = true; | 252 success = true; |
| 256 return precomputedData.toAncestorTransforms.find(localTransformNode)->value; | 253 return precomputedData.toAncestorTransforms.find(localTransformNode)->value; |
| 257 } | 254 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 | 287 |
| 291 // Walk up until we find the ancestor. | 288 // Walk up until we find the ancestor. |
| 292 while (a != b) { | 289 while (a != b) { |
| 293 a = a->parent(); | 290 a = a->parent(); |
| 294 b = b->parent(); | 291 b = b->parent(); |
| 295 } | 292 } |
| 296 return a; | 293 return a; |
| 297 } | 294 } |
| 298 | 295 |
| 299 } // namespace blink | 296 } // namespace blink |
| OLD | NEW |