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 #include "SkOpContour.h"
      8 #include "SkPath.h"
      9 
     10 #ifdef SK_DEBUG
     11 #include "SkPathOpsPoint.h"
     12 #endif
     13 
     14 class SkIntersectionHelper {
     15 public:
     16     enum SegmentType {
     17         kHorizontalLine_Segment = -1,
     18         kVerticalLine_Segment = 0,
     19         kLine_Segment = SkPath::kLine_Verb,
     20         kQuad_Segment = SkPath::kQuad_Verb,
     21         kCubic_Segment = SkPath::kCubic_Verb,
     22     };
     23 
     24     bool addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) {
     25         return fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
     26     }
     27 
     28     // FIXME: does it make sense to write otherIndex now if we're going to
     29     // fix it up later?
     30     void addOtherT(int index, double otherT, int otherIndex) {
     31         fContour->addOtherT(fIndex, index, otherT, otherIndex);
     32     }
     33 
     34     bool addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index,
     35             bool swap) {
     36         return fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index,
     37                 swap);
     38     }
     39 
     40     // Avoid collapsing t values that are close to the same since
     41     // we walk ts to describe consecutive intersections. Since a pair of ts can
     42     // be nearly equal, any problems caused by this should be taken care
     43     // of later.
     44     // On the edge or out of range values are negative; add 2 to get end
     45     int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
     46         return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT);
     47     }
     48 
     49     int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
     50         return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT);
     51     }
     52 
     53     bool advance() {
     54         return ++fIndex < fLast;
     55     }
     56 
     57     SkScalar bottom() const {
     58         return bounds().fBottom;
     59     }
     60 
     61     const SkPathOpsBounds& bounds() const {
     62         return fContour->segments()[fIndex].bounds();
     63     }
     64 
     65     void init(SkOpContour* contour) {
     66         fContour = contour;
     67         fIndex = 0;
     68         fLast = contour->segments().count();
     69     }
     70 
     71     bool isAdjacent(const SkIntersectionHelper& next) {
     72         return fContour == next.fContour && fIndex + 1 == next.fIndex;
     73     }
     74 
     75     bool isFirstLast(const SkIntersectionHelper& next) {
     76         return fContour == next.fContour && fIndex == 0
     77                 && next.fIndex == fLast - 1;
     78     }
     79 
     80     bool isPartial(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const {
     81         const SkOpSegment& segment = fContour->segments()[fIndex];
     82         double mid = (t1 + t2) / 2;
     83         SkDPoint midPtByT = segment.dPtAtT(mid);
     84         SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2);
     85         return midPtByT.approximatelyPEqual(midPtByAvg);
     86     }
     87 
     88     SkScalar left() const {
     89         return bounds().fLeft;
     90     }
     91 
     92     const SkPoint* pts() const {
     93         return fContour->segments()[fIndex].pts();
     94     }
     95 
     96     SkScalar right() const {
     97         return bounds().fRight;
     98     }
     99 
    100     SegmentType segmentType() const {
    101         const SkOpSegment& segment = fContour->segments()[fIndex];
    102         SegmentType type = (SegmentType) segment.verb();
    103         if (type != kLine_Segment) {
    104             return type;
    105         }
    106         if (segment.isHorizontal()) {
    107             return kHorizontalLine_Segment;
    108         }
    109         if (segment.isVertical()) {
    110             return kVerticalLine_Segment;
    111         }
    112         return kLine_Segment;
    113     }
    114 
    115     bool startAfter(const SkIntersectionHelper& after) {
    116         fIndex = after.fIndex;
    117         return advance();
    118     }
    119 
    120     SkScalar top() const {
    121         return bounds().fTop;
    122     }
    123 
    124     SkPath::Verb verb() const {
    125         return fContour->segments()[fIndex].verb();
    126     }
    127 
    128     SkScalar x() const {
    129         return bounds().fLeft;
    130     }
    131 
    132     bool xFlipped() const {
    133         return x() != pts()[0].fX;
    134     }
    135 
    136     SkScalar y() const {
    137         return bounds().fTop;
    138     }
    139 
    140     bool yFlipped() const {
    141         return y() != pts()[0].fY;
    142     }
    143 
    144 #ifdef SK_DEBUG
    145     void dump() {
    146         SkDPoint::dump(pts()[0]);
    147         SkDPoint::dump(pts()[1]);
    148         if (verb() >= SkPath::kQuad_Verb) {
    149             SkDPoint::dump(pts()[2]);
    150         }
    151         if (verb() >= SkPath::kCubic_Verb) {
    152             SkDPoint::dump(pts()[3]);
    153         }
    154     }
    155 #endif
    156 
    157 private:
    158     SkOpContour* fContour;
    159     int fIndex;
    160     int fLast;
    161 };
    162