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