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