1 /*
2 * Copyright (c) 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 "js_drawable_descriptor.h"
17
18 #include "drawable_descriptor.h"
19 #include "interfaces/inner_api/drawable_descriptor/drawable_descriptor.h"
20 #include "js_native_api.h"
21 #include "js_native_api_types.h"
22 #include "napi/native_api.h"
23 #include "napi/native_common.h"
24 #include "napi/native_node_api.h"
25 #ifndef PREVIEW
26 #include "pixel_map_napi.h"
27 #endif
28 #include "base/utils/utils.h"
29
30 namespace {
31 constexpr char DRAWABLE_BASE[] = "DrawableDescriptor";
32 constexpr char DRAWABLE_LAYERED[] = "LayeredDrawableDescriptor";
33 } // namespace
34
35 namespace OHOS::Ace::Napi {
36 thread_local napi_ref JsDrawableDescriptor::baseConstructor_;
37 thread_local napi_ref JsDrawableDescriptor::layeredConstructor_;
38
Constructor(napi_env env,napi_callback_info info)39 napi_value JsDrawableDescriptor::Constructor(napi_env env, napi_callback_info info)
40 {
41 napi_escapable_handle_scope scope = nullptr;
42 napi_open_escapable_handle_scope(env, &scope);
43 napi_value thisVar = nullptr;
44 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
45 // create JsDrawable
46 auto* drawable = new DrawableDescriptor;
47 // wrap to napi_value
48 napi_wrap(env, thisVar, drawable, Destructor, nullptr, nullptr);
49 napi_escape_handle(env, scope, thisVar, &thisVar);
50 napi_close_escapable_handle_scope(env, scope);
51 return thisVar;
52 }
53
Destructor(napi_env,void * data,void *)54 void JsDrawableDescriptor::Destructor(napi_env /* env */, void* data, void* /* hint */)
55 {
56 auto* field = reinterpret_cast<DrawableDescriptor*>(data);
57 delete field;
58 }
59
InitDrawable(napi_env env)60 napi_value JsDrawableDescriptor::InitDrawable(napi_env env)
61 {
62 napi_value cons = nullptr;
63 napi_property_descriptor baseDes[] = {
64 DECLARE_NAPI_FUNCTION("getPixelMap", GetPixelMap),
65 };
66 NAPI_CALL(env, napi_define_class(env, DRAWABLE_BASE, NAPI_AUTO_LENGTH, Constructor, nullptr,
67 sizeof(baseDes) / sizeof(napi_property_descriptor), baseDes, &cons));
68 NAPI_CALL(env, napi_create_reference(env, cons, 1, &baseConstructor_));
69 return cons;
70 }
71
InitLayeredDrawable(napi_env env)72 napi_value JsDrawableDescriptor::InitLayeredDrawable(napi_env env)
73 {
74 napi_value cons = nullptr;
75 napi_property_descriptor layeredDes[] = {
76 DECLARE_NAPI_FUNCTION("getPixelMap", GetPixelMap),
77 DECLARE_NAPI_FUNCTION("getForeground", GetForeground),
78 DECLARE_NAPI_FUNCTION("getBackground", GetBackground),
79 DECLARE_NAPI_FUNCTION("getMask", GetMask),
80 DECLARE_NAPI_STATIC_FUNCTION("getMaskClipPath", GetMaskClipPath),
81 };
82 NAPI_CALL(env, napi_define_class(env, DRAWABLE_LAYERED, NAPI_AUTO_LENGTH, Constructor, nullptr,
83 sizeof(layeredDes) / sizeof(napi_property_descriptor), layeredDes, &cons));
84 NAPI_CALL(env, napi_create_reference(env, cons, 1, &layeredConstructor_));
85 return cons;
86 }
87
ToNapi(napi_env env,DrawableDescriptor * drawable,DrawableDescriptor::DrawableType type)88 napi_value JsDrawableDescriptor::ToNapi(
89 napi_env env, DrawableDescriptor* drawable, DrawableDescriptor::DrawableType type)
90 {
91 if (!drawable) {
92 return nullptr;
93 }
94 if (!baseConstructor_ || !layeredConstructor_) {
95 // init js class constructor by importing module manually
96 napi_value globalValue;
97 napi_get_global(env, &globalValue);
98 napi_value func;
99 napi_get_named_property(env, globalValue, "requireNapi", &func);
100
101 napi_value module;
102 napi_create_string_utf8(env, MODULE_NAME, NAPI_AUTO_LENGTH, &module);
103 napi_value returnValue;
104 napi_call_function(env, globalValue, func, 1, &module, &returnValue);
105 }
106
107 napi_value constructor = nullptr;
108 napi_value result = nullptr;
109 napi_status status;
110 switch (type) {
111 case DrawableDescriptor::DrawableType::LAYERED:
112 status = napi_get_reference_value(env, layeredConstructor_, &constructor);
113 break;
114 case DrawableDescriptor::DrawableType::BASE:
115 status = napi_get_reference_value(env, baseConstructor_, &constructor);
116 break;
117 default:
118 status = napi_status::napi_invalid_arg;
119 break;
120 }
121 if (status == napi_status::napi_ok) {
122 NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
123 NAPI_CALL(env, napi_wrap(env, result, drawable, Destructor, nullptr, nullptr));
124 } else {
125 HILOG_INFO("create reference failed, drawable constructor is null");
126 }
127
128 return result;
129 }
130
GetPixelMap(napi_env env,napi_callback_info info)131 napi_value JsDrawableDescriptor::GetPixelMap(napi_env env, napi_callback_info info)
132 {
133 napi_escapable_handle_scope scope = nullptr;
134 napi_open_escapable_handle_scope(env, &scope);
135 napi_value thisVar = nullptr;
136 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
137 void* native = nullptr;
138 napi_unwrap(env, thisVar, &native);
139 auto* drawable = reinterpret_cast<DrawableDescriptor*>(native);
140 auto pixmap = drawable->GetPixelMap();
141
142 napi_value result = Media::PixelMapNapi::CreatePixelMap(env, pixmap);
143 napi_escape_handle(env, scope, result, &result);
144 napi_close_escapable_handle_scope(env, scope);
145 return result;
146 }
147
GetForeground(napi_env env,napi_callback_info info)148 napi_value JsDrawableDescriptor::GetForeground(napi_env env, napi_callback_info info)
149 {
150 napi_escapable_handle_scope scope = nullptr;
151 napi_open_escapable_handle_scope(env, &scope);
152 napi_value thisVar = nullptr;
153 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
154 void* native = nullptr;
155 napi_unwrap(env, thisVar, &native);
156 auto* drawable = reinterpret_cast<LayeredDrawableDescriptor*>(native);
157 if (!drawable) {
158 return nullptr;
159 }
160
161 auto foreground = drawable->GetForeground();
162 napi_value result = ToNapi(env, foreground.release(), DrawableDescriptor::DrawableType::BASE);
163 napi_escape_handle(env, scope, result, &result);
164 napi_close_escapable_handle_scope(env, scope);
165 return result;
166 }
167
GetBackground(napi_env env,napi_callback_info info)168 napi_value JsDrawableDescriptor::GetBackground(napi_env env, napi_callback_info info)
169 {
170 napi_escapable_handle_scope scope = nullptr;
171 napi_open_escapable_handle_scope(env, &scope);
172 napi_value thisVar = nullptr;
173 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
174 void* native = nullptr;
175 napi_unwrap(env, thisVar, &native);
176 auto* drawable = reinterpret_cast<LayeredDrawableDescriptor*>(native);
177 if (!drawable) {
178 return nullptr;
179 }
180
181 auto background = drawable->GetBackground();
182 napi_value result = ToNapi(env, background.release(), DrawableDescriptor::DrawableType::BASE);
183 napi_escape_handle(env, scope, result, &result);
184 napi_close_escapable_handle_scope(env, scope);
185 return result;
186 }
187
GetMask(napi_env env,napi_callback_info info)188 napi_value JsDrawableDescriptor::GetMask(napi_env env, napi_callback_info info)
189 {
190 napi_escapable_handle_scope scope = nullptr;
191 napi_open_escapable_handle_scope(env, &scope);
192 napi_value thisVar = nullptr;
193 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
194 void* native = nullptr;
195 napi_unwrap(env, thisVar, &native);
196 auto* drawable = reinterpret_cast<LayeredDrawableDescriptor*>(native);
197 if (!drawable) {
198 return nullptr;
199 }
200
201 auto mask = drawable->GetMask();
202 napi_value result = ToNapi(env, mask.release(), DrawableDescriptor::DrawableType::BASE);
203 napi_escape_handle(env, scope, result, &result);
204 napi_close_escapable_handle_scope(env, scope);
205 return result;
206 }
207
GetMaskClipPath(napi_env env,napi_callback_info info)208 napi_value JsDrawableDescriptor::GetMaskClipPath(napi_env env, napi_callback_info info)
209 {
210 auto path = OHOS::Ace::Napi::LayeredDrawableDescriptor::GetStaticMaskClipPath();
211 napi_value result = nullptr;
212 if (napi_ok != napi_create_string_utf8(env, path.c_str(), NAPI_AUTO_LENGTH, &result)) {
213 HILOG_INFO("JsDrawableDescriptor Failed");
214 }
215 return result;
216 }
217
Export(napi_env env,napi_value exports)218 napi_value JsDrawableDescriptor::Export(napi_env env, napi_value exports)
219 {
220 // export base class
221 napi_value cons = InitDrawable(env);
222 NAPI_CALL(env, napi_set_named_property(env, exports, DRAWABLE_BASE, cons));
223
224 // export child class
225 cons = InitLayeredDrawable(env);
226 NAPI_CALL(env, napi_set_named_property(env, exports, DRAWABLE_LAYERED, cons));
227 return exports;
228 }
229 } // namespace OHOS::Ace::Napi
230