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