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

Side by Side Diff: src/pathops/SkPathOpsTSect.h

Issue 1407003016: Reland of path ops: fix conic weight and partial coincidence (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 1 month 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/SkPathOpsRect.h ('k') | src/pathops/SkPathOpsWinding.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 2014 Google Inc. 2 * Copyright 2014 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 7
8 #include "SkChunkAlloc.h" 8 #include "SkChunkAlloc.h"
9 #include "SkPathOpsBounds.h" 9 #include "SkPathOpsBounds.h"
10 #include "SkPathOpsRect.h" 10 #include "SkPathOpsRect.h"
11 #include "SkIntersections.h" 11 #include "SkIntersections.h"
12 #include "SkTSort.h" 12 #include "SkTSort.h"
13 13
14 #ifdef SK_DEBUG
15 typedef uint8_t SkOpDebugBool;
16 #else
17 typedef bool SkOpDebugBool;
18 #endif
19
14 /* TCurve and OppCurve are one of { SkDQuadratic, SkDConic, SkDCubic } */ 20 /* TCurve and OppCurve are one of { SkDQuadratic, SkDConic, SkDCubic } */
15 template<typename TCurve, typename OppCurve> 21 template<typename TCurve, typename OppCurve>
16 class SkTCoincident { 22 class SkTCoincident {
17 public: 23 public:
18 SkTCoincident() { 24 SkTCoincident() {
19 this->init(); 25 this->init();
20 } 26 }
21 27
28 void debugInit() {
29 #ifdef SK_DEBUG
30 this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN;
31 this->fPerpT = SK_ScalarNaN;
32 this->fCoincident = 0xFF;
33 #endif
34 }
35
36 char dumpIsCoincidentStr() const;
22 void dump() const; 37 void dump() const;
23 38
24 bool isCoincident() const { 39 bool isCoincident() const {
25 return fCoincident; 40 SkASSERT(!!fCoincident == fCoincident);
41 return SkToBool(fCoincident);
26 } 42 }
27 43
28 void init() { 44 void init() {
29 fPerpT = -1; 45 fPerpT = -1;
30 fCoincident = false; 46 fCoincident = false;
31 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN; 47 fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN;
32 } 48 }
33 49
34 void markCoincident() { 50 void markCoincident() {
35 if (!fCoincident) { 51 if (!fCoincident) {
36 fPerpT = -1; 52 fPerpT = -1;
37 } 53 }
38 fCoincident = true; 54 fCoincident = true;
39 } 55 }
40 56
41 const SkDPoint& perpPt() const { 57 const SkDPoint& perpPt() const {
42 return fPerpPt; 58 return fPerpPt;
43 } 59 }
44 60
45 double perpT() const { 61 double perpT() const {
46 return fPerpT; 62 return fPerpT;
47 } 63 }
48 64
49 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve & ); 65 void setPerp(const TCurve& c1, double t, const SkDPoint& cPt, const OppCurve & );
50 66
51 private: 67 private:
52 SkDPoint fPerpPt; 68 SkDPoint fPerpPt;
53 double fPerpT; // perpendicular intersection on opposite curve 69 double fPerpT; // perpendicular intersection on opposite curve
54 bool fCoincident; 70 SkOpDebugBool fCoincident;
55 }; 71 };
56 72
57 template<typename TCurve, typename OppCurve> class SkTSect; 73 template<typename TCurve, typename OppCurve> class SkTSect;
58 template<typename TCurve, typename OppCurve> class SkTSpan; 74 template<typename TCurve, typename OppCurve> class SkTSpan;
59 75
60 template<typename TCurve, typename OppCurve> 76 template<typename TCurve, typename OppCurve>
61 struct SkTSpanBounded { 77 struct SkTSpanBounded {
62 SkTSpan<TCurve, OppCurve>* fBounded; 78 SkTSpan<TCurve, OppCurve>* fBounded;
63 SkTSpanBounded* fNext; 79 SkTSpanBounded* fNext;
64 }; 80 };
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 TCurve fPart; 194 TCurve fPart;
179 SkTCoincident<TCurve, OppCurve> fCoinStart; 195 SkTCoincident<TCurve, OppCurve> fCoinStart;
180 SkTCoincident<TCurve, OppCurve> fCoinEnd; 196 SkTCoincident<TCurve, OppCurve> fCoinEnd;
181 SkTSpanBounded<OppCurve, TCurve>* fBounded; 197 SkTSpanBounded<OppCurve, TCurve>* fBounded;
182 SkTSpan* fPrev; 198 SkTSpan* fPrev;
183 SkTSpan* fNext; 199 SkTSpan* fNext;
184 SkDRect fBounds; 200 SkDRect fBounds;
185 double fStartT; 201 double fStartT;
186 double fEndT; 202 double fEndT;
187 double fBoundsMax; 203 double fBoundsMax;
188 bool fCollapsed; 204 SkOpDebugBool fCollapsed;
189 bool fHasPerp; 205 SkOpDebugBool fHasPerp;
190 bool fIsLinear; 206 SkOpDebugBool fIsLinear;
191 bool fIsLine; 207 SkOpDebugBool fIsLine;
192 bool fDeleted; 208 SkOpDebugBool fDeleted;
193 SkDEBUGCODE_(SkTSect<TCurve, OppCurve>* fDebugSect); 209 SkDEBUGCODE_(SkTSect<TCurve, OppCurve>* fDebugSect);
194 PATH_OPS_DEBUG_T_SECT_CODE(int fID); 210 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
195 friend class SkTSect<TCurve, OppCurve>; 211 friend class SkTSect<TCurve, OppCurve>;
196 friend class SkTSect<OppCurve, TCurve>; 212 friend class SkTSect<OppCurve, TCurve>;
197 friend class SkTSpan<OppCurve, TCurve>; 213 friend class SkTSpan<OppCurve, TCurve>;
198 }; 214 };
199 215
200 template<typename TCurve, typename OppCurve> 216 template<typename TCurve, typename OppCurve>
201 class SkTSect { 217 class SkTSect {
202 public: 218 public:
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 void dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* ) const; 278 void dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* ) const;
263 static int EndsEqual(const SkTSect* sect1, const SkTSect<OppCurve, TCurve>* sect2, 279 static int EndsEqual(const SkTSect* sect1, const SkTSect<OppCurve, TCurve>* sect2,
264 SkIntersections* ); 280 SkIntersections* );
265 SkTSpan<TCurve, OppCurve>* extractCoincident(SkTSect<OppCurve, TCurve>* sect 2, 281 SkTSpan<TCurve, OppCurve>* extractCoincident(SkTSect<OppCurve, TCurve>* sect 2,
266 SkTSpan<TCurve, OppCurve>* fir st, 282 SkTSpan<TCurve, OppCurve>* fir st,
267 SkTSpan<TCurve, OppCurve>* las t); 283 SkTSpan<TCurve, OppCurve>* las t);
268 SkTSpan<TCurve, OppCurve>* findCoincidentRun(SkTSpan<TCurve, OppCurve>* firs t, 284 SkTSpan<TCurve, OppCurve>* findCoincidentRun(SkTSpan<TCurve, OppCurve>* firs t,
269 SkTSpan<TCurve, OppCurve>** la stPtr); 285 SkTSpan<TCurve, OppCurve>** la stPtr);
270 int intersects(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* o pp, 286 int intersects(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* o pp,
271 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult); 287 SkTSpan<OppCurve, TCurve>* oppSpan, int* oppResult);
288 bool isParallel(const SkDLine& thisLine, const SkTSect<OppCurve, TCurve>* op p) const;
272 int linesIntersect(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve >* opp, 289 int linesIntersect(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve >* opp,
273 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* ); 290 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* );
274 void markSpanGone(SkTSpan<TCurve, OppCurve>* span); 291 void markSpanGone(SkTSpan<TCurve, OppCurve>* span);
275 bool matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2, doub le t2) const; 292 bool matchedDirection(double t, const SkTSect<OppCurve, TCurve>* sect2, doub le t2) const;
276 void matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2, doubl e t2, 293 void matchedDirCheck(double t, const SkTSect<OppCurve, TCurve>* sect2, doubl e t2,
277 bool* calcMatched, bool* oppMatched) const; 294 bool* calcMatched, bool* oppMatched) const;
278 void mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2); 295 void mergeCoincidence(SkTSect<OppCurve, TCurve>* sect2);
279 SkTSpan<TCurve, OppCurve>* prev(SkTSpan<TCurve, OppCurve>* ) const; 296 SkTSpan<TCurve, OppCurve>* prev(SkTSpan<TCurve, OppCurve>* ) const;
280 void removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp); 297 void removeByPerpendicular(SkTSect<OppCurve, TCurve>* opp);
281 void recoverCollapsed(); 298 void recoverCollapsed();
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 { 838 {
822 fHead = addOne(); 839 fHead = addOne();
823 fHead->init(c); 840 fHead->init(c);
824 } 841 }
825 842
826 template<typename TCurve, typename OppCurve> 843 template<typename TCurve, typename OppCurve>
827 SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() { 844 SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
828 SkTSpan<TCurve, OppCurve>* result; 845 SkTSpan<TCurve, OppCurve>* result;
829 if (fDeleted) { 846 if (fDeleted) {
830 result = fDeleted; 847 result = fDeleted;
831 result->reset();
832 fDeleted = result->fNext; 848 fDeleted = result->fNext;
833 } else { 849 } else {
834 result = new (fHeap.allocThrow(sizeof(SkTSpan<TCurve, OppCurve>)))( 850 result = new (fHeap.allocThrow(sizeof(SkTSpan<TCurve, OppCurve>)))(
835 SkTSpan<TCurve, OppCurve>); 851 SkTSpan<TCurve, OppCurve>);
836 result->fBounded = nullptr;
837 #if DEBUG_T_SECT 852 #if DEBUG_T_SECT
838 ++fDebugAllocatedCount; 853 ++fDebugAllocatedCount;
839 #endif 854 #endif
840 } 855 }
856 result->reset();
841 result->fHasPerp = false; 857 result->fHasPerp = false;
842 result->fDeleted = false; 858 result->fDeleted = false;
843 ++fActiveCount; 859 ++fActiveCount;
844 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID); 860 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
845 SkDEBUGCODE(result->fDebugSect = this); 861 SkDEBUGCODE(result->fDebugSect = this);
862 #ifdef SK_DEBUG
863 result->fPart.debugInit();
864 result->fCoinStart.debugInit();
865 result->fCoinEnd.debugInit();
866 result->fPrev = result->fNext = nullptr;
867 result->fBounds.debugInit();
868 result->fStartT = result->fEndT = result->fBoundsMax = SK_ScalarNaN;
869 result->fCollapsed = result->fIsLinear = result->fIsLine = 0xFF;
870 #endif
846 return result; 871 return result;
847 } 872 }
848 873
849 template<typename TCurve, typename OppCurve> 874 template<typename TCurve, typename OppCurve>
850 bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect 2, double tStart, 875 bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect 2, double tStart,
851 double tStep, double* resultT, double* oppT) { 876 double tStep, double* resultT, double* oppT) {
852 SkTSpan<TCurve, OppCurve> work; 877 SkTSpan<TCurve, OppCurve> work;
853 double result = work.fStartT = work.fEndT = tStart; 878 double result = work.fStartT = work.fEndT = tStart;
854 SkDEBUGCODE(work.fDebugSect = this); 879 SkDEBUGCODE(work.fDebugSect = this);
855 SkDPoint last = fCurve.ptAtT(tStart); 880 SkDPoint last = fCurve.ptAtT(tStart);
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 span->fStartT = span->fEndT = i[0][0]; 1295 span->fStartT = span->fEndT = i[0][0];
1271 oppSpan->fStartT = oppSpan->fEndT = i[1][0]; 1296 oppSpan->fStartT = oppSpan->fEndT = i[1][0];
1272 return *oppResult = 2; 1297 return *oppResult = 2;
1273 } 1298 }
1274 if (span->fIsLinear || oppSpan->fIsLinear) { 1299 if (span->fIsLinear || oppSpan->fIsLinear) {
1275 return *oppResult = (int) span->linearsIntersect(oppSpan); 1300 return *oppResult = (int) span->linearsIntersect(oppSpan);
1276 } 1301 }
1277 return *oppResult = 1; 1302 return *oppResult = 1;
1278 } 1303 }
1279 1304
1305 template<typename TCurve>
1306 static bool is_parallel(const SkDLine& thisLine, const TCurve& opp) {
1307 if (!opp.IsConic()) {
1308 return false; // FIXME : breaks a lot of stuff now
1309 }
1310 int finds = 0;
1311 SkDLine thisPerp;
1312 thisPerp.fPts[0].fX = thisLine.fPts[1].fX + (thisLine.fPts[1].fY - thisLine. fPts[0].fY);
1313 thisPerp.fPts[0].fY = thisLine.fPts[1].fY + (thisLine.fPts[0].fX - thisLine. fPts[1].fX);
1314 thisPerp.fPts[1] = thisLine.fPts[1];
1315 SkIntersections perpRayI;
1316 perpRayI.intersectRay(opp, thisPerp);
1317 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1318 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[1]);
1319 }
1320 thisPerp.fPts[1].fX = thisLine.fPts[0].fX + (thisLine.fPts[1].fY - thisLine. fPts[0].fY);
1321 thisPerp.fPts[1].fY = thisLine.fPts[0].fY + (thisLine.fPts[0].fX - thisLine. fPts[1].fX);
1322 thisPerp.fPts[0] = thisLine.fPts[0];
1323 perpRayI.intersectRay(opp, thisPerp);
1324 for (int pIndex = 0; pIndex < perpRayI.used(); ++pIndex) {
1325 finds += perpRayI.pt(pIndex).approximatelyEqual(thisPerp.fPts[0]);
1326 }
1327 return finds >= 2;
1328 }
1329
1280 // while the intersection points are sufficiently far apart: 1330 // while the intersection points are sufficiently far apart:
1281 // construct the tangent lines from the intersections 1331 // construct the tangent lines from the intersections
1282 // find the point where the tangent line intersects the opposite curve 1332 // find the point where the tangent line intersects the opposite curve
1283 template<typename TCurve, typename OppCurve> 1333 template<typename TCurve, typename OppCurve>
1284 int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span, 1334 int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
1285 SkTSect<OppCurve, TCurve>* opp, 1335 SkTSect<OppCurve, TCurve>* opp,
1286 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) { 1336 SkTSpan<OppCurve, TCurve>* oppSpan, SkIntersections* i) {
1287 SkIntersections thisRayI, oppRayI; 1337 SkIntersections thisRayI, oppRayI;
1288 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }}; 1338 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
1289 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }}; 1339 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[OppCurve::kPointLast] }};
1290 int loopCount = 0; 1340 int loopCount = 0;
1291 double bestDistSq = DBL_MAX; 1341 double bestDistSq = DBL_MAX;
1292 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) { 1342 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1293 return 0; 1343 return 0;
1294 } 1344 }
1295 if (!oppRayI.intersectRay(this->fCurve, oppLine)) { 1345 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1296 return 0; 1346 return 0;
1297 } 1347 }
1298 // if the ends of each line intersect the opposite curve, the lines are coin cident 1348 // if the ends of each line intersect the opposite curve, the lines are coin cident
1299 if (thisRayI.used() > 1) { 1349 if (thisRayI.used() > 1) {
1300 int ptMatches = 0; 1350 int ptMatches = 0;
1301 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) { 1351 for (int tIndex = 0; tIndex < thisRayI.used(); ++tIndex) {
1302 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); + +lIndex) { 1352 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); + +lIndex) {
1303 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPt s[lIndex]); 1353 ptMatches += thisRayI.pt(tIndex).approximatelyEqual(thisLine.fPt s[lIndex]);
1304 } 1354 }
1305 } 1355 }
1306 if (ptMatches == 2) { 1356 if (ptMatches == 2 || is_parallel(thisLine, opp->fCurve)) {
1307 return 2; 1357 return 2;
1308 } 1358 }
1309 } 1359 }
1310 if (oppRayI.used() > 1) { 1360 if (oppRayI.used() > 1) {
1311 int ptMatches = 0; 1361 int ptMatches = 0;
1312 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) { 1362 for (int oIndex = 0; oIndex < oppRayI.used(); ++oIndex) {
1313 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); + +lIndex) { 1363 for (int lIndex = 0; lIndex < (int) SK_ARRAY_COUNT(thisLine.fPts); + +lIndex) {
1314 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[ lIndex]); 1364 ptMatches += oppRayI.pt(oIndex).approximatelyEqual(oppLine.fPts[ lIndex]);
1315 } 1365 }
1316 } 1366 }
1317 if (ptMatches == 2) { 1367 if (ptMatches == 2|| is_parallel(oppLine, this->fCurve)) {
1318 return 2; 1368 return 2;
1319 } 1369 }
1320 } 1370 }
1321 do { 1371 do {
1322 // pick the closest pair of points 1372 // pick the closest pair of points
1323 double closest = DBL_MAX; 1373 double closest = DBL_MAX;
1324 int closeIndex SK_INIT_TO_AVOID_WARNING; 1374 int closeIndex SK_INIT_TO_AVOID_WARNING;
1325 int oppCloseIndex SK_INIT_TO_AVOID_WARNING; 1375 int oppCloseIndex SK_INIT_TO_AVOID_WARNING;
1326 for (int index = 0; index < oppRayI.used(); ++index) { 1376 for (int index = 0; index < oppRayI.used(); ++index) {
1327 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) { 1377 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) {
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after
2174 } else if (intersections->isCoincident(index + 1)) { 2224 } else if (intersections->isCoincident(index + 1)) {
2175 intersections->removeOne(index + 1); 2225 intersections->removeOne(index + 1);
2176 --last; 2226 --last;
2177 } else { 2227 } else {
2178 intersections->setCoincident(index++); 2228 intersections->setCoincident(index++);
2179 } 2229 }
2180 intersections->setCoincident(index); 2230 intersections->setCoincident(index);
2181 } 2231 }
2182 SkASSERT(intersections->used() <= TCurve::kMaxIntersections); 2232 SkASSERT(intersections->used() <= TCurve::kMaxIntersections);
2183 } 2233 }
OLDNEW
« no previous file with comments | « src/pathops/SkPathOpsRect.h ('k') | src/pathops/SkPathOpsWinding.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698