/*
 * Copyright 2017 Google LLC
 *
 * Use of this source code is governed by a BD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkBlurTypes.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "src/core/SkBlurMask.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"

// This GM tests out the SkBlurMaskFilter's kIgnoreTransform flag. That flag causes the blur mask
// filter to not apply the CTM to the blur's radius.
class BlurIgnoreXformGM : public skiagm::GM {
public:
    enum class DrawType {
        kCircle,
        kRect,
        kRRect,
    };

    BlurIgnoreXformGM(DrawType drawType) : fDrawType(drawType) { }

protected:
    bool runAsBench() const override { return true; }

    SkString getName() const override {
        SkString name;
        name.printf("blur_ignore_xform_%s",
                    DrawType::kCircle == fDrawType ? "circle"
                        : DrawType::kRect == fDrawType ? "rect" : "rrect");
        return name;
    }

    SkISize getISize() override { return SkISize::Make(375, 475); }

    void onOnceBeforeDraw() override {
        for (int i = 0; i < kNumBlurs; ++i) {
            fBlurFilters[i] = SkMaskFilter::MakeBlur(
                                    kNormal_SkBlurStyle,
                                    SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(20)),
                                    kBlurFlags[i].fRespectCTM);
        }
    }

    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;
        paint.setColor(SK_ColorBLACK);
        paint.setAntiAlias(true);

        canvas->translate(10, 25);
        canvas->save();
        canvas->translate(80, 0);
        for (size_t i = 0; i < kNumBlurs; ++i) {
            SkAutoCanvasRestore autoRestore(canvas, true);
            canvas->translate(SkIntToScalar(i * 150), 0);
            for (auto scale : kMatrixScales) {
                canvas->save();
                canvas->scale(scale.fScale, scale.fScale);
                static const SkScalar kRadius = 20.0f;
                SkScalar coord = 50.0f * 1.0f / scale.fScale;
                SkRect rect = SkRect::MakeXYWH(coord - kRadius , coord - kRadius,
                                               2 * kRadius, 2 * kRadius);
                SkRRect rrect = SkRRect::MakeRectXY(rect, kRadius/2.0f, kRadius/2.0f);

                paint.setMaskFilter(fBlurFilters[i]);
                for (int j = 0; j < 2; ++j) {
                    canvas->save();
                    canvas->translate(10 * (1 - j), 10 * (1 - j));
                    if (DrawType::kCircle == fDrawType) {
                        canvas->drawCircle(coord, coord, kRadius, paint);
                    } else if (DrawType::kRect == fDrawType) {
                        canvas->drawRect(rect, paint);
                    } else {
                        canvas->drawRRect(rrect, paint);
                    }
                    paint.setMaskFilter(nullptr);
                    canvas->restore();
                }
                canvas->restore();
                canvas->translate(0, SkIntToScalar(150));
            }
        }
        canvas->restore();
        if (kBench_Mode != this->getMode()) {
            this->drawOverlay(canvas);
        }
    }

    void drawOverlay(SkCanvas* canvas) {
        canvas->translate(10, 0);
        SkFont font = ToolUtils::DefaultPortableFont();
        canvas->save();
        for (int i = 0; i < kNumBlurs; ++i) {
            canvas->drawString(kBlurFlags[i].fName, 100, 0, font, SkPaint());
            canvas->translate(SkIntToScalar(130), 0);
        }
        canvas->restore();
        for (auto scale : kMatrixScales) {
            canvas->drawString(scale.fName, 0, 50, font, SkPaint());
            canvas->translate(0, SkIntToScalar(150));
        }
    }

private:
    inline static constexpr int kNumBlurs = 2;

    static const struct BlurFlags {
        bool fRespectCTM;
        const char* fName;
    } kBlurFlags[kNumBlurs];

    static const struct MatrixScale {
        float fScale;
        const char* fName;
    } kMatrixScales[3];

    DrawType fDrawType;
    sk_sp<SkMaskFilter> fBlurFilters[kNumBlurs];

    using INHERITED =         skiagm::GM;
};

const BlurIgnoreXformGM::BlurFlags BlurIgnoreXformGM::kBlurFlags[] = {
    {true, "none"},
    {false, "IgnoreTransform"}
};

const BlurIgnoreXformGM::MatrixScale BlurIgnoreXformGM::kMatrixScales[] = {
    {1.0f, "Identity"},
    {0.5f, "Scale = 0.5"},
    {2.0f, "Scale = 2.0"}
};

DEF_GM(return new BlurIgnoreXformGM(BlurIgnoreXformGM::DrawType::kCircle);)
DEF_GM(return new BlurIgnoreXformGM(BlurIgnoreXformGM::DrawType::kRect);)
DEF_GM(return new BlurIgnoreXformGM(BlurIgnoreXformGM::DrawType::kRRect);)
