GrAAConvexPathRenderer.cpp revision 71c9260e6fa1798ad1e41b2c2ae9b3cce08bb610
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"
14eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrGeometryProcessor.h"
15605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h"
16b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessor.h"
1769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrPathUtils.h"
18af18a09d13611526c4217656c98947f9067cb07aegdaniel#include "SkGeometry.h"
1969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkString.h"
205f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h"
21933e65d914eb86b1fbbf8ea9cf1da58ac7c42500commit-bot@chromium.org#include "SkTraceEvent.h"
22b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
2390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLSL.h"
24249af15fb82833d2274850c589812b6e69df0033joshualitt#include "gl/GrGLGeometryProcessor.h"
25eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "gl/builders/GrGLProgramBuilder.h"
26234d4fba75aac009e34c088037fcd9e244798c40commit-bot@chromium.org
2769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comGrAAConvexPathRenderer::GrAAConvexPathRenderer() {
2869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
2969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
3069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct Segment {
3169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    enum {
329b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        // These enum values are assumed in member functions below.
339b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        kLine = 0,
349b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        kQuad = 1,
3569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    } fType;
369b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com
379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // line uses one pt, quad uses 2 pts
38972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint fPts[2];
399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // normal to edge ending at each pt
40972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkVector fNorms[2];
419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // is the corner where the previous segment meets this segment
429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // sharp. If so, fMid is a normalized bisector facing outward.
43972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkVector fMid;
449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int countPoints() {
469b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
479b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fType + 1;
489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    const SkPoint& endPt() const {
509b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
519b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fPts[fType];
529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    };
539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    const SkPoint& endNorm() const {
549b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
559b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fNorms[fType];
569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    };
5769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com};
5869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
5969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comtypedef SkTArray<Segment, true> SegmentArray;
6069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
61fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void center_of_mass(const SegmentArray& segments, SkPoint* c) {
6281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar area = 0;
636390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org    SkPoint center = {0, 0};
649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments.count();
656390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org    SkPoint p0 = {0, 0};
665b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com    if (count > 2) {
675b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // We translate the polygon so that the first point is at the origin.
685b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // This avoids some precision issues with small area polygons far away
695b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // from the origin.
705b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        p0 = segments[0].endPt();
715b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        SkPoint pi;
725b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        SkPoint pj;
73a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        // the first and last iteration of the below loop would compute
745b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // zeros since the starting / ending point is (0,0). So instead we start
755b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // at i=1 and make the last iteration i=count-2.
765b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        pj = segments[1].endPt() - p0;
775b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        for (int i = 1; i < count - 1; ++i) {
785b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            pi = pj;
795b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            const SkPoint pj = segments[i + 1].endPt() - p0;
805b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com
8181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY);
825b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            area += t;
835b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            center.fX += (pi.fX + pj.fX) * t;
845b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            center.fY += (pi.fY + pj.fY) * t;
855b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com
865b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        }
879aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
88278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // If the poly has no area then we instead return the average of
89278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // its points.
905b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com    if (SkScalarNearlyZero(area)) {
91278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        SkPoint avg;
92278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        avg.set(0, 0);
93278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        for (int i = 0; i < count; ++i) {
94278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            const SkPoint& pt = segments[i].endPt();
95278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            avg.fX += pt.fX;
96278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            avg.fY += pt.fY;
97278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        }
98278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        SkScalar denom = SK_Scalar1 / count;
99278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        avg.scale(denom);
100278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        *c = avg;
101278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    } else {
102278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        area *= 3;
10381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        area = SkScalarDiv(SK_Scalar1, area);
10481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        center.fX = SkScalarMul(center.fX, area);
10581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        center.fY = SkScalarMul(center.fY, area);
1065b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // undo the translate of p0 to the origin.
1075b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        *c = center + p0;
108278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    }
109f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY));
1109aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com}
1119aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
112fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void compute_vectors(SegmentArray* segments,
113fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            SkPoint* fanPt,
114fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            SkPath::Direction dir,
115fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            int* vCount,
116fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            int* iCount) {
1179aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    center_of_mass(*segments, fanPt);
1189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments->count();
1199aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
120278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // Make the normals point towards the outside
121972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint::Side normSide;
122278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    if (dir == SkPath::kCCW_Direction) {
123972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        normSide = SkPoint::kRight_Side;
124278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    } else {
125972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        normSide = SkPoint::kLeft_Side;
126278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    }
1279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    *vCount = 0;
1299aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    *iCount = 0;
1309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // compute normals at all points
1319aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
1327d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        Segment& sega = (*segments)[a];
1339aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
1349aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        Segment& segb = (*segments)[b];
1359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
136972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        const SkPoint* prevPt = &sega.endPt();
1379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int n = segb.countPoints();
1389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        for (int p = 0; p < n; ++p) {
1399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p] = segb.fPts[p] - *prevPt;
1409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p].normalize();
1419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p].setOrthog(segb.fNorms[p], normSide);
1429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            prevPt = &segb.fPts[p];
1439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        }
1449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        if (Segment::kLine == segb.fType) {
1459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *vCount += 5;
1469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *iCount += 9;
1479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        } else {
1489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *vCount += 6;
1499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *iCount += 12;
1509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        }
1519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
1529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // compute mid-vectors where segments meet. TODO: Detect shallow corners
1549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // and leave out the wedges and close gaps by stitching segments together.
1559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
1569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& sega = (*segments)[a];
1579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
1589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        Segment& segb = (*segments)[b];
1599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        segb.fMid = segb.fNorms[0] + sega.endNorm();
1609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        segb.fMid.normalize();
1619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        // corner wedges
1629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        *vCount += 4;
1639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        *iCount += 6;
1649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
1659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com}
1669aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1679732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.comstruct DegenerateTestData {
1689732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    DegenerateTestData() { fStage = kInitial; }
1699732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    bool isDegenerate() const { return kNonDegenerate != fStage; }
1709732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    enum {
1719732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kInitial,
1729732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kPoint,
1739732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kLine,
1749732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kNonDegenerate
1759732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    }           fStage;
176972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint     fFirstPoint;
177972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkVector    fLineNormal;
17881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar    fLineC;
1799732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com};
1809732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
181fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic const SkScalar kClose = (SK_Scalar1 / 16);
182fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic const SkScalar kCloseSqd = SkScalarMul(kClose, kClose);
1839732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
184972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orgstatic void update_degenerate_test(DegenerateTestData* data, const SkPoint& pt) {
1859732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    switch (data->fStage) {
1869732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kInitial:
1879732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            data->fFirstPoint = pt;
1889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            data->fStage = DegenerateTestData::kPoint;
1899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
1909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kPoint:
191fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org            if (pt.distanceToSqd(data->fFirstPoint) > kCloseSqd) {
1929732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal = pt - data->fFirstPoint;
1939732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal.normalize();
1949732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal.setOrthog(data->fLineNormal);
1959732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineC = -data->fLineNormal.dot(data->fFirstPoint);
1969732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fStage = DegenerateTestData::kLine;
1979732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            }
1989732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
1999732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kLine:
200fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org            if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > kClose) {
2019732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fStage = DegenerateTestData::kNonDegenerate;
2029732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            }
2039732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kNonDegenerate:
2049732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
2059732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        default:
20688cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org            SkFAIL("Unexpected degenerate test stage.");
2079732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    }
2089732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com}
2099732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
210fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline bool get_direction(const SkPath& path, const SkMatrix& m, SkPath::Direction* dir) {
211a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    if (!path.cheapComputeDirection(dir)) {
212a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        return false;
213a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    }
214af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // check whether m reverses the orientation
215f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(!m.hasPerspective());
21681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar det2x2 = SkScalarMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) -
21781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com                      SkScalarMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY));
218af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    if (det2x2 < 0) {
21930c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        *dir = SkPath::OppositeDirection(*dir);
220af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    }
221a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    return true;
222af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com}
223af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
224106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.orgstatic inline void add_line_to_segment(const SkPoint& pt,
225106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                                       SegmentArray* segments,
226106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                                       SkRect* devBounds) {
227fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    segments->push_back();
228fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    segments->back().fType = Segment::kLine;
229fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    segments->back().fPts[0] = pt;
230106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org    devBounds->growToInclude(pt.fX, pt.fY);
231fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org}
232fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org
2334b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#ifdef SK_DEBUG
234106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.orgstatic inline bool contains_inclusive(const SkRect& rect, const SkPoint& p) {
235106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org    return p.fX >= rect.fLeft && p.fX <= rect.fRight && p.fY >= rect.fTop && p.fY <= rect.fBottom;
236106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org}
2374b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#endif
2384b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org
239106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.orgstatic inline void add_quad_segment(const SkPoint pts[3],
240106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                                    SegmentArray* segments,
241106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                                    SkRect* devBounds) {
242fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    if (pts[0].distanceToSqd(pts[1]) < kCloseSqd || pts[1].distanceToSqd(pts[2]) < kCloseSqd) {
243fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        if (pts[0] != pts[2]) {
244106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org            add_line_to_segment(pts[2], segments, devBounds);
245fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        }
246fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    } else {
247fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        segments->push_back();
248fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        segments->back().fType = Segment::kQuad;
249fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        segments->back().fPts[0] = pts[1];
250fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        segments->back().fPts[1] = pts[2];
251106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org        SkASSERT(contains_inclusive(*devBounds, pts[0]));
252106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org        devBounds->growToInclude(pts + 1, 2);
253fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    }
254fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org}
255fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org
256fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline void add_cubic_segments(const SkPoint pts[4],
257fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                                      SkPath::Direction dir,
258106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                                      SegmentArray* segments,
259106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                                      SkRect* devBounds) {
260fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    SkSTArray<15, SkPoint, true> quads;
261fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads);
262fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    int count = quads.count();
263fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    for (int q = 0; q < count; q += 3) {
264106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org        add_quad_segment(&quads[q], segments, devBounds);
265fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    }
266fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org}
267fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org
268fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic bool get_segments(const SkPath& path,
269fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                         const SkMatrix& m,
270fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                         SegmentArray* segments,
271fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                         SkPoint* fanPt,
272fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                         int* vCount,
273106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                         int* iCount,
274106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                         SkRect* devBounds) {
27569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    SkPath::Iter iter(path, true);
27630c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    // This renderer over-emphasizes very thin path regions. We use the distance
2775cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // to the path from the sample to compute coverage. Every pixel intersected
2785cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // by the path will be hit and the maximum distance is sqrt(2)/2. We don't
279fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // notice that the sample may be close to a very thin area of the path and
2805cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // thus should be very light. This is particularly egregious for degenerate
2815cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // line paths. We detect paths that are very close to a line (zero area) and
2825cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // draw nothing.
2839732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    DegenerateTestData degenerateData;
284a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    SkPath::Direction dir;
285a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    // get_direction can fail for some degenerate paths.
286a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    if (!get_direction(path, m, &dir)) {
287a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        return false;
288a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    }
2899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
29069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    for (;;) {
291972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        SkPoint pts[4];
29294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com        SkPath::Verb verb = iter.next(pts);
29394b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com        switch (verb) {
29494b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kMove_Verb:
2951a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                m.mapPoints(pts, 1);
2969732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[0]);
297106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                devBounds->set(pts->fX, pts->fY, pts->fX, pts->fY);
2989732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                break;
29994b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kLine_Verb: {
300fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                m.mapPoints(&pts[1], 1);
3011a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
302106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                add_line_to_segment(pts[1], segments, devBounds);
30369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
30469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            }
30594b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kQuad_Verb:
306fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                m.mapPoints(pts, 3);
3079732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
3089732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[2]);
309106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                add_quad_segment(pts, segments, devBounds);
31069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
311af18a09d13611526c4217656c98947f9067cb07aegdaniel            case SkPath::kConic_Verb: {
312af18a09d13611526c4217656c98947f9067cb07aegdaniel                m.mapPoints(pts, 3);
313af18a09d13611526c4217656c98947f9067cb07aegdaniel                SkScalar weight = iter.conicWeight();
314af18a09d13611526c4217656c98947f9067cb07aegdaniel                SkAutoConicToQuads converter;
315af18a09d13611526c4217656c98947f9067cb07aegdaniel                const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.5f);
316af18a09d13611526c4217656c98947f9067cb07aegdaniel                for (int i = 0; i < converter.countQuads(); ++i) {
317af18a09d13611526c4217656c98947f9067cb07aegdaniel                    update_degenerate_test(&degenerateData, quadPts[2*i + 1]);
318af18a09d13611526c4217656c98947f9067cb07aegdaniel                    update_degenerate_test(&degenerateData, quadPts[2*i + 2]);
319af18a09d13611526c4217656c98947f9067cb07aegdaniel                    add_quad_segment(quadPts + 2*i, segments, devBounds);
320af18a09d13611526c4217656c98947f9067cb07aegdaniel                }
321af18a09d13611526c4217656c98947f9067cb07aegdaniel                break;
322af18a09d13611526c4217656c98947f9067cb07aegdaniel            }
32394b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kCubic_Verb: {
3241a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                m.mapPoints(pts, 4);
3259732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
3269732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[2]);
3279732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[3]);
328106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org                add_cubic_segments(pts, dir, segments, devBounds);
32969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
33069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            };
33194b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kDone_Verb:
3329732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                if (degenerateData.isDegenerate()) {
3339732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                    return false;
3349732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                } else {
335278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com                    compute_vectors(segments, fanPt, dir, vCount, iCount);
3369732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                    return true;
3379732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                }
33869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            default:
33969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
34069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        }
34169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
34269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
34369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
34469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct QuadVertex {
345972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint  fPos;
346972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint  fUV;
34781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar fD0;
34881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar fD1;
34969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com};
350fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3517d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.comstruct Draw {
3527d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    Draw() : fVertexCnt(0), fIndexCnt(0) {}
3537d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int fVertexCnt;
3547d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int fIndexCnt;
3557d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com};
3567d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
3577d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.comtypedef SkTArray<Draw, true> DrawArray;
3587d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
359fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void create_vertices(const SegmentArray&  segments,
360fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            const SkPoint& fanPt,
361fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            DrawArray*     draws,
362fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            QuadVertex*    verts,
363fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            uint16_t*      idxs) {
3647d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    Draw* draw = &draws->push_back();
3657d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    // alias just to make vert/index assignments easier to read.
3667d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int* v = &draw->fVertexCnt;
3677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int* i = &draw->fIndexCnt;
36869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
3699aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments.count();
3709aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
3719aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& sega = segments[a];
3729aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
3739aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& segb = segments[b];
374fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3757d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        // Check whether adding the verts for this segment to the current draw would cause index
3767d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        // values to overflow.
3777d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        int vCount = 4;
3787d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        if (Segment::kLine == segb.fType) {
3797d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            vCount += 5;
3807d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        } else {
3817d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            vCount += 6;
3827d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        }
3837d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        if (draw->fVertexCnt + vCount > (1 << 16)) {
3847d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts += *v;
3857d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs += *i;
3867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            draw = &draws->push_back();
3877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            v = &draw->fVertexCnt;
3887d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            i = &draw->fIndexCnt;
3897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        }
3907d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
3919aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        // FIXME: These tris are inset in the 1 unit arc around the corner
3927d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 0].fPos = sega.endPt();
3937d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 1].fPos = verts[*v + 0].fPos + sega.endNorm();
3947d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 2].fPos = verts[*v + 0].fPos + segb.fMid;
3957d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 3].fPos = verts[*v + 0].fPos + segb.fNorms[0];
3967d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 0].fUV.set(0,0);
3977d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 1].fUV.set(0,-SK_Scalar1);
3987d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 2].fUV.set(0,-SK_Scalar1);
3997d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 3].fUV.set(0,-SK_Scalar1);
4007d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1;
4017d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1;
4027d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1;
4037d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1;
4047d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4057d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 0] = *v + 0;
4067d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 1] = *v + 2;
4077d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 2] = *v + 1;
4087d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 3] = *v + 0;
4097d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 4] = *v + 3;
4107d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 5] = *v + 2;
4117d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4127d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        *v += 4;
4137d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        *i += 6;
41469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
4159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        if (Segment::kLine == segb.fType) {
4167d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fPos = fanPt;
4177d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fPos = sega.endPt();
4187d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fPos = segb.fPts[0];
4199aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4207d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fPos = verts[*v + 1].fPos + segb.fNorms[0];
4217d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fPos = verts[*v + 2].fPos + segb.fNorms[0];
4229aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4239aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            // we draw the line edge as a degenerate quad (u is 0, v is the
4249aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            // signed distance to the edge)
4257d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            SkScalar dist = fanPt.distanceToLineBetween(verts[*v + 1].fPos,
4267d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com                                                        verts[*v + 2].fPos);
4277d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fUV.set(0, dist);
4287d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fUV.set(0, 0);
4297d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fUV.set(0, 0);
4307d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fUV.set(0, -SK_Scalar1);
4317d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fUV.set(0, -SK_Scalar1);
4327d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4337d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1;
4347d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1;
4357d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1;
4367d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1;
4377d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fD0 = verts[*v + 4].fD1 = -SK_Scalar1;
4387d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4397d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 0] = *v + 0;
4407d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 1] = *v + 2;
4417d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 2] = *v + 1;
4427d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4437d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 3] = *v + 3;
4447d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 4] = *v + 1;
4457d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 5] = *v + 2;
4467d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4477d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 6] = *v + 4;
4487d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 7] = *v + 3;
4497d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 8] = *v + 2;
4507d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4517d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            *v += 5;
4527d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            *i += 9;
453068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com        } else {
454972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            SkPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]};
4559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
456972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            SkVector midVec = segb.fNorms[0] + segb.fNorms[1];
4579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            midVec.normalize();
4589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4597d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fPos = fanPt;
4607d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fPos = qpts[0];
4617d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fPos = qpts[2];
4627d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fPos = qpts[0] + segb.fNorms[0];
4637d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fPos = qpts[2] + segb.fNorms[1];
4647d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 5].fPos = qpts[1] + midVec;
4659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
46681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            SkScalar c = segb.fNorms[0].dot(qpts[0]);
4677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fD0 =  -segb.fNorms[0].dot(fanPt) + c;
4687d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fD0 =  0.f;
4697d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fD0 =  -segb.fNorms[0].dot(qpts[2]) + c;
4707d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fD0 = -SK_ScalarMax/100;
4717d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fD0 = -SK_ScalarMax/100;
4727d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 5].fD0 = -SK_ScalarMax/100;
4739aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4749aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            c = segb.fNorms[1].dot(qpts[2]);
4757d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fD1 =  -segb.fNorms[1].dot(fanPt) + c;
4767d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fD1 =  -segb.fNorms[1].dot(qpts[0]) + c;
4777d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fD1 =  0.f;
4787d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fD1 = -SK_ScalarMax/100;
4797d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fD1 = -SK_ScalarMax/100;
4807d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 5].fD1 = -SK_ScalarMax/100;
4819aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4821971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            GrPathUtils::QuadUVMatrix toUV(qpts);
483972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            toUV.apply<6, sizeof(QuadVertex), sizeof(SkPoint)>(verts + *v);
4849aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4857d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 0] = *v + 3;
4867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 1] = *v + 1;
4877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 2] = *v + 2;
4887d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 3] = *v + 4;
4897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 4] = *v + 3;
4907d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 5] = *v + 2;
4919aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4927d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 6] = *v + 5;
4937d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 7] = *v + 3;
4947d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 8] = *v + 4;
4959aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4967d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i +  9] = *v + 0;
4977d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 10] = *v + 2;
4987d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 11] = *v + 1;
4999aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
5007d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            *v += 6;
5017d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            *i += 12;
50269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        }
50369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
50469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
50569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
50690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
50790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
50890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/*
50990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
51090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * two components of the vertex attribute. Coverage is based on signed
51190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * distance with negative being inside, positive outside. The edge is specified in
51290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * window space (y-down). If either the third or fourth component of the interpolated
51390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * vertex coord is > 0 then the pixel is considered outside the edge. This is used to
514041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * attempt to trim to a portion of the infinite quad.
515041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Requires shader derivative instruction support.
51690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */
51790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
518249af15fb82833d2274850c589812b6e69df0033joshualittclass QuadEdgeEffect : public GrGeometryProcessor {
51990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic:
52090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
521d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    static GrGeometryProcessor* Create(GrColor color, const SkMatrix& localMatrix) {
522d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt        return SkNEW_ARGS(QuadEdgeEffect, (color, localMatrix));
52390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
52490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
52590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    virtual ~QuadEdgeEffect() {}
52690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
52772c9faab45124e08c85f70ca38536914862d947cmtklein    const char* name() const SK_OVERRIDE { return "QuadEdge"; }
52890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
52971c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    const Attribute* inPosition() const { return fInPosition; }
53071c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    const Attribute* inQuadEdge() const { return fInQuadEdge; }
531249af15fb82833d2274850c589812b6e69df0033joshualitt
532b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    class GLProcessor : public GrGLGeometryProcessor {
53390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    public:
534eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        GLProcessor(const GrGeometryProcessor&,
5359b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                    const GrBatchTracker&)
5369b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            : fColor(GrColor_ILLEGAL) {}
53790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
538abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        void onEmitCode(EmitArgs& args) SK_OVERRIDE {
5392dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt            const QuadEdgeEffect& qe = args.fGP.cast<QuadEdgeEffect>();
5409b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLGPBuilder* pb = args.fPB;
5419b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
5422dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
543abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            // emit attributes
544abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            vsBuilder->emitAttributes(qe);
545abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
54674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            GrGLVertToFrag v(kVec4f_GrSLType);
54774077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            args.fPB->addVarying("QuadEdge", &v);
5482dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt            vsBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.inQuadEdge()->fName);
5492dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
5509b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            const BatchTracker& local = args.fBT.cast<BatchTracker>();
5519b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
5529b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            // Setup pass through color
5539b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
5549b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                        &fColorUniform);
5559b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
556ee2af95db72152dfa61c841875df0594ca93437djoshualitt            // setup uniform viewMatrix
557ee2af95db72152dfa61c841875df0594ca93437djoshualitt            this->addUniformViewMatrix(pb);
558ee2af95db72152dfa61c841875df0594ca93437djoshualitt
559abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            // Setup position
560abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);",  this->position(), this->uViewM(),
561abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt                                   qe.inPosition()->fName);
562abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
563abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            // emit transforms
564abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            this->emitTransforms(args.fPB,  this->position(), qe.inPosition()->fName,
565abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt                                 qe.localMatrix(), args.fTransformsIn, args.fTransformsOut);
56690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
567c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt            GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
56830ba436f04e61d4505fb854d5fc56079636e0788joshualitt
56930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            SkAssertResult(fsBuilder->enableFeature(
57030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
57174077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("float edgeAlpha;");
57230ba436f04e61d4505fb854d5fc56079636e0788joshualitt
57390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            // keep the derivative instructions outside the conditional
57474077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
57574077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
57674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(), v.fsIn());
57790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            // today we know z and w are in device space. We could use derivatives
57874077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("edgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);", v.fsIn(),
57974077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                    v.fsIn());
58074077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf ("} else {");
58174077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("vec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,"
58274077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                   "               2.0*%s.x*duvdy.x - duvdy.y);",
58374077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                   v.fsIn(), v.fsIn());
58474077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("edgeAlpha = (%s.x*%s.x - %s.y);", v.fsIn(), v.fsIn(),
58574077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                    v.fsIn());
58674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("edgeAlpha = "
58774077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                   "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);}");
58874077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt
5892dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt            fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
59090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        }
59190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
5929b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        static inline void GenKey(const GrGeometryProcessor& gp,
5939b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                  const GrBatchTracker& bt,
59487f48d997ec29e5eeaa7567355775e93465dd60djoshualitt                                  const GrGLCaps&,
5959b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                  GrProcessorKeyBuilder* b) {
5969b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            const BatchTracker& local = bt.cast<BatchTracker>();
5978fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt            b->add32((local.fInputColorType << 16) |
5988fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt                     (local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 : 0x0));
5999b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
60090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
6019b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        virtual void setData(const GrGLProgramDataManager& pdman,
6029b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                             const GrPrimitiveProcessor& gp,
6039b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                             const GrBatchTracker& bt) SK_OVERRIDE {
604ee2af95db72152dfa61c841875df0594ca93437djoshualitt            this->setUniformViewMatrix(pdman, gp.viewMatrix());
605ee2af95db72152dfa61c841875df0594ca93437djoshualitt
6069b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            const BatchTracker& local = bt.cast<BatchTracker>();
6079b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
6089b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                GrGLfloat c[4];
6099b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                GrColorToRGBAFloat(local.fColor, c);
6109b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                pdman.set4fv(fColorUniform, 1, c);
6119b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                fColor = local.fColor;
6129b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            }
6139b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
61490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
61590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    private:
6169b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrColor fColor;
6179b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        UniformHandle fColorUniform;
6189b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
619249af15fb82833d2274850c589812b6e69df0033joshualitt        typedef GrGLGeometryProcessor INHERITED;
62090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    };
621041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com
622eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    virtual void getGLProcessorKey(const GrBatchTracker& bt,
623eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                   const GrGLCaps& caps,
624eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                   GrProcessorKeyBuilder* b) const SK_OVERRIDE {
625eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        GLProcessor::GenKey(*this, bt, caps, b);
626eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    }
627eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
628abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt    virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
629abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt                                                     const GrGLCaps&) const SK_OVERRIDE {
630eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        return SkNEW_ARGS(GLProcessor, (*this, bt));
631eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    }
632eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
6339b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
6349b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        BatchTracker* local = bt->cast<BatchTracker>();
6359b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
636290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt        local->fUsesLocalCoords = init.fUsesLocalCoords;
6379b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    }
6389b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
639290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool onCanMakeEqual(const GrBatchTracker& m,
640290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                        const GrGeometryProcessor& that,
641290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                        const GrBatchTracker& t) const SK_OVERRIDE {
6429b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const BatchTracker& mine = m.cast<BatchTracker>();
6439b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        const BatchTracker& theirs = t.cast<BatchTracker>();
644290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt        return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
645290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt                                       that, theirs.fUsesLocalCoords) &&
646290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt               CanCombineOutput(mine.fInputColorType, mine.fColor,
6479b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                theirs.fInputColorType, theirs.fColor);
6489b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    }
6499b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
65090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate:
651d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    QuadEdgeEffect(GrColor color, const SkMatrix& localMatrix)
6528059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt        : INHERITED(color, SkMatrix::I(), localMatrix) {
653eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        this->initClassID<QuadEdgeEffect>();
65471c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt        fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
65571c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt        fInQuadEdge = &this->addVertexAttrib(Attribute("inQuadEdge", kVec4f_GrVertexAttribType));
65690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
65790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
65872c9faab45124e08c85f70ca38536914862d947cmtklein    bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE {
65990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        return true;
66090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
66190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
66272c9faab45124e08c85f70ca38536914862d947cmtklein    void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
66356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt        out->setUnknownSingleComponent();
6641a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    }
6651a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel
6669b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    struct BatchTracker {
6679b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrGPInput fInputColorType;
6689b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrColor fColor;
669290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt        bool fUsesLocalCoords;
6709b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    };
6719b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
67271c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    const Attribute* fInPosition;
67371c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    const Attribute* fInQuadEdge;
674249af15fb82833d2274850c589812b6e69df0033joshualitt
675b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
67690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
6772e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    typedef GrGeometryProcessor INHERITED;
67890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org};
67990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
680b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_GEOMETRY_PROCESSOR_TEST(QuadEdgeEffect);
68190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
682b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGeometryProcessor* QuadEdgeEffect::TestCreate(SkRandom* random,
683b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                GrContext*,
684b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                const GrDrawTargetCaps& caps,
685b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                GrTexture*[]) {
68690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    // Doesn't work without derivative instructions.
687d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    return caps.shaderDerivativeSupport() ?
688d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt           QuadEdgeEffect::Create(GrRandomColor(random),
689d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt                                  GrProcessorUnitTest::TestMatrix(random)) : NULL;
69090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}
69190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
69290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
69390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
6949853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget* target,
6959853ccef19c200be93a6211f32589fa82a53067cjoshualitt                                         const GrDrawState*,
6968059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                         const SkMatrix& viewMatrix,
6979853ccef19c200be93a6211f32589fa82a53067cjoshualitt                                         const SkPath& path,
698e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com                                         const SkStrokeRec& stroke,
6998a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com                                         bool antiAlias) const {
700bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com    return (target->caps()->shaderDerivativeSupport() && antiAlias &&
701e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com            stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
702c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com}
703c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com
7049853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrAAConvexPathRenderer::onDrawPath(GrDrawTarget* target,
7059853ccef19c200be93a6211f32589fa82a53067cjoshualitt                                        GrDrawState* drawState,
7062e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt                                        GrColor color,
7078059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                        const SkMatrix& vm,
7089853ccef19c200be93a6211f32589fa82a53067cjoshualitt                                        const SkPath& origPath,
709e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com                                        const SkStrokeRec&,
710c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                        bool antiAlias) {
711c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com
712e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    const SkPath* path = &origPath;
713af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    if (path->isEmpty()) {
714c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com        return true;
71569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
7164647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com
7178059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt    SkMatrix viewMatrix = vm;
718d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    SkMatrix invert;
719d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    if (!viewMatrix.invert(&invert)) {
720e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return false;
72169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
72269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
723af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // We use the fact that SkPath::transform path does subdivision based on
724af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // perspective. Otherwise, we apply the view matrix when copying to the
725af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // segment representation.
726af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    SkPath tmpPath;
727137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com    if (viewMatrix.hasPerspective()) {
728e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com        origPath.transform(viewMatrix, &tmpPath);
729af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com        path = &tmpPath;
730137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com        viewMatrix = SkMatrix::I();
731af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    }
732af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
73369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    QuadVertex *verts;
73469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    uint16_t* idxs;
73569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
7369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int vCount;
7379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int iCount;
73868a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com    enum {
73968a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com        kPreallocSegmentCnt = 512 / sizeof(Segment),
7407d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        kPreallocDrawCnt = 4,
74168a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com    };
74268a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com    SkSTArray<kPreallocSegmentCnt, Segment, true> segments;
7439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    SkPoint fanPt;
744af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
745106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org    // We can't simply use the path bounds because we may degenerate cubics to quads which produces
746106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org    // new control points outside the original convex hull.
747106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org    SkRect devBounds;
748106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org    if (!get_segments(*path, viewMatrix, &segments, &fanPt, &vCount, &iCount, &devBounds)) {
749c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com        return false;
75069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
75169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
752106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org    // Our computed verts should all be within one pixel of the segment control points.
753106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org    devBounds.outset(SK_Scalar1, SK_Scalar1);
754106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org
755d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    SkAutoTUnref<GrGeometryProcessor> quadProcessor(QuadEdgeEffect::Create(color, invert));
7564647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com
7572dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    GrDrawTarget::AutoReleaseGeometry arg(target, vCount, quadProcessor->getVertexStride(), iCount);
7582dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    SkASSERT(quadProcessor->getVertexStride() == sizeof(QuadVertex));
759b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com    if (!arg.succeeded()) {
760c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com        return false;
76169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
762b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com    verts = reinterpret_cast<QuadVertex*>(arg.vertices());
763b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com    idxs = reinterpret_cast<uint16_t*>(arg.indices());
76469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
7657d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    SkSTArray<kPreallocDrawCnt, Draw, true> draws;
7667d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    create_vertices(segments, fanPt, &draws, verts, idxs);
7677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
7681dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com    // Check devBounds
769515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
7701dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com    SkRect tolDevBounds = devBounds;
7711dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com    tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000);
7721dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com    SkRect actualBounds;
7731dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com    actualBounds.set(verts[0].fPos, verts[1].fPos);
7741dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com    for (int i = 2; i < vCount; ++i) {
7751dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com        actualBounds.growToInclude(verts[i].fPos.fX, verts[i].fPos.fY);
7761dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com    }
777f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(tolDevBounds.contains(actualBounds));
7781dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com#endif
7791dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com
7807d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int vOffset = 0;
7817d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    for (int i = 0; i < draws.count(); ++i) {
7827d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        const Draw& draw = draws[i];
7839853ccef19c200be93a6211f32589fa82a53067cjoshualitt        target->drawIndexed(drawState,
78456995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt                            quadProcessor,
7859853ccef19c200be93a6211f32589fa82a53067cjoshualitt                            kTriangles_GrPrimitiveType,
7867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com                            vOffset,  // start vertex
7877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com                            0,        // start index
7887d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com                            draw.fVertexCnt,
7891dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com                            draw.fIndexCnt,
7901dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com                            &devBounds);
7917d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        vOffset += draw.fVertexCnt;
7927d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    }
793a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com
794c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com    return true;
79569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
796