/*
 * 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/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorPriv.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.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/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "include/private/SkTDArray.h"
#include "src/core/SkTLazy.h"

#include <utility>

static sk_sp<SkShader> make_shader(SkBlendMode mode) {
    SkPoint pts[2];
    SkColor colors[2];

    pts[0].set(0, 0);
    pts[1].set(SkIntToScalar(100), 0);
    colors[0] = SK_ColorRED;
    colors[1] = SK_ColorBLUE;
    auto shaderA = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);

    pts[0].set(0, 0);
    pts[1].set(0, SkIntToScalar(100));
    colors[0] = SK_ColorBLACK;
    colors[1] = SkColorSetARGB(0x80, 0, 0, 0);
    auto shaderB = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);

    return SkShaders::Blend(mode, std::move(shaderA), std::move(shaderB));
}

class ComposeShaderGM : public skiagm::GM {
public:
    ComposeShaderGM() {
        fShader = make_shader(SkBlendMode::kDstIn);
    }

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

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

    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;
        paint.setColor(SK_ColorGREEN);
        canvas->drawRect(SkRect::MakeWH(100, 100), paint);
        paint.setShader(fShader);
        canvas->drawRect(SkRect::MakeWH(100, 100), paint);
    }

protected:
    sk_sp<SkShader> fShader;

private:
    typedef GM INHERITED ;
};
DEF_GM( return new ComposeShaderGM; )

class ComposeShaderAlphaGM : public skiagm::GM {
public:
    ComposeShaderAlphaGM() {}

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

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

    void onDraw(SkCanvas* canvas) override {
        sk_sp<SkShader> shaders[] = {
            make_shader(SkBlendMode::kDstIn),
            make_shader(SkBlendMode::kSrcOver),
        };

        SkPaint paint;
        paint.setColor(SK_ColorGREEN);

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

        for (size_t y = 0; y < SK_ARRAY_COUNT(shaders); ++y) {
            canvas->save();
            for (int alpha = 0xFF; alpha > 0; alpha -= 0x28) {
                paint.setAlphaf(1.0f);
                paint.setShader(nullptr);
                canvas->drawRect(r, paint);

                paint.setAlpha(alpha);
                paint.setShader(shaders[y]);
                canvas->drawRect(r, paint);

                canvas->translate(r.width() + 5, 0);
            }
            canvas->restore();
            canvas->translate(0, r.height() + 5);
        }
    }

private:
    typedef GM INHERITED ;
};
DEF_GM( return new ComposeShaderAlphaGM; )

// creates a square bitmap with red background and a green circle in the center
static void draw_color_bm(SkBitmap* bm, int length) {
    SkPaint paint;
    paint.setColor(SK_ColorGREEN);

    bm->allocN32Pixels(length, length);
    bm->eraseColor(SK_ColorRED);

    SkCanvas canvas(*bm);
    canvas.drawCircle(SkIntToScalar(length/2), SkIntToScalar(length/2), SkIntToScalar(length/2),
                      paint);
}

// creates a square alpha8 bitmap with transparent background and an opaque circle in the center
static void draw_alpha8_bm(SkBitmap* bm, int length) {
    SkPaint circlePaint;
    circlePaint.setColor(SK_ColorBLACK);

    bm->allocPixels(SkImageInfo::MakeA8(length, length));
    bm->eraseColor(SK_ColorTRANSPARENT);

    SkCanvas canvas(*bm);
    canvas.drawCircle(SkIntToScalar(length/2), SkIntToScalar(length/2), SkIntToScalar(length/4),
                      circlePaint);
}

// creates a linear gradient shader
static sk_sp<SkShader> make_linear_gradient_shader(int length) {
    SkPoint pts[2];
    SkColor colors[2];
    pts[0].set(0, 0);
    pts[1].set(SkIntToScalar(length), 0);
    colors[0] = SK_ColorBLUE;
    colors[1] = SkColorSetARGB(0, 0, 0, 0xFF);
    return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
}


class ComposeShaderBitmapGM : public skiagm::GM {
public:
    ComposeShaderBitmapGM(bool use_lm) : fUseLocalMatrix(use_lm) {}

protected:
    void onOnceBeforeDraw() override {
        draw_color_bm(&fColorBitmap, squareLength);
        draw_alpha8_bm(&fAlpha8Bitmap, squareLength);
        SkMatrix s;
        s.reset();
        fColorBitmapShader = fColorBitmap.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &s);
        fAlpha8BitmapShader = fAlpha8Bitmap.makeShader(SkTileMode::kRepeat,
                                                       SkTileMode::kRepeat, &s);
        fLinearGradientShader = make_linear_gradient_shader(squareLength);
    }

    SkString onShortName() override {
        return SkStringPrintf("composeshader_bitmap%s", fUseLocalMatrix ? "_lm" : "");
    }

    SkISize onISize() override {
        return SkISize::Make(7 * (squareLength + 5), 2 * (squareLength + 5));
    }

    void onDraw(SkCanvas* canvas) override {
        SkBlendMode mode = SkBlendMode::kDstOver;

        SkTLazy<SkMatrix> lm;
        if (fUseLocalMatrix) {
            lm.set(SkMatrix::MakeTrans(0, squareLength * 0.5f));
        }

        sk_sp<SkShader> shaders[] = {
            // gradient should appear over color bitmap
            SkShaders::Blend(mode, fLinearGradientShader, fColorBitmapShader, lm.getMaybeNull()),
            // gradient should appear over alpha8 bitmap colorized by the paint color
            SkShaders::Blend(mode, fLinearGradientShader, fAlpha8BitmapShader, lm.getMaybeNull()),
        };

        SkPaint paint;
        paint.setColor(SK_ColorYELLOW);

        const SkRect r = SkRect::MakeXYWH(0, 0, SkIntToScalar(squareLength),
                                          SkIntToScalar(squareLength));

        for (size_t y = 0; y < SK_ARRAY_COUNT(shaders); ++y) {
            canvas->save();
            for (int alpha = 0xFF; alpha > 0; alpha -= 0x28) {
                paint.setAlpha(alpha);
                paint.setShader(shaders[y]);
                canvas->drawRect(r, paint);

                canvas->translate(r.width() + 5, 0);
            }
            canvas->restore();
            canvas->translate(0, r.height() + 5);
        }
    }

private:
    /** This determines the length and width of the bitmaps used in the ComposeShaders.  Values
     *  above 20 may cause an SkASSERT to fail in SkSmallAllocator. However, larger values will
     *  work in a release build.  You can change this parameter and then compile a release build
     *  to have this GM draw larger bitmaps for easier visual inspection.
     */
    static constexpr int squareLength = 20;

    const bool fUseLocalMatrix;

    SkBitmap fColorBitmap;
    SkBitmap fAlpha8Bitmap;
    sk_sp<SkShader> fColorBitmapShader;
    sk_sp<SkShader> fAlpha8BitmapShader;
    sk_sp<SkShader> fLinearGradientShader;

    typedef GM INHERITED;
};
DEF_GM( return new ComposeShaderBitmapGM(false); )
DEF_GM( return new ComposeShaderBitmapGM(true); )

DEF_SIMPLE_GM(composeshader_bitmap2, canvas, 200, 200) {
    int width = 255;
    int height = 255;
    SkTDArray<uint8_t> dst8Storage;
    dst8Storage.setCount(width * height);
    SkTDArray<uint32_t> dst32Storage;
    dst32Storage.setCount(width * height * sizeof(int32_t));
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            dst8Storage[y * width + x] = (y + x) / 2;
            dst32Storage[y * width + x] = SkPackARGB32(0xFF, x, y, 0);
        }
    }
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorBLUE);
    SkRect r = {0, 0, SkIntToScalar(width), SkIntToScalar(height)};
    canvas->drawRect(r, paint);
    SkBitmap skBitmap, skMask;
    SkImageInfo imageInfo = SkImageInfo::Make(width, height,
            SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
    skBitmap.installPixels(imageInfo, dst32Storage.begin(), width * sizeof(int32_t),
                           nullptr, nullptr);
    imageInfo = SkImageInfo::Make(width, height,
            SkColorType::kAlpha_8_SkColorType, kPremul_SkAlphaType);
    skMask.installPixels(imageInfo, dst8Storage.begin(), width, nullptr, nullptr);
    sk_sp<SkImage> skSrc = SkImage::MakeFromBitmap(skBitmap);
    sk_sp<SkImage> skMaskImage = SkImage::MakeFromBitmap(skMask);
    paint.setShader(
        SkShaders::Blend(SkBlendMode::kSrcIn, skMaskImage->makeShader(), skSrc->makeShader()));
    canvas->drawRect(r, paint);
}

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

static sk_sp<SkShader> make_src_shader(SkScalar size) {
    const SkPoint pts[] = { { 0, 0 }, { 0, size } };
    const SkColor colors[] = { 0xFF0000FF, 0x000000FF };
    return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
}

static sk_sp<SkShader> make_dst_shader(SkScalar size) {
    const SkPoint pts[] = { { 0, 0 }, { size, 0 } };
    const SkColor colors[] = { SK_ColorRED, 0x00FF0000 };
    return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
}

const SkScalar gCellSize = 100;

static void draw_cell(SkCanvas* canvas, sk_sp<SkShader> src, sk_sp<SkShader> dst,
                      SkBlendMode mode, SkAlpha alpha) {
    const SkRect r = SkRect::MakeWH(gCellSize, gCellSize);
    SkPaint p;
    p.setAlpha(alpha);

    SkAutoCanvasRestore acr(canvas, false);
    canvas->saveLayer(&r, &p);
    p.setAlpha(0xFF);

    p.setShader(dst);
    p.setBlendMode(SkBlendMode::kSrc);
    canvas->drawRect(r, p);

    p.setShader(src);
    p.setBlendMode(mode);
    canvas->drawRect(r, p);
}

static void draw_composed(SkCanvas* canvas, sk_sp<SkShader> src, sk_sp<SkShader> dst,
                          SkBlendMode mode, SkAlpha alpha) {
    SkPaint p;
    p.setAlpha(alpha);
    p.setShader(SkShaders::Blend(mode, dst, src));
    canvas->drawRect(SkRect::MakeWH(gCellSize, gCellSize), p);
}

static void draw_pair(SkCanvas* canvas, sk_sp<SkShader> src, sk_sp<SkShader> dst,
                      SkBlendMode mode) {
    SkAutoCanvasRestore acr(canvas, true);

    const SkScalar gap = 4;
    SkRect r = SkRect::MakeWH(2 * gCellSize + gap, 2 * gCellSize + gap);
    r.outset(gap + 1.5f, gap + 1.5f);
    SkPaint p;
    p.setStyle(SkPaint::kStroke_Style);
    canvas->drawRect(r, p); // border

    SkAlpha alpha = 0xFF;
    for (int y = 0; y < 2; ++y) {
        draw_cell(canvas, src, dst, mode, alpha);
        canvas->save();
        canvas->translate(gCellSize + gap, 0);
        draw_composed(canvas, src, dst, mode, alpha);
        canvas->restore();

        canvas->translate(0, gCellSize + gap);
        alpha = 0x80;
    }
}

DEF_SIMPLE_GM(composeshader_grid, canvas, 882, 882) {
    auto src = make_src_shader(gCellSize);
    auto dst = make_dst_shader(gCellSize);

    const SkScalar margin = 15;
    const SkScalar dx = 2*gCellSize + margin;
    const SkScalar dy = 2*gCellSize + margin;

    canvas->translate(margin, margin);
    canvas->save();
    for (int m = 0; m < 16; ++m) {
        SkBlendMode mode = static_cast<SkBlendMode>(m);
        draw_pair(canvas, src, dst, mode);
        if ((m % 4) == 3) {
            canvas->restore();
            canvas->translate(0, dy);
            canvas->save();
        } else {
            canvas->translate(dx, 0);
        }
    }
    canvas->restore();
}
