• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 "SkCanvas.h"
12 #include "SkDrawable.h"
13 #include "SkInterpolator.h"
14 #include "SkPictureRecorder.h"
15 #include "SkRandom.h"
16 
17 const SkRect gUnitSquare = { -1, -1, 1, 1 };
18 
color_to_floats(SkColor c,SkScalar f[4])19 static void color_to_floats(SkColor c, SkScalar f[4]) {
20     f[0] = SkIntToScalar(SkColorGetA(c));
21     f[1] = SkIntToScalar(SkColorGetR(c));
22     f[2] = SkIntToScalar(SkColorGetG(c));
23     f[3] = SkIntToScalar(SkColorGetB(c));
24 }
25 
floats_to_color(const SkScalar f[4])26 static SkColor floats_to_color(const SkScalar f[4]) {
27     return SkColorSetARGB(SkScalarRoundToInt(f[0]),
28                           SkScalarRoundToInt(f[1]),
29                           SkScalarRoundToInt(f[2]),
30                           SkScalarRoundToInt(f[3]));
31 }
32 
oval_contains(const SkRect & r,SkScalar x,SkScalar y)33 static bool oval_contains(const SkRect& r, SkScalar x, SkScalar y) {
34     SkMatrix m;
35     m.setRectToRect(r, gUnitSquare, SkMatrix::kFill_ScaleToFit);
36     SkPoint pt;
37     m.mapXY(x, y, &pt);
38     return pt.lengthSqd() <= 1;
39 }
40 
rand_opaque_color(uint32_t seed)41 static SkColor rand_opaque_color(uint32_t seed) {
42     SkRandom rand(seed);
43     return rand.nextU() | (0xFF << 24);
44 }
45 
46 class HTDrawable : public SkDrawable {
47     SkRect          fR;
48     SkColor         fColor;
49     SkInterpolator* fInterp;
50     SkMSec          fTime;
51 
52 public:
HTDrawable(SkRandom & rand)53     HTDrawable(SkRandom& rand) {
54         fR = SkRect::MakeXYWH(rand.nextRangeF(0, 640), rand.nextRangeF(0, 480),
55                               rand.nextRangeF(20, 200), rand.nextRangeF(20, 200));
56         fColor = rand_opaque_color(rand.nextU());
57         fInterp = nullptr;
58         fTime = 0;
59     }
60 
spawnAnimation(SkMSec now)61     void spawnAnimation(SkMSec now) {
62         this->setTime(now);
63 
64         delete fInterp;
65         fInterp = new SkInterpolator(5, 3);
66         SkScalar values[5];
67         color_to_floats(fColor, values); values[4] = 0;
68         fInterp->setKeyFrame(0, now, values);
69         values[0] = 0; values[4] = 180;
70         fInterp->setKeyFrame(1, now + 1000, values);
71         color_to_floats(rand_opaque_color(fColor), values); values[4] = 360;
72         fInterp->setKeyFrame(2, now + 2000, values);
73 
74         fInterp->setMirror(true);
75         fInterp->setRepeatCount(3);
76 
77         this->notifyDrawingChanged();
78     }
79 
hitTest(SkScalar x,SkScalar y)80     bool hitTest(SkScalar x, SkScalar y) {
81         return oval_contains(fR, x, y);
82     }
83 
setTime(SkMSec time)84     void setTime(SkMSec time) { fTime = time; }
85 
onDraw(SkCanvas * canvas)86     void onDraw(SkCanvas* canvas) override {
87         SkAutoCanvasRestore acr(canvas, false);
88 
89         SkPaint paint;
90         paint.setAntiAlias(true);
91 
92         if (fInterp) {
93             SkScalar values[5];
94             SkInterpolator::Result res = fInterp->timeToValues(fTime, values);
95             fColor = floats_to_color(values);
96 
97             canvas->save();
98             canvas->translate(fR.centerX(), fR.centerY());
99             canvas->rotate(values[4]);
100             canvas->translate(-fR.centerX(), -fR.centerY());
101 
102             switch (res) {
103                 case SkInterpolator::kFreezeEnd_Result:
104                     delete fInterp;
105                     fInterp = nullptr;
106                     break;
107                 default:
108                     break;
109             }
110         }
111         paint.setColor(fColor);
112         canvas->drawRect(fR, paint);
113     }
114 
onGetBounds()115     SkRect onGetBounds() override { return fR; }
116 };
117 
118 class HTView : public SampleView {
119 public:
120     enum {
121         N = 50,
122         W = 640,
123         H = 480,
124     };
125 
126     struct Rec {
127         HTDrawable* fDrawable;
128     };
129     Rec fArray[N];
130     SkAutoTUnref<SkDrawable> fRoot;
131     SkMSec fTime;
132 
HTView()133     HTView() {
134         SkRandom rand;
135 
136         SkPictureRecorder recorder;
137         SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(W, H));
138         for (int i = 0; i < N; ++i) {
139             fArray[i].fDrawable = new HTDrawable(rand);
140             canvas->drawDrawable(fArray[i].fDrawable);
141             fArray[i].fDrawable->unref();
142         }
143         fRoot.reset(recorder.endRecordingAsDrawable());
144     }
145 
146 protected:
onQuery(SkEvent * evt)147     bool onQuery(SkEvent* evt) override {
148         if (SampleCode::TitleQ(*evt)) {
149             SampleCode::TitleR(evt, "HT");
150             return true;
151         }
152         return this->INHERITED::onQuery(evt);
153     }
154 
onDrawContent(SkCanvas * canvas)155     void onDrawContent(SkCanvas* canvas) override {
156         canvas->drawDrawable(fRoot);
157     }
158 
onAnimate(const SkAnimTimer & timer)159     bool onAnimate(const SkAnimTimer& timer) override {
160         fTime = timer.msec();
161         for (int i = 0; i < N; ++i) {
162             fArray[i].fDrawable->setTime(fTime);
163         }
164         return true;
165     }
166 
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)167     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
168         // search backwards to find the top-most
169         for (int i = N - 1; i >= 0; --i) {
170             if (fArray[i].fDrawable->hitTest(x, y)) {
171                 fArray[i].fDrawable->spawnAnimation(fTime);
172                 break;
173             }
174         }
175         this->inval(nullptr);
176         return nullptr;
177     }
178 
179 private:
180     typedef SampleView INHERITED;
181 };
182 
183 //////////////////////////////////////////////////////////////////////////////
184 
MyFactory()185 static SkView* MyFactory() { return new HTView; }
186 static SkViewRegister reg(MyFactory);
187