• 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 <regex>
19 #include <set>
20 #include <string>
21 
22 namespace OHOS::Ace {
23 namespace {
24 constexpr char COLOR_VALUE_PREFIX[] = "$color:";
25 constexpr char MEDIA_VALUE_PREFIX[] = "/";
26 constexpr char REF_ATTR_VALUE_KEY_WORD[] = "?theme:";
27 
28 constexpr char RES_TAG[] = "resource:///";
29 // resource manager hap for system resource
30 constexpr char RES_HAP_PREFIX[] = "ohos.global.systemres";
31 #ifdef PREVIEW
32 constexpr char RES_PATH_TAG[] = "file://";
33 // resource manager hap absolute path, as resource manager api don't return
34 constexpr char RES_HAP_PATH[] = "../resources/";
35 #else
36 constexpr char RES_PATH_TAG[] = "file:///";
37 // resource manager hap absolute path, as resource manager api don't return
38 constexpr char RES_HAP_PATH[] = "/data/storage/el1/bundle/ohos.global.systemres/ohos.global.systemres/assets/";
39 #endif
40 
41 const std::string DIMENSION_PATTERN = R"(^([+-]?\d+(\.\d+)?)(px|fp|lpx|vp|%)?)";
42 constexpr int32_t WAIT_FOR_TIME = 50;
43 static const std::set<std::string> stringAttrs = {
44     "attribute_text_font_family_regular",
45     "attribute_text_font_family_medium",
46     "description_current_location",
47     "description_add_location",
48     "description_select_location",
49     "description_share_location",
50     "description_send_location",
51     "description_locating",
52     "description_location",
53     "description_send_current_location",
54     "description_relocation",
55     "description_punch_in",
56     "description_current_position",
57     "description_paste",
58     "description_download",
59     "description_download_file",
60     "description_save",
61     "description_save_image",
62     "description_save_file",
63     "description_download_and_share",
64     "description_receive",
65     "description_continue_to_receive",
66     "description_save_to_gallery",
67     "description_export_to_gallery",
68     "description_quick_save_to_gallery",
69     "description_quick_resave_to_gallery",
70     "draggable",
71     "divider_shadow_enable",
72     "camera_input",
73     "menu_bg_blur_effect_enable",
74     "menu_double_border_enable",
75     "section_unfocus_effect_enable",
76     "section_unfocus_color",
77     "sheet_type",
78     "sheet_bottom",
79     "multiple_dialog_display",
80     "menu_expand_display",
81     "popup_double_border_enable",
82     "popup_outer_border_color",
83     "popup_inner_border_color",
84     "dialog_expand_display",
85     "show_password_directly",
86     "textfield_show_handle",
87     "dialog_radius_level10",
88     "dialog_icon_primary",
89     "dialog_font_primary",
90     "menu_has_filter",
91     "calendar_picker_dialog_button_transparent",
92     "calendar_picker_dialog_divider_transparent",
93     "textfield_accessibility_property_clear",
94     "textfield_accessibility_show_password",
95     "textfield_accessibility_hide_password",
96     "rich_editor_show_handle",
97     "text_show_handle",
98     "textfield_show_password_button",
99     "textfield_hide_password_button",
100     "textfield_has_showed_password",
101     "textfield_has_hidden_password",
102     "calendar_picker_mon",
103     "calendar_picker_tue",
104     "calendar_picker_wed",
105     "calendar_picker_thu",
106     "calendar_picker_fri",
107     "calendar_picker_sat",
108     "calendar_picker_sun",
109     "slider_accessibility_selected",
110     "slider_accessibility_unselected",
111     "slider_accessibility_unselectedDesc",
112     "pass_point",
113     "slider_accessibility_disabledDesc",
114     "textfield_accessibility_clear",
115     "textfield_writting_bundle_name",
116     "textfield_writting_ability_name",
117     "rich_editor_writting_bundle_name",
118     "rich_editor_writting_ability_name",
119     "textfield_writting_is_support",
120     "rich_editor_writting_is_support",
121     "ai_write_menu_name",
122     "menu_translate_is_support"
123 };
124 
ParseNumberUnit(const std::string & value,std::string & number,std::string & unit)125 void ParseNumberUnit(const std::string& value, std::string& number, std::string& unit)
126 {
127     std::regex regex(DIMENSION_PATTERN);
128     std::smatch results;
129     if (std::regex_search(value, results, regex)) {
130         number = results[1];
131         // The unit is in the 3rd sub-match. If the value doesn't have unit,
132         // the 3rd match result is empty.
133         unit = results[3];
134     }
135 }
136 
ParseDimensionUnit(const std::string & unit)137 DimensionUnit ParseDimensionUnit(const std::string& unit)
138 {
139     if (unit == "px") {
140         return DimensionUnit::PX;
141     } else if (unit == "fp") {
142         return DimensionUnit::FP;
143     } else if (unit == "lpx") {
144         return DimensionUnit::LPX;
145     } else if (unit == "%") {
146         return DimensionUnit::PERCENT;
147     } else {
148         return DimensionUnit::VP;
149     }
150 }
151 }
152 
ParseContent()153 void ResourceThemeStyle::ParseContent()
154 {
155     for (auto& [attrName, attrValue] : rawAttrs_) {
156         if (attrName.empty() || attrValue.empty()) {
157             continue;
158         }
159         if (stringAttrs.find(attrName) != stringAttrs.end()) {
160             // string
161             attributes_[attrName] = { .type = ThemeConstantsType::STRING, .value = attrValue };
162             continue;
163         }
164         if (attrValue.front() == '#' || attrValue.find(COLOR_VALUE_PREFIX) != std::string::npos) {
165             // color
166             attributes_[attrName] = { .type = ThemeConstantsType::COLOR, .value = Color::FromString(attrValue) };
167         } else if (attrValue.find(MEDIA_VALUE_PREFIX) != std::string::npos) {
168             OnParseResourceMedia(attrName, attrValue);
169         } else if (attrValue.find(REF_ATTR_VALUE_KEY_WORD) != std::string::npos) {
170             attributes_[attrName] = { .type = ThemeConstantsType::REFERENCE_ATTR, .value = attrValue };
171         } else {
172             // int & double & dimension
173             std::string number;
174             std::string unit;
175             ParseNumberUnit(attrValue, number, unit);
176             if (number.empty()) {
177                 continue;
178             } else if (!unit.empty()) {
179                 attributes_[attrName] = { .type = ThemeConstantsType::DIMENSION,
180                     .value = Dimension(std::atof(number.c_str()), ParseDimensionUnit(unit)) };
181             } else if (number.find(".") == std::string::npos) {
182                 attributes_[attrName] = { .type = ThemeConstantsType::INT, .value = std::atoi(number.c_str()) };
183             } else {
184                 attributes_[attrName] = { .type = ThemeConstantsType::DOUBLE, .value = std::atof(number.c_str()) };
185             }
186         }
187     }
188     OnParseStyle();
189 }
190 
OnParseStyle()191 void ResourceThemeStyle::OnParseStyle()
192 {
193     for (auto& [patternName, patternMap]: patternAttrs_) {
194         auto patternStyle = AceType::MakeRefPtr<ResourceThemeStyle>(resAdapter_);
195         patternStyle->SetName(patternName);
196         patternStyle->parentStyle_ = AceType::WeakClaim(this);
197         patternStyle->rawAttrs_ = patternMap;
198         patternStyle->ParseContent();
199         attributes_[patternName] = { .type = ThemeConstantsType::PATTERN,
200             .value = RefPtr<ThemeStyle>(std::move(patternStyle)) };
201     }
202 }
203 
OnParseResourceMedia(const std::string & attrName,const std::string & attrValue)204 void ResourceThemeStyle::OnParseResourceMedia(const std::string& attrName, const std::string& attrValue)
205 {
206     std::string mediaPath;
207     if (SystemProperties::GetUnZipHap()) {
208         mediaPath = RES_PATH_TAG;
209         if (attrValue.find(RES_HAP_PREFIX) == std::string::npos) {
210             mediaPath.append(RES_HAP_PATH);
211         }
212 #ifdef PREVIEW
213         auto pos = attrValue.find(MEDIA_VALUE_PREFIX);
214         if (pos == std::string::npos) {
215             return;
216         }
217         mediaPath += attrValue.substr(pos + 1);
218 #else
219         mediaPath += attrValue;
220 #endif
221     } else {
222         // hap is not unzip, should use resource name to read file
223         auto pos = attrValue.find_last_of(MEDIA_VALUE_PREFIX);
224         if (pos == std::string::npos) {
225             LOGW("resource media invalid:[%{public}s, %{public}s]", attrName.c_str(), attrValue.c_str());
226             return;
227         }
228         mediaPath = std::string(RES_TAG) + attrValue.substr(pos + 1);
229     }
230     attributes_[attrName] = { .type = ThemeConstantsType::STRING, .value = mediaPath };
231 }
232 
CheckThemeStyleLoaded(const std::string & patternName)233 void ResourceThemeStyle::CheckThemeStyleLoaded(const std::string& patternName)
234 {
235     if (!CheckThemeStyle(patternName)) {
236         return;
237     }
238     if (future_.valid()) {
239         future_.wait_until(std::chrono::system_clock::now() + std::chrono::milliseconds(WAIT_FOR_TIME));
240     }
241 }
242 } // namespace OHOS::Ace
243