/*
 * Copyright 2017 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/SkColorPriv.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkImageFilters.h"
#include "include/gpu/GrTypes.h"

#include <utility>

static sk_sp<SkImage> make_image(GrRecordingContext* context, int size, GrSurfaceOrigin origin) {
    if (context) {
        SkImageInfo ii = SkImageInfo::Make(size, size, kN32_SkColorType, kPremul_SkAlphaType);
        sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, 0,
                                                          origin, nullptr));
        if (surf) {
            SkCanvas* canvas = surf->getCanvas();

            canvas->clear(SK_ColorRED);
            const struct {
                SkPoint fPt;
                SkColor fColor;
            } rec[] = {
                { { 1.5f, 1.5f }, SK_ColorGREEN },
                { { 2.5f, 1.5f }, SK_ColorBLUE },
                { { 1.5f, 2.5f }, SK_ColorCYAN },
                { { 2.5f, 2.5f }, SK_ColorGRAY },
            };
            SkPaint paint;
            for (const auto& r : rec) {
                paint.setColor(r.fColor);
                canvas->drawPoints(SkCanvas::kPoints_PointMode, 1, &r.fPt, paint);
            }
            return surf->makeImageSnapshot();
        }
    }

    SkBitmap bm;
    bm.allocN32Pixels(size, size);
    bm.eraseColor(SK_ColorRED);
    *bm.getAddr32(1, 1) = SkPackARGB32(0xFF, 0x00, 0xFF, 0x00);
    *bm.getAddr32(2, 1) = SkPackARGB32(0xFF, 0x00, 0x00, 0xFF);
    *bm.getAddr32(1, 2) = SkPackARGB32(0xFF, 0x00, 0xFF, 0xFF);
    *bm.getAddr32(2, 2) = SkPackARGB32(0xFF, 0x88, 0x88, 0x88);
    return bm.asImage();
}

/*
 * This GM creates an image with a 2x2:
 *    Green | Blue
 *    ------------
 *    Cyan  | Gray
 * block of pixels in one corner of a 33x33 field. The 'srcRect' feature of the
 * SkMagnifierImageFilter is then used to blow it up with different inset border widths.
 *
 * In GPU-mode we wind up drawing 4 rects:
 *
 *     BottomLeft origin + 1-wide inset | TopLeft origin + 1-wide inset
 *     ----------------------------------------------------------------
 *     BottomLeft origin + 7-wide inset | TopLeft origin + 7-wide inset
 *
 * In Raster-mode the source origin isn't used.
 */
class SimpleMagnificationGM : public skiagm::GM {
public:
    SimpleMagnificationGM() {
        this->setBGColor(0xFFCCCCCC);
    }

protected:
    SkString onShortName() override {
        return SkString("simple-magnification");
    }

    SkISize onISize() override {
        return SkISize::Make(3*kPad+2*kImgSize, 3*kPad+2*kImgSize);
    }

    void draw(SkCanvas* canvas, sk_sp<SkImage> image, const SkIPoint& offset, int inset) {
        sk_sp<SkImageFilter> imgSrc(SkImageFilters::Image(std::move(image)));

        SkRect srcRect = SkRect::MakeXYWH(1.0f, 1.0f, 2.0f, 2.0f);
        sk_sp<SkImageFilter> magFilter(SkImageFilters::Magnifier(srcRect, inset, imgSrc));

        SkPaint paint;
        paint.setImageFilter(std::move(magFilter));

        canvas->save();
        canvas->translate(offset.fX, offset.fY);
        SkRect rect = SkRect::MakeWH(kImgSize, kImgSize);
        canvas->drawRect(rect, paint);

        canvas->restore();
    }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        auto context = canvas->recordingContext();

        sk_sp<SkImage> bottomLImg = make_image(context, kImgSize, kBottomLeft_GrSurfaceOrigin);
        sk_sp<SkImage> topLImg = make_image(context, kImgSize, kTopLeft_GrSurfaceOrigin);
        if (!bottomLImg || !topLImg) {
            *errorMsg = "Could not load images. Did you forget to set the resourcePath?";
            return DrawResult::kFail;
        }

        int bigOffset = 2 * kPad + kImgSize;

        this->draw(canvas, bottomLImg, SkIPoint::Make(kPad, kPad), 1);
        this->draw(canvas, topLImg, SkIPoint::Make(bigOffset, kPad), 1);
        this->draw(canvas, bottomLImg, SkIPoint::Make(kPad, bigOffset), 7);
        this->draw(canvas, topLImg, SkIPoint::Make(bigOffset, bigOffset), 7);
        return DrawResult::kOk;
    }

private:
    static const int kImgSize = 33;
    static const int kPad = 2;

    using INHERITED = skiagm::GM;
};

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

DEF_GM(return new SimpleMagnificationGM;)
