/*
 * Copyright 2012 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/effects/SkImageFilters.h"

#include "include/core/SkFlattenable.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/base/SkFloatingPoint.h"
#include "src/core/SkImageFilterTypes.h"
#include "src/core/SkImageFilter_Base.h"
#include "src/core/SkKnownRuntimeEffects.h"
#include "src/core/SkPicturePriv.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"

#include <algorithm>
#include <optional>
#include <utility>

namespace {

class SkMagnifierImageFilter final : public SkImageFilter_Base {
public:
    SkMagnifierImageFilter(const SkRect& lensBounds,
                           float zoomAmount,
                           float inset,
                           const SkSamplingOptions& sampling,
                           sk_sp<SkImageFilter> input)
        : SkImageFilter_Base(&input, 1)
        , fLensBounds(lensBounds)
        , fZoomAmount(zoomAmount)
        , fInset(inset)
        , fSampling(sampling) {}

    SkRect computeFastBounds(const SkRect&) const override;

protected:
    void flatten(SkWriteBuffer&) const override;

private:
    friend void ::SkRegisterMagnifierImageFilterFlattenable();
    SK_FLATTENABLE_HOOKS(SkMagnifierImageFilter)

    skif::FilterResult onFilterImage(const skif::Context& context) const override;

    skif::LayerSpace<SkIRect> onGetInputLayerBounds(
            const skif::Mapping& mapping,
            const skif::LayerSpace<SkIRect>& desiredOutput,
            std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;

    std::optional<skif::LayerSpace<SkIRect>> onGetOutputLayerBounds(
            const skif::Mapping& mapping,
            std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;

    skif::ParameterSpace<SkRect> fLensBounds;
    // Zoom is relative so does not belong to a coordinate space, see note in onFilterImage().
    float fZoomAmount;
    // Inset is really a ParameterSpace<SkSize> where width = height = fInset, but we store just the
    // float here for easier serialization and convert to a size in onFilterImage().
    float fInset;
    SkSamplingOptions fSampling;
};

} // end namespace

sk_sp<SkImageFilter> SkImageFilters::Magnifier(const SkRect& lensBounds,
                                               SkScalar zoomAmount,
                                               SkScalar inset,
                                               const SkSamplingOptions& sampling,
                                               sk_sp<SkImageFilter> input,
                                               const CropRect& cropRect) {
    if (lensBounds.isEmpty() || !lensBounds.isFinite() ||
        zoomAmount <= 0.f || inset < 0.f ||
        !SkIsFinite(zoomAmount, inset)) {
        return nullptr; // invalid
    }
    // The magnifier automatically restricts its output based on the size of the image it receives
    // as input, so 'cropRect' only applies to its input.
    if (cropRect) {
        input = SkImageFilters::Crop(*cropRect, std::move(input));
    }

    if (zoomAmount > 1.f) {
        return sk_sp<SkImageFilter>(new SkMagnifierImageFilter(lensBounds, zoomAmount, inset,
                                                               sampling, std::move(input)));
    } else {
        // Zooming with a value less than 1 is technically a downscaling, which "works" but the
        // non-linear distortion behaves unintuitively. At zoomAmount = 1, this filter is an
        // expensive identity function so treat zoomAmount <= 1 as a no-op.
        return input;
    }
}

void SkRegisterMagnifierImageFilterFlattenable() {
    SK_REGISTER_FLATTENABLE(SkMagnifierImageFilter);
}

sk_sp<SkFlattenable> SkMagnifierImageFilter::CreateProc(SkReadBuffer& buffer) {
    if (buffer.isVersionLT(SkPicturePriv::kRevampMagnifierFilter)) {
        // This was actually a legacy magnifier image filter that was serialized. Chrome is the
        // only known client of the magnifier and its not used on webpages, so there shouldn't be
        // SKPs that actually contain a flattened magnifier filter (legacy or new).
        return nullptr;
    }

    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);

    SkRect lensBounds;
    buffer.readRect(&lensBounds);
    SkScalar zoomAmount = buffer.readScalar();
    SkScalar inset = buffer.readScalar();
    SkSamplingOptions sampling = buffer.readSampling();
    return SkImageFilters::Magnifier(lensBounds, zoomAmount, inset, sampling, common.getInput(0));
}

void SkMagnifierImageFilter::flatten(SkWriteBuffer& buffer) const {
    this->SkImageFilter_Base::flatten(buffer);
    buffer.writeRect(SkRect(fLensBounds));
    buffer.writeScalar(fZoomAmount);
    buffer.writeScalar(fInset);
    buffer.writeSampling(fSampling);
}

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

static sk_sp<SkShader> make_magnifier_shader(
        sk_sp<SkShader> input,
        const skif::LayerSpace<SkRect>& lensBounds,
        const skif::LayerSpace<SkMatrix>& zoomXform,
        const skif::LayerSpace<SkSize>& inset) {
    const SkRuntimeEffect* magEffect =
            GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kMagnifier);

    SkRuntimeShaderBuilder builder(sk_ref_sp(magEffect));
    builder.child("src") = std::move(input);

    SkASSERT(inset.width() > 0.f && inset.height() > 0.f);
    builder.uniform("lensBounds") = SkRect(lensBounds);
    builder.uniform("zoomXform") = SkV4{/*Tx*/zoomXform.rc(0, 2), /*Ty*/zoomXform.rc(1, 2),
                                        /*Sx*/zoomXform.rc(0, 0), /*Sy*/zoomXform.rc(1, 1)};
    builder.uniform("invInset") = SkV2{1.f / inset.width(),
                                       1.f / inset.height()};

    return builder.makeShader();
}

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

skif::FilterResult SkMagnifierImageFilter::onFilterImage(const skif::Context& context) const {
    // These represent the full lens bounds and the ideal zoom center if everything is visible.
    skif::LayerSpace<SkRect> lensBounds = context.mapping().paramToLayer(fLensBounds);
    skif::LayerSpace<SkPoint> zoomCenter = lensBounds.center();

    // When magnifying near the edge of the screen, it's common for part of the lens bounds to be
    // offscreen, which also means its input filter cannot provide the full required input.
    // The magnifier's auto-sizing's goal is to cover the visible portion of the lens bounds.
    skif::LayerSpace<SkRect> visibleLensBounds = lensBounds;
    if (!visibleLensBounds.intersect(skif::LayerSpace<SkRect>(context.desiredOutput()))) {
        return {};
    }

    // We pre-emptively fit the zoomed-in src rect to what we expect the child input filter to
    // produce. This should be correct in all cases except for failure to create an offscreen image,
    // at which point there's nothing to be done anyway.
    skif::LayerSpace<SkRect> expectedChildOutput = lensBounds;
    if (std::optional<skif::LayerSpace<SkIRect>> output =
            this->getChildOutputLayerBounds(0, context.mapping(), context.source().layerBounds())) {
        expectedChildOutput = skif::LayerSpace<SkRect>(*output);
    }

    // Clamp the zoom center to be within the childOutput image
    zoomCenter = expectedChildOutput.clamp(zoomCenter);

    // The zoom we want to apply in layer-space is equal to
    // mapping.paramToLayer(SkMatrix::Scale(fZoomAmount)).decomposeScale(&layerZoom).
    // Because this filter only supports scale+translate matrices, the paramToLayer transform of
    // the parameter-space scale matrix is a no-op. Thus layerZoom == fZoomAmount and we can avoid
    // all of that math. This assumption is invalid if the matrix complexity is more than S+T.
    SkASSERT(this->getCTMCapability() == MatrixCapability::kScaleTranslate);
    float invZoom = 1.f / fZoomAmount;

    // The srcRect is the bounding box of the pixels that are linearly scaled up, about zoomCenter.
    // This is not the visual bounds of this upscaled region, but the bounds of the source pixels
    // that will fill the main magnified region (which is simply the inset of lensBounds). When
    // lensBounds has not been cropped by the actual input image, these equations are identical to
    // the more intuitive L/R = center.x -/+ width/(2*zoom) and T/B = center.y -/+ height/(2*zoom).
    // However, when lensBounds is cropped this automatically shifts the source rectangle away from
    // the original zoom center such that the upscaled area is contained within the input image.
    skif::LayerSpace<SkRect> srcRect{{
            lensBounds.left()  * invZoom + zoomCenter.x()*(1.f - invZoom),
            lensBounds.top()   * invZoom + zoomCenter.y()*(1.f - invZoom),
            lensBounds.right() * invZoom + zoomCenter.x()*(1.f - invZoom),
            lensBounds.bottom()* invZoom + zoomCenter.y()*(1.f - invZoom)}};

    // The above adjustment helps to account for offscreen, but when the magnifier is combined with
    // backdrop offsets, more significant fitting needs to be performed to pin the visible src
    // rect to what's available.
    auto zoomXform = skif::LayerSpace<SkMatrix>::RectToRect(lensBounds, srcRect);
    if (!expectedChildOutput.contains(visibleLensBounds)) {
        // We need to pick a new srcRect such that srcRect is contained within fitRect and fills
        // visibleLens, while maintaining the aspect ratio of the original srcRect -> lensBounds.
        srcRect = zoomXform.mapRect(visibleLensBounds);

        if (expectedChildOutput.width() >= srcRect.width() &&
            expectedChildOutput.height() >= srcRect.height()) {
            float left = srcRect.left() < expectedChildOutput.left() ?
                    expectedChildOutput.left() :
                    std::min(srcRect.right(), expectedChildOutput.right()) - srcRect.width();
            float top = srcRect.top() < expectedChildOutput.top() ?
                    expectedChildOutput.top() :
                    std::min(srcRect.bottom(), expectedChildOutput.bottom()) - srcRect.height();

            // Update transform to reflect fitted src
            srcRect = skif::LayerSpace<SkRect>(
                    SkRect::MakeXYWH(left, top, srcRect.width(), srcRect.height()));
            zoomXform = skif::LayerSpace<SkMatrix>::RectToRect(visibleLensBounds, srcRect);
        } // Else not enough of the target is available to cover, so don't try adjusting
    }

    // When there is no SkSL support, or there's a 0 inset, the magnifier is equivalent to a
    // rect->rect transform and crop.
    skif::LayerSpace<SkSize> inset = context.mapping().paramToLayer(
            skif::ParameterSpace<SkSize>({fInset, fInset}));
    if (inset.width() <= 0.f || inset.height() <= 0.f)
    {
        // When applying the zoom as a direct transform, we only require the visibleSrcRect as
        // input from the child filter, and transform it by the inverse of zoomXform (to go from
        // src to lens bounds, since it was constructed to go from lens to src).
        skif::LayerSpace<SkMatrix> invZoomXform;
        SkAssertResult(zoomXform.invert(&invZoomXform));
        skif::FilterResult childOutput =
                this->getChildOutput(0, context.withNewDesiredOutput(srcRect.roundOut()));
        return childOutput.applyTransform(context, invZoomXform, fSampling)
                          .applyCrop(context, lensBounds.roundOut());
    }

    using ShaderFlags = skif::FilterResult::ShaderFlags;
    skif::FilterResult::Builder builder{context};
    builder.add(this->getChildOutput(0, context.withNewDesiredOutput(visibleLensBounds.roundOut())),
                {}, ShaderFlags::kNonTrivialSampling, fSampling);
    return builder.eval([&](SkSpan<sk_sp<SkShader>> inputs) {
            // If the input resolved to a null shader, the magnified output will be transparent too
            return inputs[0] ? make_magnifier_shader(inputs[0], lensBounds, zoomXform, inset)
                             : nullptr;
        }, lensBounds.roundOut());
}

skif::LayerSpace<SkIRect> SkMagnifierImageFilter::onGetInputLayerBounds(
        const skif::Mapping& mapping,
        const skif::LayerSpace<SkIRect>& desiredOutput,
        std::optional<skif::LayerSpace<SkIRect>> contentBounds) const {
    // The required input is always the lens bounds. The filter distorts the pixels contained within
    // these bounds to zoom in on a portion of it, depending on the inset and zoom amount. However,
    // it adjusts the region based on cropping that occurs between what's requested and what's
    // provided. Theoretically it's possible that we could restrict the required input by the
    // desired output, but that cropping should not adjust the zoom region or inset. This is non
    // trivial to separate and is an unlikely use case so for now just require fLensBounds.
    skif::LayerSpace<SkIRect> requiredInput = mapping.paramToLayer(fLensBounds).roundOut();
    // Our required input is the desired output for our child image filter.
    return this->getChildInputLayerBounds(0, mapping, requiredInput, contentBounds);
}

std::optional<skif::LayerSpace<SkIRect>> SkMagnifierImageFilter::onGetOutputLayerBounds(
        const skif::Mapping& mapping,
        std::optional<skif::LayerSpace<SkIRect>> contentBounds) const {
    // The output of this filter is fLensBounds intersected with its child's output.
    auto output = this->getChildOutputLayerBounds(0, mapping, contentBounds);
    skif::LayerSpace<SkIRect> lensBounds = mapping.paramToLayer(fLensBounds).roundOut();
    if (!output || lensBounds.intersect(*output)) {
        return lensBounds;
    } else {
        // Nothing to magnify
        return skif::LayerSpace<SkIRect>::Empty();
    }
}

SkRect SkMagnifierImageFilter::computeFastBounds(const SkRect& src) const {
    SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src;
    if (bounds.intersect(SkRect(fLensBounds))) {
        return bounds;
    } else {
        return SkRect::MakeEmpty();
    }
}
