GrAAHairLinePathRenderer.cpp revision 8dd688b7569df569a672a8a67b2db86a9d376cfc
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" 115478d427c6e67c986a3390162c8fec77c466058ajoshualitt#include "GrDefaultGeoProcFactory.h" 12c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h" 13aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrGpu.h" 14aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrIndexBuffer.h" 15dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com#include "GrPathUtils.h" 168dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel#include "GrPipelineBuilder.h" 175478d427c6e67c986a3390162c8fec77c466058ajoshualitt#include "GrProcessor.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.com// quadratics are rendered as 5-sided polys in order to bound the 25aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// AA stroke around the center-curve. See comments in push_quad_index_buffer and 265383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// bloat_quad. Quadratics and conics share an index buffer 27aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 28ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// lines are rendered as: 29ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// *______________* 30ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// |\ -_______ /| 31ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// | \ \ / | 32ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// | *--------* | 33ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// | / ______/ \ | 34ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// */_-__________\* 35ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com// For: 6 vertices and 18 indices (for 6 triangles) 36681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 375ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// Each quadratic is rendered as a five sided polygon. This poly bounds 385ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// the quadratic's bounding triangle but has been expanded so that the 395ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// 1-pixel wide area around the curve is inside the poly. 405ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// If a,b,c are the original control points then the poly a0,b0,c0,c1,a1 415ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// that is rendered would look like this: 425ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// b0 435ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// b 445ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// 455ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// a0 c0 465ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// a c 475ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// a1 c1 4814afb43b01e178b50674d16a5a62d2b7dbd600dbegdaniel// Each is drawn as three triangles ((a0,a1,b0), (b0,c1,c0), (a1,c1,b0)) 4914afb43b01e178b50674d16a5a62d2b7dbd600dbegdaniel// specified by these 9 indices: 505ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittstatic const uint16_t kQuadIdxBufPattern[] = { 515ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, 1, 2, 525ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 2, 4, 3, 535ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 1, 4, 2 545ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt}; 555ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 565ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittstatic const int kIdxsPerQuad = SK_ARRAY_COUNT(kQuadIdxBufPattern); 575ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittstatic const int kQuadNumVertices = 5; 585ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittstatic const int kQuadsNumInIdxBuffer = 256; 595ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 605ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 615ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// Each line segment is rendered as two quads and two triangles. 625ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// p0 and p1 have alpha = 1 while all other points have alpha = 0. 635ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// The four external points are offset 1 pixel perpendicular to the 645ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// line and half a pixel parallel to the line. 655ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// 665ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// p4 p5 675ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// p0 p1 685ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// p2 p3 695ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// 705ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt// Each is drawn as six triangles specified by these 18 indices: 715ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 725ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittstatic const uint16_t kLineSegIdxBufPattern[] = { 735ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, 1, 3, 745ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, 3, 2, 755ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, 4, 5, 765ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, 5, 1, 775ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, 2, 4, 785ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 1, 5, 3 795ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt}; 805ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 815ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittstatic const int kIdxsPerLineSeg = SK_ARRAY_COUNT(kLineSegIdxBufPattern); 825ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittstatic const int kLineSegNumVertices = 6; 835ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittstatic const int kLineSegsNumInIdxBuffer = 256; 84aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 85aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { 86a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrGpu* gpu = context->getGpu(); 875ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt GrIndexBuffer* qIdxBuf = gpu->createInstancedIndexBuffer(kQuadIdxBufPattern, 885ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kIdxsPerQuad, 895ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kQuadsNumInIdxBuffer, 905ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kQuadNumVertices); 91a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf); 925ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt GrIndexBuffer* lIdxBuf = gpu->createInstancedIndexBuffer(kLineSegIdxBufPattern, 935ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kIdxsPerLineSeg, 945ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kLineSegsNumInIdxBuffer, 955ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kLineSegNumVertices); 96681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkAutoTUnref<GrIndexBuffer> lIdxBuffer(lIdxBuf); 97c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com return SkNEW_ARGS(GrAAHairLinePathRenderer, 98681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com (context, lIdxBuf, qIdxBuf)); 99aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 100aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 101aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::GrAAHairLinePathRenderer( 102aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrContext* context, 103aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* linesIndexBuffer, 104aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* quadsIndexBuffer) { 105aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer = linesIndexBuffer; 106aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com linesIndexBuffer->ref(); 107aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer = quadsIndexBuffer; 108aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadsIndexBuffer->ref(); 109aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 110aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 111aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() { 112aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer->unref(); 113aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer->unref(); 114aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 115aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 116aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 117aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 11892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true> 119aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 120aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// Takes 178th time of logf on Z600 / VC2010 121aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint get_float_exp(float x) { 122aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GR_STATIC_ASSERT(sizeof(int) == sizeof(float)); 123515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG 124aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static bool tested; 125aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (!tested) { 126aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com tested = true; 127f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(0.25f) == -2); 128f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(0.3f) == -2); 129f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(0.5f) == -1); 130f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(1.f) == 0); 131f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(2.f) == 1); 132f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(2.5f) == 1); 133f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(8.f) == 3); 134f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(100.f) == 6); 135f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(1000.f) == 9); 136f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(1024.f) == 10); 137f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(get_float_exp(3000000.f) == 21); 138aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 139aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#endif 1402ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com const int* iptr = (const int*)&x; 1412ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com return (((*iptr) & 0x7f800000) >> 23) - 127; 142aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 143aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 1445383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// Uses the max curvature function for quads to estimate 1455383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// where to chop the conic. If the max curvature is not 1465383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// found along the curve segment it will return 1 and 1473f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// dst[0] is the original conic. If it returns 2 the dst[0] 1485383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// and dst[1] are the two new conics. 1493f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.comint split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) { 1505383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkScalar t = SkFindQuadMaxCurvature(src); 1515383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (t == 0) { 1525383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (dst) { 1535383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com dst[0].set(src, weight); 1545383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 1555383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 1; 1565383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } else { 1575383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (dst) { 1585383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkConic conic; 1595383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com conic.set(src, weight); 1605383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com conic.chopAt(t, dst); 1615383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 1625383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 2; 1635383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 1645383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 1655383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 1663f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// Calls split_conic on the entire conic and then once more on each subsection. 1673f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// Most cases will result in either 1 conic (chop point is not within t range) 1683f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// or 3 points (split once and then one subsection is split again). 1693f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.comint chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) { 1703f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkConic dstTemp[2]; 1713f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com int conicCnt = split_conic(src, dstTemp, weight); 1723f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com if (2 == conicCnt) { 1733f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW); 1743f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW); 1753f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com } else { 1763f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com dst[0] = dstTemp[0]; 1773f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com } 1783f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com return conicCnt; 1793f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com} 1803f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com 1815383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// returns 0 if quad/conic is degen or close to it 1825383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// in this case approx the path with lines 1835383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// otherwise returns 1 1845383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.comint is_degen_quad_or_conic(const SkPoint p[3]) { 1855383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com static const SkScalar gDegenerateToLineTol = SK_Scalar1; 1865383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com static const SkScalar gDegenerateToLineTolSqd = 1875383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 1885383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 1895383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 1905383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 1915383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 1; 1925383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 1935383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 1945383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); 1955383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (dsqd < gDegenerateToLineTolSqd) { 1965383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 1; 1975383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 1985383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 1995383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { 2005383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 1; 2015383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 2025383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com return 0; 2035383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 2045383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 205aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// we subdivide the quads to avoid huge overfill 206aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// if it returns -1 then should be drawn as lines 207aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint num_quad_subdivs(const SkPoint p[3]) { 208aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gDegenerateToLineTol = SK_Scalar1; 209fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static const SkScalar gDegenerateToLineTolSqd = 21046a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 21146a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 21246a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 21346a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 21446a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com return -1; 21546a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com } 216aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 21781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); 21846a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (dsqd < gDegenerateToLineTolSqd) { 219aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 220aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 22146a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 22246a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { 223aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 224aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 225aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 226aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tolerance of triangle height in pixels 227aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tuned on windows Quadro FX 380 / Z600 228aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // trade off of fill vs cpu time on verts 229aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // maybe different when do this using gpu (geo or tess shaders) 230aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gSubdivTol = 175 * SK_Scalar1; 231aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 2327460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) { 233aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return 0; 234aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 23587379e17c5e95c6fe0d88b3b9ae134355cfafc66robertphillips@google.com static const int kMaxSub = 4; 236aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // subdividing the quad reduces d by 4. so we want x = log4(d/tol) 237aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log4(d*d/tol*tol)/2 238aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log2(d*d/tol*tol) 239aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 240aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // +1 since we're ignoring the mantissa contribution. 241aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1; 242972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org log = SkTMin(SkTMax(0, log), kMaxSub); 243aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return log; 244aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 245aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 246aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 247dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com/** 248dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Generates the lines and quads to be rendered. Lines are always recorded in 249dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * device space. We will do a device space bloat to account for the 1pixel 250dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * thickness. 251dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Quads are recorded in device space unless m contains 252dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * perspective, then in they are in src space. We do this because we will 253dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * subdivide large quads to reduce over-fill. This subdivision has to be 254dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * performed before applying the perspective matrix. 255dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com */ 256dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.comint generate_lines_and_quads(const SkPath& path, 257dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix& m, 258fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& devClipBounds, 259681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::PtArray* lines, 260681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::PtArray* quads, 261681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::PtArray* conics, 262681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::IntArray* quadSubdivCnts, 263681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrAAHairLinePathRenderer::FloatArray* conicWeights) { 264aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPath::Iter iter(path, false); 265aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 266aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int totalQuadCount = 0; 267fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkRect bounds; 268fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect ibounds; 269dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 270dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bool persp = m.hasPerspective(); 271dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 272aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (;;) { 273972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint pathPts[4]; 274972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint devPts[4]; 275912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPath::Verb verb = iter.next(pathPts); 27694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com switch (verb) { 2775383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com case SkPath::kConic_Verb: { 2783f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkConic dst[4]; 2793f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com // We chop the conics to create tighter clipping to hide error 2803f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com // that appears near max curvature of very thin conics. Thin 2813f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com // hyperbolas with high weight still show error. 2825383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com int conicCnt = chop_conic(pathPts, dst, iter.conicWeight()); 2835383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com for (int i = 0; i < conicCnt; ++i) { 2845383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkPoint* chopPnts = dst[i].fPts; 2855383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com m.mapPoints(devPts, chopPnts, 3); 2865383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com bounds.setBounds(devPts, 3); 2875383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 2885383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com bounds.roundOut(&ibounds); 2895383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 2905383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com if (is_degen_quad_or_conic(devPts)) { 2915383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkPoint* pts = lines->push_back_n(4); 2925383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[0] = devPts[0]; 2935383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[1] = devPts[1]; 2945383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[2] = devPts[1]; 2955383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[3] = devPts[2]; 2965383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } else { 2975383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com // when in perspective keep conics in src space 2985383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkPoint* cPts = persp ? chopPnts : devPts; 2995383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkPoint* pts = conics->push_back_n(3); 3005383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[0] = cPts[0]; 3015383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[1] = cPts[1]; 3025383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com pts[2] = cPts[2]; 3035383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com conicWeights->push_back() = dst[i].fW; 3045383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 3055383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 3065383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 307277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com break; 3085383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 3095383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com case SkPath::kMove_Verb: 310aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 31194b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kLine_Verb: 312912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org m.mapPoints(devPts, pathPts, 2); 313dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 2); 314aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 315aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 3167b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 317a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(2); 318a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = devPts[0]; 319a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = devPts[1]; 320aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 321aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 322912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org case SkPath::kQuad_Verb: { 323912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint choppedPts[5]; 324912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // Chopping the quad helps when the quad is either degenerate or nearly degenerate. 325912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // When it is degenerate it allows the approximation with lines to work since the 326912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // chop point (if there is one) will be at the parabola's vertex. In the nearly 327912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // degenerate the QuadUVMatrix computed for the points is almost singular which 328912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // can cause rendering artifacts. 329912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org int n = SkChopQuadAtMaxCurvature(pathPts, choppedPts); 330912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org for (int i = 0; i < n; ++i) { 331912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint* quadPts = choppedPts + i * 2; 332912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org m.mapPoints(devPts, quadPts, 3); 333912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org bounds.setBounds(devPts, 3); 334912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org bounds.outset(SK_Scalar1, SK_Scalar1); 335912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org bounds.roundOut(&ibounds); 336912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org 337912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org if (SkIRect::Intersects(devClipBounds, ibounds)) { 338912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org int subdiv = num_quad_subdivs(devPts); 339f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(subdiv >= -1); 340912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org if (-1 == subdiv) { 341912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint* pts = lines->push_back_n(4); 342912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[0] = devPts[0]; 343912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[1] = devPts[1]; 344912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[2] = devPts[1]; 345912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[3] = devPts[2]; 346912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org } else { 347912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org // when in perspective keep quads in src space 348912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint* qPts = persp ? quadPts : devPts; 349912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org SkPoint* pts = quads->push_back_n(3); 350912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[0] = qPts[0]; 351912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[1] = qPts[1]; 352912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org pts[2] = qPts[2]; 353912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org quadSubdivCnts->push_back() = subdiv; 354912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org totalQuadCount += 1 << subdiv; 355912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org } 356aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 357aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 358a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 359912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org } 36094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kCubic_Verb: 361912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org m.mapPoints(devPts, pathPts, 4); 362dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 4); 363aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 364aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 3657b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 36692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(32) q; 367a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // we don't need a direction if we aren't constraining the subdivision 368a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction; 36969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // We convert cubics to quadratics (for now). 37069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // In perspective have to do conversion in src space. 371dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 372fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkScalar tolScale = 373dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m, 374dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com path.getBounds()); 375912e68ec469f714ec76b5ed419e5b7ea10e45500commit-bot@chromium.org GrPathUtils::convertCubicToQuads(pathPts, tolScale, false, kDummyDir, &q); 376dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 377a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, false, kDummyDir, &q); 378dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 379aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < q.count(); i += 3) { 380dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint* qInDevSpace; 381dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // bounds has to be calculated in device space, but q is 382dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // in src space when there is perspective. 383dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 384dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, &q[i], 3); 385dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 3); 386dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = devPts; 387dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 388dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(&q[i], 3); 389dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = &q[i]; 390dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 391aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 392aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 3937b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 394dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com int subdiv = num_quad_subdivs(qInDevSpace); 395f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(subdiv >= -1); 396aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (-1 == subdiv) { 397a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(4); 398dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // lines should always be in device coords 399a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = qInDevSpace[0]; 400a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = qInDevSpace[1]; 401a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = qInDevSpace[1]; 402a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[3] = qInDevSpace[2]; 403aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 404a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 405dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // q is already in src space when there is no 406dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // perspective and dev coords otherwise. 407a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = q[0 + i]; 408a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = q[1 + i]; 409a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = q[2 + i]; 410aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadSubdivCnts->push_back() = subdiv; 411aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com totalQuadCount += 1 << subdiv; 412aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 413aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 414aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 415aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 416a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 41794b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kClose_Verb: 418aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 41994b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kDone_Verb: 420aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return totalQuadCount; 421aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 422aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 423aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 424aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 425681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstruct LineVertex { 426972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint fPos; 427e27065ae243575f6d5d545909ad3030773c14db8egdaniel float fCoverage; 428681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com}; 4297475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 430681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comstruct BezierVertex { 431972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint fPos; 432aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com union { 433aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 4343f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkScalar fK; 4353f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkScalar fL; 4363f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkScalar fM; 4375383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } fConic; 438972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkVector fQuadCoord; 439aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 4403f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com SkScalar fBogus[4]; 441aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 442aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 443aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com}; 4445383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 445972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orgGR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(SkPoint)); 446aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 447aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid intersect_lines(const SkPoint& ptA, const SkVector& normA, 448aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& ptB, const SkVector& normB, 449aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint* result) { 450aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 451aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineAW = -normA.dot(ptA); 452aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineBW = -normB.dot(ptB); 453aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 454aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - 4555383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkScalarMul(normA.fY, normB.fX); 456aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com wInv = SkScalarInvert(wInv); 457aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 458aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); 459aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(result->fX, wInv); 460fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 461aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); 462aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(result->fY, wInv); 463aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 464aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 4655ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittvoid set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) { 46634b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com // this should be in the src space, not dev coords, when we have perspective 46734b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com GrPathUtils::QuadUVMatrix DevToUV(qpts); 4685ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt DevToUV.apply<kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint)>(verts); 46934b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com} 47034b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com 471b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.comvoid bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 4725ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices], 4731dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect* devBounds) { 474f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(!toDevice == !toSrc); 475aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // original quad is specified by tri a,b,c 476dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint a = qpts[0]; 477dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint b = qpts[1]; 478dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint c = qpts[2]; 479aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 480dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toDevice) { 481dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&a, 1); 482dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&b, 1); 483dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&c, 1); 484dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 485dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // make a new poly where we replace a and c by a 1-pixel wide edges orthog 486dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // to edges ab and bc: 487dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 488dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // before | after 489dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | b0 490dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // b | 491dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | 492dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | a0 c0 493dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // a c | a1 c1 494dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 495dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c, 496dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // respectively. 497681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& a0 = verts[0]; 498681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& a1 = verts[1]; 499681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& b0 = verts[2]; 500681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& c0 = verts[3]; 501681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex& c1 = verts[4]; 502dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 503aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ab = b; 504aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab -= a; 505aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ac = c; 506aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ac -= a; 507aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cb = b; 508aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb -= c; 509aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 510aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // We should have already handled degenerates 511f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(ab.length() > 0 && cb.length() > 0); 512aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 513aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab.normalize(); 514aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector abN; 515aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.setOrthog(ab, SkVector::kLeft_Side); 516aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (abN.dot(ac) > 0) { 517aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.negate(); 518aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 519aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 520aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb.normalize(); 521aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cbN; 522aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.setOrthog(cb, SkVector::kLeft_Side); 523aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (cbN.dot(ac) < 0) { 524aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.negate(); 525aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 526aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 527aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos = a; 528aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos += abN; 529aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos = a; 530aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos -= abN; 531aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 532aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos = c; 533aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos += cbN; 534aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos = c; 535aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos -= cbN; 536aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 537aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 5385ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt devBounds->growToInclude(&verts[0].fPos, sizeof(BezierVertex), kQuadNumVertices); 539aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 540dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toSrc) { 5415ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kQuadNumVertices); 542dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 543aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 544aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5453f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// Equations based off of Loop-Blinn Quadratic GPU Rendering 5465383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// Input Parametric: 5475383a7525355dec72efa2083aeadffdd09a962b9egdaniel@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) 5485383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com// Output Implicit: 5493f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// f(x, y, w) = f(P) = K^2 - LM 5503f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com// K = dot(k, P), L = dot(l, P), M = dot(m, P) 551139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org// k, l, m are calculated in function GrPathUtils::getConicKLM 5525ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualittvoid set_conic_coeffs(const SkPoint p[3], BezierVertex verts[kQuadNumVertices], 553139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org const SkScalar weight) { 554139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org SkScalar klm[9]; 5553f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com 556139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org GrPathUtils::getConicKLM(p, weight, klm); 5575383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 5585ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt for (int i = 0; i < kQuadNumVertices; ++i) { 5593f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com const SkPoint pnt = verts[i].fPos; 560139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org verts[i].fConic.fK = pnt.fX * klm[0] + pnt.fY * klm[1] + klm[2]; 561139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org verts[i].fConic.fL = pnt.fX * klm[3] + pnt.fY * klm[4] + klm[5]; 562139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org verts[i].fConic.fM = pnt.fX * klm[6] + pnt.fY * klm[7] + klm[8]; 5635383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 5645383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 5655383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 5665383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.comvoid add_conics(const SkPoint p[3], 567139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org const SkScalar weight, 5685383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com const SkMatrix* toDevice, 5695383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com const SkMatrix* toSrc, 570681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex** vert, 5715383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com SkRect* devBounds) { 5725383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com bloat_quad(p, toDevice, toSrc, *vert, devBounds); 5735383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com set_conic_coeffs(p, *vert, weight); 5745ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt *vert += kQuadNumVertices; 5755383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com} 5765383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com 577aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_quads(const SkPoint p[3], 578aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int subdiv, 579b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice, 580b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, 581681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex** vert, 5821dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect* devBounds) { 583f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(subdiv >= 0); 584aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (subdiv) { 585aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint newP[5]; 586aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkChopQuadAtHalf(p, newP); 5871dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); 5881dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); 589aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 5901dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com bloat_quad(p, toDevice, toSrc, *vert, devBounds); 59134b05ca3799f4adc2994d57a22d78ae1bdf6fb4aegdaniel@google.com set_uv_quad(p, *vert); 5925ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt *vert += kQuadNumVertices; 593aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 594aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 595aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 596aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_line(const SkPoint p[2], 597dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix* toSrc, 598e27065ae243575f6d5d545909ad3030773c14db8egdaniel uint8_t coverage, 599681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com LineVertex** vert) { 600aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& a = p[0]; 601aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& b = p[1]; 602aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 603ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com SkVector ortho, vec = b; 604ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com vec -= a; 605ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com 606ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com if (vec.setLength(SK_ScalarHalf)) { 607ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com // Create a vector orthogonal to 'vec' and of unit length 608ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com ortho.fX = 2.0f * vec.fY; 609ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com ortho.fY = -2.0f * vec.fX; 610ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com 611e27065ae243575f6d5d545909ad3030773c14db8egdaniel float floatCoverage = GrNormalizeByteToFloat(coverage); 612e27065ae243575f6d5d545909ad3030773c14db8egdaniel 613ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[0].fPos = a; 614e27065ae243575f6d5d545909ad3030773c14db8egdaniel (*vert)[0].fCoverage = floatCoverage; 615ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[1].fPos = b; 616e27065ae243575f6d5d545909ad3030773c14db8egdaniel (*vert)[1].fCoverage = floatCoverage; 617ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[2].fPos = a - vec + ortho; 618ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[2].fCoverage = 0; 619ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[3].fPos = b + vec + ortho; 620ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[3].fCoverage = 0; 621ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[4].fPos = a - vec - ortho; 622ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[4].fCoverage = 0; 623ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[5].fPos = b + vec - ortho; 624ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com (*vert)[5].fCoverage = 0; 625aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 62649f085dddff10473b6ebf832a974288300224e60bsalomon if (toSrc) { 627dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&(*vert)->fPos, 628681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com sizeof(LineVertex), 6295ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kLineSegNumVertices); 630dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 631aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 632aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // just make it degenerate and likely offscreen 6335ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt for (int i = 0; i < kLineSegNumVertices; ++i) { 634681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax); 635681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 636aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 637aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 6385ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt *vert += kLineSegNumVertices; 639aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 640aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 641aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 642aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 64390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 64490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 6459853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrAAHairLinePathRenderer::createLineGeom(GrDrawTarget* target, 6468dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder* pipelineBuilder, 6478059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 6482e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt uint8_t coverage, 64956995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt size_t vertexStride, 650ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com GrDrawTarget::AutoReleaseGeometry* arg, 6519853ccef19c200be93a6211f32589fa82a53067cjoshualitt SkRect* devBounds, 6529853ccef19c200be93a6211f32589fa82a53067cjoshualitt const SkPath& path, 6539853ccef19c200be93a6211f32589fa82a53067cjoshualitt const PtArray& lines, 6549853ccef19c200be93a6211f32589fa82a53067cjoshualitt int lineCnt) { 6555ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt int vertCnt = kLineSegNumVertices * lineCnt; 6565e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 65756995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt SkASSERT(vertexStride == sizeof(LineVertex)); 65856995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt if (!arg->set(target, vertCnt, vertexStride, 0)) { 65985eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org return false; 66085eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org } 6615e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 662681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices()); 6635e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 66485eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org const SkMatrix* toSrc = NULL; 66585eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org SkMatrix ivm; 6665e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 6678059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (viewMatrix.hasPerspective()) { 6688059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (viewMatrix.invert(&ivm)) { 66985eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org toSrc = &ivm; 67085eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org } 67185eef600dfb5d4865e2db5db8ca2b8b23f898f7ccommit-bot@chromium.org } 672b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org devBounds->set(lines.begin(), lines.count()); 673681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com for (int i = 0; i < lineCnt; ++i) { 6742e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt add_line(&lines[2*i], toSrc, coverage, &verts); 6755e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com } 676f91e3d4f54de9976b6538decadd977b19e49eaddskia.committer@gmail.com // All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the end points. 6774b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org static const SkScalar kSqrtOfOneAndAQuarter = 1.118f; 67852c75262117aa1251c7ddaf78430a55b707b8db4robertphillips@google.com // Add a little extra to account for vector normalization precision. 67952c75262117aa1251c7ddaf78430a55b707b8db4robertphillips@google.com static const SkScalar kOutset = kSqrtOfOneAndAQuarter + SK_Scalar1 / 20; 680b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org devBounds->outset(kOutset, kOutset); 6815e2d270f6346125b322afa461d874a28edfa28d5jvanverth@google.com 682681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return true; 683681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com} 684681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 6859853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrAAHairLinePathRenderer::createBezierGeom(GrDrawTarget* target, 6868dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder* pipelineBuilder, 6878059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 6889853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawTarget::AutoReleaseGeometry* arg, 6899853ccef19c200be93a6211f32589fa82a53067cjoshualitt SkRect* devBounds, 6909853ccef19c200be93a6211f32589fa82a53067cjoshualitt const SkPath& path, 6919853ccef19c200be93a6211f32589fa82a53067cjoshualitt const PtArray& quads, 6929853ccef19c200be93a6211f32589fa82a53067cjoshualitt int quadCnt, 6939853ccef19c200be93a6211f32589fa82a53067cjoshualitt const PtArray& conics, 6949853ccef19c200be93a6211f32589fa82a53067cjoshualitt int conicCnt, 6959853ccef19c200be93a6211f32589fa82a53067cjoshualitt const IntArray& qSubdivs, 6962dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt const FloatArray& cWeights, 6972dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt size_t vertexStride) { 6985ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt int vertCnt = kQuadNumVertices * quadCnt + kQuadNumVertices * conicCnt; 6997475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 7002dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt if (!arg->set(target, vertCnt, vertexStride, 0)) { 701681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return false; 702681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 7037475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 704681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices()); 7057475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 706681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const SkMatrix* toDevice = NULL; 707681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com const SkMatrix* toSrc = NULL; 708681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkMatrix ivm; 7097475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 7108059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (viewMatrix.hasPerspective()) { 7118059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (viewMatrix.invert(&ivm)) { 7128059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt toDevice = &viewMatrix; 713681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com toSrc = &ivm; 714681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 715681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 7167475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 717b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // Seed the dev bounds with some pts known to be inside. Each quad and conic grows the bounding 718b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // box to include its vertices. 719b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org SkPoint seedPts[2]; 720b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org if (quadCnt) { 721b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org seedPts[0] = quads[0]; 722b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org seedPts[1] = quads[2]; 723b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } else if (conicCnt) { 724b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org seedPts[0] = conics[0]; 725b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org seedPts[1] = conics[2]; 726b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } 72749f085dddff10473b6ebf832a974288300224e60bsalomon if (toDevice) { 728b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org toDevice->mapPoints(seedPts, 2); 729b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } 730b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org devBounds->set(seedPts[0], seedPts[1]); 731b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org 732aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int unsubdivQuadCnt = quads.count() / 3; 733aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < unsubdivQuadCnt; ++i) { 734f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(qSubdivs[i] >= 0); 7351dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); 736aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 7377475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 7385383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com // Start Conics 739681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com for (int i = 0; i < conicCnt; ++i) { 7405383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds); 7415383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 742aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 743aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 744aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7459853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target, 7468dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel const GrPipelineBuilder* pipelineBuilder, 7478059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 7489853ccef19c200be93a6211f32589fa82a53067cjoshualitt const SkPath& path, 749e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkStrokeRec& stroke, 7508a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 751e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org if (!antiAlias) { 752e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org return false; 753e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org } 754e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org 7558059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (!IsStrokeHairlineOrEquivalent(stroke, viewMatrix, NULL)) { 756c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 757c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 758c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 759e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (SkPath::kLine_SegmentMask == path.getSegmentMasks() || 7603f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com target->caps()->shaderDerivativeSupport()) { 7613f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com return true; 762c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 7633f2a2d5fdc833dd20900ee90249b03474d0e00b3egdaniel@google.com return false; 764c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 765aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 766681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.comtemplate <class VertexType> 7678059eb9f6e24ed609393fbda4ad71edea03ac258joshualittbool check_bounds(const SkMatrix& viewMatrix, const SkRect& devBounds, void* vertices, int vCount) 768681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com{ 7691dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect tolDevBounds = devBounds; 770b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // The bounds ought to be tight, but in perspective the below code runs the verts 771b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // through the view matrix to get back to dev coords, which can introduce imprecision. 7728059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (viewMatrix.hasPerspective()) { 773b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org tolDevBounds.outset(SK_Scalar1 / 1000, SK_Scalar1 / 1000); 774b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } else { 775b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org // Non-persp matrices cause this path renderer to draw in device space. 7768059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkASSERT(viewMatrix.isIdentity()); 777b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org } 7781dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect actualBounds; 7797475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 780681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com VertexType* verts = reinterpret_cast<VertexType*>(vertices); 7811dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com bool first = true; 7821dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com for (int i = 0; i < vCount; ++i) { 7831dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkPoint pos = verts[i].fPos; 7841dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // This is a hack to workaround the fact that we move some degenerate segments offscreen. 7851dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (SK_ScalarMax == pos.fX) { 7861dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com continue; 7871dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 7888059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt viewMatrix.mapPoints(&pos, 1); 7891dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (first) { 7901dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.set(pos.fX, pos.fY, pos.fX, pos.fY); 7911dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com first = false; 7921dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } else { 7931dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.growToInclude(pos.fX, pos.fY); 7941dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 7951dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 7961dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (!first) { 797681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return tolDevBounds.contains(actualBounds); 7981dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 7997475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 800681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return true; 801681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com} 8021dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com 8039853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, 8048dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder* pipelineBuilder, 8052e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrColor color, 8068059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 8079853ccef19c200be93a6211f32589fa82a53067cjoshualitt const SkPath& path, 808e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkStrokeRec& stroke, 809681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com bool antiAlias) { 810e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkScalar hairlineCoverage; 8112e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt uint8_t newCoverage = 0xff; 8128059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) { 8132e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); 814e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org } 815e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org 816681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkIRect devClipBounds; 8178dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds); 8187475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 819681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int lineCnt; 820681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int quadCnt; 821681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int conicCnt; 822681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com PREALLOC_PTARRAY(128) lines; 823681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com PREALLOC_PTARRAY(128) quads; 824681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com PREALLOC_PTARRAY(128) conics; 825681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com IntArray qSubdivs; 826681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com FloatArray cWeights; 8278059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt quadCnt = generate_lines_and_quads(path, viewMatrix, devClipBounds, 828681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &lines, &quads, &conics, &qSubdivs, &cWeights); 829681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com lineCnt = lines.count() / 2; 830681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com conicCnt = conics.count() / 3; 8317475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 832d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt // createGeom transforms the geometry to device space when the matrix does not have 833d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt // perspective. 8348059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkMatrix vm = viewMatrix; 835d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt SkMatrix invert = SkMatrix::I(); 8368059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (!viewMatrix.hasPerspective()) { 8378059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt vm = SkMatrix::I(); 8388059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (!viewMatrix.invert(&invert)) { 839d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt return false; 840d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt } 841d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt } 842d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt 843681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // do lines first 844b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org if (lineCnt) { 845681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget::AutoReleaseGeometry arg; 846681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkRect devBounds; 847681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 8488dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); 8492dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType | 8502dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt GrDefaultGeoProcFactory::kCoverage_GPType; 8518059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkAutoTUnref<const GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Create(gpFlags, 8528059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt color, 8538059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt vm, 8548059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt invert, 85556995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt false, 8568059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt newCoverage)); 8572dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt 8589853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (!this->createLineGeom(target, 8598dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder, 8608059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt viewMatrix, 8612e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt newCoverage, 86256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt gp->getVertexStride(), 863681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &arg, 8649853ccef19c200be93a6211f32589fa82a53067cjoshualitt &devBounds, 8659853ccef19c200be93a6211f32589fa82a53067cjoshualitt path, 8669853ccef19c200be93a6211f32589fa82a53067cjoshualitt lines, 8679853ccef19c200be93a6211f32589fa82a53067cjoshualitt lineCnt)) { 868681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return false; 869eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com } 870aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 871681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // Check devBounds 8728059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkASSERT(check_bounds<LineVertex>(viewMatrix.hasPerspective() ? viewMatrix : SkMatrix::I(), 8738059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt devBounds, 8748059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt arg.vertices(), 8755ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kLineSegNumVertices * lineCnt)); 876681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com 877681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com { 878681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target->setIndexSourceToBuffer(fLinesIndexBuffer); 879681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com int lines = 0; 880681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com while (lines < lineCnt) { 8815ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer); 8828dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel target->drawIndexed(pipelineBuilder, 88356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt gp, 8849853ccef19c200be93a6211f32589fa82a53067cjoshualitt kTriangles_GrPrimitiveType, 8855ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kLineSegNumVertices*lines, // startV 8865ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, // startI 8875ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kLineSegNumVertices*n, // vCount 8885ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kIdxsPerLineSeg*n, // iCount 889ada90dac10fa804b49cac9d4e8aa036cb587044frobertphillips@google.com &devBounds); 890681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com lines += n; 891681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 8925383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 8935383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 8947475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 895681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // then quadratics/conics 896b8bd6cbbcde9846094ade18cafadfad46dc00889commit-bot@chromium.org if (quadCnt || conicCnt) { 897681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com GrDrawTarget::AutoReleaseGeometry arg; 898681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com SkRect devBounds; 8997475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 9009853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (!this->createBezierGeom(target, 9018dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder, 9028059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt viewMatrix, 9039853ccef19c200be93a6211f32589fa82a53067cjoshualitt &arg, 9049853ccef19c200be93a6211f32589fa82a53067cjoshualitt &devBounds, 9059853ccef19c200be93a6211f32589fa82a53067cjoshualitt path, 906681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com quads, 907681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com quadCnt, 908681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com conics, 909681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com conicCnt, 910681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com qSubdivs, 9112dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt cWeights, 9122dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt sizeof(BezierVertex))) { 913681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com return false; 914681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 9157475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 916681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com // Check devBounds 9178059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkASSERT(check_bounds<BezierVertex>(viewMatrix.hasPerspective() ? viewMatrix : 9188059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkMatrix::I(), 9198059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt devBounds, 9208059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt arg.vertices(), 9218059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt kQuadNumVertices * quadCnt + 9228059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt kQuadNumVertices * conicCnt)); 9237475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 924884624764c1c6e6763484d86c69ebb46080ec49ccommit-bot@chromium.org if (quadCnt > 0) { 92556995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt SkAutoTUnref<GrGeometryProcessor> hairQuadProcessor( 9262e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrQuadEffect::Create(color, 9278059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt vm, 9282e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt kHairlineAA_GrProcessorEdgeType, 9292e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt *target->caps(), 930d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt invert, 93156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt newCoverage)); 932b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkASSERT(hairQuadProcessor); 9338dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); 934681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com target->setIndexSourceToBuffer(fQuadsIndexBuffer); 9352dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt 936884624764c1c6e6763484d86c69ebb46080ec49ccommit-bot@chromium.org int quads = 0; 937681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com while (quads < quadCnt) { 9385ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt int n = SkTMin(quadCnt - quads, kQuadsNumInIdxBuffer); 9398dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel target->drawIndexed(pipelineBuilder, 94056995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt hairQuadProcessor, 9419853ccef19c200be93a6211f32589fa82a53067cjoshualitt kTriangles_GrPrimitiveType, 9425ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kQuadNumVertices*quads, // startV 9435ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, // startI 9445ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kQuadNumVertices*n, // vCount 9455ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kIdxsPerQuad*n, // iCount 946681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &devBounds); 947681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com quads += n; 948681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 949681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 9507475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 951884624764c1c6e6763484d86c69ebb46080ec49ccommit-bot@chromium.org if (conicCnt > 0) { 95256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt SkAutoTUnref<GrGeometryProcessor> hairConicProcessor( 9538059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt GrConicEffect::Create(color, vm, kHairlineAA_GrProcessorEdgeType, 9548059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt *target->caps(), invert, newCoverage)); 955b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkASSERT(hairConicProcessor); 9568dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); 95714afb43b01e178b50674d16a5a62d2b7dbd600dbegdaniel target->setIndexSourceToBuffer(fQuadsIndexBuffer); 9582dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt 959884624764c1c6e6763484d86c69ebb46080ec49ccommit-bot@chromium.org int conics = 0; 960681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com while (conics < conicCnt) { 9615ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt int n = SkTMin(conicCnt - conics, kQuadsNumInIdxBuffer); 9628dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel target->drawIndexed(pipelineBuilder, 96356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt hairConicProcessor, 9649853ccef19c200be93a6211f32589fa82a53067cjoshualitt kTriangles_GrPrimitiveType, 9655ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kQuadNumVertices*(quadCnt + conics), // startV 9665ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 0, // startI 9675ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kQuadNumVertices*n, // vCount 9685ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt kIdxsPerQuad*n, // iCount 969681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com &devBounds); 970681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com conics += n; 971681ccf08758d33f6307d8d466bbe8ffe0e8b9312jvanverth@google.com } 9725383a7525355dec72efa2083aeadffdd09a962b9egdaniel@google.com } 973aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 9747475811143e190e172bf83d13c4bdba85704b604skia.committer@gmail.com 9750406b9e1faee06c6ecb2732a1bcf3b0e53104e07bsalomon@google.com target->resetIndexSource(); 9764647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 977c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 978aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 979