1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2015 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gm.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkInsetConvexPolygon.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathPriv.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void create_ngon(int n, SkPoint* pts, SkScalar width, SkScalar height) {
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    float angleStep = 360.0f / n, angle = 0.0f, sin, cos;
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if ((n % 2) == 1) {
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        angle = angleStep/2.0f;
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < n; ++i) {
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sin = SkScalarSinCos(SkDegreesToRadians(angle), &cos);
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        pts[i].fX = -sin * width;
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        pts[i].fY = cos * height;
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        angle += angleStep;
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace ConvexLineOnlyData {
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// narrow rect
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints0[] = {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -1.5f, -50.0f },
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 1.5f, -50.0f },
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 1.5f,  50.0f },
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -1.5f,  50.0f }
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// narrow rect on an angle
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints1[] = {
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -50.0f, -49.0f },
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -49.0f, -50.0f },
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 50.0f,  49.0f },
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 49.0f,  50.0f }
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// trap - narrow on top - wide on bottom
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints2[] = {
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -10.0f, -50.0f },
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 10.0f, -50.0f },
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 50.0f,  50.0f },
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -50.0f,  50.0f }
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// wide skewed rect
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints3[] = {
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -50.0f, -50.0f },
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 0.0f, -50.0f },
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 50.0f,  50.0f },
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 0.0f,  50.0f }
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// thin rect with colinear-ish lines
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints4[] = {
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -6.0f, -50.0f },
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 4.0f, -50.0f },
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 5.0f, -25.0f },
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 6.0f,   0.0f },
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 5.0f,  25.0f },
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 4.0f,  50.0f },
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -4.0f,  50.0f }
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// degenerate
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints5[] = {
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -0.025f, -0.025f },
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 0.025f, -0.025f },
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 0.025f,  0.025f },
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -0.025f,  0.025f }
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Triangle in which the first point should fuse with last
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints6[] = {
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -20.0f, -13.0f },
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -20.0f, -13.05f },
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 20.0f, -13.0f },
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 20.0f,  27.0f }
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// thin rect with colinear lines
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints7[] = {
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -10.0f, -50.0f },
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 10.0f, -50.0f },
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 10.0f, -25.0f },
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 10.0f,   0.0f },
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 10.0f,  25.0f },
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 10.0f,  50.0f },
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -10.0f,  50.0f }
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// capped teardrop
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints8[] = {
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 50.00f,  50.00f },
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 0.00f,  50.00f },
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -15.45f,  47.55f },
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -29.39f,  40.45f },
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -40.45f,  29.39f },
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -47.55f,  15.45f },
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -50.00f,   0.00f },
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -47.55f, -15.45f },
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -40.45f, -29.39f },
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -29.39f, -40.45f },
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -15.45f, -47.55f },
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 0.00f, -50.00f },
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 50.00f, -50.00f }
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// teardrop
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints9[] = {
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 4.39f,  40.45f },
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -9.55f,  47.55f },
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -25.00f,  50.00f },
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -40.45f,  47.55f },
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -54.39f,  40.45f },
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -65.45f,  29.39f },
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -72.55f,  15.45f },
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -75.00f,   0.00f },
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -72.55f, -15.45f },
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -65.45f, -29.39f },
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -54.39f, -40.45f },
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -40.45f, -47.55f },
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -25.0f,  -50.0f },
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -9.55f, -47.55f },
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 4.39f, -40.45f },
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 75.00f,   0.00f }
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// clipped triangle
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint gPoints10[] = {
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -10.0f, -50.0f },
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 10.0f, -50.0f },
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 50.0f,  31.0f },
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 40.0f,  50.0f },
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -40.0f,  50.0f },
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { -50.0f,  31.0f },
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkPoint* gPoints[] = {
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    gPoints0, gPoints1, gPoints2, gPoints3, gPoints4, gPoints5, gPoints6,
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    gPoints7, gPoints8, gPoints9, gPoints10,
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst size_t gSizes[] = {
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints0),
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints1),
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints2),
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints3),
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints4),
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints5),
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints6),
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints7),
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints8),
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints9),
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ARRAY_COUNT(gPoints10),
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic_assert(SK_ARRAY_COUNT(gSizes) == SK_ARRAY_COUNT(gPoints), "array_mismatch");
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace skiagm {
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This GM is intended to exercise Ganesh's handling of convex line-only
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// paths
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass ConvexLineOnlyPathsGM : public GM {
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ConvexLineOnlyPathsGM(bool doStrokeAndFill) : fDoStrokeAndFill(doStrokeAndFill) {
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->setBGColor(0xFFFFFFFF);
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString onShortName() override {
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fDoStrokeAndFill) {
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return SkString("convex-lineonly-paths-stroke-and-fill");
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkString("convex-lineonly-paths");
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize onISize() override { return SkISize::Make(kGMWidth, kGMHeight); }
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool runAsBench() const override { return true; }
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static SkPath GetPath(int index, SkPath::Direction dir) {
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        std::unique_ptr<SkPoint[]> data(nullptr);
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPoint* points;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int numPts;
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (index < (int) SK_ARRAY_COUNT(ConvexLineOnlyData::gPoints)) {
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // manually specified
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            points = ConvexLineOnlyData::gPoints[index];
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            numPts = (int)ConvexLineOnlyData::gSizes[index];
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // procedurally generated
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar width = kMaxPathHeight/2;
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar height = kMaxPathHeight/2;
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (index-SK_ARRAY_COUNT(ConvexLineOnlyData::gPoints)) {
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 0:
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 3;
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 1:
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 4;
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 2:
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 5;
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 3:             // squashed pentagon
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 5;
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                width = kMaxPathHeight/5;
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 4:
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 6;
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 5:
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 8;
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 6:              // squashed octogon
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 8;
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                width = kMaxPathHeight/5;
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 7:
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 20;
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 8:
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 100;
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                numPts = 3;
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            data.reset(new SkPoint[numPts]);
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            create_ngon(numPts, data.get(), width, height);
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            points = data.get();
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath path;
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (SkPath::kCW_Direction == dir) {
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            path.moveTo(points[0]);
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 1; i < numPts; ++i) {
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                path.lineTo(points[i]);
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            path.moveTo(points[numPts-1]);
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = numPts-2; i >= 0; --i) {
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                path.lineTo(points[i]);
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.close();
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Each path this method returns should be convex, only composed of
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // lines, wound the right direction, and short enough to fit in one
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // of the GMs rows.
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(path.isConvex());
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(SkPath::kLine_SegmentMask == path.getSegmentMasks());
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPathPriv::FirstDirection actualDir;
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(SkPathPriv::CheapComputeFirstDirection(path, &actualDir));
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(SkPathPriv::AsFirstDirection(dir) == actualDir);
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect bounds = path.getBounds();
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(SkScalarNearlyEqual(bounds.centerX(), 0.0f));
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(bounds.height() <= kMaxPathHeight);
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return path;
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Draw a single path several times, shrinking it, flipping its direction
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // and changing its start vertex each time.
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void drawPath(SkCanvas* canvas, int index, SkPoint* offset) {
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint center;
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPath path = GetPath(index, SkPath::kCW_Direction);
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (offset->fX+path.getBounds().width() > kGMWidth) {
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                offset->fX = 0;
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                offset->fY += kMaxPathHeight;
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (fDoStrokeAndFill) {
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    offset->fX += kStrokeWidth / 2.0f;
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    offset->fY += kStrokeWidth / 2.0f;
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            center = { offset->fX + SkScalarHalf(path.getBounds().width()), offset->fY};
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            offset->fX += path.getBounds().width();
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fDoStrokeAndFill) {
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                offset->fX += kStrokeWidth;
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkColor colors[2] = { SK_ColorBLACK, SK_ColorWHITE };
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPath::Direction dirs[2] = { SkPath::kCW_Direction, SkPath::kCCW_Direction };
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const float scales[] = { 1.0f, 0.75f, 0.5f, 0.25f, 0.1f, 0.01f, 0.001f };
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPaint::Join joins[3] = { SkPaint::kRound_Join,
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                         SkPaint::kBevel_Join,
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                         SkPaint::kMiter_Join };
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint paint;
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setAntiAlias(true);
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (size_t i = 0; i < SK_ARRAY_COUNT(scales); ++i) {
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPath path = GetPath(index, dirs[i%2]);
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fDoStrokeAndFill) {
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setStyle(SkPaint::kStrokeAndFill_Style);
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setStrokeJoin(joins[i%3]);
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setStrokeWidth(SkIntToScalar(kStrokeWidth));
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->save();
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->translate(center.fX, center.fY);
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->scale(scales[i], scales[i]);
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setColor(colors[i%2]);
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->drawPath(path, paint);
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->restore();
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(SkCanvas* canvas) override {
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // the right edge of the last drawn path
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint offset = { 0, SkScalarHalf(kMaxPathHeight) };
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fDoStrokeAndFill) {
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            offset.fX += kStrokeWidth / 2.0f;
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            offset.fY += kStrokeWidth / 2.0f;
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < kNumPaths; ++i) {
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->drawPath(canvas, i, &offset);
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Repro for crbug.com/472723 (Missing AA on portions of graphic with GPU rasterization)
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->translate(356.0f, 50.0f);
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPaint p;
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p.setAntiAlias(true);
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fDoStrokeAndFill) {
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                p.setStyle(SkPaint::kStrokeAndFill_Style);
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                p.setStrokeJoin(SkPaint::kMiter_Join);
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                p.setStrokeWidth(SkIntToScalar(kStrokeWidth));
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPath p1;
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p1.moveTo(60.8522949f, 364.671021f);
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p1.lineTo(59.4380493f, 364.671021f);
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p1.lineTo(385.414276f, 690.647217f);
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p1.lineTo(386.121399f, 689.940125f);
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawPath(p1, p);
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kStrokeWidth   = 10;
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kNumPaths      = 20;
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kMaxPathHeight = 100;
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kGMWidth       = 512;
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kGMHeight      = 512;
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fDoStrokeAndFill;
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GM INHERITED;
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This GM is intended to exercise the insetting of convex polygons
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass ConvexPolygonInsetGM : public GM {
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ConvexPolygonInsetGM() {
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->setBGColor(0xFFFFFFFF);
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString onShortName() override {
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkString("convex-polygon-inset");
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize onISize() override { return SkISize::Make(kGMWidth, kGMHeight); }
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool runAsBench() const override { return true; }
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void GetPath(int index, SkPath::Direction dir,
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        std::unique_ptr<SkPoint[]>* data, int* numPts) {
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (index < (int)SK_ARRAY_COUNT(ConvexLineOnlyData::gPoints)) {
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // manually specified
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *numPts = (int)ConvexLineOnlyData::gSizes[index];
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            data->reset(new SkPoint[*numPts]);
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkPath::kCW_Direction == dir) {
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int i = 0; i < *numPts; ++i) {
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    (*data)[i] = ConvexLineOnlyData::gPoints[index][i];
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int i = 0; i < *numPts; ++i) {
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    (*data)[i] = ConvexLineOnlyData::gPoints[index][*numPts - i - 1];
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // procedurally generated
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar width = kMaxPathHeight / 2;
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar height = kMaxPathHeight / 2;
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (index - SK_ARRAY_COUNT(ConvexLineOnlyData::gPoints)) {
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 0:
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 3;
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 1:
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 4;
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 2:
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 5;
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 3:             // squashed pentagon
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 5;
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    width = kMaxPathHeight / 5;
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 4:
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 6;
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 5:
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 8;
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 6:              // squashed octogon
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 8;
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    width = kMaxPathHeight / 5;
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 7:
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 20;
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case 8:
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 100;
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *numPts = 3;
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            data->reset(new SkPoint[*numPts]);
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            create_ngon(*numPts, data->get(), width, height);
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkPath::kCCW_Direction == dir) {
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // reverse it
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int i = 0; i < *numPts/2; ++i) {
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPoint tmp = (*data)[i];
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    (*data)[i] = (*data)[*numPts - i - 1];
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    (*data)[*numPts - i - 1] = tmp;
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Draw a single path several times, shrinking it, flipping its direction
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // and changing its start vertex each time.
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void drawPath(SkCanvas* canvas, int index, SkPoint* offset) {
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint center;
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            std::unique_ptr<SkPoint[]> data(nullptr);
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            int numPts;
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GetPath(index, SkPath::kCW_Direction, &data, &numPts);
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect bounds;
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            bounds.set(data.get(), numPts);
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (offset->fX + bounds.width() > kGMWidth) {
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                offset->fX = 0;
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                offset->fY += kMaxPathHeight;
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            center = { offset->fX + SkScalarHalf(bounds.width()), offset->fY };
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            offset->fX += bounds.width();
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPath::Direction dirs[2] = { SkPath::kCW_Direction, SkPath::kCCW_Direction };
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const float insets[] = { 5, 10, 15, 20, 25, 30, 35, 40 };
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkColor colors[] = { 0xFF901313, 0xFF8D6214, 0xFF698B14, 0xFF1C8914,
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   0xFF148755, 0xFF146C84, 0xFF142482, 0xFF4A1480 };
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint paint;
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setAntiAlias(true);
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setStyle(SkPaint::kStroke_Style);
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setStrokeWidth(1);
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        std::unique_ptr<SkPoint[]> data(nullptr);
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int numPts;
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GetPath(index, dirs[index % 2], &data, &numPts);
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPath path;
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            path.moveTo(data.get()[0]);
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 1; i < numPts; ++i) {
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                path.lineTo(data.get()[i]);
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            path.close();
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->save();
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->translate(center.fX, center.fY);
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawPath(path, paint);
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->restore();
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTDArray<SkPoint> insetPoly;
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (size_t i = 0; i < SK_ARRAY_COUNT(insets); ++i) {
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkInsetConvexPolygon(data.get(), numPts, insets[i], &insetPoly)) {
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkPath path;
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                path.moveTo(insetPoly[0]);
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int i = 1; i < insetPoly.count(); ++i) {
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    path.lineTo(insetPoly[i]);
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                path.close();
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setColor(colors[i]);
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->save();
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->translate(center.fX, center.fY);
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->drawPath(path, paint);
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->restore();
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(SkCanvas* canvas) override {
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // the right edge of the last drawn path
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint offset = { 0, SkScalarHalf(kMaxPathHeight) };
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < kNumPaths; ++i) {
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->drawPath(canvas, i, &offset);
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kNumPaths = 20;
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kMaxPathHeight = 100;
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kGMWidth = 512;
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int kGMHeight = 512;
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GM INHERITED;
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM(return new ConvexLineOnlyPathsGM(false);)
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM(return new ConvexLineOnlyPathsGM(true);)
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM(return new ConvexPolygonInsetGM();)
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
523