8bdbca3e84215f79bfdec87d3238213778d323a0
[platform/upstream/libSkiaSharp.git] / gm / addarc.cpp
1 /*
2  * Copyright 2015 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 "gm.h"
9 #include "SkAnimTimer.h"
10 #include "SkCanvas.h"
11 #include "SkPathMeasure.h"
12 #include "SkRandom.h"
13
14 class AddArcGM : public skiagm::GM {
15 public:
16     AddArcGM() : fRotate(0) {}
17
18 protected:
19     SkString onShortName() SK_OVERRIDE { return SkString("addarc"); }
20
21     SkISize onISize() SK_OVERRIDE { return SkISize::Make(1040, 1040); }
22
23     void onDraw(SkCanvas* canvas) SK_OVERRIDE {
24         canvas->translate(20, 20);
25
26         SkRect r = SkRect::MakeWH(1000, 1000);
27
28         SkPaint paint;
29         paint.setAntiAlias(true);
30         paint.setStyle(SkPaint::kStroke_Style);
31         paint.setStrokeWidth(15);
32
33         const SkScalar inset = paint.getStrokeWidth() + 4;
34         const SkScalar sweepAngle = 345;
35         SkRandom rand;
36
37         SkScalar sign = 1;
38         while (r.width() > paint.getStrokeWidth() * 3) {
39             paint.setColor(rand.nextU() | (0xFF << 24));
40             SkScalar startAngle = rand.nextUScalar1() * 360;
41
42             SkScalar speed = SkScalarSqrt(16 / r.width()) * 0.5f;
43             startAngle += fRotate * 360 * speed * sign;
44
45             SkPath path;
46             path.addArc(r, startAngle, sweepAngle);
47             canvas->drawPath(path, paint);
48
49             r.inset(inset, inset);
50             sign = -sign;
51         }
52     }
53
54     bool onAnimate(const SkAnimTimer& timer) SK_OVERRIDE {
55         fRotate = timer.scaled(1, 360);
56         return true;
57     }
58
59 private:
60     SkScalar fRotate;
61     typedef skiagm::GM INHERITED;
62 };
63 DEF_GM( return new AddArcGM; )
64
65 ///////////////////////////////////////////////////
66
67 #define R   400
68
69 class AddArcMeasGM : public skiagm::GM {
70 public:
71     AddArcMeasGM() {}
72
73 protected:
74     SkString onShortName() SK_OVERRIDE { return SkString("addarc_meas"); }
75
76     SkISize onISize() SK_OVERRIDE { return SkISize::Make(2*R + 40, 2*R + 40); }
77
78     void onDraw(SkCanvas* canvas) SK_OVERRIDE {
79         canvas->translate(R + 20, R + 20);
80
81         SkPaint paint;
82         paint.setAntiAlias(true);
83         paint.setStyle(SkPaint::kStroke_Style);
84
85         SkPaint measPaint;
86         measPaint.setAntiAlias(true);
87         measPaint.setColor(SK_ColorRED);
88
89         const SkRect oval = SkRect::MakeLTRB(-R, -R, R, R);
90         canvas->drawOval(oval, paint);
91
92         for (SkScalar deg = 0; deg < 360; deg += 10) {
93             const SkScalar rad = SkDegreesToRadians(deg);
94             SkScalar rx = SkScalarCos(rad) * R;
95             SkScalar ry = SkScalarSin(rad) * R;
96
97             canvas->drawLine(0, 0, rx, ry, paint);
98
99             SkPath path;
100             path.addArc(oval, 0, deg);
101             SkPathMeasure meas(path, false);
102             SkScalar arcLen = rad * R;
103             SkPoint pos;
104             if (meas.getPosTan(arcLen, &pos, NULL)) {
105                 canvas->drawLine(0, 0, pos.x(), pos.y(), measPaint);
106             }
107         }
108     }
109
110 private:
111     typedef skiagm::GM INHERITED;
112 };
113 DEF_GM( return new AddArcMeasGM; )
114
115 ///////////////////////////////////////////////////
116
117 // Emphasize drawing a stroked oval (containing conics) and then scaling the results up,
118 // to ensure that we compute the stroke taking the CTM into account
119 //
120 class StrokeCircleGM : public skiagm::GM {
121 public:
122     StrokeCircleGM() : fRotate(0) {}
123     
124 protected:
125     SkString onShortName() SK_OVERRIDE { return SkString("strokecircle"); }
126     
127     SkISize onISize() SK_OVERRIDE { return SkISize::Make(520, 520); }
128     
129     void onDraw(SkCanvas* canvas) SK_OVERRIDE {
130         canvas->scale(20, 20);
131         canvas->translate(13, 13);
132
133         SkPaint paint;
134         paint.setAntiAlias(true);
135         paint.setStyle(SkPaint::kStroke_Style);
136         paint.setStrokeWidth(SK_Scalar1 / 2);
137
138         const SkScalar delta = paint.getStrokeWidth() * 3 / 2;
139         SkRect r = SkRect::MakeXYWH(-12, -12, 24, 24);
140         SkRandom rand;
141
142         SkScalar sign = 1;
143         while (r.width() > paint.getStrokeWidth() * 2) {
144             SkAutoCanvasRestore acr(canvas, true);
145             canvas->rotate(fRotate * sign);
146
147             paint.setColor(rand.nextU() | (0xFF << 24));
148             canvas->drawOval(r, paint);
149             r.inset(delta, delta);
150             sign = -sign;
151         }
152     }
153
154     bool onAnimate(const SkAnimTimer& timer) SK_OVERRIDE {
155         fRotate = timer.scaled(60, 360);
156         return true;
157     }
158
159 private:
160     SkScalar fRotate;
161
162     typedef skiagm::GM INHERITED;
163 };
164 DEF_GM( return new StrokeCircleGM; )
165
166 //////////////////////
167
168 static void html_canvas_arc(SkPath* path, SkScalar x, SkScalar y, SkScalar r, SkScalar start,
169                             SkScalar end, bool ccw) {
170     SkRect bounds = { x - r, y - r, x + r, y + r };
171     SkScalar sweep = ccw ? end - start : start - end;
172     path->arcTo(bounds, start, sweep, false);
173 }
174
175 // Lifted from canvas-arc-circumference-fill-diffs.html
176 class ManyArcsGM : public skiagm::GM {
177 public:
178     ManyArcsGM() {}
179     
180 protected:
181     SkString onShortName() SK_OVERRIDE { return SkString("manyarcs"); }
182     
183     SkISize onISize() SK_OVERRIDE { return SkISize::Make(620, 330); }
184     
185     void onDraw(SkCanvas* canvas) SK_OVERRIDE {
186         SkPaint paint;
187         paint.setAntiAlias(true);
188         paint.setStyle(SkPaint::kStroke_Style);
189
190         canvas->translate(10, 10);
191
192         // 20 angles.
193         SkScalar sweepAngles[] = {
194                            -123.7f, -2.3f, -2, -1, -0.3f, -0.000001f, 0, 0.000001f, 0.3f, 0.7f,
195                            1, 1.3f, 1.5f, 1.7f, 1.99999f, 2, 2.00001f, 2.3f, 4.3f, 3934723942837.3f
196         };
197         for (size_t i = 0; i < SK_ARRAY_COUNT(sweepAngles); ++i) {
198             sweepAngles[i] *= 180;
199         }
200         
201         SkScalar startAngles[] = { -1, -0.5f, 0, 0.5f };
202         for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles); ++i) {
203             startAngles[i] *= 180;
204         }
205         
206         bool anticlockwise = false;
207         SkScalar sign = 1;
208         for (size_t i = 0; i < SK_ARRAY_COUNT(startAngles) * 2; ++i) {
209             if (i == SK_ARRAY_COUNT(startAngles)) {
210                 anticlockwise = true;
211                 sign = -1;
212             }
213             SkScalar startAngle = startAngles[i % SK_ARRAY_COUNT(startAngles)] * sign;
214             canvas->save();
215             for (size_t j = 0; j < SK_ARRAY_COUNT(sweepAngles); ++j) {
216                 SkPath path;
217                 path.moveTo(0, 2);
218                 html_canvas_arc(&path, 18, 15, 10, startAngle, startAngle + (sweepAngles[j] * sign),
219                                 anticlockwise);
220                 path.lineTo(0, 28);
221                 canvas->drawPath(path, paint);
222                 canvas->translate(30, 0);
223             }
224             canvas->restore();
225             canvas->translate(0, 40);
226         }
227     }
228     
229 private:
230     typedef skiagm::GM INHERITED;
231 };
232 DEF_GM( return new ManyArcsGM; )
233