1 /*
2  * Copyright 2011 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 "gm/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkPathBuilder.h"
13 #include "include/core/SkRect.h"
14 #include "include/core/SkScalar.h"
15 #include "include/core/SkSize.h"
16 #include "include/core/SkString.h"
17 #include "include/core/SkTypes.h"
18 
19 namespace {
20 struct PathDY {
21     SkPath   path;
22     SkScalar dy;
23 };
24 }
25 
26 typedef PathDY (*MakePathProc)();
27 
make_frame()28 static PathDY make_frame() {
29     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
30                  SkIntToScalar(630), SkIntToScalar(470) };
31     SkPath path = SkPath::RRect(SkRRect::MakeRectXY(r, 15, 15));
32     SkPaint paint;
33     paint.setStyle(SkPaint::kStroke_Style);
34     paint.setStrokeWidth(SkIntToScalar(5));
35     paint.getFillPath(path, &path);
36     return {path, 15};
37 }
38 
make_triangle()39 static PathDY make_triangle() {
40     constexpr int gCoord[] = {
41         10, 20, 15, 5, 30, 30
42     };
43     return {
44         SkPathBuilder().moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1]))
45                        .lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3]))
46                        .lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5]))
47                        .close()
48                        .offset(10, 0)
49                        .detach(),
50         30
51     };
52 }
53 
make_rect()54 static PathDY make_rect() {
55     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
56                  SkIntToScalar(30), SkIntToScalar(30) };
57     return {
58         SkPathBuilder().addRect(r).offset(10, 0).detach(),
59         30
60     };
61 }
62 
make_oval()63 static PathDY make_oval() {
64     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
65                  SkIntToScalar(30), SkIntToScalar(30) };
66     return {
67         SkPathBuilder().addOval(r).offset(10, 0).detach(),
68         30
69     };
70 }
71 
make_sawtooth(int teeth)72 static PathDY make_sawtooth(int teeth) {
73     SkScalar x = SkIntToScalar(20);
74     SkScalar y = SkIntToScalar(20);
75     const SkScalar x0 = x;
76     const SkScalar dx = SkIntToScalar(5);
77     const SkScalar dy = SkIntToScalar(10);
78 
79     SkPathBuilder builder;
80     builder.moveTo(x, y);
81     for (int i = 0; i < teeth; i++) {
82         x += dx;
83         builder.lineTo(x, y - dy);
84         x += dx;
85         builder.lineTo(x, y + dy);
86     }
87     builder.lineTo(x, y + (2 * dy));
88     builder.lineTo(x0, y + (2 * dy));
89     builder.close();
90 
91     return {builder.detach(), 30};
92 }
93 
make_sawtooth_3()94 static PathDY make_sawtooth_3() { return make_sawtooth(3); }
make_sawtooth_32()95 static PathDY make_sawtooth_32() { return make_sawtooth(32); }
96 
make_house()97 static PathDY make_house() {
98     SkPathBuilder builder;
99     builder.addPolygon({
100             {21, 23},
101             {21, 11.534f},
102             {22.327f, 12.741f},
103             {23.673f, 11.261f},
104             {12, 0.648f},
105             {8, 4.285f},
106             {8, 2},
107             {4, 2},
108             {4, 7.921f},
109             {0.327f, 11.26f},
110             {1.673f, 12.74f},
111             {3, 11.534f},
112             {3, 23},
113             {11, 23},
114             {11, 18},
115             {13, 18},
116             {13, 23},
117             {21, 23}}, true)
118         .polylineTo({
119             {9, 16},
120             {9, 21},
121             {5, 21},
122             {5, 9.715f},
123             {12, 3.351f},
124             {19, 9.715f},
125             {19, 21},
126             {15, 21},
127             {15, 16},
128             {9, 16}})
129         .close()
130         .offset(20, 0);
131     return {builder.detach(), 30};
132 }
133 
make_star(int n)134 static PathDY make_star(int n) {
135     const SkScalar c = SkIntToScalar(45);
136     const SkScalar r = SkIntToScalar(20);
137 
138     SkScalar rad = -SK_ScalarPI / 2;
139     const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;
140 
141     SkPathBuilder builder;
142     builder.moveTo(c, c - r);
143     for (int i = 1; i < n; i++) {
144         rad += drad;
145         builder.lineTo(c + SkScalarCos(rad) * r, c + SkScalarSin(rad) * r);
146     }
147     builder.close();
148 
149     return {builder.detach(), r * 2 * 6 / 5};
150 }
151 
make_star_5()152 static PathDY make_star_5()  { return make_star(5); }
make_star_13()153 static PathDY make_star_13() { return make_star(13); }
154 
155 // We don't expect any output from this path.
make_line()156 static PathDY make_line() {
157     return {
158         SkPathBuilder().moveTo(30, 30)
159                        .lineTo(120, 40)
160                        .close()
161                        .moveTo(150, 30)
162                        .lineTo(150, 30)
163                        .lineTo(300, 40)
164                        .close()
165                        .detach(),
166         40
167     };
168 }
169 
make_info()170 static SkPath make_info() {
171     SkPathBuilder path;
172     path.moveTo(24, 4);
173     path.cubicTo(12.94999980926514f, 4,
174                  4, 12.94999980926514f,
175                  4, 24);
176     path.cubicTo(4, 35.04999923706055f,
177                  12.94999980926514f, 44,
178                  24, 44);
179     path.cubicTo(35.04999923706055f, 44,
180                  44, 35.04999923706055f,
181                  44, 24);
182     path.cubicTo(44, 12.95000076293945f,
183                  35.04999923706055f, 4,
184                  24, 4);
185     path.close();
186     path.moveTo(26, 34);
187     path.lineTo(22, 34);
188     path.lineTo(22, 22);
189     path.lineTo(26, 22);
190     path.lineTo(26, 34);
191     path.close();
192     path.moveTo(26, 18);
193     path.lineTo(22, 18);
194     path.lineTo(22, 14);
195     path.lineTo(26, 14);
196     path.lineTo(26, 18);
197     path.close();
198     return path.detach();
199 }
200 
make_accessibility()201 static SkPath make_accessibility() {
202     SkPathBuilder path;
203     path.moveTo(12, 2);
204     path.cubicTo(13.10000038146973f, 2,
205                  14, 2.900000095367432f,
206                  14, 4);
207     path.cubicTo(14, 5.099999904632568f,
208                  13.10000038146973f, 6,
209                  12, 6);
210     path.cubicTo(10.89999961853027f, 6,
211                  10, 5.099999904632568f,
212                  10, 4);
213     path.cubicTo(10, 2.900000095367432f,
214                  10.89999961853027f, 2,
215                  12, 2);
216     path.close();
217     path.moveTo(21, 9);
218     path.lineTo(15, 9);
219     path.lineTo(15, 22);
220     path.lineTo(13, 22);
221     path.lineTo(13, 16);
222     path.lineTo(11, 16);
223     path.lineTo(11, 22);
224     path.lineTo(9, 22);
225     path.lineTo(9, 9);
226     path.lineTo(3, 9);
227     path.lineTo(3, 7);
228     path.lineTo(21, 7);
229     path.lineTo(21, 9);
230     path.close();
231     return path.detach();
232 }
233 
234 // test case for http://crbug.com/695196
make_visualizer()235 static SkPath make_visualizer() {
236     SkPathBuilder path;
237     path.moveTo(1.9520f, 2.0000f);
238     path.conicTo(1.5573f, 1.9992f, 1.2782f, 2.2782f, 0.9235f);
239     path.conicTo(0.9992f, 2.5573f, 1.0000f, 2.9520f, 0.9235f);
240     path.lineTo(1.0000f, 5.4300f);
241     path.lineTo(17.0000f, 5.4300f);
242     path.lineTo(17.0000f, 2.9520f);
243     path.conicTo(17.0008f, 2.5573f, 16.7218f, 2.2782f, 0.9235f);
244     path.conicTo(16.4427f, 1.9992f, 16.0480f, 2.0000f, 0.9235f);
245     path.lineTo(1.9520f, 2.0000f);
246     path.close();
247     path.moveTo(2.7140f, 3.1430f);
248     path.conicTo(3.0547f, 3.1287f, 3.2292f, 3.4216f, 0.8590f);
249     path.conicTo(3.4038f, 3.7145f, 3.2292f, 4.0074f, 0.8590f);
250     path.conicTo(3.0547f, 4.3003f, 2.7140f, 4.2860f, 0.8590f);
251     path.conicTo(2.1659f, 4.2631f, 2.1659f, 3.7145f, 0.7217f);
252     path.conicTo(2.1659f, 3.1659f, 2.7140f, 3.1430f, 0.7217f);
253     path.lineTo(2.7140f, 3.1430f);
254     path.close();
255     path.moveTo(5.0000f, 3.1430f);
256     path.conicTo(5.3407f, 3.1287f, 5.5152f, 3.4216f, 0.8590f);
257     path.conicTo(5.6898f, 3.7145f, 5.5152f, 4.0074f, 0.8590f);
258     path.conicTo(5.3407f, 4.3003f, 5.0000f, 4.2860f, 0.8590f);
259     path.conicTo(4.4519f, 4.2631f, 4.4519f, 3.7145f, 0.7217f);
260     path.conicTo(4.4519f, 3.1659f, 5.0000f, 3.1430f, 0.7217f);
261     path.lineTo(5.0000f, 3.1430f);
262     path.close();
263     path.moveTo(7.2860f, 3.1430f);
264     path.conicTo(7.6267f, 3.1287f, 7.8012f, 3.4216f, 0.8590f);
265     path.conicTo(7.9758f, 3.7145f, 7.8012f, 4.0074f, 0.8590f);
266     path.conicTo(7.6267f, 4.3003f, 7.2860f, 4.2860f, 0.8590f);
267     path.conicTo(6.7379f, 4.2631f, 6.7379f, 3.7145f, 0.7217f);
268     path.conicTo(6.7379f, 3.1659f, 7.2860f, 3.1430f, 0.7217f);
269     path.close();
270     path.moveTo(1.0000f, 6.1900f);
271     path.lineTo(1.0000f, 14.3810f);
272     path.conicTo(0.9992f, 14.7757f, 1.2782f, 15.0548f, 0.9235f);
273     path.conicTo(1.5573f, 15.3338f, 1.9520f, 15.3330f, 0.9235f);
274     path.lineTo(16.0480f, 15.3330f);
275     path.conicTo(16.4427f, 15.3338f, 16.7218f, 15.0548f, 0.9235f);
276     path.conicTo(17.0008f, 14.7757f, 17.0000f, 14.3810f, 0.9235f);
277     path.lineTo(17.0000f, 6.1910f);
278     path.lineTo(1.0000f, 6.1910f);
279     path.lineTo(1.0000f, 6.1900f);
280     path.close();
281     return path.detach();
282 }
283 
284 constexpr MakePathProc gProcs[] = {
285     make_frame,
286     make_triangle,
287     make_rect,
288     make_oval,
289     make_sawtooth_32,
290     make_star_5,
291     make_star_13,
292     make_line,
293     make_house,
294     make_sawtooth_3,
295 };
296 
297 #define N   SK_ARRAY_COUNT(gProcs)
298 
299 class PathFillGM : public skiagm::GM {
300     SkPath  fPath[N];
301     SkScalar fDY[N];
302     SkPath  fInfoPath;
303     SkPath  fAccessibilityPath;
304     SkPath  fVisualizerPath;
305 protected:
onOnceBeforeDraw()306     void onOnceBeforeDraw() override {
307         for (size_t i = 0; i < N; i++) {
308             auto [path, dy] = gProcs[i]();
309             fPath[i] = path;
310             fDY[i] = dy;
311         }
312 
313         fInfoPath = make_info();
314         fAccessibilityPath = make_accessibility();
315         fVisualizerPath = make_visualizer();
316     }
317 
318 
onShortName()319     SkString onShortName() override {
320         return SkString("pathfill");
321     }
322 
onISize()323     SkISize onISize() override {
324         return SkISize::Make(640, 480);
325     }
326 
onDraw(SkCanvas * canvas)327     void onDraw(SkCanvas* canvas) override {
328         SkPaint paint;
329         paint.setAntiAlias(true);
330 
331         for (size_t i = 0; i < N; i++) {
332             canvas->drawPath(fPath[i], paint);
333             canvas->translate(SkIntToScalar(0), fDY[i]);
334         }
335 
336         canvas->save();
337         canvas->scale(0.300000011920929f, 0.300000011920929f);
338         canvas->translate(50, 50);
339         canvas->drawPath(fInfoPath, paint);
340         canvas->restore();
341 
342         canvas->scale(2, 2);
343         canvas->translate(5, 15);
344         canvas->drawPath(fAccessibilityPath, paint);
345 
346         canvas->scale(0.5f, 0.5f);
347         canvas->translate(5, 50);
348         canvas->drawPath(fVisualizerPath, paint);
349     }
350 
351 private:
352     using INHERITED = skiagm::GM;
353 };
354 
355 // test inverse-fill w/ a clip that completely excludes the geometry
356 class PathInverseFillGM : public skiagm::GM {
357     SkPath  fPath[N];
358     SkScalar fDY[N];
359 protected:
onOnceBeforeDraw()360     void onOnceBeforeDraw() override {
361         for (size_t i = 0; i < N; i++) {
362             auto [path, dy] = gProcs[i]();
363             fPath[i] = path;
364             fDY[i] = dy;
365         }
366     }
367 
onShortName()368     SkString onShortName() override {
369         return SkString("pathinvfill");
370     }
371 
onISize()372     SkISize onISize() override {
373         return SkISize::Make(450, 220);
374     }
375 
show(SkCanvas * canvas,const SkPath & path,const SkPaint & paint,const SkRect * clip,SkScalar top,const SkScalar bottom)376     static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint,
377                      const SkRect* clip, SkScalar top, const SkScalar bottom) {
378         canvas->save();
379         if (clip) {
380             SkRect r = *clip;
381             r.fTop = top;
382             r.fBottom = bottom;
383             canvas->clipRect(r);
384         }
385         canvas->drawPath(path, paint);
386         canvas->restore();
387     }
388 
onDraw(SkCanvas * canvas)389     void onDraw(SkCanvas* canvas) override {
390         SkPath path = SkPathBuilder().addCircle(50, 50, 40)
391                                      .toggleInverseFillType()
392                                      .detach();
393 
394         SkRect clipR = {0, 0, 100, 200};
395 
396         canvas->translate(10, 10);
397 
398         for (int doclip = 0; doclip <= 1; ++doclip) {
399             for (int aa = 0; aa <= 1; ++aa) {
400                 SkPaint paint;
401                 paint.setAntiAlias(SkToBool(aa));
402 
403                 canvas->save();
404                 canvas->clipRect(clipR);
405 
406                 const SkRect* clipPtr = doclip ? &clipR : nullptr;
407 
408                 show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY());
409                 show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom);
410 
411                 canvas->restore();
412                 canvas->translate(SkIntToScalar(110), 0);
413             }
414         }
415     }
416 
417 private:
418     using INHERITED = skiagm::GM;
419 };
420 
421 DEF_SIMPLE_GM(rotatedcubicpath, canvas, 200, 200) {
422     SkPaint p;
423     p.setAntiAlias(true);
424     p.setStyle(SkPaint::kFill_Style);
425 
426     canvas->translate(50, 50);
427     SkPath path;
428     path.moveTo(48,-23);
429     path.cubicTo(48,-29.5, 6,-30, 6,-30);
430     path.cubicTo(6,-30, 2,0, 2,0);
431     path.cubicTo(2,0, 44,-21.5, 48,-23);
432     path.close();
433 
434     p.setColor(SK_ColorBLUE);
435     canvas->drawPath(path, p);
436 
437     // Rotated path, which is not antialiased on GPU
438     p.setColor(SK_ColorRED);
439     canvas->rotate(90);
440     canvas->drawPath(path, p);
441 }
442 
443 ///////////////////////////////////////////////////////////////////////////////
444 
445 DEF_GM( return new PathFillGM; )
DEF_GM(return new PathInverseFillGM;)446 DEF_GM( return new PathInverseFillGM; )
447 
448 DEF_SIMPLE_GM(bug7792, canvas, 800, 800) {
449     // from skbug.com/7792 bug description
450     SkPaint p;
451     SkPath path;
452     path.moveTo(10, 10);
453     path.moveTo(75, 75);
454     path.lineTo(150, 75);
455     path.lineTo(150, 150);
456     path.lineTo(75, 150);
457     canvas->drawPath(path, p);
458     // from skbug.com/7792#c3
459     canvas->translate(200, 0);
460     path.reset();
461     path.moveTo(75, 50);
462     path.moveTo(100, 75);
463     path.lineTo(150, 75);
464     path.lineTo(150, 150);
465     path.lineTo(75, 150);
466     path.lineTo(75, 50);
467     path.close();
468     canvas->drawPath(path, p);
469     // from skbug.com/7792#c9
470     canvas->translate(200, 0);
471     path.reset();
472     path.moveTo(10, 10);
473     path.moveTo(75, 75);
474     path.lineTo(150, 75);
475     path.lineTo(150, 150);
476     path.lineTo(75, 150);
477     path.close();
478     canvas->drawPath(path, p);
479     // from skbug.com/7792#c11
480     canvas->translate(-200 * 2, 200);
481     path.reset();
482     path.moveTo(75, 150);
483     path.lineTo(75, 75);
484     path.lineTo(150, 75);
485     path.lineTo(150, 150);
486     path.lineTo(75, 150);
487     path.moveTo(75, 150);
488     canvas->drawPath(path, p);
489     // from skbug.com/7792#c14
490     canvas->translate(200, 0);
491     path.reset();
492     path.moveTo(250, 75);
493     path.moveTo(250, 75);
494     path.moveTo(250, 75);
495     path.moveTo(100, 75);
496     path.lineTo(150, 75);
497     path.lineTo(150, 150);
498     path.lineTo(75, 150);
499     path.lineTo(75, 75);
500     path.close();
501     path.lineTo(0, 0);
502     path.close();
503     canvas->drawPath(path, p);
504     // from skbug.com/7792#c15
505     canvas->translate(200, 0);
506     path.reset();
507     path.moveTo(75, 75);
508     path.lineTo(150, 75);
509     path.lineTo(150, 150);
510     path.lineTo(75, 150);
511     path.moveTo(250, 75);
512     canvas->drawPath(path, p);
513     // from skbug.com/7792#c17
514     canvas->translate(-200 * 2, 200);
515     path.reset();
516     path.moveTo(75, 10);
517     path.moveTo(75, 75);
518     path.lineTo(150, 75);
519     path.lineTo(150, 150);
520     path.lineTo(75, 150);
521     path.lineTo(75, 10);
522     path.close();
523     canvas->drawPath(path, p);
524     // from skbug.com/7792#c19
525     canvas->translate(200, 0);
526     path.reset();
527     path.moveTo(75, 75);
528     path.lineTo(75, 75);
529     path.lineTo(75, 75);
530     path.lineTo(75, 75);
531     path.lineTo(150, 75);
532     path.lineTo(150, 150);
533     path.lineTo(75, 150);
534     path.close();
535     path.moveTo(10, 10);
536     path.lineTo(30, 10);
537     path.lineTo(10, 30);
538     canvas->drawPath(path, p);
539     // from skbug.com/7792#c23
540     canvas->translate(200, 0);
541     path.reset();
542     path.moveTo(75, 75);
543     path.lineTo(75, 75);
544     path.moveTo(75, 75);
545     path.lineTo(75, 75);
546     path.lineTo(150, 75);
547     path.lineTo(150, 150);
548     path.lineTo(75, 150);
549     path.close();
550     canvas->drawPath(path, p);
551     // from skbug.com/7792#c29
552     canvas->translate(-200 * 2, 200);
553     path.reset();
554     path.moveTo(75, 75);
555     path.lineTo(150, 75);
556     path.lineTo(150, 150);
557     path.lineTo(75, 150);
558     path.lineTo(75, 250);
559     path.moveTo(75, 75);
560     path.close();
561     canvas->drawPath(path, p);
562     // from skbug.com/7792#c31
563     canvas->translate(200, 0);
564     path.reset();
565     path.moveTo(75, 75);
566     path.lineTo(150, 75);
567     path.lineTo(150, 150);
568     path.lineTo(75, 150);
569     path.lineTo(75, 10);
570     path.moveTo(75, 75);
571     path.close();
572     canvas->drawPath(path, p);
573     // from skbug.com/7792#c36
574     canvas->translate(200, 0);
575     path.reset();
576     path.moveTo(75, 75);
577     path.lineTo(150, 75);
578     path.lineTo(150, 150);
579     path.lineTo(10, 150);
580     path.moveTo(75, 75);
581     path.lineTo(75, 75);
582     canvas->drawPath(path, p);
583     // from skbug.com/7792#c39
584     canvas->translate(200, -200 * 3);
585     path.reset();
586     path.moveTo(150, 75);
587     path.lineTo(150, 150);
588     path.lineTo(75, 150);
589     path.lineTo(75, 100);
590     canvas->drawPath(path, p);
591     // from zero_length_paths_aa
592     canvas->translate(0, 200);
593     path.reset();
594     path.moveTo(150, 100);
595     path.lineTo(150, 100);
596     path.lineTo(150, 150);
597     path.lineTo(75, 150);
598     path.lineTo(75, 100);
599     path.lineTo(75, 75);
600     path.lineTo(150, 75);
601     path.close();
602     canvas->drawPath(path, p);
603     // from skbug.com/7792#c41
604     canvas->translate(0, 200);
605     path.reset();
606     path.moveTo(75, 75);
607     path.lineTo(150, 75);
608     path.lineTo(150, 150);
609     path.lineTo(140, 150);
610     path.lineTo(140, 75);
611     path.moveTo(75, 75);
612     path.close();
613     canvas->drawPath(path, p);
614     // from skbug.com/7792#c53
615     canvas->translate(0, 200);
616     path.reset();
617     path.moveTo(75, 75);
618     path.lineTo(150, 75);
619     path.lineTo(150, 150);
620     path.lineTo(140, 150);
621     path.lineTo(140, 75);
622     path.moveTo(75, 75);
623     path.close();
624     canvas->drawPath(path, p);
625 }
626 
627 #include "include/core/SkSurface.h"
628 
629 DEF_SIMPLE_GM(path_stroke_clip_crbug1070835, canvas, 25, 50) {
630     SkCanvas* orig = canvas;
631     auto surf = SkSurface::MakeRasterN32Premul(25, 25);
632     canvas = surf->getCanvas();
633 
634     SkPaint p;
635     p.setColor(SK_ColorRED);
636     p.setAntiAlias(true);
637     p.setStyle(SkPaint::kStroke_Style);
638     p.setStrokeWidth(2);
639 
640     canvas->scale(4.16666651f/2, 4.16666651f/2);
641 
642     SkPath path;
643 
644     SkPoint pts[] = {
645     {11, 12},
646     {11, 18.0751324f},
647     {6.07513189f, 23},
648     {-4.80825292E-7f, 23},
649     {-6.07513332f, 23},
650     {-11, 18.0751324f},
651     {-11, 11.999999f},
652     {-10.999999f, 5.92486763f},
653     {-6.07513189f, 1},
654     {1.31173692E-7f, 1},
655     {6.07513141f, 1},
656     {10.9999981f, 5.92486572f},
657     {11, 11.9999971f},
658     };
659     path.moveTo(pts[0]).cubicTo(pts[1], pts[2], pts[3])
660                        .cubicTo(pts[4], pts[5], pts[6])
661                        .cubicTo(pts[7], pts[8], pts[9])
662                        .cubicTo(pts[10],pts[11],pts[12]);
663 
664     canvas->drawPath(path, p);
665 
666     surf->draw(orig, 0, 0);
667 }
668 
669 DEF_SIMPLE_GM(path_arcto_skbug_9077, canvas, 200, 200) {
670     SkPaint p;
671     p.setColor(SK_ColorRED);
672     p.setAntiAlias(true);
673     p.setStyle(SkPaint::kStroke_Style);
674     p.setStrokeWidth(2);
675 
676     SkPathBuilder path;
677     SkPoint pts[] = { {20, 20}, {100, 20}, {100, 60}, {130, 150}, {180, 160} };
678     SkScalar radius = 60;
679     path.moveTo(pts[0]);
680     path.lineTo(pts[1]);
681     path.lineTo(pts[2]);
682     path.close();
683     path.arcTo(pts[3], pts[4], radius);
684     canvas->drawPath(path.detach(), p);
685 }
686 
687 DEF_SIMPLE_GM(path_skbug_11859, canvas, 512, 512) {
688     SkPaint paint;
689     paint.setColor(SK_ColorRED);
690     paint.setAntiAlias(true);
691 
692     SkPath path;
693     path.moveTo(258, -2);
694     path.lineTo(258, 258);
695     path.lineTo(237, 258);
696     path.lineTo(240, -2);
697     path.lineTo(258, -2);
698     path.moveTo(-2, -2);
699     path.lineTo(240, -2);
700     path.lineTo(238, 131);
701     path.lineTo(-2, 131);
702     path.lineTo(-2, -2);
703 
704     canvas->scale(2, 2);
705     canvas->drawPath(path, paint);
706 }
707 
708 DEF_SIMPLE_GM(path_skbug_11886, canvas, 256, 256) {
709     SkPoint m = {0.f, 770.f};
710     SkPath path;
711     path.moveTo(m);
712     path.cubicTo(m + SkPoint{0.f, 1.f}, m + SkPoint{20.f, -750.f}, m + SkPoint{83.f, -746.f});
713     SkPaint paint;
714     paint.setAntiAlias(true);
715     canvas->drawPath(path, paint);
716 }
717