/*
 * 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.h"
#include "sk_tool_utils.h"
#include "SkBlendModePriv.h"
#include "SkCanvas.h"
#include "SkImage.h"
#include "SkMaskFilter.h"
#include "SkPictureRecorder.h"
#include "SkShaderMaskFilter.h"
#include "SkTextUtils.h"

static void draw_masked_image(SkCanvas* canvas, const SkImage* image, SkScalar x, SkScalar y,
                              const SkImage* mask, sk_sp<SkMaskFilter> outer, SkBlendMode mode) {
    SkMatrix matrix = SkMatrix::MakeScale(SkIntToScalar(image->width()) / mask->width(),
                                          SkIntToScalar(image->height() / mask->height()));
    SkPaint paint;
    auto mf = SkShaderMaskFilter::Make(mask->makeShader(&matrix));
    if (outer) {
        mf = SkMaskFilter::MakeCompose(outer, mf);
    }
    paint.setMaskFilter(mf);
    paint.setAntiAlias(true);
    paint.setBlendMode(mode);
    canvas->drawImage(image, x, y, &paint);
}

#include "SkGradientShader.h"
static sk_sp<SkShader> make_shader(const SkRect& r) {
    const SkPoint pts[] = {
        { r.fLeft, r.fTop }, { r.fRight, r.fBottom },
    };
    const SkColor colors[] = { 0, SK_ColorWHITE };
    return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kRepeat_TileMode);
}

DEF_SIMPLE_GM(shadermaskfilter_gradient, canvas, 512, 512) {
    SkRect r = { 0, 0, 100, 150 };
    auto shader = make_shader(r);
    auto mf = SkShaderMaskFilter::Make(shader);

    canvas->translate(20, 20);
    canvas->scale(2, 2);

    SkPaint paint;
    paint.setMaskFilter(mf);
    paint.setColor(SK_ColorRED);
    paint.setAntiAlias(true);
    canvas->drawOval(r, paint);
}

#include "Resources.h"
DEF_SIMPLE_GM(shadermaskfilter_image, canvas, 560, 370) {
    canvas->scale(1.25f, 1.25f);

    auto image = GetResourceAsImage("images/mandrill_128.png");
    auto mask = GetResourceAsImage("images/color_wheel.png");
    if (!image || !mask) {
        skiagm::GM::DrawFailureMessage(canvas, "Could not load images. "
                                               "Did you forget to set the resourcePath?");
        return;
    }
    auto blurmf = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5);
    auto gradmf = SkShaderMaskFilter::Make(make_shader(SkRect::MakeIWH(mask->width(),
                                                                       mask->height())));

    const sk_sp<SkMaskFilter> array[] = { nullptr , blurmf, gradmf };
    for (SkBlendMode mode : {SkBlendMode::kSrcOver, SkBlendMode::kSrcIn}) {
        canvas->save();
        for (sk_sp<SkMaskFilter> mf : array) {
            draw_masked_image(canvas, image.get(), 10, 10, mask.get(), mf, mode);
            canvas->translate(image->width() + 20.f, 0);
        }
        canvas->restore();
        canvas->translate(0, image->height() + 20.f);
    }
}

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

#include "SkPictureRecorder.h"
#include "SkPath.h"

static sk_sp<SkMaskFilter> make_path_mf(const SkPath& path, unsigned alpha) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setAlpha(alpha);

    SkPictureRecorder recorder;
    recorder.beginRecording(1000, 1000)->drawPath(path, paint);
    auto shader = SkShader::MakePictureShader(recorder.finishRecordingAsPicture(),
                                              SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
                                              nullptr, nullptr);
    return SkShaderMaskFilter::Make(shader);
}

typedef void (*MakePathsProc)(const SkRect&, SkPath*, SkPath*);

const char* gCoverageName[] = {
    "union", "sect", "diff", "rev-diff", "xor"
};

DEF_SIMPLE_GM(combinemaskfilter, canvas, 560, 510) {
    const SkRect r = { 0, 0, 100, 100 };

    SkPaint paint;
    paint.setColor(SK_ColorRED);

    SkFont font;
    font.setSize(20);

    const SkRect r2 = r.makeOutset(1.5f, 1.5f);
    SkPaint strokePaint;
    strokePaint.setStyle(SkPaint::kStroke_Style);

    auto proc0 = [](const SkRect& r, SkPath* pathA, SkPath* pathB) {
        pathA->moveTo(r.fLeft, r.fBottom);
        pathA->lineTo(r.fRight, r.fTop);
        pathA->lineTo(r.fRight, r.fBottom);
        pathB->moveTo(r.fLeft, r.fTop);
        pathB->lineTo(r.fRight, r.fBottom);
        pathB->lineTo(r.fLeft, r.fBottom);
    };
    auto proc1 = [](const SkRect& r, SkPath* pathA, SkPath* pathB) {
        pathA->addCircle(r.width()*0.25f, r.height()*0.25f, r.width()*0.5f);
        pathB->addCircle(r.width()*0.75f, r.height()*0.75f, r.width()*0.5f);
    };
    MakePathsProc procs[] = { proc0, proc1 };

    sk_sp<SkMaskFilter> mfA[2], mfB[2];
    for (int i = 0; i < 2; ++i) {
        SkPath a, b;
        procs[i](r, &a, &b);
        mfA[i] = make_path_mf(a, 1 * 0xFF / 3);
        mfB[i] = make_path_mf(b, 2 * 0xFF / 3);
    }

    canvas->translate(10, 10 + 20);
    canvas->save();
    for (int i = 0; i < 5; ++i) {
        SkTextUtils::DrawString(canvas, gCoverageName[i], r.width()*0.5f, -10, font, SkPaint(),
                                       SkTextUtils::kCenter_Align);

        SkCoverageMode cmode = static_cast<SkCoverageMode>(i);
        canvas->save();
        // esp. on gpu side, its valuable to exercise modes that do and do-not convolve coverage
        // with alpha. SrcOver and SrcIn have these properties, but also happen to "look" the same
        // for this test.
        const SkBlendMode bmodes[] = { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn };
        SkASSERT( SkBlendMode_SupportsCoverageAsAlpha(bmodes[0]));  // test as-alpha
        SkASSERT(!SkBlendMode_SupportsCoverageAsAlpha(bmodes[1]));  // test not-as-alpha
        for (auto bmode : bmodes) {
            paint.setBlendMode(bmode);
            for (int j = 0; j < 2; ++j) {
                paint.setMaskFilter(SkMaskFilter::MakeCombine(mfA[j], mfB[j], cmode));
                canvas->drawRect(r2, strokePaint);
                canvas->drawRect(r, paint);
                canvas->translate(0, r.height() + 10);
            }
            canvas->translate(0, 40);
        }
        canvas->restore();
        canvas->translate(r.width() + 10, 0);
    }
    canvas->restore();
}

#include "SkSurface.h"
#include "SkBlurImageFilter.h"
#include "SkMaskFilter.h"
static sk_sp<SkImage> make_circle_image(SkCanvas* canvas, SkScalar radius, int margin) {
    const int n = SkScalarCeilToInt(radius) * 2 + margin * 2;
    auto surf = sk_tool_utils::makeSurface(canvas, SkImageInfo::MakeN32Premul(n, n));
    SkPaint paint;
    paint.setAntiAlias(true);
    surf->getCanvas()->drawCircle(n * 0.5f, n * 0.5f, radius, paint);
    return surf->makeImageSnapshot();
}

DEF_SIMPLE_GM(savelayer_maskfilter, canvas, 450, 675) {
    auto layerImage = GetResourceAsImage("images/mandrill_128.png");
    auto maskImage = make_circle_image(canvas, 50, 1);
    SkRect r = SkRect::MakeWH(102, 102);

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

    // test that the maskfilter sees these changes to the ctm
    canvas->translate(10, 10);
    canvas->scale(2, 2);

    sk_sp<SkMaskFilter> mfs[] = {
        SkShaderMaskFilter::Make(maskImage->makeShader()),
        SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 3.5f),
        nullptr,
    };
    mfs[2] = SkMaskFilter::MakeCompose(mfs[1], mfs[0]);

    // Important that we test with and without an imagefilter attached to the layer,
    // as cpu and gpu backends treat these differently (w/ or w/o a SkSpecialImage)
    const sk_sp<SkImageFilter> imfs[] = {nullptr, SkBlurImageFilter::Make(3.5f, 3.5f, nullptr)};

    for (auto& mf : mfs) {
        SkPaint layerPaint;
        layerPaint.setMaskFilter(mf);
        canvas->save();
        for (auto& imf : imfs) {
            layerPaint.setImageFilter(imf);

            canvas->saveLayer(&r, &layerPaint);
            canvas->drawImage(layerImage, 0, 0, nullptr);
            canvas->restore();

            // now draw the (approximage) expected bounds of the mask
            canvas->drawRect(r.makeOutset(1, 1), overlayPaint);

            canvas->translate(r.width() + 10, 0);
        }
        canvas->restore();
        canvas->translate(0, r.height() + 10);
    }
}

static void draw_mask(SkCanvas* canvas) {
    SkPaint p;
    p.setAntiAlias(true);
    canvas->drawOval(SkRect::Make(canvas->imageInfo().bounds()), p);
}

DEF_SIMPLE_GM(shadermaskfilter_localmatrix, canvas, 1500, 1000) {
    static constexpr SkScalar kSize = 100;

    using ShaderMakerT = sk_sp<SkShader>(*)(SkCanvas*, const SkMatrix& lm);
    static const ShaderMakerT gShaderMakers[] = {
        [](SkCanvas* canvas, const SkMatrix& lm) -> sk_sp<SkShader> {
            auto surface = sk_tool_utils::makeSurface(canvas,
                                                      SkImageInfo::MakeN32Premul(kSize, kSize));
            draw_mask(surface->getCanvas());
            return surface->makeImageSnapshot()->makeShader(SkShader::kClamp_TileMode,
                                                            SkShader::kClamp_TileMode, &lm);
        },
        [](SkCanvas*, const SkMatrix& lm) -> sk_sp<SkShader> {
            SkPictureRecorder recorder;
            draw_mask(recorder.beginRecording(kSize, kSize));
            return SkShader::MakePictureShader(recorder.finishRecordingAsPicture(),
                                               SkShader::kClamp_TileMode,
                                               SkShader::kClamp_TileMode,
                                               &lm, nullptr);
        },
    };

    struct Config {
        SkMatrix fCanvasMatrix,
                 fMaskMatrix,
                 fShaderMatrix;
    } gConfigs[] = {
        { SkMatrix::I(), SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10) },
        { SkMatrix::MakeScale(2, 2), SkMatrix::I(), SkMatrix::MakeTrans(10, 10) },
        { SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10), SkMatrix::I() },
        { SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)),
          SkMatrix::I(), SkMatrix::I() },
        { SkMatrix::I(),
          SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)),
          SkMatrix::I() },
        { SkMatrix::I(), SkMatrix::I(),
          SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)) },
    };

    using DrawerT = void(*)(SkCanvas*, const SkRect&, const SkPaint&);
    static const DrawerT gDrawers[] = {
        [](SkCanvas* canvas, const SkRect& dest, const SkPaint& mask) {
            canvas->drawRect(dest, mask);
        },
        [](SkCanvas* canvas, const SkRect& dest, const SkPaint& mask) {
            canvas->saveLayer(&dest, &mask);
            SkPaint p = mask;
            p.setMaskFilter(nullptr);
            canvas->drawPaint(p);
            canvas->restore();
        },
    };

    SkPaint paint, rectPaint;
    paint.setColor(0xff00ff00);
    rectPaint.setStyle(SkPaint::kStroke_Style);
    rectPaint.setColor(0xffff0000);

    for (const auto& sm : gShaderMakers) {
        for (const auto& drawer : gDrawers) {
            {
                SkAutoCanvasRestore acr(canvas, true);
                for (const auto& cfg : gConfigs) {
                    paint.setMaskFilter(SkShaderMaskFilter::Make(sm(canvas, cfg.fShaderMatrix))
                                        ->makeWithMatrix(cfg.fMaskMatrix));
                    auto dest = SkRect::MakeWH(kSize, kSize);
                    SkMatrix::Concat(cfg.fMaskMatrix, cfg.fShaderMatrix).mapRect(&dest);

                    {
                        SkAutoCanvasRestore acr(canvas, true);
                        canvas->concat(cfg.fCanvasMatrix);
                        drawer(canvas, dest, paint);
                        canvas->drawRect(dest, rectPaint);
                    }

                    canvas->translate(kSize * 2.5f, 0);
                }
            }
            canvas->translate(0, kSize * 2.5f);
        }

    }
}
