GrAAConvexPathRenderer.cpp revision 94b284d719ee5ccd3e2efbd1d7084ec554583bac
169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com/*
369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * Copyright 2012 Google Inc.
469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com *
569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * found in the LICENSE file.
769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com */
869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrAAConvexPathRenderer.h"
1069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
1169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrContext.h"
1269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrDrawState.h"
13c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h"
1490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "GrEffect.h"
1569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrPathUtils.h"
1690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "GrTBackendEffectFactory.h"
1769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkString.h"
185f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h"
1969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkTrace.h"
2069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
2190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLEffect.h"
2290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLSL.h"
234647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com
2469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comGrAAConvexPathRenderer::GrAAConvexPathRenderer() {
2569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
2669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
2769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comnamespace {
2869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
2969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct Segment {
3069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    enum {
319b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        // These enum values are assumed in member functions below.
329b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        kLine = 0,
339b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        kQuad = 1,
3469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    } fType;
359b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com
369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // line uses one pt, quad uses 2 pts
379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    GrPoint fPts[2];
389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // normal to edge ending at each pt
399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    GrVec fNorms[2];
409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // is the corner where the previous segment meets this segment
419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // sharp. If so, fMid is a normalized bisector facing outward.
429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    GrVec fMid;
439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int countPoints() {
459b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
469b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fType + 1;
479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    const SkPoint& endPt() const {
499b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
509b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fPts[fType];
519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    };
529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    const SkPoint& endNorm() const {
539b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
549b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fNorms[fType];
559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    };
5669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com};
5769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
5869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comtypedef SkTArray<Segment, true> SegmentArray;
5969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.comvoid center_of_mass(const SegmentArray& segments, SkPoint* c) {
6181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar area = 0;
626390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org    SkPoint center = {0, 0};
639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments.count();
646390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org    SkPoint p0 = {0, 0};
655b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com    if (count > 2) {
665b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // We translate the polygon so that the first point is at the origin.
675b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // This avoids some precision issues with small area polygons far away
685b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // from the origin.
695b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        p0 = segments[0].endPt();
705b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        SkPoint pi;
715b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        SkPoint pj;
72a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        // the first and last iteration of the below loop would compute
735b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // zeros since the starting / ending point is (0,0). So instead we start
745b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // at i=1 and make the last iteration i=count-2.
755b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        pj = segments[1].endPt() - p0;
765b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        for (int i = 1; i < count - 1; ++i) {
775b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            pi = pj;
785b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            const SkPoint pj = segments[i + 1].endPt() - p0;
795b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com
8081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY);
815b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            area += t;
825b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            center.fX += (pi.fX + pj.fX) * t;
835b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            center.fY += (pi.fY + pj.fY) * t;
845b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com
855b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        }
869aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
87278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // If the poly has no area then we instead return the average of
88278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // its points.
895b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com    if (SkScalarNearlyZero(area)) {
90278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        SkPoint avg;
91278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        avg.set(0, 0);
92278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        for (int i = 0; i < count; ++i) {
93278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            const SkPoint& pt = segments[i].endPt();
94278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            avg.fX += pt.fX;
95278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            avg.fY += pt.fY;
96278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        }
97278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        SkScalar denom = SK_Scalar1 / count;
98278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        avg.scale(denom);
99278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        *c = avg;
100278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    } else {
101278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        area *= 3;
10281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        area = SkScalarDiv(SK_Scalar1, area);
10381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        center.fX = SkScalarMul(center.fX, area);
10481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        center.fY = SkScalarMul(center.fY, area);
1055b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // undo the translate of p0 to the origin.
1065b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        *c = center + p0;
107278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    }
108278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    GrAssert(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY));
1099aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com}
1109aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1119aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.comvoid compute_vectors(SegmentArray* segments,
112278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com                     SkPoint* fanPt,
113278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com                     SkPath::Direction dir,
1149aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                     int* vCount,
1159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                     int* iCount) {
1169aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    center_of_mass(*segments, fanPt);
1179aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments->count();
1189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
119278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // Make the normals point towards the outside
1209aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    GrPoint::Side normSide;
121278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    if (dir == SkPath::kCCW_Direction) {
122278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        normSide = GrPoint::kRight_Side;
123278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    } else {
124278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        normSide = GrPoint::kLeft_Side;
125278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    }
1269aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    *vCount = 0;
1289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    *iCount = 0;
1299aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // compute normals at all points
1309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
1319aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& sega = (*segments)[a];
1329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
1339aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        Segment& segb = (*segments)[b];
1349aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const GrPoint* prevPt = &sega.endPt();
1369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int n = segb.countPoints();
1379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        for (int p = 0; p < n; ++p) {
1389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p] = segb.fPts[p] - *prevPt;
1399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p].normalize();
1409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p].setOrthog(segb.fNorms[p], normSide);
1419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            prevPt = &segb.fPts[p];
1429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        }
1439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        if (Segment::kLine == segb.fType) {
1449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *vCount += 5;
1459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *iCount += 9;
1469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        } else {
1479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *vCount += 6;
1489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *iCount += 12;
1499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        }
1509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
1519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // compute mid-vectors where segments meet. TODO: Detect shallow corners
1539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // and leave out the wedges and close gaps by stitching segments together.
1549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
1559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& sega = (*segments)[a];
1569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
1579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        Segment& segb = (*segments)[b];
1589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        segb.fMid = segb.fNorms[0] + sega.endNorm();
1599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        segb.fMid.normalize();
1609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        // corner wedges
1619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        *vCount += 4;
1629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        *iCount += 6;
1639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
1649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com}
1659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1669732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.comstruct DegenerateTestData {
1679732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    DegenerateTestData() { fStage = kInitial; }
1689732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    bool isDegenerate() const { return kNonDegenerate != fStage; }
1699732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    enum {
1709732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kInitial,
1719732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kPoint,
1729732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kLine,
1739732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kNonDegenerate
1749732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    }           fStage;
1759732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    GrPoint     fFirstPoint;
1769732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    GrVec       fLineNormal;
17781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar    fLineC;
1789732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com};
1799732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
1809732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.comvoid update_degenerate_test(DegenerateTestData* data, const GrPoint& pt) {
1819732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    static const SkScalar TOL = (SK_Scalar1 / 16);
1829732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    static const SkScalar TOL_SQD = SkScalarMul(TOL, TOL);
1839732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
1849732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    switch (data->fStage) {
1859732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kInitial:
1869732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            data->fFirstPoint = pt;
1879732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            data->fStage = DegenerateTestData::kPoint;
1889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
1899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kPoint:
1909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            if (pt.distanceToSqd(data->fFirstPoint) > TOL_SQD) {
1919732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal = pt - data->fFirstPoint;
1929732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal.normalize();
1939732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal.setOrthog(data->fLineNormal);
1949732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineC = -data->fLineNormal.dot(data->fFirstPoint);
1959732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fStage = DegenerateTestData::kLine;
1969732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            }
1979732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
1989732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kLine:
1999732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > TOL) {
2009732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fStage = DegenerateTestData::kNonDegenerate;
2019732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            }
2029732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kNonDegenerate:
2039732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
2049732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        default:
2059732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            GrCrash("Unexpected degenerate test stage.");
2069732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    }
2079732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com}
2089732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
209b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.cominline bool get_direction(const SkPath& path, const SkMatrix& m, SkPath::Direction* dir) {
210a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    if (!path.cheapComputeDirection(dir)) {
211a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        return false;
212a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    }
213af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // check whether m reverses the orientation
214af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    GrAssert(!m.hasPerspective());
21581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar det2x2 = SkScalarMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) -
21681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com                      SkScalarMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY));
217af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    if (det2x2 < 0) {
21830c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        *dir = SkPath::OppositeDirection(*dir);
219af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    }
220a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    return true;
221af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com}
222af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
2238d033a1b125886c62906d975b5cc28a382064526bsalomon@google.combool get_segments(const SkPath& path,
224b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                  const SkMatrix& m,
225af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com                  SegmentArray* segments,
226af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com                  SkPoint* fanPt,
227af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com                  int* vCount,
228af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com                  int* iCount) {
22969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    SkPath::Iter iter(path, true);
23030c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    // This renderer over-emphasizes very thin path regions. We use the distance
2315cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // to the path from the sample to compute coverage. Every pixel intersected
2325cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // by the path will be hit and the maximum distance is sqrt(2)/2. We don't
233fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // notice that the sample may be close to a very thin area of the path and
2345cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // thus should be very light. This is particularly egregious for degenerate
2355cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // line paths. We detect paths that are very close to a line (zero area) and
2365cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // draw nothing.
2379732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    DegenerateTestData degenerateData;
238a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    SkPath::Direction dir;
239a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    // get_direction can fail for some degenerate paths.
240a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    if (!get_direction(path, m, &dir)) {
241a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        return false;
242a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    }
2439732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
24469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    for (;;) {
24569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        GrPoint pts[4];
24694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com        SkPath::Verb verb = iter.next(pts);
24794b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com        switch (verb) {
24894b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kMove_Verb:
2491a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                m.mapPoints(pts, 1);
2509732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[0]);
2519732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                break;
25294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kLine_Verb: {
253af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com                m.mapPoints(pts + 1, 1);
2541a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
25569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                segments->push_back();
25669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                segments->back().fType = Segment::kLine;
2579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                segments->back().fPts[0] = pts[1];
25869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
25969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            }
26094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kQuad_Verb:
2611a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                m.mapPoints(pts + 1, 2);
2629732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
2639732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[2]);
26469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                segments->push_back();
26569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                segments->back().fType = Segment::kQuad;
2669aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                segments->back().fPts[0] = pts[1];
2679aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                segments->back().fPts[1] = pts[2];
26869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
26994b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kCubic_Verb: {
2701a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                m.mapPoints(pts, 4);
2719732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
2729732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[2]);
2739732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[3]);
274af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com                // unlike quads and lines, the pts[0] will also be read (in
275af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com                // convertCubicToQuads).
27669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                SkSTArray<15, SkPoint, true> quads;
277a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com                GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads);
27869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                int count = quads.count();
27969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                for (int q = 0; q < count; q += 3) {
28069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                    segments->push_back();
28169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                    segments->back().fType = Segment::kQuad;
2829aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                    segments->back().fPts[0] = quads[q + 1];
2839aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                    segments->back().fPts[1] = quads[q + 2];
28469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                }
28569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
28669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            };
28794b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kDone_Verb:
2889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                if (degenerateData.isDegenerate()) {
2899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                    return false;
2909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                } else {
291278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com                    compute_vectors(segments, fanPt, dir, vCount, iCount);
2929732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                    return true;
2939732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                }
29469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            default:
29569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
29669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        }
29769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
29869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
29969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
30069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct QuadVertex {
30169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    GrPoint  fPos;
3029aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    GrPoint  fUV;
30381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar fD0;
30481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar fD1;
30569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com};
306fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3079aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.comvoid create_vertices(const SegmentArray&  segments,
3089aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                     const SkPoint& fanPt,
3099aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                     QuadVertex*    verts,
3109aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                     uint16_t*      idxs) {
31169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    int v = 0;
31269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    int i = 0;
31369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
3149aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments.count();
3159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
3169aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& sega = segments[a];
3179aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
3189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& segb = segments[b];
319fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3209aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        // FIXME: These tris are inset in the 1 unit arc around the corner
3219aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 0].fPos = sega.endPt();
3229aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 1].fPos = verts[v + 0].fPos + sega.endNorm();
3239aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 2].fPos = verts[v + 0].fPos + segb.fMid;
3249aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 3].fPos = verts[v + 0].fPos + segb.fNorms[0];
3259aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 0].fUV.set(0,0);
3269aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 1].fUV.set(0,-SK_Scalar1);
3279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 2].fUV.set(0,-SK_Scalar1);
3289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 3].fUV.set(0,-SK_Scalar1);
3299aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 0].fD0 = verts[v + 0].fD1 = -SK_Scalar1;
3309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 1].fD0 = verts[v + 1].fD1 = -SK_Scalar1;
3319aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 2].fD0 = verts[v + 2].fD1 = -SK_Scalar1;
3329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        verts[v + 3].fD0 = verts[v + 3].fD1 = -SK_Scalar1;
333fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
33469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        idxs[i + 0] = v + 0;
3359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        idxs[i + 1] = v + 2;
3369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        idxs[i + 2] = v + 1;
33769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        idxs[i + 3] = v + 0;
3389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        idxs[i + 4] = v + 3;
3399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        idxs[i + 5] = v + 2;
340fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
34169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        v += 4;
34269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        i += 6;
34369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
3449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        if (Segment::kLine == segb.fType) {
34569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            verts[v + 0].fPos = fanPt;
3469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 1].fPos = sega.endPt();
3479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 2].fPos = segb.fPts[0];
3489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
3499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 3].fPos = verts[v + 1].fPos + segb.fNorms[0];
3509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 4].fPos = verts[v + 2].fPos + segb.fNorms[0];
3519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
3529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            // we draw the line edge as a degenerate quad (u is 0, v is the
3539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            // signed distance to the edge)
35481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            SkScalar dist = fanPt.distanceToLineBetween(verts[v + 1].fPos,
3559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com                                                        verts[v + 2].fPos);
3569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 0].fUV.set(0, dist);
3579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 1].fUV.set(0, 0);
3589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 2].fUV.set(0, 0);
3599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 3].fUV.set(0, -SK_Scalar1);
3609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 4].fUV.set(0, -SK_Scalar1);
3619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
3629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 0].fD0 = verts[v + 0].fD1 = -SK_Scalar1;
3639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 1].fD0 = verts[v + 1].fD1 = -SK_Scalar1;
3649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 2].fD0 = verts[v + 2].fD1 = -SK_Scalar1;
3659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 3].fD0 = verts[v + 3].fD1 = -SK_Scalar1;
3669aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 4].fD0 = verts[v + 4].fD1 = -SK_Scalar1;
36769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
36869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            idxs[i + 0] = v + 0;
3699aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 1] = v + 2;
3709aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 2] = v + 1;
3719aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
3729aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 3] = v + 3;
3739aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 4] = v + 1;
3749aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 5] = v + 2;
3759aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
3769aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 6] = v + 4;
3779aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 7] = v + 3;
378068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com            idxs[i + 8] = v + 2;
379495e210eb1b66d8a8fc3f46ca1def3c78c724a38bsalomon@google.com
380068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com            v += 5;
3819aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            i += 9;
382068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com        } else {
3839aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            GrPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]};
3849aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
3859aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            GrVec midVec = segb.fNorms[0] + segb.fNorms[1];
3869aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            midVec.normalize();
3879aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
3889aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 0].fPos = fanPt;
3899aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 1].fPos = qpts[0];
3909aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 2].fPos = qpts[2];
3919aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 3].fPos = qpts[0] + segb.fNorms[0];
3929aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 4].fPos = qpts[2] + segb.fNorms[1];
3939aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 5].fPos = qpts[1] + midVec;
3949aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
39581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            SkScalar c = segb.fNorms[0].dot(qpts[0]);
3969aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 0].fD0 =  -segb.fNorms[0].dot(fanPt) + c;
3979aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 1].fD0 =  0.f;
3989aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 2].fD0 =  -segb.fNorms[0].dot(qpts[2]) + c;
39981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            verts[v + 3].fD0 = -SK_ScalarMax/100;
40081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            verts[v + 4].fD0 = -SK_ScalarMax/100;
40181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            verts[v + 5].fD0 = -SK_ScalarMax/100;
4029aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4039aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            c = segb.fNorms[1].dot(qpts[2]);
4049aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 0].fD1 =  -segb.fNorms[1].dot(fanPt) + c;
4059aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 1].fD1 =  -segb.fNorms[1].dot(qpts[0]) + c;
4069aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            verts[v + 2].fD1 =  0.f;
40781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            verts[v + 3].fD1 = -SK_ScalarMax/100;
40881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            verts[v + 4].fD1 = -SK_ScalarMax/100;
40981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            verts[v + 5].fD1 = -SK_ScalarMax/100;
4109aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4111971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            GrPathUtils::QuadUVMatrix toUV(qpts);
4121971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            toUV.apply<6, sizeof(QuadVertex), sizeof(GrPoint)>(verts + v);
4139aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4149aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 0] = v + 3;
4159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 1] = v + 1;
4169aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 2] = v + 2;
4179aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 3] = v + 4;
4189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 4] = v + 3;
4199aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 5] = v + 2;
4209aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4219aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 6] = v + 5;
4229aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 7] = v + 3;
4239aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 8] = v + 4;
4249aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4259aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i +  9] = v + 0;
4269aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 10] = v + 2;
4279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            idxs[i + 11] = v + 1;
4289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4299aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            v += 6;
4309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            i += 12;
43169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        }
43269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
43369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
43469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
43569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
43669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
43790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
43890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
43990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/*
44090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
44190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * two components of the vertex attribute. Coverage is based on signed
44290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * distance with negative being inside, positive outside. The edge is specified in
44390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * window space (y-down). If either the third or fourth component of the interpolated
44490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * vertex coord is > 0 then the pixel is considered outside the edge. This is used to
445041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * attempt to trim to a portion of the infinite quad.
446041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Requires shader derivative instruction support.
44790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */
44890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
44990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgclass QuadEdgeEffect : public GrEffect {
45090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic:
45190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
45290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    static GrEffectRef* Create() {
453d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com        GR_CREATE_STATIC_EFFECT(gQuadEdgeEffect, QuadEdgeEffect, ());
454d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com        gQuadEdgeEffect->ref();
455d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com        return gQuadEdgeEffect;
45690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
45790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
45890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    virtual ~QuadEdgeEffect() {}
45990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
46090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    static const char* Name() { return "QuadEdge"; }
46190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
462041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com    virtual void getConstantColorComponents(GrColor* color,
46390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                            uint32_t* validFlags) const SK_OVERRIDE {
46490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        *validFlags = 0;
46590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
46690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
46790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
46890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        return GrTBackendEffectFactory<QuadEdgeEffect>::getInstance();
46990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
47090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
47190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    class GLEffect : public GrGLEffect {
47290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    public:
47390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
47490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            : INHERITED (factory) {}
47590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
47690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        virtual void emitCode(GrGLShaderBuilder* builder,
47790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                              const GrDrawEffect& drawEffect,
47890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                              EffectKey key,
47990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                              const char* outputColor,
48090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                              const char* inputColor,
48190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                              const TextureSamplerArray& samplers) SK_OVERRIDE {
48290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            const char *vsName, *fsName;
48390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            const SkString* attrName =
48490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
48590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
48690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
48790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            SkAssertResult(builder->enableFeature(
48890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                              GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
48990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName);
49090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
49190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            // keep the derivative instructions outside the conditional
49290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
49390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
49490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
49590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            // today we know z and w are in device space. We could use derivatives
49690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName,
49790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                    fsName);
49890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf ("\t\t} else {\n");
49990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
50090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                   "\t\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
50190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                   fsName, fsName);
50290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
50390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                    fsName);
50490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t\t\tedgeAlpha = "
50590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                   "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n\t\t}\n");
50690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
50790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            SkString modulate;
508018f179efb2413431bdb1a9e6701eb44ef36b792bsalomon@google.com            GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
50990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
51090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
51190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
51290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        }
51390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
51490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
51590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            return 0x0;
51690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        }
51790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
51890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
51990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
52090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    private:
52190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        typedef GrGLEffect INHERITED;
52290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    };
523041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com
52490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate:
525041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com    QuadEdgeEffect() {
526041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com        this->addVertexAttrib(kVec4f_GrSLType);
52790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
52890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
52990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
53090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        return true;
53190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
53290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
53390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    GR_DECLARE_EFFECT_TEST;
53490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
53590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    typedef GrEffect INHERITED;
53690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org};
53790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
53890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(QuadEdgeEffect);
53990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
54090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGrEffectRef* QuadEdgeEffect::TestCreate(SkMWCRandom* random,
54190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                        GrContext*,
54290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                        const GrDrawTargetCaps& caps,
54390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org                                        GrTexture*[]) {
54490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    // Doesn't work without derivative instructions.
54590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    return caps.shaderDerivativeSupport() ? QuadEdgeEffect::Create() : NULL;
54690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}
54790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
54890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
54990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
5508a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool GrAAConvexPathRenderer::canDrawPath(const SkPath& path,
5515f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com                                         const SkStrokeRec& stroke,
5528a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com                                         const GrDrawTarget* target,
5538a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com                                         bool antiAlias) const {
554bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com    return (target->caps()->shaderDerivativeSupport() && antiAlias &&
5555f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com            stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
556c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com}
557c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com
558429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace {
559429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
560429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com// position + edge
561429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gPathAttribs[] = {
562429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
563429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
564429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
565429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
566429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
567429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
568c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.combool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
5695f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com                                        const SkStrokeRec&,
570c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                        GrDrawTarget* target,
571c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                        bool antiAlias) {
572c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com
573af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    const SkPath* path = &origPath;
574af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    if (path->isEmpty()) {
575c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com        return true;
57669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
5774647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com
5784647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com    GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
579c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com    GrDrawState* drawState = target->drawState();
58069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
581a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com    GrDrawState::AutoDeviceCoordDraw adcd(drawState);
582a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com    if (!adcd.succeeded()) {
583e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return false;
58469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
585b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    const SkMatrix* vm = &adcd.getOriginalMatrix();
58669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
587af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // We use the fact that SkPath::transform path does subdivision based on
588af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // perspective. Otherwise, we apply the view matrix when copying to the
589af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // segment representation.
590af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    SkPath tmpPath;
591a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com    if (vm->hasPerspective()) {
592a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        origPath.transform(*vm, &tmpPath);
593af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com        path = &tmpPath;
594b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        vm = &SkMatrix::I();
595af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    }
596af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
59769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    QuadVertex *verts;
59869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    uint16_t* idxs;
59969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
6009aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int vCount;
6019aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int iCount;
60268a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com    enum {
60368a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com        kPreallocSegmentCnt = 512 / sizeof(Segment),
60468a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com    };
60568a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com    SkSTArray<kPreallocSegmentCnt, Segment, true> segments;
6069aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    SkPoint fanPt;
607af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
608a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com    if (!get_segments(*path, *vm, &segments, &fanPt, &vCount, &iCount)) {
609c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com        return false;
61069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
61169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
612429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    drawState->setVertexAttribs<gPathAttribs>(SK_ARRAY_COUNT(gPathAttribs));
6134647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com
6144647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com    enum {
6154647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com        // the edge effects share this stage with glyph rendering
6164647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com        // (kGlyphMaskStage in GrTextContext) && SW path rendering
6174647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com        // (kPathMaskStage in GrSWMaskHelper)
6184647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com        kEdgeEffectStage = GrPaint::kTotalStages,
6194647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com    };
6204647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com    static const int kEdgeAttrIndex = 1;
62190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    GrEffectRef* quadEffect = QuadEdgeEffect::Create();
6224647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com    drawState->setEffect(kEdgeEffectStage, quadEffect, kEdgeAttrIndex)->unref();
6234647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com
624b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com    GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount);
625b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com    if (!arg.succeeded()) {
626c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com        return false;
62769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
6289b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    GrAssert(sizeof(QuadVertex) == drawState->getVertexSize());
629b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com    verts = reinterpret_cast<QuadVertex*>(arg.vertices());
630b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com    idxs = reinterpret_cast<uint16_t*>(arg.indices());
63169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
6329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    create_vertices(segments, fanPt, verts, idxs);
63369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
63447059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com    target->drawIndexed(kTriangles_GrPrimitiveType,
635c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                        0,        // start vertex
636c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                        0,        // start index
637c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                        vCount,
638c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                        iCount);
639a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com
640c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com    return true;
64169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
642