/*
 * 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/private/SkMalloc.h"
#include "tools/ToolUtils.h"

#include <array>

#if defined(SK_GANESH)
#include "include/gpu/ganesh/GrDirectContext.h"
#endif

#if defined(SK_GRAPHITE)
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Recorder.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/TextureUtils.h"
#endif

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();
}

/**
 *  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 getName() const override { return SkString("lattice"); }

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

    void onDrawHelper(GrDirectContext* grDContext, skgpu::graphite::Recorder* graphiteRecorder,
                      SkCanvas* canvas, int padLeft, int padTop,
                      int padRight, int padBottom) {
        canvas->save();

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

        sk_sp<SkImage> image = make_image(canvas, xDivs + 1, yDivs + 1, padLeft, padTop,
                                          padRight, padBottom);

        const auto size = std::to_array<SkSize>({
                SkSize{  50,  50, },  // shrink in both axes
                SkSize{  50, 200, },  // shrink in X
                SkSize{ 200,  50, },  // shrink in Y
                SkSize{ 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);
            }
        }

#if defined(SK_GRAPHITE)
        // Snap and submit the recording before reading pixels so the image's pixel
        // are up to date when being read.
        if (graphiteRecorder) {
            skgpu::graphite::Context* context = graphiteRecorder->priv().context();
            std::unique_ptr<skgpu::graphite::Recording> recording = graphiteRecorder->snap();
            if (recording) {
                skgpu::graphite::InsertRecordingInfo info;
                info.fRecording = recording.get();
                context->insertRecording(info);
            }
            context->submit(skgpu::graphite::SyncToCpu::kNo);
        }
#endif

        // Provide hints about 3 solid color rects. These colors match
        // what was already in the bitmap.
        std::array<int, 3> fixedColorX = {2, 4, 1};
        std::array<int, 3> fixedColorY = {1, 1, 2};
        std::array<SkColor, 3> fixedColor = {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++) {
#if defined(SK_GANESH) || defined(SK_GRAPHITE)
            int srcX = xDivs[fixedColorX[rectNum]-1];
            int srcY = yDivs[fixedColorY[rectNum]-1];
            void* const dstPixels = &fixedColor[rectNum];
#endif

            if (graphiteRecorder) {
#if defined(SK_GRAPHITE)
                SkPixmap pixmap(info, dstPixels, /*rowBytes=*/4);
                skgpu::graphite::ContextPriv contextPriv =
                        graphiteRecorder->priv().context()->priv();
                contextPriv.readPixels(pixmap, skgpu::graphite::AsView(image),
                                       image->imageInfo(), srcX, srcY);
#endif
            } else {
#if defined(SK_GANESH)
                image->readPixels(grDContext, info, dstPixels, /*dstRowBytes=*/4, srcX, srcY);
#endif
            }
        }

        // 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 {
#if defined(SK_GANESH)
        auto rContext = canvas->recordingContext();
        auto grDContext = GrAsDirectContext(rContext);
        if (rContext && !grDContext) {
            *errorMsg = "not supported in ddl";
            return DrawResult::kSkip;
        }
#else
        constexpr GrDirectContext* grDContext = nullptr;
#endif

#if defined(SK_GRAPHITE)
        skgpu::graphite::Recorder* recorder = canvas->recorder();
#else
        skgpu::graphite::Recorder* recorder = nullptr;
#endif

        this->onDrawHelper(grDContext, recorder, canvas, 0, 0, 0, 0);
        canvas->translate(0.0f, 400.0f);
        this->onDrawHelper(grDContext, recorder, 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 getName() const override { return SkString("lattice2"); }

    SkISize getISize() 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);
}

static sk_sp<SkImage> make_symmetry_test_image() {
    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(8, 8));
    auto canvas = surface->getCanvas();
    canvas->drawColor(SK_ColorBLUE);
    SkPaint p;
    p.setColor(SK_ColorGREEN);
    canvas->drawRect(SkRect::MakeXYWH(2, 2, 4, 4), p);
    return surface->makeImageSnapshot();
}

// b/349428795 : A nine-patch should be able to have zero-sized regions on either end. Before
// fixing the bug, it only worked on the left/top, leading to non-symmetric results in this GM.
// Correct rendering is for each row to be symmetric.
DEF_SIMPLE_GM(ninepatch_edge_case_349428795, canvas, 500, 150) {
    auto nine = make_symmetry_test_image();

    for (int i = -1; i < 6; i++) {
        canvas->drawImageNine(nine.get(),
                              SkIRect::MakeXYWH(i, 2, 4, 4),
                              SkRect::MakeXYWH(i * 70 + 80, 10, 64, 64),
                              SkFilterMode::kLinear);
        canvas->drawImageNine(nine.get(),
                              SkIRect::MakeXYWH(2, i, 4, 4),
                              SkRect::MakeXYWH(i * 70 + 80, 80, 64, 64),
                              SkFilterMode::kLinear);
    }
}
