blob: d53271af4df56094950ffce6ab317e8ceb55ce59 [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
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000205const SkTDArray<SkOpSpan>& SkOpSegment::debugSpans() const {
206 return fTs;
207}
208
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000209void SkOpSegment::dumpAngles() const {
210 SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID());
211 int fromIndex = -1, toIndex = -1;
212 for (int index = 0; index < count(); ++index) {
213 int fIndex = fTs[index].fFromAngleIndex;
214 int tIndex = fTs[index].fToAngleIndex;
215 if (fromIndex == fIndex && tIndex == toIndex) {
216 continue;
217 }
218 if (fIndex >= 0) {
219 SkDebugf(" [%d] from=%d ", index, fIndex);
220 const SkOpAngle& angle = this->angle(fIndex);
221 angle.dumpFromTo(this, fIndex, tIndex);
222 }
223 if (tIndex >= 0) {
224 SkDebugf(" [%d] to=%d ", index, tIndex);
225 const SkOpAngle& angle = this->angle(tIndex);
226 angle.dumpFromTo(this, fIndex, tIndex);
227 }
228 fromIndex = fIndex;
229 toIndex = tIndex;
230 }
231}
232
233void SkOpSegment::dumpContour(int firstID, int lastID) const {
234 if (debugID() < 0) {
235 return;
236 }
237 const SkOpSegment* test = this - (debugID() - 1);
238 test += (firstID - 1);
239 const SkOpSegment* last = test + (lastID - firstID);
240 while (test <= last) {
241 test->dumpSpans();
242 ++test;
243 }
244}
245
246void SkOpSegment::dumpPts() const {
247 int last = SkPathOpsVerbToPoints(fVerb);
248 SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
249 int index = 0;
250 do {
251 SkDPoint::Dump(fPts[index]);
252 SkDebugf(", ");
253 } while (++index < last);
254 SkDPoint::Dump(fPts[index]);
255 SkDebugf("}}\n");
256}
257
258void SkOpSegment::dumpDPts() const {
259 int count = SkPathOpsVerbToPoints(fVerb);
260 SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
261 int index = 0;
262 do {
263 SkDPoint dPt = {fPts[index].fX, fPts[index].fY};
264 dPt.dump();
265 if (index != count) {
266 SkDebugf(", ");
267 }
268 } while (++index <= count);
269 SkDebugf("}}\n");
270}
271
272void SkOpSegment::dumpSpans() const {
273 int count = this->count();
274 SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID());
275 for (int index = 0; index < count; ++index) {
276 const SkOpSpan& span = this->span(index);
277 SkDebugf(" [%d] ", index);
278 span.dumpOne();
279 }
280}
281
282void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle, true>& angles) {
283 int count = angles.count();
284 for (int index = 0; index < count; ++index) {
285 angles[index].dump();
286 }
287}
288
289void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle* , true>& angles) {
290 int count = angles.count();
291 for (int index = 0; index < count; ++index) {
292 angles[index]->dump();
293 }
294}
295
296void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour, true>& contours) {
297 int count = contours.count();
298 for (int index = 0; index < count; ++index) {
299 contours[index].dump();
300 }
301}
302
303void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour* , true>& contours) {
304 int count = contours.count();
305 for (int index = 0; index < count; ++index) {
306 contours[index]->dump();
307 }
308}
309
310void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour, true>& contours) {
311 int count = contours.count();
312 for (int index = 0; index < count; ++index) {
313 contours[index].dumpAngles();
314 }
315}
316
317void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour* , true>& contours) {
318 int count = contours.count();
319 for (int index = 0; index < count; ++index) {
320 contours[index]->dumpAngles();
321 }
322}
323
324void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour, true>& contours) {
325 int count = contours.count();
326 for (int index = 0; index < count; ++index) {
327 contours[index].dumpPts();
328 }
329}
330
331void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour* , true>& contours) {
332 int count = contours.count();
333 for (int index = 0; index < count; ++index) {
334 contours[index]->dumpPts();
335 }
336}
337
338void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour, true>& contours) {
339 int count = contours.count();
340 for (int index = 0; index < count; ++index) {
341 contours[index].dumpSpans();
342 }
343}
344
345void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour* , true>& contours) {
346 int count = contours.count();
347 for (int index = 0; index < count; ++index) {
348 contours[index]->dumpSpans();
349 }
350}
351
352void SkPathOpsDebug::DumpSpans(const SkTDArray<SkOpSpan *>& spans) {
353 int count = spans.count();
354 for (int index = 0; index < count; ++index) {
355 const SkOpSpan* span = spans[index];
356 const SkOpSpan& oSpan = span->fOther->span(span->fOtherIndex);
357 const SkOpSegment* segment = oSpan.fOther;
358 SkDebugf("((SkOpSegment*) 0x%p) [%d] ", segment, segment->debugID());
359 SkDebugf("spanIndex:%d ", oSpan.fOtherIndex);
360 span->dumpOne();
361 }
362}
363
364// this does not require that other T index is initialized or correct
365const SkOpSegment* SkOpSpan::debugToSegment(ptrdiff_t* spanIndex) const {
366 if (!fOther) {
367 return NULL;
368 }
369 int oppCount = fOther->count();
370 for (int index = 0; index < oppCount; ++index) {
371 const SkOpSpan& otherSpan = fOther->span(index);
372 double otherTestT = otherSpan.fT;
373 if (otherTestT < fOtherT) {
374 continue;
375 }
376 SkASSERT(otherTestT == fOtherT);
377 const SkOpSegment* candidate = otherSpan.fOther;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000378 const SkOpSpan* first = candidate->debugSpans().begin();
379 const SkOpSpan* last = candidate->debugSpans().end() - 1;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000380 if (first <= this && this <= last) {
381 if (spanIndex) {
382 *spanIndex = this - first;
383 }
384 return candidate;
385 }
386 }
387 SkASSERT(0);
388 return NULL;
389}
390
391void SkOpSpan::dumpOne() const {
392 SkDebugf("t=");
393 DebugDumpDouble(fT);
394 SkDebugf(" pt=");
395 SkDPoint::Dump(fPt);
396 if (fOther) {
397 SkDebugf(" other.fID=%d", fOther->debugID());
398 SkDebugf(" [%d] otherT=", fOtherIndex);
399 DebugDumpDouble(fOtherT);
400 } else {
401 SkDebugf(" other.fID=? [?] otherT=?");
402 }
403#if DEBUG_WINDING
404 SkDebugf(" windSum=");
405 SkPathOpsDebug::WindingPrintf(fWindSum);
406#endif
407 if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) {
408#if DEBUG_WINDING
409 SkDebugf(" oppSum=");
410 SkPathOpsDebug::WindingPrintf(fOppSum);
411#endif
412 }
413 SkDebugf(" windValue=%d", fWindValue);
414 if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) {
415 SkDebugf(" oppValue=%d", fOppValue);
416 }
417 SkDebugf(" from=%d", fFromAngleIndex);
418 SkDebugf(" to=%d", fToAngleIndex);
419 if (fDone) {
420 SkDebugf(" done");
421 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000422 if (fTiny) {
423 SkDebugf(" tiny");
424 }
425 if (fSmall) {
426 SkDebugf(" small");
427 }
428 if (fLoop) {
429 SkDebugf(" loop");
430 }
431 SkDebugf("\n");
432}
433
434void SkOpSpan::dump() const {
435 ptrdiff_t spanIndex;
436 const SkOpSegment* segment = debugToSegment(&spanIndex);
437 if (segment) {
438 SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", segment, segment->debugID());
439 SkDebugf(" [%d] ", spanIndex);
440 } else {
441 SkDebugf("((SkOpSegment*) ?) [?]\n");
442 SkDebugf(" [?] ");
443 }
444 dumpOne();
445}
446
447void Dump(const SkTArray<class SkOpAngle, true>& angles) {
448 SkPathOpsDebug::DumpAngles(angles);
449}
450
451void Dump(const SkTArray<class SkOpAngle* , true>& angles) {
452 SkPathOpsDebug::DumpAngles(angles);
453}
454
455void Dump(const SkTArray<class SkOpAngle, true>* angles) {
456 SkPathOpsDebug::DumpAngles(*angles);
457}
458
459void Dump(const SkTArray<class SkOpAngle* , true>* angles) {
460 SkPathOpsDebug::DumpAngles(*angles);
461}
462
463void Dump(const SkTArray<class SkOpContour, true>& contours) {
464 SkPathOpsDebug::DumpContours(contours);
465}
466
467void Dump(const SkTArray<class SkOpContour* , true>& contours) {
468 SkPathOpsDebug::DumpContours(contours);
469}
470
471void Dump(const SkTArray<class SkOpContour, true>* contours) {
472 SkPathOpsDebug::DumpContours(*contours);
473}
474
475void Dump(const SkTArray<class SkOpContour* , true>* contours) {
476 SkPathOpsDebug::DumpContours(*contours);
477}
478
479void Dump(const SkTDArray<SkOpSpan *>& chaseArray) {
480 SkPathOpsDebug::DumpSpans(chaseArray);
481}
482
483void Dump(const SkTDArray<SkOpSpan *>* chaseArray) {
484 SkPathOpsDebug::DumpSpans(*chaseArray);
485}
486
487void DumpAngles(const SkTArray<class SkOpContour, true>& contours) {
488 SkPathOpsDebug::DumpContourAngles(contours);
489}
490
491void DumpAngles(const SkTArray<class SkOpContour* , true>& contours) {
492 SkPathOpsDebug::DumpContourAngles(contours);
493}
494
495void DumpAngles(const SkTArray<class SkOpContour, true>* contours) {
496 SkPathOpsDebug::DumpContourAngles(*contours);
497}
498
499void DumpAngles(const SkTArray<class SkOpContour* , true>* contours) {
500 SkPathOpsDebug::DumpContourAngles(*contours);
501}
502
503void DumpSpans(const SkTArray<class SkOpContour, true>& contours) {
504 SkPathOpsDebug::DumpContourSpans(contours);
505}
506
507void DumpSpans(const SkTArray<class SkOpContour* , true>& contours) {
508 SkPathOpsDebug::DumpContourSpans(contours);
509}
510
511void DumpSpans(const SkTArray<class SkOpContour, true>* contours) {
512 SkPathOpsDebug::DumpContourSpans(*contours);
513}
514
515void DumpSpans(const SkTArray<class SkOpContour* , true>* contours) {
516 SkPathOpsDebug::DumpContourSpans(*contours);
517}
518
519void DumpPts(const SkTArray<class SkOpContour, true>& contours) {
520 SkPathOpsDebug::DumpContourPts(contours);
521}
522
523void DumpPts(const SkTArray<class SkOpContour* , true>& contours) {
524 SkPathOpsDebug::DumpContourPts(contours);
525}
526
527void DumpPts(const SkTArray<class SkOpContour, true>* contours) {
528 SkPathOpsDebug::DumpContourPts(*contours);
529}
530
531void DumpPts(const SkTArray<class SkOpContour* , true>* contours) {
532 SkPathOpsDebug::DumpContourPts(*contours);
533}
534
535static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
536 SkDebugf("<div id=\"quad%d\">\n", testNo);
537 quad1.dumpComma(",");
538 quad2.dump();
539 SkDebugf("</div>\n\n");
540}
541
542static void dumpTestTrailer() {
543 SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
544 SkDebugf(" var testDivs = [\n");
545}
546
547static void dumpTestList(int testNo, double min) {
548 SkDebugf(" quad%d,", testNo);
549 if (min > 0) {
550 SkDebugf(" // %1.9g", min);
551 }
552 SkDebugf("\n");
553}
554
555void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
556 SkDebugf("\n");
557 dumpTestCase(quad1, quad2, testNo);
558 dumpTestTrailer();
559 dumpTestList(testNo, 0);
560 SkDebugf("\n");
561}
562
563void DumpT(const SkDQuad& quad, double t) {
564 SkDLine line = {{quad.ptAtT(t), quad[0]}};
565 line.dump();
566}