1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2012 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 SkPathOpsQuad_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define SkPathOpsQuad_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMalloc.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsCubic.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsDebug.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsPoint.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsTCurve.h" 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker class SkIntersections; 22*c8dee2aaSAndroid Build Coastguard Worker class SkOpGlobalState; 23*c8dee2aaSAndroid Build Coastguard Worker struct SkDConic; 24*c8dee2aaSAndroid Build Coastguard Worker struct SkDLine; 25*c8dee2aaSAndroid Build Coastguard Worker struct SkDQuad; 26*c8dee2aaSAndroid Build Coastguard Worker struct SkDRect; 27*c8dee2aaSAndroid Build Coastguard Worker 28*c8dee2aaSAndroid Build Coastguard Worker struct SkDQuadPair { firstSkDQuadPair29*c8dee2aaSAndroid Build Coastguard Worker const SkDQuad& first() const { return (const SkDQuad&) pts[0]; } secondSkDQuadPair30*c8dee2aaSAndroid Build Coastguard Worker const SkDQuad& second() const { return (const SkDQuad&) pts[2]; } 31*c8dee2aaSAndroid Build Coastguard Worker SkDPoint pts[5]; 32*c8dee2aaSAndroid Build Coastguard Worker }; 33*c8dee2aaSAndroid Build Coastguard Worker 34*c8dee2aaSAndroid Build Coastguard Worker struct SkDQuad { 35*c8dee2aaSAndroid Build Coastguard Worker static const int kPointCount = 3; 36*c8dee2aaSAndroid Build Coastguard Worker static const int kPointLast = kPointCount - 1; 37*c8dee2aaSAndroid Build Coastguard Worker static const int kMaxIntersections = 4; 38*c8dee2aaSAndroid Build Coastguard Worker 39*c8dee2aaSAndroid Build Coastguard Worker SkDPoint fPts[kPointCount]; 40*c8dee2aaSAndroid Build Coastguard Worker collapsedSkDQuad41*c8dee2aaSAndroid Build Coastguard Worker bool collapsed() const { 42*c8dee2aaSAndroid Build Coastguard Worker return fPts[0].approximatelyEqual(fPts[1]) && fPts[0].approximatelyEqual(fPts[2]); 43*c8dee2aaSAndroid Build Coastguard Worker } 44*c8dee2aaSAndroid Build Coastguard Worker controlsInsideSkDQuad45*c8dee2aaSAndroid Build Coastguard Worker bool controlsInside() const { 46*c8dee2aaSAndroid Build Coastguard Worker SkDVector v01 = fPts[0] - fPts[1]; 47*c8dee2aaSAndroid Build Coastguard Worker SkDVector v02 = fPts[0] - fPts[2]; 48*c8dee2aaSAndroid Build Coastguard Worker SkDVector v12 = fPts[1] - fPts[2]; 49*c8dee2aaSAndroid Build Coastguard Worker return v02.dot(v01) > 0 && v02.dot(v12) > 0; 50*c8dee2aaSAndroid Build Coastguard Worker } 51*c8dee2aaSAndroid Build Coastguard Worker debugInitSkDQuad52*c8dee2aaSAndroid Build Coastguard Worker void debugInit() { 53*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(fPts, sizeof(fPts)); 54*c8dee2aaSAndroid Build Coastguard Worker } 55*c8dee2aaSAndroid Build Coastguard Worker 56*c8dee2aaSAndroid Build Coastguard Worker void debugSet(const SkDPoint* pts); 57*c8dee2aaSAndroid Build Coastguard Worker flipSkDQuad58*c8dee2aaSAndroid Build Coastguard Worker SkDQuad flip() const { 59*c8dee2aaSAndroid Build Coastguard Worker SkDQuad result = {{fPts[2], fPts[1], fPts[0]} SkDEBUGPARAMS(fDebugGlobalState) }; 60*c8dee2aaSAndroid Build Coastguard Worker return result; 61*c8dee2aaSAndroid Build Coastguard Worker } 62*c8dee2aaSAndroid Build Coastguard Worker IsConicSkDQuad63*c8dee2aaSAndroid Build Coastguard Worker static bool IsConic() { return false; } 64*c8dee2aaSAndroid Build Coastguard Worker setSkDQuad65*c8dee2aaSAndroid Build Coastguard Worker const SkDQuad& set(const SkPoint pts[kPointCount] 66*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGPARAMS(SkOpGlobalState* state = nullptr)) { 67*c8dee2aaSAndroid Build Coastguard Worker fPts[0] = pts[0]; 68*c8dee2aaSAndroid Build Coastguard Worker fPts[1] = pts[1]; 69*c8dee2aaSAndroid Build Coastguard Worker fPts[2] = pts[2]; 70*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fDebugGlobalState = state); 71*c8dee2aaSAndroid Build Coastguard Worker return *this; 72*c8dee2aaSAndroid Build Coastguard Worker } 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard Worker const SkDPoint& operator[](int n) const { SkASSERT(n >= 0 && n < kPointCount); return fPts[n]; } 75*c8dee2aaSAndroid Build Coastguard Worker SkDPoint& operator[](int n) { SkASSERT(n >= 0 && n < kPointCount); return fPts[n]; } 76*c8dee2aaSAndroid Build Coastguard Worker 77*c8dee2aaSAndroid Build Coastguard Worker static int AddValidTs(double s[], int realRoots, double* t); 78*c8dee2aaSAndroid Build Coastguard Worker void align(int endIndex, SkDPoint* dstPt) const; 79*c8dee2aaSAndroid Build Coastguard Worker SkDQuadPair chopAt(double t) const; 80*c8dee2aaSAndroid Build Coastguard Worker SkDVector dxdyAtT(double t) const; 81*c8dee2aaSAndroid Build Coastguard Worker static int FindExtrema(const double src[], double tValue[1]); 82*c8dee2aaSAndroid Build Coastguard Worker 83*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG globalStateSkDQuad84*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState* globalState() const { return fDebugGlobalState; } 85*c8dee2aaSAndroid Build Coastguard Worker #endif 86*c8dee2aaSAndroid Build Coastguard Worker 87*c8dee2aaSAndroid Build Coastguard Worker /** 88*c8dee2aaSAndroid Build Coastguard Worker * Return the number of valid roots (0 < root < 1) for this cubic intersecting the 89*c8dee2aaSAndroid Build Coastguard Worker * specified horizontal line. 90*c8dee2aaSAndroid Build Coastguard Worker */ 91*c8dee2aaSAndroid Build Coastguard Worker int horizontalIntersect(double yIntercept, double roots[2]) const; 92*c8dee2aaSAndroid Build Coastguard Worker 93*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDQuad& , bool* isLinear) const; 94*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDConic& , bool* isLinear) const; 95*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDCubic& , bool* isLinear) const; 96*c8dee2aaSAndroid Build Coastguard Worker bool isLinear(int startIndex, int endIndex) const; maxIntersectionsSkDQuad97*c8dee2aaSAndroid Build Coastguard Worker static int maxIntersections() { return kMaxIntersections; } 98*c8dee2aaSAndroid Build Coastguard Worker bool monotonicInX() const; 99*c8dee2aaSAndroid Build Coastguard Worker bool monotonicInY() const; 100*c8dee2aaSAndroid Build Coastguard Worker void otherPts(int oddMan, const SkDPoint* endPt[2]) const; pointCountSkDQuad101*c8dee2aaSAndroid Build Coastguard Worker static int pointCount() { return kPointCount; } pointLastSkDQuad102*c8dee2aaSAndroid Build Coastguard Worker static int pointLast() { return kPointLast; } 103*c8dee2aaSAndroid Build Coastguard Worker SkDPoint ptAtT(double t) const; 104*c8dee2aaSAndroid Build Coastguard Worker static int RootsReal(double A, double B, double C, double t[2]); 105*c8dee2aaSAndroid Build Coastguard Worker static int RootsValidT(const double A, const double B, const double C, double s[2]); 106*c8dee2aaSAndroid Build Coastguard Worker static void SetABC(const double* quad, double* a, double* b, double* c); 107*c8dee2aaSAndroid Build Coastguard Worker SkDQuad subDivide(double t1, double t2) const; subDivideSkDQuad108*c8dee2aaSAndroid Build Coastguard Worker void subDivide(double t1, double t2, SkDQuad* quad) const { *quad = this->subDivide(t1, t2); } 109*c8dee2aaSAndroid Build Coastguard Worker SubDivideSkDQuad110*c8dee2aaSAndroid Build Coastguard Worker static SkDQuad SubDivide(const SkPoint a[kPointCount], double t1, double t2) { 111*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad; 112*c8dee2aaSAndroid Build Coastguard Worker quad.set(a); 113*c8dee2aaSAndroid Build Coastguard Worker return quad.subDivide(t1, t2); 114*c8dee2aaSAndroid Build Coastguard Worker } 115*c8dee2aaSAndroid Build Coastguard Worker SkDPoint subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2) const; SubDivideSkDQuad116*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint SubDivide(const SkPoint pts[kPointCount], const SkDPoint& a, const SkDPoint& c, 117*c8dee2aaSAndroid Build Coastguard Worker double t1, double t2) { 118*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad; 119*c8dee2aaSAndroid Build Coastguard Worker quad.set(pts); 120*c8dee2aaSAndroid Build Coastguard Worker return quad.subDivide(a, c, t1, t2); 121*c8dee2aaSAndroid Build Coastguard Worker } 122*c8dee2aaSAndroid Build Coastguard Worker 123*c8dee2aaSAndroid Build Coastguard Worker /** 124*c8dee2aaSAndroid Build Coastguard Worker * Return the number of valid roots (0 < root < 1) for this cubic intersecting the 125*c8dee2aaSAndroid Build Coastguard Worker * specified vertical line. 126*c8dee2aaSAndroid Build Coastguard Worker */ 127*c8dee2aaSAndroid Build Coastguard Worker int verticalIntersect(double xIntercept, double roots[2]) const; 128*c8dee2aaSAndroid Build Coastguard Worker 129*c8dee2aaSAndroid Build Coastguard Worker SkDCubic debugToCubic() const; 130*c8dee2aaSAndroid Build Coastguard Worker // utilities callable by the user from the debugger when the implementation code is linked in 131*c8dee2aaSAndroid Build Coastguard Worker void dump() const; 132*c8dee2aaSAndroid Build Coastguard Worker void dumpID(int id) const; 133*c8dee2aaSAndroid Build Coastguard Worker void dumpInner() const; 134*c8dee2aaSAndroid Build Coastguard Worker 135*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState;) 136*c8dee2aaSAndroid Build Coastguard Worker }; 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Worker 139*c8dee2aaSAndroid Build Coastguard Worker class SkTQuad : public SkTCurve { 140*c8dee2aaSAndroid Build Coastguard Worker public: 141*c8dee2aaSAndroid Build Coastguard Worker SkDQuad fQuad; 142*c8dee2aaSAndroid Build Coastguard Worker SkTQuad()143*c8dee2aaSAndroid Build Coastguard Worker SkTQuad() {} 144*c8dee2aaSAndroid Build Coastguard Worker SkTQuad(const SkDQuad & q)145*c8dee2aaSAndroid Build Coastguard Worker SkTQuad(const SkDQuad& q) 146*c8dee2aaSAndroid Build Coastguard Worker : fQuad(q) { 147*c8dee2aaSAndroid Build Coastguard Worker } 148*c8dee2aaSAndroid Build Coastguard Worker ~SkTQuad()149*c8dee2aaSAndroid Build Coastguard Worker ~SkTQuad() override {} 150*c8dee2aaSAndroid Build Coastguard Worker 151*c8dee2aaSAndroid Build Coastguard Worker const SkDPoint& operator[](int n) const override { return fQuad[n]; } 152*c8dee2aaSAndroid Build Coastguard Worker SkDPoint& operator[](int n) override { return fQuad[n]; } 153*c8dee2aaSAndroid Build Coastguard Worker collapsed()154*c8dee2aaSAndroid Build Coastguard Worker bool collapsed() const override { return fQuad.collapsed(); } controlsInside()155*c8dee2aaSAndroid Build Coastguard Worker bool controlsInside() const override { return fQuad.controlsInside(); } debugInit()156*c8dee2aaSAndroid Build Coastguard Worker void debugInit() override { return fQuad.debugInit(); } 157*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_T_SECT dumpID(int id)158*c8dee2aaSAndroid Build Coastguard Worker void dumpID(int id) const override { return fQuad.dumpID(id); } 159*c8dee2aaSAndroid Build Coastguard Worker #endif dxdyAtT(double t)160*c8dee2aaSAndroid Build Coastguard Worker SkDVector dxdyAtT(double t) const override { return fQuad.dxdyAtT(t); } 161*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG globalState()162*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState* globalState() const override { return fQuad.globalState(); } 163*c8dee2aaSAndroid Build Coastguard Worker #endif 164*c8dee2aaSAndroid Build Coastguard Worker hullIntersects(const SkDQuad & quad,bool * isLinear)165*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDQuad& quad, bool* isLinear) const override { 166*c8dee2aaSAndroid Build Coastguard Worker return quad.hullIntersects(fQuad, isLinear); 167*c8dee2aaSAndroid Build Coastguard Worker } 168*c8dee2aaSAndroid Build Coastguard Worker 169*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDConic& conic, bool* isLinear) const override; 170*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const override; 171*c8dee2aaSAndroid Build Coastguard Worker hullIntersects(const SkTCurve & curve,bool * isLinear)172*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkTCurve& curve, bool* isLinear) const override { 173*c8dee2aaSAndroid Build Coastguard Worker return curve.hullIntersects(fQuad, isLinear); 174*c8dee2aaSAndroid Build Coastguard Worker } 175*c8dee2aaSAndroid Build Coastguard Worker 176*c8dee2aaSAndroid Build Coastguard Worker int intersectRay(SkIntersections* i, const SkDLine& line) const override; IsConic()177*c8dee2aaSAndroid Build Coastguard Worker bool IsConic() const override { return false; } make(SkArenaAlloc & heap)178*c8dee2aaSAndroid Build Coastguard Worker SkTCurve* make(SkArenaAlloc& heap) const override { return heap.make<SkTQuad>(); } 179*c8dee2aaSAndroid Build Coastguard Worker maxIntersections()180*c8dee2aaSAndroid Build Coastguard Worker int maxIntersections() const override { return SkDQuad::kMaxIntersections; } 181*c8dee2aaSAndroid Build Coastguard Worker otherPts(int oddMan,const SkDPoint * endPt[2])182*c8dee2aaSAndroid Build Coastguard Worker void otherPts(int oddMan, const SkDPoint* endPt[2]) const override { 183*c8dee2aaSAndroid Build Coastguard Worker fQuad.otherPts(oddMan, endPt); 184*c8dee2aaSAndroid Build Coastguard Worker } 185*c8dee2aaSAndroid Build Coastguard Worker pointCount()186*c8dee2aaSAndroid Build Coastguard Worker int pointCount() const override { return SkDQuad::kPointCount; } pointLast()187*c8dee2aaSAndroid Build Coastguard Worker int pointLast() const override { return SkDQuad::kPointLast; } ptAtT(double t)188*c8dee2aaSAndroid Build Coastguard Worker SkDPoint ptAtT(double t) const override { return fQuad.ptAtT(t); } 189*c8dee2aaSAndroid Build Coastguard Worker void setBounds(SkDRect* ) const override; 190*c8dee2aaSAndroid Build Coastguard Worker subDivide(double t1,double t2,SkTCurve * curve)191*c8dee2aaSAndroid Build Coastguard Worker void subDivide(double t1, double t2, SkTCurve* curve) const override { 192*c8dee2aaSAndroid Build Coastguard Worker ((SkTQuad*) curve)->fQuad = fQuad.subDivide(t1, t2); 193*c8dee2aaSAndroid Build Coastguard Worker } 194*c8dee2aaSAndroid Build Coastguard Worker }; 195*c8dee2aaSAndroid Build Coastguard Worker 196*c8dee2aaSAndroid Build Coastguard Worker #endif 197