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