• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "adapter/ohos/osal/resource_theme_style.h"
17 
18 #include <set>
19 
20 namespace OHOS::Ace {
21 namespace {
22 constexpr char COLOR_VALUE_PREFIX[] = "$color:";
23 constexpr char MEDIA_VALUE_PREFIX[] = "/";
24 constexpr char REF_ATTR_VALUE_KEY_WORD[] = "?theme:";
25 constexpr char RES_TAG[] = "resource:///";
26 #ifdef PREVIEW
27 constexpr char RES_PATH_TAG[] = "file://";
28 // resource manager hap absolute path, as resource manager api don't return
29 constexpr char RES_HAP_PATH[] = "../resources/";
30 #else
31 constexpr char RES_PATH_TAG[] = "file:///";
32 // resource manager hap absolute path, as resource manager api don't return
33 constexpr char RES_HAP_PATH[] = "/data/storage/el1/bundle/ohos.global.systemres/ohos.global.systemres/assets/";
34 #endif
35 // resource manager hap for system resource
36 constexpr char RES_HAP_PREFIX[] = "ohos.global.systemres";
37 
ParseDoubleUnit(const std::string & value,std::string & unit)38 double ParseDoubleUnit(const std::string& value, std::string& unit)
39 {
40     for (size_t i = 0; i < value.length(); i++) {
41         if (i == 0 && (value[i] == '-' || value[i] == '+')) {
42             continue;
43         }
44         if (value[i] != '.' && (value[i] < '0' || value[i] > '9')) {
45             unit = value.substr(i);
46             return std::atof(value.substr(0, i).c_str());
47         }
48     }
49     return std::atof(value.c_str());
50 }
51 
ParseDimensionUnit(const std::string & unit)52 DimensionUnit ParseDimensionUnit(const std::string& unit)
53 {
54     if (unit == "px") {
55         return DimensionUnit::PX;
56     } else if (unit == "fp") {
57         return DimensionUnit::FP;
58     } else if (unit == "lpx") {
59         return DimensionUnit::LPX;
60     } else if (unit == "%") {
61         return DimensionUnit::PERCENT;
62     } else {
63         return DimensionUnit::VP;
64     }
65 }
66 }
67 
ParseContent()68 void ResourceThemeStyle::ParseContent()
69 {
70     static const std::set<std::string> stringAttrs = {
71         "attribute_text_font_family_regular",
72         "attribute_text_font_family_medium"
73     };
74     for (auto& [attrName, attrValue] : rawAttrs_) {
75         if (attrName.empty() || attrValue.empty()) {
76             LOGD("theme attr name:%{public}s or value:%{public}s is empty", attrName.c_str(), attrValue.c_str());
77             continue;
78         }
79         if (attrValue.front() == '#' || attrValue.find(COLOR_VALUE_PREFIX) != std::string::npos) {
80             // color
81             attributes_[attrName] = { .type = ThemeConstantsType::COLOR, .value = Color::FromString(attrValue) };
82         } else if (attrValue.find(MEDIA_VALUE_PREFIX) != std::string::npos) {
83             OnParseResourceMedia(attrName, attrValue);
84         } else if (stringAttrs.find(attrName) != stringAttrs.end()) {
85             // string
86             attributes_[attrName] = { .type = ThemeConstantsType::STRING, .value = attrValue };
87         } else if (attrValue.find(REF_ATTR_VALUE_KEY_WORD) != std::string::npos) {
88             attributes_[attrName] = { .type = ThemeConstantsType::REFERENCE_ATTR, .value = attrValue };
89         } else {
90             // double & dimension
91             std::string unit = "";
92             auto doubleValue = ParseDoubleUnit(attrValue, unit);
93             if (unit.empty()) {
94                 attributes_[attrName] = { .type = ThemeConstantsType::DOUBLE, .value = doubleValue };
95             } else {
96                 attributes_[attrName] = { .type = ThemeConstantsType::DIMENSION,
97                     .value = Dimension(doubleValue, ParseDimensionUnit(unit)) };
98             }
99         }
100     }
101     LOGD("theme attribute size:%{public}zu", attributes_.size());
102     OnParseStyle();
103 }
104 
OnParseStyle()105 void ResourceThemeStyle::OnParseStyle()
106 {
107     for (auto& [patternName, patternMap]: patternAttrs_) {
108         auto patternStyle = AceType::MakeRefPtr<ResourceThemeStyle>(resAdapter_);
109         patternStyle->SetName(patternName);
110         patternStyle->parentStyle_ = AceType::WeakClaim(this);
111         patternStyle->rawAttrs_ = patternMap;
112         patternStyle->ParseContent();
113         attributes_[patternName] = { .type = ThemeConstantsType::PATTERN,
114             .value = RefPtr<ThemeStyle>(std::move(patternStyle)) };
115     }
116 }
117 
OnParseResourceMedia(const std::string & attrName,const std::string & attrValue)118 void ResourceThemeStyle::OnParseResourceMedia(const std::string& attrName, const std::string& attrValue)
119 {
120     std::string mediaPath;
121     if (SystemProperties::GetUnZipHap()) {
122         mediaPath = RES_PATH_TAG;
123         if (attrValue.find(RES_HAP_PREFIX) == std::string::npos) {
124             mediaPath.append(RES_HAP_PATH);
125         }
126         mediaPath += attrValue;
127     } else {
128         // hap is not unzip, should use resource name to read file
129         auto pos = attrValue.find_last_of(MEDIA_VALUE_PREFIX);
130         if (pos == std::string::npos) {
131             LOGW("resource media invalid:[%{public}s, %{public}s]", attrName.c_str(), attrValue.c_str());
132             return;
133         }
134         mediaPath = std::string(RES_TAG) + attrValue.substr(pos + 1);
135     }
136     attributes_[attrName] = { .type = ThemeConstantsType::STRING, .value = mediaPath };
137 }
138 } // namespace OHOS::Ace
139