| // 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_EFFECTS_DL_COLOR_FILTER_H_ |
| #define FLUTTER_DISPLAY_LIST_EFFECTS_DL_COLOR_FILTER_H_ |
| |
| #include "flutter/display_list/dl_attributes.h" |
| #include "flutter/display_list/dl_blend_mode.h" |
| #include "flutter/display_list/dl_color.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 supported ColorFilter operations. |
| enum class DlColorFilterType { |
| kBlend, |
| kMatrix, |
| kSrgbToLinearGamma, |
| kLinearToSrgbGamma, |
| }; |
| |
| class DlColorFilter : public DlAttribute<DlColorFilter, DlColorFilterType> { |
| public: |
| // 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 boolean indicating whether the color filtering operation can |
| // be applied either before or after modulating the pixels with an opacity |
| // value without changing the operation. |
| virtual bool can_commute_with_opacity() const { return false; } |
| |
| // 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 is not needed because it has no properties to query. |
| // Its type fully specifies its operation. |
| }; |
| |
| // 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_) {} |
| explicit DlBlendColorFilter(const DlBlendColorFilter* filter) |
| : DlBlendColorFilter(filter->color_, filter->mode_) {} |
| |
| static std::shared_ptr<DlColorFilter> Make(DlColor color, DlBlendMode mode); |
| |
| DlColorFilterType type() const override { return DlColorFilterType::kBlend; } |
| size_t size() const override { return sizeof(*this); } |
| |
| bool modifies_transparent_black() const override; |
| bool can_commute_with_opacity() const override; |
| |
| std::shared_ptr<DlColorFilter> shared() const override { |
| return std::make_shared<DlBlendColorFilter>(this); |
| } |
| |
| 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. |
| // |
| // The incoming and outgoing [iR,iG,iB,iA] and [oR,oG,oB,oA] are |
| // considered to be non-premultiplied. When working on premultiplied |
| // pixel data, the necessary pre<->non-pre conversions must be performed. |
| class DlMatrixColorFilter final : public DlColorFilter { |
| public: |
| explicit DlMatrixColorFilter(const float matrix[20]) { |
| memcpy(matrix_, matrix, sizeof(matrix_)); |
| } |
| DlMatrixColorFilter(const DlMatrixColorFilter& filter) |
| : DlMatrixColorFilter(filter.matrix_) {} |
| explicit DlMatrixColorFilter(const DlMatrixColorFilter* filter) |
| : DlMatrixColorFilter(filter->matrix_) {} |
| |
| static std::shared_ptr<DlColorFilter> Make(const float matrix[20]); |
| |
| DlColorFilterType type() const override { return DlColorFilterType::kMatrix; } |
| size_t size() const override { return sizeof(*this); } |
| |
| bool modifies_transparent_black() const override; |
| bool can_commute_with_opacity() const override; |
| |
| std::shared_ptr<DlColorFilter> shared() const override { |
| return std::make_shared<DlMatrixColorFilter>(this); |
| } |
| |
| 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> kInstance; |
| |
| DlSrgbToLinearGammaColorFilter() {} |
| DlSrgbToLinearGammaColorFilter(const DlSrgbToLinearGammaColorFilter& filter) |
| : DlSrgbToLinearGammaColorFilter() {} |
| explicit 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; } |
| bool can_commute_with_opacity() const override { return true; } |
| |
| std::shared_ptr<DlColorFilter> shared() const override { return kInstance; } |
| |
| protected: |
| bool equals_(const DlColorFilter& other) const override { |
| FML_DCHECK(other.type() == DlColorFilterType::kSrgbToLinearGamma); |
| return true; |
| } |
| |
| private: |
| 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> kInstance; |
| |
| DlLinearToSrgbGammaColorFilter() {} |
| DlLinearToSrgbGammaColorFilter(const DlLinearToSrgbGammaColorFilter& filter) |
| : DlLinearToSrgbGammaColorFilter() {} |
| explicit 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; } |
| bool can_commute_with_opacity() const override { return true; } |
| |
| std::shared_ptr<DlColorFilter> shared() const override { return kInstance; } |
| |
| protected: |
| bool equals_(const DlColorFilter& other) const override { |
| FML_DCHECK(other.type() == DlColorFilterType::kLinearToSrgbGamma); |
| return true; |
| } |
| |
| private: |
| friend class DlColorFilter; |
| }; |
| |
| } // namespace flutter |
| |
| #endif // FLUTTER_DISPLAY_LIST_EFFECTS_DL_COLOR_FILTER_H_ |