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" | 8 #include "platform/graphics/paint/ClipPaintPropertyNode.h" |
9 #include "platform/graphics/paint/EffectPaintPropertyNode.h" | 9 #include "platform/graphics/paint/EffectPaintPropertyNode.h" |
10 #include "platform/graphics/paint/TransformPaintPropertyNode.h" | 10 #include "platform/graphics/paint/TransformPaintPropertyNode.h" |
11 | 11 |
12 namespace blink { | 12 namespace blink { |
13 | 13 |
14 FloatRect GeometryMapper::mapToVisualRectInDestinationSpace(const FloatRect& rec
t, | 14 FloatRect GeometryMapper::mapToVisualRectInDestinationSpace(const FloatRect& rec
t, |
15 const PropertyTreeState& sourceState, | 15 const GeometryPropertyTreeState& sourceState, |
16 const PropertyTreeState& destinationState, | 16 const GeometryPropertyTreeState& destinationState, |
17 bool& success) | 17 bool& success) |
18 { | 18 { |
19 FloatRect result = localToVisualRectInAncestorSpace(rect, sourceState, desti
nationState, success); | 19 FloatRect result = localToVisualRectInAncestorSpace(rect, sourceState, desti
nationState, success); |
20 if (success) | 20 if (success) |
21 return result; | 21 return result; |
22 return slowMapToVisualRectInDestinationSpace(rect, sourceState, destinationS
tate, success); | 22 return slowMapToVisualRectInDestinationSpace(rect, sourceState, destinationS
tate, success); |
23 } | 23 } |
24 | 24 |
25 FloatRect GeometryMapper::mapRectToDestinationSpace(const FloatRect& rect, | 25 FloatRect GeometryMapper::mapRectToDestinationSpace(const FloatRect& rect, |
26 const PropertyTreeState& sourceState, | 26 const GeometryPropertyTreeState& sourceState, |
27 const PropertyTreeState& destinationState, | 27 const GeometryPropertyTreeState& destinationState, |
28 bool& success) | 28 bool& success) |
29 { | 29 { |
30 FloatRect result = localToAncestorRect(rect, sourceState, destinationState,
success); | 30 FloatRect result = localToAncestorRect(rect, sourceState, destinationState,
success); |
31 if (success) | 31 if (success) |
32 return result; | 32 return result; |
33 return slowMapRectToDestinationSpace(rect, sourceState, destinationState, su
ccess); | 33 return slowMapRectToDestinationSpace(rect, sourceState, destinationState, su
ccess); |
34 } | 34 } |
35 | 35 |
36 FloatRect GeometryMapper::slowMapToVisualRectInDestinationSpace(const FloatRect&
rect, | 36 FloatRect GeometryMapper::slowMapToVisualRectInDestinationSpace(const FloatRect&
rect, |
37 const PropertyTreeState& sourceState, | 37 const GeometryPropertyTreeState& sourceState, |
38 const PropertyTreeState& destinationState, | 38 const GeometryPropertyTreeState& destinationState, |
39 bool& success) | 39 bool& success) |
40 { | 40 { |
41 const TransformPaintPropertyNode* lcaTransform = propertyTreeNearestCommonAn
cestor<TransformPaintPropertyNode>(sourceState.transform.get(), destinationState
.transform.get()); | 41 const TransformPaintPropertyNode* lcaTransform = propertyTreeNearestCommonAn
cestor<TransformPaintPropertyNode>(sourceState.transform.get(), destinationState
.transform.get()); |
42 DCHECK(lcaTransform); | 42 DCHECK(lcaTransform); |
43 | 43 |
44 // Assume that the clip of destinationState is an ancestor of the clip of so
urceState | 44 // Assume that the clip of destinationState is an ancestor of the clip of so
urceState |
45 // and is under the space of lcaTransform. Otherwise localToAncestorClipRect
() will fail. | 45 // and is under the space of lcaTransform. Otherwise localToAncestorClipRect
() will fail. |
46 PropertyTreeState lcaState = destinationState; | 46 GeometryPropertyTreeState lcaState = destinationState; |
47 lcaState.transform = lcaTransform; | 47 lcaState.transform = lcaTransform; |
48 | 48 |
49 const auto clipRect = localToAncestorClipRect(sourceState, lcaState, success
); | 49 const auto clipRect = localToAncestorClipRect(sourceState, lcaState, success
); |
50 if (!success) | 50 if (!success) |
51 return rect; | 51 return rect; |
52 | 52 |
53 FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success)
; | 53 FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success)
; |
54 DCHECK(success); | 54 DCHECK(success); |
55 result.intersect(clipRect); | 55 result.intersect(clipRect); |
56 | 56 |
57 const TransformationMatrix& destinationToLca = localToAncestorMatrix(destina
tionState.transform.get(), lcaState, success); | 57 const TransformationMatrix& destinationToLca = localToAncestorMatrix(destina
tionState.transform.get(), lcaState, success); |
58 DCHECK(success); | 58 DCHECK(success); |
59 if (destinationToLca.isInvertible()) { | 59 if (destinationToLca.isInvertible()) { |
60 success = true; | 60 success = true; |
61 return destinationToLca.inverse().mapRect(result); | 61 return destinationToLca.inverse().mapRect(result); |
62 } | 62 } |
63 success = false; | 63 success = false; |
64 return rect; | 64 return rect; |
65 } | 65 } |
66 | 66 |
67 FloatRect GeometryMapper::slowMapRectToDestinationSpace(const FloatRect& rect, | 67 FloatRect GeometryMapper::slowMapRectToDestinationSpace(const FloatRect& rect, |
68 const PropertyTreeState& sourceState, | 68 const GeometryPropertyTreeState& sourceState, |
69 const PropertyTreeState& destinationState, | 69 const GeometryPropertyTreeState& destinationState, |
70 bool& success) | 70 bool& success) |
71 { | 71 { |
72 const TransformPaintPropertyNode* lcaTransform = propertyTreeNearestCommonAn
cestor<TransformPaintPropertyNode>(sourceState.transform.get(), destinationState
.transform.get()); | 72 const TransformPaintPropertyNode* lcaTransform = propertyTreeNearestCommonAn
cestor<TransformPaintPropertyNode>(sourceState.transform.get(), destinationState
.transform.get()); |
73 DCHECK(lcaTransform); | 73 DCHECK(lcaTransform); |
74 PropertyTreeState lcaState = sourceState; | 74 GeometryPropertyTreeState lcaState = sourceState; |
75 lcaState.transform = lcaTransform; | 75 lcaState.transform = lcaTransform; |
76 | 76 |
77 FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success)
; | 77 FloatRect result = localToAncestorRect(rect, sourceState, lcaState, success)
; |
78 DCHECK(success); | 78 DCHECK(success); |
79 | 79 |
80 const TransformationMatrix& destinationToLca = localToAncestorMatrix(destina
tionState.transform.get(), lcaState, success); | 80 const TransformationMatrix& destinationToLca = localToAncestorMatrix(destina
tionState.transform.get(), lcaState, success); |
81 DCHECK(success); | 81 DCHECK(success); |
82 if (destinationToLca.isInvertible()) { | 82 if (destinationToLca.isInvertible()) { |
83 success = true; | 83 success = true; |
84 return destinationToLca.inverse().mapRect(result); | 84 return destinationToLca.inverse().mapRect(result); |
85 } | 85 } |
86 success = false; | 86 success = false; |
87 return rect; | 87 return rect; |
88 } | 88 } |
89 | 89 |
90 FloatRect GeometryMapper::localToVisualRectInAncestorSpace( | 90 FloatRect GeometryMapper::localToVisualRectInAncestorSpace( |
91 const FloatRect& rect, | 91 const FloatRect& rect, |
92 const PropertyTreeState& localState, | 92 const GeometryPropertyTreeState& localState, |
93 const PropertyTreeState& ancestorState, bool& success) | 93 const GeometryPropertyTreeState& ancestorState, bool& success) |
94 { | 94 { |
95 const auto& transformMatrix = localToAncestorMatrix(localState.transform.get
(), ancestorState, success); | 95 const auto& transformMatrix = localToAncestorMatrix(localState.transform.get
(), ancestorState, success); |
96 if (!success) | 96 if (!success) |
97 return rect; | 97 return rect; |
98 | 98 |
99 FloatRect mappedRect = transformMatrix.mapRect(rect); | 99 FloatRect mappedRect = transformMatrix.mapRect(rect); |
100 | 100 |
101 const auto clipRect = localToAncestorClipRect(localState, ancestorState, suc
cess); | 101 const auto clipRect = localToAncestorClipRect(localState, ancestorState, suc
cess); |
102 DCHECK(success); | 102 DCHECK(success); |
103 | 103 |
104 mappedRect.intersect(clipRect); | 104 mappedRect.intersect(clipRect); |
105 return mappedRect; | 105 return mappedRect; |
106 } | 106 } |
107 | 107 |
108 FloatRect GeometryMapper::localToAncestorRect( | 108 FloatRect GeometryMapper::localToAncestorRect( |
109 const FloatRect& rect, | 109 const FloatRect& rect, |
110 const PropertyTreeState& localState, | 110 const GeometryPropertyTreeState& localState, |
111 const PropertyTreeState& ancestorState, | 111 const GeometryPropertyTreeState& ancestorState, |
112 bool& success) | 112 bool& success) |
113 { | 113 { |
114 const auto& transformMatrix = localToAncestorMatrix(localState.transform.get
(), ancestorState, success); | 114 const auto& transformMatrix = localToAncestorMatrix(localState.transform.get
(), ancestorState, success); |
115 if (!success) | 115 if (!success) |
116 return rect; | 116 return rect; |
117 return transformMatrix.mapRect(rect); | 117 return transformMatrix.mapRect(rect); |
118 } | 118 } |
119 | 119 |
120 FloatRect GeometryMapper::ancestorToLocalRect( | 120 FloatRect GeometryMapper::ancestorToLocalRect( |
121 const FloatRect& rect, | 121 const FloatRect& rect, |
122 const PropertyTreeState& localState, | 122 const GeometryPropertyTreeState& localState, |
123 const PropertyTreeState& ancestorState, bool& success) | 123 const GeometryPropertyTreeState& ancestorState, bool& success) |
124 { | 124 { |
125 const auto& transformMatrix = localToAncestorMatrix(localState.transform.get
(), ancestorState, success); | 125 const auto& transformMatrix = localToAncestorMatrix(localState.transform.get
(), ancestorState, success); |
126 if (!success) | 126 if (!success) |
127 return rect; | 127 return rect; |
128 | 128 |
129 if (!transformMatrix.isInvertible()) { | 129 if (!transformMatrix.isInvertible()) { |
130 success = false; | 130 success = false; |
131 return rect; | 131 return rect; |
132 } | 132 } |
133 success = true; | 133 success = true; |
134 | 134 |
135 // TODO(chrishtr): Cache the inverse? | 135 // TODO(chrishtr): Cache the inverse? |
136 return transformMatrix.inverse().mapRect(rect); | 136 return transformMatrix.inverse().mapRect(rect); |
137 } | 137 } |
138 | 138 |
139 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor(const
PropertyTreeState& ancestorState) | 139 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor(const
GeometryPropertyTreeState& ancestorState) |
140 { | 140 { |
141 auto addResult = m_data.add(ancestorState.transform.get(), nullptr); | 141 auto addResult = m_data.add(ancestorState.transform.get(), nullptr); |
142 if (addResult.isNewEntry) | 142 if (addResult.isNewEntry) |
143 addResult.storedValue->value = PrecomputedDataForAncestor::create(); | 143 addResult.storedValue->value = PrecomputedDataForAncestor::create(); |
144 return *addResult.storedValue->value; | 144 return *addResult.storedValue->value; |
145 } | 145 } |
146 | 146 |
147 FloatRect GeometryMapper::localToAncestorClipRect( | 147 FloatRect GeometryMapper::localToAncestorClipRect( |
148 const PropertyTreeState& localState, | 148 const GeometryPropertyTreeState& localState, |
149 const PropertyTreeState& ancestorState, | 149 const GeometryPropertyTreeState& ancestorState, |
150 bool& success) | 150 bool& success) |
151 { | 151 { |
152 PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor(
ancestorState); | 152 PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor(
ancestorState); |
153 const ClipPaintPropertyNode* clipNode = localState.clip.get(); | 153 const ClipPaintPropertyNode* clipNode = localState.clip.get(); |
154 Vector<const ClipPaintPropertyNode*> intermediateNodes; | 154 Vector<const ClipPaintPropertyNode*> intermediateNodes; |
155 FloatRect clip(LayoutRect::infiniteIntRect()); | 155 FloatRect clip(LayoutRect::infiniteIntRect()); |
156 | 156 |
157 bool found = false; | 157 bool found = false; |
158 // Iterate over the path from localState.clip to ancestorState.clip. Stop if
we've found a memoized (precomputed) clip | 158 // Iterate over the path from localState.clip to ancestorState.clip. Stop if
we've found a memoized (precomputed) clip |
159 // for any particular node. | 159 // for any particular node. |
(...skipping 29 matching lines...) Expand all Loading... |
189 | 189 |
190 precomputedData.toAncestorClipRects.set(*it, clip); | 190 precomputedData.toAncestorClipRects.set(*it, clip); |
191 } | 191 } |
192 | 192 |
193 success = true; | 193 success = true; |
194 return precomputedData.toAncestorClipRects.find(localState.clip.get())->valu
e; | 194 return precomputedData.toAncestorClipRects.find(localState.clip.get())->valu
e; |
195 } | 195 } |
196 | 196 |
197 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( | 197 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( |
198 const TransformPaintPropertyNode* localTransformNode, | 198 const TransformPaintPropertyNode* localTransformNode, |
199 const PropertyTreeState& ancestorState, bool& success) { | 199 const GeometryPropertyTreeState& ancestorState, bool& success) { |
200 PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor(
ancestorState); | 200 PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor(
ancestorState); |
201 | 201 |
202 const TransformPaintPropertyNode* transformNode = localTransformNode; | 202 const TransformPaintPropertyNode* transformNode = localTransformNode; |
203 Vector<const TransformPaintPropertyNode*> intermediateNodes; | 203 Vector<const TransformPaintPropertyNode*> intermediateNodes; |
204 TransformationMatrix transformMatrix; | 204 TransformationMatrix transformMatrix; |
205 | 205 |
206 bool found = false; | 206 bool found = false; |
207 // Iterate over the path from localTransformNode to ancestorState.transform.
Stop if we've found a memoized (precomputed) transform | 207 // Iterate over the path from localTransformNode to ancestorState.transform.
Stop if we've found a memoized (precomputed) transform |
208 // for any particular node. | 208 // for any particular node. |
209 while (transformNode) { | 209 while (transformNode) { |
(...skipping 24 matching lines...) Expand all Loading... |
234 transformMatrix = transformMatrix * localTransformMatrix; | 234 transformMatrix = transformMatrix * localTransformMatrix; |
235 } | 235 } |
236 | 236 |
237 precomputedData.toAncestorTransforms.set(*it, transformMatrix); | 237 precomputedData.toAncestorTransforms.set(*it, transformMatrix); |
238 } | 238 } |
239 success = true; | 239 success = true; |
240 return precomputedData.toAncestorTransforms.find(localTransformNode)->value; | 240 return precomputedData.toAncestorTransforms.find(localTransformNode)->value; |
241 } | 241 } |
242 | 242 |
243 } // namespace blink | 243 } // namespace blink |
OLD | NEW |