• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "core/common/resource/resource_parse_utils.h"
17 
18 #include <regex>
19 #include <cstdint>
20 
21 #include "base/utils/utf_helper.h"
22 #include "core/common/card_scope.h"
23 #include "core/common/container.h"
24 #ifdef PLUGIN_COMPONENT_SUPPORTED
25 #include "core/common/plugin_manager.h"
26 #endif
27 #include "core/common/color_inverter.h"
28 #include "core/common/resource/resource_manager.h"
29 #include "core/common/resource/resource_wrapper.h"
30 #include "core/pipeline/pipeline_base.h"
31 
32 namespace OHOS::Ace {
33 constexpr uint32_t COLOR_ALPHA_OFFSET = 24;
34 constexpr uint32_t COLOR_ALPHA_VALUE = 0xFF000000;
35 constexpr int32_t UNKNOWN_INSTANCE_ID = -1;
36 constexpr int32_t UNKNOWN_RESOURCE_ID = -1;
37 constexpr int32_t UNKNOWN_RESOURCE_TYPE = -1;
38 const std::regex FLOAT_PATTERN(R"(-?(0|[1-9]\d*)(\.\d+))", std::regex::icase);
39 bool ResourceParseUtils::isReloading_ = false;
40 
ColorAlphaAdapt(uint32_t origin)41 uint32_t ColorAlphaAdapt(uint32_t origin)
42 {
43     uint32_t result = origin;
44     if ((origin >> COLOR_ALPHA_OFFSET) == 0) {
45         result = origin | COLOR_ALPHA_VALUE;
46     }
47     return result;
48 }
49 
GetThemeConstants(const RefPtr<ResourceObject> & resObj)50 RefPtr<ThemeConstants> ResourceParseUtils::GetThemeConstants(const RefPtr<ResourceObject>& resObj)
51 {
52     std::string bundleName;
53     std::string moduleName;
54     if (resObj) {
55         bundleName = resObj->GetBundleName();
56         moduleName = resObj->GetModuleName();
57     }
58 
59 #if !defined(ACE_UNITTEST)
60     auto cardId = CardScope::CurrentId();
61     if (cardId != INVALID_CARD_ID) {
62         auto container = Container::Current();
63         auto weak = container->GetCardPipeline(cardId);
64         auto cardPipelineContext = weak.Upgrade();
65         CHECK_NULL_RETURN(cardPipelineContext, nullptr);
66         auto cardThemeManager = cardPipelineContext->GetThemeManager();
67         CHECK_NULL_RETURN(cardThemeManager, nullptr);
68         return cardThemeManager->GetThemeConstants(bundleName, moduleName);
69     }
70 #endif
71 
72 #ifdef PLUGIN_COMPONENT_SUPPORTED
73     if (Container::CurrentId() >= MIN_PLUGIN_SUBCONTAINER_ID) {
74         auto pluginContainer = PluginManager::GetInstance().GetPluginSubContainer(Container::CurrentId());
75         if (!pluginContainer) {
76             return nullptr;
77         }
78         auto pluginPipelineContext = pluginContainer->GetPipelineContext();
79         if (!pluginPipelineContext) {
80             return nullptr;
81         }
82         auto pluginThemeManager = pluginPipelineContext->GetThemeManager();
83         if (!pluginThemeManager) {
84             return nullptr;
85         }
86         return pluginThemeManager->GetThemeConstants(bundleName, moduleName);
87     }
88 #endif
89     auto container = Container::Current();
90     CHECK_NULL_RETURN(container, nullptr);
91     auto pipelineContext = container->GetPipelineContext();
92     CHECK_NULL_RETURN(pipelineContext, nullptr);
93     auto themeManager = pipelineContext->GetThemeManager();
94     CHECK_NULL_RETURN(themeManager, nullptr);
95     return themeManager->GetThemeConstants(bundleName, moduleName);
96 }
97 
CreateResourceWrapper()98 RefPtr<ResourceWrapper> CreateResourceWrapper()
99 {
100     RefPtr<ResourceObject> resObj;
101     RefPtr<ResourceAdapter> resourceAdapter = nullptr;
102     RefPtr<ThemeConstants> themeConstants = nullptr;
103     if (SystemProperties::GetResourceDecoupling()) {
104         resourceAdapter = ResourceManager::GetInstance().GetResourceAdapter(Container::CurrentIdSafely());
105         if (!resourceAdapter) {
106             return nullptr;
107         }
108     } else {
109         themeConstants = ResourceParseUtils::GetThemeConstants(resObj);
110         if (!themeConstants) {
111             return nullptr;
112         }
113     }
114     auto resourceWrapper = AceType::MakeRefPtr<ResourceWrapper>(themeConstants, resourceAdapter);
115     return resourceWrapper;
116 }
117 
GetOrCreateResourceWrapper(const RefPtr<ResourceObject> & resObj)118 RefPtr<ResourceWrapper> GetOrCreateResourceWrapper(const RefPtr<ResourceObject>& resObj)
119 {
120     RefPtr<ResourceAdapter> resourceAdapter = nullptr;
121     RefPtr<ThemeConstants> themeConstants = nullptr;
122     if (SystemProperties::GetResourceDecoupling()) {
123         resourceAdapter = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj);
124         if (!resourceAdapter) {
125             return nullptr;
126         }
127     } else {
128         themeConstants = ResourceParseUtils::GetThemeConstants(resObj);
129         if (!themeConstants) {
130             return nullptr;
131         }
132     }
133     auto resourceWrapper = AceType::MakeRefPtr<ResourceWrapper>(themeConstants, resourceAdapter);
134     return resourceWrapper;
135 }
136 
CompleteResourceObject(const std::unique_ptr<JsonValue> & json)137 RefPtr<ResourceObject> CompleteResourceObject(const std::unique_ptr<JsonValue>& json)
138 {
139     auto id = json->GetValue("id")->GetInt();
140     auto type = json->GetValue("type")->GetInt();
141     auto params = json->GetValue("params");
142 
143     std::string bundleName;
144     std::string moduleName;
145     auto bundle = json->GetValue("bundleName");
146     auto module = json->GetValue("moduleName");
147     if (bundle->IsString() && module->IsString()) {
148         bundleName = bundle->ToString();
149         moduleName = module->ToString();
150     }
151 
152     if (!params->IsArray()) {
153         return nullptr;
154     }
155 
156     std::vector<ResourceObjectParams> resObjParamsList;
157     auto size = params->GetArraySize();
158     for (int32_t i = 0; i < size; i++) {
159         auto item = params->GetArrayItem(i);
160         ResourceObjectParams resObjParams { .value = item->ToString().c_str() };
161         if (item->IsString()) {
162             resObjParams.type = ResourceObjectParamType::STRING;
163         } else if (item->IsNumber()) {
164             if (std::regex_match(item->ToString(), FLOAT_PATTERN)) {
165                 resObjParams.type = ResourceObjectParamType::FLOAT;
166             } else {
167                 resObjParams.type = ResourceObjectParamType::INT;
168             }
169         }
170         resObjParamsList.push_back(resObjParams);
171     }
172     auto resourceObject = AceType::MakeRefPtr<ResourceObject>(
173         id, type, resObjParamsList, bundleName, moduleName, Container::CurrentIdSafely());
174     return resourceObject;
175 }
176 
GetReplaceContentStr(int pos,const std::string & type,const std::vector<ResourceObjectParams> params,int32_t containCount)177 std::string GetReplaceContentStr(int pos, const std::string& type,
178     const std::vector<ResourceObjectParams> params, int32_t containCount)
179 {
180     auto index = pos + containCount;
181     if (index < 0 || (index >= static_cast<int32_t>(params.size()))) {
182         return std::string();
183     }
184 
185     auto item = params[index].value;
186     auto itemType = params[index].type;
187     auto entityReson = JsonUtil::ParseJsonString(item.value());
188     if (type == "d") {
189         if (itemType == ResourceObjectParamType::INT ||
190             itemType == ResourceObjectParamType::FLOAT) {
191             return item.value();
192         } else if (itemType == ResourceObjectParamType::NONE) {
193             auto resObj = CompleteResourceObject(entityReson);
194             int32_t result = 0;
195             ResourceParseUtils::ParseResInteger(resObj, result);
196             return std::to_string(result);
197         }
198     } else if (type == "s") {
199         if (itemType == ResourceObjectParamType::STRING) {
200             return item.value();
201         } else if (itemType == ResourceObjectParamType::NONE) {
202             auto resObj = CompleteResourceObject(entityReson);
203             std::string result;
204             ResourceParseUtils::ParseResString(resObj, result);
205             return result;
206         }
207     } else if (type == "f") {
208         if (itemType == ResourceObjectParamType::INT ||
209             itemType == ResourceObjectParamType::FLOAT) {
210             return item.value();
211         } else if (itemType == ResourceObjectParamType::NONE) {
212             auto resObj = CompleteResourceObject(entityReson);
213             double result = 0.0;
214             ResourceParseUtils::ParseResDouble(resObj, result);
215             return std::to_string(result);
216         }
217     }
218     return std::string();
219 }
220 
ReplaceHolder(std::string & originStr,const std::vector<ResourceObjectParams> params,int32_t containCount)221 void ReplaceHolder(std::string& originStr, const std::vector<ResourceObjectParams> params, int32_t containCount)
222 {
223     auto size = static_cast<int32_t>(params.size());
224     if (containCount == size) {
225         return;
226     }
227     std::string::const_iterator start = originStr.begin();
228     std::string::const_iterator end = originStr.end();
229     std::smatch matches;
230     bool shortHolderType = false;
231     bool firstMatch = true;
232     int searchTime = 0;
233     const std::regex RESOURCE_APP_STRING_PLACEHOLDER(R"(\%((\d+)(\$)){0,1}([dsf]))", std::regex::icase);
234     while (std::regex_search(start, end, matches, RESOURCE_APP_STRING_PLACEHOLDER)) {
235         std::string pos = matches[2];
236         std::string type = matches[4];
237         if (firstMatch) {
238             firstMatch = false;
239             shortHolderType = pos.length() == 0;
240         } else {
241             if (shortHolderType ^ (pos.length() == 0)) {
242                 return;
243             }
244         }
245 
246         std::string replaceContentStr;
247         if (shortHolderType) {
248             replaceContentStr = GetReplaceContentStr(searchTime, type, params, containCount);
249         } else {
250             replaceContentStr = GetReplaceContentStr(StringUtils::StringToInt(pos) - 1, type, params, containCount);
251         }
252 
253         originStr.replace(matches[0].first - originStr.begin(), matches[0].length(), replaceContentStr);
254         start = originStr.begin() + matches.prefix().length() + replaceContentStr.length();
255         end = originStr.end();
256         searchTime++;
257     }
258 }
259 
ParseResInteger(const RefPtr<ResourceObject> & resObj,uint32_t & result)260 bool ResourceParseUtils::ParseResInteger(const RefPtr<ResourceObject>& resObj, uint32_t& result)
261 {
262     return ParseResInteger<uint32_t>(resObj, result);
263 }
264 
ParseResInteger(const RefPtr<ResourceObject> & resObj,int32_t & result)265 bool ResourceParseUtils::ParseResInteger(const RefPtr<ResourceObject>& resObj, int32_t& result)
266 {
267     return ParseResInteger<int32_t>(resObj, result);
268 }
269 
ParseResIntegerArray(const RefPtr<ResourceObject> & resObj,std::vector<uint32_t> & result)270 bool ResourceParseUtils::ParseResIntegerArray(const RefPtr<ResourceObject>& resObj, std::vector<uint32_t>& result)
271 {
272     CHECK_NULL_RETURN(resObj, false);
273     auto resType = resObj->GetType();
274     if (resType == UNKNOWN_RESOURCE_TYPE) {
275         return false;
276     }
277 
278     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
279     if (!resourceWrapper) {
280         return false;
281     }
282 
283     auto resId = resObj->GetId();
284     if (resId == -1) {
285         auto params = resObj->GetParams();
286         if (params.empty()) {
287             return false;
288         }
289         if (resType == static_cast<int32_t>(ResourceType::INTARRAY)) {
290             result = resourceWrapper->GetIntArrayByName(params[0].value.value());
291             return true;
292         }
293         return false;
294     }
295     if (resType == static_cast<int32_t>(ResourceType::INTARRAY)) {
296         result = resourceWrapper->GetIntArray(resId);
297         return true;
298     }
299     return false;
300 }
301 
ParseResStrArray(const RefPtr<ResourceObject> & resObj,std::vector<std::string> & result)302 bool ResourceParseUtils::ParseResStrArray(const RefPtr<ResourceObject>& resObj, std::vector<std::string>& result)
303 {
304     CHECK_NULL_RETURN(resObj, false);
305     auto resType = resObj->GetType();
306     if (resType == UNKNOWN_RESOURCE_TYPE) {
307         return false;
308     }
309 
310     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
311     if (!resourceWrapper) {
312         return false;
313     }
314 
315     auto resId = resObj->GetId();
316     if (resId == -1) {
317         auto params = resObj->GetParams();
318         if (params.empty()) {
319             return false;
320         }
321         if (resType == static_cast<int32_t>(ResourceType::STRARRAY)) {
322             result = resourceWrapper->GetStringArrayByName(params[0].value.value());
323             return true;
324         }
325         return false;
326     }
327     if (resType == static_cast<int32_t>(ResourceType::STRARRAY)) {
328         result = resourceWrapper->GetStringArray(resId);
329         return true;
330     }
331     return false;
332 }
333 
ParseResFontFamilies(const RefPtr<ResourceObject> & resObj,std::vector<std::string> & result)334 bool ResourceParseUtils::ParseResFontFamilies(const RefPtr<ResourceObject>& resObj, std::vector<std::string>& result)
335 {
336     CHECK_NULL_RETURN(resObj, false);
337     result.clear();
338     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
339     if (!resourceWrapper) {
340         return false;
341     }
342 
343     auto resId = resObj->GetId();
344     if (resId == -1) {
345         auto params = resObj->GetParams();
346         if (params.empty()) {
347             return false;
348         }
349         result.emplace_back(resourceWrapper->GetStringByName(params[0].value.value()));
350         return true;
351     }
352     result.emplace_back(resourceWrapper->GetString(resId));
353     return true;
354 }
355 
InvertColorWithResource(const RefPtr<ResourceObject> & resObj,Color & result,const ColorMode & colorMode)356 void ResourceParseUtils::InvertColorWithResource(const RefPtr<ResourceObject>& resObj, Color& result,
357     const ColorMode& colorMode)
358 {
359     if (!isReloading_ || (resObj->GetColorMode() == ColorMode::COLOR_MODE_UNDEFINED)) {
360         return;
361     }
362     if ((colorMode == ColorMode::DARK) && !resObj->HasDarkResource()) {
363         result = ColorInverter::Invert(result, resObj->GetInstanceId(), resObj->GetNodeTag());
364     }
365     resObj->SetColorMode(colorMode);
366 }
367 
ParseResColorWithName(const RefPtr<ResourceObject> & resObj,Color & result,RefPtr<ResourceWrapper> & resourceWrapper,const ColorMode & colorMode)368 bool ResourceParseUtils::ParseResColorWithName(const RefPtr<ResourceObject>& resObj, Color& result,
369     RefPtr<ResourceWrapper>& resourceWrapper, const ColorMode& colorMode)
370 {
371     auto params = resObj->GetParams();
372     if (params.empty()) {
373         return false;
374     }
375     result = resourceWrapper->GetColorByName(params[0].value.value());
376     InvertColorWithResource(resObj, result, colorMode);
377     return true;
378 }
379 
ParseResColor(const RefPtr<ResourceObject> & resObj,Color & result)380 bool ResourceParseUtils::ParseResColor(const RefPtr<ResourceObject>& resObj, Color& result)
381 {
382     CHECK_NULL_RETURN(resObj, false);
383 
384     auto colorMode = Container::CurrentColorMode();
385     if (!resObj->IsResource()) {
386         if (resObj->GetColorMode() == ColorMode::COLOR_MODE_UNDEFINED) {
387             return false;
388         }
389         if (isReloading_ && (colorMode == ColorMode::DARK)) {
390             result = ColorInverter::Invert(resObj->GetColor(), resObj->GetInstanceId(), resObj->GetNodeTag());
391         } else {
392             result = resObj->GetColor();
393         }
394         resObj->SetColorMode(colorMode);
395         return true;
396     }
397 
398     if (resObj->GetInstanceId() == UNKNOWN_INSTANCE_ID) {
399         resObj->SetInstanceId(Container::CurrentIdSafely());
400     }
401     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
402     CHECK_NULL_RETURN(resourceWrapper, false);
403     auto resId = resObj->GetId();
404     if (resId == -1) {
405         return ParseResColorWithName(resObj, result, resourceWrapper, colorMode);
406     }
407 
408     auto type = resObj->GetType();
409     if (type == static_cast<int32_t>(ResourceType::STRING)) {
410         auto value = resourceWrapper->GetString(resId);
411         bool state = Color::ParseColorString(value, result);
412         InvertColorWithResource(resObj, result, colorMode);
413         return state;
414     }
415     if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
416         auto value = resourceWrapper->GetInt(resId);
417         result = Color(ColorAlphaAdapt(value));
418         InvertColorWithResource(resObj, result, colorMode);
419         return true;
420     }
421     if (type == static_cast<int32_t>(ResourceType::COLOR)) {
422         result = resourceWrapper->GetColor(resId);
423         result.SetResourceId(resId);
424         InvertColorWithResource(resObj, result, colorMode);
425         return true;
426     }
427     return false;
428 }
429 
ParseResColorWithColorMode(const RefPtr<ResourceObject> & resObj,Color & result,const ColorMode & colorMode)430 bool ResourceParseUtils::ParseResColorWithColorMode(const RefPtr<ResourceObject>& resObj, Color& result,
431     const ColorMode& colorMode)
432 {
433     CHECK_NULL_RETURN(resObj, false);
434     auto container = Container::CurrentSafely();
435     CHECK_NULL_RETURN(container, false);
436     if (resObj->GetInstanceId() == UNKNOWN_INSTANCE_ID) {
437         resObj->SetInstanceId(container->GetInstanceId());
438     }
439     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
440     CHECK_NULL_RETURN(resourceWrapper, false);
441     auto resourceAdapter = resourceWrapper->GetResourceAdapter();
442     auto colorModeValue = resourceAdapter ? resourceAdapter->GetResourceColorMode() : container->GetColorMode();
443     ResourceManager::GetInstance().UpdateColorMode(
444         container->GetBundleName(), container->GetModuleName(), container->GetInstanceId(), colorMode);
445     bool state = ParseResColor(resObj, result);
446     ResourceManager::GetInstance().UpdateColorMode(
447         container->GetBundleName(), container->GetModuleName(), container->GetInstanceId(), colorModeValue);
448     return state;
449 }
450 
ParseResString(const RefPtr<ResourceObject> & resObj,std::u16string & result)451 bool ResourceParseUtils::ParseResString(const RefPtr<ResourceObject>& resObj, std::u16string& result)
452 {
453     CHECK_NULL_RETURN(resObj, false);
454     std::string u8Result;
455     bool ret = ParseResString(resObj, u8Result);
456     if (ret) {
457         result = UtfUtils::Str8DebugToStr16(u8Result);
458         return true;
459     }
460     return false;
461 }
462 
ParseResStringObj(const std::vector<ResourceObjectParams> & params,RefPtr<ResourceWrapper> & resourceWrapper,std::string & result,int32_t type)463 bool ResourceParseUtils::ParseResStringObj(const std::vector<ResourceObjectParams>& params,
464     RefPtr<ResourceWrapper>& resourceWrapper, std::string& result, int32_t type)
465 {
466     if (params.empty()) {
467         return false;
468     }
469     auto param = params[0];
470     if (type == static_cast<int32_t>(ResourceType::STRING)) {
471         auto originStr = resourceWrapper->GetStringByName(param.value.value());
472         ReplaceHolder(originStr, params, 1);
473         result = originStr;
474     } else if (type == static_cast<int32_t>(ResourceType::PLURAL)) {
475         auto countJsVal = params[1];
476         int count = 0;
477         if (!IsNumberType(static_cast<int32_t>(countJsVal.type))) {
478             return false;
479         }
480         count = StringUtils::StringToInt(countJsVal.value.value());
481         auto pluralStr = resourceWrapper->GetPluralStringByName(param.value.value(), count);
482         ReplaceHolder(pluralStr, params, 2); // params[2] applys pluralStr.
483         result = pluralStr;
484     } else {
485         return false;
486     }
487     return true;
488 }
489 
ParseResString(const RefPtr<ResourceObject> & resObj,std::string & result)490 bool ResourceParseUtils::ParseResString(const RefPtr<ResourceObject>& resObj, std::string& result)
491 {
492     CHECK_NULL_RETURN(resObj, false);
493     auto type = resObj->GetType();
494     if (type == UNKNOWN_RESOURCE_TYPE) {
495         return false;
496     }
497     auto params = resObj->GetParams();
498     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
499     if (!resourceWrapper) {
500         return false;
501     }
502     auto resIdNum = resObj->GetId();
503     if (resIdNum == -1) {
504         return ResourceParseUtils::ParseResStringObj(params, resourceWrapper, result, type);
505     }
506     if (type == static_cast<int32_t>(ResourceType::STRING)) {
507         auto originStr = resourceWrapper->GetString(resIdNum);
508         ReplaceHolder(originStr, params, 0);
509         result = originStr;
510     } else if (type == static_cast<int32_t>(ResourceType::PLURAL)) {
511         if (params.empty()) {
512             return false;
513         }
514         auto countJsVal = params[0];
515         int count = 0;
516         if (!IsNumberType(static_cast<int32_t>(countJsVal.type))) {
517             return false;
518         }
519         count = StringUtils::StringToInt(countJsVal.value.value());
520         auto pluralStr = resourceWrapper->GetPluralString(resIdNum, count);
521         ReplaceHolder(pluralStr, params, 1);
522         result = pluralStr;
523     } else if (type == static_cast<int32_t>(ResourceType::FLOAT)) {
524         result = std::to_string(resourceWrapper->GetDouble(resIdNum));
525     } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
526         result = std::to_string(resourceWrapper->GetInt(resIdNum));
527     } else {
528         return false;
529     }
530     return true;
531 }
532 
ParseResMedia(const RefPtr<ResourceObject> & resObj,std::string & result)533 bool ResourceParseUtils::ParseResMedia(const RefPtr<ResourceObject>& resObj, std::string& result)
534 {
535     CHECK_NULL_RETURN(resObj, false);
536     auto type = resObj->GetType();
537     auto resIdNum = resObj->GetId();
538     if (type != UNKNOWN_RESOURCE_TYPE) {
539         auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
540         if (!resourceWrapper) {
541             return false;
542         }
543         if (type == static_cast<int32_t>(ResourceType::RAWFILE)) {
544             auto params = resObj->GetParams();
545             if (!params.size()) {
546                 return false;
547             }
548             auto fileName = params[0];
549             if (fileName.type != ResourceObjectParamType::STRING) {
550                 return false;
551             }
552             result = resourceWrapper->GetRawfile(fileName.value.value());
553             return true;
554         }
555         if (resIdNum == -1) {
556             auto params = resObj->GetParams();
557             if (!params.size()) {
558                 return false;
559             }
560             if (type == static_cast<int32_t>(ResourceType::MEDIA)) {
561                 result = resourceWrapper->GetMediaPathByName(params[0].value.value());
562                 return true;
563             }
564             if (type == static_cast<int32_t>(ResourceType::STRING)) {
565                 result = resourceWrapper->GetStringByName(params[0].value.value());
566                 return true;
567             }
568             return false;
569         } else if (type == static_cast<int32_t>(ResourceType::MEDIA)) {
570             result = resourceWrapper->GetMediaPath(resIdNum);
571             return true;
572         } else if (type == static_cast<int32_t>(ResourceType::STRING)) {
573             result = resourceWrapper->GetString(resIdNum);
574             return true;
575         }
576     }
577     return false;
578 }
579 
ParseResBool(const RefPtr<ResourceObject> & resObj,bool & result)580 bool ResourceParseUtils::ParseResBool(const RefPtr<ResourceObject>& resObj, bool& result)
581 {
582     CHECK_NULL_RETURN(resObj, false);
583     auto type = resObj->GetType();
584     if (type == UNKNOWN_RESOURCE_TYPE) {
585         return false;
586     }
587 
588     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
589     if (!resourceWrapper) {
590         return false;
591     }
592     auto resIdNum = resObj->GetId();
593     if (resIdNum == -1) {
594         auto params = resObj->GetParams();
595         if (!params.size()) {
596             return false;
597         }
598         if (type == static_cast<int32_t>(ResourceType::BOOLEAN)) {
599             result = resourceWrapper->GetBooleanByName(params[0].value.value());
600             return true;
601         }
602         return false;
603     }
604     if (type == static_cast<int32_t>(ResourceType::BOOLEAN)) {
605         result = resourceWrapper->GetBoolean(resIdNum);
606         return true;
607     }
608     return false;
609 }
610 
ParseResourceToDouble(const RefPtr<ResourceObject> & resObj,double & result)611 bool ResourceParseUtils::ParseResourceToDouble(const RefPtr<ResourceObject>& resObj, double& result)
612 {
613     CHECK_NULL_RETURN(resObj, false);
614     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
615     if (!resourceWrapper) {
616         return false;
617     }
618     auto resIdNum = resObj->GetId();
619     auto type = resObj->GetType();
620     auto params = resObj->GetParams();
621     if (resIdNum == -1) {
622         if (params.empty()) {
623             return false;
624         }
625         auto param = params[0];
626         if (type == static_cast<int32_t>(ResourceType::STRING)) {
627             auto numberStr = resourceWrapper->GetStringByName(param.value.value());
628             return StringUtils::StringToDouble(numberStr, result);
629         } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
630             result = resourceWrapper->GetIntByName(param.value.value());
631             return true;
632         } else if (type == static_cast<int32_t>(ResourceType::FLOAT)) {
633             result = resourceWrapper->GetDoubleByName(param.value.value());
634             return true;
635         }
636         return false;
637     }
638     if (type == static_cast<int32_t>(ResourceType::STRING)) {
639         auto numberStr = resourceWrapper->GetString(resIdNum);
640         return StringUtils::StringToDouble(numberStr, result);
641     } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
642         result = resourceWrapper->GetInt(resIdNum);
643         return true;
644     } else if (type == static_cast<int32_t>(ResourceType::FLOAT)) {
645         result = resourceWrapper->GetDouble(resIdNum);
646         return true;
647     }
648     return false;
649 }
650 
ParseResDouble(const RefPtr<ResourceObject> & resObj,double & result)651 bool ResourceParseUtils::ParseResDouble(const RefPtr<ResourceObject>& resObj, double& result)
652 {
653     return ParseResourceToDouble(resObj, result);
654 }
655 
ParseResDimensionFpNG(const RefPtr<ResourceObject> & resObj,CalcDimension & result,bool isSupportPercent)656 bool ResourceParseUtils::ParseResDimensionFpNG(const RefPtr<ResourceObject>& resObj, CalcDimension& result,
657     bool isSupportPercent)
658 {
659     return ParseResDimensionNG(resObj, result, DimensionUnit::FP, isSupportPercent);
660 }
661 
ParseResDimensionVpNG(const RefPtr<ResourceObject> & resObj,CalcDimension & result,bool isSupportPercent)662 bool ResourceParseUtils::ParseResDimensionVpNG(const RefPtr<ResourceObject>& resObj, CalcDimension& result,
663     bool isSupportPercent)
664 {
665     return ParseResDimensionNG(resObj, result, DimensionUnit::VP, isSupportPercent);
666 }
667 
ParseResDimensionNG(const RefPtr<ResourceObject> & resObj,CalcDimension & result,DimensionUnit defaultUnit,bool isSupportPercent)668 bool ResourceParseUtils::ParseResDimensionNG(
669     const RefPtr<ResourceObject>& resObj, CalcDimension& result, DimensionUnit defaultUnit, bool isSupportPercent)
670 {
671     CHECK_NULL_RETURN(resObj, false);
672     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
673     if (!resourceWrapper) {
674         return false;
675     }
676     auto resIdNum = resObj->GetId();
677     auto type = resObj->GetType();
678     auto params = resObj->GetParams();
679     if (resIdNum == -1) {
680         if (params.empty()) {
681             return false;
682         }
683         auto param = params[0];
684         if (type == static_cast<int32_t>(ResourceType::STRING)) {
685             auto value = resourceWrapper->GetStringByName(param.value.value());
686             return StringUtils::StringToCalcDimensionNG(value, result, false, defaultUnit);
687         } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
688             auto value = std::to_string(resourceWrapper->GetIntByName(param.value.value()));
689             StringUtils::StringToDimensionWithUnitNG(value, result, defaultUnit);
690             return true;
691         }
692         result = resourceWrapper->GetDimensionByName(param.value.value());
693         return true;
694     }
695     if (type == static_cast<int32_t>(ResourceType::STRING)) {
696         auto value = resourceWrapper->GetString(resIdNum);
697         return StringUtils::StringToCalcDimensionNG(value, result, false, defaultUnit);
698     } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
699         auto value = std::to_string(resourceWrapper->GetInt(resIdNum));
700         StringUtils::StringToDimensionWithUnitNG(value, result, defaultUnit);
701         return true;
702     } else if (type == static_cast<int32_t>(ResourceType::FLOAT)) {
703         result = resourceWrapper->GetDimension(resIdNum);
704         return true;
705     }
706     return false;
707 }
708 
ParseResDimensionVp(const RefPtr<ResourceObject> & resObj,CalcDimension & result)709 bool ResourceParseUtils::ParseResDimensionVp(const RefPtr<ResourceObject>& resObj, CalcDimension& result)
710 {
711     // 'vp' -> the value varies with pixel density of device.
712     return ParseResDimension(resObj, result, DimensionUnit::VP);
713 }
714 
ParseResDimensionFp(const RefPtr<ResourceObject> & resObj,CalcDimension & result)715 bool ResourceParseUtils::ParseResDimensionFp(const RefPtr<ResourceObject>& resObj, CalcDimension& result)
716 {
717     // the 'fp' unit is used for text scenes.
718     return ParseResDimension(resObj, result, DimensionUnit::FP);
719 }
720 
ParseResDimensionPx(const RefPtr<ResourceObject> & resObj,CalcDimension & result)721 bool ResourceParseUtils::ParseResDimensionPx(const RefPtr<ResourceObject>& resObj, CalcDimension& result)
722 {
723     return ParseResDimension(resObj, result, DimensionUnit::PX);
724 }
725 
ParseResDimension(const RefPtr<ResourceObject> & resObj,CalcDimension & result,DimensionUnit defaultUnit)726 bool ResourceParseUtils::ParseResDimension(
727     const RefPtr<ResourceObject>& resObj, CalcDimension& result, DimensionUnit defaultUnit)
728 {
729     CHECK_NULL_RETURN(resObj, false);
730     auto resourceWrapper = GetOrCreateResourceWrapper(resObj);
731     if (!resourceWrapper) {
732         return false;
733     }
734     auto resIdNum = resObj->GetId();
735     auto type = resObj->GetType();
736     if (type == UNKNOWN_RESOURCE_TYPE) {
737         return false;
738     }
739     auto params = resObj->GetParams();
740     if (resIdNum == -1) {
741         if (params.empty()) {
742             return false;
743         }
744         auto param = params[0];
745         if (type == static_cast<int32_t>(ResourceType::STRING)) {
746             auto value = resourceWrapper->GetStringByName(param.value.value());
747             result = StringUtils::StringToCalcDimension(value, false, defaultUnit);
748             return true;
749         } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
750             auto value = std::to_string(resourceWrapper->GetIntByName(param.value.value()));
751             result = StringUtils::StringToDimensionWithUnit(value, defaultUnit);
752             return true;
753         }
754         result = resourceWrapper->GetDimensionByName(param.value.value());
755         return true;
756     }
757     if (type == static_cast<int32_t>(ResourceType::STRING)) {
758         auto value = resourceWrapper->GetString(resIdNum);
759         result = StringUtils::StringToCalcDimension(value, false, defaultUnit);
760         return true;
761     } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
762         auto value = std::to_string(resourceWrapper->GetInt(resIdNum));
763         result = StringUtils::StringToDimensionWithUnit(value, defaultUnit);
764         return true;
765     }
766     result = resourceWrapper->GetDimension(resIdNum);
767     return true;
768 }
769 
ParseResResource(const RefPtr<ResourceObject> & resObj,CalcDimension & result)770 bool ResourceParseUtils::ParseResResource(const RefPtr<ResourceObject>& resObj, CalcDimension& result)
771 {
772     CHECK_NULL_RETURN(resObj, false);
773     auto resIdNum = resObj->GetId();
774     auto type = resObj->GetType();
775     if (type == UNKNOWN_RESOURCE_TYPE) {
776         return false;
777     }
778     resIdNum = resIdNum == UNKNOWN_RESOURCE_ID ? 0 : resIdNum;
779 
780     auto resourceWrapper = CreateResourceWrapper();
781     CHECK_NULL_RETURN(resourceWrapper, false);
782     if (type == static_cast<int32_t>(ResourceType::STRING)) {
783         auto value = resourceWrapper->GetString(resIdNum);
784         return StringUtils::StringToCalcDimensionNG(value, result, false);
785     }
786     if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
787         auto value = std::to_string(resourceWrapper->GetInt(resIdNum));
788         StringUtils::StringToDimensionWithUnitNG(value, result);
789         return true;
790     }
791 
792     if (type == static_cast<int32_t>(ResourceType::FLOAT)) {
793         result = resourceWrapper->GetDimension(resIdNum);
794         return true;
795     }
796     return false;
797 }
798 
799 template<class T>
ConvertFromResObjNG(const RefPtr<ResourceObject> & resObj,T & result)800 bool ResourceParseUtils::ConvertFromResObjNG(const RefPtr<ResourceObject>& resObj, T& result)
801 {
802     CHECK_NULL_RETURN(resObj, false);
803     if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) {
804         double value;
805         if (ParseResDouble(resObj, value)) {
806             result = static_cast<T>(value);
807             return true;
808         }
809         result = 0;
810     } else if constexpr (std::is_same_v<T, Dimension>) {
811         CalcDimension calc;
812         bool ret = ParseResDimensionVpNG(resObj, calc);
813         result = calc;
814         return ret;
815     } else if constexpr (std::is_same_v<T, CalcDimension>) {
816         return ParseResDimensionVpNG(resObj, result);
817     } else if constexpr (std::is_same_v<T, Color>) {
818         return ParseResColor(resObj, result);
819     }
820     return false;
821 }
822 
823 template<class T>
ConvertFromResObj(const RefPtr<ResourceObject> & resObj,T & result)824 bool ResourceParseUtils::ConvertFromResObj(const RefPtr<ResourceObject>& resObj, T& result)
825 {
826     CHECK_NULL_RETURN(resObj, false);
827     if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) {
828         double value;
829         if (ParseResDouble(resObj, value)) {
830             result = static_cast<T>(value);
831             return true;
832         }
833         result = 0;
834     } else if constexpr (std::is_same_v<T, Dimension>) {
835         CalcDimension calc;
836         bool ret = ParseResDimensionVp(resObj, calc);
837         result = calc;
838         return ret;
839     } else if constexpr (std::is_same_v<T, CalcDimension>) {
840         return ParseResDimensionVp(resObj, result);
841     } else if constexpr (std::is_same_v<T, Color>) {
842         return ParseResColor(resObj, result);
843     }
844     return false;
845 }
846 
847 template bool ResourceParseUtils::ConvertFromResObjNG<Dimension>(
848     const RefPtr<ResourceObject>& resObj, Dimension& result);
849 }
850