/*
 * 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"

#define WIDTH 500
#define HEIGHT 500

class SkDoOnce {
public:
    SkDoOnce() : fOnce(false) {};

    bool once() const {
        if (fOnce) {
            return false;
        }
        fOnce = true;
        return true;
    }

private:
    mutable bool fOnce;
};

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

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

namespace skiagm {

class ColorMatrixGM : public GM {
    SkDoOnce fOnce;
    void init() {
        if (fOnce.once()) {
            fSolidBitmap = this->createSolidBitmap(64, 64);
            fTransparentBitmap = this->createTransparentBitmap(64, 64);
        }
    }

public:
    ColorMatrixGM() {
        this->setBGColor(0xFF808080);
    }

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

    virtual SkISize onISize() {
        return SkISize::Make(WIDTH, HEIGHT);
    }

    SkBitmap 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 bm;
    }

    // creates a bitmap with shades of transparent gray.
    SkBitmap 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, NULL, 2,
                                                       SkShader::kClamp_TileMode))->unref();
        canvas.drawRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), paint);
        return bm;
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->init();

        SkPaint paint;
        SkColorMatrix matrix;

        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
        const SkBitmap bmps[] = { fSolidBitmap, fTransparentBitmap };

        for (size_t i = 0; i < SK_ARRAY_COUNT(bmps); ++i) {

            matrix.setIdentity();
            setColorMatrix(&paint, matrix);
            canvas->drawBitmap(bmps[i], 0, 0, &paint);

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

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

            matrix.setRotate(SkColorMatrix::kB_Axis, 90);
            setColorMatrix(&paint, matrix);
            canvas->drawBitmap(bmps[i], 240, 0, &paint);

            matrix.setSaturation(0.0f);
            setColorMatrix(&paint, matrix);
            canvas->drawBitmap(bmps[i], 0, 80, &paint);

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

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

            matrix.setSaturation(2.0f);
            setColorMatrix(&paint, matrix);
            canvas->drawBitmap(bmps[i], 240, 80, &paint);

            matrix.setRGB2YUV();
            setColorMatrix(&paint, matrix);
            canvas->drawBitmap(bmps[i], 0, 160, &paint);

            matrix.setYUV2RGB();
            setColorMatrix(&paint, matrix);
            canvas->drawBitmap(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,
            };

            setArray(&paint, data);
            canvas->drawBitmap(bmps[i], 160, 160, &paint);

            canvas->translate(0, 240);
        }
    }

private:
    SkBitmap fSolidBitmap;
    SkBitmap fTransparentBitmap;
    typedef GM INHERITED;
};

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

static GM* MyFactory(void*) { return new ColorMatrixGM; }
static GMRegistry reg(MyFactory);

}
