17272935744670aebf82699c2f91aaff3cd4c3172robertphillips/*
27272935744670aebf82699c2f91aaff3cd4c3172robertphillips * Copyright 2015 Google Inc.
37272935744670aebf82699c2f91aaff3cd4c3172robertphillips *
47272935744670aebf82699c2f91aaff3cd4c3172robertphillips * Use of this source code is governed by a BSD-style license that can be
57272935744670aebf82699c2f91aaff3cd4c3172robertphillips * found in the LICENSE file.
67272935744670aebf82699c2f91aaff3cd4c3172robertphillips */
77272935744670aebf82699c2f91aaff3cd4c3172robertphillips
87272935744670aebf82699c2f91aaff3cd4c3172robertphillips#include "gm.h"
9ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon#include "SkInsetConvexPolygon.h"
10026beb52a29a620290fcfb24f1e7e9e75547b80freed#include "SkPathPriv.h"
117272935744670aebf82699c2f91aaff3cd4c3172robertphillips
127272935744670aebf82699c2f91aaff3cd4c3172robertphillipsstatic void create_ngon(int n, SkPoint* pts, SkScalar width, SkScalar height) {
137272935744670aebf82699c2f91aaff3cd4c3172robertphillips    float angleStep = 360.0f / n, angle = 0.0f, sin, cos;
147272935744670aebf82699c2f91aaff3cd4c3172robertphillips    if ((n % 2) == 1) {
157272935744670aebf82699c2f91aaff3cd4c3172robertphillips        angle = angleStep/2.0f;
167272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
177272935744670aebf82699c2f91aaff3cd4c3172robertphillips
187272935744670aebf82699c2f91aaff3cd4c3172robertphillips    for (int i = 0; i < n; ++i) {
197272935744670aebf82699c2f91aaff3cd4c3172robertphillips        sin = SkScalarSinCos(SkDegreesToRadians(angle), &cos);
207272935744670aebf82699c2f91aaff3cd4c3172robertphillips        pts[i].fX = -sin * width;
217272935744670aebf82699c2f91aaff3cd4c3172robertphillips        pts[i].fY = cos * height;
227272935744670aebf82699c2f91aaff3cd4c3172robertphillips        angle += angleStep;
237272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
247272935744670aebf82699c2f91aaff3cd4c3172robertphillips}
257272935744670aebf82699c2f91aaff3cd4c3172robertphillips
26ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonnamespace ConvexLineOnlyData {
27ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// narrow rect
28ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints0[] = {
29ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -1.5f, -50.0f },
30ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 1.5f, -50.0f },
31ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 1.5f,  50.0f },
32ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -1.5f,  50.0f }
33ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
34ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// narrow rect on an angle
35ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints1[] = {
36ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -50.0f, -49.0f },
37ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -49.0f, -50.0f },
38ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 50.0f,  49.0f },
39ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 49.0f,  50.0f }
40ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
41ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// trap - narrow on top - wide on bottom
42ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints2[] = {
43ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -10.0f, -50.0f },
44ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 10.0f, -50.0f },
45ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 50.0f,  50.0f },
46ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -50.0f,  50.0f }
47ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
48ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// wide skewed rect
49ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints3[] = {
50ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -50.0f, -50.0f },
51ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 0.0f, -50.0f },
52ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 50.0f,  50.0f },
53ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 0.0f,  50.0f }
54ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
55ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// thin rect with colinear-ish lines
56ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints4[] = {
57ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -6.0f, -50.0f },
58ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 4.0f, -50.0f },
59ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 5.0f, -25.0f },
60ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 6.0f,   0.0f },
61ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 5.0f,  25.0f },
62ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 4.0f,  50.0f },
63ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -4.0f,  50.0f }
64ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
65ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// degenerate
66ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints5[] = {
67ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -0.025f, -0.025f },
68ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 0.025f, -0.025f },
69ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 0.025f,  0.025f },
70ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -0.025f,  0.025f }
71ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
72ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// Triangle in which the first point should fuse with last
73ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints6[] = {
74ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -20.0f, -13.0f },
75ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -20.0f, -13.05f },
76ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 20.0f, -13.0f },
77ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 20.0f,  27.0f }
78ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
79ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// thin rect with colinear lines
80ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints7[] = {
81ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -10.0f, -50.0f },
82ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 10.0f, -50.0f },
83ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 10.0f, -25.0f },
84ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 10.0f,   0.0f },
85ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 10.0f,  25.0f },
86ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 10.0f,  50.0f },
87ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -10.0f,  50.0f }
88ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
89ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// capped teardrop
90ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints8[] = {
91ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 50.00f,  50.00f },
92ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 0.00f,  50.00f },
93ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -15.45f,  47.55f },
94ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -29.39f,  40.45f },
95ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -40.45f,  29.39f },
96ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -47.55f,  15.45f },
97ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -50.00f,   0.00f },
98ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -47.55f, -15.45f },
99ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -40.45f, -29.39f },
100ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -29.39f, -40.45f },
101ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -15.45f, -47.55f },
102ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 0.00f, -50.00f },
103ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 50.00f, -50.00f }
104ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
105ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// teardrop
106ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints9[] = {
107ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 4.39f,  40.45f },
108ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -9.55f,  47.55f },
109ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -25.00f,  50.00f },
110ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -40.45f,  47.55f },
111ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -54.39f,  40.45f },
112ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -65.45f,  29.39f },
113ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -72.55f,  15.45f },
114ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -75.00f,   0.00f },
115ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -72.55f, -15.45f },
116ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -65.45f, -29.39f },
117ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -54.39f, -40.45f },
118ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -40.45f, -47.55f },
119ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -25.0f,  -50.0f },
120ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -9.55f, -47.55f },
121ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 4.39f, -40.45f },
122ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 75.00f,   0.00f }
123ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
124ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// clipped triangle
125ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint gPoints10[] = {
126ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -10.0f, -50.0f },
127ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 10.0f, -50.0f },
128ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 50.0f,  31.0f },
129ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { 40.0f,  50.0f },
130ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -40.0f,  50.0f },
131ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    { -50.0f,  31.0f },
132ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
133ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
134ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst SkPoint* gPoints[] = {
135ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    gPoints0, gPoints1, gPoints2, gPoints3, gPoints4, gPoints5, gPoints6,
136ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    gPoints7, gPoints8, gPoints9, gPoints10,
137ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
138ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
139ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonconst size_t gSizes[] = {
140ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints0),
141ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints1),
142ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints2),
143ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints3),
144ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints4),
145ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints5),
146ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints6),
147ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints7),
148ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints8),
149ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints9),
150ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SK_ARRAY_COUNT(gPoints10),
151ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
152ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonstatic_assert(SK_ARRAY_COUNT(gSizes) == SK_ARRAY_COUNT(gPoints), "array_mismatch");
153ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon}
154ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
1557272935744670aebf82699c2f91aaff3cd4c3172robertphillipsnamespace skiagm {
1567272935744670aebf82699c2f91aaff3cd4c3172robertphillips
1577272935744670aebf82699c2f91aaff3cd4c3172robertphillips// This GM is intended to exercise Ganesh's handling of convex line-only
1587272935744670aebf82699c2f91aaff3cd4c3172robertphillips// paths
1597272935744670aebf82699c2f91aaff3cd4c3172robertphillipsclass ConvexLineOnlyPathsGM : public GM {
1607272935744670aebf82699c2f91aaff3cd4c3172robertphillipspublic:
161ad2344693c70f13d5e4216df8458b4d907395bderobertphillips    ConvexLineOnlyPathsGM(bool doStrokeAndFill) : fDoStrokeAndFill(doStrokeAndFill) {
1627272935744670aebf82699c2f91aaff3cd4c3172robertphillips        this->setBGColor(0xFFFFFFFF);
1637272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
1647272935744670aebf82699c2f91aaff3cd4c3172robertphillips
1657272935744670aebf82699c2f91aaff3cd4c3172robertphillipsprotected:
166ad2344693c70f13d5e4216df8458b4d907395bderobertphillips    SkString onShortName() override {
167ad2344693c70f13d5e4216df8458b4d907395bderobertphillips        if (fDoStrokeAndFill) {
168ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            return SkString("convex-lineonly-paths-stroke-and-fill");
169ad2344693c70f13d5e4216df8458b4d907395bderobertphillips        }
170ad2344693c70f13d5e4216df8458b4d907395bderobertphillips        return SkString("convex-lineonly-paths");
171ad2344693c70f13d5e4216df8458b4d907395bderobertphillips    }
1727272935744670aebf82699c2f91aaff3cd4c3172robertphillips    SkISize onISize() override { return SkISize::Make(kGMWidth, kGMHeight); }
1737272935744670aebf82699c2f91aaff3cd4c3172robertphillips    bool runAsBench() const override { return true; }
1747272935744670aebf82699c2f91aaff3cd4c3172robertphillips
175ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    static SkPath GetPath(int index, SkPath::Direction dir) {
1767ecc59610de72043e9b7ebaf1ef45c43425e54fcBen Wagner        std::unique_ptr<SkPoint[]> data(nullptr);
1777272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint* points;
1787272935744670aebf82699c2f91aaff3cd4c3172robertphillips        int numPts;
179ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        if (index < (int) SK_ARRAY_COUNT(ConvexLineOnlyData::gPoints)) {
1807272935744670aebf82699c2f91aaff3cd4c3172robertphillips            // manually specified
181ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            points = ConvexLineOnlyData::gPoints[index];
182ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            numPts = (int)ConvexLineOnlyData::gSizes[index];
1837272935744670aebf82699c2f91aaff3cd4c3172robertphillips        } else {
1847272935744670aebf82699c2f91aaff3cd4c3172robertphillips            // procedurally generated
1857272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkScalar width = kMaxPathHeight/2;
1867272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkScalar height = kMaxPathHeight/2;
187ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            switch (index-SK_ARRAY_COUNT(ConvexLineOnlyData::gPoints)) {
1887272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 0:
1897272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 3;
1907272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1917272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 1:
1927272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 4;
1937272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1947272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 2:
1957272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 5;
1967272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1977272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 3:             // squashed pentagon
1987272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 5;
1997272935744670aebf82699c2f91aaff3cd4c3172robertphillips                width = kMaxPathHeight/5;
2007272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2017272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 4:
2027272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 6;
2037272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2047272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 5:
2057272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 8;
2067272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2077272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 6:              // squashed octogon
2087272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 8;
2097272935744670aebf82699c2f91aaff3cd4c3172robertphillips                width = kMaxPathHeight/5;
2107272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2117272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 7:
2127272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 20;
2137272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2147272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 8:
2157272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 100;
2167272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2177272935744670aebf82699c2f91aaff3cd4c3172robertphillips            default:
2187272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 3;
2197272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2207272935744670aebf82699c2f91aaff3cd4c3172robertphillips            }
2217272935744670aebf82699c2f91aaff3cd4c3172robertphillips
222385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            data.reset(new SkPoint[numPts]);
2237272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2247272935744670aebf82699c2f91aaff3cd4c3172robertphillips            create_ngon(numPts, data.get(), width, height);
2257272935744670aebf82699c2f91aaff3cd4c3172robertphillips            points = data.get();
2267272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
2277272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2287272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkPath path;
2297272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2307272935744670aebf82699c2f91aaff3cd4c3172robertphillips        if (SkPath::kCW_Direction == dir) {
2317272935744670aebf82699c2f91aaff3cd4c3172robertphillips            path.moveTo(points[0]);
2327272935744670aebf82699c2f91aaff3cd4c3172robertphillips            for (int i = 1; i < numPts; ++i) {
2337272935744670aebf82699c2f91aaff3cd4c3172robertphillips                path.lineTo(points[i]);
2347272935744670aebf82699c2f91aaff3cd4c3172robertphillips            }
2357272935744670aebf82699c2f91aaff3cd4c3172robertphillips        } else {
2367272935744670aebf82699c2f91aaff3cd4c3172robertphillips            path.moveTo(points[numPts-1]);
2377272935744670aebf82699c2f91aaff3cd4c3172robertphillips            for (int i = numPts-2; i >= 0; --i) {
2387272935744670aebf82699c2f91aaff3cd4c3172robertphillips                path.lineTo(points[i]);
2397272935744670aebf82699c2f91aaff3cd4c3172robertphillips            }
2407272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
2417272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2427272935744670aebf82699c2f91aaff3cd4c3172robertphillips        path.close();
2437272935744670aebf82699c2f91aaff3cd4c3172robertphillips#ifdef SK_DEBUG
2447272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // Each path this method returns should be convex, only composed of
2457272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // lines, wound the right direction, and short enough to fit in one
2467272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // of the GMs rows.
2477272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(path.isConvex());
2487272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(SkPath::kLine_SegmentMask == path.getSegmentMasks());
249026beb52a29a620290fcfb24f1e7e9e75547b80freed        SkPathPriv::FirstDirection actualDir;
250026beb52a29a620290fcfb24f1e7e9e75547b80freed        SkASSERT(SkPathPriv::CheapComputeFirstDirection(path, &actualDir));
251026beb52a29a620290fcfb24f1e7e9e75547b80freed        SkASSERT(SkPathPriv::AsFirstDirection(dir) == actualDir);
2527272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkRect bounds = path.getBounds();
2537272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(SkScalarNearlyEqual(bounds.centerX(), 0.0f));
2547272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(bounds.height() <= kMaxPathHeight);
2557272935744670aebf82699c2f91aaff3cd4c3172robertphillips#endif
2567272935744670aebf82699c2f91aaff3cd4c3172robertphillips        return path;
2577272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
2587272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2597272935744670aebf82699c2f91aaff3cd4c3172robertphillips    // Draw a single path several times, shrinking it, flipping its direction
2607272935744670aebf82699c2f91aaff3cd4c3172robertphillips    // and changing its start vertex each time.
2612a974625c559fcb2640b587fed6f92d5b58cab24robertphillips    void drawPath(SkCanvas* canvas, int index, SkPoint* offset) {
2627272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2637272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkPoint center;
2647272935744670aebf82699c2f91aaff3cd4c3172robertphillips        {
265ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            SkPath path = GetPath(index, SkPath::kCW_Direction);
2662a974625c559fcb2640b587fed6f92d5b58cab24robertphillips            if (offset->fX+path.getBounds().width() > kGMWidth) {
2672a974625c559fcb2640b587fed6f92d5b58cab24robertphillips                offset->fX = 0;
2682a974625c559fcb2640b587fed6f92d5b58cab24robertphillips                offset->fY += kMaxPathHeight;
269ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                if (fDoStrokeAndFill) {
270ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                    offset->fX += kStrokeWidth / 2.0f;
271ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                    offset->fY += kStrokeWidth / 2.0f;
272ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                }
2737272935744670aebf82699c2f91aaff3cd4c3172robertphillips            }
2742a974625c559fcb2640b587fed6f92d5b58cab24robertphillips            center = { offset->fX + SkScalarHalf(path.getBounds().width()), offset->fY};
2752a974625c559fcb2640b587fed6f92d5b58cab24robertphillips            offset->fX += path.getBounds().width();
276ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            if (fDoStrokeAndFill) {
277ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                offset->fX += kStrokeWidth;
278ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            }
2797272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
2807272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2817272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkColor colors[2] = { SK_ColorBLACK, SK_ColorWHITE };
2827272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPath::Direction dirs[2] = { SkPath::kCW_Direction, SkPath::kCCW_Direction };
2837272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const float scales[] = { 1.0f, 0.75f, 0.5f, 0.25f, 0.1f, 0.01f, 0.001f };
284dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const SkPaint::Join joins[3] = { SkPaint::kRound_Join,
285ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                                         SkPaint::kBevel_Join,
286ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                                         SkPaint::kMiter_Join };
2877272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2887272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkPaint paint;
2897272935744670aebf82699c2f91aaff3cd4c3172robertphillips        paint.setAntiAlias(true);
2907272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2917272935744670aebf82699c2f91aaff3cd4c3172robertphillips        for (size_t i = 0; i < SK_ARRAY_COUNT(scales); ++i) {
292ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            SkPath path = GetPath(index, dirs[i%2]);
293ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            if (fDoStrokeAndFill) {
294ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                paint.setStyle(SkPaint::kStrokeAndFill_Style);
295ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                paint.setStrokeJoin(joins[i%3]);
296ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                paint.setStrokeWidth(SkIntToScalar(kStrokeWidth));
297ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            }
2987272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2997272935744670aebf82699c2f91aaff3cd4c3172robertphillips            canvas->save();
3007272935744670aebf82699c2f91aaff3cd4c3172robertphillips                canvas->translate(center.fX, center.fY);
3017272935744670aebf82699c2f91aaff3cd4c3172robertphillips                canvas->scale(scales[i], scales[i]);
3027272935744670aebf82699c2f91aaff3cd4c3172robertphillips                paint.setColor(colors[i%2]);
3037272935744670aebf82699c2f91aaff3cd4c3172robertphillips                canvas->drawPath(path, paint);
3047272935744670aebf82699c2f91aaff3cd4c3172robertphillips            canvas->restore();
3057272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
3067272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
3077272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3087272935744670aebf82699c2f91aaff3cd4c3172robertphillips    void onDraw(SkCanvas* canvas) override {
3092a974625c559fcb2640b587fed6f92d5b58cab24robertphillips        // the right edge of the last drawn path
3109d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        SkPoint offset = { 0, SkScalarHalf(kMaxPathHeight) };
311ad2344693c70f13d5e4216df8458b4d907395bderobertphillips        if (fDoStrokeAndFill) {
312ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            offset.fX += kStrokeWidth / 2.0f;
313ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            offset.fY += kStrokeWidth / 2.0f;
314ad2344693c70f13d5e4216df8458b4d907395bderobertphillips        }
3152a974625c559fcb2640b587fed6f92d5b58cab24robertphillips
3167272935744670aebf82699c2f91aaff3cd4c3172robertphillips        for (int i = 0; i < kNumPaths; ++i) {
3172a974625c559fcb2640b587fed6f92d5b58cab24robertphillips            this->drawPath(canvas, i, &offset);
3187272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
3197272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3207272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // Repro for crbug.com/472723 (Missing AA on portions of graphic with GPU rasterization)
3217272935744670aebf82699c2f91aaff3cd4c3172robertphillips        {
3227272935744670aebf82699c2f91aaff3cd4c3172robertphillips            canvas->translate(356.0f, 50.0f);
3237272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3247272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkPaint p;
3257272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p.setAntiAlias(true);
326ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            if (fDoStrokeAndFill) {
327ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                p.setStyle(SkPaint::kStrokeAndFill_Style);
328ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                p.setStrokeJoin(SkPaint::kMiter_Join);
329ad2344693c70f13d5e4216df8458b4d907395bderobertphillips                p.setStrokeWidth(SkIntToScalar(kStrokeWidth));
330ad2344693c70f13d5e4216df8458b4d907395bderobertphillips            }
3317272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3327272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkPath p1;
3337272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p1.moveTo(60.8522949f, 364.671021f);
3347272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p1.lineTo(59.4380493f, 364.671021f);
3357272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p1.lineTo(385.414276f, 690.647217f);
3367272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p1.lineTo(386.121399f, 689.940125f);
3377272935744670aebf82699c2f91aaff3cd4c3172robertphillips            canvas->drawPath(p1, p);
3387272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
3397272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
3407272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3417272935744670aebf82699c2f91aaff3cd4c3172robertphillipsprivate:
342dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kStrokeWidth   = 10;
343dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kNumPaths      = 20;
344dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kMaxPathHeight = 100;
345dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kGMWidth       = 512;
346dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kGMHeight      = 512;
3477272935744670aebf82699c2f91aaff3cd4c3172robertphillips
348ad2344693c70f13d5e4216df8458b4d907395bderobertphillips    bool fDoStrokeAndFill;
349ad2344693c70f13d5e4216df8458b4d907395bderobertphillips
3507272935744670aebf82699c2f91aaff3cd4c3172robertphillips    typedef GM INHERITED;
3517272935744670aebf82699c2f91aaff3cd4c3172robertphillips};
3527272935744670aebf82699c2f91aaff3cd4c3172robertphillips
353ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon// This GM is intended to exercise the insetting of convex polygons
354ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonclass ConvexPolygonInsetGM : public GM {
355ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonpublic:
356ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    ConvexPolygonInsetGM() {
357ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        this->setBGColor(0xFFFFFFFF);
358ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    }
359ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
360ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonprotected:
361ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SkString onShortName() override {
362ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        return SkString("convex-polygon-inset");
363ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    }
364ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    SkISize onISize() override { return SkISize::Make(kGMWidth, kGMHeight); }
365ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    bool runAsBench() const override { return true; }
366ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
367ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    static void GetPath(int index, SkPath::Direction dir,
368ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                        std::unique_ptr<SkPoint[]>* data, int* numPts) {
369ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        if (index < (int)SK_ARRAY_COUNT(ConvexLineOnlyData::gPoints)) {
370ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            // manually specified
371ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            *numPts = (int)ConvexLineOnlyData::gSizes[index];
372ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            data->reset(new SkPoint[*numPts]);
373ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            if (SkPath::kCW_Direction == dir) {
374ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                for (int i = 0; i < *numPts; ++i) {
375ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    (*data)[i] = ConvexLineOnlyData::gPoints[index][i];
376ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                }
377ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            } else {
378ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                for (int i = 0; i < *numPts; ++i) {
379ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    (*data)[i] = ConvexLineOnlyData::gPoints[index][*numPts - i - 1];
380ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                }
381ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            }
382ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        } else {
383ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            // procedurally generated
384ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            SkScalar width = kMaxPathHeight / 2;
385ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            SkScalar height = kMaxPathHeight / 2;
386ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            switch (index - SK_ARRAY_COUNT(ConvexLineOnlyData::gPoints)) {
387ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 0:
388ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 3;
389ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
390ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 1:
391ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 4;
392ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
393ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 2:
394ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 5;
395ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
396ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 3:             // squashed pentagon
397ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 5;
398ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    width = kMaxPathHeight / 5;
399ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
400ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 4:
401ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 6;
402ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
403ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 5:
404ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 8;
405ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
406ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 6:              // squashed octogon
407ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 8;
408ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    width = kMaxPathHeight / 5;
409ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
410ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 7:
411ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 20;
412ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
413ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                case 8:
414ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 100;
415ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
416ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                default:
417ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    *numPts = 3;
418ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    break;
419ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            }
420ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
421ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            data->reset(new SkPoint[*numPts]);
422ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
423ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            create_ngon(*numPts, data->get(), width, height);
424ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            if (SkPath::kCCW_Direction == dir) {
425ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                // reverse it
426ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                for (int i = 0; i < *numPts/2; ++i) {
427ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    SkPoint tmp = (*data)[i];
428ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    (*data)[i] = (*data)[*numPts - i - 1];
429ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    (*data)[*numPts - i - 1] = tmp;
430ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                }
431ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            }
432ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        }
433ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    }
434ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
435ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    // Draw a single path several times, shrinking it, flipping its direction
436ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    // and changing its start vertex each time.
437ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    void drawPath(SkCanvas* canvas, int index, SkPoint* offset) {
438ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
439ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        SkPoint center;
440ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        {
441ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            std::unique_ptr<SkPoint[]> data(nullptr);
442ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            int numPts;
443ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            GetPath(index, SkPath::kCW_Direction, &data, &numPts);
444ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            SkRect bounds;
445ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            bounds.set(data.get(), numPts);
446ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            if (offset->fX + bounds.width() > kGMWidth) {
447ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                offset->fX = 0;
448ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                offset->fY += kMaxPathHeight;
449ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            }
450ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            center = { offset->fX + SkScalarHalf(bounds.width()), offset->fY };
451ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            offset->fX += bounds.width();
452ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        }
453ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
454ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        const SkPath::Direction dirs[2] = { SkPath::kCW_Direction, SkPath::kCCW_Direction };
455ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        const float insets[] = { 5, 10, 15, 20, 25, 30, 35, 40 };
456ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        const SkColor colors[] = { 0xFF901313, 0xFF8D6214, 0xFF698B14, 0xFF1C8914,
457ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                                   0xFF148755, 0xFF146C84, 0xFF142482, 0xFF4A1480 };
458ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
459ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        SkPaint paint;
460ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        paint.setAntiAlias(true);
461ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        paint.setStyle(SkPaint::kStroke_Style);
462ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        paint.setStrokeWidth(1);
463ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
464ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        std::unique_ptr<SkPoint[]> data(nullptr);
465ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        int numPts;
466ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        GetPath(index, dirs[index % 2], &data, &numPts);
467ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        {
468ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            SkPath path;
469ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            path.moveTo(data.get()[0]);
470ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            for (int i = 1; i < numPts; ++i) {
471ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                path.lineTo(data.get()[i]);
472ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            }
473ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            path.close();
474ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            canvas->save();
475ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            canvas->translate(center.fX, center.fY);
476ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            canvas->drawPath(path, paint);
477ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            canvas->restore();
478ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        }
479ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
480ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        SkTDArray<SkPoint> insetPoly;
481ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        for (size_t i = 0; i < SK_ARRAY_COUNT(insets); ++i) {
482ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            if (SkInsetConvexPolygon(data.get(), numPts, insets[i], &insetPoly)) {
483ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                SkPath path;
484ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                path.moveTo(insetPoly[0]);
485ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                for (int i = 1; i < insetPoly.count(); ++i) {
486ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                    path.lineTo(insetPoly[i]);
487ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                }
488ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                path.close();
489ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
490ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                paint.setColor(colors[i]);
491ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                canvas->save();
492ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                canvas->translate(center.fX, center.fY);
493ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                canvas->drawPath(path, paint);
494ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon                canvas->restore();
495ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            }
496ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        }
497ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    }
498ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
499ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    void onDraw(SkCanvas* canvas) override {
500ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        // the right edge of the last drawn path
501ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        SkPoint offset = { 0, SkScalarHalf(kMaxPathHeight) };
502ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
503ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        for (int i = 0; i < kNumPaths; ++i) {
504ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon            this->drawPath(canvas, i, &offset);
505ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon        }
506ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    }
507ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
508ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonprivate:
509ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    static constexpr int kNumPaths = 20;
510ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    static constexpr int kMaxPathHeight = 100;
511ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    static constexpr int kGMWidth = 512;
512ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    static constexpr int kGMHeight = 512;
513ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
514ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon    typedef GM INHERITED;
515ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon};
516ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon
5177272935744670aebf82699c2f91aaff3cd4c3172robertphillips//////////////////////////////////////////////////////////////////////////////
5187272935744670aebf82699c2f91aaff3cd4c3172robertphillips
519ad2344693c70f13d5e4216df8458b4d907395bderobertphillipsDEF_GM(return new ConvexLineOnlyPathsGM(false);)
520ad2344693c70f13d5e4216df8458b4d907395bderobertphillipsDEF_GM(return new ConvexLineOnlyPathsGM(true);)
521ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian SalomonDEF_GM(return new ConvexPolygonInsetGM();)
5227272935744670aebf82699c2f91aaff3cd4c3172robertphillips}
523