• 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 
17 #include <unicode/localebuilder.h>
18 #include <unicode/locid.h>
19 
20 #include "locale_matcher.h"
21 #include "res_locale.h"
22 #include "utils/utils.h"
23 using icu::Locale;
24 using icu::LocaleBuilder;
25 namespace OHOS {
26 namespace Global {
27 namespace Resource {
ResConfigImpl()28 ResConfigImpl::ResConfigImpl()
29     : resLocale_(nullptr),
30       direction_(DIRECTION_NOT_SET),
31       screenDensity_(SCREEN_DENSITY_NOT_SET),
32       colorMode_(LIGHT),
33       deviceType_(DEVICE_NOT_SET),
34       isCompletedScript_(false), localeInfo_(nullptr)
35 {}
36 
SetLocaleInfo(Locale & localeInfo)37 RState ResConfigImpl::SetLocaleInfo(Locale &localeInfo)
38 {
39     return this->SetLocaleInfo(localeInfo.getLanguage(), localeInfo.getScript(), localeInfo.getCountry());
40 }
41 
SetLocaleInfo(const char * language,const char * script,const char * region)42 RState ResConfigImpl::SetLocaleInfo(const char *language,
43     const char *script,
44     const char *region)
45 {
46     RState state = SUCCESS;
47     if (Utils::IsStrEmpty(language)) {
48         delete this->resLocale_;
49         delete this->localeInfo_;
50         this->resLocale_ = nullptr;
51         this->localeInfo_ = nullptr;
52         return state;
53     }
54     ResLocale *resLocale =
55         ResLocale::BuildFromParts(language, script, region, state);
56     if (state == SUCCESS) {
57         this->isCompletedScript_ = false;
58         if (script == nullptr || script[0] == '\0') {
59             if (LocaleMatcher::Normalize(resLocale)) {
60                 this->isCompletedScript_ = true;
61             } else {
62                 delete resLocale;
63                 return NOT_ENOUGH_MEM;
64             }
65         }
66         UErrorCode errCode = U_ZERO_ERROR;
67         Locale temp = icu::LocaleBuilder().setLanguage(resLocale->GetLanguage())
68                                  .setRegion(resLocale->GetRegion()).setScript(resLocale->GetScript()).build(errCode);
69 
70         if (!U_SUCCESS(errCode)) {
71             state = NOT_ENOUGH_MEM;
72             delete resLocale;
73             return state;
74         }
75         delete resLocale_;
76         delete localeInfo_;
77         resLocale_ = resLocale;
78         localeInfo_ = new Locale(temp);
79     }
80 
81     return state;
82 }
83 
SetDeviceType(DeviceType deviceType)84 void ResConfigImpl::SetDeviceType(DeviceType deviceType)
85 {
86     this->deviceType_ = deviceType;
87 }
88 
SetDirection(Direction direction)89 void ResConfigImpl::SetDirection(Direction direction)
90 {
91     this->direction_ = direction;
92 }
93 
SetColorMode(ColorMode colorMode)94 void ResConfigImpl::SetColorMode(ColorMode colorMode)
95 {
96     this->colorMode_ = colorMode;
97 }
98 
SetScreenDensity(ScreenDensity screenDensity)99 void ResConfigImpl::SetScreenDensity(ScreenDensity screenDensity)
100 {
101     this->screenDensity_ = screenDensity;
102 }
103 
GetLocaleInfo() const104 const Locale *ResConfigImpl::GetLocaleInfo() const
105 {
106     return localeInfo_;
107 }
108 
GetResLocale() const109 const ResLocale *ResConfigImpl::GetResLocale() const
110 {
111     return this->resLocale_;
112 }
113 
GetDirection() const114 Direction ResConfigImpl::GetDirection() const
115 {
116     return this->direction_;
117 }
118 
GetScreenDensity() const119 ScreenDensity ResConfigImpl::GetScreenDensity() const
120 {
121     return this->screenDensity_;
122 }
123 
GetColorMode() const124 ColorMode ResConfigImpl::GetColorMode() const
125 {
126     return this->colorMode_;
127 }
128 
GetDeviceType() const129 DeviceType ResConfigImpl::GetDeviceType() const
130 {
131     return this->deviceType_;
132 }
CopyLocale(ResConfig & other)133 bool ResConfigImpl::CopyLocale(ResConfig &other)
134 {
135     bool needCopy = false;
136     if (this->GetLocaleInfo() == nullptr && other.GetLocaleInfo() != nullptr) {
137         needCopy = true;
138     }
139     if (this->GetLocaleInfo() != nullptr && other.GetLocaleInfo() == nullptr) {
140         delete this->resLocale_;
141         delete this->localeInfo_;
142         this->resLocale_ = nullptr;
143         this->localeInfo_ = nullptr;
144         return true;
145     }
146     if (this->GetResLocale() != nullptr && other.GetLocaleInfo() != nullptr) {
147         uint64_t encodedLocale = Utils::EncodeLocale(
148             this->GetResLocale()->GetLanguage(),
149             this->GetResLocale()->GetScript(), this->GetResLocale()->GetRegion());
150         uint64_t otherEncodedLocale = Utils::EncodeLocale(
151             other.GetLocaleInfo()->getLanguage(),
152             other.GetLocaleInfo()->getScript(), other.GetLocaleInfo()->getCountry());
153         if (encodedLocale != otherEncodedLocale) {
154             needCopy = true;
155         }
156     }
157     if (needCopy) {
158         ResLocale *temp = new(std::nothrow) ResLocale;
159         if (temp == nullptr) {
160             return false;
161         }
162         RState rs = temp->CopyFromLocaleInfo(other.GetLocaleInfo());
163         if (rs != SUCCESS) {
164             delete temp;
165             return false;
166         }
167         UErrorCode errCode = U_ZERO_ERROR;
168         Locale tempLocale = icu::LocaleBuilder().setLocale(*other.GetLocaleInfo()).build(errCode);
169 
170         if (!U_SUCCESS(errCode)) {
171             delete temp;
172             return false;
173         }
174         delete this->resLocale_;
175         delete this->localeInfo_;
176         this->resLocale_ = temp;
177         this->localeInfo_ = new Locale(tempLocale);
178     }
179     return true;
180 }
Copy(ResConfig & other)181 bool ResConfigImpl::Copy(ResConfig &other)
182 {
183     bool isSuccess = this->CopyLocale(other);
184     if (!isSuccess) {
185         return false;
186     }
187     if (this->GetDeviceType() != other.GetDeviceType()) {
188         this->SetDeviceType(other.GetDeviceType());
189     }
190     if (this->GetDirection() != other.GetDirection()) {
191         this->SetDirection(other.GetDirection());
192     }
193     if (this->GetColorMode() != other.GetColorMode()) {
194         this->SetColorMode(other.GetColorMode());
195     }
196     if (this->GetScreenDensity() != other.GetScreenDensity()) {
197         this->SetScreenDensity(other.GetScreenDensity());
198     }
199     return true;
200 }
201 
Match(const ResConfigImpl * other) const202 bool ResConfigImpl::Match(const ResConfigImpl *other) const
203 {
204     if (other == nullptr) {
205         return false;
206     }
207     if (LocaleMatcher::Match(this->resLocale_, other->GetResLocale()) == false) {
208         return false;
209     }
210     if (this->direction_ != DIRECTION_NOT_SET &&
211         other->direction_ != DIRECTION_NOT_SET) {
212         if (this->direction_ != other->direction_) {
213             return false;
214         }
215     }
216     if (this->deviceType_ != DEVICE_NOT_SET &&
217         other->deviceType_ != DEVICE_NOT_SET) {
218         if (this->deviceType_ != other->deviceType_) {
219             return false;
220         }
221     }
222     if (this->colorMode_ != COLOR_MODE_NOT_SET &&
223         other->colorMode_ != COLOR_MODE_NOT_SET) {
224         if (this->colorMode_ != other->colorMode_) {
225             return false;
226         }
227     }
228     return true;
229 }
230 
231 /**
232  * compare this  and target
233  * if this more match request,then return true
234  * else
235  * return false
236  *
237  */
IsMoreSuitable(const ResConfigImpl * other,const ResConfigImpl * request) const238 bool ResConfigImpl::IsMoreSuitable(const ResConfigImpl *other,
239     const ResConfigImpl *request) const
240 {
241     if (request != nullptr && other != nullptr) {
242         int8_t result =
243             LocaleMatcher::IsMoreSuitable(this->GetResLocale(), other->GetResLocale(),
244                                           request->GetResLocale());
245         if (result > 0) {
246             return true;
247         }
248         if (result < 0) {
249             return false;
250         }
251         /**
252          * direction must full match.
253          * when request is set direction and this is not equal other.
254          * this or other oriention is not set.
255          */
256         if (this->direction_ != other->direction_ &&
257             request->direction_ != Direction::DIRECTION_NOT_SET) {
258             return this->direction_ != Direction::DIRECTION_NOT_SET;
259         }
260         if (this->deviceType_ != other->deviceType_ &&
261             request->deviceType_ != DeviceType::DEVICE_NOT_SET) {
262             return this->deviceType_ != DeviceType::DEVICE_NOT_SET;
263         }
264         if (this->colorMode_ != other->colorMode_ &&
265             request->colorMode_ != ColorMode::COLOR_MODE_NOT_SET) {
266             return this->colorMode_ != ColorMode::COLOR_MODE_NOT_SET;
267         }
268         if (request->screenDensity_ != ScreenDensity::SCREEN_DENSITY_NOT_SET &&
269             this->screenDensity_ != other->screenDensity_) {
270             int thisDistance = this->screenDensity_ - request->screenDensity_;
271             int otherDistance = other->screenDensity_ - request->screenDensity_;
272             if (thisDistance >= 0 && otherDistance >= 0) {
273                 return (thisDistance <= otherDistance);
274             }
275             if (thisDistance > 0) {
276                 return true;
277             }
278             if (otherDistance > 0) {
279                 return false;
280             }
281             return (thisDistance >= otherDistance);
282         }
283     }
284     return this->IsMoreSpecificThan(other);
285 }
286 
~ResConfigImpl()287 ResConfigImpl::~ResConfigImpl()
288 {
289     delete resLocale_;
290     delete localeInfo_;
291 }
292 
CompleteScript()293 void ResConfigImpl::CompleteScript()
294 {
295     if (isCompletedScript_) {
296         return;
297     }
298     if (LocaleMatcher::Normalize(this->resLocale_)) {
299         isCompletedScript_ = true;
300     }
301 }
302 
IsCompletedScript() const303 bool ResConfigImpl::IsCompletedScript() const
304 {
305     return isCompletedScript_;
306 }
307 
IsMoreSpecificThan(const ResConfigImpl * other) const308 bool ResConfigImpl::IsMoreSpecificThan(const ResConfigImpl *other) const
309 {
310     if (other == nullptr) {
311         return true;
312     }
313     int8_t result = LocaleMatcher::IsMoreSpecificThan(
314         this->GetResLocale(),
315         (other == nullptr) ? nullptr : other->GetResLocale());
316     if (result > 0) {
317         return true;
318     }
319     if (result < 0) {
320         return false;
321     }
322     if (this->direction_ != other->direction_) {
323         return (this->direction_ != Direction::DIRECTION_NOT_SET);
324     }
325     if (this->deviceType_ != other->deviceType_) {
326         return (this->deviceType_ != DeviceType::DEVICE_NOT_SET);
327     }
328     if (this->colorMode_ != other->colorMode_) {
329         return (this->colorMode_ != ColorMode::COLOR_MODE_NOT_SET);
330     }
331     if (this->screenDensity_ != other->screenDensity_) {
332         return  (this->screenDensity_ != ScreenDensity::SCREEN_DENSITY_NOT_SET);
333     }
334     return true;
335 }
336 
CreateResConfig()337 ResConfig *CreateResConfig()
338 {
339     ResConfigImpl *temp = new(std::nothrow) ResConfigImpl;
340     return temp;
341 }
342 } // namespace Resource
343 } // namespace Global
344 } // namespace OHOS