1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
69d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org */
79d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
89d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org#ifndef GrPathUtils_DEFINED
99d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org#define GrPathUtils_DEFINED
109d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
11febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton#include "SkGeometry.h"
12fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org#include "SkRect.h"
13026beb52a29a620290fcfb24f1e7e9e75547b80freed#include "SkPathPriv.h"
1469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkTArray.h"
159d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org
16b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.comclass SkMatrix;
17b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com
189d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org/**
199d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org *  Utilities for evaluating paths.
209d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org */
21181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.comnamespace GrPathUtils {
2225294d76b1c5ca34ba6cc7033ee42af6484b046bBrian Osman    // Very small tolerances will be increased to a minimum threshold value, to avoid division
2325294d76b1c5ca34ba6cc7033ee42af6484b046bBrian Osman    // problems in subsequent math.
2481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar scaleToleranceToSrc(SkScalar devTol,
25b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                                 const SkMatrix& viewM,
26fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                                 const SkRect& pathBounds);
27181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com
288d033a1b125886c62906d975b5cc28a382064526bsalomon@google.com    int worstCasePointCount(const SkPath&,
29181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com                            int* subpaths,
3081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com                            SkScalar tol);
311971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com
32972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    uint32_t quadraticPointCount(const SkPoint points[], SkScalar tol);
331971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com
34972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    uint32_t generateQuadraticPoints(const SkPoint& p0,
35972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                                     const SkPoint& p1,
36972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                                     const SkPoint& p2,
3781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com                                     SkScalar tolSqd,
38972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                                     SkPoint** points,
39181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com                                     uint32_t pointsLeft);
401971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com
41972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    uint32_t cubicPointCount(const SkPoint points[], SkScalar tol);
421971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com
43972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    uint32_t generateCubicPoints(const SkPoint& p0,
44972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                                 const SkPoint& p1,
45972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                                 const SkPoint& p2,
46972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                                 const SkPoint& p3,
4781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com                                 SkScalar tolSqd,
48972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                                 SkPoint** points,
49181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com                                 uint32_t pointsLeft);
501971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com
511971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com    // A 2x3 matrix that goes from the 2d space coordinates to UV space where
521971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com    // u^2-v = 0 specifies the quad. The matrix is determined by the control
531971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com    // points of the quadratic.
541971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com    class QuadUVMatrix {
551971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com    public:
56fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein        QuadUVMatrix() {}
571971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com        // Initialize the matrix from the control pts
58972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        QuadUVMatrix(const SkPoint controlPts[3]) { this->set(controlPts); }
59972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        void set(const SkPoint controlPts[3]);
601971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com
611971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com        /**
621971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * Applies the matrix to vertex positions to compute UV coords. This
631971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * has been templated so that the compiler can easliy unroll the loop
641971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * and reorder to avoid stalling for loads. The assumption is that a
651971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * path renderer will have a small fixed number of vertices that it
661971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * uploads for each quad.
671971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         *
681971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * N is the number of vertices.
691971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * STRIDE is the size of each vertex.
701971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * UV_OFFSET is the offset of the UV values within each vertex.
711971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         * vertices is a pointer to the first vertex.
721971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com         */
731971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com        template <int N, size_t STRIDE, size_t UV_OFFSET>
74144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt        void apply(const void* vertices) const {
751971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            intptr_t xyPtr = reinterpret_cast<intptr_t>(vertices);
761971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            intptr_t uvPtr = reinterpret_cast<intptr_t>(vertices) + UV_OFFSET;
771971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            float sx = fM[0];
781971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            float kx = fM[1];
791971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            float tx = fM[2];
801971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            float ky = fM[3];
811971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            float sy = fM[4];
821971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            float ty = fM[5];
831971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            for (int i = 0; i < N; ++i) {
84972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                const SkPoint* xy = reinterpret_cast<const SkPoint*>(xyPtr);
85972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                SkPoint* uv = reinterpret_cast<SkPoint*>(uvPtr);
861971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com                uv->fX = sx * xy->fX + kx * xy->fY + tx;
871971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com                uv->fY = ky * xy->fX + sy * xy->fY + ty;
881971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com                xyPtr += STRIDE;
891971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com                uvPtr += STRIDE;
901971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            }
911971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com        }
921971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com    private:
931971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com        float fM[6];
941971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com    };
951971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com
96139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org    // Input is 3 control points and a weight for a bezier conic. Calculates the
97139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org    // three linear functionals (K,L,M) that represent the implicit equation of the
98cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    // conic, k^2 - lm.
99139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org    //
100cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    // Output: klm holds the linear functionals K,L,M as row vectors:
101cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //
102cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //     | ..K.. |   | x |      | k |
103cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //     | ..L.. | * | y |  ==  | l |
104cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //     | ..M.. |   | 1 |      | m |
105cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //
106cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    void getConicKLM(const SkPoint p[3], const SkScalar weight, SkMatrix* klm);
107a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com
10869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    // Converts a cubic into a sequence of quads. If working in device space
10969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    // use tolScale = 1, otherwise set based on stretchiness of the matrix. The
11018fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon    // result is sets of 3 points in quads.
11118fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon    void convertCubicToQuads(const SkPoint p[4],
11218fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon                             SkScalar tolScale,
11318fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon                             SkTArray<SkPoint, true>* quads);
11418fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon
115a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    // When we approximate a cubic {a,b,c,d} with a quadratic we may have to
116a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    // ensure that the new control point lies between the lines ab and cd. The
117a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    // convex path renderer requires this. It starts with a path where all the
118a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    // control points taken together form a convex polygon. It relies on this
119a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    // property and the quadratic approximation of cubics step cannot alter it.
12018fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon    // This variation enforces this constraint. The cubic must be simple and dir
12118fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon    // must specify the orientation of the contour containing the cubic.
12218fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon    void convertCubicToQuadsConstrainToTangents(const SkPoint p[4],
12318fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon                                                SkScalar tolScale,
12418fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon                                                SkPathPriv::FirstDirection dir,
12518fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon                                                SkTArray<SkPoint, true>* quads);
126858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org
127695db408437807d049ecc02b3b852704092728f2Chris Dalton    enum class ExcludedTerm {
128695db408437807d049ecc02b3b852704092728f2Chris Dalton        kNonInvertible,
129695db408437807d049ecc02b3b852704092728f2Chris Dalton        kQuadraticTerm,
130695db408437807d049ecc02b3b852704092728f2Chris Dalton        kLinearTerm
131695db408437807d049ecc02b3b852704092728f2Chris Dalton    };
132695db408437807d049ecc02b3b852704092728f2Chris Dalton
133695db408437807d049ecc02b3b852704092728f2Chris Dalton    // Computes the inverse-transpose of the cubic's power basis matrix, after removing a specific
134695db408437807d049ecc02b3b852704092728f2Chris Dalton    // row of coefficients.
135695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
136695db408437807d049ecc02b3b852704092728f2Chris Dalton    // E.g. if the cubic is defined in power basis form as follows:
137695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
138695db408437807d049ecc02b3b852704092728f2Chris Dalton    //                                         | x3   y3   0 |
139695db408437807d049ecc02b3b852704092728f2Chris Dalton    //     C(t,s) = [t^3  t^2*s  t*s^2  s^3] * | x2   y2   0 |
140695db408437807d049ecc02b3b852704092728f2Chris Dalton    //                                         | x1   y1   0 |
141695db408437807d049ecc02b3b852704092728f2Chris Dalton    //                                         | x0   y0   1 |
142695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
143695db408437807d049ecc02b3b852704092728f2Chris Dalton    // And the excluded term is "kQuadraticTerm", then the resulting inverse-transpose will be:
144695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
145695db408437807d049ecc02b3b852704092728f2Chris Dalton    //     | x3   y3   0 | -1 T
146695db408437807d049ecc02b3b852704092728f2Chris Dalton    //     | x1   y1   0 |
147695db408437807d049ecc02b3b852704092728f2Chris Dalton    //     | x0   y0   1 |
148695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
149695db408437807d049ecc02b3b852704092728f2Chris Dalton    // (The term to exclude is chosen based on maximizing the resulting matrix determinant.)
150695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
151695db408437807d049ecc02b3b852704092728f2Chris Dalton    // This can be used to find the KLM linear functionals:
152695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
153695db408437807d049ecc02b3b852704092728f2Chris Dalton    //     | ..K.. |   | ..kcoeffs.. |
154695db408437807d049ecc02b3b852704092728f2Chris Dalton    //     | ..L.. | = | ..lcoeffs.. | * inverse_transpose_power_basis_matrix
155695db408437807d049ecc02b3b852704092728f2Chris Dalton    //     | ..M.. |   | ..mcoeffs.. |
156695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
157695db408437807d049ecc02b3b852704092728f2Chris Dalton    // NOTE: the same term that was excluded here must also be removed from the corresponding column
158695db408437807d049ecc02b3b852704092728f2Chris Dalton    // of the klmcoeffs matrix.
159695db408437807d049ecc02b3b852704092728f2Chris Dalton    //
160695db408437807d049ecc02b3b852704092728f2Chris Dalton    // Returns which row of coefficients was removed, or kNonInvertible if the cubic was degenerate.
161695db408437807d049ecc02b3b852704092728f2Chris Dalton    ExcludedTerm calcCubicInverseTransposePowerBasisMatrix(const SkPoint p[4], SkMatrix* out);
162695db408437807d049ecc02b3b852704092728f2Chris Dalton
163febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // Computes the KLM linear functionals for the cubic implicit form. The "right" side of the
164febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // curve (when facing in the direction of increasing parameter values) will be the area that
165febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // satisfies:
166febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //
167febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //     k^3 < l*m
168febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //
169febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // Output:
170febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //
171febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // klm: Holds the linear functionals K,L,M as row vectors:
172febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //
173febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //          | ..K.. |   | x |      | k |
174febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //          | ..L.. | * | y |  ==  | l |
175febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //          | ..M.. |   | 1 |      | m |
176febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //
177febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // NOTE: the KLM lines are calculated in the same space as the input control points. If you
178febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // transform the points the lines will also need to be transformed. This can be done by mapping
179febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // the lines with the inverse-transpose of the matrix used to map the points.
180febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //
181febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // t[],s[]: These are set to the two homogeneous parameter values at which points the lines L&M
182febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // intersect with K (See SkClassifyCubic).
183febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //
184febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // Returns the cubic's classification.
185390f6cd6f9f9ddd8a53da804cee3eff60cd2e2b4Chris Dalton    SkCubicType getCubicKLM(const SkPoint src[4], SkMatrix* klm, double t[2], double s[2]);
186febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton
187858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org    // Chops the cubic bezier passed in by src, at the double point (intersection point)
188858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org    // if the curve is a cubic loop. If it is a loop, there will be two parametric values for
189cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    // the double point: t1 and t2. We chop the cubic at these values if they are between 0 and 1.
190858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org    // Return value:
191cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    // Value of 3: t1 and t2 are both between (0,1), and dst will contain the three cubics,
19296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    //             dst[0..3], dst[3..6], and dst[6..9] if dst is not nullptr
193cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    // Value of 2: Only one of t1 and t2 are between (0,1), and dst will contain the two cubics,
19496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    //             dst[0..3] and dst[3..6] if dst is not nullptr
195cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    // Value of 1: Neither t1 nor t2 are between (0,1), and dst will contain the one original cubic,
196febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //             src[0..3]
197cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //
198858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org    // Output:
199858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org    //
200febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    // klm: Holds the linear functionals K,L,M as row vectors. (See getCubicKLM().)
201cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //
202cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    // loopIndex: This value will tell the caller which of the chopped sections (if any) are the
203cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //            actual loop. A value of -1 means there is no loop section. The caller can then use
204cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //            this value to decide how/if they want to flip the orientation of this section.
205cc26127920069cbd83e92cca3c69bb56cb165bcccsmartdalton    //            The flip should be done by negating the k and l values as follows:
206858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org    //
207febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    //            KLM.postScale(-1, -1)
208febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton    int chopCubicAtLoopIntersection(const SkPoint src[4], SkPoint dst[10], SkMatrix* klm,
209febbffad1c24136f041d7fc2d5ffcd50e47a047fChris Dalton                                    int* loopIndex);
2102b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco
2112b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco    // When tessellating curved paths into linear segments, this defines the maximum distance
2122b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco    // in screen space which a segment may deviate from the mathmatically correct value.
2132b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco    // Above this value, the segment will be subdivided.
2142b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco    // This value was chosen to approximate the supersampling accuracy of the raster path (16
2152b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco    // samples, or one quarter pixel).
2162b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco    static const SkScalar kDefaultTolerance = SkDoubleToScalar(0.25);
21749b7b6f38fc9d6cbcfa5865db364ff79c3ed7bfeBrian Osman
21849b7b6f38fc9d6cbcfa5865db364ff79c3ed7bfeBrian Osman    // We guarantee that no quad or cubic will ever produce more than this many points
21949b7b6f38fc9d6cbcfa5865db364ff79c3ed7bfeBrian Osman    static const int kMaxPointsPerCurve = 1 << 10;
2209d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org};
2219d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org#endif
222