• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkColorSpace.h"
9 #include "include/core/SkFlattenable.h"
10 #include "include/core/SkImageFilter.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkRect.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/core/SkShader.h"
15 #include "include/core/SkTypes.h"
16 #include "include/effects/SkImageFilters.h"
17 #include "src/core/SkImageFilterTypes.h"
18 #include "src/core/SkImageFilter_Base.h"
19 #include "src/core/SkPicturePriv.h"
20 #include "src/core/SkReadBuffer.h"
21 #include "src/core/SkRectPriv.h"
22 #include "src/core/SkWriteBuffer.h"
23 
24 #include <optional>
25 #include <utility>
26 
27 namespace {
28 
29 class SkShaderImageFilter final : public SkImageFilter_Base {
30 public:
SkShaderImageFilter(sk_sp<SkShader> shader,SkImageFilters::Dither dither)31     SkShaderImageFilter(sk_sp<SkShader> shader, SkImageFilters::Dither dither)
32             : SkImageFilter_Base(nullptr, 0)
33             , fShader(std::move(shader))
34             , fDither(dither) {
35         SkASSERT(fShader);
36     }
37 
computeFastBounds(const SkRect &) const38     SkRect computeFastBounds(const SkRect& /*bounds*/) const override {
39         return SkRectPriv::MakeLargeS32();
40     }
41 
42 protected:
43     void flatten(SkWriteBuffer&) const override;
44 
45 private:
46     friend void ::SkRegisterShaderImageFilterFlattenable();
SK_FLATTENABLE_HOOKS(SkShaderImageFilter)47     SK_FLATTENABLE_HOOKS(SkShaderImageFilter)
48 
49     bool onAffectsTransparentBlack() const override { return true; }
50 
onGetCTMCapability() const51     MatrixCapability onGetCTMCapability() const override { return MatrixCapability::kComplex; }
52 
53     skif::FilterResult onFilterImage(const skif::Context&) const override;
54 
55     skif::LayerSpace<SkIRect> onGetInputLayerBounds(
56             const skif::Mapping& mapping,
57             const skif::LayerSpace<SkIRect>& desiredOutput,
58             std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;
59 
60     std::optional<skif::LayerSpace<SkIRect>> onGetOutputLayerBounds(
61             const skif::Mapping& mapping,
62             std::optional<skif::LayerSpace<SkIRect>> contentBounds) const override;
63 
64     sk_sp<SkShader> fShader;
65     SkImageFilters::Dither fDither;
66 };
67 
68 } // end namespace
69 
Shader(sk_sp<SkShader> shader,Dither dither,const CropRect & cropRect)70 sk_sp<SkImageFilter> SkImageFilters::Shader(sk_sp<SkShader> shader,
71                                             Dither dither,
72                                             const CropRect& cropRect) {
73     if (!shader) {
74         return SkImageFilters::Empty();
75     }
76 
77     sk_sp<SkImageFilter> filter{new SkShaderImageFilter(std::move(shader), dither)};
78     if (cropRect) {
79         filter = SkImageFilters::Crop(*cropRect, std::move(filter));
80     }
81     return filter;
82 }
83 
SkRegisterShaderImageFilterFlattenable()84 void SkRegisterShaderImageFilterFlattenable() {
85     SK_REGISTER_FLATTENABLE(SkShaderImageFilter);
86     // TODO (michaelludwig) - Remove after grace period for SKPs to stop using old name
87     SkFlattenable::Register("SkPaintImageFilter", SkShaderImageFilter::CreateProc);
88     SkFlattenable::Register("SkPaintImageFilterImpl", SkShaderImageFilter::CreateProc);
89 }
90 
CreateProc(SkReadBuffer & buffer)91 sk_sp<SkFlattenable> SkShaderImageFilter::CreateProc(SkReadBuffer& buffer) {
92     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
93     sk_sp<SkShader> shader;
94     bool dither;
95     if (buffer.isVersionLT(SkPicturePriv::kShaderImageFilterSerializeShader)) {
96         // The old implementation stored an entire SkPaint, but we only need the SkShader and dither
97         // boolean. We could fail if the paint stores more effects than that, but this is simpler.
98         SkPaint paint = buffer.readPaint();
99         shader = paint.getShader() ? paint.refShader()
100                                    : SkShaders::Color(paint.getColor4f(), nullptr);
101         dither = paint.isDither();
102     } else {
103         shader = buffer.readShader();
104         dither = buffer.readBool();
105     }
106     return SkImageFilters::Shader(std::move(shader),
107                                   SkImageFilters::Dither(dither),
108                                   common.cropRect());
109 }
110 
flatten(SkWriteBuffer & buffer) const111 void SkShaderImageFilter::flatten(SkWriteBuffer& buffer) const {
112     this->SkImageFilter_Base::flatten(buffer);
113     buffer.writeFlattenable(fShader.get());
114     buffer.writeBool(fDither == SkImageFilters::Dither::kYes);
115 }
116 
117 ///////////////////////////////////////////////////////////////////////////////////////////////////
118 
onFilterImage(const skif::Context & ctx) const119 skif::FilterResult SkShaderImageFilter::onFilterImage(const skif::Context& ctx) const {
120     const bool dither = fDither == SkImageFilters::Dither::kYes;
121     return skif::FilterResult::MakeFromShader(ctx, fShader, dither);
122 }
123 
onGetInputLayerBounds(const skif::Mapping &,const skif::LayerSpace<SkIRect> &,std::optional<skif::LayerSpace<SkIRect>>) const124 skif::LayerSpace<SkIRect> SkShaderImageFilter::onGetInputLayerBounds(
125         const skif::Mapping&,
126         const skif::LayerSpace<SkIRect>&,
127         std::optional<skif::LayerSpace<SkIRect>>) const {
128     // This is a leaf filter, it requires no input and no further recursion
129     return skif::LayerSpace<SkIRect>::Empty();
130 }
131 
onGetOutputLayerBounds(const skif::Mapping &,std::optional<skif::LayerSpace<SkIRect>>) const132 std::optional<skif::LayerSpace<SkIRect>> SkShaderImageFilter::onGetOutputLayerBounds(
133         const skif::Mapping&,
134         std::optional<skif::LayerSpace<SkIRect>>) const {
135     // The output of a shader is infinite, unless we were to inspect the shader for a decal
136     // tile mode around a gradient or image.
137     return skif::LayerSpace<SkIRect>::Unbounded();
138 }
139