GrAAHairLinePathRenderer.cpp revision 4647f9059825c062169d4d454c12640d82ae16c0
1f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com 2f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com/* 3f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * Copyright 2011 Google Inc. 4f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * 5f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 6f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * found in the LICENSE file. 7f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com */ 8f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com 9aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrAAHairLinePathRenderer.h" 10aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 11aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrContext.h" 129381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrDrawState.h" 13c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h" 14aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrGpu.h" 15aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrIndexBuffer.h" 16dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com#include "GrPathUtils.h" 17aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "SkGeometry.h" 1812b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com#include "SkStroke.h" 19aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "SkTemplates.h" 20aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 214647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com#include "effects/GrEdgeEffect.h" 224647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 23aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 24aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// quadratics are rendered as 5-sided polys in order to bound the 25aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// AA stroke around the center-curve. See comments in push_quad_index_buffer and 26aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// bloat_quad. 27aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kVertsPerQuad = 5; 28aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kIdxsPerQuad = 9; 29aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 30aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kVertsPerLineSeg = 4; 31aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kIdxsPerLineSeg = 6; 32aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 33aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kNumQuadsInIdxBuffer = 256; 34aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const size_t kQuadIdxSBufize = kIdxsPerQuad * 35aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com sizeof(uint16_t) * 36aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com kNumQuadsInIdxBuffer; 37aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 38aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.combool push_quad_index_data(GrIndexBuffer* qIdxBuffer) { 39aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com uint16_t* data = (uint16_t*) qIdxBuffer->lock(); 40aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bool tempData = NULL == data; 41aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (tempData) { 42c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad); 43aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 44aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) { 45aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 46aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // Each quadratic is rendered as a five sided polygon. This poly bounds 47aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // the quadratic's bounding triangle but has been expanded so that the 48aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // 1-pixel wide area around the curve is inside the poly. 49aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // If a,b,c are the original control points then the poly a0,b0,c0,c1,a1 50aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // that is rendered would look like this: 51aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // b0 52aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // b 53aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // 54aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a0 c0 55aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a c 56aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a1 c1 570e5104c1570de4709e04720e62d80a0ca8970260bsalomon@google.com // Each is drawn as three triangles specified by these 9 indices: 58aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int baseIdx = i * kIdxsPerQuad; 59aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com uint16_t baseVert = (uint16_t)(i * kVertsPerQuad); 60aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[0 + baseIdx] = baseVert + 0; // a0 61aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[1 + baseIdx] = baseVert + 1; // a1 62aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[2 + baseIdx] = baseVert + 2; // b0 63aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[3 + baseIdx] = baseVert + 2; // b0 64aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[4 + baseIdx] = baseVert + 4; // c1 65aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[5 + baseIdx] = baseVert + 3; // c0 66aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[6 + baseIdx] = baseVert + 1; // a1 67aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[7 + baseIdx] = baseVert + 4; // c1 68aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[8 + baseIdx] = baseVert + 2; // b0 69aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 70aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (tempData) { 71aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bool ret = qIdxBuffer->updateData(data, kQuadIdxSBufize); 72aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com delete[] data; 73aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return ret; 74aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 75aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com qIdxBuffer->unlock(); 76aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 77aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 78aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 79aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 80aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 81aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { 82a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com const GrIndexBuffer* lIdxBuffer = context->getQuadIndexBuffer(); 83a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com if (NULL == lIdxBuffer) { 84aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return NULL; 85aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 86a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrGpu* gpu = context->getGpu(); 87a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false); 88a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf); 89a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com if (NULL == qIdxBuf || 90a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com !push_quad_index_data(qIdxBuf)) { 91a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com return NULL; 92a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com } 93c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com return SkNEW_ARGS(GrAAHairLinePathRenderer, 94c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com (context, lIdxBuffer, qIdxBuf)); 95aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 96aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 97aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::GrAAHairLinePathRenderer( 98aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrContext* context, 99aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* linesIndexBuffer, 100aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* quadsIndexBuffer) { 101aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer = linesIndexBuffer; 102aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com linesIndexBuffer->ref(); 103aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer = quadsIndexBuffer; 104aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadsIndexBuffer->ref(); 105aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 106aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 107aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() { 108aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer->unref(); 109aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer->unref(); 110aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 111aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 112aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 113aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 11449313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comtypedef SkTArray<SkPoint, true> PtArray; 11592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true> 11649313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comtypedef SkTArray<int, true> IntArray; 117aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 118aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// Takes 178th time of logf on Z600 / VC2010 119aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint get_float_exp(float x) { 120aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GR_STATIC_ASSERT(sizeof(int) == sizeof(float)); 121aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#if GR_DEBUG 122aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static bool tested; 123aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (!tested) { 124aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com tested = true; 125aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.25f) == -2); 126aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.3f) == -2); 127aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.5f) == -1); 128aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1.f) == 0); 129aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(2.f) == 1); 130aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(2.5f) == 1); 131aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(8.f) == 3); 132aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(100.f) == 6); 133aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1000.f) == 9); 134aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1024.f) == 10); 135aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(3000000.f) == 21); 136aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 137aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#endif 1382ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com const int* iptr = (const int*)&x; 1392ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com return (((*iptr) & 0x7f800000) >> 23) - 127; 140aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 141aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 142aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// we subdivide the quads to avoid huge overfill 143aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// if it returns -1 then should be drawn as lines 144aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint num_quad_subdivs(const SkPoint p[3]) { 145aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gDegenerateToLineTol = SK_Scalar1; 146fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static const SkScalar gDegenerateToLineTolSqd = 14746a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 14846a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 14946a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 15046a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 15146a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com return -1; 15246a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com } 153aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 15481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); 15546a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (dsqd < gDegenerateToLineTolSqd) { 156aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 157aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 15846a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 15946a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { 160aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 161aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 162aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 163aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const int kMaxSub = 4; 164aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tolerance of triangle height in pixels 165aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tuned on windows Quadro FX 380 / Z600 166aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // trade off of fill vs cpu time on verts 167aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // maybe different when do this using gpu (geo or tess shaders) 168aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gSubdivTol = 175 * SK_Scalar1; 169aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 1707460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) { 171aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return 0; 172aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 173aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // subdividing the quad reduces d by 4. so we want x = log4(d/tol) 174aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log4(d*d/tol*tol)/2 175aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log2(d*d/tol*tol) 176aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 177aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#ifdef SK_SCALAR_IS_FLOAT 178aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // +1 since we're ignoring the mantissa contribution. 179aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1; 180aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com log = GrMin(GrMax(0, log), kMaxSub); 181aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return log; 182aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#else 1837460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com SkScalar log = SkScalarLog( 184fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkScalarDiv(dsqd, 1857460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com SkScalarMul(gSubdivTol, gSubdivTol))); 186aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar conv = SkScalarInvert(SkScalarLog(2)); 187aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com log = SkScalarMul(log, conv); 188aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return GrMin(GrMax(0, SkScalarCeilToInt(log)),kMaxSub); 189aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#endif 190aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 191aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 192aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 193dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com/** 194dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Generates the lines and quads to be rendered. Lines are always recorded in 195dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * device space. We will do a device space bloat to account for the 1pixel 196dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * thickness. 197dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Quads are recorded in device space unless m contains 198dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * perspective, then in they are in src space. We do this because we will 199dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * subdivide large quads to reduce over-fill. This subdivision has to be 200dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * performed before applying the perspective matrix. 201dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com */ 202dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.comint generate_lines_and_quads(const SkPath& path, 203dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix& m, 2047b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com const GrIRect& devClipBounds, 205dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com PtArray* lines, 206dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com PtArray* quads, 207dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com IntArray* quadSubdivCnts) { 208aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPath::Iter iter(path, false); 209aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 210aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int totalQuadCount = 0; 211aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrRect bounds; 212aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrIRect ibounds; 213dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 214dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bool persp = m.hasPerspective(); 215dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 216aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (;;) { 217aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPoint pts[4]; 218dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrPoint devPts[4]; 219aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPathCmd cmd = (GrPathCmd)iter.next(pts); 220aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com switch (cmd) { 221aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kMove_PathCmd: 222aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 223aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kLine_PathCmd: 224dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 2); 225dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 2); 226aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 227aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2287b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 229a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(2); 230a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = devPts[0]; 231a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = devPts[1]; 232aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 233aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 234dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com case kQuadratic_PathCmd: 235dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 3); 236dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 3); 237aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 238aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2397b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 240dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com int subdiv = num_quad_subdivs(devPts); 241aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= -1); 242aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (-1 == subdiv) { 243a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(4); 244a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = devPts[0]; 245a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = devPts[1]; 246a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = devPts[1]; 247a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[3] = devPts[2]; 248aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 249dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // when in perspective keep quads in src space 250dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint* qPts = persp ? pts : devPts; 251a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 252a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = qPts[0]; 253a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = qPts[1]; 254a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = qPts[2]; 255aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadSubdivCnts->push_back() = subdiv; 256aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com totalQuadCount += 1 << subdiv; 257aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 258aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 259a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 260dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com case kCubic_PathCmd: 261dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 4); 262dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 4); 263aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 264aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2657b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 26692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(32) q; 267a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // we don't need a direction if we aren't constraining the subdivision 268a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction; 26969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // We convert cubics to quadratics (for now). 27069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // In perspective have to do conversion in src space. 271dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 272fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkScalar tolScale = 273dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m, 274dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com path.getBounds()); 275a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(pts, tolScale, false, kDummyDir, &q); 276dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 277a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, false, kDummyDir, &q); 278dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 279aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < q.count(); i += 3) { 280dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint* qInDevSpace; 281dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // bounds has to be calculated in device space, but q is 282dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // in src space when there is perspective. 283dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 284dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, &q[i], 3); 285dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 3); 286dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = devPts; 287dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 288dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(&q[i], 3); 289dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = &q[i]; 290dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 291aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 292aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2937b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 294dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com int subdiv = num_quad_subdivs(qInDevSpace); 295aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= -1); 296aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (-1 == subdiv) { 297a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(4); 298dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // lines should always be in device coords 299a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = qInDevSpace[0]; 300a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = qInDevSpace[1]; 301a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = qInDevSpace[1]; 302a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[3] = qInDevSpace[2]; 303aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 304a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 305dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // q is already in src space when there is no 306dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // perspective and dev coords otherwise. 307a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = q[0 + i]; 308a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = q[1 + i]; 309a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = q[2 + i]; 310aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadSubdivCnts->push_back() = subdiv; 311aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com totalQuadCount += 1 << subdiv; 312aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 313aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 314aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 315aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 316a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 317aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kClose_PathCmd: 318aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 319aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kEnd_PathCmd: 320aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return totalQuadCount; 321aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 322aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 323aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 324aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 325aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstruct Vertex { 326aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPoint fPos; 327aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com union { 328aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 32981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fA; 33081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fB; 33181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fC; 332aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } fLine; 333aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrVec fQuadCoord; 334aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 33581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fBogus[4]; 336aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 337aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 338aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com}; 339aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint)); 340aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 341aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid intersect_lines(const SkPoint& ptA, const SkVector& normA, 342aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& ptB, const SkVector& normB, 343aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint* result) { 344aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 345aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineAW = -normA.dot(ptA); 346aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineBW = -normB.dot(ptB); 347aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 348aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - 349aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalarMul(normA.fY, normB.fX); 350aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com wInv = SkScalarInvert(wInv); 351aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 352aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); 353aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(result->fX, wInv); 354fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 355aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); 356aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(result->fY, wInv); 357aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 358aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 359b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.comvoid bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 360b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, Vertex verts[kVertsPerQuad]) { 361dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrAssert(!toDevice == !toSrc); 362aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // original quad is specified by tri a,b,c 363dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint a = qpts[0]; 364dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint b = qpts[1]; 365dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint c = qpts[2]; 366aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 367dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // this should be in the src space, not dev coords, when we have perspective 3681971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com GrPathUtils::QuadUVMatrix DevToUV(qpts); 369aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 370dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toDevice) { 371dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&a, 1); 372dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&b, 1); 373dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&c, 1); 374dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 375dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // make a new poly where we replace a and c by a 1-pixel wide edges orthog 376dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // to edges ab and bc: 377dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 378dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // before | after 379dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | b0 380dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // b | 381dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | 382dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | a0 c0 383dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // a c | a1 c1 384dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 385dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c, 386dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // respectively. 387dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& a0 = verts[0]; 388dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& a1 = verts[1]; 389dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& b0 = verts[2]; 390dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& c0 = verts[3]; 391dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& c1 = verts[4]; 392dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 393aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ab = b; 394aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab -= a; 395aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ac = c; 396aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ac -= a; 397aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cb = b; 398aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb -= c; 399aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 400aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // We should have already handled degenerates 401aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(ab.length() > 0 && cb.length() > 0); 402aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 403aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab.normalize(); 404aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector abN; 405aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.setOrthog(ab, SkVector::kLeft_Side); 406aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (abN.dot(ac) > 0) { 407aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.negate(); 408aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 409aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 410aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb.normalize(); 411aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cbN; 412aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.setOrthog(cb, SkVector::kLeft_Side); 413aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (cbN.dot(ac) < 0) { 414aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.negate(); 415aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 416aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 417aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos = a; 418aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos += abN; 419aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos = a; 420aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos -= abN; 421aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 422aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos = c; 423aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos += cbN; 424aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos = c; 425aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos -= cbN; 426aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 427aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 428aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 429dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toSrc) { 430dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad); 431dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 4321971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts); 433aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 434aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 435aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_quads(const SkPoint p[3], 436aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int subdiv, 437b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice, 438b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, 439aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com Vertex** vert) { 440aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= 0); 441aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (subdiv) { 442aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint newP[5]; 443aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkChopQuadAtHalf(p, newP); 444dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); 445dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); 446aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 447dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bloat_quad(p, toDevice, toSrc, *vert); 448aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerQuad; 449aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 450aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 451aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 452aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_line(const SkPoint p[2], 453aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int rtHeight, 454dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix* toSrc, 455aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com Vertex** vert) { 456aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& a = p[0]; 457aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& b = p[1]; 458aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 459aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector orthVec = b; 460aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com orthVec -= a; 461aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 462aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (orthVec.setLength(SK_Scalar1)) { 463aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com orthVec.setOrthog(orthVec); 464aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 465706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com SkScalar lineC = -(a.dot(orthVec)); 466aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < kVertsPerLineSeg; ++i) { 467aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos = (i < 2) ? a : b; 468aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (0 == i || 3 == i) { 469aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos -= orthVec; 470aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 471aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos += orthVec; 472aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 473706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com (*vert)[i].fLine.fA = orthVec.fX; 474706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com (*vert)[i].fLine.fB = orthVec.fY; 475aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fLine.fC = lineC; 476aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 477dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (NULL != toSrc) { 478dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&(*vert)->fPos, 479dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com sizeof(Vertex), 480dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com kVertsPerLineSeg); 481dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 482aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 483aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // just make it degenerate and likely offscreen 484aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[0].fPos.set(SK_ScalarMax, SK_ScalarMax); 485aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); 486aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); 487aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); 488aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 489aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 490aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerLineSeg; 491aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 492aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 493aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 494aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 495b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.combool GrAAHairLinePathRenderer::createGeom( 496b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com const SkPath& path, 497b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget* target, 498b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com int* lineCnt, 499b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com int* quadCnt, 500b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget::AutoReleaseGeometry* arg) { 5019b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com GrDrawState* drawState = target->drawState(); 5029b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com int rtHeight = drawState->getRenderTarget()->height(); 503aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5047b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com GrIRect devClipBounds; 5059b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->getClip()->getConservativeBounds(drawState->getRenderTarget(), 5067b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com &devClipBounds); 507aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5089b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com // position + edge 5099b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com static const GrVertexAttrib kAttribs[] = { 5103b0d631cdfe2dcf59e7b7ea60d92566eade7bfc0jvanverth@google.com {kVec2f_GrVertexAttribType, 0}, 5113b0d631cdfe2dcf59e7b7ea60d92566eade7bfc0jvanverth@google.com {kVec4f_GrVertexAttribType, sizeof(GrPoint)} 5129b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com }; 5139b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com SkMatrix viewM = drawState->getViewMatrix(); 514aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 51592669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(128) lines; 51692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(128) quads; 517aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com IntArray qSubdivs; 5180f11e1ab5b6e53f6176dde2dbb25a8e3ae34858fbsalomon@google.com *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, 519dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com &lines, &quads, &qSubdivs); 520aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 521c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com *lineCnt = lines.count() / 2; 522c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; 523aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5249b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->drawState()->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs)); 5259b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); 5264647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com target->drawState()->setAttribBindings(GrDrawState::kDefault_AttribBindings); 527b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize()); 528aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 529b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com if (!arg->set(target, vertCnt, 0)) { 530aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return false; 531aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 532dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 533b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices()); 534b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com 535b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice = NULL; 536b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc = NULL; 537b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix ivm; 538dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 539dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (viewM.hasPerspective()) { 540dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (viewM.invert(&ivm)) { 541dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice = &viewM; 542dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc = &ivm; 543dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 544dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 545aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 546c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com for (int i = 0; i < *lineCnt; ++i) { 547dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_line(&lines[2*i], rtHeight, toSrc, &verts); 548aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 549dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 550aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int unsubdivQuadCnt = quads.count() / 3; 551aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < unsubdivQuadCnt; ++i) { 552aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(qSubdivs[i] >= 0); 553dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); 554aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 555aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 556aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 557aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 558aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5598a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, 5605f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec& stroke, 5618a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const GrDrawTarget* target, 5628a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 5635f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (!stroke.isHairlineStyle() || !antiAlias) { 564c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 565c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 566c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 567c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask | 568c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com SkPath::kQuad_SegmentMask; 569bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com if (!target->caps()->shaderDerivativeSupport() && 570c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com (gReqDerivMask & path.getSegmentMasks())) { 571c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 572c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 573c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 574c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 575aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 576c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.combool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, 5775f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec&, 578c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com GrDrawTarget* target, 579c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com bool antiAlias) { 580c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 581c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int lineCnt; 582c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int quadCnt; 583b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget::AutoReleaseGeometry arg; 584c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com if (!this->createGeom(path, 585c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target, 586c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com &lineCnt, 587b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com &quadCnt, 588b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com &arg)) { 589c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 590aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 591aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5924647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); 593873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com GrDrawState* drawState = target->drawState(); 5944647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 5954647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrDrawState::AutoDeviceCoordDraw adcd; 596a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com // createGeom transforms the geometry to device space when the matrix does not have 597a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com // perspective. 5988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com if (!drawState->getViewMatrix().hasPerspective()) { 599a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com adcd.set(drawState); 600a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com if (!adcd.succeeded()) { 601e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return false; 602dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 603aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 604fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 605aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // TODO: See whether rendering lines as degenerate quads improves perf 606aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // when we have a mix 607a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 6084647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com enum { 6094647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // the edge effects share this stage with glyph rendering 6104647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // (kGlyphMaskStage in GrTextContext) && SW path rendering 6114647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // (kPathMaskStage in GrSWMaskHelper) 6124647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com kEdgeEffectStage = GrPaint::kTotalStages, 6134647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com }; 6144647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com static const int kEdgeAttrIndex = 1; 615a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 6164647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrEffectRef* hairLineEffect = GrEdgeEffect::Create(GrEdgeEffect::kHairLine_EdgeType); 6174647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrEffectRef* hairQuadEffect = GrEdgeEffect::Create(GrEdgeEffect::kHairQuad_EdgeType); 6184647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 619c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target->setIndexSourceToBuffer(fLinesIndexBuffer); 620aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int lines = 0; 621aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int nBufLines = fLinesIndexBuffer->maxQuads(); 6224647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unref(); 623c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com while (lines < lineCnt) { 624c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int n = GrMin(lineCnt - lines, nBufLines); 62547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 626c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerLineSeg*lines, // startV 627c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // startI 628c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerLineSeg*n, // vCount 629c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kIdxsPerLineSeg*n); // iCount 630aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com lines += n; 631aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 632aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 633c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target->setIndexSourceToBuffer(fQuadsIndexBuffer); 634aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int quads = 0; 6354647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com drawState->setEffect(kEdgeEffectStage, hairQuadEffect, kEdgeAttrIndex)->unref(); 636c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com while (quads < quadCnt) { 637c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); 63847059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 639c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 4 * lineCnt + kVertsPerQuad*quads, // startV 640c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // startI 641c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerQuad*n, // vCount 642c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kIdxsPerQuad*n); // iCount 643aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quads += n; 644aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 6454647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 646c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 647aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 648