1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 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/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTDArray.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkPolyUtils.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
24*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_ENABLE_OPTIMIZE_SIZE)
create_ngon(int n,SkPoint * pts,SkScalar w,SkScalar h,SkPathDirection dir)27*c8dee2aaSAndroid Build Coastguard Worker static void create_ngon(int n, SkPoint* pts, SkScalar w, SkScalar h, SkPathDirection dir) {
28*c8dee2aaSAndroid Build Coastguard Worker float angleStep = 360.0f / n, angle = 0.0f;
29*c8dee2aaSAndroid Build Coastguard Worker if ((n % 2) == 1) {
30*c8dee2aaSAndroid Build Coastguard Worker angle = angleStep/2.0f;
31*c8dee2aaSAndroid Build Coastguard Worker }
32*c8dee2aaSAndroid Build Coastguard Worker if (SkPathDirection::kCCW == dir) {
33*c8dee2aaSAndroid Build Coastguard Worker angle = -angle;
34*c8dee2aaSAndroid Build Coastguard Worker angleStep = -angleStep;
35*c8dee2aaSAndroid Build Coastguard Worker }
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < n; ++i) {
38*c8dee2aaSAndroid Build Coastguard Worker pts[i].fX = -SkScalarSin(SkDegreesToRadians(angle)) * w;
39*c8dee2aaSAndroid Build Coastguard Worker pts[i].fY = SkScalarCos(SkDegreesToRadians(angle)) * h;
40*c8dee2aaSAndroid Build Coastguard Worker angle += angleStep;
41*c8dee2aaSAndroid Build Coastguard Worker }
42*c8dee2aaSAndroid Build Coastguard Worker }
43*c8dee2aaSAndroid Build Coastguard Worker
44*c8dee2aaSAndroid Build Coastguard Worker namespace PolygonOffsetData {
45*c8dee2aaSAndroid Build Coastguard Worker // narrow rect
46*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints0[] = {
47*c8dee2aaSAndroid Build Coastguard Worker { -1.5f, -50.0f },
48*c8dee2aaSAndroid Build Coastguard Worker { 1.5f, -50.0f },
49*c8dee2aaSAndroid Build Coastguard Worker { 1.5f, 50.0f },
50*c8dee2aaSAndroid Build Coastguard Worker { -1.5f, 50.0f }
51*c8dee2aaSAndroid Build Coastguard Worker };
52*c8dee2aaSAndroid Build Coastguard Worker // narrow rect on an angle
53*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints1[] = {
54*c8dee2aaSAndroid Build Coastguard Worker { -50.0f, -49.0f },
55*c8dee2aaSAndroid Build Coastguard Worker { -49.0f, -50.0f },
56*c8dee2aaSAndroid Build Coastguard Worker { 50.0f, 49.0f },
57*c8dee2aaSAndroid Build Coastguard Worker { 49.0f, 50.0f }
58*c8dee2aaSAndroid Build Coastguard Worker };
59*c8dee2aaSAndroid Build Coastguard Worker // trap - narrow on top - wide on bottom
60*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints2[] = {
61*c8dee2aaSAndroid Build Coastguard Worker { -10.0f, -50.0f },
62*c8dee2aaSAndroid Build Coastguard Worker { 10.0f, -50.0f },
63*c8dee2aaSAndroid Build Coastguard Worker { 50.0f, 50.0f },
64*c8dee2aaSAndroid Build Coastguard Worker { -50.0f, 50.0f }
65*c8dee2aaSAndroid Build Coastguard Worker };
66*c8dee2aaSAndroid Build Coastguard Worker // wide skewed rect
67*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints3[] = {
68*c8dee2aaSAndroid Build Coastguard Worker { -50.0f, -50.0f },
69*c8dee2aaSAndroid Build Coastguard Worker { 0.0f, -50.0f },
70*c8dee2aaSAndroid Build Coastguard Worker { 50.0f, 50.0f },
71*c8dee2aaSAndroid Build Coastguard Worker { 0.0f, 50.0f }
72*c8dee2aaSAndroid Build Coastguard Worker };
73*c8dee2aaSAndroid Build Coastguard Worker // thin rect with colinear-ish lines
74*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints4[] = {
75*c8dee2aaSAndroid Build Coastguard Worker { -6.0f, -50.0f },
76*c8dee2aaSAndroid Build Coastguard Worker { 4.0f, -50.0f },
77*c8dee2aaSAndroid Build Coastguard Worker { 5.0f, -25.0f },
78*c8dee2aaSAndroid Build Coastguard Worker { 6.0f, 0.0f },
79*c8dee2aaSAndroid Build Coastguard Worker { 5.0f, 25.0f },
80*c8dee2aaSAndroid Build Coastguard Worker { 4.0f, 50.0f },
81*c8dee2aaSAndroid Build Coastguard Worker { -4.0f, 50.0f }
82*c8dee2aaSAndroid Build Coastguard Worker };
83*c8dee2aaSAndroid Build Coastguard Worker // degenerate
84*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints5[] = {
85*c8dee2aaSAndroid Build Coastguard Worker { -0.025f, -0.025f },
86*c8dee2aaSAndroid Build Coastguard Worker { 0.025f, -0.025f },
87*c8dee2aaSAndroid Build Coastguard Worker { 0.025f, 0.025f },
88*c8dee2aaSAndroid Build Coastguard Worker { -0.025f, 0.025f }
89*c8dee2aaSAndroid Build Coastguard Worker };
90*c8dee2aaSAndroid Build Coastguard Worker // Quad with near coincident point
91*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints6[] = {
92*c8dee2aaSAndroid Build Coastguard Worker { -20.0f, -13.0f },
93*c8dee2aaSAndroid Build Coastguard Worker { -20.0f, -13.05f },
94*c8dee2aaSAndroid Build Coastguard Worker { 20.0f, -13.0f },
95*c8dee2aaSAndroid Build Coastguard Worker { 20.0f, 27.0f }
96*c8dee2aaSAndroid Build Coastguard Worker };
97*c8dee2aaSAndroid Build Coastguard Worker // thin rect with colinear lines
98*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints7[] = {
99*c8dee2aaSAndroid Build Coastguard Worker { -10.0f, -50.0f },
100*c8dee2aaSAndroid Build Coastguard Worker { 10.0f, -50.0f },
101*c8dee2aaSAndroid Build Coastguard Worker { 10.0f, -20.0f },
102*c8dee2aaSAndroid Build Coastguard Worker { 10.0f, 0.0f },
103*c8dee2aaSAndroid Build Coastguard Worker { 10.0f, 35.0f },
104*c8dee2aaSAndroid Build Coastguard Worker { 10.0f, 50.0f },
105*c8dee2aaSAndroid Build Coastguard Worker { -10.0f, 50.0f }
106*c8dee2aaSAndroid Build Coastguard Worker };
107*c8dee2aaSAndroid Build Coastguard Worker // capped teardrop
108*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints8[] = {
109*c8dee2aaSAndroid Build Coastguard Worker { 50.00f, 50.00f },
110*c8dee2aaSAndroid Build Coastguard Worker { 0.00f, 50.00f },
111*c8dee2aaSAndroid Build Coastguard Worker { -15.45f, 47.55f },
112*c8dee2aaSAndroid Build Coastguard Worker { -29.39f, 40.45f },
113*c8dee2aaSAndroid Build Coastguard Worker { -40.45f, 29.39f },
114*c8dee2aaSAndroid Build Coastguard Worker { -47.55f, 15.45f },
115*c8dee2aaSAndroid Build Coastguard Worker { -50.00f, 0.00f },
116*c8dee2aaSAndroid Build Coastguard Worker { -47.55f, -15.45f },
117*c8dee2aaSAndroid Build Coastguard Worker { -40.45f, -29.39f },
118*c8dee2aaSAndroid Build Coastguard Worker { -29.39f, -40.45f },
119*c8dee2aaSAndroid Build Coastguard Worker { -15.45f, -47.55f },
120*c8dee2aaSAndroid Build Coastguard Worker { 0.00f, -50.00f },
121*c8dee2aaSAndroid Build Coastguard Worker { 50.00f, -50.00f }
122*c8dee2aaSAndroid Build Coastguard Worker };
123*c8dee2aaSAndroid Build Coastguard Worker // teardrop
124*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints9[] = {
125*c8dee2aaSAndroid Build Coastguard Worker { 4.39f, 40.45f },
126*c8dee2aaSAndroid Build Coastguard Worker { -9.55f, 47.55f },
127*c8dee2aaSAndroid Build Coastguard Worker { -25.00f, 50.00f },
128*c8dee2aaSAndroid Build Coastguard Worker { -40.45f, 47.55f },
129*c8dee2aaSAndroid Build Coastguard Worker { -54.39f, 40.45f },
130*c8dee2aaSAndroid Build Coastguard Worker { -65.45f, 29.39f },
131*c8dee2aaSAndroid Build Coastguard Worker { -72.55f, 15.45f },
132*c8dee2aaSAndroid Build Coastguard Worker { -75.00f, 0.00f },
133*c8dee2aaSAndroid Build Coastguard Worker { -72.55f, -15.45f },
134*c8dee2aaSAndroid Build Coastguard Worker { -65.45f, -29.39f },
135*c8dee2aaSAndroid Build Coastguard Worker { -54.39f, -40.45f },
136*c8dee2aaSAndroid Build Coastguard Worker { -40.45f, -47.55f },
137*c8dee2aaSAndroid Build Coastguard Worker { -25.0f, -50.0f },
138*c8dee2aaSAndroid Build Coastguard Worker { -9.55f, -47.55f },
139*c8dee2aaSAndroid Build Coastguard Worker { 4.39f, -40.45f },
140*c8dee2aaSAndroid Build Coastguard Worker { 75.00f, 0.00f }
141*c8dee2aaSAndroid Build Coastguard Worker };
142*c8dee2aaSAndroid Build Coastguard Worker // clipped triangle
143*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints10[] = {
144*c8dee2aaSAndroid Build Coastguard Worker { -10.0f, -50.0f },
145*c8dee2aaSAndroid Build Coastguard Worker { 10.0f, -50.0f },
146*c8dee2aaSAndroid Build Coastguard Worker { 50.0f, 31.0f },
147*c8dee2aaSAndroid Build Coastguard Worker { 40.0f, 50.0f },
148*c8dee2aaSAndroid Build Coastguard Worker { -40.0f, 50.0f },
149*c8dee2aaSAndroid Build Coastguard Worker { -50.0f, 31.0f },
150*c8dee2aaSAndroid Build Coastguard Worker };
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker // tab
153*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints11[] = {
154*c8dee2aaSAndroid Build Coastguard Worker { -45, -25 },
155*c8dee2aaSAndroid Build Coastguard Worker { 45, -25 },
156*c8dee2aaSAndroid Build Coastguard Worker { 45, 25 },
157*c8dee2aaSAndroid Build Coastguard Worker { 20, 25 },
158*c8dee2aaSAndroid Build Coastguard Worker { 19.6157f, 25.f + 3.9018f },
159*c8dee2aaSAndroid Build Coastguard Worker { 18.4776f, 25.f + 7.6537f },
160*c8dee2aaSAndroid Build Coastguard Worker { 16.6294f, 25.f + 11.1114f },
161*c8dee2aaSAndroid Build Coastguard Worker { 14.1421f, 25.f + 14.1421f },
162*c8dee2aaSAndroid Build Coastguard Worker { 11.1114f, 25.f + 16.6294f },
163*c8dee2aaSAndroid Build Coastguard Worker { 7.6537f, 25.f + 18.4776f },
164*c8dee2aaSAndroid Build Coastguard Worker { 3.9018f, 25.f + 19.6157f },
165*c8dee2aaSAndroid Build Coastguard Worker { 0, 45.f },
166*c8dee2aaSAndroid Build Coastguard Worker { -3.9018f, 25.f + 19.6157f },
167*c8dee2aaSAndroid Build Coastguard Worker { -7.6537f, 25.f + 18.4776f },
168*c8dee2aaSAndroid Build Coastguard Worker { -11.1114f, 25.f + 16.6294f },
169*c8dee2aaSAndroid Build Coastguard Worker { -14.1421f, 25.f + 14.1421f },
170*c8dee2aaSAndroid Build Coastguard Worker { -16.6294f, 25.f + 11.1114f },
171*c8dee2aaSAndroid Build Coastguard Worker { -18.4776f, 25.f + 7.6537f },
172*c8dee2aaSAndroid Build Coastguard Worker { -19.6157f, 25.f + 3.9018f },
173*c8dee2aaSAndroid Build Coastguard Worker { -20, 25 },
174*c8dee2aaSAndroid Build Coastguard Worker { -45, 25 }
175*c8dee2aaSAndroid Build Coastguard Worker };
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker // star of david
178*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints12[] = {
179*c8dee2aaSAndroid Build Coastguard Worker { 0.0f, -50.0f },
180*c8dee2aaSAndroid Build Coastguard Worker { 14.43f, -25.0f },
181*c8dee2aaSAndroid Build Coastguard Worker { 43.30f, -25.0f },
182*c8dee2aaSAndroid Build Coastguard Worker { 28.86f, 0.0f },
183*c8dee2aaSAndroid Build Coastguard Worker { 43.30f, 25.0f },
184*c8dee2aaSAndroid Build Coastguard Worker { 14.43f, 25.0f },
185*c8dee2aaSAndroid Build Coastguard Worker { 0.0f, 50.0f },
186*c8dee2aaSAndroid Build Coastguard Worker { -14.43f, 25.0f },
187*c8dee2aaSAndroid Build Coastguard Worker { -43.30f, 25.0f },
188*c8dee2aaSAndroid Build Coastguard Worker { -28.86f, 0.0f },
189*c8dee2aaSAndroid Build Coastguard Worker { -43.30f, -25.0f },
190*c8dee2aaSAndroid Build Coastguard Worker { -14.43f, -25.0f },
191*c8dee2aaSAndroid Build Coastguard Worker };
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker // notch
194*c8dee2aaSAndroid Build Coastguard Worker const SkScalar kBottom = 25.f;
195*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints13[] = {
196*c8dee2aaSAndroid Build Coastguard Worker { -50, kBottom - 50.f },
197*c8dee2aaSAndroid Build Coastguard Worker { 50, kBottom - 50.f },
198*c8dee2aaSAndroid Build Coastguard Worker { 50, kBottom },
199*c8dee2aaSAndroid Build Coastguard Worker { 20, kBottom },
200*c8dee2aaSAndroid Build Coastguard Worker { 19.6157f, kBottom - 3.9018f },
201*c8dee2aaSAndroid Build Coastguard Worker { 18.4776f, kBottom - 7.6537f },
202*c8dee2aaSAndroid Build Coastguard Worker { 16.6294f, kBottom - 11.1114f },
203*c8dee2aaSAndroid Build Coastguard Worker { 14.1421f, kBottom - 14.1421f },
204*c8dee2aaSAndroid Build Coastguard Worker { 11.1114f, kBottom - 16.6294f },
205*c8dee2aaSAndroid Build Coastguard Worker { 7.6537f, kBottom - 18.4776f },
206*c8dee2aaSAndroid Build Coastguard Worker { 3.9018f, kBottom - 19.6157f },
207*c8dee2aaSAndroid Build Coastguard Worker { 0, kBottom - 20.f },
208*c8dee2aaSAndroid Build Coastguard Worker { -3.9018f, kBottom - 19.6157f },
209*c8dee2aaSAndroid Build Coastguard Worker { -7.6537f, kBottom - 18.4776f },
210*c8dee2aaSAndroid Build Coastguard Worker { -11.1114f, kBottom - 16.6294f },
211*c8dee2aaSAndroid Build Coastguard Worker { -14.1421f, kBottom - 14.1421f },
212*c8dee2aaSAndroid Build Coastguard Worker { -16.6294f, kBottom - 11.1114f },
213*c8dee2aaSAndroid Build Coastguard Worker { -18.4776f, kBottom - 7.6537f },
214*c8dee2aaSAndroid Build Coastguard Worker { -19.6157f, kBottom - 3.9018f },
215*c8dee2aaSAndroid Build Coastguard Worker { -20, kBottom },
216*c8dee2aaSAndroid Build Coastguard Worker { -50, kBottom }
217*c8dee2aaSAndroid Build Coastguard Worker };
218*c8dee2aaSAndroid Build Coastguard Worker
219*c8dee2aaSAndroid Build Coastguard Worker // crown
220*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints14[] = {
221*c8dee2aaSAndroid Build Coastguard Worker { -40, -39 },
222*c8dee2aaSAndroid Build Coastguard Worker { 40, -39 },
223*c8dee2aaSAndroid Build Coastguard Worker { 40, -20 },
224*c8dee2aaSAndroid Build Coastguard Worker { 30, 40 },
225*c8dee2aaSAndroid Build Coastguard Worker { 20, -20 },
226*c8dee2aaSAndroid Build Coastguard Worker { 10, 40 },
227*c8dee2aaSAndroid Build Coastguard Worker { 0, -20 },
228*c8dee2aaSAndroid Build Coastguard Worker { -10, 40 },
229*c8dee2aaSAndroid Build Coastguard Worker { -20, -20 },
230*c8dee2aaSAndroid Build Coastguard Worker { -30, 40 },
231*c8dee2aaSAndroid Build Coastguard Worker { -40, -20 }
232*c8dee2aaSAndroid Build Coastguard Worker };
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker // dumbbell
235*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints15[] = {
236*c8dee2aaSAndroid Build Coastguard Worker { -26, -3 },
237*c8dee2aaSAndroid Build Coastguard Worker { -24, -6.2f },
238*c8dee2aaSAndroid Build Coastguard Worker { -22.5f, -8 },
239*c8dee2aaSAndroid Build Coastguard Worker { -20, -9.9f },
240*c8dee2aaSAndroid Build Coastguard Worker { -17.5f, -10.3f },
241*c8dee2aaSAndroid Build Coastguard Worker { -15, -10.9f },
242*c8dee2aaSAndroid Build Coastguard Worker { -12.5f, -10.2f },
243*c8dee2aaSAndroid Build Coastguard Worker { -10, -9.7f },
244*c8dee2aaSAndroid Build Coastguard Worker { -7.5f, -8.1f },
245*c8dee2aaSAndroid Build Coastguard Worker { -5, -7.7f },
246*c8dee2aaSAndroid Build Coastguard Worker { -2.5f, -7.4f },
247*c8dee2aaSAndroid Build Coastguard Worker { 0, -7.7f },
248*c8dee2aaSAndroid Build Coastguard Worker { 3, -9 },
249*c8dee2aaSAndroid Build Coastguard Worker { 6.5f, -11.5f },
250*c8dee2aaSAndroid Build Coastguard Worker { 10.6f, -14 },
251*c8dee2aaSAndroid Build Coastguard Worker { 14, -15.2f },
252*c8dee2aaSAndroid Build Coastguard Worker { 17, -15.5f },
253*c8dee2aaSAndroid Build Coastguard Worker { 20, -15.2f },
254*c8dee2aaSAndroid Build Coastguard Worker { 23.4f, -14 },
255*c8dee2aaSAndroid Build Coastguard Worker { 27.5f, -11.5f },
256*c8dee2aaSAndroid Build Coastguard Worker { 30, -8 },
257*c8dee2aaSAndroid Build Coastguard Worker { 32, -4 },
258*c8dee2aaSAndroid Build Coastguard Worker { 32.5f, 0 },
259*c8dee2aaSAndroid Build Coastguard Worker { 32, 4 },
260*c8dee2aaSAndroid Build Coastguard Worker { 30, 8 },
261*c8dee2aaSAndroid Build Coastguard Worker { 27.5f, 11.5f },
262*c8dee2aaSAndroid Build Coastguard Worker { 23.4f, 14 },
263*c8dee2aaSAndroid Build Coastguard Worker { 20, 15.2f },
264*c8dee2aaSAndroid Build Coastguard Worker { 17, 15.5f },
265*c8dee2aaSAndroid Build Coastguard Worker { 14, 15.2f },
266*c8dee2aaSAndroid Build Coastguard Worker { 10.6f, 14 },
267*c8dee2aaSAndroid Build Coastguard Worker { 6.5f, 11.5f },
268*c8dee2aaSAndroid Build Coastguard Worker { 3, 9 },
269*c8dee2aaSAndroid Build Coastguard Worker { 0, 7.7f },
270*c8dee2aaSAndroid Build Coastguard Worker { -2.5f, 7.4f },
271*c8dee2aaSAndroid Build Coastguard Worker { -5, 7.7f },
272*c8dee2aaSAndroid Build Coastguard Worker { -7.5f, 8.1f },
273*c8dee2aaSAndroid Build Coastguard Worker { -10, 9.7f },
274*c8dee2aaSAndroid Build Coastguard Worker { -12.5f, 10.2f },
275*c8dee2aaSAndroid Build Coastguard Worker { -15, 10.9f },
276*c8dee2aaSAndroid Build Coastguard Worker { -17.5f, 10.3f },
277*c8dee2aaSAndroid Build Coastguard Worker { -20, 9.9f },
278*c8dee2aaSAndroid Build Coastguard Worker { -22.5f, 8 },
279*c8dee2aaSAndroid Build Coastguard Worker { -24, 6.2f },
280*c8dee2aaSAndroid Build Coastguard Worker { -26, 3 },
281*c8dee2aaSAndroid Build Coastguard Worker { -26.5f, 0 }
282*c8dee2aaSAndroid Build Coastguard Worker };
283*c8dee2aaSAndroid Build Coastguard Worker
284*c8dee2aaSAndroid Build Coastguard Worker // truncated dumbbell
285*c8dee2aaSAndroid Build Coastguard Worker // (checks winding computation in OffsetSimplePolygon)
286*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints16[] = {
287*c8dee2aaSAndroid Build Coastguard Worker { -15 + 3, -9 },
288*c8dee2aaSAndroid Build Coastguard Worker { -15 + 6.5f, -11.5f },
289*c8dee2aaSAndroid Build Coastguard Worker { -15 + 10.6f, -14 },
290*c8dee2aaSAndroid Build Coastguard Worker { -15 + 14, -15.2f },
291*c8dee2aaSAndroid Build Coastguard Worker { -15 + 17, -15.5f },
292*c8dee2aaSAndroid Build Coastguard Worker { -15 + 20, -15.2f },
293*c8dee2aaSAndroid Build Coastguard Worker { -15 + 23.4f, -14 },
294*c8dee2aaSAndroid Build Coastguard Worker { -15 + 27.5f, -11.5f },
295*c8dee2aaSAndroid Build Coastguard Worker { -15 + 30, -8 },
296*c8dee2aaSAndroid Build Coastguard Worker { -15 + 32, -4 },
297*c8dee2aaSAndroid Build Coastguard Worker { -15 + 32.5f, 0 },
298*c8dee2aaSAndroid Build Coastguard Worker { -15 + 32, 4 },
299*c8dee2aaSAndroid Build Coastguard Worker { -15 + 30, 8 },
300*c8dee2aaSAndroid Build Coastguard Worker { -15 + 27.5f, 11.5f },
301*c8dee2aaSAndroid Build Coastguard Worker { -15 + 23.4f, 14 },
302*c8dee2aaSAndroid Build Coastguard Worker { -15 + 20, 15.2f },
303*c8dee2aaSAndroid Build Coastguard Worker { -15 + 17, 15.5f },
304*c8dee2aaSAndroid Build Coastguard Worker { -15 + 14, 15.2f },
305*c8dee2aaSAndroid Build Coastguard Worker { -15 + 10.6f, 14 },
306*c8dee2aaSAndroid Build Coastguard Worker { -15 + 6.5f, 11.5f },
307*c8dee2aaSAndroid Build Coastguard Worker { -15 + 3, 9 },
308*c8dee2aaSAndroid Build Coastguard Worker };
309*c8dee2aaSAndroid Build Coastguard Worker
310*c8dee2aaSAndroid Build Coastguard Worker // square notch
311*c8dee2aaSAndroid Build Coastguard Worker // (to detect segment-segment intersection)
312*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints17[] = {
313*c8dee2aaSAndroid Build Coastguard Worker { -50, kBottom - 50.f },
314*c8dee2aaSAndroid Build Coastguard Worker { 50, kBottom - 50.f },
315*c8dee2aaSAndroid Build Coastguard Worker { 50, kBottom },
316*c8dee2aaSAndroid Build Coastguard Worker { 20, kBottom },
317*c8dee2aaSAndroid Build Coastguard Worker { 20, kBottom - 20.f },
318*c8dee2aaSAndroid Build Coastguard Worker { -20, kBottom - 20.f },
319*c8dee2aaSAndroid Build Coastguard Worker { -20, kBottom },
320*c8dee2aaSAndroid Build Coastguard Worker { -50, kBottom }
321*c8dee2aaSAndroid Build Coastguard Worker };
322*c8dee2aaSAndroid Build Coastguard Worker
323*c8dee2aaSAndroid Build Coastguard Worker // box with Peano curve
324*c8dee2aaSAndroid Build Coastguard Worker const SkPoint gPoints18[] = {
325*c8dee2aaSAndroid Build Coastguard Worker { 0, 0 },
326*c8dee2aaSAndroid Build Coastguard Worker { 0, -12 },
327*c8dee2aaSAndroid Build Coastguard Worker { -6, -12 },
328*c8dee2aaSAndroid Build Coastguard Worker { -6, 0 },
329*c8dee2aaSAndroid Build Coastguard Worker { -12, 0 },
330*c8dee2aaSAndroid Build Coastguard Worker { -12, -12},
331*c8dee2aaSAndroid Build Coastguard Worker { -18, -12},
332*c8dee2aaSAndroid Build Coastguard Worker { -18, 18},
333*c8dee2aaSAndroid Build Coastguard Worker { -12, 18},
334*c8dee2aaSAndroid Build Coastguard Worker {-12, 6},
335*c8dee2aaSAndroid Build Coastguard Worker {-6, 6},
336*c8dee2aaSAndroid Build Coastguard Worker {-6, 36},
337*c8dee2aaSAndroid Build Coastguard Worker {-12, 36},
338*c8dee2aaSAndroid Build Coastguard Worker {-12, 24},
339*c8dee2aaSAndroid Build Coastguard Worker {-18, 24},
340*c8dee2aaSAndroid Build Coastguard Worker {-18, 36},
341*c8dee2aaSAndroid Build Coastguard Worker {-24, 36},
342*c8dee2aaSAndroid Build Coastguard Worker {-24, 24},
343*c8dee2aaSAndroid Build Coastguard Worker {-30, 24},
344*c8dee2aaSAndroid Build Coastguard Worker {-30, 36},
345*c8dee2aaSAndroid Build Coastguard Worker {-36, 36},
346*c8dee2aaSAndroid Build Coastguard Worker {-36, 6},
347*c8dee2aaSAndroid Build Coastguard Worker {-30, 6},
348*c8dee2aaSAndroid Build Coastguard Worker {-30, 18},
349*c8dee2aaSAndroid Build Coastguard Worker {-24, 18},
350*c8dee2aaSAndroid Build Coastguard Worker {-24, -12},
351*c8dee2aaSAndroid Build Coastguard Worker {-30, -12},
352*c8dee2aaSAndroid Build Coastguard Worker {-30, 0},
353*c8dee2aaSAndroid Build Coastguard Worker {-36, 0},
354*c8dee2aaSAndroid Build Coastguard Worker {-36, -36},
355*c8dee2aaSAndroid Build Coastguard Worker {36, -36},
356*c8dee2aaSAndroid Build Coastguard Worker {36, 36},
357*c8dee2aaSAndroid Build Coastguard Worker {12, 36},
358*c8dee2aaSAndroid Build Coastguard Worker {12, 24},
359*c8dee2aaSAndroid Build Coastguard Worker {6, 24},
360*c8dee2aaSAndroid Build Coastguard Worker {6, 36},
361*c8dee2aaSAndroid Build Coastguard Worker {0, 36},
362*c8dee2aaSAndroid Build Coastguard Worker {0, 6},
363*c8dee2aaSAndroid Build Coastguard Worker {6, 6},
364*c8dee2aaSAndroid Build Coastguard Worker {6, 18},
365*c8dee2aaSAndroid Build Coastguard Worker {12, 18},
366*c8dee2aaSAndroid Build Coastguard Worker {12, -12},
367*c8dee2aaSAndroid Build Coastguard Worker {6, -12},
368*c8dee2aaSAndroid Build Coastguard Worker {6, 0}
369*c8dee2aaSAndroid Build Coastguard Worker };
370*c8dee2aaSAndroid Build Coastguard Worker
371*c8dee2aaSAndroid Build Coastguard Worker
372*c8dee2aaSAndroid Build Coastguard Worker const SkPoint* gConvexPoints[] = {
373*c8dee2aaSAndroid Build Coastguard Worker gPoints0, gPoints1, gPoints2, gPoints3, gPoints4, gPoints5, gPoints6,
374*c8dee2aaSAndroid Build Coastguard Worker gPoints7, gPoints8, gPoints9, gPoints10,
375*c8dee2aaSAndroid Build Coastguard Worker };
376*c8dee2aaSAndroid Build Coastguard Worker
377*c8dee2aaSAndroid Build Coastguard Worker const size_t gConvexSizes[] = {
378*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints0),
379*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints1),
380*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints2),
381*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints3),
382*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints4),
383*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints5),
384*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints6),
385*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints7),
386*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints8),
387*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints9),
388*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints10),
389*c8dee2aaSAndroid Build Coastguard Worker };
390*c8dee2aaSAndroid Build Coastguard Worker static_assert(std::size(gConvexSizes) == std::size(gConvexPoints), "array_mismatch");
391*c8dee2aaSAndroid Build Coastguard Worker
392*c8dee2aaSAndroid Build Coastguard Worker const SkPoint* gSimplePoints[] = {
393*c8dee2aaSAndroid Build Coastguard Worker gPoints0, gPoints1, gPoints2, gPoints4, gPoints5, gPoints7,
394*c8dee2aaSAndroid Build Coastguard Worker gPoints8, gPoints11, gPoints12, gPoints13, gPoints14, gPoints15,
395*c8dee2aaSAndroid Build Coastguard Worker gPoints16, gPoints17, gPoints18,
396*c8dee2aaSAndroid Build Coastguard Worker };
397*c8dee2aaSAndroid Build Coastguard Worker
398*c8dee2aaSAndroid Build Coastguard Worker const size_t gSimpleSizes[] = {
399*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints0),
400*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints1),
401*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints2),
402*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints4),
403*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints5),
404*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints7),
405*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints8),
406*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints11),
407*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints12),
408*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints13),
409*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints14),
410*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints15),
411*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints16),
412*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints17),
413*c8dee2aaSAndroid Build Coastguard Worker std::size(gPoints18),
414*c8dee2aaSAndroid Build Coastguard Worker };
415*c8dee2aaSAndroid Build Coastguard Worker static_assert(std::size(gSimpleSizes) == std::size(gSimplePoints), "array_mismatch");
416*c8dee2aaSAndroid Build Coastguard Worker
417*c8dee2aaSAndroid Build Coastguard Worker } // namespace PolygonOffsetData
418*c8dee2aaSAndroid Build Coastguard Worker
419*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
420*c8dee2aaSAndroid Build Coastguard Worker
421*c8dee2aaSAndroid Build Coastguard Worker // This GM is intended to exercise the offsetting of polygons
422*c8dee2aaSAndroid Build Coastguard Worker // When fVariableOffset is true it will skew the offset by x,
423*c8dee2aaSAndroid Build Coastguard Worker // to test perspective and other variable offset functions
424*c8dee2aaSAndroid Build Coastguard Worker class PolygonOffsetGM : public GM {
425*c8dee2aaSAndroid Build Coastguard Worker public:
PolygonOffsetGM(bool convexOnly)426*c8dee2aaSAndroid Build Coastguard Worker PolygonOffsetGM(bool convexOnly)
427*c8dee2aaSAndroid Build Coastguard Worker : fConvexOnly(convexOnly) {
428*c8dee2aaSAndroid Build Coastguard Worker this->setBGColor(0xFFFFFFFF);
429*c8dee2aaSAndroid Build Coastguard Worker }
430*c8dee2aaSAndroid Build Coastguard Worker
431*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const432*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override {
433*c8dee2aaSAndroid Build Coastguard Worker if (fConvexOnly) {
434*c8dee2aaSAndroid Build Coastguard Worker return SkString("convex-polygon-inset");
435*c8dee2aaSAndroid Build Coastguard Worker } else {
436*c8dee2aaSAndroid Build Coastguard Worker return SkString("simple-polygon-offset");
437*c8dee2aaSAndroid Build Coastguard Worker }
438*c8dee2aaSAndroid Build Coastguard Worker }
getISize()439*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(kGMWidth, kGMHeight); }
runAsBench() const440*c8dee2aaSAndroid Build Coastguard Worker bool runAsBench() const override { return true; }
441*c8dee2aaSAndroid Build Coastguard Worker
GetConvexPolygon(int index,SkPathDirection dir,std::unique_ptr<SkPoint[]> * data,int * numPts)442*c8dee2aaSAndroid Build Coastguard Worker static void GetConvexPolygon(int index, SkPathDirection dir,
443*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkPoint[]>* data, int* numPts) {
444*c8dee2aaSAndroid Build Coastguard Worker if (index < (int)std::size(PolygonOffsetData::gConvexPoints)) {
445*c8dee2aaSAndroid Build Coastguard Worker // manually specified
446*c8dee2aaSAndroid Build Coastguard Worker *numPts = (int)PolygonOffsetData::gConvexSizes[index];
447*c8dee2aaSAndroid Build Coastguard Worker *data = std::make_unique<SkPoint[]>(*numPts);
448*c8dee2aaSAndroid Build Coastguard Worker if (SkPathDirection::kCW == dir) {
449*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < *numPts; ++i) {
450*c8dee2aaSAndroid Build Coastguard Worker (*data)[i] = PolygonOffsetData::gConvexPoints[index][i];
451*c8dee2aaSAndroid Build Coastguard Worker }
452*c8dee2aaSAndroid Build Coastguard Worker } else {
453*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < *numPts; ++i) {
454*c8dee2aaSAndroid Build Coastguard Worker (*data)[i] = PolygonOffsetData::gConvexPoints[index][*numPts - i - 1];
455*c8dee2aaSAndroid Build Coastguard Worker }
456*c8dee2aaSAndroid Build Coastguard Worker }
457*c8dee2aaSAndroid Build Coastguard Worker } else {
458*c8dee2aaSAndroid Build Coastguard Worker // procedurally generated
459*c8dee2aaSAndroid Build Coastguard Worker SkScalar width = kMaxPathHeight / 2;
460*c8dee2aaSAndroid Build Coastguard Worker SkScalar height = kMaxPathHeight / 2;
461*c8dee2aaSAndroid Build Coastguard Worker int numPtsArray[] = { 3, 4, 5, 5, 6, 8, 8, 20, 100 };
462*c8dee2aaSAndroid Build Coastguard Worker
463*c8dee2aaSAndroid Build Coastguard Worker size_t arrayIndex = index - std::size(PolygonOffsetData::gConvexPoints);
464*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(arrayIndex < std::size(numPtsArray));
465*c8dee2aaSAndroid Build Coastguard Worker *numPts = numPtsArray[arrayIndex];
466*c8dee2aaSAndroid Build Coastguard Worker if (arrayIndex == 3 || arrayIndex == 6) {
467*c8dee2aaSAndroid Build Coastguard Worker // squashed pentagon and octagon
468*c8dee2aaSAndroid Build Coastguard Worker width = kMaxPathHeight / 5;
469*c8dee2aaSAndroid Build Coastguard Worker }
470*c8dee2aaSAndroid Build Coastguard Worker
471*c8dee2aaSAndroid Build Coastguard Worker *data = std::make_unique<SkPoint[]>(*numPts);
472*c8dee2aaSAndroid Build Coastguard Worker
473*c8dee2aaSAndroid Build Coastguard Worker create_ngon(*numPts, data->get(), width, height, dir);
474*c8dee2aaSAndroid Build Coastguard Worker }
475*c8dee2aaSAndroid Build Coastguard Worker }
476*c8dee2aaSAndroid Build Coastguard Worker
GetSimplePolygon(int index,SkPathDirection dir,std::unique_ptr<SkPoint[]> * data,int * numPts)477*c8dee2aaSAndroid Build Coastguard Worker static void GetSimplePolygon(int index, SkPathDirection dir,
478*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkPoint[]>* data, int* numPts) {
479*c8dee2aaSAndroid Build Coastguard Worker if (index < (int)std::size(PolygonOffsetData::gSimplePoints)) {
480*c8dee2aaSAndroid Build Coastguard Worker // manually specified
481*c8dee2aaSAndroid Build Coastguard Worker *numPts = (int)PolygonOffsetData::gSimpleSizes[index];
482*c8dee2aaSAndroid Build Coastguard Worker *data = std::make_unique<SkPoint[]>(*numPts);
483*c8dee2aaSAndroid Build Coastguard Worker if (SkPathDirection::kCW == dir) {
484*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < *numPts; ++i) {
485*c8dee2aaSAndroid Build Coastguard Worker (*data)[i] = PolygonOffsetData::gSimplePoints[index][i];
486*c8dee2aaSAndroid Build Coastguard Worker }
487*c8dee2aaSAndroid Build Coastguard Worker } else {
488*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < *numPts; ++i) {
489*c8dee2aaSAndroid Build Coastguard Worker (*data)[i] = PolygonOffsetData::gSimplePoints[index][*numPts - i - 1];
490*c8dee2aaSAndroid Build Coastguard Worker }
491*c8dee2aaSAndroid Build Coastguard Worker }
492*c8dee2aaSAndroid Build Coastguard Worker } else {
493*c8dee2aaSAndroid Build Coastguard Worker // procedurally generated
494*c8dee2aaSAndroid Build Coastguard Worker SkScalar width = kMaxPathHeight / 2;
495*c8dee2aaSAndroid Build Coastguard Worker SkScalar height = kMaxPathHeight / 2;
496*c8dee2aaSAndroid Build Coastguard Worker int numPtsArray[] = { 5, 7, 8, 20, 100 };
497*c8dee2aaSAndroid Build Coastguard Worker
498*c8dee2aaSAndroid Build Coastguard Worker size_t arrayIndex = index - std::size(PolygonOffsetData::gSimplePoints);
499*c8dee2aaSAndroid Build Coastguard Worker arrayIndex = std::min(arrayIndex, std::size(numPtsArray) - 1);
500*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(arrayIndex < std::size(numPtsArray));
501*c8dee2aaSAndroid Build Coastguard Worker *numPts = numPtsArray[arrayIndex];
502*c8dee2aaSAndroid Build Coastguard Worker // squash horizontally
503*c8dee2aaSAndroid Build Coastguard Worker width = kMaxPathHeight / 5;
504*c8dee2aaSAndroid Build Coastguard Worker
505*c8dee2aaSAndroid Build Coastguard Worker *data = std::make_unique<SkPoint[]>(*numPts);
506*c8dee2aaSAndroid Build Coastguard Worker
507*c8dee2aaSAndroid Build Coastguard Worker create_ngon(*numPts, data->get(), width, height, dir);
508*c8dee2aaSAndroid Build Coastguard Worker }
509*c8dee2aaSAndroid Build Coastguard Worker }
510*c8dee2aaSAndroid Build Coastguard Worker // Draw a single polygon with insets and potentially outsets
drawPolygon(SkCanvas * canvas,int index,SkPoint * position)511*c8dee2aaSAndroid Build Coastguard Worker void drawPolygon(SkCanvas* canvas, int index, SkPoint* position) {
512*c8dee2aaSAndroid Build Coastguard Worker
513*c8dee2aaSAndroid Build Coastguard Worker SkPoint center;
514*c8dee2aaSAndroid Build Coastguard Worker {
515*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkPoint[]> data(nullptr);
516*c8dee2aaSAndroid Build Coastguard Worker int numPts;
517*c8dee2aaSAndroid Build Coastguard Worker if (fConvexOnly) {
518*c8dee2aaSAndroid Build Coastguard Worker GetConvexPolygon(index, SkPathDirection::kCW, &data, &numPts);
519*c8dee2aaSAndroid Build Coastguard Worker } else {
520*c8dee2aaSAndroid Build Coastguard Worker GetSimplePolygon(index, SkPathDirection::kCW, &data, &numPts);
521*c8dee2aaSAndroid Build Coastguard Worker }
522*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds;
523*c8dee2aaSAndroid Build Coastguard Worker bounds.setBounds(data.get(), numPts);
524*c8dee2aaSAndroid Build Coastguard Worker if (!fConvexOnly) {
525*c8dee2aaSAndroid Build Coastguard Worker bounds.outset(kMaxOutset, kMaxOutset);
526*c8dee2aaSAndroid Build Coastguard Worker }
527*c8dee2aaSAndroid Build Coastguard Worker if (position->fX + bounds.width() > kGMWidth) {
528*c8dee2aaSAndroid Build Coastguard Worker position->fX = 0;
529*c8dee2aaSAndroid Build Coastguard Worker position->fY += kMaxPathHeight;
530*c8dee2aaSAndroid Build Coastguard Worker }
531*c8dee2aaSAndroid Build Coastguard Worker center = { position->fX + SkScalarHalf(bounds.width()), position->fY };
532*c8dee2aaSAndroid Build Coastguard Worker position->fX += bounds.width();
533*c8dee2aaSAndroid Build Coastguard Worker }
534*c8dee2aaSAndroid Build Coastguard Worker
535*c8dee2aaSAndroid Build Coastguard Worker const SkPathDirection dirs[2] = { SkPathDirection::kCW, SkPathDirection::kCCW };
536*c8dee2aaSAndroid Build Coastguard Worker const float insets[] = { 5, 10, 15, 20, 25, 30, 35, 40 };
537*c8dee2aaSAndroid Build Coastguard Worker const float offsets[] = { 2, 5, 9, 14, 20, 27, 35, 44, -2, -5, -9 };
538*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { 0xFF901313, 0xFF8D6214, 0xFF698B14, 0xFF1C8914,
539*c8dee2aaSAndroid Build Coastguard Worker 0xFF148755, 0xFF146C84, 0xFF142482, 0xFF4A1480,
540*c8dee2aaSAndroid Build Coastguard Worker 0xFF901313, 0xFF8D6214, 0xFF698B14 };
541*c8dee2aaSAndroid Build Coastguard Worker
542*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
543*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
544*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
545*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(1);
546*c8dee2aaSAndroid Build Coastguard Worker
547*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkPoint[]> data(nullptr);
548*c8dee2aaSAndroid Build Coastguard Worker int numPts;
549*c8dee2aaSAndroid Build Coastguard Worker if (fConvexOnly) {
550*c8dee2aaSAndroid Build Coastguard Worker GetConvexPolygon(index, dirs[index % 2], &data, &numPts);
551*c8dee2aaSAndroid Build Coastguard Worker } else {
552*c8dee2aaSAndroid Build Coastguard Worker GetSimplePolygon(index, dirs[index % 2], &data, &numPts);
553*c8dee2aaSAndroid Build Coastguard Worker }
554*c8dee2aaSAndroid Build Coastguard Worker
555*c8dee2aaSAndroid Build Coastguard Worker {
556*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
557*c8dee2aaSAndroid Build Coastguard Worker path.moveTo(data.get()[0]);
558*c8dee2aaSAndroid Build Coastguard Worker for (int i = 1; i < numPts; ++i) {
559*c8dee2aaSAndroid Build Coastguard Worker path.lineTo(data.get()[i]);
560*c8dee2aaSAndroid Build Coastguard Worker }
561*c8dee2aaSAndroid Build Coastguard Worker path.close();
562*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
563*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(center.fX, center.fY);
564*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
565*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
566*c8dee2aaSAndroid Build Coastguard Worker }
567*c8dee2aaSAndroid Build Coastguard Worker
568*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<SkPoint> offsetPoly;
569*c8dee2aaSAndroid Build Coastguard Worker size_t count = fConvexOnly ? std::size(insets) : std::size(offsets);
570*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) {
571*c8dee2aaSAndroid Build Coastguard Worker SkScalar offset = fConvexOnly ? insets[i] : offsets[i];
572*c8dee2aaSAndroid Build Coastguard Worker std::function<SkScalar(const SkPoint&)> offsetFunc;
573*c8dee2aaSAndroid Build Coastguard Worker
574*c8dee2aaSAndroid Build Coastguard Worker bool result;
575*c8dee2aaSAndroid Build Coastguard Worker if (fConvexOnly) {
576*c8dee2aaSAndroid Build Coastguard Worker result = SkInsetConvexPolygon(data.get(), numPts, offset, &offsetPoly);
577*c8dee2aaSAndroid Build Coastguard Worker } else {
578*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds;
579*c8dee2aaSAndroid Build Coastguard Worker bounds.setBoundsCheck(data.get(), numPts);
580*c8dee2aaSAndroid Build Coastguard Worker result = SkOffsetSimplePolygon(data.get(), numPts, bounds, offset, &offsetPoly);
581*c8dee2aaSAndroid Build Coastguard Worker }
582*c8dee2aaSAndroid Build Coastguard Worker if (result) {
583*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
584*c8dee2aaSAndroid Build Coastguard Worker path.moveTo(offsetPoly[0]);
585*c8dee2aaSAndroid Build Coastguard Worker for (int j = 1; j < offsetPoly.size(); ++j) {
586*c8dee2aaSAndroid Build Coastguard Worker path.lineTo(offsetPoly[j]);
587*c8dee2aaSAndroid Build Coastguard Worker }
588*c8dee2aaSAndroid Build Coastguard Worker path.close();
589*c8dee2aaSAndroid Build Coastguard Worker
590*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(ToolUtils::color_to_565(colors[i]));
591*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
592*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(center.fX, center.fY);
593*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
594*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
595*c8dee2aaSAndroid Build Coastguard Worker }
596*c8dee2aaSAndroid Build Coastguard Worker }
597*c8dee2aaSAndroid Build Coastguard Worker }
598*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)599*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
600*c8dee2aaSAndroid Build Coastguard Worker // the right edge of the last drawn path
601*c8dee2aaSAndroid Build Coastguard Worker SkPoint offset = { 0, SkScalarHalf(kMaxPathHeight) };
602*c8dee2aaSAndroid Build Coastguard Worker if (!fConvexOnly) {
603*c8dee2aaSAndroid Build Coastguard Worker offset.fY += kMaxOutset;
604*c8dee2aaSAndroid Build Coastguard Worker }
605*c8dee2aaSAndroid Build Coastguard Worker
606*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumPaths; ++i) {
607*c8dee2aaSAndroid Build Coastguard Worker this->drawPolygon(canvas, i, &offset);
608*c8dee2aaSAndroid Build Coastguard Worker }
609*c8dee2aaSAndroid Build Coastguard Worker }
610*c8dee2aaSAndroid Build Coastguard Worker
611*c8dee2aaSAndroid Build Coastguard Worker private:
612*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumPaths = 20;
613*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kMaxPathHeight = 100;
614*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kMaxOutset = 16;
615*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kGMWidth = 512;
616*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kGMHeight = 512;
617*c8dee2aaSAndroid Build Coastguard Worker
618*c8dee2aaSAndroid Build Coastguard Worker bool fConvexOnly;
619*c8dee2aaSAndroid Build Coastguard Worker
620*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
621*c8dee2aaSAndroid Build Coastguard Worker };
622*c8dee2aaSAndroid Build Coastguard Worker
623*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
624*c8dee2aaSAndroid Build Coastguard Worker
625*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new PolygonOffsetGM(true);)
626*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new PolygonOffsetGM(false);)
627*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm
628*c8dee2aaSAndroid Build Coastguard Worker
629*c8dee2aaSAndroid Build Coastguard Worker #endif // !defined(SK_ENABLE_OPTIMIZE_SIZE)
630