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