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