1 /*
2 * Copyright (c) 2020-2021 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
16 #include "font/ui_multi_font_manager.h"
17 #include "common/typed_text.h"
18 #include "font/ui_font.h"
19
20 #include "gfx_utils/mem_api.h"
21 #include "securec.h"
22 #if ENABLE_SHAPING
23 #include "font/ui_text_shaping.h"
24 #endif
25 #if ENABLE_MULTI_FONT
26 namespace OHOS {
UIMultiFontManager()27 UIMultiFontManager::UIMultiFontManager()
28 : arbicTtfId_(0), thaiTtfId_(0), myanmarTtfId_(0),
29 devanagariTtfId_(0), hebrewTtfId_(0),
30 bengaliTtfId_(0), topIndex_(0)
31 {
32 const UITextLanguageFontParam* fontParam = nullptr;
33 uint16_t totalFontId = UIFontBuilder::GetInstance()->GetTotalFontId();
34 for (uint16_t i = 0; i < totalFontId; i++) {
35 fontParam = UIFont::GetInstance()->GetFontInfo(i);
36 if (fontParam == nullptr) {
37 continue;
38 }
39 if (!fontParam->shaping) {
40 continue;
41 }
42 if (strstr(fontParam->ttfName, ARABIC_LANG) != nullptr) {
43 arbicTtfId_ = fontParam->ttfId;
44 } else if (strstr(fontParam->ttfName, THAI_LANG) != nullptr) {
45 thaiTtfId_ = fontParam->ttfId;
46 } else if (strstr(fontParam->ttfName, MYAN_LANG) != nullptr) {
47 myanmarTtfId_ = fontParam->ttfId;
48 } else if (strstr(fontParam->ttfName, DVCARI_LANG) != nullptr) {
49 devanagariTtfId_ = fontParam->ttfId;
50 } else if (strstr(fontParam->ttfName, HBREW_LANG) != nullptr) {
51 hebrewTtfId_ = fontParam->ttfId;
52 } else if (strstr(fontParam->ttfName, BENGALI_LANG) != nullptr) {
53 bengaliTtfId_ = fontParam->ttfId;
54 }
55 }
56 fontIdIndex_ = static_cast<uint8_t*>(UIMalloc(totalFontId));
57 if (fontIdIndex_ == nullptr) {
58 return;
59 }
60 for (uint16_t index = 0; index < totalFontId; index++) {
61 fontIdIndex_[index] = MAX_FONT_SEARCH_NUM;
62 }
63 for (uint8_t index = 0; index < MAX_FONT_SEARCH_NUM; index++) {
64 fontNodes_[index].fontIds = nullptr;
65 fontNodes_[index].size = 0;
66 }
67 }
68
~UIMultiFontManager()69 UIMultiFontManager::~UIMultiFontManager()
70 {
71 UIFree(fontIdIndex_);
72 fontIdIndex_ = nullptr;
73 }
74
AddNewFont(uint16_t fontListId,uint16_t * fontIds,int8_t size,uint8_t fontIndex)75 int8_t UIMultiFontManager::AddNewFont(uint16_t fontListId, uint16_t* fontIds, int8_t size, uint8_t fontIndex)
76 {
77 fontNodes_[fontIndex].fontIds = static_cast<uint16_t*>(UIMalloc(size * sizeof(uint16_t)));
78 if (fontNodes_[fontIndex].fontIds == nullptr) {
79 return fontIndex;
80 }
81 fontIdIndex_[fontListId] = fontIndex;
82 (void)memcpy_s(fontNodes_[fontIndex].fontIds, size * sizeof(uint16_t), fontIds, size * sizeof(uint16_t));
83 fontNodes_[fontIndex].size = size;
84 return fontIndex + 1;
85 }
86
UpdateFont(uint16_t fontListId,uint16_t * fontIds,uint8_t size)87 int8_t UIMultiFontManager::UpdateFont(uint16_t fontListId, uint16_t* fontIds, uint8_t size)
88 {
89 uint8_t index = fontIdIndex_[fontListId];
90 if (index < topIndex_) {
91 UIFree(fontNodes_[index].fontIds);
92 fontNodes_[index].fontIds = nullptr;
93 } else {
94 index = topIndex_;
95 }
96
97 uint8_t nextIndex = AddNewFont(fontListId, fontIds, size, index);
98 if (topIndex_ < nextIndex) {
99 topIndex_ = nextIndex;
100 }
101 return (fontNodes_[index].fontIds == nullptr) ? INVALID_RET_VALUE : RET_VALUE_OK;
102 }
103
UpdateScript(UITextLanguageFontParam & fonts)104 void UIMultiFontManager::UpdateScript(UITextLanguageFontParam& fonts)
105 {
106 if (strstr(fonts.ttfName, ARABIC_LANG) != nullptr) {
107 arbicTtfId_ = fonts.ttfId;
108 } else if (strstr(fonts.ttfName, THAI_LANG) != nullptr) {
109 thaiTtfId_ = fonts.ttfId;
110 } else if (strstr(fonts.ttfName, MYAN_LANG) != nullptr) {
111 myanmarTtfId_ = fonts.ttfId;
112 } else if (strstr(fonts.ttfName, DVCARI_LANG) != nullptr) {
113 devanagariTtfId_ = fonts.ttfId;
114 } else if (strstr(fonts.ttfName, HBREW_LANG) != nullptr) {
115 hebrewTtfId_ = fonts.ttfId;
116 } else if (strstr(fonts.ttfName, BENGALI_LANG) != nullptr) {
117 bengaliTtfId_ = fonts.ttfId;
118 }
119 }
120
GetInstance()121 UIMultiFontManager* UIMultiFontManager::GetInstance()
122 {
123 static UIMultiFontManager instance;
124 return &instance;
125 }
126
ClearSearchFontList()127 void UIMultiFontManager::ClearSearchFontList()
128 {
129 uint16_t totalFontId = UIFontBuilder::GetInstance()->GetTotalFontId();
130 for (uint16_t index = 0; index < totalFontId; index++) {
131 fontIdIndex_[index] = MAX_FONT_SEARCH_NUM;
132 }
133
134 for (auto &node : fontNodes_) {
135 UIFree(node.fontIds);
136 node.fontIds = nullptr;
137 node.size = 0;
138 }
139 topIndex_ = 0;
140 }
141
SetSearchFontList(uint16_t fontListId,uint16_t * fontIds,uint8_t size)142 int8_t UIMultiFontManager::SetSearchFontList(uint16_t fontListId, uint16_t* fontIds, uint8_t size)
143 {
144 if ((fontListId >= UIFontBuilder::GetInstance()->GetTotalFontId()) || (fontIds == nullptr) || (size == 0) ||
145 (fontIdIndex_ == nullptr) || (topIndex_ >= MAX_FONT_SEARCH_NUM)) {
146 return INVALID_RET_VALUE;
147 }
148 // update
149 return UpdateFont(fontListId, fontIds, size);
150 }
151
GetSearchFontList(uint16_t fontListId,uint16_t ** fontIds)152 int32_t UIMultiFontManager::GetSearchFontList(uint16_t fontListId, uint16_t** fontIds)
153 {
154 if ((fontListId >= UIFontBuilder::GetInstance()->GetTotalFontId()) || (fontIds == nullptr) ||
155 (fontIdIndex_ == nullptr) || (fontIdIndex_[fontListId] >= MAX_FONT_SEARCH_NUM)) {
156 return static_cast<uint32_t>(INVALID_RET_VALUE);
157 }
158 *fontIds = fontNodes_[fontIdIndex_[fontListId]].fontIds;
159 return static_cast<uint32_t>(fontNodes_[fontIdIndex_[fontListId]].size);
160 }
161
IsNeedShaping(const char * text,uint8_t & ttfId,uint32_t & script)162 bool UIMultiFontManager::IsNeedShaping(const char *text, uint8_t &ttfId, uint32_t &script)
163 {
164 if (text == nullptr) {
165 return false;
166 }
167
168 uint32_t i = 0;
169 while (text[i] != '\0') {
170 uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
171 if (IsShapingLetter(unicode, ttfId)) {
172 #if ENABLE_SHAPING
173 script = GetScriptByTtfId(ttfId);
174 #endif
175 return true;
176 }
177 }
178 return false;
179 }
180
GetShapingFontId(const char * text,uint16_t fontId,uint8_t & ttfId,uint32_t & script)181 uint16_t UIMultiFontManager::GetShapingFontId(const char* text, uint16_t fontId, uint8_t& ttfId, uint32_t& script)
182 {
183 // the shaping font is in search list, then shapingFontId_ store the real shaping fontid
184 UIFont* fontEngine = UIFont::GetInstance();
185 const UITextLanguageFontParam* fontParam1 = fontEngine->GetFontInfo(fontId);
186 if (fontParam1 == nullptr) {
187 return DEFAULT_SHAPING_ID;
188 }
189 if (!fontParam1->shaping) {
190 if (!IsNeedShaping(text, ttfId, script)) {
191 return 0; // 0 means no need to shape
192 }
193 uint16_t* searchLists = nullptr;
194 int32_t length = GetSearchFontList(fontId, &searchLists);
195 const UITextLanguageFontParam* fontParam2 = nullptr;
196 for (uint16_t i = 0; i < length; i++) {
197 fontParam2 = fontEngine->GetFontInfo(searchLists[i]);
198 if (fontParam2 == nullptr) {
199 continue;
200 }
201 if (fontParam2->ttfId == ttfId) {
202 return searchLists[i];
203 }
204 }
205 return 0;
206 }
207 ttfId = fontParam1->ttfId;
208
209 #if ENABLE_SHAPING
210 script = GetScriptByTtfId(ttfId);
211 #endif
212 return DEFAULT_SHAPING_ID;
213 }
IsShapingLetter(uint32_t unicode,uint8_t & ttfId)214 int8_t UIMultiFontManager::IsShapingLetter(uint32_t unicode, uint8_t &ttfId)
215 {
216 // arbic
217 if ((unicode <= 0x06FF) && (unicode >= 0x0600)) {
218 ttfId = arbicTtfId_;
219 return ttfId != 0;
220 }
221 // thai
222 if ((unicode <= 0x0E7F) && (unicode >= 0x0E00)) {
223 ttfId = thaiTtfId_;
224 return ttfId != 0;
225 }
226 // Devanagari
227 if ((unicode <= 0x097F) && (unicode >= 0x0900)) {
228 ttfId = devanagariTtfId_;
229 return ttfId != 0;
230 }
231 // Hebrew
232 if ((unicode <= 0x05FF) && (unicode >= 0x0590)) {
233 ttfId = hebrewTtfId_;
234 return ttfId != 0;
235 }
236 // Myanmar
237 if ((unicode <= 0x109F) && (unicode >= 0x1000)) {
238 ttfId = myanmarTtfId_;
239 return ttfId != 0;
240 }
241 // Bengali
242 if ((unicode <= 0x9FF) && (unicode >= 0x980)) {
243 ttfId = bengaliTtfId_;
244 return ttfId != 0;
245 }
246 return false;
247 }
248 #if ENABLE_SHAPING
GetScriptByTtfId(uint8_t ttfId)249 uint32_t UIMultiFontManager::GetScriptByTtfId(uint8_t ttfId)
250 {
251 // arbic
252 if (ttfId == arbicTtfId_) {
253 return SHAPING_SCRIPT_ARABIC;
254 }
255 // thai
256 if (ttfId == thaiTtfId_) {
257 return SHAPING_SCRIPT_THAI;
258 }
259 // Devanagari
260 if (ttfId == devanagariTtfId_) {
261 return SHAPING_SCRIPT_DEVANAGARI;
262 }
263 // Hebrew
264 if (ttfId == hebrewTtfId_) {
265 return SHAPING_SCRIPT_HEBREW;
266 }
267 // Myanmar
268 if (ttfId == myanmarTtfId_) {
269 return SHAPING_SCRIPT_MYANMAR;
270 }
271 // Bengali
272 if (ttfId == bengaliTtfId_) {
273 return SHAPING_SCRIPT_BENGALI;
274 }
275 return SHAPING_SCRIPT_INVALID;
276 }
277 #endif
278 }
279 #endif
280