| 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 { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 | 154 |
| 155 const auto& transformMatrix = | 155 const auto& transformMatrix = |
| 156 localToAncestorMatrix(localTransformNode, ancestorTransformNode); | 156 localToAncestorMatrix(localTransformNode, ancestorTransformNode); |
| 157 DCHECK(transformMatrix.isInvertible()); | 157 DCHECK(transformMatrix.isInvertible()); |
| 158 | 158 |
| 159 // TODO(chrishtr): Cache the inverse? | 159 // TODO(chrishtr): Cache the inverse? |
| 160 return transformMatrix.inverse().mapRect(rect); | 160 return transformMatrix.inverse().mapRect(rect); |
| 161 } | 161 } |
| 162 | 162 |
| 163 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor( | 163 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor( |
| 164 const TransformPaintPropertyNode* ancestorTransformNode) { | 164 const TransformPaintPropertyNode* transform) { |
| 165 auto addResult = m_data.insert(ancestorTransformNode, nullptr); | 165 auto addResult = m_data.insert(transform, nullptr); |
| 166 if (addResult.isNewEntry) | 166 if (addResult.isNewEntry) |
| 167 addResult.storedValue->value = PrecomputedDataForAncestor::create(); | 167 addResult.storedValue->value = PrecomputedDataForAncestor::create(); |
| 168 return *addResult.storedValue->value; | 168 return *addResult.storedValue->value; |
| 169 } | 169 } |
| 170 | 170 |
| 171 TransformCache& GeometryMapper::getTransformCache( |
| 172 const TransformPaintPropertyNode* node) { |
| 173 return getPrecomputedDataForAncestor(node).toAncestorTransforms; |
| 174 } |
| 175 |
| 176 ClipCache& GeometryMapper::getClipCache( |
| 177 const TransformPaintPropertyNode* transform, |
| 178 const ClipPaintPropertyNode* clip) { |
| 179 PrecomputedDataForAncestor& precomputedData = |
| 180 getPrecomputedDataForAncestor(transform); |
| 181 |
| 182 auto addResult = precomputedData.precomputedClips.insert(clip, nullptr); |
| 183 if (addResult.isNewEntry) |
| 184 addResult.storedValue->value = WTF::makeUnique<ClipCache>(); |
| 185 return *addResult.storedValue->value; |
| 186 } |
| 187 |
| 171 FloatRect GeometryMapper::localToAncestorClipRect( | 188 FloatRect GeometryMapper::localToAncestorClipRect( |
| 172 const PropertyTreeState& localState, | 189 const PropertyTreeState& localState, |
| 173 const PropertyTreeState& ancestorState) { | 190 const PropertyTreeState& ancestorState) { |
| 174 bool success = false; | 191 bool success = false; |
| 175 FloatRect result = | 192 FloatRect result = |
| 176 localToAncestorClipRectInternal(localState, ancestorState, success); | 193 localToAncestorClipRectInternal(localState, ancestorState, success); |
| 177 DCHECK(success); | 194 DCHECK(success); |
| 178 return result; | 195 return result; |
| 179 } | 196 } |
| 180 | 197 |
| 181 FloatRect GeometryMapper::localToAncestorClipRectInternal( | 198 FloatRect GeometryMapper::localToAncestorClipRectInternal( |
| 182 const PropertyTreeState& localState, | 199 const PropertyTreeState& localState, |
| 183 const PropertyTreeState& ancestorState, | 200 const PropertyTreeState& ancestorState, |
| 184 bool& success) { | 201 bool& success) { |
| 185 FloatRect clip(LayoutRect::infiniteIntRect()); | 202 FloatRect clip(LayoutRect::infiniteIntRect()); |
| 186 if (localState.clip() == ancestorState.clip()) { | 203 if (localState.clip() == ancestorState.clip()) { |
| 187 success = true; | 204 success = true; |
| 188 return clip; | 205 return clip; |
| 189 } | 206 } |
| 190 | 207 |
| 191 PrecomputedDataForAncestor& precomputedData = | 208 ClipCache& clipCache = |
| 192 getPrecomputedDataForAncestor(ancestorState.transform()); | 209 getClipCache(ancestorState.transform(), ancestorState.clip()); |
| 193 const ClipPaintPropertyNode* clipNode = localState.clip(); | 210 const ClipPaintPropertyNode* clipNode = localState.clip(); |
| 194 Vector<const ClipPaintPropertyNode*> intermediateNodes; | 211 Vector<const ClipPaintPropertyNode*> intermediateNodes; |
| 195 | 212 |
| 196 // Iterate over the path from localState.clip to ancestorState.clip. Stop if | 213 // Iterate over the path from localState.clip to ancestorState.clip. Stop if |
| 197 // we've found a memoized (precomputed) clip for any particular node. | 214 // we've found a memoized (precomputed) clip for any particular node. |
| 198 while (clipNode && clipNode != ancestorState.clip()) { | 215 while (clipNode && clipNode != ancestorState.clip()) { |
| 199 auto it = precomputedData.toAncestorClipRects.find(clipNode); | 216 auto it = clipCache.find(clipNode); |
| 200 if (it != precomputedData.toAncestorClipRects.end()) { | 217 if (it != clipCache.end()) { |
| 201 clip = it->value; | 218 clip = it->value; |
| 202 break; | 219 break; |
| 203 } | 220 } |
| 204 intermediateNodes.push_back(clipNode); | 221 intermediateNodes.push_back(clipNode); |
| 205 clipNode = clipNode->parent(); | 222 clipNode = clipNode->parent(); |
| 206 } | 223 } |
| 207 if (!clipNode) { | 224 if (!clipNode) { |
| 208 success = false; | 225 success = false; |
| 209 return clip; | 226 return clip; |
| 210 } | 227 } |
| 211 | 228 |
| 212 // Iterate down from the top intermediate node found in the previous loop, | 229 // Iterate down from the top intermediate node found in the previous loop, |
| 213 // computing and memoizing clip rects as we go. | 230 // computing and memoizing clip rects as we go. |
| 214 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); | 231 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); |
| 215 ++it) { | 232 ++it) { |
| 216 success = false; | 233 success = false; |
| 217 const TransformationMatrix& transformMatrix = localToAncestorMatrixInternal( | 234 const TransformationMatrix& transformMatrix = localToAncestorMatrixInternal( |
| 218 (*it)->localTransformSpace(), ancestorState.transform(), success); | 235 (*it)->localTransformSpace(), ancestorState.transform(), success); |
| 219 if (!success) | 236 if (!success) |
| 220 return clip; | 237 return clip; |
| 221 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect()); | 238 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect()); |
| 222 clip.intersect(mappedRect); | 239 clip.intersect(mappedRect); |
| 223 precomputedData.toAncestorClipRects.set(*it, clip); | 240 clipCache.set(*it, clip); |
| 224 } | 241 } |
| 225 | 242 |
| 226 success = true; | 243 success = true; |
| 227 return precomputedData.toAncestorClipRects.find(localState.clip())->value; | 244 return clipCache.find(localState.clip())->value; |
| 228 } | 245 } |
| 229 | 246 |
| 230 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( | 247 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( |
| 231 const TransformPaintPropertyNode* localTransformNode, | 248 const TransformPaintPropertyNode* localTransformNode, |
| 232 const TransformPaintPropertyNode* ancestorTransformNode) { | 249 const TransformPaintPropertyNode* ancestorTransformNode) { |
| 233 bool success = false; | 250 bool success = false; |
| 234 const auto& result = localToAncestorMatrixInternal( | 251 const auto& result = localToAncestorMatrixInternal( |
| 235 localTransformNode, ancestorTransformNode, success); | 252 localTransformNode, ancestorTransformNode, success); |
| 236 DCHECK(success); | 253 DCHECK(success); |
| 237 return result; | 254 return result; |
| 238 } | 255 } |
| 239 | 256 |
| 240 const TransformationMatrix& GeometryMapper::localToAncestorMatrixInternal( | 257 const TransformationMatrix& GeometryMapper::localToAncestorMatrixInternal( |
| 241 const TransformPaintPropertyNode* localTransformNode, | 258 const TransformPaintPropertyNode* localTransformNode, |
| 242 const TransformPaintPropertyNode* ancestorTransformNode, | 259 const TransformPaintPropertyNode* ancestorTransformNode, |
| 243 bool& success) { | 260 bool& success) { |
| 244 if (localTransformNode == ancestorTransformNode) { | 261 if (localTransformNode == ancestorTransformNode) { |
| 245 success = true; | 262 success = true; |
| 246 return m_identity; | 263 return m_identity; |
| 247 } | 264 } |
| 248 | 265 |
| 249 PrecomputedDataForAncestor& precomputedData = | 266 TransformCache& transformCache = getTransformCache(ancestorTransformNode); |
| 250 getPrecomputedDataForAncestor(ancestorTransformNode); | |
| 251 | 267 |
| 252 const TransformPaintPropertyNode* transformNode = localTransformNode; | 268 const TransformPaintPropertyNode* transformNode = localTransformNode; |
| 253 Vector<const TransformPaintPropertyNode*> intermediateNodes; | 269 Vector<const TransformPaintPropertyNode*> intermediateNodes; |
| 254 TransformationMatrix transformMatrix; | 270 TransformationMatrix transformMatrix; |
| 255 | 271 |
| 256 // Iterate over the path from localTransformNode to ancestorState.transform. | 272 // Iterate over the path from localTransformNode to ancestorState.transform. |
| 257 // Stop if we've found a memoized (precomputed) transform for any particular | 273 // Stop if we've found a memoized (precomputed) transform for any particular |
| 258 // node. | 274 // node. |
| 259 while (transformNode && transformNode != ancestorTransformNode) { | 275 while (transformNode && transformNode != ancestorTransformNode) { |
| 260 auto it = precomputedData.toAncestorTransforms.find(transformNode); | 276 auto it = transformCache.find(transformNode); |
| 261 if (it != precomputedData.toAncestorTransforms.end()) { | 277 if (it != transformCache.end()) { |
| 262 transformMatrix = it->value; | 278 transformMatrix = it->value; |
| 263 break; | 279 break; |
| 264 } | 280 } |
| 265 intermediateNodes.push_back(transformNode); | 281 intermediateNodes.push_back(transformNode); |
| 266 transformNode = transformNode->parent(); | 282 transformNode = transformNode->parent(); |
| 267 } | 283 } |
| 268 if (!transformNode) { | 284 if (!transformNode) { |
| 269 success = false; | 285 success = false; |
| 270 return m_identity; | 286 return m_identity; |
| 271 } | 287 } |
| 272 | 288 |
| 273 // Iterate down from the top intermediate node found in the previous loop, | 289 // Iterate down from the top intermediate node found in the previous loop, |
| 274 // computing and memoizing transforms as we go. | 290 // computing and memoizing transforms as we go. |
| 275 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); | 291 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); |
| 276 it++) { | 292 it++) { |
| 277 TransformationMatrix localTransformMatrix = (*it)->matrix(); | 293 TransformationMatrix localTransformMatrix = (*it)->matrix(); |
| 278 localTransformMatrix.applyTransformOrigin((*it)->origin()); | 294 localTransformMatrix.applyTransformOrigin((*it)->origin()); |
| 279 transformMatrix = transformMatrix * localTransformMatrix; | 295 transformMatrix = transformMatrix * localTransformMatrix; |
| 280 precomputedData.toAncestorTransforms.set(*it, transformMatrix); | 296 transformCache.set(*it, transformMatrix); |
| 281 } | 297 } |
| 282 success = true; | 298 success = true; |
| 283 return precomputedData.toAncestorTransforms.find(localTransformNode)->value; | 299 return transformCache.find(localTransformNode)->value; |
| 284 } | 300 } |
| 285 | 301 |
| 286 void GeometryMapper::clearCache() { | 302 void GeometryMapper::clearCache() { |
| 287 m_data.clear(); | 303 m_data.clear(); |
| 288 } | 304 } |
| 289 | 305 |
| 290 namespace { | 306 namespace { |
| 291 | 307 |
| 292 template <typename NodeType> | 308 template <typename NodeType> |
| 293 unsigned nodeDepth(const NodeType* node) { | 309 unsigned nodeDepth(const NodeType* node) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 const TransformPaintPropertyNode*, | 354 const TransformPaintPropertyNode*, |
| 339 const TransformPaintPropertyNode*); | 355 const TransformPaintPropertyNode*); |
| 340 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor( | 356 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor( |
| 341 const ClipPaintPropertyNode*, | 357 const ClipPaintPropertyNode*, |
| 342 const ClipPaintPropertyNode*); | 358 const ClipPaintPropertyNode*); |
| 343 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor( | 359 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor( |
| 344 const ScrollPaintPropertyNode*, | 360 const ScrollPaintPropertyNode*, |
| 345 const ScrollPaintPropertyNode*); | 361 const ScrollPaintPropertyNode*); |
| 346 | 362 |
| 347 } // namespace blink | 363 } // namespace blink |
| OLD | NEW |