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