Home | History | Annotate | Download | only in pathops
      1 /*
      2  * Copyright 2013 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 SkOpContour_DEFINED
      8 #define SkOpContour_DEFINED
      9 
     10 #include "SkOpSegment.h"
     11 #include "SkTArray.h"
     12 
     13 class SkIntersections;
     14 class SkOpContour;
     15 class SkPathWriter;
     16 
     17 struct SkCoincidence {
     18     SkOpContour* fContours[2];
     19     int fSegments[2];
     20     double fTs[2][2];
     21     SkPoint fPts[2];
     22 };
     23 
     24 class SkOpContour {
     25 public:
     26     SkOpContour() {
     27         reset();
     28 #if DEBUG_DUMP
     29         fID = ++gContourID;
     30 #endif
     31     }
     32 
     33     bool operator<(const SkOpContour& rh) const {
     34         return fBounds.fTop == rh.fBounds.fTop
     35                 ? fBounds.fLeft < rh.fBounds.fLeft
     36                 : fBounds.fTop < rh.fBounds.fTop;
     37     }
     38 
     39     void addCoincident(int index, SkOpContour* other, int otherIndex,
     40                        const SkIntersections& ts, bool swap);
     41     void addCoincidentPoints();
     42 
     43     void addCross(const SkOpContour* crosser) {
     44 #ifdef DEBUG_CROSS
     45         for (int index = 0; index < fCrosses.count(); ++index) {
     46             SkASSERT(fCrosses[index] != crosser);
     47         }
     48 #endif
     49         fCrosses.push_back(crosser);
     50     }
     51 
     52     void addCubic(const SkPoint pts[4]) {
     53         fSegments.push_back().addCubic(pts, fOperand, fXor);
     54         fContainsCurves = fContainsCubics = true;
     55     }
     56 
     57     int addLine(const SkPoint pts[2]) {
     58         fSegments.push_back().addLine(pts, fOperand, fXor);
     59         return fSegments.count();
     60     }
     61 
     62     void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) {
     63         fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex);
     64     }
     65 
     66     int addQuad(const SkPoint pts[3]) {
     67         fSegments.push_back().addQuad(pts, fOperand, fXor);
     68         fContainsCurves = true;
     69         return fSegments.count();
     70     }
     71 
     72     int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) {
     73         setContainsIntercepts();
     74         return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT);
     75     }
     76 
     77     int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) {
     78         setContainsIntercepts();
     79         return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, newT);
     80     }
     81 
     82     int addUnsortableT(int segIndex, SkOpContour* other, int otherIndex, bool start,
     83                        const SkPoint& pt, double newT) {
     84         return fSegments[segIndex].addUnsortableT(&other->fSegments[otherIndex], start, pt, newT);
     85     }
     86 
     87     const SkPathOpsBounds& bounds() const {
     88         return fBounds;
     89     }
     90 
     91     void calcCoincidentWinding();
     92 
     93     void checkEnds() {
     94         if (!fContainsCurves) {
     95             return;
     96         }
     97         int segmentCount = fSegments.count();
     98         for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
     99             SkOpSegment* segment = &fSegments[sIndex];
    100             if (segment->verb() == SkPath::kLine_Verb) {
    101                 continue;
    102             }
    103             fSegments[sIndex].checkEnds();
    104         }
    105     }
    106 
    107     void complete() {
    108         setBounds();
    109         fContainsIntercepts = false;
    110     }
    111 
    112     bool containsCubics() const {
    113         return fContainsCubics;
    114     }
    115 
    116     bool crosses(const SkOpContour* crosser) const {
    117         for (int index = 0; index < fCrosses.count(); ++index) {
    118             if (fCrosses[index] == crosser) {
    119                 return true;
    120             }
    121         }
    122         return false;
    123     }
    124 
    125     bool done() const {
    126         return fDone;
    127     }
    128 
    129     const SkPoint& end() const {
    130         const SkOpSegment& segment = fSegments.back();
    131         return segment.pts()[SkPathOpsVerbToPoints(segment.verb())];
    132     }
    133 
    134     void findTooCloseToCall() {
    135         int segmentCount = fSegments.count();
    136         for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
    137             fSegments[sIndex].findTooCloseToCall();
    138         }
    139     }
    140 
    141     void fixOtherTIndex() {
    142         int segmentCount = fSegments.count();
    143         for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
    144             fSegments[sIndex].fixOtherTIndex();
    145         }
    146     }
    147 
    148     SkOpSegment* nonVerticalSegment(int* start, int* end);
    149 
    150     bool operand() const {
    151         return fOperand;
    152     }
    153 
    154     void reset() {
    155         fSegments.reset();
    156         fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
    157         fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false;
    158     }
    159 
    160     SkTArray<SkOpSegment>& segments() {
    161         return fSegments;
    162     }
    163 
    164     void setContainsIntercepts() {
    165         fContainsIntercepts = true;
    166     }
    167 
    168     void setOperand(bool isOp) {
    169         fOperand = isOp;
    170     }
    171 
    172     void setOppXor(bool isOppXor) {
    173         fOppXor = isOppXor;
    174         int segmentCount = fSegments.count();
    175         for (int test = 0; test < segmentCount; ++test) {
    176             fSegments[test].setOppXor(isOppXor);
    177         }
    178     }
    179 
    180     void setXor(bool isXor) {
    181         fXor = isXor;
    182     }
    183 
    184     void sortSegments();
    185 
    186     const SkPoint& start() const {
    187         return fSegments.front().pts()[0];
    188     }
    189 
    190     void toPath(SkPathWriter* path) const;
    191 
    192     void toPartialBackward(SkPathWriter* path) const {
    193         int segmentCount = fSegments.count();
    194         for (int test = segmentCount - 1; test >= 0; --test) {
    195             fSegments[test].addCurveTo(1, 0, path, true);
    196         }
    197     }
    198 
    199     void toPartialForward(SkPathWriter* path) const {
    200         int segmentCount = fSegments.count();
    201         for (int test = 0; test < segmentCount; ++test) {
    202             fSegments[test].addCurveTo(0, 1, path, true);
    203         }
    204     }
    205 
    206     void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment** topStart);
    207     SkOpSegment* undoneSegment(int* start, int* end);
    208 
    209     int updateSegment(int index, const SkPoint* pts) {
    210         SkOpSegment& segment = fSegments[index];
    211         segment.updatePts(pts);
    212         return SkPathOpsVerbToPoints(segment.verb()) + 1;
    213     }
    214 
    215 #if DEBUG_TEST
    216     SkTArray<SkOpSegment>& debugSegments() {
    217         return fSegments;
    218     }
    219 #endif
    220 
    221 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
    222     void debugShowActiveSpans() {
    223         for (int index = 0; index < fSegments.count(); ++index) {
    224             fSegments[index].debugShowActiveSpans();
    225         }
    226     }
    227 #endif
    228 
    229 #if DEBUG_SHOW_WINDING
    230     int debugShowWindingValues(int totalSegments, int ofInterest);
    231     static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& contourList);
    232 #endif
    233 
    234 private:
    235     void setBounds();
    236 
    237     SkTArray<SkOpSegment> fSegments;
    238     SkTArray<SkOpSegment*, true> fSortedSegments;
    239     int fFirstSorted;
    240     SkTArray<SkCoincidence, true> fCoincidences;
    241     SkTArray<const SkOpContour*, true> fCrosses;
    242     SkPathOpsBounds fBounds;
    243     bool fContainsIntercepts;  // FIXME: is this used by anybody?
    244     bool fContainsCubics;
    245     bool fContainsCurves;
    246     bool fDone;
    247     bool fOperand;  // true for the second argument to a binary operator
    248     bool fXor;
    249     bool fOppXor;
    250 #if DEBUG_DUMP
    251     int fID;
    252 #endif
    253 };
    254 
    255 #endif
    256