/*
 * Copyright 2017 Google LLC
 *
 * 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/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.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/SkSurface.h"
#include "include/effects/SkImageFilters.h"
#include "tools/ToolUtils.h"

#include <array>
#include <initializer_list>
#include <utility>

static sk_sp<SkImage> make_image(SkCanvas* canvas, int direction) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(250, 200);
    auto        surface = ToolUtils::makeSurface(canvas, info);
    SkCanvas* c = surface->getCanvas();
    SkPaint paint;
    paint.setAntiAlias(true);

    const auto colors = std::to_array<SkColor>({
            SK_ColorRED,
            SK_ColorBLUE,
            SK_ColorGREEN,
            SK_ColorYELLOW,
            SK_ColorBLACK,
    });

    int width = 25;
    bool xDirection = (direction & 0x1) == 1;
    bool yDirection = (direction & 0x2) == 2;
    if (xDirection) {
        for (int x = 0; x < info.width(); x += width) {
            paint.setColor(colors[x/width % 5]);
            if (yDirection) {
                paint.setAlphaf(0.5f);
            }
            c->drawRect(SkRect::MakeXYWH(x, 0, width, info.height()), paint);
        }
    }

    if (yDirection) {
        for (int y = 0; y < info.height(); y += width) {
            paint.setColor(colors[y/width % 5]);
            if (xDirection) {
                paint.setAlphaf(0.5f);
            }
            c->drawRect(SkRect::MakeXYWH(0, y, info.width(), width), paint);
        }
    }
    return surface->makeImageSnapshot();
}

static void draw_image(SkCanvas* canvas, const sk_sp<SkImage> image, sk_sp<SkImageFilter> filter) {
    SkAutoCanvasRestore acr(canvas, true);
    SkPaint paint;
    paint.setImageFilter(std::move(filter));

    canvas->translate(SkIntToScalar(30), 0);
    canvas->clipIRect(image->bounds());
    canvas->drawImage(image, 0, 0, SkSamplingOptions(), &paint);
}

namespace skiagm {

// This GM draws a colorful grids with different blur settings.
class ImageBlurRepeatModeGM : public GM {
public:
    ImageBlurRepeatModeGM() {
        this->setBGColor(0xFFCCCCCC);
    }

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

    SkISize getISize() override { return SkISize::Make(850, 920); }

    bool runAsBench() const override { return true; }

    void onDraw(SkCanvas* canvas) override {
        sk_sp<SkImage> image[] =
                { make_image(canvas, 1), make_image(canvas, 2), make_image(canvas, 3) };
        sk_sp<SkImageFilter> filter;

        canvas->translate(0, 30);
        // Test different kernel size, including the one to launch 2d Gaussian
        // blur.
        for (auto sigma: { 0.6f, 3.0f, 8.0f, 20.0f }) {
            // FIXME crops
            canvas->save();
            filter = SkImageFilters::Blur(
                    sigma, 0.0f, SkTileMode::kRepeat, nullptr, image[0]->bounds());
            draw_image(canvas, image[0], std::move(filter));
            canvas->translate(image[0]->width() + 20, 0);

            filter = SkImageFilters::Blur(
                    0.0f, sigma, SkTileMode::kRepeat, nullptr, image[1]->bounds());
            draw_image(canvas, image[1], std::move(filter));
            canvas->translate(image[1]->width() + 20, 0);

            filter = SkImageFilters::Blur(
                    sigma, sigma, SkTileMode::kRepeat, nullptr, image[2]->bounds());
            draw_image(canvas, image[2], std::move(filter));
            canvas->translate(image[2]->width() + 20, 0);

            canvas->restore();
            canvas->translate(0, image[0]->height() + 20);
        }
    }

private:
    using INHERITED = GM;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM(return new ImageBlurRepeatModeGM;)
}  // namespace skiagm

// See skbug.com/40039025 for more context, but if the blur doesn't have its own crop rect and
// the canvas is not clipped, repeat can behave strangely (before fixes, this meant:
//  1. The filtered results became semi-transparent when they should have remained opaque.
//  2. The filtered results clip to 3xSigma, which makes sense for the decal tile mode, but not
//     the others.
//  3. The repeat filter interacts non-intuitively when an expanded clip rect intersects the draw
//     geometry (it repeats across the edges of the intersection instead of repeating across the
//     draw and then clipping)).
DEF_SIMPLE_GM(imageblurrepeatunclipped, canvas, 256, 128) {
    // To show translucency
    auto checkerboard = ToolUtils::create_checkerboard_image(256, 128, SK_ColorLTGRAY,
                                                             SK_ColorGRAY, 8);
    canvas->drawImage(checkerboard, 0, 0);

    // Make an image with one red and one blue band
    SkBitmap bmp;
    bmp.allocN32Pixels(100, 20);
    bmp.eraseArea(SkIRect::MakeWH(100, 10), SK_ColorRED);
    bmp.eraseArea(SkIRect::MakeXYWH(0, 10, 100, 10), SK_ColorBLUE);

    auto img = bmp.asImage();
    // The blur filter uses a repeat crop applied to the image bounds to define the tiling geometry,
    // but the crop IF is created directly since the tilemode factory for ::Blur also adds a kDecal
    // post-crop that is undesired for this GM.
    auto filter = SkImageFilters::Blur(0, 10,
            SkImageFilters::Crop(SkRect::Make(img->bounds()), SkTileMode::kRepeat, nullptr));
    SkPaint paint;
    paint.setImageFilter(std::move(filter));

    // Draw the blurred image once with a clip that shows the repeat is tiled several times.
    // 3xsigma is used to match the historic, but underspecified behavior for when kRepeat was used
    // with no crop rect (which must now be provided or kRepeat is ignored).
    canvas->translate(0, 50);
    canvas->save();
        canvas->clipIRect(img->bounds().makeOutset(0, 30));
        canvas->drawImage(img, 0, 0, SkSamplingOptions(), &paint);
    canvas->restore();

    // Draw the blurred image with a clip positioned such that the draw would be excluded except
    // that the image filter causes it to intersect with the clip. It should look like the
    // left image, but clipped to the debug-black rectangle.
    canvas->translate(110, 0);
    canvas->save();
        canvas->clipIRect(SkIRect::MakeXYWH(0, -30, 100, 10));
        canvas->drawImage(img, 0, 0, SkSamplingOptions(), &paint);
    canvas->restore();

    // Visualize the clip
    SkPaint line;
    line.setStyle(SkPaint::kStroke_Style);
    canvas->drawRect(SkRect::MakeXYWH(0, -30, 99, 9), line);
}
