blob: 45aa0a2047b15cc93edcc662c3f2bfe65a540cec [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkMatrix.h"
9#include "include/core/SkPath.h"
10#include "include/core/SkRRect.h"
11#include "src/core/SkPathPriv.h"
12#include "tests/Test.h"
caryclarkda707bf2015-11-19 14:47:43 -080013
bsalomon78d58d12016-05-27 09:17:04 -070014static SkRRect path_contains_rrect(skiatest::Reporter* reporter, const SkPath& path,
Mike Reed30bc5272019-11-22 18:34:02 +000015 SkPathDirection* 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[] = {
Mike Reed1f607332020-05-21 12:11:27 -040024 SkMatrix::Scale( 1, 1),
25 SkMatrix::Scale(-1, 1),
26 SkMatrix::Scale( 1, -1),
27 SkMatrix::Scale(-1, -1),
bsalomon78d58d12016-05-27 09:17:04 -070028 };
29 for (auto& m : kMatrices) {
30 SkPath xformed;
31 path.transform(m, &xformed);
32 SkRRect xrr = SkRRect::MakeRect(SkRect::MakeEmpty());
Mike Reed30bc5272019-11-22 18:34:02 +000033 SkPathDirection xd = SkPathDirection::kCCW;
bsalomon78d58d12016-05-27 09:17:04 -070034 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,
Mike Reed30bc5272019-11-22 18:34:02 +000044 SkPathDirection 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);
Mike Reed30bc5272019-11-22 18:34:02 +000055 SkPathDirection outDir;
bsalomon78d58d12016-05-27 09:17:04 -070056 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,
Mike Reed30bc5272019-11-22 18:34:02 +000063 SkPathDirection dir, unsigned start) {
bsalomon78d58d12016-05-27 09:17:04 -070064 SkRRect out = inner_path_contains_rrect(reporter, in, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -080065 if (in != out) {
John Stiles7bf79992021-06-25 11:05:20 -040066 SkDebugf("%s", "");
caryclarkda707bf2015-11-19 14:47:43 -080067 }
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,
Mike Reed30bc5272019-11-22 18:34:02 +000072 SkPathDirection dir, unsigned start) {
bsalomon78d58d12016-05-27 09:17:04 -070073 SkRRect out = inner_path_contains_rrect(reporter, in, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -080074 if (in == out) {
John Stiles7bf79992021-06-25 11:05:20 -040075 SkDebugf("%s", "");
caryclarkda707bf2015-11-19 14:47:43 -080076 }
77}
78
79static void path_contains_rrect_check(skiatest::Reporter* reporter, const SkRect& r,
Mike Reed30bc5272019-11-22 18:34:02 +000080 SkVector v[4], SkPathDirection 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:
Mike Reed30bc5272019-11-22 18:34:02 +000088 ForceIsRRect_Private(SkPath* path, SkPathDirection dir, unsigned start) {
89 path->fPathRef->setIsRRect(true, dir == SkPathDirection::kCCW, 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,
Mike Reed30bc5272019-11-22 18:34:02 +000094 SkPathDirection dir, unsigned start) {
bsalomon78d58d12016-05-27 09:17:04 -070095 ForceIsRRect_Private force_rrect(&path, dir, start);
Mike Reed30bc5272019-11-22 18:34:02 +000096 SkPathDirection outDir;
bsalomon78d58d12016-05-27 09:17:04 -070097 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) {
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400103 // We first get the exact conic weight used by SkPath for a circular arc. This
bsalomon78d58d12016-05-27 09:17:04 -0700104 // allows our local, hand-crafted, artisanal round rect paths below to exactly match the
105 // factory made corporate paths produced by SkPath.
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400106 SkPath exactPath;
107 exactPath.addCircle(0, 0, 10);
108 REPORTER_ASSERT(reporter, SkPath::kMove_Verb == SkPathPriv::VerbData(exactPath)[0]);
109 REPORTER_ASSERT(reporter, SkPath::kConic_Verb == SkPathPriv::VerbData(exactPath)[1]);
110 const SkScalar weight = SkPathPriv::ConicWeightData(exactPath)[0];
bsalomon78d58d12016-05-27 09:17:04 -0700111
caryclarkda707bf2015-11-19 14:47:43 -0800112 SkPath path;
113 path.moveTo(0, 62.5f);
114 path.lineTo(0, 3.5f);
bsalomon78d58d12016-05-27 09:17:04 -0700115 path.conicTo(0, 0, 3.5f, 0, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800116 path.lineTo(196.5f, 0);
bsalomon78d58d12016-05-27 09:17:04 -0700117 path.conicTo(200, 0, 200, 3.5f, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800118 path.lineTo(200, 62.5f);
bsalomon78d58d12016-05-27 09:17:04 -0700119 path.conicTo(200, 66, 196.5f, 66, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800120 path.lineTo(3.5f, 66);
bsalomon78d58d12016-05-27 09:17:04 -0700121 path.conicTo(0, 66, 0, 62.5, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800122 path.close();
Mike Reed30bc5272019-11-22 18:34:02 +0000123 force_path_contains_rrect(reporter, path, SkPathDirection::kCW, 6);
caryclarkda707bf2015-11-19 14:47:43 -0800124
125 path.reset();
126 path.moveTo(0, 81.5f);
127 path.lineTo(0, 3.5f);
bsalomon78d58d12016-05-27 09:17:04 -0700128 path.conicTo(0, 0, 3.5f, 0, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800129 path.lineTo(149.5, 0);
bsalomon78d58d12016-05-27 09:17:04 -0700130 path.conicTo(153, 0, 153, 3.5f, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800131 path.lineTo(153, 81.5f);
bsalomon78d58d12016-05-27 09:17:04 -0700132 path.conicTo(153, 85, 149.5f, 85, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800133 path.lineTo(3.5f, 85);
bsalomon78d58d12016-05-27 09:17:04 -0700134 path.conicTo(0, 85, 0, 81.5f, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800135 path.close();
Mike Reed30bc5272019-11-22 18:34:02 +0000136 force_path_contains_rrect(reporter, path, SkPathDirection::kCW, 6);
caryclarkda707bf2015-11-19 14:47:43 -0800137
138 path.reset();
139 path.moveTo(14, 1189);
140 path.lineTo(14, 21);
bsalomon78d58d12016-05-27 09:17:04 -0700141 path.conicTo(14, 14, 21, 14, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800142 path.lineTo(1363, 14);
bsalomon78d58d12016-05-27 09:17:04 -0700143 path.conicTo(1370, 14, 1370, 21, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800144 path.lineTo(1370, 1189);
bsalomon78d58d12016-05-27 09:17:04 -0700145 path.conicTo(1370, 1196, 1363, 1196, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800146 path.lineTo(21, 1196);
bsalomon78d58d12016-05-27 09:17:04 -0700147 path.conicTo(14, 1196, 14, 1189, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800148 path.close();
Mike Reed30bc5272019-11-22 18:34:02 +0000149 force_path_contains_rrect(reporter, path, SkPathDirection::kCW, 6);
caryclarkda707bf2015-11-19 14:47:43 -0800150
151 path.reset();
152 path.moveTo(14, 1743);
153 path.lineTo(14, 21);
bsalomon78d58d12016-05-27 09:17:04 -0700154 path.conicTo(14, 14, 21, 14, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800155 path.lineTo(1363, 14);
bsalomon78d58d12016-05-27 09:17:04 -0700156 path.conicTo(1370, 14, 1370, 21, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800157 path.lineTo(1370, 1743);
bsalomon78d58d12016-05-27 09:17:04 -0700158 path.conicTo(1370, 1750, 1363, 1750, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800159 path.lineTo(21, 1750);
bsalomon78d58d12016-05-27 09:17:04 -0700160 path.conicTo(14, 1750, 14, 1743, weight);
caryclarkda707bf2015-11-19 14:47:43 -0800161 path.close();
Mike Reed30bc5272019-11-22 18:34:02 +0000162 force_path_contains_rrect(reporter, path, SkPathDirection::kCW, 6);
caryclarkda707bf2015-11-19 14:47:43 -0800163}
164
165static const SkScalar kWidth = 100.0f;
166static const SkScalar kHeight = 100.0f;
167
168static void test_tricky_radii(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000169 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700170 for (int start = 0; start < 8; ++start) {
171 {
172 // crbug.com/458522
173 SkRRect rr;
174 const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 };
175 const SkScalar rad = 12814;
176 const SkVector vec[] = { { rad, rad }, { 0, rad }, { rad, rad }, { 0, rad } };
177 rr.setRectRadii(bounds, vec);
178 path_contains_rrect_check(reporter, rr, dir, start);
179 }
caryclarkda707bf2015-11-19 14:47:43 -0800180
bsalomon78d58d12016-05-27 09:17:04 -0700181 {
182 // crbug.com//463920
183 SkRect r = SkRect::MakeLTRB(0, 0, 1009, 33554432.0);
184 SkVector radii[4] = {
185 { 13.0f, 8.0f }, { 170.0f, 2.0 }, { 256.0f, 33554432.0 }, { 110.0f, 5.0f }
186 };
187 SkRRect rr;
188 rr.setRectRadii(r, radii);
189 path_contains_rrect_nocheck(reporter, rr, dir, start);
190 }
191 }
caryclarkda707bf2015-11-19 14:47:43 -0800192 }
193}
194
195static void test_empty_crbug_458524(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000196 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700197 for (int start = 0; start < 8; ++start) {
198 SkRRect rr;
199 const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 };
200 const SkScalar rad = 40;
201 rr.setRectXY(bounds, rad, rad);
202 path_contains_rrect_check(reporter, rr, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800203
bsalomon78d58d12016-05-27 09:17:04 -0700204 SkRRect other;
205 SkMatrix matrix;
206 matrix.setScale(0, 1);
207 rr.transform(matrix, &other);
208 path_contains_rrect_check(reporter, rr, dir, start);
209 }
210 }
caryclarkda707bf2015-11-19 14:47:43 -0800211}
212
213static void test_inset(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000214 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700215 for (int start = 0; start < 8; ++start) {
216 SkRRect rr, rr2;
217 SkRect r = { 0, 0, 100, 100 };
caryclarkda707bf2015-11-19 14:47:43 -0800218
bsalomon78d58d12016-05-27 09:17:04 -0700219 rr.setRect(r);
220 rr.inset(-20, -20, &rr2);
221 path_contains_rrect_check(reporter, rr, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800222
bsalomon78d58d12016-05-27 09:17:04 -0700223 rr.inset(20, 20, &rr2);
224 path_contains_rrect_check(reporter, rr, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800225
bsalomon78d58d12016-05-27 09:17:04 -0700226 rr.inset(r.width()/2, r.height()/2, &rr2);
227 path_contains_rrect_check(reporter, rr, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800228
bsalomon78d58d12016-05-27 09:17:04 -0700229 rr.setRectXY(r, 20, 20);
230 rr.inset(19, 19, &rr2);
231 path_contains_rrect_check(reporter, rr, dir, start);
232 rr.inset(20, 20, &rr2);
233 path_contains_rrect_check(reporter, rr, dir, start);
234 }
235 }
caryclarkda707bf2015-11-19 14:47:43 -0800236}
237
238
239static void test_9patch_rrect(skiatest::Reporter* reporter,
240 const SkRect& rect,
241 SkScalar l, SkScalar t, SkScalar r, SkScalar b,
242 bool checkRadii) {
Mike Reed30bc5272019-11-22 18:34:02 +0000243 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700244 for (int start = 0; start < 8; ++start) {
245 SkRRect rr;
246 rr.setNinePatch(rect, l, t, r, b);
247 if (checkRadii) {
248 path_contains_rrect_check(reporter, rr, dir, start);
249 } else {
250 path_contains_rrect_nocheck(reporter, rr, dir, start);
251 }
caryclarkda707bf2015-11-19 14:47:43 -0800252
bsalomon78d58d12016-05-27 09:17:04 -0700253 SkRRect rr2; // construct the same RR using the most general set function
254 SkVector radii[4] = { { l, t }, { r, t }, { r, b }, { l, b } };
255 rr2.setRectRadii(rect, radii);
256 if (checkRadii) {
257 path_contains_rrect_check(reporter, rr, dir, start);
258 } else {
259 path_contains_rrect_nocheck(reporter, rr, dir, start);
260 }
261 }
caryclarkda707bf2015-11-19 14:47:43 -0800262 }
263}
264
265// Test out the basic API entry points
266static void test_round_rect_basic(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000267 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700268 for (int start = 0; start < 8; ++start) {
269 //----
270 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
caryclarkda707bf2015-11-19 14:47:43 -0800271
bsalomon78d58d12016-05-27 09:17:04 -0700272 SkRRect rr1;
273 rr1.setRect(rect);
274 path_contains_rrect_check(reporter, rr1, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800275
bsalomon78d58d12016-05-27 09:17:04 -0700276 SkRRect rr1_2; // construct the same RR using the most general set function
277 SkVector rr1_2_radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
278 rr1_2.setRectRadii(rect, rr1_2_radii);
279 path_contains_rrect_check(reporter, rr1_2, dir, start);
280 SkRRect rr1_3; // construct the same RR using the nine patch set function
281 rr1_3.setNinePatch(rect, 0, 0, 0, 0);
282 path_contains_rrect_check(reporter, rr1_2, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800283
bsalomon78d58d12016-05-27 09:17:04 -0700284 //----
285 SkPoint halfPoint = { SkScalarHalf(kWidth), SkScalarHalf(kHeight) };
286 SkRRect rr2;
287 rr2.setOval(rect);
288 path_contains_rrect_check(reporter, rr2, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800289
bsalomon78d58d12016-05-27 09:17:04 -0700290 SkRRect rr2_2; // construct the same RR using the most general set function
291 SkVector rr2_2_radii[4] = { { halfPoint.fX, halfPoint.fY },
292 { halfPoint.fX, halfPoint.fY },
293 { halfPoint.fX, halfPoint.fY },
294 { halfPoint.fX, halfPoint.fY } };
295 rr2_2.setRectRadii(rect, rr2_2_radii);
296 path_contains_rrect_check(reporter, rr2_2, dir, start);
297 SkRRect rr2_3; // construct the same RR using the nine patch set function
298 rr2_3.setNinePatch(rect, halfPoint.fX, halfPoint.fY, halfPoint.fX, halfPoint.fY);
299 path_contains_rrect_check(reporter, rr2_3, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800300
bsalomon78d58d12016-05-27 09:17:04 -0700301 //----
302 SkPoint p = { 5, 5 };
303 SkRRect rr3;
304 rr3.setRectXY(rect, p.fX, p.fY);
305 path_contains_rrect_check(reporter, rr3, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800306
bsalomon78d58d12016-05-27 09:17:04 -0700307 SkRRect rr3_2; // construct the same RR using the most general set function
308 SkVector rr3_2_radii[4] = { { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 } };
309 rr3_2.setRectRadii(rect, rr3_2_radii);
310 path_contains_rrect_check(reporter, rr3_2, dir, start);
311 SkRRect rr3_3; // construct the same RR using the nine patch set function
312 rr3_3.setNinePatch(rect, 5, 5, 5, 5);
313 path_contains_rrect_check(reporter, rr3_3, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800314
bsalomon78d58d12016-05-27 09:17:04 -0700315 //----
316 test_9patch_rrect(reporter, rect, 10, 9, 8, 7, true);
caryclarkda707bf2015-11-19 14:47:43 -0800317
bsalomon78d58d12016-05-27 09:17:04 -0700318 {
319 // Test out the rrect from skia:3466
320 SkRect rect2 = SkRect::MakeLTRB(0.358211994f, 0.755430222f, 0.872866154f,
321 0.806214333f);
caryclarkda707bf2015-11-19 14:47:43 -0800322
bsalomon78d58d12016-05-27 09:17:04 -0700323 test_9patch_rrect(reporter,
324 rect2,
325 0.926942348f, 0.642850280f, 0.529063463f, 0.587844372f,
326 false);
327 }
caryclarkda707bf2015-11-19 14:47:43 -0800328
bsalomon78d58d12016-05-27 09:17:04 -0700329 //----
330 SkPoint radii2[4] = { { 0, 0 }, { 0, 0 }, { 50, 50 }, { 20, 50 } };
331
332 SkRRect rr5;
333 rr5.setRectRadii(rect, radii2);
334 path_contains_rrect_check(reporter, rr5, dir, start);
335 }
caryclarkda707bf2015-11-19 14:47:43 -0800336 }
caryclarkda707bf2015-11-19 14:47:43 -0800337}
338
339// Test out the cases when the RR degenerates to a rect
340static void test_round_rect_rects(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000341 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700342 for (int start = 0; start < 8; ++start) {
343 //----
344 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
345 SkRRect rr1;
346 rr1.setRectXY(rect, 0, 0);
caryclarkda707bf2015-11-19 14:47:43 -0800347
bsalomon78d58d12016-05-27 09:17:04 -0700348 path_contains_rrect_check(reporter, rr1, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800349
bsalomon78d58d12016-05-27 09:17:04 -0700350 //----
351 SkPoint radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
caryclarkda707bf2015-11-19 14:47:43 -0800352
bsalomon78d58d12016-05-27 09:17:04 -0700353 SkRRect rr2;
354 rr2.setRectRadii(rect, radii);
caryclarkda707bf2015-11-19 14:47:43 -0800355
bsalomon78d58d12016-05-27 09:17:04 -0700356 path_contains_rrect_check(reporter, rr2, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800357
bsalomon78d58d12016-05-27 09:17:04 -0700358 //----
359 SkPoint radii2[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
caryclarkda707bf2015-11-19 14:47:43 -0800360
bsalomon78d58d12016-05-27 09:17:04 -0700361 SkRRect rr3;
362 rr3.setRectRadii(rect, radii2);
363 path_contains_rrect_check(reporter, rr3, dir, start);
364 }
365 }
caryclarkda707bf2015-11-19 14:47:43 -0800366}
367
368// Test out the cases when the RR degenerates to an oval
369static void test_round_rect_ovals(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000370 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700371 for (int start = 0; start < 8; ++start) {
372 //----
373 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
374 SkRRect rr1;
375 rr1.setRectXY(rect, SkScalarHalf(kWidth), SkScalarHalf(kHeight));
caryclarkda707bf2015-11-19 14:47:43 -0800376
bsalomon78d58d12016-05-27 09:17:04 -0700377 path_contains_rrect_check(reporter, rr1, dir, start);
378 }
379 }
caryclarkda707bf2015-11-19 14:47:43 -0800380}
381
382// Test out the non-degenerate RR cases
383static void test_round_rect_general(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000384 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700385 for (int start = 0; start < 8; ++start) {
386 //----
387 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
388 SkRRect rr1;
389 rr1.setRectXY(rect, 20, 20);
caryclarkda707bf2015-11-19 14:47:43 -0800390
bsalomon78d58d12016-05-27 09:17:04 -0700391 path_contains_rrect_check(reporter, rr1, dir, start);
caryclarkda707bf2015-11-19 14:47:43 -0800392
bsalomon78d58d12016-05-27 09:17:04 -0700393 //----
394 SkPoint radii[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
caryclarkda707bf2015-11-19 14:47:43 -0800395
bsalomon78d58d12016-05-27 09:17:04 -0700396 SkRRect rr2;
397 rr2.setRectRadii(rect, radii);
caryclarkda707bf2015-11-19 14:47:43 -0800398
bsalomon78d58d12016-05-27 09:17:04 -0700399 path_contains_rrect_check(reporter, rr2, dir, start);
400 }
401 }
caryclarkda707bf2015-11-19 14:47:43 -0800402}
403
404static void test_round_rect_iffy_parameters(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000405 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700406 for (int start = 0; start < 8; ++start) {
407 SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
408 SkPoint radii[4] = { { 50, 100 }, { 100, 50 }, { 50, 100 }, { 100, 50 } };
409 SkRRect rr1;
410 rr1.setRectRadii(rect, radii);
411 path_contains_rrect_nocheck(reporter, rr1, dir, start);
412 }
413 }
caryclarkda707bf2015-11-19 14:47:43 -0800414}
415
416static void set_radii(SkVector radii[4], int index, float rad) {
417 sk_bzero(radii, sizeof(SkVector) * 4);
418 radii[index].set(rad, rad);
419}
420
421static void test_skbug_3239(skiatest::Reporter* reporter) {
422 const float min = SkBits2Float(0xcb7f16c8); /* -16717512.000000 */
423 const float max = SkBits2Float(0x4b7f1c1d); /* 16718877.000000 */
424 const float big = SkBits2Float(0x4b7f1bd7); /* 16718807.000000 */
425
426 const float rad = 33436320;
427
428 const SkRect rectx = SkRect::MakeLTRB(min, min, max, big);
429 const SkRect recty = SkRect::MakeLTRB(min, min, big, max);
430
Mike Reed30bc5272019-11-22 18:34:02 +0000431 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700432 for (int start = 0; start < 8; ++start) {
433 SkVector radii[4];
434 for (int i = 0; i < 4; ++i) {
435 set_radii(radii, i, rad);
436 path_contains_rrect_check(reporter, rectx, radii, dir, start);
437 path_contains_rrect_check(reporter, recty, radii, dir, start);
438 }
439 }
caryclarkda707bf2015-11-19 14:47:43 -0800440 }
441}
442
443static void test_mix(skiatest::Reporter* reporter) {
Mike Reed30bc5272019-11-22 18:34:02 +0000444 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
bsalomon78d58d12016-05-27 09:17:04 -0700445 for (int start = 0; start < 8; ++start) {
446 // Test out mixed degenerate and non-degenerate geometry with Conics
447 const SkVector radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 100, 100 } };
448 SkRect r = SkRect::MakeWH(100, 100);
449 SkRRect rr;
450 rr.setRectRadii(r, radii);
451 path_contains_rrect_check(reporter, rr, dir, start);
452 }
453 }
caryclarkda707bf2015-11-19 14:47:43 -0800454}
455
456DEF_TEST(RoundRectInPath, reporter) {
457 test_tricky_radii(reporter);
458 test_empty_crbug_458524(reporter);
459 test_inset(reporter);
460 test_round_rect_basic(reporter);
461 test_round_rect_rects(reporter);
462 test_round_rect_ovals(reporter);
463 test_round_rect_general(reporter);
464 test_undetected_paths(reporter);
465 test_round_rect_iffy_parameters(reporter);
466 test_skbug_3239(reporter);
467 test_mix(reporter);
468}
Mike Reedd72d6c52018-02-12 15:56:06 -0500469
470DEF_TEST(RRect_fragile, reporter) {
471 SkRect rect = {
472 SkBits2Float(0x1f800000), // 0x003F0000 was the starter value that also fails
473 SkBits2Float(0x1400001C),
474 SkBits2Float(0x3F000004),
475 SkBits2Float(0x3F000004),
476 };
477
478 SkPoint radii[] = {
479 { SkBits2Float(0x00000001), SkBits2Float(0x00000001) },
480 { SkBits2Float(0x00000020), SkBits2Float(0x00000001) },
481 { SkBits2Float(0x00000000), SkBits2Float(0x00000000) },
482 { SkBits2Float(0x3F000004), SkBits2Float(0x3F000004) },
483 };
484
485 SkRRect rr;
486 // please don't assert
487 if (false) { // disable until we fix this
488 SkDebugf("%g 0x%08X\n", rect.fLeft, SkFloat2Bits(rect.fLeft));
489 rr.setRectRadii(rect, radii);
490 }
491}
492