/*
 * Copyright 2019 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/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "include/effects/SkImageFilters.h"
#include "src/core/SkCanvasPriv.h"

#include <initializer_list>

// Make a noisy (with hard-edges) background, so we can see the effect of the blur
//
static sk_sp<SkShader> make_shader(SkScalar cx, SkScalar cy, SkScalar rad) {
    const SkColor colors[] = {
        SK_ColorRED, SK_ColorRED, SK_ColorBLUE, SK_ColorBLUE, SK_ColorGREEN, SK_ColorGREEN,
        SK_ColorRED, SK_ColorRED, SK_ColorBLUE, SK_ColorBLUE, SK_ColorGREEN, SK_ColorGREEN,
    };
    constexpr int count = std::size(colors);
    SkScalar pos[count] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6 };
    for (int i = 0; i < count; ++i) {
        pos[i] *= 1.0f/6;
    }
    return SkGradientShader::MakeSweep(cx, cy, colors, pos, count);
}

static void do_draw(SkCanvas* canvas, bool useClip, bool useHintRect, SkScalar scaleFactor) {
    SkAutoCanvasRestore acr(canvas, true);
    canvas->clipRect({0, 0, 256, 256});

    const SkScalar cx = 128, cy = 128, rad = 100;
    SkPaint p;
    p.setShader(make_shader(cx, cy, rad));
    p.setAntiAlias(true);
    canvas->drawCircle(cx, cy, rad, p);

    // now setup a saveLayer that will pull in the backdrop and blur it
    //
    const SkRect r = {cx-50, cy-50, cx+50, cy+50};
    const SkRect* drawrptr = useHintRect ? &r : nullptr;
    const SkScalar sigma = 10;
    if (useClip) {
        canvas->clipRect(r);
    }
    // Using kClamp because kDecal, the default, produces transparency near the edge of the canvas's
    // device.
    auto blur = SkImageFilters::Blur(sigma, sigma, SkTileMode::kClamp, nullptr);
    auto rec = SkCanvasPriv::ScaledBackdropLayer(drawrptr, nullptr, blur.get(), scaleFactor, 0);
    canvas->saveLayer(rec);
        // draw something inside, just to demonstrate that we don't blur the new contents,
        // just the backdrop.
        p.setColor(SK_ColorYELLOW);
        p.setShader(nullptr);
        canvas->drawCircle(cx, cy, 30, p);
    canvas->restore();
}

/*
 *  Draws a 2x4 grid of sweep circles.
 *  - for a given row, each col should be identical (canvas, picture)
 *  - row:0     no-hint-rect    no-clip-rect        expect big blur (except inner circle)
 *  - row:1     no-hint-rect    clip-rect           expect small blur (except inner circle)
 *  - row:2     hint-rect       no-clip-rect        expect big blur (except inner circle)
 *  - row:3     hint-rect       clip-rect           expect small blur (except inner circle)
 *
 *  The test is that backdrop effects should be independent of the hint-rect, but should
 *  respect the clip-rect.
 */
DEF_SIMPLE_GM(backdrop_hintrect_clipping, canvas, 512, 1024) {
    for (bool useHintRect : {false, true}) {
        for (bool useClip : {false, true}) {
            canvas->save();
                do_draw(canvas, useClip, useHintRect, 1.0f);

                SkPictureRecorder rec;
                do_draw(rec.beginRecording(256, 256), useClip, useHintRect, 1.0f);
                canvas->translate(256, 0);
                canvas->drawPicture(rec.finishRecordingAsPicture());
            canvas->restore();

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

/*
 *  Draws a 3x4 grid of sweep circles.
 *  - for a given row, each col should be identical except that the intermediate scale factor used
 *    to evaluate the backdrop follows (1.0, 0.25, 0.1). Rows follow same pattern as above.
 *
 *  The test is that backdrop effects should be independent of the hint-rect, should respect the
 *  clip rect, and be logically consistent with the reduced intermediate scaling.
 */
DEF_SIMPLE_GM(backdrop_scalefactor, canvas, 768, 1024) {
    for (bool useHintRect : {false, true}) {
        for (bool useClip : {false, true}) {
            canvas->save();
                do_draw(canvas, useClip, useHintRect, 1.0f);
                canvas->translate(256, 0);
                do_draw(canvas, useClip, useHintRect, 0.25f);
                canvas->translate(256, 0);
                do_draw(canvas, useClip, useHintRect, 0.1f);
            canvas->restore();

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