11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrAAHairLinePathRenderer.h"
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrContext.h"
121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrDrawState.h"
131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrGpu.h"
141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrIndexBuffer.h"
151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrPathUtils.h"
161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkGeometry.h"
171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkTemplates.h"
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace {
201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// quadratics are rendered as 5-sided polys in order to bound the
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// AA stroke around the center-curve. See comments in push_quad_index_buffer and
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// bloat_quad.
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const int kVertsPerQuad = 5;
241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const int kIdxsPerQuad = 9;
251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const int kVertsPerLineSeg = 4;
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const int kIdxsPerLineSeg = 6;
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const int kNumQuadsInIdxBuffer = 256;
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const size_t kQuadIdxSBufize = kIdxsPerQuad *
311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      sizeof(uint16_t) *
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      kNumQuadsInIdxBuffer;
331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    uint16_t* data = (uint16_t*) qIdxBuffer->lock();
361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool tempData = NULL == data;
371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (tempData) {
381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data = new uint16_t[kNumQuadsInIdxBuffer * kIdxsPerQuad];
391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) {
411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // Each quadratic is rendered as a five sided polygon. This poly bounds
431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // the quadratic's bounding triangle but has been expanded so that the
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // 1-pixel wide area around the curve is inside the poly.
451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // If a,b,c are the original control points then the poly a0,b0,c0,c1,a1
461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // that is rendered would look like this:
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        //              b0
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        //              b
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        //
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        //     a0              c0
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        //      a            c
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        //       a1       c1
531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // Each is drawn as three triagnles specified by these 9 indices:
541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int baseIdx = i * kIdxsPerQuad;
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        uint16_t baseVert = (uint16_t)(i * kVertsPerQuad);
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[0 + baseIdx] = baseVert + 0; // a0
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[1 + baseIdx] = baseVert + 1; // a1
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[2 + baseIdx] = baseVert + 2; // b0
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[3 + baseIdx] = baseVert + 2; // b0
601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[4 + baseIdx] = baseVert + 4; // c1
611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[5 + baseIdx] = baseVert + 3; // c0
621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[6 + baseIdx] = baseVert + 1; // a1
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[7 + baseIdx] = baseVert + 4; // c1
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        data[8 + baseIdx] = baseVert + 2; // b0
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (tempData) {
671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bool ret = qIdxBuffer->updateData(data, kQuadIdxSBufize);
681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        delete[] data;
691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return ret;
701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        qIdxBuffer->unlock();
721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return true;
731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
771cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) {
781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const GrIndexBuffer* lIdxBuffer = context->getQuadIndexBuffer();
791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL == lIdxBuffer) {
801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return NULL;
811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGpu* gpu = context->getGpu();
831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false);
841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf);
851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL == qIdxBuf ||
861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        !push_quad_index_data(qIdxBuf)) {
871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return NULL;
881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return new GrAAHairLinePathRenderer(context,
901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        lIdxBuffer,
911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        qIdxBuf);
921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
941cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrAAHairLinePathRenderer::GrAAHairLinePathRenderer(
951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        const GrContext* context,
961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        const GrIndexBuffer* linesIndexBuffer,
971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        const GrIndexBuffer* quadsIndexBuffer) {
981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fLinesIndexBuffer = linesIndexBuffer;
991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    linesIndexBuffer->ref();
1001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fQuadsIndexBuffer = quadsIndexBuffer;
1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    quadsIndexBuffer->ref();
1021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1041cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fLinesIndexBuffer->unref();
1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fQuadsIndexBuffer->unref();
1071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace {
1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef SkTArray<SkPoint, true> PtArray;
1121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef SkTArray<int, true> IntArray;
1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// Takes 178th time of logf on Z600 / VC2010
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerint get_float_exp(float x) {
1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GR_STATIC_ASSERT(sizeof(int) == sizeof(float));
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if GR_DEBUG
1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static bool tested;
1201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!tested) {
1211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        tested = true;
1221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(0.25f) == -2);
1231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(0.3f) == -2);
1241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(0.5f) == -1);
1251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(1.f) == 0);
1261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(2.f) == 1);
1271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(2.5f) == 1);
1281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(8.f) == 3);
1291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(100.f) == 6);
1301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(1000.f) == 9);
1311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(1024.f) == 10);
1321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(get_float_exp(3000000.f) == 21);
1331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int* iptr = (const int*)&x;
1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return (((*iptr) & 0x7f800000) >> 23) - 127;
1371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// we subdivide the quads to avoid huge overfill
1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// if it returns -1 then should be drawn as lines
1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerint num_quad_subdivs(const SkPoint p[3]) {
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const SkScalar gDegenerateToLineTol = SK_Scalar1;
1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const SkScalar gDegenerateToLineTolSqd =
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol);
1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd ||
1471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) {
1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return -1;
1491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]);
1521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (dsqd < gDegenerateToLineTolSqd) {
1531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return -1;
1541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) {
1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return -1;
1581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const int kMaxSub = 4;
1611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // tolerance of triangle height in pixels
1621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // tuned on windows  Quadro FX 380 / Z600
1631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // trade off of fill vs cpu time on verts
1641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // maybe different when do this using gpu (geo or tess shaders)
1651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const SkScalar gSubdivTol = 175 * SK_Scalar1;
1661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (dsqd <= gSubdivTol*gSubdivTol) {
1681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return 0;
1691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
1701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // subdividing the quad reduces d by 4. so we want x = log4(d/tol)
1711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // = log4(d*d/tol*tol)/2
1721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // = log2(d*d/tol*tol)
1731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT
1751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // +1 since we're ignoring the mantissa contribution.
1761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1;
1771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        log = GrMin(GrMax(0, log), kMaxSub);
1781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return log;
1791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
1801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkScalar log = SkScalarLog(SkScalarDiv(dsqd,gSubdivTol*gSubdivTol));
1811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        static const SkScalar conv = SkScalarInvert(SkScalarLog(2));
1821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        log = SkScalarMul(log, conv);
1831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return  GrMin(GrMax(0, SkScalarCeilToInt(log)),kMaxSub);
1841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/**
1891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Generates the lines and quads to be rendered. Lines are always recorded in
1901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * device space. We will do a device space bloat to account for the 1pixel
1911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * thickness.
1921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Quads are recorded in device space unless m contains
1931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * perspective, then in they are in src space. We do this because we will
1941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * subdivide large quads to reduce over-fill. This subdivision has to be
1951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * performed before applying the perspective matrix.
1961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
1971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerint generate_lines_and_quads(const SkPath& path,
1981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkMatrix& m,
1991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkVector& translate,
2001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             GrIRect clip,
2011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             PtArray* lines,
2021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             PtArray* quads,
2031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             IntArray* quadSubdivCnts) {
2041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPath::Iter iter(path, false);
2051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int totalQuadCount = 0;
2071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrRect bounds;
2081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrIRect ibounds;
2091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool persp = m.hasPerspective();
2111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (;;) {
2131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrPoint pts[4];
2141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrPoint devPts[4];
2151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrPathCmd cmd = (GrPathCmd)iter.next(pts);
2161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (cmd) {
2171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case kMove_PathCmd:
2181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
2191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case kLine_PathCmd:
2201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkPoint::Offset(pts, 2, translate);
2211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                m.mapPoints(devPts, pts, 2);
2221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.setBounds(devPts, 2);
2231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.outset(SK_Scalar1, SK_Scalar1);
2241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.roundOut(&ibounds);
2251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                if (SkIRect::Intersects(clip, ibounds)) {
2261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    SkPoint* pts = lines->push_back_n(2);
2271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    pts[0] = devPts[0];
2281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    pts[1] = devPts[1];
2291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                }
2301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
2311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case kQuadratic_PathCmd:
2321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkPoint::Offset(pts, 3, translate);
2331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                m.mapPoints(devPts, pts, 3);
2341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.setBounds(devPts, 3);
2351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.outset(SK_Scalar1, SK_Scalar1);
2361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.roundOut(&ibounds);
2371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                if (SkIRect::Intersects(clip, ibounds)) {
2381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    int subdiv = num_quad_subdivs(devPts);
2391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    GrAssert(subdiv >= -1);
2401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    if (-1 == subdiv) {
2411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        SkPoint* pts = lines->push_back_n(4);
2421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        pts[0] = devPts[0];
2431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        pts[1] = devPts[1];
2441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        pts[2] = devPts[1];
2451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        pts[3] = devPts[2];
2461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    } else {
2471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        // when in perspective keep quads in src space
2481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        SkPoint* qPts = persp ? pts : devPts;
2491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        SkPoint* pts = quads->push_back_n(3);
2501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        pts[0] = qPts[0];
2511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        pts[1] = qPts[1];
2521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        pts[2] = qPts[2];
2531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        quadSubdivCnts->push_back() = subdiv;
2541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        totalQuadCount += 1 << subdiv;
2551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    }
2561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                }
2571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
2581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case kCubic_PathCmd:
2591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkPoint::Offset(pts, 4, translate);
2601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                m.mapPoints(devPts, pts, 4);
2611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.setBounds(devPts, 4);
2621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.outset(SK_Scalar1, SK_Scalar1);
2631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                bounds.roundOut(&ibounds);
2641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                if (SkIRect::Intersects(clip, ibounds)) {
2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    PREALLOC_PTARRAY(32) q;
2664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    // We convert cubics to quadratics (for now).
2674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    // In perspective have to do conversion in src space.
2681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    if (persp) {
2691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        SkScalar tolScale =
2701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m,
2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                             path.getBounds());
2724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        GrPathUtils::convertCubicToQuads(pts, tolScale, &q);
2731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    } else {
2744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, &q);
2751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    }
2761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    for (int i = 0; i < q.count(); i += 3) {
2771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        SkPoint* qInDevSpace;
2781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        // bounds has to be calculated in device space, but q is
2791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        // in src space when there is perspective.
2801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        if (persp) {
2811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            m.mapPoints(devPts, &q[i], 3);
2821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            bounds.setBounds(devPts, 3);
2831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            qInDevSpace = devPts;
2841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        } else {
2851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            bounds.setBounds(&q[i], 3);
2861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            qInDevSpace = &q[i];
2871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        }
2881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        bounds.outset(SK_Scalar1, SK_Scalar1);
2891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        bounds.roundOut(&ibounds);
2901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        if (SkIRect::Intersects(clip, ibounds)) {
2911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            int subdiv = num_quad_subdivs(qInDevSpace);
2921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            GrAssert(subdiv >= -1);
2931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            if (-1 == subdiv) {
2941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                SkPoint* pts = lines->push_back_n(4);
2951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                // lines should always be in device coords
2961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                pts[0] = qInDevSpace[0];
2971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                pts[1] = qInDevSpace[1];
2981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                pts[2] = qInDevSpace[1];
2991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                pts[3] = qInDevSpace[2];
3001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            } else {
3011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                SkPoint* pts = quads->push_back_n(3);
3021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                // q is already in src space when there is no
3031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                // perspective and dev coords otherwise.
3041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                pts[0] = q[0 + i];
3051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                pts[1] = q[1 + i];
3061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                pts[2] = q[2 + i];
3071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                quadSubdivCnts->push_back() = subdiv;
3081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                totalQuadCount += 1 << subdiv;
3091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            }
3101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        }
3111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    }
3121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                }
3131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
3141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case kClose_PathCmd:
3151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
3161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case kEnd_PathCmd:
3171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                return totalQuadCount;
3181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
3191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstruct Vertex {
3231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrPoint fPos;
3241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    union {
3251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        struct {
3261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrScalar fA;
3271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrScalar fB;
3281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrScalar fC;
3291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } fLine;
3301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrVec   fQuadCoord;
3311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        struct {
3321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrScalar fBogus[4];
3331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        };
3341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    };
3351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
3361cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint));
3371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid intersect_lines(const SkPoint& ptA, const SkVector& normA,
3391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                     const SkPoint& ptB, const SkVector& normB,
3401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                     SkPoint* result) {
3411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar lineAW = -normA.dot(ptA);
3431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar lineBW = -normB.dot(ptB);
3441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar wInv = SkScalarMul(normA.fX, normB.fY) -
3461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    SkScalarMul(normA.fY, normB.fX);
3471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    wInv = SkScalarInvert(wInv);
3481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY);
3501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    result->fX = SkScalarMul(result->fX, wInv);
3511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW);
3531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    result->fY = SkScalarMul(result->fY, wInv);
3541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid bloat_quad(const SkPoint qpts[3], const GrMatrix* toDevice,
3571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                const GrMatrix* toSrc, Vertex verts[kVertsPerQuad]) {
3581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(!toDevice == !toSrc);
3591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // original quad is specified by tri a,b,c
3601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPoint a = qpts[0];
3611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPoint b = qpts[1];
3621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPoint c = qpts[2];
3631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // this should be in the src space, not dev coords, when we have perspective
3651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMatrix DevToUV;
3664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GrPathUtils::quadDesignSpaceToUVCoordsMatrix(qpts, &DevToUV);
3671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (toDevice) {
3691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        toDevice->mapPoints(&a, 1);
3701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        toDevice->mapPoints(&b, 1);
3711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        toDevice->mapPoints(&c, 1);
3721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // make a new poly where we replace a and c by a 1-pixel wide edges orthog
3741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // to edges ab and bc:
3751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //
3761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //   before       |        after
3771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //                |              b0
3781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //         b      |
3791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //                |
3801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //                |     a0            c0
3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // a         c    |        a1       c1
3821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //
3831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c,
3841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // respectively.
3851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Vertex& a0 = verts[0];
3861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Vertex& a1 = verts[1];
3871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Vertex& b0 = verts[2];
3881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Vertex& c0 = verts[3];
3891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Vertex& c1 = verts[4];
3901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkVector ab = b;
3921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ab -= a;
3931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkVector ac = c;
3941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ac -= a;
3951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkVector cb = b;
3961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    cb -= c;
3971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // We should have already handled degenerates
3991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(ab.length() > 0 && cb.length() > 0);
4001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ab.normalize();
4021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkVector abN;
4031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    abN.setOrthog(ab, SkVector::kLeft_Side);
4041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (abN.dot(ac) > 0) {
4051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        abN.negate();
4061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    cb.normalize();
4091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkVector cbN;
4101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    cbN.setOrthog(cb, SkVector::kLeft_Side);
4111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (cbN.dot(ac) < 0) {
4121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        cbN.negate();
4131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    a0.fPos = a;
4161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    a0.fPos += abN;
4171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    a1.fPos = a;
4181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    a1.fPos -= abN;
4191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    c0.fPos = c;
4211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    c0.fPos += cbN;
4221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    c1.fPos = c;
4231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    c1.fPos -= cbN;
4241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos);
4261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (toSrc) {
4281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad);
4291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    DevToUV.mapPointsWithStride(&verts[0].fQuadCoord,
4311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                &verts[0].fPos, sizeof(Vertex), kVertsPerQuad);
4321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid add_quads(const SkPoint p[3],
4351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger               int subdiv,
4361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger               const GrMatrix* toDevice,
4371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger               const GrMatrix* toSrc,
4381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger               Vertex** vert) {
4391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(subdiv >= 0);
4401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (subdiv) {
4411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkPoint newP[5];
4421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkChopQuadAtHalf(p, newP);
4431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert);
4441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert);
4451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
4461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bloat_quad(p, toDevice, toSrc, *vert);
4471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *vert += kVertsPerQuad;
4481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid add_line(const SkPoint p[2],
4521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              int rtHeight,
4531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              const SkMatrix* toSrc,
4541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              Vertex** vert) {
4551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const SkPoint& a = p[0];
4561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const SkPoint& b = p[1];
4571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkVector orthVec = b;
4591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    orthVec -= a;
4601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (orthVec.setLength(SK_Scalar1)) {
4621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        orthVec.setOrthog(orthVec);
4631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // the values we pass down to the frag shader
4651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // have to be in y-points-up space;
4661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkVector normal;
4671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        normal.fX = orthVec.fX;
4681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        normal.fY = -orthVec.fY;
4691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkPoint aYDown;
4701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        aYDown.fX = a.fX;
4711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        aYDown.fY = rtHeight - a.fY;
4721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkScalar lineC = -(aYDown.dot(normal));
4741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int i = 0; i < kVertsPerLineSeg; ++i) {
4751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            (*vert)[i].fPos = (i < 2) ? a : b;
4761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (0 == i || 3 == i) {
4771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                (*vert)[i].fPos -= orthVec;
4781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else {
4791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                (*vert)[i].fPos += orthVec;
4801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
4811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            (*vert)[i].fLine.fA = normal.fX;
4821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            (*vert)[i].fLine.fB = normal.fY;
4831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            (*vert)[i].fLine.fC = lineC;
4841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (NULL != toSrc) {
4861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            toSrc->mapPointsWithStride(&(*vert)->fPos,
4871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                       sizeof(Vertex),
4881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                       kVertsPerLineSeg);
4891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
4911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // just make it degenerate and likely offscreen
4921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        (*vert)[0].fPos.set(SK_ScalarMax, SK_ScalarMax);
4931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax);
4941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax);
4951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax);
4961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *vert += kVertsPerLineSeg;
4991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
5001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
5021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool GrAAHairLinePathRenderer::createGeom(const SkPath& path,
5044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          const GrVec* translate,
5054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          GrDrawTarget* target,
5064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          GrDrawState::StageMask stageMask,
5074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          int* lineCnt,
5084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          int* quadCnt) {
5094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    const GrDrawState& drawState = target->getDrawState();
5101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int rtHeight = drawState.getRenderTarget()->height();
5111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrIRect clip;
5134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (target->getClip().hasConservativeBounds()) {
5144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GrRect clipRect =  target->getClip().getConservativeBounds();
5151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        clipRect.roundOut(&clip);
5161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
5171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        clip.setLargest();
5181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit;
5221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
5231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if ((1 << s) & stageMask) {
5241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
5251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
5261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrMatrix viewM = drawState.getViewMatrix();
5291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    PREALLOC_PTARRAY(128) lines;
5311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    PREALLOC_PTARRAY(128) quads;
5321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    IntArray qSubdivs;
5334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    static const GrVec gZeroVec = {0, 0};
5344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (NULL == translate) {
5354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        translate = &gZeroVec;
5364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    *quadCnt = generate_lines_and_quads(path, viewM, *translate, clip,
5381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        &lines, &quads, &qSubdivs);
5391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    *lineCnt = lines.count() / 2;
5414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt;
5421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(sizeof(Vertex) == GrDrawTarget::VertexSize(layout));
5441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Vertex* verts;
5464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (!target->reserveVertexSpace(layout, vertCnt, (void**)&verts)) {
5471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
5481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const GrMatrix* toDevice = NULL;
5511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const GrMatrix* toSrc = NULL;
5521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrMatrix ivm;
5531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (viewM.hasPerspective()) {
5551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (viewM.invert(&ivm)) {
5561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            toDevice = &viewM;
5571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            toSrc = &ivm;
5581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
5591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    for (int i = 0; i < *lineCnt; ++i) {
5621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        add_line(&lines[2*i], rtHeight, toSrc, &verts);
5631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int unsubdivQuadCnt = quads.count() / 3;
5661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < unsubdivQuadCnt; ++i) {
5671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(qSubdivs[i] >= 0);
5681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts);
5691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
5721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
5731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
5754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                           GrPathFill fill,
5764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                           const GrDrawTarget* target,
5774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                           bool antiAlias) const {
5784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fill != kHairLine_PathFill || !antiAlias) {
5794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        return false;
5804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask |
5834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          SkPath::kQuad_SegmentMask;
5844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (!target->getCaps().fShaderDerivativeSupport &&
5854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        (gReqDerivMask & path.getSegmentMasks())) {
5864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        return false;
5871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return true;
5894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
5924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          GrPathFill fill,
5934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          const GrVec* translate,
5944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          GrDrawTarget* target,
5954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          GrDrawState::StageMask stageMask,
5964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          bool antiAlias) {
5974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int lineCnt;
5994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int quadCnt;
6004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
6014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (!this->createGeom(path,
6024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                          translate,
6034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                          target,
6044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                          stageMask,
6054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                          &lineCnt,
6064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                          &quadCnt)) {
6074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        return false;
6084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
6094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
6104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GrDrawState* drawState = target->drawState();
6111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrDrawTarget::AutoStateRestore asr;
6131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!drawState->getViewMatrix().hasPerspective()) {
6144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        asr.set(target);
6151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrMatrix ivm;
6161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (drawState->getViewInverse(&ivm)) {
6171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            drawState->preConcatSamplerMatrices(stageMask, ivm);
6181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
6191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        drawState->setViewMatrix(GrMatrix::I());
6201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // TODO: See whether rendering lines as degenerate quads improves perf
6231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // when we have a mix
6244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    target->setIndexSourceToBuffer(fLinesIndexBuffer);
6251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int lines = 0;
6261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int nBufLines = fLinesIndexBuffer->maxQuads();
6274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    while (lines < lineCnt) {
6284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        int n = GrMin(lineCnt - lines, nBufLines);
6291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType);
6304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        target->drawIndexed(kTriangles_PrimitiveType,
6314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            kVertsPerLineSeg*lines,    // startV
6324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            0,                         // startI
6334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            kVertsPerLineSeg*n,        // vCount
6344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            kIdxsPerLineSeg*n);        // iCount
6351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        lines += n;
6361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    target->setIndexSourceToBuffer(fQuadsIndexBuffer);
6391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int quads = 0;
6404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    while (quads < quadCnt) {
6414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
6421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType);
6434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        target->drawIndexed(kTriangles_PrimitiveType,
6444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            4 * lineCnt + kVertsPerQuad*quads, // startV
6454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            0,                                 // startI
6464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            kVertsPerQuad*n,                   // vCount
6474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            kIdxsPerQuad*n);                   // iCount
6481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        quads += n;
6491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return true;
6511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
6521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
653