• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "bridge/declarative_frontend/jsview/js_utils.h"
17 
18 #include "scope_manager/native_scope_manager.h"
19 
20 #include "base/image/drawing_lattice.h"
21 
22 #if !defined(PREVIEW)
23 #include <dlfcn.h>
24 #endif
25 #if !defined(WINDOWS_PLATFORM)
26 #include <regex.h>
27 #endif
28 
29 #ifdef PIXEL_MAP_SUPPORTED
30 #include "pixel_map.h"
31 #include "pixel_map_napi.h"
32 #endif
33 #include "napi/native_node_api.h"
34 
35 #include "base/image/pixel_map.h"
36 #include "base/log/ace_trace.h"
37 #include "base/want/want_wrap.h"
38 #include "bridge/common/utils/engine_helper.h"
39 #include "bridge/declarative_frontend/engine/js_converter.h"
40 #include "frameworks/bridge/common/utils/engine_helper.h"
41 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
42 #include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h"
43 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
44 #include "frameworks/bridge/js_frontend/engine/common/js_engine.h"
45 
46 namespace OHOS::Ace::Framework {
47 namespace {
48 #if defined(WINDOWS_PLATFORM)
49 constexpr char CHECK_REGEX_VALID[] = "__checkRegexValid__";
50 #endif
51 } // namespace
52 
53 #if !defined(PREVIEW)
CreatePixelMapFromNapiValue(const JSRef<JSVal> & obj,NativeEngine * localNativeEngine)54 RefPtr<PixelMap> CreatePixelMapFromNapiValue(const JSRef<JSVal>& obj, NativeEngine* localNativeEngine)
55 {
56     if (!obj->IsObject()) {
57         return nullptr;
58     }
59     NativeEngine* nativeEngine = nullptr;
60     if (localNativeEngine != nullptr) {
61         nativeEngine = localNativeEngine;
62     } else {
63         auto engine = EngineHelper::GetCurrentEngineSafely();
64         if (!engine) {
65             return nullptr;
66         }
67         nativeEngine = engine->GetNativeEngine();
68     }
69     if (nativeEngine == nullptr) {
70         return nullptr;
71     }
72 #ifdef USE_ARK_ENGINE
73     panda::Local<JsiValue> value = obj.Get().GetLocalHandle();
74 #endif
75     JSValueWrapper valueWrapper = value;
76 
77     ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
78     napi_value napiValue = nativeEngine->ValueToNapiValue(valueWrapper);
79 
80     PixelMapNapiEntry pixelMapNapiEntry = JsEngine::GetPixelMapNapiEntry();
81     if (!pixelMapNapiEntry) {
82         return nullptr;
83     }
84 
85     void* pixmapPtrAddr = pixelMapNapiEntry(reinterpret_cast<napi_env>(nativeEngine), napiValue);
86     if (pixmapPtrAddr == nullptr) {
87         return nullptr;
88     }
89     return PixelMap::CreatePixelMap(pixmapPtrAddr);
90 }
91 
GetPixelMapListFromAnimatedDrawable(JSRef<JSVal> obj,std::vector<RefPtr<PixelMap>> & pixelMaps,int32_t & duration,int32_t & iterations)92 bool GetPixelMapListFromAnimatedDrawable(
93     JSRef<JSVal> obj, std::vector<RefPtr<PixelMap>>& pixelMaps, int32_t& duration, int32_t& iterations)
94 {
95     return PixelMap::GetPxielMapListFromAnimatedDrawable(UnwrapNapiValue(obj), pixelMaps, duration, iterations);
96 }
97 
GetDrawablePixmap(JSRef<JSVal> obj)98 RefPtr<PixelMap> GetDrawablePixmap(JSRef<JSVal> obj)
99 {
100     return PixelMap::GetFromDrawable(UnwrapNapiValue(obj));
101 }
102 
CreateRSNodeFromNapiValue(JSRef<JSVal> obj)103 const std::shared_ptr<Rosen::RSNode> CreateRSNodeFromNapiValue(JSRef<JSVal> obj)
104 {
105     auto nodePtr = static_cast<std::shared_ptr<Rosen::RSNode>*>(UnwrapNapiValue(obj));
106     if (nodePtr == nullptr) {
107         return nullptr;
108     }
109     return *nodePtr;
110 }
111 
CreateWantWrapFromNapiValue(JSRef<JSVal> obj)112 RefPtr<OHOS::Ace::WantWrap> CreateWantWrapFromNapiValue(JSRef<JSVal> obj)
113 {
114     if (!obj->IsObject()) {
115         LOGE("invalid object when try CreateWantWrapFromNapiValue");
116         return nullptr;
117     }
118     auto engine = EngineHelper::GetCurrentEngine();
119     CHECK_NULL_RETURN(engine, nullptr);
120 
121     NativeEngine* nativeEngine = engine->GetNativeEngine();
122     CHECK_NULL_RETURN(nativeEngine, nullptr);
123 
124 #ifdef USE_ARK_ENGINE
125     panda::Local<JsiValue> value = obj.Get().GetLocalHandle();
126 #endif
127     JSValueWrapper valueWrapper = value;
128     ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
129     napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
130     return WantWrap::CreateWantWrap(reinterpret_cast<napi_env>(nativeEngine), nativeValue);
131 }
132 #endif
133 
CreateRSEffectFromNapiValue(JSRef<JSVal> obj)134 const Rosen::VisualEffect* CreateRSEffectFromNapiValue(JSRef<JSVal> obj)
135 {
136     auto visualEffectPtr = static_cast<Rosen::VisualEffect*>(UnwrapNapiValue(obj));
137     return visualEffectPtr;
138 }
139 
CreateRSFilterFromNapiValue(JSRef<JSVal> obj)140 const Rosen::Filter* CreateRSFilterFromNapiValue(JSRef<JSVal> obj)
141 {
142     auto filterPtr = static_cast<Rosen::Filter*>(UnwrapNapiValue(obj));
143     return filterPtr;
144 }
145 
CreateRSBrightnessBlenderFromNapiValue(JSRef<JSVal> obj)146 const Rosen::BrightnessBlender* CreateRSBrightnessBlenderFromNapiValue(JSRef<JSVal> obj)
147 {
148     auto blenderPtr = static_cast<Rosen::BrightnessBlender*>(UnwrapNapiValue(obj));
149     return blenderPtr;
150 }
151 
CreateDrawingColorFilter(JSRef<JSVal> obj)152 RefPtr<DrawingColorFilter> CreateDrawingColorFilter(JSRef<JSVal> obj)
153 {
154     return DrawingColorFilter::CreateDrawingColorFilter(UnwrapNapiValue(obj));
155 }
156 
CreateDrawingLattice(JSRef<JSVal> obj)157 RefPtr<DrawingLattice> CreateDrawingLattice(JSRef<JSVal> obj)
158 {
159     return DrawingLattice::CreateDrawingLattice(UnwrapNapiValue(obj));
160 }
161 
HandleDifferentRadius(JsiRef<JSVal> args)162 std::optional<NG::BorderRadiusProperty> HandleDifferentRadius(JsiRef<JSVal> args)
163 {
164     std::optional<NG::BorderRadiusProperty> prop = std::nullopt;
165     if (!args->IsObject()) {
166         return prop;
167     }
168 
169     std::optional<CalcDimension> radiusTopLeft;
170     std::optional<CalcDimension> radiusTopRight;
171     std::optional<CalcDimension> radiusBottomLeft;
172     std::optional<CalcDimension> radiusBottomRight;
173     JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
174     CalcDimension topLeft;
175     if (JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topLeft"), topLeft)) {
176         radiusTopLeft = topLeft;
177     }
178     CalcDimension topRight;
179     if (JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topRight"), topRight)) {
180         radiusTopRight = topRight;
181     }
182     CalcDimension bottomLeft;
183     if (JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomLeft"), bottomLeft)) {
184         radiusBottomLeft = bottomLeft;
185     }
186     CalcDimension bottomRight;
187     if (JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomRight"), bottomRight)) {
188         radiusBottomRight = bottomRight;
189     }
190     if (!radiusTopLeft.has_value() && !radiusTopRight.has_value() && !radiusBottomLeft.has_value() &&
191         !radiusBottomRight.has_value()) {
192         return prop;
193     }
194     NG::BorderRadiusProperty borderRadius;
195     if (radiusTopLeft.has_value()) {
196         borderRadius.radiusTopLeft = radiusTopLeft;
197     }
198     if (radiusTopRight.has_value()) {
199         borderRadius.radiusTopRight = radiusTopRight;
200     }
201     if (radiusBottomLeft.has_value()) {
202         borderRadius.radiusBottomLeft = radiusBottomLeft;
203     }
204     if (radiusBottomRight.has_value()) {
205         borderRadius.radiusBottomRight = radiusBottomRight;
206     }
207     borderRadius.multiValued = true;
208     prop = borderRadius;
209 
210     return prop;
211 }
212 
ParseBorderRadiusAttr(JsiRef<JSVal> args)213 std::optional<NG::BorderRadiusProperty> ParseBorderRadiusAttr(JsiRef<JSVal> args)
214 {
215     std::optional<NG::BorderRadiusProperty> prop = std::nullopt;
216     CalcDimension radiusDim;
217     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
218         return prop;
219     }
220     if (JSViewAbstract::ParseJsDimensionVpNG(args, radiusDim)) {
221         NG::BorderRadiusProperty borderRadius;
222         borderRadius.SetRadius(radiusDim);
223         borderRadius.multiValued = false;
224         prop = borderRadius;
225     } else if (args->IsObject()) {
226         prop = HandleDifferentRadius(args);
227     }
228     return prop;
229 }
230 
231 // When the api version >= 11, it is disable event version.
IsDisableEventVersion()232 bool IsDisableEventVersion()
233 {
234     return Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN);
235 }
236 
ParseTextShadowFromShadowObject(const JSRef<JSVal> & shadowObject,std::vector<Shadow> & shadows)237 void ParseTextShadowFromShadowObject(const JSRef<JSVal>& shadowObject, std::vector<Shadow>& shadows)
238 {
239     if (!shadowObject->IsNumber() && !shadowObject->IsObject() && !shadowObject->IsArray()) {
240         return;
241     }
242     if (!shadowObject->IsArray()) {
243         Shadow shadow;
244         if (!JSViewAbstract::ParseShadowProps(shadowObject, shadow)) {
245             return;
246         }
247         shadows.push_back(shadow);
248         return;
249     }
250     JSRef<JSArray> params = JSRef<JSArray>::Cast(shadowObject);
251     auto shadowLength = params->Length();
252     for (size_t i = 0; i < shadowLength; ++i) {
253         auto shadowJsVal = params->GetValueAt(i);
254         Shadow shadow;
255         if (!JSViewAbstract::ParseShadowProps(shadowJsVal, shadow)) {
256             continue;
257         }
258         shadows.push_back(shadow);
259     }
260 }
261 
262 #ifdef PIXEL_MAP_SUPPORTED
ConvertPixmap(const RefPtr<PixelMap> & pixelMap)263 JSRef<JSVal> ConvertPixmap(const RefPtr<PixelMap>& pixelMap)
264 {
265     ContainerScope scope(Container::CurrentIdSafely());
266     auto engine = EngineHelper::GetCurrentEngine();
267     CHECK_NULL_RETURN(engine, {});
268     NativeEngine* nativeEngine = engine->GetNativeEngine();
269     auto* env = reinterpret_cast<napi_env>(nativeEngine);
270     napi_value napiValue = OHOS::Media::PixelMapNapi::CreatePixelMap(env, pixelMap->GetPixelMapSharedPtr());
271     return JsConverter::ConvertNapiValueToJsVal(napiValue);
272 }
273 #endif
274 
275 #ifdef PIXEL_MAP_SUPPORTED
ConvertPixmapNapi(const RefPtr<PixelMap> & pixelMap)276 napi_value ConvertPixmapNapi(const RefPtr<PixelMap>& pixelMap)
277 {
278     auto engine = EngineHelper::GetCurrentEngine();
279     CHECK_NULL_RETURN(engine, {});
280     NativeEngine* nativeEngine = engine->GetNativeEngine();
281     auto* env = reinterpret_cast<napi_env>(nativeEngine);
282     napi_value napiValue = OHOS::Media::PixelMapNapi::CreatePixelMap(env, pixelMap->GetPixelMapSharedPtr());
283     return napiValue;
284 }
285 #endif
286 
IsDrawable(const JSRef<JSVal> & jsValue)287 bool IsDrawable(const JSRef<JSVal>& jsValue)
288 {
289     if (!jsValue->IsObject()) {
290         return false;
291     }
292     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
293     if (jsObj->IsUndefined()) {
294         return false;
295     }
296 
297     // if jsObject has function getPixelMap, it's a DrawableDescriptor object
298     JSRef<JSVal> func = jsObj->GetProperty("getPixelMap");
299     return (!func->IsNull() && func->IsFunction());
300 }
301 
CheckRegexValid(const std::string & pattern)302 bool CheckRegexValid(const std::string& pattern)
303 {
304 #if !defined(WINDOWS_PLATFORM)
305     regex_t regex;
306     // compile regex
307     const char* patternPtr = pattern.c_str();
308     int32_t ret = regcomp(&regex, patternPtr, REG_EXTENDED);
309     if (ret != 0) {
310         regfree(&regex);
311         return false;
312     }
313     regfree(&regex);
314     return true;
315 #else
316     auto engine = EngineHelper::GetCurrentEngine();
317     CHECK_NULL_RETURN(engine, false);
318     NativeEngine* nativeEngine = engine->GetNativeEngine();
319     CHECK_NULL_RETURN(nativeEngine, false);
320     auto env = reinterpret_cast<napi_env>(nativeEngine);
321     napi_value global;
322     napi_status ret = napi_get_global(env, &global);
323     if (ret != napi_ok) {
324         return false;
325     }
326     napi_value checkRegexValid;
327     ret = napi_get_named_property(env, global, CHECK_REGEX_VALID, &checkRegexValid);
328     if (ret != napi_ok) {
329         return false;
330     }
331     // create napi string
332     napi_value argv[1];
333     napi_create_string_utf8(env, pattern.c_str(), pattern.length(), &argv[0]);
334     napi_value result;
335     napi_call_function(env, nullptr, checkRegexValid, 1, argv, &result);
336     bool isValid = false;
337     napi_get_value_bool(env, result, &isValid);
338     return isValid;
339 #endif
340 }
341 
GetCurrentEnv()342 napi_env GetCurrentEnv()
343 {
344     auto engine = EngineHelper::GetCurrentEngine();
345     if (!engine) {
346         return nullptr;
347     }
348     NativeEngine* nativeEngine = engine->GetNativeEngine();
349     if (!nativeEngine) {
350         return nullptr;
351     }
352     return reinterpret_cast<napi_env>(nativeEngine);
353 }
354 
UnwrapNapiValue(const JSRef<JSVal> & obj)355 void* UnwrapNapiValue(const JSRef<JSVal>& obj)
356 {
357 #ifdef ENABLE_ROSEN_BACKEND
358     if (!obj->IsObject()) {
359         LOGE("info[0] is not an object when try CreateFromNapiValue");
360         return nullptr;
361     }
362     auto engine = EngineHelper::GetCurrentEngine();
363     CHECK_NULL_RETURN(engine, nullptr);
364     auto nativeEngine = engine->GetNativeEngine();
365     CHECK_NULL_RETURN(nativeEngine, nullptr);
366 #ifdef USE_ARK_ENGINE
367     panda::Local<JsiValue> value = obj.Get().GetLocalHandle();
368 #endif
369     JSValueWrapper valueWrapper = value;
370 
371     ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
372     napi_value napiValue = nativeEngine->ValueToNapiValue(valueWrapper);
373     auto env = reinterpret_cast<napi_env>(nativeEngine);
374     napi_valuetype valueType = napi_undefined;
375     napi_typeof(env, napiValue, &valueType);
376     if (valueType != napi_object) {
377         LOGE("napiValue is not napi_object");
378         return nullptr;
379     }
380     void* objectNapi = nullptr;
381     napi_unwrap(env, napiValue, &objectNapi);
382     return objectNapi;
383 #else
384     return nullptr;
385 #endif
386 }
387 } // namespace OHOS::Ace::Framework
388