1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2011 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef GrPathUtils_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define GrPathUtils_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h" 14*c8dee2aaSAndroid Build Coastguard Worker 15*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef> 16*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard Worker class SkMatrix; 19*c8dee2aaSAndroid Build Coastguard Worker enum class SkPathFirstDirection; 20*c8dee2aaSAndroid Build Coastguard Worker struct SkRect; 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker /** 23*c8dee2aaSAndroid Build Coastguard Worker * Utilities for evaluating paths. 24*c8dee2aaSAndroid Build Coastguard Worker */ 25*c8dee2aaSAndroid Build Coastguard Worker namespace GrPathUtils { 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker // When tessellating curved paths into linear segments, this defines the maximum distance in screen 28*c8dee2aaSAndroid Build Coastguard Worker // space which a segment may deviate from the mathematically correct value. Above this value, the 29*c8dee2aaSAndroid Build Coastguard Worker // segment will be subdivided. 30*c8dee2aaSAndroid Build Coastguard Worker // This value was chosen to approximate the supersampling accuracy of the raster path (16 samples, 31*c8dee2aaSAndroid Build Coastguard Worker // or one quarter pixel). 32*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar kDefaultTolerance = SkDoubleToScalar(0.25); 33*c8dee2aaSAndroid Build Coastguard Worker 34*c8dee2aaSAndroid Build Coastguard Worker // We guarantee that no quad or cubic will ever produce more than this many points 35*c8dee2aaSAndroid Build Coastguard Worker static const int kMaxPointsPerCurve = 1 << 10; 36*c8dee2aaSAndroid Build Coastguard Worker 37*c8dee2aaSAndroid Build Coastguard Worker // Very small tolerances will be increased to a minimum threshold value, to avoid division problems 38*c8dee2aaSAndroid Build Coastguard Worker // in subsequent math. 39*c8dee2aaSAndroid Build Coastguard Worker SkScalar scaleToleranceToSrc(SkScalar devTol, 40*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& viewM, 41*c8dee2aaSAndroid Build Coastguard Worker const SkRect& pathBounds); 42*c8dee2aaSAndroid Build Coastguard Worker 43*c8dee2aaSAndroid Build Coastguard Worker // Returns the maximum number of vertices required when using a recursive chopping algorithm to 44*c8dee2aaSAndroid Build Coastguard Worker // linearize the quadratic Bezier (e.g. generateQuadraticPoints below) to the given error tolerance. 45*c8dee2aaSAndroid Build Coastguard Worker // This is a power of two and will not exceed kMaxPointsPerCurve. 46*c8dee2aaSAndroid Build Coastguard Worker uint32_t quadraticPointCount(const SkPoint points[], SkScalar tol); 47*c8dee2aaSAndroid Build Coastguard Worker 48*c8dee2aaSAndroid Build Coastguard Worker // Returns the number of points actually written to 'points', will be <= to 'pointsLeft' 49*c8dee2aaSAndroid Build Coastguard Worker uint32_t generateQuadraticPoints(const SkPoint& p0, 50*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& p1, 51*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& p2, 52*c8dee2aaSAndroid Build Coastguard Worker SkScalar tolSqd, 53*c8dee2aaSAndroid Build Coastguard Worker SkPoint** points, 54*c8dee2aaSAndroid Build Coastguard Worker uint32_t pointsLeft); 55*c8dee2aaSAndroid Build Coastguard Worker 56*c8dee2aaSAndroid Build Coastguard Worker // Returns the maximum number of vertices required when using a recursive chopping algorithm to 57*c8dee2aaSAndroid Build Coastguard Worker // linearize the cubic Bezier (e.g. generateQuadraticPoints below) to the given error tolerance. 58*c8dee2aaSAndroid Build Coastguard Worker // This is a power of two and will not exceed kMaxPointsPerCurve. 59*c8dee2aaSAndroid Build Coastguard Worker uint32_t cubicPointCount(const SkPoint points[], SkScalar tol); 60*c8dee2aaSAndroid Build Coastguard Worker 61*c8dee2aaSAndroid Build Coastguard Worker // Returns the number of points actually written to 'points', will be <= to 'pointsLeft' 62*c8dee2aaSAndroid Build Coastguard Worker uint32_t generateCubicPoints(const SkPoint& p0, 63*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& p1, 64*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& p2, 65*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& p3, 66*c8dee2aaSAndroid Build Coastguard Worker SkScalar tolSqd, 67*c8dee2aaSAndroid Build Coastguard Worker SkPoint** points, 68*c8dee2aaSAndroid Build Coastguard Worker uint32_t pointsLeft); 69*c8dee2aaSAndroid Build Coastguard Worker 70*c8dee2aaSAndroid Build Coastguard Worker // A 2x3 matrix that goes from the 2d space coordinates to UV space where u^2-v = 0 specifies the 71*c8dee2aaSAndroid Build Coastguard Worker // quad. The matrix is determined by the control points of the quadratic. 72*c8dee2aaSAndroid Build Coastguard Worker class QuadUVMatrix { 73*c8dee2aaSAndroid Build Coastguard Worker public: QuadUVMatrix()74*c8dee2aaSAndroid Build Coastguard Worker QuadUVMatrix() {} 75*c8dee2aaSAndroid Build Coastguard Worker // Initialize the matrix from the control pts QuadUVMatrix(const SkPoint controlPts[3])76*c8dee2aaSAndroid Build Coastguard Worker QuadUVMatrix(const SkPoint controlPts[3]) { this->set(controlPts); } 77*c8dee2aaSAndroid Build Coastguard Worker void set(const SkPoint controlPts[3]); 78*c8dee2aaSAndroid Build Coastguard Worker 79*c8dee2aaSAndroid Build Coastguard Worker /** 80*c8dee2aaSAndroid Build Coastguard Worker * Applies the matrix to vertex positions to compute UV coords. 81*c8dee2aaSAndroid Build Coastguard Worker * 82*c8dee2aaSAndroid Build Coastguard Worker * vertices is a pointer to the first vertex. 83*c8dee2aaSAndroid Build Coastguard Worker * vertexCount is the number of vertices. 84*c8dee2aaSAndroid Build Coastguard Worker * stride is the size of each vertex. 85*c8dee2aaSAndroid Build Coastguard Worker * uvOffset is the offset of the UV values within each vertex. 86*c8dee2aaSAndroid Build Coastguard Worker */ apply(void * vertices,int vertexCount,size_t stride,size_t uvOffset)87*c8dee2aaSAndroid Build Coastguard Worker void apply(void* vertices, int vertexCount, size_t stride, size_t uvOffset) const { 88*c8dee2aaSAndroid Build Coastguard Worker intptr_t xyPtr = reinterpret_cast<intptr_t>(vertices); 89*c8dee2aaSAndroid Build Coastguard Worker intptr_t uvPtr = reinterpret_cast<intptr_t>(vertices) + uvOffset; 90*c8dee2aaSAndroid Build Coastguard Worker float sx = fM[0]; 91*c8dee2aaSAndroid Build Coastguard Worker float kx = fM[1]; 92*c8dee2aaSAndroid Build Coastguard Worker float tx = fM[2]; 93*c8dee2aaSAndroid Build Coastguard Worker float ky = fM[3]; 94*c8dee2aaSAndroid Build Coastguard Worker float sy = fM[4]; 95*c8dee2aaSAndroid Build Coastguard Worker float ty = fM[5]; 96*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < vertexCount; ++i) { 97*c8dee2aaSAndroid Build Coastguard Worker const SkPoint* xy = reinterpret_cast<const SkPoint*>(xyPtr); 98*c8dee2aaSAndroid Build Coastguard Worker SkPoint* uv = reinterpret_cast<SkPoint*>(uvPtr); 99*c8dee2aaSAndroid Build Coastguard Worker uv->fX = sx * xy->fX + kx * xy->fY + tx; 100*c8dee2aaSAndroid Build Coastguard Worker uv->fY = ky * xy->fX + sy * xy->fY + ty; 101*c8dee2aaSAndroid Build Coastguard Worker xyPtr += stride; 102*c8dee2aaSAndroid Build Coastguard Worker uvPtr += stride; 103*c8dee2aaSAndroid Build Coastguard Worker } 104*c8dee2aaSAndroid Build Coastguard Worker } 105*c8dee2aaSAndroid Build Coastguard Worker private: 106*c8dee2aaSAndroid Build Coastguard Worker float fM[6]; 107*c8dee2aaSAndroid Build Coastguard Worker }; 108*c8dee2aaSAndroid Build Coastguard Worker 109*c8dee2aaSAndroid Build Coastguard Worker // Input is 3 control points and a weight for a bezier conic. Calculates the three linear 110*c8dee2aaSAndroid Build Coastguard Worker // functionals (K,L,M) that represent the implicit equation of the conic, k^2 - lm. 111*c8dee2aaSAndroid Build Coastguard Worker // 112*c8dee2aaSAndroid Build Coastguard Worker // Output: klm holds the linear functionals K,L,M as row vectors: 113*c8dee2aaSAndroid Build Coastguard Worker // 114*c8dee2aaSAndroid Build Coastguard Worker // | ..K.. | | x | | k | 115*c8dee2aaSAndroid Build Coastguard Worker // | ..L.. | * | y | == | l | 116*c8dee2aaSAndroid Build Coastguard Worker // | ..M.. | | 1 | | m | 117*c8dee2aaSAndroid Build Coastguard Worker // 118*c8dee2aaSAndroid Build Coastguard Worker void getConicKLM(const SkPoint p[3], const SkScalar weight, SkMatrix* klm); 119*c8dee2aaSAndroid Build Coastguard Worker 120*c8dee2aaSAndroid Build Coastguard Worker // Converts a cubic into a sequence of quads. If working in device space use tolScale = 1, otherwise 121*c8dee2aaSAndroid Build Coastguard Worker // set based on stretchiness of the matrix. The result is sets of 3 points in quads. This will 122*c8dee2aaSAndroid Build Coastguard Worker // preserve the starting and ending tangent vectors (modulo FP precision). 123*c8dee2aaSAndroid Build Coastguard Worker void convertCubicToQuads(const SkPoint p[4], 124*c8dee2aaSAndroid Build Coastguard Worker SkScalar tolScale, 125*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<SkPoint, true>* quads); 126*c8dee2aaSAndroid Build Coastguard Worker 127*c8dee2aaSAndroid Build Coastguard Worker // When we approximate a cubic {a,b,c,d} with a quadratic we may have to ensure that the new control 128*c8dee2aaSAndroid Build Coastguard Worker // point lies between the lines ab and cd. The convex path renderer requires this. It starts with a 129*c8dee2aaSAndroid Build Coastguard Worker // path where all the control points taken together form a convex polygon. It relies on this 130*c8dee2aaSAndroid Build Coastguard Worker // property and the quadratic approximation of cubics step cannot alter it. This variation enforces 131*c8dee2aaSAndroid Build Coastguard Worker // this constraint. The cubic must be simple and dir must specify the orientation of the contour 132*c8dee2aaSAndroid Build Coastguard Worker // containing the cubic. 133*c8dee2aaSAndroid Build Coastguard Worker void convertCubicToQuadsConstrainToTangents(const SkPoint p[4], 134*c8dee2aaSAndroid Build Coastguard Worker SkScalar tolScale, 135*c8dee2aaSAndroid Build Coastguard Worker SkPathFirstDirection dir, 136*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<SkPoint, true>* quads); 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Worker } // namespace GrPathUtils 139*c8dee2aaSAndroid Build Coastguard Worker 140*c8dee2aaSAndroid Build Coastguard Worker #endif 141