• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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