/*
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "samplecode/Sample.h"

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/effects/SkDashPathEffect.h"
#include "include/effects/SkGradientShader.h"
#include "include/effects/SkImageFilters.h"

#include "src/core/SkImageFilterTypes.h"
#include "src/core/SkImageFilter_Base.h"
#include "src/core/SkMatrixPriv.h"

#include "tools/ToolUtils.h"

static constexpr float kLineHeight = 16.f;
static constexpr float kLineInset = 8.f;

static float print_size(SkCanvas* canvas, const char* prefix, const SkIRect& rect,
                        float x, float y, const SkFont& font, const SkPaint& paint) {
    canvas->drawString(prefix, x, y, font, paint);
    y += kLineHeight;
    SkString sz;
    sz.appendf("%d x %d", rect.width(), rect.height());
    canvas->drawString(sz, x, y, font, paint);
    return y + kLineHeight;
}

static float print_info(SkCanvas* canvas,
                        const SkIRect& layerContentBounds,
                        const SkIRect& outputBounds,
                        const SkIRect& hintedOutputBounds,
                        const SkIRect& unhintedLayerBounds) {
    SkFont font(nullptr, 12);
    SkPaint text;
    text.setAntiAlias(true);

    float y = kLineHeight;

    text.setColor(SK_ColorRED);
    y = print_size(canvas, "Content (in layer)", layerContentBounds, kLineInset, y, font, text);
    text.setColor(SK_ColorDKGRAY);
    y = print_size(canvas, "Target (in device)", outputBounds, kLineInset, y, font, text);
    text.setColor(SK_ColorBLUE);
    y = print_size(canvas, "Output (w/ hint)", hintedOutputBounds, kLineInset, y, font, text);
    text.setColor(SK_ColorGREEN);
    y = print_size(canvas, "Input (w/ no hint)", unhintedLayerBounds, kLineInset, y, font, text);

    return y;
}

static void print_label(SkCanvas* canvas, float x, float y, float value) {
    SkFont font(nullptr, 12);
    SkPaint text;
    text.setAntiAlias(true);

    SkString label;
    label.printf("%.3f", value);

    canvas->drawString(label, x, y + kLineHeight / 2.f, font, text);
}

static SkPaint line_paint(SkColor color, bool dashed = false) {
    SkPaint paint;
    paint.setColor(color);
    paint.setStrokeWidth(0.f);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setAntiAlias(true);
    if (dashed) {
        SkScalar dash[2] = {10.f, 10.f};
        paint.setPathEffect(SkDashPathEffect::Make(dash, 2, 0.f));
    }
    return paint;
}

static SkPath create_axis_path(const SkRect& rect, float axisSpace) {
    SkPath localSpace;
    for (float y = rect.fTop + axisSpace; y <= rect.fBottom; y += axisSpace) {
        localSpace.moveTo(rect.fLeft, y);
        localSpace.lineTo(rect.fRight, y);
    }
    for (float x = rect.fLeft + axisSpace; x <= rect.fRight; x += axisSpace) {
        localSpace.moveTo(x, rect.fTop);
        localSpace.lineTo(x, rect.fBottom);
    }
    return localSpace;
}

static const SkColor4f kScaleGradientColors[] =
                { { 0.05f, 0.0f, 6.f,  1.f },   // Severe downscaling, s < 1/8, log(s) < -3
                  { 0.6f,  0.6f, 0.8f, 0.6f },  // Okay downscaling,   s < 1/2, log(s) < -1
                  { 1.f,   1.f,  1.f,  0.2f },  // No scaling,         s = 1,   log(s) = 0
                  { 0.95f, 0.6f, 0.5f, 0.6f },  // Okay upscaling,     s > 2,   log(s) > 1
                  { 0.8f,  0.1f, 0.f,  1.f } }; // Severe upscaling,   s > 8,   log(s) > 3
static const SkScalar kLogScaleFactors[] = { -3.f, -1.f, 0.f, 1.f, 3.f };
static const SkScalar kGradientStops[] = { 0.f, 0.33333f, 0.5f, 0.66667f, 1.f };
static const int kStopCount = (int) std::size(kScaleGradientColors);

static void draw_scale_key(SkCanvas* canvas, float y) {
    SkRect key = SkRect::MakeXYWH(15.f, y + 30.f, 15.f, 100.f);
    SkPoint pts[] = {{key.centerX(), key.fTop}, {key.centerX(), key.fBottom}};
    sk_sp<SkShader> gradient = SkGradientShader::MakeLinear(
            pts, kScaleGradientColors, nullptr, kGradientStops, kStopCount, SkTileMode::kClamp,
            SkGradientShader::kInterpolateColorsInPremul_Flag, nullptr);
    SkPaint keyPaint;
    keyPaint.setShader(gradient);
    canvas->drawRect(key, keyPaint);
    for (int i = 0; i < kStopCount; ++i) {
        print_label(canvas, key.fRight + 5.f, key.fTop + kGradientStops[i] * key.height(),
                    SkScalarPow(2.f, kLogScaleFactors[i]));
    }
}

static void draw_scale_factors(SkCanvas* canvas, const skif::Mapping& mapping, const SkRect& rect) {
    SkPoint testPoints[5];
    testPoints[0] = {rect.centerX(), rect.centerY()};
    rect.toQuad(testPoints + 1);
    for (int i = 0; i < 5; ++i) {
        float scale = SkMatrixPriv::DifferentialAreaScale(
                mapping.layerToDevice(),
                SkPoint(mapping.paramToLayer(skif::ParameterSpace<SkPoint>(testPoints[i]))));
        SkColor4f color = {0.f, 0.f, 0.f, 1.f};

        if (SkScalarIsFinite(scale)) {
            float logScale = SkScalarLog2(scale);
            for (int j = 0; j <= kStopCount; ++j) {
                if (j == kStopCount) {
                    color = kScaleGradientColors[j - 1];
                    break;
                } else if (kLogScaleFactors[j] >= logScale) {
                    if (j == 0) {
                        color = kScaleGradientColors[0];
                    } else {
                        SkScalar t = (logScale - kLogScaleFactors[j - 1]) /
                                    (kLogScaleFactors[j] - kLogScaleFactors[j - 1]);

                        SkColor4f a = kScaleGradientColors[j - 1] * (1.f - t);
                        SkColor4f b = kScaleGradientColors[j] * t;
                        color = {a.fR + b.fR, a.fG + b.fG, a.fB + b.fB, a.fA + b.fA};
                    }
                    break;
                }
            }
        }

        SkPaint p;
        p.setAntiAlias(true);
        p.setColor4f(color, nullptr);
        canvas->drawRect(SkRect::MakeLTRB(testPoints[i].fX - 4.f, testPoints[i].fY - 4.f,
                                          testPoints[i].fX + 4.f, testPoints[i].fY + 4.f), p);
    }
}

class FilterBoundsSample : public Sample {
public:
    FilterBoundsSample() {}

    void onOnceBeforeDraw() override {
        fBlur = SkImageFilters::Blur(8.f, 8.f, nullptr);
        fImage = ToolUtils::create_checkerboard_image(
                300, 300, SK_ColorMAGENTA, SK_ColorLTGRAY, 50);
    }

    void onDrawContent(SkCanvas* canvas) override {
        // The local content, e.g. what would be submitted to drawRect or the bounds to saveLayer
        const SkRect localContentRect = SkRect::MakeLTRB(100.f, 20.f, 180.f, 140.f);
        SkMatrix ctm = canvas->getLocalToDeviceAs3x3();

        // Base rendering of a filter
        SkPaint blurPaint;
        blurPaint.setImageFilter(fBlur);
        canvas->saveLayer(&localContentRect, &blurPaint);
        canvas->drawImageRect(fImage.get(), localContentRect, localContentRect,
                              SkSamplingOptions(SkFilterMode::kLinear),
                              nullptr, SkCanvas::kFast_SrcRectConstraint);
        canvas->restore();

        // Now visualize the underlying bounds calculations used to determine the layer for the blur
        SkIRect target = ctm.mapRect(localContentRect).roundOut();
        if (!target.intersect(SkIRect::MakeWH(canvas->imageInfo().width(),
                                              canvas->imageInfo().height()))) {
            return;
        }
        skif::DeviceSpace<SkIRect> targetOutput(target);
        skif::ParameterSpace<SkRect> contentBounds(localContentRect);
        skif::ParameterSpace<SkPoint> contentCenter({localContentRect.centerX(),
                                                     localContentRect.centerY()});
        skif::Mapping mapping;
        SkAssertResult(mapping.decomposeCTM(ctm, fBlur.get(), contentCenter));

        // Add axis lines, to show perspective distortion
        canvas->save();
        canvas->setMatrix(mapping.layerToDevice());
        canvas->drawPath(create_axis_path(SkRect(mapping.paramToLayer(contentBounds)), 20.f),
                         line_paint(SK_ColorGRAY));
        canvas->restore();

        // Visualize scale factors at the four corners and center of the local rect
        draw_scale_factors(canvas, mapping, localContentRect);

        // The device content rect, e.g. the clip bounds if 'localContentRect' were used as a clip
        // before the draw or saveLayer, representing what the filter must cover if it affects
        // transparent black or doesn't have a local content hint.
        canvas->setMatrix(SkMatrix::I());
        canvas->drawRect(ctm.mapRect(localContentRect), line_paint(SK_ColorDKGRAY));

        // Layer bounds for the filter, in the layer space compatible with the filter's matrix
        // type requirements.
        skif::LayerSpace<SkIRect> targetOutputInLayer = mapping.deviceToLayer(targetOutput);
        skif::LayerSpace<SkIRect> hintedLayerBounds = as_IFB(fBlur)->getInputBounds(
                mapping, targetOutput, &contentBounds);
        skif::LayerSpace<SkIRect> unhintedLayerBounds = as_IFB(fBlur)->getInputBounds(
                mapping, targetOutput, nullptr);

        canvas->setMatrix(mapping.layerToDevice());
        canvas->drawRect(SkRect::Make(SkIRect(targetOutputInLayer)),
                         line_paint(SK_ColorDKGRAY, true));
        canvas->drawRect(SkRect::Make(SkIRect(hintedLayerBounds)), line_paint(SK_ColorRED));
        canvas->drawRect(SkRect::Make(SkIRect(unhintedLayerBounds)), line_paint(SK_ColorGREEN));

        // For visualization purposes, we want to show the layer-space output, this is what we get
        // when contentBounds is provided as a hint in local/parameter space.
        skif::Mapping layerOnly{mapping.layerMatrix()};
        skif::DeviceSpace<SkIRect> hintedOutputBounds = as_IFB(fBlur)->getOutputBounds(
                layerOnly, contentBounds);
        canvas->drawRect(SkRect::Make(SkIRect(hintedOutputBounds)), line_paint(SK_ColorBLUE));

        canvas->resetMatrix();
        float y = print_info(canvas, SkIRect(mapping.paramToLayer(contentBounds).roundOut()),
                             SkIRect(targetOutput),
                             SkIRect(hintedOutputBounds),
                             SkIRect(unhintedLayerBounds));

        // Draw color key for layer visualization
        draw_scale_key(canvas, y);
    }

    SkString name() override { return SkString("FilterBounds"); }

private:
    sk_sp<SkImageFilter> fBlur;
    sk_sp<SkImage>       fImage;

    using INHERITED = Sample;
};

DEF_SAMPLE(return new FilterBoundsSample();)
