Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/pathops/SkOpAngle.cpp

Issue 1037573004: cumulative pathops patch (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix pathopsinverse gm Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpBuilder.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #include "SkIntersections.h"
8 #include "SkOpAngle.h" 7 #include "SkOpAngle.h"
9 #include "SkOpSegment.h" 8 #include "SkOpSegment.h"
10 #include "SkPathOpsCurve.h" 9 #include "SkPathOpsCurve.h"
11 #include "SkTSort.h" 10 #include "SkTSort.h"
12 11
13 #if DEBUG_ANGLE
14 #include "SkString.h"
15 #endif
16
17 /* Angles are sorted counterclockwise. The smallest angle has a positive x and t he smallest 12 /* Angles are sorted counterclockwise. The smallest angle has a positive x and t he smallest
18 positive y. The largest angle has a positive x and a zero y. */ 13 positive y. The largest angle has a positive x and a zero y. */
19 14
20 #if DEBUG_ANGLE 15 #if DEBUG_ANGLE
21 static bool CompareResult(SkString* bugOut, int append, bool compare) { 16 static bool CompareResult(const char* func, SkString* bugOut, SkString* bugP art, int append,
17 bool compare) {
22 SkDebugf("%s %c %d\n", bugOut->c_str(), compare ? 'T' : 'F', append); 18 SkDebugf("%s %c %d\n", bugOut->c_str(), compare ? 'T' : 'F', append);
19 SkDebugf("%sPart %s\n", func, bugPart[0].c_str());
20 SkDebugf("%sPart %s\n", func, bugPart[1].c_str());
21 SkDebugf("%sPart %s\n", func, bugPart[2].c_str());
23 return compare; 22 return compare;
24 } 23 }
25 24
26 #define COMPARE_RESULT(append, compare) CompareResult(&bugOut, append, compa re) 25 #define COMPARE_RESULT(append, compare) CompareResult(__FUNCTION__, &bugOut, bugPart, append, \
26 compare)
27 #else 27 #else
28 #define COMPARE_RESULT(append, compare) compare 28 #define COMPARE_RESULT(append, compare) compare
29 #endif 29 #endif
30 30
31 /* quarter angle values for sector 31 /* quarter angle values for sector
32 32
33 31 x > 0, y == 0 horizontal line (to the right) 33 31 x > 0, y == 0 horizontal line (to the right)
34 0 x > 0, y == epsilon quad/cubic horizontal tangent eventually going + y 34 0 x > 0, y == epsilon quad/cubic horizontal tangent eventually going + y
35 1 x > 0, y > 0, x > y nearer horizontal angle 35 1 x > 0, y > 0, x > y nearer horizontal angle
36 2 x + e == y quad/cubic 45 going horiz 36 2 x + e == y quad/cubic 45 going horiz
(...skipping 14 matching lines...) Expand all
51 16 | 30 51 16 | 30
52 17 | 29 52 17 | 29
53 18 / | \ 28 53 18 / | \ 28
54 19 | 27 54 19 | 27
55 20 | 26 55 20 | 26
56 21 | 25 56 21 | 25
57 22 23 24 57 22 23 24
58 */ 58 */
59 59
60 // return true if lh < this < rh 60 // return true if lh < this < rh
61 bool SkOpAngle::after(const SkOpAngle* test) const { 61 bool SkOpAngle::after(SkOpAngle* test) {
62 const SkOpAngle& lh = *test; 62 SkOpAngle* lh = test;
63 const SkOpAngle& rh = *lh.fNext; 63 SkOpAngle* rh = lh->fNext;
64 SkASSERT(&lh != &rh); 64 SkASSERT(lh != rh);
65 #if DEBUG_ANGLE 65 #if DEBUG_ANGLE
66 SkString bugOut; 66 SkString bugOut;
67 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" 67 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
68 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" 68 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
69 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__, 69 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
70 lh.fSegment->debugID(), lh.debugID(), lh.fSectorStart, lh.fSectorEnd , 70 lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSect orEnd,
71 lh.fSegment->t(lh.fStart), lh.fSegment->t(lh.fEnd), 71 lh->fStart->t(), lh->fEnd->t(),
72 fSegment->debugID(), debugID(), fSectorStart, fSectorEnd, fSegment-> t(fStart), 72 segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t (), fEnd->t(),
73 fSegment->t(fEnd), 73 rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSect orEnd,
74 rh.fSegment->debugID(), rh.debugID(), rh.fSectorStart, rh.fSectorEnd , 74 rh->fStart->t(), rh->fEnd->t());
75 rh.fSegment->t(rh.fStart), rh.fSegment->t(rh.fEnd)); 75 SkString bugPart[3] = { lh->debugPart(), this->debugPart(), rh->debugPart() };
76 #endif 76 #endif
77 if (lh.fComputeSector && !const_cast<SkOpAngle&>(lh).computeSector()) { 77 if (lh->fComputeSector && !lh->computeSector()) {
78 return COMPARE_RESULT(1, true); 78 return COMPARE_RESULT(1, true);
79 } 79 }
80 if (fComputeSector && !const_cast<SkOpAngle*>(this)->computeSector()) { 80 if (fComputeSector && !this->computeSector()) {
81 return COMPARE_RESULT(2, true); 81 return COMPARE_RESULT(2, true);
82 } 82 }
83 if (rh.fComputeSector && !const_cast<SkOpAngle&>(rh).computeSector()) { 83 if (rh->fComputeSector && !rh->computeSector()) {
84 return COMPARE_RESULT(3, true); 84 return COMPARE_RESULT(3, true);
85 } 85 }
86 #if DEBUG_ANGLE // reset bugOut with computed sectors 86 #if DEBUG_ANGLE // reset bugOut with computed sectors
87 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" 87 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
88 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" 88 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
89 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__, 89 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
90 lh.fSegment->debugID(), lh.debugID(), lh.fSectorStart, lh.fSectorEnd , 90 lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSect orEnd,
91 lh.fSegment->t(lh.fStart), lh.fSegment->t(lh.fEnd), 91 lh->fStart->t(), lh->fEnd->t(),
92 fSegment->debugID(), debugID(), fSectorStart, fSectorEnd, fSegment-> t(fStart), 92 segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t (), fEnd->t(),
93 fSegment->t(fEnd), 93 rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSect orEnd,
94 rh.fSegment->debugID(), rh.debugID(), rh.fSectorStart, rh.fSectorEnd , 94 rh->fStart->t(), rh->fEnd->t());
95 rh.fSegment->t(rh.fStart), rh.fSegment->t(rh.fEnd));
96 #endif 95 #endif
97 bool ltrOverlap = (lh.fSectorMask | rh.fSectorMask) & fSectorMask; 96 bool ltrOverlap = (lh->fSectorMask | rh->fSectorMask) & fSectorMask;
98 bool lrOverlap = lh.fSectorMask & rh.fSectorMask; 97 bool lrOverlap = lh->fSectorMask & rh->fSectorMask;
99 int lrOrder; // set to -1 if either order works 98 int lrOrder; // set to -1 if either order works
100 if (!lrOverlap) { // no lh/rh sector overlap 99 if (!lrOverlap) { // no lh/rh sector overlap
101 if (!ltrOverlap) { // no lh/this/rh sector overlap 100 if (!ltrOverlap) { // no lh/this/rh sector overlap
102 return COMPARE_RESULT(4, (lh.fSectorEnd > rh.fSectorStart) 101 return COMPARE_RESULT(4, (lh->fSectorEnd > rh->fSectorStart)
103 ^ (fSectorStart > lh.fSectorEnd) ^ (fSectorStart > rh.fSecto rStart)); 102 ^ (fSectorStart > lh->fSectorEnd) ^ (fSectorStart > rh->fSec torStart));
104 } 103 }
105 int lrGap = (rh.fSectorStart - lh.fSectorStart + 32) & 0x1f; 104 int lrGap = (rh->fSectorStart - lh->fSectorStart + 32) & 0x1f;
106 /* A tiny change can move the start +/- 4. The order can only be determi ned if 105 /* A tiny change can move the start +/- 4. The order can only be determi ned if
107 lr gap is not 12 to 20 or -12 to -20. 106 lr gap is not 12 to 20 or -12 to -20.
108 -31 ..-21 1 107 -31 ..-21 1
109 -20 ..-12 -1 108 -20 ..-12 -1
110 -11 .. -1 0 109 -11 .. -1 0
111 0 shouldn't get here 110 0 shouldn't get here
112 11 .. 1 1 111 11 .. 1 1
113 12 .. 20 -1 112 12 .. 20 -1
114 21 .. 31 0 113 21 .. 31 0
115 */ 114 */
116 lrOrder = lrGap > 20 ? 0 : lrGap > 11 ? -1 : 1; 115 lrOrder = lrGap > 20 ? 0 : lrGap > 11 ? -1 : 1;
117 } else { 116 } else {
118 lrOrder = (int) lh.orderable(rh); 117 lrOrder = (int) lh->orderable(rh);
119 if (!ltrOverlap) { 118 if (!ltrOverlap) {
120 return COMPARE_RESULT(5, !lrOrder); 119 return COMPARE_RESULT(5, !lrOrder);
121 } 120 }
122 } 121 }
123 int ltOrder; 122 int ltOrder;
124 SkASSERT((lh.fSectorMask & fSectorMask) || (rh.fSectorMask & fSectorMask)); 123 SkASSERT((lh->fSectorMask & fSectorMask) || (rh->fSectorMask & fSectorMask)) ;
125 if (lh.fSectorMask & fSectorMask) { 124 if (lh->fSectorMask & fSectorMask) {
126 ltOrder = (int) lh.orderable(*this); 125 ltOrder = (int) lh->orderable(this);
127 } else { 126 } else {
128 int ltGap = (fSectorStart - lh.fSectorStart + 32) & 0x1f; 127 int ltGap = (fSectorStart - lh->fSectorStart + 32) & 0x1f;
129 ltOrder = ltGap > 20 ? 0 : ltGap > 11 ? -1 : 1; 128 ltOrder = ltGap > 20 ? 0 : ltGap > 11 ? -1 : 1;
130 } 129 }
131 int trOrder; 130 int trOrder;
132 if (rh.fSectorMask & fSectorMask) { 131 if (rh->fSectorMask & fSectorMask) {
133 trOrder = (int) orderable(rh); 132 trOrder = (int) orderable(rh);
134 } else { 133 } else {
135 int trGap = (rh.fSectorStart - fSectorStart + 32) & 0x1f; 134 int trGap = (rh->fSectorStart - fSectorStart + 32) & 0x1f;
136 trOrder = trGap > 20 ? 0 : trGap > 11 ? -1 : 1; 135 trOrder = trGap > 20 ? 0 : trGap > 11 ? -1 : 1;
137 } 136 }
138 if (lrOrder >= 0 && ltOrder >= 0 && trOrder >= 0) { 137 if (lrOrder >= 0 && ltOrder >= 0 && trOrder >= 0) {
139 return COMPARE_RESULT(7, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOr der)); 138 return COMPARE_RESULT(7, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOr der));
140 } 139 }
141 SkASSERT(lrOrder >= 0 || ltOrder >= 0 || trOrder >= 0); 140 SkASSERT(lrOrder >= 0 || ltOrder >= 0 || trOrder >= 0);
142 // There's not enough information to sort. Get the pairs of angles in opposite p lanes. 141 // There's not enough information to sort. Get the pairs of angles in opposite p lanes.
143 // If an order is < 0, the pair is already in an opposite plane. Check the remai ning pairs. 142 // If an order is < 0, the pair is already in an opposite plane. Check the remai ning pairs.
144 // FIXME : once all variants are understood, rewrite this more simply 143 // FIXME : once all variants are understood, rewrite this more simply
145 if (ltOrder == 0 && lrOrder == 0) { 144 if (ltOrder == 0 && lrOrder == 0) {
146 SkASSERT(trOrder < 0); 145 SkASSERT(trOrder < 0);
147 // FIXME : once this is verified to work, remove one opposite angle call 146 // FIXME : once this is verified to work, remove one opposite angle call
148 SkDEBUGCODE(bool lrOpposite = lh.oppositePlanes(rh)); 147 SkDEBUGCODE(bool lrOpposite = lh->oppositePlanes(rh));
149 bool ltOpposite = lh.oppositePlanes(*this); 148 bool ltOpposite = lh->oppositePlanes(this);
150 SkASSERT(lrOpposite != ltOpposite); 149 SkASSERT(lrOpposite != ltOpposite);
151 return COMPARE_RESULT(8, ltOpposite); 150 return COMPARE_RESULT(8, ltOpposite);
152 } else if (ltOrder == 1 && trOrder == 0) { 151 } else if (ltOrder == 1 && trOrder == 0) {
153 SkASSERT(lrOrder < 0); 152 SkASSERT(lrOrder < 0);
154 SkDEBUGCODE(bool ltOpposite = lh.oppositePlanes(*this)); 153 SkDEBUGCODE(bool ltOpposite = lh->oppositePlanes(this));
155 bool trOpposite = oppositePlanes(rh); 154 bool trOpposite = oppositePlanes(rh);
156 SkASSERT(ltOpposite != trOpposite); 155 SkASSERT(ltOpposite != trOpposite);
157 return COMPARE_RESULT(9, trOpposite); 156 return COMPARE_RESULT(9, trOpposite);
158 } else if (lrOrder == 1 && trOrder == 1) { 157 } else if (lrOrder == 1 && trOrder == 1) {
159 SkASSERT(ltOrder < 0); 158 SkASSERT(ltOrder < 0);
160 SkDEBUGCODE(bool trOpposite = oppositePlanes(rh)); 159 SkDEBUGCODE(bool trOpposite = oppositePlanes(rh));
161 bool lrOpposite = lh.oppositePlanes(rh); 160 bool lrOpposite = lh->oppositePlanes(rh);
162 SkASSERT(lrOpposite != trOpposite); 161 SkASSERT(lrOpposite != trOpposite);
163 return COMPARE_RESULT(10, lrOpposite); 162 return COMPARE_RESULT(10, lrOpposite);
164 } 163 }
165 if (lrOrder < 0) { 164 if (lrOrder < 0) {
166 if (ltOrder < 0) { 165 if (ltOrder < 0) {
167 return COMPARE_RESULT(11, trOrder); 166 return COMPARE_RESULT(11, trOrder);
168 } 167 }
169 return COMPARE_RESULT(12, ltOrder); 168 return COMPARE_RESULT(12, ltOrder);
170 } 169 }
171 return COMPARE_RESULT(13, !lrOrder); 170 return COMPARE_RESULT(13, !lrOrder);
172 } 171 }
173 172
174 // given a line, see if the opposite curve's convex hull is all on one side 173 // given a line, see if the opposite curve's convex hull is all on one side
175 // returns -1=not on one side 0=this CW of test 1=this CCW of test 174 // returns -1=not on one side 0=this CW of test 1=this CCW of test
176 int SkOpAngle::allOnOneSide(const SkOpAngle& test) const { 175 int SkOpAngle::allOnOneSide(const SkOpAngle* test) {
177 SkASSERT(!fIsCurve); 176 SkASSERT(!fIsCurve);
178 SkASSERT(test.fIsCurve); 177 SkASSERT(test->fIsCurve);
179 const SkDPoint& origin = test.fCurvePart[0]; 178 const SkDPoint& origin = test->fCurvePart[0];
180 SkVector line; 179 SkVector line;
181 if (fSegment->verb() == SkPath::kLine_Verb) { 180 if (segment()->verb() == SkPath::kLine_Verb) {
182 const SkPoint* linePts = fSegment->pts(); 181 const SkPoint* linePts = segment()->pts();
183 int lineStart = fStart < fEnd ? 0 : 1; 182 int lineStart = fStart->t() < fEnd->t() ? 0 : 1;
184 line = linePts[lineStart ^ 1] - linePts[lineStart]; 183 line = linePts[lineStart ^ 1] - linePts[lineStart];
185 } else { 184 } else {
186 SkPoint shortPts[2] = { fCurvePart[0].asSkPoint(), fCurvePart[1].asSkPoi nt() }; 185 SkPoint shortPts[2] = { fCurvePart[0].asSkPoint(), fCurvePart[1].asSkPoi nt() };
187 line = shortPts[1] - shortPts[0]; 186 line = shortPts[1] - shortPts[0];
188 } 187 }
189 float crosses[3]; 188 float crosses[3];
190 SkPath::Verb testVerb = test.fSegment->verb(); 189 SkPath::Verb testVerb = test->segment()->verb();
191 int iMax = SkPathOpsVerbToPoints(testVerb); 190 int iMax = SkPathOpsVerbToPoints(testVerb);
192 // SkASSERT(origin == test.fCurveHalf[0]); 191 // SkASSERT(origin == test.fCurveHalf[0]);
193 const SkDCubic& testCurve = test.fCurvePart; 192 const SkDCubic& testCurve = test->fCurvePart;
194 // do { 193 for (int index = 1; index <= iMax; ++index) {
195 for (int index = 1; index <= iMax; ++index) { 194 float xy1 = (float) (line.fX * (testCurve[index].fY - origin.fY));
196 float xy1 = (float) (line.fX * (testCurve[index].fY - origin.fY)); 195 float xy2 = (float) (line.fY * (testCurve[index].fX - origin.fX));
197 float xy2 = (float) (line.fY * (testCurve[index].fX - origin.fX)); 196 crosses[index - 1] = AlmostEqualUlps(xy1, xy2) ? 0 : xy1 - xy2;
198 crosses[index - 1] = AlmostEqualUlps(xy1, xy2) ? 0 : xy1 - xy2; 197 }
199 } 198 if (crosses[0] * crosses[1] < 0) {
200 if (crosses[0] * crosses[1] < 0) { 199 return -1;
200 }
201 if (SkPath::kCubic_Verb == testVerb) {
202 if (crosses[0] * crosses[2] < 0 || crosses[1] * crosses[2] < 0) {
201 return -1; 203 return -1;
202 } 204 }
203 if (SkPath::kCubic_Verb == testVerb) { 205 }
204 if (crosses[0] * crosses[2] < 0 || crosses[1] * crosses[2] < 0) { 206 if (crosses[0]) {
205 return -1; 207 return crosses[0] < 0;
206 } 208 }
207 } 209 if (crosses[1]) {
208 if (crosses[0]) { 210 return crosses[1] < 0;
209 return crosses[0] < 0; 211 }
210 } 212 if (SkPath::kCubic_Verb == testVerb && crosses[2]) {
211 if (crosses[1]) { 213 return crosses[2] < 0;
212 return crosses[1] < 0; 214 }
213 }
214 if (SkPath::kCubic_Verb == testVerb && crosses[2]) {
215 return crosses[2] < 0;
216 }
217 fUnorderable = true; 215 fUnorderable = true;
218 return -1; 216 return -1;
219 } 217 }
220 218
221 bool SkOpAngle::calcSlop(double x, double y, double rx, double ry, bool* result) const {
222 double absX = fabs(x);
223 double absY = fabs(y);
224 double length = absX < absY ? absX / 2 + absY : absX + absY / 2;
225 int exponent;
226 (void) frexp(length, &exponent);
227 double epsilon = ldexp(FLT_EPSILON, exponent);
228 SkPath::Verb verb = fSegment->verb();
229 SkASSERT(verb == SkPath::kQuad_Verb || verb == SkPath::kCubic_Verb);
230 // FIXME: the quad and cubic factors are made up ; determine actual values
231 double slop = verb == SkPath::kQuad_Verb ? 4 * epsilon : 512 * epsilon;
232 double xSlop = slop;
233 double ySlop = x * y < 0 ? -xSlop : xSlop; // OPTIMIZATION: use copysign / _ copysign ?
234 double x1 = x - xSlop;
235 double y1 = y + ySlop;
236 double x_ry1 = x1 * ry;
237 double rx_y1 = rx * y1;
238 *result = x_ry1 < rx_y1;
239 double x2 = x + xSlop;
240 double y2 = y - ySlop;
241 double x_ry2 = x2 * ry;
242 double rx_y2 = rx * y2;
243 bool less2 = x_ry2 < rx_y2;
244 return *result == less2;
245 }
246
247 bool SkOpAngle::checkCrossesZero() const { 219 bool SkOpAngle::checkCrossesZero() const {
248 int start = SkTMin(fSectorStart, fSectorEnd); 220 int start = SkTMin(fSectorStart, fSectorEnd);
249 int end = SkTMax(fSectorStart, fSectorEnd); 221 int end = SkTMax(fSectorStart, fSectorEnd);
250 bool crossesZero = end - start > 16; 222 bool crossesZero = end - start > 16;
251 return crossesZero; 223 return crossesZero;
252 } 224 }
253 225
254 bool SkOpAngle::checkParallel(const SkOpAngle& rh) const { 226 // loop looking for a pair of angle parts that are too close to be sorted
227 /* This is called after other more simple intersection and angle sorting tests h ave been exhausted.
228 This should be rarely called -- the test below is thorough and time consuming .
229 This checks the distance between start points; the distance between
230 */
231 void SkOpAngle::checkNearCoincidence() {
232 SkOpAngle* test = this;
233 do {
234 SkOpSegment* testSegment = test->segment();
235 double testStartT = test->start()->t();
236 SkDPoint testStartPt = testSegment->dPtAtT(testStartT);
237 double testEndT = test->end()->t();
238 SkDPoint testEndPt = testSegment->dPtAtT(testEndT);
239 double testLenSq = testStartPt.distanceSquared(testEndPt);
240 if (0) {
241 SkDebugf("%s testLenSq=%1.9g id=%d\n", __FUNCTION__, testLenSq, test Segment->debugID());
242 }
243 double testMidT = (testStartT + testEndT) / 2;
244 SkOpAngle* next = test;
245 while ((next = next->fNext) != this) {
246 SkOpSegment* nextSegment = next->segment();
247 double testMidDistSq = testSegment->distSq(testMidT, next);
248 double testEndDistSq = testSegment->distSq(testEndT, next);
249 double nextStartT = next->start()->t();
250 SkDPoint nextStartPt = nextSegment->dPtAtT(nextStartT);
251 double distSq = testStartPt.distanceSquared(nextStartPt);
252 double nextEndT = next->end()->t();
253 double nextMidT = (nextStartT + nextEndT) / 2;
254 double nextMidDistSq = nextSegment->distSq(nextMidT, test);
255 double nextEndDistSq = nextSegment->distSq(nextEndT, test);
256 if (0) {
257 SkDebugf("%s distSq=%1.9g testId=%d nextId=%d\n", __FUNCTION__, distSq,
258 testSegment->debugID(), nextSegment->debugID());
259 SkDebugf("%s testMidDistSq=%1.9g\n", __FUNCTION__, testMidDistSq );
260 SkDebugf("%s testEndDistSq=%1.9g\n", __FUNCTION__, testEndDistSq );
261 SkDebugf("%s nextMidDistSq=%1.9g\n", __FUNCTION__, nextMidDistSq );
262 SkDebugf("%s nextEndDistSq=%1.9g\n", __FUNCTION__, nextEndDistSq );
263 SkDPoint nextEndPt = nextSegment->dPtAtT(nextEndT);
264 double nextLenSq = nextStartPt.distanceSquared(nextEndPt);
265 SkDebugf("%s nextLenSq=%1.9g\n", __FUNCTION__, nextLenSq);
266 SkDebugf("\n");
267 }
268 }
269 test = test->fNext;
270 } while (test->fNext != this);
271 }
272
273 bool SkOpAngle::checkParallel(SkOpAngle* rh) {
255 SkDVector scratch[2]; 274 SkDVector scratch[2];
256 const SkDVector* sweep, * tweep; 275 const SkDVector* sweep, * tweep;
257 if (!fUnorderedSweep) { 276 if (!this->fUnorderedSweep) {
258 sweep = fSweep; 277 sweep = this->fSweep;
259 } else { 278 } else {
260 scratch[0] = fCurvePart[1] - fCurvePart[0]; 279 scratch[0] = this->fCurvePart[1] - this->fCurvePart[0];
261 sweep = &scratch[0]; 280 sweep = &scratch[0];
262 } 281 }
263 if (!rh.fUnorderedSweep) { 282 if (!rh->fUnorderedSweep) {
264 tweep = rh.fSweep; 283 tweep = rh->fSweep;
265 } else { 284 } else {
266 scratch[1] = rh.fCurvePart[1] - rh.fCurvePart[0]; 285 scratch[1] = rh->fCurvePart[1] - rh->fCurvePart[0];
267 tweep = &scratch[1]; 286 tweep = &scratch[1];
268 } 287 }
269 double s0xt0 = sweep->crossCheck(*tweep); 288 double s0xt0 = sweep->crossCheck(*tweep);
270 if (tangentsDiverge(rh, s0xt0)) { 289 if (tangentsDiverge(rh, s0xt0)) {
271 return s0xt0 < 0; 290 return s0xt0 < 0;
272 } 291 }
273 SkDVector m0 = fSegment->dPtAtT(midT()) - fCurvePart[0]; 292 // compute the perpendicular to the endpoints and see where it intersects th e opposite curve
274 SkDVector m1 = rh.fSegment->dPtAtT(rh.midT()) - rh.fCurvePart[0]; 293 // if the intersections within the t range, do a cross check on those
294 bool inside;
295 if (this->endToSide(rh, &inside)) {
296 return inside;
297 }
298 if (rh->endToSide(this, &inside)) {
299 return !inside;
300 }
301 if (this->midToSide(rh, &inside)) {
302 return inside;
303 }
304 if (rh->midToSide(this, &inside)) {
305 return !inside;
306 }
307 // compute the cross check from the mid T values (last resort)
308 SkDVector m0 = segment()->dPtAtT(this->midT()) - this->fCurvePart[0];
309 SkDVector m1 = rh->segment()->dPtAtT(rh->midT()) - rh->fCurvePart[0];
275 double m0xm1 = m0.crossCheck(m1); 310 double m0xm1 = m0.crossCheck(m1);
276 if (m0xm1 == 0) { 311 if (m0xm1 == 0) {
277 fUnorderable = true; 312 this->fUnorderable = true;
278 rh.fUnorderable = true; 313 rh->fUnorderable = true;
279 return true; 314 return true;
280 } 315 }
281 return m0xm1 < 0; 316 return m0xm1 < 0;
282 } 317 }
283 318
284 // the original angle is too short to get meaningful sector information 319 // the original angle is too short to get meaningful sector information
285 // lengthen it until it is long enough to be meaningful or leave it unset if len gthening it 320 // lengthen it until it is long enough to be meaningful or leave it unset if len gthening it
286 // would cause it to intersect one of the adjacent angles 321 // would cause it to intersect one of the adjacent angles
287 bool SkOpAngle::computeSector() { 322 bool SkOpAngle::computeSector() {
288 if (fComputedSector) { 323 if (fComputedSector) {
289 return !fUnorderable; 324 return !fUnorderable;
290 } 325 }
291 // SkASSERT(fSegment->verb() != SkPath::kLine_Verb && small());
292 fComputedSector = true; 326 fComputedSector = true;
293 int step = fStart < fEnd ? 1 : -1; 327 bool stepUp = fStart->t() < fEnd->t();
294 int limit = step > 0 ? fSegment->count() : -1; 328 const SkOpSpanBase* checkEnd = fEnd;
295 int checkEnd = fEnd; 329 if (checkEnd->final() && stepUp) {
330 fUnorderable = true;
331 return false;
332 }
296 do { 333 do {
297 // advance end 334 // advance end
298 const SkOpSpan& span = fSegment->span(checkEnd); 335 const SkOpSegment* other = checkEnd->segment();
299 const SkOpSegment* other = span.fOther; 336 const SkOpSpanBase* oSpan = other->head();
300 int oCount = other->count(); 337 do {
301 for (int oIndex = 0; oIndex < oCount; ++oIndex) { 338 if (oSpan->segment() != segment()) {
302 const SkOpSpan& oSpan = other->span(oIndex);
303 if (oSpan.fOther != fSegment) {
304 continue; 339 continue;
305 } 340 }
306 if (oSpan.fOtherIndex == checkEnd) { 341 if (oSpan == checkEnd) {
307 continue; 342 continue;
308 } 343 }
309 if (!approximately_equal(oSpan.fOtherT, span.fT)) { 344 if (!approximately_equal(oSpan->t(), checkEnd->t())) {
310 continue; 345 continue;
311 } 346 }
312 goto recomputeSector; 347 goto recomputeSector;
313 } 348 } while (!oSpan->final() && (oSpan = oSpan->upCast()->next()));
314 checkEnd += step; 349 checkEnd = stepUp ? !checkEnd->final()
315 } while (checkEnd != limit); 350 ? checkEnd->upCast()->next() : NULL
351 : checkEnd->prev();
352 } while (checkEnd);
316 recomputeSector: 353 recomputeSector:
317 if (checkEnd == fEnd || checkEnd - step == fEnd) { 354 SkOpSpanBase* computedEnd = stepUp ? checkEnd ? checkEnd->prev() : fEnd->seg ment()->head()
355 : checkEnd ? checkEnd->upCast()->next() : fEnd->segment()->tail();
356 if (checkEnd == fEnd || computedEnd == fEnd || computedEnd == fStart) {
318 fUnorderable = true; 357 fUnorderable = true;
319 return false; 358 return false;
320 } 359 }
321 int saveEnd = fEnd; 360 SkOpSpanBase* saveEnd = fEnd;
322 fComputedEnd = fEnd = checkEnd - step; 361 fComputedEnd = fEnd = computedEnd;
323 setSpans(); 362 setSpans();
324 setSector(); 363 setSector();
325 fEnd = saveEnd; 364 fEnd = saveEnd;
326 return !fUnorderable; 365 return !fUnorderable;
327 } 366 }
328 367
329 // returns -1 if overlaps 0 if no overlap cw 1 if no overlap ccw 368 int SkOpAngle::convexHullOverlaps(const SkOpAngle* rh) const {
330 int SkOpAngle::convexHullOverlaps(const SkOpAngle& rh) const { 369 const SkDVector* sweep = this->fSweep;
331 const SkDVector* sweep = fSweep; 370 const SkDVector* tweep = rh->fSweep;
332 const SkDVector* tweep = rh.fSweep;
333 double s0xs1 = sweep[0].crossCheck(sweep[1]); 371 double s0xs1 = sweep[0].crossCheck(sweep[1]);
334 double s0xt0 = sweep[0].crossCheck(tweep[0]); 372 double s0xt0 = sweep[0].crossCheck(tweep[0]);
335 double s1xt0 = sweep[1].crossCheck(tweep[0]); 373 double s1xt0 = sweep[1].crossCheck(tweep[0]);
336 bool tBetweenS = s0xs1 > 0 ? s0xt0 > 0 && s1xt0 < 0 : s0xt0 < 0 && s1xt0 > 0 ; 374 bool tBetweenS = s0xs1 > 0 ? s0xt0 > 0 && s1xt0 < 0 : s0xt0 < 0 && s1xt0 > 0 ;
337 double s0xt1 = sweep[0].crossCheck(tweep[1]); 375 double s0xt1 = sweep[0].crossCheck(tweep[1]);
338 double s1xt1 = sweep[1].crossCheck(tweep[1]); 376 double s1xt1 = sweep[1].crossCheck(tweep[1]);
339 tBetweenS |= s0xs1 > 0 ? s0xt1 > 0 && s1xt1 < 0 : s0xt1 < 0 && s1xt1 > 0; 377 tBetweenS |= s0xs1 > 0 ? s0xt1 > 0 && s1xt1 < 0 : s0xt1 < 0 && s1xt1 > 0;
340 double t0xt1 = tweep[0].crossCheck(tweep[1]); 378 double t0xt1 = tweep[0].crossCheck(tweep[1]);
341 if (tBetweenS) { 379 if (tBetweenS) {
342 return -1; 380 return -1;
343 } 381 }
344 if ((s0xt0 == 0 && s1xt1 == 0) || (s1xt0 == 0 && s0xt1 == 0)) { // s0 to s1 equals t0 to t1 382 if ((s0xt0 == 0 && s1xt1 == 0) || (s1xt0 == 0 && s0xt1 == 0)) { // s0 to s1 equals t0 to t1
345 return -1; 383 return -1;
346 } 384 }
347 bool sBetweenT = t0xt1 > 0 ? s0xt0 < 0 && s0xt1 > 0 : s0xt0 > 0 && s0xt1 < 0 ; 385 bool sBetweenT = t0xt1 > 0 ? s0xt0 < 0 && s0xt1 > 0 : s0xt0 > 0 && s0xt1 < 0 ;
348 sBetweenT |= t0xt1 > 0 ? s1xt0 < 0 && s1xt1 > 0 : s1xt0 > 0 && s1xt1 < 0; 386 sBetweenT |= t0xt1 > 0 ? s1xt0 < 0 && s1xt1 > 0 : s1xt0 > 0 && s1xt1 < 0;
349 if (sBetweenT) { 387 if (sBetweenT) {
350 return -1; 388 return -1;
351 } 389 }
352 // if all of the sweeps are in the same half plane, then the order of any pa ir is enough 390 // if all of the sweeps are in the same half plane, then the order of any pa ir is enough
353 if (s0xt0 >= 0 && s0xt1 >= 0 && s1xt0 >= 0 && s1xt1 >= 0) { 391 if (s0xt0 >= 0 && s0xt1 >= 0 && s1xt0 >= 0 && s1xt1 >= 0) {
354 return 0; 392 return 0;
355 } 393 }
356 if (s0xt0 <= 0 && s0xt1 <= 0 && s1xt0 <= 0 && s1xt1 <= 0) { 394 if (s0xt0 <= 0 && s0xt1 <= 0 && s1xt0 <= 0 && s1xt1 <= 0) {
357 return 1; 395 return 1;
358 } 396 }
359 // if the outside sweeps are greater than 180 degress: 397 // if the outside sweeps are greater than 180 degress:
360 // first assume the inital tangents are the ordering 398 // first assume the inital tangents are the ordering
361 // if the midpoint direction matches the inital order, that is enough 399 // if the midpoint direction matches the inital order, that is enough
362 SkDVector m0 = fSegment->dPtAtT(midT()) - fCurvePart[0]; 400 SkDVector m0 = this->segment()->dPtAtT(this->midT()) - this->fCurvePart[0];
363 SkDVector m1 = rh.fSegment->dPtAtT(rh.midT()) - rh.fCurvePart[0]; 401 SkDVector m1 = rh->segment()->dPtAtT(rh->midT()) - rh->fCurvePart[0];
364 double m0xm1 = m0.crossCheck(m1); 402 double m0xm1 = m0.crossCheck(m1);
365 if (s0xt0 > 0 && m0xm1 > 0) { 403 if (s0xt0 > 0 && m0xm1 > 0) {
366 return 0; 404 return 0;
367 } 405 }
368 if (s0xt0 < 0 && m0xm1 < 0) { 406 if (s0xt0 < 0 && m0xm1 < 0) {
369 return 1; 407 return 1;
370 } 408 }
371 if (tangentsDiverge(rh, s0xt0)) { 409 if (tangentsDiverge(rh, s0xt0)) {
372 return s0xt0 < 0; 410 return s0xt0 < 0;
373 } 411 }
(...skipping 13 matching lines...) Expand all
387 } 425 }
388 SkDVector v; 426 SkDVector v;
389 v.set(pts[idx2] - pts[idx1]); 427 v.set(pts[idx2] - pts[idx1]);
390 double lenSq = v.lengthSquared(); 428 double lenSq = v.lengthSquared();
391 longest = SkTMax(longest, lenSq); 429 longest = SkTMax(longest, lenSq);
392 } 430 }
393 } 431 }
394 return sqrt(longest) / dist; 432 return sqrt(longest) / dist;
395 } 433 }
396 434
397 bool SkOpAngle::endsIntersect(const SkOpAngle& rh) const { 435 bool SkOpAngle::endsIntersect(SkOpAngle* rh) {
398 SkPath::Verb lVerb = fSegment->verb(); 436 SkPath::Verb lVerb = this->segment()->verb();
399 SkPath::Verb rVerb = rh.fSegment->verb(); 437 SkPath::Verb rVerb = rh->segment()->verb();
400 int lPts = SkPathOpsVerbToPoints(lVerb); 438 int lPts = SkPathOpsVerbToPoints(lVerb);
401 int rPts = SkPathOpsVerbToPoints(rVerb); 439 int rPts = SkPathOpsVerbToPoints(rVerb);
402 SkDLine rays[] = {{{fCurvePart[0], rh.fCurvePart[rPts]}}, 440 SkDLine rays[] = {{{this->fCurvePart[0], rh->fCurvePart[rPts]}},
403 {{fCurvePart[0], fCurvePart[lPts]}}}; 441 {{this->fCurvePart[0], this->fCurvePart[lPts]}}};
404 if (rays[0][1] == rays[1][1]) { 442 if (rays[0][1] == rays[1][1]) {
405 return checkParallel(rh); 443 return checkParallel(rh);
406 } 444 }
407 double smallTs[2] = {-1, -1}; 445 double smallTs[2] = {-1, -1};
408 bool limited[2] = {false, false}; 446 bool limited[2] = {false, false};
409 for (int index = 0; index < 2; ++index) { 447 for (int index = 0; index < 2; ++index) {
410 const SkOpSegment& segment = index ? *rh.fSegment : *fSegment;
411 SkIntersections i;
412 int cPts = index ? rPts : lPts; 448 int cPts = index ? rPts : lPts;
413 (*CurveIntersectRay[cPts])(segment.pts(), rays[index], &i);
414 // if the curve is a line, then the line and the ray intersect only at t heir crossing 449 // if the curve is a line, then the line and the ray intersect only at t heir crossing
415 if (cPts == 1) { // line 450 if (cPts == 1) { // line
416 continue; 451 continue;
417 } 452 }
418 // SkASSERT(i.used() >= 1); 453 const SkOpSegment& segment = index ? *rh->segment() : *this->segment();
419 // if (i.used() <= 1) { 454 SkIntersections i;
420 // continue; 455 (*CurveIntersectRay[cPts])(segment.pts(), rays[index], &i);
421 // } 456 double tStart = index ? rh->fStart->t() : this->fStart->t();
422 double tStart = segment.t(index ? rh.fStart : fStart); 457 double tEnd = index ? rh->fComputedEnd->t() : this->fComputedEnd->t();
423 double tEnd = segment.t(index ? rh.fComputedEnd : fComputedEnd); 458 bool testAscends = tStart < (index ? rh->fComputedEnd->t() : this->fComp utedEnd->t());
424 bool testAscends = index ? rh.fStart < rh.fComputedEnd : fStart < fCompu tedEnd;
425 double t = testAscends ? 0 : 1; 459 double t = testAscends ? 0 : 1;
426 for (int idx2 = 0; idx2 < i.used(); ++idx2) { 460 for (int idx2 = 0; idx2 < i.used(); ++idx2) {
427 double testT = i[0][idx2]; 461 double testT = i[0][idx2];
428 if (!approximately_between_orderable(tStart, testT, tEnd)) { 462 if (!approximately_between_orderable(tStart, testT, tEnd)) {
429 continue; 463 continue;
430 } 464 }
431 if (approximately_equal_orderable(tStart, testT)) { 465 if (approximately_equal_orderable(tStart, testT)) {
432 continue; 466 continue;
433 } 467 }
434 smallTs[index] = t = testAscends ? SkTMax(t, testT) : SkTMin(t, test T); 468 smallTs[index] = t = testAscends ? SkTMax(t, testT) : SkTMin(t, test T);
435 limited[index] = approximately_equal_orderable(t, tEnd); 469 limited[index] = approximately_equal_orderable(t, tEnd);
436 } 470 }
437 } 471 }
438 #if 0
439 if (smallTs[0] < 0 && smallTs[1] < 0) { // if neither ray intersects, do en dpoint sort
440 double m0xm1 = 0;
441 if (lVerb == SkPath::kLine_Verb) {
442 SkASSERT(rVerb != SkPath::kLine_Verb);
443 SkDVector m0 = rays[1][1] - fCurvePart[0];
444 SkDPoint endPt;
445 endPt.set(rh.fSegment->pts()[rh.fStart < rh.fEnd ? rPts : 0]);
446 SkDVector m1 = endPt - fCurvePart[0];
447 m0xm1 = m0.crossCheck(m1);
448 }
449 if (rVerb == SkPath::kLine_Verb) {
450 SkDPoint endPt;
451 endPt.set(fSegment->pts()[fStart < fEnd ? lPts : 0]);
452 SkDVector m0 = endPt - fCurvePart[0];
453 SkDVector m1 = rays[0][1] - fCurvePart[0];
454 m0xm1 = m0.crossCheck(m1);
455 }
456 if (m0xm1 != 0) {
457 return m0xm1 < 0;
458 }
459 }
460 #endif
461 bool sRayLonger = false; 472 bool sRayLonger = false;
462 SkDVector sCept = {0, 0}; 473 SkDVector sCept = {0, 0};
463 double sCeptT = -1; 474 double sCeptT = -1;
464 int sIndex = -1; 475 int sIndex = -1;
465 bool useIntersect = false; 476 bool useIntersect = false;
466 for (int index = 0; index < 2; ++index) { 477 for (int index = 0; index < 2; ++index) {
467 if (smallTs[index] < 0) { 478 if (smallTs[index] < 0) {
468 continue; 479 continue;
469 } 480 }
470 const SkOpSegment& segment = index ? *rh.fSegment : *fSegment; 481 const SkOpSegment& segment = index ? *rh->segment() : *this->segment();
471 const SkDPoint& dPt = segment.dPtAtT(smallTs[index]); 482 const SkDPoint& dPt = segment.dPtAtT(smallTs[index]);
472 SkDVector cept = dPt - rays[index][0]; 483 SkDVector cept = dPt - rays[index][0];
473 // If this point is on the curve, it should have been detected earlier b y ordinary 484 // If this point is on the curve, it should have been detected earlier b y ordinary
474 // curve intersection. This may be hard to determine in general, but for lines, 485 // curve intersection. This may be hard to determine in general, but for lines,
475 // the point could be close to or equal to its end, but shouldn't be nea r the start. 486 // the point could be close to or equal to its end, but shouldn't be nea r the start.
476 if ((index ? lPts : rPts) == 1) { 487 if ((index ? lPts : rPts) == 1) {
477 SkDVector total = rays[index][1] - rays[index][0]; 488 SkDVector total = rays[index][1] - rays[index][0];
478 if (cept.lengthSquared() * 2 < total.lengthSquared()) { 489 if (cept.lengthSquared() * 2 < total.lengthSquared()) {
479 continue; 490 continue;
480 } 491 }
(...skipping 10 matching lines...) Expand all
491 sRayLonger = rayLonger; 502 sRayLonger = rayLonger;
492 sCept = cept; 503 sCept = cept;
493 sCeptT = smallTs[index]; 504 sCeptT = smallTs[index];
494 sIndex = index; 505 sIndex = index;
495 break; 506 break;
496 } 507 }
497 double delta = fabs(rayDist - endDist); 508 double delta = fabs(rayDist - endDist);
498 double minX, minY, maxX, maxY; 509 double minX, minY, maxX, maxY;
499 minX = minY = SK_ScalarInfinity; 510 minX = minY = SK_ScalarInfinity;
500 maxX = maxY = -SK_ScalarInfinity; 511 maxX = maxY = -SK_ScalarInfinity;
501 const SkDCubic& curve = index ? rh.fCurvePart : fCurvePart; 512 const SkDCubic& curve = index ? rh->fCurvePart : this->fCurvePart;
502 int ptCount = index ? rPts : lPts; 513 int ptCount = index ? rPts : lPts;
503 for (int idx2 = 0; idx2 <= ptCount; ++idx2) { 514 for (int idx2 = 0; idx2 <= ptCount; ++idx2) {
504 minX = SkTMin(minX, curve[idx2].fX); 515 minX = SkTMin(minX, curve[idx2].fX);
505 minY = SkTMin(minY, curve[idx2].fY); 516 minY = SkTMin(minY, curve[idx2].fY);
506 maxX = SkTMax(maxX, curve[idx2].fX); 517 maxX = SkTMax(maxX, curve[idx2].fX);
507 maxY = SkTMax(maxY, curve[idx2].fY); 518 maxY = SkTMax(maxY, curve[idx2].fY);
508 } 519 }
509 double maxWidth = SkTMax(maxX - minX, maxY - minY); 520 double maxWidth = SkTMax(maxX - minX, maxY - minY);
510 delta /= maxWidth; 521 delta /= maxWidth;
511 if (delta > 1e-4 && (useIntersect ^= true)) { // FIXME: move this magic number 522 if (delta > 1e-3 && (useIntersect ^= true)) { // FIXME: move this magic number
512 sRayLonger = rayLonger; 523 sRayLonger = rayLonger;
513 sCept = cept; 524 sCept = cept;
514 sCeptT = smallTs[index]; 525 sCeptT = smallTs[index];
515 sIndex = index; 526 sIndex = index;
516 } 527 }
517 } 528 }
518 if (useIntersect) { 529 if (useIntersect) {
519 const SkDCubic& curve = sIndex ? rh.fCurvePart : fCurvePart; 530 const SkDCubic& curve = sIndex ? rh->fCurvePart : this->fCurvePart;
520 const SkOpSegment& segment = sIndex ? *rh.fSegment : *fSegment; 531 const SkOpSegment& segment = sIndex ? *rh->segment() : *this->segment();
521 double tStart = segment.t(sIndex ? rh.fStart : fStart); 532 double tStart = sIndex ? rh->fStart->t() : fStart->t();
522 SkDVector mid = segment.dPtAtT(tStart + (sCeptT - tStart) / 2) - curve[0 ]; 533 SkDVector mid = segment.dPtAtT(tStart + (sCeptT - tStart) / 2) - curve[0 ];
523 double septDir = mid.crossCheck(sCept); 534 double septDir = mid.crossCheck(sCept);
524 if (!septDir) { 535 if (!septDir) {
525 return checkParallel(rh); 536 return checkParallel(rh);
526 } 537 }
527 return sRayLonger ^ (sIndex == 0) ^ (septDir < 0); 538 return sRayLonger ^ (sIndex == 0) ^ (septDir < 0);
528 } else { 539 } else {
529 return checkParallel(rh); 540 return checkParallel(rh);
530 } 541 }
531 } 542 }
532 543
544 bool SkOpAngle::endToSide(const SkOpAngle* rh, bool* inside) const {
545 const SkOpSegment* segment = this->segment();
546 SkPath::Verb verb = segment->verb();
547 int pts = SkPathOpsVerbToPoints(verb);
548 SkDLine rayEnd;
549 rayEnd[0].set(this->fEnd->pt());
550 rayEnd[1] = rayEnd[0];
551 SkDVector slopeAtEnd = (*CurveDSlopeAtT[pts])(segment->pts(), this->fEnd->t( ));
552 rayEnd[1].fX += slopeAtEnd.fY;
553 rayEnd[1].fY -= slopeAtEnd.fX;
554 SkIntersections iEnd;
555 const SkOpSegment* oppSegment = rh->segment();
556 SkPath::Verb oppVerb = oppSegment->verb();
557 int oppPts = SkPathOpsVerbToPoints(oppVerb);
558 (*CurveIntersectRay[oppPts])(oppSegment->pts(), rayEnd, &iEnd);
559 double endDist;
560 int closestEnd = iEnd.closestTo(rh->fStart->t(), rh->fEnd->t(), rayEnd[0], & endDist);
561 if (closestEnd < 0) {
562 return false;
563 }
564 if (!endDist) {
565 return false;
566 }
567 SkDPoint start;
568 start.set(this->fStart->pt());
569 // OPTIMIZATION: multiple times in the code we find the max scalar
570 double minX, minY, maxX, maxY;
571 minX = minY = SK_ScalarInfinity;
572 maxX = maxY = -SK_ScalarInfinity;
573 const SkDCubic& curve = rh->fCurvePart;
574 for (int idx2 = 0; idx2 <= oppPts; ++idx2) {
575 minX = SkTMin(minX, curve[idx2].fX);
576 minY = SkTMin(minY, curve[idx2].fY);
577 maxX = SkTMax(maxX, curve[idx2].fX);
578 maxY = SkTMax(maxY, curve[idx2].fY);
579 }
580 double maxWidth = SkTMax(maxX - minX, maxY - minY);
581 endDist /= maxWidth;
582 if (endDist < 5e-11) { // empirically found
583 return false;
584 }
585 const SkDPoint* endPt = &rayEnd[0];
586 SkDPoint oppPt = iEnd.pt(closestEnd);
587 SkDVector vLeft = *endPt - start;
588 SkDVector vRight = oppPt - start;
589 double dir = vLeft.crossCheck(vRight);
590 if (!dir) {
591 return false;
592 }
593 *inside = dir < 0;
594 return true;
595 }
596
533 // Most of the time, the first one can be found trivially by detecting the small est sector value. 597 // Most of the time, the first one can be found trivially by detecting the small est sector value.
534 // If all angles have the same sector value, actual sorting is required. 598 // If all angles have the same sector value, actual sorting is required.
535 const SkOpAngle* SkOpAngle::findFirst() const { 599 SkOpAngle* SkOpAngle::findFirst() {
536 const SkOpAngle* best = this; 600 SkOpAngle* best = this;
537 int bestStart = SkTMin(fSectorStart, fSectorEnd); 601 int bestStart = SkTMin(fSectorStart, fSectorEnd);
538 const SkOpAngle* angle = this; 602 SkOpAngle* angle = this;
539 while ((angle = angle->fNext) != this) { 603 while ((angle = angle->fNext) != this) {
540 int angleEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd); 604 int angleEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
541 if (angleEnd < bestStart) { 605 if (angleEnd < bestStart) {
542 return angle; // we wrapped around 606 return angle; // we wrapped around
543 } 607 }
544 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd); 608 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
545 if (bestStart > angleStart) { 609 if (bestStart > angleStart) {
546 best = angle; 610 best = angle;
547 bestStart = angleStart; 611 bestStart = angleStart;
548 } 612 }
549 } 613 }
550 // back up to the first possible angle 614 // back up to the first possible angle
551 const SkOpAngle* firstBest = best; 615 SkOpAngle* firstBest = best;
552 angle = best; 616 angle = best;
553 int bestEnd = SkTMax(best->fSectorStart, best->fSectorEnd); 617 int bestEnd = SkTMax(best->fSectorStart, best->fSectorEnd);
554 while ((angle = angle->previous()) != firstBest) { 618 while ((angle = angle->previous()) != firstBest) {
555 if (angle->fStop) { 619 if (angle->fStop) {
556 break; 620 break;
557 } 621 }
558 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd); 622 int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
559 // angles that are smaller by one aren't necessary better, since the lar ger may be a line 623 // angles that are smaller by one aren't necessary better, since the lar ger may be a line
560 // and the smaller may be a curve that curls to the other side of the li ne. 624 // and the smaller may be a curve that curls to the other side of the li ne.
561 if (bestEnd + 1 < angleStart) { 625 if (bestEnd + 1 < angleStart) {
562 return best; 626 return best;
563 } 627 }
564 best = angle; 628 best = angle;
565 bestEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd); 629 bestEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
566 } 630 }
567 // in the case where all angles are nearly in the same sector, check the ord er to find the best 631 // in the case where all angles are nearly in the same sector, check the ord er to find the best
568 firstBest = best; 632 firstBest = best;
569 angle = best; 633 angle = best;
570 do { 634 do {
571 angle = angle->fNext; 635 angle = angle->fNext;
572 if (angle->fStop) { 636 if (angle->fStop) {
573 return firstBest; 637 return firstBest;
574 } 638 }
575 bool orderable = best->orderable(*angle); // note: may return an unorde rable angle 639 bool orderable = best->orderable(angle); // note: may return an unorder able angle
576 if (orderable == 0) { 640 if (orderable == 0) {
577 return angle; 641 return angle;
578 } 642 }
579 best = angle; 643 best = angle;
580 } while (angle != firstBest); 644 } while (angle != firstBest);
581 // if the angles are equally ordered, fall back on the initial tangent 645 // if the angles are equally ordered, fall back on the initial tangent
582 bool foundBelow = false; 646 bool foundBelow = false;
583 while ((angle = angle->fNext)) { 647 while ((angle = angle->fNext)) {
584 SkDVector scratch[2]; 648 SkDVector scratch[2];
585 const SkDVector* sweep; 649 const SkDVector* sweep;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 // x<0 x==0 x>0 x<0 x==0 x>0 x<0 x==0 x>0 696 // x<0 x==0 x>0 x<0 x==0 x>0 x<0 x==0 x>0
633 {{ 4, 3, 2}, { 7, -1, 15}, {10, 11, 12}}, // abs(x) < abs(y) 697 {{ 4, 3, 2}, { 7, -1, 15}, {10, 11, 12}}, // abs(x) < abs(y)
634 {{ 5, -1, 1}, {-1, -1, -1}, { 9, -1, 13}}, // abs(x) == abs(y) 698 {{ 5, -1, 1}, {-1, -1, -1}, { 9, -1, 13}}, // abs(x) == abs(y)
635 {{ 6, 3, 0}, { 7, -1, 15}, { 8, 11, 14}}, // abs(x) > abs(y) 699 {{ 6, 3, 0}, { 7, -1, 15}, { 8, 11, 14}}, // abs(x) > abs(y)
636 }; 700 };
637 int sector = sedecimant[(xy >= 0) + (xy > 0)][(y >= 0) + (y > 0)][(x >= 0) + (x > 0)] * 2 + 1; 701 int sector = sedecimant[(xy >= 0) + (xy > 0)][(y >= 0) + (y > 0)][(x >= 0) + (x > 0)] * 2 + 1;
638 // SkASSERT(SkPath::kLine_Verb == verb || sector >= 0); 702 // SkASSERT(SkPath::kLine_Verb == verb || sector >= 0);
639 return sector; 703 return sector;
640 } 704 }
641 705
706 SkOpGlobalState* SkOpAngle::globalState() const {
707 return this->segment()->globalState();
708 }
709
710
642 // OPTIMIZE: if this loops to only one other angle, after first compare fails, i nsert on other side 711 // OPTIMIZE: if this loops to only one other angle, after first compare fails, i nsert on other side
643 // OPTIMIZE: return where insertion succeeded. Then, start next insertion on opp osite side 712 // OPTIMIZE: return where insertion succeeded. Then, start next insertion on opp osite side
644 void SkOpAngle::insert(SkOpAngle* angle) { 713 void SkOpAngle::insert(SkOpAngle* angle) {
645 if (angle->fNext) { 714 if (angle->fNext) {
646 if (loopCount() >= angle->loopCount()) { 715 if (loopCount() >= angle->loopCount()) {
647 if (!merge(angle)) { 716 if (!merge(angle)) {
648 return; 717 return;
649 } 718 }
650 } else if (fNext) { 719 } else if (fNext) {
651 if (!angle->merge(this)) { 720 if (!angle->merge(this)) {
652 return; 721 return;
653 } 722 }
654 } else { 723 } else {
655 angle->insert(this); 724 angle->insert(this);
656 } 725 }
657 return; 726 return;
658 } 727 }
659 bool singleton = NULL == fNext; 728 bool singleton = NULL == fNext;
660 if (singleton) { 729 if (singleton) {
661 fNext = this; 730 fNext = this;
662 } 731 }
663 SkOpAngle* next = fNext; 732 SkOpAngle* next = fNext;
664 if (next->fNext == this) { 733 if (next->fNext == this) {
665 if (angle->overlap(*this)) { // angles are essentially coincident
666 return;
667 }
668 if (singleton || angle->after(this)) { 734 if (singleton || angle->after(this)) {
669 this->fNext = angle; 735 this->fNext = angle;
670 angle->fNext = next; 736 angle->fNext = next;
671 } else { 737 } else {
672 next->fNext = angle; 738 next->fNext = angle;
673 angle->fNext = this; 739 angle->fNext = this;
674 } 740 }
675 debugValidateNext(); 741 debugValidateNext();
676 return; 742 return;
677 } 743 }
678 SkOpAngle* last = this; 744 SkOpAngle* last = this;
679 do { 745 do {
680 SkASSERT(last->fNext == next); 746 SkASSERT(last->fNext == next);
681 if (angle->overlap(*last) || angle->overlap(*next)) {
682 return;
683 }
684 if (angle->after(last)) { 747 if (angle->after(last)) {
685 last->fNext = angle; 748 last->fNext = angle;
686 angle->fNext = next; 749 angle->fNext = next;
687 debugValidateNext(); 750 debugValidateNext();
688 return; 751 return;
689 } 752 }
690 last = next; 753 last = next;
691 next = next->fNext; 754 next = next->fNext;
692 if (last == this && next->fUnorderable) { 755 if (last == this) {
693 fUnorderable = true; 756 if (next->fUnorderable) {
757 fUnorderable = true;
758 } else {
759 globalState()->setAngleCoincidence();
760 this->fNext = angle;
761 angle->fNext = next;
762 angle->fCheckCoincidence = true;
763 }
694 return; 764 return;
695 } 765 }
696 SkASSERT(last != this);
697 } while (true); 766 } while (true);
698 } 767 }
699 768
700 bool SkOpAngle::isHorizontal() const { 769 SkOpSpanBase* SkOpAngle::lastMarked() const {
701 return !fIsCurve && fSweep[0].fY == 0;
702 }
703
704 SkOpSpan* SkOpAngle::lastMarked() const {
705 if (fLastMarked) { 770 if (fLastMarked) {
706 if (fLastMarked->fChased) { 771 if (fLastMarked->chased()) {
707 return NULL; 772 return NULL;
708 } 773 }
709 fLastMarked->fChased = true; 774 fLastMarked->setChased(true);
710 } 775 }
711 return fLastMarked; 776 return fLastMarked;
712 } 777 }
713 778
714 bool SkOpAngle::loopContains(const SkOpAngle& test) const { 779 bool SkOpAngle::loopContains(const SkOpAngle* angle) const {
715 if (!fNext) { 780 if (!fNext) {
716 return false; 781 return false;
717 } 782 }
718 const SkOpAngle* first = this; 783 const SkOpAngle* first = this;
719 const SkOpAngle* loop = this; 784 const SkOpAngle* loop = this;
720 const SkOpSegment* tSegment = test.fSegment; 785 const SkOpSegment* tSegment = angle->fStart->segment();
721 double tStart = tSegment->span(test.fStart).fT; 786 double tStart = angle->fStart->t();
722 double tEnd = tSegment->span(test.fEnd).fT; 787 double tEnd = angle->fEnd->t();
723 do { 788 do {
724 const SkOpSegment* lSegment = loop->fSegment; 789 const SkOpSegment* lSegment = loop->fStart->segment();
725 // FIXME : use precisely_equal ? or compare points exactly ?
726 if (lSegment != tSegment) { 790 if (lSegment != tSegment) {
727 continue; 791 continue;
728 } 792 }
729 double lStart = lSegment->span(loop->fStart).fT; 793 double lStart = loop->fStart->t();
730 if (lStart != tEnd) { 794 if (lStart != tEnd) {
731 continue; 795 continue;
732 } 796 }
733 double lEnd = lSegment->span(loop->fEnd).fT; 797 double lEnd = loop->fEnd->t();
734 if (lEnd == tStart) { 798 if (lEnd == tStart) {
735 return true; 799 return true;
736 } 800 }
737 } while ((loop = loop->fNext) != first); 801 } while ((loop = loop->fNext) != first);
738 return false; 802 return false;
739 } 803 }
740 804
741 int SkOpAngle::loopCount() const { 805 int SkOpAngle::loopCount() const {
742 int count = 0; 806 int count = 0;
743 const SkOpAngle* first = this; 807 const SkOpAngle* first = this;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 } 839 }
776 working = working->fNext; 840 working = working->fNext;
777 } while (working != angle); 841 } while (working != angle);
778 do { 842 do {
779 SkOpAngle* next = working->fNext; 843 SkOpAngle* next = working->fNext;
780 working->fNext = NULL; 844 working->fNext = NULL;
781 insert(working); 845 insert(working);
782 working = next; 846 working = next;
783 } while (working != angle); 847 } while (working != angle);
784 // it's likely that a pair of the angles are unorderable 848 // it's likely that a pair of the angles are unorderable
785 #if 0 && DEBUG_ANGLE
786 SkOpAngle* last = angle;
787 working = angle->fNext;
788 do {
789 SkASSERT(last->fNext == working);
790 last->fNext = working->fNext;
791 SkASSERT(working->after(last));
792 last->fNext = working;
793 last = working;
794 working = working->fNext;
795 } while (last != angle);
796 #endif
797 debugValidateNext(); 849 debugValidateNext();
798 return true; 850 return true;
799 } 851 }
800 852
801 double SkOpAngle::midT() const { 853 double SkOpAngle::midT() const {
802 return (fSegment->t(fStart) + fSegment->t(fEnd)) / 2; 854 return (fStart->t() + fEnd->t()) / 2;
803 } 855 }
804 856
805 bool SkOpAngle::oppositePlanes(const SkOpAngle& rh) const { 857 bool SkOpAngle::midToSide(const SkOpAngle* rh, bool* inside) const {
806 int startSpan = abs(rh.fSectorStart - fSectorStart); 858 const SkOpSegment* segment = this->segment();
859 SkPath::Verb verb = segment->verb();
860 int pts = SkPathOpsVerbToPoints(verb);
861 const SkPoint& startPt = this->fStart->pt();
862 const SkPoint& endPt = this->fEnd->pt();
863 SkDPoint dStartPt;
864 dStartPt.set(startPt);
865 SkDLine rayMid;
866 rayMid[0].fX = (startPt.fX + endPt.fX) / 2;
867 rayMid[0].fY = (startPt.fY + endPt.fY) / 2;
868 rayMid[1].fX = rayMid[0].fX + (endPt.fY - startPt.fY);
869 rayMid[1].fY = rayMid[0].fY - (endPt.fX - startPt.fX);
870 SkIntersections iMid;
871 (*CurveIntersectRay[pts])(segment->pts(), rayMid, &iMid);
872 int iOutside = iMid.mostOutside(this->fStart->t(), this->fEnd->t(), dStartPt );
873 if (iOutside < 0) {
874 return false;
875 }
876 const SkOpSegment* oppSegment = rh->segment();
877 SkPath::Verb oppVerb = oppSegment->verb();
878 int oppPts = SkPathOpsVerbToPoints(oppVerb);
879 SkIntersections oppMid;
880 (*CurveIntersectRay[oppPts])(oppSegment->pts(), rayMid, &oppMid);
881 int oppOutside = oppMid.mostOutside(rh->fStart->t(), rh->fEnd->t(), dStartPt );
882 if (oppOutside < 0) {
883 return false;
884 }
885 SkDVector iSide = iMid.pt(iOutside) - dStartPt;
886 SkDVector oppSide = oppMid.pt(oppOutside) - dStartPt;
887 double dir = iSide.crossCheck(oppSide);
888 if (!dir) {
889 return false;
890 }
891 *inside = dir < 0;
892 return true;
893 }
894
895 bool SkOpAngle::oppositePlanes(const SkOpAngle* rh) const {
896 int startSpan = abs(rh->fSectorStart - fSectorStart);
807 return startSpan >= 8; 897 return startSpan >= 8;
808 } 898 }
809 899
810 bool SkOpAngle::orderable(const SkOpAngle& rh) const { 900 bool SkOpAngle::orderable(SkOpAngle* rh) {
811 int result; 901 int result;
812 if (!fIsCurve) { 902 if (!fIsCurve) {
813 if (!rh.fIsCurve) { 903 if (!rh->fIsCurve) {
814 double leftX = fTangentHalf.dx(); 904 double leftX = fTangentHalf.dx();
815 double leftY = fTangentHalf.dy(); 905 double leftY = fTangentHalf.dy();
816 double rightX = rh.fTangentHalf.dx(); 906 double rightX = rh->fTangentHalf.dx();
817 double rightY = rh.fTangentHalf.dy(); 907 double rightY = rh->fTangentHalf.dy();
818 double x_ry = leftX * rightY; 908 double x_ry = leftX * rightY;
819 double rx_y = rightX * leftY; 909 double rx_y = rightX * leftY;
820 if (x_ry == rx_y) { 910 if (x_ry == rx_y) {
821 if (leftX * rightX < 0 || leftY * rightY < 0) { 911 if (leftX * rightX < 0 || leftY * rightY < 0) {
822 return true; // exactly 180 degrees apart 912 return true; // exactly 180 degrees apart
823 } 913 }
824 goto unorderable; 914 goto unorderable;
825 } 915 }
826 SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- wo rth finding earlier 916 SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- wo rth finding earlier
827 return x_ry < rx_y; 917 return x_ry < rx_y;
828 } 918 }
829 if ((result = allOnOneSide(rh)) >= 0) { 919 if ((result = allOnOneSide(rh)) >= 0) {
830 return result; 920 return result;
831 } 921 }
832 if (fUnorderable || approximately_zero(rh.fSide)) { 922 if (fUnorderable || approximately_zero(rh->fSide)) {
833 goto unorderable; 923 goto unorderable;
834 } 924 }
835 } else if (!rh.fIsCurve) { 925 } else if (!rh->fIsCurve) {
836 if ((result = rh.allOnOneSide(*this)) >= 0) { 926 if ((result = rh->allOnOneSide(this)) >= 0) {
837 return !result; 927 return !result;
838 } 928 }
839 if (rh.fUnorderable || approximately_zero(fSide)) { 929 if (rh->fUnorderable || approximately_zero(fSide)) {
840 goto unorderable; 930 goto unorderable;
841 } 931 }
842 } 932 }
843 if ((result = convexHullOverlaps(rh)) >= 0) { 933 if ((result = convexHullOverlaps(rh)) >= 0) {
844 return result; 934 return result;
845 } 935 }
846 return endsIntersect(rh); 936 return endsIntersect(rh);
847 unorderable: 937 unorderable:
848 fUnorderable = true; 938 fUnorderable = true;
849 rh.fUnorderable = true; 939 rh->fUnorderable = true;
850 return true; 940 return true;
851 } 941 }
852 942
853 bool SkOpAngle::overlap(const SkOpAngle& other) const {
854 int min = SkTMin(fStart, fEnd);
855 const SkOpSpan& span = fSegment->span(min);
856 const SkOpSegment* oSeg = other.fSegment;
857 int oMin = SkTMin(other.fStart, other.fEnd);
858 const SkOpSpan& oSpan = oSeg->span(oMin);
859 if (!span.fSmall && !oSpan.fSmall) {
860 return false;
861 }
862 if (fSegment->span(fStart).fPt != oSeg->span(other.fStart).fPt) {
863 return false;
864 }
865 // see if small span is contained by opposite span
866 return span.fSmall ? oSeg->containsPt(fSegment->span(fEnd).fPt, other.fEnd, other.fStart)
867 : fSegment->containsPt(oSeg->span(other.fEnd).fPt, fEnd, fStart);
868 }
869
870 // OPTIMIZE: if this shows up in a profile, add a previous pointer 943 // OPTIMIZE: if this shows up in a profile, add a previous pointer
871 // as is, this should be rarely called 944 // as is, this should be rarely called
872 SkOpAngle* SkOpAngle::previous() const { 945 SkOpAngle* SkOpAngle::previous() const {
873 SkOpAngle* last = fNext; 946 SkOpAngle* last = fNext;
874 do { 947 do {
875 SkOpAngle* next = last->fNext; 948 SkOpAngle* next = last->fNext;
876 if (next == this) { 949 if (next == this) {
877 return last; 950 return last;
878 } 951 }
879 last = next; 952 last = next;
880 } while (true); 953 } while (true);
881 } 954 }
882 955
883 void SkOpAngle::set(const SkOpSegment* segment, int start, int end) { 956 SkOpSegment* SkOpAngle::segment() const {
884 fSegment = segment; 957 return fStart->segment();
958 }
959
960 void SkOpAngle::set(SkOpSpanBase* start, SkOpSpanBase* end) {
885 fStart = start; 961 fStart = start;
886 fComputedEnd = fEnd = end; 962 fComputedEnd = fEnd = end;
963 SkASSERT(start != end);
887 fNext = NULL; 964 fNext = NULL;
888 fComputeSector = fComputedSector = false; 965 fComputeSector = fComputedSector = fCheckCoincidence = false;
889 fStop = false; 966 fStop = false;
890 setSpans(); 967 setSpans();
891 setSector(); 968 setSector();
969 PATH_OPS_DEBUG_CODE(fID = start->globalState()->nextAngleID());
892 } 970 }
893 971
894 void SkOpAngle::setCurveHullSweep() { 972 void SkOpAngle::setCurveHullSweep() {
895 fUnorderedSweep = false; 973 fUnorderedSweep = false;
896 fSweep[0] = fCurvePart[1] - fCurvePart[0]; 974 fSweep[0] = fCurvePart[1] - fCurvePart[0];
897 if (SkPath::kLine_Verb == fSegment->verb()) { 975 const SkOpSegment* segment = fStart->segment();
976 if (SkPath::kLine_Verb == segment->verb()) {
898 fSweep[1] = fSweep[0]; 977 fSweep[1] = fSweep[0];
899 return; 978 return;
900 } 979 }
901 fSweep[1] = fCurvePart[2] - fCurvePart[0]; 980 fSweep[1] = fCurvePart[2] - fCurvePart[0];
902 if (SkPath::kCubic_Verb != fSegment->verb()) { 981 if (SkPath::kCubic_Verb != segment->verb()) {
903 if (!fSweep[0].fX && !fSweep[0].fY) { 982 if (!fSweep[0].fX && !fSweep[0].fY) {
904 fSweep[0] = fSweep[1]; 983 fSweep[0] = fSweep[1];
905 } 984 }
906 return; 985 return;
907 } 986 }
908 SkDVector thirdSweep = fCurvePart[3] - fCurvePart[0]; 987 SkDVector thirdSweep = fCurvePart[3] - fCurvePart[0];
909 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { 988 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) {
910 fSweep[0] = fSweep[1]; 989 fSweep[0] = fSweep[1];
911 fSweep[1] = thirdSweep; 990 fSweep[1] = thirdSweep;
912 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { 991 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) {
(...skipping 13 matching lines...) Expand all
926 // probably such wide sweeps should be artificially subdivided earlier so th at never happens 1005 // probably such wide sweeps should be artificially subdivided earlier so th at never happens
927 SkASSERT(s1x3 * s2x1 < 0 || s1x3 * s3x2 < 0); 1006 SkASSERT(s1x3 * s2x1 < 0 || s1x3 * s3x2 < 0);
928 if (s3x2 * s2x1 < 0) { 1007 if (s3x2 * s2x1 < 0) {
929 SkASSERT(s2x1 * s1x3 > 0); 1008 SkASSERT(s2x1 * s1x3 > 0);
930 fSweep[0] = fSweep[1]; 1009 fSweep[0] = fSweep[1];
931 fUnorderedSweep = true; 1010 fUnorderedSweep = true;
932 } 1011 }
933 fSweep[1] = thirdSweep; 1012 fSweep[1] = thirdSweep;
934 } 1013 }
935 1014
936 void SkOpAngle::setSector() {
937 SkPath::Verb verb = fSegment->verb();
938 if (SkPath::kLine_Verb != verb && small()) {
939 goto deferTilLater;
940 }
941 fSectorStart = findSector(verb, fSweep[0].fX, fSweep[0].fY);
942 if (fSectorStart < 0) {
943 goto deferTilLater;
944 }
945 if (!fIsCurve) { // if it's a line or line-like, note that both sectors are the same
946 SkASSERT(fSectorStart >= 0);
947 fSectorEnd = fSectorStart;
948 fSectorMask = 1 << fSectorStart;
949 return;
950 }
951 SkASSERT(SkPath::kLine_Verb != verb);
952 fSectorEnd = findSector(verb, fSweep[1].fX, fSweep[1].fY);
953 if (fSectorEnd < 0) {
954 deferTilLater:
955 fSectorStart = fSectorEnd = -1;
956 fSectorMask = 0;
957 fComputeSector = true; // can't determine sector until segment length c an be found
958 return;
959 }
960 if (fSectorEnd == fSectorStart) {
961 SkASSERT((fSectorStart & 3) != 3); // if the sector has no span, it can 't be an exact angle
962 fSectorMask = 1 << fSectorStart;
963 return;
964 }
965 bool crossesZero = checkCrossesZero();
966 int start = SkTMin(fSectorStart, fSectorEnd);
967 bool curveBendsCCW = (fSectorStart == start) ^ crossesZero;
968 // bump the start and end of the sector span if they are on exact compass po ints
969 if ((fSectorStart & 3) == 3) {
970 fSectorStart = (fSectorStart + (curveBendsCCW ? 1 : 31)) & 0x1f;
971 }
972 if ((fSectorEnd & 3) == 3) {
973 fSectorEnd = (fSectorEnd + (curveBendsCCW ? 31 : 1)) & 0x1f;
974 }
975 crossesZero = checkCrossesZero();
976 start = SkTMin(fSectorStart, fSectorEnd);
977 int end = SkTMax(fSectorStart, fSectorEnd);
978 if (!crossesZero) {
979 fSectorMask = (unsigned) -1 >> (31 - end + start) << start;
980 } else {
981 fSectorMask = (unsigned) -1 >> (31 - start) | (-1 << end);
982 }
983 }
984
985 void SkOpAngle::setSpans() { 1015 void SkOpAngle::setSpans() {
986 fUnorderable = fSegment->isTiny(this); 1016 fUnorderable = false;
987 fLastMarked = NULL; 1017 fLastMarked = NULL;
988 const SkPoint* pts = fSegment->pts(); 1018 const SkOpSegment* segment = fStart->segment();
1019 const SkPoint* pts = segment->pts();
989 SkDEBUGCODE(fCurvePart[2].fX = fCurvePart[2].fY = fCurvePart[3].fX = fCurveP art[3].fY 1020 SkDEBUGCODE(fCurvePart[2].fX = fCurvePart[2].fY = fCurvePart[3].fX = fCurveP art[3].fY
990 = SK_ScalarNaN); 1021 = SK_ScalarNaN);
991 fSegment->subDivide(fStart, fEnd, &fCurvePart); 1022 segment->subDivide(fStart, fEnd, &fCurvePart);
992 setCurveHullSweep(); 1023 setCurveHullSweep();
993 const SkPath::Verb verb = fSegment->verb(); 1024 const SkPath::Verb verb = segment->verb();
994 if (verb != SkPath::kLine_Verb 1025 if (verb != SkPath::kLine_Verb
995 && !(fIsCurve = fSweep[0].crossCheck(fSweep[1]) != 0)) { 1026 && !(fIsCurve = fSweep[0].crossCheck(fSweep[1]) != 0)) {
996 SkDLine lineHalf; 1027 SkDLine lineHalf;
997 lineHalf[0].set(fCurvePart[0].asSkPoint()); 1028 lineHalf[0].set(fCurvePart[0].asSkPoint());
998 lineHalf[1].set(fCurvePart[SkPathOpsVerbToPoints(verb)].asSkPoint()); 1029 lineHalf[1].set(fCurvePart[SkPathOpsVerbToPoints(verb)].asSkPoint());
999 fTangentHalf.lineEndPoints(lineHalf); 1030 fTangentHalf.lineEndPoints(lineHalf);
1000 fSide = 0; 1031 fSide = 0;
1001 } 1032 }
1002 switch (verb) { 1033 switch (verb) {
1003 case SkPath::kLine_Verb: { 1034 case SkPath::kLine_Verb: {
1004 SkASSERT(fStart != fEnd); 1035 SkASSERT(fStart != fEnd);
1005 const SkPoint& cP1 = pts[fStart < fEnd]; 1036 const SkPoint& cP1 = pts[fStart->t() < fEnd->t()];
1006 SkDLine lineHalf; 1037 SkDLine lineHalf;
1007 lineHalf[0].set(fSegment->span(fStart).fPt); 1038 lineHalf[0].set(fStart->pt());
1008 lineHalf[1].set(cP1); 1039 lineHalf[1].set(cP1);
1009 fTangentHalf.lineEndPoints(lineHalf); 1040 fTangentHalf.lineEndPoints(lineHalf);
1010 fSide = 0; 1041 fSide = 0;
1011 fIsCurve = false; 1042 fIsCurve = false;
1012 } return; 1043 } return;
1013 case SkPath::kQuad_Verb: { 1044 case SkPath::kQuad_Verb: {
1014 SkLineParameters tangentPart; 1045 SkLineParameters tangentPart;
1015 SkDQuad& quad2 = *SkTCast<SkDQuad*>(&fCurvePart); 1046 SkDQuad& quad2 = *SkTCast<SkDQuad*>(&fCurvePart);
1016 (void) tangentPart.quadEndPoints(quad2); 1047 (void) tangentPart.quadEndPoints(quad2);
1017 fSide = -tangentPart.pointDistance(fCurvePart[2]); // not normalized -- compare sign only 1048 fSide = -tangentPart.pointDistance(fCurvePart[2]); // not normalized -- compare sign only
1018 } break; 1049 } break;
1019 case SkPath::kCubic_Verb: { 1050 case SkPath::kCubic_Verb: {
1020 SkLineParameters tangentPart; 1051 SkLineParameters tangentPart;
1021 (void) tangentPart.cubicPart(fCurvePart); 1052 (void) tangentPart.cubicPart(fCurvePart);
1022 fSide = -tangentPart.pointDistance(fCurvePart[3]); 1053 fSide = -tangentPart.pointDistance(fCurvePart[3]);
1023 double testTs[4]; 1054 double testTs[4];
1024 // OPTIMIZATION: keep inflections precomputed with cubic segment? 1055 // OPTIMIZATION: keep inflections precomputed with cubic segment?
1025 int testCount = SkDCubic::FindInflections(pts, testTs); 1056 int testCount = SkDCubic::FindInflections(pts, testTs);
1026 double startT = fSegment->t(fStart); 1057 double startT = fStart->t();
1027 double endT = fSegment->t(fEnd); 1058 double endT = fEnd->t();
1028 double limitT = endT; 1059 double limitT = endT;
1029 int index; 1060 int index;
1030 for (index = 0; index < testCount; ++index) { 1061 for (index = 0; index < testCount; ++index) {
1031 if (!::between(startT, testTs[index], limitT)) { 1062 if (!::between(startT, testTs[index], limitT)) {
1032 testTs[index] = -1; 1063 testTs[index] = -1;
1033 } 1064 }
1034 } 1065 }
1035 testTs[testCount++] = startT; 1066 testTs[testCount++] = startT;
1036 testTs[testCount++] = endT; 1067 testTs[testCount++] = endT;
1037 SkTQSort<double>(testTs, &testTs[testCount - 1]); 1068 SkTQSort<double>(testTs, &testTs[testCount - 1]);
(...skipping 19 matching lines...) Expand all
1057 bestSide = testSide; 1088 bestSide = testSide;
1058 } 1089 }
1059 } 1090 }
1060 fSide = -bestSide; // compare sign only 1091 fSide = -bestSide; // compare sign only
1061 } break; 1092 } break;
1062 default: 1093 default:
1063 SkASSERT(0); 1094 SkASSERT(0);
1064 } 1095 }
1065 } 1096 }
1066 1097
1067 bool SkOpAngle::small() const { 1098 void SkOpAngle::setSector() {
1068 int min = SkMin32(fStart, fEnd); 1099 const SkOpSegment* segment = fStart->segment();
1069 int max = SkMax32(fStart, fEnd); 1100 SkPath::Verb verb = segment->verb();
1070 for (int index = min; index < max; ++index) { 1101 fSectorStart = this->findSector(verb, fSweep[0].fX, fSweep[0].fY);
1071 const SkOpSpan& mSpan = fSegment->span(index); 1102 if (fSectorStart < 0) {
1072 if (!mSpan.fSmall) { 1103 goto deferTilLater;
1073 return false;
1074 }
1075 } 1104 }
1076 return true; 1105 if (!fIsCurve) { // if it's a line or line-like, note that both sectors are the same
1106 SkASSERT(fSectorStart >= 0);
1107 fSectorEnd = fSectorStart;
1108 fSectorMask = 1 << fSectorStart;
1109 return;
1110 }
1111 SkASSERT(SkPath::kLine_Verb != verb);
1112 fSectorEnd = this->findSector(verb, fSweep[1].fX, fSweep[1].fY);
1113 if (fSectorEnd < 0) {
1114 deferTilLater:
1115 fSectorStart = fSectorEnd = -1;
1116 fSectorMask = 0;
1117 fComputeSector = true; // can't determine sector until segment length c an be found
1118 return;
1119 }
1120 if (fSectorEnd == fSectorStart
1121 && (fSectorStart & 3) != 3) { // if the sector has no span, it can't be an exact angle
1122 fSectorMask = 1 << fSectorStart;
1123 return;
1124 }
1125 bool crossesZero = this->checkCrossesZero();
1126 int start = SkTMin(fSectorStart, fSectorEnd);
1127 bool curveBendsCCW = (fSectorStart == start) ^ crossesZero;
1128 // bump the start and end of the sector span if they are on exact compass po ints
1129 if ((fSectorStart & 3) == 3) {
1130 fSectorStart = (fSectorStart + (curveBendsCCW ? 1 : 31)) & 0x1f;
1131 }
1132 if ((fSectorEnd & 3) == 3) {
1133 fSectorEnd = (fSectorEnd + (curveBendsCCW ? 31 : 1)) & 0x1f;
1134 }
1135 crossesZero = this->checkCrossesZero();
1136 start = SkTMin(fSectorStart, fSectorEnd);
1137 int end = SkTMax(fSectorStart, fSectorEnd);
1138 if (!crossesZero) {
1139 fSectorMask = (unsigned) -1 >> (31 - end + start) << start;
1140 } else {
1141 fSectorMask = (unsigned) -1 >> (31 - start) | (-1 << end);
1142 }
1077 } 1143 }
1078 1144
1079 bool SkOpAngle::tangentsDiverge(const SkOpAngle& rh, double s0xt0) const { 1145 int SkOpAngle::sign() const {
1146 SkASSERT(fStart->t() != fEnd->t());
1147 return fStart->t() < fEnd->t() ? -1 : 1;
1148 }
1149
1150 SkOpSpan* SkOpAngle::starter() {
1151 return fStart->starter(fEnd);
1152 }
1153
1154 bool SkOpAngle::tangentsDiverge(const SkOpAngle* rh, double s0xt0) const {
1080 if (s0xt0 == 0) { 1155 if (s0xt0 == 0) {
1081 return false; 1156 return false;
1082 } 1157 }
1083 // if the ctrl tangents are not nearly parallel, use them 1158 // if the ctrl tangents are not nearly parallel, use them
1084 // solve for opposite direction displacement scale factor == m 1159 // solve for opposite direction displacement scale factor == m
1085 // initial dir = v1.cross(v2) == v2.x * v1.y - v2.y * v1.x 1160 // initial dir = v1.cross(v2) == v2.x * v1.y - v2.y * v1.x
1086 // displacement of q1[1] : dq1 = { -m * v1.y, m * v1.x } + q1[1] 1161 // displacement of q1[1] : dq1 = { -m * v1.y, m * v1.x } + q1[1]
1087 // straight angle when : v2.x * (dq1.y - q1[0].y) == v2.y * (dq1.x - q1[0].x ) 1162 // straight angle when : v2.x * (dq1.y - q1[0].y) == v2.y * (dq1.x - q1[0].x )
1088 // v2.x * (m * v1.x + v1.y) == v2.y * (-m * v1.y + v1. x) 1163 // v2.x * (m * v1.x + v1.y) == v2.y * (-m * v1.y + v1. x)
1089 // - m * (v2.x * v1.x + v2.y * v1.y) == v2.x * v1.y - v2.y * v1.x 1164 // - m * (v2.x * v1.x + v2.y * v1.y) == v2.x * v1.y - v2.y * v1.x
1090 // m = (v2.y * v1.x - v2.x * v1.y) / (v2.x * v1.x + v2.y * v1.y) 1165 // m = (v2.y * v1.x - v2.x * v1.y) / (v2.x * v1.x + v2.y * v1.y)
1091 // m = v1.cross(v2) / v1.dot(v2) 1166 // m = v1.cross(v2) / v1.dot(v2)
1092 const SkDVector* sweep = fSweep; 1167 const SkDVector* sweep = fSweep;
1093 const SkDVector* tweep = rh.fSweep; 1168 const SkDVector* tweep = rh->fSweep;
1094 double s0dt0 = sweep[0].dot(tweep[0]); 1169 double s0dt0 = sweep[0].dot(tweep[0]);
1095 if (!s0dt0) { 1170 if (!s0dt0) {
1096 return true; 1171 return true;
1097 } 1172 }
1098 SkASSERT(s0dt0 != 0); 1173 SkASSERT(s0dt0 != 0);
1099 double m = s0xt0 / s0dt0; 1174 double m = s0xt0 / s0dt0;
1100 double sDist = sweep[0].length() * m; 1175 double sDist = sweep[0].length() * m;
1101 double tDist = tweep[0].length() * m; 1176 double tDist = tweep[0].length() * m;
1102 bool useS = fabs(sDist) < fabs(tDist); 1177 bool useS = fabs(sDist) < fabs(tDist);
1103 double mFactor = fabs(useS ? distEndRatio(sDist) : rh.distEndRatio(tDist)); 1178 double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tD ist));
1104 return mFactor < 5000; // empirically found limit 1179 return mFactor < 5000; // empirically found limit
1105 } 1180 }
1106
1107 SkOpAngleSet::SkOpAngleSet()
1108 : fAngles(NULL)
1109 #if DEBUG_ANGLE
1110 , fCount(0)
1111 #endif
1112 {
1113 }
1114
1115 SkOpAngleSet::~SkOpAngleSet() {
1116 SkDELETE(fAngles);
1117 }
1118
1119 SkOpAngle& SkOpAngleSet::push_back() {
1120 if (!fAngles) {
1121 fAngles = SkNEW_ARGS(SkChunkAlloc, (2));
1122 }
1123 void* ptr = fAngles->allocThrow(sizeof(SkOpAngle));
1124 SkOpAngle* angle = (SkOpAngle*) ptr;
1125 #if DEBUG_ANGLE
1126 angle->setID(++fCount);
1127 #endif
1128 return *angle;
1129 }
1130
1131 void SkOpAngleSet::reset() {
1132 if (fAngles) {
1133 fAngles->reset();
1134 }
1135 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpAngle.h ('k') | src/pathops/SkOpBuilder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698