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 #ifndef SkIntersections_DEFINE
      8 #define SkIntersections_DEFINE
      9 
     10 #include "SkPathOpsCubic.h"
     11 #include "SkPathOpsLine.h"
     12 #include "SkPathOpsPoint.h"
     13 #include "SkPathOpsQuad.h"
     14 
     15 class SkIntersections {
     16 public:
     17     SkIntersections()
     18         : fSwap(0)
     19 #ifdef SK_DEBUG
     20         , fDepth(0)
     21 #endif
     22     {
     23         sk_bzero(fPt, sizeof(fPt));
     24         sk_bzero(fPt2, sizeof(fPt2));
     25         sk_bzero(fT, sizeof(fT));
     26         sk_bzero(fIsCoincident, sizeof(fIsCoincident));
     27         sk_bzero(fNearlySame, sizeof(fNearlySame));
     28         reset();
     29         fMax = 0;  // require that the caller set the max
     30     }
     31 
     32     class TArray {
     33     public:
     34         explicit TArray(const double ts[9]) : fTArray(ts) {}
     35         double operator[](int n) const {
     36             return fTArray[n];
     37         }
     38         const double* fTArray;
     39     };
     40     TArray operator[](int n) const { return TArray(fT[n]); }
     41 
     42     void allowNear(bool nearAllowed) {
     43         fAllowNear = nearAllowed;
     44     }
     45 
     46     int cubic(const SkPoint a[4]) {
     47         SkDCubic cubic;
     48         cubic.set(a);
     49         fMax = 1;  // self intersect
     50         return intersect(cubic);
     51     }
     52 
     53     int cubicCubic(const SkPoint a[4], const SkPoint b[4]) {
     54         SkDCubic aCubic;
     55         aCubic.set(a);
     56         SkDCubic bCubic;
     57         bCubic.set(b);
     58         fMax = 9;
     59         return intersect(aCubic, bCubic);
     60     }
     61 
     62     int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
     63                         bool flipped) {
     64         SkDCubic cubic;
     65         cubic.set(a);
     66         fMax = 3;
     67         return horizontal(cubic, left, right, y, flipped);
     68     }
     69 
     70     int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
     71         SkDCubic cubic;
     72         cubic.set(a);
     73         fMax = 3;
     74         return vertical(cubic, top, bottom, x, flipped);
     75     }
     76 
     77     int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
     78         SkDCubic cubic;
     79         cubic.set(a);
     80         SkDLine line;
     81         line.set(b);
     82         fMax = 3;
     83         return intersect(cubic, line);
     84     }
     85 
     86     int cubicQuad(const SkPoint a[4], const SkPoint b[3]) {
     87         SkDCubic cubic;
     88         cubic.set(a);
     89         SkDQuad quad;
     90         quad.set(b);
     91         fMax = 6;
     92         return intersect(cubic, quad);
     93     }
     94 
     95     bool hasT(double t) const {
     96         SkASSERT(t == 0 || t == 1);
     97         return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1);
     98     }
     99 
    100     int insertSwap(double one, double two, const SkDPoint& pt) {
    101         if (fSwap) {
    102             return insert(two, one, pt);
    103         } else {
    104             return insert(one, two, pt);
    105         }
    106     }
    107 
    108     bool isCoincident(int index) {
    109         return (fIsCoincident[0] & 1 << index) != 0;
    110     }
    111 
    112     int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y,
    113                        bool flipped) {
    114         SkDLine line;
    115         line.set(a);
    116         fMax = 2;
    117         return horizontal(line, left, right, y, flipped);
    118     }
    119 
    120     int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
    121         SkDLine line;
    122         line.set(a);
    123         fMax = 2;
    124         return vertical(line, top, bottom, x, flipped);
    125     }
    126 
    127     int lineLine(const SkPoint a[2], const SkPoint b[2]) {
    128         SkDLine aLine, bLine;
    129         aLine.set(a);
    130         bLine.set(b);
    131         fMax = 2;
    132         return intersect(aLine, bLine);
    133     }
    134 
    135     bool nearlySame(int index) const {
    136         SkASSERT(index == 0 || index == 1);
    137         return fNearlySame[index];
    138     }
    139 
    140     const SkDPoint& pt(int index) const {
    141         return fPt[index];
    142     }
    143 
    144     const SkDPoint& pt2(int index) const {
    145         return fPt2[index];
    146     }
    147 
    148     int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
    149                        bool flipped) {
    150         SkDQuad quad;
    151         quad.set(a);
    152         fMax = 2;
    153         return horizontal(quad, left, right, y, flipped);
    154     }
    155 
    156     int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
    157         SkDQuad quad;
    158         quad.set(a);
    159         fMax = 2;
    160         return vertical(quad, top, bottom, x, flipped);
    161     }
    162 
    163     int quadLine(const SkPoint a[3], const SkPoint b[2]) {
    164         SkDQuad quad;
    165         quad.set(a);
    166         SkDLine line;
    167         line.set(b);
    168         fMax = 3; // 2;  permit small coincident segment + non-coincident intersection
    169         return intersect(quad, line);
    170     }
    171 
    172     int quadQuad(const SkPoint a[3], const SkPoint b[3]) {
    173         SkDQuad aQuad;
    174         aQuad.set(a);
    175         SkDQuad bQuad;
    176         bQuad.set(b);
    177         fMax = 4;
    178         return intersect(aQuad, bQuad);
    179     }
    180 
    181     // leaves swap, max alone
    182     void reset() {
    183         fAllowNear = true;
    184         fUsed = 0;
    185     }
    186 
    187     void set(bool swap, int tIndex, double t) {
    188         fT[(int) swap][tIndex] = t;
    189     }
    190 
    191     void setMax(int max) {
    192         fMax = max;
    193     }
    194 
    195     void swap() {
    196         fSwap ^= true;
    197     }
    198 
    199     void swapPts();
    200 
    201     bool swapped() const {
    202         return fSwap;
    203     }
    204 
    205     int used() const {
    206         return fUsed;
    207     }
    208 
    209     void downDepth() {
    210         SkASSERT(--fDepth >= 0);
    211     }
    212 
    213     void upDepth() {
    214         SkASSERT(++fDepth < 16);
    215     }
    216 
    217     void append(const SkIntersections& );
    218     void cleanUpCoincidence();
    219     int coincidentUsed() const;
    220     void cubicInsert(double one, double two, const SkDPoint& pt, const SkDCubic& c1,
    221                      const SkDCubic& c2);
    222     int cubicRay(const SkPoint pts[4], const SkDLine& line);
    223     void flip();
    224     int horizontal(const SkDLine&, double y);
    225     int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
    226     int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
    227     int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
    228     int horizontal(const SkDCubic&, double y, double tRange[3]);
    229     int horizontal(const SkDCubic&, double left, double right, double y, bool flipped);
    230     int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
    231     // FIXME : does not respect swap
    232     int insert(double one, double two, const SkDPoint& pt);
    233     void insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2);
    234     // start if index == 0 : end if index == 1
    235     void insertCoincident(double one, double two, const SkDPoint& pt);
    236     int intersect(const SkDLine&, const SkDLine&);
    237     int intersect(const SkDQuad&, const SkDLine&);
    238     int intersect(const SkDQuad&, const SkDQuad&);
    239     int intersect(const SkDCubic&);  // return true if cubic self-intersects
    240     int intersect(const SkDCubic&, const SkDLine&);
    241     int intersect(const SkDCubic&, const SkDQuad&);
    242     int intersect(const SkDCubic&, const SkDCubic&);
    243     int intersectRay(const SkDLine&, const SkDLine&);
    244     int intersectRay(const SkDQuad&, const SkDLine&);
    245     int intersectRay(const SkDCubic&, const SkDLine&);
    246     static SkDPoint Line(const SkDLine&, const SkDLine&);
    247     int lineRay(const SkPoint pts[2], const SkDLine& line);
    248     void offset(int base, double start, double end);
    249     void quickRemoveOne(int index, int replace);
    250     int quadRay(const SkPoint pts[3], const SkDLine& line);
    251     void removeOne(int index);
    252     static bool Test(const SkDLine& , const SkDLine&);
    253     int vertical(const SkDLine&, double x);
    254     int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
    255     int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
    256     int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
    257     int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
    258     int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
    259     int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
    260 
    261     int depth() const {
    262 #ifdef SK_DEBUG
    263         return fDepth;
    264 #else
    265         return 0;
    266 #endif
    267     }
    268 
    269 private:
    270     bool cubicCheckCoincidence(const SkDCubic& c1, const SkDCubic& c2);
    271     bool cubicExactEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2);
    272     void cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, const SkDRect& );
    273     void cleanUpParallelLines(bool parallel);
    274     void computePoints(const SkDLine& line, int used);
    275 
    276     SkDPoint fPt[9];  // FIXME: since scans store points as SkPoint, this should also
    277     SkDPoint fPt2[9];  // used by nearly same to store alternate intersection point
    278     double fT[2][9];
    279     uint16_t fIsCoincident[2];  // bit set for each curve's coincident T
    280     bool fNearlySame[2];  // true if end points nearly match
    281     unsigned char fUsed;
    282     unsigned char fMax;
    283     bool fAllowNear;
    284     bool fSwap;
    285 #ifdef SK_DEBUG
    286     int fDepth;
    287 #endif
    288 };
    289 
    290 extern int (SkIntersections::* const CurveRay[])(const SkPoint[], const SkDLine& );
    291 extern int (SkIntersections::* const CurveVertical[])(const SkPoint[], SkScalar top, SkScalar bottom,
    292             SkScalar x, bool flipped);
    293 
    294 #endif
    295