• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
9 #include "SkPath.h"
10 
11 typedef SkScalar (*MakePathProc)(SkPath*);
12 
make_frame(SkPath * path)13 static SkScalar make_frame(SkPath* path) {
14     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
15                  SkIntToScalar(630), SkIntToScalar(470) };
16     path->addRoundRect(r, SkIntToScalar(15), SkIntToScalar(15));
17 
18     SkPaint paint;
19     paint.setStyle(SkPaint::kStroke_Style);
20     paint.setStrokeWidth(SkIntToScalar(5));
21     paint.getFillPath(*path, path);
22     return SkIntToScalar(15);
23 }
24 
make_triangle(SkPath * path)25 static SkScalar make_triangle(SkPath* path) {
26     constexpr int gCoord[] = {
27         10, 20, 15, 5, 30, 30
28     };
29     path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1]));
30     path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3]));
31     path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5]));
32     path->close();
33     path->offset(SkIntToScalar(10), SkIntToScalar(0));
34     return SkIntToScalar(30);
35 }
36 
make_rect(SkPath * path)37 static SkScalar make_rect(SkPath* path) {
38     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
39                  SkIntToScalar(30), SkIntToScalar(30) };
40     path->addRect(r);
41     path->offset(SkIntToScalar(10), SkIntToScalar(0));
42     return SkIntToScalar(30);
43 }
44 
make_oval(SkPath * path)45 static SkScalar make_oval(SkPath* path) {
46     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
47                  SkIntToScalar(30), SkIntToScalar(30) };
48     path->addOval(r);
49     path->offset(SkIntToScalar(10), SkIntToScalar(0));
50     return SkIntToScalar(30);
51 }
52 
make_sawtooth(SkPath * path,int teeth)53 static SkScalar make_sawtooth(SkPath* path, int teeth) {
54     SkScalar x = SkIntToScalar(20);
55     SkScalar y = SkIntToScalar(20);
56     const SkScalar x0 = x;
57     const SkScalar dx = SkIntToScalar(5);
58     const SkScalar dy = SkIntToScalar(10);
59 
60     path->moveTo(x, y);
61     for (int i = 0; i < teeth; i++) {
62         x += dx;
63         path->lineTo(x, y - dy);
64         x += dx;
65         path->lineTo(x, y + dy);
66     }
67     path->lineTo(x, y + (2 * dy));
68     path->lineTo(x0, y + (2 * dy));
69     path->close();
70     return SkIntToScalar(30);
71 }
72 
make_sawtooth_3(SkPath * path)73 static SkScalar make_sawtooth_3(SkPath* path) { return make_sawtooth(path, 3); }
make_sawtooth_32(SkPath * path)74 static SkScalar make_sawtooth_32(SkPath* path) { return make_sawtooth(path, 32); }
75 
make_house(SkPath * path)76 static SkScalar make_house(SkPath* path) {
77     path->moveTo(21, 23);
78     path->lineTo(21, 11.534f);
79     path->lineTo(22.327f, 12.741f);
80     path->lineTo(23.673f, 11.261f);
81     path->lineTo(12, 0.648f);
82     path->lineTo(8, 4.285f);
83     path->lineTo(8, 2);
84     path->lineTo(4, 2);
85     path->lineTo(4, 7.921f);
86     path->lineTo(0.327f, 11.26f);
87     path->lineTo(1.673f, 12.74f);
88     path->lineTo(3, 11.534f);
89     path->lineTo(3, 23);
90     path->lineTo(11, 23);
91     path->lineTo(11, 18);
92     path->lineTo(13, 18);
93     path->lineTo(13, 23);
94     path->lineTo(21, 23);
95     path->close();
96     path->lineTo(9, 16);
97     path->lineTo(9, 21);
98     path->lineTo(5, 21);
99     path->lineTo(5, 9.715f);
100     path->lineTo(12, 3.351f);
101     path->lineTo(19, 9.715f);
102     path->lineTo(19, 21);
103     path->lineTo(15, 21);
104     path->lineTo(15, 16);
105     path->lineTo(9, 16);
106     path->close();
107     path->offset(20, 0);
108     return SkIntToScalar(30);
109 }
110 
make_star(SkPath * path,int n)111 static SkScalar make_star(SkPath* path, int n) {
112     const SkScalar c = SkIntToScalar(45);
113     const SkScalar r = SkIntToScalar(20);
114 
115     SkScalar rad = -SK_ScalarPI / 2;
116     const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;
117 
118     path->moveTo(c, c - r);
119     for (int i = 1; i < n; i++) {
120         rad += drad;
121         SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV);
122         path->lineTo(c + cosV * r, c + sinV * r);
123     }
124     path->close();
125     return r * 2 * 6 / 5;
126 }
127 
make_star_5(SkPath * path)128 static SkScalar make_star_5(SkPath* path) { return make_star(path, 5); }
make_star_13(SkPath * path)129 static SkScalar make_star_13(SkPath* path) { return make_star(path, 13); }
130 
131 // We don't expect any output from this path.
make_line(SkPath * path)132 static SkScalar make_line(SkPath* path) {
133     path->moveTo(SkIntToScalar(30), SkIntToScalar(30));
134     path->lineTo(SkIntToScalar(120), SkIntToScalar(40));
135     path->close();
136     path->moveTo(SkIntToScalar(150), SkIntToScalar(30));
137     path->lineTo(SkIntToScalar(150), SkIntToScalar(30));
138     path->lineTo(SkIntToScalar(300), SkIntToScalar(40));
139     path->close();
140     return SkIntToScalar(40);
141 }
142 
make_info(SkPath * path)143 static void make_info(SkPath* path) {
144     path->moveTo(24, 4);
145     path->cubicTo(12.94999980926514f,
146                   4,
147                   4,
148                   12.94999980926514f,
149                   4,
150                   24);
151     path->cubicTo(4,
152                   35.04999923706055f,
153                   12.94999980926514f,
154                   44,
155                   24,
156                   44);
157     path->cubicTo(35.04999923706055f,
158                   44,
159                   44,
160                   35.04999923706055f,
161                   44,
162                   24);
163     path->cubicTo(44,
164                   12.95000076293945f,
165                   35.04999923706055f,
166                   4,
167                   24,
168                   4);
169     path->close();
170     path->moveTo(26, 34);
171     path->lineTo(22, 34);
172     path->lineTo(22, 22);
173     path->lineTo(26, 22);
174     path->lineTo(26, 34);
175     path->close();
176     path->moveTo(26, 18);
177     path->lineTo(22, 18);
178     path->lineTo(22, 14);
179     path->lineTo(26, 14);
180     path->lineTo(26, 18);
181     path->close();
182 }
183 
make_accessibility(SkPath * path)184 static void make_accessibility(SkPath* path) {
185     path->moveTo(12, 2);
186     path->cubicTo(13.10000038146973f,
187                   2,
188                   14,
189                   2.900000095367432f,
190                   14,
191                   4);
192     path->cubicTo(14,
193                   5.099999904632568f,
194                   13.10000038146973f,
195                   6,
196                   12,
197                   6);
198     path->cubicTo(10.89999961853027f,
199                   6,
200                   10,
201                   5.099999904632568f,
202                   10,
203                   4);
204     path->cubicTo(10,
205                   2.900000095367432f,
206                   10.89999961853027f,
207                   2,
208                   12,
209                   2);
210     path->close();
211     path->moveTo(21, 9);
212     path->lineTo(15, 9);
213     path->lineTo(15, 22);
214     path->lineTo(13, 22);
215     path->lineTo(13, 16);
216     path->lineTo(11, 16);
217     path->lineTo(11, 22);
218     path->lineTo(9, 22);
219     path->lineTo(9, 9);
220     path->lineTo(3, 9);
221     path->lineTo(3, 7);
222     path->lineTo(21, 7);
223     path->lineTo(21, 9);
224     path->close();
225 }
226 
227 // test case for http://crbug.com/695196
make_visualizer(SkPath * path)228 static void make_visualizer(SkPath* path) {
229     path->moveTo(1.9520f, 2.0000f);
230     path->conicTo(1.5573f, 1.9992f, 1.2782f, 2.2782f, 0.9235f);
231     path->conicTo(0.9992f, 2.5573f, 1.0000f, 2.9520f, 0.9235f);
232     path->lineTo(1.0000f, 5.4300f);
233     path->lineTo(17.0000f, 5.4300f);
234     path->lineTo(17.0000f, 2.9520f);
235     path->conicTo(17.0008f, 2.5573f, 16.7218f, 2.2782f, 0.9235f);
236     path->conicTo(16.4427f, 1.9992f, 16.0480f, 2.0000f, 0.9235f);
237     path->lineTo(1.9520f, 2.0000f);
238     path->close();
239     path->moveTo(2.7140f, 3.1430f);
240     path->conicTo(3.0547f, 3.1287f, 3.2292f, 3.4216f, 0.8590f);
241     path->conicTo(3.4038f, 3.7145f, 3.2292f, 4.0074f, 0.8590f);
242     path->conicTo(3.0547f, 4.3003f, 2.7140f, 4.2860f, 0.8590f);
243     path->conicTo(2.1659f, 4.2631f, 2.1659f, 3.7145f, 0.7217f);
244     path->conicTo(2.1659f, 3.1659f, 2.7140f, 3.1430f, 0.7217f);
245     path->lineTo(2.7140f, 3.1430f);
246     path->close();
247     path->moveTo(5.0000f, 3.1430f);
248     path->conicTo(5.3407f, 3.1287f, 5.5152f, 3.4216f, 0.8590f);
249     path->conicTo(5.6898f, 3.7145f, 5.5152f, 4.0074f, 0.8590f);
250     path->conicTo(5.3407f, 4.3003f, 5.0000f, 4.2860f, 0.8590f);
251     path->conicTo(4.4519f, 4.2631f, 4.4519f, 3.7145f, 0.7217f);
252     path->conicTo(4.4519f, 3.1659f, 5.0000f, 3.1430f, 0.7217f);
253     path->lineTo(5.0000f, 3.1430f);
254     path->close();
255     path->moveTo(7.2860f, 3.1430f);
256     path->conicTo(7.6267f, 3.1287f, 7.8012f, 3.4216f, 0.8590f);
257     path->conicTo(7.9758f, 3.7145f, 7.8012f, 4.0074f, 0.8590f);
258     path->conicTo(7.6267f, 4.3003f, 7.2860f, 4.2860f, 0.8590f);
259     path->conicTo(6.7379f, 4.2631f, 6.7379f, 3.7145f, 0.7217f);
260     path->conicTo(6.7379f, 3.1659f, 7.2860f, 3.1430f, 0.7217f);
261     path->close();
262     path->moveTo(1.0000f, 6.1900f);
263     path->lineTo(1.0000f, 14.3810f);
264     path->conicTo(0.9992f, 14.7757f, 1.2782f, 15.0548f, 0.9235f);
265     path->conicTo(1.5573f, 15.3338f, 1.9520f, 15.3330f, 0.9235f);
266     path->lineTo(16.0480f, 15.3330f);
267     path->conicTo(16.4427f, 15.3338f, 16.7218f, 15.0548f, 0.9235f);
268     path->conicTo(17.0008f, 14.7757f, 17.0000f, 14.3810f, 0.9235f);
269     path->lineTo(17.0000f, 6.1910f);
270     path->lineTo(1.0000f, 6.1910f);
271     path->lineTo(1.0000f, 6.1900f);
272     path->close();
273 }
274 
275 constexpr MakePathProc gProcs[] = {
276     make_frame,
277     make_triangle,
278     make_rect,
279     make_oval,
280     make_sawtooth_32,
281     make_star_5,
282     make_star_13,
283     make_line,
284     make_house,
285     make_sawtooth_3,
286 };
287 
288 #define N   SK_ARRAY_COUNT(gProcs)
289 
290 class PathFillGM : public skiagm::GM {
291     SkPath  fPath[N];
292     SkScalar fDY[N];
293     SkPath  fInfoPath;
294     SkPath  fAccessibilityPath;
295     SkPath  fVisualizerPath;
296 protected:
onOnceBeforeDraw()297     void onOnceBeforeDraw() override {
298         for (size_t i = 0; i < N; i++) {
299             fDY[i] = gProcs[i](&fPath[i]);
300         }
301 
302         make_info(&fInfoPath);
303         make_accessibility(&fAccessibilityPath);
304         make_visualizer(&fVisualizerPath);
305     }
306 
307 
onShortName()308     SkString onShortName() override {
309         return SkString("pathfill");
310     }
311 
onISize()312     SkISize onISize() override {
313         return SkISize::Make(640, 480);
314     }
315 
onDraw(SkCanvas * canvas)316     void onDraw(SkCanvas* canvas) override {
317         SkPaint paint;
318         paint.setAntiAlias(true);
319 
320         for (size_t i = 0; i < N; i++) {
321             canvas->drawPath(fPath[i], paint);
322             canvas->translate(SkIntToScalar(0), fDY[i]);
323         }
324 
325         canvas->save();
326         canvas->scale(0.300000011920929f, 0.300000011920929f);
327         canvas->translate(50, 50);
328         canvas->drawPath(fInfoPath, paint);
329         canvas->restore();
330 
331         canvas->scale(2, 2);
332         canvas->translate(5, 15);
333         canvas->drawPath(fAccessibilityPath, paint);
334 
335         canvas->scale(0.5f, 0.5f);
336         canvas->translate(5, 50);
337         canvas->drawPath(fVisualizerPath, paint);
338     }
339 
340 private:
341     typedef skiagm::GM INHERITED;
342 };
343 
344 // test inverse-fill w/ a clip that completely excludes the geometry
345 class PathInverseFillGM : public skiagm::GM {
346     SkPath  fPath[N];
347     SkScalar fDY[N];
348 protected:
onOnceBeforeDraw()349     void onOnceBeforeDraw() override {
350         for (size_t i = 0; i < N; i++) {
351             fDY[i] = gProcs[i](&fPath[i]);
352         }
353     }
354 
onShortName()355     SkString onShortName() override {
356         return SkString("pathinvfill");
357     }
358 
onISize()359     SkISize onISize() override {
360         return SkISize::Make(450, 220);
361     }
362 
show(SkCanvas * canvas,const SkPath & path,const SkPaint & paint,const SkRect * clip,SkScalar top,const SkScalar bottom)363     static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint,
364                      const SkRect* clip, SkScalar top, const SkScalar bottom) {
365         canvas->save();
366         if (clip) {
367             SkRect r = *clip;
368             r.fTop = top;
369             r.fBottom = bottom;
370             canvas->clipRect(r);
371         }
372         canvas->drawPath(path, paint);
373         canvas->restore();
374     }
375 
onDraw(SkCanvas * canvas)376     void onDraw(SkCanvas* canvas) override {
377         SkPath path;
378 
379         path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40));
380         path.toggleInverseFillType();
381 
382         SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) };
383 
384         canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
385 
386         for (int doclip = 0; doclip <= 1; ++doclip) {
387             for (int aa = 0; aa <= 1; ++aa) {
388                 SkPaint paint;
389                 paint.setAntiAlias(SkToBool(aa));
390 
391                 canvas->save();
392                 canvas->clipRect(clipR);
393 
394                 const SkRect* clipPtr = doclip ? &clipR : nullptr;
395 
396                 show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY());
397                 show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom);
398 
399                 canvas->restore();
400                 canvas->translate(SkIntToScalar(110), 0);
401             }
402         }
403     }
404 
405 private:
406     typedef skiagm::GM INHERITED;
407 };
408 
409 DEF_SIMPLE_GM(rotatedcubicpath, canvas, 200, 200) {
410     SkPaint p;
411     p.setAntiAlias(true);
412     p.setStyle(SkPaint::kFill_Style);
413 
414     canvas->translate(50, 50);
415     SkPath path;
416     path.moveTo(48,-23);
417     path.cubicTo(48,-29.5, 6,-30, 6,-30);
418     path.cubicTo(6,-30, 2,0, 2,0);
419     path.cubicTo(2,0, 44,-21.5, 48,-23);
420     path.close();
421 
422     p.setColor(SK_ColorBLUE);
423     canvas->drawPath(path, p);
424 
425     // Rotated path, which is not antialiased on GPU
426     p.setColor(SK_ColorRED);
427     canvas->rotate(90);
428     canvas->drawPath(path, p);
429 }
430 
431 ///////////////////////////////////////////////////////////////////////////////
432 
433 DEF_GM( return new PathFillGM; )
434 DEF_GM( return new PathInverseFillGM; )
435