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

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"
pdr. 2016/07/01 22:56:26 No longer needed
chrishtr 2016/07/01 23:01:14 Done.
11 12
12 namespace blink { 13 namespace blink {
13 14
14 FloatRect GeometryMapper::LocalToVisualRectInAncestorSpace( 15 FloatRect GeometryMapper::mapToVisualRectInDestinationSpace(const FloatRect& rec t,
16 const PropertyTreeState& sourceState,
17 const PropertyTreeState& destinationState,
18 bool& success)
19 {
20 FloatRect result = localToVisualRectInAncestorSpace(rect, sourceState, desti nationState, success);
21 if (success)
22 return result;
23
24 // TODO(chrishtr): fixed const-ness here.
25 RefPtr<TransformPaintPropertyNode> lcaTransform = const_cast<TransformPaintP ropertyNode*>(propertyTreeNearestCommonAncestor<TransformPaintPropertyNode>(sour ceState.transform.get(), destinationState.transform.get()));
26 DCHECK(lcaTransform.get());
27 PropertyTreeState lcaState = sourceState;
28 lcaState.transform = lcaTransform;
29
30 result = localToAncestorMatrix(sourceState.transform.get(), lcaState, succes s).mapRect(rect);
31 DCHECK(success);
32
33 const TransformationMatrix& destinationToLca = localToAncestorMatrix(destina tionState.transform.get(), lcaState, success);
34 DCHECK(success);
35 if (destinationToLca.isInvertible()) {
36 success = true;
37 return destinationToLca.inverse().mapRect(result);
pdr. 2016/07/01 22:56:26 Do we need to intersect clip rects along the way l
chrishtr 2016/07/01 23:01:14 We basically give up on clipping at this point, be
38 }
39 success = false;
40 return rect;
41 }
42
43 FloatRect GeometryMapper::localToVisualRectInAncestorSpace(
15 const FloatRect& rect, 44 const FloatRect& rect,
16 const PropertyTreeState& localState, 45 const PropertyTreeState& localState,
17 const PropertyTreeState& ancestorState) 46 const PropertyTreeState& ancestorState, bool& success)
18 { 47 {
19 const auto transformMatrix = LocalToAncestorMatrix(localState.transform, anc estorState); 48 const auto transformMatrix = localToAncestorMatrix(localState.transform.get( ), ancestorState, success);
49 if (!success)
50 return rect;
51
20 FloatRect mappedRect = transformMatrix.mapRect(rect); 52 FloatRect mappedRect = transformMatrix.mapRect(rect);
21 53
22 const auto clipRect = LocalToAncestorClipRect(localState, ancestorState); 54 const auto clipRect = localToAncestorClipRect(localState, ancestorState);
23 55
24 mappedRect.intersect(clipRect); 56 mappedRect.intersect(clipRect);
25 return mappedRect; 57 return mappedRect;
26 } 58 }
27 59
28 FloatRect GeometryMapper::LocalToAncestorRect( 60 FloatRect GeometryMapper::localToAncestorRect(
29 const FloatRect& rect, 61 const FloatRect& rect,
30 const PropertyTreeState& localState, 62 const PropertyTreeState& localState,
31 const PropertyTreeState& ancestorState) 63 const PropertyTreeState& ancestorState,
64 bool& success)
32 { 65 {
33 const auto transformMatrix = LocalToAncestorMatrix(localState.transform, anc estorState); 66 const auto transformMatrix = localToAncestorMatrix(localState.transform.get( ), ancestorState, success);
67 if (!success)
68 return rect;
34 return transformMatrix.mapRect(rect); 69 return transformMatrix.mapRect(rect);
35 } 70 }
36 71
37 FloatRect GeometryMapper::AncestorToLocalRect( 72 FloatRect GeometryMapper::ancestorToLocalRect(
38 const FloatRect& rect, 73 const FloatRect& rect,
39 const PropertyTreeState& localState, 74 const PropertyTreeState& localState,
40 const PropertyTreeState& ancestorState, bool* success) 75 const PropertyTreeState& ancestorState, bool& success)
41 { 76 {
42 const auto& transformMatrix = LocalToAncestorMatrix(localState.transform, an cestorState); 77 const auto& transformMatrix = localToAncestorMatrix(localState.transform.get (), ancestorState, success);
78 if (!success)
79 return rect;
80
43 if (!transformMatrix.isInvertible()) { 81 if (!transformMatrix.isInvertible()) {
44 *success = false; 82 success = false;
45 return FloatRect(); 83 return rect;
46 } 84 }
47 *success = true; 85 success = true;
48 86
49 // TODO(chrishtr): Cache the inverse? 87 // TODO(chrishtr): Cache the inverse?
50 return transformMatrix.inverse().mapRect(rect); 88 return transformMatrix.inverse().mapRect(rect);
51 } 89 }
52 90
53 PrecomputedDataForAncestor& GeometryMapper::GetPrecomputedDataForAncestor(const PropertyTreeState& ancestorState) 91 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor(const PropertyTreeState& ancestorState)
54 { 92 {
55 auto addResult = m_data.add(ancestorState.transform, nullptr); 93 auto addResult = m_data.add(ancestorState.transform.get(), nullptr);
56 if (addResult.isNewEntry) 94 if (addResult.isNewEntry)
57 addResult.storedValue->value = PrecomputedDataForAncestor::create(); 95 addResult.storedValue->value = PrecomputedDataForAncestor::create();
58 return *addResult.storedValue->value; 96 return *addResult.storedValue->value;
59 } 97 }
60 98
61 const FloatRect& GeometryMapper::LocalToAncestorClipRect( 99 const FloatRect& GeometryMapper::localToAncestorClipRect(
62 const PropertyTreeState& localState, 100 const PropertyTreeState& localState,
63 const PropertyTreeState& ancestorState) 101 const PropertyTreeState& ancestorState)
64 { 102 {
65 PrecomputedDataForAncestor& precomputedData = GetPrecomputedDataForAncestor( ancestorState); 103 PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor( ancestorState);
66 const ClipPaintPropertyNode* clipNode = localState.clip; 104 const ClipPaintPropertyNode* clipNode = localState.clip.get();
67 Vector<const ClipPaintPropertyNode*> intermediateNodes; 105 Vector<const ClipPaintPropertyNode*> intermediateNodes;
68 FloatRect clip(LayoutRect::infiniteIntRect()); 106 FloatRect clip(LayoutRect::infiniteIntRect());
69 107
70 bool found = false; 108 bool found = false;
71 // Iterate over the path from localState.clip to ancestorState.clip. Stop if we've found a memoized (precomputed) clip 109 // Iterate over the path from localState.clip to ancestorState.clip. Stop if we've found a memoized (precomputed) clip
72 // for any particular node. 110 // for any particular node.
73 while (clipNode) { 111 while (clipNode) {
74 auto it = precomputedData.toAncestorClipRects.find(clipNode); 112 auto it = precomputedData.toAncestorClipRects.find(clipNode);
75 if (it != precomputedData.toAncestorClipRects.end()) { 113 if (it != precomputedData.toAncestorClipRects.end()) {
76 clip = it->value; 114 clip = it->value;
77 found = true; 115 found = true;
78 break; 116 break;
79 } 117 }
80 intermediateNodes.append(clipNode); 118 intermediateNodes.append(clipNode);
81 119
82 if (clipNode == ancestorState.clip) 120 if (clipNode == ancestorState.clip)
83 break; 121 break;
84 122
85 clipNode = clipNode->parent(); 123 clipNode = clipNode->parent();
86 } 124 }
87 // It's illegal to ask for a local-to-ancestor clip when the ancestor is not an ancestor. 125 // It's illegal to ask for a local-to-ancestor clip when the ancestor is not an ancestor.
88 DCHECK(clipNode == ancestorState.clip || found); 126 DCHECK(clipNode == ancestorState.clip || found);
89 127
90 // Iterate down from the top intermediate node found in the previous loop, c omputing and memoizing clip rects as we go. 128 // 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) { 129 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); + +it) {
92 if ((*it) != ancestorState.clip) { 130 if ((*it) != ancestorState.clip) {
93 const TransformationMatrix transformMatrix = LocalToAncestorMatrix(( *it)->localTransformSpace(), ancestorState); 131 bool success = false;
132 const TransformationMatrix transformMatrix = localToAncestorMatrix(( *it)->localTransformSpace(), ancestorState, success);
133 DCHECK(success);
94 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rec t()); 134 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rec t());
95 clip.intersect(mappedRect); 135 clip.intersect(mappedRect);
96 } 136 }
97 137
98 precomputedData.toAncestorClipRects.set(*it, clip); 138 precomputedData.toAncestorClipRects.set(*it, clip);
99 } 139 }
100 140
101 return precomputedData.toAncestorClipRects.find(localState.clip)->value; 141 return precomputedData.toAncestorClipRects.find(localState.clip.get())->valu e;
102 } 142 }
103 143
104 const TransformationMatrix& GeometryMapper::LocalToAncestorMatrix( 144
145 const TransformationMatrix& GeometryMapper::localToAncestorMatrix(
105 const TransformPaintPropertyNode* localTransformNode, 146 const TransformPaintPropertyNode* localTransformNode,
106 const PropertyTreeState& ancestorState) { 147 const PropertyTreeState& ancestorState, bool& success) {
107 PrecomputedDataForAncestor& precomputedData = GetPrecomputedDataForAncestor( ancestorState); 148 PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor( ancestorState);
108 149
109 const TransformPaintPropertyNode* transformNode = localTransformNode; 150 const TransformPaintPropertyNode* transformNode = localTransformNode;
110 Vector<const TransformPaintPropertyNode*> intermediateNodes; 151 Vector<const TransformPaintPropertyNode*> intermediateNodes;
111 TransformationMatrix transformMatrix; 152 TransformationMatrix transformMatrix;
112 153
113 bool found = false; 154 bool found = false;
114 // Iterate over the path from localTransformNode to ancestorState.transform. Stop if we've found a memoized (precomputed) transform 155 // Iterate over the path from localTransformNode to ancestorState.transform. Stop if we've found a memoized (precomputed) transform
115 // for any particular node. 156 // for any particular node.
116 while (transformNode) { 157 while (transformNode) {
117 auto it = precomputedData.toAncestorTransforms.find(transformNode); 158 auto it = precomputedData.toAncestorTransforms.find(transformNode);
118 if (it != precomputedData.toAncestorTransforms.end()) { 159 if (it != precomputedData.toAncestorTransforms.end()) {
119 transformMatrix = it->value; 160 transformMatrix = it->value;
120 found = true; 161 found = true;
121 break; 162 break;
122 } 163 }
123 164
124 intermediateNodes.append(transformNode); 165 intermediateNodes.append(transformNode);
125 166
126 if (transformNode == ancestorState.transform) 167 if (transformNode == ancestorState.transform)
127 break; 168 break;
128 169
129 transformNode = transformNode->parent(); 170 transformNode = transformNode->parent();
130 } 171 }
131 // It's illegal to ask for a local-to-ancestor matrix when the ancestor is n ot an ancestor. 172 if (!found && transformNode != ancestorState.transform) {
132 DCHECK(transformNode == ancestorState.transform || found); 173 success = false;
174 return m_identity;
175 }
133 176
134 // Iterate down from the top intermediate node found in the previous loop, c omputing and memoizing transforms as we go. 177 // 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++) { 178 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); i t++) {
136 if ((*it) != ancestorState.transform) { 179 if ((*it) != ancestorState.transform) {
137 TransformationMatrix localTransformMatrix = (*it)->matrix(); 180 TransformationMatrix localTransformMatrix = (*it)->matrix();
138 localTransformMatrix.applyTransformOrigin((*it)->origin()); 181 localTransformMatrix.applyTransformOrigin((*it)->origin());
139 transformMatrix = localTransformMatrix * transformMatrix; 182 transformMatrix = localTransformMatrix * transformMatrix;
140 } 183 }
141 184
142 precomputedData.toAncestorTransforms.set(*it, transformMatrix); 185 precomputedData.toAncestorTransforms.set(*it, transformMatrix);
143 } 186 }
187 success = true;
144 return precomputedData.toAncestorTransforms.find(localTransformNode)->value; 188 return precomputedData.toAncestorTransforms.find(localTransformNode)->value;
145 } 189 }
146 190
147 } // namespace blink 191 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698