/*
 * Copyright 2015 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/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.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/SkTypes.h"
#include "include/effects/SkGradient.h"
#include "tools/DecodeUtils.h"
#include "tools/ToolUtils.h"

static sk_sp<SkImage> make_image(SkCanvas* origCanvas, int w, int h) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
    auto        surface(ToolUtils::makeSurface(origCanvas, info));
    SkCanvas* canvas = surface->getCanvas();

    ToolUtils::draw_checkerboard(canvas, SK_ColorRED, SK_ColorGREEN, w / 10);
    return surface->makeImageSnapshot();
}

namespace skiagm {

class PerspShadersGM : public GM {
public:
    PerspShadersGM(bool doAA) : fDoAA(doAA) { }

protected:
    SkString getName() const override {
        SkString name;
        name.printf("persp_shaders_%s",
                     fDoAA ? "aa" : "bw");
        return name;
    }

    SkISize getISize() override {
        return SkISize::Make(kCellSize*kNumCols, kCellSize*kNumRows);
    }

    void onOnceBeforeDraw() override {
        fBitmapImage = ToolUtils::create_checkerboard_image(
                kCellSize, kCellSize, SK_ColorBLUE, SK_ColorYELLOW, kCellSize / 10);

        SkPoint pts1[] = {
            { 0, 0 },
            { SkIntToScalar(kCellSize), SkIntToScalar(kCellSize) }
        };
        SkPoint pts2[] = {
            { 0, 0 },
            { 0, SkIntToScalar(kCellSize) }
        };
        constexpr SkColor4f colors[] = {
            SkColors::kRed, SkColors::kGreen, SkColors::kRed, SkColors::kGreen, SkColors::kRed
        };
        constexpr SkScalar pos[] = { 0, 0.25f, 0.5f, 0.75f, SK_Scalar1 };

        fLinearGrad1 = SkShaders::LinearGradient(pts1, {{colors, pos, SkTileMode::kClamp}, {}});
        fLinearGrad2 = SkShaders::LinearGradient(pts2, {{colors, pos, SkTileMode::kClamp}, {}});

        fPerspMatrix.reset();
        fPerspMatrix.setPerspY(SK_Scalar1 / 50);

        fPath = SkPathBuilder()
                .moveTo(0, 0)
                .lineTo(0, SkIntToScalar(kCellSize))
                .lineTo(kCellSize/2.0f, kCellSize/2.0f)
                .lineTo(SkIntToScalar(kCellSize), SkIntToScalar(kCellSize))
                .lineTo(SkIntToScalar(kCellSize), 0)
                .close()
                .detach();
    }

    void drawRow(SkCanvas* canvas, const SkSamplingOptions& sampling) {
        SkPaint filterPaint;
        filterPaint.setAntiAlias(fDoAA);

        SkPaint pathPaint;
        pathPaint.setShader(fBitmapImage->makeShader(sampling));
        pathPaint.setAntiAlias(fDoAA);

        SkPaint gradPaint1;
        gradPaint1.setShader(fLinearGrad1);
        gradPaint1.setAntiAlias(fDoAA);
        SkPaint gradPaint2;
        gradPaint2.setShader(fLinearGrad2);
        gradPaint2.setAntiAlias(fDoAA);

        SkRect r = SkRect::MakeWH(SkIntToScalar(kCellSize), SkIntToScalar(kCellSize));

        canvas->save();

        canvas->save();
        canvas->concat(fPerspMatrix);
        canvas->drawImageRect(fBitmapImage, r, sampling, &filterPaint);
        canvas->restore();

        canvas->translate(SkIntToScalar(kCellSize), 0);
        canvas->save();
        canvas->concat(fPerspMatrix);
        canvas->drawImage(fImage.get(), 0, 0, sampling, &filterPaint);
        canvas->restore();

        canvas->translate(SkIntToScalar(kCellSize), 0);
        canvas->save();
        canvas->concat(fPerspMatrix);
        canvas->drawRect(r, pathPaint);
        canvas->restore();

        canvas->translate(SkIntToScalar(kCellSize), 0);
        canvas->save();
        canvas->concat(fPerspMatrix);
        canvas->drawPath(fPath, pathPaint);
        canvas->restore();

        canvas->translate(SkIntToScalar(kCellSize), 0);
        canvas->save();
        canvas->concat(fPerspMatrix);
        canvas->drawRect(r, gradPaint1);
        canvas->restore();

        canvas->translate(SkIntToScalar(kCellSize), 0);
        canvas->save();
        canvas->concat(fPerspMatrix);
        canvas->drawPath(fPath, gradPaint2);
        canvas->restore();

        canvas->restore();
    }

    void onDraw(SkCanvas* canvas) override {
        if (!fImage || !fImage->isValid(canvas->baseRecorder())) {
            fImage = make_image(canvas, kCellSize, kCellSize);
        }

        this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kNearest));
        canvas->translate(0, SkIntToScalar(kCellSize));
        this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear));
        canvas->translate(0, SkIntToScalar(kCellSize));
        this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear,
                                                SkMipmapMode::kNearest));
        canvas->translate(0, SkIntToScalar(kCellSize));
        this->drawRow(canvas, SkSamplingOptions(SkCubicResampler::Mitchell()));
        canvas->translate(0, SkIntToScalar(kCellSize));
        this->drawRow(canvas, SkSamplingOptions::Aniso(16));
        canvas->translate(0, SkIntToScalar(kCellSize));
    }
private:
    inline static constexpr int kCellSize = 50;
    inline static constexpr int kNumRows = 5;
    inline static constexpr int kNumCols = 6;

    bool            fDoAA;
    SkPath          fPath;
    sk_sp<SkShader> fLinearGrad1;
    sk_sp<SkShader> fLinearGrad2;
    SkMatrix        fPerspMatrix;
    sk_sp<SkImage>  fImage;
    sk_sp<SkImage>  fBitmapImage;

    using INHERITED = GM;
};
DEF_GM(return new PerspShadersGM(true);)
DEF_GM(return new PerspShadersGM(false);)
}  // namespace skiagm

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

#include "tools/Resources.h"

static SkPath make_path() {
    SkRandom rand;
    auto rand_pt = [&rand]() {
        auto x = rand.nextF();
        auto y = rand.nextF();
        return SkPoint{x * 400, y * 400};
    };

    SkPathBuilder builder;
    for (int i = 0; i < 4; ++i) {
        SkPoint pts[6];
        for (auto& p : pts) {
            p = rand_pt();
        }
        builder.moveTo(pts[0])
               .quadTo(pts[1], pts[2])
               .quadTo(pts[3], pts[4]).lineTo(pts[5]);
    }
    return builder.detach();
}

DEF_SIMPLE_GM(perspective_clip, canvas, 800, 800) {
    SkPath path = make_path();
    auto shader = ToolUtils::GetResourceAsImage("images/mandrill_128.png")
                          ->makeShader(SkSamplingOptions(), SkMatrix::Scale(3, 3));

    SkPaint paint;
    paint.setColor({0.75, 0.75, 0.75, 1});
    canvas->drawPath(path, paint);

    // This is a crazy perspective matrix, derived from halfplanes3, to draw a shape where
    // part of it is "behind" the viewer, hence showing the need for "half-plane" clipping
    // when in perspective.
    SkMatrix mx;
    const SkScalar array[] = {
        -1.7866f,  1.3357f, 273.0295f,
        -1.0820f,  1.3186f, 135.5196f,
        -0.0047f, -0.0015f,  2.1485f,
    };
    mx.set9(array);

    paint.setShader(shader);
    canvas->concat(mx);
    canvas->drawPath(path, paint);
}
