/*
 * 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 "SkShaderMaskFilter.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");
    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);

    SkPaint labelP;
    labelP.setAntiAlias(true);
    labelP.setTextSize(20);
    labelP.setTextAlign(SkPaint::kCenter_Align);

    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) {
        canvas->drawText(gCoverageName[i], strlen(gCoverageName[i]), r.width()*0.5f, -10, labelP);

        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);
    }
}

