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_shader_effect.h"
17
18 #include <vector>
19
20 #include "include/core/SkMatrix.h"
21 #include "include/core/SkSamplingOptions.h"
22 #include "include/core/SkTileMode.h"
23 #include "include/effects/SkGradientShader.h"
24 #include "include/effects/SkRuntimeEffect.h"
25 #include "src/core/SkReadBuffer.h"
26 #include "src/core/SkWriteBuffer.h"
27 #include "src/shaders/SkShaderBase.h"
28
29 #include "skia_helper.h"
30 #include "skia_image.h"
31 #include "skia_matrix.h"
32 #include "skia_picture.h"
33
34 #include "effect/shader_effect.h"
35 #include "image/image.h"
36 #include "image/picture.h"
37 #include "utils/matrix.h"
38 #include "utils/data.h"
39 #include "utils/log.h"
40
41 namespace OHOS {
42 namespace Rosen {
43 namespace Drawing {
SkiaShaderEffect()44 SkiaShaderEffect::SkiaShaderEffect() noexcept : shader_(nullptr) {}
45
InitWithColor(ColorQuad color)46 void SkiaShaderEffect::InitWithColor(ColorQuad color)
47 {
48 shader_ = SkShaders::Color(color);
49 }
50
InitWithColorSpace(const Color4f & color,std::shared_ptr<ColorSpace> colorSpace)51 void SkiaShaderEffect::InitWithColorSpace(const Color4f& color, std::shared_ptr<ColorSpace> colorSpace)
52 {
53 const SkColor4f& skC4f = { .fR = color.redF_, .fG = color.greenF_, .fB = color.blueF_, .fA = color.alphaF_ };
54 shader_ = SkShaders::Color(skC4f, colorSpace->GetSkColorSpace());
55 }
56
InitWithBlend(const ShaderEffect & s1,const ShaderEffect & s2,BlendMode mode)57 void SkiaShaderEffect::InitWithBlend(const ShaderEffect& s1, const ShaderEffect& s2, BlendMode mode)
58 {
59 auto dst = s1.GetImpl<SkiaShaderEffect>();
60 auto src = s2.GetImpl<SkiaShaderEffect>();
61 if (dst != nullptr && src != nullptr) {
62 shader_ = SkShaders::Blend(static_cast<SkBlendMode>(mode), dst->GetShader(), src->GetShader());
63 }
64 }
65
InitWithImage(const Image & image,TileMode tileX,TileMode tileY,const SamplingOptions & sampling,const Matrix & matrix)66 void SkiaShaderEffect::InitWithImage(
67 const Image& image, TileMode tileX, TileMode tileY, const SamplingOptions& sampling, const Matrix& matrix)
68 {
69 SkTileMode modeX = static_cast<SkTileMode>(tileX);
70 SkTileMode modeY = static_cast<SkTileMode>(tileY);
71
72 auto m = matrix.GetImpl<SkiaMatrix>();
73 auto i = image.GetImpl<SkiaImage>();
74 SkMatrix skiaMatrix;
75 sk_sp<SkImage> skiaImage;
76 if (m != nullptr && i != nullptr) {
77 skiaMatrix = m->ExportSkiaMatrix();
78 skiaImage = i->GetImage();
79 if (skiaImage != nullptr) {
80 SkSamplingOptions samplingOptions;
81 if (sampling.GetUseCubic()) {
82 samplingOptions = SkSamplingOptions({ sampling.GetCubicCoffB(), sampling.GetCubicCoffC() });
83 } else {
84 samplingOptions = SkSamplingOptions(static_cast<SkFilterMode>(sampling.GetFilterMode()),
85 static_cast<SkMipmapMode>(sampling.GetMipmapMode()));
86 }
87 shader_ = skiaImage->makeShader(modeX, modeY, samplingOptions, &skiaMatrix);
88 }
89 }
90 }
91
InitWithPicture(const Picture & picture,TileMode tileX,TileMode tileY,FilterMode mode,const Matrix & matrix,const Rect & rect)92 void SkiaShaderEffect::InitWithPicture(
93 const Picture& picture, TileMode tileX, TileMode tileY, FilterMode mode, const Matrix& matrix, const Rect& rect)
94 {
95 SkTileMode modeX = static_cast<SkTileMode>(tileX);
96 SkTileMode modeY = static_cast<SkTileMode>(tileY);
97 SkRect r = SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
98
99 auto p = picture.GetImpl<SkiaPicture>();
100 auto m = matrix.GetImpl<SkiaMatrix>();
101 sk_sp<SkPicture> skiaPicture;
102 SkMatrix skiaMatrix;
103 if (p != nullptr && m != nullptr) {
104 skiaPicture = p->GetPicture();
105 skiaMatrix = m->ExportSkiaMatrix();
106 if (skiaPicture != nullptr) {
107 SkFilterMode skFilterMode = static_cast<SkFilterMode>(mode);
108 shader_ = skiaPicture->makeShader(modeX, modeY, skFilterMode, &skiaMatrix, &r);
109 }
110 }
111 }
112
InitWithLinearGradient(const Point & startPt,const Point & endPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)113 void SkiaShaderEffect::InitWithLinearGradient(const Point& startPt, const Point& endPt,
114 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode, const Matrix *matrix)
115 {
116 SkPoint pts[2];
117 pts[0].set(startPt.GetX(), startPt.GetY());
118 pts[1].set(endPt.GetX(), endPt.GetY());
119
120 if (colors.empty()) {
121 return;
122 }
123 size_t colorsCount = colors.size();
124
125 std::vector<SkColor> c;
126 std::vector<SkScalar> p;
127 for (size_t i = 0; i < colorsCount; ++i) {
128 c.emplace_back(colors[i]);
129 }
130 for (size_t i = 0; i < pos.size(); ++i) {
131 p.emplace_back(pos[i]);
132 }
133 const SkMatrix *skMatrix = nullptr;
134 if (matrix != nullptr) {
135 skMatrix = &matrix->GetImpl<SkiaMatrix>()->ExportSkiaMatrix();
136 }
137 shader_ = SkGradientShader::MakeLinear(pts, &c[0], pos.empty() ? nullptr : &p[0],
138 colorsCount, static_cast<SkTileMode>(mode), 0, skMatrix);
139 }
140
InitWithRadialGradient(const Point & centerPt,scalar radius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)141 void SkiaShaderEffect::InitWithRadialGradient(const Point& centerPt, scalar radius,
142 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode, const Matrix *matrix)
143 {
144 SkPoint center;
145 center.set(centerPt.GetX(), centerPt.GetY());
146
147 if (colors.empty()) {
148 return;
149 }
150 size_t colorsCount = colors.size();
151
152 std::vector<SkColor> c;
153 std::vector<SkScalar> p;
154 for (size_t i = 0; i < colorsCount; ++i) {
155 c.emplace_back(colors[i]);
156 }
157 for (size_t i = 0; i < pos.size(); ++i) {
158 p.emplace_back(pos[i]);
159 }
160 const SkMatrix *skMatrix = nullptr;
161 if (matrix != nullptr) {
162 skMatrix = &matrix->GetImpl<SkiaMatrix>()->ExportSkiaMatrix();
163 }
164 shader_ = SkGradientShader::MakeRadial(center, radius, &c[0],
165 pos.empty() ? nullptr : &p[0], colorsCount, static_cast<SkTileMode>(mode), 0, skMatrix);
166 }
167
InitWithTwoPointConical(const Point & startPt,scalar startRadius,const Point & endPt,scalar endRadius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)168 void SkiaShaderEffect::InitWithTwoPointConical(const Point& startPt, scalar startRadius, const Point& endPt,
169 scalar endRadius, const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode,
170 const Matrix *matrix)
171 {
172 SkPoint start;
173 SkPoint end;
174 start.set(startPt.GetX(), startPt.GetY());
175 end.set(endPt.GetX(), endPt.GetY());
176
177 if (colors.empty()) {
178 return;
179 }
180 size_t colorsCount = colors.size();
181
182 std::vector<SkColor> c;
183 std::vector<SkScalar> p;
184 for (size_t i = 0; i < colorsCount; ++i) {
185 c.emplace_back(colors[i]);
186 }
187 for (size_t i = 0; i < pos.size(); ++i) {
188 p.emplace_back(pos[i]);
189 }
190 const SkMatrix *skMatrix = nullptr;
191 if (matrix != nullptr) {
192 skMatrix = &matrix->GetImpl<SkiaMatrix>()->ExportSkiaMatrix();
193 }
194
195 shader_ = SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
196 &c[0], pos.empty() ? nullptr : &p[0], colorsCount, static_cast<SkTileMode>(mode), 0, skMatrix);
197 }
198
InitWithSweepGradient(const Point & centerPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,scalar startAngle,scalar endAngle,const Matrix * matrix)199 void SkiaShaderEffect::InitWithSweepGradient(const Point& centerPt, const std::vector<ColorQuad>& colors,
200 const std::vector<scalar>& pos, TileMode mode, scalar startAngle, scalar endAngle, const Matrix *matrix)
201 {
202 if (colors.empty()) {
203 return;
204 }
205 size_t colorsCount = colors.size();
206
207 std::vector<SkColor> c;
208 std::vector<SkScalar> p;
209 for (size_t i = 0; i < colorsCount; ++i) {
210 c.emplace_back(colors[i]);
211 }
212 for (size_t i = 0; i < pos.size(); ++i) {
213 p.emplace_back(pos[i]);
214 }
215 const SkMatrix *skMatrix = nullptr;
216 if (matrix != nullptr) {
217 skMatrix = &matrix->GetImpl<SkiaMatrix>()->ExportSkiaMatrix();
218 }
219 shader_ = SkGradientShader::MakeSweep(centerPt.GetX(), centerPt.GetY(), &c[0],
220 pos.empty() ? nullptr : &p[0], colorsCount,
221 static_cast<SkTileMode>(mode), startAngle, endAngle, 0, skMatrix);
222 }
223
GetShader() const224 sk_sp<SkShader> SkiaShaderEffect::GetShader() const
225 {
226 return shader_;
227 }
228
SetSkShader(const sk_sp<SkShader> & skShader)229 void SkiaShaderEffect::SetSkShader(const sk_sp<SkShader>& skShader)
230 {
231 shader_ = skShader;
232 }
233
Serialize() const234 std::shared_ptr<Data> SkiaShaderEffect::Serialize() const
235 {
236 if (shader_ == nullptr) {
237 LOGD("SkiaShaderEffect::Serialize, shader_ is nullptr!");
238 return nullptr;
239 }
240
241 SkBinaryWriteBuffer writer;
242 writer.writeFlattenable(shader_.get());
243 size_t length = writer.bytesWritten();
244 std::shared_ptr<Data> data = std::make_shared<Data>();
245 data->BuildUninitialized(length);
246 writer.writeToMemory(data->WritableData());
247 return data;
248 }
249
Deserialize(std::shared_ptr<Data> data)250 bool SkiaShaderEffect::Deserialize(std::shared_ptr<Data> data)
251 {
252 if (data == nullptr) {
253 LOGD("SkiaShaderEffect::Deserialize, data is invalid!");
254 return false;
255 }
256 SkReadBuffer reader(data->GetData(), data->GetSize());
257 shader_ = reader.readShader();
258 return true;
259 }
260
261 } // namespace Drawing
262 } // namespace Rosen
263 } // namespace OHOS