/*
 * 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 = SK_ARRAY_COUNT(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);
        }
    }
}
