• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_theme_bridge.h"
17 
18 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_common_bridge.h"
19 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
20 #include "core/components_ng/syntax/with_theme_node.h"
21 #include "core/components_ng/token_theme/token_theme_storage.h"
22 
23 namespace OHOS::Ace::NG {
Create(ArkUIRuntimeCallInfo * runtimeCallInfo)24 ArkUINativeModuleValue ThemeBridge::Create(ArkUIRuntimeCallInfo* runtimeCallInfo)
25 {
26     EcmaVM* vm = runtimeCallInfo->GetVM();
27     CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
28     Local<JSValueRef> themeScopeIdArg = runtimeCallInfo->GetCallArgRef(0);
29     Local<JSValueRef> themeIdArg = runtimeCallInfo->GetCallArgRef(1);
30     Local<JSValueRef> colorsArg = runtimeCallInfo->GetCallArgRef(2); // 2: colorsArg index
31     Local<JSValueRef> colorModeArg = runtimeCallInfo->GetCallArgRef(3); // 3: colorModeArg index
32     Local<JSValueRef> onThemeScopeDestroyArg = runtimeCallInfo->GetCallArgRef(4); // 4: destroy callback arg index
33 
34     // handle theme scope id argument
35     if (!themeScopeIdArg->IsNumber()) {
36         return panda::JSValueRef::Undefined(vm);
37     }
38     ArkUI_Int32 themeScopeId = static_cast<ArkUI_Int32>(themeScopeIdArg->Int32Value(vm));
39 
40     // handle theme id argument
41     if (!themeIdArg->IsNumber()) {
42         return panda::JSValueRef::Undefined(vm);
43     }
44     ArkUI_Int32 themeId = static_cast<ArkUI_Int32>(themeIdArg->Int32Value(vm));
45 
46     // handle colors argument
47     if (!colorsArg->IsArray(vm)) {
48         return panda::JSValueRef::Undefined(vm);
49     }
50     std::vector<ArkUI_Uint32> colors;
51     if (!HandleThemeColorsArg(vm, colorsArg, colors)) {
52         return panda::JSValueRef::Undefined(vm);
53     }
54 
55     // handle color mode argument
56     if (!colorModeArg->IsNumber()) {
57         return panda::JSValueRef::Undefined(vm);
58     }
59     ArkUI_Int32 colorMode = static_cast<ArkUI_Int32>(colorModeArg->Int32Value(vm));
60 
61     // handle on theme scope destroy argument
62     if (!onThemeScopeDestroyArg->IsFunction(vm)) {
63         return panda::JSValueRef::Undefined(vm);
64     }
65     auto obj = onThemeScopeDestroyArg->ToObject(vm);
66     auto containerId = Container::CurrentId();
67     panda::Local<panda::FunctionRef> func = obj;
68     std::function<void()> onThemeScopeDestroy = [vm, func = panda::CopyableGlobal(vm, func), containerId]() {
69         panda::LocalScope pandaScope(vm);
70         panda::TryCatch trycatch(vm);
71         ContainerScope scope(containerId);
72         func->Call(vm, func.ToLocal(), nullptr, 0);
73     };
74 
75     // execute C-API
76     auto themeModifier = GetArkUINodeModifiers()->getThemeModifier();
77     auto theme = themeModifier->createTheme(themeId, colors.data(), colorMode);
78     CHECK_NULL_RETURN(theme, panda::NativePointerRef::New(vm, nullptr));
79     ArkUINodeHandle node = themeModifier->getWithThemeNode(themeScopeId);
80     if (!node) {
81         node = CreateWithThemeNode(themeScopeId);
82     }
83     themeModifier->createThemeScope(node, theme);
84     themeModifier->setOnThemeScopeDestroy(node, reinterpret_cast<void*>(&onThemeScopeDestroy));
85 
86     return panda::JSValueRef::Undefined(vm);
87 }
88 
HandleThemeColorsArg(const EcmaVM * vm,const Local<JSValueRef> & colorsArg,std::vector<ArkUI_Uint32> & colors)89 bool ThemeBridge::HandleThemeColorsArg(const EcmaVM* vm, const Local<JSValueRef>& colorsArg,
90     std::vector<ArkUI_Uint32>& colors)
91 {
92     auto basisTheme = TokenThemeStorage::GetInstance()->GetDefaultTheme();
93     if (!basisTheme) {
94         basisTheme = TokenThemeStorage::GetInstance()->ObtainSystemTheme();
95     }
96     if (!basisTheme) {
97         return false;
98     }
99     for (size_t i = 0; i < TokenColors::TOTAL_NUMBER; i++) {
100         Color color;
101         auto colorParams = panda::ArrayRef::GetValueAt(vm, colorsArg, i);
102         if (!ArkTSUtils::ParseJsColorAlpha(vm, colorParams, color)) {
103             color = basisTheme->Colors()->GetByIndex(i);
104         }
105         colors.push_back(static_cast<ArkUI_Uint32>(color.GetValue()));
106     }
107     return true;
108 }
109 
CreateWithThemeNode(ArkUI_Int32 themeScopeId)110 ArkUINodeHandle ThemeBridge::CreateWithThemeNode(ArkUI_Int32 themeScopeId)
111 {
112     auto themeModifier = GetArkUINodeModifiers()->getThemeModifier();
113     auto node = themeModifier->createWithThemeNode(themeScopeId);
114     RefPtr<WithThemeNode> withThemeNode = AceType::Claim(reinterpret_cast<WithThemeNode*>(node));
115     withThemeNode->DecRefCount();
116     ViewStackProcessor::GetInstance()->Push(withThemeNode);
117     return node;
118 }
119 
Pop(ArkUIRuntimeCallInfo * runtimeCallInfo)120 ArkUINativeModuleValue ThemeBridge::Pop(ArkUIRuntimeCallInfo* runtimeCallInfo)
121 {
122     EcmaVM* vm = runtimeCallInfo->GetVM();
123     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
124     ViewStackProcessor::GetInstance()->PopContainer();
125     return panda::JSValueRef::Undefined(vm);
126 }
127 
SetDefaultTheme(ArkUIRuntimeCallInfo * runtimeCallInfo)128 ArkUINativeModuleValue ThemeBridge::SetDefaultTheme(ArkUIRuntimeCallInfo* runtimeCallInfo)
129 {
130     EcmaVM* vm = runtimeCallInfo->GetVM();
131     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
132     Local<JSValueRef> colorsArg = runtimeCallInfo->GetCallArgRef(0);
133     Local<JSValueRef> isDarkArg = runtimeCallInfo->GetCallArgRef(1);
134 
135     // handle color mode argument
136     if (!isDarkArg->IsBoolean()) {
137         return panda::JSValueRef::Undefined(vm);
138     }
139     ArkUI_Bool isDark = static_cast<ArkUI_Bool>(isDarkArg->BooleaValue(vm));
140 
141     // handle colors argument
142     if (!colorsArg->IsArray(vm)) {
143         return panda::JSValueRef::Undefined(vm);
144     }
145     std::vector<ArkUI_Uint32> colors;
146     auto basisTheme = TokenThemeStorage::GetInstance()->ObtainSystemTheme();
147     for (size_t i = 0; i < TokenColors::TOTAL_NUMBER; i++) {
148         Color color;
149         auto colorParams = panda::ArrayRef::GetValueAt(vm, colorsArg, i);
150         bool isColorAvailable = false;
151         if (!ArkTSUtils::ParseJsColorAlpha(vm, colorParams, color)) {
152             if (basisTheme) {
153                 color = basisTheme->Colors()->GetByIndex(i);
154                 isColorAvailable = true;
155             }
156         } else {
157             isColorAvailable = true;
158         }
159         TokenThemeStorage::GetInstance()->SetIsThemeColorAvailable(isDark, i, isColorAvailable);
160 
161         colors.push_back(static_cast<ArkUI_Uint32>(color.GetValue()));
162     }
163 
164     // execute C-API
165     GetArkUINodeModifiers()->getThemeModifier()->setDefaultTheme(colors.data(), isDark);
166     return panda::JSValueRef::Undefined(vm);
167 }
168 
RemoveFromCache(ArkUIRuntimeCallInfo * runtimeCallInfo)169 ArkUINativeModuleValue ThemeBridge::RemoveFromCache(ArkUIRuntimeCallInfo* runtimeCallInfo)
170 {
171     EcmaVM* vm = runtimeCallInfo->GetVM();
172     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
173     Local<JSValueRef> themeIdArg = runtimeCallInfo->GetCallArgRef(0);
174 
175     // handle theme id argument
176     if (!themeIdArg->IsNumber()) {
177         return panda::JSValueRef::Undefined(vm);
178     }
179     ArkUI_Int32 themeId = static_cast<ArkUI_Int32>(themeIdArg->Int32Value(vm));
180 
181     // execute C-API
182     GetArkUINodeModifiers()->getThemeModifier()->removeFromCache(themeId);
183     return panda::JSValueRef::Undefined(vm);
184 }
185 } // namespace OHOS::Ace::NG