blob: bec4a7d1bb71f177455c37d4ef52d639a86a2fec [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
9#include "include/core/SkDrawable.h"
10#include "include/core/SkPictureRecorder.h"
11#include "include/utils/SkInterpolator.h"
12#include "include/utils/SkRandom.h"
13#include "samplecode/Sample.h"
14#include "src/core/SkPointPriv.h"
Hal Canary41248072019-07-11 16:32:53 -040015#include "tools/timer/TimeUtils.h"
reedadc8d982014-11-26 08:45:36 -080016
17const SkRect gUnitSquare = { -1, -1, 1, 1 };
18
19static 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
26static 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
33static 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);
Cary Clarkdf429f32017-11-08 11:44:31 -050038 return SkPointPriv::LengthSqd(pt) <= 1;
reedadc8d982014-11-26 08:45:36 -080039}
40
41static SkColor rand_opaque_color(uint32_t seed) {
42 SkRandom rand(seed);
43 return rand.nextU() | (0xFF << 24);
44}
45
reed3cb38402015-02-06 08:36:15 -080046class HTDrawable : public SkDrawable {
reedadc8d982014-11-26 08:45:36 -080047 SkRect fR;
48 SkColor fColor;
49 SkInterpolator* fInterp;
reedd9adfe62015-02-01 19:01:04 -080050 SkMSec fTime;
reedadc8d982014-11-26 08:45:36 -080051
52public:
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());
halcanary96fcdcc2015-08-27 07:41:13 -070057 fInterp = nullptr;
reedd9adfe62015-02-01 19:01:04 -080058 fTime = 0;
reedadc8d982014-11-26 08:45:36 -080059 }
halcanary9d524f22016-03-29 09:03:52 -070060
reedd9adfe62015-02-01 19:01:04 -080061 void spawnAnimation(SkMSec now) {
62 this->setTime(now);
63
halcanary385fe4d2015-08-26 13:07:48 -070064 delete fInterp;
65 fInterp = new SkInterpolator(5, 3);
reedadc8d982014-11-26 08:45:36 -080066 SkScalar values[5];
67 color_to_floats(fColor, values); values[4] = 0;
reedd9adfe62015-02-01 19:01:04 -080068 fInterp->setKeyFrame(0, now, values);
reedadc8d982014-11-26 08:45:36 -080069 values[0] = 0; values[4] = 180;
reedd9adfe62015-02-01 19:01:04 -080070 fInterp->setKeyFrame(1, now + 1000, values);
reedadc8d982014-11-26 08:45:36 -080071 color_to_floats(rand_opaque_color(fColor), values); values[4] = 360;
reedd9adfe62015-02-01 19:01:04 -080072 fInterp->setKeyFrame(2, now + 2000, values);
reedadc8d982014-11-26 08:45:36 -080073
74 fInterp->setMirror(true);
75 fInterp->setRepeatCount(3);
76
77 this->notifyDrawingChanged();
78 }
79
80 bool hitTest(SkScalar x, SkScalar y) {
81 return oval_contains(fR, x, y);
82 }
83
reedd9adfe62015-02-01 19:01:04 -080084 void setTime(SkMSec time) { fTime = time; }
85
mtklein36352bf2015-03-25 18:17:31 -070086 void onDraw(SkCanvas* canvas) override {
reedadc8d982014-11-26 08:45:36 -080087 SkAutoCanvasRestore acr(canvas, false);
88
89 SkPaint paint;
90 paint.setAntiAlias(true);
91
92 if (fInterp) {
93 SkScalar values[5];
reedd9adfe62015-02-01 19:01:04 -080094 SkInterpolator::Result res = fInterp->timeToValues(fTime, values);
reedadc8d982014-11-26 08:45:36 -080095 fColor = floats_to_color(values);
96
97 canvas->save();
bungeman7438bfc2016-07-12 15:01:19 -070098 canvas->rotate(values[4], fR.centerX(), fR.centerY());
reedadc8d982014-11-26 08:45:36 -080099
100 switch (res) {
101 case SkInterpolator::kFreezeEnd_Result:
halcanary385fe4d2015-08-26 13:07:48 -0700102 delete fInterp;
halcanary96fcdcc2015-08-27 07:41:13 -0700103 fInterp = nullptr;
reedadc8d982014-11-26 08:45:36 -0800104 break;
105 default:
106 break;
107 }
108 }
109 paint.setColor(fColor);
110 canvas->drawRect(fR, paint);
111 }
reedd9adfe62015-02-01 19:01:04 -0800112
mtklein36352bf2015-03-25 18:17:31 -0700113 SkRect onGetBounds() override { return fR; }
reedadc8d982014-11-26 08:45:36 -0800114};
115
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400116class HTView : public Sample {
reedadc8d982014-11-26 08:45:36 -0800117public:
118 enum {
119 N = 50,
120 W = 640,
121 H = 480,
122 };
halcanary9d524f22016-03-29 09:03:52 -0700123
reedadc8d982014-11-26 08:45:36 -0800124 struct Rec {
125 HTDrawable* fDrawable;
126 };
127 Rec fArray[N];
reedca2622b2016-03-18 07:25:55 -0700128 sk_sp<SkDrawable> fRoot;
reedd9adfe62015-02-01 19:01:04 -0800129 SkMSec fTime;
halcanary9d524f22016-03-29 09:03:52 -0700130
reedadc8d982014-11-26 08:45:36 -0800131 HTView() {
132 SkRandom rand;
133
134 SkPictureRecorder recorder;
135 SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(W, H));
136 for (int i = 0; i < N; ++i) {
137 fArray[i].fDrawable = new HTDrawable(rand);
reed3cb38402015-02-06 08:36:15 -0800138 canvas->drawDrawable(fArray[i].fDrawable);
reedadc8d982014-11-26 08:45:36 -0800139 fArray[i].fDrawable->unref();
140 }
reedca2622b2016-03-18 07:25:55 -0700141 fRoot = recorder.finishRecordingAsDrawable();
reedadc8d982014-11-26 08:45:36 -0800142 }
143
144protected:
Hal Canary8a027312019-07-03 10:55:44 -0400145 SkString name() override { return SkString("HT"); }
reedadc8d982014-11-26 08:45:36 -0800146
mtklein36352bf2015-03-25 18:17:31 -0700147 void onDrawContent(SkCanvas* canvas) override {
reedca2622b2016-03-18 07:25:55 -0700148 canvas->drawDrawable(fRoot.get());
reedd9adfe62015-02-01 19:01:04 -0800149 }
150
Hal Canary41248072019-07-11 16:32:53 -0400151 bool onAnimate(double nanos) override {
152 fTime = TimeUtils::NanosToMSec(nanos);
reedd9adfe62015-02-01 19:01:04 -0800153 for (int i = 0; i < N; ++i) {
154 fArray[i].fDrawable->setTime(fTime);
155 }
156 return true;
reedadc8d982014-11-26 08:45:36 -0800157 }
158
Hal Canaryb1f411a2019-08-29 10:39:22 -0400159 Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
reedadc8d982014-11-26 08:45:36 -0800160 // search backwards to find the top-most
161 for (int i = N - 1; i >= 0; --i) {
162 if (fArray[i].fDrawable->hitTest(x, y)) {
reedd9adfe62015-02-01 19:01:04 -0800163 fArray[i].fDrawable->spawnAnimation(fTime);
reedadc8d982014-11-26 08:45:36 -0800164 break;
165 }
166 }
halcanary96fcdcc2015-08-27 07:41:13 -0700167 return nullptr;
reedadc8d982014-11-26 08:45:36 -0800168 }
169
170private:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400171 typedef Sample INHERITED;
reedadc8d982014-11-26 08:45:36 -0800172};
173
174//////////////////////////////////////////////////////////////////////////////
175
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400176DEF_SAMPLE( return new HTView(); )