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