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

#include <initializer_list>

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;
    SkTArray<sk_sp<SkImage>> fImages;

    using INHERITED = GM;
};

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

DEF_GM(return new PerspImages();)

}  // namespace skiagm
