1 /*
2  * Copyright 2014 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 "PathOpsExtendedTest.h"
9 #include "PathOpsTestCommon.h"
10 #include "SkBitmap.h"
11 #include "Test.h"
12 
DEF_TEST(PathOpsBuilder,reporter)13 DEF_TEST(PathOpsBuilder, reporter) {
14     SkOpBuilder builder;
15     SkPath result;
16     REPORTER_ASSERT(reporter, builder.resolve(&result));
17     REPORTER_ASSERT(reporter, result.isEmpty());
18 
19     builder.add(result, kDifference_SkPathOp);
20     REPORTER_ASSERT(reporter, builder.resolve(&result));
21     REPORTER_ASSERT(reporter, result.isEmpty());
22 
23     builder.add(result, kUnion_SkPathOp);
24     REPORTER_ASSERT(reporter, builder.resolve(&result));
25     REPORTER_ASSERT(reporter, result.isEmpty());
26 
27     SkPath rectPath;
28     rectPath.setFillType(SkPath::kEvenOdd_FillType);
29     rectPath.addRect(0, 1, 2, 3, SkPath::kCW_Direction);
30     builder.add(rectPath, kUnion_SkPathOp);
31     REPORTER_ASSERT(reporter, builder.resolve(&result));
32     bool closed;
33     SkPath::Direction dir;
34     REPORTER_ASSERT(reporter, result.isRect(nullptr, &closed, &dir));
35     REPORTER_ASSERT(reporter, closed);
36     REPORTER_ASSERT(reporter, dir == SkPath::kCCW_Direction);
37     int pixelDiff = comparePaths(reporter, __FUNCTION__, rectPath, result);
38     REPORTER_ASSERT(reporter, pixelDiff == 0);
39 
40     rectPath.reset();
41     rectPath.setFillType(SkPath::kEvenOdd_FillType);
42     rectPath.addRect(0, 1, 2, 3, SkPath::kCCW_Direction);
43     builder.add(rectPath, kUnion_SkPathOp);
44     REPORTER_ASSERT(reporter, builder.resolve(&result));
45     REPORTER_ASSERT(reporter, result.isRect(nullptr, &closed, &dir));
46     REPORTER_ASSERT(reporter, closed);
47     REPORTER_ASSERT(reporter, dir == SkPath::kCCW_Direction);
48     REPORTER_ASSERT(reporter, rectPath == result);
49 
50     builder.add(rectPath, kDifference_SkPathOp);
51     REPORTER_ASSERT(reporter, builder.resolve(&result));
52     REPORTER_ASSERT(reporter, result.isEmpty());
53 
54     SkPath rect2, rect3;
55     rect2.addRect(2, 1, 4, 3, SkPath::kCW_Direction);
56     rect3.addRect(4, 1, 5, 3, SkPath::kCCW_Direction);
57     builder.add(rectPath, kUnion_SkPathOp);
58     builder.add(rect2, kUnion_SkPathOp);
59     builder.add(rect3, kUnion_SkPathOp);
60     REPORTER_ASSERT(reporter, builder.resolve(&result));
61     REPORTER_ASSERT(reporter, result.isRect(nullptr, &closed, &dir));
62     REPORTER_ASSERT(reporter, closed);
63     SkRect expected;
64     expected.set(0, 1, 5, 3);
65     REPORTER_ASSERT(reporter, result.getBounds() == expected);
66 
67     SkPath circle1, circle2, circle3;
68     circle1.addCircle(5, 6, 4, SkPath::kCW_Direction);
69     circle2.addCircle(7, 4, 8, SkPath::kCCW_Direction);
70     circle3.addCircle(6, 5, 6, SkPath::kCW_Direction);
71     SkPath opCompare;
72     Op(circle1, circle2, kUnion_SkPathOp, &opCompare);
73     Op(opCompare, circle3, kDifference_SkPathOp, &opCompare);
74     builder.add(circle1, kUnion_SkPathOp);
75     builder.add(circle2, kUnion_SkPathOp);
76     builder.add(circle3, kDifference_SkPathOp);
77     REPORTER_ASSERT(reporter, builder.resolve(&result));
78     pixelDiff = comparePaths(reporter, __FUNCTION__, opCompare, result);
79     REPORTER_ASSERT(reporter, pixelDiff == 0);
80 }
81 
DEF_TEST(BuilderIssue3838,reporter)82 DEF_TEST(BuilderIssue3838, reporter) {
83     SkPath path;
84     path.moveTo(200, 170);
85     path.lineTo(220, 170);
86     path.lineTo(220, 230);
87     path.lineTo(240, 230);
88     path.lineTo(240, 210);
89     path.lineTo(180, 210);
90     path.lineTo(180, 190);
91     path.lineTo(260, 190);
92     path.lineTo(260, 250);
93     path.lineTo(200, 250);
94     path.lineTo(200, 170);
95     path.close();
96     SkPath path2;
97     SkOpBuilder builder;
98     builder.add(path, kUnion_SkPathOp);
99     builder.resolve(&path2);
100     int pixelDiff = comparePaths(reporter, __FUNCTION__, path, path2);
101     REPORTER_ASSERT(reporter, pixelDiff == 0);
102 }
103 
DEF_TEST(BuilderIssue3838_2,reporter)104 DEF_TEST(BuilderIssue3838_2, reporter) {
105     SkPath path;
106     path.addCircle(100, 100, 50);
107 
108     SkOpBuilder builder;
109     builder.add(path, kUnion_SkPathOp);
110     builder.add(path, kUnion_SkPathOp);
111 
112     SkPath result;
113     builder.resolve(&result);
114     int pixelDiff = comparePaths(reporter, __FUNCTION__, path, result);
115     REPORTER_ASSERT(reporter, pixelDiff == 0);
116 }
117 
DEF_TEST(BuilderIssue3838_3,reporter)118 DEF_TEST(BuilderIssue3838_3, reporter) {
119     SkPath path;
120     path.moveTo(40, 10);
121     path.lineTo(60, 10);
122     path.lineTo(60, 30);
123     path.lineTo(40, 30);
124     path.lineTo(40, 10);
125     path.moveTo(41, 11);
126     path.lineTo(41, 29);
127     path.lineTo(59, 29);
128     path.lineTo(59, 11);
129     path.lineTo(41, 11);
130 
131     SkOpBuilder builder;
132     builder.add(path, kUnion_SkPathOp);
133     SkPath result;
134     builder.resolve(&result);
135     int pixelDiff = comparePaths(reporter, __FUNCTION__, path, result);
136     REPORTER_ASSERT(reporter, pixelDiff == 0);
137 }
138 
DEF_TEST(BuilderIssue502792_2,reporter)139 DEF_TEST(BuilderIssue502792_2, reporter) {
140     SkPath path, pathB;
141     path.setFillType(SkPath::kWinding_FillType);
142     path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
143     path.addRect(2, 2, 3, 3, SkPath::kCW_Direction);
144     pathB.setFillType(SkPath::kEvenOdd_FillType);
145     pathB.addRect(3, 3, 4, 4, SkPath::kCW_Direction);
146     pathB.addRect(3, 3, 4, 4, SkPath::kCW_Direction);
147     SkOpBuilder builder;
148     builder.add(path, kUnion_SkPathOp);
149     builder.add(pathB, kDifference_SkPathOp);
150     SkPath result;
151     builder.resolve(&result);
152 }
153 
DEF_TEST(Fuzz846,reporter)154 DEF_TEST(Fuzz846, reporter) {
155 /*
156 <clipPath id="clip-circle">
157     <circle id="circle" cx="60" cy="60" r="50" />
158 </clipPath>
159 <clipPath id="clip-rect">
160     <clipPath id="clip-rect">
161         <clipPath id="clip-rect">
162             <clipPath id="clip-rect">
163                 <rect x="10" y="30" width="0" height="60" />
164                 <rect x="10" y="30" width="0" height="60" />
165                 <rect x="10" y="30" width="100" height="60" />
166                 <rect x="10" y="30" width="32668" />
167                 <rect x="10" y="30" width="100" height="18446744073709551615" />
168                 <rect x="10" y="255" width="100" height="60" />
169                 <rect width="100" height="60" />
170                 <rect x="10" y="30" width="100" height="60" />
171                 <rect x="10" y="30" width="100" height="4294967236" />
172                 <rect x="10" y="30" width="100" height="60" />
173             </clipPath>
174             <rect x="10" y="30" width="0" height="60" />
175             <rect x="10" y="30" width="0" height="0.18093252719929986369568203" />
176             <rect x="10" y="30" width="100" height="60" />
177             <rect x="10" y="30" width="32668" height="60" />
178             <rect x="10" y="30" width="100" height="18446744073709551615" />
179             <rect x="10" y="255" width="100" height="60" />
180             <rect x="2147483649" y="30" width="100" height="60" />
181             <rect x="10" y="30" width="100" height="60" />
182             <rect x="10" y="30" width="100" height="60" />
183             <rect x="10" y="30" width="100" height="60" />
184         </clipPath>
185         <rect x="10" y="30" width="0" height="60" />
186         <rect x="10" y="30" width="0" height="60" />
187         <rect x="10" y="30" width="100" height="60" />
188         <rect x="10" y="30" width="32668" height="60" />
189         <rect x="10" y="30" width="100" height="18446744073709551615" />
190         <rect x="10" y="255" width="100" height="60" />
191         <rect x="2147483649" y="30" width="100" height="60" />
192         <rect x="10" y="30" width="100" height="60" />
193         <rect x="10" y="2879753595" width="100" height="60" />
194         <rect x="10" y="30" width="100" height="60" />
195     </clipPath>
196     <rect x="10" y="30" width="100" height="60" />
197     <rect x="10" y="30" width="0" height="60" />
198     <rect x="10" y="30" width="100" height="60" />
199     <rect x="10" y="30" width="32668" height="60" />
200     <rect x="10" y="30" width="100" height="18446744073709551615" />
201     <rect x="10" y="255" width="100" height="60" />
202     <rect x="2147483649" y="30" width="100" height="60" />
203     <rect x="10" y="30" width="100" height="60" />
204     <rect x="10" y="30" width="100" height="4294967236" />
205     <rect x="10" y="30" width="100" height="4294967236" />
206     <rect x="10" y="30" width="100" height="4294967236" />
207     <rect x="10" y="30" width="100" height="4294967236" />
208     <rect x="10" y="30" width="100" height="60" />
209     <rect x="757798030" y="30" width="100" height="60" />
210 */
211     SkPath clipCircle, clipRect;
212     SkPath inner;
213     clipCircle.addCircle(60, 60, 50);             // <circle id="circle" cx="60" cy="60" r="50" />
214 
215     inner.addRect(10, 30, 10+0, 30+60);           // <rect x="10" y="30" width="0" height="60" />
216     inner.addRect(10, 30, 10+0, 30+60);           // <rect x="10" y="30" width="0" height="60" />
217     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
218     inner.addRect(10, 30, 10+32668, 30+0);        // <rect x="10" y="30" width="32668" />
219     inner.addRect(10, 30, 10+100, 30+18446744073709551615.f); // <rect x="10" y="30" width="100" height="18446744073709551615" />
220     inner.addRect(10, 255, 10+100, 255+60);       // <rect x="10" y="255" width="100" height="60" />
221     inner.addRect(0, 0, 0+100, 0+60);             //  <rect width="100" height="60" />
222     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
223     inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
224     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
225     clipRect.addPath(inner);
226     inner.reset();
227     inner.addRect(10, 30, 10+0, 30+60);           // <rect x="10" y="30" width="0" height="60" />
228     inner.addRect(10, 30, 10+0, 30+0.18093252719929986369568203f); // <rect x="10" y="30" width="0" height="0.18093252719929986369568203" />
229     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
230     inner.addRect(10, 30, 10+32668, 30+60);       // <rect x="10" y="30" width="32668" height="60" />
231     inner.addRect(10, 30, 10+100, 30+18446744073709551615.f); // <rect x="10" y="30" width="100" height="18446744073709551615" />
232     inner.addRect(10, 255, 10+100, 255+60);       // <rect x="10" y="255" width="100" height="60" />
233     inner.addRect(2147483649.f, 30, 2147483649.f+100, 30+60); // <rect x="2147483649" y="30" width="100" height="60" />
234     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
235     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
236     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
237     clipRect.addPath(inner);
238     inner.reset();
239     inner.addRect(10, 30, 10+0, 30+60);           // <rect x="10" y="30" width="0" height="60" />
240     inner.addRect(10, 30, 10+0, 30+60);           // <rect x="10" y="30" width="0" height="60" />
241     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
242     inner.addRect(10, 30, 10+32668, 30+60);       // <rect x="10" y="30" width="32668" height="60" />
243     inner.addRect(10, 30, 10+100, 30+18446744073709551615.f); // <rect x="10" y="30" width="100" height="18446744073709551615" />
244     inner.addRect(10, 255, 10+100, 255+60);       // <rect x="10" y="255" width="100" height="60" />
245     inner.addRect(2147483649.f, 30, 2147483649.f+100, 30+60); // <rect x="2147483649" y="30" width="100" height="60" />
246     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
247     inner.addRect(10, 2879753595.f, 10+100, 30+2879753595.f); // <rect x="10" y="2879753595" width="100" height="60" />
248     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
249     clipRect.addPath(inner);
250     inner.reset();
251     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
252     inner.addRect(10, 30, 10+0, 30+60);           // <rect x="10" y="30" width="0" height="60" />
253     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
254     inner.addRect(10, 30, 10+32668, 30+60);       // <rect x="10" y="30" width="32668" height="60" />
255     inner.addRect(10, 30, 10+100, 30+18446744073709551615.f); // <rect x="10" y="30" width="100" height="18446744073709551615" />
256     inner.addRect(10, 255, 10+100, 255+60);       // <rect x="10" y="255" width="100" height="60" />
257     inner.addRect(2147483649.f, 30, 2147483649.f+100, 30+60); // <rect x="2147483649" y="30" width="100" height="60" />
258     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
259     inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
260     inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
261     inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
262     inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
263     inner.addRect(10, 30, 10+100, 30+60);         // <rect x="10" y="30" width="100" height="60" />
264     inner.addRect(757798030.f, 30, 757798030.f+100, 30+60); // <rect x="757798030" y="30" width="100" height="60" />
265     clipRect.addPath(inner);
266 
267     SkOpBuilder builder;
268     builder.add(clipCircle, kUnion_SkPathOp);
269     builder.add(clipRect, kDifference_SkPathOp);
270     SkPath result;
271     builder.resolve(&result);
272 }
273 
DEF_TEST(Issue569540,reporter)274 DEF_TEST(Issue569540, reporter) {
275     SkPath path1;
276     path1.moveTo(5, -225);
277     path1.lineTo(-225, 7425);
278     path1.lineTo(7425, 7425);
279     path1.lineTo(7425, -225);
280     path1.lineTo(-225, -225);
281     path1.lineTo(5, -225);
282     path1.close();
283 
284     SkPath path2;
285     path2.moveTo(5940, 2790);
286     path2.lineTo(5940, 2160);
287     path2.lineTo(5970, 1980);
288     path2.lineTo(5688, 773669888);
289     path2.lineTo(5688, 2160);
290     path2.lineTo(5688, 2430);
291     path2.lineTo(5400, 4590);
292     path2.lineTo(5220, 4590);
293     path2.lineTo(5220, 4920);
294     path2.cubicTo(5182.22900390625f, 4948.328125f, 5160, 4992.78662109375f, 5160, 5040.00048828125f);
295     path2.lineTo(5940, 2790);
296     path2.close();
297 
298     SkOpBuilder builder;
299     builder.add(path1, kUnion_SkPathOp);
300     builder.add(path2, kUnion_SkPathOp);
301     SkPath result;
302     builder.resolve(&result);
303 }
304 
DEF_TEST(SkOpBuilderFuzz665,reporter)305 DEF_TEST(SkOpBuilderFuzz665, reporter) {
306     SkPath path;
307     path.setFillType(SkPath::kEvenOdd_FillType);
308 path.moveTo(SkBits2Float(0xcc4264a7), SkBits2Float(0x4bb12e50));  // -5.0959e+07f, 2.32235e+07f
309 path.lineTo(SkBits2Float(0xcc4264b0), SkBits2Float(0x4bb12e48));  // -5.0959e+07f, 2.32234e+07f
310 path.lineTo(SkBits2Float(0xcc4264a7), SkBits2Float(0x4bb12e50));  // -5.0959e+07f, 2.32235e+07f
311 path.close();
312     SkPath path1(path);
313     path.reset();
314     path.setFillType(SkPath::kWinding_FillType);
315 path.moveTo(SkBits2Float(0x43213333), SkBits2Float(0x43080000));  // 161.2f, 136
316 path.lineTo(SkBits2Float(0x43038000), SkBits2Float(0x43080000));  // 131.5f, 136
317 path.cubicTo(SkBits2Float(0x43038000), SkBits2Float(0x42f00000), SkBits2Float(0x42f16666), SkBits2Float(0x42d53333), SkBits2Float(0x42d3cccd), SkBits2Float(0x42cd6666));  // 131.5f, 120, 120.7f, 106.6f, 105.9f, 102.7f
318 path.lineTo(SkBits2Float(0x42e33333), SkBits2Float(0x42940000));  // 113.6f, 74
319     SkPath path2(path);
320     SkOpBuilder builder;
321     builder.add(path1, kUnion_SkPathOp);
322     builder.add(path2, kUnion_SkPathOp);
323     SkPath result;
324     builder.resolve(&result);
325 }
326 
DEF_TEST(SkOpBuilder618991,reporter)327 DEF_TEST(SkOpBuilder618991, reporter) {
328     SkPath path0;
329     path0.moveTo(140, 40);
330     path0.lineTo(200, 210);
331     path0.lineTo(40, 100);
332     path0.lineTo(2.22223e+07f, 2.22222e+14f);
333     path0.lineTo(2.22223e+07f, 2.22222e+14f);
334 
335     SkPath path1;
336     path1.moveTo(160, 60);
337     path1.lineTo(220, 230);
338     path1.lineTo(60, 120);
339     path1.lineTo(2.22223e+07f, 2.22222e+14f);
340     path1.lineTo(2.22223e+07f, 2.22222e+14f);
341 
342     SkOpBuilder builder;
343     builder.add(path0, SkPathOp::kUnion_SkPathOp);
344     builder.add(path1, SkPathOp::kUnion_SkPathOp);
345     builder.resolve(&path0);
346 }
347 
DEF_TEST(SkOpBuilderKFuzz1,reporter)348 DEF_TEST(SkOpBuilderKFuzz1, reporter) {
349     SkPath path;
350 path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
351 path.lineTo(SkBits2Float(0x39008001), SkBits2Float(0xd31fbc1d));  // 0.000122547f, -6.86056e+11f
352 path.conicTo(SkBits2Float(0x246a205a), SkBits2Float(0x0080d3fb), SkBits2Float(0xce000001), SkBits2Float(0x04d31fbc), SkBits2Float(0x57a82c00));  // 5.07681e-17f, 1.1831e-38f, -5.36871e+08f, 4.9635e-36f, 3.69814e+14f
353     SkPath path0(path);
354     path.reset();
355 path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
356 path.cubicTo(SkBits2Float(0x80d3f924), SkBits2Float(0xcecece4f), SkBits2Float(0xcececece), SkBits2Float(0xcececece), SkBits2Float(0x9a9a9ace), SkBits2Float(0x9a9a9a9a));  // -1.94667e-38f, -1.73481e+09f, -1.73483e+09f, -1.73483e+09f, -6.3943e-23f, -6.39427e-23f
357 path.moveTo(SkBits2Float(0x9a9a019a), SkBits2Float(0xa59a9a9a));  // -6.36955e-23f, -2.68195e-16f
358     SkPath path1(path);
359 SkOpBuilder builder;
360     builder.add(path0, SkPathOp::kUnion_SkPathOp);
361     builder.add(path1, SkPathOp::kUnion_SkPathOp);
362     builder.resolve(&path);
363 }
364