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