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
75
AddNewFont(uint16_t fontListId,uint16_t * fontIds,int8_t size,uint8_t fontIndex)76 int8_t UIMultiFontManager::AddNewFont(uint16_t fontListId, uint16_t *fontIds, int8_t size, uint8_t fontIndex)
77 {
78 fontNodes_[fontIndex].fontIds = static_cast<uint16_t *>(UIMalloc(size * sizeof(uint16_t)));
79 if (fontNodes_[fontIndex].fontIds == nullptr) {
80 return fontIndex;
81 }
82 fontIdIndex_[fontListId] = fontIndex;
83 (void)memcpy_s(fontNodes_[fontIndex].fontIds, size * sizeof(uint16_t), fontIds, size * sizeof(uint16_t));
84 fontNodes_[fontIndex].size = size;
85 return fontIndex + 1;
86 }
87
UpdateFont(uint16_t fontListId,uint16_t * fontIds,uint8_t size)88 int8_t UIMultiFontManager::UpdateFont(uint16_t fontListId, uint16_t *fontIds, uint8_t size)
89 {
90 uint8_t index = fontIdIndex_[fontListId];
91 if (index < topIndex_) {
92 UIFree(fontNodes_[index].fontIds);
93 fontNodes_[index].fontIds = nullptr;
94 } else {
95 index = topIndex_;
96 }
97
98 uint8_t nextIndex = AddNewFont(fontListId, fontIds, size, index);
99 if (topIndex_ < nextIndex) {
100 topIndex_ = nextIndex;
101 }
102 return (fontNodes_[index].fontIds == nullptr) ? INVALID_RET_VALUE : RET_VALUE_OK;
103 }
104
UpdateScript(UITextLanguageFontParam & fonts)105 void UIMultiFontManager::UpdateScript(UITextLanguageFontParam& fonts)
106 {
107 if (strstr(fonts.ttfName, ARABIC_LANG) != nullptr) {
108 arbicTtfId_ = fonts.ttfId;
109 } else if (strstr(fonts.ttfName, THAI_LANG) != nullptr) {
110 thaiTtfId_ = fonts.ttfId;
111 } else if (strstr(fonts.ttfName, MYAN_LANG) != nullptr) {
112 myanmarTtfId_ = fonts.ttfId;
113 } else if (strstr(fonts.ttfName, DVCARI_LANG) != nullptr) {
114 devanagariTtfId_ = fonts.ttfId;
115 } else if (strstr(fonts.ttfName, HBREW_LANG) != nullptr) {
116 hebrewTtfId_ = fonts.ttfId;
117 } else if (strstr(fonts.ttfName, BENGALI_LANG) != nullptr) {
118 bengaliTtfId_ = fonts.ttfId;
119 }
120 }
121
GetInstance()122 UIMultiFontManager* UIMultiFontManager::GetInstance()
123 {
124 static UIMultiFontManager instance;
125 return &instance;
126 }
127
ClearSearchFontList()128 void UIMultiFontManager::ClearSearchFontList()
129 {
130 uint16_t totalFontId = UIFontBuilder::GetInstance()->GetTotalFontId();
131 for (uint16_t index = 0; index < totalFontId; index++) {
132 fontIdIndex_[index] = MAX_FONT_SEARCH_NUM;
133 }
134
135 for (auto &node : fontNodes_) {
136 UIFree(node.fontIds);
137 node.fontIds = nullptr;
138 node.size = 0;
139 }
140 topIndex_ = 0;
141 }
142
SetSearchFontList(uint16_t fontListId,uint16_t * fontIds,uint8_t size)143 int8_t UIMultiFontManager::SetSearchFontList(uint16_t fontListId, uint16_t *fontIds, uint8_t size)
144 {
145 if ((fontListId >= UIFontBuilder::GetInstance()->GetTotalFontId()) || (fontIds == nullptr) || (size == 0) ||
146 (fontIdIndex_ == nullptr) || (topIndex_ >= MAX_FONT_SEARCH_NUM)) {
147 return INVALID_RET_VALUE;
148 }
149 // update
150 return UpdateFont(fontListId, fontIds, size);
151 }
152
GetSearchFontList(uint16_t fontListId,uint16_t ** fontIds)153 int32_t UIMultiFontManager::GetSearchFontList(uint16_t fontListId, uint16_t **fontIds)
154 {
155 if ((fontListId >= UIFontBuilder::GetInstance()->GetTotalFontId()) || (fontIds == nullptr) ||
156 (fontIdIndex_ == nullptr) || (fontIdIndex_[fontListId] >= MAX_FONT_SEARCH_NUM)) {
157 return INVALID_RET_VALUE;
158 }
159 *fontIds = fontNodes_[fontIdIndex_[fontListId]].fontIds;
160 return fontNodes_[fontIdIndex_[fontListId]].size;
161 }
162
IsNeedShaping(const char * text,uint8_t & ttfId,uint32_t & script)163 bool UIMultiFontManager::IsNeedShaping(const char *text, uint8_t &ttfId, uint32_t &script)
164 {
165 if (text == nullptr) {
166 return false;
167 }
168
169 uint32_t i = 0;
170 while (text[i] != '\0') {
171 uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
172 if (IsShapingLetter(unicode, ttfId)) {
173 #if ENABLE_SHAPING
174 script = GetScriptByTtfId(ttfId);
175 #endif
176 return true;
177 }
178 }
179 return false;
180 }
181
GetShapingFontId(const char * text,uint16_t fontId,uint8_t & ttfId,uint32_t & script)182 uint16_t UIMultiFontManager::GetShapingFontId(const char* text, uint16_t fontId, uint8_t& ttfId, uint32_t& script)
183 {
184 // the shaping font is in search list, then shapingFontId_ store the real shaping fontid
185 const UITextLanguageFontParam* fontParam1 = UIFont::GetInstance()->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 = UIFont::GetInstance()->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