• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 "ani_uieffect.h"
17 namespace OHOS {
18 namespace Rosen {
BindVisualEffectMethod(ani_env * env)19 ani_status AniEffect::BindVisualEffectMethod(ani_env* env)
20 {
21     static const char* visualEffectClassName = "L@ohos/graphics/uiEffect/uiEffect/VisualEffectInternal;";
22     ani_class visualEffectClass;
23     if (env->FindClass(visualEffectClassName, &visualEffectClass) != ANI_OK) {
24         UIEFFECT_LOG_E("Not found %{public}s", visualEffectClassName);
25         return ANI_NOT_FOUND;
26     };
27     std::array visualEffectMethods = {
28         ani_native_function { "backgroundColorBlenderNative",
29             "L@ohos/graphics/uiEffect/uiEffect/BrightnessBlender;:L@ohos/graphics/uiEffect/uiEffect/VisualEffect;",
30             reinterpret_cast<void*>(OHOS::Rosen::AniEffect::BackgroundColorBlender) },
31     };
32     ani_status ret = env->Class_BindNativeMethods(visualEffectClass,
33         visualEffectMethods.data(), visualEffectMethods.size());
34     if (ret != ANI_OK) {
35         UIEFFECT_LOG_E("Class_BindNativeMethods failed: %{public}d", ret);
36         return ANI_ERROR;
37     };
38     return ret;
39 }
40 
BindFilterMethod(ani_env * env)41 ani_status AniEffect::BindFilterMethod(ani_env* env)
42 {
43     static const char* filterClassName = "L@ohos/graphics/uiEffect/uiEffect/FilterInternal;";
44     ani_class filterClass;
45     if (env->FindClass(filterClassName, &filterClass) != ANI_OK) {
46         UIEFFECT_LOG_E("Not found %{public}s", filterClassName);
47         return ANI_NOT_FOUND;
48     };
49     std::array filterMethods = {
50         ani_native_function { "pixelStretchNative", nullptr,
51             reinterpret_cast<void*>(OHOS::Rosen::AniEffect::PixelStretch) },
52         ani_native_function { "blurNative", nullptr,
53             reinterpret_cast<void*>(OHOS::Rosen::AniEffect::Blur) },
54     };
55     ani_status ret = env->Class_BindNativeMethods(filterClass, filterMethods.data(), filterMethods.size());
56     if (ret != ANI_OK) {
57         UIEFFECT_LOG_E("Class_BindNativeMethods failed: %{public}d", ret);
58         return ANI_ERROR;
59     };
60     return ret;
61 }
62 
CreateAniObject(ani_env * env,std::string name,const char * signature,ani_long addr)63 ani_object AniEffect::CreateAniObject(ani_env* env, std::string name, const char* signature, ani_long addr)
64 {
65     ani_class cls;
66     if (env->FindClass(name.c_str(), &cls) != ANI_OK) {
67         UIEFFECT_LOG_E("not found '%{public}s'", name.c_str());
68         return {};
69     };
70     ani_method ctor;
71     if (env->Class_FindMethod(cls, "<ctor>", signature, &ctor) != ANI_OK) {
72         UIEFFECT_LOG_E("get ctor failed '%{public}s'", name.c_str());
73         return {};
74     };
75     ani_object obj = {};
76     if (env->Object_New(cls, ctor, &obj, addr) != ANI_OK) {
77         UIEFFECT_LOG_E("create object failed '%{public}s'", name.c_str());
78         return obj;
79     };
80     UIEFFECT_LOG_I("create object success '%{public}s'", name.c_str());
81     return obj;
82 }
83 
CheckCreateBrightnessBlender(ani_env * env,ani_object para_obj,ani_object & blender_obj)84 bool CheckCreateBrightnessBlender(ani_env* env, ani_object para_obj, ani_object& blender_obj)
85 {
86     ani_double cubicRateAni;
87     ani_double quadraticRateAni;
88     ani_double linearRateAni;
89     ani_double degreeAni;
90     ani_double saturationAni;
91     ani_double fractionAni;
92     ani_ref positiveCoefficientAni;
93     ani_ref negativeCoefficientAni;
94     if ((env->Object_GetPropertyByName_Double(para_obj, "cubicRate", &cubicRateAni) != ANI_OK) ||
95         (env->Object_GetPropertyByName_Double(para_obj, "quadraticRate", &quadraticRateAni) != ANI_OK) ||
96         (env->Object_GetPropertyByName_Double(para_obj, "linearRate", &linearRateAni) != ANI_OK) ||
97         (env->Object_GetPropertyByName_Double(para_obj, "degree", &degreeAni) != ANI_OK) ||
98         (env->Object_GetPropertyByName_Double(para_obj, "saturation", &saturationAni) != ANI_OK) ||
99         (env->Object_GetPropertyByName_Double(para_obj, "fraction", &fractionAni) != ANI_OK) ||
100         (env->Object_GetPropertyByName_Ref(para_obj, "positiveCoefficient", &positiveCoefficientAni) != ANI_OK) ||
101         (env->Object_GetPropertyByName_Ref(para_obj, "negativeCoefficient", &negativeCoefficientAni) != ANI_OK)) {
102         UIEFFECT_LOG_E("Input para is not BrightnessBlenderParam, some property cannot be found");
103         return false;
104     };
105     if ((env->Object_SetPropertyByName_Double(blender_obj, "cubicRate", cubicRateAni) != ANI_OK) ||
106         (env->Object_SetPropertyByName_Double(blender_obj, "quadraticRate", quadraticRateAni) != ANI_OK) ||
107         (env->Object_SetPropertyByName_Double(blender_obj, "linearRate", linearRateAni) != ANI_OK) ||
108         (env->Object_SetPropertyByName_Double(blender_obj, "degree", degreeAni) != ANI_OK) ||
109         (env->Object_SetPropertyByName_Double(blender_obj, "saturation", saturationAni) != ANI_OK) ||
110         (env->Object_SetPropertyByName_Double(blender_obj, "fraction", fractionAni) != ANI_OK) ||
111         (env->Object_SetPropertyByName_Ref(blender_obj, "positiveCoefficient", positiveCoefficientAni) != ANI_OK) ||
112         (env->Object_SetPropertyByName_Ref(blender_obj, "negativeCoefficient", negativeCoefficientAni) != ANI_OK)) {
113         UIEFFECT_LOG_E("Cannot set all property for BrightnessBlender, some property cannot be found");
114         return false;
115     };
116     return true;
117 }
118 
ParseBrightnessBlender(ani_env * env,ani_object para_obj,std::unique_ptr<BrightnessBlender> & blender)119 void AniEffect::ParseBrightnessBlender(ani_env* env, ani_object para_obj, std::unique_ptr<BrightnessBlender>& blender)
120 {
121     ani_double cubicRateAni;
122     ani_double quadraticRateAni;
123     ani_double linearRateAni;
124     ani_double degreeAni;
125     ani_double saturationAni;
126     ani_double fractionAni;
127     ani_ref positiveCoefficientAni;
128     ani_ref negativeCoefficientAni;
129     env->Object_GetPropertyByName_Double(para_obj, "cubicRate", &cubicRateAni);
130     env->Object_GetPropertyByName_Double(para_obj, "quadraticRate", &quadraticRateAni);
131     env->Object_GetPropertyByName_Double(para_obj, "linearRate", &linearRateAni);
132     env->Object_GetPropertyByName_Double(para_obj, "degree", &degreeAni);
133     env->Object_GetPropertyByName_Double(para_obj, "saturation", &saturationAni);
134     env->Object_GetPropertyByName_Double(para_obj, "fraction", &fractionAni);
135     env->Object_GetPropertyByName_Ref(para_obj, "positiveCoefficient", &positiveCoefficientAni);
136     env->Object_GetPropertyByName_Ref(para_obj, "negativeCoefficient", &negativeCoefficientAni);
137     const auto positiveCoefficientAniArray = reinterpret_cast<ani_array_double>(positiveCoefficientAni);
138     const auto negativeCoefficientAniArray = reinterpret_cast<ani_array_double>(negativeCoefficientAni);
139     ani_double posCoefNativeBuffer[3U] = { 0.0 };
140     ani_double negCoefNativeBuffer[3U] = { 0.0 };
141     const ani_size offset = 0;
142     const ani_size len = 3;
143     env->Array_GetRegion_Double(positiveCoefficientAniArray, offset, len, posCoefNativeBuffer);
144     env->Array_GetRegion_Double(negativeCoefficientAniArray, offset, len, negCoefNativeBuffer);
145     const int xIndex = 0;
146     const int yIndex = 1;
147     const int zIndex = 2;
148     Vector3f posCoefNative(posCoefNativeBuffer[xIndex], posCoefNativeBuffer[yIndex], posCoefNativeBuffer[zIndex]);
149     Vector3f negCoefNative(negCoefNativeBuffer[xIndex], negCoefNativeBuffer[yIndex], negCoefNativeBuffer[zIndex]);
150     blender->SetCubicRate(static_cast<float>(cubicRateAni));
151     blender->SetQuadRate(static_cast<float>(quadraticRateAni));
152     blender->SetLinearRate(static_cast<float>(linearRateAni));
153     blender->SetDegree(static_cast<float>(degreeAni));
154     blender->SetSaturation(static_cast<float>(saturationAni));
155     blender->SetFraction(static_cast<float>(fractionAni));
156     blender->SetPositiveCoeff(posCoefNative);
157     blender->SetNegativeCoeff(negCoefNative);
158 }
159 
CreateEffect(ani_env * env)160 ani_object AniEffect::CreateEffect(ani_env* env)
161 {
162     auto effectObj = std::make_unique<VisualEffect>();
163     auto retVal = CreateAniObject(env, ANI_UIEFFECT_VISUAL_EFFECT, nullptr,
164         reinterpret_cast<ani_long>(effectObj.release()));
165     return retVal;
166 }
167 
CreateBrightnessBlender(ani_env * env,ani_object para)168 ani_object AniEffect::CreateBrightnessBlender(ani_env* env, ani_object para)
169 {
170     ani_object retVal {};
171     ani_class cls;
172     if (env->FindClass(ANI_UIEFFECT_BRIGHTNESS_BLENDER.c_str(), &cls) != ANI_OK) {
173         UIEFFECT_LOG_E("not found '%{public}s'", ANI_UIEFFECT_BRIGHTNESS_BLENDER.c_str());
174         return {};
175     }
176     ani_method ctor;
177     if (env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor) != ANI_OK) {
178         UIEFFECT_LOG_E("get ctor failed '%{public}s'", ANI_UIEFFECT_BRIGHTNESS_BLENDER.c_str());
179         return {};
180     }
181     if (env->Object_New(cls, ctor, &retVal) != ANI_OK) {
182         UIEFFECT_LOG_E("create object failed '%{public}s'", ANI_UIEFFECT_BRIGHTNESS_BLENDER.c_str());
183         return {};
184     }
185     auto brightnessObj = std::make_unique<BrightnessBlender>();
186     retVal = CreateAniObject(env, ANI_UIEFFECT_BRIGHTNESS_BLENDER, nullptr,
187         reinterpret_cast<ani_long>(brightnessObj.release()));
188     if (!CheckCreateBrightnessBlender(env, para, retVal)) {
189         UIEFFECT_LOG_E("EffectNapi  CheckCreateBrightnessBlender failed.");
190         return {};
191     }
192     return retVal;
193 }
194 
CreateHdrBrightnessBlender(ani_env * env,ani_object para)195 ani_object AniEffect::CreateHdrBrightnessBlender(ani_env* env, ani_object para)
196 {
197     ani_object retVal {};
198     ani_class cls;
199     if (env->FindClass(ANI_UIEFFECT_HDRBRIGHTNESS_BLENDER.c_str(), &cls) != ANI_OK) {
200         UIEFFECT_LOG_E("not found '%{public}s'", ANI_UIEFFECT_HDRBRIGHTNESS_BLENDER.c_str());
201         return {};
202     };
203     ani_method ctor;
204     if (env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor) != ANI_OK) {
205         UIEFFECT_LOG_E("get ctor failed '%{public}s'", ANI_UIEFFECT_HDRBRIGHTNESS_BLENDER.c_str());
206         return {};
207     };
208     if (env->Object_New(cls, ctor, &retVal) != ANI_OK) {
209         UIEFFECT_LOG_E("create object failed '%{public}s'", ANI_UIEFFECT_HDRBRIGHTNESS_BLENDER.c_str());
210         return {};
211     };
212     auto brightnessObj = std::make_unique<BrightnessBlender>();
213     brightnessObj->SetHdr(true);
214     retVal = CreateAniObject(env, ANI_UIEFFECT_HDRBRIGHTNESS_BLENDER, nullptr,
215         reinterpret_cast<ani_long>(brightnessObj.release()));
216     if (!CheckCreateBrightnessBlender(env, para, retVal)) {
217         UIEFFECT_LOG_E("EffectNapi  CheckCreateBrightnessBlender failed.");
218         return {};
219     };
220     return retVal;
221 }
222 
BackgroundColorBlender(ani_env * env,ani_object obj,ani_object para)223 ani_object AniEffect::BackgroundColorBlender(ani_env* env, ani_object obj, ani_object para)
224 {
225     ani_object retVal {};
226     auto uniqueBlender = std::make_unique<BrightnessBlender>();
227     ParseBrightnessBlender(env, para, uniqueBlender);
228     auto bgColorEffectPara = std::make_shared<BackgroundColorEffectPara>();
229     std::shared_ptr<BrightnessBlender> sharedBlender = std::move(uniqueBlender);
230     bgColorEffectPara->SetBlender(sharedBlender);
231     ani_long nativeObj;
232     if (env->Object_GetFieldByName_Long(obj, "visualEffectNativeObj", &nativeObj) != ANI_OK) {
233         UIEFFECT_LOG_E("get generator visualEffectNativeObj failed");
234         return retVal;
235     }
236     VisualEffect* effectObj = reinterpret_cast<VisualEffect*>(nativeObj);
237     if (effectObj == nullptr) {
238         UIEFFECT_LOG_E("effectObj reinterpret_cast to VisualEffect failed");
239         return retVal;
240     }
241     effectObj->AddPara(bgColorEffectPara);
242     retVal = CreateAniObject(env, ANI_UIEFFECT_VISUAL_EFFECT, nullptr, reinterpret_cast<ani_long>(effectObj));
243     return retVal;
244 }
245 
CreateFilter(ani_env * env)246 ani_object AniEffect::CreateFilter(ani_env* env)
247 {
248     ani_object retVal {};
249     auto filterObj = std::make_unique<Filter>();
250     retVal = CreateAniObject(env, ANI_UIEFFECT_FILTER, nullptr, reinterpret_cast<ani_long>(filterObj.release()));
251     return retVal;
252 }
253 
PixelStretch(ani_env * env,ani_object obj,ani_object arrayObj,ani_enum_item enumItem)254 ani_object AniEffect::PixelStretch(ani_env* env, ani_object obj, ani_object arrayObj, ani_enum_item enumItem)
255 {
256     ani_object retVal {};
257 
258     ani_size enumIndex;
259     env->EnumItem_GetIndex(enumItem, &enumIndex);
260     Drawing::TileMode tileMode = static_cast<Drawing::TileMode>(enumIndex);
261 
262     auto pixelStretchPara = std::make_shared<PixelStretchPara>();
263     pixelStretchPara->SetTileMode(tileMode);
264 
265     ani_double length;
266     if (ANI_OK != env->Object_GetPropertyByName_Double(arrayObj, "length", &length)) {
267         UIEFFECT_LOG_E("get stretchSizes length failed");
268         return retVal;
269     }
270 
271     Vector4f stretchPercent;
272     // 4 mean Vector4f length
273     int vectorLen = 4;
274     for (int i = 0; i < int(length) && i < vectorLen; i++) {
275         ani_double val;
276         ani_ref ref;
277         if (ANI_OK != env->Object_CallMethodByName_Ref(arrayObj, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i) ||
278             ANI_OK != env->Object_CallMethodByName_Double(static_cast<ani_object>(ref), "unboxed", ":D", &val)) {
279             UIEFFECT_LOG_E("Object_CallMethodByName_Ref or Object_CallMethodByName_Double Failed");
280             return retVal;
281         }
282         stretchPercent[i] = static_cast<float>(val);
283     }
284     pixelStretchPara->SetStretchPercent(stretchPercent);
285 
286     ani_long nativeObj;
287     if (ANI_OK != env->Object_GetFieldByName_Long(obj, "filterNativeObj", &nativeObj)) {
288         UIEFFECT_LOG_E("get generator filterNativeObj failed");
289         return retVal;
290     }
291 
292     Filter* filterObj = reinterpret_cast<Filter*>(nativeObj);
293     filterObj->AddPara(pixelStretchPara);
294     retVal = CreateAniObject(env, ANI_UIEFFECT_FILTER, nullptr, reinterpret_cast<ani_long>(filterObj));
295 
296     return retVal;
297 }
298 
Blur(ani_env * env,ani_object obj,ani_double radius)299 ani_object AniEffect::Blur(ani_env* env, ani_object obj, ani_double radius)
300 {
301     ani_object retVal {};
302     auto filterBlurPara = std::make_shared<FilterBlurPara>();
303     filterBlurPara->SetRadius(static_cast<float>(radius));
304 
305     ani_long nativeObj;
306     if (ANI_OK != env->Object_GetFieldByName_Long(obj, "filterNativeObj", &nativeObj)) {
307         UIEFFECT_LOG_E("get generator filterNativeObj failed");
308         return retVal;
309     }
310 
311     Filter* filterObj = reinterpret_cast<Filter*>(nativeObj);
312     filterObj->AddPara(filterBlurPara);
313     retVal = CreateAniObject(env, ANI_UIEFFECT_FILTER, nullptr, reinterpret_cast<ani_long>(filterObj));
314 
315     return retVal;
316 }
317 } // namespace Rosen
318 } // namespace OHOS
319 
320 extern "C" {
ANI_Constructor(ani_vm * vm,uint32_t * result)321 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
322 {
323     ani_env* env;
324     if (vm->GetEnv(ANI_VERSION_1, &env) != ANI_OK) {
325         UIEFFECT_LOG_E("[ANI_Constructor] Unsupported ANI_VERSION_1");
326         return ANI_ERROR;
327     };
328     static const char* staticClassName = "L@ohos/graphics/uiEffect/uiEffect;";
329     ani_namespace uiEffectNamespace;
330     if (env->FindNamespace(staticClassName, &uiEffectNamespace) != ANI_OK) {
331         UIEFFECT_LOG_E("[ANI_Constructor] FindNamespace failed");
332         return ANI_ERROR;
333     };
334     std::array staticMethods = {
335         ani_native_function { "createEffect", nullptr, reinterpret_cast<void*>(OHOS::Rosen::AniEffect::CreateEffect) },
336         ani_native_function { "createBrightnessBlender", nullptr,
337             reinterpret_cast<void*>(OHOS::Rosen::AniEffect::CreateBrightnessBlender) },
338         ani_native_function { "createHdrBrightnessBlender", nullptr,
339             reinterpret_cast<void*>(OHOS::Rosen::AniEffect::CreateHdrBrightnessBlender) },
340         ani_native_function { "createFilter", nullptr, reinterpret_cast<void*>(OHOS::Rosen::AniEffect::CreateFilter) }
341     };
342     if (env->Namespace_BindNativeFunctions(uiEffectNamespace, staticMethods.data(), staticMethods.size()) != ANI_OK) {
343         UIEFFECT_LOG_E("[ANI_Constructor] Namespace_BindNativeFunctions failed");
344         return ANI_ERROR;
345     }
346     ani_status status = OHOS::Rosen::AniEffect::BindVisualEffectMethod(env);
347     if (status != ANI_OK) {
348         return status;
349     }
350     status = OHOS::Rosen::AniEffect::BindFilterMethod(env);
351     if (status != ANI_OK) {
352         return status;
353     }
354     *result = ANI_VERSION_1;
355     return ANI_OK;
356 }
357 }