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