/*
 * 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 "gm/gm.h"
#include "include/core/SkBlurTypes.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkPaint.h"
#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"
#include "src/core/SkBlurMask.h"

#include <array>

// This GM tests out the quick reject bounds of the blur mask filter. It draws
// four blurred rects around a central clip. The blurred rect geometry outset
// by the blur radius does not overlap the clip rect so, if the blur clipping
// just uses the radius, they will be clipped out (and the result will differ
// from the result if quick reject were disabled. If the blur clipping uses
// the correct 3 sigma bound then the images with and without quick rejecting
// will be the same.
class BlurQuickRejectGM : public skiagm::GM {
public:
    BlurQuickRejectGM() {}

protected:
    SkString getName() const override { return SkString("blurquickreject"); }

    SkISize getISize() override { return SkISize::Make(kWidth, kHeight); }

    void onDraw(SkCanvas* canvas) override {
        constexpr SkScalar kBlurRadius = SkIntToScalar(20);
        constexpr SkScalar kBoxSize = SkIntToScalar(100);

        SkRect clipRect = SkRect::MakeXYWH(0, 0, kBoxSize, kBoxSize);
        auto blurRects = std::to_array<SkRect>({
                SkRect{-kBoxSize - (kBlurRadius + 1), 0, -(kBlurRadius + 1), kBoxSize},
                SkRect{0, -kBoxSize - (kBlurRadius + 1), kBoxSize, -(kBlurRadius + 1)},
                SkRect{kBoxSize + kBlurRadius + 1, 0, 2 * kBoxSize + kBlurRadius + 1, kBoxSize},
                SkRect{0, kBoxSize + kBlurRadius + 1, kBoxSize, 2 * kBoxSize + kBlurRadius + 1}
        });
        auto colors = std::to_array<SkColor>({
                SK_ColorRED,
                SK_ColorGREEN,
                SK_ColorBLUE,
                SK_ColorYELLOW,
        });
        SkASSERT(std::size(colors) == std::size(blurRects));

        SkPaint hairlinePaint;
        hairlinePaint.setStyle(SkPaint::kStroke_Style);
        hairlinePaint.setColor(SK_ColorWHITE);
        hairlinePaint.setStrokeWidth(0);

        SkPaint blurPaint;
        blurPaint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
                                                    SkBlurMask::ConvertRadiusToSigma(kBlurRadius)));

        canvas->clear(SK_ColorBLACK);
        canvas->save();
        canvas->translate(kBoxSize, kBoxSize);
        canvas->drawRect(clipRect, hairlinePaint);
        canvas->clipRect(clipRect);
        for (size_t i = 0; i < std::size(blurRects); ++i) {
            blurPaint.setColor(colors[i]);
            canvas->drawRect(blurRects[i], blurPaint);
            canvas->drawRect(blurRects[i], hairlinePaint);
        }
        canvas->restore();
    }

private:
    inline static constexpr int kWidth = 300;
    inline static constexpr int kHeight = 300;

    using INHERITED = GM;
};

DEF_GM( return new BlurQuickRejectGM(); )
