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 "res_config_impl.h"
16 #ifdef SUPPORT_GRAPHICS
17 #include <unicode/localebuilder.h>
18 #include <unicode/locid.h>
19 #include <unicode/utypes.h>
20 #endif
21 #include "locale_matcher.h"
22 #include "res_locale.h"
23 #include "utils/utils.h"
24 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
25 #include "parameters.h"
26 #endif
27
28 #ifdef SUPPORT_GRAPHICS
29 using icu::Locale;
30 using icu::LocaleBuilder;
31 #endif
32 namespace OHOS {
33 namespace Global {
34 namespace Resource {
35 const std::string PROPERTY_DEVICE_TYPE = "const.product.devicetype";
36 const std::string PROPERTY_SUPPORT_APP_TYPES = "const.bms.supportAppTypes";
37 const std::string PROPERTY_DEVICE_TYPE_DEFAULT = "default";
38
39 static const std::vector<std::pair<float, ScreenDensity>> resolutions = {
40 { 0.0, ScreenDensity::SCREEN_DENSITY_NOT_SET },
41 { 120.0, ScreenDensity::SCREEN_DENSITY_SDPI },
42 { 160.0, ScreenDensity::SCREEN_DENSITY_MDPI },
43 { 240.0, ScreenDensity::SCREEN_DENSITY_LDPI },
44 { 320.0, ScreenDensity::SCREEN_DENSITY_XLDPI },
45 { 480.0, ScreenDensity::SCREEN_DENSITY_XXLDPI },
46 { 640.0, ScreenDensity::SCREEN_DENSITY_XXXLDPI },
47 };
48
ResConfigImpl()49 ResConfigImpl::ResConfigImpl()
50 : resLocale_(nullptr),
51 direction_(DIRECTION_NOT_SET),
52 density_(SCREEN_DENSITY_NOT_SET),
53 screenDensityDpi_(SCREEN_DENSITY_NOT_SET),
54 colorMode_(LIGHT),
55 mcc_(MCC_UNDEFINED),
56 mnc_(MNC_UNDEFINED),
57 deviceType_(DEVICE_NOT_SET),
58 inputDevice_(INPUTDEVICE_NOT_SET),
59 #ifdef SUPPORT_GRAPHICS
60 resPreferredLocale_(nullptr),
61 preferredLocaleInfo_(nullptr),
62 localeInfo_(nullptr),
63 #endif
64 themeId_(0),
65 isCompletedScript_(false),
66 isAppColorMode_(false),
67 isAppDarkRes_(false),
68 isThemeIcon_(false)
69 {}
70
71 #ifdef SUPPORT_GRAPHICS
SetPreferredLocaleInfo(Locale & preferredLocaleInfo)72 RState ResConfigImpl::SetPreferredLocaleInfo(Locale &preferredLocaleInfo)
73 {
74 const char *language = preferredLocaleInfo.getLanguage();
75 const char *script = preferredLocaleInfo.getScript();
76 const char *region = preferredLocaleInfo.getCountry();
77 if (Utils::IsStrEmpty(language)) {
78 if (this->resPreferredLocale_ != nullptr) {
79 delete this->resPreferredLocale_;
80 this->resPreferredLocale_ = nullptr;
81 }
82
83 if (this->preferredLocaleInfo_ != nullptr) {
84 delete this->preferredLocaleInfo_;
85 this->preferredLocaleInfo_ = nullptr;
86 }
87 return SUCCESS;
88 }
89 RState state = BuildResLocale(language, script, region, &this->resPreferredLocale_);
90 if (state != SUCCESS) {
91 return state;
92 }
93 return BuildLocaleInfo(this->resPreferredLocale_, &this->preferredLocaleInfo_);
94 }
95
SetLocaleInfo(Locale & localeInfo)96 RState ResConfigImpl::SetLocaleInfo(Locale &localeInfo)
97 {
98 return this->SetLocaleInfo(localeInfo.getLanguage(), localeInfo.getScript(), localeInfo.getCountry());
99 }
100
BuildResLocale(const char * language,const char * script,const char * region,ResLocale ** resLocale)101 RState ResConfigImpl::BuildResLocale(const char *language, const char *script,
102 const char *region, ResLocale **resLocale)
103 {
104 RState state = SUCCESS;
105 ResLocale *temp = ResLocale::BuildFromParts(language, script, region, state);
106 if (state != SUCCESS) {
107 return state;
108 }
109 if (script == nullptr || script[0] == '\0') {
110 if (!LocaleMatcher::Normalize(temp)) {
111 delete temp;
112 temp = nullptr;
113 return NOT_ENOUGH_MEM;
114 }
115 }
116 if (*resLocale != nullptr) {
117 delete *resLocale;
118 *resLocale = nullptr;
119 }
120 *resLocale = temp;
121 return state;
122 }
123
BuildLocaleInfo(const ResLocale * resLocale,Locale ** localeInfo)124 RState ResConfigImpl::BuildLocaleInfo(const ResLocale *resLocale, Locale **localeInfo)
125 {
126 UErrorCode errCode = U_ZERO_ERROR;
127 Locale temp = icu::LocaleBuilder().setLanguage(resLocale->GetLanguage())
128 .setRegion(resLocale->GetRegion()).setScript(resLocale->GetScript()).build(errCode);
129 if (!U_SUCCESS(errCode)) {
130 return NOT_ENOUGH_MEM;
131 }
132 if (*localeInfo != nullptr) {
133 delete *localeInfo;
134 *localeInfo = nullptr;
135 }
136 *localeInfo = new Locale(temp);
137 return SUCCESS;
138 }
139 #endif
140
SetLocaleInfo(const char * localeStr)141 RState ResConfigImpl::SetLocaleInfo(const char* localeStr)
142 {
143 #ifdef SUPPORT_GRAPHICS
144 icu::Locale localeInfo(localeStr);
145 return this->SetLocaleInfo(localeInfo);
146 #endif
147 return SUCCESS;
148 }
149
SetLocaleInfo(const char * language,const char * script,const char * region)150 RState ResConfigImpl::SetLocaleInfo(const char *language,
151 const char *script,
152 const char *region)
153 {
154 #ifdef SUPPORT_GRAPHICS
155 RState state = SUCCESS;
156 if (Utils::IsStrEmpty(language)) {
157 delete this->resLocale_;
158 delete this->localeInfo_;
159 this->resLocale_ = nullptr;
160 this->localeInfo_ = nullptr;
161 return state;
162 }
163 this->isCompletedScript_ = false;
164 state = BuildResLocale(language, script, region, &this->resLocale_);
165 if (state != SUCCESS) {
166 return state;
167 }
168 state = BuildLocaleInfo(this->resLocale_, &this->localeInfo_);
169 if (state != SUCCESS) {
170 return state;
171 }
172 this->isCompletedScript_ = true;
173 return state;
174 #else
175 return NOT_SUPPORT_SEP;
176 #endif
177 }
178
SetDeviceType(DeviceType deviceType)179 void ResConfigImpl::SetDeviceType(DeviceType deviceType)
180 {
181 this->deviceType_ = deviceType;
182 }
183
SetDirection(Direction direction)184 void ResConfigImpl::SetDirection(Direction direction)
185 {
186 this->direction_ = direction;
187 }
188
SetColorMode(ColorMode colorMode)189 void ResConfigImpl::SetColorMode(ColorMode colorMode)
190 {
191 this->colorMode_ = colorMode;
192 }
193
SetInputDevice(InputDevice inputDevice)194 void ResConfigImpl::SetInputDevice(InputDevice inputDevice)
195 {
196 this->inputDevice_ = inputDevice;
197 }
198
SetMcc(uint32_t mcc)199 void ResConfigImpl::SetMcc(uint32_t mcc)
200 {
201 this->mcc_ = mcc;
202 }
203
SetMnc(uint32_t mnc)204 void ResConfigImpl::SetMnc(uint32_t mnc)
205 {
206 this->mnc_ = mnc;
207 }
208
SetThemeId(uint32_t themeId)209 void ResConfigImpl::SetThemeId(uint32_t themeId)
210 {
211 this->themeId_ = themeId;
212 }
213
SetThemeIcon(bool isIcon)214 void ResConfigImpl::SetThemeIcon(bool isIcon)
215 {
216 this->isThemeIcon_ = isIcon;
217 }
218
ConvertDensity(float density)219 ScreenDensity ResConfigImpl::ConvertDensity(float density)
220 {
221 float deviceDpi = density * Utils::DPI_BASE;
222 auto resolution = SCREEN_DENSITY_NOT_SET;
223 for (const auto& [dpi, value] : resolutions) {
224 resolution = value;
225 if (deviceDpi <= dpi) {
226 break;
227 }
228 }
229 return resolution;
230 }
231
SetScreenDensity(float screenDensity)232 void ResConfigImpl::SetScreenDensity(float screenDensity)
233 {
234 this->density_ = screenDensity;
235 this->screenDensityDpi_ = ConvertDensity(screenDensity);
236 }
237
SetScreenDensityDpi(ScreenDensity screenDensityDpi)238 void ResConfigImpl::SetScreenDensityDpi(ScreenDensity screenDensityDpi)
239 {
240 this->density_ = screenDensityDpi / Utils::DPI_BASE;
241 this->screenDensityDpi_ = screenDensityDpi;
242 }
243
244 #ifdef SUPPORT_GRAPHICS
GetResPreferredLocale() const245 const ResLocale *ResConfigImpl::GetResPreferredLocale() const
246 {
247 return this->resPreferredLocale_;
248 }
249
GetPreferredLocaleInfo() const250 const Locale *ResConfigImpl::GetPreferredLocaleInfo() const
251 {
252 return this->preferredLocaleInfo_;
253 }
254
GetLocaleInfo() const255 const Locale *ResConfigImpl::GetLocaleInfo() const
256 {
257 return localeInfo_;
258 }
259 #endif
260
GetResLocale() const261 const ResLocale *ResConfigImpl::GetResLocale() const
262 {
263 return this->resLocale_;
264 }
265
GetDirection() const266 Direction ResConfigImpl::GetDirection() const
267 {
268 return this->direction_;
269 }
270
GetScreenDensity() const271 float ResConfigImpl::GetScreenDensity() const
272 {
273 return this->density_;
274 }
275
GetScreenDensityDpi() const276 ScreenDensity ResConfigImpl::GetScreenDensityDpi() const
277 {
278 return this->screenDensityDpi_;
279 }
280
GetColorMode() const281 ColorMode ResConfigImpl::GetColorMode() const
282 {
283 return this->colorMode_;
284 }
285
GetInputDevice() const286 InputDevice ResConfigImpl::GetInputDevice() const
287 {
288 return this->inputDevice_;
289 }
290
GetMcc() const291 uint32_t ResConfigImpl::GetMcc() const
292 {
293 return this->mcc_;
294 }
295
GetMnc() const296 uint32_t ResConfigImpl::GetMnc() const
297 {
298 return this->mnc_;
299 }
300
GetThemeId() const301 uint32_t ResConfigImpl::GetThemeId() const
302 {
303 return this->themeId_;
304 }
305
GetThemeIcon() const306 bool ResConfigImpl::GetThemeIcon() const
307 {
308 return this->isThemeIcon_;
309 }
310
GetDeviceType() const311 DeviceType ResConfigImpl::GetDeviceType() const
312 {
313 return this->deviceType_;
314 }
315
316 #ifdef SUPPORT_GRAPHICS
CopyLocale(Locale ** currentLocaleInfo,ResLocale ** currentResLocale,const Locale * otherLocaleInfo)317 bool ResConfigImpl::CopyLocale(Locale **currentLocaleInfo, ResLocale **currentResLocale,
318 const Locale *otherLocaleInfo)
319 {
320 bool needCopy = false;
321 if (*currentLocaleInfo == nullptr && otherLocaleInfo != nullptr) {
322 needCopy = true;
323 }
324 if (*currentLocaleInfo != nullptr && otherLocaleInfo == nullptr) {
325 delete *currentResLocale;
326 delete *currentLocaleInfo;
327 *currentResLocale = nullptr;
328 *currentLocaleInfo = nullptr;
329 return true;
330 }
331 if (*currentResLocale != nullptr && otherLocaleInfo != nullptr) {
332 uint64_t encodedLocale = Utils::EncodeLocale(
333 (*currentResLocale)->GetLanguage(),
334 (*currentResLocale)->GetScript(), (*currentResLocale)->GetRegion());
335 uint64_t otherEncodedLocale = Utils::EncodeLocale(
336 otherLocaleInfo->getLanguage(),
337 otherLocaleInfo->getScript(), otherLocaleInfo->getCountry());
338 if (encodedLocale != otherEncodedLocale) {
339 needCopy = true;
340 }
341 }
342 if (needCopy) {
343 ResLocale *temp = new(std::nothrow) ResLocale;
344 if (temp == nullptr) {
345 return false;
346 }
347 RState rs = temp->CopyFromLocaleInfo(otherLocaleInfo);
348 if (rs != SUCCESS) {
349 delete temp;
350 return false;
351 }
352 UErrorCode errCode = U_ZERO_ERROR;
353 Locale tempLocale = icu::LocaleBuilder().setLocale(*otherLocaleInfo).build(errCode);
354
355 if (!U_SUCCESS(errCode)) {
356 delete temp;
357 return false;
358 }
359 delete *currentResLocale;
360 delete *currentLocaleInfo;
361 *currentResLocale = temp;
362 *currentLocaleInfo = new Locale(tempLocale);
363 }
364 return true;
365 }
366 #endif
367
368 #ifdef SUPPORT_GRAPHICS
CopyPreferredLocale(const ResConfig & other)369 bool ResConfigImpl::CopyPreferredLocale(const ResConfig &other)
370 {
371 return CopyLocale(&this->preferredLocaleInfo_, &this->resPreferredLocale_, other.GetPreferredLocaleInfo());
372 }
373 #endif
374
CopyLocale(const ResConfig & other)375 bool ResConfigImpl::CopyLocale(const ResConfig &other)
376 {
377 #ifdef SUPPORT_GRAPHICS
378 return CopyLocale(&this->localeInfo_, &this->resLocale_, other.GetLocaleInfo());
379 #else
380 return false;
381 #endif
382 }
383
isLocaleInfoSet()384 bool ResConfigImpl::isLocaleInfoSet()
385 {
386 #ifdef SUPPORT_GRAPHICS
387 return localeInfo_ != nullptr;
388 #endif
389 return false;
390 }
391
CopyLocaleAndPreferredLocale(const ResConfig & other)392 bool ResConfigImpl::CopyLocaleAndPreferredLocale(const ResConfig &other)
393 {
394 if (!this->CopyLocale(other)) {
395 return false;
396 }
397 #ifdef SUPPORT_GRAPHICS
398 if (!this->CopyPreferredLocale(other)) {
399 return false;
400 }
401 #endif
402 return true;
403 }
404
GetCurrentDeviceType()405 std::string ResConfigImpl::GetCurrentDeviceType()
406 {
407 std::string deviceType;
408 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
409 deviceType = system::GetParameter(PROPERTY_DEVICE_TYPE, PROPERTY_DEVICE_TYPE_DEFAULT);
410 #endif
411 return deviceType;
412 }
413
GetAppSupportDeviceTypes()414 std::vector<std::string> ResConfigImpl::GetAppSupportDeviceTypes()
415 {
416 std::vector<std::string> supportDeviceTypes;
417 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
418 std::string deviceTypes = system::GetParameter(PROPERTY_SUPPORT_APP_TYPES, PROPERTY_DEVICE_TYPE_DEFAULT);
419 std::string deviceType = "";
420 for (size_t i = 0; i < deviceTypes.length(); i++) {
421 if (deviceTypes[i] == ',') {
422 supportDeviceTypes.push_back(deviceType);
423 deviceType = "";
424 } else {
425 deviceType += deviceTypes[i];
426 }
427 }
428 if (deviceType.length() != 0) {
429 supportDeviceTypes.push_back(deviceType);
430 deviceType = "";
431 }
432 #endif
433 return supportDeviceTypes;
434 }
435
ParseDeviceTypeStr(const std::string & deviceType)436 DeviceType ResConfigImpl::ParseDeviceTypeStr(const std::string &deviceType)
437 {
438 if (deviceType == std::string(PHONE_STR)) {
439 return DeviceType::DEVICE_PHONE;
440 }
441 if (deviceType == std::string(TABLET_STR)) {
442 return DeviceType::DEVICE_TABLET;
443 }
444 if (deviceType == std::string(CAR_STR)) {
445 return DeviceType::DEVICE_CAR;
446 }
447 if (deviceType == std::string(PAD_STR)) {
448 return DeviceType::DEVICE_PAD;
449 }
450 if (deviceType == std::string(TV_STR)) {
451 return DeviceType::DEVICE_TV;
452 }
453 if (deviceType == std::string(WEARABLE_STR)) {
454 return DeviceType::DEVICE_WEARABLE;
455 }
456 if (deviceType == std::string(TWOINONE_STR)) {
457 return DeviceType::DEVICE_TWOINONE;
458 }
459 return DeviceType::DEVICE_NOT_SET;
460 }
461
Copy(ResConfig & other,bool isRead)462 bool ResConfigImpl::Copy(ResConfig &other, bool isRead)
463 {
464 if (!this->CopyLocaleAndPreferredLocale(other)) {
465 return false;
466 }
467 if (this->GetDeviceType() != other.GetDeviceType()) {
468 if (other.GetDeviceType() != DEVICE_NOT_SET) {
469 this->SetDeviceType(other.GetDeviceType());
470 } else {
471 this->SetDeviceType(ParseDeviceTypeStr(GetCurrentDeviceType()));
472 }
473 }
474 if (this->GetDirection() != other.GetDirection()) {
475 this->SetDirection(other.GetDirection());
476 }
477 if (this->GetColorMode() != other.GetColorMode()) {
478 this->SetColorMode(other.GetColorMode());
479 }
480 if (this->GetInputDevice() != other.GetInputDevice()) {
481 this->SetInputDevice(other.GetInputDevice());
482 }
483 if (this->GetMcc() != other.GetMcc()) {
484 this->SetMcc(other.GetMcc());
485 }
486 if (this->GetMnc() != other.GetMnc()) {
487 this->SetMnc(other.GetMnc());
488 }
489 if (this->GetScreenDensity() != other.GetScreenDensity()) {
490 this->SetScreenDensity(other.GetScreenDensity());
491 }
492 if (this->GetAppColorMode() != other.GetAppColorMode()) {
493 this->SetAppColorMode(other.GetAppColorMode());
494 }
495 if (isRead) {
496 this->SetAppDarkRes(other.GetAppDarkRes());
497 }
498 if (this->GetThemeId() != other.GetThemeId()) {
499 this->SetThemeId(other.GetThemeId());
500 }
501 return true;
502 }
503
MatchLocal(const ResConfig & other) const504 bool ResConfigImpl::MatchLocal(const ResConfig &other) const
505 {
506 #ifdef SUPPORT_GRAPHICS
507 auto localeInfo = other.GetPreferredLocaleInfo();
508 if (!localeInfo) {
509 localeInfo = other.GetLocaleInfo();
510 }
511 if (!localeInfo) {
512 return true;
513 }
514 if (localeInfo && !resLocale_) {
515 return false;
516 }
517 ResLocale resLocal;
518 resLocal.CopyFromLocaleInfo(localeInfo);
519
520 bool isPreferredLocaleMatch = false;
521 if (this->resPreferredLocale_ != nullptr) {
522 isPreferredLocaleMatch = true;
523 if (!LocaleMatcher::Match(this->resPreferredLocale_, &resLocal)) {
524 return false;
525 }
526 }
527
528 if (!isPreferredLocaleMatch && !(LocaleMatcher::Match(this->resLocale_, &resLocal))) {
529 return false;
530 }
531 #endif
532 return true;
533 }
534
PathAppend(std::string & path,const std::string & append,const std::string & connector)535 void PathAppend(std::string &path, const std::string &append, const std::string &connector)
536 {
537 if (!append.size()) {
538 return;
539 }
540 if (path.size() > 0) {
541 path.append(connector);
542 }
543 path.append(append);
544 }
545
ToString() const546 std::string ResConfigImpl::ToString() const
547 {
548 /*
549 * folder path struct: mcc_mnc-language_script_region-direction-deviceType-colorMode-inputDevice-screenDensity
550 * default is base
551 */
552 std::string path = "";
553 std::string underScore = "_";
554 std::string hyphen = "-";
555
556 if (mcc_ != MCC_UNDEFINED) {
557 PathAppend(path, "mcc" + std::to_string(mcc_), hyphen);
558 if (mnc_ != MNC_UNDEFINED) {
559 PathAppend(path, "mnc" + std::to_string(mnc_), underScore);
560 }
561 }
562
563 if (resLocale_ != nullptr) {
564 PathAppend(path, std::string(resLocale_->GetLanguage()), hyphen);
565 PathAppend(path, std::string(resLocale_->GetScript()), underScore);
566 PathAppend(path, std::string(resLocale_->GetRegion()), underScore);
567 }
568
569 if (direction_ != Direction::DIRECTION_NOT_SET) {
570 PathAppend(path, std::string((direction_ == Direction::DIRECTION_VERTICAL) ? VERTICAL : HORIZONTAL), hyphen);
571 }
572
573 PathAppend(path, GetDeviceTypeStr(), hyphen);
574
575 if (colorMode_ != ColorMode::COLOR_MODE_NOT_SET) {
576 PathAppend(path, std::string((colorMode_ == ColorMode::DARK) ? DARK_STR : LIGHT_STR), hyphen);
577 }
578
579 if (inputDevice_ != InputDevice::INPUTDEVICE_NOT_SET) {
580 PathAppend(path, std::string(POINTING_DEVICE_STR), hyphen);
581 }
582
583 PathAppend(path, GetScreenDensityStr(), hyphen);
584
585 if (path.size() == 0) {
586 path = "base";
587 }
588 return path;
589 }
590
GetDeviceTypeStr() const591 std::string ResConfigImpl::GetDeviceTypeStr() const
592 {
593 std::string deviceType;
594 switch (deviceType_) {
595 case DeviceType::DEVICE_PHONE:
596 deviceType = std::string(PHONE_STR);
597 break;
598 case DeviceType::DEVICE_TABLET:
599 deviceType = std::string(TABLET_STR);
600 break;
601 case DeviceType::DEVICE_CAR:
602 deviceType = std::string(CAR_STR);
603 break;
604 case DeviceType::DEVICE_PAD:
605 deviceType = std::string(PAD_STR);
606 break;
607 case DeviceType::DEVICE_TV:
608 deviceType = std::string(TV_STR);
609 break;
610 case DeviceType::DEVICE_WEARABLE:
611 deviceType = std::string(WEARABLE_STR);
612 break;
613 case DeviceType::DEVICE_TWOINONE:
614 deviceType = std::string(TWOINONE_STR);
615 break;
616 default:
617 break;
618 }
619 return deviceType;
620 }
621
GetScreenDensityStr() const622 std::string ResConfigImpl::GetScreenDensityStr() const
623 {
624 std::string screenDensity;
625 switch (screenDensityDpi_) {
626 case ScreenDensity::SCREEN_DENSITY_SDPI:
627 screenDensity = std::string(RE_120_STR);
628 break;
629 case ScreenDensity::SCREEN_DENSITY_MDPI:
630 screenDensity = std::string(RE_160_STR);
631 break;
632 case ScreenDensity::SCREEN_DENSITY_LDPI:
633 screenDensity = std::string(RE_240_STR);
634 break;
635 case ScreenDensity::SCREEN_DENSITY_XLDPI:
636 screenDensity = std::string(RE_320_STR);
637 break;
638 case ScreenDensity::SCREEN_DENSITY_XXLDPI:
639 screenDensity = std::string(RE_480_STR);
640 break;
641 case ScreenDensity::SCREEN_DENSITY_XXXLDPI:
642 screenDensity = std::string(RE_640_STR);
643 break;
644 default:
645 break;
646 }
647 return screenDensity;
648 }
649
Match(const std::shared_ptr<ResConfigImpl> other,bool isCheckDarkAdaptation) const650 bool ResConfigImpl::Match(const std::shared_ptr<ResConfigImpl> other, bool isCheckDarkAdaptation) const
651 {
652 if (other == nullptr) {
653 return false;
654 }
655 if (!IsMccMncMatch(other->mcc_, other->mnc_)) {
656 return false;
657 }
658
659 bool isPreferredLocaleMatch = false;
660 #ifdef SUPPORT_GRAPHICS
661 if (this->resPreferredLocale_ != nullptr) {
662 isPreferredLocaleMatch = true;
663 if (!LocaleMatcher::Match(this->resPreferredLocale_, other->GetResLocale())) {
664 return false;
665 }
666 }
667 #endif
668
669 if (!isPreferredLocaleMatch && !(LocaleMatcher::Match(this->resLocale_, other->GetResLocale()))) {
670 return false;
671 }
672 if (!IsDirectionMatch(other->direction_)) {
673 return false;
674 }
675 if (!IsDeviceTypeMatch(other->deviceType_)) {
676 return false;
677 }
678 if (!IsColorModeMatch(other->colorMode_, isCheckDarkAdaptation)) {
679 return false;
680 }
681 if (!IsInputDeviceMatch(other->inputDevice_)) {
682 return false;
683 }
684 return true;
685 }
686
IsMccMncMatch(uint32_t mcc,uint32_t mnc) const687 bool ResConfigImpl::IsMccMncMatch(uint32_t mcc, uint32_t mnc) const
688 {
689 if (mcc == MCC_UNDEFINED && mnc == MNC_UNDEFINED) {
690 return true;
691 }
692 if (this->mcc_ == mcc) {
693 if (mnc == MNC_UNDEFINED || this->mnc_ == mnc) {
694 return true;
695 }
696 }
697 return false;
698 }
699
IsDirectionMatch(Direction direction) const700 bool ResConfigImpl::IsDirectionMatch(Direction direction) const
701 {
702 if (this->direction_ != DIRECTION_NOT_SET && direction != DIRECTION_NOT_SET) {
703 if (this->direction_ != direction) {
704 return false;
705 }
706 }
707 return true;
708 }
709
IsDeviceTypeMatch(DeviceType deviceType) const710 bool ResConfigImpl::IsDeviceTypeMatch(DeviceType deviceType) const
711 {
712 if (this->deviceType_ != DEVICE_NOT_SET && deviceType != DEVICE_NOT_SET) {
713 if (this->deviceType_ != deviceType) {
714 return false;
715 }
716 }
717 return true;
718 }
719
IsColorModeMatch(ColorMode colorMode,bool isCheckDarkAdaptation) const720 bool ResConfigImpl::IsColorModeMatch(ColorMode colorMode, bool isCheckDarkAdaptation) const
721 {
722 if (isCheckDarkAdaptation && this->colorMode_ == DARK && !this->GetAppColorMode() && !this->GetAppDarkRes()) {
723 return colorMode == COLOR_MODE_NOT_SET;
724 }
725 if (this->colorMode_ != COLOR_MODE_NOT_SET && colorMode != COLOR_MODE_NOT_SET) {
726 if (this->colorMode_ != colorMode) {
727 return false;
728 }
729 }
730 return true;
731 }
732
IsInputDeviceMatch(InputDevice inputDevice) const733 bool ResConfigImpl::IsInputDeviceMatch(InputDevice inputDevice) const
734 {
735 if (this->inputDevice_ == INPUTDEVICE_NOT_SET && inputDevice != INPUTDEVICE_NOT_SET) {
736 return false;
737 }
738 // reserve for future InputDevice expansion
739 if (this->inputDevice_ != INPUTDEVICE_NOT_SET && inputDevice != INPUTDEVICE_NOT_SET) {
740 if (this->inputDevice_ != inputDevice) {
741 return false;
742 }
743 }
744 return true;
745 }
746
747 /**
748 * compare this and target
749 * if this more match request,then return true
750 * else
751 * return false
752 *
753 */
IsMoreSuitable(const std::shared_ptr<ResConfigImpl> other,const std::shared_ptr<ResConfigImpl> request,uint32_t density) const754 bool ResConfigImpl::IsMoreSuitable(const std::shared_ptr<ResConfigImpl> other,
755 const std::shared_ptr<ResConfigImpl> request, uint32_t density) const
756 {
757 if (request != nullptr && other != nullptr) {
758 int ret = IsMccMncMoreSuitable(other->mcc_, other->mnc_, request->mcc_, request->mnc_);
759 if (ret != 0) {
760 return ret > 0;
761 }
762 #ifdef SUPPORT_GRAPHICS
763 if (request->GetResPreferredLocale() != nullptr) {
764 int8_t preferredResult = LocaleMatcher::IsMoreSuitable(this->GetResLocale(), other->GetResLocale(),
765 request->GetResPreferredLocale());
766 if (preferredResult != 0) {
767 return preferredResult > 0;
768 }
769 }
770 #endif
771 int8_t result = LocaleMatcher::IsMoreSuitable(this->GetResLocale(), other->GetResLocale(),
772 request->GetResLocale());
773 if (result != 0) {
774 return result > 0;
775 }
776 /**
777 * direction must full match.
778 * when request is set direction and this is not equal other.
779 * this or other oriention is not set.
780 */
781 if (this->direction_ != other->direction_ &&
782 request->direction_ != Direction::DIRECTION_NOT_SET) {
783 return this->direction_ != Direction::DIRECTION_NOT_SET;
784 }
785 if (this->deviceType_ != other->deviceType_ &&
786 request->deviceType_ != DeviceType::DEVICE_NOT_SET) {
787 return this->deviceType_ != DeviceType::DEVICE_NOT_SET;
788 }
789 if (this->colorMode_ != other->colorMode_ &&
790 request->colorMode_ != ColorMode::COLOR_MODE_NOT_SET) {
791 return this->colorMode_ != ColorMode::COLOR_MODE_NOT_SET;
792 }
793 if (this->inputDevice_ != other->inputDevice_ &&
794 request->inputDevice_ != InputDevice::INPUTDEVICE_NOT_SET) {
795 return this->inputDevice_ != InputDevice::INPUTDEVICE_NOT_SET;
796 }
797 ret = IsDensityMoreSuitable(other->screenDensityDpi_, request->screenDensityDpi_, density);
798 if (ret != 0) {
799 return ret > 0;
800 }
801 }
802 return this->IsMoreSpecificThan(other, density);
803 }
804
805 /**
806 * compare this and target mcc/mnc
807 * if this more match other,then return 1, else if other more match this, return -1,
808 * else
809 * return 0
810 *
811 */
IsMccMncMoreSuitable(uint32_t otherMcc,uint32_t otherMnc,uint32_t requestMcc,uint32_t requestMnc) const812 int ResConfigImpl::IsMccMncMoreSuitable(uint32_t otherMcc, uint32_t otherMnc, uint32_t requestMcc,
813 uint32_t requestMnc) const
814 {
815 int ret = 0;
816 bool defined = requestMcc != MCC_UNDEFINED && requestMnc != MNC_UNDEFINED;
817 bool mccDefined = requestMcc != MCC_UNDEFINED && requestMnc == MNC_UNDEFINED;
818 bool isMccOrMncDiff = this->mcc_ != otherMcc || this->mnc_ != otherMnc;
819 bool isMccDiff = this->mcc_ != otherMcc;
820 int weightsThis = static_cast<int>(this->mcc_ != MCC_UNDEFINED) + static_cast<int>(this->mnc_ != MNC_UNDEFINED);
821 int weightsOther = static_cast<int>(otherMcc != MCC_UNDEFINED) + static_cast<int>(otherMnc != MNC_UNDEFINED);
822 if ((defined && isMccOrMncDiff) || (mccDefined && isMccDiff)) {
823 // 1 means the mcc/mnc of this resConfig is suitable than other resConfig
824 // -1 means the mcc/mnc of other resConfig mcc/mnc is suitable than this resConfig
825 ret = weightsThis > weightsOther ? 1 : -1;
826 }
827 return ret;
828 }
829
830 /**
831 * compare this and target density
832 * if this more match other,then return 1, else if other more match this, return -1,
833 * else
834 * return 0
835 *
836 */
IsDensityMoreSuitable(ScreenDensity otherDensity,ScreenDensity requestDensity,uint32_t density) const837 __attribute__((no_sanitize("integer"))) int ResConfigImpl::IsDensityMoreSuitable(ScreenDensity otherDensity,
838 ScreenDensity requestDensity, uint32_t density) const
839 {
840 int ret = 0;
841 int thisDistance;
842 int otherDistance;
843 if (density == ScreenDensity::SCREEN_DENSITY_NOT_SET) {
844 if (requestDensity != ScreenDensity::SCREEN_DENSITY_NOT_SET &&
845 this->screenDensityDpi_ != otherDensity) {
846 thisDistance = this->screenDensityDpi_ - requestDensity;
847 otherDistance = otherDensity - requestDensity;
848 if (IsDensityMoreSuitable(thisDistance, otherDistance)) {
849 // the density of this resConfig is suitable than other resConfig
850 ret = 1;
851 } else {
852 // the density of other resConfig is suitable than this resConfig
853 ret = -1;
854 }
855 }
856 } else {
857 if (this->screenDensityDpi_ != otherDensity) {
858 thisDistance = static_cast<int>(this->screenDensityDpi_ - density);
859 otherDistance = static_cast<int>(otherDensity - density);
860 if (IsDensityMoreSuitable(thisDistance, otherDistance)) {
861 // the density of this resConfig is suitable than other resConfig
862 ret = 1;
863 } else {
864 // the density of other resConfig is suitable than this resConfig
865 ret = -1;
866 }
867 }
868 }
869 return ret;
870 }
871
IsDensityMoreSuitable(int thisDistance,int otherDistance) const872 bool ResConfigImpl::IsDensityMoreSuitable(int thisDistance, int otherDistance) const
873 {
874 if (thisDistance >= 0 && otherDistance >= 0) {
875 return (thisDistance <= otherDistance);
876 }
877 if (thisDistance > 0) {
878 return true;
879 }
880 if (otherDistance > 0) {
881 return false;
882 }
883 return (thisDistance >= otherDistance);
884 }
885
~ResConfigImpl()886 ResConfigImpl::~ResConfigImpl()
887 {
888 if (resLocale_ != nullptr) {
889 delete resLocale_;
890 resLocale_ = nullptr;
891 }
892 #ifdef SUPPORT_GRAPHICS
893 if (resPreferredLocale_ != nullptr) {
894 delete resPreferredLocale_;
895 resPreferredLocale_ = nullptr;
896 }
897 if (localeInfo_ != nullptr) {
898 delete localeInfo_;
899 localeInfo_ = nullptr;
900 }
901 if (preferredLocaleInfo_ != nullptr) {
902 delete preferredLocaleInfo_;
903 preferredLocaleInfo_ = nullptr;
904 }
905 #endif
906 }
907
CompleteScript()908 void ResConfigImpl::CompleteScript()
909 {
910 if (isCompletedScript_) {
911 return;
912 }
913 if (LocaleMatcher::Normalize(this->resLocale_)) {
914 isCompletedScript_ = true;
915 }
916 }
917
IsCompletedScript() const918 bool ResConfigImpl::IsCompletedScript() const
919 {
920 return isCompletedScript_;
921 }
922
IsMoreSpecificThan(const std::shared_ptr<ResConfigImpl> other,uint32_t density) const923 bool ResConfigImpl::IsMoreSpecificThan(const std::shared_ptr<ResConfigImpl> other, uint32_t density) const
924 {
925 if (other == nullptr) {
926 return true;
927 }
928 if (this->mcc_ != MCC_UNDEFINED && this->mnc_ != MNC_UNDEFINED) {
929 if (this->mcc_ != other->mcc_ || this->mnc_ != other->mnc_) {
930 return false;
931 }
932 } else if (this->mcc_ != MCC_UNDEFINED && this->mnc_ == MNC_UNDEFINED) {
933 if (this->mcc_ != other->mcc_) {
934 return true;
935 }
936 }
937 int8_t result = LocaleMatcher::IsMoreSpecificThan(
938 this->GetResLocale(),
939 (other == nullptr) ? nullptr : other->GetResLocale());
940 if (result > 0) {
941 return true;
942 }
943 if (result < 0) {
944 return false;
945 }
946 if (this->direction_ != other->direction_) {
947 return (this->direction_ != Direction::DIRECTION_NOT_SET);
948 }
949 if (this->deviceType_ != other->deviceType_) {
950 return (this->deviceType_ != DeviceType::DEVICE_NOT_SET);
951 }
952 if (this->colorMode_ != other->colorMode_) {
953 return (this->colorMode_ != ColorMode::COLOR_MODE_NOT_SET);
954 }
955 if (this->inputDevice_ != other->inputDevice_) {
956 return (this->inputDevice_ == InputDevice::INPUTDEVICE_NOT_SET);
957 }
958 int ret = IsDensityMoreSpecificThan(other->screenDensityDpi_, density);
959 if (ret != 0) {
960 return ret > 0;
961 }
962
963 return true;
964 }
965
IsDensityMoreSpecificThan(ScreenDensity otherDensity,uint32_t density) const966 int ResConfigImpl::IsDensityMoreSpecificThan(ScreenDensity otherDensity, uint32_t density) const
967 {
968 int ret = 0;
969 if (density == SCREEN_DENSITY_NOT_SET) {
970 if (this->screenDensityDpi_ != otherDensity) {
971 if (this->screenDensityDpi_ != ScreenDensity::SCREEN_DENSITY_NOT_SET) {
972 // the density of this resConfig is suitable than other resConfig
973 ret = 1;
974 } else {
975 // the density of other resConfig is suitable than this resConfig
976 ret = -1;
977 }
978 }
979 } else {
980 if ((this->screenDensityDpi_ != ScreenDensity::SCREEN_DENSITY_NOT_SET) &&
981 (otherDensity == ScreenDensity::SCREEN_DENSITY_NOT_SET)) {
982 // the density of this resConfig is suitable than other resConfig
983 ret = 1;
984 }
985 if ((this->screenDensityDpi_ == ScreenDensity::SCREEN_DENSITY_NOT_SET) &&
986 (otherDensity != ScreenDensity::SCREEN_DENSITY_NOT_SET)) {
987 // the density of other resConfig is suitable than this resConfig
988 ret = -1;
989 }
990 if (this->screenDensityDpi_ != otherDensity) {
991 int thisDistance = static_cast<int>(this->screenDensityDpi_ - density);
992 int otherDistance = static_cast<int>(otherDensity - density);
993 if (IsDensityMoreSuitable(thisDistance, otherDistance)) {
994 // the density of this resConfig is suitable than other resConfig
995 ret = 1;
996 } else {
997 // the density of other resConfig is suitable than this resConfig
998 ret = -1;
999 }
1000 }
1001 }
1002 return ret;
1003 }
1004
CreateResConfig()1005 ResConfig *CreateResConfig()
1006 {
1007 ResConfigImpl *temp = new(std::nothrow) ResConfigImpl;
1008 return temp;
1009 }
1010
CreateDefaultResConfig()1011 ResConfig *CreateDefaultResConfig()
1012 {
1013 ResConfigImpl *temp = new(std::nothrow) ResConfigImpl;
1014 if (temp != nullptr) {
1015 temp->SetColorMode(COLOR_MODE_NOT_SET);
1016 }
1017 return temp;
1018 }
1019
SetAppColorMode(bool isAppColorMode)1020 void ResConfigImpl::SetAppColorMode(bool isAppColorMode)
1021 {
1022 this->isAppColorMode_ = isAppColorMode;
1023 }
1024
GetAppColorMode() const1025 bool ResConfigImpl::GetAppColorMode() const
1026 {
1027 return this->isAppColorMode_;
1028 }
1029
SetAppDarkRes(bool isAppDarkRes)1030 void ResConfigImpl::SetAppDarkRes(bool isAppDarkRes)
1031 {
1032 this->isAppDarkRes_ = isAppDarkRes;
1033 }
1034
GetAppDarkRes() const1035 bool ResConfigImpl::GetAppDarkRes() const
1036 {
1037 return this->isAppDarkRes_;
1038 }
1039
IsInvalidResConfig()1040 bool ResConfigImpl::IsInvalidResConfig()
1041 {
1042 return this->colorMode_ == LIGHT && this->direction_ == DIRECTION_NOT_SET
1043 && this->density_ == SCREEN_DENSITY_NOT_SET
1044 && this->screenDensityDpi_ == SCREEN_DENSITY_NOT_SET;
1045 }
1046 } // namespace Resource
1047 } // namespace Global
1048 } // namespace OHOS