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