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