1f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com/* 2f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * Copyright 2011 Google Inc. 3f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * 4f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 5f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * found in the LICENSE file. 6f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com */ 7f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com 8aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrAAHairLinePathRenderer.h" 9aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 10aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrContext.h" 119381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrDrawState.h" 12c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h" 13b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessor.h" 14aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrGpu.h" 15aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrIndexBuffer.h" 16dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com#include "GrPathUtils.h" 17b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 18aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "SkGeometry.h" 1912b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com#include "SkStroke.h" 20aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "SkTemplates.h" 21aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 2207e1c3fd5030869c480c15ff30d36bd161718262commit-bot@chromium.org#include "effects/GrBezierEffect.h" 234647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 24aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 25aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// quadratics are rendered as 5-sided polys in order to bound the 26aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// AA stroke around the center-curve. See comments in push_quad_index_buffer and 275383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// bloat_quad. Quadratics and conics share an index buffer 28aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kVertsPerQuad = 5; 29aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kIdxsPerQuad = 9; 30aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 31ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// lines are rendered as: 32ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// *______________* 33ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// |\ -_______ /| 34ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// | \ \ / | 35ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// | *--------* | 36ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// | / ______/ \ | 37ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// */_-__________\* 38ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// For: 6 vertices and 18 indices (for 6 triangles) 39681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstatic const int kVertsPerLineSeg = 6; 40ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.comstatic const int kIdxsPerLineSeg = 18; 41aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 42aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kNumQuadsInIdxBuffer = 256; 43aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const size_t kQuadIdxSBufize = kIdxsPerQuad * 44aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com sizeof(uint16_t) * 45aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com kNumQuadsInIdxBuffer; 46aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 47681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstatic const int kNumLineSegsInIdxBuffer = 256; 48681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstatic const size_t kLineSegIdxSBufize = kIdxsPerLineSeg * 49681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com sizeof(uint16_t) * 50681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kNumLineSegsInIdxBuffer; 51681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 52681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstatic bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) { 538341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org uint16_t* data = (uint16_t*) qIdxBuffer->map(); 54aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bool tempData = NULL == data; 55aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (tempData) { 56c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad); 57aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 58aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) { 59aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 60aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // Each quadratic is rendered as a five sided polygon. This poly bounds 61aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // the quadratic's bounding triangle but has been expanded so that the 62aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // 1-pixel wide area around the curve is inside the poly. 63aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // If a,b,c are the original control points then the poly a0,b0,c0,c1,a1 64aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // that is rendered would look like this: 65aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // b0 66aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // b 67aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // 68aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a0 c0 69aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a c 70aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a1 c1 710e5104c1570de4709e04720e62d80a0ca8970260bsalomon@google.com // Each is drawn as three triangles specified by these 9 indices: 72aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int baseIdx = i * kIdxsPerQuad; 73aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com uint16_t baseVert = (uint16_t)(i * kVertsPerQuad); 74aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[0 + baseIdx] = baseVert + 0; // a0 75aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[1 + baseIdx] = baseVert + 1; // a1 76aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[2 + baseIdx] = baseVert + 2; // b0 77aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[3 + baseIdx] = baseVert + 2; // b0 78aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[4 + baseIdx] = baseVert + 4; // c1 79aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[5 + baseIdx] = baseVert + 3; // c0 80aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[6 + baseIdx] = baseVert + 1; // a1 81aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[7 + baseIdx] = baseVert + 4; // c1 82aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[8 + baseIdx] = baseVert + 2; // b0 83aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 84aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (tempData) { 85aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bool ret = qIdxBuffer->updateData(data, kQuadIdxSBufize); 86aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com delete[] data; 87aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return ret; 88aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 898341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org qIdxBuffer->unmap(); 90aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 91aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 92aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 93681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 94681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstatic bool push_line_index_data(GrIndexBuffer* lIdxBuffer) { 958341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org uint16_t* data = (uint16_t*) lIdxBuffer->map(); 96681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com bool tempData = NULL == data; 97681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (tempData) { 98681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com data = SkNEW_ARRAY(uint16_t, kNumLineSegsInIdxBuffer * kIdxsPerLineSeg); 99681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 100681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com for (int i = 0; i < kNumLineSegsInIdxBuffer; ++i) { 101ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // Each line segment is rendered as two quads and two triangles. 102ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // p0 and p1 have alpha = 1 while all other points have alpha = 0. 103ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // The four external points are offset 1 pixel perpendicular to the 104ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // line and half a pixel parallel to the line. 105681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // 106681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // p4 p5 107ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // p0 p1 108681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // p2 p3 109681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // 110ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // Each is drawn as six triangles specified by these 18 indices: 111681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int baseIdx = i * kIdxsPerLineSeg; 112681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com uint16_t baseVert = (uint16_t)(i * kVertsPerLineSeg); 113ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[0 + baseIdx] = baseVert + 0; 114ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[1 + baseIdx] = baseVert + 1; 115ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[2 + baseIdx] = baseVert + 3; 1167475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 117ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[3 + baseIdx] = baseVert + 0; 118ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[4 + baseIdx] = baseVert + 3; 119ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[5 + baseIdx] = baseVert + 2; 1207475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 121ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[6 + baseIdx] = baseVert + 0; 122ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[7 + baseIdx] = baseVert + 4; 123ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[8 + baseIdx] = baseVert + 5; 1247475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 125ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[9 + baseIdx] = baseVert + 0; 126ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[10+ baseIdx] = baseVert + 5; 127ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[11+ baseIdx] = baseVert + 1; 128ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com 129ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[12 + baseIdx] = baseVert + 0; 130ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[13 + baseIdx] = baseVert + 2; 131ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[14 + baseIdx] = baseVert + 4; 132ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com 133ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[15 + baseIdx] = baseVert + 1; 134ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[16 + baseIdx] = baseVert + 5; 135ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com data[17 + baseIdx] = baseVert + 3; 136681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 137681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (tempData) { 138681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com bool ret = lIdxBuffer->updateData(data, kLineSegIdxSBufize); 139681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com delete[] data; 140681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return ret; 141681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } else { 1428341eb76fbc54593e873f5589961e02793e7f15fcommit-bot@chromium.org lIdxBuffer->unmap(); 143681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return true; 144681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 145681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com} 146aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 147aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 148aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { 149a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrGpu* gpu = context->getGpu(); 150a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false); 151a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf); 152681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (NULL == qIdxBuf || !push_quad_index_data(qIdxBuf)) { 153681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return NULL; 154681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 155681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrIndexBuffer* lIdxBuf = gpu->createIndexBuffer(kLineSegIdxSBufize, false); 156681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkAutoTUnref<GrIndexBuffer> lIdxBuffer(lIdxBuf); 157681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (NULL == lIdxBuf || !push_line_index_data(lIdxBuf)) { 158a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com return NULL; 159a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com } 160c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com return SkNEW_ARGS(GrAAHairLinePathRenderer, 161681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com (context, lIdxBuf, qIdxBuf)); 162aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 163aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 164aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::GrAAHairLinePathRenderer( 165aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrContext* context, 166aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* linesIndexBuffer, 167aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* quadsIndexBuffer) { 168aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer = linesIndexBuffer; 169aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com linesIndexBuffer->ref(); 170aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer = quadsIndexBuffer; 171aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadsIndexBuffer->ref(); 172aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 173aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 174aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() { 175aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer->unref(); 176aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer->unref(); 177aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 178aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 179aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 180aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 18192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true> 182aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 183aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// Takes 178th time of logf on Z600 / VC2010 184aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint get_float_exp(float x) { 185aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GR_STATIC_ASSERT(sizeof(int) == sizeof(float)); 186515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG 187aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static bool tested; 188aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (!tested) { 189aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com tested = true; 190f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(0.25f) == -2); 191f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(0.3f) == -2); 192f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(0.5f) == -1); 193f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(1.f) == 0); 194f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(2.f) == 1); 195f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(2.5f) == 1); 196f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(8.f) == 3); 197f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(100.f) == 6); 198f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(1000.f) == 9); 199f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(1024.f) == 10); 200f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(3000000.f) == 21); 201aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 202aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#endif 2032ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com const int* iptr = (const int*)&x; 2042ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com return (((*iptr) & 0x7f800000) >> 23) - 127; 205aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 206aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 2075383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// Uses the max curvature function for quads to estimate 2085383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// where to chop the conic. If the max curvature is not 2095383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// found along the curve segment it will return 1 and 2103f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// dst[0] is the original conic. If it returns 2 the dst[0] 2115383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// and dst[1] are the two new conics. 2123f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.comint split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) { 2135383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkScalar t = SkFindQuadMaxCurvature(src); 2145383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (t == 0) { 2155383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (dst) { 2165383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com dst[0].set(src, weight); 2175383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 2185383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 1; 2195383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } else { 2205383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (dst) { 2215383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkConic conic; 2225383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com conic.set(src, weight); 2235383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com conic.chopAt(t, dst); 2245383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 2255383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 2; 2265383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 2275383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 2285383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 2293f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// Calls split_conic on the entire conic and then once more on each subsection. 2303f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// Most cases will result in either 1 conic (chop point is not within t range) 2313f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// or 3 points (split once and then one subsection is split again). 2323f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.comint chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) { 2333f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkConic dstTemp[2]; 2343f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com int conicCnt = split_conic(src, dstTemp, weight); 2353f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com if (2 == conicCnt) { 2363f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW); 2373f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW); 2383f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com } else { 2393f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com dst[0] = dstTemp[0]; 2403f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com } 2413f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com return conicCnt; 2423f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com} 2433f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com 2445383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// returns 0 if quad/conic is degen or close to it 2455383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// in this case approx the path with lines 2465383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// otherwise returns 1 2475383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.comint is_degen_quad_or_conic(const SkPoint p[3]) { 2485383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com static const SkScalar gDegenerateToLineTol = SK_Scalar1; 2495383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com static const SkScalar gDegenerateToLineTolSqd = 2505383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 2515383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 2525383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 2535383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 2545383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 1; 2555383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 2565383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 2575383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); 2585383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (dsqd < gDegenerateToLineTolSqd) { 2595383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 1; 2605383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 2615383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 2625383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { 2635383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 1; 2645383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 2655383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 0; 2665383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 2675383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 268aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// we subdivide the quads to avoid huge overfill 269aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// if it returns -1 then should be drawn as lines 270aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint num_quad_subdivs(const SkPoint p[3]) { 271aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gDegenerateToLineTol = SK_Scalar1; 272fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static const SkScalar gDegenerateToLineTolSqd = 27346a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 27446a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 27546a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 27646a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 27746a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com return -1; 27846a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com } 279aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 28081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); 28146a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (dsqd < gDegenerateToLineTolSqd) { 282aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 283aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 28446a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 28546a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { 286aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 287aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 288aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 289aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tolerance of triangle height in pixels 290aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tuned on windows Quadro FX 380 / Z600 291aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // trade off of fill vs cpu time on verts 292aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // maybe different when do this using gpu (geo or tess shaders) 293aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gSubdivTol = 175 * SK_Scalar1; 294aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 2957460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) { 296aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return 0; 297aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 29887379e17c5e95c6fe0d88b3b9ae134355cfafc66robertphillips@google.com static const int kMaxSub = 4; 299aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // subdividing the quad reduces d by 4. so we want x = log4(d/tol) 300aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log4(d*d/tol*tol)/2 301aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log2(d*d/tol*tol) 302aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 303aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // +1 since we're ignoring the mantissa contribution. 304aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1; 305972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org log = SkTMin(SkTMax(0, log), kMaxSub); 306aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return log; 307aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 308aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 309aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 310dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com/** 311dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Generates the lines and quads to be rendered. Lines are always recorded in 312dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * device space. We will do a device space bloat to account for the 1pixel 313dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * thickness. 314dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Quads are recorded in device space unless m contains 315dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * perspective, then in they are in src space. We do this because we will 316dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * subdivide large quads to reduce over-fill. This subdivision has to be 317dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * performed before applying the perspective matrix. 318dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com */ 319dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.comint generate_lines_and_quads(const SkPath& path, 320dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix& m, 321fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& devClipBounds, 322681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::PtArray* lines, 323681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::PtArray* quads, 324681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::PtArray* conics, 325681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::IntArray* quadSubdivCnts, 326681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::FloatArray* conicWeights) { 327aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPath::Iter iter(path, false); 328aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 329aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int totalQuadCount = 0; 330fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkRect bounds; 331fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect ibounds; 332dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 333dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bool persp = m.hasPerspective(); 334dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 335aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (;;) { 336972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint pathPts[4]; 337972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint devPts[4]; 338912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPath::Verb verb = iter.next(pathPts); 33994b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com switch (verb) { 3405383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com case SkPath::kConic_Verb: { 3413f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkConic dst[4]; 3423f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com // We chop the conics to create tighter clipping to hide error 3433f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com // that appears near max curvature of very thin conics. Thin 3443f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com // hyperbolas with high weight still show error. 3455383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com int conicCnt = chop_conic(pathPts, dst, iter.conicWeight()); 3465383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com for (int i = 0; i < conicCnt; ++i) { 3475383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkPoint* chopPnts = dst[i].fPts; 3485383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com m.mapPoints(devPts, chopPnts, 3); 3495383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com bounds.setBounds(devPts, 3); 3505383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 3515383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com bounds.roundOut(&ibounds); 3525383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 3535383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (is_degen_quad_or_conic(devPts)) { 3545383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkPoint* pts = lines->push_back_n(4); 3555383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[0] = devPts[0]; 3565383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[1] = devPts[1]; 3575383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[2] = devPts[1]; 3585383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[3] = devPts[2]; 3595383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } else { 3605383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com // when in perspective keep conics in src space 3615383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkPoint* cPts = persp ? chopPnts : devPts; 3625383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkPoint* pts = conics->push_back_n(3); 3635383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[0] = cPts[0]; 3645383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[1] = cPts[1]; 3655383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[2] = cPts[2]; 3665383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com conicWeights->push_back() = dst[i].fW; 3675383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 3685383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 3695383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 370277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com break; 3715383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 3725383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com case SkPath::kMove_Verb: 373aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 37494b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kLine_Verb: 375912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org m.mapPoints(devPts, pathPts, 2); 376dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 2); 377aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 378aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 3797b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 380a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(2); 381a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = devPts[0]; 382a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = devPts[1]; 383aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 384aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 385912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org case SkPath::kQuad_Verb: { 386912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint choppedPts[5]; 387912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // Chopping the quad helps when the quad is either degenerate or nearly degenerate. 388912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // When it is degenerate it allows the approximation with lines to work since the 389912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // chop point (if there is one) will be at the parabola's vertex. In the nearly 390912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // degenerate the QuadUVMatrix computed for the points is almost singular which 391912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // can cause rendering artifacts. 392912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org int n = SkChopQuadAtMaxCurvature(pathPts, choppedPts); 393912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org for (int i = 0; i < n; ++i) { 394912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint* quadPts = choppedPts + i * 2; 395912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org m.mapPoints(devPts, quadPts, 3); 396912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org bounds.setBounds(devPts, 3); 397912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org bounds.outset(SK_Scalar1, SK_Scalar1); 398912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org bounds.roundOut(&ibounds); 399912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org 400912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org if (SkIRect::Intersects(devClipBounds, ibounds)) { 401912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org int subdiv = num_quad_subdivs(devPts); 402f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(subdiv >= -1); 403912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org if (-1 == subdiv) { 404912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint* pts = lines->push_back_n(4); 405912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[0] = devPts[0]; 406912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[1] = devPts[1]; 407912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[2] = devPts[1]; 408912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[3] = devPts[2]; 409912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org } else { 410912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // when in perspective keep quads in src space 411912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint* qPts = persp ? quadPts : devPts; 412912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint* pts = quads->push_back_n(3); 413912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[0] = qPts[0]; 414912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[1] = qPts[1]; 415912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[2] = qPts[2]; 416912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org quadSubdivCnts->push_back() = subdiv; 417912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org totalQuadCount += 1 << subdiv; 418912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org } 419aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 420aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 421a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 422912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org } 42394b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kCubic_Verb: 424912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org m.mapPoints(devPts, pathPts, 4); 425dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 4); 426aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 427aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 4287b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 42992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(32) q; 430a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // we don't need a direction if we aren't constraining the subdivision 431a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction; 43269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // We convert cubics to quadratics (for now). 43369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // In perspective have to do conversion in src space. 434dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 435fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkScalar tolScale = 436dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m, 437dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com path.getBounds()); 438912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org GrPathUtils::convertCubicToQuads(pathPts, tolScale, false, kDummyDir, &q); 439dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 440a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, false, kDummyDir, &q); 441dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 442aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < q.count(); i += 3) { 443dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint* qInDevSpace; 444dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // bounds has to be calculated in device space, but q is 445dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // in src space when there is perspective. 446dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 447dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, &q[i], 3); 448dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 3); 449dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = devPts; 450dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 451dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(&q[i], 3); 452dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = &q[i]; 453dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 454aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 455aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 4567b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 457dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com int subdiv = num_quad_subdivs(qInDevSpace); 458f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(subdiv >= -1); 459aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (-1 == subdiv) { 460a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(4); 461dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // lines should always be in device coords 462a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = qInDevSpace[0]; 463a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = qInDevSpace[1]; 464a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = qInDevSpace[1]; 465a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[3] = qInDevSpace[2]; 466aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 467a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 468dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // q is already in src space when there is no 469dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // perspective and dev coords otherwise. 470a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = q[0 + i]; 471a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = q[1 + i]; 472a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = q[2 + i]; 473aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadSubdivCnts->push_back() = subdiv; 474aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com totalQuadCount += 1 << subdiv; 475aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 476aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 477aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 478aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 479a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 48094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kClose_Verb: 481aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 48294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kDone_Verb: 483aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return totalQuadCount; 484aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 485aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 486aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 487aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 488681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstruct LineVertex { 489972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint fPos; 490681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrColor fCoverage; 491681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com}; 4927475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 493681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstruct BezierVertex { 494972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint fPos; 495aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com union { 496aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 4973f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkScalar fK; 4983f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkScalar fL; 4993f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkScalar fM; 5005383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } fConic; 501972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkVector fQuadCoord; 502aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 5033f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkScalar fBogus[4]; 504aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 505aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 506aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com}; 5075383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 508972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orgGR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(SkPoint)); 509aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 510aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid intersect_lines(const SkPoint& ptA, const SkVector& normA, 511aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& ptB, const SkVector& normB, 512aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint* result) { 513aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 514aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineAW = -normA.dot(ptA); 515aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineBW = -normB.dot(ptB); 516aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 517aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - 5185383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkScalarMul(normA.fY, normB.fX); 519aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com wInv = SkScalarInvert(wInv); 520aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 521aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); 522aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(result->fX, wInv); 523fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 524aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); 525aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(result->fY, wInv); 526aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 527aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 528681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comvoid set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kVertsPerQuad]) { 52934b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com // this should be in the src space, not dev coords, when we have perspective 53034b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com GrPathUtils::QuadUVMatrix DevToUV(qpts); 531972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org DevToUV.apply<kVertsPerQuad, sizeof(BezierVertex), sizeof(SkPoint)>(verts); 53234b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com} 53334b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com 534b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.comvoid bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 535681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const SkMatrix* toSrc, BezierVertex verts[kVertsPerQuad], 5361dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect* devBounds) { 537f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(!toDevice == !toSrc); 538aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // original quad is specified by tri a,b,c 539dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint a = qpts[0]; 540dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint b = qpts[1]; 541dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint c = qpts[2]; 542aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 543dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toDevice) { 544dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&a, 1); 545dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&b, 1); 546dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&c, 1); 547dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 548dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // make a new poly where we replace a and c by a 1-pixel wide edges orthog 549dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // to edges ab and bc: 550dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 551dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // before | after 552dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | b0 553dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // b | 554dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | 555dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | a0 c0 556dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // a c | a1 c1 557dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 558dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c, 559dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // respectively. 560681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& a0 = verts[0]; 561681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& a1 = verts[1]; 562681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& b0 = verts[2]; 563681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& c0 = verts[3]; 564681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& c1 = verts[4]; 565dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 566aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ab = b; 567aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab -= a; 568aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ac = c; 569aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ac -= a; 570aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cb = b; 571aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb -= c; 572aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 573aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // We should have already handled degenerates 574f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(ab.length() > 0 && cb.length() > 0); 575aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 576aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab.normalize(); 577aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector abN; 578aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.setOrthog(ab, SkVector::kLeft_Side); 579aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (abN.dot(ac) > 0) { 580aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.negate(); 581aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 582aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 583aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb.normalize(); 584aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cbN; 585aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.setOrthog(cb, SkVector::kLeft_Side); 586aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (cbN.dot(ac) < 0) { 587aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.negate(); 588aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 589aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 590aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos = a; 591aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos += abN; 592aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos = a; 593aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos -= abN; 594aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 595aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos = c; 596aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos += cbN; 597aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos = c; 598aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos -= cbN; 599aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 600aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 601b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org devBounds->growToInclude(&verts[0].fPos, sizeof(BezierVertex), kVertsPerQuad); 602aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 603dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toSrc) { 604681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kVertsPerQuad); 605dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 606aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 607aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 6083f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// Equations based off of Loop-Blinn Quadratic GPU Rendering 6095383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// Input Parametric: 6105383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2) 6115383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// Output Implicit: 6123f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// f(x, y, w) = f(P) = K^2 - LM 6133f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// K = dot(k, P), L = dot(l, P), M = dot(m, P) 614139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org// k, l, m are calculated in function GrPathUtils::getConicKLM 615139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.orgvoid set_conic_coeffs(const SkPoint p[3], BezierVertex verts[kVertsPerQuad], 616139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org const SkScalar weight) { 617139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org SkScalar klm[9]; 6183f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com 619139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org GrPathUtils::getConicKLM(p, weight, klm); 6205383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 6215383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com for (int i = 0; i < kVertsPerQuad; ++i) { 6223f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com const SkPoint pnt = verts[i].fPos; 623139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org verts[i].fConic.fK = pnt.fX * klm[0] + pnt.fY * klm[1] + klm[2]; 624139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org verts[i].fConic.fL = pnt.fX * klm[3] + pnt.fY * klm[4] + klm[5]; 625139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org verts[i].fConic.fM = pnt.fX * klm[6] + pnt.fY * klm[7] + klm[8]; 6265383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 6275383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 6285383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 6295383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.comvoid add_conics(const SkPoint p[3], 630139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org const SkScalar weight, 6315383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com const SkMatrix* toDevice, 6325383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com const SkMatrix* toSrc, 633681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex** vert, 6345383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkRect* devBounds) { 6355383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com bloat_quad(p, toDevice, toSrc, *vert, devBounds); 6365383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com set_conic_coeffs(p, *vert, weight); 6375383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com *vert += kVertsPerQuad; 6385383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 6395383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 640aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_quads(const SkPoint p[3], 641aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int subdiv, 642b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice, 643b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, 644681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex** vert, 6451dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect* devBounds) { 646f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(subdiv >= 0); 647aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (subdiv) { 648aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint newP[5]; 649aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkChopQuadAtHalf(p, newP); 6501dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); 6511dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); 652aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 6531dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com bloat_quad(p, toDevice, toSrc, *vert, devBounds); 65434b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com set_uv_quad(p, *vert); 655aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerQuad; 656aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 657aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 658aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 659aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_line(const SkPoint p[2], 660dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix* toSrc, 661681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrColor coverage, 662681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com LineVertex** vert) { 663aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& a = p[0]; 664aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& b = p[1]; 665aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 666ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com SkVector ortho, vec = b; 667ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com vec -= a; 668ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com 669ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com if (vec.setLength(SK_ScalarHalf)) { 670ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // Create a vector orthogonal to 'vec' and of unit length 671ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com ortho.fX = 2.0f * vec.fY; 672ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com ortho.fY = -2.0f * vec.fX; 673ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com 674ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[0].fPos = a; 675ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[0].fCoverage = coverage; 676ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[1].fPos = b; 677ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[1].fCoverage = coverage; 678ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[2].fPos = a - vec + ortho; 679ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[2].fCoverage = 0; 680ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[3].fPos = b + vec + ortho; 681ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[3].fCoverage = 0; 682ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[4].fPos = a - vec - ortho; 683ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[4].fCoverage = 0; 684ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[5].fPos = b + vec - ortho; 685ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[5].fCoverage = 0; 686aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 68749f085dddff10473b6ebf832a974288300224e60bsalomon if (toSrc) { 688dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&(*vert)->fPos, 689681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com sizeof(LineVertex), 690dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com kVertsPerLineSeg); 691dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 692aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 693aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // just make it degenerate and likely offscreen 694681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com for (int i = 0; i < kVertsPerLineSeg; ++i) { 695681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax); 696681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 697aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 698aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 699aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerLineSeg; 700aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 701aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 702aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 703aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 70490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 70590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 7065e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.comnamespace { 7075e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 7085e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com// position + edge 709681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comextern const GrVertexAttrib gHairlineBezierAttribs[] = { 7105e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 711b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding} 7125e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com}; 713681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 714681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com// position + coverage 715681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comextern const GrVertexAttrib gHairlineLineAttribs[] = { 716681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 717972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding}, 718681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com}; 719681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 7205e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com}; 7215e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 722ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.combool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path, 723ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com GrDrawTarget* target, 724ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com const PtArray& lines, 725ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com int lineCnt, 726ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com GrDrawTarget::AutoReleaseGeometry* arg, 727ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com SkRect* devBounds) { 72885eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org GrDrawState* drawState = target->drawState(); 7295e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 730681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const SkMatrix& viewM = drawState->getViewMatrix(); 7315e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 732681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int vertCnt = kVertsPerLineSeg * lineCnt; 7335e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 7347b3d5ee72c2238aa239bce4d5b3aea98a437ca7aegdaniel drawState->setVertexAttribs<gHairlineLineAttribs>(SK_ARRAY_COUNT(gHairlineLineAttribs), 7357b3d5ee72c2238aa239bce4d5b3aea98a437ca7aegdaniel sizeof(LineVertex)); 7365e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 73785eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org if (!arg->set(target, vertCnt, 0)) { 73885eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org return false; 73985eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org } 7405e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 741681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices()); 7425e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 74385eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org const SkMatrix* toSrc = NULL; 74485eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org SkMatrix ivm; 7455e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 74685eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org if (viewM.hasPerspective()) { 74785eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org if (viewM.invert(&ivm)) { 74885eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org toSrc = &ivm; 74985eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org } 75085eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org } 751b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org devBounds->set(lines.begin(), lines.count()); 752681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com for (int i = 0; i < lineCnt; ++i) { 753e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org add_line(&lines[2*i], toSrc, drawState->getCoverageColor(), &verts); 7545e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com } 755f91e3d4f54de9976b6538decadd977b19e49eaddskia.committer@gmail.com // All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the end points. 7564b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org static const SkScalar kSqrtOfOneAndAQuarter = 1.118f; 75752c75262117aa1251c7ddaf78430a55b707b8db4robertphillips@google.com // Add a little extra to account for vector normalization precision. 75852c75262117aa1251c7ddaf78430a55b707b8db4robertphillips@google.com static const SkScalar kOutset = kSqrtOfOneAndAQuarter + SK_Scalar1 / 20; 759b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org devBounds->outset(kOutset, kOutset); 7605e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 761681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return true; 762681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com} 763681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 764681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.combool GrAAHairLinePathRenderer::createBezierGeom( 765681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const SkPath& path, 766681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget* target, 767681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const PtArray& quads, 768681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int quadCnt, 769681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const PtArray& conics, 770681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int conicCnt, 771681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const IntArray& qSubdivs, 772681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const FloatArray& cWeights, 773681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget::AutoReleaseGeometry* arg, 774681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkRect* devBounds) { 775681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawState* drawState = target->drawState(); 7767475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 777681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const SkMatrix& viewM = drawState->getViewMatrix(); 7787475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 779681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int vertCnt = kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt; 7807475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 7817b3d5ee72c2238aa239bce4d5b3aea98a437ca7aegdaniel int vAttribCnt = SK_ARRAY_COUNT(gHairlineBezierAttribs); 7827b3d5ee72c2238aa239bce4d5b3aea98a437ca7aegdaniel target->drawState()->setVertexAttribs<gHairlineBezierAttribs>(vAttribCnt, sizeof(BezierVertex)); 7837475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 784681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (!arg->set(target, vertCnt, 0)) { 785681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return false; 786681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 7877475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 788681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices()); 7897475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 790681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const SkMatrix* toDevice = NULL; 791681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const SkMatrix* toSrc = NULL; 792681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkMatrix ivm; 7937475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 794681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (viewM.hasPerspective()) { 795681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (viewM.invert(&ivm)) { 796681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com toDevice = &viewM; 797681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com toSrc = &ivm; 798681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 799681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 8007475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 801b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // Seed the dev bounds with some pts known to be inside. Each quad and conic grows the bounding 802b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // box to include its vertices. 803b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org SkPoint seedPts[2]; 804b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org if (quadCnt) { 805b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org seedPts[0] = quads[0]; 806b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org seedPts[1] = quads[2]; 807b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } else if (conicCnt) { 808b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org seedPts[0] = conics[0]; 809b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org seedPts[1] = conics[2]; 810b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } 81149f085dddff10473b6ebf832a974288300224e60bsalomon if (toDevice) { 812b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org toDevice->mapPoints(seedPts, 2); 813b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } 814b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org devBounds->set(seedPts[0], seedPts[1]); 815b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org 816aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int unsubdivQuadCnt = quads.count() / 3; 817aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < unsubdivQuadCnt; ++i) { 818f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(qSubdivs[i] >= 0); 8191dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); 820aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 8217475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 8225383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com // Start Conics 823681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com for (int i = 0; i < conicCnt; ++i) { 8245383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds); 8255383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 826aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 827aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 828aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 829e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, 830e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkStrokeRec& stroke, 8318a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const GrDrawTarget* target, 8328a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 833e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org if (!antiAlias) { 834e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org return false; 835e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org } 836e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org 837e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org if (!IsStrokeHairlineOrEquivalent(stroke, 838e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org target->getDrawState().getViewMatrix(), 839e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org NULL)) { 840c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 841c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 842c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 843e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (SkPath::kLine_SegmentMask == path.getSegmentMasks() || 8443f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com target->caps()->shaderDerivativeSupport()) { 8453f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com return true; 846c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 8473f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com return false; 848c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 849aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 850681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comtemplate <class VertexType> 851681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.combool check_bounds(GrDrawState* drawState, const SkRect& devBounds, void* vertices, int vCount) 852681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com{ 8531dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect tolDevBounds = devBounds; 854b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // The bounds ought to be tight, but in perspective the below code runs the verts 855b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // through the view matrix to get back to dev coords, which can introduce imprecision. 856b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org if (drawState->getViewMatrix().hasPerspective()) { 857b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org tolDevBounds.outset(SK_Scalar1 / 1000, SK_Scalar1 / 1000); 858b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } else { 859b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // Non-persp matrices cause this path renderer to draw in device space. 860b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org SkASSERT(drawState->getViewMatrix().isIdentity()); 861b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } 8621dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect actualBounds; 8637475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 864681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com VertexType* verts = reinterpret_cast<VertexType*>(vertices); 8651dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com bool first = true; 8661dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com for (int i = 0; i < vCount; ++i) { 8671dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkPoint pos = verts[i].fPos; 8681dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // This is a hack to workaround the fact that we move some degenerate segments offscreen. 8691dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (SK_ScalarMax == pos.fX) { 8701dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com continue; 8711dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 8721dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com drawState->getViewMatrix().mapPoints(&pos, 1); 8731dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (first) { 8741dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.set(pos.fX, pos.fY, pos.fX, pos.fY); 8751dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com first = false; 8761dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } else { 8771dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.growToInclude(pos.fX, pos.fY); 8781dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 8791dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 8801dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (!first) { 881681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return tolDevBounds.contains(actualBounds); 8821dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 8837475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 884681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return true; 885681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com} 8861dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com 887e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, 888e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkStrokeRec& stroke, 889681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget* target, 890681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com bool antiAlias) { 891681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawState* drawState = target->drawState(); 8927475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 893e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkScalar hairlineCoverage; 894e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org if (IsStrokeHairlineOrEquivalent(stroke, 895e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org target->getDrawState().getViewMatrix(), 896e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org &hairlineCoverage)) { 897e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * 898e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org target->getDrawState().getCoverage()); 899e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org target->drawState()->setCoverage(newCoverage); 900e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org } 901e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org 902681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkIRect devClipBounds; 903681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devClipBounds); 9047475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 905681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int lineCnt; 906681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int quadCnt; 907681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int conicCnt; 908681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com PREALLOC_PTARRAY(128) lines; 909681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com PREALLOC_PTARRAY(128) quads; 910681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com PREALLOC_PTARRAY(128) conics; 911681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com IntArray qSubdivs; 912681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com FloatArray cWeights; 913e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClipBounds, 914681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &lines, &quads, &conics, &qSubdivs, &cWeights); 915681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com lineCnt = lines.count() / 2; 916681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com conicCnt = conics.count() / 3; 9177475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 918681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // do lines first 919b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org if (lineCnt) { 920681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget::AutoReleaseGeometry arg; 921681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkRect devBounds; 922681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 923e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (!this->createLineGeom(path, 924681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target, 925681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com lines, 926681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com lineCnt, 927681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &arg, 928681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &devBounds)) { 929681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return false; 930eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com } 931aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 932681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget::AutoStateRestore asr; 933681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 934ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // createLineGeom transforms the geometry to device space when the matrix does not have 935681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // perspective. 936681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (target->getDrawState().getViewMatrix().hasPerspective()) { 937681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com asr.set(target, GrDrawTarget::kPreserve_ASRInit); 938681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { 939681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return false; 940681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 941681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawState* drawState = target->drawState(); 942681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 943681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // Check devBounds 94452c75262117aa1251c7ddaf78430a55b707b8db4robertphillips@google.com SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(), 94552c75262117aa1251c7ddaf78430a55b707b8db4robertphillips@google.com kVertsPerLineSeg * lineCnt)); 946681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 947681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com { 948681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawState::AutoRestoreEffects are(drawState); 949681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target->setIndexSourceToBuffer(fLinesIndexBuffer); 950681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int lines = 0; 951681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com while (lines < lineCnt) { 952972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org int n = SkTMin(lineCnt - lines, kNumLineSegsInIdxBuffer); 953681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 954681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kVertsPerLineSeg*lines, // startV 955681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 0, // startI 956681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kVertsPerLineSeg*n, // vCount 957ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com kIdxsPerLineSeg*n, // iCount 958ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com &devBounds); 959681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com lines += n; 960681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 9615383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 9625383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 9637475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 964681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // then quadratics/conics 965b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org if (quadCnt || conicCnt) { 966681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget::AutoReleaseGeometry arg; 967681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkRect devBounds; 9687475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 969e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (!this->createBezierGeom(path, 970681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target, 971681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com quads, 972681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com quadCnt, 973681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com conics, 974681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com conicCnt, 975681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com qSubdivs, 976681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com cWeights, 977681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &arg, 978681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &devBounds)) { 979681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return false; 980681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 9817475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 982681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget::AutoStateRestore asr; 9837475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 984681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // createGeom transforms the geometry to device space when the matrix does not have 985681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // perspective. 986681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com if (target->getDrawState().getViewMatrix().hasPerspective()) { 987681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com asr.set(target, GrDrawTarget::kPreserve_ASRInit); 988681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { 989681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return false; 990681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 991681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawState* drawState = target->drawState(); 992681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 993681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // Check devBounds 994681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices(), 995681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt)); 9967475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 997884624764c1c6e6763484d86c69ebb46080ec49ccommit-bot@chromium.org if (quadCnt > 0) { 998b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrGeometryProcessor* hairQuadProcessor = 999b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrQuadEffect::Create(kHairlineAA_GrProcessorEdgeType, *target->caps()); 1000b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkASSERT(hairQuadProcessor); 1001681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawState::AutoRestoreEffects are(drawState); 1002681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target->setIndexSourceToBuffer(fQuadsIndexBuffer); 1003b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt drawState->setGeometryProcessor(hairQuadProcessor)->unref(); 1004884624764c1c6e6763484d86c69ebb46080ec49ccommit-bot@chromium.org int quads = 0; 1005681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com while (quads < quadCnt) { 1006972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org int n = SkTMin(quadCnt - quads, kNumQuadsInIdxBuffer); 1007681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 1008681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kVertsPerQuad*quads, // startV 1009681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 0, // startI 1010681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kVertsPerQuad*n, // vCount 1011681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kIdxsPerQuad*n, // iCount 1012681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &devBounds); 1013681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com quads += n; 1014681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 1015681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 10167475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 1017884624764c1c6e6763484d86c69ebb46080ec49ccommit-bot@chromium.org if (conicCnt > 0) { 1018681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawState::AutoRestoreEffects are(drawState); 1019b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrGeometryProcessor* hairConicProcessor = GrConicEffect::Create( 1020b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt kHairlineAA_GrProcessorEdgeType, *target->caps()); 1021b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkASSERT(hairConicProcessor); 1022b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt drawState->setGeometryProcessor(hairConicProcessor)->unref(); 1023884624764c1c6e6763484d86c69ebb46080ec49ccommit-bot@chromium.org int conics = 0; 1024681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com while (conics < conicCnt) { 1025972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org int n = SkTMin(conicCnt - conics, kNumQuadsInIdxBuffer); 1026681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 1027681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kVertsPerQuad*(quadCnt + conics), // startV 1028681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 0, // startI 1029681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kVertsPerQuad*n, // vCount 1030681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com kIdxsPerQuad*n, // iCount 1031681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &devBounds); 1032681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com conics += n; 1033681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 10345383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 1035aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 10367475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 10370406b9e1faee06c6ecb2732a1bcf3b0e53104e07bsalomon@google.com target->resetIndexSource(); 10384647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 1039c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 1040aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 1041