/*
 * Copyright 2012 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/SkFont.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypeface.h"
#include "include/effects/SkGradientShader.h"
#include "include/effects/SkImageFilters.h"
#include "tools/ToolUtils.h"

#include <vector>

namespace skiagm {

enum KernelFixture {
    kBasic_KernelFixture,
    kLarge_KernelFixture
};

class MatrixConvolutionGM : public GM {
public:
    MatrixConvolutionGM(SkColor colorOne, SkColor colorTwo, KernelFixture kernelFixture, const char* nameSuffix)
            : fNameSuffix(nameSuffix),
              fKernelFixture(kernelFixture) {
        this->setBGColor(0x00000000);
        fColors[0] = colorOne;
        fColors[1] = colorTwo;
    }

protected:

    SkString onShortName() override {
        return SkStringPrintf("matrixconvolution%s", fNameSuffix);
    }

    void makeBitmap() {
        // Draw our bitmap in N32, so legacy devices get "premul" values they understand
        fBitmap.allocN32Pixels(80, 80);
        SkCanvas canvas(fBitmap);
        canvas.clear(0x00000000);
        SkPaint paint;
        paint.setColor(0xFFFFFFFF);
        SkPoint pts[2] = { {0, 0},
                           {0, 80.0f} };
        SkScalar pos[2] = { 0, 80.0f };
        paint.setShader(SkGradientShader::MakeLinear(
            pts, fColors, pos, 2, SkTileMode::kClamp));
        SkFont font(ToolUtils::create_portable_typeface(), 180.0f);
        canvas.drawString("e", -10.0f, 80.0f, font, paint);
    }

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

    sk_sp<SkImageFilter> makeFilter(const SkIPoint &kernelOffset, SkTileMode tileMode,
                                    bool convolveAlpha, const SkIRect *cropRect = nullptr) {
        switch (fKernelFixture) {
            case kBasic_KernelFixture: {
                // All 1s except center value, which is -7 (sum of 1).
                std::vector<SkScalar> kernel(9, SkIntToScalar(1));
                kernel[4] = SkIntToScalar(-7);
                return SkImageFilters::MatrixConvolution({3,3}, kernel.data(), /* gain */ 0.3f, /* bias */ SkIntToScalar(100), kernelOffset, tileMode, convolveAlpha, nullptr, cropRect);
            }
            case kLarge_KernelFixture: {
                // Intentionally go over the MAX_KERNEL_SIZE limit and trigger CPU fallback.
                // All 1s except center value, which is -47 (sum of 1).
                std::vector<SkScalar> kernel(49, SkIntToScalar(1));
                kernel[24] = SkIntToScalar(-47);
                return SkImageFilters::MatrixConvolution({7,7}, kernel.data(), /* gain */ 0.3f, /* bias */ SkIntToScalar(100), kernelOffset, tileMode, convolveAlpha, nullptr, cropRect);
            }
            default:
                return nullptr;
        }
    }

    void draw(SkCanvas* canvas, int x, int y, const SkIPoint& kernelOffset,
              SkTileMode tileMode, bool convolveAlpha,
              const SkIRect* cropRect = nullptr) {
        SkPaint paint;
        paint.setImageFilter(this->makeFilter(kernelOffset, tileMode, convolveAlpha, cropRect));
        canvas->save();
        canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
        const SkRect layerBounds = SkRect::MakeIWH(fBitmap.width(), fBitmap.height());
        canvas->clipRect(layerBounds);
        // This GM is, in part, intended to display the wrapping behavior of the
        // matrix image filter. The only (rational) way to achieve that for repeat mode
        // is to create a tight layer.
        canvas->saveLayer(layerBounds, &paint);
            canvas->drawBitmap(fBitmap, 0, 0, nullptr);
        canvas->restore();
        canvas->restore();
    }

    void onOnceBeforeDraw() override {
        this->makeBitmap();
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->clear(SK_ColorBLACK);
        SkIPoint kernelOffset = SkIPoint::Make(1, 0);
        SkIRect rect = fBitmap.bounds();
        for (int x = 10; x < 310; x += 100) {
            this->draw(canvas, x, 10, kernelOffset, SkTileMode::kClamp, true, &rect);
            this->draw(canvas, x, 110, kernelOffset, SkTileMode::kDecal, true, &rect);
            this->draw(canvas, x, 210, kernelOffset, SkTileMode::kRepeat, true, &rect);
            kernelOffset.fY++;
        }
        kernelOffset.fY = 1;
        SkIRect smallRect = SkIRect::MakeXYWH(10, 5, 60, 60);
        this->draw(canvas, 310, 10, kernelOffset, SkTileMode::kClamp, true, &smallRect);
        this->draw(canvas, 310, 110, kernelOffset, SkTileMode::kDecal, true, &smallRect);
        this->draw(canvas, 310, 210, kernelOffset, SkTileMode::kRepeat, true, &smallRect);

        this->draw(canvas, 410, 10, kernelOffset, SkTileMode::kClamp, false, &rect);
        this->draw(canvas, 410, 110, kernelOffset, SkTileMode::kDecal, false, &rect);
        this->draw(canvas, 410, 210, kernelOffset, SkTileMode::kRepeat, false, &rect);
    }

private:
    SkBitmap fBitmap;
    SkColor fColors[2];
    const char* fNameSuffix;
    KernelFixture fKernelFixture;

    typedef GM INHERITED;
};

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

DEF_GM(return new MatrixConvolutionGM(0xFFFFFFFF, 0x40404040, KernelFixture::kBasic_KernelFixture, "");)
DEF_GM(return new MatrixConvolutionGM(0xFFFF0000, 0xFF00FF00, KernelFixture::kBasic_KernelFixture, "_color");)
DEF_GM(return new MatrixConvolutionGM(0xFFFFFFFF, 0x40404040, KernelFixture::kLarge_KernelFixture, "_big");)
DEF_GM(return new MatrixConvolutionGM(0xFFFF0000, 0xFF00FF00, KernelFixture::kLarge_KernelFixture, "_big_color");)

}
