/*
 * 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/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 "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& origLayerBounds,
                        const SkIRect& localLayerBounds, const SkIRect& filterInputBounds,
                        const SkIRect& devLayerBounds) {
    SkFont font(nullptr, 12);
    SkPaint text;
    text.setAntiAlias(true);

    float y = kLineHeight;

    text.setColor(SK_ColorBLACK);
    y = print_size(canvas, "Orig layer", origLayerBounds, kLineInset, y, font, text);
    text.setColor(SK_ColorRED);
    y = print_size(canvas, "Filter layer", localLayerBounds, kLineInset, y, font, text);
    text.setColor(SK_ColorBLUE);
    y = print_size(canvas, "Filter input", filterInputBounds, kLineInset, y, font, text);
    text.setColor(SK_ColorMAGENTA);
    y = print_size(canvas, "Backdrop size", devLayerBounds, kLineInset, y, font, text);

    return y;
}

static SkPaint line_paint(SkScalar width, SkColor color) {
    SkPaint paint;
    paint.setColor(color);
    paint.setStrokeWidth(width);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setAntiAlias(true);
    return paint;
}

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

    void onDrawContent(SkCanvas* canvas) override {
        SkMatrix ctm = canvas->getTotalMatrix();

        // This decomposition is for the backdrop filtering, and does not represent the CTM that
        // the layer actually uses (unless it also has a filter during restore).
        SkMatrix toGlobal, layerMatrix;
        SkSize scale;
        if (ctm.isScaleTranslate()) {
            // No decomposition needed
            toGlobal = SkMatrix::I();
            layerMatrix = ctm;
        } else if (ctm.decomposeScale(&scale, &toGlobal)) {
            layerMatrix = SkMatrix::Scale(scale.fWidth, scale.fHeight);
        } else {
            toGlobal = ctm;
            layerMatrix = SkMatrix::I();
        }

        SkMatrix fromGlobal;
        if (!toGlobal.invert(&fromGlobal)) {
            SkDebugf("Unable to invert CTM\n");
            return;
        }

        // The local content, e.g. what would be submitted to drawRect
        const SkRect localContentRect = SkRect::MakeLTRB(45.5f, 23.123f, 150.f, 140.45f);
        canvas->drawRect(localContentRect, line_paint(0.f, SK_ColorBLACK));

        canvas->save();
        // The layer bounds of the content, this is the size of the actual layer and does not
        // reflect the backdrop specific decomposition.
        canvas->setMatrix(SkMatrix::I());
        SkIRect origLayerBounds = ctm.mapRect(localContentRect).roundOut();
        canvas->drawRect(SkRect::Make(origLayerBounds), line_paint(1.f, SK_ColorBLACK));

        // Have to undo the full CTM transform on the layer bounds to get the layer bounds
        // for the specific backdrop filter decomposition
        canvas->setMatrix(toGlobal);
        SkIRect layerBounds = fromGlobal.mapRect(SkRect::Make(origLayerBounds)).roundOut();
        canvas->drawRect(SkRect::Make(layerBounds), line_paint(0.5f, SK_ColorRED));

        // Input bounds for the backdrop filter to cover the actual layer bounds (emulate some
        // blur that must outset by 5px for reading on the edge).
        SkIRect filterInputBounds = layerBounds;
        filterInputBounds.outset(5, 5);
        canvas->drawRect(SkRect::Make(filterInputBounds), line_paint(1.f, SK_ColorBLUE));

        // The destination bounds that must be snapped in order to transform and fill the
        // filterInputBounds
        canvas->setMatrix(SkMatrix::I());
        SkIRect devLayerBounds = toGlobal.mapRect(SkRect::Make(filterInputBounds)).roundOut();
        canvas->drawRect(SkRect::Make(devLayerBounds), line_paint(2.f, SK_ColorMAGENTA));

        // The destination bounds mapped back into the layer space, which should cover 'layerBounds'
        SkPath backdropCoveringBounds;

        // Add axis lines, to show perspective distortion
        SkIRect local = fromGlobal.mapRect(SkRect::Make(devLayerBounds)).roundOut();
        static int kAxisSpace = 10;
        for (int y = local.fTop + kAxisSpace; y <= local.fBottom - kAxisSpace; y += kAxisSpace) {
            backdropCoveringBounds.moveTo(local.fLeft, y);
            backdropCoveringBounds.lineTo(local.fRight, y);
        }
        for (int x = local.fLeft + kAxisSpace; x <= local.fRight - kAxisSpace; x += kAxisSpace) {
            backdropCoveringBounds.moveTo(x, local.fTop);
            backdropCoveringBounds.lineTo(x, local.fBottom);
        }

        canvas->setMatrix(toGlobal);
        canvas->drawPath(backdropCoveringBounds, line_paint(0.f, SK_ColorGREEN));

        canvas->resetMatrix();
        print_info(canvas, origLayerBounds, layerBounds, filterInputBounds, devLayerBounds);

        canvas->restore();
    }

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

private:

    typedef Sample INHERITED;
};

DEF_SAMPLE(return new BackdropBoundsSample();)
