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
10template<typename TCurve, typename OppCurve>
11char SkTCoincident<TCurve, OppCurve>::dumpIsCoincidentStr() const {
12    if (!!fCoincident != fCoincident) {
13        return '?';
14    }
15    return fCoincident ? '*' : 0;
16}
17
18template<typename TCurve, typename OppCurve>
19void 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
24template<typename TCurve, typename OppCurve>
25const 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
35template<typename TCurve, typename OppCurve>
36const 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
54template<typename TCurve, typename OppCurve>
55void SkTSect<TCurve, OppCurve>::dump() const {
56    dumpCommon(fHead);
57}
58
59extern int gDumpTSectNum;
60
61template<typename TCurve, typename OppCurve>
62void 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
83template<typename TCurve, typename OppCurve>
84void 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
100template<typename TCurve, typename OppCurve>
101void SkTSect<TCurve, OppCurve>::dumpBounds() const {
102    const SkTSpan<TCurve, OppCurve>* test = fHead;
103    do {
104        test->dumpBounds();
105    } while ((test = test->next()));
106}
107
108template<typename TCurve, typename OppCurve>
109void SkTSect<TCurve, OppCurve>::dumpCoin() const {
110    dumpCommon(fCoincident);
111}
112
113template<typename TCurve, typename OppCurve>
114void SkTSect<TCurve, OppCurve>::dumpCoinCurves() const {
115    dumpCommonCurves(fCoincident);
116}
117
118template<typename TCurve, typename OppCurve>
119void 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
131template<typename TCurve, typename OppCurve>
132void 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
138template<typename TCurve, typename OppCurve>
139void SkTSect<TCurve, OppCurve>::dumpCurves() const {
140    dumpCommonCurves(fHead);
141}
142
143template<typename TCurve, typename OppCurve>
144const SkTSpan<TCurve, OppCurve>* SkTSpan<TCurve, OppCurve>::debugSpan(int id) const {
145    return SkDEBUGRELEASE(fDebugSect->debugSpan(id), nullptr);
146}
147
148template<typename TCurve, typename OppCurve>
149const SkTSpan<TCurve, OppCurve>* SkTSpan<TCurve, OppCurve>::debugT(double t) const {
150    return SkDEBUGRELEASE(fDebugSect->debugT(t), nullptr);
151}
152
153template<typename TCurve, typename OppCurve>
154void 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
171template<typename TCurve, typename OppCurve>
172void 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
188template<typename TCurve, typename OppCurve>
189void SkTSpan<TCurve, OppCurve>::dumpBounded(int id) const {
190    SkDEBUGCODE(fDebugSect->dumpBounded(id));
191}
192
193template<typename TCurve, typename OppCurve>
194void 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
201template<typename TCurve, typename OppCurve>
202void SkTSpan<TCurve, OppCurve>::dumpCoin() const {
203    dumpID();
204    SkDebugf(" coinStart ");
205    fCoinStart.dump();
206    SkDebugf(" coinEnd ");
207    fCoinEnd.dump();
208}
209
210template<typename TCurve, typename OppCurve>
211void 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