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.h>
17 #include <cstdint>
18 #include <sys/stat.h>
19 #ifdef PIXEL_MAP_SUPPORTED
20 #include "pixel_map.h"
21 #include "pixel_map_ani.h"
22 #include "pixel_map_napi.h"
23
24 #endif
25 #include "core/common/ace_engine.h"
26 #include "frameworks/bridge/common/utils/engine_helper.h"
27
28 namespace {
createInt(ani_env * env,ani_int value)29 static ani_ref createInt(ani_env* env, ani_int value)
30 {
31 ani_class cls;
32 env->FindClass("Lstd/core/Int;", &cls);
33 ani_method ctor;
34 env->Class_FindMethod(cls, "<ctor>", ":V", &ctor);
35
36 ani_object rs;
37 env->Object_New(cls, ctor, &rs, value);
38 return static_cast<ani_object>(rs);
39 }
40 } // namespace
41
GetOptionsScale(ani_env * env,ani_object options,float & value)42 static bool GetOptionsScale(ani_env* env, ani_object options, float& value)
43 {
44 ani_boolean isUndefined;
45 env->Reference_IsUndefined(options, &isUndefined);
46 if (!isUndefined) {
47 return false;
48 }
49 static const char* className = "L@ohos/componentSnapshot/componentSnapshot/SnapshotOptions;";
50 ani_class cls;
51 if (ANI_OK != env->FindClass(className, &cls)) {
52 return false;
53 }
54 ani_ref propertyRef;
55 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "scale", &propertyRef)) {
56 return false;
57 }
58
59 ani_boolean isPropertyUndefined;
60 env->Reference_IsUndefined(propertyRef, &isPropertyUndefined);
61 if (!isPropertyUndefined) {
62 return false;
63 }
64 ani_double aniValue;
65 if (ANI_OK !=
66 env->Object_CallMethodByName_Double(static_cast<ani_object>(propertyRef), "doubleValue", nullptr, &aniValue)) {
67 return false;
68 }
69 value = static_cast<double>(aniValue);
70 return true;
71 }
72
GetOptionsWaitUntilRenderFinished(ani_env * env,ani_object options,bool & value)73 static bool GetOptionsWaitUntilRenderFinished(ani_env* env, ani_object options, bool& value)
74 {
75 ani_boolean isUndefined;
76 env->Reference_IsUndefined(options, &isUndefined);
77 if (!isUndefined) {
78 return false;
79 }
80 static const char* className = "L@ohos/componentSnapshot/componentSnapshot/SnapshotOptions;";
81 ani_class cls;
82 if (ANI_OK != env->FindClass(className, &cls)) {
83 return false;
84 }
85 ani_ref propertyRef;
86 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "waitUntilRenderFinished", &propertyRef)) {
87 return false;
88 }
89
90 ani_boolean isPropertyUndefined;
91 env->Reference_IsUndefined(propertyRef, &isPropertyUndefined);
92 if (!isPropertyUndefined) {
93 return false;
94 }
95 ani_boolean aniValue;
96 if (ANI_OK !=
97 env->Object_CallMethodByName_Boolean(static_cast<ani_object>(propertyRef), "unboxed", nullptr, &aniValue)) {
98 return false;
99 }
100 value = static_cast<bool>(aniValue);
101 return true;
102 }
103
GetDelay(ani_env * env,ani_object object,int32_t & value)104 static bool GetDelay(ani_env* env, ani_object object, int32_t& value)
105 {
106 ani_boolean isUndefined;
107 env->Reference_IsUndefined(object, &isUndefined);
108 if (!isUndefined) {
109 return false;
110 }
111 ani_int aniValue;
112 if (ANI_OK != env->Object_CallMethodByName_Int(object, "intValue", nullptr, &aniValue)) {
113 return false;
114 }
115 value = static_cast<int32_t>(aniValue);
116 return true;
117 }
118
GetCheckImageStatus(ani_env * env,ani_object object,bool & value)119 static bool GetCheckImageStatus(ani_env* env, ani_object object, bool& value)
120 {
121 ani_boolean isUndefined;
122 env->Reference_IsUndefined(object, &isUndefined);
123 if (!isUndefined) {
124 return false;
125 }
126 ani_boolean aniValue;
127 if (ANI_OK != env->Object_CallMethodByName_Boolean(object, "unboxed", nullptr, &aniValue)) {
128 return false;
129 }
130 value = static_cast<bool>(aniValue);
131 return true;
132 }
133
createFromBuilder(ani_env * env,ani_object builderObj,ani_object callbackObj,ani_object delay,ani_object checkImageStatus,ani_object options)134 static void createFromBuilder([[maybe_unused]] ani_env* env, ani_object builderObj, ani_object callbackObj,
135 ani_object delay, ani_object checkImageStatus, ani_object options)
136 {
137 auto biulder = [env, builderObj]() {
138 env->FunctionalObject_Call(static_cast<ani_fn_object>(builderObj), 0, nullptr, nullptr);
139 };
140 auto callback = [env, callbackObj](std::shared_ptr<OHOS::Media::PixelMap> pixmap, int32_t errCode,
141 std::function<void()> finishCallback) {
142 std::vector<ani_ref> vec;
143 vec.push_back(createInt(env, ani_int(errCode)));
144 if (errCode == 0) {
145 #ifdef PIXEL_MAP_SUPPORTED
146 ani_ref pixmapItem = OHOS::Media::PixelMapAni::CreateAniPixelMap(env, pixmap);
147 if (pixmapItem) {
148 vec.push_back(pixmapItem);
149 }
150 #endif
151 }
152 env->FunctionalObject_Call(static_cast<ani_fn_object>(callbackObj), vec.size(), vec.data(), nullptr);
153 };
154
155 OHOS::Ace::NG::SnapshotParam param;
156 GetDelay(env, delay, param.delay);
157 GetCheckImageStatus(env, checkImageStatus, param.checkImageStatus);
158 GetOptionsScale(env, options, param.options.scale);
159 GetOptionsWaitUntilRenderFinished(env, options, param.options.waitUntilRenderFinished);
160
161 auto delegate = OHOS::Ace::EngineHelper::GetCurrentDelegateSafely();
162 if (!delegate) {
163 return;
164 }
165 delegate->CreateSnapshot(biulder, callback, true, param);
166 }
167
ANI_Constructor(ani_vm * vm,uint32_t * result)168 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
169 {
170 ani_env* env;
171 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
172 return ANI_ERROR;
173 }
174
175 ani_namespace ns;
176 if (ANI_OK != env->FindNamespace("L@ohos/componentSnapshot/componentSnapshot;", &ns)) {
177 return ANI_ERROR;
178 }
179 std::array methods = {
180 ani_native_function { "createFromBuilder", nullptr, reinterpret_cast<void*>(createFromBuilder) },
181 };
182 if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
183 return ANI_ERROR;
184 }
185
186 *result = ANI_VERSION_1;
187 return ANI_OK;
188 }
189