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