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