1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 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 SkPathOpsConic_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define SkPathOpsConic_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/SkDebug.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsDebug.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsPoint.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsQuad.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsTCurve.h" 19*c8dee2aaSAndroid Build Coastguard Worker 20*c8dee2aaSAndroid Build Coastguard Worker class SkIntersections; 21*c8dee2aaSAndroid Build Coastguard Worker class SkOpGlobalState; 22*c8dee2aaSAndroid Build Coastguard Worker struct SkDCubic; 23*c8dee2aaSAndroid Build Coastguard Worker struct SkDLine; 24*c8dee2aaSAndroid Build Coastguard Worker struct SkDRect; 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker struct SkDConic { 27*c8dee2aaSAndroid Build Coastguard Worker static const int kPointCount = 3; 28*c8dee2aaSAndroid Build Coastguard Worker static const int kPointLast = kPointCount - 1; 29*c8dee2aaSAndroid Build Coastguard Worker static const int kMaxIntersections = 4; 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard Worker SkDQuad fPts; 32*c8dee2aaSAndroid Build Coastguard Worker SkScalar fWeight; 33*c8dee2aaSAndroid Build Coastguard Worker collapsedSkDConic34*c8dee2aaSAndroid Build Coastguard Worker bool collapsed() const { 35*c8dee2aaSAndroid Build Coastguard Worker return fPts.collapsed(); 36*c8dee2aaSAndroid Build Coastguard Worker } 37*c8dee2aaSAndroid Build Coastguard Worker controlsInsideSkDConic38*c8dee2aaSAndroid Build Coastguard Worker bool controlsInside() const { 39*c8dee2aaSAndroid Build Coastguard Worker return fPts.controlsInside(); 40*c8dee2aaSAndroid Build Coastguard Worker } 41*c8dee2aaSAndroid Build Coastguard Worker debugInitSkDConic42*c8dee2aaSAndroid Build Coastguard Worker void debugInit() { 43*c8dee2aaSAndroid Build Coastguard Worker fPts.debugInit(); 44*c8dee2aaSAndroid Build Coastguard Worker fWeight = 0; 45*c8dee2aaSAndroid Build Coastguard Worker } 46*c8dee2aaSAndroid Build Coastguard Worker 47*c8dee2aaSAndroid Build Coastguard Worker void debugSet(const SkDPoint* pts, SkScalar weight); 48*c8dee2aaSAndroid Build Coastguard Worker flipSkDConic49*c8dee2aaSAndroid Build Coastguard Worker SkDConic flip() const { 50*c8dee2aaSAndroid Build Coastguard Worker SkDConic result = {{{fPts[2], fPts[1], fPts[0]} 51*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGPARAMS(fPts.fDebugGlobalState) }, fWeight}; 52*c8dee2aaSAndroid Build Coastguard Worker return result; 53*c8dee2aaSAndroid Build Coastguard Worker } 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG globalStateSkDConic56*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState* globalState() const { return fPts.globalState(); } 57*c8dee2aaSAndroid Build Coastguard Worker #endif 58*c8dee2aaSAndroid Build Coastguard Worker IsConicSkDConic59*c8dee2aaSAndroid Build Coastguard Worker static bool IsConic() { return true; } 60*c8dee2aaSAndroid Build Coastguard Worker setSkDConic61*c8dee2aaSAndroid Build Coastguard Worker const SkDConic& set(const SkPoint pts[kPointCount], SkScalar weight 62*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGPARAMS(SkOpGlobalState* state = nullptr)) { 63*c8dee2aaSAndroid Build Coastguard Worker fPts.set(pts SkDEBUGPARAMS(state)); 64*c8dee2aaSAndroid Build Coastguard Worker fWeight = weight; 65*c8dee2aaSAndroid Build Coastguard Worker return *this; 66*c8dee2aaSAndroid Build Coastguard Worker } 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker const SkDPoint& operator[](int n) const { return fPts[n]; } 69*c8dee2aaSAndroid Build Coastguard Worker SkDPoint& operator[](int n) { return fPts[n]; } 70*c8dee2aaSAndroid Build Coastguard Worker AddValidTsSkDConic71*c8dee2aaSAndroid Build Coastguard Worker static int AddValidTs(double s[], int realRoots, double* t) { 72*c8dee2aaSAndroid Build Coastguard Worker return SkDQuad::AddValidTs(s, realRoots, t); 73*c8dee2aaSAndroid Build Coastguard Worker } 74*c8dee2aaSAndroid Build Coastguard Worker alignSkDConic75*c8dee2aaSAndroid Build Coastguard Worker void align(int endIndex, SkDPoint* dstPt) const { 76*c8dee2aaSAndroid Build Coastguard Worker fPts.align(endIndex, dstPt); 77*c8dee2aaSAndroid Build Coastguard Worker } 78*c8dee2aaSAndroid Build Coastguard Worker 79*c8dee2aaSAndroid Build Coastguard Worker SkDVector dxdyAtT(double t) const; 80*c8dee2aaSAndroid Build Coastguard Worker static int FindExtrema(const double src[], SkScalar weight, double tValue[1]); 81*c8dee2aaSAndroid Build Coastguard Worker hullIntersectsSkDConic82*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDQuad& quad, bool* isLinear) const { 83*c8dee2aaSAndroid Build Coastguard Worker return fPts.hullIntersects(quad, isLinear); 84*c8dee2aaSAndroid Build Coastguard Worker } 85*c8dee2aaSAndroid Build Coastguard Worker hullIntersectsSkDConic86*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDConic& conic, bool* isLinear) const { 87*c8dee2aaSAndroid Build Coastguard Worker return fPts.hullIntersects(conic.fPts, isLinear); 88*c8dee2aaSAndroid Build Coastguard Worker } 89*c8dee2aaSAndroid Build Coastguard Worker 90*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const; 91*c8dee2aaSAndroid Build Coastguard Worker isLinearSkDConic92*c8dee2aaSAndroid Build Coastguard Worker bool isLinear(int startIndex, int endIndex) const { 93*c8dee2aaSAndroid Build Coastguard Worker return fPts.isLinear(startIndex, endIndex); 94*c8dee2aaSAndroid Build Coastguard Worker } 95*c8dee2aaSAndroid Build Coastguard Worker maxIntersectionsSkDConic96*c8dee2aaSAndroid Build Coastguard Worker static int maxIntersections() { return kMaxIntersections; } 97*c8dee2aaSAndroid Build Coastguard Worker monotonicInXSkDConic98*c8dee2aaSAndroid Build Coastguard Worker bool monotonicInX() const { 99*c8dee2aaSAndroid Build Coastguard Worker return fPts.monotonicInX(); 100*c8dee2aaSAndroid Build Coastguard Worker } 101*c8dee2aaSAndroid Build Coastguard Worker monotonicInYSkDConic102*c8dee2aaSAndroid Build Coastguard Worker bool monotonicInY() const { 103*c8dee2aaSAndroid Build Coastguard Worker return fPts.monotonicInY(); 104*c8dee2aaSAndroid Build Coastguard Worker } 105*c8dee2aaSAndroid Build Coastguard Worker otherPtsSkDConic106*c8dee2aaSAndroid Build Coastguard Worker void otherPts(int oddMan, const SkDPoint* endPt[2]) const { 107*c8dee2aaSAndroid Build Coastguard Worker fPts.otherPts(oddMan, endPt); 108*c8dee2aaSAndroid Build Coastguard Worker } 109*c8dee2aaSAndroid Build Coastguard Worker pointCountSkDConic110*c8dee2aaSAndroid Build Coastguard Worker static int pointCount() { return kPointCount; } pointLastSkDConic111*c8dee2aaSAndroid Build Coastguard Worker static int pointLast() { return kPointLast; } 112*c8dee2aaSAndroid Build Coastguard Worker SkDPoint ptAtT(double t) const; 113*c8dee2aaSAndroid Build Coastguard Worker RootsRealSkDConic114*c8dee2aaSAndroid Build Coastguard Worker static int RootsReal(double A, double B, double C, double t[2]) { 115*c8dee2aaSAndroid Build Coastguard Worker return SkDQuad::RootsReal(A, B, C, t); 116*c8dee2aaSAndroid Build Coastguard Worker } 117*c8dee2aaSAndroid Build Coastguard Worker RootsValidTSkDConic118*c8dee2aaSAndroid Build Coastguard Worker static int RootsValidT(const double A, const double B, const double C, double s[2]) { 119*c8dee2aaSAndroid Build Coastguard Worker return SkDQuad::RootsValidT(A, B, C, s); 120*c8dee2aaSAndroid Build Coastguard Worker } 121*c8dee2aaSAndroid Build Coastguard Worker 122*c8dee2aaSAndroid Build Coastguard Worker SkDConic subDivide(double t1, double t2) const; subDivideSkDConic123*c8dee2aaSAndroid Build Coastguard Worker void subDivide(double t1, double t2, SkDConic* c) const { *c = this->subDivide(t1, t2); } 124*c8dee2aaSAndroid Build Coastguard Worker SubDivideSkDConic125*c8dee2aaSAndroid Build Coastguard Worker static SkDConic SubDivide(const SkPoint a[kPointCount], SkScalar weight, double t1, double t2) { 126*c8dee2aaSAndroid Build Coastguard Worker SkDConic conic; 127*c8dee2aaSAndroid Build Coastguard Worker conic.set(a, weight); 128*c8dee2aaSAndroid Build Coastguard Worker return conic.subDivide(t1, t2); 129*c8dee2aaSAndroid Build Coastguard Worker } 130*c8dee2aaSAndroid Build Coastguard Worker 131*c8dee2aaSAndroid Build Coastguard Worker SkDPoint subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2, 132*c8dee2aaSAndroid Build Coastguard Worker SkScalar* weight) const; 133*c8dee2aaSAndroid Build Coastguard Worker SubDivideSkDConic134*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint SubDivide(const SkPoint pts[kPointCount], SkScalar weight, 135*c8dee2aaSAndroid Build Coastguard Worker const SkDPoint& a, const SkDPoint& c, 136*c8dee2aaSAndroid Build Coastguard Worker double t1, double t2, SkScalar* newWeight) { 137*c8dee2aaSAndroid Build Coastguard Worker SkDConic conic; 138*c8dee2aaSAndroid Build Coastguard Worker conic.set(pts, weight); 139*c8dee2aaSAndroid Build Coastguard Worker return conic.subDivide(a, c, t1, t2, newWeight); 140*c8dee2aaSAndroid Build Coastguard Worker } 141*c8dee2aaSAndroid Build Coastguard Worker 142*c8dee2aaSAndroid Build Coastguard Worker // utilities callable by the user from the debugger when the implementation code is linked in 143*c8dee2aaSAndroid Build Coastguard Worker void dump() const; 144*c8dee2aaSAndroid Build Coastguard Worker void dumpID(int id) const; 145*c8dee2aaSAndroid Build Coastguard Worker void dumpInner() const; 146*c8dee2aaSAndroid Build Coastguard Worker 147*c8dee2aaSAndroid Build Coastguard Worker }; 148*c8dee2aaSAndroid Build Coastguard Worker 149*c8dee2aaSAndroid Build Coastguard Worker class SkTConic : public SkTCurve { 150*c8dee2aaSAndroid Build Coastguard Worker public: 151*c8dee2aaSAndroid Build Coastguard Worker SkDConic fConic; 152*c8dee2aaSAndroid Build Coastguard Worker SkTConic()153*c8dee2aaSAndroid Build Coastguard Worker SkTConic() {} 154*c8dee2aaSAndroid Build Coastguard Worker SkTConic(const SkDConic & c)155*c8dee2aaSAndroid Build Coastguard Worker SkTConic(const SkDConic& c) 156*c8dee2aaSAndroid Build Coastguard Worker : fConic(c) { 157*c8dee2aaSAndroid Build Coastguard Worker } 158*c8dee2aaSAndroid Build Coastguard Worker ~SkTConic()159*c8dee2aaSAndroid Build Coastguard Worker ~SkTConic() override {} 160*c8dee2aaSAndroid Build Coastguard Worker 161*c8dee2aaSAndroid Build Coastguard Worker const SkDPoint& operator[](int n) const override { return fConic[n]; } 162*c8dee2aaSAndroid Build Coastguard Worker SkDPoint& operator[](int n) override { return fConic[n]; } 163*c8dee2aaSAndroid Build Coastguard Worker collapsed()164*c8dee2aaSAndroid Build Coastguard Worker bool collapsed() const override { return fConic.collapsed(); } controlsInside()165*c8dee2aaSAndroid Build Coastguard Worker bool controlsInside() const override { return fConic.controlsInside(); } debugInit()166*c8dee2aaSAndroid Build Coastguard Worker void debugInit() override { return fConic.debugInit(); } 167*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_T_SECT dumpID(int id)168*c8dee2aaSAndroid Build Coastguard Worker void dumpID(int id) const override { return fConic.dumpID(id); } 169*c8dee2aaSAndroid Build Coastguard Worker #endif dxdyAtT(double t)170*c8dee2aaSAndroid Build Coastguard Worker SkDVector dxdyAtT(double t) const override { return fConic.dxdyAtT(t); } 171*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG globalState()172*c8dee2aaSAndroid Build Coastguard Worker SkOpGlobalState* globalState() const override { return fConic.globalState(); } 173*c8dee2aaSAndroid Build Coastguard Worker #endif 174*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDQuad& quad, bool* isLinear) const override; 175*c8dee2aaSAndroid Build Coastguard Worker hullIntersects(const SkDConic & conic,bool * isLinear)176*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDConic& conic, bool* isLinear) const override { 177*c8dee2aaSAndroid Build Coastguard Worker return conic.hullIntersects(fConic, isLinear); 178*c8dee2aaSAndroid Build Coastguard Worker } 179*c8dee2aaSAndroid Build Coastguard Worker 180*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const override; 181*c8dee2aaSAndroid Build Coastguard Worker hullIntersects(const SkTCurve & curve,bool * isLinear)182*c8dee2aaSAndroid Build Coastguard Worker bool hullIntersects(const SkTCurve& curve, bool* isLinear) const override { 183*c8dee2aaSAndroid Build Coastguard Worker return curve.hullIntersects(fConic, isLinear); 184*c8dee2aaSAndroid Build Coastguard Worker } 185*c8dee2aaSAndroid Build Coastguard Worker 186*c8dee2aaSAndroid Build Coastguard Worker int intersectRay(SkIntersections* i, const SkDLine& line) const override; IsConic()187*c8dee2aaSAndroid Build Coastguard Worker bool IsConic() const override { return true; } make(SkArenaAlloc & heap)188*c8dee2aaSAndroid Build Coastguard Worker SkTCurve* make(SkArenaAlloc& heap) const override { return heap.make<SkTConic>(); } 189*c8dee2aaSAndroid Build Coastguard Worker maxIntersections()190*c8dee2aaSAndroid Build Coastguard Worker int maxIntersections() const override { return SkDConic::kMaxIntersections; } 191*c8dee2aaSAndroid Build Coastguard Worker otherPts(int oddMan,const SkDPoint * endPt[2])192*c8dee2aaSAndroid Build Coastguard Worker void otherPts(int oddMan, const SkDPoint* endPt[2]) const override { 193*c8dee2aaSAndroid Build Coastguard Worker fConic.otherPts(oddMan, endPt); 194*c8dee2aaSAndroid Build Coastguard Worker } 195*c8dee2aaSAndroid Build Coastguard Worker pointCount()196*c8dee2aaSAndroid Build Coastguard Worker int pointCount() const override { return SkDConic::kPointCount; } pointLast()197*c8dee2aaSAndroid Build Coastguard Worker int pointLast() const override { return SkDConic::kPointLast; } ptAtT(double t)198*c8dee2aaSAndroid Build Coastguard Worker SkDPoint ptAtT(double t) const override { return fConic.ptAtT(t); } 199*c8dee2aaSAndroid Build Coastguard Worker void setBounds(SkDRect* ) const override; 200*c8dee2aaSAndroid Build Coastguard Worker subDivide(double t1,double t2,SkTCurve * curve)201*c8dee2aaSAndroid Build Coastguard Worker void subDivide(double t1, double t2, SkTCurve* curve) const override { 202*c8dee2aaSAndroid Build Coastguard Worker ((SkTConic*) curve)->fConic = fConic.subDivide(t1, t2); 203*c8dee2aaSAndroid Build Coastguard Worker } 204*c8dee2aaSAndroid Build Coastguard Worker }; 205*c8dee2aaSAndroid Build Coastguard Worker 206*c8dee2aaSAndroid Build Coastguard Worker #endif 207