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