1 /*
2 * Copyright (c) 2021-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 #include "base/resource/ace_res_config.h"
16
17 #include <algorithm>
18 #include <cstddef>
19 #include <cstring>
20 #include <memory>
21 #include <unordered_map>
22 #include <utility>
23
24 #include "base/i18n/localization.h"
25 #include "base/log/ace_trace.h"
26 #include "base/log/log.h"
27 #include "base/resource/ace_res_data_struct.h"
28 #include "base/resource/ace_res_key_parser.h"
29 #include "base/utils/linear_map.h"
30 #include "base/utils/utils.h"
31
32 namespace OHOS::Ace {
33 namespace {
34
35 const std::unordered_map<std::string, std::string> DEFAULT_LANG {
36 { "es-419", "es-US" },
37 { "en-Qaag", "en-GB" },
38 { "en-001", "en-GB" },
39 };
40
41 const std::unordered_map<std::string, std::string> LANGUAGE_CODE_MAP {
42 { "iw", "he" },
43 { "tl", "fil" },
44 { "in", "id" },
45 };
46
ComputeScript(const AceResConfig & resConfig)47 std::string ComputeScript(const AceResConfig& resConfig)
48 {
49 return Localization::ComputeScript(resConfig.language_, resConfig.region_);
50 }
51
ConvertLocaleTagToConfig(const std::string & localeTag)52 AceResConfig ConvertLocaleTagToConfig(const std::string& localeTag)
53 {
54 std::string language, script, region;
55 Localization::ParseLocaleTag(localeTag, language, script, region, false);
56 return AceResConfig(language, script, region);
57 }
58
ConvertLocaleConfigToTag(const AceResConfig & localeConfig)59 std::string ConvertLocaleConfigToTag(const AceResConfig& localeConfig)
60 {
61 std::string localeTag = localeConfig.language_;
62 if (!localeConfig.script_.empty()) {
63 localeTag += ('-' + localeConfig.script_);
64 }
65 if (!localeConfig.region_.empty()) {
66 localeTag += ('-' + localeConfig.region_);
67 }
68 return localeTag;
69 }
70
IsPseudoLocale(const AceResConfig & resConfig)71 bool IsPseudoLocale(const AceResConfig& resConfig)
72 {
73 return (resConfig.language_ == "en" && resConfig.region_ == "XA") ||
74 (resConfig.language_ == "ar" && resConfig.region_ == "XB");
75 }
76
MatchLocaleConfig(const std::vector<AceResConfig> & candidatesLocaleConfig,const AceResConfig & deviceLocaleConfig,std::vector<AceResConfig> & matchedLocaleConfigs,bool isDeclarative=false)77 void MatchLocaleConfig(const std::vector<AceResConfig>& candidatesLocaleConfig, const AceResConfig& deviceLocaleConfig,
78 std::vector<AceResConfig>& matchedLocaleConfigs, bool isDeclarative = false)
79 {
80 std::string deviceLanguage = deviceLocaleConfig.language_;
81 std::string deviceScript = deviceLocaleConfig.script_;
82 auto iter = LANGUAGE_CODE_MAP.find(deviceLanguage);
83 if (iter != LANGUAGE_CODE_MAP.end()) {
84 deviceLanguage = iter->second;
85 }
86 for (auto& candidate : candidatesLocaleConfig) {
87 if (isDeclarative && candidate.language_ == "" && candidate.script_ == "") {
88 matchedLocaleConfigs.emplace_back(candidate);
89 continue;
90 }
91 std::string candidateLanguage = candidate.language_;
92 // Languages codes need to be specially handled.
93 auto candidateIter = LANGUAGE_CODE_MAP.find(candidateLanguage);
94 if (candidateIter != LANGUAGE_CODE_MAP.end()) {
95 candidateLanguage = candidateIter->second;
96 }
97 if (candidateLanguage != deviceLanguage) {
98 continue;
99 }
100 if (IsPseudoLocale(candidate)) {
101 if (IsPseudoLocale(deviceLocaleConfig)) {
102 matchedLocaleConfigs.emplace_back(candidate);
103 }
104 continue;
105 }
106 if (deviceLanguage == "en" && deviceScript == "Qaag") {
107 deviceScript = "Latn";
108 }
109 // Compute Script when it is not provided.
110 std::string candidateScript = candidate.script_.empty() ? ComputeScript(candidate) : candidate.script_;
111 if (deviceScript != candidateScript) {
112 continue;
113 }
114 matchedLocaleConfigs.emplace_back(candidate);
115 }
116 }
117
FindBacktrackPath(const AceResConfig & localeConfig,std::vector<std::string> & backtrackPath,const std::string & localeTag)118 void FindBacktrackPath(
119 const AceResConfig& localeConfig, std::vector<std::string>& backtrackPath, const std::string& localeTag)
120 {
121 static const std::unordered_map<std::string, std::string> LOCALE_PARENTS {
122 { "ar-DZ", "ar-015" },
123 { "ar-EH", "ar-015" },
124 { "ar-LY", "ar-015" },
125 { "ar-MA", "ar-015" },
126 { "ar-TN", "ar-015" },
127 { "zh-MO", "zh-HK" },
128 { "en-150", "en-001" },
129 { "en-AG", "en-001" },
130 { "en-AI", "en-001" },
131 { "en-AU", "en-001" },
132 { "en-BB", "en-001" },
133 { "en-BE", "en-001" },
134 { "en-BM", "en-001" },
135 { "en-BS", "en-001" },
136 { "en-BZ", "en-001" },
137 { "en-CC", "en-001" },
138 { "en-CK", "en-001" },
139 { "en-CX", "en-001" },
140 { "en-DG", "en-001" },
141 { "en-ER", "en-001" },
142 { "en-FK", "en-001" },
143 { "en-FM", "en-001" },
144 { "en-GB", "en-001" },
145 { "en-GD", "en-001" },
146 { "en-GG", "en-001" },
147 { "en-GI", "en-001" },
148 { "en-GY", "en-001" },
149 { "en-HK", "en-001" },
150 { "en-IE", "en-001" },
151 { "en-IM", "en-001" },
152 { "en-IN", "en-001" },
153 { "en-IO", "en-001" },
154 { "en-JE", "en-001" },
155 { "en-KI", "en-001" },
156 { "en-KN", "en-001" },
157 { "en-KY", "en-001" },
158 { "en-LC", "en-001" },
159 { "en-LR", "en-001" },
160 { "en-LS", "en-001" },
161 { "en-MM", "en-001" },
162 { "en-MO", "en-001" },
163 { "en-MS", "en-001" },
164 { "en-MT", "en-001" },
165 { "en-MY", "en-001" },
166 { "en-NF", "en-001" },
167 { "en-NR", "en-001" },
168 { "en-NU", "en-001" },
169 { "en-NZ", "en-001" },
170 { "en-PG", "en-001" },
171 { "en-PK", "en-001" },
172 { "en-PN", "en-001" },
173 { "en-PW", "en-001" },
174 { "en-SB", "en-001" },
175 { "en-SC", "en-001" },
176 { "en-SD", "en-001" },
177 { "en-SG", "en-001" },
178 { "en-SH", "en-001" },
179 { "en-SL", "en-001" },
180 { "en-SS", "en-001" },
181 { "en-SX", "en-001" },
182 { "en-SZ", "en-001" },
183 { "en-TC", "en-001" },
184 { "en-TK", "en-001" },
185 { "en-TT", "en-001" },
186 { "en-TV", "en-001" },
187 { "en-VC", "en-001" },
188 { "en-VG", "en-001" },
189 { "en-WS", "en-001" },
190 { "en-ZG", "en-001" },
191 { "es-AR", "es-419" },
192 { "es-BO", "es-419" },
193 { "es-BR", "es-419" },
194 { "es-BZ", "es-419" },
195 { "es-CL", "es-419" },
196 { "es-CO", "es-419" },
197 { "es-CR", "es-419" },
198 { "es-CU", "es-419" },
199 { "es-DO", "es-419" },
200 { "es-EC", "es-419" },
201 { "es-GT", "es-419" },
202 { "es-HN", "es-419" },
203 { "es-MX", "es-419" },
204 { "es-NI", "es-419" },
205 { "es-PA", "es-419" },
206 { "es-PE", "es-419" },
207 { "es-PR", "es-419" },
208 { "es-PY", "es-419" },
209 { "es-SV", "es-419" },
210 { "es-US", "es-419" },
211 { "es-UY", "es-419" },
212 { "es-VE", "es-419" },
213 { "pt-AO", "pt-PT" },
214 { "pt-CH", "pt-PT" },
215 { "pt-CV", "pt-PT" },
216 { "pt-GQ", "pt-PT" },
217 { "pt-GW", "pt-PT" },
218 { "pt-LU", "pt-PT" },
219 { "pt-MO", "pt-PT" },
220 { "pt-MZ", "pt-PT" },
221 { "pt-ST", "pt-PT" },
222 { "pt-TL", "pt-PT" },
223 };
224 if (LOCALE_PARENTS.find(localeTag) != LOCALE_PARENTS.end()) {
225 std::string curTag = LOCALE_PARENTS.find(localeTag)->second;
226 backtrackPath.emplace_back(curTag);
227 FindBacktrackPath(localeConfig, backtrackPath, curTag);
228 } else {
229 backtrackPath.emplace_back(localeConfig.language_);
230 }
231 }
232
IsOnBacktrackingPath(const std::string & bestConfigTag,const std::string & candidateConfigTag,const AceResConfig & bestLocaleConfig,const AceResConfig & candidateLocaleConfig,std::vector<std::string> backtrackPath)233 bool IsOnBacktrackingPath(const std::string& bestConfigTag, const std::string& candidateConfigTag,
234 const AceResConfig& bestLocaleConfig, const AceResConfig& candidateLocaleConfig,
235 std::vector<std::string> backtrackPath)
236 {
237 std::vector<std::string> bestConfigBacktrackPaths;
238 FindBacktrackPath(bestLocaleConfig, bestConfigBacktrackPaths, bestConfigTag);
239 std::vector<std::string> candidateConfigBacktrackPaths;
240 FindBacktrackPath(candidateLocaleConfig, candidateConfigBacktrackPaths, candidateConfigTag);
241 int32_t bestConfigIndex = -1;
242 int32_t candidateConfigIndex = -1;
243 for (std::size_t i = 0; i < backtrackPath.size(); i++) {
244 for (const auto& bestConfigPath : bestConfigBacktrackPaths) {
245 if (bestConfigPath == backtrackPath[i] && bestConfigIndex == -1) {
246 bestConfigIndex = static_cast<int32_t>(i);
247 }
248 }
249 for (const auto& candidateConfigPath : candidateConfigBacktrackPaths) {
250 if (candidateConfigPath == backtrackPath[i] && candidateConfigIndex == -1) {
251 candidateConfigIndex = static_cast<int32_t>(i);
252 }
253 }
254 }
255 if (bestConfigIndex < candidateConfigIndex) {
256 return (bestConfigIndex == -1);
257 } else if (candidateConfigIndex < bestConfigIndex) {
258 return (candidateConfigIndex != -1);
259 }
260 // Check if candidate and best are on the default area of device's backtracking path.
261 for (auto& path : backtrackPath) {
262 if (DEFAULT_LANG.find(path) != DEFAULT_LANG.end()) {
263 std::string curTag = DEFAULT_LANG.find(path)->second;
264 if (bestConfigTag == curTag) {
265 return false;
266 } else if (candidateConfigTag == curTag) {
267 return true;
268 }
269 }
270 }
271
272 // Compute the default region code through the device language code.
273 std::string language, script, region;
274 Localization::ParseLocaleTag(backtrackPath[backtrackPath.size() - 1], language, script, region, true);
275
276 if (bestLocaleConfig.region_ == region) {
277 return false;
278 }
279 if (candidateLocaleConfig.region_ == region) {
280 return true;
281 }
282
283 // If configs did not meet all the conditions above, sort the config region with dictionary order.
284 return strcmp(bestLocaleConfig.region_.c_str(), candidateLocaleConfig.region_.c_str()) >= 0;
285 }
286
IsLocaleConfigMoreSpecified(const AceResConfig & bestLocaleConfig,const AceResConfig & deviceLocaleConfig,const AceResConfig & candidateLocaleConfig)287 bool IsLocaleConfigMoreSpecified(const AceResConfig& bestLocaleConfig, const AceResConfig& deviceLocaleConfig,
288 const AceResConfig& candidateLocaleConfig)
289 {
290 // Candidates' language and script are equal with the device's after being filtered MatchLocaleConfig().
291 std::string deviceRegion = deviceLocaleConfig.region_;
292 if (bestLocaleConfig.region_ == deviceRegion) {
293 return false;
294 }
295 if (candidateLocaleConfig.region_ == deviceRegion) {
296 return true;
297 }
298 std::string deviceTag = deviceLocaleConfig.language_ + '-' + deviceLocaleConfig.region_;
299 std::vector<std::string> deviceBacktrackPath;
300 FindBacktrackPath(deviceLocaleConfig, deviceBacktrackPath, deviceTag);
301 std::string bestConfigTag = bestLocaleConfig.language_;
302 if (!bestLocaleConfig.region_.empty()) {
303 bestConfigTag += '-' + bestLocaleConfig.region_;
304 }
305 std::string candidateConfigTag = candidateLocaleConfig.language_;
306 if (!candidateLocaleConfig.region_.empty()) {
307 candidateConfigTag += '-' + candidateLocaleConfig.region_;
308 }
309 int32_t bestConfigIndex = -1;
310 int32_t candidateConfigIndex = -1;
311 for (std::size_t i = 0; i < deviceBacktrackPath.size(); i++) {
312 if (deviceBacktrackPath[i] == bestConfigTag && bestConfigIndex == -1) {
313 bestConfigIndex = static_cast<int32_t>(i);
314 }
315 if (deviceBacktrackPath[i] == candidateConfigTag && candidateConfigIndex == -1) {
316 candidateConfigIndex = static_cast<int32_t>(i);
317 }
318 }
319 if (bestConfigIndex < candidateConfigIndex) {
320 return (bestConfigIndex == -1);
321 } else if (candidateConfigIndex < bestConfigIndex) {
322 return (candidateConfigIndex != -1);
323 }
324 // Neither best nor candidate on the device's backtracking path, check if they are the default locale of the device.
325 if (candidateConfigIndex == bestConfigIndex && candidateConfigIndex == -1) {
326 std::string deviceTagWithScript = deviceLocaleConfig.language_ + "-" + deviceLocaleConfig.script_;
327 if (DEFAULT_LANG.find(deviceTagWithScript) != DEFAULT_LANG.end()) {
328 std::string defaultTag = DEFAULT_LANG.find(deviceTagWithScript)->second;
329 std::string defaultRegion = defaultTag.substr(defaultTag.find('-') + 1);
330 if (candidateLocaleConfig.region_ == defaultRegion) {
331 return true;
332 }
333 if (bestLocaleConfig.region_ == defaultRegion) {
334 return false;
335 }
336 }
337 // If they are not on the default area, continue to check the candidates' backtacking path.
338 return IsOnBacktrackingPath(
339 bestConfigTag, candidateConfigTag, bestLocaleConfig, candidateLocaleConfig, deviceBacktrackPath);
340 }
341 // Both best and candidate on the device's backtracking path with same index.
342 return false;
343 }
344
SortLocaleConfigs(std::vector<AceResConfig> & candidatesLocaleConfig,const AceResConfig & deviceLocaleConfig,int32_t left,int32_t right)345 void SortLocaleConfigs(std::vector<AceResConfig>& candidatesLocaleConfig, const AceResConfig& deviceLocaleConfig,
346 int32_t left, int32_t right)
347 {
348 if (left < right) {
349 AceResConfig bestLocaleConfig = candidatesLocaleConfig[left];
350 int32_t i = left;
351 int32_t j = right;
352 while (i < j) {
353 while (i < j &&
354 !IsLocaleConfigMoreSpecified(bestLocaleConfig, deviceLocaleConfig, candidatesLocaleConfig[j])) {
355 j--;
356 }
357 candidatesLocaleConfig[i] = candidatesLocaleConfig[j];
358 while (
359 i < j && IsLocaleConfigMoreSpecified(bestLocaleConfig, deviceLocaleConfig, candidatesLocaleConfig[i])) {
360 i++;
361 }
362 candidatesLocaleConfig[j] = candidatesLocaleConfig[i];
363 }
364 candidatesLocaleConfig[i] = bestLocaleConfig;
365 SortLocaleConfigs(candidatesLocaleConfig, deviceLocaleConfig, left, i - 1);
366 SortLocaleConfigs(candidatesLocaleConfig, deviceLocaleConfig, i + 1, right);
367 }
368 }
369
IsLowerResolutionPreferred(int32_t high,int32_t low,int32_t request)370 bool IsLowerResolutionPreferred(int32_t high, int32_t low, int32_t request)
371 {
372 if (request <= low) {
373 return true;
374 }
375
376 if (request >= high) {
377 return false;
378 }
379
380 return ((2 * low) - request) * high > request * request; // scaling down is 2x better than up
381 }
382
IsCandidateResolutionPreferred(const AceResConfig & deviceConfig,const AceResConfig & bestConfig,const AceResConfig & candidateConfig)383 bool IsCandidateResolutionPreferred(
384 const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
385 {
386 if (bestConfig.resolution_ == candidateConfig.resolution_) {
387 return false;
388 }
389
390 const ResolutionType bestRes = bestConfig.resolution_ != ResolutionType::RESOLUTION_NONE
391 ? bestConfig.resolution_
392 : ResolutionType::RESOLUTION_MDPI;
393 const ResolutionType candidateRes = candidateConfig.resolution_ != ResolutionType::RESOLUTION_NONE
394 ? candidateConfig.resolution_
395 : ResolutionType::RESOLUTION_MDPI;
396
397 if (bestRes == ResolutionType::RESOLUTION_ANY) {
398 return false;
399 } else if (candidateRes == ResolutionType::RESOLUTION_ANY) {
400 return true;
401 }
402
403 ResolutionType deviceRes = deviceConfig.resolution_;
404 if (deviceConfig.resolution_ == ResolutionType::RESOLUTION_NONE ||
405 deviceConfig.resolution_ == ResolutionType::RESOLUTION_ANY) {
406 deviceRes = ResolutionType::RESOLUTION_MDPI;
407 }
408
409 if (bestRes > candidateRes) {
410 return IsLowerResolutionPreferred(
411 static_cast<int32_t>(bestRes), static_cast<int32_t>(candidateRes), static_cast<int32_t>(deviceRes));
412 }
413
414 if (bestRes < candidateRes) {
415 return !IsLowerResolutionPreferred(
416 static_cast<int32_t>(candidateRes), static_cast<int32_t>(bestRes), static_cast<int32_t>(deviceRes));
417 }
418
419 return false;
420 }
421
IsCandidateResConfigPreferred(const AceResConfig & deviceConfig,const AceResConfig & bestConfig,const AceResConfig & candidateConfig)422 bool IsCandidateResConfigPreferred(
423 const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
424 {
425 if ((candidateConfig.mcc_ != bestConfig.mcc_) && deviceConfig.mcc_) {
426 return candidateConfig.mcc_;
427 }
428 if ((candidateConfig.mnc_ != bestConfig.mnc_) && deviceConfig.mnc_) {
429 return candidateConfig.mnc_;
430 }
431
432 if (bestConfig.orientation_ != candidateConfig.orientation_ &&
433 deviceConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
434 return candidateConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED;
435 }
436
437 if (bestConfig.colorMode_ != candidateConfig.colorMode_) {
438 return candidateConfig.colorMode_ == deviceConfig.colorMode_;
439 }
440
441 if (bestConfig.deviceType_ != DeviceType::UNKNOWN || candidateConfig.deviceType_ != DeviceType::UNKNOWN) {
442 if (bestConfig.deviceType_ != candidateConfig.deviceType_) {
443 return candidateConfig.deviceType_ != DeviceType::UNKNOWN;
444 }
445 }
446
447 return IsCandidateResolutionPreferred(deviceConfig, bestConfig, candidateConfig);
448 }
449
IsCandidateDeclarativeResConfigPreferred(const AceResConfig & deviceConfig,const AceResConfig & bestConfig,const AceResConfig & candidateConfig)450 bool IsCandidateDeclarativeResConfigPreferred(
451 const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
452 {
453 if (bestConfig.screenLong_ != candidateConfig.screenLong_ &&
454 deviceConfig.screenLong_ != LongScreenType::LONG_SCREEN_UNDEFINED) {
455 if ((bestConfig.screenLong_ == deviceConfig.screenLong_) ||
456 (candidateConfig.screenLong_ == deviceConfig.screenLong_)) {
457 return candidateConfig.screenLong_ == deviceConfig.screenLong_;
458 }
459 return candidateConfig.screenLong_ == LongScreenType::LONG_SCREEN_UNDEFINED;
460 }
461
462 if (bestConfig.screenShape_ != candidateConfig.screenShape_ &&
463 deviceConfig.screenShape_ != ScreenShape::SCREEN_SHAPE_UNDEFINED) {
464 if ((bestConfig.screenShape_ == deviceConfig.screenShape_) ||
465 (candidateConfig.screenShape_ == deviceConfig.screenShape_)) {
466 return candidateConfig.screenShape_ == deviceConfig.screenShape_;
467 }
468 return candidateConfig.screenShape_ == ScreenShape::SCREEN_SHAPE_UNDEFINED;
469 }
470
471 if (bestConfig.orientation_ != candidateConfig.orientation_ &&
472 deviceConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
473 return candidateConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED;
474 }
475
476 if (bestConfig.colorMode_ != candidateConfig.colorMode_ &&
477 deviceConfig.colorMode_ != ColorMode::COLOR_MODE_UNDEFINED) {
478 if ((bestConfig.colorMode_ == deviceConfig.colorMode_) ||
479 (candidateConfig.colorMode_ == deviceConfig.colorMode_)) {
480 return candidateConfig.colorMode_ == deviceConfig.colorMode_;
481 }
482 return candidateConfig.colorMode_ == ColorMode::COLOR_MODE_UNDEFINED;
483 }
484
485 if (bestConfig.deviceType_ != DeviceType::UNKNOWN || candidateConfig.deviceType_ != DeviceType::UNKNOWN) {
486 if (bestConfig.deviceType_ != candidateConfig.deviceType_) {
487 return candidateConfig.deviceType_ != DeviceType::UNKNOWN;
488 }
489 }
490
491 return IsCandidateResolutionPreferred(deviceConfig, bestConfig, candidateConfig);
492 }
493
IsDialectsOfEnUs(const AceResConfig & config)494 bool IsDialectsOfEnUs(const AceResConfig& config)
495 {
496 int tracebackPathLength = 0;
497 if (config.language_ == "en") {
498 std::string configTag = config.language_ + "-" + config.region_;
499 std::vector<std::string> backtrackPath;
500 backtrackPath.push_back(configTag);
501 FindBacktrackPath(config, backtrackPath, configTag);
502 tracebackPathLength = static_cast<int>(backtrackPath.size());
503 }
504 // backtracking size 2, means that the locale is an American English dialect.
505 return tracebackPathLength == 2;
506 }
507
IsBaseLanguagePreferred(const AceResConfig & deviceConfig,const AceResConfig & bestConfig,const AceResConfig & candidateConfig)508 CompareResult IsBaseLanguagePreferred(
509 const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
510 {
511 if (deviceConfig.language_ == "en" && deviceConfig.region_ == "US") {
512 if (candidateConfig.region_.length() == 0 && candidateConfig.language_.length() == 0) {
513 return (bestConfig.region_ != "US" && bestConfig.region_.length() != 0) ? CompareResult::PREFERRED
514 : CompareResult::NOT_PREFERRED;
515 }
516 if (bestConfig.region_.length() == 0 && bestConfig.language_.length() == 0) {
517 return (candidateConfig.region_ == "US" || candidateConfig.region_.length() == 0)
518 ? CompareResult::PREFERRED
519 : CompareResult::NOT_PREFERRED;
520 }
521 }
522 if (!IsDialectsOfEnUs(deviceConfig)) {
523 if (bestConfig.language_.length() == 0 && candidateConfig.language_.length() > 0) {
524 return CompareResult::PREFERRED;
525 } else if (bestConfig.language_.length() > 0 && candidateConfig.language_.length() == 0) {
526 return CompareResult::NOT_PREFERRED;
527 }
528 }
529 return CompareResult::EQUAL_RES;
530 }
531
IsCandidateDeclarativeConfigPreferred(const AceResConfig & bestConfig,const AceResConfig & deviceConfig,const AceResConfig & candidateConfig)532 bool IsCandidateDeclarativeConfigPreferred(
533 const AceResConfig& bestConfig, const AceResConfig& deviceConfig, const AceResConfig& candidateConfig)
534 {
535 if (bestConfig.language_ != candidateConfig.language_) {
536 auto isBasePreferred = IsBaseLanguagePreferred(deviceConfig, bestConfig, candidateConfig);
537 if (isBasePreferred == CompareResult::PREFERRED) {
538 return true;
539 }
540 if (isBasePreferred == CompareResult::NOT_PREFERRED) {
541 return false;
542 }
543 }
544
545 if (bestConfig.region_ != candidateConfig.region_) {
546 return IsLocaleConfigMoreSpecified(bestConfig, deviceConfig, candidateConfig);
547 }
548
549 return IsCandidateDeclarativeResConfigPreferred(deviceConfig, bestConfig, candidateConfig);
550 }
551
SortResConfigs(const AceResConfig & desiredConfig,std::vector<AceResConfig> & candidateConfigs,int32_t left,int32_t right)552 void SortResConfigs(
553 const AceResConfig& desiredConfig, std::vector<AceResConfig>& candidateConfigs, int32_t left, int32_t right)
554 {
555 if (left < right) {
556 AceResConfig bestConfig = candidateConfigs[left];
557 int32_t i = left;
558 int32_t j = right;
559 while (i < j) {
560 while (i < j && !IsCandidateResConfigPreferred(desiredConfig, bestConfig, candidateConfigs[j])) {
561 j--;
562 }
563 candidateConfigs[i] = candidateConfigs[j];
564 while (i < j && IsCandidateResConfigPreferred(desiredConfig, bestConfig, candidateConfigs[i])) {
565 i++;
566 }
567 candidateConfigs[j] = candidateConfigs[i];
568 }
569 candidateConfigs[i] = bestConfig;
570 SortResConfigs(desiredConfig, candidateConfigs, left, i - 1);
571 SortResConfigs(desiredConfig, candidateConfigs, i + 1, right);
572 }
573 }
574
SortDeclarativeResConfigs(const AceResConfig & desiredConfig,std::vector<AceResConfig> & candidateConfigs,int32_t left,int32_t right)575 void SortDeclarativeResConfigs(
576 const AceResConfig& desiredConfig, std::vector<AceResConfig>& candidateConfigs, int32_t left, int32_t right)
577 {
578 if (left < right) {
579 AceResConfig bestConfig = candidateConfigs[left];
580 int32_t i = left;
581 int32_t j = right;
582 while (i < j) {
583 while (i < j && !IsCandidateDeclarativeConfigPreferred(bestConfig, desiredConfig, candidateConfigs[j])) {
584 j--;
585 }
586 candidateConfigs[i] = candidateConfigs[j];
587 while (i < j && IsCandidateDeclarativeConfigPreferred(bestConfig, desiredConfig, candidateConfigs[i])) {
588 i++;
589 }
590 candidateConfigs[j] = candidateConfigs[i];
591 }
592 candidateConfigs[i] = bestConfig;
593 SortDeclarativeResConfigs(desiredConfig, candidateConfigs, left, i - 1);
594 SortDeclarativeResConfigs(desiredConfig, candidateConfigs, i + 1, right);
595 }
596 }
597
IsOrientationMatch(const AceResConfig & desired,const AceResConfig & supported)598 bool IsOrientationMatch(const AceResConfig& desired, const AceResConfig& supported)
599 {
600 return supported.orientation_ == DeviceOrientation::ORIENTATION_UNDEFINED ||
601 supported.orientation_ == desired.orientation_;
602 }
603
IsDeviceTypeMatch(const AceResConfig & desired,const AceResConfig & supported)604 bool IsDeviceTypeMatch(const AceResConfig& desired, const AceResConfig& supported)
605 {
606 return supported.deviceType_ == DeviceType::UNKNOWN || supported.deviceType_ == desired.deviceType_;
607 }
608
IsColorModeMatch(const AceResConfig & desired,const AceResConfig & supported)609 bool IsColorModeMatch(const AceResConfig& desired, const AceResConfig& supported)
610 {
611 return supported.colorMode_ == ColorMode::COLOR_MODE_UNDEFINED || supported.colorMode_ == desired.colorMode_;
612 }
613
IsMccMncMatch(const AceResConfig & desired,const AceResConfig & supported)614 bool IsMccMncMatch(const AceResConfig& desired, const AceResConfig& supported)
615 {
616 if (supported.mcc_ != 0 && supported.mcc_ != desired.mcc_) {
617 return false;
618 }
619 return !(supported.mnc_ != 0 && supported.mnc_ != desired.mnc_);
620 }
621
IsResolutionMatch(const AceResConfig & desired,const AceResConfig & supported)622 bool IsResolutionMatch(const AceResConfig& desired, const AceResConfig& supported)
623 {
624 return supported.resolution_ == ResolutionType::RESOLUTION_NONE || supported.resolution_ == desired.resolution_;
625 }
626
MatchResConfig(const AceResConfig & desired,const AceResConfig & supported)627 bool MatchResConfig(const AceResConfig& desired, const AceResConfig& supported)
628 {
629 return !(!IsOrientationMatch(desired, supported) || !IsDeviceTypeMatch(desired, supported) ||
630 !IsColorModeMatch(desired, supported) || !IsMccMncMatch(desired, supported) ||
631 !IsResolutionMatch(desired, supported));
632 }
633
DeclarativeMatchResConfig(const AceResConfig & desired,const AceResConfig & supported)634 bool DeclarativeMatchResConfig(const AceResConfig& desired, const AceResConfig& supported)
635 {
636 return !(!IsOrientationMatch(desired, supported) || !IsDeviceTypeMatch(desired, supported));
637 }
638
GetConfigString(KeyType type,int32_t value,std::string & buf)639 void GetConfigString(KeyType type, int32_t value, std::string& buf)
640 {
641 std::string appending;
642 if (!buf.empty()) {
643 appending = "-";
644 }
645
646 switch (type) {
647 case KeyType::ORIENTATION:
648 appending.append(
649 AceResKeyParser::GetInstance().GetOrientationByType(static_cast<DeviceOrientation>(value)));
650 break;
651 case KeyType::DEVICETYPE:
652 appending.append(AceResKeyParser::GetInstance().GetDeviceByType(static_cast<DeviceType>(value)));
653 break;
654 case KeyType::RESOLUTION:
655 appending.append(AceResKeyParser::GetInstance().GetResolutionByType(static_cast<ResolutionType>(value)));
656 break;
657 case KeyType::COLOR_MODE:
658 appending.append(AceResKeyParser::GetInstance().GetColorModeByType(static_cast<ColorMode>(value)));
659 break;
660 case KeyType::DECLARATIVE_COLOR_MODE:
661 appending.append(
662 AceResKeyParser::GetInstance().GetDeclarativeColorModeByType(static_cast<ColorMode>(value)));
663 break;
664 case KeyType::MCC:
665 appending.append(AceResKeyParser::GetInstance().GetMccByValue(value));
666 break;
667 case KeyType::MNC_SHORT_LEN:
668 appending.append(AceResKeyParser::GetInstance().GetMncShortLenByValue(value));
669 break;
670 case KeyType::MNC:
671 appending.append(AceResKeyParser::GetInstance().GetMncByValue(value));
672 break;
673 case KeyType::SCREENSHAPE:
674 appending.append(AceResKeyParser::GetInstance().GetScreenShapeByType(static_cast<ScreenShape>(value)));
675 break;
676 case KeyType::LONGSCREEN:
677 appending.append(AceResKeyParser::GetInstance().GetScreenLongByType(static_cast<LongScreenType>(value)));
678 break;
679 default:
680 break;
681 }
682
683 if (appending != "" && appending != "-") {
684 buf.append(appending);
685 }
686 }
687
688 } // namespace
689
operator ==(const AceResConfig & other) const690 bool AceResConfig::operator==(const AceResConfig& other) const
691 {
692 return language_ == other.language_ && script_ == other.script_ && region_ == other.region_ && mcc_ == other.mcc_ &&
693 mnc_ == other.mnc_ && screenLong_ == other.screenLong_ && screenShape_ == other.screenShape_ &&
694 orientation_ == other.orientation_ && colorMode_ == other.colorMode_ && deviceType_ == other.deviceType_ &&
695 resolution_ == other.resolution_;
696 }
697
GetLocaleFallback(const std::string & localeTag,const std::vector<std::string> & localeList)698 std::vector<std::string> AceResConfig::GetLocaleFallback(
699 const std::string& localeTag, const std::vector<std::string>& localeList)
700 {
701 ACE_SCOPED_TRACE("GetLocaleFallback");
702 std::vector<std::string> fileList;
703 AceResConfig::MatchAndSortI18nConfigs(localeList, localeTag, fileList);
704 return fileList;
705 }
706
GetResourceFallback(const std::vector<std::string> & resourceList)707 std::vector<std::string> AceResConfig::GetResourceFallback(const std::vector<std::string>& resourceList)
708 {
709 ACE_SCOPED_TRACE("GetResourceFallback");
710 std::string deviceConfigTag = GetCurrentDeviceResTag();
711 std::vector<std::string> fileList;
712 AceResConfig::MatchAndSortResConfigs(resourceList, deviceConfigTag, fileList);
713 return fileList;
714 }
715
GetStyleResourceFallback(const std::vector<std::string> & resourceList)716 std::vector<std::string> AceResConfig::GetStyleResourceFallback(const std::vector<std::string>& resourceList)
717 {
718 std::vector<std::string> fileList;
719 std::string deviceConfigTag = GetCurrentDeviceResTag();
720 AceResConfig::MatchAndSortStyleResConfigs(resourceList, deviceConfigTag, fileList);
721 return fileList;
722 }
723
GetDeclarativeResourceFallback(const std::set<std::string> & resourceFolderList)724 std::vector<std::string> AceResConfig::GetDeclarativeResourceFallback(const std::set<std::string>& resourceFolderList)
725 {
726 std::string deviceConfigTag = GetCurrentDeviceDeclarativeResTag();
727 std::vector<std::string> folderList;
728 AceResConfig::MatchAndSortDeclarativeResConfigs(resourceFolderList, deviceConfigTag, folderList);
729 return folderList;
730 }
731
GetCurrentDeviceResTag()732 std::string AceResConfig::GetCurrentDeviceResTag()
733 {
734 ResolutionType resolutionType = AceResConfig::GetResolutionType(SystemProperties::GetResolution());
735 AceResConfig deviceResConfig = AceResConfig(SystemProperties::GetMcc(), SystemProperties::GetMnc(),
736 SystemProperties::GetDeviceOrientation(), SystemProperties::GetColorMode(),
737 (SystemProperties::GetParamDeviceType() == "tablet" || SystemProperties::GetParamDeviceType() == "2in1")
738 ? DeviceType::TABLET
739 : SystemProperties::GetDeviceType(),
740 resolutionType);
741 return AceResConfig::ConvertResConfigToTag(deviceResConfig, false);
742 }
743
GetCurrentDeviceDeclarativeResTag()744 std::string AceResConfig::GetCurrentDeviceDeclarativeResTag()
745 {
746 auto localeTag = Localization::GetInstance()->GetLanguageTag();
747 std::string language, script, region;
748 Localization::ParseLocaleTag(localeTag, language, script, region, false);
749
750 ResolutionType resolutionType = AceResConfig::GetResolutionType(SystemProperties::GetResolution());
751 LongScreenType longScreenType = AceResConfig::GetLongScreenType(SystemProperties::GetResolution());
752 AceResConfig deviceResConfig;
753
754 deviceResConfig = AceResConfig(language, script, region, longScreenType, SystemProperties::GetScreenShape(),
755 SystemProperties::GetDeviceOrientation(), SystemProperties::GetColorMode(),
756 (SystemProperties::GetParamDeviceType() == "tablet" || SystemProperties::GetParamDeviceType() == "2in1")
757 ? DeviceType::TABLET
758 : SystemProperties::GetDeviceType(),
759 resolutionType);
760
761 return AceResConfig::ConvertDeclarativeResConfigToTag(deviceResConfig);
762 }
763
GetTargetMediaScaleRatio(const std::string & targetResTag)764 double AceResConfig::GetTargetMediaScaleRatio(const std::string& targetResTag)
765 {
766 std::string deviceConfigTag = GetCurrentDeviceDeclarativeResTag();
767 auto deviceConfig = AceResConfig::ConvertDeclarativeResTagToConfig(deviceConfigTag);
768 ResolutionType deviceResolution = (deviceConfig.resolution_ != ResolutionType::RESOLUTION_NONE)
769 ? deviceConfig.resolution_
770 : ResolutionType::RESOLUTION_MDPI;
771
772 ResolutionType targetResolution;
773 if (targetResTag == "default") {
774 targetResolution = ResolutionType::RESOLUTION_MDPI;
775 } else {
776 AceResConfig targetConfig = AceResConfig::ConvertDeclarativeResTagToConfig(targetResTag);
777 targetResolution = (targetConfig.resolution_ != ResolutionType::RESOLUTION_NONE)
778 ? targetConfig.resolution_
779 : ResolutionType::RESOLUTION_MDPI;
780 }
781
782 return static_cast<double>(deviceResolution) / static_cast<double>(targetResolution);
783 }
784
MatchAndSortI18nConfigs(const std::vector<std::string> & candidatesFiles,const std::string & devicesLocaleTag,std::vector<std::string> & fileList)785 void AceResConfig::MatchAndSortI18nConfigs(const std::vector<std::string>& candidatesFiles,
786 const std::string& devicesLocaleTag, std::vector<std::string>& fileList)
787 {
788 std::vector<AceResConfig> candidateLocaleConfigs;
789 for (auto& file : candidatesFiles) {
790 AceResConfig LocaleConfig = ConvertLocaleTagToConfig(file);
791 if (file == ConvertLocaleConfigToTag(LocaleConfig)) {
792 candidateLocaleConfigs.emplace_back(LocaleConfig);
793 }
794 }
795 AceResConfig deviceLocaleConfig = ConvertLocaleTagToConfig(devicesLocaleTag);
796 // Compute Script when it is not provided.
797 if (deviceLocaleConfig.script_.empty()) {
798 deviceLocaleConfig.script_ = ComputeScript(deviceLocaleConfig);
799 }
800 std::vector<AceResConfig> matchedLocaleConfigs;
801 MatchLocaleConfig(candidateLocaleConfigs, deviceLocaleConfig, matchedLocaleConfigs);
802 int32_t left = 0;
803 int32_t right = static_cast<int32_t>(matchedLocaleConfigs.size()) - 1;
804 SortLocaleConfigs(matchedLocaleConfigs, deviceLocaleConfig, left, right);
805 bool existDefault = false;
806 for (const auto& matchedLocaleConfig : matchedLocaleConfigs) {
807 std::string localeConfigTag = ConvertLocaleConfigToTag(matchedLocaleConfig);
808 if (localeConfigTag == "en-US") {
809 existDefault = true;
810 }
811 fileList.emplace_back(localeConfigTag);
812 }
813
814 if (!existDefault) {
815 fileList.emplace_back("en-US");
816 }
817 }
818
MatchAndSortResConfigs(const std::vector<std::string> & candidateFiles,const std::string & deviceResTag,std::vector<std::string> & matchedFileList,bool styleRes)819 void AceResConfig::MatchAndSortResConfigs(const std::vector<std::string>& candidateFiles,
820 const std::string& deviceResTag, std::vector<std::string>& matchedFileList, bool styleRes)
821 {
822 std::vector<AceResConfig> candidateResConfigs;
823 for (auto& file : candidateFiles) {
824 AceResConfig ResConfig = ConvertResTagToConfig(file, styleRes);
825 if (file == ConvertResConfigToTag(ResConfig, styleRes)) {
826 candidateResConfigs.emplace_back(ResConfig);
827 }
828 }
829
830 AceResConfig deviceResConfig = ConvertResTagToConfig(deviceResTag, false);
831 int32_t candidateConfigSize = static_cast<int32_t>(candidateResConfigs.size());
832 std::vector<AceResConfig> matchedResConfigs;
833 for (auto i = 0; i < candidateConfigSize; i++) {
834 if (!MatchResConfig(deviceResConfig, candidateResConfigs[i])) {
835 continue;
836 } else {
837 matchedResConfigs.emplace_back(candidateResConfigs[i]);
838 }
839 }
840 int32_t left = 0;
841 int32_t right = static_cast<int32_t>(matchedResConfigs.size()) - 1;
842 SortResConfigs(deviceResConfig, matchedResConfigs, left, right);
843 for (const auto& matchedConfig : matchedResConfigs) {
844 matchedFileList.emplace_back(ConvertResConfigToTag(matchedConfig, styleRes));
845 }
846
847 if (styleRes) {
848 matchedFileList.emplace_back("default");
849 } else {
850 matchedFileList.emplace_back("res-defaults");
851 }
852 }
853
MatchAndSortStyleResConfigs(const std::vector<std::string> & candidateFiles,const std::string & deviceResTag,std::vector<std::string> & matchedFileList)854 void AceResConfig::MatchAndSortStyleResConfigs(const std::vector<std::string>& candidateFiles,
855 const std::string& deviceResTag, std::vector<std::string>& matchedFileList)
856 {
857 MatchAndSortResConfigs(candidateFiles, deviceResTag, matchedFileList, true);
858 }
859
MatchAndSortDeclarativeResConfigs(const std::set<std::string> & candidateFolders,const std::string & deviceConfigTag,std::vector<std::string> & matchedFoldersList)860 void AceResConfig::MatchAndSortDeclarativeResConfigs(const std::set<std::string>& candidateFolders,
861 const std::string& deviceConfigTag, std::vector<std::string>& matchedFoldersList)
862 {
863 std::vector<AceResConfig> candidateResConfigs;
864 for (auto& folder : candidateFolders) {
865 if (folder == "default") {
866 continue;
867 }
868 AceResConfig resConfig = ConvertDeclarativeResTagToConfig(folder);
869 if (folder == ConvertDeclarativeResConfigToTag(resConfig)) {
870 candidateResConfigs.emplace_back(resConfig);
871 }
872 }
873
874 AceResConfig deviceResConfig = ConvertDeclarativeResTagToConfig(deviceConfigTag);
875 // Compute Script when it is not provided.
876 if (deviceResConfig.script_.empty()) {
877 deviceResConfig.script_ = ComputeScript(deviceResConfig);
878 }
879
880 std::vector<AceResConfig> matchedLocaleConfigs;
881 MatchLocaleConfig(candidateResConfigs, deviceResConfig, matchedLocaleConfigs, true);
882 int32_t candidateConfigSize = static_cast<int32_t>(matchedLocaleConfigs.size());
883 std::vector<AceResConfig> matchedResConfigs;
884 for (auto i = 0; i < candidateConfigSize; i++) {
885 if (!DeclarativeMatchResConfig(deviceResConfig, matchedLocaleConfigs[i])) {
886 continue;
887 } else {
888 matchedResConfigs.emplace_back(matchedLocaleConfigs[i]);
889 }
890 }
891
892 int32_t left = 0;
893 int32_t right = static_cast<int32_t>(matchedResConfigs.size()) - 1;
894 SortDeclarativeResConfigs(deviceResConfig, matchedResConfigs, left, right);
895 for (const auto& matchedConfig : matchedResConfigs) {
896 matchedFoldersList.emplace_back(ConvertDeclarativeResConfigToTag(matchedConfig));
897 }
898
899 matchedFoldersList.emplace_back("default");
900 }
901
ParseConfig(const std::vector<KeyParam> & keyParams)902 bool AceResConfig::ParseConfig(const std::vector<KeyParam>& keyParams)
903 {
904 for (auto keyParam : keyParams) {
905 switch (keyParam.keyType) {
906 case KeyType::RESOLUTION:
907 resolution_ = static_cast<ResolutionType>(keyParam.value);
908 break;
909 case KeyType::ORIENTATION:
910 orientation_ = static_cast<DeviceOrientation>(keyParam.value);
911 break;
912 case KeyType::DEVICETYPE:
913 deviceType_ = static_cast<DeviceType>(keyParam.value);
914 break;
915 case KeyType::DECLARATIVE_COLOR_MODE:
916 case KeyType::COLOR_MODE:
917 colorMode_ = static_cast<ColorMode>(keyParam.value);
918 break;
919 case KeyType::MCC:
920 mcc_ = keyParam.value;
921 break;
922 case KeyType::MNC:
923 mnc_ = keyParam.value;
924 break;
925 case KeyType::MNC_SHORT_LEN:
926 mnc_ = keyParam.value;
927 mncShortLen_ = true;
928 break;
929 case KeyType::SCREENSHAPE:
930 screenShape_ = static_cast<ScreenShape>(keyParam.value);
931 break;
932 case KeyType::LONGSCREEN:
933 screenLong_ = static_cast<LongScreenType>(keyParam.value);
934 break;
935 default:
936 LOGE("unknown KeyType:%{public}d", keyParam.keyType);
937 break;
938 }
939 }
940 return true;
941 }
942
GetResolutionType(double resolution)943 ResolutionType AceResConfig::GetResolutionType(double resolution)
944 {
945 static const LinearEnumMapNode<ResolutionType, bool (*)(double)> resolutionMap[] = {
946 { ResolutionType::RESOLUTION_LDPI,
947 [](double resolution) { return GreatNotEqual(resolution, 0.0) && LessNotEqual(resolution, 0.875); } },
948 { ResolutionType::RESOLUTION_MDPI,
949 [](double resolution) { return GreatOrEqual(resolution, 0.875) && LessNotEqual(resolution, 1.25); } },
950 { ResolutionType::RESOLUTION_HDPI,
951 [](double resolution) { return GreatOrEqual(resolution, 1.25) && LessNotEqual(resolution, 1.75); } },
952 { ResolutionType::RESOLUTION_XHDPI,
953 [](double resolution) { return GreatOrEqual(resolution, 1.75) && LessNotEqual(resolution, 2.5); } },
954 { ResolutionType::RESOLUTION_XXHDPI,
955 [](double resolution) { return GreatOrEqual(resolution, 2.5) && LessNotEqual(resolution, 3.5); } },
956 { ResolutionType::RESOLUTION_XXXHDPI, [](double resolution) { return GreatOrEqual(resolution, 3.5); } },
957 };
958
959 for (const auto& idx : resolutionMap) {
960 if (idx.value(resolution)) {
961 return idx.key;
962 }
963 }
964 return ResolutionType::RESOLUTION_MDPI;
965 }
966
GetLongScreenType(double resolution)967 LongScreenType AceResConfig::GetLongScreenType(double resolution)
968 {
969 if (GreatNotEqual(resolution, 1.5)) {
970 return LongScreenType::LONG;
971 } else if (GreatNotEqual(resolution, 0.0) && LessOrEqual(resolution, 1.5)) {
972 return LongScreenType::NOT_LONG;
973 }
974
975 return LongScreenType::NOT_LONG;
976 }
977
ConvertResTagToConfig(const std::string & deviceResConfigTag,bool styleRes)978 AceResConfig AceResConfig::ConvertResTagToConfig(const std::string& deviceResConfigTag, bool styleRes)
979 {
980 AceResConfig resConfig;
981 std::vector<KeyParam> keyParams;
982 bool parseSucceed = AceResKeyParser::GetInstance().Parse(deviceResConfigTag, keyParams, styleRes);
983 if (parseSucceed) {
984 resConfig.ParseConfig(keyParams);
985 }
986 return resConfig;
987 }
988
ConvertDeclarativeResTagToConfig(const std::string & deviceResConfigTag)989 AceResConfig AceResConfig::ConvertDeclarativeResTagToConfig(const std::string& deviceResConfigTag)
990 {
991 AceResConfig resConfig;
992 std::vector<KeyParam> keyParams;
993 if (deviceResConfigTag.find_first_of("-") == std::string::npos) {
994 if (deviceResConfigTag.find_first_of("_") == std::string::npos) {
995 bool parseSucceed = AceResKeyParser::GetInstance().DeclarativeParse(deviceResConfigTag, keyParams);
996 if (parseSucceed) {
997 resConfig = AceResConfig("", "", "");
998 resConfig.ParseConfig(keyParams);
999 return resConfig;
1000 }
1001 }
1002
1003 std::string tempResTag(deviceResConfigTag);
1004 std::replace(tempResTag.begin(), tempResTag.end(), '_', '-');
1005 std::string language, script, region;
1006 Localization::ParseLocaleTag(tempResTag, language, script, region, false);
1007 resConfig = AceResConfig(language, script, region);
1008
1009 return resConfig;
1010 }
1011
1012 resConfig = AceResConfig("", "", "");
1013 bool parseSucceed = AceResKeyParser::GetInstance().DeclarativeParse(deviceResConfigTag, keyParams);
1014 if (parseSucceed) {
1015 resConfig.ParseConfig(keyParams);
1016 return resConfig;
1017 }
1018
1019 std::string localeTag = deviceResConfigTag.substr(0, deviceResConfigTag.find_first_of("-"));
1020 std::string resConfigTag = deviceResConfigTag.substr(deviceResConfigTag.find_first_of("-"));
1021 std::replace(localeTag.begin(), localeTag.end(), '_', '-');
1022
1023 std::string language, script, region;
1024 Localization::ParseLocaleTag(localeTag, language, script, region, false);
1025 resConfig = AceResConfig(language, script, region);
1026
1027 parseSucceed = AceResKeyParser::GetInstance().DeclarativeParse(resConfigTag, keyParams);
1028 if (parseSucceed) {
1029 resConfig.ParseConfig(keyParams);
1030 }
1031
1032 return resConfig;
1033 }
1034
ConvertResConfigToTag(const AceResConfig & resConfig,bool styleRes)1035 std::string AceResConfig::ConvertResConfigToTag(const AceResConfig& resConfig, bool styleRes)
1036 {
1037 std::string resTag;
1038 if (!styleRes) {
1039 resTag = "res";
1040 }
1041 if (resConfig.mcc_ != MCC_UNDEFINED && resConfig.mnc_ != MNC_UNDEFINED) {
1042 GetConfigString(KeyType::MCC, resConfig.mcc_, resTag);
1043 if (resConfig.mncShortLen_) {
1044 GetConfigString(KeyType::MNC_SHORT_LEN, resConfig.mnc_, resTag);
1045 } else {
1046 GetConfigString(KeyType::MNC, resConfig.mnc_, resTag);
1047 }
1048 }
1049
1050 if (resConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
1051 GetConfigString(KeyType::ORIENTATION, static_cast<int32_t>(resConfig.orientation_), resTag);
1052 }
1053
1054 if (resConfig.colorMode_ != ColorMode::COLOR_MODE_UNDEFINED) {
1055 GetConfigString(KeyType::COLOR_MODE, static_cast<int32_t>(resConfig.colorMode_), resTag);
1056 }
1057
1058 if (resConfig.deviceType_ != DeviceType::UNKNOWN) {
1059 GetConfigString(KeyType::DEVICETYPE, static_cast<int32_t>(resConfig.deviceType_), resTag);
1060 }
1061
1062 if (resConfig.resolution_ != ResolutionType::RESOLUTION_NONE) {
1063 GetConfigString(KeyType::RESOLUTION, static_cast<int32_t>(resConfig.resolution_), resTag);
1064 }
1065 return resTag;
1066 }
1067
ConvertDeclarativeResConfigToTag(const AceResConfig & resConfig)1068 std::string AceResConfig::ConvertDeclarativeResConfigToTag(const AceResConfig& resConfig)
1069 {
1070 std::string resTag = resConfig.language_;
1071 if (!resConfig.script_.empty()) {
1072 resTag += ('_' + resConfig.script_);
1073 }
1074 if (!resConfig.region_.empty()) {
1075 resTag += ('_' + resConfig.region_);
1076 }
1077
1078 if (resConfig.screenLong_ != LongScreenType::LONG_SCREEN_UNDEFINED) {
1079 GetConfigString(KeyType::LONGSCREEN, static_cast<int32_t>(resConfig.screenLong_), resTag);
1080 }
1081
1082 if (resConfig.screenShape_ != ScreenShape::SCREEN_SHAPE_UNDEFINED) {
1083 GetConfigString(KeyType::SCREENSHAPE, static_cast<int32_t>(resConfig.screenShape_), resTag);
1084 }
1085
1086 if (resConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
1087 GetConfigString(KeyType::ORIENTATION, static_cast<int32_t>(resConfig.orientation_), resTag);
1088 }
1089
1090 if (resConfig.colorMode_ != ColorMode::COLOR_MODE_UNDEFINED) {
1091 GetConfigString(KeyType::DECLARATIVE_COLOR_MODE, static_cast<int32_t>(resConfig.colorMode_), resTag);
1092 }
1093
1094 if (resConfig.deviceType_ != DeviceType::UNKNOWN) {
1095 GetConfigString(KeyType::DEVICETYPE, static_cast<int32_t>(resConfig.deviceType_), resTag);
1096 }
1097
1098 if (resConfig.resolution_ != ResolutionType::RESOLUTION_NONE) {
1099 GetConfigString(KeyType::RESOLUTION, static_cast<int32_t>(resConfig.resolution_), resTag);
1100 }
1101 return resTag;
1102 }
1103
1104 } // namespace OHOS::Ace