/*
 * Copyright 2013 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 "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkGradientShader.h"
#include "SkRandom.h"

static SkShader* make_shader1(SkScalar w, SkScalar h) {
    const SkColor colors[] = {
        SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE,
        SK_ColorMAGENTA, SK_ColorBLUE, SK_ColorYELLOW,
    };
    const SkPoint pts[] = { { w/4, 0 }, { 3*w/4, h } };

    return SkGradientShader::CreateLinear(pts, colors, nullptr,
                                          SK_ARRAY_COUNT(colors),
                                          SkShader::kMirror_TileMode);
}

static SkShader* make_shader2() {
    return SkShader::CreateColorShader(SK_ColorBLUE);
}

static SkColorFilter* make_color_filter() {
    return SkColorFilter::CreateModeFilter(0xFFAABBCC, SkXfermode::kDarken_Mode);
}

class VerticesGM : public skiagm::GM {
    SkPoint                     fPts[9];
    SkPoint                     fTexs[9];
    SkColor                     fColors[9];
    SkAutoTUnref<SkShader>      fShader1;
    SkAutoTUnref<SkShader>      fShader2;
    SkAutoTUnref<SkColorFilter> fColorFilter;

public:
    VerticesGM() {}

protected:

    void onOnceBeforeDraw() override {
        const SkScalar X = 30;
        const SkScalar Y = 30;

        fPts[0].set(0, 0);    fPts[1].set(X/2, 3);   fPts[2].set(X, 0);
        fPts[3].set(3, Y/2);  fPts[4].set(X/2, Y/2); fPts[5].set(X-3, Y/2);
        fPts[6].set(0, Y);    fPts[7].set(X/2, Y-3); fPts[8].set(X, Y);

        const SkScalar w = 40;
        const SkScalar h = 40;

        fTexs[0].set(0, 0);     fTexs[1].set(w/2, 0);   fTexs[2].set(w, 0);
        fTexs[3].set(0, h/2);   fTexs[4].set(w/2, h/2); fTexs[5].set(w, h/2);
        fTexs[6].set(0, h);     fTexs[7].set(w/2, h);   fTexs[8].set(w, h);

        fShader1.reset(make_shader1(w, h));
        fShader2.reset(make_shader2());
        fColorFilter.reset(make_color_filter());

        SkRandom rand;
        for (size_t i = 0; i < SK_ARRAY_COUNT(fColors); ++i) {
            fColors[i] = rand.nextU() | 0xFF000000;
        }
    }

    SkString onShortName() override {
        SkString name("vertices");
        return name;
    }

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

    void onDraw(SkCanvas* canvas) override {
        // start with the center of a 3x3 grid
        static const uint16_t fan[] = {
            4,
            0, 1, 2, 5, 8, 7, 6, 3, 0
        };

        const struct {
            const SkColor*  fColors;
            const SkPoint*  fTexs;
            SkShader*       fShader;
            SkColorFilter*  fColorFilter;
            uint8_t         fAlpha;
        } rec[] = {
            { fColors,  nullptr, fShader1, nullptr     , 0xFF },
            { nullptr,  fTexs  , fShader1, nullptr     , 0xFF },
            { fColors,  fTexs  , fShader1, nullptr     , 0xFF },
            { fColors,  nullptr, fShader2, nullptr     , 0xFF },
            { nullptr,  fTexs  , fShader2, nullptr     , 0xFF },
            { fColors,  fTexs  , fShader2, nullptr     , 0xFF },
            { fColors,  nullptr, fShader1, fColorFilter, 0xFF },
            { nullptr,  fTexs  , fShader1, fColorFilter, 0xFF },
            { fColors,  fTexs  , fShader1, fColorFilter, 0xFF },
            { fColors,  nullptr, fShader2, fColorFilter, 0xFF },
            { nullptr,  fTexs  , fShader2, fColorFilter, 0xFF },
            { fColors,  fTexs  , fShader2, fColorFilter, 0xFF },
            { fColors,  nullptr, fShader1, nullptr     , 0x80 },
            { nullptr,  fTexs  , fShader1, nullptr     , 0x80 },
            { fColors,  fTexs  , fShader1, nullptr     , 0x80 },
            { fColors,  nullptr, fShader2, nullptr     , 0x80 },
            { nullptr,  fTexs  , fShader2, nullptr     , 0x80 },
            { fColors,  fTexs  , fShader2, nullptr     , 0x80 },
            { fColors,  nullptr, fShader1, fColorFilter, 0x80 },
            { nullptr,  fTexs  , fShader1, fColorFilter, 0x80 },
            { fColors,  fTexs  , fShader1, fColorFilter, 0x80 },
            { fColors,  nullptr, fShader2, fColorFilter, 0x80 },
            { nullptr,  fTexs  , fShader2, fColorFilter, 0x80 },
            { fColors,  fTexs  , fShader2, fColorFilter, 0x80 },
        };

        const SkXfermode::Mode modes[] = {
            SkXfermode::kClear_Mode,
            SkXfermode::kSrc_Mode,
            SkXfermode::kDst_Mode,
            SkXfermode::kSrcOver_Mode,
            SkXfermode::kDstOver_Mode,
            SkXfermode::kSrcIn_Mode,
            SkXfermode::kDstIn_Mode,
            SkXfermode::kSrcOut_Mode,
            SkXfermode::kDstOut_Mode,
            SkXfermode::kSrcATop_Mode,
            SkXfermode::kDstATop_Mode,
            SkXfermode::kXor_Mode,
            SkXfermode::kPlus_Mode,
            SkXfermode::kModulate_Mode,
            SkXfermode::kScreen_Mode,
            SkXfermode::kOverlay_Mode,
            SkXfermode::kDarken_Mode,
            SkXfermode::kLighten_Mode,
            SkXfermode::kColorDodge_Mode,
            SkXfermode::kColorBurn_Mode,
            SkXfermode::kHardLight_Mode,
            SkXfermode::kSoftLight_Mode,
            SkXfermode::kDifference_Mode,
            SkXfermode::kExclusion_Mode,
            SkXfermode::kMultiply_Mode,
            SkXfermode::kHue_Mode,
            SkXfermode::kSaturation_Mode,
            SkXfermode::kColor_Mode,
            SkXfermode::kLuminosity_Mode,
        };

        SkPaint paint;

        canvas->translate(4, 4);
        int x = 0;
        for (size_t j = 0; j < SK_ARRAY_COUNT(modes); ++j) {
            SkXfermode* xfer = SkXfermode::Create(modes[j]);
            canvas->save();
            for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
                paint.setShader(rec[i].fShader);
                paint.setColorFilter(rec[i].fColorFilter);
                paint.setAlpha(rec[i].fAlpha);
                //if (2 == x)
                canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode,
                                     SK_ARRAY_COUNT(fPts), fPts,
                                     rec[i].fTexs, rec[i].fColors,
                                     xfer, fan, SK_ARRAY_COUNT(fan), paint);
                canvas->translate(40, 0);
                ++x;
            }
            canvas->restore();
            canvas->translate(0, 40);
            SkSafeUnref(xfer);
        }
    }

private:
    typedef skiagm::GM INHERITED;
};

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

DEF_GM(return new VerticesGM();)
