xref: /aosp_15_r20/external/skia/src/gpu/ganesh/geometry/GrPathUtils.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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