/*
 * Copyright 2015 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/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.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/SkGradientShader.h"
#include "include/effects/SkImageFilters.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
#include "tools/timer/TimeUtils.h"

#include <utility>

namespace skiagm {

// This GM draws image filters with a CTM containing shearing / rotation.
// It checks that the scale portion of the CTM is correctly extracted
// and applied to the image inputs separately from the non-scale portion.

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(SkSurface::MakeRasterN32Premul(width, height));
    SkCanvas* canvas = surface->getCanvas();

    canvas->clear(0x00000000);
    SkColor colors[2];
    colors[0] = SK_ColorWHITE;
    colors[1] = SK_ColorBLACK;
    SkPaint paint;
    paint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr, 2,
                                                 SkTileMode::kClamp));
    canvas->drawCircle(x, y, radius, paint);

    return surface->makeImageSnapshot();
}

class ImageFiltersTransformedGM : public GM {
public:
    ImageFiltersTransformedGM() {
        this->setBGColor(SK_ColorBLACK);
    }

protected:

    SkString onShortName() override { return SkString("imagefilterstransformed"); }

    SkISize onISize() override { return SkISize::Make(420, 240); }

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

    void onDraw(SkCanvas* canvas) override {
        sk_sp<SkImageFilter> gradient(SkImageFilters::Image(fGradientCircle));
        sk_sp<SkImageFilter> checkerboard(SkImageFilters::Image(fCheckerboard));
        sk_sp<SkImageFilter> filters[] = {
            SkImageFilters::Blur(12, 0, nullptr),
            SkImageFilters::DropShadow(0, 15, 8, 0, SK_ColorGREEN, nullptr),
            SkImageFilters::DisplacementMap(SkColorChannel::kR, SkColorChannel::kR, 12,
                                            std::move(gradient), checkerboard),
            SkImageFilters::Dilate(2, 2, checkerboard),
            SkImageFilters::Erode(2, 2, checkerboard),
        };

        const SkScalar margin = SkIntToScalar(20);
        const SkScalar size = SkIntToScalar(60);

        for (size_t j = 0; j < 3; j++) {
            canvas->save();
            canvas->translate(margin, 0);
            for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
                SkPaint paint;
                paint.setColor(SK_ColorWHITE);
                paint.setImageFilter(filters[i]);
                paint.setAntiAlias(true);
                canvas->save();
                canvas->translate(size * SK_ScalarHalf, size * SK_ScalarHalf);
                canvas->scale(SkDoubleToScalar(0.8), SkDoubleToScalar(0.8));
                if (j == 1) {
                    canvas->rotate(SkIntToScalar(45));
                } else if (j == 2) {
                    canvas->skew(SkDoubleToScalar(0.5), SkDoubleToScalar(0.2));
                }
                canvas->translate(-size * SK_ScalarHalf, -size * SK_ScalarHalf);
                canvas->drawOval(SkRect::MakeXYWH(0, size * SkDoubleToScalar(0.1),
                                                  size, size * SkDoubleToScalar(0.6)), paint);
                canvas->restore();
                canvas->translate(size + margin, 0);
            }
            canvas->restore();
            canvas->translate(0, size + margin);
        }
    }

private:
    sk_sp<SkImage> fCheckerboard;
    sk_sp<SkImage> fGradientCircle;
    using INHERITED = GM;
};
DEF_GM( return new ImageFiltersTransformedGM; )
}  // namespace skiagm

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

DEF_SIMPLE_GM(rotate_imagefilter, canvas, 500, 500) {
    SkPaint paint;

    const SkRect r = SkRect::MakeXYWH(50, 50, 100, 100);

    sk_sp<SkImageFilter> filters[] = {
        nullptr,
        SkImageFilters::Blur(6, 0, nullptr),
        SkImageFilters::Blend(SkBlendMode::kSrcOver, nullptr),
    };

    for (auto& filter : filters) {
        paint.setAntiAlias(false);
        paint.setImageFilter(filter);

        canvas->save();

        canvas->drawRect(r, paint);

        canvas->translate(150, 0);
        canvas->save();
            canvas->rotate(30, 100, 100);
            canvas->drawRect(r, paint);
        canvas->restore();

        paint.setAntiAlias(true);
        canvas->translate(150, 0);
        canvas->save();
            canvas->rotate(30, 100, 100);
            canvas->drawRect(r, paint);
        canvas->restore();

        canvas->restore();
        canvas->translate(0, 150);
    }
}

class ImageFilterMatrixWLocalMatrix : public skiagm::GM {
public:

    // Start at 132 degrees, since that resulted in a skipped draw before the fix to
    // SkLocalMatrixImageFilter's computeFastBounds() function.
    ImageFilterMatrixWLocalMatrix() : fDegrees(132.f) {}

protected:
    SkString onShortName() override {
        return SkString("imagefilter_matrix_localmatrix");
    }

    SkISize onISize() override {
        return SkISize::Make(512, 512);
    }

    bool onAnimate(double nanos) override {
        // Animate the rotation angle to ensure the local matrix bounds modifications work
        // for a variety of transformations.
        fDegrees = TimeUtils::Scaled(1e-9f * nanos, 360.f);
        return true;
    }

    void onOnceBeforeDraw() override {
        fImage = GetResourceAsImage("images/mandrill_256.png");
    }

    void onDraw(SkCanvas* canvas) override {
        SkMatrix localMatrix;
        localMatrix.preTranslate(128, 128);
        localMatrix.preScale(2.0f, 2.0f);

        // This matrix applies a rotate around the center of the image (prior to the simulated
        // hi-dpi 2x device scale).
        SkMatrix filterMatrix;
        filterMatrix.setRotate(fDegrees, 64, 64);

        sk_sp<SkImageFilter> filter =
                SkImageFilters::MatrixTransform(filterMatrix,
                                                SkSamplingOptions(SkFilterMode::kLinear), nullptr)
                             ->makeWithLocalMatrix(localMatrix);

        SkPaint p;
        p.setImageFilter(filter);
        canvas->drawImage(fImage.get(), 128, 128, SkSamplingOptions(), &p);
    }

private:
    SkScalar fDegrees;
    sk_sp<SkImage> fImage;
};

DEF_GM(return new ImageFilterMatrixWLocalMatrix();)

class ImageFilterComposedTransform : public skiagm::GM {
public:

    // Start at 70 degrees since that highlighted the issue in skbug.com/10888
    ImageFilterComposedTransform() : fDegrees(70.f) {}

protected:
    SkString onShortName() override {
        return SkString("imagefilter_composed_transform");
    }

    SkISize onISize() override {
        return SkISize::Make(512, 512);
    }

    bool onAnimate(double nanos) override {
        // Animate the rotation angle to test a variety of transformations
        fDegrees = TimeUtils::Scaled(1e-9f * nanos, 360.f);
        return true;
    }

    void onOnceBeforeDraw() override {
        fImage = GetResourceAsImage("images/mandrill_256.png");
    }

    void onDraw(SkCanvas* canvas) override {
        SkMatrix matrix = SkMatrix::RotateDeg(fDegrees);
        // All four quadrants should render the same
        this->drawFilter(canvas, 0.f, 0.f, this->makeDirectFilter(matrix));
        this->drawFilter(canvas, 256.f, 0.f, this->makeEarlyComposeFilter(matrix));
        this->drawFilter(canvas, 0.f, 256.f, this->makeLateComposeFilter(matrix));
        this->drawFilter(canvas, 256.f, 256.f, this->makeFullComposeFilter(matrix));
    }

private:
    SkScalar fDegrees;
    sk_sp<SkImage> fImage;

    void drawFilter(SkCanvas* canvas, SkScalar tx, SkScalar ty, sk_sp<SkImageFilter> filter) const {
        SkPaint p;
        p.setImageFilter(std::move(filter));

        canvas->save();
        canvas->translate(tx, ty);
        canvas->clipRect(SkRect::MakeWH(256, 256));
        canvas->scale(0.5f, 0.5f);
        canvas->translate(128, 128);
        canvas->drawImage(fImage, 0, 0, SkSamplingOptions(), &p);
        canvas->restore();
    }

    // offset(matrix(offset))
    sk_sp<SkImageFilter> makeDirectFilter(const SkMatrix& matrix) const {
        SkPoint v = {fImage->width() / 2.f, fImage->height() / 2.f};
        sk_sp<SkImageFilter> filter = SkImageFilters::Offset(-v.fX, -v.fY, nullptr);
        filter = SkImageFilters::MatrixTransform(matrix, SkSamplingOptions(SkFilterMode::kLinear),
                                                 std::move(filter));
        filter = SkImageFilters::Offset(v.fX, v.fY, std::move(filter));
        return filter;
    }

    // offset(compose(matrix, offset))
    sk_sp<SkImageFilter> makeEarlyComposeFilter(const SkMatrix& matrix) const {
        SkPoint v = {fImage->width() / 2.f, fImage->height() / 2.f};
        sk_sp<SkImageFilter> offset = SkImageFilters::Offset(-v.fX, -v.fY, nullptr);
        sk_sp<SkImageFilter> filter = SkImageFilters::MatrixTransform(
                matrix, SkSamplingOptions(SkFilterMode::kLinear), nullptr);
        filter = SkImageFilters::Compose(std::move(filter), std::move(offset));
        filter = SkImageFilters::Offset(v.fX, v.fY, std::move(filter));
        return filter;
    }

    // compose(offset, matrix(offset))
    sk_sp<SkImageFilter> makeLateComposeFilter(const SkMatrix& matrix) const {
        SkPoint v = {fImage->width() / 2.f, fImage->height() / 2.f};
        sk_sp<SkImageFilter> filter = SkImageFilters::Offset(-v.fX, -v.fY, nullptr);
        filter = SkImageFilters::MatrixTransform(matrix, SkSamplingOptions(SkFilterMode::kLinear),
                                                 std::move(filter));
        sk_sp<SkImageFilter> offset = SkImageFilters::Offset(v.fX, v.fY, nullptr);
        filter = SkImageFilters::Compose(std::move(offset), std::move(filter));
        return filter;
    }

    // compose(offset, compose(matrix, offset))
    sk_sp<SkImageFilter> makeFullComposeFilter(const SkMatrix& matrix) const {
        SkPoint v = {fImage->width() / 2.f, fImage->height() / 2.f};
        sk_sp<SkImageFilter> offset = SkImageFilters::Offset(-v.fX, -v.fY, nullptr);
        sk_sp<SkImageFilter> filter = SkImageFilters::MatrixTransform(
                matrix, SkSamplingOptions(SkFilterMode::kLinear), nullptr);
        filter = SkImageFilters::Compose(std::move(filter), std::move(offset));
        offset = SkImageFilters::Offset(v.fX, v.fY, nullptr);
        filter = SkImageFilters::Compose(std::move(offset), std::move(filter));
        return filter;
    }
};

DEF_GM(return new ImageFilterComposedTransform();)

// Tests SkImageFilters::Image under tricky matrices (mirrors and perspective)
DEF_SIMPLE_GM(imagefilter_transformed_image, canvas, 256, 256) {
    sk_sp<SkImage> image = GetResourceAsImage("images/color_wheel.png");
    sk_sp<SkImageFilter> imageFilter = SkImageFilters::Image(image);

    const SkRect imageRect = SkRect::MakeIWH(image->width(), image->height());

    SkM44 m1 = SkM44::Translate(0.9f * image->width(), 0.1f * image->height()) *
               SkM44::Scale(-.8f, .8f);

    SkM44 m2 = SkM44::RectToRect({-1.f, -1.f, 1.f, 1.f}, imageRect) *
               SkM44::Perspective(0.01f, 100.f, SK_ScalarPI / 3.f) *
               SkM44::Translate(0.f, 0.f, -2.f) *
               SkM44::Rotate({0.f, 1.f, 0.f}, SK_ScalarPI / 6.f) *
               SkM44::RectToRect(imageRect, {-1.f, -1.f, 1.f, 1.f});

    SkFont font(ToolUtils::create_portable_typeface());
    canvas->drawString("Columns should match", 5.f, 15.f, font, SkPaint());
    canvas->translate(0.f, 10.f);

    SkSamplingOptions sampling(SkFilterMode::kLinear);
    for (auto m : {m1, m2}) {
        canvas->save();
        for (bool canvasTransform : {false, true}) {
            canvas->save();
            canvas->clipRect(imageRect);

            sk_sp<SkImageFilter> finalFilter;
            if (canvasTransform) {
                canvas->concat(m);
                finalFilter = imageFilter;
            } else {
                finalFilter = SkImageFilters::MatrixTransform(m.asM33(), sampling, imageFilter);
            }

            SkPaint paint;
            paint.setImageFilter(std::move(finalFilter));
            canvas->drawPaint(paint);

            canvas->restore();
            canvas->translate(image->width(), 0.f);
        }
        canvas->restore();

        canvas->translate(0.f, image->height());
    }
}
