1/*
2 * Copyright 2013 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#include "SampleCode.h"
8
9#include "SkCanvas.h"
10#include "SkPath.h"
11#include "SkRandom.h"
12#include "SkRRect.h"
13#include "SkTime.h"
14
15// Implementation in C++ of Mozilla Canvas2D benchmark Canvas Clock Test
16// See https://code.google.com/p/skia/issues/detail?id=1626
17
18#define USE_PATH 1
19
20class ClockView : public SampleView {
21public:
22    ClockView() {}
23
24protected:
25    // overrides from SkEventSink
26    bool onQuery(SkEvent* evt) override {
27        if (SampleCode::TitleQ(*evt)) {
28            SampleCode::TitleR(evt, "Clock");
29            return true;
30        }
31        return this->INHERITED::onQuery(evt);
32    }
33
34    void onDrawContent(SkCanvas* canvas) override {
35        SkPaint paintFill;
36        SkPaint paintStroke;
37        SkPath  path;
38
39        canvas->save();
40        canvas->translate(150, 150);
41        canvas->scale(0.4f, 0.4f);
42        canvas->rotate(-180.f/2.f);
43
44        paintFill.setAntiAlias(true);
45        paintFill.setColor(SK_ColorBLACK);
46        paintStroke.setAntiAlias(true);
47        paintStroke.setStyle(SkPaint::kStroke_Style);
48        paintStroke.setColor(SK_ColorBLACK);
49        paintStroke.setStrokeWidth(8);
50        paintStroke.setStrokeCap(SkPaint::kRound_Cap);
51
52        // Hour marks
53        SkRect rect;
54#ifndef USE_PATH
55        rect = SkRect::MakeLTRB(200-4, -4, 240+4, 4);
56        SkRRect rrect;
57        SkVector radii[4] = {{4,4}, {4,4}, {4,4}, {4,4}};
58        rrect.setRectRadii(rect, radii);
59#endif
60        canvas->save();
61        for (int i=0;i<12;i++){
62            canvas->rotate(180.f/6.f);
63#ifdef USE_PATH
64            path.reset();
65            path.moveTo(200,0);
66            path.lineTo(240,0);
67            canvas->drawPath(path, paintStroke);
68#else
69            canvas->drawRRect(rrect, paintFill);
70#endif
71        }
72        canvas->restore();
73
74        // Minute marks
75        canvas->save();
76#ifdef USE_PATH
77        paintStroke.setStrokeWidth(5);
78#else
79        rect = SkRect::MakeLTRB(231.5f, -2.5f, 242.5, 2.5f);
80        radii[0] = SkPoint::Make(2.5f,2.5f);
81        radii[1] = SkPoint::Make(2.5f,2.5f);
82        radii[2] = SkPoint::Make(2.5f,2.5f);
83        radii[3] = SkPoint::Make(2.5f,2.5f);
84        rrect.setRectRadii(rect, radii);
85#endif
86        for (int i=0;i<60;i++){
87            if (i%5 == 0) {
88                canvas->rotate(180.f/30.f);
89                continue;
90            }
91#ifdef USE_PATH
92            path.reset();
93            path.moveTo(234,0);
94            path.lineTo(240,0);
95            canvas->drawPath(path, paintStroke);
96#else
97            canvas->drawRRect(rrect, paintFill);
98#endif
99            canvas->rotate(180.f/30.f);
100        }
101        canvas->restore();
102
103        SkTime::DateTime time;
104        SkTime::GetDateTime(&time);
105        time.fHour = time.fHour >= 12 ? time.fHour-12 : time.fHour;
106        paintFill.setColor(SK_ColorBLACK);
107
108        // Write hours
109        canvas->save();
110        canvas->rotate(time.fHour*(180.f/6.f) + time.fMinute*(180.f/360.f)
111                       + time.fSecond*(180.f/21600.f) );
112#ifdef USE_PATH
113        paintStroke.setStrokeWidth(14);
114        path.reset();
115        path.moveTo(-20,0);
116        path.lineTo(80,0);
117        canvas->drawPath(path, paintStroke);
118#else
119        rect = SkRect::MakeLTRB(-20-7, -7, 80+7, 7);
120        radii[0] = SkPoint::Make(7,7);
121        radii[1] = SkPoint::Make(7,7);
122        radii[2] = SkPoint::Make(7,7);
123        radii[3] = SkPoint::Make(7,7);
124        rrect.setRectRadii(rect, radii);
125        canvas->drawRRect(rrect, paintFill);
126#endif
127        canvas->restore();
128
129        // Write minutes
130        canvas->save();
131        canvas->rotate(time.fMinute*(180.f/30.f)
132                       + time.fSecond*(180.f/1800.f) );
133#ifdef USE_PATH
134        paintStroke.setStrokeWidth(10);
135        path.reset();
136        path.moveTo(-56,0);
137        path.lineTo(224,0);
138        canvas->drawPath(path, paintStroke);
139#else
140        rect = SkRect::MakeLTRB(-56-5, -5, 224+5, 5);
141        radii[0] = SkPoint::Make(5,5);
142        radii[1] = SkPoint::Make(5,5);
143        radii[2] = SkPoint::Make(5,5);
144        radii[3] = SkPoint::Make(5,5);
145        rrect.setRectRadii(rect, radii);
146        canvas->drawRRect(rrect, paintFill);
147#endif
148        canvas->restore();
149
150        // Write seconds
151        canvas->save();
152        canvas->rotate(time.fSecond*(180.f/30.f));
153        paintFill.setColor(0xffd40000);
154        paintStroke.setColor(0xffd40000);
155        paintStroke.setStrokeWidth(6);
156#ifdef USE_PATH
157        path.reset();
158        path.moveTo(-60,0);
159        path.lineTo(166,0);
160        canvas->drawPath(path, paintStroke);
161#else
162        rect = SkRect::MakeLTRB(-60-3, -3, 166+3, 3);
163        radii[0] = SkPoint::Make(3,3);
164        radii[1] = SkPoint::Make(3,3);
165        radii[2] = SkPoint::Make(3,3);
166        radii[3] = SkPoint::Make(3,3);
167        rrect.setRectRadii(rect, radii);
168        canvas->drawRRect(rrect, paintFill);
169#endif
170        rect = SkRect::MakeLTRB(-20, -20, 20, 20);
171#ifdef USE_PATH
172        path.reset();
173        path.arcTo(rect, 0, 0, false);
174        path.addOval(rect, SkPath::kCCW_Direction);
175        path.arcTo(rect, 360, 0, true);
176        canvas->drawPath(path, paintFill);
177#else
178        canvas->drawOval(rect, paintFill);
179#endif
180        rect = SkRect::MakeLTRB(-20+190, -20, 20+190, 20);
181#ifdef USE_PATH
182        path.reset();
183        path.arcTo(rect, 0, 0, false);
184        path.addOval(rect, SkPath::kCCW_Direction);
185        path.arcTo(rect, 360, 0, true);
186        canvas->drawPath(path, paintStroke);
187#else
188        canvas->drawOval(rect, paintStroke);
189#endif
190        paintFill.setColor(0xff505050);
191#ifdef USE_PATH
192        rect = SkRect::MakeLTRB(-6, -6, 6, 6);
193        path.arcTo(rect, 0, 0, false);
194        path.addOval(rect, SkPath::kCCW_Direction);
195        path.arcTo(rect, 360, 0, true);
196        canvas->drawPath(path, paintFill);
197#else
198        canvas->drawOval(rect, paintFill);
199        rect = SkRect::MakeLTRB(-6, -6, 6, 6);
200        canvas->drawOval(rect, paintFill);
201#endif
202        canvas->restore();
203
204        paintStroke.setStrokeWidth(18);
205        paintStroke.setColor(0xff325FA2);
206        rect = SkRect::MakeLTRB(-284, -284, 284, 284);
207#ifdef USE_PATH
208        path.reset();
209        path.arcTo(rect, 0, 0, false);
210        path.addOval(rect, SkPath::kCCW_Direction);
211        path.arcTo(rect, 360, 0, true);
212        canvas->drawPath(path, paintStroke);
213#else
214        canvas->drawOval(rect, paintStroke);
215#endif
216
217        canvas->restore();
218    }
219
220    bool onAnimate(const SkAnimTimer&) override {
221        return true;
222    }
223
224private:
225
226    typedef SampleView INHERITED;
227};
228
229//////////////////////////////////////////////////////////////////////////////
230
231static SkView* MyFactory() { return new ClockView; }
232static SkViewRegister reg(MyFactory);
233