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

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

Issue 1973343003: Initial implementation of GeometryMapper (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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "platform/graphics/paint/GeometryMapper.h"
6
7 #include "platform/geometry/GeometryTestHelpers.h"
8 #include "platform/geometry/LayoutRect.h"
9 #include "platform/graphics/paint/ClipPaintPropertyNode.h"
10 #include "platform/graphics/paint/EffectPaintPropertyNode.h"
11 #include "platform/graphics/paint/TransformPaintPropertyNode.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace blink {
15
16 class GeometryMapperTest : public ::testing::Test {
17 public:
18 RefPtr<TransformPaintPropertyNode> rootTransformNode;
19 RefPtr<ClipPaintPropertyNode> rootClipNode;
20 RefPtr<EffectPaintPropertyNode> rootEffectNode;
21
22 std::unique_ptr<GeometryMapper> geometryMapper;
23
24 PropertyTreeState rootPropertyTreeState()
25 {
26 PropertyTreeState state(rootTransformNode.get(), rootClipNode.get(), roo tEffectNode.get());
27 return state;
28 }
29
30 PrecomputedDataForAncestor& GetPrecomputedDataForAncestor(const PropertyTree State& propertyTreeState)
31 {
32 return geometryMapper->GetPrecomputedDataForAncestor(propertyTreeState);
33 }
34
35 private:
36 void SetUp() override
37 {
38 rootTransformNode = TransformPaintPropertyNode::create(TransformationMat rix(), FloatPoint3D(), nullptr);
39 rootClipNode = ClipPaintPropertyNode::create(rootTransformNode, FloatRou ndedRect(LayoutRect::infiniteIntRect()), nullptr);
40 rootEffectNode = EffectPaintPropertyNode::create(1.0, nullptr);
41 geometryMapper = wrapUnique(new GeometryMapper());
42 }
43
44 void TearDown() override
45 {
46 geometryMapper.reset();
47 }
48 };
49
50 const static float kTestEpsilon = 1e-6;
51
52 #define EXPECT_RECT_EQ(expected, actual) \
53 do { \
54 const FloatRect& actualRect = actual; \
55 EXPECT_TRUE(GeometryTest::ApproximatelyEqual(expected.x(), actualRect.x(), k TestEpsilon)) << "actual: " << actualRect.x() << ", expected: " << expected.x(); \
56 EXPECT_TRUE(GeometryTest::ApproximatelyEqual(expected.y(), actualRect.y(), k TestEpsilon)) << "actual: " << actualRect.y() << ", expected: " << expected.y(); \
57 EXPECT_TRUE(GeometryTest::ApproximatelyEqual(expected.width(), actualRect.wi dth(), kTestEpsilon)) << "actual: " << actualRect.width() << ", expected: " << e xpected.width(); \
58 EXPECT_TRUE(GeometryTest::ApproximatelyEqual(expected.height(), actualRect.h eight(), kTestEpsilon)) << "actual: " << actualRect.height() << ", expected: " < < expected.height(); \
59 } while (false)
60
61 #define CHECK_MAPPINGS(inputRect, expectedVisualRect, expectedTransformedRect, e xpectedTransformToAncestor, expectedClipInAncestorSpace, localPropertyTreeState, ancestorPropertyTreeState) \
62 do { \
63 EXPECT_RECT_EQ(expectedVisualRect, \
64 geometryMapper->LocalToVisualRectInAncestorSpace(inputRect, localPropert yTreeState, ancestorPropertyTreeState)); \
65 EXPECT_RECT_EQ(expectedTransformedRect, \
66 geometryMapper->LocalToAncestorRect(inputRect, localPropertyTreeState, a ncestorPropertyTreeState)); \
67 EXPECT_EQ(expectedTransformToAncestor, GetPrecomputedDataForAncestor(ancesto rPropertyTreeState).toAncestorTransforms.get(localPropertyTreeState.transform)); \
68 EXPECT_EQ(expectedClipInAncestorSpace, GetPrecomputedDataForAncestor(ancesto rPropertyTreeState).toAncestorClipRects.get(localPropertyTreeState.clip)); \
69 } while (false)
70
71 TEST_F(GeometryMapperTest, Root)
72 {
73 FloatRect input(0, 0, 100, 100);
74
75 CHECK_MAPPINGS(input, input, input, rootTransformNode->matrix(), rootClipNod e->clipRect().rect(), rootPropertyTreeState(), rootPropertyTreeState());
76 }
77
78 TEST_F(GeometryMapperTest, IdentityTransform)
79 {
80 RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::c reate(TransformationMatrix(), FloatPoint3D(), rootPropertyTreeState().transform) ;
81 PropertyTreeState localState = rootPropertyTreeState();
82 localState.transform = transform.get();
83
84 FloatRect input(0, 0, 100, 100);
85
86 CHECK_MAPPINGS(input, input, input, transform->matrix(), rootClipNode->clipR ect().rect(), localState, rootPropertyTreeState());
87 }
88
89 TEST_F(GeometryMapperTest, TranslationTransform)
90 {
91 TransformationMatrix transformMatrix;
92 transformMatrix.translate(20, 10);
93 RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::c reate(transformMatrix, FloatPoint3D(), rootPropertyTreeState().transform);
94 PropertyTreeState localState = rootPropertyTreeState();
95 localState.transform = transform.get();
96
97 FloatRect input(0, 0, 100, 100);
98 FloatRect output = transformMatrix.mapRect(input);
99
100 CHECK_MAPPINGS(input, output, output, transform->matrix(), rootClipNode->cli pRect().rect(), localState, rootPropertyTreeState());
101
102 bool success = false;
103 EXPECT_RECT_EQ(input,
104 geometryMapper->AncestorToLocalRect(output, localState, rootPropertyTree State(), &success));
105 EXPECT_TRUE(success);
106 }
107
108 TEST_F(GeometryMapperTest, RotationAndScaleTransform)
109 {
110 TransformationMatrix transformMatrix;
111 transformMatrix.rotate(45);
112 transformMatrix.scale(2);
113 RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::c reate(transformMatrix, FloatPoint3D(0, 0, 0), rootPropertyTreeState().transform) ;
114 PropertyTreeState localState = rootPropertyTreeState();
115 localState.transform = transform.get();
116
117 FloatRect input(0, 0, 100, 100);
118 FloatRect output = transformMatrix.mapRect(input);
119
120 CHECK_MAPPINGS(input, output, output, transformMatrix, rootClipNode->clipRec t().rect(), localState, rootPropertyTreeState());
121 }
122
123 TEST_F(GeometryMapperTest, RotationAndScaleTransformWithTransformOrigin)
124 {
125 TransformationMatrix transformMatrix;
126 transformMatrix.rotate(45);
127 transformMatrix.scale(2);
128 RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::c reate(transformMatrix, FloatPoint3D(50, 50, 0), rootPropertyTreeState().transfor m);
129 PropertyTreeState localState = rootPropertyTreeState();
130 localState.transform = transform.get();
131
132 FloatRect input(0, 0, 100, 100);
133 transformMatrix.applyTransformOrigin(50, 50, 0);
134 FloatRect output = transformMatrix.mapRect(input);
135
136 CHECK_MAPPINGS(input, output, output, transformMatrix, rootClipNode->clipRec t().rect(), localState, rootPropertyTreeState());
137 }
138
139 TEST_F(GeometryMapperTest, NestedTransforms)
140 {
141 TransformationMatrix rotateTransform;
142 rotateTransform.rotate(45);
143 RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode:: create(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
144
145 TransformationMatrix scaleTransform;
146 scaleTransform.scale(2);
147 RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode:: create(scaleTransform, FloatPoint3D(), transform1);
148
149 PropertyTreeState localState = rootPropertyTreeState();
150 localState.transform = transform2.get();
151
152 FloatRect input(0, 0, 100, 100);
153 TransformationMatrix final = rotateTransform * scaleTransform;
154 FloatRect output = final.mapRect(input);
155
156 CHECK_MAPPINGS(input, output, output, final, rootClipNode->clipRect().rect() , localState, rootPropertyTreeState());
157
158 // Check the cached matrix for the intermediate transform.
159 EXPECT_EQ(rotateTransform, GetPrecomputedDataForAncestor(rootPropertyTreeSta te()).toAncestorTransforms.get(transform1.get()));
160 }
161
162 TEST_F(GeometryMapperTest, NestedTransformsIntermediateDestination)
163 {
164 TransformationMatrix rotateTransform;
165 rotateTransform.rotate(45);
166 RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode:: create(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
167
168 TransformationMatrix scaleTransform;
169 scaleTransform.scale(2);
170 RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode:: create(scaleTransform, FloatPoint3D(), transform1);
171
172 PropertyTreeState localState = rootPropertyTreeState();
173 localState.transform = transform2.get();
174
175 PropertyTreeState intermediateState = rootPropertyTreeState();
176 intermediateState.transform = transform1.get();
177
178 FloatRect input(0, 0, 100, 100);
179 FloatRect output = scaleTransform.mapRect(input);
180
181 CHECK_MAPPINGS(input, output, output, scaleTransform, rootClipNode->clipRect ().rect(), localState, intermediateState);
182 }
183
184 TEST_F(GeometryMapperTest, SimpleClip)
185 {
186 RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(rootTrans formNode, FloatRoundedRect(10, 10, 50, 50), rootClipNode);
187
188 PropertyTreeState localState = rootPropertyTreeState();
189 localState.clip = clip.get();
190
191 FloatRect input(0, 0, 100, 100);
192 FloatRect output(10, 10, 50, 50);
193
194 CHECK_MAPPINGS(
195 input, // Input
196 output, // Visual rect
197 input, // Transformed rect (not clipped).
198 rootTransformNode->matrix(), // Transform matrix to ancestor space
199 clip->clipRect().rect(), // Clip rect in ancestor space
200 localState, rootPropertyTreeState());
201 }
202
203 TEST_F(GeometryMapperTest, ClipBeforeTransform)
204 {
205 TransformationMatrix rotateTransform;
206 rotateTransform.rotate(45);
207 RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::c reate(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
208
209 RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(transform .get(), FloatRoundedRect(10, 10, 50, 50), rootClipNode);
210
211 PropertyTreeState localState = rootPropertyTreeState();
212 localState.clip = clip.get();
213 localState.transform = transform.get();
214
215 FloatRect input(0, 0, 100, 100);
216 FloatRect output(input);
217 output.intersect(clip->clipRect().rect());
218 output = rotateTransform.mapRect(output);
219
220 CHECK_MAPPINGS(
221 input, // Input
222 output, // Visual rect
223 rotateTransform.mapRect(input), // Transformed rect (not clipped).
224 rotateTransform, // Transform matrix to ancestor space
225 rotateTransform.mapRect(clip->clipRect().rect()), // Clip rect in ancest or space
226 localState, rootPropertyTreeState());
227 }
228
229 TEST_F(GeometryMapperTest, ClipAfterTransform)
230 {
231 TransformationMatrix rotateTransform;
232 rotateTransform.rotate(45);
233 RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::c reate(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
234
235 RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(rootTrans formNode.get(), FloatRoundedRect(10, 10, 200, 200), rootClipNode);
236
237 PropertyTreeState localState = rootPropertyTreeState();
238 localState.clip = clip.get();
239 localState.transform = transform.get();
240
241 FloatRect input(0, 0, 100, 100);
242 FloatRect output(input);
243 output = rotateTransform.mapRect(output);
244 output.intersect(clip->clipRect().rect());
245
246 CHECK_MAPPINGS(
247 input, // Input
248 output, // Visual rect
249 rotateTransform.mapRect(input), // Transformed rect (not clipped)
250 rotateTransform, // Transform matrix to ancestor space
251 clip->clipRect().rect(), // Clip rect in ancestor space
252 localState, rootPropertyTreeState());
253 }
254
255 TEST_F(GeometryMapperTest, TwoClipsWithTransformBetween)
256 {
257 RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(rootTran sformNode.get(), FloatRoundedRect(10, 10, 200, 200), rootClipNode);
258
259 TransformationMatrix rotateTransform;
260 rotateTransform.rotate(45);
261 RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::c reate(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
262
263 RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create(transfor m.get(), FloatRoundedRect(10, 10, 200, 200), clip1.get());
264
265 FloatRect input(0, 0, 100, 100);
266
267 {
268 PropertyTreeState localState = rootPropertyTreeState();
269 localState.clip = clip1.get();
270 localState.transform = transform.get();
271
272 FloatRect output(input);
273 output = rotateTransform.mapRect(output);
274 output.intersect(clip1->clipRect().rect());
275
276 CHECK_MAPPINGS(
277 input, // Input
278 output, // Visual rect
279 rotateTransform.mapRect(input), // Transformed rect (not clipped)
280 rotateTransform, // Transform matrix to ancestor space
281 clip1->clipRect().rect(), // Clip rect in ancestor space
282 localState, rootPropertyTreeState());
283 }
284
285 {
286 PropertyTreeState localState = rootPropertyTreeState();
287 localState.clip = clip2.get();
288 localState.transform = transform.get();
289
290
291 FloatRect mappedClip = rotateTransform.mapRect(clip2->clipRect().rect()) ;
292 mappedClip.intersect(clip1->clipRect().rect());
293
294 // All clips are performed in the space of the ancestor. In cases such a s this, this means the
295 // clip is a bit lossy.
296 FloatRect output(input);
297 // Map to transformed rect in ancestor space.
298 output = rotateTransform.mapRect(output);
299 // Intersect with all clips between local and ancestor, independently ma pped to ancestor space.
300 output.intersect(mappedClip);
301
302 CHECK_MAPPINGS(
303 input, // Input
304 output, // Visual rect
305 rotateTransform.mapRect(input), // Transformed rect (not clipped)
306 rotateTransform, // Transform matrix to ancestor space
307 mappedClip, // Clip rect in ancestor space
308 localState, rootPropertyTreeState());
309 }
310 }
311
312 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698