blob: 5c3563ed0fef325b4ff7b6e4a3ffba72f42db5f4 [file] [log] [blame]
commit-bot@chromium.org4431e772014-04-14 17:08:59 +00001#include "SkOpContour.h"
2#include "SkIntersectionHelper.h"
3#include "SkOpSegment.h"
4
5inline void DebugDumpDouble(double x) {
6 if (x == floor(x)) {
7 SkDebugf("%.0f", x);
8 } else {
9 SkDebugf("%1.19g", x);
10 }
11}
12
13inline void DebugDumpFloat(float x) {
14 if (x == floorf(x)) {
15 SkDebugf("%.0f", x);
16 } else {
17 SkDebugf("%1.9gf", x);
18 }
19}
20
21// if not defined by PathOpsDebug.cpp ...
22#if !defined SK_DEBUG && FORCE_RELEASE
23bool SkPathOpsDebug::ValidWind(int wind) {
24 return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
25}
26
27void SkPathOpsDebug::WindingPrintf(int wind) {
28 if (wind == SK_MinS32) {
29 SkDebugf("?");
30 } else {
31 SkDebugf("%d", wind);
32 }
33}
34#endif
35
36void SkOpAngle::dump() const {
37#if DEBUG_SORT
38 debugOne(false);
39#endif
40 SkDebugf("\n");
41}
42
43void SkOpAngle::dumpFromTo(const SkOpSegment* segment, int from, int to) const {
44#if DEBUG_SORT && DEBUG_ANGLE
45 const SkOpAngle* first = this;
46 const SkOpAngle* next = this;
47 const char* indent = "";
48 do {
49 SkDebugf("%s", indent);
50 next->debugOne(false);
51 if (segment == next->fSegment) {
52 if (fNext && from == fNext->debugID()) {
53 SkDebugf(" << from");
54 }
55 if (fNext && to == fNext->debugID()) {
56 SkDebugf(" << to");
57 }
58 }
59 SkDebugf("\n");
60 indent = " ";
61 next = next->fNext;
62 } while (next && next != first);
63#endif
64}
65
66void SkOpAngle::dumpLoop() const {
67 const SkOpAngle* first = this;
68 const SkOpAngle* next = this;
69 do {
70 next->dump();
71 next = next->fNext;
72 } while (next && next != first);
73}
74
75void SkOpAngle::dumpPartials() const {
76 const SkOpAngle* first = this;
77 const SkOpAngle* next = this;
78 do {
79 next->fCurvePart.dumpNumber();
80 next = next->fNext;
81 } while (next && next != first);
82}
83
84void SkOpContour::dump() const {
85 int segmentCount = fSegments.count();
86 SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
87 for (int test = 0; test < segmentCount; ++test) {
88 SkDebugf(" [%d] ((SkOpSegment*) 0x%p) [%d]\n", test, &fSegments[test],
89 fSegments[test].debugID());
90 }
91}
92
93void SkOpContour::dumpAngles() const {
94 int segmentCount = fSegments.count();
95 SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
96 for (int test = 0; test < segmentCount; ++test) {
97 SkDebugf(" [%d] ", test);
98 fSegments[test].dumpAngles();
99 }
100}
101
102void SkOpContour::dumpPts() const {
103 int segmentCount = fSegments.count();
104 SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
105 for (int test = 0; test < segmentCount; ++test) {
106 SkDebugf(" [%d] ", test);
107 fSegments[test].dumpPts();
108 }
109}
110
111void SkOpContour::dumpSpans() const {
112 int segmentCount = fSegments.count();
113 SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
114 for (int test = 0; test < segmentCount; ++test) {
115 SkDebugf(" [%d] ", test);
116 fSegments[test].dumpSpans();
117 }
118}
119
120void SkDCubic::dump() const {
121 SkDebugf("{{");
122 int index = 0;
123 do {
124 fPts[index].dump();
125 SkDebugf(", ");
126 } while (++index < 3);
127 fPts[index].dump();
128 SkDebugf("}}\n");
129}
130
131void SkDCubic::dumpNumber() const {
132 SkDebugf("{{");
133 int index = 0;
134 bool dumpedOne = false;
135 do {
136 if (!(fPts[index].fX == fPts[index].fX && fPts[index].fY == fPts[index].fY)) {
137 continue;
138 }
139 if (dumpedOne) {
140 SkDebugf(", ");
141 }
142 fPts[index].dump();
143 dumpedOne = true;
144 } while (++index < 3);
145 if (fPts[index].fX == fPts[index].fX && fPts[index].fY == fPts[index].fY) {
146 if (dumpedOne) {
147 SkDebugf(", ");
148 }
149 fPts[index].dump();
150 }
151 SkDebugf("}}\n");
152}
153
154void SkDLine::dump() const {
155 SkDebugf("{{");
156 fPts[0].dump();
157 SkDebugf(", ");
158 fPts[1].dump();
159 SkDebugf("}}\n");
160}
161
162void SkDPoint::dump() const {
163 SkDebugf("{");
164 DebugDumpDouble(fX);
165 SkDebugf(", ");
166 DebugDumpDouble(fY);
167 SkDebugf("}");
168}
169
170void SkDPoint::Dump(const SkPoint& pt) {
171 SkDebugf("{");
172 DebugDumpFloat(pt.fX);
173 SkDebugf(", ");
174 DebugDumpFloat(pt.fY);
175 SkDebugf("}");
176}
177
178
179void SkDQuad::dumpComma(const char* comma) const {
180 SkDebugf("{{");
181 int index = 0;
182 do {
183 fPts[index].dump();
184 SkDebugf(", ");
185 } while (++index < 2);
186 fPts[index].dump();
187 SkDebugf("}}%s\n", comma ? comma : "");
188}
189
190void SkDQuad::dump() const {
191 dumpComma("");
192}
193
194void SkIntersectionHelper::dump() const {
195 SkDPoint::Dump(pts()[0]);
196 SkDPoint::Dump(pts()[1]);
197 if (verb() >= SkPath::kQuad_Verb) {
198 SkDPoint::Dump(pts()[2]);
199 }
200 if (verb() >= SkPath::kCubic_Verb) {
201 SkDPoint::Dump(pts()[3]);
202 }
203}
204
205void SkOpSegment::dumpAngles() const {
206 SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID());
207 int fromIndex = -1, toIndex = -1;
208 for (int index = 0; index < count(); ++index) {
209 int fIndex = fTs[index].fFromAngleIndex;
210 int tIndex = fTs[index].fToAngleIndex;
211 if (fromIndex == fIndex && tIndex == toIndex) {
212 continue;
213 }
214 if (fIndex >= 0) {
215 SkDebugf(" [%d] from=%d ", index, fIndex);
216 const SkOpAngle& angle = this->angle(fIndex);
217 angle.dumpFromTo(this, fIndex, tIndex);
218 }
219 if (tIndex >= 0) {
220 SkDebugf(" [%d] to=%d ", index, tIndex);
221 const SkOpAngle& angle = this->angle(tIndex);
222 angle.dumpFromTo(this, fIndex, tIndex);
223 }
224 fromIndex = fIndex;
225 toIndex = tIndex;
226 }
227}
228
229void SkOpSegment::dumpContour(int firstID, int lastID) const {
230 if (debugID() < 0) {
231 return;
232 }
233 const SkOpSegment* test = this - (debugID() - 1);
234 test += (firstID - 1);
235 const SkOpSegment* last = test + (lastID - firstID);
236 while (test <= last) {
237 test->dumpSpans();
238 ++test;
239 }
240}
241
242void SkOpSegment::dumpPts() const {
243 int last = SkPathOpsVerbToPoints(fVerb);
244 SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
245 int index = 0;
246 do {
247 SkDPoint::Dump(fPts[index]);
248 SkDebugf(", ");
249 } while (++index < last);
250 SkDPoint::Dump(fPts[index]);
251 SkDebugf("}}\n");
252}
253
254void SkOpSegment::dumpDPts() const {
255 int count = SkPathOpsVerbToPoints(fVerb);
256 SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
257 int index = 0;
258 do {
259 SkDPoint dPt = {fPts[index].fX, fPts[index].fY};
260 dPt.dump();
261 if (index != count) {
262 SkDebugf(", ");
263 }
264 } while (++index <= count);
265 SkDebugf("}}\n");
266}
267
268void SkOpSegment::dumpSpans() const {
269 int count = this->count();
270 SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID());
271 for (int index = 0; index < count; ++index) {
272 const SkOpSpan& span = this->span(index);
273 SkDebugf(" [%d] ", index);
274 span.dumpOne();
275 }
276}
277
278void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle, true>& angles) {
279 int count = angles.count();
280 for (int index = 0; index < count; ++index) {
281 angles[index].dump();
282 }
283}
284
285void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle* , true>& angles) {
286 int count = angles.count();
287 for (int index = 0; index < count; ++index) {
288 angles[index]->dump();
289 }
290}
291
292void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour, true>& contours) {
293 int count = contours.count();
294 for (int index = 0; index < count; ++index) {
295 contours[index].dump();
296 }
297}
298
299void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour* , true>& contours) {
300 int count = contours.count();
301 for (int index = 0; index < count; ++index) {
302 contours[index]->dump();
303 }
304}
305
306void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour, true>& contours) {
307 int count = contours.count();
308 for (int index = 0; index < count; ++index) {
309 contours[index].dumpAngles();
310 }
311}
312
313void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour* , true>& contours) {
314 int count = contours.count();
315 for (int index = 0; index < count; ++index) {
316 contours[index]->dumpAngles();
317 }
318}
319
320void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour, true>& contours) {
321 int count = contours.count();
322 for (int index = 0; index < count; ++index) {
323 contours[index].dumpPts();
324 }
325}
326
327void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour* , true>& contours) {
328 int count = contours.count();
329 for (int index = 0; index < count; ++index) {
330 contours[index]->dumpPts();
331 }
332}
333
334void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour, true>& contours) {
335 int count = contours.count();
336 for (int index = 0; index < count; ++index) {
337 contours[index].dumpSpans();
338 }
339}
340
341void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour* , true>& contours) {
342 int count = contours.count();
343 for (int index = 0; index < count; ++index) {
344 contours[index]->dumpSpans();
345 }
346}
347
348void SkPathOpsDebug::DumpSpans(const SkTDArray<SkOpSpan *>& spans) {
349 int count = spans.count();
350 for (int index = 0; index < count; ++index) {
351 const SkOpSpan* span = spans[index];
352 const SkOpSpan& oSpan = span->fOther->span(span->fOtherIndex);
353 const SkOpSegment* segment = oSpan.fOther;
354 SkDebugf("((SkOpSegment*) 0x%p) [%d] ", segment, segment->debugID());
355 SkDebugf("spanIndex:%d ", oSpan.fOtherIndex);
356 span->dumpOne();
357 }
358}
359
360// this does not require that other T index is initialized or correct
361const SkOpSegment* SkOpSpan::debugToSegment(ptrdiff_t* spanIndex) const {
362 if (!fOther) {
363 return NULL;
364 }
365 int oppCount = fOther->count();
366 for (int index = 0; index < oppCount; ++index) {
367 const SkOpSpan& otherSpan = fOther->span(index);
368 double otherTestT = otherSpan.fT;
369 if (otherTestT < fOtherT) {
370 continue;
371 }
372 SkASSERT(otherTestT == fOtherT);
373 const SkOpSegment* candidate = otherSpan.fOther;
374 const SkOpSpan* first = candidate->spans().begin();
375 const SkOpSpan* last = candidate->spans().end() - 1;
376 if (first <= this && this <= last) {
377 if (spanIndex) {
378 *spanIndex = this - first;
379 }
380 return candidate;
381 }
382 }
383 SkASSERT(0);
384 return NULL;
385}
386
387void SkOpSpan::dumpOne() const {
388 SkDebugf("t=");
389 DebugDumpDouble(fT);
390 SkDebugf(" pt=");
391 SkDPoint::Dump(fPt);
392 if (fOther) {
393 SkDebugf(" other.fID=%d", fOther->debugID());
394 SkDebugf(" [%d] otherT=", fOtherIndex);
395 DebugDumpDouble(fOtherT);
396 } else {
397 SkDebugf(" other.fID=? [?] otherT=?");
398 }
399#if DEBUG_WINDING
400 SkDebugf(" windSum=");
401 SkPathOpsDebug::WindingPrintf(fWindSum);
402#endif
403 if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) {
404#if DEBUG_WINDING
405 SkDebugf(" oppSum=");
406 SkPathOpsDebug::WindingPrintf(fOppSum);
407#endif
408 }
409 SkDebugf(" windValue=%d", fWindValue);
410 if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) {
411 SkDebugf(" oppValue=%d", fOppValue);
412 }
413 SkDebugf(" from=%d", fFromAngleIndex);
414 SkDebugf(" to=%d", fToAngleIndex);
415 if (fDone) {
416 SkDebugf(" done");
417 }
418 if (fUnsortableStart) {
419 SkDebugf(" unsortable-start");
420 }
421 if (fUnsortableEnd) {
422 SkDebugf(" unsortable-end");
423 }
424 if (fTiny) {
425 SkDebugf(" tiny");
426 }
427 if (fSmall) {
428 SkDebugf(" small");
429 }
430 if (fLoop) {
431 SkDebugf(" loop");
432 }
433 SkDebugf("\n");
434}
435
436void SkOpSpan::dump() const {
437 ptrdiff_t spanIndex;
438 const SkOpSegment* segment = debugToSegment(&spanIndex);
439 if (segment) {
440 SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", segment, segment->debugID());
441 SkDebugf(" [%d] ", spanIndex);
442 } else {
443 SkDebugf("((SkOpSegment*) ?) [?]\n");
444 SkDebugf(" [?] ");
445 }
446 dumpOne();
447}
448
449void Dump(const SkTArray<class SkOpAngle, true>& angles) {
450 SkPathOpsDebug::DumpAngles(angles);
451}
452
453void Dump(const SkTArray<class SkOpAngle* , true>& angles) {
454 SkPathOpsDebug::DumpAngles(angles);
455}
456
457void Dump(const SkTArray<class SkOpAngle, true>* angles) {
458 SkPathOpsDebug::DumpAngles(*angles);
459}
460
461void Dump(const SkTArray<class SkOpAngle* , true>* angles) {
462 SkPathOpsDebug::DumpAngles(*angles);
463}
464
465void Dump(const SkTArray<class SkOpContour, true>& contours) {
466 SkPathOpsDebug::DumpContours(contours);
467}
468
469void Dump(const SkTArray<class SkOpContour* , true>& contours) {
470 SkPathOpsDebug::DumpContours(contours);
471}
472
473void Dump(const SkTArray<class SkOpContour, true>* contours) {
474 SkPathOpsDebug::DumpContours(*contours);
475}
476
477void Dump(const SkTArray<class SkOpContour* , true>* contours) {
478 SkPathOpsDebug::DumpContours(*contours);
479}
480
481void Dump(const SkTDArray<SkOpSpan *>& chaseArray) {
482 SkPathOpsDebug::DumpSpans(chaseArray);
483}
484
485void Dump(const SkTDArray<SkOpSpan *>* chaseArray) {
486 SkPathOpsDebug::DumpSpans(*chaseArray);
487}
488
489void DumpAngles(const SkTArray<class SkOpContour, true>& contours) {
490 SkPathOpsDebug::DumpContourAngles(contours);
491}
492
493void DumpAngles(const SkTArray<class SkOpContour* , true>& contours) {
494 SkPathOpsDebug::DumpContourAngles(contours);
495}
496
497void DumpAngles(const SkTArray<class SkOpContour, true>* contours) {
498 SkPathOpsDebug::DumpContourAngles(*contours);
499}
500
501void DumpAngles(const SkTArray<class SkOpContour* , true>* contours) {
502 SkPathOpsDebug::DumpContourAngles(*contours);
503}
504
505void DumpSpans(const SkTArray<class SkOpContour, true>& contours) {
506 SkPathOpsDebug::DumpContourSpans(contours);
507}
508
509void DumpSpans(const SkTArray<class SkOpContour* , true>& contours) {
510 SkPathOpsDebug::DumpContourSpans(contours);
511}
512
513void DumpSpans(const SkTArray<class SkOpContour, true>* contours) {
514 SkPathOpsDebug::DumpContourSpans(*contours);
515}
516
517void DumpSpans(const SkTArray<class SkOpContour* , true>* contours) {
518 SkPathOpsDebug::DumpContourSpans(*contours);
519}
520
521void DumpPts(const SkTArray<class SkOpContour, true>& contours) {
522 SkPathOpsDebug::DumpContourPts(contours);
523}
524
525void DumpPts(const SkTArray<class SkOpContour* , true>& contours) {
526 SkPathOpsDebug::DumpContourPts(contours);
527}
528
529void DumpPts(const SkTArray<class SkOpContour, true>* contours) {
530 SkPathOpsDebug::DumpContourPts(*contours);
531}
532
533void DumpPts(const SkTArray<class SkOpContour* , true>* contours) {
534 SkPathOpsDebug::DumpContourPts(*contours);
535}
536
537static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
538 SkDebugf("<div id=\"quad%d\">\n", testNo);
539 quad1.dumpComma(",");
540 quad2.dump();
541 SkDebugf("</div>\n\n");
542}
543
544static void dumpTestTrailer() {
545 SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
546 SkDebugf(" var testDivs = [\n");
547}
548
549static void dumpTestList(int testNo, double min) {
550 SkDebugf(" quad%d,", testNo);
551 if (min > 0) {
552 SkDebugf(" // %1.9g", min);
553 }
554 SkDebugf("\n");
555}
556
557void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
558 SkDebugf("\n");
559 dumpTestCase(quad1, quad2, testNo);
560 dumpTestTrailer();
561 dumpTestList(testNo, 0);
562 SkDebugf("\n");
563}
564
565void DumpT(const SkDQuad& quad, double t) {
566 SkDLine line = {{quad.ptAtT(t), quad[0]}};
567 line.dump();
568}