b5edeb3ad385bd4b56f3bc11679ccf8cea925055
[platform/upstream/libSkiaSharp.git] / samplecode / SamplePath.cpp
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
9 #include "SampleCode.h"
10 #include "SkAnimTimer.h"
11 #include "SkView.h"
12 #include "SkCanvas.h"
13 #include "SkGradientShader.h"
14 #include "SkGraphics.h"
15 #include "SkImageDecoder.h"
16 #include "SkPath.h"
17 #include "SkRegion.h"
18 #include "SkShader.h"
19 #include "SkUtils.h"
20 #include "SkXfermode.h"
21 #include "SkColorPriv.h"
22 #include "SkColorFilter.h"
23 #include "SkParsePath.h"
24 #include "SkTime.h"
25 #include "SkTypeface.h"
26
27 #include "SkGeometry.h"
28
29 // http://code.google.com/p/skia/issues/detail?id=32
30 static void test_cubic() {
31     SkPoint src[4] = {
32         { 556.25000f, 523.03003f },
33         { 556.23999f, 522.96002f },
34         { 556.21997f, 522.89001f },
35         { 556.21997f, 522.82001f }
36     };
37     SkPoint dst[11];
38     dst[10].set(42, -42);   // one past the end, that we don't clobber these
39     SkScalar tval[] = { 0.33333334f, 0.99999994f };
40
41     SkChopCubicAt(src, dst, tval, 2);
42
43 #if 0
44     for (int i = 0; i < 11; i++) {
45         SkDebugf("--- %d [%g %g]\n", i, dst[i].fX, dst[i].fY);
46     }
47 #endif
48 }
49
50 static void test_cubic2() {
51     const char* str = "M2242 -590088L-377758 9.94099e+07L-377758 9.94099e+07L2242 -590088Z";
52     SkPath path;
53     SkParsePath::FromSVGString(str, &path);
54
55     {
56 #ifdef SK_BUILD_FOR_WIN
57         // windows doesn't have strtof
58         float x = (float)strtod("9.94099e+07", NULL);
59 #else
60         float x = strtof("9.94099e+07", NULL);
61 #endif
62         int ix = (int)x;
63         int fx = (int)(x * 65536);
64         int ffx = SkScalarToFixed(x);
65         SkDebugf("%g %x %x %x\n", x, ix, fx, ffx);
66
67         SkRect r = path.getBounds();
68         SkIRect ir;
69         r.round(&ir);
70         SkDebugf("[%g %g %g %g] [%x %x %x %x]\n",
71                 SkScalarToDouble(r.fLeft), SkScalarToDouble(r.fTop),
72                 SkScalarToDouble(r.fRight), SkScalarToDouble(r.fBottom),
73                 ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
74     }
75
76     SkBitmap bitmap;
77     bitmap.allocN32Pixels(300, 200);
78
79     SkCanvas canvas(bitmap);
80     SkPaint paint;
81     paint.setAntiAlias(true);
82     canvas.drawPath(path, paint);
83 }
84
85 class PathView : public SampleView {
86     SkScalar fPrevSecs;
87 public:
88     SkScalar fDStroke, fStroke, fMinStroke, fMaxStroke;
89     SkPath fPath[6];
90     bool fShowHairline;
91     bool fOnce;
92
93     PathView() {
94         fPrevSecs = 0;
95         fOnce = false;
96     }
97
98     void init() {
99         if (fOnce) {
100             return;
101         }
102         fOnce = true;
103
104         test_cubic();
105         test_cubic2();
106
107         fShowHairline = false;
108
109         fDStroke = 1;
110         fStroke = 10;
111         fMinStroke = 10;
112         fMaxStroke = 180;
113
114         const SkScalar V = 85;
115
116         fPath[0].moveTo(40, 70);
117         fPath[0].lineTo(70, 70 + SK_ScalarHalf);
118         fPath[0].lineTo(110, 70);
119
120         fPath[1].moveTo(40, 70);
121         fPath[1].lineTo(70, 70 - SK_ScalarHalf);
122         fPath[1].lineTo(110, 70);
123
124         fPath[2].moveTo(V, V);
125         fPath[2].lineTo(50, V);
126         fPath[2].lineTo(50, 50);
127
128         fPath[3].moveTo(50, 50);
129         fPath[3].lineTo(50, V);
130         fPath[3].lineTo(V, V);
131
132         fPath[4].moveTo(50, 50);
133         fPath[4].lineTo(50, V);
134         fPath[4].lineTo(52, 50);
135
136         fPath[5].moveTo(52, 50);
137         fPath[5].lineTo(50, V);
138         fPath[5].lineTo(50, 50);
139
140         this->setBGColor(0xFFDDDDDD);
141     }
142
143 protected:
144     // overrides from SkEventSink
145     virtual bool onQuery(SkEvent* evt) {
146         if (SampleCode::TitleQ(*evt)) {
147             SampleCode::TitleR(evt, "Paths");
148             return true;
149         }
150         return this->INHERITED::onQuery(evt);
151     }
152
153     void drawPath(SkCanvas* canvas, const SkPath& path, SkPaint::Join j) {
154         SkPaint paint;
155
156         paint.setAntiAlias(true);
157         paint.setStyle(SkPaint::kStroke_Style);
158         paint.setStrokeJoin(j);
159         paint.setStrokeWidth(fStroke);
160
161         if (fShowHairline) {
162             SkPath  fill;
163
164             paint.getFillPath(path, &fill);
165             paint.setStrokeWidth(0);
166             canvas->drawPath(fill, paint);
167         } else {
168             canvas->drawPath(path, paint);
169         }
170
171         paint.setColor(SK_ColorRED);
172         paint.setStrokeWidth(0);
173         canvas->drawPath(path, paint);
174     }
175
176     virtual void onDrawContent(SkCanvas* canvas) {
177         this->init();
178         canvas->translate(50, 50);
179
180         static const SkPaint::Join gJoins[] = {
181             SkPaint::kBevel_Join,
182             SkPaint::kMiter_Join,
183             SkPaint::kRound_Join
184         };
185
186         for (size_t i = 0; i < SK_ARRAY_COUNT(gJoins); i++) {
187             canvas->save();
188             for (size_t j = 0; j < SK_ARRAY_COUNT(fPath); j++) {
189                 this->drawPath(canvas, fPath[j], gJoins[i]);
190                 canvas->translate(200, 0);
191             }
192             canvas->restore();
193
194             canvas->translate(0, 200);
195         }
196     }
197     
198     bool onAnimate(const SkAnimTimer& timer) SK_OVERRIDE {
199         SkScalar currSecs = timer.scaled(100);
200         SkScalar delta = currSecs - fPrevSecs;
201         fPrevSecs = currSecs;
202
203         fStroke += fDStroke * delta;
204         if (fStroke > fMaxStroke || fStroke < fMinStroke) {
205             fDStroke = -fDStroke;
206         }
207         return true;
208     }
209
210     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) SK_OVERRIDE {
211         fShowHairline = !fShowHairline;
212         this->inval(NULL);
213         return this->INHERITED::onFindClickHandler(x, y, modi);
214     }
215
216 private:
217     typedef SampleView INHERITED;
218 };
219 DEF_SAMPLE( return new PathView; )
220
221 //////////////////////////////////////////////////////////////////////////////
222
223 #include "SkArcToPathEffect.h"
224 #include "SkCornerPathEffect.h"
225 #include "SkRandom.h"
226
227 class ArcToView : public SampleView {
228     bool fDoFrame, fDoArcTo, fDoCorner, fDoConic;
229     SkPaint fPtsPaint, fArcToPaint, fSkeletonPaint, fCornerPaint;
230 public:
231     enum {
232         N = 4
233     };
234     SkPoint fPts[N];
235
236     ArcToView()
237         : fDoFrame(false), fDoArcTo(false), fDoCorner(false), fDoConic(false)
238     {
239         SkRandom rand;
240         for (int i = 0; i < N; ++i) {
241             fPts[i].fX = 20 + rand.nextUScalar1() * 640;
242             fPts[i].fY = 20 + rand.nextUScalar1() * 480;
243         }
244         
245         const SkScalar rad = 50;
246
247         fPtsPaint.setAntiAlias(true);
248         fPtsPaint.setStrokeWidth(15);
249         fPtsPaint.setStrokeCap(SkPaint::kRound_Cap);
250
251         fArcToPaint.setAntiAlias(true);
252         fArcToPaint.setStyle(SkPaint::kStroke_Style);
253         fArcToPaint.setStrokeWidth(9);
254         fArcToPaint.setColor(0x800000FF);
255         fArcToPaint.setPathEffect(SkArcToPathEffect::Create(rad))->unref();
256
257         fCornerPaint.setAntiAlias(true);
258         fCornerPaint.setStyle(SkPaint::kStroke_Style);
259         fCornerPaint.setStrokeWidth(13);
260         fCornerPaint.setColor(SK_ColorGREEN);
261         fCornerPaint.setPathEffect(SkCornerPathEffect::Create(rad*2))->unref();
262
263         fSkeletonPaint.setAntiAlias(true);
264         fSkeletonPaint.setStyle(SkPaint::kStroke_Style);
265         fSkeletonPaint.setColor(SK_ColorRED);
266     }
267
268     void toggle(bool& value) {
269         value = !value;
270         this->inval(NULL);
271     }
272
273 protected:
274     // overrides from SkEventSink
275     bool onQuery(SkEvent* evt) SK_OVERRIDE {
276         if (SampleCode::TitleQ(*evt)) {
277             SampleCode::TitleR(evt, "ArcTo");
278             return true;
279         }
280         SkUnichar uni;
281         if (SampleCode::CharQ(*evt, &uni)) {
282             switch (uni) {
283                 case '1': this->toggle(fDoFrame); return true;
284                 case '2': this->toggle(fDoArcTo); return true;
285                 case '3': this->toggle(fDoCorner); return true;
286                 case '4': this->toggle(fDoConic); return true;
287                 default: break;
288             }
289         }
290         return this->INHERITED::onQuery(evt);
291     }
292     
293     void makePath(SkPath* path) {
294         path->moveTo(fPts[0]);
295         for (int i = 1; i < N; ++i) {
296             path->lineTo(fPts[i]);
297         }
298         if (!fDoFrame) {
299             path->close();
300         }
301     }
302
303     void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
304         canvas->drawPoints(SkCanvas::kPoints_PointMode, N, fPts, fPtsPaint);
305
306         SkPath path;
307         this->makePath(&path);
308
309         if (fDoCorner) {
310             canvas->drawPath(path, fCornerPaint);
311         }
312         if (fDoArcTo) {
313             canvas->drawPath(path, fArcToPaint);
314         }
315
316         canvas->drawPath(path, fSkeletonPaint);
317     }
318
319     bool onClick(Click* click) SK_OVERRIDE {
320         int32_t index;
321         if (click->fMeta.findS32("index", &index)) {
322             SkASSERT((unsigned)index < N);
323             fPts[index] = click->fCurr;
324             this->inval(NULL);
325             return true;
326         }
327         return false;
328     }
329
330     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) SK_OVERRIDE {
331         const SkScalar tol = 4;
332         const SkRect r = SkRect::MakeXYWH(x - tol, y - tol, tol * 2, tol * 2);
333         for (int i = 0; i < N; ++i) {
334             if (r.intersects(SkRect::MakeXYWH(fPts[i].fX, fPts[i].fY, 1, 1))) {
335                 Click* click = new Click(this);
336                 click->fMeta.setS32("index", i);
337                 return click;
338             }
339         }
340         return this->INHERITED::onFindClickHandler(x, y, modi);
341     }
342
343 private:
344     typedef SampleView INHERITED;
345 };
346 DEF_SAMPLE( return new ArcToView; )
347