/*
 * Copyright 2013 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 "SkCanvas.h"
#include "SkBlurImageFilter.h"
#include "SkRSXform.h"
#include "SkSurface.h"

static void make_bm(SkBitmap* bm) {
    bm->allocN32Pixels(100, 100);
    bm->eraseColor(SK_ColorBLUE);

    SkCanvas canvas(*bm);
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorRED);
    canvas.drawCircle(50, 50, 50, paint);
}

static void draw_2_bitmaps(SkCanvas* canvas, const SkBitmap& bm, bool doClip,
                           int dx, int dy, SkImageFilter* filter = nullptr) {
    SkAutoCanvasRestore acr(canvas, true);
    SkPaint paint;

    SkRect clipR = SkRect::MakeXYWH(SkIntToScalar(dx),
                                    SkIntToScalar(dy),
                                    SkIntToScalar(bm.width()),
                                    SkIntToScalar(bm.height()));

    paint.setImageFilter(filter);
    clipR.inset(5, 5);

    if (doClip) {
        canvas->save();
        canvas->clipRect(clipR);
    }
    canvas->drawSprite(bm, dx, dy, &paint);
    if (doClip) {
        canvas->restore();
    }

    canvas->translate(SkIntToScalar(bm.width() + 20), 0);

    if (doClip) {
        canvas->save();
        canvas->clipRect(clipR);
    }
    canvas->drawBitmap(bm, SkIntToScalar(dx), SkIntToScalar(dy), &paint);
    if (doClip) {
        canvas->restore();
    }
}

/**
 *  Compare output of drawSprite and drawBitmap (esp. clipping and imagefilters)
 */
class SpriteBitmapGM : public skiagm::GM {
public:
    SpriteBitmapGM() {}

protected:

    SkString onShortName() override {
        return SkString("spritebitmap");
    }

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

    void onDraw(SkCanvas* canvas) override {
        SkBitmap bm;
        make_bm(&bm);

        int dx = 10;
        int dy = 10;

        SkScalar sigma = 8;
        SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(sigma, sigma));

        draw_2_bitmaps(canvas, bm, false, dx, dy);
        dy += bm.height() + 20;
        draw_2_bitmaps(canvas, bm, false, dx, dy, filter);
        dy += bm.height() + 20;
        draw_2_bitmaps(canvas, bm, true, dx, dy);
        dy += bm.height() + 20;
        draw_2_bitmaps(canvas, bm, true, dx, dy, filter);
    }

private:
    typedef GM INHERITED;
};
DEF_GM( return new SpriteBitmapGM; )

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

#include "SkColorFilterImageFilter.h"
#include "SkModeColorFilter.h"
#include "SkMorphologyImageFilter.h"
#include "SkOffsetImageFilter.h"

static SkImage* make_image(SkCanvas* rootCanvas) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
    SkAutoTUnref<SkSurface> surface(rootCanvas->newSurface(info));
    if (!surface) {
        surface.reset(SkSurface::NewRaster(info));
    }

    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorRED);
    surface->getCanvas()->drawCircle(50, 50, 50, paint);
    return surface->newImageSnapshot();
}

static void show_image(SkCanvas* canvas, SkImage* image, const SkIPoint& offset) {
    SkScalar x = SkIntToScalar(offset.x());
    SkScalar y = SkIntToScalar(offset.y());

    SkPaint paint;
    paint.setStyle(SkPaint::kStroke_Style);

    SkRect r = SkRect::MakeIWH(image->width(), image->height());
    r.offset(x, y);
    // get on pixel-centers to make the hairline land on a numerical stable boundary
    r.outset(SK_ScalarHalf, SK_ScalarHalf);
    canvas->drawRect(r, paint);

    canvas->drawImage(image, x, y, nullptr);
}

typedef SkImageFilter* (*ImageFilterFactory)();

// +[]{...} did not work on windows (VS)
// (ImageFilterFactory)[]{...} did not work on linux (gcc)
// hence this cast function
template <typename T> ImageFilterFactory IFCCast(T arg) { return arg; }

// We expect that applying the filter will keep us in the same domain (raster or gpu)
static void check_same_domain(SkImage* a, SkImage* b) {
    SkASSERT(a->isTextureBacked() == b->isTextureBacked());
}

/**
 *  Compare output of drawSprite and drawBitmap (esp. clipping and imagefilters)
 */
class ApplyFilterGM : public skiagm::GM {
public:
    ApplyFilterGM() {}

protected:
    SkString onShortName() override {
        return SkString("apply-filter");
    }

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

    void onDraw(SkCanvas* canvas) override {
        SkAutoTUnref<SkImage> image0(make_image(canvas));

        const ImageFilterFactory factories[] = {
            IFCCast([]{ return SkBlurImageFilter::Create(8, 8); }),
            IFCCast([]{ SkAutoTUnref<SkColorFilter> cf(SkModeColorFilter::Create(SK_ColorBLUE,
                                                                     SkXfermode::kSrcIn_Mode));
                 return SkColorFilterImageFilter::Create(cf);
            }),
            IFCCast([]{ return SkDilateImageFilter::Create(8, 8); }),
            IFCCast([]{ return SkErodeImageFilter::Create(8, 8); }),
            IFCCast([]{ return SkOffsetImageFilter::Create(8, 8); }),
        };

        const SkScalar spacer = image0->width() * 3.0f / 2;

        for (auto&& factory : factories) {
            SkAutoTUnref<SkImageFilter> filter(factory());

            SkIPoint offset1, offset2;
            SkAutoTUnref<SkImage> image1(image0->applyFilter(filter, &offset1, true));
            SkAutoTUnref<SkImage> image2(image0->applyFilter(filter, &offset2, false));

            check_same_domain(image0, image1);
            check_same_domain(image0, image2);

            canvas->save();
            canvas->translate(30, 30);
            show_image(canvas, image0, SkIPoint::Make(0, 0));   // original
            canvas->translate(spacer, 0);
            show_image(canvas, image1, offset1);                // snug
            canvas->translate(spacer, 0);
            show_image(canvas, image2, offset2);                // not snug

            // Try drawing the original w/ the filter, to see that it "draws" the same as
            // when we have manually applied the filter (above).
            {
                SkPaint paint;
                paint.setImageFilter(filter);

                SkBitmap bm;
                image0->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode);
                SkPoint loc = { 0, 0 };
                canvas->translate(spacer, 0);
                canvas->getTotalMatrix().mapPoints(&loc, 1);
                canvas->drawSprite(bm, (int)loc.x(), (int)loc.y(), &paint); // like snug

                canvas->translate(spacer, 0);
                canvas->drawImage(image0, 0, 0, &paint);        // like not snug
            }
            canvas->restore();

            canvas->translate(0, spacer);
        }
    }

private:
    typedef GM INHERITED;
};
DEF_GM( return new ApplyFilterGM; )

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

#include "SkDisplacementMapEffect.h"
#include "SkMatrixConvolutionImageFilter.h"

static SkPMColor max_component(SkPMColor a, SkPMColor b) {
    int dr = SkAbs32(SkGetPackedR32(a) - SkGetPackedR32(b));
    int dg = SkAbs32(SkGetPackedG32(a) - SkGetPackedG32(b));
    int db = SkAbs32(SkGetPackedB32(a) - SkGetPackedB32(b));
    int d = SkTMax(dr, SkTMax(dg, db));
    d = 0xFF - d;
    return SkPackARGB32(0xFF, d, d, d);
}

static SkImage* compute_diff(SkImage* a, SkImage* b) {
    SkASSERT(a->width() == b->width() && a->height() == b->height());
    const SkImageInfo info = SkImageInfo::MakeN32Premul(a->width(), a->height());
    SkBitmap bma, bmb, bmdiff;
    bma.allocPixels(info);
    bmb.allocPixels(info);
    bmdiff.allocPixels(info);

    a->readPixels(info, bma.getPixels(), bma.rowBytes(), 0, 0);
    b->readPixels(info, bmb.getPixels(), bmb.rowBytes(), 0, 0);
    for (int y = 0; y < info.height(); ++y) {
        for (int x = 0; x < info.width(); ++x) {
            *bmdiff.getAddr32(x, y) = max_component(*bma.getAddr32(x, y), *bmb.getAddr32(x, y));
        }
    }
    bmdiff.setImmutable();  // avoid the copy
    return SkImage::NewFromBitmap(bmdiff);
}

static SkImage* make_native_red_oval(SkCanvas* rootCanvas) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(160, 90);
    SkAutoTUnref<SkSurface> surface(rootCanvas->newSurface(info));
    if (!surface) {
        surface.reset(SkSurface::NewRaster(info));
    }

    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorRED);
    surface->getCanvas()->drawOval(SkRect::MakeWH(160, 90), paint);
    return surface->newImageSnapshot();
}


static SkSurface* make_surface(SkCanvas* factory, const SkImageInfo& info) {
    SkSurface* surface = factory->newSurface(info);
    if (!surface) {
        surface = SkSurface::NewRaster(info);
    }
    return surface;
}

template <typename DrawProc> SkImage* snapshot(SkCanvas* canvas, const SkImageInfo& info,
                                               DrawProc p) {
    SkAutoTUnref<SkSurface> surface(make_surface(canvas, info));
    p(surface->getCanvas());
    return surface->newImageSnapshot();
}

/**
 *  Try drawing an image+imagefilter in two different ways
 *  1. as drawSprite
 *  2. as drawImage + clipped to image bounds
 *  The two should draw the same. To try to visualize this, we draw a 4th column of the difference
 *  between the two versions. If it is all black (where there is alpha), they drew the same!
 */
class DrawWithFilterGM : public skiagm::GM {
public:
    DrawWithFilterGM() {}

protected:
    SkString onShortName() override {
        return SkString("draw-with-filter");
    }

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

    void onDraw(SkCanvas* canvas) override {
        SkAutoTUnref<SkImage> image0(make_native_red_oval(canvas));
        SkAutoTUnref<SkImage> image1(make_native_red_oval(canvas));

        const ImageFilterFactory factories[] = {
            IFCCast([]{ return SkBlurImageFilter::Create(8, 8); }),
            IFCCast([]{ SkAutoTUnref<SkColorFilter> cf(SkModeColorFilter::Create(SK_ColorBLUE,
                                                                         SkXfermode::kSrcIn_Mode));
                return SkColorFilterImageFilter::Create(cf);
            }),
            IFCCast([]{ return SkDilateImageFilter::Create(8, 8); }),
            IFCCast([]{ return SkErodeImageFilter::Create(8, 8); }),
            IFCCast([]{ return SkOffsetImageFilter::Create(8, 8); }),

            IFCCast([]{ return (SkImageFilter*)SkDisplacementMapEffect::Create(
                                                   SkDisplacementMapEffect::kR_ChannelSelectorType,
                                                   SkDisplacementMapEffect::kG_ChannelSelectorType,
                                                   10, nullptr); }),
            IFCCast([]{
                const SkScalar kernel[] = { 1, 1, 1, 1, -7, 1, 1, 1, 1 };
                return (SkImageFilter*)SkMatrixConvolutionImageFilter::Create(
                                                  SkISize::Make(3, 3),
                                                  kernel, 1, 0,
                                                  SkIPoint::Make(0, 0),
                                                  SkMatrixConvolutionImageFilter::kClamp_TileMode,
                                                  true); }),
        };

        const SkScalar dx = 180;
        const SkScalar dy = 110;
        const SkImageInfo info = SkImageInfo::MakeN32Premul(image0->width(), image0->height());

        canvas->translate(20, 20);
        for (auto&& factory : factories) {
            SkAutoTUnref<SkImageFilter> filter(factory());
            SkPaint paint;
            paint.setImageFilter(filter);

            SkAutoTUnref<SkImage> snap0(snapshot(canvas, info, [&](SkCanvas* c) {
                c->drawImage(image0, 0, 0, &paint);
            }));
            canvas->drawImage(snap0, 0, 0);

            SkAutoTUnref<SkImage> snap1(snapshot(canvas, info, [&](SkCanvas* c) {
                SkBitmap bm;
                image1->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode);
                c->drawSprite(bm, 0, 0, &paint);
            }));
            canvas->drawImage(snap1, dx, 0);

            SkAutoTUnref<SkImage> diff(snapshot(canvas, info, [&](SkCanvas* c) {
                SkAutoTUnref<SkImage> diff(compute_diff(snap0, snap1));
                c->drawImage(diff, 0, 0);
            }));
            canvas->drawImage(diff, 2*dx, 0);

            canvas->translate(0, dy);
        }
    }
    
private:
    typedef GM INHERITED;
};
DEF_GM( return new DrawWithFilterGM; )

