16e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips/* 26e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips * Copyright 2016 Google Inc. 36e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips * 46e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips * Use of this source code is governed by a BSD-style license that can be 56e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips * found in the LICENSE file. 66e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips */ 76e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 86e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips#include "gm.h" 933d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h" 106e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips#include "SkAnimTimer.h" 116e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips#include "SkBlurImageFilter.h" 126e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips#include "SkRandom.h" 136e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips#include "SkRRect.h" 146e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 156e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipsstatic const SkScalar kBlurMax = 7.0f; 166e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipsstatic const int kNumNodes = 30; 176e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipsstatic const int kWidth = 512; 186e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipsstatic const int kHeight = 512; 196e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipsstatic const SkScalar kBlurAnimationDuration = 4.0f; // in secs 206e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 216e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips// This GM draws a lot of layers with animating BlurImageFilters 226e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipsclass AnimatedImageBlurs : public skiagm::GM { 236e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipspublic: 246e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips AnimatedImageBlurs() : fLastTime(0.0f) { 256e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); 266e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 276e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 286e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipsprotected: 296e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips bool runAsBench() const override { return true; } 306e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 316e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkString onShortName() override { return SkString("animated-image-blurs"); } 326e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 336e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkISize onISize() override { return SkISize::Make(kWidth, kHeight); } 346e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 356e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips void onOnceBeforeDraw() override { 366e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips for (int i = 0; i < kNumNodes; ++i) { 376e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fNodes[i].init(&fRand); 386e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 396e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 406e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 416e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips void onDraw(SkCanvas* canvas) override { 426e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkPaint paint; 436e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips paint.setAntiAlias(true); 446e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 456e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips for (int i = 0; i < kNumNodes; ++i) { 466e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkPaint layerPaint; 476e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips layerPaint.setImageFilter(SkBlurImageFilter::Make(fNodes[i].sigma(), 486e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fNodes[i].sigma(), 496e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips nullptr)); 506e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 516e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips canvas->saveLayer(nullptr, &layerPaint); 526e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips // The rect is outset to block the circle case 536e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkRect rect = SkRect::MakeLTRB(fNodes[i].pos().fX - fNodes[i].size()-0.5f, 546e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fNodes[i].pos().fY - fNodes[i].size()-0.5f, 556e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fNodes[i].pos().fX + fNodes[i].size()+0.5f, 566e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fNodes[i].pos().fY + fNodes[i].size()+0.5f); 576e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkRRect rrect = SkRRect::MakeRectXY(rect, fNodes[i].size(), fNodes[i].size()); 586e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips canvas->drawRRect(rrect, paint); 596e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips canvas->restore(); 606e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 616e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 626e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 636e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips bool onAnimate(const SkAnimTimer& timer) override { 646e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips if (0.0f != fLastTime) { 656e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips for (int i = 0; i < kNumNodes; ++i) { 666e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fNodes[i].update(timer, fLastTime); 676e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 686e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 696e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 706e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fLastTime = timer.secs(); 716e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips return true; 726e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 736e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 746e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillipsprivate: 756e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips class Node { 766e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips public: 776e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips Node() 786e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips : fSize(0.0f) 796e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips , fPos { 0.0f, 0.0f } 806e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips , fDir { 1.0f, 0.0f } 816e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips , fBlurOffset(0.0f) 826e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips , fBlur(fBlurOffset) 836e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips , fSpeed(0.0f) { 846e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 856e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 866e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips void init(SkRandom* rand) { 876e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fSize = rand->nextRangeF(10.0f, 60.f); 886e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fPos.fX = rand->nextRangeF(fSize, kWidth - fSize); 896e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fPos.fY = rand->nextRangeF(fSize, kHeight - fSize); 906e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fDir.fX = rand->nextRangeF(-1.0f, 1.0f); 916e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fDir.fY = SkScalarSqrt(1.0f - fDir.fX * fDir.fX); 926e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips if (rand->nextBool()) { 936e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fDir.fY = -fDir.fY; 946e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 956e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fBlurOffset = rand->nextRangeF(0.0f, kBlurMax); 966e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fBlur = fBlurOffset; 976e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fSpeed = rand->nextRangeF(20.0f, 60.0f); 986e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 996e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1006e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips void update(const SkAnimTimer& timer, SkScalar lastTime) { 1016e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1026e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkScalar deltaTime = timer.secs() - lastTime; 1036e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1046e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fPos.fX += deltaTime * fSpeed * fDir.fX; 1056e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fPos.fY += deltaTime * fSpeed * fDir.fY; 1066e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips if (fPos.fX >= kWidth || fPos.fX < 0.0f) { 1076e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fPos.fX = SkTPin<SkScalar>(fPos.fX, 0.0f, kWidth); 1086e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fDir.fX = -fDir.fX; 1096e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 1106e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips if (fPos.fY >= kHeight || fPos.fY < 0.0f) { 1116e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fPos.fY = SkTPin<SkScalar>(fPos.fY, 0.0f, kHeight); 1126e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fDir.fY = -fDir.fY; 1136e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 1146e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1156e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips fBlur = timer.pingPong(kBlurAnimationDuration, fBlurOffset, 0.0f, kBlurMax); 1166e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips } 1176e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1186e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkScalar sigma() const { return fBlur; } 1196e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips const SkPoint& pos() const { return fPos; } 1206e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkScalar size() const { return fSize; } 1216e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1226e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips private: 1236e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkScalar fSize; 1246e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkPoint fPos; 1256e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkVector fDir; 1266e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkScalar fBlurOffset; 1276e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkScalar fBlur; 1286e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkScalar fSpeed; 1296e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips }; 1306e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1316e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips Node fNodes[kNumNodes]; 1326e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkRandom fRand; 1336e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips SkScalar fLastTime; 1346e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1356e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips typedef GM INHERITED; 1366e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips}; 1376e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1386e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips////////////////////////////////////////////////////////////////////////////// 1396e1fca43b4e7d326d202e6672170e767c0017e9dRobert Phillips 1406e1fca43b4e7d326d202e6672170e767c0017e9dRobert PhillipsDEF_GM(return new AnimatedImageBlurs;) 141