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