Add fixes & test for isConfigTexturable and isConfigRenderable
[platform/upstream/libSkiaSharp.git] / gm / concavepaths.cpp
1 /*
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
8 #include "gm.h"
9 #include "SkCanvas.h"
10 #include "SkPath.h"
11
12 namespace {
13 // Concave test
14 void test_concave(SkCanvas* canvas, const SkPaint& paint) {
15     SkPath path;
16     canvas->translate(0, 0);
17     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
18     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
19     path.lineTo(SkIntToScalar(30), SkIntToScalar(30));
20     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
21     canvas->drawPath(path, paint);
22 }
23
24 // Reverse concave test
25 void test_reverse_concave(SkCanvas* canvas, const SkPaint& paint) {
26     SkPath path;
27     canvas->save();
28     canvas->translate(100, 0);
29     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
30     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
31     path.lineTo(SkIntToScalar(30), SkIntToScalar(30));
32     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
33     canvas->drawPath(path, paint);
34     canvas->restore();
35 }
36
37 // Bowtie (intersection)
38 void test_bowtie(SkCanvas* canvas, const SkPaint& paint) {
39     SkPath path;
40     canvas->save();
41     canvas->translate(200, 0);
42     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
43     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
44     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
45     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
46     canvas->drawPath(path, paint);
47     canvas->restore();
48 }
49
50 // "fake" bowtie (concave, but no intersection)
51 void test_fake_bowtie(SkCanvas* canvas, const SkPaint& paint) {
52     SkPath path;
53     canvas->save();
54     canvas->translate(300, 0);
55     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
56     path.lineTo(SkIntToScalar(50), SkIntToScalar(40));
57     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
58     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
59     path.lineTo(SkIntToScalar(50), SkIntToScalar(60));
60     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
61     canvas->drawPath(path, paint);
62     canvas->restore();
63 }
64
65 // Bowtie with a smaller right hand lobe. The outer vertex of the left hand
66 // lobe intrudes into the interior of the right hand lobe.
67 void test_intruding_vertex(SkCanvas* canvas, const SkPaint& paint) {
68     SkPath path;
69     canvas->save();
70     canvas->translate(400, 0);
71     path.setIsVolatile(true);
72     path.moveTo(20, 20);
73     path.lineTo(50, 50);
74     path.lineTo(68, 20);
75     path.lineTo(68, 80);
76     path.lineTo(50, 50);
77     path.lineTo(20, 80);
78     canvas->drawPath(path, paint);
79     canvas->restore();
80 }
81
82 // A shape with an edge that becomes inverted on AA stroking and that also contains
83 // a repeated start/end vertex.
84 void test_inversion_repeat_vertex(SkCanvas* canvas, const SkPaint& paint) {
85     SkPath path;
86     canvas->save();
87     canvas->translate(400, 100);
88     path.setIsVolatile(true);
89     path.moveTo(80,     50);
90     path.lineTo(40,     80);
91     path.lineTo(60,     20);
92     path.lineTo(20,     20);
93     path.lineTo(39.99f, 80);
94     path.lineTo(80,     50);
95     canvas->drawPath(path, paint);
96     canvas->restore();
97 }
98
99 // Fish test (intersection/concave)
100 void test_fish(SkCanvas* canvas, const SkPaint& paint) {
101     SkPath path;
102     canvas->save();
103     canvas->translate(0, 100);
104     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
105     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
106     path.lineTo(SkIntToScalar(70), SkIntToScalar(50));
107     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
108     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
109     path.lineTo(SkIntToScalar(0), SkIntToScalar(50));
110     canvas->drawPath(path, paint);
111     canvas->restore();
112 }
113
114 // Overlapping "Fast-forward" icon: tests coincidence of inner and outer
115 // vertices generated by intersection.
116 void test_fast_forward(SkCanvas* canvas, const SkPaint& paint) {
117     SkPath path;
118     canvas->save();
119     canvas->translate(100, 100);
120     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
121     path.lineTo(SkIntToScalar(60), SkIntToScalar(50));
122     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
123     path.moveTo(SkIntToScalar(40), SkIntToScalar(20));
124     path.lineTo(SkIntToScalar(40), SkIntToScalar(80));
125     path.lineTo(SkIntToScalar(80), SkIntToScalar(50));
126     canvas->drawPath(path, paint);
127     canvas->restore();
128 }
129
130 // Square polygon with a square hole.
131 void test_hole(SkCanvas* canvas, const SkPaint& paint) {
132     SkPath path;
133     canvas->save();
134     canvas->translate(200, 100);
135     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
136     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
137     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
138     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
139     path.moveTo(SkIntToScalar(30), SkIntToScalar(30));
140     path.lineTo(SkIntToScalar(30), SkIntToScalar(70));
141     path.lineTo(SkIntToScalar(70), SkIntToScalar(70));
142     path.lineTo(SkIntToScalar(70), SkIntToScalar(30));
143     canvas->drawPath(path, paint);
144     canvas->restore();
145 }
146
147 // Star test (self-intersecting)
148 void test_star(SkCanvas* canvas, const SkPaint& paint) {
149     SkPath path;
150     canvas->save();
151     canvas->translate(300, 100);
152     path.moveTo(30, 20);
153     path.lineTo(50, 80);
154     path.lineTo(70, 20);
155     path.lineTo(20, 57);
156     path.lineTo(80, 57);
157     path.close();
158     canvas->drawPath(path, paint);
159     canvas->restore();
160 }
161
162 // Stairstep with repeated vert (intersection)
163 void test_stairstep(SkCanvas* canvas, const SkPaint& paint) {
164     SkPath path;
165     canvas->save();
166     canvas->translate(0, 200);
167     path.moveTo(SkIntToScalar(50), SkIntToScalar(50));
168     path.lineTo(SkIntToScalar(50), SkIntToScalar(20));
169     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
170     path.lineTo(SkIntToScalar(50), SkIntToScalar(50));
171     path.lineTo(SkIntToScalar(20), SkIntToScalar(50));
172     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
173     canvas->drawPath(path, paint);
174     canvas->restore();
175 }
176
177 void test_stairstep2(SkCanvas* canvas, const SkPaint& paint) {
178     SkPath path;
179     canvas->save();
180     canvas->translate(100, 200);
181     path.moveTo(20, 60);
182     path.lineTo(35, 80);
183     path.lineTo(50, 60);
184     path.lineTo(65, 80);
185     path.lineTo(80, 60);
186     canvas->drawPath(path, paint);
187     canvas->restore();
188 }
189
190 // Overlapping segments
191 void test_overlapping(SkCanvas* canvas, const SkPaint& paint) {
192     SkPath path;
193     canvas->save();
194     canvas->translate(200, 200);
195     path.moveTo(SkIntToScalar(20), SkIntToScalar(80));
196     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
197     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
198     path.lineTo(SkIntToScalar(80), SkIntToScalar(30));
199     canvas->drawPath(path, paint);
200     canvas->restore();
201 }
202
203 // Two "island" triangles inside a containing rect.
204 // This exercises the partnering code in the tessellator.
205 void test_partners(SkCanvas* canvas, const SkPaint& paint) {
206     SkPath path;
207     canvas->save();
208     canvas->translate(300, 200);
209     path.moveTo(20, 80);
210     path.lineTo(80, 80);
211     path.lineTo(80, 20);
212     path.lineTo(20, 20);
213     path.moveTo(30, 30);
214     path.lineTo(45, 50);
215     path.lineTo(30, 70);
216     path.moveTo(70, 30);
217     path.lineTo(70, 70);
218     path.lineTo(55, 50);
219     canvas->drawPath(path, paint);
220     canvas->restore();
221 }
222
223 // Monotone test 1 (point in the middle)
224 void test_monotone_1(SkCanvas* canvas, const SkPaint& paint) {
225     SkPath path;
226     canvas->save();
227     canvas->translate(0, 300);
228     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
229     path.quadTo(SkIntToScalar(20), SkIntToScalar(50),
230                 SkIntToScalar(80), SkIntToScalar(50));
231     path.quadTo(SkIntToScalar(20), SkIntToScalar(50),
232                 SkIntToScalar(20), SkIntToScalar(80));
233     canvas->drawPath(path, paint);
234     canvas->restore();
235 }
236
237 // Monotone test 2 (point at the top)
238 void test_monotone_2(SkCanvas* canvas, const SkPaint& paint) {
239     SkPath path;
240     canvas->save();
241     canvas->translate(100, 300);
242     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
243     path.lineTo(SkIntToScalar(80), SkIntToScalar(30));
244     path.quadTo(SkIntToScalar(20), SkIntToScalar(20),
245                 SkIntToScalar(20), SkIntToScalar(80));
246     canvas->drawPath(path, paint);
247     canvas->restore();
248 }
249
250 // Monotone test 3 (point at the bottom)
251 void test_monotone_3(SkCanvas* canvas, const SkPaint& paint) {
252     SkPath path;
253     canvas->save();
254     canvas->translate(200, 300);
255     path.moveTo(SkIntToScalar(20), SkIntToScalar(80));
256     path.lineTo(SkIntToScalar(80), SkIntToScalar(70));
257     path.quadTo(SkIntToScalar(20), SkIntToScalar(80),
258                 SkIntToScalar(20), SkIntToScalar(20));
259     canvas->drawPath(path, paint);
260     canvas->restore();
261 }
262
263 // Monotone test 4 (merging of two monotones)
264 void test_monotone_4(SkCanvas* canvas, const SkPaint& paint) {
265     SkPath path;
266     canvas->save();
267     canvas->translate(300, 300);
268     path.moveTo(80, 25);
269     path.lineTo(50, 39);
270     path.lineTo(20, 25);
271     path.lineTo(40, 45);
272     path.lineTo(70, 50);
273     path.lineTo(80, 80);
274     canvas->drawPath(path, paint);
275     canvas->restore();
276 }
277
278 // Monotone test 5 (aborted merging of two monotones)
279 void test_monotone_5(SkCanvas* canvas, const SkPaint& paint) {
280     SkPath path;
281     canvas->save();
282     canvas->translate(0, 400);
283     path.moveTo(50, 20);
284     path.lineTo(80, 80);
285     path.lineTo(50, 50);
286     path.lineTo(20, 80);
287     canvas->drawPath(path, paint);
288     canvas->restore();
289 }
290 // Degenerate intersection test
291 void test_degenerate(SkCanvas* canvas, const SkPaint& paint) {
292     SkPath path;
293     canvas->save();
294     canvas->translate(100, 400);
295     path.moveTo(50, 20);
296     path.lineTo(70, 30);
297     path.lineTo(20, 50);
298     path.moveTo(50, 20);
299     path.lineTo(80, 80);
300     path.lineTo(50, 80);
301     canvas->drawPath(path, paint);
302     canvas->restore();
303 }
304 // Two triangles with a coincident edge.
305 void test_coincident_edge(SkCanvas* canvas, const SkPaint& paint) {
306     SkPath path;
307     canvas->save();
308     canvas->translate(200, 400);
309
310     path.moveTo(80, 20);
311     path.lineTo(80, 80);
312     path.lineTo(20, 80);
313
314     path.moveTo(20, 20);
315     path.lineTo(80, 80);
316     path.lineTo(20, 80);
317
318     canvas->drawPath(path, paint);
319     canvas->restore();
320 }
321 // Bowtie with a coincident triangle (one triangle vertex coincident with the
322 // bowtie's intersection).
323 void test_bowtie_coincident_triangle(SkCanvas* canvas, const SkPaint& paint) {
324     SkPath path;
325     canvas->save();
326     canvas->translate(300, 400);
327     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
328     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
329     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
330     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
331     path.moveTo(SkIntToScalar(50), SkIntToScalar(50));
332     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
333     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
334     canvas->drawPath(path, paint);
335     canvas->restore();
336 }
337
338 // Coincident edges (big ones first, coincident vert on top).
339 void test_coincident_edges_1(SkCanvas* canvas, const SkPaint& paint) {
340     SkPath path;
341     canvas->save();
342     canvas->translate(0, 500);
343     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
344     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
345     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
346     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
347     path.lineTo(SkIntToScalar(50), SkIntToScalar(50));
348     path.lineTo(SkIntToScalar(20), SkIntToScalar(50));
349     canvas->drawPath(path, paint);
350     canvas->restore();
351 }
352 // Coincident edges (small ones first, coincident vert on top).
353 void test_coincident_edges_2(SkCanvas* canvas, const SkPaint& paint) {
354     SkPath path;
355     canvas->save();
356     canvas->translate(100, 500);
357     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
358     path.lineTo(SkIntToScalar(50), SkIntToScalar(50));
359     path.lineTo(SkIntToScalar(20), SkIntToScalar(50));
360     path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
361     path.lineTo(SkIntToScalar(80), SkIntToScalar(80));
362     path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
363     canvas->drawPath(path, paint);
364     canvas->restore();
365 }
366 // Coincident edges (small ones first, coincident vert on bottom).
367 void test_coincident_edges_3(SkCanvas* canvas, const SkPaint& paint) {
368     SkPath path;
369     canvas->save();
370     canvas->translate(200, 500);
371     path.moveTo(SkIntToScalar(20), SkIntToScalar(80));
372     path.lineTo(SkIntToScalar(20), SkIntToScalar(50));
373     path.lineTo(SkIntToScalar(50), SkIntToScalar(50));
374     path.moveTo(SkIntToScalar(20), SkIntToScalar(80));
375     path.lineTo(SkIntToScalar(20), SkIntToScalar(20));
376     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
377     canvas->drawPath(path, paint);
378     canvas->restore();
379 }
380 // Coincident edges (big ones first, coincident vert on bottom).
381 void test_coincident_edges_4(SkCanvas* canvas, const SkPaint& paint) {
382     SkPath path;
383     canvas->save();
384     canvas->translate(300, 500);
385     path.moveTo(SkIntToScalar(20), SkIntToScalar(80));
386     path.lineTo(SkIntToScalar(20), SkIntToScalar(20));
387     path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
388     path.moveTo(SkIntToScalar(20), SkIntToScalar(80));
389     path.lineTo(SkIntToScalar(20), SkIntToScalar(50));
390     path.lineTo(SkIntToScalar(50), SkIntToScalar(50));
391     canvas->drawPath(path, paint);
392     canvas->restore();
393 }
394
395 };
396
397 DEF_SIMPLE_GM(concavepaths, canvas, 500, 600) {
398     SkPaint paint;
399
400     paint.setAntiAlias(true);
401     paint.setStyle(SkPaint::kFill_Style);
402
403     test_concave(canvas, paint);
404     test_reverse_concave(canvas, paint);
405     test_bowtie(canvas, paint);
406     test_fake_bowtie(canvas, paint);
407     test_intruding_vertex(canvas, paint);
408     test_fish(canvas, paint);
409     test_fast_forward(canvas, paint);
410     test_hole(canvas, paint);
411     test_star(canvas, paint);
412     test_inversion_repeat_vertex(canvas, paint);
413     test_stairstep(canvas, paint);
414     test_stairstep2(canvas, paint);
415     test_overlapping(canvas, paint);
416     test_partners(canvas, paint);
417     test_monotone_1(canvas, paint);
418     test_monotone_2(canvas, paint);
419     test_monotone_3(canvas, paint);
420     test_monotone_4(canvas, paint);
421     test_monotone_5(canvas, paint);
422     test_degenerate(canvas, paint);
423     test_coincident_edge(canvas, paint);
424     test_bowtie_coincident_triangle(canvas, paint);
425     test_coincident_edges_1(canvas, paint);
426     test_coincident_edges_2(canvas, paint);
427     test_coincident_edges_3(canvas, paint);
428     test_coincident_edges_4(canvas, paint);
429 }