blob: 5ad3403fe5cb7ddc9746a352ded51aaefe04dd3a [file] [log] [blame]
caryclarkda707bf2015-11-19 14:47:43 -08001/*
2 * Copyright 2015 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 "SkMatrix.h"
9#include "SkPath.h"
Mike Reed0c3137c2018-02-20 13:57:05 -050010#include "SkPathPriv.h"
caryclarkda707bf2015-11-19 14:47:43 -080011#include "SkRRect.h"
12#include "Test.h"
13
bsalomon78d58d12016-05-27 09:17:04 -070014static SkRRect path_contains_rrect(skiatest::Reporter* reporter, const SkPath& path,
15 SkPath::Direction* dir, unsigned* start) {
caryclarkda707bf2015-11-19 14:47:43 -080016 SkRRect out;
Mike Reed0c3137c2018-02-20 13:57:05 -050017 REPORTER_ASSERT(reporter, SkPathPriv::IsRRect(path, &out, dir, start));
bsalomon78d58d12016-05-27 09:17:04 -070018 SkPath recreatedPath;
19 recreatedPath.addRRect(out, *dir, *start);
20 REPORTER_ASSERT(reporter, path == recreatedPath);
21 // Test that rotations/mirrors of the rrect path are still rrect paths and the returned
22 // parameters for the transformed paths are correct.
23 static const SkMatrix kMatrices[] = {
24 SkMatrix::MakeScale(1, 1),
25 SkMatrix::MakeScale(-1, 1),
26 SkMatrix::MakeScale(1, -1),
27 SkMatrix::MakeScale(-1, -1),
28 };
29 for (auto& m : kMatrices) {
30 SkPath xformed;
31 path.transform(m, &xformed);
32 SkRRect xrr = SkRRect::MakeRect(SkRect::MakeEmpty());
33 SkPath::Direction xd = SkPath::kCCW_Direction;
34 unsigned xs = ~0U;
Mike Reed0c3137c2018-02-20 13:57:05 -050035 REPORTER_ASSERT(reporter, SkPathPriv::IsRRect(xformed, &xrr, &xd, &xs));
bsalomon78d58d12016-05-27 09:17:04 -070036 recreatedPath.reset();
37 recreatedPath.addRRect(xrr, xd, xs);
38 REPORTER_ASSERT(reporter, recreatedPath == xformed);
caryclarkda707bf2015-11-19 14:47:43 -080039 }
caryclarkda707bf2015-11-19 14:47:43 -080040 return out;
41}
42
bsalomon78d58d12016-05-27 09:17:04 -070043static SkRRect inner_path_contains_rrect(skiatest::Reporter* reporter, const SkRRect& in,
44 SkPath::Direction dir, unsigned start) {
caryclarkda707bf2015-11-19 14:47:43 -080045 switch (in.getType()) {
46 case SkRRect::kEmpty_Type:
47 case SkRRect::kRect_Type:
48 case SkRRect::kOval_Type:
49 return in;
50 default:
51 break;
52 }
53 SkPath path;
bsalomon78d58d12016-05-27 09:17:04 -070054 path.addRRect(in, dir, start);
55 SkPath::Direction outDir;
56 unsigned outStart;
57 SkRRect rrect = path_contains_rrect(reporter, path, &outDir, &outStart);
58 REPORTER_ASSERT(reporter, outDir == dir && outStart == start);
59 return rrect;
caryclarkda707bf2015-11-19 14:47:43 -080060}
61
bsalomon78d58d12016-05-27 09:17:04 -070062static void path_contains_rrect_check(skiatest::Reporter* reporter, const SkRRect& in,
63 SkPath::Direction dir, unsigned start) {
64 SkRRect out = inner_path_contains_rrect(reporter, in, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -080065 if (in != out) {
66 SkDebugf("");
67 }
68 REPORTER_ASSERT(reporter, in == out);
69}
70
bsalomon78d58d12016-05-27 09:17:04 -070071static void path_contains_rrect_nocheck(skiatest::Reporter* reporter, const SkRRect& in,
72 SkPath::Direction dir, unsigned start) {
73 SkRRect out = inner_path_contains_rrect(reporter, in, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -080074 if (in == out) {
75 SkDebugf("");
76 }
77}
78
79static void path_contains_rrect_check(skiatest::Reporter* reporter, const SkRect& r,
bsalomon78d58d12016-05-27 09:17:04 -070080 SkVector v[4], SkPath::Direction dir, unsigned start) {
caryclarkda707bf2015-11-19 14:47:43 -080081 SkRRect rrect;
82 rrect.setRectRadii(r, v);
bsalomon78d58d12016-05-27 09:17:04 -070083 path_contains_rrect_check(reporter, rrect, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -080084}
85
86class ForceIsRRect_Private {
87public:
bsalomon78d58d12016-05-27 09:17:04 -070088 ForceIsRRect_Private(SkPath* path, SkPath::Direction dir, unsigned start) {
89 path->fPathRef->setIsRRect(true, dir == SkPath::kCCW_Direction, start);
caryclarkda707bf2015-11-19 14:47:43 -080090 }
91};
92
bsalomon78d58d12016-05-27 09:17:04 -070093static void force_path_contains_rrect(skiatest::Reporter* reporter, SkPath& path,
94 SkPath::Direction dir, unsigned start) {
95 ForceIsRRect_Private force_rrect(&path, dir, start);
96 SkPath::Direction outDir;
97 unsigned outStart;
98 path_contains_rrect(reporter, path, &outDir, &outStart);
99 REPORTER_ASSERT(reporter, outDir == dir && outStart == start);
caryclarkda707bf2015-11-19 14:47:43 -0800100}
101
102static void test_undetected_paths(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700103 // We use a dummy path to get the exact conic weight used by SkPath for a circular arc. This
104 // allows our local, hand-crafted, artisanal round rect paths below to exactly match the
105 // factory made corporate paths produced by SkPath.
106 SkPath dummyPath;
107 dummyPath.addCircle(0, 0, 10);
108 SkPath::RawIter iter(dummyPath);
109 SkPoint dummyPts[4];
110 SkPath::Verb v = iter.next(dummyPts);
111 REPORTER_ASSERT(reporter, SkPath::kMove_Verb == v);
112 v = iter.next(dummyPts);
113 REPORTER_ASSERT(reporter, SkPath::kConic_Verb == v);
114 const SkScalar weight = iter.conicWeight();
115
caryclarkda707bf2015-11-19 14:47:43 -0800116 SkPath path;
117 path.moveTo(0, 62.5f);
118 path.lineTo(0, 3.5f);
bsalomon78d58d12016-05-27 09:17:04 -0700119 path.conicTo(0, 0, 3.5f, 0, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800120 path.lineTo(196.5f, 0);
bsalomon78d58d12016-05-27 09:17:04 -0700121 path.conicTo(200, 0, 200, 3.5f, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800122 path.lineTo(200, 62.5f);
bsalomon78d58d12016-05-27 09:17:04 -0700123 path.conicTo(200, 66, 196.5f, 66, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800124 path.lineTo(3.5f, 66);
bsalomon78d58d12016-05-27 09:17:04 -0700125 path.conicTo(0, 66, 0, 62.5, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800126 path.close();
bsalomon78d58d12016-05-27 09:17:04 -0700127 force_path_contains_rrect(reporter, path, SkPath::kCW_Direction, 6);
caryclarkda707bf2015-11-19 14:47:43 -0800128
129 path.reset();
130 path.moveTo(0, 81.5f);
131 path.lineTo(0, 3.5f);
bsalomon78d58d12016-05-27 09:17:04 -0700132 path.conicTo(0, 0, 3.5f, 0, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800133 path.lineTo(149.5, 0);
bsalomon78d58d12016-05-27 09:17:04 -0700134 path.conicTo(153, 0, 153, 3.5f, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800135 path.lineTo(153, 81.5f);
bsalomon78d58d12016-05-27 09:17:04 -0700136 path.conicTo(153, 85, 149.5f, 85, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800137 path.lineTo(3.5f, 85);
bsalomon78d58d12016-05-27 09:17:04 -0700138 path.conicTo(0, 85, 0, 81.5f, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800139 path.close();
bsalomon78d58d12016-05-27 09:17:04 -0700140 force_path_contains_rrect(reporter, path, SkPath::kCW_Direction, 6);
caryclarkda707bf2015-11-19 14:47:43 -0800141
142 path.reset();
143 path.moveTo(14, 1189);
144 path.lineTo(14, 21);
bsalomon78d58d12016-05-27 09:17:04 -0700145 path.conicTo(14, 14, 21, 14, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800146 path.lineTo(1363, 14);
bsalomon78d58d12016-05-27 09:17:04 -0700147 path.conicTo(1370, 14, 1370, 21, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800148 path.lineTo(1370, 1189);
bsalomon78d58d12016-05-27 09:17:04 -0700149 path.conicTo(1370, 1196, 1363, 1196, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800150 path.lineTo(21, 1196);
bsalomon78d58d12016-05-27 09:17:04 -0700151 path.conicTo(14, 1196, 14, 1189, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800152 path.close();
bsalomon78d58d12016-05-27 09:17:04 -0700153 force_path_contains_rrect(reporter, path, SkPath::kCW_Direction, 6);
caryclarkda707bf2015-11-19 14:47:43 -0800154
155 path.reset();
156 path.moveTo(14, 1743);
157 path.lineTo(14, 21);
bsalomon78d58d12016-05-27 09:17:04 -0700158 path.conicTo(14, 14, 21, 14, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800159 path.lineTo(1363, 14);
bsalomon78d58d12016-05-27 09:17:04 -0700160 path.conicTo(1370, 14, 1370, 21, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800161 path.lineTo(1370, 1743);
bsalomon78d58d12016-05-27 09:17:04 -0700162 path.conicTo(1370, 1750, 1363, 1750, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800163 path.lineTo(21, 1750);
bsalomon78d58d12016-05-27 09:17:04 -0700164 path.conicTo(14, 1750, 14, 1743, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800165 path.close();
bsalomon78d58d12016-05-27 09:17:04 -0700166 force_path_contains_rrect(reporter, path, SkPath::kCW_Direction, 6);
caryclarkda707bf2015-11-19 14:47:43 -0800167}
168
169static const SkScalar kWidth = 100.0f;
170static const SkScalar kHeight = 100.0f;
171
172static void test_tricky_radii(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700173 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
174 for (int start = 0; start < 8; ++start) {
175 {
176 // crbug.com/458522
177 SkRRect rr;
178 const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 };
179 const SkScalar rad = 12814;
180 const SkVector vec[] = { { rad, rad }, { 0, rad }, { rad, rad }, { 0, rad } };
181 rr.setRectRadii(bounds, vec);
182 path_contains_rrect_check(reporter, rr, dir, start);
183 }
caryclarkda707bf2015-11-19 14:47:43 -0800184
bsalomon78d58d12016-05-27 09:17:04 -0700185 {
186 // crbug.com//463920
187 SkRect r = SkRect::MakeLTRB(0, 0, 1009, 33554432.0);
188 SkVector radii[4] = {
189 { 13.0f, 8.0f }, { 170.0f, 2.0 }, { 256.0f, 33554432.0 }, { 110.0f, 5.0f }
190 };
191 SkRRect rr;
192 rr.setRectRadii(r, radii);
193 path_contains_rrect_nocheck(reporter, rr, dir, start);
194 }
195 }
caryclarkda707bf2015-11-19 14:47:43 -0800196 }
197}
198
199static void test_empty_crbug_458524(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700200 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
201 for (int start = 0; start < 8; ++start) {
202 SkRRect rr;
203 const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 };
204 const SkScalar rad = 40;
205 rr.setRectXY(bounds, rad, rad);
206 path_contains_rrect_check(reporter, rr, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800207
bsalomon78d58d12016-05-27 09:17:04 -0700208 SkRRect other;
209 SkMatrix matrix;
210 matrix.setScale(0, 1);
211 rr.transform(matrix, &other);
212 path_contains_rrect_check(reporter, rr, dir, start);
213 }
214 }
caryclarkda707bf2015-11-19 14:47:43 -0800215}
216
217static void test_inset(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700218 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
219 for (int start = 0; start < 8; ++start) {
220 SkRRect rr, rr2;
221 SkRect r = { 0, 0, 100, 100 };
caryclarkda707bf2015-11-19 14:47:43 -0800222
bsalomon78d58d12016-05-27 09:17:04 -0700223 rr.setRect(r);
224 rr.inset(-20, -20, &rr2);
225 path_contains_rrect_check(reporter, rr, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800226
bsalomon78d58d12016-05-27 09:17:04 -0700227 rr.inset(20, 20, &rr2);
228 path_contains_rrect_check(reporter, rr, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800229
bsalomon78d58d12016-05-27 09:17:04 -0700230 rr.inset(r.width()/2, r.height()/2, &rr2);
231 path_contains_rrect_check(reporter, rr, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800232
bsalomon78d58d12016-05-27 09:17:04 -0700233 rr.setRectXY(r, 20, 20);
234 rr.inset(19, 19, &rr2);
235 path_contains_rrect_check(reporter, rr, dir, start);
236 rr.inset(20, 20, &rr2);
237 path_contains_rrect_check(reporter, rr, dir, start);
238 }
239 }
caryclarkda707bf2015-11-19 14:47:43 -0800240}
241
242
243static void test_9patch_rrect(skiatest::Reporter* reporter,
244 const SkRect& rect,
245 SkScalar l, SkScalar t, SkScalar r, SkScalar b,
246 bool checkRadii) {
bsalomon78d58d12016-05-27 09:17:04 -0700247 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
248 for (int start = 0; start < 8; ++start) {
249 SkRRect rr;
250 rr.setNinePatch(rect, l, t, r, b);
251 if (checkRadii) {
252 path_contains_rrect_check(reporter, rr, dir, start);
253 } else {
254 path_contains_rrect_nocheck(reporter, rr, dir, start);
255 }
caryclarkda707bf2015-11-19 14:47:43 -0800256
bsalomon78d58d12016-05-27 09:17:04 -0700257 SkRRect rr2; // construct the same RR using the most general set function
258 SkVector radii[4] = { { l, t }, { r, t }, { r, b }, { l, b } };
259 rr2.setRectRadii(rect, radii);
260 if (checkRadii) {
261 path_contains_rrect_check(reporter, rr, dir, start);
262 } else {
263 path_contains_rrect_nocheck(reporter, rr, dir, start);
264 }
265 }
caryclarkda707bf2015-11-19 14:47:43 -0800266 }
267}
268
269// Test out the basic API entry points
270static void test_round_rect_basic(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700271 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
272 for (int start = 0; start < 8; ++start) {
273 //----
274 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
caryclarkda707bf2015-11-19 14:47:43 -0800275
bsalomon78d58d12016-05-27 09:17:04 -0700276 SkRRect rr1;
277 rr1.setRect(rect);
278 path_contains_rrect_check(reporter, rr1, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800279
bsalomon78d58d12016-05-27 09:17:04 -0700280 SkRRect rr1_2; // construct the same RR using the most general set function
281 SkVector rr1_2_radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
282 rr1_2.setRectRadii(rect, rr1_2_radii);
283 path_contains_rrect_check(reporter, rr1_2, dir, start);
284 SkRRect rr1_3; // construct the same RR using the nine patch set function
285 rr1_3.setNinePatch(rect, 0, 0, 0, 0);
286 path_contains_rrect_check(reporter, rr1_2, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800287
bsalomon78d58d12016-05-27 09:17:04 -0700288 //----
289 SkPoint halfPoint = { SkScalarHalf(kWidth), SkScalarHalf(kHeight) };
290 SkRRect rr2;
291 rr2.setOval(rect);
292 path_contains_rrect_check(reporter, rr2, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800293
bsalomon78d58d12016-05-27 09:17:04 -0700294 SkRRect rr2_2; // construct the same RR using the most general set function
295 SkVector rr2_2_radii[4] = { { halfPoint.fX, halfPoint.fY },
296 { halfPoint.fX, halfPoint.fY },
297 { halfPoint.fX, halfPoint.fY },
298 { halfPoint.fX, halfPoint.fY } };
299 rr2_2.setRectRadii(rect, rr2_2_radii);
300 path_contains_rrect_check(reporter, rr2_2, dir, start);
301 SkRRect rr2_3; // construct the same RR using the nine patch set function
302 rr2_3.setNinePatch(rect, halfPoint.fX, halfPoint.fY, halfPoint.fX, halfPoint.fY);
303 path_contains_rrect_check(reporter, rr2_3, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800304
bsalomon78d58d12016-05-27 09:17:04 -0700305 //----
306 SkPoint p = { 5, 5 };
307 SkRRect rr3;
308 rr3.setRectXY(rect, p.fX, p.fY);
309 path_contains_rrect_check(reporter, rr3, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800310
bsalomon78d58d12016-05-27 09:17:04 -0700311 SkRRect rr3_2; // construct the same RR using the most general set function
312 SkVector rr3_2_radii[4] = { { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 } };
313 rr3_2.setRectRadii(rect, rr3_2_radii);
314 path_contains_rrect_check(reporter, rr3_2, dir, start);
315 SkRRect rr3_3; // construct the same RR using the nine patch set function
316 rr3_3.setNinePatch(rect, 5, 5, 5, 5);
317 path_contains_rrect_check(reporter, rr3_3, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800318
bsalomon78d58d12016-05-27 09:17:04 -0700319 //----
320 test_9patch_rrect(reporter, rect, 10, 9, 8, 7, true);
caryclarkda707bf2015-11-19 14:47:43 -0800321
bsalomon78d58d12016-05-27 09:17:04 -0700322 {
323 // Test out the rrect from skia:3466
324 SkRect rect2 = SkRect::MakeLTRB(0.358211994f, 0.755430222f, 0.872866154f,
325 0.806214333f);
caryclarkda707bf2015-11-19 14:47:43 -0800326
bsalomon78d58d12016-05-27 09:17:04 -0700327 test_9patch_rrect(reporter,
328 rect2,
329 0.926942348f, 0.642850280f, 0.529063463f, 0.587844372f,
330 false);
331 }
caryclarkda707bf2015-11-19 14:47:43 -0800332
bsalomon78d58d12016-05-27 09:17:04 -0700333 //----
334 SkPoint radii2[4] = { { 0, 0 }, { 0, 0 }, { 50, 50 }, { 20, 50 } };
335
336 SkRRect rr5;
337 rr5.setRectRadii(rect, radii2);
338 path_contains_rrect_check(reporter, rr5, dir, start);
339 }
caryclarkda707bf2015-11-19 14:47:43 -0800340 }
caryclarkda707bf2015-11-19 14:47:43 -0800341}
342
343// Test out the cases when the RR degenerates to a rect
344static void test_round_rect_rects(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700345 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
346 for (int start = 0; start < 8; ++start) {
347 //----
348 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
349 SkRRect rr1;
350 rr1.setRectXY(rect, 0, 0);
caryclarkda707bf2015-11-19 14:47:43 -0800351
bsalomon78d58d12016-05-27 09:17:04 -0700352 path_contains_rrect_check(reporter, rr1, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800353
bsalomon78d58d12016-05-27 09:17:04 -0700354 //----
355 SkPoint radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
caryclarkda707bf2015-11-19 14:47:43 -0800356
bsalomon78d58d12016-05-27 09:17:04 -0700357 SkRRect rr2;
358 rr2.setRectRadii(rect, radii);
caryclarkda707bf2015-11-19 14:47:43 -0800359
bsalomon78d58d12016-05-27 09:17:04 -0700360 path_contains_rrect_check(reporter, rr2, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800361
bsalomon78d58d12016-05-27 09:17:04 -0700362 //----
363 SkPoint radii2[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
caryclarkda707bf2015-11-19 14:47:43 -0800364
bsalomon78d58d12016-05-27 09:17:04 -0700365 SkRRect rr3;
366 rr3.setRectRadii(rect, radii2);
367 path_contains_rrect_check(reporter, rr3, dir, start);
368 }
369 }
caryclarkda707bf2015-11-19 14:47:43 -0800370}
371
372// Test out the cases when the RR degenerates to an oval
373static void test_round_rect_ovals(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700374 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
375 for (int start = 0; start < 8; ++start) {
376 //----
377 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
378 SkRRect rr1;
379 rr1.setRectXY(rect, SkScalarHalf(kWidth), SkScalarHalf(kHeight));
caryclarkda707bf2015-11-19 14:47:43 -0800380
bsalomon78d58d12016-05-27 09:17:04 -0700381 path_contains_rrect_check(reporter, rr1, dir, start);
382 }
383 }
caryclarkda707bf2015-11-19 14:47:43 -0800384}
385
386// Test out the non-degenerate RR cases
387static void test_round_rect_general(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700388 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
389 for (int start = 0; start < 8; ++start) {
390 //----
391 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
392 SkRRect rr1;
393 rr1.setRectXY(rect, 20, 20);
caryclarkda707bf2015-11-19 14:47:43 -0800394
bsalomon78d58d12016-05-27 09:17:04 -0700395 path_contains_rrect_check(reporter, rr1, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800396
bsalomon78d58d12016-05-27 09:17:04 -0700397 //----
398 SkPoint radii[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
caryclarkda707bf2015-11-19 14:47:43 -0800399
bsalomon78d58d12016-05-27 09:17:04 -0700400 SkRRect rr2;
401 rr2.setRectRadii(rect, radii);
caryclarkda707bf2015-11-19 14:47:43 -0800402
bsalomon78d58d12016-05-27 09:17:04 -0700403 path_contains_rrect_check(reporter, rr2, dir, start);
404 }
405 }
caryclarkda707bf2015-11-19 14:47:43 -0800406}
407
408static void test_round_rect_iffy_parameters(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700409 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
410 for (int start = 0; start < 8; ++start) {
411 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
412 SkPoint radii[4] = { { 50, 100 }, { 100, 50 }, { 50, 100 }, { 100, 50 } };
413 SkRRect rr1;
414 rr1.setRectRadii(rect, radii);
415 path_contains_rrect_nocheck(reporter, rr1, dir, start);
416 }
417 }
caryclarkda707bf2015-11-19 14:47:43 -0800418}
419
420static void set_radii(SkVector radii[4], int index, float rad) {
421 sk_bzero(radii, sizeof(SkVector) * 4);
422 radii[index].set(rad, rad);
423}
424
425static void test_skbug_3239(skiatest::Reporter* reporter) {
426 const float min = SkBits2Float(0xcb7f16c8); /* -16717512.000000 */
427 const float max = SkBits2Float(0x4b7f1c1d); /* 16718877.000000 */
428 const float big = SkBits2Float(0x4b7f1bd7); /* 16718807.000000 */
429
430 const float rad = 33436320;
431
432 const SkRect rectx = SkRect::MakeLTRB(min, min, max, big);
433 const SkRect recty = SkRect::MakeLTRB(min, min, big, max);
434
bsalomon78d58d12016-05-27 09:17:04 -0700435 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
436 for (int start = 0; start < 8; ++start) {
437 SkVector radii[4];
438 for (int i = 0; i < 4; ++i) {
439 set_radii(radii, i, rad);
440 path_contains_rrect_check(reporter, rectx, radii, dir, start);
441 path_contains_rrect_check(reporter, recty, radii, dir, start);
442 }
443 }
caryclarkda707bf2015-11-19 14:47:43 -0800444 }
445}
446
447static void test_mix(skiatest::Reporter* reporter) {
bsalomon78d58d12016-05-27 09:17:04 -0700448 for (auto dir : {SkPath::kCW_Direction, SkPath::kCCW_Direction}) {
449 for (int start = 0; start < 8; ++start) {
450 // Test out mixed degenerate and non-degenerate geometry with Conics
451 const SkVector radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 100, 100 } };
452 SkRect r = SkRect::MakeWH(100, 100);
453 SkRRect rr;
454 rr.setRectRadii(r, radii);
455 path_contains_rrect_check(reporter, rr, dir, start);
456 }
457 }
caryclarkda707bf2015-11-19 14:47:43 -0800458}
459
460DEF_TEST(RoundRectInPath, reporter) {
461 test_tricky_radii(reporter);
462 test_empty_crbug_458524(reporter);
463 test_inset(reporter);
464 test_round_rect_basic(reporter);
465 test_round_rect_rects(reporter);
466 test_round_rect_ovals(reporter);
467 test_round_rect_general(reporter);
468 test_undetected_paths(reporter);
469 test_round_rect_iffy_parameters(reporter);
470 test_skbug_3239(reporter);
471 test_mix(reporter);
472}
Mike Reedd72d6c52018-02-12 15:56:06 -0500473
474DEF_TEST(RRect_fragile, reporter) {
475 SkRect rect = {
476 SkBits2Float(0x1f800000), // 0x003F0000 was the starter value that also fails
477 SkBits2Float(0x1400001C),
478 SkBits2Float(0x3F000004),
479 SkBits2Float(0x3F000004),
480 };
481
482 SkPoint radii[] = {
483 { SkBits2Float(0x00000001), SkBits2Float(0x00000001) },
484 { SkBits2Float(0x00000020), SkBits2Float(0x00000001) },
485 { SkBits2Float(0x00000000), SkBits2Float(0x00000000) },
486 { SkBits2Float(0x3F000004), SkBits2Float(0x3F000004) },
487 };
488
489 SkRRect rr;
490 // please don't assert
491 if (false) { // disable until we fix this
492 SkDebugf("%g 0x%08X\n", rect.fLeft, SkFloat2Bits(rect.fLeft));
493 rr.setRectRadii(rect, radii);
494 }
495}
496