/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkColorMatrixFilter.h"
#include "SkGradientShader.h"
#include "SkImage.h"

#define WIDTH 500
#define HEIGHT 500

static void set_color_matrix(SkPaint* paint, const SkColorMatrix& matrix) {
    paint->setColorFilter(SkColorMatrixFilter::Create(matrix))->unref();
}

static void set_array(SkPaint* paint, const SkScalar array[]) {
    paint->setColorFilter(SkColorMatrixFilter::Create(array))->unref();
}

class ColorMatrixGM : public skiagm::GM {
public:
    ColorMatrixGM() {
        this->setBGColor(sk_tool_utils::color_to_565(0xFF808080));
    }

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

    SkISize onISize() override {
        return SkISize::Make(WIDTH, HEIGHT);
    }
    
    void onOnceBeforeDraw() override {
        fSolidImg.reset(CreateSolidBitmap(64, 64));
        fTransparentImg.reset(CreateTransparentBitmap(64, 64));
    }

    static SkImage* CreateSolidBitmap(int width, int height) {
        SkBitmap bm;
        bm.allocN32Pixels(width, height);
        SkCanvas canvas(bm);
        canvas.clear(0x0);
        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                SkPaint paint;
                paint.setColor(SkColorSetARGB(255, x * 255 / width, y * 255 / height, 0));
                canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(x),
                    SkIntToScalar(y), SK_Scalar1, SK_Scalar1), paint);
            }
        }
        return SkImage::NewFromBitmap(bm);
    }

    // creates a bitmap with shades of transparent gray.
    static SkImage* CreateTransparentBitmap(int width, int height) {
        SkBitmap bm;
        bm.allocN32Pixels(width, height);
        SkCanvas canvas(bm);
        canvas.clear(0x0);

        SkPoint pts[] = {{0, 0}, {SkIntToScalar(width), SkIntToScalar(height)}};
        SkColor colors[] = {0x00000000, 0xFFFFFFFF};
        SkPaint paint;
        paint.setShader(SkGradientShader::CreateLinear(pts, colors, nullptr, 2,
                                                       SkShader::kClamp_TileMode))->unref();
        canvas.drawRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), paint);
        return SkImage::NewFromBitmap(bm);
    }

    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;
        SkColorMatrix matrix;

        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
        const SkImage* bmps[] = { fSolidImg, fTransparentImg };

        for (size_t i = 0; i < SK_ARRAY_COUNT(bmps); ++i) {
            matrix.setIdentity();
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 0, 0, &paint);

            matrix.setRotate(SkColorMatrix::kR_Axis, 90);
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 80, 0, &paint);

            matrix.setRotate(SkColorMatrix::kG_Axis, 90);
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 160, 0, &paint);

            matrix.setRotate(SkColorMatrix::kB_Axis, 90);
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 240, 0, &paint);
            ///////////////////////////////////////////////
            matrix.setSaturation(0.0f);
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 0, 80, &paint);

            matrix.setSaturation(0.5f);
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 80, 80, &paint);

            matrix.setSaturation(1.0f);
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 160, 80, &paint);

            matrix.setSaturation(2.0f);
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 240, 80, &paint);
            ///////////////////////////////////////////////
            matrix.setRGB2YUV();
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 0, 160, &paint);

            matrix.setYUV2RGB();
            set_color_matrix(&paint, matrix);
            canvas->drawImage(bmps[i], 80, 160, &paint);

            SkScalar s1 = SK_Scalar1;
            SkScalar s255 = SkIntToScalar(255);
            // Move red into alpha, set color to white
            SkScalar data[20] = {
                0,  0, 0, 0, s255,
                0,  0, 0, 0, s255,
                0,  0, 0, 0, s255,
                s1, 0, 0, 0, 0,
            };

            set_array(&paint, data);
            canvas->drawImage(bmps[i], 160, 160, &paint);
            ///////////////////////////////////////////////
            canvas->translate(0, 240);
        }
    }

private:
    SkAutoTUnref<SkImage>   fSolidImg;
    SkAutoTUnref<SkImage>   fTransparentImg;

    typedef skiagm::GM INHERITED;
};
DEF_GM( return new ColorMatrixGM; )

