1 /*
2  * Copyright 2012 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkPathOpsQuad_DEFINED
9 #define SkPathOpsQuad_DEFINED
10 
11 #include "SkPathOpsPoint.h"
12 
13 struct SkOpCurve;
14 
15 struct SkDQuadPair {
firstSkDQuadPair16     const SkDQuad& first() const { return (const SkDQuad&) pts[0]; }
secondSkDQuadPair17     const SkDQuad& second() const { return (const SkDQuad&) pts[2]; }
18     SkDPoint pts[5];
19 };
20 
21 struct SkDQuad {
22     static const int kPointCount = 3;
23     static const int kPointLast = kPointCount - 1;
24     static const int kMaxIntersections = 4;
25 
26     SkDPoint fPts[kPointCount];
27 
collapsedSkDQuad28     bool collapsed() const {
29         return fPts[0].approximatelyEqual(fPts[1]) && fPts[0].approximatelyEqual(fPts[2]);
30     }
31 
controlsInsideSkDQuad32     bool controlsInside() const {
33         SkDVector v01 = fPts[0] - fPts[1];
34         SkDVector v02 = fPts[0] - fPts[2];
35         SkDVector v12 = fPts[1] - fPts[2];
36         return v02.dot(v01) > 0 && v02.dot(v12) > 0;
37     }
38 
debugInitSkDQuad39     void debugInit() {
40         sk_bzero(fPts, sizeof(fPts));
41     }
42 
43     void debugSet(const SkDPoint* pts);
44 
flipSkDQuad45     SkDQuad flip() const {
46         SkDQuad result = {{fPts[2], fPts[1], fPts[0]}  SkDEBUGPARAMS(fDebugGlobalState) };
47         return result;
48     }
49 
IsConicSkDQuad50     static bool IsConic() { return false; }
51 
setSkDQuad52     const SkDQuad& set(const SkPoint pts[kPointCount]
53             SkDEBUGPARAMS(SkOpGlobalState* state = nullptr)) {
54         fPts[0] = pts[0];
55         fPts[1] = pts[1];
56         fPts[2] = pts[2];
57         SkDEBUGCODE(fDebugGlobalState = state);
58         return *this;
59     }
60 
61     const SkDPoint& operator[](int n) const { SkASSERT(n >= 0 && n < kPointCount); return fPts[n]; }
62     SkDPoint& operator[](int n) { SkASSERT(n >= 0 && n < kPointCount); return fPts[n]; }
63 
64     static int AddValidTs(double s[], int realRoots, double* t);
65     void align(int endIndex, SkDPoint* dstPt) const;
66     SkDQuadPair chopAt(double t) const;
67     SkDVector dxdyAtT(double t) const;
68     static int FindExtrema(const double src[], double tValue[1]);
69 
70 #ifdef SK_DEBUG
globalStateSkDQuad71     SkOpGlobalState* globalState() const { return fDebugGlobalState; }
72 #endif
73 
74     /**
75      *  Return the number of valid roots (0 < root < 1) for this cubic intersecting the
76      *  specified horizontal line.
77      */
78     int horizontalIntersect(double yIntercept, double roots[2]) const;
79 
80     bool hullIntersects(const SkDQuad& , bool* isLinear) const;
81     bool hullIntersects(const SkDConic& , bool* isLinear) const;
82     bool hullIntersects(const SkDCubic& , bool* isLinear) const;
83     bool isLinear(int startIndex, int endIndex) const;
84     bool monotonicInX() const;
85     bool monotonicInY() const;
86     void otherPts(int oddMan, const SkDPoint* endPt[2]) const;
87     SkDPoint ptAtT(double t) const;
88     static int RootsReal(double A, double B, double C, double t[2]);
89     static int RootsValidT(const double A, const double B, const double C, double s[2]);
90     static void SetABC(const double* quad, double* a, double* b, double* c);
91     SkDQuad subDivide(double t1, double t2) const;
SubDivideSkDQuad92     static SkDQuad SubDivide(const SkPoint a[kPointCount], double t1, double t2) {
93         SkDQuad quad;
94         quad.set(a);
95         return quad.subDivide(t1, t2);
96     }
97     SkDPoint subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2) const;
SubDivideSkDQuad98     static SkDPoint SubDivide(const SkPoint pts[kPointCount], const SkDPoint& a, const SkDPoint& c,
99                               double t1, double t2) {
100         SkDQuad quad;
101         quad.set(pts);
102         return quad.subDivide(a, c, t1, t2);
103     }
104 
105     /**
106      *  Return the number of valid roots (0 < root < 1) for this cubic intersecting the
107      *  specified vertical line.
108      */
109     int verticalIntersect(double xIntercept, double roots[2]) const;
110 
111     SkDCubic debugToCubic() const;
112     // utilities callable by the user from the debugger when the implementation code is linked in
113     void dump() const;
114     void dumpID(int id) const;
115     void dumpInner() const;
116 
117     SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
118 };
119 
120 #endif
121