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