/*
 * Copyright 2014 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 "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkShader.h"

#include "SkBlurImageFilter.h"
#include "SkColorMatrixFilter.h"
#include "SkDisplacementMapEffect.h"
#include "SkDropShadowImageFilter.h"
#include "SkGradientShader.h"
#include "SkImageSource.h"
#include "SkMorphologyImageFilter.h"
#include "SkColorFilterImageFilter.h"
#include "SkLightingImageFilter.h"
#include "SkMergeImageFilter.h"
#include "SkOffsetImageFilter.h"
#include "SkPoint3.h"
#include "SkSurface.h"

namespace {

void make_checkerboard(SkBitmap* bitmap);
sk_sp<SkImage> make_gradient_circle(int width, int height);
void draw(SkCanvas* canvas, const SkBitmap& bitmap, const SkRect& rect,
                 sk_sp<SkImageFilter> filter);

};

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

DEF_SIMPLE_GM(imagefilterscropexpand, canvas, 730, 650) {
    SkImageFilter::CropRect cropRect(
        SkRect::Make(SkIRect::MakeXYWH(10, 10, 44, 44)),
        SkImageFilter::CropRect::kHasAll_CropEdge);

    sk_sp<SkImage> gradientCircle(make_gradient_circle(64, 64));
    SkBitmap checkerboard;
    make_checkerboard(&checkerboard);

    sk_sp<SkImageFilter> gradientCircleSource(SkImageSource::Make(std::move(gradientCircle)));
    sk_sp<SkImageFilter> noopCropped(SkOffsetImageFilter::Make(0, 0, nullptr, &cropRect));
    // This color matrix saturates the green component but only partly increases the opacity.
    // For the opaque checkerboard, the opacity boost doesn't matter but it does impact the
    // area outside the checkerboard.
    SkScalar matrix[20] = { 1, 0, 0, 0, 0,
                            0, 1, 0, 0, 255,
                            0, 0, 1, 0, 0,
                            0, 0, 0, 1, 32 };
    sk_sp<SkColorFilter> cfAlphaTrans(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));

    SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
    SkScalar MARGIN = SkIntToScalar(12);

    SkPoint3 pointLocation = SkPoint3::Make(0, 0, SkIntToScalar(10));
    SkScalar kd = SkIntToScalar(2);
    SkScalar surfaceScale = SkIntToScalar(1);
    SkIRect bounds;
    r.roundOut(&bounds);

    SkPaint paint;
    canvas->translate(MARGIN, MARGIN);
    for (int outset = -15; outset <= 20; outset += 5) {
        canvas->save();
        SkRect rect = cropRect.rect();
        rect.outset(SkIntToScalar(outset),
                    SkIntToScalar(outset));
        SkImageFilter::CropRect bigRect(rect, SkImageFilter::CropRect::kHasAll_CropEdge);

        draw(canvas, checkerboard, rect, SkColorFilterImageFilter::Make(cfAlphaTrans,
                                                                        noopCropped,
                                                                        &bigRect));

        draw(canvas, checkerboard, rect, SkBlurImageFilter::Make(0.3f, 0.3f,
                                                                 noopCropped,
                                                                 &bigRect));

        draw(canvas, checkerboard, rect, SkBlurImageFilter::Make(8.0f, 8.0f,
                                                                 noopCropped,
                                                                 &bigRect));

        draw(canvas, checkerboard, rect, SkDilateImageFilter::Make(2, 2,
                                                                   noopCropped,
                                                                   &bigRect));

        draw(canvas, checkerboard, rect, SkErodeImageFilter::Make(2, 2,
                                                                  noopCropped,
                                                                  &bigRect));

        draw(canvas, checkerboard, rect,
             SkDropShadowImageFilter::Make(
                                SkIntToScalar(10),
                                SkIntToScalar(10),
                                SkIntToScalar(3),
                                SkIntToScalar(3),
                                SK_ColorBLUE,
                                SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
                                noopCropped,
                                &bigRect));

        draw(canvas, checkerboard, rect,
             SkDisplacementMapEffect::Make(SkDisplacementMapEffect::kR_ChannelSelectorType,
                                           SkDisplacementMapEffect::kR_ChannelSelectorType,
                                           SkIntToScalar(12),
                                           gradientCircleSource,
                                           noopCropped,
                                           &bigRect));

        draw(canvas, checkerboard, rect,
             SkOffsetImageFilter::Make(SkIntToScalar(-8), SkIntToScalar(16),
                                       noopCropped,
                                       &bigRect));

        draw(canvas, checkerboard, rect,
             SkLightingImageFilter::MakePointLitDiffuse(pointLocation,
                                                        SK_ColorWHITE,
                                                        surfaceScale,
                                                        kd,
                                                        noopCropped,
                                                        &bigRect));

        canvas->restore();
        canvas->translate(0, SkIntToScalar(80));
    }
}

namespace {
    void make_checkerboard(SkBitmap* bitmap) {
        bitmap->allocN32Pixels(64, 64);
        SkCanvas canvas(*bitmap);
        canvas.clear(0xFFFF0000);
        SkPaint darkPaint;
        darkPaint.setColor(sk_tool_utils::color_to_565(0xFF404040));
        SkPaint lightPaint;
        lightPaint.setColor(sk_tool_utils::color_to_565(0xFFA0A0A0));
        for (int y = 8; y < 48; y += 16) {
            for (int x = 8; x < 48; x += 16) {
                canvas.save();
                canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
                canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
                canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
                canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
                canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
                canvas.restore();
            }
        }
    }

    sk_sp<SkImage> make_gradient_circle(int width, int height) {
        SkScalar x = SkIntToScalar(width / 2);
        SkScalar y = SkIntToScalar(height / 2);
        SkScalar radius = SkMinScalar(x, y) * 0.8f;
        auto surface(SkSurface::MakeRasterN32Premul(width, height));
        SkCanvas* canvas = surface->getCanvas();
        canvas->clear(0x00000000);
        SkColor colors[2];
        colors[0] = SK_ColorWHITE;
        colors[1] = SK_ColorBLACK;
        SkPaint paint;
        paint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr,
                                                     2, SkShader::kClamp_TileMode));
        canvas->drawCircle(x, y, radius, paint);

        return surface->makeImageSnapshot();
    }

    void draw(SkCanvas* canvas, const SkBitmap& bitmap, const SkRect& rect,
                     sk_sp<SkImageFilter> filter) {
        SkPaint paint;
        paint.setImageFilter(std::move(filter));
        canvas->saveLayer(&rect, &paint);
        canvas->drawBitmap(bitmap, 0, 0);
        canvas->restore();

        SkPaint strokePaint;
        strokePaint.setColor(0xFFFF0000);
        strokePaint.setStyle(SkPaint::kStroke_Style);
        canvas->drawRect(rect, strokePaint);

        canvas->translate(SkIntToScalar(80), 0);
    }
};
