blob: 90eb1d404ce2f921c9fee8946be869e20c07bbd3 [file] [log] [blame]
Robert Phillips6e1fca42016-12-01 12:42:43 -05001/*
2 * Copyright 2016 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 "gm/gm.h"
Ben Wagnerd1701ba2019-04-30 13:44:26 -04009#include "include/core/SkCanvas.h"
10#include "include/core/SkImageFilter.h"
11#include "include/core/SkPaint.h"
12#include "include/core/SkPoint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkRRect.h"
Ben Wagnerd1701ba2019-04-30 13:44:26 -040014#include "include/core/SkRect.h"
15#include "include/core/SkScalar.h"
16#include "include/core/SkSize.h"
17#include "include/core/SkString.h"
18#include "include/core/SkTypes.h"
Michael Ludwig898bbfa2019-08-02 15:21:23 -040019#include "include/effects/SkImageFilters.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "include/utils/SkRandom.h"
Hal Canary41248072019-07-11 16:32:53 -040021#include "tools/timer/TimeUtils.h"
Robert Phillips6e1fca42016-12-01 12:42:43 -050022
23static const SkScalar kBlurMax = 7.0f;
24static const int kNumNodes = 30;
25static const int kWidth = 512;
26static const int kHeight = 512;
27static const SkScalar kBlurAnimationDuration = 4.0f; // in secs
28
29// This GM draws a lot of layers with animating BlurImageFilters
30class AnimatedImageBlurs : public skiagm::GM {
31public:
32 AnimatedImageBlurs() : fLastTime(0.0f) {
Mike Kleind46dce32018-08-16 10:17:03 -040033 this->setBGColor(0xFFCCCCCC);
Robert Phillips6e1fca42016-12-01 12:42:43 -050034 }
35
36protected:
37 bool runAsBench() const override { return true; }
38
39 SkString onShortName() override { return SkString("animated-image-blurs"); }
40
41 SkISize onISize() override { return SkISize::Make(kWidth, kHeight); }
42
43 void onOnceBeforeDraw() override {
44 for (int i = 0; i < kNumNodes; ++i) {
45 fNodes[i].init(&fRand);
46 }
47 }
48
49 void onDraw(SkCanvas* canvas) override {
50 SkPaint paint;
51 paint.setAntiAlias(true);
52
53 for (int i = 0; i < kNumNodes; ++i) {
54 SkPaint layerPaint;
Michael Ludwig898bbfa2019-08-02 15:21:23 -040055 layerPaint.setImageFilter(SkImageFilters::Blur(fNodes[i].sigma(), fNodes[i].sigma(),
56 nullptr));
Robert Phillips6e1fca42016-12-01 12:42:43 -050057
58 canvas->saveLayer(nullptr, &layerPaint);
59 // The rect is outset to block the circle case
60 SkRect rect = SkRect::MakeLTRB(fNodes[i].pos().fX - fNodes[i].size()-0.5f,
61 fNodes[i].pos().fY - fNodes[i].size()-0.5f,
62 fNodes[i].pos().fX + fNodes[i].size()+0.5f,
63 fNodes[i].pos().fY + fNodes[i].size()+0.5f);
64 SkRRect rrect = SkRRect::MakeRectXY(rect, fNodes[i].size(), fNodes[i].size());
65 canvas->drawRRect(rrect, paint);
66 canvas->restore();
67 }
68 }
69
Hal Canary41248072019-07-11 16:32:53 -040070 bool onAnimate(double nanos) override {
Robert Phillips6e1fca42016-12-01 12:42:43 -050071 if (0.0f != fLastTime) {
72 for (int i = 0; i < kNumNodes; ++i) {
Hal Canary41248072019-07-11 16:32:53 -040073 fNodes[i].update(nanos, fLastTime);
Robert Phillips6e1fca42016-12-01 12:42:43 -050074 }
75 }
76
Hal Canary41248072019-07-11 16:32:53 -040077 fLastTime = 1e-9 * nanos;
Robert Phillips6e1fca42016-12-01 12:42:43 -050078 return true;
79 }
80
81private:
82 class Node {
83 public:
84 Node()
85 : fSize(0.0f)
86 , fPos { 0.0f, 0.0f }
87 , fDir { 1.0f, 0.0f }
88 , fBlurOffset(0.0f)
89 , fBlur(fBlurOffset)
90 , fSpeed(0.0f) {
91 }
92
93 void init(SkRandom* rand) {
94 fSize = rand->nextRangeF(10.0f, 60.f);
95 fPos.fX = rand->nextRangeF(fSize, kWidth - fSize);
96 fPos.fY = rand->nextRangeF(fSize, kHeight - fSize);
97 fDir.fX = rand->nextRangeF(-1.0f, 1.0f);
98 fDir.fY = SkScalarSqrt(1.0f - fDir.fX * fDir.fX);
99 if (rand->nextBool()) {
100 fDir.fY = -fDir.fY;
101 }
102 fBlurOffset = rand->nextRangeF(0.0f, kBlurMax);
103 fBlur = fBlurOffset;
104 fSpeed = rand->nextRangeF(20.0f, 60.0f);
105 }
106
Hal Canary41248072019-07-11 16:32:53 -0400107 void update(double nanos, SkScalar lastTime) {
108 SkScalar deltaTime = 1e-9 * nanos - lastTime;
Robert Phillips6e1fca42016-12-01 12:42:43 -0500109
110 fPos.fX += deltaTime * fSpeed * fDir.fX;
111 fPos.fY += deltaTime * fSpeed * fDir.fY;
112 if (fPos.fX >= kWidth || fPos.fX < 0.0f) {
113 fPos.fX = SkTPin<SkScalar>(fPos.fX, 0.0f, kWidth);
114 fDir.fX = -fDir.fX;
115 }
116 if (fPos.fY >= kHeight || fPos.fY < 0.0f) {
117 fPos.fY = SkTPin<SkScalar>(fPos.fY, 0.0f, kHeight);
118 fDir.fY = -fDir.fY;
119 }
120
Hal Canary41248072019-07-11 16:32:53 -0400121 fBlur = TimeUtils::PingPong(1e-9 * nanos, kBlurAnimationDuration, fBlurOffset, 0.0f, kBlurMax);
Robert Phillips6e1fca42016-12-01 12:42:43 -0500122 }
123
124 SkScalar sigma() const { return fBlur; }
125 const SkPoint& pos() const { return fPos; }
126 SkScalar size() const { return fSize; }
127
128 private:
129 SkScalar fSize;
130 SkPoint fPos;
131 SkVector fDir;
132 SkScalar fBlurOffset;
133 SkScalar fBlur;
134 SkScalar fSpeed;
135 };
136
137 Node fNodes[kNumNodes];
138 SkRandom fRand;
139 SkScalar fLastTime;
140
141 typedef GM INHERITED;
142};
143
144//////////////////////////////////////////////////////////////////////////////
145
146DEF_GM(return new AnimatedImageBlurs;)