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

#ifndef SkImageFilter_Base_DEFINED
#define SkImageFilter_Base_DEFINED

#include "include/core/SkColorSpace.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkImageInfo.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTemplates.h"

#include "src/core/SkImageFilterTypes.h"

#include <optional>

class GrFragmentProcessor;
class GrRecordingContext;

// True base class that all SkImageFilter implementations need to extend from. This provides the
// actual API surface that Skia will use to compute the filtered images.
class SkImageFilter_Base : public SkImageFilter {
public:
    // DEPRECATED - Use skif::Context directly.
    using Context = skif::Context;

    /**
     *  Request a new filtered image to be created from the src image. The returned skif::Image
     *  provides both the pixel data and the origin point that it should be drawn at, relative to
     *  the layer space defined by the provided context.
     *
     *  If the result image cannot be created, or the result would be transparent black, returns
     *  a skif::Image that has a null special image, in which its origin should be ignored.
     *
     *  TODO: Right now the imagefilters sometimes return empty result bitmaps/
     *        specialimages. That doesn't seem quite right.
     */
    skif::FilterResult filterImage(const skif::Context& context) const;

    /**
     *  Calculate the smallest-possible required layer bounds that would provide sufficient
     *  information to correctly compute the image filter for every pixel in the desired output
     *  bounds. The 'desiredOutput' is intended to represent either the root render target bounds,
     *  or the device-space bounds of the current clip. If the bounds of the content that will be
     *  drawn into the layer is known, 'knownContentBounds' should be provided, since it can be
     *  used to restrict the size of the layer if the image filter DAG does not affect transparent
     *  black.
     *
     *  The returned rect is in the layer space defined by 'mapping', so it directly represents
     *  the size and location of the SkDevice created to rasterize the content prior to invoking the
     *  image filter (assuming its CTM and basis matrix are configured to match 'mapping').
     *
     *  While this operation transforms an device-space output bounds to a layer-space input bounds,
     *  it is not necessarily the inverse of getOutputBounds(). For instance, a blur needs to have
     *  an outset margin when reading pixels at the edge (to satisfy its kernel), thus it expands
     *  its required input rect to include every pixel that contributes to the desired output rect.

     *  @param mapping       The coordinate space mapping that defines both the transformation
     *                       between local and layer, and layer to root device space, that will be
     *                       used when the filter is later invoked.
     *  @param desiredOutput The desired output boundary that needs to be covered by the filter's
     *                       output (assuming that the filter is then invoked with a suitable input)
     *  @param knownContentBounds
     *                       Optional, the known layer-space bounds of the non-transparent content
     *                       that would be rasterized in the source input image.
     *
     * @return The layer-space bounding box to use for an SkDevice when drawing the source image.
     */
    skif::LayerSpace<SkIRect> getInputBounds(
            const skif::Mapping& mapping, const skif::DeviceSpace<SkIRect>& desiredOutput,
            const skif::ParameterSpace<SkRect>* knownContentBounds) const;

    /**
     *  Calculate the device-space bounds of the output of this filter DAG, if it were to process
     *  an image layer covering the 'contentBounds'. The 'mapping' defines how the content will be
     *  transformed to layer space when it is drawn, and how the output filter image is then
     *  transformed to the final device space (i.e. it specifies the mapping between the root device
     *  space and the parameter space of the initially provided content).
     *
     *  While this operation transforms a parameter-space input bounds to an device-space output
     *  bounds, it is not necessarily the inverse of getInputBounds(). For instance, a blur needs to
     *  have an outset margin when reading pixels at the edge (to satisfy its kernel), so it will
     *  generate a result larger than its input (so that the blur is visible) and, thus, expands its
     *  output to include every pixel that it will touch.
     *
     *  @param mapping       The coordinate space mapping that defines both the transformation
     *                       between local and layer, and layer to root device space, that will be
     *                       used when the filter is later invoked.
     *  @param contentBounds The local-space bounds of the non-transparent content that would be
     *                       drawn into the source image prior to filtering with this DAG,  i.e.
     *                       the same as 'knownContentBounds' in getInputBounds().
     *
     *  @return The root device-space bounding box of the filtered image, were it applied to
     *          content contained by 'contentBounds' and then drawn with 'mapping' to the root
     *          device (w/o any additional clipping).
     */
    skif::DeviceSpace<SkIRect> getOutputBounds(
            const skif::Mapping& mapping, const skif::ParameterSpace<SkRect>& contentBounds) const;

    // Returns true if this image filter graph transforms a source transparent black pixel to a
    // color other than transparent black.
    bool affectsTransparentBlack() const;

    // Returns true if this image filter graph references the Context's source image.
    bool usesSource() const { return fUsesSrcInput; }

    /**
     *  Most ImageFilters can natively handle scaling and translate components in the CTM. Only
     *  some of them can handle affine (or more complex) matrices. Some may only handle translation.
     *  This call returns the maximum "kind" of CTM for a filter and all of its (non-null) inputs.
     */
    enum class MatrixCapability {
        kTranslate,
        kScaleTranslate,
        kComplex,
    };
    MatrixCapability getCTMCapability() const;

    uint32_t uniqueID() const { return fUniqueID; }

    static SkFlattenable::Type GetFlattenableType() {
        return kSkImageFilter_Type;
    }

    SkFlattenable::Type getFlattenableType() const override {
        return kSkImageFilter_Type;
    }

protected:
    // DEPRECATED: Will be removed once cropping is handled by a standalone image filter
    class CropRect {
    public:
        enum CropEdge {
            kHasLeft_CropEdge   = 0x01,
            kHasTop_CropEdge    = 0x02,
            kHasWidth_CropEdge  = 0x04,
            kHasHeight_CropEdge = 0x08,
            kHasAll_CropEdge    = 0x0F,
        };
        CropRect() : fFlags(0) {}
        explicit CropRect(const SkRect* rect)
            : fRect(rect ? *rect : SkRect::MakeEmpty()), fFlags(rect ? kHasAll_CropEdge : 0x0) {}

        // CropRect(const CropRect&) = default;

        uint32_t flags() const { return fFlags; }
        const SkRect& rect() const { return fRect; }

        /**
         *  Apply this cropRect to the imageBounds. If a given edge of the cropRect is not set, then
         *  the corresponding edge from imageBounds will be used. If "embiggen" is true, the crop
         *  rect is allowed to enlarge the size of the rect, otherwise it may only reduce the rect.
         *  Filters that can affect transparent black should pass "true", while all other filters
         *  should pass "false".
         *
         *  Note: imageBounds is in "device" space, as the output cropped rectangle will be, so the
         *  matrix is ignored for those. It is only applied to the cropRect's bounds.
         */
        void applyTo(const SkIRect& imageBounds, const SkMatrix& matrix, bool embiggen,
                     SkIRect* cropped) const;

    private:
        SkRect fRect;
        uint32_t fFlags;
    };

    class Common {
    public:
        /**
         *  Attempt to unflatten the cropRect and the expected number of input filters.
         *  If any number of input filters is valid, pass -1.
         *  If this fails (i.e. corrupt buffer or contents) then return false and common will
         *  be left uninitialized.
         *  If this returns true, then inputCount() is the number of found input filters, each
         *  of which may be NULL or a valid imagefilter.
         */
        bool unflatten(SkReadBuffer&, int expectedInputs);

        const SkRect* cropRect() const {
            return fCropRect.flags() != 0x0 ? &fCropRect.rect() : nullptr;
        }
        int inputCount() const { return fInputs.size(); }
        sk_sp<SkImageFilter>* inputs() { return fInputs.begin(); }

        sk_sp<SkImageFilter> getInput(int index) { return fInputs[index]; }

    private:
        CropRect fCropRect;
        // most filters accept at most 2 input-filters
        skia_private::STArray<2, sk_sp<SkImageFilter>, true> fInputs;
    };

    SkImageFilter_Base(sk_sp<SkImageFilter> const* inputs, int inputCount,
                       const SkRect* cropRect, std::optional<bool> usesSrc = {});

    ~SkImageFilter_Base() override;

    void flatten(SkWriteBuffer&) const override;

    // DEPRECATED - Use the private context-only variant
    virtual sk_sp<SkSpecialImage> onFilterImage(const Context&, SkIPoint* offset) const {
        return nullptr;
    }

    // DEPRECATED - Override onGetOutputLayerBounds and onGetInputLayerBounds instead. The
    // node-specific and aggregation functions are no longer separated in the current API. A helper
    // function is provided to do the default recursion for the common filter case.
    virtual SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,
                                   MapDirection, const SkIRect* inputRect) const;
    virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,
                                       MapDirection, const SkIRect* inputRect) const;

    // DEPRECRATED - Call the Context-only getChildOutput()
    sk_sp<SkSpecialImage> filterInput(int index, const Context& ctx, SkIPoint* offset) const;

    // Helper function to calculate the required input/output of a specific child filter,
    // automatically handling if the child filter is null.
    skif::LayerSpace<SkIRect> getChildInputLayerBounds(
            int index,
            const skif::Mapping& mapping,
            const skif::LayerSpace<SkIRect>& desiredOutput,
            const skif::LayerSpace<SkIRect>& contentBounds) const;
    skif::LayerSpace<SkIRect> getChildOutputLayerBounds(
            int index,
            const skif::Mapping& mapping,
            const skif::LayerSpace<SkIRect>& contentBounds) const;

    // Helper function for recursing through the filter DAG. It automatically evaluates the input
    // image filter at 'index' using the given context. If the input image filter is null, it
    // returns the context's dynamic source image.
    //
    // When an image filter requires a different output than what is requested in it's own Context
    // passed to onFilterImage(), it should explicitly pass in an updated Context via
    // `withNewDesiredOutput`.
    skif::FilterResult getChildOutput(int index, const skif::Context& ctx) const;

    /**
     *  Returns whether any edges of the crop rect have been set. The crop
     *  rect is set at construction time, and determines which pixels from the
     *  input image will be processed, and which pixels in the output image will be allowed.
     *  The size of the crop rect should be
     *  used as the size of the destination image. The origin of this rect
     *  should be used to offset access to the input images, and should also
     *  be added to the "offset" parameter in onFilterImage.
     *
     *  DEPRECATED - Remove once cropping is handled by a separate filter
     */
    bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }

    // DEPRECATED - Remove once cropping is handled by a separate filter
    CropRect getCropRect() const { return fCropRect; }

    // DEPRECATED - Remove once cropping is handled by a separate filter
    const CropRect* getCropRectIfSet() const {
        return this->cropRectIsSet() ? &fCropRect : nullptr;
    }

    /** Given a "srcBounds" rect, computes destination bounds for this filter.
     *  "dstBounds" are computed by transforming the crop rect by the context's
     *  CTM, applying it to the initial bounds, and intersecting the result with
     *  the context's clip bounds.  "srcBounds" (if non-null) are computed by
     *  intersecting the initial bounds with "dstBounds", to ensure that we never
     *  sample outside of the crop rect (this restriction may be relaxed in the
     *  future).
     *
     *  DEPRECATED - Remove once cropping is handled by a separate filter, although it may be
     *  necessary to provide a similar convenience function to compute the output bounds given the
     *  images returned by filterInput().
     */
    bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;

    /** A variant of the above call which takes the original source bitmap and
     *  source offset. If the resulting crop rect is not entirely contained by
     *  the source bitmap's bounds, it creates a new bitmap in "result" and
     *  pads the edges with transparent black. In that case, the srcOffset is
     *  modified to be the same as the bounds, since no further adjustment is
     *  needed by the caller. This version should only be used by filters
     *  which are not capable of processing a smaller source bitmap into a
     *  larger destination.
     *
     *  DEPRECATED - Remove once cropping is handled by a separate filter.
     */
    sk_sp<SkSpecialImage> applyCropRectAndPad(const Context&, SkSpecialImage* src,
                                              SkIPoint* srcOffset, SkIRect* bounds) const;

    /**
     *  Creates a modified Context for use when recursing up the image filter DAG.
     *  The clip bounds are adjusted to accommodate any margins that this
     *  filter requires by calling this node's
     *  onFilterNodeBounds(..., kReverse_MapDirection).
     */
    // TODO (michaelludwig) - I don't think this is necessary to keep as protected. Other than the
    // real use case in recursing through the DAG for filterInput(), it feels wrong for blur and
    // other filters to need to call it.
    Context mapContext(const Context& ctx) const;

#if defined(SK_GANESH)
    static sk_sp<SkSpecialImage> DrawWithFP(GrRecordingContext* context,
                                            std::unique_ptr<GrFragmentProcessor> fp,
                                            const SkIRect& bounds,
                                            SkColorType colorType,
                                            const SkColorSpace* colorSpace,
                                            const SkSurfaceProps&,
                                            GrSurfaceOrigin surfaceOrigin,
                                            GrProtected isProtected = GrProtected::kNo);

    /**
     *  Returns a version of the passed-in image (possibly the original), that is in the Context's
     *  colorspace and color type. This allows filters that do many
     *  texture samples to guarantee that any color space conversion has happened before running.
     */
    static sk_sp<SkSpecialImage> ImageToColorSpace(const skif::Context& ctx, SkSpecialImage* src);
#endif

    // If 'srcBounds' will sample outside the border of 'originalSrcBounds' (i.e., the sample
    // will wrap around to the other side) we must preserve the far side of the src along that
    // axis (e.g., if we will sample beyond the left edge of the src, the right side must be
    // preserved for the repeat sampling to work).
    // DEPRECATED - Remove once cropping is handled by a separate filter, that can also handle all
    // tile modes (including repeat) properly
    static SkIRect DetermineRepeatedSrcBound(const SkIRect& srcBounds,
                                             const SkIVector& filterOffset,
                                             const SkISize& filterSize,
                                             const SkIRect& originalSrcBounds);

private:
    friend class SkImageFilter;
    // For PurgeCache()
    friend class SkGraphics;

    static void PurgeCache();

    // Configuration points for the filter implementation, marked private since they should not
    // need to be invoked by the subclasses. These refer to the node's specific behavior and are
    // not responsible for aggregating the behavior of the entire filter DAG.

    /**
     *  Return true (and returns a ref'd colorfilter) if this node in the DAG is just a colorfilter
     *  w/o CropRect constraints.
     */
    virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const { return false; }

    /**
     *  Return the most complex matrix type this filter can support (mapping from its parameter
     *  space to a layer space). If this returns anything less than kComplex, the filter only needs
     *  to worry about mapping from parameter to layer using a matrix that is constrained in that
     *  way (eg, scale+translate).
     */
    virtual MatrixCapability onGetCTMCapability() const {
        return MatrixCapability::kScaleTranslate;
    }

    /**
     *  Return true if this filter would transform transparent black pixels to a color other than
     *  transparent black. When false, optimizations can be taken to discard regions known to be
     *  transparent black and thus process fewer pixels.
     */
    virtual bool onAffectsTransparentBlack() const { return false; }

    /**
     *  This is the virtual which should be overridden by the derived class to perform image
     *  filtering. Subclasses are responsible for recursing to their input filters, although the
     *  filterInput() function is provided to handle all necessary details of this.
     *
     *  If the image cannot be created (either because of an error or if the result would be empty
     *  because it was clipped out), this should return a filtered Image with a null SkSpecialImage.
     *  In these situations, callers that do not affect transparent black can end early, since the
     *  "transparent" implicit image would be unchanged. Callers that affect transparent black need
     *  to safely handle these null and empty images and return an image filling the context's clip
     *  bounds as if its input filtered image were transparent black.
     */
    virtual skif::FilterResult onFilterImage(const skif::Context& context) const;

    /**
     *  Calculates the necessary input layer size in order for the final output of the filter to
     *  cover the desired output bounds. The provided 'desiredOutput' represents the requested
     *  input bounds for this node's parent filter node, i.e. this function answers "what does this
     *  node require for input in order to satisfy (as its own output), the input needs of its
     *  parent?".
     *
     *  If 'recurse' is true, this function is responsible for recursing to its child image filters
     *  and accounting for what they require to meet this filter's input requirements. It is up to
     *  the filter to determine how to aggregate these inputs, but a helper function is provided for
     *  the common case where the final required layer size is the union of the child filters'
     *  required inputs, evaluated on what this filter requires for itself. 'recurse' is kNo
     *  when mapping Contexts while actually filtering images, since the child recursion is
     *  happening at a higher level.
     *
     *  Unlike the public getInputBounds(), all internal bounds calculations are done in the shared
     *  layer space defined by 'mapping'.
     *
     *  The default implementation assumes that current filter requires an input equal to
     *  'desiredOutputBounds', and passes this down to its child filters, and returns the union of
     *  their required inputs.
     */
    virtual skif::LayerSpace<SkIRect> onGetInputLayerBounds(
            const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& desiredOutput,
            const skif::LayerSpace<SkIRect>& contentBounds) const;

    /**
     *  Calculates the output bounds that this filter node would touch when processing an input
     *  sized to 'contentBounds'. This function is responsible for recursing to its child image
     *  filters and accounting for what they output. It is up to the filter to determine how to
     *  aggregate the outputs of its children, but a helper function is provided for the common
     *  case where the filter output is the union of its child outputs.
     *
     *  Unlike the public getOutputBounds(), all internal bounds calculations are done in the
     *  shared layer space defined by 'mapping'.
     *
     *  The default implementation assumes that the output of this filter is equal to the union of
     *  the outputs of its child filters evaluated with 'contentBounds'.
     */
    // TODO (michaelludwig) - When layerMatrix = I, this function could be used to implement
    // onComputeFastBounds() instead of making filters implement the essentially the same calcs x2
    virtual skif::LayerSpace<SkIRect> onGetOutputLayerBounds(
            const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& contentBounds) const;

    skia_private::AutoSTArray<2, sk_sp<SkImageFilter>> fInputs;

    bool fUsesSrcInput;
    CropRect fCropRect;
    uint32_t fUniqueID; // Globally unique

    using INHERITED = SkImageFilter;
};

static inline SkImageFilter_Base* as_IFB(SkImageFilter* filter) {
    return static_cast<SkImageFilter_Base*>(filter);
}

static inline SkImageFilter_Base* as_IFB(const sk_sp<SkImageFilter>& filter) {
    return static_cast<SkImageFilter_Base*>(filter.get());
}

static inline const SkImageFilter_Base* as_IFB(const SkImageFilter* filter) {
    return static_cast<const SkImageFilter_Base*>(filter);
}

/**
 *  Helper to unflatten the common data, and return nullptr if we fail.
 */
#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
    Common localVar;                                                \
    do {                                                            \
        if (!localVar.unflatten(buffer, expectedCount)) {           \
            return nullptr;                                         \
        }                                                           \
    } while (0)


/**
 * All image filter implementations defined for the include/effects/SkImageFilters.h factories
 * are entirely encapsulated within their own CPP files. SkFlattenable deserialization needs a hook
 * into these types, so their registration functions are exposed here.
 */
void SkRegisterAlphaThresholdImageFilterFlattenable();
void SkRegisterArithmeticImageFilterFlattenable();
void SkRegisterBlendImageFilterFlattenable();
void SkRegisterBlurImageFilterFlattenable();
void SkRegisterColorFilterImageFilterFlattenable();
void SkRegisterComposeImageFilterFlattenable();
void SkRegisterCropImageFilterFlattenable();
void SkRegisterDisplacementMapImageFilterFlattenable();
void SkRegisterDropShadowImageFilterFlattenable();
void SkRegisterImageImageFilterFlattenable();
void SkRegisterLightingImageFilterFlattenables();
void SkRegisterMagnifierImageFilterFlattenable();
void SkRegisterMatrixConvolutionImageFilterFlattenable();
void SkRegisterMatrixTransformImageFilterFlattenable();
void SkRegisterMergeImageFilterFlattenable();
void SkRegisterMorphologyImageFilterFlattenables();
void SkRegisterPictureImageFilterFlattenable();
#ifdef SK_ENABLE_SKSL
void SkRegisterRuntimeImageFilterFlattenable();
#endif
void SkRegisterShaderImageFilterFlattenable();
void SkRegisterTileImageFilterFlattenable();

#endif // SkImageFilter_Base_DEFINED
