/*
 * Copyright 2016 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/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/private/SkMalloc.h"
#include "tools/ToolUtils.h"

static sk_sp<SkSurface> make_surface(SkCanvas* root, int N, int padLeft, int padTop,
                                     int padRight, int padBottom) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(N + padLeft + padRight, N + padTop + padBottom);
    return ToolUtils::makeSurface(root, info);
}

static sk_sp<SkImage> make_image(SkCanvas* root, int* xDivs, int* yDivs, int padLeft, int padTop,
                                 int padRight, int padBottom) {
    const int kCap = 28;
    const int kMid = 8;
    const int kSize = 2*kCap + 3*kMid;

    auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
    SkCanvas* canvas = surface->getCanvas();
    canvas->translate((float) padLeft, (float) padTop);

    SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
    const SkScalar strokeWidth = SkIntToScalar(6);
    const SkScalar radius = SkIntToScalar(kCap) - strokeWidth/2;

    xDivs[0] = kCap + padLeft;
    yDivs[0] = kCap + padTop;
    xDivs[1] = kCap + kMid + padLeft;
    yDivs[1] = kCap + kMid + padTop;
    xDivs[2] = kCap + 2 * kMid + padLeft;
    yDivs[2] = kCap + 2 * kMid + padTop;
    xDivs[3] = kCap + 3 * kMid + padLeft;
    yDivs[3] = kCap + 3 * kMid + padTop;

    SkPaint paint;
    paint.setAntiAlias(true);

    paint.setColor(0xFFFFFF00);
    canvas->drawRoundRect(r, radius, radius, paint);

    r.setXYWH(SkIntToScalar(kCap), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
    paint.setColor(0x8800FF00);
    canvas->drawRect(r, paint);
    r.setXYWH(SkIntToScalar(kCap + kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
    paint.setColor(0x880000FF);
    canvas->drawRect(r, paint);
    r.setXYWH(SkIntToScalar(kCap + 2*kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
    paint.setColor(0x88FF00FF);
    canvas->drawRect(r, paint);

    r.setXYWH(0, SkIntToScalar(kCap), SkIntToScalar(kSize), SkIntToScalar(kMid));
    paint.setColor(0x8800FF00);
    canvas->drawRect(r, paint);
    r.setXYWH(0, SkIntToScalar(kCap + kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
    paint.setColor(0x880000FF);
    canvas->drawRect(r, paint);
    r.setXYWH(0, SkIntToScalar(kCap + 2*kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
    paint.setColor(0x88FF00FF);
    canvas->drawRect(r, paint);

    return surface->makeImageSnapshot();
}

static void image_to_bitmap(GrDirectContext* dContext, const SkImage* image, SkBitmap* bm) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(image->width(), image->height());
    bm->allocPixels(info);
    image->readPixels(dContext, info, bm->getPixels(), bm->rowBytes(), 0, 0);
}

/**
 *  This is similar to NinePatchStretchGM, but it also tests "ninepatch" images with more
 *  than nine patches.
 */
class LatticeGM : public skiagm::GM {
public:
    LatticeGM() {}

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

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

    void onDrawHelper(GrDirectContext* dContext, SkCanvas* canvas, int padLeft, int padTop,
                      int padRight, int padBottom) {
        canvas->save();

        int xDivs[5];
        int yDivs[5];
        xDivs[0] = padLeft;
        yDivs[0] = padTop;

        SkBitmap bitmap;
        sk_sp<SkImage> image = make_image(canvas, xDivs + 1, yDivs + 1, padLeft, padTop,
                                          padRight, padBottom);
        image_to_bitmap(dContext, image.get(), &bitmap);

        const SkSize size[] = {
            {  50,  50, }, // shrink in both axes
            {  50, 200, }, // shrink in X
            { 200,  50, }, // shrink in Y
            { 200, 200, },
        };

        canvas->drawImage(image, 10, 10);

        SkScalar x = SkIntToScalar(100);
        SkScalar y = SkIntToScalar(100);

        SkCanvas::Lattice lattice;
        lattice.fXCount = 4;
        lattice.fXDivs = xDivs + 1;
        lattice.fYCount = 4;
        lattice.fYDivs = yDivs + 1;
        lattice.fRectTypes = nullptr;
        lattice.fColors = nullptr;

        SkIRect bounds = SkIRect::MakeLTRB(padLeft, padTop,
                                           image->width() - padRight, image->height() - padBottom);
        lattice.fBounds = (bounds == SkIRect::MakeWH(image->width(), image->height())) ?
                nullptr : &bounds;

        for (int iy = 0; iy < 2; ++iy) {
            for (int ix = 0; ix < 2; ++ix) {
                int i = ix * 2 + iy;
                SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
                                            size[i].width(), size[i].height());
                canvas->drawImageLattice(image.get(), lattice, r);
            }
        }

        // Provide hints about 3 solid color rects. These colors match
        // what was already in the bitmap.
        int fixedColorX[3] = {2, 4, 1};
        int fixedColorY[3] = {1, 1, 2};
        SkColor fixedColor[3] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
        const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType,
                                                   kUnpremul_SkAlphaType);
        for (int rectNum = 0; rectNum < 3; rectNum++) {
            int srcX = xDivs[fixedColorX[rectNum]-1];
            int srcY = yDivs[fixedColorY[rectNum]-1];
            image->readPixels(dContext, info, &fixedColor[rectNum], 4, srcX, srcY);
        }

        // Include the degenerate first div.  While normally the first patch is "scalable",
        // this will mean that the first non-degenerate patch is "fixed".
        lattice.fXCount = 5;
        lattice.fXDivs = xDivs;
        lattice.fYCount = 5;
        lattice.fYDivs = yDivs;

        // Let's skip a few rects.
        SkCanvas::Lattice::RectType flags[36];
        sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::RectType));
        flags[4] = SkCanvas::Lattice::kTransparent;
        flags[9] = SkCanvas::Lattice::kTransparent;
        flags[12] = SkCanvas::Lattice::kTransparent;
        flags[19] = SkCanvas::Lattice::kTransparent;
        for (int rectNum = 0; rectNum < 3; rectNum++) {
            flags[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
                   = SkCanvas::Lattice::kFixedColor;
        }
        lattice.fRectTypes = flags;

        SkColor colors[36];
        sk_bzero(colors, 36 * sizeof(SkColor));
        for (int rectNum = 0; rectNum < 3; rectNum++) {
            colors[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
                   = fixedColor[rectNum];
        }

        lattice.fColors = colors;

        canvas->translate(400, 0);
        for (int iy = 0; iy < 2; ++iy) {
            for (int ix = 0; ix < 2; ++ix) {
                int i = ix * 2 + iy;
                SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
                                            size[i].width(), size[i].height());
                canvas->drawImageLattice(image.get(), lattice, r);
            }
        }

        canvas->restore();
    }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        auto rContext = canvas->recordingContext();
        auto dContext = GrAsDirectContext(rContext);
        if (rContext && !dContext) {
            *errorMsg = "not supported in ddl";
            return DrawResult::kSkip;
        }
        this->onDrawHelper(dContext, canvas, 0, 0, 0, 0);
        canvas->translate(0.0f, 400.0f);
        this->onDrawHelper(dContext, canvas, 3, 7, 4, 11);
        return DrawResult::kOk;
    }

private:
    using INHERITED = skiagm::GM;
};
DEF_GM( return new LatticeGM; )


// LatticeGM2 exercises code paths that draw fixed color and 1x1 rectangles.
class LatticeGM2 : public skiagm::GM {
public:
    LatticeGM2() {}
    SkString onShortName() override {
        return SkString("lattice2");
    }

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

    sk_sp<SkImage> makeImage(SkCanvas* root, int padLeft, int padTop, int padRight, int padBottom) {
        const int kSize = 80;
        auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
        SkCanvas* canvas = surface->getCanvas();
        SkPaint paint;
        paint.setAntiAlias(false);
        SkRect r;

        //first line
        r.setXYWH(0, 0, 4, 1);  //4x1 green rect
        paint.setColor(0xFF00FF00);
        canvas->drawRect(r, paint);

        r.setXYWH(4, 0, 1, 1); //1x1 blue pixel -> draws as rectangle
        paint.setColor(0xFF0000FF);
        canvas->drawRect(r, paint);

        r.setXYWH(5, 0, kSize-5, 1); //the rest of the line is red
        paint.setColor(0xFFFF0000);
        canvas->drawRect(r, paint);


        //second line -> draws as fixed color rectangles
        r.setXYWH(0, 1, 4, 1);  //4x1 red rect
        paint.setColor(0xFFFF0000);
        canvas->drawRect(r, paint);

        r.setXYWH(4, 1, 1, 1); //1x1 blue pixel with alpha
        paint.setColor(0x880000FF);
        canvas->drawRect(r, paint);

        r.setXYWH(5, 1, kSize-5, 1); //the rest of the line is green
        paint.setColor(0xFF00FF00);
        canvas->drawRect(r, paint);


        //third line - does not draw, because it is transparent
        r.setXYWH(0, 2, 4, kSize-2);  //4x78 green rect
        paint.setColor(0xFF00FF00);
        canvas->drawRect(r, paint);

        r.setXYWH(4, 2, 1, kSize-2); //1x78 red pixel with alpha
        paint.setColor(0x88FF0000);
        canvas->drawRect(r, paint);

        r.setXYWH(5, 2, kSize-5, kSize-2); //the rest of the image is blue
        paint.setColor(0xFF0000FF);
        canvas->drawRect(r, paint);

        return surface->makeImageSnapshot();
    }

    void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom,
                      SkPaint& paint) {
        int xDivs[2] = {4, 5};
        int yDivs[2] = {1, 2};

        canvas->save();

        sk_sp<SkImage> image = makeImage(canvas, padLeft, padTop, padRight, padBottom);

        canvas->drawImage(image, 10, 10);

        SkCanvas::Lattice lattice;
        lattice.fXCount = 2;
        lattice.fXDivs = xDivs;
        lattice.fYCount = 2;
        lattice.fYDivs = yDivs;
        lattice.fBounds = nullptr;

        SkCanvas::Lattice::RectType flags[9];
        sk_bzero(flags, 9 * sizeof(SkCanvas::Lattice::RectType));
        flags[3] = SkCanvas::Lattice::kFixedColor;
        flags[4] = SkCanvas::Lattice::kFixedColor;
        flags[5] = SkCanvas::Lattice::kFixedColor;

        flags[6] = SkCanvas::Lattice::kTransparent;
        flags[7] = SkCanvas::Lattice::kTransparent;
        flags[8] = SkCanvas::Lattice::kTransparent;
        lattice.fRectTypes = flags;

        SkColor colors[9] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK,
                             0xFFFF0000, 0x880000FF, 0xFF00FF00,
                             SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
        lattice.fColors = colors;
        paint.setColor(0xFFFFFFFF);
        canvas->drawImageLattice(image.get(), lattice,
                                 SkRect::MakeXYWH(100, 100, 200, 200),
                                 SkFilterMode::kNearest, &paint);

        //draw the same content with alpha
        canvas->translate(400, 0);
        paint.setColor(0x80000FFF);
        canvas->drawImageLattice(image.get(), lattice,
                                 SkRect::MakeXYWH(100, 100, 200, 200),
                                 SkFilterMode::kNearest, &paint);

        canvas->restore();
    }

    void onDraw(SkCanvas* canvas) override {

        //draw a rectangle in the background with transparent pixels
        SkPaint paint;
        paint.setColor(0x7F123456);
        paint.setBlendMode(SkBlendMode::kSrc);
        canvas->drawRect( SkRect::MakeXYWH(300, 0, 300, 800), paint);

        //draw image lattice with kSrcOver blending
        paint.setBlendMode(SkBlendMode::kSrcOver);
        this->onDrawHelper(canvas, 0, 0, 0, 0, paint);

        //draw image lattice with kSrcATop blending
        canvas->translate(0.0f, 400.0f);
        paint.setBlendMode(SkBlendMode::kSrcATop);
        this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
    }

private:
    using INHERITED = skiagm::GM;
};
DEF_GM( return new LatticeGM2; )

// Code paths that incorporate the paint color when drawing the lattice (using an alpha image)
DEF_SIMPLE_GM_BG(lattice_alpha, canvas, 120, 120, SK_ColorWHITE) {
    auto surface = ToolUtils::makeSurface(canvas, SkImageInfo::MakeA8(100, 100));
    surface->getCanvas()->clear(0);
    surface->getCanvas()->drawCircle(50, 50, 50, SkPaint());
    auto image = surface->makeImageSnapshot();

    int divs[] = { 20, 40, 60, 80 };

    SkCanvas::Lattice lattice;
    lattice.fXCount = 4;
    lattice.fXDivs = divs;
    lattice.fYCount = 4;
    lattice.fYDivs = divs;
    lattice.fRectTypes = nullptr;
    lattice.fColors = nullptr;
    lattice.fBounds = nullptr;

    SkPaint paint;
    paint.setColor(SK_ColorMAGENTA);
    canvas->drawImageLattice(image.get(), lattice, SkRect::MakeWH(120, 120),
                             SkFilterMode::kNearest, &paint);
}
