Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp

Issue 2105273004: GeometryMapper: Support computing visual rects in spaces that are not direct ancestors. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: none Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "wtf/HashSet.h"
11 12
12 namespace blink { 13 namespace blink {
13 14
14 FloatRect GeometryMapper::LocalToVisualRectInAncestorSpace( 15 PassRefPtr<TransformPaintPropertyNode> GeometryMapper::leastCommonAncestor(PassR efPtr<TransformPaintPropertyNode> a, PassRefPtr<TransformPaintPropertyNode> b)
16 {
17 HashSet<RefPtr<TransformPaintPropertyNode>> intermediates;
pdr. 2016/07/01 18:39:40 We may want to use a lowest common ancestor approa
chrishtr 2016/07/01 22:01:12 Refactored to reuse that code, templated for all p
18 RefPtr<TransformPaintPropertyNode> currA = a;
19 RefPtr<TransformPaintPropertyNode> currB = b;
20 while (currA || currB) {
21 if (currA) {
22 auto it = intermediates.find(currA);
23 if (it != intermediates.end())
24 return *it;
25 intermediates.add(currA);
26 currA = currA->parent();
27 }
28
29 if (currB) {
30 auto it = intermediates.find(currB);
31 if (it != intermediates.end())
32 return *it;
33 intermediates.add(currB);
34 currB = currB->parent();
35 }
36 }
37 CHECK(false);
38 return nullptr;
39 }
40
41 FloatRect GeometryMapper::mapToVisualRectInDestinationSpace(const FloatRect& rec t,
42 const PropertyTreeState& sourceState,
43 const PropertyTreeState& destinationState,
44 bool* success)
45 {
46 FloatRect result = localToVisualRectInAncestorSpace(rect, sourceState, desti nationState, success);
47 if (*success)
48 return result;
49
50 RefPtr<TransformPaintPropertyNode> lcaTransform = leastCommonAncestor(source State.transform.get(), destinationState.transform.get());
51 DCHECK(lcaTransform.get());
52 PropertyTreeState lcaState = sourceState;
53 lcaState.transform = lcaTransform;
54
55 result = localToAncestorMatrix(sourceState.transform.get(), lcaState, succes s).mapRect(rect);
56 DCHECK(*success);
57
58 const TransformationMatrix& destinationToLca = localToAncestorMatrix(destina tionState.transform.get(), lcaState, success);
59 DCHECK(*success);
60 if (destinationToLca.isInvertible()) {
61 *success = true;
62 return destinationToLca.inverse().mapRect(result);
63 }
64 *success = false;
65 return rect;
66 }
67
68 FloatRect GeometryMapper::localToVisualRectInAncestorSpace(
15 const FloatRect& rect, 69 const FloatRect& rect,
16 const PropertyTreeState& localState, 70 const PropertyTreeState& localState,
17 const PropertyTreeState& ancestorState) 71 const PropertyTreeState& ancestorState, bool* success)
18 { 72 {
19 const auto transformMatrix = LocalToAncestorMatrix(localState.transform, anc estorState); 73 const auto transformMatrix = localToAncestorMatrix(localState.transform.get( ), ancestorState, success);
74 if (!(*success))
75 return rect;
76
20 FloatRect mappedRect = transformMatrix.mapRect(rect); 77 FloatRect mappedRect = transformMatrix.mapRect(rect);
21 78
22 const auto clipRect = LocalToAncestorClipRect(localState, ancestorState); 79 const auto clipRect = localToAncestorClipRect(localState, ancestorState);
23 80
24 mappedRect.intersect(clipRect); 81 mappedRect.intersect(clipRect);
25 return mappedRect; 82 return mappedRect;
26 } 83 }
27 84
28 FloatRect GeometryMapper::LocalToAncestorRect( 85 FloatRect GeometryMapper::localToAncestorRect(
29 const FloatRect& rect, 86 const FloatRect& rect,
30 const PropertyTreeState& localState, 87 const PropertyTreeState& localState,
31 const PropertyTreeState& ancestorState) 88 const PropertyTreeState& ancestorState,
89 bool* success)
32 { 90 {
33 const auto transformMatrix = LocalToAncestorMatrix(localState.transform, anc estorState); 91 const auto transformMatrix = localToAncestorMatrix(localState.transform.get( ), ancestorState, success);
92 if (!(*success))
93 return rect;
34 return transformMatrix.mapRect(rect); 94 return transformMatrix.mapRect(rect);
35 } 95 }
36 96
37 FloatRect GeometryMapper::AncestorToLocalRect( 97 FloatRect GeometryMapper::ancestorToLocalRect(
38 const FloatRect& rect, 98 const FloatRect& rect,
39 const PropertyTreeState& localState, 99 const PropertyTreeState& localState,
40 const PropertyTreeState& ancestorState, bool* success) 100 const PropertyTreeState& ancestorState, bool* success)
41 { 101 {
42 const auto& transformMatrix = LocalToAncestorMatrix(localState.transform, an cestorState); 102 const auto& transformMatrix = localToAncestorMatrix(localState.transform.get (), ancestorState, success);
103 if (!(*success))
104 return rect;
105
43 if (!transformMatrix.isInvertible()) { 106 if (!transformMatrix.isInvertible()) {
44 *success = false; 107 *success = false;
45 return FloatRect(); 108 return rect;
46 } 109 }
47 *success = true; 110 *success = true;
48 111
49 // TODO(chrishtr): Cache the inverse? 112 // TODO(chrishtr): Cache the inverse?
50 return transformMatrix.inverse().mapRect(rect); 113 return transformMatrix.inverse().mapRect(rect);
51 } 114 }
52 115
53 PrecomputedDataForAncestor& GeometryMapper::GetPrecomputedDataForAncestor(const PropertyTreeState& ancestorState) 116 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor(const PropertyTreeState& ancestorState)
54 { 117 {
55 auto addResult = m_data.add(ancestorState.transform, nullptr); 118 auto addResult = m_data.add(ancestorState.transform.get(), nullptr);
56 if (addResult.isNewEntry) 119 if (addResult.isNewEntry)
57 addResult.storedValue->value = PrecomputedDataForAncestor::create(); 120 addResult.storedValue->value = PrecomputedDataForAncestor::create();
58 return *addResult.storedValue->value; 121 return *addResult.storedValue->value;
59 } 122 }
60 123
61 const FloatRect& GeometryMapper::LocalToAncestorClipRect( 124 const FloatRect& GeometryMapper::localToAncestorClipRect(
62 const PropertyTreeState& localState, 125 const PropertyTreeState& localState,
63 const PropertyTreeState& ancestorState) 126 const PropertyTreeState& ancestorState)
64 { 127 {
65 PrecomputedDataForAncestor& precomputedData = GetPrecomputedDataForAncestor( ancestorState); 128 PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor( ancestorState);
66 const ClipPaintPropertyNode* clipNode = localState.clip; 129 const ClipPaintPropertyNode* clipNode = localState.clip.get();
67 Vector<const ClipPaintPropertyNode*> intermediateNodes; 130 Vector<const ClipPaintPropertyNode*> intermediateNodes;
68 FloatRect clip(LayoutRect::infiniteIntRect()); 131 FloatRect clip(LayoutRect::infiniteIntRect());
69 132
70 bool found = false; 133 bool found = false;
71 // Iterate over the path from localState.clip to ancestorState.clip. Stop if we've found a memoized (precomputed) clip 134 // Iterate over the path from localState.clip to ancestorState.clip. Stop if we've found a memoized (precomputed) clip
72 // for any particular node. 135 // for any particular node.
73 while (clipNode) { 136 while (clipNode) {
74 auto it = precomputedData.toAncestorClipRects.find(clipNode); 137 auto it = precomputedData.toAncestorClipRects.find(clipNode);
75 if (it != precomputedData.toAncestorClipRects.end()) { 138 if (it != precomputedData.toAncestorClipRects.end()) {
76 clip = it->value; 139 clip = it->value;
77 found = true; 140 found = true;
78 break; 141 break;
79 } 142 }
80 intermediateNodes.append(clipNode); 143 intermediateNodes.append(clipNode);
81 144
82 if (clipNode == ancestorState.clip) 145 if (clipNode == ancestorState.clip)
83 break; 146 break;
84 147
85 clipNode = clipNode->parent(); 148 clipNode = clipNode->parent();
86 } 149 }
87 // It's illegal to ask for a local-to-ancestor clip when the ancestor is not an ancestor. 150 // It's illegal to ask for a local-to-ancestor clip when the ancestor is not an ancestor.
88 DCHECK(clipNode == ancestorState.clip || found); 151 DCHECK(clipNode == ancestorState.clip || found);
89 152
90 // Iterate down from the top intermediate node found in the previous loop, c omputing and memoizing clip rects as we go. 153 // Iterate down from the top intermediate node found in the previous loop, c omputing and memoizing clip rects as we go.
91 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); + +it) { 154 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); + +it) {
92 if ((*it) != ancestorState.clip) { 155 if ((*it) != ancestorState.clip) {
93 const TransformationMatrix transformMatrix = LocalToAncestorMatrix(( *it)->localTransformSpace(), ancestorState); 156 bool success = false;
157 const TransformationMatrix transformMatrix = localToAncestorMatrix(( *it)->localTransformSpace(), ancestorState, &success);
158 DCHECK(success);
94 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rec t()); 159 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rec t());
95 clip.intersect(mappedRect); 160 clip.intersect(mappedRect);
96 } 161 }
97 162
98 precomputedData.toAncestorClipRects.set(*it, clip); 163 precomputedData.toAncestorClipRects.set(*it, clip);
99 } 164 }
100 165
101 return precomputedData.toAncestorClipRects.find(localState.clip)->value; 166 return precomputedData.toAncestorClipRects.find(localState.clip.get())->valu e;
102 } 167 }
103 168
104 const TransformationMatrix& GeometryMapper::LocalToAncestorMatrix( 169 const TransformationMatrix& GeometryMapper::localToAncestorMatrix(
105 const TransformPaintPropertyNode* localTransformNode, 170 const TransformPaintPropertyNode* localTransformNode,
106 const PropertyTreeState& ancestorState) { 171 const PropertyTreeState& ancestorState, bool* success) {
107 PrecomputedDataForAncestor& precomputedData = GetPrecomputedDataForAncestor( ancestorState); 172 PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor( ancestorState);
108 173
109 const TransformPaintPropertyNode* transformNode = localTransformNode; 174 const TransformPaintPropertyNode* transformNode = localTransformNode;
110 Vector<const TransformPaintPropertyNode*> intermediateNodes; 175 Vector<const TransformPaintPropertyNode*> intermediateNodes;
111 TransformationMatrix transformMatrix; 176 TransformationMatrix transformMatrix;
112 177
113 bool found = false; 178 bool found = false;
114 // Iterate over the path from localTransformNode to ancestorState.transform. Stop if we've found a memoized (precomputed) transform 179 // Iterate over the path from localTransformNode to ancestorState.transform. Stop if we've found a memoized (precomputed) transform
115 // for any particular node. 180 // for any particular node.
116 while (transformNode) { 181 while (transformNode) {
117 auto it = precomputedData.toAncestorTransforms.find(transformNode); 182 auto it = precomputedData.toAncestorTransforms.find(transformNode);
118 if (it != precomputedData.toAncestorTransforms.end()) { 183 if (it != precomputedData.toAncestorTransforms.end()) {
119 transformMatrix = it->value; 184 transformMatrix = it->value;
120 found = true; 185 found = true;
121 break; 186 break;
122 } 187 }
123 188
124 intermediateNodes.append(transformNode); 189 intermediateNodes.append(transformNode);
125 190
126 if (transformNode == ancestorState.transform) 191 if (transformNode == ancestorState.transform)
127 break; 192 break;
128 193
129 transformNode = transformNode->parent(); 194 transformNode = transformNode->parent();
130 } 195 }
131 // It's illegal to ask for a local-to-ancestor matrix when the ancestor is n ot an ancestor. 196 if (!found && transformNode != ancestorState.transform) {
132 DCHECK(transformNode == ancestorState.transform || found); 197 *success = false;
198 return m_identity;
pdr. 2016/07/01 18:39:40 Instead of using a member, you can use a static li
chrishtr 2016/07/01 22:01:12 That doesn't work, because it requires a global co
199 }
133 200
134 // Iterate down from the top intermediate node found in the previous loop, c omputing and memoizing transforms as we go. 201 // Iterate down from the top intermediate node found in the previous loop, c omputing and memoizing transforms as we go.
135 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); i t++) { 202 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); i t++) {
136 if ((*it) != ancestorState.transform) { 203 if ((*it) != ancestorState.transform) {
137 TransformationMatrix localTransformMatrix = (*it)->matrix(); 204 TransformationMatrix localTransformMatrix = (*it)->matrix();
138 localTransformMatrix.applyTransformOrigin((*it)->origin()); 205 localTransformMatrix.applyTransformOrigin((*it)->origin());
139 transformMatrix = localTransformMatrix * transformMatrix; 206 transformMatrix = localTransformMatrix * transformMatrix;
140 } 207 }
141 208
142 precomputedData.toAncestorTransforms.set(*it, transformMatrix); 209 precomputedData.toAncestorTransforms.set(*it, transformMatrix);
143 } 210 }
211 *success = true;
144 return precomputedData.toAncestorTransforms.find(localTransformNode)->value; 212 return precomputedData.toAncestorTransforms.find(localTransformNode)->value;
145 } 213 }
146 214
147 } // namespace blink 215 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698