convex_all_line_paths.cpp revision db3f8cdb5969dbdc65008b87ab90a0bfe33a406b
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"
97272935744670aebf82699c2f91aaff3cd4c3172robertphillips
107272935744670aebf82699c2f91aaff3cd4c3172robertphillipsstatic void create_ngon(int n, SkPoint* pts, SkScalar width, SkScalar height) {
117272935744670aebf82699c2f91aaff3cd4c3172robertphillips    float angleStep = 360.0f / n, angle = 0.0f, sin, cos;
127272935744670aebf82699c2f91aaff3cd4c3172robertphillips    if ((n % 2) == 1) {
137272935744670aebf82699c2f91aaff3cd4c3172robertphillips        angle = angleStep/2.0f;
147272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
157272935744670aebf82699c2f91aaff3cd4c3172robertphillips
167272935744670aebf82699c2f91aaff3cd4c3172robertphillips    for (int i = 0; i < n; ++i) {
177272935744670aebf82699c2f91aaff3cd4c3172robertphillips        sin = SkScalarSinCos(SkDegreesToRadians(angle), &cos);
187272935744670aebf82699c2f91aaff3cd4c3172robertphillips        pts[i].fX = -sin * width;
197272935744670aebf82699c2f91aaff3cd4c3172robertphillips        pts[i].fY = cos * height;
207272935744670aebf82699c2f91aaff3cd4c3172robertphillips        angle += angleStep;
217272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
227272935744670aebf82699c2f91aaff3cd4c3172robertphillips}
237272935744670aebf82699c2f91aaff3cd4c3172robertphillips
247272935744670aebf82699c2f91aaff3cd4c3172robertphillipsnamespace skiagm {
257272935744670aebf82699c2f91aaff3cd4c3172robertphillips
267272935744670aebf82699c2f91aaff3cd4c3172robertphillips// This GM is intended to exercise Ganesh's handling of convex line-only
277272935744670aebf82699c2f91aaff3cd4c3172robertphillips// paths
287272935744670aebf82699c2f91aaff3cd4c3172robertphillipsclass ConvexLineOnlyPathsGM : public GM {
297272935744670aebf82699c2f91aaff3cd4c3172robertphillipspublic:
307272935744670aebf82699c2f91aaff3cd4c3172robertphillips    ConvexLineOnlyPathsGM() {
317272935744670aebf82699c2f91aaff3cd4c3172robertphillips        fOffset.set(0, SkScalarHalf(kMaxPathHeight));
327272935744670aebf82699c2f91aaff3cd4c3172robertphillips        this->setBGColor(0xFFFFFFFF);
337272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
347272935744670aebf82699c2f91aaff3cd4c3172robertphillips
357272935744670aebf82699c2f91aaff3cd4c3172robertphillipsprotected:
367272935744670aebf82699c2f91aaff3cd4c3172robertphillips    SkString onShortName() override { return SkString("convex-lineonly-paths"); }
377272935744670aebf82699c2f91aaff3cd4c3172robertphillips    SkISize onISize() override { return SkISize::Make(kGMWidth, kGMHeight); }
387272935744670aebf82699c2f91aaff3cd4c3172robertphillips    bool runAsBench() const override { return true; }
397272935744670aebf82699c2f91aaff3cd4c3172robertphillips
407272935744670aebf82699c2f91aaff3cd4c3172robertphillips    static SkPath GetPath(int index, int offset, SkPath::Direction dir) {
417272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // narrow rect
427272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints0[] = {
437272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -1.5f, -50.0f },
447272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  1.5f, -50.0f },
457272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  1.5f,  50.0f },
467272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -1.5f,  50.0f }
477272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
487272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // narrow rect on an angle
497272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints1[] = {
507272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -50.0f, -49.0f },
517272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -49.0f, -50.0f },
527272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  50.0f,  49.0f },
537272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  49.0f,  50.0f }
547272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
557272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // trap - narrow on top - wide on bottom
567272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints2[] = {
577272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -10.0f, -50.0f },
587272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  10.0f, -50.0f },
597272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  50.0f,  50.0f },
607272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -50.0f,  50.0f }
617272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
627272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // wide skewed rect
637272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints3[] = {
647272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -50.0f, -50.0f },
657272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {   0.0f, -50.0f },
667272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  50.0f,  50.0f },
677272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {   0.0f,  50.0f }
687272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
697272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // thin rect with colinear-ish lines
707272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints4[] = {
717272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -6.0f, -50.0f },
727272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  4.0f, -50.0f },
737272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  5.0f, -25.0f },
747272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  6.0f,   0.0f },
757272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  5.0f,  25.0f },
767272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  4.0f,  50.0f },
777272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -4.0f,  50.0f }
787272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
797272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // degenerate
807272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints5[] = {
817272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -0.025f, -0.025f  },
827272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  0.025f, -0.025f  },
837272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  0.025f,  0.025f },
847272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -0.025f,  0.025f }
857272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
867272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // Triangle in which the first point should fuse with last
877272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints6[] = {
887272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -20.0f, -13.0f },
897272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -20.0f, -13.05f },
907272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  20.0f, -13.0f },
917272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  20.0f,  27.0f }
927272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
937272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // thin rect with colinear lines
947272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints7[] = {
957272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -10.0f, -50.0f },
967272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  10.0f, -50.0f },
977272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  10.0f, -25.0f },
987272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  10.0f,   0.0f },
997272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  10.0f,  25.0f },
1007272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  10.0f,  50.0f },
1017272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -10.0f,  50.0f }
1027272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
1037272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // capped teardrop
1047272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints8[] = {
1057272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  50.00f,  50.00f },
1067272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {   0.00f,  50.00f },
1077272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -15.45f,  47.55f },
1087272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -29.39f,  40.45f },
1097272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -40.45f,  29.39f },
1107272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -47.55f,  15.45f },
1117272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -50.00f,   0.00f },
1127272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -47.55f, -15.45f },
1137272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -40.45f, -29.39f },
1147272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -29.39f, -40.45f },
1157272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -15.45f, -47.55f },
1167272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {   0.00f, -50.00f },
1177272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  50.00f, -50.00f }
1187272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
1197272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // teardrop
1207272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints9[] = {
1217272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {   4.39f,  40.45f },
1227272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  -9.55f,  47.55f },
1237272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -25.00f,  50.00f },
1247272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -40.45f,  47.55f },
1257272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -54.39f,  40.45f },
1267272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -65.45f,  29.39f },
1277272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -72.55f,  15.45f },
1287272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -75.00f,   0.00f },
1297272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -72.55f, -15.45f },
1307272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -65.45f, -29.39f },
1317272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -54.39f, -40.45f },
1327272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -40.45f, -47.55f },
1337272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -25.0f,  -50.0f },
1347272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  -9.55f, -47.55f },
1357272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {   4.39f, -40.45f },
1367272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  75.00f,   0.00f }
1377272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
1387272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // clipped triangle
1397272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint gPoints10[] = {
1407272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -10.0f, -50.0f },
1417272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  10.0f, -50.0f },
1427272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  50.0f,  31.0f },
1437272935744670aebf82699c2f91aaff3cd4c3172robertphillips            {  40.0f,  50.0f },
1447272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -40.0f,  50.0f },
1457272935744670aebf82699c2f91aaff3cd4c3172robertphillips            { -50.0f,  31.0f },
1467272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
1477272935744670aebf82699c2f91aaff3cd4c3172robertphillips
1487272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint* gPoints[] = {
1497272935744670aebf82699c2f91aaff3cd4c3172robertphillips            gPoints0, gPoints1, gPoints2, gPoints3, gPoints4, gPoints5, gPoints6,
1507272935744670aebf82699c2f91aaff3cd4c3172robertphillips            gPoints7, gPoints8, gPoints9, gPoints10,
1517272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
1527272935744670aebf82699c2f91aaff3cd4c3172robertphillips
1537272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const size_t gSizes[] = {
1547272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints0),
1557272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints1),
1567272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints2),
1577272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints3),
1587272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints4),
1597272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints5),
1607272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints6),
1617272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints7),
1627272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints8),
1637272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints9),
1647272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SK_ARRAY_COUNT(gPoints10),
1657272935744670aebf82699c2f91aaff3cd4c3172robertphillips        };
1667272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gSizes) == SK_ARRAY_COUNT(gPoints), array_mismatch);
1677272935744670aebf82699c2f91aaff3cd4c3172robertphillips
168db3f8cdb5969dbdc65008b87ab90a0bfe33a406brobertphillips        SkAutoTDeleteArray<SkPoint> data(NULL);
1697272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPoint* points;
1707272935744670aebf82699c2f91aaff3cd4c3172robertphillips        int numPts;
1717272935744670aebf82699c2f91aaff3cd4c3172robertphillips        if (index < (int) SK_ARRAY_COUNT(gPoints)) {
1727272935744670aebf82699c2f91aaff3cd4c3172robertphillips            // manually specified
1737272935744670aebf82699c2f91aaff3cd4c3172robertphillips            points = gPoints[index];
1747272935744670aebf82699c2f91aaff3cd4c3172robertphillips            numPts = (int) gSizes[index];
1757272935744670aebf82699c2f91aaff3cd4c3172robertphillips        } else {
1767272935744670aebf82699c2f91aaff3cd4c3172robertphillips            // procedurally generated
1777272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkScalar width = kMaxPathHeight/2;
1787272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkScalar height = kMaxPathHeight/2;
1797272935744670aebf82699c2f91aaff3cd4c3172robertphillips            switch (index-SK_ARRAY_COUNT(gPoints)) {
1807272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 0:
1817272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 3;
1827272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1837272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 1:
1847272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 4;
1857272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1867272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 2:
1877272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 5;
1887272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1897272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 3:             // squashed pentagon
1907272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 5;
1917272935744670aebf82699c2f91aaff3cd4c3172robertphillips                width = kMaxPathHeight/5;
1927272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1937272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 4:
1947272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 6;
1957272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1967272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 5:
1977272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 8;
1987272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
1997272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 6:              // squashed octogon
2007272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 8;
2017272935744670aebf82699c2f91aaff3cd4c3172robertphillips                width = kMaxPathHeight/5;
2027272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2037272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 7:
2047272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 20;
2057272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2067272935744670aebf82699c2f91aaff3cd4c3172robertphillips            case 8:
2077272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 100;
2087272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2097272935744670aebf82699c2f91aaff3cd4c3172robertphillips            default:
2107272935744670aebf82699c2f91aaff3cd4c3172robertphillips                numPts = 3;
2117272935744670aebf82699c2f91aaff3cd4c3172robertphillips                break;
2127272935744670aebf82699c2f91aaff3cd4c3172robertphillips            }
2137272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2147272935744670aebf82699c2f91aaff3cd4c3172robertphillips            data.reset(SkNEW_ARRAY(SkPoint, numPts));
2157272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2167272935744670aebf82699c2f91aaff3cd4c3172robertphillips            create_ngon(numPts, data.get(), width, height);
2177272935744670aebf82699c2f91aaff3cd4c3172robertphillips            points = data.get();
2187272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
2197272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2207272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkPath path;
2217272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2227272935744670aebf82699c2f91aaff3cd4c3172robertphillips        if (SkPath::kCW_Direction == dir) {
2237272935744670aebf82699c2f91aaff3cd4c3172robertphillips            path.moveTo(points[0]);
2247272935744670aebf82699c2f91aaff3cd4c3172robertphillips            for (int i = 1; i < numPts; ++i) {
2257272935744670aebf82699c2f91aaff3cd4c3172robertphillips                path.lineTo(points[i]);
2267272935744670aebf82699c2f91aaff3cd4c3172robertphillips            }
2277272935744670aebf82699c2f91aaff3cd4c3172robertphillips        } else {
2287272935744670aebf82699c2f91aaff3cd4c3172robertphillips            path.moveTo(points[numPts-1]);
2297272935744670aebf82699c2f91aaff3cd4c3172robertphillips            for (int i = numPts-2; i >= 0; --i) {
2307272935744670aebf82699c2f91aaff3cd4c3172robertphillips                path.lineTo(points[i]);
2317272935744670aebf82699c2f91aaff3cd4c3172robertphillips            }
2327272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
2337272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2347272935744670aebf82699c2f91aaff3cd4c3172robertphillips        path.close();
2357272935744670aebf82699c2f91aaff3cd4c3172robertphillips#ifdef SK_DEBUG
2367272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // Each path this method returns should be convex, only composed of
2377272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // lines, wound the right direction, and short enough to fit in one
2387272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // of the GMs rows.
2397272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(path.isConvex());
2407272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(SkPath::kLine_SegmentMask == path.getSegmentMasks());
2417272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkPath::Direction actualDir;
2427272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(path.cheapComputeDirection(&actualDir));
2437272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(dir == actualDir);
2447272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkRect bounds = path.getBounds();
2457272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(SkScalarNearlyEqual(bounds.centerX(), 0.0f));
2467272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkASSERT(bounds.height() <= kMaxPathHeight);
2477272935744670aebf82699c2f91aaff3cd4c3172robertphillips#endif
2487272935744670aebf82699c2f91aaff3cd4c3172robertphillips        return path;
2497272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
2507272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2517272935744670aebf82699c2f91aaff3cd4c3172robertphillips    // Draw a single path several times, shrinking it, flipping its direction
2527272935744670aebf82699c2f91aaff3cd4c3172robertphillips    // and changing its start vertex each time.
2537272935744670aebf82699c2f91aaff3cd4c3172robertphillips    void drawPath(SkCanvas* canvas, int index) {
2547272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2557272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkPoint center;
2567272935744670aebf82699c2f91aaff3cd4c3172robertphillips        {
2577272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkPath path = GetPath(index, 0, SkPath::kCW_Direction);
2587272935744670aebf82699c2f91aaff3cd4c3172robertphillips            if (fOffset.fX+path.getBounds().width() > kGMWidth) {
2597272935744670aebf82699c2f91aaff3cd4c3172robertphillips                fOffset.fX = 0;
2607272935744670aebf82699c2f91aaff3cd4c3172robertphillips                fOffset.fY += kMaxPathHeight;
2617272935744670aebf82699c2f91aaff3cd4c3172robertphillips            }
2627272935744670aebf82699c2f91aaff3cd4c3172robertphillips            center = { fOffset.fX + SkScalarHalf(path.getBounds().width()), fOffset.fY};
2637272935744670aebf82699c2f91aaff3cd4c3172robertphillips            fOffset.fX += path.getBounds().width();
2647272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
2657272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2667272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkColor colors[2] = { SK_ColorBLACK, SK_ColorWHITE };
2677272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const SkPath::Direction dirs[2] = { SkPath::kCW_Direction, SkPath::kCCW_Direction };
2687272935744670aebf82699c2f91aaff3cd4c3172robertphillips        const float scales[] = { 1.0f, 0.75f, 0.5f, 0.25f, 0.1f, 0.01f, 0.001f };
2697272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2707272935744670aebf82699c2f91aaff3cd4c3172robertphillips        SkPaint paint;
2717272935744670aebf82699c2f91aaff3cd4c3172robertphillips        paint.setAntiAlias(true);
2727272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2737272935744670aebf82699c2f91aaff3cd4c3172robertphillips        for (size_t i = 0; i < SK_ARRAY_COUNT(scales); ++i) {
2747272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkPath path = GetPath(index, (int) i, dirs[i%2]);
2757272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2767272935744670aebf82699c2f91aaff3cd4c3172robertphillips            canvas->save();
2777272935744670aebf82699c2f91aaff3cd4c3172robertphillips                canvas->translate(center.fX, center.fY);
2787272935744670aebf82699c2f91aaff3cd4c3172robertphillips                canvas->scale(scales[i], scales[i]);
2797272935744670aebf82699c2f91aaff3cd4c3172robertphillips                paint.setColor(colors[i%2]);
2807272935744670aebf82699c2f91aaff3cd4c3172robertphillips                canvas->drawPath(path, paint);
2817272935744670aebf82699c2f91aaff3cd4c3172robertphillips            canvas->restore();
2827272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
2837272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
2847272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2857272935744670aebf82699c2f91aaff3cd4c3172robertphillips    void onDraw(SkCanvas* canvas) override {
2867272935744670aebf82699c2f91aaff3cd4c3172robertphillips        for (int i = 0; i < kNumPaths; ++i) {
2877272935744670aebf82699c2f91aaff3cd4c3172robertphillips            this->drawPath(canvas, i);
2887272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
2897272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2907272935744670aebf82699c2f91aaff3cd4c3172robertphillips        // Repro for crbug.com/472723 (Missing AA on portions of graphic with GPU rasterization)
2917272935744670aebf82699c2f91aaff3cd4c3172robertphillips        {
2927272935744670aebf82699c2f91aaff3cd4c3172robertphillips            canvas->translate(356.0f, 50.0f);
2937272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2947272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkPaint p;
2957272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p.setAntiAlias(true);
2967272935744670aebf82699c2f91aaff3cd4c3172robertphillips
2977272935744670aebf82699c2f91aaff3cd4c3172robertphillips            SkPath p1;
2987272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p1.moveTo(60.8522949f, 364.671021f);
2997272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p1.lineTo(59.4380493f, 364.671021f);
3007272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p1.lineTo(385.414276f, 690.647217f);
3017272935744670aebf82699c2f91aaff3cd4c3172robertphillips            p1.lineTo(386.121399f, 689.940125f);
3027272935744670aebf82699c2f91aaff3cd4c3172robertphillips            canvas->drawPath(p1, p);
3037272935744670aebf82699c2f91aaff3cd4c3172robertphillips        }
3047272935744670aebf82699c2f91aaff3cd4c3172robertphillips    }
3057272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3067272935744670aebf82699c2f91aaff3cd4c3172robertphillipsprivate:
3077272935744670aebf82699c2f91aaff3cd4c3172robertphillips    static const int kNumPaths      = 20;
3087272935744670aebf82699c2f91aaff3cd4c3172robertphillips    static const int kMaxPathHeight = 100;
3097272935744670aebf82699c2f91aaff3cd4c3172robertphillips    static const int kGMWidth       = 512;
3107272935744670aebf82699c2f91aaff3cd4c3172robertphillips    static const int kGMHeight      = 512;
3117272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3127272935744670aebf82699c2f91aaff3cd4c3172robertphillips    SkPoint fOffset;        // the right edge of the last drawn path
3137272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3147272935744670aebf82699c2f91aaff3cd4c3172robertphillips    typedef GM INHERITED;
3157272935744670aebf82699c2f91aaff3cd4c3172robertphillips};
3167272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3177272935744670aebf82699c2f91aaff3cd4c3172robertphillips//////////////////////////////////////////////////////////////////////////////
3187272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3197272935744670aebf82699c2f91aaff3cd4c3172robertphillipsDEF_GM( return SkNEW(ConvexLineOnlyPathsGM); )
3207272935744670aebf82699c2f91aaff3cd4c3172robertphillips
3217272935744670aebf82699c2f91aaff3cd4c3172robertphillips}
322