/*
 * Copyright 2014 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/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/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkPoint3.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradient.h"
#include "include/effects/SkImageFilters.h"
#include "include/effects/SkPerlinNoiseShader.h"
#include "tools/DecodeUtils.h"
#include "tools/ToolUtils.h"

#include <utility>

#define RESIZE_FACTOR_X SkIntToScalar(2)
#define RESIZE_FACTOR_Y SkIntToScalar(5)

static sk_sp<SkImage> make_gradient_circle(int width, int height) {
    SkScalar x = SkIntToScalar(width / 2);
    SkScalar y = SkIntToScalar(height / 2);
    SkScalar radius = std::min(x, y) * 0.8f;
    auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(width, height)));
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(0x00000000);
    const SkColor4f colors[2] = {SkColors::kWhite, SkColors::kBlack};
    SkPaint paint;
    paint.setShader(SkShaders::RadialGradient({x, y}, radius,
                                              {{colors, {}, SkTileMode::kClamp}, {}}));
    canvas->drawCircle(x, y, radius, paint);
    return surface->makeImageSnapshot();
}

static void draw_clipped_filter(SkCanvas* canvas, sk_sp<SkImageFilter> filter, size_t i,
                                const SkRect& primBounds, const SkRect& clipBounds) {
    SkPaint paint;
    paint.setColor(SK_ColorWHITE);
    paint.setImageFilter(std::move(filter));
    paint.setAntiAlias(true);
    canvas->save();
    canvas->clipRect(clipBounds);
    if (5 == i) {
        canvas->translate(SkIntToScalar(16), SkIntToScalar(-32));
    } else if (6 == i) {
        canvas->scale(SkScalarInvert(RESIZE_FACTOR_X), SkScalarInvert(RESIZE_FACTOR_Y));
    }
    canvas->drawCircle(primBounds.centerX(), primBounds.centerY(),
                       primBounds.width() * 2 / 5, paint);
    canvas->restore();
}

namespace skiagm {

class ImageFiltersClippedGM : public GM {
public:
    ImageFiltersClippedGM() {
        this->setBGColor(0x00000000);
    }

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

    SkISize getISize() override { return SkISize::Make(860, 500); }

    void onOnceBeforeDraw() override {
        fCheckerboard =
                ToolUtils::create_checkerboard_image(64, 64, 0xFFA0A0A0, 0xFF404040, 8);
        fGradientCircle = make_gradient_circle(64, 64);
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->clear(SK_ColorBLACK);

        sk_sp<SkImageFilter> gradient(SkImageFilters::Image(fGradientCircle,
                                                            SkFilterMode::kLinear));
        sk_sp<SkImageFilter> checkerboard(SkImageFilters::Image(fCheckerboard,
                                                                SkFilterMode::kLinear));
        SkMatrix resizeMatrix;
        resizeMatrix.setScale(RESIZE_FACTOR_X, RESIZE_FACTOR_Y);
        SkPoint3 pointLocation = SkPoint3::Make(32, 32, SkIntToScalar(10));

        SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
        sk_sp<SkImageFilter> filters[] = {
            SkImageFilters::Blur(SkIntToScalar(12), SkIntToScalar(12), nullptr),
            SkImageFilters::DropShadow(SkIntToScalar(10), SkIntToScalar(10),
                                       SkIntToScalar(3), SkIntToScalar(3), SK_ColorGREEN, nullptr),
            SkImageFilters::DisplacementMap(SkColorChannel::kR, SkColorChannel::kR,
                                            SkIntToScalar(12), std::move(gradient), checkerboard),
            SkImageFilters::Dilate(2, 2, checkerboard),
            SkImageFilters::Erode(2, 2, checkerboard),
            SkImageFilters::Offset(SkIntToScalar(-16), SkIntToScalar(32), nullptr),
            SkImageFilters::MatrixTransform(resizeMatrix, SkSamplingOptions(), nullptr),
            // Crop output of lighting to the checkerboard
            SkImageFilters::PointLitDiffuse(pointLocation, SK_ColorWHITE, SK_Scalar1,
                                            SkIntToScalar(2), checkerboard, r),
        };

        SkScalar margin = SkIntToScalar(16);
        SkRect bounds = r;
        bounds.outset(margin, margin);

        canvas->save();
        for (int xOffset = 0; xOffset < 80; xOffset += 16) {
            canvas->save();
            bounds.fLeft = SkIntToScalar(xOffset);
            for (size_t i = 0; i < std::size(filters); ++i) {
                draw_clipped_filter(canvas, filters[i], i, r, bounds);
                canvas->translate(r.width() + margin, 0);
            }
            canvas->restore();
            canvas->translate(0, r.height() + margin);
        }
        canvas->restore();

        sk_sp<SkImageFilter> rectFilter(
                SkImageFilters::Shader(SkShaders::MakeFractalNoise(0.1f, 0.05f, 1, 0)));
        canvas->translate(std::size(filters)*(r.width() + margin), 0);
        for (int xOffset = 0; xOffset < 80; xOffset += 16) {
            bounds.fLeft = SkIntToScalar(xOffset);
            draw_clipped_filter(canvas, rectFilter, 0, r, bounds);
            canvas->translate(0, r.height() + margin);
        }
    }

private:
    sk_sp<SkImage> fCheckerboard, fGradientCircle;

    using INHERITED = GM;
};

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

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

DEF_SIMPLE_GM(imagefilter_convolve_subset, canvas, 160, 180) {
    sk_sp<SkImage> reference = ToolUtils::GetResourceAsImage("images/filter_reference.png");
    SkRect crop = SkRect::Make(reference->dimensions()).makeInset(10, 10);
    auto drawFilteredImage = [&](sk_sp<SkImageFilter> filter) {
        SkPaint p;
        p.setImageFilter(std::move(filter));
        canvas->drawImage(reference, 0, 0, {}, &p);
        canvas->translate(0, reference->height());
    };

    {
        float kernel[] = {1.f,  1.f, 1.f,
                          1.f, -7.f, 1.f,
                          1.f,  1.f, 1.f};
        drawFilteredImage(SkImageFilters::MatrixConvolution(
                {3, 3}, kernel, 1.f, 0.3f, {1, 1}, SkTileMode::kClamp, true, nullptr, crop));
    }

    drawFilteredImage(SkImageFilters::Blur(10.f, 10.f, SkTileMode::kMirror, nullptr, crop));
}
