/*
 * Copyright 2018 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/SkCanvas.h"
#include "include/core/SkImage.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTDArray.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"

#include <initializer_list>

using namespace skia_private;

static sk_sp<SkImage> make_image1() { return GetResourceAsImage("images/mandrill_128.png"); }

static sk_sp<SkImage> make_image2() {
    return GetResourceAsImage("images/brickwork-texture.jpg")->makeSubset({0, 0, 128, 128});
}

namespace skiagm {

class PerspImages : public GM {
public:
    PerspImages() = default;

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

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

    void onOnceBeforeDraw() override {
        fImages.push_back(make_image1());
        fImages.push_back(make_image2());
    }

    void onDraw(SkCanvas* canvas) override {
        SkTDArray<SkMatrix> matrices;
        matrices.append()->setAll(1.f, 0.f,    0.f,
                                0.f, 1.f,    0.f,
                                0.f, 0.005f, 1.f);
        matrices.append()->setAll(1.f,     0.f,    0.f,
                                0.f,     1.f,    0.f,
                                0.007f, -0.005f, 1.f);
        matrices[1].preSkew(0.2f, -0.1f);
        matrices[1].preRotate(-65.f);
        matrices[1].preScale(1.2f, .8f);
        matrices[1].postTranslate(0.f, 60.f);
        SkPaint paint;
        int n = 0;
        SkRect bounds = SkRect::MakeEmpty();
        for (const auto& img : fImages) {
            SkRect imgB = SkRect::MakeWH(img->width(), img->height());
            for (const auto& m : matrices) {
                SkRect temp;
                m.mapRect(&temp, imgB);
                bounds.join(temp);
            }
        }
        canvas->translate(-bounds.fLeft + 10.f, -bounds.fTop + 10.f);
        canvas->save();
        enum class DrawType {
            kDrawImage,
            kDrawImageRectStrict,
            kDrawImageRectFast,
        };
        for (auto type :
             {DrawType::kDrawImage, DrawType::kDrawImageRectStrict, DrawType::kDrawImageRectFast}) {
            for (const auto& m : matrices) {
                for (auto aa : {false, true}) {
                    paint.setAntiAlias(aa);
                    for (auto sampling : {
                        SkSamplingOptions(SkFilterMode::kNearest),
                        SkSamplingOptions(SkFilterMode::kLinear),
                        SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear),
                        SkSamplingOptions(SkCubicResampler::Mitchell())}) {
                        for (const auto& origImage : fImages) {
                            sk_sp<SkImage> img = ToolUtils::MakeTextureImage(canvas, origImage);
                            if (img) {
                                canvas->save();
                                canvas->concat(m);
                                SkRect src = { img->width() / 4.f, img->height() / 4.f,
                                               3.f * img->width() / 4.f, 3.f * img->height() / 4 };
                                SkRect dst = { 0, 0,
                                               3.f / 4.f * img->width(), 3.f / 4.f * img->height()};
                                switch (type) {
                                    case DrawType::kDrawImage:
                                        canvas->drawImage(img, 0, 0, sampling, &paint);
                                        break;
                                    case DrawType::kDrawImageRectStrict:
                                        canvas->drawImageRect(img, src, dst, sampling, &paint,
                                                              SkCanvas::kStrict_SrcRectConstraint);
                                        break;
                                    case DrawType::kDrawImageRectFast:
                                        canvas->drawImageRect(img, src, dst, sampling, &paint,
                                                              SkCanvas::kFast_SrcRectConstraint);
                                        break;
                                }
                                canvas->restore();
                            }
                            ++n;
                            if (n < 8) {
                                canvas->translate(bounds.width() + 10.f, 0);
                            } else {
                                canvas->restore();
                                canvas->translate(0, bounds.height() + 10.f);
                                canvas->save();
                                n = 0;
                            }
                        }
                    }
                }
            }
        }
        canvas->restore();
    }

private:
    inline static constexpr int kNumImages = 4;
    TArray<sk_sp<SkImage>> fImages;

    using INHERITED = GM;
};

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

DEF_GM(return new PerspImages();)

}  // namespace skiagm
