blob: 7cadf0187113ecff061bb01fb0698be471d9ea39 [file] [log] [blame]
robertphillips@google.com5985e7c2012-11-29 13:24:55 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Test.h"
scroggo@google.com20e3cd22013-11-05 15:54:42 +00009#include "SkMatrix.h"
robertphillips@google.com5985e7c2012-11-29 13:24:55 +000010#include "SkRRect.h"
11
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000012static const SkScalar kWidth = 100.0f;
13static const SkScalar kHeight = 100.0f;
robertphillips@google.com5985e7c2012-11-29 13:24:55 +000014
mike@reedtribe.orgbcbef572012-12-23 23:11:21 +000015static void test_inset(skiatest::Reporter* reporter) {
16 SkRRect rr, rr2;
17 SkRect r = { 0, 0, 100, 100 };
18
19 rr.setRect(r);
20 rr.inset(-20, -20, &rr2);
21 REPORTER_ASSERT(reporter, rr2.isRect());
22
23 rr.inset(20, 20, &rr2);
24 REPORTER_ASSERT(reporter, rr2.isRect());
skia.committer@gmail.com1a60dab2012-12-24 02:01:25 +000025
mike@reedtribe.orgbcbef572012-12-23 23:11:21 +000026 rr.inset(r.width()/2, r.height()/2, &rr2);
27 REPORTER_ASSERT(reporter, rr2.isEmpty());
28
29 rr.setRectXY(r, 20, 20);
30 rr.inset(19, 19, &rr2);
31 REPORTER_ASSERT(reporter, rr2.isSimple());
32 rr.inset(20, 20, &rr2);
33 REPORTER_ASSERT(reporter, rr2.isRect());
34}
35
robertphillips@google.com5985e7c2012-11-29 13:24:55 +000036// Test out the basic API entry points
37static void test_round_rect_basic(skiatest::Reporter* reporter) {
38 // Test out initialization methods
reed@google.com2b57dc62013-01-08 13:23:32 +000039 SkPoint zeroPt = { 0, 0 };
robertphillips@google.com5985e7c2012-11-29 13:24:55 +000040 SkRRect empty;
skia.committer@gmail.comc3d7d902012-11-30 02:01:24 +000041
robertphillips@google.com5985e7c2012-11-29 13:24:55 +000042 empty.setEmpty();
43
44 REPORTER_ASSERT(reporter, SkRRect::kEmpty_Type == empty.type());
45 REPORTER_ASSERT(reporter, empty.rect().isEmpty());
46
47 for (int i = 0; i < 4; ++i) {
48 REPORTER_ASSERT(reporter, zeroPt == empty.radii((SkRRect::Corner) i));
49 }
50
51 //----
52 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
53
54 SkRRect rr1;
55 rr1.setRect(rect);
56
57 REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr1.type());
58 REPORTER_ASSERT(reporter, rr1.rect() == rect);
59
60 for (int i = 0; i < 4; ++i) {
61 REPORTER_ASSERT(reporter, zeroPt == rr1.radii((SkRRect::Corner) i));
62 }
63
64 //----
65 SkPoint halfPoint = { SkScalarHalf(kWidth), SkScalarHalf(kHeight) };
66 SkRRect rr2;
67 rr2.setOval(rect);
68
69 REPORTER_ASSERT(reporter, SkRRect::kOval_Type == rr2.type());
70 REPORTER_ASSERT(reporter, rr2.rect() == rect);
71
72 for (int i = 0; i < 4; ++i) {
skia.committer@gmail.comc3d7d902012-11-30 02:01:24 +000073 REPORTER_ASSERT(reporter,
robertphillips@google.com5985e7c2012-11-29 13:24:55 +000074 rr2.radii((SkRRect::Corner) i).equalsWithinTolerance(halfPoint));
75 }
76
77 //----
78 SkPoint p = { 5, 5 };
79 SkRRect rr3;
80 rr3.setRectXY(rect, p.fX, p.fY);
81
82 REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr3.type());
83 REPORTER_ASSERT(reporter, rr3.rect() == rect);
84
85 for (int i = 0; i < 4; ++i) {
86 REPORTER_ASSERT(reporter, p == rr3.radii((SkRRect::Corner) i));
87 }
skia.committer@gmail.comc3d7d902012-11-30 02:01:24 +000088
robertphillips@google.com5985e7c2012-11-29 13:24:55 +000089 //----
90 SkPoint radii[4] = { { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 } };
91
92 SkRRect rr4;
93 rr4.setRectRadii(rect, radii);
94
95 REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr4.type());
96 REPORTER_ASSERT(reporter, rr4.rect() == rect);
97
98 for (int i = 0; i < 4; ++i) {
99 REPORTER_ASSERT(reporter, radii[i] == rr4.radii((SkRRect::Corner) i));
100 }
101
102 //----
103 SkPoint radii2[4] = { { 0, 0 }, { 0, 0 }, { 50, 50 }, { 20, 50 } };
104
105 SkRRect rr5;
106 rr5.setRectRadii(rect, radii2);
107
108 REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr5.type());
109 REPORTER_ASSERT(reporter, rr5.rect() == rect);
110
111 for (int i = 0; i < 4; ++i) {
112 REPORTER_ASSERT(reporter, radii2[i] == rr5.radii((SkRRect::Corner) i));
113 }
114
115 // Test out == & !=
116 REPORTER_ASSERT(reporter, empty != rr3);
117 REPORTER_ASSERT(reporter, rr3 == rr4);
118 REPORTER_ASSERT(reporter, rr4 != rr5);
119}
120
121// Test out the cases when the RR degenerates to a rect
122static void test_round_rect_rects(skiatest::Reporter* reporter) {
123 SkRect r;
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000124
125 //----
126 SkRRect empty;
skia.committer@gmail.comc3d7d902012-11-30 02:01:24 +0000127
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000128 empty.setEmpty();
129
130 REPORTER_ASSERT(reporter, SkRRect::kEmpty_Type == empty.type());
131 r = empty.rect();
132 REPORTER_ASSERT(reporter, 0 == r.fLeft && 0 == r.fTop && 0 == r.fRight && 0 == r.fBottom);
133
134 //----
135 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
136 SkRRect rr1;
137 rr1.setRectXY(rect, 0, 0);
138
139 REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr1.type());
140 r = rr1.rect();
141 REPORTER_ASSERT(reporter, rect == r);
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000142
143 //----
144 SkPoint radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
145
146 SkRRect rr2;
147 rr2.setRectRadii(rect, radii);
148
149 REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr2.type());
150 r = rr2.rect();
151 REPORTER_ASSERT(reporter, rect == r);
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000152
153 //----
154 SkPoint radii2[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
155
156 SkRRect rr3;
157 rr3.setRectRadii(rect, radii2);
158 REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr3.type());
159}
160
161// Test out the cases when the RR degenerates to an oval
162static void test_round_rect_ovals(skiatest::Reporter* reporter) {
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000163 //----
164 SkRect oval;
165 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
166 SkRRect rr1;
167 rr1.setRectXY(rect, SkScalarHalf(kWidth), SkScalarHalf(kHeight));
168
169 REPORTER_ASSERT(reporter, SkRRect::kOval_Type == rr1.type());
170 oval = rr1.rect();
171 REPORTER_ASSERT(reporter, oval == rect);
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000172}
173
174// Test out the non-degenerate RR cases
175static void test_round_rect_general(skiatest::Reporter* reporter) {
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000176 //----
177 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
178 SkRRect rr1;
179 rr1.setRectXY(rect, 20, 20);
180
181 REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr1.type());
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000182
183 //----
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000184 SkPoint radii[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
185
186 SkRRect rr2;
187 rr2.setRectRadii(rect, radii);
188
189 REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr2.type());
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000190}
191
192// Test out questionable-parameter handling
193static void test_round_rect_iffy_parameters(skiatest::Reporter* reporter) {
194
195 // When the radii exceed the base rect they are proportionally scaled down
196 // to fit
197 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
198 SkPoint radii[4] = { { 50, 100 }, { 100, 50 }, { 50, 100 }, { 100, 50 } };
199
200 SkRRect rr1;
201 rr1.setRectRadii(rect, radii);
202
203 REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr1.type());
204
205 const SkPoint& p = rr1.radii(SkRRect::kUpperLeft_Corner);
206
207 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(p.fX, 33.33333f));
208 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(p.fY, 66.66666f));
209
210 // Negative radii should be capped at zero
211 SkRRect rr2;
212 rr2.setRectXY(rect, -10, -20);
213
214 REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr2.type());
215
216 const SkPoint& p2 = rr2.radii(SkRRect::kUpperLeft_Corner);
217
218 REPORTER_ASSERT(reporter, 0.0f == p2.fX);
219 REPORTER_ASSERT(reporter, 0.0f == p2.fY);
220}
221
robertphillips@google.com32c1b662013-04-25 12:23:00 +0000222// Move a small box from the start position by (stepX, stepY) 'numSteps' times
223// testing for containment in 'rr' at each step.
224static void test_direction(skiatest::Reporter* reporter, const SkRRect &rr,
skia.committer@gmail.com2cf444f2013-04-26 07:00:58 +0000225 SkScalar initX, int stepX, SkScalar initY, int stepY,
robertphillips@google.com32c1b662013-04-25 12:23:00 +0000226 int numSteps, const bool* contains) {
227 SkScalar x = initX, y = initY;
228 for (int i = 0; i < numSteps; ++i) {
skia.committer@gmail.com2cf444f2013-04-26 07:00:58 +0000229 SkRect test = SkRect::MakeXYWH(x, y,
230 stepX ? SkIntToScalar(stepX) : SK_Scalar1,
robertphillips@google.com32c1b662013-04-25 12:23:00 +0000231 stepY ? SkIntToScalar(stepY) : SK_Scalar1);
232 test.sort();
233
234 REPORTER_ASSERT(reporter, contains[i] == rr.contains(test));
235
236 x += stepX;
237 y += stepY;
238 }
239}
240
241// Exercise the RR's contains rect method
242static void test_round_rect_contains_rect(skiatest::Reporter* reporter) {
243
244 static const int kNumRRects = 4;
245 static const SkVector gRadii[kNumRRects][4] = {
246 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // rect
247 { { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 } }, // circle
248 { { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 } }, // simple
249 { { 0, 0 }, { 20, 20 }, { 10, 10 }, { 30, 30 } } // complex
250 };
251
252 SkRRect rrects[kNumRRects];
253 for (int i = 0; i < kNumRRects; ++i) {
254 rrects[i].setRectRadii(SkRect::MakeWH(40, 40), gRadii[i]);
255 }
256
257 // First test easy outs - boxes that are obviously out on
258 // each corner and edge
259 static const SkRect easyOuts[] = {
260 { -5, -5, 5, 5 }, // NW
261 { 15, -5, 20, 5 }, // N
262 { 35, -5, 45, 5 }, // NE
263 { 35, 15, 45, 20 }, // E
264 { 35, 45, 35, 45 }, // SE
265 { 15, 35, 20, 45 }, // S
266 { -5, 35, 5, 45 }, // SW
267 { -5, 15, 5, 20 } // W
268 };
skia.committer@gmail.com2cf444f2013-04-26 07:00:58 +0000269
robertphillips@google.com32c1b662013-04-25 12:23:00 +0000270 for (int i = 0; i < kNumRRects; ++i) {
271 for (size_t j = 0; j < SK_ARRAY_COUNT(easyOuts); ++j) {
272 REPORTER_ASSERT(reporter, !rrects[i].contains(easyOuts[j]));
273 }
274 }
275
skia.committer@gmail.com2cf444f2013-04-26 07:00:58 +0000276 // Now test non-trivial containment. For each compass
277 // point walk a 1x1 rect in from the edge of the bounding
robertphillips@google.com32c1b662013-04-25 12:23:00 +0000278 // rect
279 static const int kNumSteps = 15;
280 bool answers[kNumRRects][8][kNumSteps] = {
281 // all the test rects are inside the degenerate rrect
282 {
283 // rect
284 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
285 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
286 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
287 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
288 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
289 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
290 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
291 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
292 },
293 // for the circle we expect 6 blocks to be out on the
skia.committer@gmail.com2cf444f2013-04-26 07:00:58 +0000294 // corners (then the rest in) and only the first block
295 // out on the vertical and horizontal axes (then
robertphillips@google.com32c1b662013-04-25 12:23:00 +0000296 // the rest in)
297 {
298 // circle
299 { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
300 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
301 { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
302 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
303 { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
304 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
305 { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
306 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
307 },
308 // for the simple round rect we expect 3 out on
309 // the corners (then the rest in) and no blocks out
310 // on the vertical and horizontal axes
311 {
312 // simple RR
313 { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
314 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
315 { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
316 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
317 { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
318 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
319 { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
320 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
321 },
322 // for the complex case the answer is different for each direction
323 {
324 // complex RR
325 // all in for NW (rect) corner (same as rect case)
326 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
327 // only first block out for N (same as circle case)
328 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
329 // first 6 blocks out for NE (same as circle case)
330 { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
331 // only first block out for E (same as circle case)
332 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
333 // first 3 blocks out for SE (same as simple case)
334 { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
335 // first two blocks out for S
336 { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
337 // first 9 blocks out for SW
338 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
339 // first two blocks out for W (same as S)
340 { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
341 }
342 };
343
344 for (int i = 0; i < kNumRRects; ++i) {
345 test_direction(reporter, rrects[i], 0, 1, 0, 1, kNumSteps, answers[i][0]); // NW
346 test_direction(reporter, rrects[i], 19.5f, 0, 0, 1, kNumSteps, answers[i][1]); // N
347 test_direction(reporter, rrects[i], 40, -1, 0, 1, kNumSteps, answers[i][2]); // NE
348 test_direction(reporter, rrects[i], 40, -1, 19.5f, 0, kNumSteps, answers[i][3]); // E
349 test_direction(reporter, rrects[i], 40, -1, 40, -1, kNumSteps, answers[i][4]); // SE
350 test_direction(reporter, rrects[i], 19.5f, 0, 40, -1, kNumSteps, answers[i][5]); // S
351 test_direction(reporter, rrects[i], 0, 1, 40, -1, kNumSteps, answers[i][6]); // SW
352 test_direction(reporter, rrects[i], 0, 1, 19.5f, 0, kNumSteps, answers[i][7]); // W
353 }
354}
355
scroggo@google.com20e3cd22013-11-05 15:54:42 +0000356// Called for a matrix that should cause SkRRect::transform to fail.
357static void assert_transform_failure(skiatest::Reporter* reporter, const SkRRect& orig,
358 const SkMatrix& matrix) {
359 // The test depends on the fact that the original is not empty.
360 SkASSERT(!orig.isEmpty());
361 SkRRect dst;
362 dst.setEmpty();
363
364 const SkRRect copyOfDst = dst;
365 const SkRRect copyOfOrig = orig;
366 bool success = orig.transform(matrix, &dst);
367 // This transform should fail.
368 REPORTER_ASSERT(reporter, !success);
369 // Since the transform failed, dst should be unchanged.
370 REPORTER_ASSERT(reporter, copyOfDst == dst);
371 // original should not be modified.
372 REPORTER_ASSERT(reporter, copyOfOrig == orig);
373 REPORTER_ASSERT(reporter, orig != dst);
374}
375
376#define GET_RADII \
377 const SkVector& origUL = orig.radii(SkRRect::kUpperLeft_Corner); \
378 const SkVector& origUR = orig.radii(SkRRect::kUpperRight_Corner); \
379 const SkVector& origLR = orig.radii(SkRRect::kLowerRight_Corner); \
380 const SkVector& origLL = orig.radii(SkRRect::kLowerLeft_Corner); \
381 const SkVector& dstUL = dst.radii(SkRRect::kUpperLeft_Corner); \
382 const SkVector& dstUR = dst.radii(SkRRect::kUpperRight_Corner); \
383 const SkVector& dstLR = dst.radii(SkRRect::kLowerRight_Corner); \
384 const SkVector& dstLL = dst.radii(SkRRect::kLowerLeft_Corner)
385
386// Called to test various transforms on a single SkRRect.
387static void test_transform_helper(skiatest::Reporter* reporter, const SkRRect& orig) {
388 SkRRect dst;
389 dst.setEmpty();
390
391 // The identity matrix will duplicate the rrect.
392 bool success = orig.transform(SkMatrix::I(), &dst);
393 REPORTER_ASSERT(reporter, success);
394 REPORTER_ASSERT(reporter, orig == dst);
395
396 // Skew and Perspective make transform fail.
397 SkMatrix matrix;
398 matrix.reset();
399 matrix.setSkewX(SkIntToScalar(2));
400 assert_transform_failure(reporter, orig, matrix);
401
402 matrix.reset();
403 matrix.setSkewY(SkIntToScalar(3));
404 assert_transform_failure(reporter, orig, matrix);
405
406 matrix.reset();
407 matrix.setPerspX(SkScalarToPersp(SkIntToScalar(4)));
408 assert_transform_failure(reporter, orig, matrix);
409
410 matrix.reset();
411 matrix.setPerspY(SkScalarToPersp(SkIntToScalar(5)));
412 assert_transform_failure(reporter, orig, matrix);
413
414 // Rotation fails.
415 matrix.reset();
416 matrix.setRotate(SkIntToScalar(90));
417 assert_transform_failure(reporter, orig, matrix);
418 matrix.setRotate(SkIntToScalar(37));
419 assert_transform_failure(reporter, orig, matrix);
420
421 // Translate will keep the rect moved, but otherwise the same.
422 matrix.reset();
423 SkScalar translateX = SkIntToScalar(32);
424 SkScalar translateY = SkIntToScalar(15);
425 matrix.setTranslateX(translateX);
426 matrix.setTranslateY(translateY);
427 dst.setEmpty();
428 success = orig.transform(matrix, &dst);
429 REPORTER_ASSERT(reporter, success);
430 for (int i = 0; i < 4; ++i) {
431 REPORTER_ASSERT(reporter,
432 orig.radii((SkRRect::Corner) i) == dst.radii((SkRRect::Corner) i));
433 }
434 REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width());
435 REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height());
436 REPORTER_ASSERT(reporter, dst.rect().left() == orig.rect().left() + translateX);
437 REPORTER_ASSERT(reporter, dst.rect().top() == orig.rect().top() + translateY);
438
439 // Keeping the translation, but adding skew will make transform fail.
440 matrix.setSkewY(SkIntToScalar(7));
441 assert_transform_failure(reporter, orig, matrix);
442
443 // Scaling in -x will flip the round rect horizontally.
444 matrix.reset();
445 matrix.setScaleX(SkIntToScalar(-1));
446 dst.setEmpty();
447 success = orig.transform(matrix, &dst);
448 REPORTER_ASSERT(reporter, success);
449 {
450 GET_RADII;
451 // Radii have swapped in x.
452 REPORTER_ASSERT(reporter, origUL == dstUR);
453 REPORTER_ASSERT(reporter, origUR == dstUL);
454 REPORTER_ASSERT(reporter, origLR == dstLL);
455 REPORTER_ASSERT(reporter, origLL == dstLR);
456 }
457 // Width and height remain the same.
458 REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width());
459 REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height());
460 // Right and left have swapped (sort of)
461 REPORTER_ASSERT(reporter, orig.rect().right() == -dst.rect().left());
462 // Top has stayed the same.
463 REPORTER_ASSERT(reporter, orig.rect().top() == dst.rect().top());
464
465 // Keeping the scale, but adding a persp will make transform fail.
466 matrix.setPerspX(SkScalarToPersp(SkIntToScalar(7)));
467 assert_transform_failure(reporter, orig, matrix);
468
469 // Scaling in -y will flip the round rect vertically.
470 matrix.reset();
471 matrix.setScaleY(SkIntToScalar(-1));
472 dst.setEmpty();
473 success = orig.transform(matrix, &dst);
474 REPORTER_ASSERT(reporter, success);
475 {
476 GET_RADII;
477 // Radii have swapped in y.
478 REPORTER_ASSERT(reporter, origUL == dstLL);
479 REPORTER_ASSERT(reporter, origUR == dstLR);
480 REPORTER_ASSERT(reporter, origLR == dstUR);
481 REPORTER_ASSERT(reporter, origLL == dstUL);
482 }
483 // Width and height remain the same.
484 REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width());
485 REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height());
486 // Top and bottom have swapped (sort of)
487 REPORTER_ASSERT(reporter, orig.rect().top() == -dst.rect().bottom());
488 // Left has stayed the same.
489 REPORTER_ASSERT(reporter, orig.rect().left() == dst.rect().left());
490
491 // Scaling in -x and -y will swap in both directions.
492 matrix.reset();
493 matrix.setScaleY(SkIntToScalar(-1));
494 matrix.setScaleX(SkIntToScalar(-1));
495 dst.setEmpty();
496 success = orig.transform(matrix, &dst);
497 REPORTER_ASSERT(reporter, success);
498 {
499 GET_RADII;
500 REPORTER_ASSERT(reporter, origUL == dstLR);
501 REPORTER_ASSERT(reporter, origUR == dstLL);
502 REPORTER_ASSERT(reporter, origLR == dstUL);
503 REPORTER_ASSERT(reporter, origLL == dstUR);
504 }
505 // Width and height remain the same.
506 REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width());
507 REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height());
508 REPORTER_ASSERT(reporter, orig.rect().top() == -dst.rect().bottom());
509 REPORTER_ASSERT(reporter, orig.rect().right() == -dst.rect().left());
510
511 // Scale in both directions.
512 SkScalar xScale = SkIntToScalar(3);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000513 SkScalar yScale = 3.2f;
scroggo@google.com20e3cd22013-11-05 15:54:42 +0000514 matrix.reset();
515 matrix.setScaleX(xScale);
516 matrix.setScaleY(yScale);
517 dst.setEmpty();
518 success = orig.transform(matrix, &dst);
519 REPORTER_ASSERT(reporter, success);
520 // Radii are scaled.
521 for (int i = 0; i < 4; ++i) {
522 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.radii((SkRRect::Corner) i).fX,
523 SkScalarMul(orig.radii((SkRRect::Corner) i).fX, xScale)));
524 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.radii((SkRRect::Corner) i).fY,
525 SkScalarMul(orig.radii((SkRRect::Corner) i).fY, yScale)));
526 }
527 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().width(),
528 SkScalarMul(orig.rect().width(), xScale)));
529 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().height(),
530 SkScalarMul(orig.rect().height(), yScale)));
531 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().left(),
532 SkScalarMul(orig.rect().left(), xScale)));
533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().top(),
534 SkScalarMul(orig.rect().top(), yScale)));
535}
536
537static void test_round_rect_transform(skiatest::Reporter* reporter) {
538 SkRRect rrect;
539 {
540 SkRect r = { 0, 0, kWidth, kHeight };
541 rrect.setRectXY(r, SkIntToScalar(4), SkIntToScalar(7));
542 test_transform_helper(reporter, rrect);
543 }
544 {
545 SkRect r = { SkIntToScalar(5), SkIntToScalar(15),
546 SkIntToScalar(27), SkIntToScalar(34) };
547 SkVector radii[4] = { { 0, SkIntToScalar(1) },
548 { SkIntToScalar(2), SkIntToScalar(3) },
549 { SkIntToScalar(4), SkIntToScalar(5) },
550 { SkIntToScalar(6), SkIntToScalar(7) } };
551 rrect.setRectRadii(r, radii);
552 test_transform_helper(reporter, rrect);
553 }
554}
555
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000556static void TestRoundRect(skiatest::Reporter* reporter) {
557 test_round_rect_basic(reporter);
558 test_round_rect_rects(reporter);
559 test_round_rect_ovals(reporter);
560 test_round_rect_general(reporter);
561 test_round_rect_iffy_parameters(reporter);
mike@reedtribe.orgbcbef572012-12-23 23:11:21 +0000562 test_inset(reporter);
robertphillips@google.com32c1b662013-04-25 12:23:00 +0000563 test_round_rect_contains_rect(reporter);
scroggo@google.com20e3cd22013-11-05 15:54:42 +0000564 test_round_rect_transform(reporter);
robertphillips@google.com5985e7c2012-11-29 13:24:55 +0000565}
566
567#include "TestClassDef.h"
568DEFINE_TESTCLASS("RoundRect", TestRoundRectClass, TestRoundRect)