2016-12-01 17:42:43 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "gm/gm.h"
|
2019-04-30 17:44:26 +00:00
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkImageFilter.h"
|
|
|
|
#include "include/core/SkPaint.h"
|
|
|
|
#include "include/core/SkPoint.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkRRect.h"
|
2019-04-30 17:44:26 +00:00
|
|
|
#include "include/core/SkRect.h"
|
|
|
|
#include "include/core/SkScalar.h"
|
|
|
|
#include "include/core/SkSize.h"
|
|
|
|
#include "include/core/SkString.h"
|
|
|
|
#include "include/core/SkTypes.h"
|
2019-08-02 19:21:23 +00:00
|
|
|
#include "include/effects/SkImageFilters.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/utils/SkRandom.h"
|
2019-07-11 20:32:53 +00:00
|
|
|
#include "tools/timer/TimeUtils.h"
|
2016-12-01 17:42:43 +00:00
|
|
|
|
|
|
|
static const SkScalar kBlurMax = 7.0f;
|
|
|
|
static const int kNumNodes = 30;
|
|
|
|
static const int kWidth = 512;
|
|
|
|
static const int kHeight = 512;
|
|
|
|
static const SkScalar kBlurAnimationDuration = 4.0f; // in secs
|
|
|
|
|
|
|
|
// This GM draws a lot of layers with animating BlurImageFilters
|
|
|
|
class AnimatedImageBlurs : public skiagm::GM {
|
|
|
|
public:
|
|
|
|
AnimatedImageBlurs() : fLastTime(0.0f) {
|
2018-08-16 14:17:03 +00:00
|
|
|
this->setBGColor(0xFFCCCCCC);
|
2016-12-01 17:42:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool runAsBench() const override { return true; }
|
|
|
|
|
|
|
|
SkString onShortName() override { return SkString("animated-image-blurs"); }
|
|
|
|
|
|
|
|
SkISize onISize() override { return SkISize::Make(kWidth, kHeight); }
|
|
|
|
|
|
|
|
void onOnceBeforeDraw() override {
|
|
|
|
for (int i = 0; i < kNumNodes; ++i) {
|
|
|
|
fNodes[i].init(&fRand);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setAntiAlias(true);
|
|
|
|
|
|
|
|
for (int i = 0; i < kNumNodes; ++i) {
|
|
|
|
SkPaint layerPaint;
|
2019-08-02 19:21:23 +00:00
|
|
|
layerPaint.setImageFilter(SkImageFilters::Blur(fNodes[i].sigma(), fNodes[i].sigma(),
|
|
|
|
nullptr));
|
2016-12-01 17:42:43 +00:00
|
|
|
|
|
|
|
canvas->saveLayer(nullptr, &layerPaint);
|
|
|
|
// The rect is outset to block the circle case
|
|
|
|
SkRect rect = SkRect::MakeLTRB(fNodes[i].pos().fX - fNodes[i].size()-0.5f,
|
|
|
|
fNodes[i].pos().fY - fNodes[i].size()-0.5f,
|
|
|
|
fNodes[i].pos().fX + fNodes[i].size()+0.5f,
|
|
|
|
fNodes[i].pos().fY + fNodes[i].size()+0.5f);
|
|
|
|
SkRRect rrect = SkRRect::MakeRectXY(rect, fNodes[i].size(), fNodes[i].size());
|
|
|
|
canvas->drawRRect(rrect, paint);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-11 20:32:53 +00:00
|
|
|
bool onAnimate(double nanos) override {
|
2016-12-01 17:42:43 +00:00
|
|
|
if (0.0f != fLastTime) {
|
|
|
|
for (int i = 0; i < kNumNodes; ++i) {
|
2019-07-11 20:32:53 +00:00
|
|
|
fNodes[i].update(nanos, fLastTime);
|
2016-12-01 17:42:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-11 20:32:53 +00:00
|
|
|
fLastTime = 1e-9 * nanos;
|
2016-12-01 17:42:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
class Node {
|
|
|
|
public:
|
|
|
|
Node()
|
|
|
|
: fSize(0.0f)
|
|
|
|
, fPos { 0.0f, 0.0f }
|
|
|
|
, fDir { 1.0f, 0.0f }
|
|
|
|
, fBlurOffset(0.0f)
|
|
|
|
, fBlur(fBlurOffset)
|
|
|
|
, fSpeed(0.0f) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void init(SkRandom* rand) {
|
|
|
|
fSize = rand->nextRangeF(10.0f, 60.f);
|
|
|
|
fPos.fX = rand->nextRangeF(fSize, kWidth - fSize);
|
|
|
|
fPos.fY = rand->nextRangeF(fSize, kHeight - fSize);
|
|
|
|
fDir.fX = rand->nextRangeF(-1.0f, 1.0f);
|
|
|
|
fDir.fY = SkScalarSqrt(1.0f - fDir.fX * fDir.fX);
|
|
|
|
if (rand->nextBool()) {
|
|
|
|
fDir.fY = -fDir.fY;
|
|
|
|
}
|
|
|
|
fBlurOffset = rand->nextRangeF(0.0f, kBlurMax);
|
|
|
|
fBlur = fBlurOffset;
|
|
|
|
fSpeed = rand->nextRangeF(20.0f, 60.0f);
|
|
|
|
}
|
|
|
|
|
2019-07-11 20:32:53 +00:00
|
|
|
void update(double nanos, SkScalar lastTime) {
|
|
|
|
SkScalar deltaTime = 1e-9 * nanos - lastTime;
|
2016-12-01 17:42:43 +00:00
|
|
|
|
|
|
|
fPos.fX += deltaTime * fSpeed * fDir.fX;
|
|
|
|
fPos.fY += deltaTime * fSpeed * fDir.fY;
|
|
|
|
if (fPos.fX >= kWidth || fPos.fX < 0.0f) {
|
|
|
|
fPos.fX = SkTPin<SkScalar>(fPos.fX, 0.0f, kWidth);
|
|
|
|
fDir.fX = -fDir.fX;
|
|
|
|
}
|
|
|
|
if (fPos.fY >= kHeight || fPos.fY < 0.0f) {
|
|
|
|
fPos.fY = SkTPin<SkScalar>(fPos.fY, 0.0f, kHeight);
|
|
|
|
fDir.fY = -fDir.fY;
|
|
|
|
}
|
|
|
|
|
2019-07-11 20:32:53 +00:00
|
|
|
fBlur = TimeUtils::PingPong(1e-9 * nanos, kBlurAnimationDuration, fBlurOffset, 0.0f, kBlurMax);
|
2016-12-01 17:42:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SkScalar sigma() const { return fBlur; }
|
|
|
|
const SkPoint& pos() const { return fPos; }
|
|
|
|
SkScalar size() const { return fSize; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
SkScalar fSize;
|
|
|
|
SkPoint fPos;
|
|
|
|
SkVector fDir;
|
|
|
|
SkScalar fBlurOffset;
|
|
|
|
SkScalar fBlur;
|
|
|
|
SkScalar fSpeed;
|
|
|
|
};
|
|
|
|
|
|
|
|
Node fNodes[kNumNodes];
|
|
|
|
SkRandom fRand;
|
|
|
|
SkScalar fLastTime;
|
|
|
|
|
|
|
|
typedef GM INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
DEF_GM(return new AnimatedImageBlurs;)
|