/*
 * 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.h"
#include "SkImage.h"
#include "SkImageGenerator.h"
#include "SkMutex.h"
#include "SkSurface.h"
#include "SkTArray.h"

namespace {

void release_proc(void*, void* releaseCtx) {
    reinterpret_cast<SkImage*>(releaseCtx)->unref();
}

class ExternalGenerator : public SkImageGenerator {
public:
    ExternalGenerator(const SkISize size)
        : INHERITED(SkImageInfo::MakeN32Premul(size.width(), size.height())) {

        int level = 0;
        for (int size = kMaxSize; size; size /= 2) {
            sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(size, size);
            DrawRings(surface->getCanvas(), 0xff008000, level++);
            fMips.emplace_back(surface->makeImageSnapshot());
        }
    }

    virtual ~ExternalGenerator() {}

protected:
    bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
                     SkPMColor[], int*) override {
        sk_sp<SkSurface> s = SkSurface::MakeRasterDirect(info, pixels, rowBytes);
        s->getCanvas()->clear(SK_ColorTRANSPARENT);
        DrawRings(s->getCanvas(), SK_ColorRED);
        return true;
    }

    bool onAccessScaledImage(const SkRect& src, const SkMatrix& matrix, SkFilterQuality,
                             ScaledImageRec* rec) override {
        // Not strictly needed for this immutable class.
        SkAutoExclusive lock(fMutex);

        SkSize scaleSize;
        if (!matrix.decomposeScale(&scaleSize, nullptr)) {
            return false;
        }
        scaleSize.set(scaleSize.width()  * this->getInfo().width()  / kMaxSize,
                      scaleSize.height() * this->getInfo().height() / kMaxSize);

        const SkScalar scale = SkTMin(scaleSize.width(), scaleSize.height());
        const int lvl = SkScalarFloorToInt(-SkScalarLog2(scale));

        const sk_sp<SkImage>& img = fMips[SkTPin(lvl, 0, fMips.count())];
        SkAssertResult(img->peekPixels(&rec->fPixmap));

        const SkRect origBounds = SkRect::Make(this->getInfo().bounds());
        const SkRect  newBounds = SkRect::Make(img->bounds());

        SkMatrix srcMap = SkMatrix::MakeScale(newBounds.width()  / origBounds.width(),
                                              newBounds.height() / origBounds.height());
        srcMap.preTranslate(src.x(), src.y());
        srcMap.mapRect(&rec->fSrcRect, SkRect::MakeWH(src.width(), src.height()));

        rec->fQuality = kLow_SkFilterQuality;

        rec->fReleaseProc = release_proc;
        rec->fReleaseCtx  = SkRef(img.get());

        return true;
    }

private:
    static void DrawRings(SkCanvas* c, SkColor color, int lvl = 0) {
        static constexpr SkScalar kStep = 0.2f;

        SkRect rect = SkRect::MakeWH(1, 1);

        SkPaint p;
        p.setStyle(SkPaint::kStroke_Style);
        p.setStrokeWidth(0.02f);
        p.setAntiAlias(true);
        p.setColor(color);

        c->concat(SkMatrix::MakeRectToRect(SkRect::MakeWH(1, 1),
                                           SkRect::MakeIWH(c->imageInfo().width(),
                                                           c->imageInfo().height()),
                                           SkMatrix::kFill_ScaleToFit));
        while (!rect.isEmpty()) {
            c->drawRect(rect, p);
            rect.inset(kStep, kStep);
        }

        static constexpr SkScalar kTxtSize = 0.2f;
        SkASSERT(lvl >= 0 && lvl <= 9);
        const char label = '0' + lvl;
        p.setTextSize(kTxtSize);
        p.setLinearText(true);
        p.setStyle(SkPaint::kFill_Style);
        SkRect labelBounds;
        p.measureText(&label, 1, &labelBounds);

        c->drawText(&label, 1, 0.5f - labelBounds.width() / 2, 0.5f + labelBounds.height() / 2, p);
    }

    SkMutex fMutex;

    static constexpr int kMaxSize = 512;
    SkTArray<sk_sp<SkImage>> fMips;

    typedef SkImageGenerator INHERITED;
};

} // anonymous ns

class ImageGenExternalGM : public skiagm::GM {
public:
    explicit ImageGenExternalGM(bool useShader) : fUseShader(useShader) {}

protected:
    SkString onShortName() override {
        return SkStringPrintf("ImageGeneratorExternal%s", fUseShader ? "_shader" : "_rect");
    }

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

    void onOnceBeforeDraw() override {
        fImage = SkImage::MakeFromGenerator(new ExternalGenerator(SkISize::Make(kGeneratorSize,
                                                                                kGeneratorSize)));
    }

    void onDraw(SkCanvas* canvas) override {
        static const SkRect gSubsets[] = {
            SkRect::MakeLTRB(0    , 0    , 1    , 1    ),
            SkRect::MakeLTRB(0    , 0    , 0.5f , 0.5f ),
            SkRect::MakeLTRB(0.5f , 0    , 1    , 0.5f ),
            SkRect::MakeLTRB(0.5f , 0.5f , 1    , 1    ),
            SkRect::MakeLTRB(0    , 0.5f , 0.5f , 1    ),
            SkRect::MakeLTRB(0.25f, 0.25f, 0.75f, 0.75f),
        };

        SkPaint p;
        p.setFilterQuality(kLow_SkFilterQuality);

        for (int i = 1; i <= 4; ++i) {
            const SkRect dst = SkRect::MakeIWH(kGeneratorSize / i, kGeneratorSize / i);

            canvas->save();
            for (size_t j = 0; j < SK_ARRAY_COUNT(gSubsets); ++j) {
                SkRect subset = gSubsets[j];
                subset.set(kGeneratorSize * subset.left(),
                           kGeneratorSize * subset.top(),
                           kGeneratorSize * subset.right(),
                           kGeneratorSize * subset.bottom());
                this->drawSubset(canvas, subset, dst, p);
                canvas->translate(kGeneratorSize * 1.1f, 0);
            }
            canvas->restore();
            canvas->translate(0, dst.height() * 1.2f);
        }
    }

private:
    void drawSubset(SkCanvas* canvas, const SkRect& src, const SkRect& dst,
                    const SkPaint& paint) const {
        if (fUseShader) {
            SkPaint p(paint);
            SkMatrix localMatrix = SkMatrix::MakeRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
            p.setShader(fImage->makeShader(SkShader::kClamp_TileMode,
                                           SkShader::kClamp_TileMode,
                                           &localMatrix));
            canvas->drawRect(dst, p);
        } else {
            canvas->drawImageRect(fImage, src, dst, &paint);
        }
    }

    static constexpr int kGeneratorSize = 200;
    sk_sp<SkImage> fImage;
    bool           fUseShader;

    typedef skiagm::GM INHERITED;
};

DEF_GM( return new ImageGenExternalGM(false); )
DEF_GM( return new ImageGenExternalGM(true); )
