1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "skia_image_filter.h"
17 #include "skia_helper.h"
18 
19 #include "include/effects/SkImageFilters.h"
20 #include "include/core/SkTileMode.h"
21 #include "src/core/SkImageFilter_Base.h"
22 
23 #include "skia_color_filter.h"
24 #include "skia_shader_effect.h"
25 
26 #include "effect/color_filter.h"
27 #include "effect/image_filter.h"
28 #include "utils/data.h"
29 #include "utils/log.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 namespace Drawing {
34 static constexpr size_t numberOfCoefficients = 4;
35 
SkiaImageFilter()36 SkiaImageFilter::SkiaImageFilter() noexcept : filter_(nullptr) {}
37 
ConvertToSkTileMode(const TileMode & mode)38 static inline SkTileMode ConvertToSkTileMode(const TileMode& mode)
39 {
40     switch (mode) {
41         case TileMode::CLAMP:
42             return SkTileMode::kClamp;
43         case TileMode::REPEAT:
44             return SkTileMode::kRepeat;
45         case TileMode::MIRROR:
46             return SkTileMode::kMirror;
47         case TileMode::DECAL:
48             return SkTileMode::kDecal;
49         default:
50             return SkTileMode::kClamp;
51     }
52 }
53 
InitWithBlur(scalar sigmaX,scalar sigmaY,TileMode mode,const std::shared_ptr<ImageFilter> f,ImageBlurType blurType,const Rect & cropRect)54 void SkiaImageFilter::InitWithBlur(scalar sigmaX, scalar sigmaY, TileMode mode, const std::shared_ptr<ImageFilter> f,
55     ImageBlurType blurType, const Rect& cropRect)
56 {
57     // SK only support gauss, ignore the input blurType
58     sk_sp<SkImageFilter> input = nullptr;
59     if (f != nullptr && f->GetImpl<SkiaImageFilter>() != nullptr) {
60         input = f->GetImpl<SkiaImageFilter>()->GetImageFilter();
61     }
62     SkRect skiaRect = {cropRect.left_, cropRect.top_, cropRect.right_, cropRect.bottom_};
63     SkImageFilters::CropRect skCropRect(skiaRect);
64     filter_ = SkImageFilters::Blur(sigmaX, sigmaY, ConvertToSkTileMode(mode), input, skCropRect);
65 }
66 
InitWithColor(const ColorFilter & colorFilter,const std::shared_ptr<ImageFilter> f,const Rect & cropRect)67 void SkiaImageFilter::InitWithColor(const ColorFilter& colorFilter,
68     const std::shared_ptr<ImageFilter> f, const Rect& cropRect)
69 {
70     sk_sp<SkImageFilter> input = nullptr;
71     if (f != nullptr && f->GetImpl<SkiaImageFilter>() != nullptr) {
72         input = f->GetImpl<SkiaImageFilter>()->GetImageFilter();
73     }
74     SkRect skiaRect = {cropRect.left_, cropRect.top_, cropRect.right_, cropRect.bottom_};
75     SkImageFilters::CropRect skCropRect(skiaRect);
76     auto skColorFilterImpl = colorFilter.GetImpl<SkiaColorFilter>();
77     if (skColorFilterImpl != nullptr) {
78         filter_ = SkImageFilters::ColorFilter(skColorFilterImpl->GetColorFilter(), input, skCropRect);
79     }
80 }
81 
InitWithOffset(scalar dx,scalar dy,const std::shared_ptr<ImageFilter> f,const Rect & cropRect)82 void SkiaImageFilter::InitWithOffset(scalar dx, scalar dy,
83     const std::shared_ptr<ImageFilter> f, const Rect& cropRect)
84 {
85     sk_sp<SkImageFilter> input = nullptr;
86     if (f != nullptr && f->GetImpl<SkiaImageFilter>() != nullptr) {
87         input = f->GetImpl<SkiaImageFilter>()->GetImageFilter();
88     }
89     SkRect skiaRect = {cropRect.left_, cropRect.top_, cropRect.right_, cropRect.bottom_};
90     SkImageFilters::CropRect skCropRect(skiaRect);
91     filter_ = SkImageFilters::Offset(dx, dy, input, skCropRect);
92 }
93 
InitWithColorBlur(const ColorFilter & colorFilter,scalar sigmaX,scalar sigmaY,ImageBlurType blurType,const Rect & cropRect)94 void SkiaImageFilter::InitWithColorBlur(const ColorFilter& colorFilter, scalar sigmaX, scalar sigmaY,
95     ImageBlurType blurType, const Rect& cropRect)
96 {
97     // SK only support gauss, ignore the input blurType
98     auto skColorFilterImpl = colorFilter.GetImpl<SkiaColorFilter>();
99     SkRect skiaRect = {cropRect.left_, cropRect.top_, cropRect.right_, cropRect.bottom_};
100     SkImageFilters::CropRect skCropRect(skiaRect);
101     filter_ = SkImageFilters::ColorFilter(
102         skColorFilterImpl->GetColorFilter(),
103         SkImageFilters::Blur(sigmaX, sigmaY, SkTileMode::kClamp, nullptr), skCropRect);
104 }
105 
InitWithArithmetic(const std::vector<scalar> & coefficients,bool enforcePMColor,const std::shared_ptr<ImageFilter> f1,const std::shared_ptr<ImageFilter> f2,const Rect & cropRect)106 void SkiaImageFilter::InitWithArithmetic(const std::vector<scalar>& coefficients,
107     bool enforcePMColor, const std::shared_ptr<ImageFilter> f1,
108     const std::shared_ptr<ImageFilter> f2, const Rect& cropRect)
109 {
110     if (coefficients.size() != numberOfCoefficients) {
111         LOGD("SkiaImageFilter::InitWithArithmetic: the number of coefficients must be 4");
112         return;
113     }
114 
115     sk_sp<SkImageFilter> background = nullptr;
116     sk_sp<SkImageFilter> foreground = nullptr;
117     if (f1 != nullptr && f1->GetImpl<SkiaImageFilter>() != nullptr) {
118         background = f1->GetImpl<SkiaImageFilter>()->GetImageFilter();
119     }
120     if (f2 != nullptr && f2->GetImpl<SkiaImageFilter>() != nullptr) {
121         foreground = f2->GetImpl<SkiaImageFilter>()->GetImageFilter();
122     }
123     SkRect skiaRect = {cropRect.left_, cropRect.top_, cropRect.right_, cropRect.bottom_};
124     SkImageFilters::CropRect skCropRect(skiaRect);
125     filter_ = SkImageFilters::Arithmetic(coefficients[0],
126         coefficients[1], coefficients[2], coefficients[3], // 0 1 2 3 used to combine the foreground and background.
127         enforcePMColor, background, foreground, skCropRect);
128 }
129 
InitWithCompose(const std::shared_ptr<ImageFilter> f1,const std::shared_ptr<ImageFilter> f2)130 void SkiaImageFilter::InitWithCompose(const std::shared_ptr<ImageFilter> f1, const std::shared_ptr<ImageFilter> f2)
131 {
132     sk_sp<SkImageFilter> outer = nullptr;
133     sk_sp<SkImageFilter> inner = nullptr;
134     if (f1 != nullptr && f1->GetImpl<SkiaImageFilter>() != nullptr) {
135         outer = f1->GetImpl<SkiaImageFilter>()->GetImageFilter();
136     }
137     if (f2 != nullptr && f2->GetImpl<SkiaImageFilter>() != nullptr) {
138         inner = f2->GetImpl<SkiaImageFilter>()->GetImageFilter();
139     }
140     filter_ = SkImageFilters::Compose(outer, inner);
141 }
142 
InitWithGradientBlur(float radius,const std::vector<std::pair<float,float>> & fractionStops,GradientDir direction,GradientBlurType blurType,const std::shared_ptr<ImageFilter> f)143 void SkiaImageFilter::InitWithGradientBlur(float radius,
144     const std::vector<std::pair<float, float>>& fractionStops, GradientDir direction,
145     GradientBlurType blurType, const std::shared_ptr<ImageFilter> f)
146 {
147     return;
148 }
149 
GetImageFilter() const150 sk_sp<SkImageFilter> SkiaImageFilter::GetImageFilter() const
151 {
152     return filter_;
153 }
154 
SetSkImageFilter(const sk_sp<SkImageFilter> & filter)155 void SkiaImageFilter::SetSkImageFilter(const sk_sp<SkImageFilter>& filter)
156 {
157     filter_ = filter;
158 }
159 
Serialize() const160 std::shared_ptr<Data> SkiaImageFilter::Serialize() const
161 {
162     if (filter_ == nullptr) {
163         return nullptr;
164     }
165 
166     SkBinaryWriteBuffer writer;
167     writer.writeFlattenable(filter_.get());
168     size_t length = writer.bytesWritten();
169     std::shared_ptr<Data> data = std::make_shared<Data>();
170     data->BuildUninitialized(length);
171     writer.writeToMemory(data->WritableData());
172     return data;
173 }
174 
Deserialize(std::shared_ptr<Data> data)175 bool SkiaImageFilter::Deserialize(std::shared_ptr<Data> data)
176 {
177     if (data == nullptr) {
178         LOGD("SkiaImageFilter::Deserialize, data is invalid!");
179         return false;
180     }
181 
182     SkReadBuffer reader(data->GetData(), data->GetSize());
183     filter_ = SkiaHelper::FlattenableDeserialize<SkImageFilter_Base>(data);
184     return true;
185 }
186 
InitWithBlend(BlendMode mode,const Rect & cropRect,std::shared_ptr<ImageFilter> background,std::shared_ptr<ImageFilter> foreground)187 void SkiaImageFilter::InitWithBlend(BlendMode mode, const Rect& cropRect,
188     std::shared_ptr<ImageFilter> background, std::shared_ptr<ImageFilter> foreground)
189 {
190     sk_sp<SkImageFilter> outer = nullptr;
191     sk_sp<SkImageFilter> inner = nullptr;
192     if (background != nullptr && background->GetImpl<SkiaImageFilter>() != nullptr) {
193         outer = background->GetImpl<SkiaImageFilter>()->GetImageFilter();
194     }
195     if (foreground != nullptr && foreground->GetImpl<SkiaImageFilter>() != nullptr) {
196         inner = foreground->GetImpl<SkiaImageFilter>()->GetImageFilter();
197     }
198     SkRect skiaRect = {cropRect.left_, cropRect.top_, cropRect.right_, cropRect.bottom_};
199     SkImageFilters::CropRect skCropRect(skiaRect);
200     filter_ = SkImageFilters::Blend(static_cast<SkBlendMode>(mode), outer, inner, skCropRect);
201 }
202 
InitWithShader(std::shared_ptr<ShaderEffect> shader,const Rect & cropRect)203 void SkiaImageFilter::InitWithShader(std::shared_ptr<ShaderEffect> shader, const Rect& cropRect)
204 {
205     sk_sp<SkShader> skShader = nullptr;
206     if (shader != nullptr && shader->GetImpl<SkiaShaderEffect>() != nullptr) {
207         skShader = shader->GetImpl<SkiaShaderEffect>()->GetShader();
208     }
209     SkRect skiaRect = {cropRect.left_, cropRect.top_, cropRect.right_, cropRect.bottom_};
210     SkImageFilters::CropRect skCropRect(skiaRect);
211     filter_ = SkImageFilters::Shader(skShader, skCropRect);
212 }
213 
214 } // namespace Drawing
215 } // namespace Rosen
216 } // namespace OHOS
217