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/utils/SkRandom.h" 21 #include "tools/timer/TimeUtils.h" 22 23 static const SkScalar kBlurMax = 7.0f; 24 static const int kNumNodes = 30; 25 static const int kWidth = 512; 26 static const int kHeight = 512; 27 static const SkScalar kBlurAnimationDuration = 4.0f; // in secs 28 29 // This GM draws a lot of layers with animating BlurImageFilters 30 class AnimatedImageBlurs : public skiagm::GM { 31 public: AnimatedImageBlurs()32 AnimatedImageBlurs() : fLastTime(0.0f) { 33 this->setBGColor(0xFFCCCCCC); 34 } 35 36 protected: runAsBench() const37 bool runAsBench() const override { return true; } 38 onShortName()39 SkString onShortName() override { return SkString("animated-image-blurs"); } 40 onISize()41 SkISize onISize() override { return SkISize::Make(kWidth, kHeight); } 42 onOnceBeforeDraw()43 void onOnceBeforeDraw() override { 44 for (int i = 0; i < kNumNodes; ++i) { 45 fNodes[i].init(&fRand); 46 } 47 } 48 onDraw(SkCanvas * canvas)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; 55 layerPaint.setImageFilter(SkImageFilters::Blur(fNodes[i].sigma(), fNodes[i].sigma(), 56 nullptr)); 57 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 onAnimate(double nanos)70 bool onAnimate(double nanos) override { 71 if (0.0f != fLastTime) { 72 for (int i = 0; i < kNumNodes; ++i) { 73 fNodes[i].update(nanos, fLastTime); 74 } 75 } 76 77 fLastTime = 1e-9 * nanos; 78 return true; 79 } 80 81 private: 82 class Node { 83 public: Node()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 init(SkRandom * rand)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 update(double nanos,SkScalar lastTime)107 void update(double nanos, SkScalar lastTime) { 108 SkScalar deltaTime = 1e-9 * nanos - lastTime; 109 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 121 fBlur = TimeUtils::PingPong(1e-9 * nanos, kBlurAnimationDuration, fBlurOffset, 0.0f, kBlurMax); 122 } 123 sigma() const124 SkScalar sigma() const { return fBlur; } pos() const125 const SkPoint& pos() const { return fPos; } size() const126 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 146 DEF_GM(return new AnimatedImageBlurs;) 147