• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #include "gm.h"
9 #include "SkAnimTimer.h"
10 #include "SkBlurImageFilter.h"
11 #include "SkRandom.h"
12 #include "SkRRect.h"
13 
14 static const SkScalar kBlurMax = 7.0f;
15 static const int kNumNodes = 30;
16 static const int kWidth = 512;
17 static const int kHeight = 512;
18 static const SkScalar kBlurAnimationDuration = 4.0f; // in secs
19 
20 // This GM draws a lot of layers with animating BlurImageFilters
21 class AnimatedImageBlurs : public skiagm::GM {
22 public:
AnimatedImageBlurs()23     AnimatedImageBlurs() : fLastTime(0.0f) {
24         this->setBGColor(0xFFCCCCCC);
25     }
26 
27 protected:
runAsBench() const28     bool runAsBench() const override { return true; }
29 
onShortName()30     SkString onShortName() override { return SkString("animated-image-blurs"); }
31 
onISize()32     SkISize onISize() override { return SkISize::Make(kWidth, kHeight); }
33 
onOnceBeforeDraw()34     void onOnceBeforeDraw() override {
35         for (int i = 0; i < kNumNodes; ++i) {
36             fNodes[i].init(&fRand);
37         }
38     }
39 
onDraw(SkCanvas * canvas)40     void onDraw(SkCanvas* canvas) override {
41         SkPaint paint;
42         paint.setAntiAlias(true);
43 
44         for (int i = 0; i < kNumNodes; ++i) {
45             SkPaint layerPaint;
46             layerPaint.setImageFilter(SkBlurImageFilter::Make(fNodes[i].sigma(),
47                                                               fNodes[i].sigma(),
48                                                               nullptr));
49 
50             canvas->saveLayer(nullptr, &layerPaint);
51                 // The rect is outset to block the circle case
52                 SkRect rect = SkRect::MakeLTRB(fNodes[i].pos().fX - fNodes[i].size()-0.5f,
53                                                fNodes[i].pos().fY - fNodes[i].size()-0.5f,
54                                                fNodes[i].pos().fX + fNodes[i].size()+0.5f,
55                                                fNodes[i].pos().fY + fNodes[i].size()+0.5f);
56                 SkRRect rrect = SkRRect::MakeRectXY(rect, fNodes[i].size(), fNodes[i].size());
57                 canvas->drawRRect(rrect, paint);
58             canvas->restore();
59         }
60     }
61 
onAnimate(const SkAnimTimer & timer)62     bool onAnimate(const SkAnimTimer& timer) override {
63         if (0.0f != fLastTime) {
64             for (int i = 0; i < kNumNodes; ++i) {
65                 fNodes[i].update(timer, fLastTime);
66             }
67         }
68 
69         fLastTime = timer.secs();
70         return true;
71     }
72 
73 private:
74     class Node {
75     public:
Node()76         Node()
77             : fSize(0.0f)
78             , fPos { 0.0f, 0.0f }
79             , fDir { 1.0f, 0.0f }
80             , fBlurOffset(0.0f)
81             , fBlur(fBlurOffset)
82             , fSpeed(0.0f) {
83         }
84 
init(SkRandom * rand)85         void init(SkRandom* rand) {
86             fSize = rand->nextRangeF(10.0f, 60.f);
87             fPos.fX = rand->nextRangeF(fSize, kWidth - fSize);
88             fPos.fY = rand->nextRangeF(fSize, kHeight - fSize);
89             fDir.fX = rand->nextRangeF(-1.0f, 1.0f);
90             fDir.fY = SkScalarSqrt(1.0f - fDir.fX * fDir.fX);
91             if (rand->nextBool()) {
92                 fDir.fY = -fDir.fY;
93             }
94             fBlurOffset = rand->nextRangeF(0.0f, kBlurMax);
95             fBlur = fBlurOffset;
96             fSpeed = rand->nextRangeF(20.0f, 60.0f);
97         }
98 
update(const SkAnimTimer & timer,SkScalar lastTime)99         void update(const SkAnimTimer& timer, SkScalar lastTime) {
100 
101             SkScalar deltaTime = timer.secs() - lastTime;
102 
103             fPos.fX += deltaTime * fSpeed * fDir.fX;
104             fPos.fY += deltaTime * fSpeed * fDir.fY;
105             if (fPos.fX >= kWidth || fPos.fX < 0.0f) {
106                 fPos.fX = SkTPin<SkScalar>(fPos.fX, 0.0f, kWidth);
107                 fDir.fX = -fDir.fX;
108             }
109             if (fPos.fY >= kHeight || fPos.fY < 0.0f) {
110                 fPos.fY = SkTPin<SkScalar>(fPos.fY, 0.0f, kHeight);
111                 fDir.fY = -fDir.fY;
112             }
113 
114             fBlur = timer.pingPong(kBlurAnimationDuration, fBlurOffset, 0.0f, kBlurMax);
115         }
116 
sigma() const117         SkScalar sigma() const { return fBlur; }
pos() const118         const SkPoint& pos() const { return fPos; }
size() const119         SkScalar size() const { return fSize; }
120 
121     private:
122         SkScalar fSize;
123         SkPoint  fPos;
124         SkVector fDir;
125         SkScalar fBlurOffset;
126         SkScalar fBlur;
127         SkScalar fSpeed;
128     };
129 
130     Node     fNodes[kNumNodes];
131     SkRandom fRand;
132     SkScalar fLastTime;
133 
134     typedef GM INHERITED;
135 };
136 
137 //////////////////////////////////////////////////////////////////////////////
138 
139 DEF_GM(return new AnimatedImageBlurs;)
140