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