// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_IMAGE_FILTER_H_
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_IMAGE_FILTER_H_

#include "flutter/display_list/display_list_attributes.h"
#include "flutter/display_list/display_list_color_filter.h"
#include "flutter/display_list/display_list_comparable.h"
#include "flutter/display_list/display_list_tile_mode.h"
#include "flutter/display_list/types.h"
#include "flutter/fml/logging.h"
#include "third_party/skia/include/effects/SkImageFilters.h"

namespace flutter {

// The DisplayList ImageFilter class. This class implements all of the
// facilities and adheres to the design goals of the |DlAttribute| base
// class.
//
// The objects here define operations that can take a location and one or
// more input pixels and produce a color for that output pixel

// An enumerated type for the recognized ImageFilter operations.
// If a custom ImageFilter outside of the recognized types is needed
// then a |kUnknown| type that simply defers to an SkImageFilter is
// provided as a fallback.
enum class DlImageFilterType {
  kBlur,
  kDilate,
  kErode,
  kMatrix,
  kComposeFilter,
  kColorFilter,
  kUnknown
};

class DlBlurImageFilter;
class DlDilateImageFilter;
class DlErodeImageFilter;
class DlMatrixImageFilter;
class DlComposeImageFilter;
class DlColorFilterImageFilter;

class DlImageFilter
    : public DlAttribute<DlImageFilter, SkImageFilter, DlImageFilterType> {
 public:
  // Return a shared_ptr holding a DlImageFilter representing the indicated
  // Skia SkImageFilter pointer.
  //
  // This method can only detect the ColorFilter type of ImageFilter from an
  // analogous SkImageFilter as there are no "asA..." methods for the other
  // types on SkImageFilter.
  static std::shared_ptr<DlImageFilter> From(SkImageFilter* sk_filter);

  // Return a shared_ptr holding a DlImageFilter representing the indicated
  // Skia SkImageFilter pointer.
  //
  // This method can only detect the ColorFilter type of ImageFilter from an
  // analogous SkImageFilter as there are no "asA..." methods for the other
  // types on SkImageFilter.
  static std::shared_ptr<DlImageFilter> From(sk_sp<SkImageFilter> sk_filter) {
    return From(sk_filter.get());
  }

  // Return a DlBlurImageFilter pointer to this object iff it is a Blur
  // type of ImageFilter, otherwise return nullptr.
  virtual const DlBlurImageFilter* asBlur() const { return nullptr; }

  // Return a DlDilateImageFilter pointer to this object iff it is a Dilate
  // type of ImageFilter, otherwise return nullptr.
  virtual const DlDilateImageFilter* asDilate() const { return nullptr; }

  // Return a DlErodeImageFilter pointer to this object iff it is an Erode
  // type of ImageFilter, otherwise return nullptr.
  virtual const DlErodeImageFilter* asErode() const { return nullptr; }

  // Return a DlMatrixImageFilter pointer to this object iff it is a Matrix
  // type of ImageFilter, otherwise return nullptr.
  virtual const DlMatrixImageFilter* asMatrix() const { return nullptr; }

  // Return a DlComposeImageFilter pointer to this object iff it is a Compose
  // type of ImageFilter, otherwise return nullptr.
  virtual const DlComposeImageFilter* asCompose() const { return nullptr; }

  // Return a DlColorFilterImageFilter pointer to this object iff it is a
  // ColorFilter type of ImageFilter, otherwise return nullptr.
  virtual const DlColorFilterImageFilter* asColorFilter() const {
    return nullptr;
  }

  // Return a boolean indicating whether the image filtering operation will
  // modify transparent black. This is typically used to determine if applying
  // the ImageFilter to a temporary saveLayer buffer will turn the surrounding
  // pixels non-transparent and therefore expand the bounds.
  virtual bool modifies_transparent_black() const = 0;

  // Return the bounds of the output for this image filtering operation
  // based on the supplied input bounds where both are measured in the local
  // (untransformed) coordinate space.
  //
  // The output bounds parameter must be supplied and the method will either
  // return a pointer to it with the result filled in, or it will return a
  // nullptr if it cannot determine the results.
  virtual SkRect* map_local_bounds(const SkRect& input_bounds,
                                   SkRect& output_bounds) const = 0;

  // Return the device bounds of the output for this image filtering operation
  // based on the supplied input device bounds where both are measured in the
  // pixel coordinate space and relative to the given rendering ctm. The
  // transform matrix is used to adjust the filter parameters for when it
  // is used in a rendering operation (for example, the blur radius of a
  // Blur filter will expand based on the ctm).
  //
  // The output bounds parameter must be supplied and the method will either
  // return a pointer to it with the result filled in, or it will return a
  // nullptr if it cannot determine the results.
  virtual SkIRect* map_device_bounds(const SkIRect& input_bounds,
                                     const SkMatrix& ctm,
                                     SkIRect& output_bounds) const = 0;
};

class DlBlurImageFilter final : public DlImageFilter {
 public:
  DlBlurImageFilter(SkScalar sigma_x, SkScalar sigma_y, DlTileMode tile_mode)
      : sigma_x_(sigma_x), sigma_y_(sigma_y), tile_mode_(tile_mode) {}
  explicit DlBlurImageFilter(const DlBlurImageFilter* filter)
      : DlBlurImageFilter(filter->sigma_x_,
                          filter->sigma_y_,
                          filter->tile_mode_) {}
  explicit DlBlurImageFilter(const DlBlurImageFilter& filter)
      : DlBlurImageFilter(&filter) {}

  std::shared_ptr<DlImageFilter> shared() const override {
    return std::make_shared<DlBlurImageFilter>(this);
  }

  DlImageFilterType type() const override { return DlImageFilterType::kBlur; }
  size_t size() const override { return sizeof(*this); }

  const DlBlurImageFilter* asBlur() const override { return this; }

  bool modifies_transparent_black() const override { return false; }

  SkRect* map_local_bounds(const SkRect& input_bounds,
                           SkRect& output_bounds) const override {
    output_bounds = input_bounds.makeOutset(sigma_x_ * 3, sigma_y_ * 3);
    return &output_bounds;
  }

  SkIRect* map_device_bounds(const SkIRect& input_bounds,
                             const SkMatrix& ctm,
                             SkIRect& output_bounds) const override {
    SkVector device_sigma = ctm.mapVector(sigma_x_ * 3, sigma_y_ * 3);
    if (!SkScalarIsFinite(device_sigma.fX)) {
      device_sigma.fX = 0;
    }
    if (!SkScalarIsFinite(device_sigma.fY)) {
      device_sigma.fY = 0;
    }
    output_bounds = input_bounds.makeOutset(ceil(abs(device_sigma.fX)),
                                            ceil(abs(device_sigma.fY)));
    return &output_bounds;
  }

  SkScalar sigma_x() const { return sigma_x_; }
  SkScalar sigma_y() const { return sigma_y_; }
  DlTileMode tile_mode() const { return tile_mode_; }

  sk_sp<SkImageFilter> skia_object() const override {
    return SkImageFilters::Blur(sigma_x_, sigma_y_, ToSk(tile_mode_), nullptr);
  }

 protected:
  bool equals_(const DlImageFilter& other) const override {
    FML_DCHECK(other.type() == DlImageFilterType::kBlur);
    auto that = static_cast<const DlBlurImageFilter*>(&other);
    return (sigma_x_ == that->sigma_x_ && sigma_y_ == that->sigma_y_ &&
            tile_mode_ == that->tile_mode_);
  }

 private:
  SkScalar sigma_x_;
  SkScalar sigma_y_;
  DlTileMode tile_mode_;
};

class DlDilateImageFilter final : public DlImageFilter {
 public:
  DlDilateImageFilter(SkScalar radius_x, SkScalar radius_y)
      : radius_x_(radius_x), radius_y_(radius_y) {}
  explicit DlDilateImageFilter(const DlDilateImageFilter* filter)
      : DlDilateImageFilter(filter->radius_x_, filter->radius_y_) {}
  explicit DlDilateImageFilter(const DlDilateImageFilter& filter)
      : DlDilateImageFilter(&filter) {}

  std::shared_ptr<DlImageFilter> shared() const override {
    return std::make_shared<DlDilateImageFilter>(this);
  }

  DlImageFilterType type() const override { return DlImageFilterType::kDilate; }
  size_t size() const override { return sizeof(*this); }

  const DlDilateImageFilter* asDilate() const override { return this; }

  bool modifies_transparent_black() const override { return false; }

  SkRect* map_local_bounds(const SkRect& input_bounds,
                           SkRect& output_bounds) const override {
    output_bounds = input_bounds.makeOutset(radius_x_, radius_y_);
    return &output_bounds;
  }

  SkIRect* map_device_bounds(const SkIRect& input_bounds,
                             const SkMatrix& ctm,
                             SkIRect& output_bounds) const override {
    SkVector device_radius = ctm.mapVector(radius_x_, radius_y_);
    if (!SkScalarIsFinite(device_radius.fX)) {
      device_radius.fX = 0;
    }
    if (!SkScalarIsFinite(device_radius.fY)) {
      device_radius.fY = 0;
    }
    output_bounds = input_bounds.makeOutset(ceil(abs(device_radius.fX)),
                                            ceil(abs(device_radius.fY)));
    return &output_bounds;
  }

  SkScalar radius_x() const { return radius_x_; }
  SkScalar radius_y() const { return radius_y_; }

  sk_sp<SkImageFilter> skia_object() const override {
    return SkImageFilters::Dilate(radius_x_, radius_y_, nullptr);
  }

 protected:
  bool equals_(const DlImageFilter& other) const override {
    FML_DCHECK(other.type() == DlImageFilterType::kDilate);
    auto that = static_cast<const DlDilateImageFilter*>(&other);
    return (radius_x_ == that->radius_x_ && radius_y_ == that->radius_y_);
  }

 private:
  SkScalar radius_x_;
  SkScalar radius_y_;
};

class DlErodeImageFilter final : public DlImageFilter {
 public:
  DlErodeImageFilter(SkScalar radius_x, SkScalar radius_y)
      : radius_x_(radius_x), radius_y_(radius_y) {}
  explicit DlErodeImageFilter(const DlErodeImageFilter* filter)
      : DlErodeImageFilter(filter->radius_x_, filter->radius_y_) {}
  explicit DlErodeImageFilter(const DlErodeImageFilter& filter)
      : DlErodeImageFilter(&filter) {}

  std::shared_ptr<DlImageFilter> shared() const override {
    return std::make_shared<DlErodeImageFilter>(this);
  }

  DlImageFilterType type() const override { return DlImageFilterType::kErode; }
  size_t size() const override { return sizeof(*this); }

  const DlErodeImageFilter* asErode() const override { return this; }

  bool modifies_transparent_black() const override { return false; }

  SkRect* map_local_bounds(const SkRect& input_bounds,
                           SkRect& output_bounds) const override {
    output_bounds = input_bounds.makeOutset(radius_x_, radius_y_);
    return &output_bounds;
  }

  SkIRect* map_device_bounds(const SkIRect& input_bounds,
                             const SkMatrix& ctm,
                             SkIRect& output_bounds) const override {
    SkVector device_radius = ctm.mapVector(radius_x_, radius_y_);
    if (!SkScalarIsFinite(device_radius.fX)) {
      device_radius.fX = 0;
    }
    if (!SkScalarIsFinite(device_radius.fY)) {
      device_radius.fY = 0;
    }
    output_bounds = input_bounds.makeOutset(ceil(abs(device_radius.fX)),
                                            ceil(abs(device_radius.fY)));
    return &output_bounds;
  }

  SkScalar radius_x() const { return radius_x_; }
  SkScalar radius_y() const { return radius_y_; }

  sk_sp<SkImageFilter> skia_object() const override {
    return SkImageFilters::Erode(radius_x_, radius_y_, nullptr);
  }

 protected:
  bool equals_(const DlImageFilter& other) const override {
    FML_DCHECK(other.type() == DlImageFilterType::kErode);
    auto that = static_cast<const DlErodeImageFilter*>(&other);
    return (radius_x_ == that->radius_x_ && radius_y_ == that->radius_y_);
  }

 private:
  SkScalar radius_x_;
  SkScalar radius_y_;
};

class DlMatrixImageFilter final : public DlImageFilter {
 public:
  DlMatrixImageFilter(const SkMatrix& matrix, const SkSamplingOptions& sampling)
      : matrix_(matrix), sampling_(sampling) {}
  explicit DlMatrixImageFilter(const DlMatrixImageFilter* filter)
      : DlMatrixImageFilter(filter->matrix_, filter->sampling_) {}
  explicit DlMatrixImageFilter(const DlMatrixImageFilter& filter)
      : DlMatrixImageFilter(&filter) {}

  std::shared_ptr<DlImageFilter> shared() const override {
    return std::make_shared<DlMatrixImageFilter>(this);
  }

  DlImageFilterType type() const override { return DlImageFilterType::kMatrix; }
  size_t size() const override { return sizeof(*this); }

  const SkMatrix& matrix() const { return matrix_; }
  const SkSamplingOptions& sampling() const { return sampling_; }

  const DlMatrixImageFilter* asMatrix() const override { return this; }

  bool modifies_transparent_black() const override { return false; }

  SkRect* map_local_bounds(const SkRect& input_bounds,
                           SkRect& output_bounds) const override {
    output_bounds = matrix_.mapRect(input_bounds);
    return &output_bounds;
  }

  SkIRect* map_device_bounds(const SkIRect& input_bounds,
                             const SkMatrix& ctm,
                             SkIRect& output_bounds) const override {
    SkMatrix matrix;
    if (!ctm.invert(&matrix)) {
      output_bounds = input_bounds;
      return nullptr;
    }
    matrix.postConcat(matrix_);
    matrix.postConcat(ctm);
    SkRect device_rect;
    matrix.mapRect(&device_rect, SkRect::Make(input_bounds));
    output_bounds = device_rect.roundOut();
    return &output_bounds;
  }

  sk_sp<SkImageFilter> skia_object() const override {
    return SkImageFilters::MatrixTransform(matrix_, sampling_, nullptr);
  }

 protected:
  bool equals_(const DlImageFilter& other) const override {
    FML_DCHECK(other.type() == DlImageFilterType::kMatrix);
    auto that = static_cast<const DlMatrixImageFilter*>(&other);
    return (matrix_ == that->matrix_ && sampling_ == that->sampling_);
  }

 private:
  SkMatrix matrix_;
  SkSamplingOptions sampling_;
};

class DlComposeImageFilter final : public DlImageFilter {
 public:
  DlComposeImageFilter(std::shared_ptr<DlImageFilter> outer,
                       std::shared_ptr<DlImageFilter> inner)
      : outer_(std::move(outer)), inner_(std::move(inner)) {}
  DlComposeImageFilter(const DlImageFilter* outer, const DlImageFilter* inner)
      : outer_(outer->shared()), inner_(inner->shared()) {}
  DlComposeImageFilter(const DlImageFilter& outer, const DlImageFilter& inner)
      : DlComposeImageFilter(&outer, &inner) {}
  explicit DlComposeImageFilter(const DlComposeImageFilter* filter)
      : DlComposeImageFilter(filter->outer_, filter->inner_) {}
  explicit DlComposeImageFilter(const DlComposeImageFilter& filter)
      : DlComposeImageFilter(&filter) {}

  std::shared_ptr<DlImageFilter> shared() const override {
    return std::make_shared<DlComposeImageFilter>(this);
  }

  DlImageFilterType type() const override {
    return DlImageFilterType::kComposeFilter;
  }
  size_t size() const override { return sizeof(*this); }

  std::shared_ptr<DlImageFilter> outer() const { return outer_; }
  std::shared_ptr<DlImageFilter> inner() const { return inner_; }

  const DlComposeImageFilter* asCompose() const override { return this; }

  bool modifies_transparent_black() const override {
    if (inner_ && inner_->modifies_transparent_black()) {
      return true;
    }
    if (outer_ && outer_->modifies_transparent_black()) {
      return true;
    }
    return false;
  }

  SkRect* map_local_bounds(const SkRect& input_bounds,
                           SkRect& output_bounds) const override {
    SkRect* ret = &output_bounds;
    if (inner_) {
      if (!inner_->map_local_bounds(input_bounds, output_bounds)) {
        ret = nullptr;
      }
    }
    if (ret && outer_) {
      if (!outer_->map_local_bounds(input_bounds, output_bounds)) {
        ret = nullptr;
      }
    }
    if (!ret) {
      output_bounds = input_bounds;
    }
    return ret;
  }

  SkIRect* map_device_bounds(const SkIRect& input_bounds,
                             const SkMatrix& ctm,
                             SkIRect& output_bounds) const override {
    SkIRect* ret = &output_bounds;
    if (inner_) {
      if (!inner_->map_device_bounds(input_bounds, ctm, output_bounds)) {
        ret = nullptr;
      }
    }
    if (ret && outer_) {
      if (!outer_->map_device_bounds(input_bounds, ctm, output_bounds)) {
        ret = nullptr;
      }
    }
    if (!ret) {
      output_bounds = input_bounds;
    }
    return ret;
  }

  sk_sp<SkImageFilter> skia_object() const override {
    return SkImageFilters::Compose(outer_->skia_object(),
                                   inner_->skia_object());
  }

 protected:
  bool equals_(const DlImageFilter& other) const override {
    FML_DCHECK(other.type() == DlImageFilterType::kComposeFilter);
    auto that = static_cast<const DlComposeImageFilter*>(&other);
    return (Equals(outer_, that->outer_) && Equals(inner_, that->inner_));
  }

 private:
  std::shared_ptr<DlImageFilter> outer_;
  std::shared_ptr<DlImageFilter> inner_;
};

class DlColorFilterImageFilter final : public DlImageFilter {
 public:
  explicit DlColorFilterImageFilter(std::shared_ptr<DlColorFilter> filter)
      : color_filter_(std::move(filter)) {}
  explicit DlColorFilterImageFilter(const DlColorFilter* filter)
      : color_filter_(filter->shared()) {}
  explicit DlColorFilterImageFilter(const DlColorFilter& filter)
      : color_filter_(filter.shared()) {}
  explicit DlColorFilterImageFilter(const DlColorFilterImageFilter* filter)
      : DlColorFilterImageFilter(filter->color_filter_) {}
  explicit DlColorFilterImageFilter(const DlColorFilterImageFilter& filter)
      : DlColorFilterImageFilter(&filter) {}

  std::shared_ptr<DlImageFilter> shared() const override {
    return std::make_shared<DlColorFilterImageFilter>(color_filter_);
  }

  DlImageFilterType type() const override {
    return DlImageFilterType::kColorFilter;
  }
  size_t size() const override { return sizeof(*this); }

  const std::shared_ptr<DlColorFilter> color_filter() const {
    return color_filter_;
  }

  const DlColorFilterImageFilter* asColorFilter() const override {
    return this;
  }

  bool modifies_transparent_black() const override {
    if (color_filter_) {
      return color_filter_->modifies_transparent_black();
    }
    return false;
  }

  SkRect* map_local_bounds(const SkRect& input_bounds,
                           SkRect& output_bounds) const override {
    output_bounds = input_bounds;
    return modifies_transparent_black() ? nullptr : &output_bounds;
  }

  SkIRect* map_device_bounds(const SkIRect& input_bounds,
                             const SkMatrix& ctm,
                             SkIRect& output_bounds) const override {
    output_bounds = input_bounds;
    return modifies_transparent_black() ? nullptr : &output_bounds;
  }

  sk_sp<SkImageFilter> skia_object() const override {
    return SkImageFilters::ColorFilter(color_filter_->skia_object(), nullptr);
  }

 protected:
  bool equals_(const DlImageFilter& other) const override {
    FML_DCHECK(other.type() == DlImageFilterType::kColorFilter);
    auto that = static_cast<const DlColorFilterImageFilter*>(&other);
    return Equals(color_filter_, that->color_filter_);
  }

 private:
  std::shared_ptr<DlColorFilter> color_filter_;
};

// A wrapper class for a Skia ImageFilter of unknown type. The above 4 types
// are the only types that can be constructed by Flutter using the
// ui.ImageFilter class so this class should be rarely used. The main use
// would come from the |DisplayListCanvasRecorder| recording Skia rendering
// calls that originated outside of the Flutter dart code. This would
// primarily happen in the Paragraph code that renders the text using the
// SkCanvas interface which we capture into DisplayList data structures.
class DlUnknownImageFilter final : public DlImageFilter {
 public:
  explicit DlUnknownImageFilter(sk_sp<SkImageFilter> sk_filter)
      : sk_filter_(std::move(sk_filter)) {}
  explicit DlUnknownImageFilter(const SkImageFilter* sk_filter)
      : sk_filter_(sk_ref_sp(sk_filter)) {}
  explicit DlUnknownImageFilter(const DlUnknownImageFilter* filter)
      : DlUnknownImageFilter(filter->sk_filter_) {}
  explicit DlUnknownImageFilter(const DlUnknownImageFilter& filter)
      : DlUnknownImageFilter(&filter) {}

  DlImageFilterType type() const override {
    return DlImageFilterType::kUnknown;
  }
  size_t size() const override { return sizeof(*this); }

  std::shared_ptr<DlImageFilter> shared() const override {
    return std::make_shared<DlUnknownImageFilter>(this);
  }

  bool modifies_transparent_black() const override {
    if (!sk_filter_) {
      return false;
    }
    return !sk_filter_->canComputeFastBounds();
  }

  SkRect* map_local_bounds(const SkRect& input_bounds,
                           SkRect& output_bounds) const override {
    output_bounds = input_bounds;
    if (modifies_transparent_black()) {
      return nullptr;
    }
    output_bounds = sk_filter_->computeFastBounds(input_bounds);
    return &output_bounds;
  }

  SkIRect* map_device_bounds(const SkIRect& input_bounds,
                             const SkMatrix& ctm,
                             SkIRect& output_bounds) const override {
    output_bounds = input_bounds;
    if (modifies_transparent_black()) {
      return nullptr;
    }
    output_bounds = sk_filter_->filterBounds(
        input_bounds, ctm, SkImageFilter::kForward_MapDirection);
    return &output_bounds;
  }

  sk_sp<SkImageFilter> skia_object() const override { return sk_filter_; }

  virtual ~DlUnknownImageFilter() = default;

 protected:
  bool equals_(const DlImageFilter& other) const override {
    FML_DCHECK(other.type() == DlImageFilterType::kUnknown);
    auto that = static_cast<DlUnknownImageFilter const*>(&other);
    return sk_filter_ == that->sk_filter_;
  }

 private:
  sk_sp<SkImageFilter> sk_filter_;
};

}  // namespace flutter

#endif  // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_IMAGE_FILTER_H_
