• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 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 "SampleCode.h"
9 #include "SkAnimTimer.h"
10 #include "SkView.h"
11 #include "SkBitmap.h"
12 #include "SkCanvas.h"
13 #include "SkGradientShader.h"
14 #include "SkGraphics.h"
15 #include "SkPath.h"
16 #include "SkRegion.h"
17 #include "SkShader.h"
18 #include "SkUtils.h"
19 #include "SkColorPriv.h"
20 #include "SkColorFilter.h"
21 #include "SkParsePath.h"
22 #include "SkTime.h"
23 #include "SkTypeface.h"
24 
25 #include "SkGeometry.h"
26 
27 #include <stdlib.h>
28 
29 // http://code.google.com/p/skia/issues/detail?id=32
test_cubic()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 
test_cubic2()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         SkRect r = path.getBounds();
57         SkIRect ir;
58         r.round(&ir);
59         SkDebugf("[%g %g %g %g] [%x %x %x %x]\n",
60                 SkScalarToDouble(r.fLeft), SkScalarToDouble(r.fTop),
61                 SkScalarToDouble(r.fRight), SkScalarToDouble(r.fBottom),
62                 ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
63     }
64 
65     SkBitmap bitmap;
66     bitmap.allocN32Pixels(300, 200);
67 
68     SkCanvas canvas(bitmap);
69     SkPaint paint;
70     paint.setAntiAlias(true);
71     canvas.drawPath(path, paint);
72 }
73 
74 class PathView : public SampleView {
75     SkScalar fPrevSecs;
76 public:
77     SkScalar fDStroke, fStroke, fMinStroke, fMaxStroke;
78     SkPath fPath[6];
79     bool fShowHairline;
80     bool fOnce;
81 
PathView()82     PathView() {
83         fPrevSecs = 0;
84         fOnce = false;
85     }
86 
init()87     void init() {
88         if (fOnce) {
89             return;
90         }
91         fOnce = true;
92 
93         test_cubic();
94         test_cubic2();
95 
96         fShowHairline = false;
97 
98         fDStroke = 1;
99         fStroke = 10;
100         fMinStroke = 10;
101         fMaxStroke = 180;
102 
103         const SkScalar V = 85;
104 
105         fPath[0].moveTo(40, 70);
106         fPath[0].lineTo(70, 70 + SK_ScalarHalf);
107         fPath[0].lineTo(110, 70);
108 
109         fPath[1].moveTo(40, 70);
110         fPath[1].lineTo(70, 70 - SK_ScalarHalf);
111         fPath[1].lineTo(110, 70);
112 
113         fPath[2].moveTo(V, V);
114         fPath[2].lineTo(50, V);
115         fPath[2].lineTo(50, 50);
116 
117         fPath[3].moveTo(50, 50);
118         fPath[3].lineTo(50, V);
119         fPath[3].lineTo(V, V);
120 
121         fPath[4].moveTo(50, 50);
122         fPath[4].lineTo(50, V);
123         fPath[4].lineTo(52, 50);
124 
125         fPath[5].moveTo(52, 50);
126         fPath[5].lineTo(50, V);
127         fPath[5].lineTo(50, 50);
128 
129         this->setBGColor(0xFFDDDDDD);
130     }
131 
132 protected:
133     // overrides from SkEventSink
onQuery(SkEvent * evt)134     bool onQuery(SkEvent* evt) override {
135         if (SampleCode::TitleQ(*evt)) {
136             SampleCode::TitleR(evt, "Paths");
137             return true;
138         }
139         return this->INHERITED::onQuery(evt);
140     }
141 
drawPath(SkCanvas * canvas,const SkPath & path,SkPaint::Join j)142     void drawPath(SkCanvas* canvas, const SkPath& path, SkPaint::Join j) {
143         SkPaint paint;
144 
145         paint.setAntiAlias(true);
146         paint.setStyle(SkPaint::kStroke_Style);
147         paint.setStrokeJoin(j);
148         paint.setStrokeWidth(fStroke);
149 
150         if (fShowHairline) {
151             SkPath  fill;
152 
153             paint.getFillPath(path, &fill);
154             paint.setStrokeWidth(0);
155             canvas->drawPath(fill, paint);
156         } else {
157             canvas->drawPath(path, paint);
158         }
159 
160         paint.setColor(SK_ColorRED);
161         paint.setStrokeWidth(0);
162         canvas->drawPath(path, paint);
163     }
164 
onDrawContent(SkCanvas * canvas)165     void onDrawContent(SkCanvas* canvas) override {
166         this->init();
167         canvas->translate(50, 50);
168 
169         static const SkPaint::Join gJoins[] = {
170             SkPaint::kBevel_Join,
171             SkPaint::kMiter_Join,
172             SkPaint::kRound_Join
173         };
174 
175         for (size_t i = 0; i < SK_ARRAY_COUNT(gJoins); i++) {
176             canvas->save();
177             for (size_t j = 0; j < SK_ARRAY_COUNT(fPath); j++) {
178                 this->drawPath(canvas, fPath[j], gJoins[i]);
179                 canvas->translate(200, 0);
180             }
181             canvas->restore();
182 
183             canvas->translate(0, 200);
184         }
185     }
186 
onAnimate(const SkAnimTimer & timer)187     bool onAnimate(const SkAnimTimer& timer) override {
188         SkScalar currSecs = timer.scaled(100);
189         SkScalar delta = currSecs - fPrevSecs;
190         fPrevSecs = currSecs;
191 
192         fStroke += fDStroke * delta;
193         if (fStroke > fMaxStroke || fStroke < fMinStroke) {
194             fDStroke = -fDStroke;
195         }
196         return true;
197     }
198 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)199     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
200         fShowHairline = !fShowHairline;
201         return this->INHERITED::onFindClickHandler(x, y, modi);
202     }
203 
204 private:
205     typedef SampleView INHERITED;
206 };
207 DEF_SAMPLE( return new PathView; )
208 
209 //////////////////////////////////////////////////////////////////////////////
210 
211 #include "SkCornerPathEffect.h"
212 #include "SkRandom.h"
213 
214 class ArcToView : public SampleView {
215     bool fDoFrame, fDoCorner, fDoConic;
216     SkPaint fPtsPaint, fSkeletonPaint, fCornerPaint;
217 public:
218     enum {
219         N = 4
220     };
221     SkPoint fPts[N];
222 
ArcToView()223     ArcToView()
224         : fDoFrame(false), fDoCorner(false), fDoConic(false)
225     {
226         SkRandom rand;
227         for (int i = 0; i < N; ++i) {
228             fPts[i].fX = 20 + rand.nextUScalar1() * 640;
229             fPts[i].fY = 20 + rand.nextUScalar1() * 480;
230         }
231 
232         const SkScalar rad = 50;
233 
234         fPtsPaint.setAntiAlias(true);
235         fPtsPaint.setStrokeWidth(15);
236         fPtsPaint.setStrokeCap(SkPaint::kRound_Cap);
237 
238         fCornerPaint.setAntiAlias(true);
239         fCornerPaint.setStyle(SkPaint::kStroke_Style);
240         fCornerPaint.setStrokeWidth(13);
241         fCornerPaint.setColor(SK_ColorGREEN);
242         fCornerPaint.setPathEffect(SkCornerPathEffect::Make(rad*2));
243 
244         fSkeletonPaint.setAntiAlias(true);
245         fSkeletonPaint.setStyle(SkPaint::kStroke_Style);
246         fSkeletonPaint.setColor(SK_ColorRED);
247     }
248 
toggle(bool & value)249     void toggle(bool& value) {
250         value = !value;
251     }
252 
253 protected:
254     // overrides from SkEventSink
onQuery(SkEvent * evt)255     bool onQuery(SkEvent* evt) override {
256         if (SampleCode::TitleQ(*evt)) {
257             SampleCode::TitleR(evt, "ArcTo");
258             return true;
259         }
260         SkUnichar uni;
261         if (SampleCode::CharQ(*evt, &uni)) {
262             switch (uni) {
263                 case '1': this->toggle(fDoFrame); return true;
264                 case '2': this->toggle(fDoCorner); return true;
265                 case '3': this->toggle(fDoConic); return true;
266                 default: break;
267             }
268         }
269         return this->INHERITED::onQuery(evt);
270     }
271 
makePath(SkPath * path)272     void makePath(SkPath* path) {
273         path->moveTo(fPts[0]);
274         for (int i = 1; i < N; ++i) {
275             path->lineTo(fPts[i]);
276         }
277         if (!fDoFrame) {
278             path->close();
279         }
280     }
281 
onDrawContent(SkCanvas * canvas)282     void onDrawContent(SkCanvas* canvas) override {
283         canvas->drawPoints(SkCanvas::kPoints_PointMode, N, fPts, fPtsPaint);
284 
285         SkPath path;
286         this->makePath(&path);
287 
288         if (fDoCorner) {
289             canvas->drawPath(path, fCornerPaint);
290         }
291 
292         canvas->drawPath(path, fSkeletonPaint);
293     }
294 
onClick(Click * click)295     bool onClick(Click* click) override {
296         int32_t index;
297         if (click->fMeta.findS32("index", &index)) {
298             SkASSERT((unsigned)index < N);
299             fPts[index] = click->fCurr;
300             return true;
301         }
302         return false;
303     }
304 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)305     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
306         const SkScalar tol = 4;
307         const SkRect r = SkRect::MakeXYWH(x - tol, y - tol, tol * 2, tol * 2);
308         for (int i = 0; i < N; ++i) {
309             if (r.intersects(SkRect::MakeXYWH(fPts[i].fX, fPts[i].fY, 1, 1))) {
310                 Click* click = new Click(this);
311                 click->fMeta.setS32("index", i);
312                 return click;
313             }
314         }
315         return this->INHERITED::onFindClickHandler(x, y, modi);
316     }
317 
318 private:
319     typedef SampleView INHERITED;
320 };
321 DEF_SAMPLE( return new ArcToView; )
322 
323 /////////////
324 
325 class FatStroke : public SampleView {
326     bool fClosed, fShowStroke, fShowHidden, fShowSkeleton;
327     int  fJoinType, fCapType;
328     float fWidth = 30;
329     SkPaint fPtsPaint, fHiddenPaint, fSkeletonPaint, fStrokePaint;
330 public:
331     enum {
332         N = 4
333     };
334     SkPoint fPts[N];
335 
FatStroke()336     FatStroke() : fClosed(false), fShowStroke(true), fShowHidden(false), fShowSkeleton(true),
337                   fJoinType(0), fCapType(0)
338     {
339         SkRandom rand;
340         for (int i = 0; i < N; ++i) {
341             fPts[i].fX = 20 + rand.nextUScalar1() * 640;
342             fPts[i].fY = 20 + rand.nextUScalar1() * 480;
343         }
344 
345         fPtsPaint.setAntiAlias(true);
346         fPtsPaint.setStrokeWidth(10);
347         fPtsPaint.setStrokeCap(SkPaint::kRound_Cap);
348 
349         fHiddenPaint.setAntiAlias(true);
350         fHiddenPaint.setStyle(SkPaint::kStroke_Style);
351         fHiddenPaint.setColor(0xFF0000FF);
352 
353         fStrokePaint.setAntiAlias(true);
354         fStrokePaint.setStyle(SkPaint::kStroke_Style);
355         fStrokePaint.setStrokeWidth(50);
356         fStrokePaint.setColor(0x8000FF00);
357 
358         fSkeletonPaint.setAntiAlias(true);
359         fSkeletonPaint.setStyle(SkPaint::kStroke_Style);
360         fSkeletonPaint.setColor(SK_ColorRED);
361     }
362 
toggle(bool & value)363     void toggle(bool& value) {
364         value = !value;
365     }
366 
toggle3(int & value)367     void toggle3(int& value) {
368         value = (value + 1) % 3;
369     }
370 
371 protected:
372     // overrides from SkEventSink
onQuery(SkEvent * evt)373     bool onQuery(SkEvent* evt) override {
374         if (SampleCode::TitleQ(*evt)) {
375             SampleCode::TitleR(evt, "FatStroke");
376             return true;
377         }
378         SkUnichar uni;
379         if (SampleCode::CharQ(*evt, &uni)) {
380             switch (uni) {
381                 case '1': this->toggle(fShowSkeleton); return true;
382                 case '2': this->toggle(fShowStroke); return true;
383                 case '3': this->toggle(fShowHidden); return true;
384                 case '4': this->toggle3(fJoinType); return true;
385                 case '5': this->toggle3(fCapType); return true;
386                 case '6': this->toggle(fClosed); return true;
387                 case '-': fWidth -= 5; return true;
388                 case '=': fWidth += 5; return true;
389                 default: break;
390             }
391         }
392         return this->INHERITED::onQuery(evt);
393     }
394 
makePath(SkPath * path)395     void makePath(SkPath* path) {
396         path->moveTo(fPts[0]);
397         for (int i = 1; i < N; ++i) {
398             path->lineTo(fPts[i]);
399         }
400         if (fClosed) {
401             path->close();
402         }
403     }
404 
onDrawContent(SkCanvas * canvas)405     void onDrawContent(SkCanvas* canvas) override {
406         canvas->drawColor(0xFFEEEEEE);
407 
408         SkPath path;
409         this->makePath(&path);
410 
411         fStrokePaint.setStrokeWidth(fWidth);
412         fStrokePaint.setStrokeJoin((SkPaint::Join)fJoinType);
413         fStrokePaint.setStrokeCap((SkPaint::Cap)fCapType);
414 
415         if (fShowStroke) {
416             canvas->drawPath(path, fStrokePaint);
417         }
418         if (fShowHidden) {
419             SkPath hidden;
420             fStrokePaint.getFillPath(path, &hidden);
421             canvas->drawPath(hidden, fHiddenPaint);
422         }
423         if (fShowSkeleton) {
424             canvas->drawPath(path, fSkeletonPaint);
425         }
426         canvas->drawPoints(SkCanvas::kPoints_PointMode, N, fPts, fPtsPaint);
427     }
428 
onClick(Click * click)429     bool onClick(Click* click) override {
430         int32_t index;
431         if (click->fMeta.findS32("index", &index)) {
432             SkASSERT((unsigned)index < N);
433             fPts[index] = click->fCurr;
434             return true;
435         }
436         return false;
437     }
438 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)439     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
440         const SkScalar tol = 4;
441         const SkRect r = SkRect::MakeXYWH(x - tol, y - tol, tol * 2, tol * 2);
442         for (int i = 0; i < N; ++i) {
443             if (r.intersects(SkRect::MakeXYWH(fPts[i].fX, fPts[i].fY, 1, 1))) {
444                 Click* click = new Click(this);
445                 click->fMeta.setS32("index", i);
446                 return click;
447             }
448         }
449         return this->INHERITED::onFindClickHandler(x, y, modi);
450     }
451 
452 private:
453     typedef SampleView INHERITED;
454 };
455 DEF_SAMPLE( return new FatStroke; )
456