// 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_COLOR_FILTER_H_
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_COLOR_FILTER_H_

#include "flutter/display_list/display_list_attributes.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_color.h"
#include "flutter/display_list/types.h"
#include "flutter/fml/logging.h"

namespace flutter {

class DlBlendColorFilter;
class DlMatrixColorFilter;

// The DisplayList ColorFilter class. This class implements all of the
// facilities and adheres to the design goals of the |DlAttribute| base
// class.

// An enumerated type for the recognized ColorFilter operations.
// If a custom ColorFilter outside of the recognized types is needed
// then a |kUnknown| type that simply defers to an SkColorFilter is
// provided as a fallback.
enum class DlColorFilterType {
  kBlend,
  kMatrix,
  kSrgbToLinearGamma,
  kLinearToSrgbGamma,
  kUnknown
};

class DlColorFilter
    : public DlAttribute<DlColorFilter, SkColorFilter, DlColorFilterType> {
 public:
  // Return a shared_ptr holding a DlColorFilter representing the indicated
  // Skia SkColorFilter pointer.
  //
  // This method can detect each of the 4 recognized types from an analogous
  // SkColorFilter.
  static std::shared_ptr<DlColorFilter> From(SkColorFilter* sk_filter);

  // Return a shared_ptr holding a DlColorFilter representing the indicated
  // Skia SkColorFilter pointer.
  //
  // This method can detect each of the 4 recognized types from an analogous
  // SkColorFilter.
  static std::shared_ptr<DlColorFilter> From(sk_sp<SkColorFilter> sk_filter) {
    return From(sk_filter.get());
  }

  // Return a boolean indicating whether the color filtering operation will
  // modify transparent black. This is typically used to determine if applying
  // the ColorFilter 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 a DlBlendColorFilter pointer to this object iff it is a Blend
  // type of ColorFilter, otherwise return nullptr.
  virtual const DlBlendColorFilter* asBlend() const { return nullptr; }

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

  // asSrgb<->Linear and asUnknown are not needed because they
  // have no properties to query. Their type fully specifies their
  // operation or can be accessed via the common skia_object() method.
};

// The Blend type of ColorFilter which specifies modifying the
// colors as if the color specified in the Blend filter is the
// source color and the color drawn by the rendering operation
// is the destination color. The mode parameter of the Blend
// filter is then used to combine those colors.
class DlBlendColorFilter final : public DlColorFilter {
 public:
  DlBlendColorFilter(DlColor color, DlBlendMode mode)
      : color_(color), mode_(mode) {}
  DlBlendColorFilter(const DlBlendColorFilter& filter)
      : DlBlendColorFilter(filter.color_, filter.mode_) {}
  DlBlendColorFilter(const DlBlendColorFilter* filter)
      : DlBlendColorFilter(filter->color_, filter->mode_) {}

  DlColorFilterType type() const override { return DlColorFilterType::kBlend; }
  size_t size() const override { return sizeof(*this); }
  bool modifies_transparent_black() const override {
    // Look at blend and color to make a faster determination?
    sk_sp<SkColorFilter> sk_filter = skia_object();
    return sk_filter &&
           sk_filter->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
  }

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

  sk_sp<SkColorFilter> skia_object() const override {
    return SkColorFilters::Blend(color_, ToSk(mode_));
  }

  const DlBlendColorFilter* asBlend() const override { return this; }

  DlColor color() const { return color_; }
  DlBlendMode mode() const { return mode_; }

 protected:
  bool equals_(DlColorFilter const& other) const override {
    FML_DCHECK(other.type() == DlColorFilterType::kBlend);
    auto that = static_cast<DlBlendColorFilter const*>(&other);
    return color_ == that->color_ && mode_ == that->mode_;
  }

 private:
  DlColor color_;
  DlBlendMode mode_;
};

// The Matrix type of ColorFilter which runs every pixel drawn by
// the rendering operation [iR,iG,iB,iA] through a vector/matrix
// multiplication, as in:
//
//  [ oR ]   [ m[ 0] m[ 1] m[ 2] m[ 3] m[ 4] ]   [ iR ]
//  [ oG ]   [ m[ 5] m[ 6] m[ 7] m[ 8] m[ 9] ]   [ iG ]
//  [ oB ] = [ m[10] m[11] m[12] m[13] m[14] ] x [ iB ]
//  [ oA ]   [ m[15] m[16] m[17] m[18] m[19] ]   [ iA ]
//                                               [  1 ]
//
// The resulting color [oR,oG,oB,oA] is then clamped to the range of
// valid pixel components before storing in the output.
class DlMatrixColorFilter final : public DlColorFilter {
 public:
  DlMatrixColorFilter(const float matrix[20]) {
    memcpy(matrix_, matrix, sizeof(matrix_));
  }
  DlMatrixColorFilter(const DlMatrixColorFilter& filter)
      : DlMatrixColorFilter(filter.matrix_) {}
  DlMatrixColorFilter(const DlMatrixColorFilter* filter)
      : DlMatrixColorFilter(filter->matrix_) {}

  DlColorFilterType type() const override { return DlColorFilterType::kMatrix; }
  size_t size() const override { return sizeof(*this); }
  bool modifies_transparent_black() const override {
    // Look at the matrix to make a faster determination?
    // Basically, are the translation components all 0?
    sk_sp<SkColorFilter> sk_filter = skia_object();
    return sk_filter &&
           sk_filter->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
  }

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

  sk_sp<SkColorFilter> skia_object() const override {
    return SkColorFilters::Matrix(matrix_);
  }

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

  const float& operator[](int index) const { return matrix_[index]; }
  void get_matrix(float matrix[20]) const {
    memcpy(matrix, matrix_, sizeof(matrix_));
  }

 protected:
  bool equals_(const DlColorFilter& other) const override {
    FML_DCHECK(other.type() == DlColorFilterType::kMatrix);
    auto that = static_cast<DlMatrixColorFilter const*>(&other);
    return memcmp(matrix_, that->matrix_, sizeof(matrix_)) == 0;
  }

 private:
  float matrix_[20];
};

// The SrgbToLinear type of ColorFilter that applies the inverse of the sRGB
// gamma curve to the rendered pixels.
class DlSrgbToLinearGammaColorFilter final : public DlColorFilter {
 public:
  static const std::shared_ptr<DlSrgbToLinearGammaColorFilter> instance;

  DlSrgbToLinearGammaColorFilter() {}
  DlSrgbToLinearGammaColorFilter(const DlSrgbToLinearGammaColorFilter& filter)
      : DlSrgbToLinearGammaColorFilter() {}
  DlSrgbToLinearGammaColorFilter(const DlSrgbToLinearGammaColorFilter* filter)
      : DlSrgbToLinearGammaColorFilter() {}

  DlColorFilterType type() const override {
    return DlColorFilterType::kSrgbToLinearGamma;
  }
  size_t size() const override { return sizeof(*this); }
  bool modifies_transparent_black() const override { return false; }

  std::shared_ptr<DlColorFilter> shared() const override { return instance; }
  sk_sp<SkColorFilter> skia_object() const override { return sk_filter_; }

 protected:
  bool equals_(const DlColorFilter& other) const override {
    FML_DCHECK(other.type() == DlColorFilterType::kSrgbToLinearGamma);
    return true;
  }

 private:
  static const sk_sp<SkColorFilter> sk_filter_;
  friend class DlColorFilter;
};

// The LinearToSrgb type of ColorFilter that applies the sRGB gamma curve
// to the rendered pixels.
class DlLinearToSrgbGammaColorFilter final : public DlColorFilter {
 public:
  static const std::shared_ptr<DlLinearToSrgbGammaColorFilter> instance;

  DlLinearToSrgbGammaColorFilter() {}
  DlLinearToSrgbGammaColorFilter(const DlLinearToSrgbGammaColorFilter& filter)
      : DlLinearToSrgbGammaColorFilter() {}
  DlLinearToSrgbGammaColorFilter(const DlLinearToSrgbGammaColorFilter* filter)
      : DlLinearToSrgbGammaColorFilter() {}

  DlColorFilterType type() const override {
    return DlColorFilterType::kLinearToSrgbGamma;
  }
  size_t size() const override { return sizeof(*this); }
  bool modifies_transparent_black() const override { return false; }

  std::shared_ptr<DlColorFilter> shared() const override { return instance; }
  sk_sp<SkColorFilter> skia_object() const override { return sk_filter_; }

 protected:
  bool equals_(const DlColorFilter& other) const override {
    FML_DCHECK(other.type() == DlColorFilterType::kLinearToSrgbGamma);
    return true;
  }

 private:
  static const sk_sp<SkColorFilter> sk_filter_;
  friend class DlColorFilter;
};

// A wrapper class for a Skia ColorFilter of unknown type. The above 4 types
// are the only types that can be constructed by Flutter using the
// ui.ColorFilter 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 DlUnknownColorFilter final : public DlColorFilter {
 public:
  DlUnknownColorFilter(sk_sp<SkColorFilter> sk_filter)
      : sk_filter_(std::move(sk_filter)) {}
  DlUnknownColorFilter(const DlUnknownColorFilter& filter)
      : DlUnknownColorFilter(filter.sk_filter_) {}
  DlUnknownColorFilter(const DlUnknownColorFilter* filter)
      : DlUnknownColorFilter(filter->sk_filter_) {}

  DlColorFilterType type() const override {
    return DlColorFilterType::kUnknown;
  }
  size_t size() const override { return sizeof(*this); }
  bool modifies_transparent_black() const override {
    return sk_filter_->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
  }

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

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

  virtual ~DlUnknownColorFilter() = default;

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

 private:
  sk_sp<SkColorFilter> sk_filter_;
};

}  // namespace flutter

#endif  // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_COLOR_FILTER_H_
