1 /*
2 * Copyright (c) 2024 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/engine/jsi/nativeModule/arkts_native_utils_bridge.h"
17
18 #include "jsnapi_expo.h"
19
20 #include "base/geometry/calc_dimension.h"
21 #include "base/geometry/dimension.h"
22 #include "base/memory/ace_type.h"
23 #include "frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
24
25 namespace OHOS::Ace::NG {
26 constexpr uint32_t MAX_COLOR_ARRAY_COUNT = 4;
27 constexpr uint32_t ARRAY_INDEX_RED = 0;
28 constexpr uint32_t ARRAY_INDEX_GREEN = 1;
29 constexpr uint32_t ARRAY_INDEX_BLUE = 2;
30 constexpr uint32_t ARRAY_INDEX_ALPHA = 3;
31 constexpr uint32_t ARRAY_SIZE = 2;
32
CreateNativeWeakRef(ArkUIRuntimeCallInfo * runtimeCallInfo)33 ArkUINativeModuleValue NativeUtilsBridge::CreateNativeWeakRef(ArkUIRuntimeCallInfo* runtimeCallInfo)
34 {
35 EcmaVM* vm = runtimeCallInfo->GetVM();
36 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
37 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
38 if (firstArg.IsEmpty() || !firstArg->IsNativePointer(vm)) {
39 return panda::JSValueRef::Undefined(vm);
40 }
41 auto refPtr = AceType::Claim(reinterpret_cast<AceType*>(firstArg->ToNativePointer(vm)->Value()));
42 return NativeUtilsBridge::CreateWeakRef(vm, refPtr);
43 }
44
CreateWeakRef(EcmaVM * vm,const RefPtr<AceType> & ref)45 ArkUINativeModuleValue NativeUtilsBridge::CreateWeakRef(EcmaVM* vm, const RefPtr<AceType>& ref)
46 {
47 CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
48 CHECK_NULL_RETURN(ref, panda::JSValueRef::Undefined(vm));
49 auto* weak = new NativeWeakRef(AceType::RawPtr(ref));
50 auto nativeWeakRef = panda::ObjectRef::New(vm);
51 nativeWeakRef->SetNativePointerFieldCount(vm, 1);
52 nativeWeakRef->SetConcurrentNativePointerField(vm, 0, weak, &DestructorInterceptor<NativeWeakRef>);
53 nativeWeakRef->Set(vm, panda::StringRef::NewFromUtf8(vm, "invalid"),
54 panda::FunctionRef::New(const_cast<panda::EcmaVM*>(vm), NativeUtilsBridge::WeakRefInvalid));
55 nativeWeakRef->Set(vm, panda::StringRef::NewFromUtf8(vm, "getNativeHandle"),
56 panda::FunctionRef::New(const_cast<panda::EcmaVM*>(vm), NativeUtilsBridge::GetNativeHandleForWeak));
57 nativeWeakRef->Set(vm, panda::StringRef::NewFromUtf8(vm, "upgrade"),
58 panda::FunctionRef::New(const_cast<panda::EcmaVM*>(vm), NativeUtilsBridge::Upgrade));
59 return nativeWeakRef;
60 }
61
CreateStrongRef(EcmaVM * vm,const RefPtr<AceType> & ref)62 ArkUINativeModuleValue NativeUtilsBridge::CreateStrongRef(EcmaVM* vm, const RefPtr<AceType>& ref)
63 {
64 CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
65 CHECK_NULL_RETURN(ref, panda::JSValueRef::Undefined(vm));
66 auto* nativeRef = new NativeStrongRef(ref);
67 auto nativeStrongRef = panda::ObjectRef::New(vm);
68 nativeStrongRef->SetNativePointerFieldCount(vm, 1);
69 nativeStrongRef->SetConcurrentNativePointerField(vm, 0, nativeRef, &DestructorInterceptor<NativeStrongRef>);
70 nativeStrongRef->Set(vm, panda::StringRef::NewFromUtf8(vm, "getNativeHandle"),
71 panda::FunctionRef::New(const_cast<panda::EcmaVM*>(vm), NativeUtilsBridge::GetNativeHandleForStrong));
72 nativeStrongRef->Set(vm, panda::StringRef::NewFromUtf8(vm, "dispose"),
73 panda::FunctionRef::New(const_cast<panda::EcmaVM*>(vm), NativeUtilsBridge::Dispose));
74 return nativeStrongRef;
75 }
76
CreateNativeStrongRef(ArkUIRuntimeCallInfo * runtimeCallInfo)77 ArkUINativeModuleValue NativeUtilsBridge::CreateNativeStrongRef(ArkUIRuntimeCallInfo* runtimeCallInfo)
78 {
79 EcmaVM* vm = runtimeCallInfo->GetVM();
80 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
81 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
82 if (firstArg.IsEmpty() || !firstArg->IsNativePointer(vm)) {
83 return panda::JSValueRef::Undefined(vm);
84 }
85 auto refPtr = AceType::Claim(reinterpret_cast<AceType*>(firstArg->ToNativePointer(vm)->Value()));
86 return NativeUtilsBridge::CreateStrongRef(vm, refPtr);
87 }
88
WeakRefInvalid(ArkUIRuntimeCallInfo * runtimeCallInfo)89 ArkUINativeModuleValue NativeUtilsBridge::WeakRefInvalid(ArkUIRuntimeCallInfo* runtimeCallInfo)
90 {
91 EcmaVM* vm = runtimeCallInfo->GetVM();
92 CHECK_NULL_RETURN(vm, panda::BooleanRef::New(vm, true));
93 auto* weak = GetPointerField<NativeWeakRef>(runtimeCallInfo);
94 if (weak != nullptr) {
95 return panda::BooleanRef::New(vm, weak->Invalid());
96 }
97 return panda::BooleanRef::New(vm, true);
98 }
99
GetNativeHandleForStrong(ArkUIRuntimeCallInfo * runtimeCallInfo)100 ArkUINativeModuleValue NativeUtilsBridge::GetNativeHandleForStrong(ArkUIRuntimeCallInfo* runtimeCallInfo)
101 {
102 EcmaVM* vm = runtimeCallInfo->GetVM();
103 CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
104 auto* strong = GetPointerField<NativeStrongRef>(runtimeCallInfo);
105 if (strong != nullptr && strong->strongRef) {
106 return panda::NativePointerRef::New(vm, strong->RawPtr());
107 }
108 return panda::JSValueRef::Undefined(vm);
109 }
110
GetNativeHandleForWeak(ArkUIRuntimeCallInfo * runtimeCallInfo)111 ArkUINativeModuleValue NativeUtilsBridge::GetNativeHandleForWeak(ArkUIRuntimeCallInfo* runtimeCallInfo)
112 {
113 EcmaVM* vm = runtimeCallInfo->GetVM();
114 CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
115 auto* weak = GetPointerField<NativeWeakRef>(runtimeCallInfo);
116 if (weak != nullptr && !weak->Invalid()) {
117 return panda::NativePointerRef::New(vm, weak->rawPtr);
118 }
119 return panda::JSValueRef::Undefined(vm);
120 }
121
Upgrade(ArkUIRuntimeCallInfo * runtimeCallInfo)122 ArkUINativeModuleValue NativeUtilsBridge::Upgrade(ArkUIRuntimeCallInfo* runtimeCallInfo)
123 {
124 EcmaVM* vm = runtimeCallInfo->GetVM();
125 CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
126 auto* weak = GetPointerField<NativeWeakRef>(runtimeCallInfo);
127 if (weak != nullptr) {
128 auto ref = weak->weakRef.Upgrade();
129 return NativeUtilsBridge::CreateStrongRef(vm, ref);
130 }
131 return panda::JSValueRef::Undefined(vm);
132 }
133
Dispose(ArkUIRuntimeCallInfo * runtimeCallInfo)134 ArkUINativeModuleValue NativeUtilsBridge::Dispose(ArkUIRuntimeCallInfo* runtimeCallInfo)
135 {
136 EcmaVM* vm = runtimeCallInfo->GetVM();
137 auto* ptr = GetPointerField<NativeStrongRef>(runtimeCallInfo);
138 if (ptr != nullptr) {
139 ptr->strongRef.Reset();
140 return panda::JSValueRef::Undefined(vm);
141 }
142 return panda::JSValueRef::Undefined(vm);
143 }
144
ParseResourceColor(ArkUIRuntimeCallInfo * runtimeCallInfo)145 ArkUINativeModuleValue NativeUtilsBridge::ParseResourceColor(ArkUIRuntimeCallInfo* runtimeCallInfo)
146 {
147 EcmaVM* vm = runtimeCallInfo->GetVM();
148 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
149 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
150 if (firstArg.IsEmpty() || !firstArg->IsObject(vm)) {
151 return panda::JSValueRef::Undefined(vm);
152 }
153 Color color;
154 if (!ArkTSUtils::ParseJsColorFromResource(vm, firstArg, color)) {
155 return panda::JSValueRef::Undefined(vm);
156 }
157 Local<panda::ArrayRef> chanels = panda::ArrayRef::New(vm, MAX_COLOR_ARRAY_COUNT);
158 panda::ArrayRef::SetValueAt(vm, chanels, ARRAY_INDEX_RED, panda::NumberRef::New(vm, color.GetRed()));
159 panda::ArrayRef::SetValueAt(vm, chanels, ARRAY_INDEX_GREEN, panda::NumberRef::New(vm, color.GetGreen()));
160 panda::ArrayRef::SetValueAt(vm, chanels, ARRAY_INDEX_BLUE, panda::NumberRef::New(vm, color.GetBlue()));
161 panda::ArrayRef::SetValueAt(vm, chanels, ARRAY_INDEX_ALPHA, panda::NumberRef::New(vm, color.GetAlpha()));
162 return chanels;
163 }
164
BlendColor(ArkUIRuntimeCallInfo * runtimeCallInfo)165 ArkUINativeModuleValue NativeUtilsBridge::BlendColor(ArkUIRuntimeCallInfo* runtimeCallInfo)
166 {
167 EcmaVM* vm = runtimeCallInfo->GetVM();
168 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
169 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
170 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1);
171
172 if (firstArg.IsEmpty() || !firstArg->IsNumber() || secondArg.IsEmpty() || !secondArg->IsNumber()) {
173 return panda::JSValueRef::Undefined(vm);
174 }
175 Color color;
176 Color overlayColor;
177 if (!ArkTSUtils::ParseJsColor(vm, firstArg, color) || !ArkTSUtils::ParseJsColor(vm, secondArg, overlayColor)) {
178 return panda::JSValueRef::Undefined(vm);
179 }
180 auto blendColor = color.BlendColor(overlayColor);
181 Local<panda::ArrayRef> chanels = panda::ArrayRef::New(vm, MAX_COLOR_ARRAY_COUNT);
182 panda::ArrayRef::SetValueAt(vm, chanels, ARRAY_INDEX_RED, panda::NumberRef::New(vm, blendColor.GetRed()));
183 panda::ArrayRef::SetValueAt(vm, chanels, ARRAY_INDEX_GREEN, panda::NumberRef::New(vm, blendColor.GetGreen()));
184 panda::ArrayRef::SetValueAt(vm, chanels, ARRAY_INDEX_BLUE, panda::NumberRef::New(vm, blendColor.GetBlue()));
185 panda::ArrayRef::SetValueAt(vm, chanels, ARRAY_INDEX_ALPHA, panda::NumberRef::New(vm, blendColor.GetAlpha()));
186 return chanels;
187 }
188
ResoureToLengthMetrics(ArkUIRuntimeCallInfo * runtimeCallInfo)189 ArkUINativeModuleValue NativeUtilsBridge::ResoureToLengthMetrics(ArkUIRuntimeCallInfo* runtimeCallInfo)
190 {
191 EcmaVM* vm = runtimeCallInfo->GetVM();
192 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
193 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
194 if (!firstArg->IsObject(vm)) {
195 return panda::JSValueRef::Undefined(vm);
196 }
197 CalcDimension result;
198 ArkTSUtils::ParseJsDimensionFromResourceNG(vm, firstArg, DimensionUnit::VP, result);
199 Local<panda::ArrayRef> length = panda::ArrayRef::New(vm, ARRAY_SIZE);
200 panda::ArrayRef::SetValueAt(vm, length, 0, panda::NumberRef::New(vm, result.Value()));
201 panda::ArrayRef::SetValueAt(vm, length, 1, panda::NumberRef::New(vm, static_cast<int32_t>(result.Unit())));
202 return length;
203 }
204 } // namespace OHOS::Ace::NG
205