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