blob: e1483bef2cc105c17f60146aafae47ff6c1f75ec [file] [log] [blame]
reedadc8d982014-11-26 08:45:36 -08001/*
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"
reed76113a92015-02-02 12:55:02 -08009#include "SkAnimTimer.h"
reedadc8d982014-11-26 08:45:36 -080010#include "SkView.h"
11#include "SkCanvas.h"
reed3cb38402015-02-06 08:36:15 -080012#include "SkDrawable.h"
reedadc8d982014-11-26 08:45:36 -080013#include "SkInterpolator.h"
14#include "SkPictureRecorder.h"
Cary Clarkdf429f32017-11-08 11:44:31 -050015#include "SkPointPriv.h"
reedadc8d982014-11-26 08:45:36 -080016#include "SkRandom.h"
17
18const SkRect gUnitSquare = { -1, -1, 1, 1 };
19
20static 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
27static 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
34static 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);
Cary Clarkdf429f32017-11-08 11:44:31 -050039 return SkPointPriv::LengthSqd(pt) <= 1;
reedadc8d982014-11-26 08:45:36 -080040}
41
42static SkColor rand_opaque_color(uint32_t seed) {
43 SkRandom rand(seed);
44 return rand.nextU() | (0xFF << 24);
45}
46
reed3cb38402015-02-06 08:36:15 -080047class HTDrawable : public SkDrawable {
reedadc8d982014-11-26 08:45:36 -080048 SkRect fR;
49 SkColor fColor;
50 SkInterpolator* fInterp;
reedd9adfe62015-02-01 19:01:04 -080051 SkMSec fTime;
reedadc8d982014-11-26 08:45:36 -080052
53public:
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());
halcanary96fcdcc2015-08-27 07:41:13 -070058 fInterp = nullptr;
reedd9adfe62015-02-01 19:01:04 -080059 fTime = 0;
reedadc8d982014-11-26 08:45:36 -080060 }
halcanary9d524f22016-03-29 09:03:52 -070061
reedd9adfe62015-02-01 19:01:04 -080062 void spawnAnimation(SkMSec now) {
63 this->setTime(now);
64
halcanary385fe4d2015-08-26 13:07:48 -070065 delete fInterp;
66 fInterp = new SkInterpolator(5, 3);
reedadc8d982014-11-26 08:45:36 -080067 SkScalar values[5];
68 color_to_floats(fColor, values); values[4] = 0;
reedd9adfe62015-02-01 19:01:04 -080069 fInterp->setKeyFrame(0, now, values);
reedadc8d982014-11-26 08:45:36 -080070 values[0] = 0; values[4] = 180;
reedd9adfe62015-02-01 19:01:04 -080071 fInterp->setKeyFrame(1, now + 1000, values);
reedadc8d982014-11-26 08:45:36 -080072 color_to_floats(rand_opaque_color(fColor), values); values[4] = 360;
reedd9adfe62015-02-01 19:01:04 -080073 fInterp->setKeyFrame(2, now + 2000, values);
reedadc8d982014-11-26 08:45:36 -080074
75 fInterp->setMirror(true);
76 fInterp->setRepeatCount(3);
77
78 this->notifyDrawingChanged();
79 }
80
81 bool hitTest(SkScalar x, SkScalar y) {
82 return oval_contains(fR, x, y);
83 }
84
reedd9adfe62015-02-01 19:01:04 -080085 void setTime(SkMSec time) { fTime = time; }
86
mtklein36352bf2015-03-25 18:17:31 -070087 void onDraw(SkCanvas* canvas) override {
reedadc8d982014-11-26 08:45:36 -080088 SkAutoCanvasRestore acr(canvas, false);
89
90 SkPaint paint;
91 paint.setAntiAlias(true);
92
93 if (fInterp) {
94 SkScalar values[5];
reedd9adfe62015-02-01 19:01:04 -080095 SkInterpolator::Result res = fInterp->timeToValues(fTime, values);
reedadc8d982014-11-26 08:45:36 -080096 fColor = floats_to_color(values);
97
98 canvas->save();
bungeman7438bfc2016-07-12 15:01:19 -070099 canvas->rotate(values[4], fR.centerX(), fR.centerY());
reedadc8d982014-11-26 08:45:36 -0800100
101 switch (res) {
102 case SkInterpolator::kFreezeEnd_Result:
halcanary385fe4d2015-08-26 13:07:48 -0700103 delete fInterp;
halcanary96fcdcc2015-08-27 07:41:13 -0700104 fInterp = nullptr;
reedadc8d982014-11-26 08:45:36 -0800105 break;
106 default:
107 break;
108 }
109 }
110 paint.setColor(fColor);
111 canvas->drawRect(fR, paint);
112 }
reedd9adfe62015-02-01 19:01:04 -0800113
mtklein36352bf2015-03-25 18:17:31 -0700114 SkRect onGetBounds() override { return fR; }
reedadc8d982014-11-26 08:45:36 -0800115};
116
117class HTView : public SampleView {
118public:
119 enum {
120 N = 50,
121 W = 640,
122 H = 480,
123 };
halcanary9d524f22016-03-29 09:03:52 -0700124
reedadc8d982014-11-26 08:45:36 -0800125 struct Rec {
126 HTDrawable* fDrawable;
127 };
128 Rec fArray[N];
reedca2622b2016-03-18 07:25:55 -0700129 sk_sp<SkDrawable> fRoot;
reedd9adfe62015-02-01 19:01:04 -0800130 SkMSec fTime;
halcanary9d524f22016-03-29 09:03:52 -0700131
reedadc8d982014-11-26 08:45:36 -0800132 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);
reed3cb38402015-02-06 08:36:15 -0800139 canvas->drawDrawable(fArray[i].fDrawable);
reedadc8d982014-11-26 08:45:36 -0800140 fArray[i].fDrawable->unref();
141 }
reedca2622b2016-03-18 07:25:55 -0700142 fRoot = recorder.finishRecordingAsDrawable();
reedadc8d982014-11-26 08:45:36 -0800143 }
144
145protected:
mtklein36352bf2015-03-25 18:17:31 -0700146 bool onQuery(SkEvent* evt) override {
reedadc8d982014-11-26 08:45:36 -0800147 if (SampleCode::TitleQ(*evt)) {
148 SampleCode::TitleR(evt, "HT");
149 return true;
150 }
151 return this->INHERITED::onQuery(evt);
152 }
153
mtklein36352bf2015-03-25 18:17:31 -0700154 void onDrawContent(SkCanvas* canvas) override {
reedca2622b2016-03-18 07:25:55 -0700155 canvas->drawDrawable(fRoot.get());
reedd9adfe62015-02-01 19:01:04 -0800156 }
157
mtklein36352bf2015-03-25 18:17:31 -0700158 bool onAnimate(const SkAnimTimer& timer) override {
reed76113a92015-02-02 12:55:02 -0800159 fTime = timer.msec();
reedd9adfe62015-02-01 19:01:04 -0800160 for (int i = 0; i < N; ++i) {
161 fArray[i].fDrawable->setTime(fTime);
162 }
163 return true;
reedadc8d982014-11-26 08:45:36 -0800164 }
165
mtklein36352bf2015-03-25 18:17:31 -0700166 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
reedadc8d982014-11-26 08:45:36 -0800167 // search backwards to find the top-most
168 for (int i = N - 1; i >= 0; --i) {
169 if (fArray[i].fDrawable->hitTest(x, y)) {
reedd9adfe62015-02-01 19:01:04 -0800170 fArray[i].fDrawable->spawnAnimation(fTime);
reedadc8d982014-11-26 08:45:36 -0800171 break;
172 }
173 }
halcanary96fcdcc2015-08-27 07:41:13 -0700174 this->inval(nullptr);
175 return nullptr;
reedadc8d982014-11-26 08:45:36 -0800176 }
177
178private:
179 typedef SampleView INHERITED;
180};
181
182//////////////////////////////////////////////////////////////////////////////
183
184static SkView* MyFactory() { return new HTView; }
185static SkViewRegister reg(MyFactory);