1/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9#include "sk_tool_utils.h"
10
11#include "SkBlurMask.h"
12#include "SkBlurMaskFilter.h"
13#include "SkCanvas.h"
14#include "SkPaint.h"
15
16// This GM tests out the SkBlurMaskFilter's kIgnoreTransform flag. That flag causes the blur mask
17// filter to not apply the CTM to the blur's radius.
18class BlurIgnoreXformGM : public skiagm::GM {
19public:
20    enum class DrawType {
21        kCircle,
22        kRect,
23        kRRect,
24    };
25
26    BlurIgnoreXformGM(DrawType drawType) : fDrawType(drawType) { }
27
28protected:
29    bool runAsBench() const override { return true; }
30
31    SkString onShortName() override {
32        SkString name;
33        name.printf("blur_ignore_xform_%s",
34                    DrawType::kCircle == fDrawType ? "circle"
35                        : DrawType::kRect == fDrawType ? "rect" : "rrect");
36        return name;
37    }
38
39    SkISize onISize() override {
40        return SkISize::Make(375, 475);
41    }
42
43    void onOnceBeforeDraw() override {
44        for (int i = 0; i < kNumBlurs; ++i) {
45            fBlurFilters[i] = SkBlurMaskFilter::Make(
46                                    kNormal_SkBlurStyle,
47                                    SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(20)),
48                                    SkBlurMaskFilter::kHighQuality_BlurFlag | kBlurFlags[i].fFlags);
49        }
50    }
51
52    void onDraw(SkCanvas* canvas) override {
53        SkPaint paint;
54        paint.setColor(SK_ColorBLACK);
55        paint.setAntiAlias(true);
56
57        canvas->translate(10, 25);
58        canvas->save();
59        canvas->translate(80, 0);
60        for (size_t i = 0; i < kNumBlurs; ++i) {
61            SkAutoCanvasRestore autoRestore(canvas, true);
62            canvas->translate(SkIntToScalar(i * 150), 0);
63            for (auto scale : kMatrixScales) {
64                canvas->save();
65                canvas->scale(scale.fScale, scale.fScale);
66                static const SkScalar kRadius = 20.0f;
67                SkScalar coord = 50.0f * 1.0f / scale.fScale;
68                SkRect rect = SkRect::MakeXYWH(coord - kRadius , coord - kRadius,
69                                               2 * kRadius, 2 * kRadius);
70                SkRRect rrect = SkRRect::MakeRectXY(rect, kRadius/2.0f, kRadius/2.0f);
71
72                paint.setMaskFilter(fBlurFilters[i]);
73                for (int j = 0; j < 2; ++j) {
74                    canvas->save();
75                    canvas->translate(10 * (1 - j), 10 * (1 - j));
76                    if (DrawType::kCircle == fDrawType) {
77                        canvas->drawCircle(coord, coord, kRadius, paint);
78                    } else if (DrawType::kRect == fDrawType) {
79                        canvas->drawRect(rect, paint);
80                    } else {
81                        canvas->drawRRect(rrect, paint);
82                    }
83                    paint.setMaskFilter(nullptr);
84                    canvas->restore();
85                }
86                canvas->restore();
87                canvas->translate(0, SkIntToScalar(150));
88            }
89        }
90        canvas->restore();
91        if (kBench_Mode != this->getMode()) {
92            this->drawOverlay(canvas);
93        }
94    }
95
96    void drawOverlay(SkCanvas* canvas) {
97        canvas->translate(10, 0);
98        SkPaint textPaint;
99        sk_tool_utils::set_portable_typeface(&textPaint);
100        textPaint.setAntiAlias(true);
101        canvas->save();
102        for (int i = 0; i < kNumBlurs; ++i) {
103            canvas->drawString(kBlurFlags[i].fName, 100, 0, textPaint);
104            canvas->translate(SkIntToScalar(130), 0);
105        }
106        canvas->restore();
107        for (auto scale : kMatrixScales) {
108            canvas->drawString(scale.fName, 0, 50, textPaint);
109            canvas->translate(0, SkIntToScalar(150));
110        }
111    }
112
113private:
114    static constexpr int kNumBlurs = 2;
115
116    static const struct BlurFlags {
117        uint32_t fFlags;
118        const char* fName;
119    } kBlurFlags[kNumBlurs];
120
121    static const struct MatrixScale {
122        float fScale;
123        const char* fName;
124    } kMatrixScales[3];
125
126    DrawType fDrawType;
127    sk_sp<SkMaskFilter> fBlurFilters[kNumBlurs];
128
129    typedef         skiagm::GM INHERITED;
130};
131
132const BlurIgnoreXformGM::BlurFlags BlurIgnoreXformGM::kBlurFlags[] = {
133    {0, "none"},
134    {SkBlurMaskFilter::kIgnoreTransform_BlurFlag, "IgnoreTransform"}
135};
136
137const BlurIgnoreXformGM::MatrixScale BlurIgnoreXformGM::kMatrixScales[] = {
138    {1.0f, "Identity"},
139    {0.5f, "Scale = 0.5"},
140    {2.0f, "Scale = 2.0"}
141};
142
143DEF_GM(return new BlurIgnoreXformGM(BlurIgnoreXformGM::DrawType::kCircle);)
144DEF_GM(return new BlurIgnoreXformGM(BlurIgnoreXformGM::DrawType::kRect);)
145DEF_GM(return new BlurIgnoreXformGM(BlurIgnoreXformGM::DrawType::kRRect);)
146
147
148
149