1#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGradientShader.h"
5#include "SkGraphics.h"
6#include "SkImageDecoder.h"
7#include "SkPath.h"
8#include "SkRegion.h"
9#include "SkShader.h"
10#include "SkUtils.h"
11#include "SkXfermode.h"
12#include "SkColorPriv.h"
13#include "SkColorFilter.h"
14#include "SkTime.h"
15#include "SkRandom.h"
16
17#include "SkLineClipper.h"
18#include "SkEdgeClipper.h"
19
20#define AUTO_ANIMATE    true
21
22static int test0(SkPoint pts[], SkRect* clip) {
23    pts[0].set(200000, 140);
24    pts[1].set(-740000, 483);
25    pts[2].set(1.00000102e-06f, 9.10000017e-05f);
26    clip->set(0, 0, 640, 480);
27    return 2;
28}
29
30///////////////////////////////////////////////////////////////////////////////
31
32static void drawQuad(SkCanvas* canvas, const SkPoint pts[3], const SkPaint& p) {
33    SkPath path;
34    path.moveTo(pts[0]);
35    path.quadTo(pts[1], pts[2]);
36    canvas->drawPath(path, p);
37}
38
39static void drawCubic(SkCanvas* canvas, const SkPoint pts[4], const SkPaint& p) {
40    SkPath path;
41    path.moveTo(pts[0]);
42    path.cubicTo(pts[1], pts[2], pts[3]);
43    canvas->drawPath(path, p);
44}
45
46typedef void (*clipper_proc)(const SkPoint src[], const SkRect& clip,
47                            SkCanvas*, const SkPaint&, const SkPaint&);
48
49static void check_clipper(int count, const SkPoint pts[], const SkRect& clip) {
50    for (int i = 0; i < count; i++) {
51        SkASSERT(pts[i].fX >= clip.fLeft);
52        SkASSERT(pts[i].fX <= clip.fRight);
53        SkASSERT(pts[i].fY >= clip.fTop);
54        SkASSERT(pts[i].fY <= clip.fBottom);
55    }
56
57    if (count > 1) {
58        sk_assert_monotonic_y(pts, count);
59    }
60}
61
62static void line_intersector(const SkPoint src[], const SkRect& clip,
63                         SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) {
64    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, src, p1);
65
66    SkPoint dst[2];
67    if (SkLineClipper::IntersectLine(src, clip, dst)) {
68        check_clipper(2, dst, clip);
69        canvas->drawPoints(SkCanvas::kLines_PointMode, 2, dst, p0);
70    }
71}
72
73static void line_clipper(const SkPoint src[], const SkRect& clip,
74                         SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) {
75    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, src, p1);
76
77    SkPoint dst[SkLineClipper::kMaxPoints];
78    int count = SkLineClipper::ClipLine(src, clip, dst);
79    for (int i = 0; i < count; i++) {
80        check_clipper(2, &dst[i], clip);
81        canvas->drawPoints(SkCanvas::kLines_PointMode, 2, &dst[i], p0);
82    }
83}
84
85static void quad_clipper(const SkPoint src[], const SkRect& clip,
86                         SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) {
87    drawQuad(canvas, src, p1);
88
89    SkEdgeClipper clipper;
90    if (clipper.clipQuad(src, clip)) {
91        SkPoint pts[4];
92        SkPath::Verb verb;
93        while ((verb = clipper.next(pts)) != SkPath::kDone_Verb) {
94            switch (verb) {
95                case SkPath::kLine_Verb:
96                    check_clipper(2, pts, clip);
97                    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p0);
98                    break;
99                case SkPath::kQuad_Verb:
100                    check_clipper(3, pts, clip);
101                    drawQuad(canvas, pts, p0);
102                    break;
103                default:
104                    SkASSERT(!"unexpected verb");
105            }
106        }
107    }
108}
109
110static void cubic_clipper(const SkPoint src[], const SkRect& clip,
111                       SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) {
112    drawCubic(canvas, src, p1);
113
114    SkEdgeClipper clipper;
115    if (clipper.clipCubic(src, clip)) {
116        SkPoint pts[4];
117        SkPath::Verb verb;
118        while ((verb = clipper.next(pts)) != SkPath::kDone_Verb) {
119            switch (verb) {
120                case SkPath::kLine_Verb:
121                    check_clipper(2, pts, clip);
122                    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p0);
123                    break;
124                case SkPath::kCubic_Verb:
125                 //   check_clipper(4, pts, clip);
126                    drawCubic(canvas, pts, p0);
127                    break;
128                default:
129                    SkASSERT(!"unexpected verb");
130            }
131        }
132    }
133}
134
135static const clipper_proc gProcs[] = {
136    line_intersector,
137    line_clipper,
138    quad_clipper,
139    cubic_clipper
140};
141
142///////////////////////////////////////////////////////////////////////////////
143
144enum {
145    W = 640/3,
146    H = 480/3
147};
148
149class LineClipperView : public SkView {
150    SkMSec      fNow;
151    int         fCounter;
152    int         fProcIndex;
153    SkRect      fClip;
154    SkRandom    fRand;
155    SkPoint     fPts[4];
156
157    void randPts() {
158        for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
159            fPts[i].set(fRand.nextUScalar1() * 640,
160                        fRand.nextUScalar1() * 480);
161        }
162        fCounter += 1;
163    }
164
165public:
166	LineClipperView() {
167        fProcIndex = 0;
168        fCounter = 0;
169        fNow = 0;
170
171        int x = (640 - W)/2;
172        int y = (480 - H)/2;
173        fClip.set(SkIntToScalar(x), SkIntToScalar(y),
174                  SkIntToScalar(x + W), SkIntToScalar(y + H));
175        this->randPts();
176    }
177
178protected:
179    // overrides from SkEventSink
180    virtual bool onQuery(SkEvent* evt) {
181        if (SampleCode::TitleQ(*evt)) {
182            SampleCode::TitleR(evt, "LineClipper");
183            return true;
184        }
185        return this->INHERITED::onQuery(evt);
186    }
187
188    void drawBG(SkCanvas* canvas) {
189        canvas->drawColor(SK_ColorWHITE);
190    }
191
192    static void drawVLine(SkCanvas* canvas, SkScalar x, const SkPaint& paint) {
193        canvas->drawLine(x, -999, x, 999, paint);
194    }
195
196    static void drawHLine(SkCanvas* canvas, SkScalar y, const SkPaint& paint) {
197        canvas->drawLine(-999, y, 999, y, paint);
198    }
199
200    virtual void onDraw(SkCanvas* canvas) {
201        this->drawBG(canvas);
202
203        SkMSec now = SampleCode::GetAnimTime();
204        if (fNow != now) {
205            fNow = now;
206            this->randPts();
207            this->inval(NULL);
208        }
209
210     //   fProcIndex = test0(fPts, &fClip);
211
212        SkPaint paint, paint1;
213
214        drawVLine(canvas, fClip.fLeft + SK_ScalarHalf, paint);
215        drawVLine(canvas, fClip.fRight - SK_ScalarHalf, paint);
216        drawHLine(canvas, fClip.fTop + SK_ScalarHalf, paint);
217        drawHLine(canvas, fClip.fBottom - SK_ScalarHalf, paint);
218
219        paint.setColor(SK_ColorLTGRAY);
220        canvas->drawRect(fClip, paint);
221
222        paint.setAntiAlias(true);
223        paint.setColor(SK_ColorBLUE);
224        paint.setStyle(SkPaint::kStroke_Style);
225      //  paint.setStrokeWidth(SkIntToScalar(3));
226        paint.setStrokeCap(SkPaint::kRound_Cap);
227
228        paint1.setAntiAlias(true);
229        paint1.setColor(SK_ColorRED);
230        paint1.setStyle(SkPaint::kStroke_Style);
231        gProcs[fProcIndex](fPts, fClip, canvas, paint, paint1);
232    }
233
234    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
235     //   fProcIndex = (fProcIndex + 1) % SK_ARRAY_COUNT(gProcs);
236        if (x < 50 && y < 50) {
237            this->randPts();
238        }
239        this->inval(NULL);
240        return NULL;
241    }
242
243    virtual bool onClick(Click* click) {
244        return false;
245    }
246
247private:
248    typedef SkView INHERITED;
249};
250
251//////////////////////////////////////////////////////////////////////////////
252
253static SkView* MyFactory() { return new LineClipperView; }
254static SkViewRegister reg(MyFactory);
255
256