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