• 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     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