| /* | 
 |  * Copyright 2013 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "Benchmark.h" | 
 | #include "SkCanvas.h" | 
 | #include "SkLayerDrawLooper.h" | 
 | #include "SkMaskFilter.h" | 
 | #include "SkPaint.h" | 
 | #include "SkPath.h" | 
 | #include "SkRandom.h" | 
 |  | 
 | // This bench replicates a problematic use case of a draw looper used | 
 | // to create an inner blurred rect | 
 | class RectoriBench : public Benchmark { | 
 | public: | 
 |     RectoriBench() {} | 
 |  | 
 | protected: | 
 |  | 
 |     const char* onGetName() override { | 
 |         return "rectori"; | 
 |     } | 
 |  | 
 |     void onDraw(int loops, SkCanvas* canvas) override { | 
 |         SkRandom Random; | 
 |  | 
 |         for (int i = 0; i < loops; i++) { | 
 |             SkScalar blurSigma = Random.nextRangeScalar(1.5f, 25.0f); | 
 |             SkScalar size = Random.nextRangeScalar(20*blurSigma, 50*blurSigma); | 
 |  | 
 |             SkScalar x = Random.nextRangeScalar(0.0f, W - size); | 
 |             SkScalar y = Random.nextRangeScalar(0.0f, H - size); | 
 |  | 
 |             SkRect inner = { x, y, x + size, y + size }; | 
 |  | 
 |             SkRect outer(inner); | 
 |             // outer is always outset either 2x or 4x the blur radius (we go with 2x) | 
 |             outer.outset(2*blurSigma, 2*blurSigma); | 
 |  | 
 |             SkPath p; | 
 |  | 
 |             p.addRect(outer); | 
 |             p.addRect(inner); | 
 |             p.setFillType(SkPath::kEvenOdd_FillType); | 
 |  | 
 |             // This will be used to translate the normal draw outside the | 
 |             // clip rect and translate the blurred version back inside | 
 |             SkScalar translate = 2.0f * size; | 
 |  | 
 |             SkPaint paint; | 
 |             paint.setLooper(this->createLooper(-translate, blurSigma)); | 
 |             paint.setColor(0xff000000 | Random.nextU()); | 
 |             paint.setAntiAlias(true); | 
 |  | 
 |             canvas->save(); | 
 |             // clip always equals inner rect so we get the inside blur | 
 |             canvas->clipRect(inner); | 
 |             canvas->translate(translate, 0); | 
 |             canvas->drawPath(p, paint); | 
 |             canvas->restore(); | 
 |         } | 
 |     } | 
 |  | 
 | private: | 
 |     enum { | 
 |         W = 640, | 
 |         H = 480, | 
 |     }; | 
 |  | 
 |     sk_sp<SkDrawLooper> createLooper(SkScalar xOff, SkScalar sigma) { | 
 |         SkLayerDrawLooper::Builder looperBuilder; | 
 |  | 
 |         //----------------------------------------------- | 
 |         SkLayerDrawLooper::LayerInfo info; | 
 |  | 
 |         // TODO: add a color filter to better match what is seen in the wild | 
 |         info.fPaintBits = /* SkLayerDrawLooper::kColorFilter_Bit |*/ | 
 |                           SkLayerDrawLooper::kMaskFilter_Bit; | 
 |         info.fColorMode = SkBlendMode::kDst; | 
 |         info.fOffset.set(xOff, 0); | 
 |         info.fPostTranslate = false; | 
 |  | 
 |         SkPaint* paint = looperBuilder.addLayer(info); | 
 |  | 
 |         paint->setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma)); | 
 |  | 
 |         //----------------------------------------------- | 
 |         info.fPaintBits = 0; | 
 |         info.fOffset.set(0, 0); | 
 |  | 
 |         paint = looperBuilder.addLayer(info); | 
 |         return looperBuilder.detach(); | 
 |     } | 
 |  | 
 |     typedef Benchmark INHERITED; | 
 | }; | 
 |  | 
 | DEF_BENCH(return new RectoriBench();) |