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 SkPoint& pt, double newT) {
     50         return fContour->addSelfT(fIndex, pt, newT);
     51     }
     52 
     53     bool advance() {
     54         return ++fIndex < fLast;
     55     }
     56 
     57     void alignTPt(SkIntersectionHelper& other, bool swap, int index,
     58             SkIntersections* ts, SkPoint* point) {
     59         fContour->alignTPt(fIndex, other.fContour, other.fIndex, swap, index, ts, point);
     60     }
     61 
     62     SkScalar bottom() const {
     63         return bounds().fBottom;
     64     }
     65 
     66     const SkPathOpsBounds& bounds() const {
     67         return fContour->segments()[fIndex].bounds();
     68     }
     69 
     70     void init(SkOpContour* contour) {
     71         fContour = contour;
     72         fIndex = 0;
     73         fLast = contour->segments().count();
     74     }
     75 
     76     bool isAdjacent(const SkIntersectionHelper& next) {
     77         return fContour == next.fContour && fIndex + 1 == next.fIndex;
     78     }
     79 
     80     bool isFirstLast(const SkIntersectionHelper& next) {
     81         return fContour == next.fContour && fIndex == 0
     82                 && next.fIndex == fLast - 1;
     83     }
     84 
     85     bool isPartial(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const {
     86         const SkOpSegment& segment = fContour->segments()[fIndex];
     87         double mid = (t1 + t2) / 2;
     88         SkDPoint midPtByT = segment.dPtAtT(mid);
     89         SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2);
     90         return midPtByT.approximatelyPEqual(midPtByAvg);
     91     }
     92 
     93     SkScalar left() const {
     94         return bounds().fLeft;
     95     }
     96 
     97     const SkPoint* pts() const {
     98         return fContour->segments()[fIndex].pts();
     99     }
    100 
    101     SkScalar right() const {
    102         return bounds().fRight;
    103     }
    104 
    105     SegmentType segmentType() const {
    106         const SkOpSegment& segment = fContour->segments()[fIndex];
    107         SegmentType type = (SegmentType) segment.verb();
    108         if (type != kLine_Segment) {
    109             return type;
    110         }
    111         if (segment.isHorizontal()) {
    112             return kHorizontalLine_Segment;
    113         }
    114         if (segment.isVertical()) {
    115             return kVerticalLine_Segment;
    116         }
    117         return kLine_Segment;
    118     }
    119 
    120     bool startAfter(const SkIntersectionHelper& after) {
    121         fIndex = after.fIndex;
    122         return advance();
    123     }
    124 
    125     SkScalar top() const {
    126         return bounds().fTop;
    127     }
    128 
    129     SkPath::Verb verb() const {
    130         return fContour->segments()[fIndex].verb();
    131     }
    132 
    133     SkScalar x() const {
    134         return bounds().fLeft;
    135     }
    136 
    137     bool xFlipped() const {
    138         return x() != pts()[0].fX;
    139     }
    140 
    141     SkScalar y() const {
    142         return bounds().fTop;
    143     }
    144 
    145     bool yFlipped() const {
    146         return y() != pts()[0].fY;
    147     }
    148 
    149 private:
    150     // utility callable by the user from the debugger when the implementation code is linked in
    151     void dump() const;
    152 
    153     SkOpContour* fContour;
    154     int fIndex;
    155     int fLast;
    156 };
    157