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