/*
 * Copyright 2012 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/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTiledImageUtils.h"
#include "include/effects/SkGradientShader.h"
#include "tools/ToolUtils.h"

static void draw(SkCanvas* canvas, int width, int height, SkColor colors[2]) {
    const SkPoint center = { SkIntToScalar(width)/2, SkIntToScalar(height)/2 };
    const SkScalar radius = 40;
    SkPaint paint;
    paint.setShader(SkGradientShader::MakeRadial(center, radius, colors, nullptr, 2,
                                                 SkTileMode::kMirror));
    paint.setBlendMode(SkBlendMode::kSrc);
    canvas->drawPaint(paint);
}

static sk_sp<SkImage> make_raster_image(int width, int height, SkColor colors[2]) {
    auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(width, height)));
    draw(surface->getCanvas(), width, height, colors);
    return surface->makeImageSnapshot();
}

static sk_sp<SkImage> make_picture_image(int width, int height, SkColor colors[2]) {
    SkPictureRecorder recorder;
    draw(recorder.beginRecording(SkRect::MakeIWH(width, height)), width, height, colors);
    return SkImages::DeferredFromPicture(recorder.finishRecordingAsPicture(),
                                         {width, height},
                                         nullptr,
                                         nullptr,
                                         SkImages::BitDepth::kU8,
                                         SkColorSpace::MakeSRGB());
}

typedef sk_sp<SkImage> (*ImageMakerProc)(int width, int height, SkColor colors[2]);

static void show_image(SkCanvas* canvas, int width, int height, SkColor colors[2],
                       ImageMakerProc proc, bool manuallyTile) {
    sk_sp<SkImage> image = ToolUtils::MakeTextureImage(canvas, proc(width, height, colors));
    if (!image) {
        return;
    }

    SkPaint borderPaint;

    borderPaint.setStyle(SkPaint::kStroke_Style);

    SkRect dstRect = SkRect::MakeWH(128.f, 128.f);

    canvas->save();
    canvas->clipRect(dstRect);
    if (manuallyTile) {
        SkTiledImageUtils::DrawImage(canvas, image, 0, 0);
    } else {
        canvas->drawImage(image, 0, 0);
    }
    canvas->restore();
    canvas->drawRect(dstRect, borderPaint);

    dstRect.offset(SkIntToScalar(150), 0);
    int hw = width / 2;
    int hh = height / 2;
    SkRect subset = SkRect::MakeLTRB(hw - 64, hh - 32, hw + 64, hh + 32);
    if (manuallyTile) {
        SkTiledImageUtils::DrawImageRect(canvas, image, subset, dstRect, {}, nullptr,
                                         SkCanvas::kStrict_SrcRectConstraint);
    } else {
        canvas->drawImageRect(image, subset, dstRect, {}, nullptr,
                              SkCanvas::kStrict_SrcRectConstraint);
    }
    canvas->drawRect(dstRect, borderPaint);

    dstRect.offset(SkIntToScalar(150), 0);
    if (manuallyTile) {
        SkTiledImageUtils::DrawImageRect(canvas, image, dstRect);
    } else {
        canvas->drawImageRect(image, dstRect, {});
    }
    canvas->drawRect(dstRect, borderPaint);
}

class VeryLargeBitmapGM : public skiagm::GM {
    ImageMakerProc  fProc;
    const char*     fBaseName;
    bool            fManuallyTile;

public:
    VeryLargeBitmapGM(ImageMakerProc proc, const char baseName[], bool manuallyTile)
            : fProc(proc)
            , fBaseName(baseName)
            , fManuallyTile(manuallyTile) {}

private:
    SkString onShortName() override {
        SkString name(fBaseName);

        if (fManuallyTile) {
            name.append("_manual");
        }

        return name;
    }

    SkISize onISize() override { return {500, 600}; }

    void onDraw(SkCanvas* canvas) override {
        int veryBig = 65*1024; // 64K < size
        int big = 33*1024;     // 32K < size < 64K
        // smaller than many max texture sizes, but large enough to gpu-tile for memory reasons.
        int medium = 5*1024;
        int small = 150;

        SkColor colors[2];

        canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
        colors[0] = SK_ColorRED;
        colors[1] = SK_ColorGREEN;
        show_image(canvas, small, small, colors, fProc, fManuallyTile);
        canvas->translate(0, SkIntToScalar(150));

        colors[0] = SK_ColorBLUE;
        colors[1] = SK_ColorMAGENTA;
        show_image(canvas, big, small, colors, fProc, fManuallyTile);
        canvas->translate(0, SkIntToScalar(150));

        colors[0] = SK_ColorMAGENTA;
        colors[1] = SK_ColorYELLOW;
        show_image(canvas, medium, medium, colors, fProc, fManuallyTile);
        canvas->translate(0, SkIntToScalar(150));

        colors[0] = SK_ColorGREEN;
        colors[1] = SK_ColorYELLOW;
        // This used to be big enough that we didn't draw on CPU, but now we do.
        show_image(canvas, veryBig, small, colors, fProc, fManuallyTile);
    }
};

DEF_GM( return new VeryLargeBitmapGM(make_raster_image, "verylargebitmap",
                                     /* manuallyTile= */ false); )
DEF_GM( return new VeryLargeBitmapGM(make_raster_image, "verylargebitmap",
                                     /* manuallyTile= */ true); )
DEF_GM( return new VeryLargeBitmapGM(make_picture_image, "verylarge_picture_image",
                                     /* manuallyTile= */ false); )
DEF_GM( return new VeryLargeBitmapGM(make_picture_image, "verylarge_picture_image",
                                     /* manuallyTile= */ true); )
