• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
addCoincident(SkIntersectionHelper & other,const SkIntersections & ts,bool swap)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?
addOtherT(int index,double otherT,int otherIndex)30     void addOtherT(int index, double otherT, int otherIndex) {
31         fContour->addOtherT(fIndex, index, otherT, otherIndex);
32     }
33 
addPartialCoincident(SkIntersectionHelper & other,const SkIntersections & ts,int index,bool swap)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
addT(const SkIntersectionHelper & other,const SkPoint & pt,double newT)45     int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
46         return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT);
47     }
48 
addSelfT(const SkIntersectionHelper & other,const SkPoint & pt,double newT)49     int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
50         return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT);
51     }
52 
advance()53     bool advance() {
54         return ++fIndex < fLast;
55     }
56 
bottom()57     SkScalar bottom() const {
58         return bounds().fBottom;
59     }
60 
bounds()61     const SkPathOpsBounds& bounds() const {
62         return fContour->segments()[fIndex].bounds();
63     }
64 
init(SkOpContour * contour)65     void init(SkOpContour* contour) {
66         fContour = contour;
67         fIndex = 0;
68         fLast = contour->segments().count();
69     }
70 
isAdjacent(const SkIntersectionHelper & next)71     bool isAdjacent(const SkIntersectionHelper& next) {
72         return fContour == next.fContour && fIndex + 1 == next.fIndex;
73     }
74 
isFirstLast(const SkIntersectionHelper & next)75     bool isFirstLast(const SkIntersectionHelper& next) {
76         return fContour == next.fContour && fIndex == 0
77                 && next.fIndex == fLast - 1;
78     }
79 
isPartial(double t1,double t2,const SkDPoint & pt1,const SkDPoint & pt2)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 
left()88     SkScalar left() const {
89         return bounds().fLeft;
90     }
91 
pts()92     const SkPoint* pts() const {
93         return fContour->segments()[fIndex].pts();
94     }
95 
right()96     SkScalar right() const {
97         return bounds().fRight;
98     }
99 
segmentType()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 
startAfter(const SkIntersectionHelper & after)115     bool startAfter(const SkIntersectionHelper& after) {
116         fIndex = after.fIndex;
117         return advance();
118     }
119 
top()120     SkScalar top() const {
121         return bounds().fTop;
122     }
123 
verb()124     SkPath::Verb verb() const {
125         return fContour->segments()[fIndex].verb();
126     }
127 
x()128     SkScalar x() const {
129         return bounds().fLeft;
130     }
131 
xFlipped()132     bool xFlipped() const {
133         return x() != pts()[0].fX;
134     }
135 
y()136     SkScalar y() const {
137         return bounds().fTop;
138     }
139 
yFlipped()140     bool yFlipped() const {
141         return y() != pts()[0].fY;
142     }
143 
144 #ifdef SK_DEBUG
dump()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