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