• 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 <unordered_set>
20 
21 namespace OHOS::Ace {
22 namespace {
23 constexpr char COLOR_VALUE_PREFIX[] = "$color:";
24 constexpr char MEDIA_VALUE_PREFIX[] = "/";
25 constexpr char REF_ATTR_VALUE_KEY_WORD[] = "?theme:";
26 
27 constexpr char RES_TAG[] = "resource:///";
28 // resource manager hap for system resource
29 constexpr char RES_HAP_PREFIX[] = "ohos.global.systemres";
30 #ifdef PREVIEW
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[] = "../resources/";
34 #else
35 constexpr char RES_PATH_TAG[] = "file:///";
36 // resource manager hap absolute path, as resource manager api don't return
37 constexpr char RES_HAP_PATH[] = "/data/storage/el1/bundle/ohos.global.systemres/ohos.global.systemres/assets/";
38 #endif
39 
40 const std::regex DIMENSION_REGEX(R"(^([+-]?\d+(\.\d+)?)(px|fp|lpx|vp|%)?)");
41 constexpr int32_t WAIT_FOR_TIME = 50;
42 static const std::unordered_set<std::string> stringAttrs = {
43     "attribute_text_font_family_regular",
44     "attribute_text_font_family_medium",
45     "description_current_location",
46     "description_add_location",
47     "description_select_location",
48     "description_share_location",
49     "description_send_location",
50     "description_locating",
51     "description_location",
52     "description_send_current_location",
53     "description_relocation",
54     "description_punch_in",
55     "description_current_position",
56     "description_paste",
57     "description_download",
58     "description_download_file",
59     "description_save",
60     "description_save_image",
61     "description_save_file",
62     "description_download_and_share",
63     "description_receive",
64     "description_continue_to_receive",
65     "description_save_to_gallery",
66     "description_export_to_gallery",
67     "description_quick_save_to_gallery",
68     "description_quick_resave_to_gallery",
69     "description_save_all",
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_close",
79     "multiple_dialog_display",
80     "menu_expand_display",
81     "popup_double_border_enable",
82     "tips_double_border_enable",
83     "dialog_expand_display",
84     "show_password_directly",
85     "textfield_show_handle",
86     "dialog_radius_level10",
87     "dialog_icon_primary",
88     "dialog_font_primary",
89     "menu_has_filter",
90     "navigation_general_more",
91     "navigation_back",
92     "calendar_picker_dialog_button_transparent",
93     "calendar_picker_dialog_divider_transparent",
94     "textfield_accessibility_property_clear",
95     "textfield_accessibility_show_password",
96     "textfield_accessibility_hide_password",
97     "rich_editor_show_handle",
98     "text_show_handle",
99     "list_fadeout_enable",
100     "text_fadeout_enable",
101     "textfield_show_password_button",
102     "textfield_hide_password_button",
103     "textfield_has_showed_password",
104     "textfield_has_hidden_password",
105     "calendar_picker_mon",
106     "calendar_picker_tue",
107     "calendar_picker_wed",
108     "calendar_picker_thu",
109     "calendar_picker_fri",
110     "calendar_picker_sat",
111     "calendar_picker_sun",
112     "general_today",
113     "picker_dialog_lunar_switch",
114     "picker_dialog_previous_button",
115     "picker_dialog_next_button",
116     "filter_accessibility_expand",
117     "filter_accessibility_collapse",
118     "filter_accessibility_collapsed",
119     "filter_accessibility_expanded",
120     "slider_accessibility_selected",
121     "slider_accessibility_unselected",
122     "slider_accessibility_unselectedDesc",
123     "slider_accessibility_disabledDesc",
124     "stepper_back",
125     "stepper_skip",
126     "stepper_start",
127     "stepper_next",
128     "textfield_writting_bundle_name",
129     "textfield_writting_ability_name",
130     "rich_editor_writting_bundle_name",
131     "rich_editor_writting_ability_name",
132     "textfield_writting_is_support",
133     "rich_editor_writting_is_support",
134     "ai_write_menu_name",
135     "menu_translate_is_support",
136     "text_menu_search_is_support",
137     "textfield_menu_search_is_support",
138     "richeditor_menu_search_is_support",
139     "textfield_accessibility_clear",
140     "pass_point",
141     "side_length",
142     "general_next_year",
143     "general_next_month",
144     "general_pre_year",
145     "general_pre_month",
146     "prev_arrow_accessibility_text",
147     "next_arrow_accessibility_text",
148     "menu_haptic_feedback",
149     "text_overlay_menu_cut_label",
150     "text_overlay_menu_copy_label",
151     "text_overlay_menu_paste_label",
152     "text_overlay_menu_select_all_label",
153     "text_overlay_menu_translate_label",
154     "text_overlay_menu_share_label",
155     "text_overlay_menu_search_label",
156     "switch_on_text",
157     "switch_off_text",
158     "common_cancel_text",
159     "common_ok_text",
160     "textoverlay_paste",
161     "text_overlay_menu_more_accessibility_text",
162     "text_overlay_menu_back_accessibility_text",
163     "general_ai_menu_address",
164     "general_ai_menu_date",
165     "general_ai_menu_email",
166     "general_ai_menu_phone_number",
167     "general_ai_menu_url",
168     "menu_animation_curve",
169     "general_ai_preview_menu_address_open_map_app",
170     "general_ai_preview_menu_url_open_browser_app",
171     "general_ai_preview_menu_date_install_calendar_app",
172     "general_ai_preview_menu_address_install_map_app",
173     "general_ai_preview_menu_display_failed",
174     "textfield_show_password",
175     "textfield_hide_password",
176     "general_ai_ask_celia",
177 };
178 
ParseNumberUnit(const std::string & value,std::string & number,std::string & unit)179 void ParseNumberUnit(const std::string& value, std::string& number, std::string& unit)
180 {
181     std::smatch results;
182     if (std::regex_search(value, results, DIMENSION_REGEX)) {
183         number = results[1];
184         // The unit is in the 3rd sub-match. If the value doesn't have unit,
185         // the 3rd match result is empty.
186         unit = results[3];
187     }
188 }
189 
ParseDimensionUnit(const std::string & unit)190 DimensionUnit ParseDimensionUnit(const std::string& unit)
191 {
192     if (unit == "px") {
193         return DimensionUnit::PX;
194     } else if (unit == "fp") {
195         return DimensionUnit::FP;
196     } else if (unit == "lpx") {
197         return DimensionUnit::LPX;
198     } else if (unit == "%") {
199         return DimensionUnit::PERCENT;
200     } else {
201         return DimensionUnit::VP;
202     }
203 }
204 }
205 
ParseContent()206 void ResourceThemeStyle::ParseContent()
207 {
208     for (const auto& [attrName, attrValue] : rawAttrs_) {
209         if (attrName.empty() || attrValue.empty()) {
210             continue;
211         }
212         if (stringAttrs.find(attrName) != stringAttrs.end()) {
213             // string
214             attributes_[attrName] = { .type = ThemeConstantsType::STRING, .value = attrValue };
215             continue;
216         }
217         if (attrValue.front() == '#' || attrValue.find(COLOR_VALUE_PREFIX) != std::string::npos) {
218             // color
219             attributes_[attrName] = { .type = ThemeConstantsType::COLOR, .value = Color::FromString(attrValue) };
220         } else if (attrValue.find(MEDIA_VALUE_PREFIX) != std::string::npos) {
221             OnParseResourceMedia(attrName, attrValue);
222         } else if (attrValue.find(REF_ATTR_VALUE_KEY_WORD) != std::string::npos) {
223             attributes_[attrName] = { .type = ThemeConstantsType::REFERENCE_ATTR, .value = attrValue };
224         } else {
225             // int & double & dimension
226             std::string number;
227             std::string unit;
228             ParseNumberUnit(attrValue, number, unit);
229             if (number.empty()) {
230                 continue;
231             } else if (!unit.empty()) {
232                 attributes_[attrName] = { .type = ThemeConstantsType::DIMENSION,
233                     .value = Dimension(std::atof(number.c_str()), ParseDimensionUnit(unit)) };
234             } else if (number.find(".") == std::string::npos) {
235                 attributes_[attrName] = { .type = ThemeConstantsType::INT, .value = std::atoi(number.c_str()) };
236             } else {
237                 attributes_[attrName] = { .type = ThemeConstantsType::DOUBLE, .value = std::atof(number.c_str()) };
238             }
239         }
240     }
241     OnParseStyle();
242 }
243 
OnParseStyle()244 void ResourceThemeStyle::OnParseStyle()
245 {
246     for (const auto& [patternName, patternMap]: patternAttrs_) {
247         auto patternStyle = AceType::MakeRefPtr<ResourceThemeStyle>(resAdapter_);
248         patternStyle->SetName(patternName);
249         patternStyle->parentStyle_ = AceType::WeakClaim(this);
250         patternStyle->rawAttrs_ = patternMap;
251         patternStyle->ParseContent();
252         attributes_[patternName] = { .type = ThemeConstantsType::PATTERN,
253             .value = RefPtr<ThemeStyle>(std::move(patternStyle)) };
254     }
255 }
256 
OnParseResourceMedia(const std::string & attrName,const std::string & attrValue)257 void ResourceThemeStyle::OnParseResourceMedia(const std::string& attrName, const std::string& attrValue)
258 {
259     std::string mediaPath;
260     if (SystemProperties::GetUnZipHap()) {
261         mediaPath = RES_PATH_TAG;
262         if (attrValue.find(RES_HAP_PREFIX) == std::string::npos) {
263             mediaPath.append(RES_HAP_PATH);
264         }
265 #ifdef PREVIEW
266         auto pos = attrValue.find(MEDIA_VALUE_PREFIX);
267         if (pos == std::string::npos) {
268             return;
269         }
270         mediaPath += attrValue.substr(pos + 1);
271 #else
272         mediaPath += attrValue;
273 #endif
274     } else {
275         // hap is not unzip, should use resource name to read file
276         auto pos = attrValue.find_last_of(MEDIA_VALUE_PREFIX);
277         if (pos == std::string::npos) {
278             LOGW("resource media invalid:[%{public}s, %{public}s]", attrName.c_str(), attrValue.c_str());
279             return;
280         }
281         mediaPath = std::string(RES_TAG) + attrValue.substr(pos + 1);
282     }
283     attributes_[attrName] = { .type = ThemeConstantsType::STRING, .value = mediaPath };
284 }
285 
CheckThemeStyleLoaded(const std::string & patternName)286 void ResourceThemeStyle::CheckThemeStyleLoaded(const std::string& patternName)
287 {
288     if (!CheckThemeStyle(patternName)) {
289         return;
290     }
291     if (future_.valid()) {
292         future_.wait_until(std::chrono::system_clock::now() + std::chrono::milliseconds(WAIT_FOR_TIME));
293     }
294 }
295 } // namespace OHOS::Ace
296