blob: 3569c934de14a29d17224d2330d8bdfb8ce3676f [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
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
robertphillips@google.comd998bec2013-11-03 13:40:34 +000010#ifdef SK_DEBUG
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000011#include "SkPathOpsPoint.h"
12#endif
13
caryclark@google.com07393ca2013-04-08 11:47:37 +000014class SkIntersectionHelper {
15public:
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
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000024 bool addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) {
25 return fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
caryclark@google.com07393ca2013-04-08 11:47:37 +000026 }
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
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000034 bool addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index,
caryclark@google.com570863f2013-09-16 15:55:01 +000035 bool swap) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000036 return fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index,
37 swap);
caryclark@google.com570863f2013-09-16 15:55:01 +000038 }
39
caryclark@google.com07393ca2013-04-08 11:47:37 +000040 // 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
commit-bot@chromium.org866f4e32013-11-21 17:04:29 +000045 int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
46 return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT);
caryclark@google.com07393ca2013-04-08 11:47:37 +000047 }
48
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000049 int addSelfT(const SkPoint& pt, double newT) {
50 return fContour->addSelfT(fIndex, pt, newT);
caryclark@google.com07393ca2013-04-08 11:47:37 +000051 }
52
caryclark@google.com07393ca2013-04-08 11:47:37 +000053 bool advance() {
54 return ++fIndex < fLast;
55 }
56
caryclarkdac1d172014-06-17 05:15:38 -070057 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
caryclark@google.com07393ca2013-04-08 11:47:37 +000062 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
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000085 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
caryclark@google.com07393ca2013-04-08 11:47:37 +000093 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
caryclark@google.com07393ca2013-04-08 11:47:37 +0000149private:
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000150 // utility callable by the user from the debugger when the implementation code is linked in
151 void dump() const;
152
caryclark@google.com07393ca2013-04-08 11:47:37 +0000153 SkOpContour* fContour;
154 int fIndex;
155 int fLast;
156};