1 /*
2 * Copyright (c) 2023-2025 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 "drawing_shader_effect.h"
17
18 #include "drawing_canvas_utils.h"
19 #include "drawing_helper.h"
20 #include "native_pixel_map_manager.h"
21
22 #include "effect/shader_effect.h"
23 #include "effect/shader_effect_lazy.h"
24 #include "render/rs_pixel_map_util.h"
25 #include "render/rs_pixel_map_shader_obj.h"
26
27 using namespace OHOS;
28 using namespace Rosen;
29 using namespace Drawing;
30
CastToPoint(const OH_Drawing_Point * cPoint)31 static const Point* CastToPoint(const OH_Drawing_Point* cPoint)
32 {
33 return reinterpret_cast<const Point*>(cPoint);
34 }
35
CastToPoint(const OH_Drawing_Point2D * cPoint)36 static const Point* CastToPoint(const OH_Drawing_Point2D* cPoint)
37 {
38 return reinterpret_cast<const Point*>(cPoint);
39 }
40
CastToImage(const OH_Drawing_Image & cImage)41 static const Image& CastToImage(const OH_Drawing_Image& cImage)
42 {
43 return reinterpret_cast<const Image&>(cImage);
44 }
45
CastToSamplingOptions(const OH_Drawing_SamplingOptions & cSamplingOptions)46 static const SamplingOptions& CastToSamplingOptions(const OH_Drawing_SamplingOptions& cSamplingOptions)
47 {
48 return reinterpret_cast<const SamplingOptions&>(cSamplingOptions);
49 }
50
CastToMatrix(const OH_Drawing_Matrix * cMatrix)51 static const Matrix* CastToMatrix(const OH_Drawing_Matrix* cMatrix)
52 {
53 return reinterpret_cast<const Matrix*>(cMatrix);
54 }
55
CastShaderEffect(std::shared_ptr<ShaderEffect> shaderEffect)56 static OH_Drawing_ShaderEffect* CastShaderEffect(std::shared_ptr<ShaderEffect> shaderEffect)
57 {
58 NativeHandle<ShaderEffect>* shaderEffectHandle = new NativeHandle<ShaderEffect>;
59 shaderEffectHandle->value = shaderEffect;
60 return Helper::CastTo<NativeHandle<ShaderEffect>*, OH_Drawing_ShaderEffect*>(shaderEffectHandle);
61 }
62
OH_Drawing_ShaderEffectCreateColorShader(const uint32_t color)63 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateColorShader(const uint32_t color)
64 {
65 return CastShaderEffect(ShaderEffect::CreateColorShader(color));
66 }
67
OH_Drawing_ShaderEffectCreateLinearGradient(const OH_Drawing_Point * cStartPt,const OH_Drawing_Point * cEndPt,const uint32_t * colors,const float * pos,uint32_t size,OH_Drawing_TileMode cTileMode)68 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateLinearGradient(const OH_Drawing_Point* cStartPt,
69 const OH_Drawing_Point* cEndPt, const uint32_t* colors, const float* pos, uint32_t size,
70 OH_Drawing_TileMode cTileMode)
71 {
72 if (cStartPt == nullptr || cEndPt == nullptr || colors == nullptr) {
73 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
74 return nullptr;
75 }
76 if (cTileMode < CLAMP || cTileMode > DECAL) {
77 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
78 return nullptr;
79 }
80 std::vector<ColorQuad> colorsVector;
81 std::vector<scalar> posVector;
82 for (uint32_t i = 0; i < size; i++) {
83 colorsVector.emplace_back(colors[i]);
84 }
85 if (pos != nullptr) {
86 for (uint32_t i = 0; i < size; i++) {
87 posVector.emplace_back(pos[i]);
88 }
89 }
90 return CastShaderEffect(ShaderEffect::CreateLinearGradient(
91 *CastToPoint(cStartPt), *CastToPoint(cEndPt), colorsVector, posVector, static_cast<TileMode>(cTileMode)));
92 }
93
OH_Drawing_ShaderEffectCreateLinearGradientWithLocalMatrix(const OH_Drawing_Point2D * startPt,const OH_Drawing_Point2D * endPt,const uint32_t * colors,const float * pos,uint32_t size,OH_Drawing_TileMode cTileMode,const OH_Drawing_Matrix * cMatrix)94 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateLinearGradientWithLocalMatrix(
95 const OH_Drawing_Point2D* startPt, const OH_Drawing_Point2D* endPt, const uint32_t* colors, const float* pos,
96 uint32_t size, OH_Drawing_TileMode cTileMode, const OH_Drawing_Matrix* cMatrix)
97 {
98 if (startPt == nullptr || endPt == nullptr || colors == nullptr) {
99 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
100 return nullptr;
101 }
102 if (cTileMode < CLAMP || cTileMode > DECAL) {
103 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
104 return nullptr;
105 }
106 std::vector<ColorQuad> colorsVector;
107 std::vector<scalar> posVector;
108 for (uint32_t i = 0; i < size; i++) {
109 colorsVector.emplace_back(colors[i]);
110 }
111 if (pos != nullptr) {
112 for (uint32_t i = 0; i < size; i++) {
113 posVector.emplace_back(pos[i]);
114 }
115 }
116 return CastShaderEffect(ShaderEffect::CreateLinearGradient(
117 *CastToPoint(startPt), *CastToPoint(endPt), colorsVector,
118 posVector, static_cast<TileMode>(cTileMode), cMatrix ? CastToMatrix(cMatrix) : nullptr));
119 }
120
OH_Drawing_ShaderEffectCreateRadialGradient(const OH_Drawing_Point * cCenterPt,float radius,const uint32_t * colors,const float * pos,uint32_t size,OH_Drawing_TileMode cTileMode)121 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateRadialGradient(const OH_Drawing_Point* cCenterPt, float radius,
122 const uint32_t* colors, const float* pos, uint32_t size, OH_Drawing_TileMode cTileMode)
123 {
124 if (cCenterPt == nullptr || colors == nullptr) {
125 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
126 return nullptr;
127 }
128 if (cTileMode < CLAMP || cTileMode > DECAL) {
129 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
130 return nullptr;
131 }
132 std::vector<ColorQuad> colorsVector;
133 std::vector<scalar> posVector;
134 for (uint32_t i = 0; i < size; i++) {
135 colorsVector.emplace_back(colors[i]);
136 if (pos) {
137 posVector.emplace_back(pos[i]);
138 }
139 }
140 return CastShaderEffect(ShaderEffect::CreateRadialGradient(
141 *CastToPoint(cCenterPt), radius, colorsVector, posVector, static_cast<TileMode>(cTileMode)));
142 }
143
OH_Drawing_ShaderEffectCreateRadialGradientWithLocalMatrix(const OH_Drawing_Point2D * centerPt,float radius,const uint32_t * colors,const float * pos,uint32_t size,OH_Drawing_TileMode cTileMode,const OH_Drawing_Matrix * cMatrix)144 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateRadialGradientWithLocalMatrix(
145 const OH_Drawing_Point2D* centerPt, float radius, const uint32_t* colors, const float* pos, uint32_t size,
146 OH_Drawing_TileMode cTileMode, const OH_Drawing_Matrix* cMatrix)
147 {
148 if (centerPt == nullptr || colors == nullptr) {
149 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
150 return nullptr;
151 }
152 if (cTileMode < CLAMP || cTileMode > DECAL) {
153 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
154 return nullptr;
155 }
156 std::vector<ColorQuad> colorsVector;
157 std::vector<scalar> posVector;
158 for (uint32_t i = 0; i < size; i++) {
159 colorsVector.emplace_back(colors[i]);
160 if (pos) {
161 posVector.emplace_back(pos[i]);
162 }
163 }
164 return CastShaderEffect(ShaderEffect::CreateRadialGradient(
165 *CastToPoint(centerPt), radius, colorsVector, posVector,
166 static_cast<TileMode>(cTileMode), cMatrix ? CastToMatrix(cMatrix) : nullptr));
167 }
168
OH_Drawing_ShaderEffectCreateSweepGradientWithLocalMatrix(const OH_Drawing_Point * centerPt,const uint32_t * colors,const float * pos,uint32_t size,OH_Drawing_TileMode tileMode,const OH_Drawing_Matrix * matrix)169 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateSweepGradientWithLocalMatrix(
170 const OH_Drawing_Point* centerPt, const uint32_t* colors, const float* pos, uint32_t size,
171 OH_Drawing_TileMode tileMode, const OH_Drawing_Matrix* matrix)
172 {
173 if (centerPt == nullptr || colors == nullptr) {
174 return nullptr;
175 }
176 if (tileMode < CLAMP || tileMode > DECAL) {
177 return nullptr;
178 }
179 std::vector<ColorQuad> colorsVector;
180 std::vector<scalar> posVector;
181 for (uint32_t i = 0; i < size; i++) {
182 colorsVector.emplace_back(colors[i]);
183 if (pos) {
184 posVector.emplace_back(pos[i]);
185 }
186 }
187 return CastShaderEffect(ShaderEffect::CreateSweepGradient(
188 *CastToPoint(centerPt), colorsVector, posVector, static_cast<TileMode>(tileMode), 0,
189 360, matrix ? CastToMatrix(matrix) : nullptr)); // 360: endAngle
190 }
191
OH_Drawing_ShaderEffectCreateSweepGradient(const OH_Drawing_Point * cCenterPt,const uint32_t * colors,const float * pos,uint32_t size,OH_Drawing_TileMode cTileMode)192 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateSweepGradient(const OH_Drawing_Point* cCenterPt,
193 const uint32_t* colors, const float* pos, uint32_t size, OH_Drawing_TileMode cTileMode)
194 {
195 if (cCenterPt == nullptr || colors == nullptr) {
196 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
197 return nullptr;
198 }
199 if (cTileMode < CLAMP || cTileMode > DECAL) {
200 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
201 return nullptr;
202 }
203 std::vector<ColorQuad> colorsVector;
204 std::vector<scalar> posVector;
205 for (uint32_t i = 0; i < size; i++) {
206 colorsVector.emplace_back(colors[i]);
207 if (pos) {
208 posVector.emplace_back(pos[i]);
209 }
210 }
211 return CastShaderEffect(ShaderEffect::CreateSweepGradient(
212 *CastToPoint(cCenterPt), colorsVector, posVector, static_cast<TileMode>(cTileMode), 0,
213 360, nullptr)); // 360: endAngle
214 }
215
OH_Drawing_ShaderEffectCreateImageShader(OH_Drawing_Image * cImage,OH_Drawing_TileMode tileX,OH_Drawing_TileMode tileY,const OH_Drawing_SamplingOptions * cSampling,const OH_Drawing_Matrix * cMatrix)216 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateImageShader(OH_Drawing_Image* cImage, OH_Drawing_TileMode tileX,
217 OH_Drawing_TileMode tileY, const OH_Drawing_SamplingOptions* cSampling, const OH_Drawing_Matrix* cMatrix)
218 {
219 if (cImage == nullptr || cSampling == nullptr) {
220 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
221 return nullptr;
222 }
223 if (tileX < CLAMP || tileX > DECAL || tileY < CLAMP || tileY > DECAL) {
224 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
225 return nullptr;
226 }
227 if (cMatrix == nullptr) {
228 Matrix matrix;
229 return CastShaderEffect(ShaderEffect::CreateImageShader(
230 CastToImage(*cImage), static_cast<TileMode>(tileX), static_cast<TileMode>(tileY),
231 CastToSamplingOptions(*cSampling), matrix));
232 }
233 return CastShaderEffect(ShaderEffect::CreateImageShader(
234 CastToImage(*cImage), static_cast<TileMode>(tileX), static_cast<TileMode>(tileY),
235 CastToSamplingOptions(*cSampling), *CastToMatrix(cMatrix)));
236 }
237
OH_Drawing_ShaderEffectCreatePixelMapShader(OH_Drawing_PixelMap * pixelMap,OH_Drawing_TileMode tileX,OH_Drawing_TileMode tileY,const OH_Drawing_SamplingOptions * samplingOptions,const OH_Drawing_Matrix * matrix)238 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreatePixelMapShader(OH_Drawing_PixelMap* pixelMap,
239 OH_Drawing_TileMode tileX, OH_Drawing_TileMode tileY, const OH_Drawing_SamplingOptions* samplingOptions,
240 const OH_Drawing_Matrix* matrix)
241 {
242 #ifdef OHOS_PLATFORM
243 if (pixelMap == nullptr || samplingOptions == nullptr) {
244 return nullptr;
245 }
246 if (tileX < CLAMP || tileX > DECAL || tileY < CLAMP || tileY > DECAL) {
247 return nullptr;
248 }
249
250 std::shared_ptr<Media::PixelMap> pixelMapPtr = OHOS::Rosen::GetPixelMapFromNativePixelMap(pixelMap);
251 if (!pixelMapPtr) {
252 return nullptr;
253 }
254
255 Matrix defaultMatrix;
256 const Matrix& matrixRef = matrix ? *CastToMatrix(matrix) : defaultMatrix;
257
258 return CastShaderEffect(RSPixelMapShaderObj::CreatePixelMapShader(
259 pixelMapPtr, static_cast<TileMode>(tileX), static_cast<TileMode>(tileY),
260 CastToSamplingOptions(*samplingOptions), matrixRef));
261 #else
262 return nullptr;
263 #endif
264 }
265
OH_Drawing_ShaderEffectCreateTwoPointConicalGradient(const OH_Drawing_Point2D * startPt,float startRadius,const OH_Drawing_Point2D * endPt,float endRadius,const uint32_t * colors,const float * pos,uint32_t size,OH_Drawing_TileMode cTileMode,const OH_Drawing_Matrix * cMatrix)266 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateTwoPointConicalGradient(const OH_Drawing_Point2D* startPt,
267 float startRadius, const OH_Drawing_Point2D* endPt, float endRadius, const uint32_t* colors, const float* pos,
268 uint32_t size, OH_Drawing_TileMode cTileMode, const OH_Drawing_Matrix* cMatrix)
269 {
270 if (startPt == nullptr || endPt == nullptr || colors == nullptr) {
271 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
272 return nullptr;
273 }
274 if (cTileMode < CLAMP || cTileMode > DECAL) {
275 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
276 return nullptr;
277 }
278 std::vector<ColorQuad> colorsVector;
279 std::vector<scalar> posVector;
280 for (uint32_t i = 0; i < size; i++) {
281 colorsVector.emplace_back(colors[i]);
282 if (pos) {
283 posVector.emplace_back(pos[i]);
284 }
285 }
286 return CastShaderEffect(ShaderEffect::CreateTwoPointConical(
287 *CastToPoint(startPt), startRadius, *CastToPoint(endPt), endRadius, colorsVector, posVector,
288 static_cast<TileMode>(cTileMode), cMatrix ? CastToMatrix(cMatrix) : nullptr));
289 }
290
OH_Drawing_ShaderEffectCreateCompose(OH_Drawing_ShaderEffect * dst,OH_Drawing_ShaderEffect * src,OH_Drawing_BlendMode mode)291 OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateCompose(OH_Drawing_ShaderEffect* dst,
292 OH_Drawing_ShaderEffect* src, OH_Drawing_BlendMode mode)
293 {
294 if (dst == nullptr || src == nullptr) {
295 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
296 return nullptr;
297 }
298 if (mode < BLEND_MODE_CLEAR || mode > BLEND_MODE_LUMINOSITY) {
299 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
300 return nullptr;
301 }
302 auto dstHandle = Helper::CastTo<OH_Drawing_ShaderEffect*, NativeHandle<ShaderEffect>*>(dst);
303 auto srcHandle = Helper::CastTo<OH_Drawing_ShaderEffect*, NativeHandle<ShaderEffect>*>(src);
304 if (dstHandle->value.get() == nullptr || srcHandle->value.get() == nullptr) {
305 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
306 return nullptr;
307 }
308 return CastShaderEffect(ShaderEffectLazy::CreateBlendShader(dstHandle->value,
309 srcHandle->value, static_cast<BlendMode>(mode)));
310 }
311
OH_Drawing_ShaderEffectDestroy(OH_Drawing_ShaderEffect * cShaderEffect)312 void OH_Drawing_ShaderEffectDestroy(OH_Drawing_ShaderEffect* cShaderEffect)
313 {
314 if (!cShaderEffect) {
315 return;
316 }
317 delete Helper::CastTo<OH_Drawing_ShaderEffect*, NativeHandle<ShaderEffect>*>(cShaderEffect);
318 }