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 #include "skia_helper.h"
18
19 #include <vector>
20
21 #include "include/core/SkMatrix.h"
22 #include "include/core/SkTileMode.h"
23 #include "include/effects/SkGradientShader.h"
24 #include "src/shaders/SkShaderBase.h"
25 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
26 #include "include/core/SkSamplingOptions.h"
27 #endif
28
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
40 namespace OHOS {
41 namespace Rosen {
42 namespace Drawing {
SkiaShaderEffect()43 SkiaShaderEffect::SkiaShaderEffect() noexcept : shader_(nullptr) {}
44
InitWithColor(ColorQuad color)45 void SkiaShaderEffect::InitWithColor(ColorQuad color)
46 {
47 shader_ = SkShaders::Color(color);
48 }
49
InitWithBlend(const ShaderEffect & s1,const ShaderEffect & s2,BlendMode mode)50 void SkiaShaderEffect::InitWithBlend(const ShaderEffect& s1, const ShaderEffect& s2, BlendMode mode)
51 {
52 auto dst = s1.GetImpl<SkiaShaderEffect>();
53 auto src = s2.GetImpl<SkiaShaderEffect>();
54 if (dst != nullptr && src != nullptr) {
55 shader_ = SkShaders::Blend(static_cast<SkBlendMode>(mode), dst->GetShader(), src->GetShader());
56 }
57 }
58
InitWithImage(const Image & image,TileMode tileX,TileMode tileY,const SamplingOptions & sampling,const Matrix & matrix)59 void SkiaShaderEffect::InitWithImage(
60 const Image& image, TileMode tileX, TileMode tileY, const SamplingOptions& sampling, const Matrix& matrix)
61 {
62 SkTileMode modeX = static_cast<SkTileMode>(tileX);
63 SkTileMode modeY = static_cast<SkTileMode>(tileY);
64
65 auto m = matrix.GetImpl<SkiaMatrix>();
66 auto i = image.GetImpl<SkiaImage>();
67 SkMatrix skiaMatrix;
68 sk_sp<SkImage> skiaImage;
69 if (m != nullptr && i != nullptr) {
70 skiaMatrix = m->ExportSkiaMatrix();
71 skiaImage = i->GetImage();
72 if (skiaImage != nullptr) {
73 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
74 SkSamplingOptions samplingOptions;
75 if (sampling.GetUseCubic()) {
76 samplingOptions = SkSamplingOptions({ sampling.GetCubicCoffB(), sampling.GetCubicCoffC() });
77 } else {
78 samplingOptions = SkSamplingOptions(static_cast<SkFilterMode>(sampling.GetFilterMode()),
79 static_cast<SkMipmapMode>(sampling.GetMipmapMode()));
80 }
81 shader_ = skiaImage->makeShader(modeX, modeY, samplingOptions, &skiaMatrix);
82 #else
83 shader_ = skiaImage->makeShader(modeX, modeY, &skiaMatrix);
84 #endif
85 }
86 }
87 }
88
InitWithPicture(const Picture & picture,TileMode tileX,TileMode tileY,FilterMode mode,const Matrix & matrix,const Rect & rect)89 void SkiaShaderEffect::InitWithPicture(
90 const Picture& picture, TileMode tileX, TileMode tileY, FilterMode mode, const Matrix& matrix, const Rect& rect)
91 {
92 SkTileMode modeX = static_cast<SkTileMode>(tileX);
93 SkTileMode modeY = static_cast<SkTileMode>(tileY);
94 SkRect r = SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
95
96 auto p = picture.GetImpl<SkiaPicture>();
97 auto m = matrix.GetImpl<SkiaMatrix>();
98 sk_sp<SkPicture> skiaPicture;
99 SkMatrix skiaMatrix;
100 if (p != nullptr && m != nullptr) {
101 skiaPicture = p->GetPicture();
102 skiaMatrix = m->ExportSkiaMatrix();
103 if (skiaPicture != nullptr) {
104 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
105 SkFilterMode skFilterMode = static_cast<SkFilterMode>(mode);
106 shader_ = skiaPicture->makeShader(modeX, modeY, skFilterMode, &skiaMatrix, &r);
107 #else
108 shader_ = skiaPicture->makeShader(modeX, modeY, &skiaMatrix, &r);
109 #endif
110 }
111 }
112 }
113
InitWithLinearGradient(const Point & startPt,const Point & endPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode)114 void SkiaShaderEffect::InitWithLinearGradient(const Point& startPt, const Point& endPt,
115 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode)
116 {
117 SkPoint pts[2];
118 pts[0].set(startPt.GetX(), startPt.GetY());
119 pts[1].set(endPt.GetX(), endPt.GetY());
120
121 size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
122 if (count == 0) {
123 return;
124 }
125 std::vector<SkColor> c;
126 std::vector<SkScalar> p;
127 for (size_t i = 0; i < count; ++i) {
128 c.emplace_back(colors[i]);
129 p.emplace_back(pos[i]);
130 }
131 shader_ = SkGradientShader::MakeLinear(pts, &c[0], &p[0], count, static_cast<SkTileMode>(mode));
132 }
133
InitWithRadialGradient(const Point & centerPt,scalar radius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode)134 void SkiaShaderEffect::InitWithRadialGradient(const Point& centerPt, scalar radius,
135 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode)
136 {
137 SkPoint center;
138 center.set(centerPt.GetX(), centerPt.GetY());
139
140 size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
141 if (count == 0) {
142 return;
143 }
144 std::vector<SkColor> c;
145 std::vector<SkScalar> p;
146 for (size_t i = 0; i < count; ++i) {
147 c.emplace_back(colors[i]);
148 p.emplace_back(pos[i]);
149 }
150 shader_ = SkGradientShader::MakeRadial(center, radius, &c[0], &p[0], count, static_cast<SkTileMode>(mode));
151 }
152
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)153 void SkiaShaderEffect::InitWithTwoPointConical(const Point& startPt, scalar startRadius, const Point& endPt,
154 scalar endRadius, const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode,
155 const Matrix *matrix)
156 {
157 SkPoint start;
158 SkPoint end;
159 start.set(startPt.GetX(), startPt.GetY());
160 end.set(endPt.GetX(), endPt.GetY());
161
162 size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
163 if (count == 0) {
164 return;
165 }
166 std::vector<SkColor> c;
167 std::vector<SkScalar> p;
168 for (size_t i = 0; i < count; ++i) {
169 c.emplace_back(colors[i]);
170 p.emplace_back(pos[i]);
171 }
172 const SkMatrix *skMatrix = nullptr;
173 if (matrix != nullptr) {
174 skMatrix = &matrix->GetImpl<SkiaMatrix>()->ExportSkiaMatrix();
175 }
176
177 shader_ = SkGradientShader::MakeTwoPointConical(
178 start, startRadius, end, endRadius, &c[0], &p[0], count, static_cast<SkTileMode>(mode), 0, skMatrix);
179 }
180
InitWithSweepGradient(const Point & centerPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,scalar startAngle,scalar endAngle,const Matrix * matrix)181 void SkiaShaderEffect::InitWithSweepGradient(const Point& centerPt, const std::vector<ColorQuad>& colors,
182 const std::vector<scalar>& pos, TileMode mode, scalar startAngle, scalar endAngle, const Matrix *matrix)
183 {
184 size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
185 if (count == 0) {
186 return;
187 }
188 std::vector<SkColor> c;
189 std::vector<SkScalar> p;
190 for (size_t i = 0; i < count; ++i) {
191 c.emplace_back(colors[i]);
192 p.emplace_back(pos[i]);
193 }
194 const SkMatrix *skMatrix = nullptr;
195 if (matrix != nullptr) {
196 skMatrix = &matrix->GetImpl<SkiaMatrix>()->ExportSkiaMatrix();
197 }
198 shader_ = SkGradientShader::MakeSweep(centerPt.GetX(), centerPt.GetY(), &c[0], &p[0], count,
199 static_cast<SkTileMode>(mode), startAngle, endAngle, 0, skMatrix);
200 }
201
GetShader() const202 sk_sp<SkShader> SkiaShaderEffect::GetShader() const
203 {
204 return shader_;
205 }
206
SetSkShader(const sk_sp<SkShader> & skShader)207 void SkiaShaderEffect::SetSkShader(const sk_sp<SkShader>& skShader)
208 {
209 shader_ = skShader;
210 }
211
Serialize() const212 std::shared_ptr<Data> SkiaShaderEffect::Serialize() const
213 {
214 if (shader_ == nullptr) {
215 LOGD("SkiaShaderEffect::Serialize, shader_ is nullptr!");
216 return nullptr;
217 }
218
219 return SkiaHelper::FlattenableSerialize(shader_.get());
220 }
221
Deserialize(std::shared_ptr<Data> data)222 bool SkiaShaderEffect::Deserialize(std::shared_ptr<Data> data)
223 {
224 if (data == nullptr) {
225 LOGD("SkiaShaderEffect::Deserialize, data is invalid!");
226 return false;
227 }
228
229 shader_ = SkiaHelper::FlattenableDeserialize<SkShaderBase>(data);
230 return true;
231 }
232
233 } // namespace Drawing
234 } // namespace Rosen
235 } // namespace OHOS