1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkPathOpsTSect.h"
9 
10 template<typename TCurve, typename OppCurve>
dumpIsCoincidentStr()11 char SkTCoincident<TCurve, OppCurve>::dumpIsCoincidentStr() const {
12     if (!!fCoincident != fCoincident) {
13         return '?';
14     }
15     return fCoincident ? '*' : 0;
16 }
17 
18 template<typename TCurve, typename OppCurve>
dump()19 void SkTCoincident<TCurve, OppCurve>::dump() const {
20     SkDebugf("t=%1.9g pt=(%1.9g,%1.9g)%s\n", fPerpT, fPerpPt.fX, fPerpPt.fY,
21             fCoincident ? " coincident" : "");
22 }
23 
24 template<typename TCurve, typename OppCurve>
debugSpan(int id)25 const SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::debugSpan(int id) const {
26     const SkTSpan<TCurve, OppCurve>* test = fHead;
27     do {
28         if (test->debugID() == id) {
29             return test;
30         }
31     } while ((test = test->next()));
32     return nullptr;
33 }
34 
35 template<typename TCurve, typename OppCurve>
debugT(double t)36 const SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::debugT(double t) const {
37     const SkTSpan<TCurve, OppCurve>* test = fHead;
38     const SkTSpan<TCurve, OppCurve>* closest = nullptr;
39     double bestDist = DBL_MAX;
40     do {
41         if (between(test->fStartT, t, test->fEndT)) {
42             return test;
43         }
44         double testDist = SkTMin(fabs(test->fStartT - t), fabs(test->fEndT - t));
45         if (bestDist > testDist) {
46             bestDist = testDist;
47             closest = test;
48         }
49     } while ((test = test->next()));
50     SkASSERT(closest);
51     return closest;
52 }
53 
54 template<typename TCurve, typename OppCurve>
dump()55 void SkTSect<TCurve, OppCurve>::dump() const {
56     dumpCommon(fHead);
57 }
58 
59 extern int gDumpTSectNum;
60 
61 template<typename TCurve, typename OppCurve>
dumpBoth(SkTSect<OppCurve,TCurve> * opp)62 void SkTSect<TCurve, OppCurve>::dumpBoth(SkTSect<OppCurve, TCurve>* opp) const {
63 #if DEBUG_T_SECT_DUMP <= 2
64 #if DEBUG_T_SECT_DUMP == 2
65     SkDebugf("%d ", ++gDumpTSectNum);
66 #endif
67     this->dump();
68     SkDebugf(" ");
69     opp->dump();
70     SkDebugf("\n");
71 #elif DEBUG_T_SECT_DUMP == 3
72     SkDebugf("<div id=\"sect%d\">\n", ++gDumpTSectNum);
73     if (this->fHead) {
74         this->dumpCurves();
75     }
76     if (opp->fHead) {
77         opp->dumpCurves();
78     }
79     SkDebugf("</div>\n\n");
80 #endif
81 }
82 
83 template<typename TCurve, typename OppCurve>
dumpBounded(int id)84 void SkTSect<TCurve, OppCurve>::dumpBounded(int id) const {
85     const SkTSpan<TCurve, OppCurve>* bounded = debugSpan(id);
86     if (!bounded) {
87         SkDebugf("no span matches %d\n", id);
88         return;
89     }
90     const SkTSpan<OppCurve, TCurve>* test = bounded->debugOpp()->fHead;
91     do {
92         if (test->findOppSpan(bounded)) {
93             test->dump();
94             SkDebugf(" ");
95         }
96     } while ((test = test->next()));
97     SkDebugf("\n");
98 }
99 
100 template<typename TCurve, typename OppCurve>
dumpBounds()101 void SkTSect<TCurve, OppCurve>::dumpBounds() const {
102     const SkTSpan<TCurve, OppCurve>* test = fHead;
103     do {
104         test->dumpBounds();
105     } while ((test = test->next()));
106 }
107 
108 template<typename TCurve, typename OppCurve>
dumpCoin()109 void SkTSect<TCurve, OppCurve>::dumpCoin() const {
110     dumpCommon(fCoincident);
111 }
112 
113 template<typename TCurve, typename OppCurve>
dumpCoinCurves()114 void SkTSect<TCurve, OppCurve>::dumpCoinCurves() const {
115     dumpCommonCurves(fCoincident);
116 }
117 
118 template<typename TCurve, typename OppCurve>
dumpCommon(const SkTSpan<TCurve,OppCurve> * test)119 void SkTSect<TCurve, OppCurve>::dumpCommon(const SkTSpan<TCurve, OppCurve>* test) const {
120     SkDebugf("id=%d", debugID());
121     if (!test) {
122         SkDebugf(" (empty)");
123         return;
124     }
125     do {
126         SkDebugf(" ");
127         test->dump();
128     } while ((test = test->next()));
129 }
130 
131 template<typename TCurve, typename OppCurve>
dumpCommonCurves(const SkTSpan<TCurve,OppCurve> * test)132 void SkTSect<TCurve, OppCurve>::dumpCommonCurves(const SkTSpan<TCurve, OppCurve>* test) const {
133     do {
134         test->fPart.dumpID(test->debugID());
135     } while ((test = test->next()));
136 }
137 
138 template<typename TCurve, typename OppCurve>
dumpCurves()139 void SkTSect<TCurve, OppCurve>::dumpCurves() const {
140     dumpCommonCurves(fHead);
141 }
142 
143 template<typename TCurve, typename OppCurve>
debugSpan(int id)144 const SkTSpan<TCurve, OppCurve>* SkTSpan<TCurve, OppCurve>::debugSpan(int id) const {
145     return SkDEBUGRELEASE(fDebugSect->debugSpan(id), nullptr);
146 }
147 
148 template<typename TCurve, typename OppCurve>
debugT(double t)149 const SkTSpan<TCurve, OppCurve>* SkTSpan<TCurve, OppCurve>::debugT(double t) const {
150     return SkDEBUGRELEASE(fDebugSect->debugT(t), nullptr);
151 }
152 
153 template<typename TCurve, typename OppCurve>
dumpAll()154 void SkTSpan<TCurve, OppCurve>::dumpAll() const {
155     dumpID();
156     SkDebugf("=(%g,%g) [", fStartT, fEndT);
157     const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
158     while (testBounded) {
159         const SkTSpan<OppCurve, TCurve>* span = testBounded->fBounded;
160         const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
161         span->dumpID();
162         SkDebugf("=(%g,%g)", span->fStartT, span->fEndT);
163         if (next) {
164             SkDebugf(" ");
165         }
166         testBounded = next;
167     }
168     SkDebugf("]\n");
169 }
170 
171 template<typename TCurve, typename OppCurve>
dump()172 void SkTSpan<TCurve, OppCurve>::dump() const {
173     dumpID();
174     SkDebugf("=(%g,%g) [", fStartT, fEndT);
175     const SkTSpanBounded<OppCurve, TCurve>* testBounded = fBounded;
176     while (testBounded) {
177         const SkTSpan<OppCurve, TCurve>* span = testBounded->fBounded;
178         const SkTSpanBounded<OppCurve, TCurve>* next = testBounded->fNext;
179         span->dumpID();
180         if (next) {
181             SkDebugf(",");
182         }
183         testBounded = next;
184     }
185     SkDebugf("]");
186 }
187 
188 template<typename TCurve, typename OppCurve>
dumpBounded(int id)189 void SkTSpan<TCurve, OppCurve>::dumpBounded(int id) const {
190     SkDEBUGCODE(fDebugSect->dumpBounded(id));
191 }
192 
193 template<typename TCurve, typename OppCurve>
dumpBounds()194 void SkTSpan<TCurve, OppCurve>::dumpBounds() const {
195     dumpID();
196     SkDebugf(" bounds=(%1.9g,%1.9g, %1.9g,%1.9g) boundsMax=%1.9g%s\n",
197             fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom, fBoundsMax,
198             fCollapsed ? " collapsed" : "");
199 }
200 
201 template<typename TCurve, typename OppCurve>
dumpCoin()202 void SkTSpan<TCurve, OppCurve>::dumpCoin() const {
203     dumpID();
204     SkDebugf(" coinStart ");
205     fCoinStart.dump();
206     SkDebugf(" coinEnd ");
207     fCoinEnd.dump();
208 }
209 
210 template<typename TCurve, typename OppCurve>
dumpID()211 void SkTSpan<TCurve, OppCurve>::dumpID() const {
212     char cS = fCoinStart.dumpIsCoincidentStr();
213     if (cS) {
214         SkDebugf("%c", cS);
215     }
216     SkDebugf("%d", debugID());
217     char cE = fCoinEnd.dumpIsCoincidentStr();
218     if (cE) {
219         SkDebugf("%c", cE);
220     }
221 }
222