@react-native-ohos/react-native-svg 15.12.1-rc.1 → 15.12.1-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -21
  2. package/README.OpenSource +10 -10
  3. package/README.md +13 -13
  4. package/css/package.json +5 -5
  5. package/harmony/svg/BuildProfile.ets +16 -16
  6. package/harmony/svg/build-profile.json5 +9 -9
  7. package/harmony/svg/hvigorfile.ts +1 -1
  8. package/harmony/svg/index.ets +6 -6
  9. package/harmony/svg/oh-package.json5 +13 -13
  10. package/harmony/svg/src/main/cpp/SvgFilter.cpp +505 -505
  11. package/harmony/svg/src/main/cpp/SvgFilter.h +112 -112
  12. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeBlendComponentInstance.cpp +40 -40
  13. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeBlendComponentInstance.h +48 -48
  14. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeColorMatrixComponentInstance.cpp +33 -33
  15. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeColorMatrixComponentInstance.h +48 -48
  16. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeCompositeComponentInstance.cpp +39 -39
  17. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeCompositeComponentInstance.h +55 -55
  18. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeFloodComponentInstance.cpp +33 -33
  19. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeFloodComponentInstance.h +49 -49
  20. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeGaussianBlurComponentInstance.cpp +34 -34
  21. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeGaussianBlurComponentInstance.h +48 -48
  22. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeOffsetComponentInstance.cpp +35 -35
  23. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFeOffsetComponentInstance.h +45 -45
  24. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFilterComponentInstance.cpp +198 -198
  25. package/harmony/svg/src/main/cpp/componentInstances/RNSVGFilterComponentInstance.h +48 -48
  26. package/harmony/svg/src/main/cpp/componentInstances/RNSVGImageComponentInstance.cpp +4 -1
  27. package/harmony/svg/src/main/cpp/downloadUtils/ImageSourceResolver.cpp +36 -15
  28. package/harmony/svg/src/main/cpp/downloadUtils/ImageSourceResolver.h +6 -10
  29. package/harmony/svg/src/main/cpp/generated/RNOH/generated/components/RNSVGFeBlendJSIBinder.h +26 -26
  30. package/harmony/svg/src/main/cpp/generated/RNOH/generated/components/RNSVGFeColorMatrixJSIBinder.h +26 -26
  31. package/harmony/svg/src/main/cpp/generated/RNOH/generated/components/RNSVGFeCompositeJSIBinder.h +30 -30
  32. package/harmony/svg/src/main/cpp/generated/RNOH/generated/components/RNSVGFeFloodJSIBinder.h +26 -26
  33. package/harmony/svg/src/main/cpp/generated/RNOH/generated/components/RNSVGFeGaussianBlurJSIBinder.h +26 -26
  34. package/harmony/svg/src/main/cpp/generated/RNOH/generated/components/RNSVGFeOffsetJSIBinder.h +26 -26
  35. package/harmony/svg/src/main/cpp/generated/RNOH/generated/components/RNSVGFilterJSIBinder.h +44 -44
  36. package/harmony/svg/src/main/cpp/generated/react/renderer/components/react_native_svg/Props.cpp +977 -977
  37. package/harmony/svg/src/main/cpp/generated/react/renderer/components/react_native_svg/Props.h +1280 -1280
  38. package/harmony/svg/src/main/cpp/utils/DynamicUtils.h +55 -55
  39. package/harmony/svg/src/main/cpp/utils/FilterManager.h +190 -190
  40. package/harmony/svg/src/main/ets/RNSVGImageModule.ts +21 -21
  41. package/harmony/svg/src/main/ets/RNSVGRenderableModule.ts +16 -16
  42. package/harmony/svg/src/main/ets/RNSVGSvgViewModule.ts +18 -18
  43. package/harmony/svg/src/main/ets/SvgPackage.ts +57 -57
  44. package/harmony/svg/src/main/module.json5 +7 -7
  45. package/harmony/svg/src/main/resources/base/element/string.json +8 -8
  46. package/harmony/svg/src/main/resources/en_US/element/string.json +8 -8
  47. package/harmony/svg/src/main/resources/zh_CN/element/string.json +8 -8
  48. package/harmony/svg/ts.ts +7 -7
  49. package/harmony/svg.har +0 -0
  50. package/lib/commonjs/css/index.js +54 -54
  51. package/lib/commonjs/index.js +25 -25
  52. package/lib/module/css/index.js +3 -3
  53. package/lib/module/index.js +2 -2
  54. package/package.json +52 -54
  55. package/src/css/index.tsx +19 -19
  56. package/src/index.tsx +2 -2
  57. package/tsconfig.json +11 -11
  58. package/lib/typescript/babel.config.d.ts +0 -8
  59. package/lib/typescript/babel.config.d.ts.map +0 -1
  60. package/lib/typescript/example/babel.config.d.ts +0 -3
  61. package/lib/typescript/example/babel.config.d.ts.map +0 -1
  62. package/lib/typescript/example/contexts.d.ts +0 -3
  63. package/lib/typescript/example/contexts.d.ts.map +0 -1
  64. package/lib/typescript/example/harmony/entry/hvigorfile.d.ts +0 -2
  65. package/lib/typescript/example/harmony/entry/hvigorfile.d.ts.map +0 -1
  66. package/lib/typescript/example/harmony/hvigorfile.d.ts +0 -2
  67. package/lib/typescript/example/harmony/hvigorfile.d.ts.map +0 -1
  68. package/lib/typescript/example/index.d.ts +0 -2
  69. package/lib/typescript/example/index.d.ts.map +0 -1
  70. package/lib/typescript/example/jest.config.d.ts +0 -3
  71. package/lib/typescript/example/jest.config.d.ts.map +0 -1
  72. package/lib/typescript/example/metro.config.d.ts +0 -3
  73. package/lib/typescript/example/metro.config.d.ts.map +0 -1
  74. package/lib/typescript/example/react-native.config.d.ts +0 -3
  75. package/lib/typescript/example/react-native.config.d.ts.map +0 -1
  76. package/lib/typescript/example/scripts/create-build-profile.d.ts +0 -2
  77. package/lib/typescript/example/scripts/create-build-profile.d.ts.map +0 -1
  78. package/lib/typescript/example/src/index.d.ts +0 -3
  79. package/lib/typescript/example/src/index.d.ts.map +0 -1
  80. package/lib/typescript/src/css/index.d.ts +0 -4
  81. package/lib/typescript/src/css/index.d.ts.map +0 -1
  82. package/lib/typescript/src/index.d.ts +0 -3
  83. package/lib/typescript/src/index.d.ts.map +0 -1
@@ -1,505 +1,505 @@
1
- /*
2
- * Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
3
- * Use of this source code is governed by a MIT license that can be
4
- * found in the LICENSE file.
5
- */
6
-
7
- #include "SvgFilter.h"
8
- #include <native_drawing/drawing_mask_filter.h>
9
- #include <native_drawing/drawing_color_filter.h>
10
- #include <native_drawing/drawing_image_filter.h>
11
- #include <native_drawing/drawing_shadow_layer.h>
12
- #include <native_drawing/drawing_brush.h>
13
- #include <native_drawing/drawing_pen.h>
14
- #include <native_drawing/drawing_types.h>
15
- #include <glog/logging.h>
16
- #include <algorithm>
17
- #include <cmath>
18
- #include <string>
19
- #include <stdexcept>
20
- #include <sstream>
21
- #include <vector>
22
- #include <set>
23
- #include <map>
24
- #include <memory>
25
-
26
- #ifndef M_PI
27
- #define M_PI 3.14159265358979323846
28
- #endif
29
-
30
- namespace rnoh {
31
- namespace svg {
32
-
33
- struct InputSource {
34
- std::string name;
35
- OH_Drawing_ImageFilter* imageFilter = nullptr;
36
- OH_Drawing_ColorFilter* colorFilter = nullptr;
37
- OH_Drawing_MaskFilter* maskFilter = nullptr;
38
- OH_Drawing_Filter* combinedFilter = nullptr;
39
- bool ownsFilters = false;
40
-
41
- ~InputSource() {
42
- }
43
-
44
- void cleanup() {
45
- if (ownsFilters) {
46
- if (imageFilter) {
47
- OH_Drawing_ImageFilterDestroy(imageFilter);
48
- imageFilter = nullptr;
49
- }
50
- if (colorFilter) {
51
- OH_Drawing_ColorFilterDestroy(colorFilter);
52
- colorFilter = nullptr;
53
- }
54
- if (maskFilter) {
55
- OH_Drawing_MaskFilterDestroy(maskFilter);
56
- maskFilter = nullptr;
57
- }
58
- if (combinedFilter) {
59
- OH_Drawing_FilterDestroy(combinedFilter);
60
- combinedFilter = nullptr;
61
- }
62
- ownsFilters = false;
63
- }
64
- }
65
- };
66
-
67
- class InputSourceManager {
68
- private:
69
- std::map<std::string, std::shared_ptr<InputSource>> sources_;
70
-
71
- public:
72
- void RegisterSource(const std::string& name, OH_Drawing_ImageFilter* imageFilter = nullptr,
73
- OH_Drawing_ColorFilter* colorFilter = nullptr, OH_Drawing_MaskFilter* maskFilter = nullptr) {
74
- auto source = std::make_shared<InputSource>();
75
- source->name = name;
76
- source->imageFilter = imageFilter;
77
- source->colorFilter = colorFilter;
78
- source->maskFilter = maskFilter;
79
-
80
- if (imageFilter || colorFilter || maskFilter) {
81
- source->combinedFilter = OH_Drawing_FilterCreate();
82
- if (source->combinedFilter) {
83
- if (imageFilter) OH_Drawing_FilterSetImageFilter(source->combinedFilter, imageFilter);
84
- if (colorFilter) OH_Drawing_FilterSetColorFilter(source->combinedFilter, colorFilter);
85
- if (maskFilter) OH_Drawing_FilterSetMaskFilter(source->combinedFilter, maskFilter);
86
- }
87
- }
88
-
89
- sources_[name] = source;
90
- }
91
-
92
- std::shared_ptr<InputSource> GetSource(const std::string& name) {
93
- if (name.empty()) {
94
- return nullptr;
95
- }
96
-
97
- auto it = sources_.find(name);
98
- if (it != sources_.end()) {
99
- return it->second;
100
- }
101
-
102
- if (name == "SourceGraphic") {
103
- return GetOrCreateStandardSource("SourceGraphic");
104
- } else if (name == "SourceAlpha") {
105
- return GetOrCreateStandardSource("SourceAlpha");
106
- } else if (name == "BackgroundImage") {
107
- return GetOrCreateStandardSource("BackgroundImage");
108
- } else if (name == "BackgroundAlpha") {
109
- return GetOrCreateStandardSource("BackgroundAlpha");
110
- } else if (name == "FillPaint") {
111
- return GetOrCreateStandardSource("FillPaint");
112
- } else if (name == "StrokePaint") {
113
- return GetOrCreateStandardSource("StrokePaint");
114
- }
115
- DLOG(WARNING) << "[SvgFilter] Input source not found: " << name;
116
- return nullptr;
117
- }
118
-
119
- void Clear() {
120
- for (auto& pair : sources_) {
121
- if (pair.second) {
122
- pair.second->cleanup();
123
- }
124
- }
125
- sources_.clear();
126
- }
127
-
128
- private:
129
- std::shared_ptr<InputSource> GetOrCreateStandardSource(const std::string& name) {
130
- auto it = sources_.find(name);
131
- if (it != sources_.end()) {
132
- return it->second;
133
- }
134
-
135
- auto source = std::make_shared<InputSource>();
136
- source->name = name;
137
- if (name == "SourceAlpha") {
138
- float alphaMatrix[20] = {
139
- 0, 0, 0, 0, 0,
140
- 0, 0, 0, 0, 0,
141
- 0, 0, 0, 0, 0,
142
- 0, 0, 0, 1, 0
143
- };
144
- source->colorFilter = OH_Drawing_ColorFilterCreateMatrix(alphaMatrix);
145
- } else if (name == "BackgroundImage") {
146
- } else if (name == "BackgroundAlpha") {
147
- float backgroundAlphaMatrix[20] = {
148
- 0, 0, 0, 0, 0,
149
- 0, 0, 0, 0, 0,
150
- 0, 0, 0, 0, 0,
151
- 0, 0, 0, 1, 0
152
- };
153
- source->colorFilter = OH_Drawing_ColorFilterCreateMatrix(backgroundAlphaMatrix);
154
- } else if (name == "FillPaint" || name == "StrokePaint") {
155
- float matrix[20] = {
156
- 1, 0, 0, 0, 0,
157
- 0, 1, 0, 0, 0,
158
- 0, 0, 1, 0, 0,
159
- 0, 0, 0, 1, 0
160
- };
161
- source->colorFilter = OH_Drawing_ColorFilterCreateMatrix(matrix);
162
- }
163
-
164
- sources_[name] = source;
165
- return source;
166
- }
167
- };
168
-
169
- static InputSourceManager g_inputSourceManager;
170
- OH_Drawing_ImageFilter* SvgFilter::GetInputImageFilter(const std::string& inputName) {
171
- if (inputName.empty() || inputName == "SourceGraphic") {
172
- return nullptr;
173
- }
174
-
175
- auto source = g_inputSourceManager.GetSource(inputName);
176
- return source ? source->imageFilter : nullptr;
177
- }
178
-
179
- OH_Drawing_ColorFilter* SvgFilter::GetInputColorFilter(const std::string& inputName) {
180
- if (inputName.empty() || inputName == "SourceGraphic") {
181
- return nullptr;
182
- }
183
-
184
- auto source = g_inputSourceManager.GetSource(inputName);
185
- if (source) {
186
- return source->colorFilter;
187
- }
188
- return nullptr;
189
- }
190
-
191
- OH_Drawing_Filter* SvgFilter::GetInputFilter(const std::string& inputName) {
192
- if (inputName.empty() || inputName == "SourceGraphic") {
193
- return nullptr;
194
- }
195
-
196
- auto source = g_inputSourceManager.GetSource(inputName);
197
- return source ? source->combinedFilter : nullptr;
198
- }
199
-
200
- OH_Drawing_ColorFilter* SvgFilter::CombineWithInputColor(OH_Drawing_ColorFilter* newFilter, const std::string& inputName) {
201
- if (inputName.empty() || inputName == "SourceGraphic" || !newFilter) {
202
- return newFilter;
203
- }
204
-
205
- auto inputFilter = GetInputColorFilter(inputName);
206
- if (inputFilter) {
207
- return OH_Drawing_ColorFilterCreateCompose(newFilter, inputFilter);
208
- }
209
-
210
- return newFilter;
211
- }
212
-
213
- void SvgFilter::RegisterFilterResult(const std::string& resultId, OH_Drawing_ImageFilter* imageFilter,
214
- OH_Drawing_ColorFilter* colorFilter, OH_Drawing_MaskFilter* maskFilter) {
215
- if (!resultId.empty()) {
216
- g_inputSourceManager.RegisterSource(resultId, imageFilter, colorFilter, maskFilter);
217
- }
218
- }
219
-
220
- void SvgFilter::AddFilterEffect(const FilterEffect& effect) {
221
- effects_.push_back(effect);
222
- }
223
-
224
- void SvgFilter::ApplyToBrush(rnoh::drawing::Brush& brush, const std::string& extra) {
225
- if (effects_.empty()) {
226
- return;
227
- }
228
-
229
- g_inputSourceManager.Clear();
230
- auto* mainFilter = OH_Drawing_FilterCreate();
231
- if (!mainFilter) {
232
- DLOG(WARNING) << "[SvgFilter] Failed to create main filter";
233
- return;
234
- }
235
-
236
- for (const auto& effect : effects_) {
237
- ApplySingleEffectToFilter(mainFilter, effect, &brush, nullptr, extra);
238
- }
239
-
240
- OH_Drawing_BrushSetFilter(brush.get(), mainFilter);
241
- }
242
-
243
- void SvgFilter::ApplyToPen(rnoh::drawing::Pen& pen) {
244
- if (effects_.empty()) {
245
- return;
246
- }
247
-
248
- g_inputSourceManager.Clear();
249
- auto* mainFilter = OH_Drawing_FilterCreate();
250
- if (!mainFilter) {
251
- DLOG(WARNING) << "[SvgFilter] Failed to create main filter";
252
- return;
253
- }
254
-
255
- for (const auto& effect : effects_) {
256
- ApplySingleEffectToFilter(mainFilter, effect, nullptr, &pen);
257
- }
258
- OH_Drawing_PenSetFilter(pen.get(), mainFilter);
259
- }
260
-
261
- void SvgFilter::ApplySingleEffectToFilter(OH_Drawing_Filter* filter, const FilterEffect& effect,
262
- rnoh::drawing::Brush* brush, rnoh::drawing::Pen* pen, const std::string& extra) {
263
- if (!filter) {
264
- DLOG(WARNING) << "[SvgFilter] Null filter passed to ApplySingleEffectToFilter";
265
- return;
266
- }
267
- switch (effect.filterType) {
268
- case FilterType::GAUSSIAN_BLUR: {
269
- if (extra == "image") {
270
- auto* imageFilter = CreateGaussianBlurFilter(effect);
271
- if (imageFilter) {
272
- OH_Drawing_FilterSetImageFilter(filter, imageFilter);
273
- }
274
- } else {
275
- auto* maskFilter = CreateBlurFilter(effect);
276
- if (maskFilter) {
277
- OH_Drawing_FilterSetMaskFilter(filter, maskFilter);
278
- }
279
- }
280
- break;
281
- }
282
- case FilterType::COLOR_MATRIX: {
283
- auto* colorFilter = CreateColorMatrixFilter(effect);
284
- if (colorFilter) {
285
- float identityMatrix[20] = {
286
- 1,0,0,0,0, 0,1,0,0,0, 0,0,1,0,0, 0,0,0,1,0
287
- };
288
- OH_Drawing_ColorFilter* existingColorFilter = OH_Drawing_ColorFilterCreateMatrix(identityMatrix);
289
- OH_Drawing_FilterGetColorFilter(filter,existingColorFilter);
290
- if (existingColorFilter) {
291
- auto* composedColorFilter = OH_Drawing_ColorFilterCreateCompose(colorFilter, existingColorFilter);
292
- if (composedColorFilter) {
293
- OH_Drawing_FilterSetColorFilter(filter, composedColorFilter);
294
- }
295
- } else {
296
- OH_Drawing_FilterSetColorFilter(filter, colorFilter);
297
- }
298
- }
299
- break;
300
- }
301
- case FilterType::FEFLOOD: {
302
- break;
303
- }
304
- case FilterType::FEOFFSET: {
305
- break;
306
- }
307
- case FilterType::BLUR: {
308
- auto* maskFilter = CreateBlurFilter(effect);
309
- if (maskFilter) {
310
- OH_Drawing_FilterSetMaskFilter(filter, maskFilter);
311
- }
312
- break;
313
- }
314
- case FilterType::DROP_SHADOW: {
315
- auto* shadowLayer = CreateDropShadowFilter(effect);
316
- if (shadowLayer) {
317
- if (brush) {
318
- OH_Drawing_BrushSetShadowLayer(brush->get(), shadowLayer);
319
- } else if (pen) {
320
- OH_Drawing_PenSetShadowLayer(pen->get(), shadowLayer);
321
- }
322
- }
323
- break;
324
- }
325
- case FilterType::BLEND: {
326
- break;
327
- }
328
- case FilterType::COMPOSITE: {
329
- break;
330
- }
331
- case FilterType::MERGE:
332
- break;
333
- default:
334
- DLOG(WARNING) << "[SvgFilter] Unsupported filter type: " << static_cast<int>(effect.filterType);
335
- break;
336
- }
337
- }
338
-
339
- OH_Drawing_ImageFilter* SvgFilter::CreateGaussianBlurFilter(const FilterEffect& effect) {
340
- auto inputFilter = GetInputImageFilter(effect.in);
341
- auto* blurFilter = OH_Drawing_ImageFilterCreateBlur(
342
- static_cast<double>(effect.stdDeviationX_),
343
- static_cast<double>(effect.stdDeviationY_),
344
- OH_Drawing_TileMode::CLAMP,
345
- inputFilter
346
- );
347
-
348
- if (!effect.result.empty()) {
349
- RegisterFilterResult(effect.result, blurFilter, nullptr, nullptr);
350
- }
351
-
352
- return blurFilter;
353
- }
354
-
355
- OH_Drawing_MaskFilter* SvgFilter::CreateBlurFilter(const FilterEffect& effect) {
356
- if (effect.values.size() >= 1) {
357
- auto* maskFilter = OH_Drawing_MaskFilterCreateBlur(
358
- OH_Drawing_BlurType::NORMAL,
359
- static_cast<double>(effect.values[0]),
360
- false
361
- );
362
-
363
- if (!effect.result.empty()) {
364
- RegisterFilterResult(effect.result, nullptr, nullptr, maskFilter);
365
- }
366
-
367
- return maskFilter;
368
- }
369
- return nullptr;
370
- }
371
-
372
- OH_Drawing_ColorFilter* SvgFilter::CreateColorMatrixFilter(const FilterEffect& effect) {
373
- OH_Drawing_ColorFilter* colorFilter = nullptr;
374
- if (effect.type == "matrix") {
375
- colorFilter = CreateMatrixFilter(effect.values);
376
- } else if (effect.type == "saturate") {
377
- colorFilter = CreateSaturateFilter(effect.values);
378
- } else if (effect.type == "hueRotate") {
379
- colorFilter = CreateHueRotateFilter(effect.values);
380
- } else if (effect.type == "luminanceToAlpha") {
381
- colorFilter = CreateLuminanceToAlphaFilter();
382
- } else {
383
- float identityMatrix[20] = {
384
- 1,0,0,0,0, 0,1,0,0,0, 0,0,1,0,0, 0,0,0,1,0
385
- };
386
- colorFilter = OH_Drawing_ColorFilterCreateMatrix(identityMatrix);
387
- }
388
-
389
- colorFilter = CombineWithInputColor(colorFilter, effect.in);
390
- if (!effect.result.empty()) {
391
- RegisterFilterResult(effect.result, nullptr, colorFilter, nullptr);
392
- }
393
- return colorFilter;
394
- }
395
-
396
- OH_Drawing_ColorFilter* SvgFilter::CreateMatrixFilter(const std::vector<float>& values) {
397
- if (values.size() >= 20) {
398
- return OH_Drawing_ColorFilterCreateMatrix(values.data());
399
- } else {
400
- float identityMatrix[20] = {
401
- 1,0,0,0,0, 0,1,0,0,0, 0,0,1,0,0, 0,0,0,1,0
402
- };
403
- return OH_Drawing_ColorFilterCreateMatrix(identityMatrix);
404
- }
405
- }
406
-
407
- OH_Drawing_ColorFilter* SvgFilter::CreateSaturateFilter(const std::vector<float>& values) {
408
- float saturation = values.empty() ? 1.0f : values[0];
409
- saturation = std::max(0.0f, saturation);
410
- const float rWeight = 0.213f;
411
- const float gWeight = 0.715f;
412
- const float bWeight = 0.072f;
413
-
414
- float colorMatrix[20] = {
415
- rWeight + (1.0f - rWeight) * saturation, gWeight * (1.0f - saturation), bWeight * (1.0f - saturation), 0.0f, 0.0f,
416
- rWeight * (1.0f - saturation), gWeight + (1.0f - gWeight) * saturation, bWeight * (1.0f - saturation), 0.0f, 0.0f,
417
- rWeight * (1.0f - saturation), gWeight * (1.0f - saturation), bWeight + (1.0f - bWeight) * saturation, 0.0f, 0.0f,
418
- 0.0f, 0.0f, 0.0f, 1.0f, 0.0f
419
- };
420
-
421
- return OH_Drawing_ColorFilterCreateMatrix(colorMatrix);
422
- }
423
-
424
- OH_Drawing_ColorFilter* SvgFilter::CreateHueRotateFilter(const std::vector<float>& values) {
425
- float angle = values.empty() ? 0.0f : values[0];
426
- float radians = angle * M_PI / 180.0f;
427
- float cosA = cos(radians);
428
- float sinA = sin(radians);
429
- float colorMatrix[20] = {
430
- 0.213f + 0.787f * cosA - 0.213f * sinA, 0.715f - 0.715f * cosA - 0.715f * sinA, 0.072f - 0.072f * cosA + 0.928f * sinA, 0.0f, 0.0f,
431
- 0.213f - 0.213f * cosA + 0.143f * sinA, 0.715f + 0.285f * cosA + 0.140f * sinA, 0.072f - 0.072f * cosA - 0.283f * sinA, 0.0f, 0.0f,
432
- 0.213f - 0.213f * cosA - 0.787f * sinA, 0.715f - 0.715f * cosA + 0.715f * sinA, 0.072f + 0.928f * cosA + 0.072f * sinA, 0.0f, 0.0f,
433
- 0.0f, 0.0f, 0.0f, 1.0f, 0.0f
434
- };
435
-
436
- return OH_Drawing_ColorFilterCreateMatrix(colorMatrix);
437
- }
438
-
439
- OH_Drawing_ColorFilter* SvgFilter::CreateLuminanceToAlphaFilter() {
440
- float colorMatrix[20] = {
441
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
442
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
443
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
444
- 0.2125f, 0.7154f, 0.0721f, 0.0f, 0.0f
445
- };
446
-
447
- return OH_Drawing_ColorFilterCreateMatrix(colorMatrix);
448
- }
449
-
450
- OH_Drawing_ShadowLayer* SvgFilter::CreateDropShadowFilter(const FilterEffect& effect) {
451
- uint32_t shadowColor = 0xFF000000;
452
- if (!effect.floodColor.empty() && effect.floodColor != "none") {
453
- uint32_t baseColor = 0x000000;
454
-
455
- if (effect.floodColor.find("0x") == 0 || effect.floodColor.find("0X") == 0) {
456
- try {
457
- baseColor = static_cast<uint32_t>(std::stoul(effect.floodColor, nullptr, 16));
458
- if (effect.floodColor.length() > 8) {
459
- baseColor = baseColor & 0x00FFFFFF;
460
- }
461
- } catch (const std::exception& e) {
462
- baseColor = 0x000000;
463
- }
464
- } else if (effect.floodColor.front() == '#') {
465
- std::string hex = effect.floodColor.substr(1);
466
- try {
467
- if (hex.length() == 6) {
468
- baseColor = static_cast<uint32_t>(std::stoul(hex, nullptr, 16));
469
- } else if (hex.length() == 3) {
470
- uint32_t r = std::stoul(hex.substr(0, 1), nullptr, 16);
471
- uint32_t g = std::stoul(hex.substr(1, 1), nullptr, 16);
472
- uint32_t b = std::stoul(hex.substr(2, 1), nullptr, 16);
473
- baseColor = (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b;
474
- }
475
- } catch (const std::exception& e) {
476
- baseColor = 0x000000;
477
- }
478
- }
479
-
480
- uint32_t red = (baseColor >> 16) & 0xFF;
481
- uint32_t green = (baseColor >> 8) & 0xFF;
482
- uint32_t blue = baseColor & 0xFF;
483
- float opacity = std::max(0.0f, std::min(1.0f, effect.floodOpacity));
484
-
485
- red = static_cast<uint32_t>(red * opacity + 255 * (1.0f - opacity));
486
- green = static_cast<uint32_t>(green * opacity + 255 * (1.0f - opacity));
487
- blue = static_cast<uint32_t>(blue * opacity + 255 * (1.0f - opacity));
488
-
489
- red = std::min(red, 255u);
490
- green = std::min(green, 255u);
491
- blue = std::min(blue, 255u);
492
-
493
- uint32_t alpha = 0xFF;
494
- shadowColor = (alpha << 24) | (red << 16) | (green << 8) | blue;
495
- }
496
-
497
- return OH_Drawing_ShadowLayerCreate(
498
- static_cast<double>(effect.stdDeviationX_),
499
- static_cast<double>(effect.dx_),
500
- static_cast<double>(effect.dy_),
501
- shadowColor
502
- );
503
- }
504
- }
505
- }
1
+ /*
2
+ * Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
3
+ * Use of this source code is governed by a MIT license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ #include "SvgFilter.h"
8
+ #include <native_drawing/drawing_mask_filter.h>
9
+ #include <native_drawing/drawing_color_filter.h>
10
+ #include <native_drawing/drawing_image_filter.h>
11
+ #include <native_drawing/drawing_shadow_layer.h>
12
+ #include <native_drawing/drawing_brush.h>
13
+ #include <native_drawing/drawing_pen.h>
14
+ #include <native_drawing/drawing_types.h>
15
+ #include <glog/logging.h>
16
+ #include <algorithm>
17
+ #include <cmath>
18
+ #include <string>
19
+ #include <stdexcept>
20
+ #include <sstream>
21
+ #include <vector>
22
+ #include <set>
23
+ #include <map>
24
+ #include <memory>
25
+
26
+ #ifndef M_PI
27
+ #define M_PI 3.14159265358979323846
28
+ #endif
29
+
30
+ namespace rnoh {
31
+ namespace svg {
32
+
33
+ struct InputSource {
34
+ std::string name;
35
+ OH_Drawing_ImageFilter* imageFilter = nullptr;
36
+ OH_Drawing_ColorFilter* colorFilter = nullptr;
37
+ OH_Drawing_MaskFilter* maskFilter = nullptr;
38
+ OH_Drawing_Filter* combinedFilter = nullptr;
39
+ bool ownsFilters = false;
40
+
41
+ ~InputSource() {
42
+ }
43
+
44
+ void cleanup() {
45
+ if (ownsFilters) {
46
+ if (imageFilter) {
47
+ OH_Drawing_ImageFilterDestroy(imageFilter);
48
+ imageFilter = nullptr;
49
+ }
50
+ if (colorFilter) {
51
+ OH_Drawing_ColorFilterDestroy(colorFilter);
52
+ colorFilter = nullptr;
53
+ }
54
+ if (maskFilter) {
55
+ OH_Drawing_MaskFilterDestroy(maskFilter);
56
+ maskFilter = nullptr;
57
+ }
58
+ if (combinedFilter) {
59
+ OH_Drawing_FilterDestroy(combinedFilter);
60
+ combinedFilter = nullptr;
61
+ }
62
+ ownsFilters = false;
63
+ }
64
+ }
65
+ };
66
+
67
+ class InputSourceManager {
68
+ private:
69
+ std::map<std::string, std::shared_ptr<InputSource>> sources_;
70
+
71
+ public:
72
+ void RegisterSource(const std::string& name, OH_Drawing_ImageFilter* imageFilter = nullptr,
73
+ OH_Drawing_ColorFilter* colorFilter = nullptr, OH_Drawing_MaskFilter* maskFilter = nullptr) {
74
+ auto source = std::make_shared<InputSource>();
75
+ source->name = name;
76
+ source->imageFilter = imageFilter;
77
+ source->colorFilter = colorFilter;
78
+ source->maskFilter = maskFilter;
79
+
80
+ if (imageFilter || colorFilter || maskFilter) {
81
+ source->combinedFilter = OH_Drawing_FilterCreate();
82
+ if (source->combinedFilter) {
83
+ if (imageFilter) OH_Drawing_FilterSetImageFilter(source->combinedFilter, imageFilter);
84
+ if (colorFilter) OH_Drawing_FilterSetColorFilter(source->combinedFilter, colorFilter);
85
+ if (maskFilter) OH_Drawing_FilterSetMaskFilter(source->combinedFilter, maskFilter);
86
+ }
87
+ }
88
+
89
+ sources_[name] = source;
90
+ }
91
+
92
+ std::shared_ptr<InputSource> GetSource(const std::string& name) {
93
+ if (name.empty()) {
94
+ return nullptr;
95
+ }
96
+
97
+ auto it = sources_.find(name);
98
+ if (it != sources_.end()) {
99
+ return it->second;
100
+ }
101
+
102
+ if (name == "SourceGraphic") {
103
+ return GetOrCreateStandardSource("SourceGraphic");
104
+ } else if (name == "SourceAlpha") {
105
+ return GetOrCreateStandardSource("SourceAlpha");
106
+ } else if (name == "BackgroundImage") {
107
+ return GetOrCreateStandardSource("BackgroundImage");
108
+ } else if (name == "BackgroundAlpha") {
109
+ return GetOrCreateStandardSource("BackgroundAlpha");
110
+ } else if (name == "FillPaint") {
111
+ return GetOrCreateStandardSource("FillPaint");
112
+ } else if (name == "StrokePaint") {
113
+ return GetOrCreateStandardSource("StrokePaint");
114
+ }
115
+ DLOG(WARNING) << "[SvgFilter] Input source not found: " << name;
116
+ return nullptr;
117
+ }
118
+
119
+ void Clear() {
120
+ for (auto& pair : sources_) {
121
+ if (pair.second) {
122
+ pair.second->cleanup();
123
+ }
124
+ }
125
+ sources_.clear();
126
+ }
127
+
128
+ private:
129
+ std::shared_ptr<InputSource> GetOrCreateStandardSource(const std::string& name) {
130
+ auto it = sources_.find(name);
131
+ if (it != sources_.end()) {
132
+ return it->second;
133
+ }
134
+
135
+ auto source = std::make_shared<InputSource>();
136
+ source->name = name;
137
+ if (name == "SourceAlpha") {
138
+ float alphaMatrix[20] = {
139
+ 0, 0, 0, 0, 0,
140
+ 0, 0, 0, 0, 0,
141
+ 0, 0, 0, 0, 0,
142
+ 0, 0, 0, 1, 0
143
+ };
144
+ source->colorFilter = OH_Drawing_ColorFilterCreateMatrix(alphaMatrix);
145
+ } else if (name == "BackgroundImage") {
146
+ } else if (name == "BackgroundAlpha") {
147
+ float backgroundAlphaMatrix[20] = {
148
+ 0, 0, 0, 0, 0,
149
+ 0, 0, 0, 0, 0,
150
+ 0, 0, 0, 0, 0,
151
+ 0, 0, 0, 1, 0
152
+ };
153
+ source->colorFilter = OH_Drawing_ColorFilterCreateMatrix(backgroundAlphaMatrix);
154
+ } else if (name == "FillPaint" || name == "StrokePaint") {
155
+ float matrix[20] = {
156
+ 1, 0, 0, 0, 0,
157
+ 0, 1, 0, 0, 0,
158
+ 0, 0, 1, 0, 0,
159
+ 0, 0, 0, 1, 0
160
+ };
161
+ source->colorFilter = OH_Drawing_ColorFilterCreateMatrix(matrix);
162
+ }
163
+
164
+ sources_[name] = source;
165
+ return source;
166
+ }
167
+ };
168
+
169
+ static InputSourceManager g_inputSourceManager;
170
+ OH_Drawing_ImageFilter* SvgFilter::GetInputImageFilter(const std::string& inputName) {
171
+ if (inputName.empty() || inputName == "SourceGraphic") {
172
+ return nullptr;
173
+ }
174
+
175
+ auto source = g_inputSourceManager.GetSource(inputName);
176
+ return source ? source->imageFilter : nullptr;
177
+ }
178
+
179
+ OH_Drawing_ColorFilter* SvgFilter::GetInputColorFilter(const std::string& inputName) {
180
+ if (inputName.empty() || inputName == "SourceGraphic") {
181
+ return nullptr;
182
+ }
183
+
184
+ auto source = g_inputSourceManager.GetSource(inputName);
185
+ if (source) {
186
+ return source->colorFilter;
187
+ }
188
+ return nullptr;
189
+ }
190
+
191
+ OH_Drawing_Filter* SvgFilter::GetInputFilter(const std::string& inputName) {
192
+ if (inputName.empty() || inputName == "SourceGraphic") {
193
+ return nullptr;
194
+ }
195
+
196
+ auto source = g_inputSourceManager.GetSource(inputName);
197
+ return source ? source->combinedFilter : nullptr;
198
+ }
199
+
200
+ OH_Drawing_ColorFilter* SvgFilter::CombineWithInputColor(OH_Drawing_ColorFilter* newFilter, const std::string& inputName) {
201
+ if (inputName.empty() || inputName == "SourceGraphic" || !newFilter) {
202
+ return newFilter;
203
+ }
204
+
205
+ auto inputFilter = GetInputColorFilter(inputName);
206
+ if (inputFilter) {
207
+ return OH_Drawing_ColorFilterCreateCompose(newFilter, inputFilter);
208
+ }
209
+
210
+ return newFilter;
211
+ }
212
+
213
+ void SvgFilter::RegisterFilterResult(const std::string& resultId, OH_Drawing_ImageFilter* imageFilter,
214
+ OH_Drawing_ColorFilter* colorFilter, OH_Drawing_MaskFilter* maskFilter) {
215
+ if (!resultId.empty()) {
216
+ g_inputSourceManager.RegisterSource(resultId, imageFilter, colorFilter, maskFilter);
217
+ }
218
+ }
219
+
220
+ void SvgFilter::AddFilterEffect(const FilterEffect& effect) {
221
+ effects_.push_back(effect);
222
+ }
223
+
224
+ void SvgFilter::ApplyToBrush(rnoh::drawing::Brush& brush, const std::string& extra) {
225
+ if (effects_.empty()) {
226
+ return;
227
+ }
228
+
229
+ g_inputSourceManager.Clear();
230
+ auto* mainFilter = OH_Drawing_FilterCreate();
231
+ if (!mainFilter) {
232
+ DLOG(WARNING) << "[SvgFilter] Failed to create main filter";
233
+ return;
234
+ }
235
+
236
+ for (const auto& effect : effects_) {
237
+ ApplySingleEffectToFilter(mainFilter, effect, &brush, nullptr, extra);
238
+ }
239
+
240
+ OH_Drawing_BrushSetFilter(brush.get(), mainFilter);
241
+ }
242
+
243
+ void SvgFilter::ApplyToPen(rnoh::drawing::Pen& pen) {
244
+ if (effects_.empty()) {
245
+ return;
246
+ }
247
+
248
+ g_inputSourceManager.Clear();
249
+ auto* mainFilter = OH_Drawing_FilterCreate();
250
+ if (!mainFilter) {
251
+ DLOG(WARNING) << "[SvgFilter] Failed to create main filter";
252
+ return;
253
+ }
254
+
255
+ for (const auto& effect : effects_) {
256
+ ApplySingleEffectToFilter(mainFilter, effect, nullptr, &pen);
257
+ }
258
+ OH_Drawing_PenSetFilter(pen.get(), mainFilter);
259
+ }
260
+
261
+ void SvgFilter::ApplySingleEffectToFilter(OH_Drawing_Filter* filter, const FilterEffect& effect,
262
+ rnoh::drawing::Brush* brush, rnoh::drawing::Pen* pen, const std::string& extra) {
263
+ if (!filter) {
264
+ DLOG(WARNING) << "[SvgFilter] Null filter passed to ApplySingleEffectToFilter";
265
+ return;
266
+ }
267
+ switch (effect.filterType) {
268
+ case FilterType::GAUSSIAN_BLUR: {
269
+ if (extra == "image") {
270
+ auto* imageFilter = CreateGaussianBlurFilter(effect);
271
+ if (imageFilter) {
272
+ OH_Drawing_FilterSetImageFilter(filter, imageFilter);
273
+ }
274
+ } else {
275
+ auto* maskFilter = CreateBlurFilter(effect);
276
+ if (maskFilter) {
277
+ OH_Drawing_FilterSetMaskFilter(filter, maskFilter);
278
+ }
279
+ }
280
+ break;
281
+ }
282
+ case FilterType::COLOR_MATRIX: {
283
+ auto* colorFilter = CreateColorMatrixFilter(effect);
284
+ if (colorFilter) {
285
+ float identityMatrix[20] = {
286
+ 1,0,0,0,0, 0,1,0,0,0, 0,0,1,0,0, 0,0,0,1,0
287
+ };
288
+ OH_Drawing_ColorFilter* existingColorFilter = OH_Drawing_ColorFilterCreateMatrix(identityMatrix);
289
+ OH_Drawing_FilterGetColorFilter(filter,existingColorFilter);
290
+ if (existingColorFilter) {
291
+ auto* composedColorFilter = OH_Drawing_ColorFilterCreateCompose(colorFilter, existingColorFilter);
292
+ if (composedColorFilter) {
293
+ OH_Drawing_FilterSetColorFilter(filter, composedColorFilter);
294
+ }
295
+ } else {
296
+ OH_Drawing_FilterSetColorFilter(filter, colorFilter);
297
+ }
298
+ }
299
+ break;
300
+ }
301
+ case FilterType::FEFLOOD: {
302
+ break;
303
+ }
304
+ case FilterType::FEOFFSET: {
305
+ break;
306
+ }
307
+ case FilterType::BLUR: {
308
+ auto* maskFilter = CreateBlurFilter(effect);
309
+ if (maskFilter) {
310
+ OH_Drawing_FilterSetMaskFilter(filter, maskFilter);
311
+ }
312
+ break;
313
+ }
314
+ case FilterType::DROP_SHADOW: {
315
+ auto* shadowLayer = CreateDropShadowFilter(effect);
316
+ if (shadowLayer) {
317
+ if (brush) {
318
+ OH_Drawing_BrushSetShadowLayer(brush->get(), shadowLayer);
319
+ } else if (pen) {
320
+ OH_Drawing_PenSetShadowLayer(pen->get(), shadowLayer);
321
+ }
322
+ }
323
+ break;
324
+ }
325
+ case FilterType::BLEND: {
326
+ break;
327
+ }
328
+ case FilterType::COMPOSITE: {
329
+ break;
330
+ }
331
+ case FilterType::MERGE:
332
+ break;
333
+ default:
334
+ DLOG(WARNING) << "[SvgFilter] Unsupported filter type: " << static_cast<int>(effect.filterType);
335
+ break;
336
+ }
337
+ }
338
+
339
+ OH_Drawing_ImageFilter* SvgFilter::CreateGaussianBlurFilter(const FilterEffect& effect) {
340
+ auto inputFilter = GetInputImageFilter(effect.in);
341
+ auto* blurFilter = OH_Drawing_ImageFilterCreateBlur(
342
+ static_cast<double>(effect.stdDeviationX_),
343
+ static_cast<double>(effect.stdDeviationY_),
344
+ OH_Drawing_TileMode::CLAMP,
345
+ inputFilter
346
+ );
347
+
348
+ if (!effect.result.empty()) {
349
+ RegisterFilterResult(effect.result, blurFilter, nullptr, nullptr);
350
+ }
351
+
352
+ return blurFilter;
353
+ }
354
+
355
+ OH_Drawing_MaskFilter* SvgFilter::CreateBlurFilter(const FilterEffect& effect) {
356
+ if (effect.values.size() >= 1) {
357
+ auto* maskFilter = OH_Drawing_MaskFilterCreateBlur(
358
+ OH_Drawing_BlurType::NORMAL,
359
+ static_cast<double>(effect.values[0]),
360
+ false
361
+ );
362
+
363
+ if (!effect.result.empty()) {
364
+ RegisterFilterResult(effect.result, nullptr, nullptr, maskFilter);
365
+ }
366
+
367
+ return maskFilter;
368
+ }
369
+ return nullptr;
370
+ }
371
+
372
+ OH_Drawing_ColorFilter* SvgFilter::CreateColorMatrixFilter(const FilterEffect& effect) {
373
+ OH_Drawing_ColorFilter* colorFilter = nullptr;
374
+ if (effect.type == "matrix") {
375
+ colorFilter = CreateMatrixFilter(effect.values);
376
+ } else if (effect.type == "saturate") {
377
+ colorFilter = CreateSaturateFilter(effect.values);
378
+ } else if (effect.type == "hueRotate") {
379
+ colorFilter = CreateHueRotateFilter(effect.values);
380
+ } else if (effect.type == "luminanceToAlpha") {
381
+ colorFilter = CreateLuminanceToAlphaFilter();
382
+ } else {
383
+ float identityMatrix[20] = {
384
+ 1,0,0,0,0, 0,1,0,0,0, 0,0,1,0,0, 0,0,0,1,0
385
+ };
386
+ colorFilter = OH_Drawing_ColorFilterCreateMatrix(identityMatrix);
387
+ }
388
+
389
+ colorFilter = CombineWithInputColor(colorFilter, effect.in);
390
+ if (!effect.result.empty()) {
391
+ RegisterFilterResult(effect.result, nullptr, colorFilter, nullptr);
392
+ }
393
+ return colorFilter;
394
+ }
395
+
396
+ OH_Drawing_ColorFilter* SvgFilter::CreateMatrixFilter(const std::vector<float>& values) {
397
+ if (values.size() >= 20) {
398
+ return OH_Drawing_ColorFilterCreateMatrix(values.data());
399
+ } else {
400
+ float identityMatrix[20] = {
401
+ 1,0,0,0,0, 0,1,0,0,0, 0,0,1,0,0, 0,0,0,1,0
402
+ };
403
+ return OH_Drawing_ColorFilterCreateMatrix(identityMatrix);
404
+ }
405
+ }
406
+
407
+ OH_Drawing_ColorFilter* SvgFilter::CreateSaturateFilter(const std::vector<float>& values) {
408
+ float saturation = values.empty() ? 1.0f : values[0];
409
+ saturation = std::max(0.0f, saturation);
410
+ const float rWeight = 0.213f;
411
+ const float gWeight = 0.715f;
412
+ const float bWeight = 0.072f;
413
+
414
+ float colorMatrix[20] = {
415
+ rWeight + (1.0f - rWeight) * saturation, gWeight * (1.0f - saturation), bWeight * (1.0f - saturation), 0.0f, 0.0f,
416
+ rWeight * (1.0f - saturation), gWeight + (1.0f - gWeight) * saturation, bWeight * (1.0f - saturation), 0.0f, 0.0f,
417
+ rWeight * (1.0f - saturation), gWeight * (1.0f - saturation), bWeight + (1.0f - bWeight) * saturation, 0.0f, 0.0f,
418
+ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f
419
+ };
420
+
421
+ return OH_Drawing_ColorFilterCreateMatrix(colorMatrix);
422
+ }
423
+
424
+ OH_Drawing_ColorFilter* SvgFilter::CreateHueRotateFilter(const std::vector<float>& values) {
425
+ float angle = values.empty() ? 0.0f : values[0];
426
+ float radians = angle * M_PI / 180.0f;
427
+ float cosA = cos(radians);
428
+ float sinA = sin(radians);
429
+ float colorMatrix[20] = {
430
+ 0.213f + 0.787f * cosA - 0.213f * sinA, 0.715f - 0.715f * cosA - 0.715f * sinA, 0.072f - 0.072f * cosA + 0.928f * sinA, 0.0f, 0.0f,
431
+ 0.213f - 0.213f * cosA + 0.143f * sinA, 0.715f + 0.285f * cosA + 0.140f * sinA, 0.072f - 0.072f * cosA - 0.283f * sinA, 0.0f, 0.0f,
432
+ 0.213f - 0.213f * cosA - 0.787f * sinA, 0.715f - 0.715f * cosA + 0.715f * sinA, 0.072f + 0.928f * cosA + 0.072f * sinA, 0.0f, 0.0f,
433
+ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f
434
+ };
435
+
436
+ return OH_Drawing_ColorFilterCreateMatrix(colorMatrix);
437
+ }
438
+
439
+ OH_Drawing_ColorFilter* SvgFilter::CreateLuminanceToAlphaFilter() {
440
+ float colorMatrix[20] = {
441
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
442
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
443
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
444
+ 0.2125f, 0.7154f, 0.0721f, 0.0f, 0.0f
445
+ };
446
+
447
+ return OH_Drawing_ColorFilterCreateMatrix(colorMatrix);
448
+ }
449
+
450
+ OH_Drawing_ShadowLayer* SvgFilter::CreateDropShadowFilter(const FilterEffect& effect) {
451
+ uint32_t shadowColor = 0xFF000000;
452
+ if (!effect.floodColor.empty() && effect.floodColor != "none") {
453
+ uint32_t baseColor = 0x000000;
454
+
455
+ if (effect.floodColor.find("0x") == 0 || effect.floodColor.find("0X") == 0) {
456
+ try {
457
+ baseColor = static_cast<uint32_t>(std::stoul(effect.floodColor, nullptr, 16));
458
+ if (effect.floodColor.length() > 8) {
459
+ baseColor = baseColor & 0x00FFFFFF;
460
+ }
461
+ } catch (const std::exception& e) {
462
+ baseColor = 0x000000;
463
+ }
464
+ } else if (effect.floodColor.front() == '#') {
465
+ std::string hex = effect.floodColor.substr(1);
466
+ try {
467
+ if (hex.length() == 6) {
468
+ baseColor = static_cast<uint32_t>(std::stoul(hex, nullptr, 16));
469
+ } else if (hex.length() == 3) {
470
+ uint32_t r = std::stoul(hex.substr(0, 1), nullptr, 16);
471
+ uint32_t g = std::stoul(hex.substr(1, 1), nullptr, 16);
472
+ uint32_t b = std::stoul(hex.substr(2, 1), nullptr, 16);
473
+ baseColor = (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b;
474
+ }
475
+ } catch (const std::exception& e) {
476
+ baseColor = 0x000000;
477
+ }
478
+ }
479
+
480
+ uint32_t red = (baseColor >> 16) & 0xFF;
481
+ uint32_t green = (baseColor >> 8) & 0xFF;
482
+ uint32_t blue = baseColor & 0xFF;
483
+ float opacity = std::max(0.0f, std::min(1.0f, effect.floodOpacity));
484
+
485
+ red = static_cast<uint32_t>(red * opacity + 255 * (1.0f - opacity));
486
+ green = static_cast<uint32_t>(green * opacity + 255 * (1.0f - opacity));
487
+ blue = static_cast<uint32_t>(blue * opacity + 255 * (1.0f - opacity));
488
+
489
+ red = std::min(red, 255u);
490
+ green = std::min(green, 255u);
491
+ blue = std::min(blue, 255u);
492
+
493
+ uint32_t alpha = 0xFF;
494
+ shadowColor = (alpha << 24) | (red << 16) | (green << 8) | blue;
495
+ }
496
+
497
+ return OH_Drawing_ShadowLayerCreate(
498
+ static_cast<double>(effect.stdDeviationX_),
499
+ static_cast<double>(effect.dx_),
500
+ static_cast<double>(effect.dy_),
501
+ shadowColor
502
+ );
503
+ }
504
+ }
505
+ }