• 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     isCompletedScript_(false)
58 {}
59 
60 #ifdef SUPPORT_GRAPHICS
SetPreferredLocaleInfo(Locale & preferredLocaleInfo)61 RState ResConfigImpl::SetPreferredLocaleInfo(Locale &preferredLocaleInfo)
62 {
63     const char *language = preferredLocaleInfo.getLanguage();
64     const char *script = preferredLocaleInfo.getScript();
65     const char *region = preferredLocaleInfo.getCountry();
66     if (Utils::IsStrEmpty(language)) {
67         delete this->resPreferredLocale_;
68         delete this->preferredLocaleInfo_;
69         this->resPreferredLocale_ = nullptr;
70         this->preferredLocaleInfo_ = nullptr;
71         return SUCCESS;
72     }
73     RState state = BuildResLocale(language, script, region, &this->resPreferredLocale_);
74     if (state != SUCCESS) {
75         return state;
76     }
77     return BuildLocaleInfo(this->resPreferredLocale_, &this->preferredLocaleInfo_);
78 }
79 
SetLocaleInfo(Locale & localeInfo)80 RState ResConfigImpl::SetLocaleInfo(Locale &localeInfo)
81 {
82     return this->SetLocaleInfo(localeInfo.getLanguage(), localeInfo.getScript(), localeInfo.getCountry());
83 }
84 #endif
85 
BuildResLocale(const char * language,const char * script,const char * region,ResLocale ** resLocale)86 RState ResConfigImpl::BuildResLocale(const char *language, const char *script,
87     const char *region, ResLocale **resLocale)
88 {
89     RState state = SUCCESS;
90     ResLocale *temp = ResLocale::BuildFromParts(language, script, region, state);
91     if (state != SUCCESS) {
92         return state;
93     }
94     if (script == nullptr || script[0] == '\0') {
95         if (!LocaleMatcher::Normalize(temp)) {
96             delete temp;
97             temp = nullptr;
98             return NOT_ENOUGH_MEM;
99         }
100     }
101     delete *resLocale;
102     *resLocale = temp;
103     return state;
104 }
105 
BuildLocaleInfo(const ResLocale * resLocale,Locale ** localeInfo)106 RState ResConfigImpl::BuildLocaleInfo(const ResLocale *resLocale, Locale **localeInfo)
107 {
108     UErrorCode errCode = U_ZERO_ERROR;
109     Locale temp  = icu::LocaleBuilder().setLanguage(resLocale->GetLanguage())
110         .setRegion(resLocale->GetRegion()).setScript(resLocale->GetScript()).build(errCode);
111     if (!U_SUCCESS(errCode)) {
112         return NOT_ENOUGH_MEM;
113     }
114     delete *localeInfo;
115     *localeInfo = new Locale(temp);
116     return SUCCESS;
117 }
118 
SetLocaleInfo(const char * language,const char * script,const char * region)119 RState ResConfigImpl::SetLocaleInfo(const char *language,
120     const char *script,
121     const char *region)
122 {
123 #ifdef SUPPORT_GRAPHICS
124     RState state = SUCCESS;
125     if (Utils::IsStrEmpty(language)) {
126         delete this->resLocale_;
127         delete this->localeInfo_;
128         this->resLocale_ = nullptr;
129         this->localeInfo_ = nullptr;
130         return state;
131     }
132     this->isCompletedScript_ = false;
133     state = BuildResLocale(language, script, region, &this->resLocale_);
134     if (state != SUCCESS) {
135         return state;
136     }
137     state = BuildLocaleInfo(this->resLocale_, &this->localeInfo_);
138     if (state != SUCCESS) {
139         return state;
140     }
141     this->isCompletedScript_ = true;
142     return state;
143 #else
144     return NOT_SUPPORT_SEP;
145 #endif
146 }
147 
SetDeviceType(DeviceType deviceType)148 void ResConfigImpl::SetDeviceType(DeviceType deviceType)
149 {
150     this->deviceType_ = deviceType;
151 }
152 
SetDirection(Direction direction)153 void ResConfigImpl::SetDirection(Direction direction)
154 {
155     this->direction_ = direction;
156 }
157 
SetColorMode(ColorMode colorMode)158 void ResConfigImpl::SetColorMode(ColorMode colorMode)
159 {
160     this->colorMode_ = colorMode;
161 }
162 
SetInputDevice(InputDevice inputDevice)163 void ResConfigImpl::SetInputDevice(InputDevice inputDevice)
164 {
165     this->inputDevice_ = inputDevice;
166 }
167 
SetMcc(uint32_t mcc)168 void ResConfigImpl::SetMcc(uint32_t mcc)
169 {
170     this->mcc_ = mcc;
171 }
172 
SetMnc(uint32_t mnc)173 void ResConfigImpl::SetMnc(uint32_t mnc)
174 {
175     this->mnc_ = mnc;
176 }
177 
ConvertDensity(float density)178 ScreenDensity ResConfigImpl::ConvertDensity(float density)
179 {
180     float deviceDpi = density * Utils::DPI_BASE;
181     auto resolution = SCREEN_DENSITY_NOT_SET;
182     for (const auto& [dpi, value] : resolutions) {
183         resolution = value;
184         if (deviceDpi <= dpi) {
185             break;
186         }
187     }
188     return resolution;
189 }
190 
SetScreenDensity(float screenDensity)191 void ResConfigImpl::SetScreenDensity(float screenDensity)
192 {
193     this->density_ = screenDensity;
194     this->screenDensityDpi_ = ConvertDensity(screenDensity);
195 }
196 
197 #ifdef SUPPORT_GRAPHICS
GetResPreferredLocale() const198 const ResLocale *ResConfigImpl::GetResPreferredLocale() const
199 {
200     return this->resPreferredLocale_;
201 }
202 
GetPreferredLocaleInfo() const203 const Locale *ResConfigImpl::GetPreferredLocaleInfo() const
204 {
205     return this->preferredLocaleInfo_;
206 }
207 
GetLocaleInfo() const208 const Locale *ResConfigImpl::GetLocaleInfo() const
209 {
210     return localeInfo_;
211 }
212 #endif
213 
GetResLocale() const214 const ResLocale *ResConfigImpl::GetResLocale() const
215 {
216     return this->resLocale_;
217 }
218 
GetDirection() const219 Direction ResConfigImpl::GetDirection() const
220 {
221     return this->direction_;
222 }
223 
GetScreenDensity() const224 float ResConfigImpl::GetScreenDensity() const
225 {
226     return this->density_;
227 }
228 
GetColorMode() const229 ColorMode ResConfigImpl::GetColorMode() const
230 {
231     return this->colorMode_;
232 }
233 
GetInputDevice() const234 InputDevice ResConfigImpl::GetInputDevice() const
235 {
236     return this->inputDevice_;
237 }
238 
GetMcc() const239 uint32_t ResConfigImpl::GetMcc() const
240 {
241     return this->mcc_;
242 }
243 
GetMnc() const244 uint32_t ResConfigImpl::GetMnc() const
245 {
246     return this->mnc_;
247 }
248 
GetDeviceType() const249 DeviceType ResConfigImpl::GetDeviceType() const
250 {
251     return this->deviceType_;
252 }
253 
254 #ifdef SUPPORT_GRAPHICS
CopyLocale(Locale ** currentLocaleInfo,ResLocale ** currentResLocale,const Locale * otherLocaleInfo)255 bool ResConfigImpl::CopyLocale(Locale **currentLocaleInfo, ResLocale **currentResLocale,
256     const Locale *otherLocaleInfo)
257 {
258     bool needCopy = false;
259     if (*currentLocaleInfo == nullptr && otherLocaleInfo != nullptr) {
260         needCopy = true;
261     }
262     if (*currentLocaleInfo != nullptr && otherLocaleInfo == nullptr) {
263         delete *currentResLocale;
264         delete *currentLocaleInfo;
265         *currentResLocale = nullptr;
266         *currentLocaleInfo = nullptr;
267         return true;
268     }
269     if (*currentResLocale != nullptr && otherLocaleInfo != nullptr) {
270         uint64_t encodedLocale = Utils::EncodeLocale(
271             (*currentResLocale)->GetLanguage(),
272             (*currentResLocale)->GetScript(), (*currentResLocale)->GetRegion());
273         uint64_t otherEncodedLocale = Utils::EncodeLocale(
274             otherLocaleInfo->getLanguage(),
275             otherLocaleInfo->getScript(), otherLocaleInfo->getCountry());
276         if (encodedLocale != otherEncodedLocale) {
277             needCopy = true;
278         }
279     }
280     if (needCopy) {
281         ResLocale *temp = new(std::nothrow) ResLocale;
282         if (temp == nullptr) {
283             return false;
284         }
285         RState rs = temp->CopyFromLocaleInfo(otherLocaleInfo);
286         if (rs != SUCCESS) {
287             delete temp;
288             return false;
289         }
290         UErrorCode errCode = U_ZERO_ERROR;
291         Locale tempLocale = icu::LocaleBuilder().setLocale(*otherLocaleInfo).build(errCode);
292 
293         if (!U_SUCCESS(errCode)) {
294             delete temp;
295             return false;
296         }
297         delete *currentResLocale;
298         delete *currentLocaleInfo;
299         *currentResLocale = temp;
300         *currentLocaleInfo = new Locale(tempLocale);
301     }
302     return true;
303 }
304 #endif
305 
306 #ifdef SUPPORT_GRAPHICS
CopyPreferredLocale(ResConfig & other)307 bool ResConfigImpl::CopyPreferredLocale(ResConfig &other)
308 {
309     return CopyLocale(&this->preferredLocaleInfo_, &this->resPreferredLocale_, other.GetPreferredLocaleInfo());
310 }
311 #endif
312 
CopyLocale(ResConfig & other)313 bool ResConfigImpl::CopyLocale(ResConfig &other)
314 {
315 #ifdef SUPPORT_GRAPHICS
316     return CopyLocale(&this->localeInfo_, &this->resLocale_, other.GetLocaleInfo());
317 #else
318     return false;
319 #endif
320 }
Copy(ResConfig & other)321 bool ResConfigImpl::Copy(ResConfig &other)
322 {
323     if (!this->CopyLocale(other)) {
324         return false;
325     }
326 #ifdef SUPPORT_GRAPHICS
327     if (!this->CopyPreferredLocale(other)) {
328         return false;
329     }
330 #endif
331     if (this->GetDeviceType() != other.GetDeviceType()) {
332         this->SetDeviceType(other.GetDeviceType());
333     }
334     if (this->GetDirection() != other.GetDirection()) {
335         this->SetDirection(other.GetDirection());
336     }
337     if (this->GetColorMode() != other.GetColorMode()) {
338         this->SetColorMode(other.GetColorMode());
339     }
340     if (this->GetInputDevice() != other.GetInputDevice()) {
341         this->SetInputDevice(other.GetInputDevice());
342     }
343     if (this->GetMcc() != other.GetMcc()) {
344         this->SetMcc(other.GetMcc());
345     }
346     if (this->GetMnc() != other.GetMnc()) {
347         this->SetMnc(other.GetMnc());
348     }
349     if (this->GetScreenDensity() != other.GetScreenDensity()) {
350         this->SetScreenDensity(other.GetScreenDensity());
351     }
352     return true;
353 }
354 
Match(const ResConfigImpl * other) const355 bool ResConfigImpl::Match(const ResConfigImpl *other) const
356 {
357     if (other == nullptr) {
358         return false;
359     }
360     if (!IsMccMncMatch(other->mcc_, other->mnc_)) {
361         return false;
362     }
363 
364     bool isPreferredLocaleMatch = false;
365 #ifdef SUPPORT_GRAPHICS
366     if (this->resPreferredLocale_ != nullptr) {
367         isPreferredLocaleMatch = LocaleMatcher::Match(this->resPreferredLocale_, other->GetResLocale());
368     }
369 #endif
370 
371     if (!isPreferredLocaleMatch && !(LocaleMatcher::Match(this->resLocale_, other->GetResLocale()))) {
372         return false;
373     }
374     if (!IsDirectionMatch(other->direction_)) {
375         return false;
376     }
377     if (!IsDeviceTypeMatch(other->deviceType_)) {
378         return false;
379     }
380     if (!IsColorModeMatch(other->colorMode_)) {
381         return false;
382     }
383     if (!IsInputDeviceMatch(other->inputDevice_)) {
384         return false;
385     }
386     return true;
387 }
388 
IsMccMncMatch(uint32_t mcc,uint32_t mnc) const389 bool ResConfigImpl::IsMccMncMatch(uint32_t mcc,  uint32_t mnc) const
390 {
391     if (this->mcc_ != MCC_UNDEFINED && this->mnc_ != MNC_UNDEFINED) {
392         if (mcc != MCC_UNDEFINED && mnc != MNC_UNDEFINED) {
393             if (this->mcc_ != mcc || this->mnc_ != mnc) {
394                 return false;
395             }
396         }
397     } else if (this->mcc_ != MCC_UNDEFINED && this->mnc_ == MNC_UNDEFINED) {
398         if (mcc != MCC_UNDEFINED && this->mcc_ != mcc) {
399             return false;
400         }
401     }
402     return true;
403 }
404 
IsDirectionMatch(Direction direction) const405 bool ResConfigImpl::IsDirectionMatch(Direction direction) const
406 {
407     if (this->direction_ != DIRECTION_NOT_SET && direction != DIRECTION_NOT_SET) {
408         if (this->direction_ != direction) {
409             return false;
410         }
411     }
412     return true;
413 }
414 
IsDeviceTypeMatch(DeviceType deviceType) const415 bool ResConfigImpl::IsDeviceTypeMatch(DeviceType deviceType) const
416 {
417     if (this->deviceType_ != DEVICE_NOT_SET && deviceType != DEVICE_NOT_SET) {
418         if (this->deviceType_ != deviceType) {
419             return false;
420         }
421     }
422     return true;
423 }
424 
IsColorModeMatch(ColorMode colorMode) const425 bool ResConfigImpl::IsColorModeMatch(ColorMode colorMode) const
426 {
427     if (this->colorMode_ != COLOR_MODE_NOT_SET && colorMode != COLOR_MODE_NOT_SET) {
428         if (this->colorMode_ != colorMode) {
429             return false;
430         }
431     }
432     return true;
433 }
434 
IsInputDeviceMatch(InputDevice inputDevice) const435 bool ResConfigImpl::IsInputDeviceMatch(InputDevice inputDevice) const
436 {
437     if (this->inputDevice_ == INPUTDEVICE_NOT_SET && inputDevice != INPUTDEVICE_NOT_SET) {
438         return false;
439     }
440     // reserve for future InputDevice expansion
441     if (this->inputDevice_ != INPUTDEVICE_NOT_SET && inputDevice != INPUTDEVICE_NOT_SET) {
442         if (this->inputDevice_ != inputDevice) {
443             return false;
444         }
445     }
446     return true;
447 }
448 
449 /**
450  * compare this  and target
451  * if this more match request,then return true
452  * else
453  * return false
454  *
455  */
IsMoreSuitable(const ResConfigImpl * other,const ResConfigImpl * request,uint32_t density) const456 bool ResConfigImpl::IsMoreSuitable(const ResConfigImpl *other,
457     const ResConfigImpl *request, uint32_t density) const
458 {
459     if (request != nullptr && other != nullptr) {
460         int ret = IsMccMncMoreSuitable(other->mcc_, other->mnc_, request->mcc_, request->mnc_);
461         if (ret != 0) {
462             return ret > 0;
463         }
464 #ifdef SUPPORT_GRAPHICS
465         if (request->GetResPreferredLocale() != nullptr) {
466             int8_t preferredResult = LocaleMatcher::IsMoreSuitable(this->GetResLocale(), other->GetResLocale(),
467                 request->GetResPreferredLocale());
468             if (preferredResult != 0) {
469                 return preferredResult > 0;
470             }
471         }
472 #endif
473         int8_t result = LocaleMatcher::IsMoreSuitable(this->GetResLocale(), other->GetResLocale(),
474             request->GetResLocale());
475         if (result != 0) {
476             return result > 0;
477         }
478         /**
479          * direction must full match.
480          * when request is set direction and this is not equal other.
481          * this or other oriention is not set.
482          */
483         if (this->direction_ != other->direction_ &&
484             request->direction_ != Direction::DIRECTION_NOT_SET) {
485             return this->direction_ != Direction::DIRECTION_NOT_SET;
486         }
487         if (this->deviceType_ != other->deviceType_ &&
488             request->deviceType_ != DeviceType::DEVICE_NOT_SET) {
489             return this->deviceType_ != DeviceType::DEVICE_NOT_SET;
490         }
491         if (this->colorMode_ != other->colorMode_ &&
492             request->colorMode_ != ColorMode::COLOR_MODE_NOT_SET) {
493             return this->colorMode_ != ColorMode::COLOR_MODE_NOT_SET;
494         }
495         if (this->inputDevice_ != other->inputDevice_ &&
496             request->inputDevice_ != InputDevice::INPUTDEVICE_NOT_SET) {
497             return this->inputDevice_ != InputDevice::INPUTDEVICE_NOT_SET;
498         }
499         ret = IsDensityMoreSuitable(other->screenDensityDpi_, request->screenDensityDpi_, density);
500         if (ret != 0) {
501             return ret > 0;
502         }
503     }
504     return this->IsMoreSpecificThan(other, density);
505 }
506 
507 /**
508  * compare this and target mcc/mnc
509  * if this more match other,then return 1, else if other more match this, return -1,
510  * else
511  * return 0
512  *
513  */
IsMccMncMoreSuitable(uint32_t otherMcc,uint32_t otherMnc,uint32_t requestMcc,uint32_t requestMnc) const514 int ResConfigImpl::IsMccMncMoreSuitable(uint32_t otherMcc, uint32_t otherMnc, uint32_t requestMcc,
515     uint32_t requestMnc) const
516 {
517     int ret = 0;
518     bool defined = requestMcc != MCC_UNDEFINED && requestMnc != MNC_UNDEFINED;
519     bool mccDefined = requestMcc != MCC_UNDEFINED && requestMnc == MNC_UNDEFINED;
520     bool isMccOrMncDiff = this->mcc_ != otherMcc || this->mnc_ != otherMnc;
521     bool isMccDiff = this->mcc_ != otherMcc;
522     if (defined && isMccOrMncDiff) {
523         if ((this->mcc_ != MCC_UNDEFINED) && (this->mnc_ != MNC_UNDEFINED)) {
524             // the mcc/mnc of this resConfig is suitable than other resConfig
525             ret = 1;
526         } else {
527             // the mcc/mnc of other resConfig mcc/mnc is suitable than this resConfig
528             ret = -1;
529         }
530     } else if (mccDefined && isMccDiff) {
531         if (this->mcc_ != MCC_UNDEFINED) {
532             // the mcc of this resConfig is suitable than other resConfig
533             ret = 1;
534         } else {
535             // the mcc of other resConfig is suitable than this resConfig
536             ret = -1;
537         }
538     }
539     return ret;
540 }
541 
542 /**
543  * compare this and target density
544  * if this more match other,then return 1, else if other more match this, return -1,
545  * else
546  * return 0
547  *
548  */
IsDensityMoreSuitable(ScreenDensity otherDensity,ScreenDensity requestDensity,uint32_t density) const549 int ResConfigImpl::IsDensityMoreSuitable(ScreenDensity otherDensity, ScreenDensity requestDensity,
550     uint32_t density) const
551 {
552     int ret = 0;
553     int thisDistance;
554     int otherDistance;
555     if (density == ScreenDensity::SCREEN_DENSITY_NOT_SET) {
556         if (requestDensity != ScreenDensity::SCREEN_DENSITY_NOT_SET &&
557             this->screenDensityDpi_ != otherDensity) {
558             thisDistance = this->screenDensityDpi_ - requestDensity;
559             otherDistance = otherDensity - requestDensity;
560             if (IsDensityMoreSuitable(thisDistance, otherDistance)) {
561                 // the density of this resConfig is suitable than other resConfig
562                 ret = 1;
563             } else {
564                 // the density of other resConfig is suitable than this resConfig
565                 ret = -1;
566             }
567         }
568     } else {
569         if (this->screenDensityDpi_ != otherDensity) {
570             thisDistance = static_cast<int>(this->screenDensityDpi_ - density);
571             otherDistance = static_cast<int>(otherDensity - density);
572             if (IsDensityMoreSuitable(thisDistance, otherDistance)) {
573                 // the density of this resConfig is suitable than other resConfig
574                 ret = 1;
575             } else {
576                 // the density of other resConfig is suitable than this resConfig
577                 ret = -1;
578             }
579         }
580     }
581     return ret;
582 }
583 
IsDensityMoreSuitable(int thisDistance,int otherDistance) const584 bool ResConfigImpl::IsDensityMoreSuitable(int thisDistance, int otherDistance) const
585 {
586     if (thisDistance >= 0 && otherDistance >= 0) {
587         return (thisDistance <= otherDistance);
588     }
589     if (thisDistance > 0) {
590         return true;
591     }
592     if (otherDistance > 0) {
593         return false;
594     }
595     return (thisDistance >= otherDistance);
596 }
597 
~ResConfigImpl()598 ResConfigImpl::~ResConfigImpl()
599 {
600     if (resLocale_ != nullptr) {
601         delete resLocale_;
602         resLocale_ = nullptr;
603     }
604     if (resPreferredLocale_ != nullptr) {
605         delete resPreferredLocale_;
606         resPreferredLocale_ = nullptr;
607     }
608 #ifdef SUPPORT_GRAPHICS
609     if (localeInfo_ != nullptr) {
610         delete localeInfo_;
611         localeInfo_ = nullptr;
612     }
613     if (preferredLocaleInfo_ != nullptr) {
614         delete preferredLocaleInfo_;
615         preferredLocaleInfo_ = nullptr;
616     }
617 #endif
618 }
619 
CompleteScript()620 void ResConfigImpl::CompleteScript()
621 {
622     if (isCompletedScript_) {
623         return;
624     }
625     if (LocaleMatcher::Normalize(this->resLocale_)) {
626         isCompletedScript_ = true;
627     }
628 }
629 
IsCompletedScript() const630 bool ResConfigImpl::IsCompletedScript() const
631 {
632     return isCompletedScript_;
633 }
634 
IsMoreSpecificThan(const ResConfigImpl * other,uint32_t density) const635 bool ResConfigImpl::IsMoreSpecificThan(const ResConfigImpl *other, uint32_t density) const
636 {
637     if (other == nullptr) {
638         return true;
639     }
640     if (this->mcc_ != MCC_UNDEFINED && this->mnc_ != MNC_UNDEFINED) {
641         if (this->mcc_ != other->mcc_ || this->mnc_ != other->mnc_) {
642             return false;
643         }
644     } else if (this->mcc_ != MCC_UNDEFINED && this->mnc_ == MNC_UNDEFINED) {
645         if (this->mcc_ != other->mcc_) {
646             return true;
647         }
648     }
649     int8_t result = LocaleMatcher::IsMoreSpecificThan(
650         this->GetResLocale(),
651         (other == nullptr) ? nullptr : other->GetResLocale());
652     if (result > 0) {
653         return true;
654     }
655     if (result < 0) {
656         return false;
657     }
658     if (this->direction_ != other->direction_) {
659         return (this->direction_ != Direction::DIRECTION_NOT_SET);
660     }
661     if (this->deviceType_ != other->deviceType_) {
662         return (this->deviceType_ != DeviceType::DEVICE_NOT_SET);
663     }
664     if (this->colorMode_ != other->colorMode_) {
665         return (this->colorMode_ != ColorMode::COLOR_MODE_NOT_SET);
666     }
667     if (this->inputDevice_ != other->inputDevice_) {
668         return (this->inputDevice_ == InputDevice::INPUTDEVICE_NOT_SET);
669     }
670     int ret = IsDensityMoreSpecificThan(other->screenDensityDpi_, density);
671     if (ret != 0) {
672         return ret > 0;
673     }
674 
675     return true;
676 }
677 
IsDensityMoreSpecificThan(ScreenDensity otherDensity,uint32_t density) const678 int ResConfigImpl::IsDensityMoreSpecificThan(ScreenDensity otherDensity, uint32_t density) const
679 {
680     int ret = 0;
681     if (density == SCREEN_DENSITY_NOT_SET) {
682         if (this->screenDensityDpi_ != otherDensity) {
683             if (this->screenDensityDpi_ != ScreenDensity::SCREEN_DENSITY_NOT_SET) {
684                 // the density of this resConfig is suitable than other resConfig
685                 ret = 1;
686             } else {
687                 // the density of other resConfig is suitable than this resConfig
688                 ret = -1;
689             }
690         }
691     } else {
692         if ((this->screenDensityDpi_ != ScreenDensity::SCREEN_DENSITY_NOT_SET) &&
693                 (otherDensity == ScreenDensity::SCREEN_DENSITY_NOT_SET)) {
694             // the density of this resConfig is suitable than other resConfig
695             ret = 1;
696         }
697         if ((this->screenDensityDpi_ == ScreenDensity::SCREEN_DENSITY_NOT_SET) &&
698                 (otherDensity != ScreenDensity::SCREEN_DENSITY_NOT_SET)) {
699             // the density of other resConfig is suitable than this resConfig
700             ret = -1;
701         }
702         if (this->screenDensityDpi_ != otherDensity) {
703             int thisDistance = static_cast<int>(this->screenDensityDpi_ - density);
704             int otherDistance = static_cast<int>(otherDensity - density);
705             if (IsDensityMoreSuitable(thisDistance, otherDistance)) {
706                 // the density of this resConfig is suitable than other resConfig
707                 ret = 1;
708             } else {
709                 // the density of other resConfig is suitable than this resConfig
710                 ret = -1;
711             }
712         }
713     }
714     return ret;
715 }
716 
CreateResConfig()717 ResConfig *CreateResConfig()
718 {
719     ResConfigImpl *temp = new(std::nothrow) ResConfigImpl;
720     return temp;
721 }
722 } // namespace Resource
723 } // namespace Global
724 } // namespace OHOS