1 /*
2 * Copyright (c) 2020-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
16 #include "font/ui_font_bitmap.h"
17
18 #include "draw/draw_utils.h"
19 #include "font/font_ram_allocator.h"
20 #include "font/ui_font.h"
21 #include "font/ui_font_adaptor.h"
22 #include "font/ui_font_builder.h"
23 #include "gfx_utils/file.h"
24 #include "gfx_utils/graphic_log.h"
25 #include "graphic_config.h"
26 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
27 #include "font/ui_multi_font_manager.h"
28 #endif
29 #if defined(ENABLE_SHAPING) && ENABLE_SHAPING
30 #include "font/ui_text_shaping.h"
31 #endif
32 #include "font/ui_font_cache_manager.h"
33
34 namespace OHOS {
UIFontBitmap()35 UIFontBitmap::UIFontBitmap() : offset_(0), dynamicFont_() {}
36
~UIFontBitmap()37 UIFontBitmap::~UIFontBitmap()
38 {
39 CloseFontFd();
40 }
41
CloseFontFd()42 void UIFontBitmap::CloseFontFd()
43 {
44 for (uint16_t i = 0; i < dynamicFontFd_.Size(); i++) {
45 if (dynamicFontFd_[i] >= 0) {
46 close(dynamicFontFd_[i]);
47 dynamicFontFd_[i] = -1;
48 }
49 }
50 }
51
IsVectorFont() const52 bool UIFontBitmap::IsVectorFont() const
53 {
54 return false;
55 }
56
57 uint16_t
GetShapingFontId(char * text,uint8_t & ttfId,uint32_t & script,uint16_t fontId,uint8_t size) const58 UIFontBitmap::GetShapingFontId(char* text, uint8_t& ttfId, uint32_t& script, uint16_t fontId, uint8_t size) const
59 {
60 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
61 return UIMultiFontManager::GetInstance()->GetShapingFontId(text, fontId, ttfId, script);
62 #else
63 UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
64 if (fontParam == nullptr) {
65 return 0;
66 }
67 ttfId = fontParam->ttfId;
68 return fontParam->shaping;
69 #endif
70 }
71
GetFontWeight(uint16_t fontId)72 uint8_t UIFontBitmap::GetFontWeight(uint16_t fontId)
73 {
74 UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
75 if (fontParam == nullptr) {
76 GRAPHIC_LOGE("UIFontBitmap::GetFontWeigh invalid fontId");
77 return 0;
78 }
79 return fontParam->fontWeight;
80 }
81
SetFontPath(const char * path,FontType type)82 int8_t UIFontBitmap::SetFontPath(const char* path, FontType type)
83 {
84 if ((path == nullptr) || (type != DYNAMIC_FONT)) {
85 GRAPHIC_LOGE("UIFontBitmap::SetFontPath invalid parameter");
86 return INVALID_RET_VALUE;
87 }
88 #ifdef _WIN32
89 int32_t fontFd = open(path, O_RDONLY | O_BINARY);
90 #else
91 int32_t fontFd = open(path, O_RDONLY);
92 #endif
93 if (fontFd < 0) {
94 GRAPHIC_LOGE("UIFontBitmap::SetFontPath file Open failed");
95 return INVALID_RET_VALUE;
96 }
97
98 int32_t ret = dynamicFont_.SetFile(path, fontFd, offset_, GlyphCacheType::CACHE_TYPE_DYNAMIC);
99 if (ret == INVALID_RET_VALUE) {
100 GRAPHIC_LOGE("GlyphsManager::SetFile failed");
101 close(fontFd);
102 return ret;
103 }
104 dynamicFontFd_.PushBack(fontFd);
105 return RET_VALUE_OK;
106 }
107
GetHeight(uint16_t fontId,uint8_t fontSize)108 uint16_t UIFontBitmap::GetHeight(uint16_t fontId, uint8_t fontSize)
109 {
110 return dynamicFont_.GetFontHeight(fontId);
111 }
112
GetFontId(const char * ttfName,uint8_t size) const113 uint16_t UIFontBitmap::GetFontId(const char* ttfName, uint8_t size) const
114 {
115 UIFontBuilder* fontBuilder = UIFontBuilder::GetInstance();
116 if (ttfName == nullptr) {
117 return fontBuilder->GetBitmapFontIdMax();
118 }
119 uint16_t id;
120 for (id = 0; id < fontBuilder->GetBitmapFontIdMax(); ++id) {
121 UITextLanguageFontParam* fontParam = fontBuilder->GetTextLangFontsTable(id);
122 if (fontParam != nullptr) {
123 if ((fontParam->size == size) && (strncmp(fontParam->ttfName, ttfName, TTF_NAME_LEN_MAX) == 0)) {
124 break;
125 }
126 }
127 }
128 return id;
129 }
130
GetWidth(uint32_t unicode,uint16_t fontId,uint8_t fontSize)131 int16_t UIFontBitmap::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize)
132 {
133 return GetWidthInFontId(unicode, fontId);
134 }
135
GetBitmap(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)136 uint8_t* UIFontBitmap::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
137 {
138 return SearchInFont(unicode, glyphNode, fontId);
139 }
140
IsEmojiFont(uint16_t fontId)141 bool UIFontBitmap::IsEmojiFont(uint16_t fontId)
142 {
143 return false;
144 }
145
GetFontHeader(FontHeader & fontHeader,uint16_t fontId,uint8_t fontSize)146 int8_t UIFontBitmap::GetFontHeader(FontHeader& fontHeader, uint16_t fontId, uint8_t fontSize)
147 {
148 const FontHeader* header = dynamicFont_.GetFontHeader(fontId);
149 if (header != nullptr) {
150 fontHeader = *header;
151 return RET_VALUE_OK;
152 }
153 return INVALID_RET_VALUE;
154 }
155
156 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
GetMultiGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)157 int8_t UIFontBitmap::GetMultiGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
158 {
159 int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
160 if (ret == RET_VALUE_OK) {
161 return ret;
162 }
163
164 uint16_t* searchLists = nullptr;
165 int8_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
166 int8_t currentIndex = 0;
167 if ((searchLists == nullptr) || (listSize == 0)) {
168 return INVALID_RET_VALUE;
169 }
170 do {
171 ret = GetGlyphNode(unicode, glyphNode, searchLists[currentIndex]);
172 if (ret != INVALID_RET_VALUE) {
173 return ret;
174 }
175 // switch to next search List
176 currentIndex++;
177 } while ((currentIndex < listSize) && (searchLists != nullptr));
178 return INVALID_RET_VALUE;
179 }
180 #endif
181
GetGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)182 int8_t UIFontBitmap::GetGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
183 {
184 const GlyphNode* node = dynamicFont_.GetGlyphNode(unicode, fontId);
185 if (node != nullptr) {
186 glyphNode = *node;
187 return RET_VALUE_OK;
188 }
189 GRAPHIC_LOGE("UIFontBitmap::GetGlyphNode get glyphNode failed");
190 return INVALID_RET_VALUE;
191 }
192
GetGlyphNodeFromFile(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)193 int8_t UIFontBitmap::GetGlyphNodeFromFile(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
194 {
195 const GlyphNode* node = dynamicFont_.GetGlyphNodeFromFiles(unicode, fontId);
196 if (node != nullptr) {
197 glyphNode = *node;
198 return RET_VALUE_OK;
199 }
200 return INVALID_RET_VALUE;
201 }
202
GetFontVersion(FontType type,const char * path,char * version,uint8_t len)203 int8_t UIFontBitmap::GetFontVersion(FontType type, const char* path, char* version, uint8_t len)
204 {
205 if (type != DYNAMIC_FONT) {
206 return INVALID_RET_VALUE;
207 }
208 return dynamicFont_.GetFontVersion(path, version, len);
209 }
210
SetCurrentLangId(uint8_t langId)211 int8_t UIFontBitmap::SetCurrentLangId(uint8_t langId)
212 {
213 GRAPHIC_LOGE("UIFontBitmap::SetCurrentLangId start");
214 UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
215
216 if (fontCacheManager->GlyphsCacheInit() != RET_VALUE_OK) {
217 GRAPHIC_LOGE("UIFontCacheManager::GlyphsCacheInit init failed");
218 return INVALID_RET_VALUE;
219 }
220
221 fontCacheManager->BitmapCacheInit();
222 return RET_VALUE_OK;
223 }
224
GetFontInfo(uint16_t fontId) const225 UITextLanguageFontParam* UIFontBitmap::GetFontInfo(uint16_t fontId) const
226 {
227 return UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
228 }
229
GetDynamicFontBitmap(uint32_t unicode,BufferInfo & bufInfo,uint16_t fontId)230 int8_t UIFontBitmap::GetDynamicFontBitmap(uint32_t unicode, BufferInfo& bufInfo, uint16_t fontId)
231 {
232 return dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
233 }
234
GetCacheBitmap(uint16_t fontId,uint32_t unicode)235 uint8_t* UIFontBitmap::GetCacheBitmap(uint16_t fontId, uint32_t unicode)
236 {
237 TextStyle textStyle = TEXT_STYLE_NORMAL;
238 return UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode, textStyle);
239 }
240
PutCacheSpace(uint8_t * addr)241 void UIFontBitmap::PutCacheSpace(uint8_t* addr)
242 {
243 UIFontCacheManager::GetInstance()->PutSpace(addr);
244 }
245
GetDynamicFontWidth(uint32_t unicode,uint16_t fontId)246 int16_t UIFontBitmap::GetDynamicFontWidth(uint32_t unicode, uint16_t fontId)
247 {
248 return dynamicFont_.GetFontWidth(unicode, fontId);
249 }
250
SearchInFont(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)251 uint8_t* UIFontBitmap::SearchInFont(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
252 {
253 GraphicLockGuard guard(lock_);
254 UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
255 if (fontCacheManager->GetBitmapCache() == nullptr) {
256 return nullptr;
257 }
258 if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
259 GRAPHIC_LOGE("UIFontBitmap::SearchInFont fontId and unicode not match");
260 return nullptr;
261 }
262 int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
263 if (ret != RET_VALUE_OK) {
264 return nullptr;
265 }
266 TextStyle textStyle = TEXT_STYLE_NORMAL;
267 uint8_t* bitmap = fontCacheManager->GetBitmap(fontId, unicode, textStyle);
268 if (bitmap != nullptr) {
269 if (glyphNode.dataFlag == glyphNode.fontId && fontId == glyphNode.fontId) {
270 return bitmap;
271 } else {
272 GRAPHIC_LOGE("DataFlag of bitmap node not equal to fontId.");
273 }
274 }
275 if (glyphNode.kernOff <= glyphNode.dataOff) {
276 return nullptr;
277 }
278 ColorMode mode = UIFont::GetInstance()->GetColorType(fontId);
279 BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(fontId, unicode, mode, glyphNode, false, textStyle);
280 ret = dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
281 if (ret == RET_VALUE_OK) {
282 return reinterpret_cast<uint8_t*>(bufInfo.virAddr);
283 }
284 PutCacheSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
285 return nullptr;
286 }
287
GetWidthInFontId(uint32_t unicode,uint16_t fontId)288 int16_t UIFontBitmap::GetWidthInFontId(uint32_t unicode, uint16_t fontId)
289 {
290 if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
291 GRAPHIC_LOGE("UIFontBitmap::GetWidthInFontId fontId and unicode not match");
292 return INVALID_RET_VALUE;
293 }
294 return GetDynamicFontWidth(unicode, fontId);
295 }
296
SetFontFileOffset(uint32_t offset)297 void UIFontBitmap::SetFontFileOffset(uint32_t offset)
298 {
299 offset_ = offset;
300 }
301
GetOffsetPosY(const char * text,uint16_t lineLength,bool & isEmoijLarge,uint16_t fontId,uint8_t fontSize)302 uint16_t UIFontBitmap::GetOffsetPosY(const char* text,
303 uint16_t lineLength,
304 bool& isEmoijLarge,
305 uint16_t fontId,
306 uint8_t fontSize)
307 {
308 uint32_t i = 0;
309 uint16_t textNum = 0;
310 uint16_t emojiNum = 0;
311
312 uint16_t loopNum = 0;
313 GlyphNode glyphNode;
314 GlyphNode emoijMaxNode = {};
315 uint8_t maxFontSie = fontSize;
316 while (i < lineLength) {
317 uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
318 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
319 uint8_t ret = GetMultiGlyphNode(unicode, glyphNode, fontId);
320 #else
321 uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
322 #endif
323 if (ret == RET_VALUE_OK) {
324 uint8_t weight = GetFontWeight(glyphNode.fontId);
325 if (weight >= 16) { // 16: bit rgb565 rgba8888
326 emoijMaxNode = glyphNode.rows > emoijMaxNode.rows ? glyphNode : emoijMaxNode;
327 emojiNum++;
328 } else {
329 textNum++;
330 }
331 loopNum++;
332 }
333 }
334 // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
335 // The number of words is the same as the number of cycles, which means that this line is all words
336 if ((emojiNum == loopNum) || (textNum == loopNum)) {
337 isEmoijLarge = true;
338 return 0;
339 }
340 isEmoijLarge = emoijMaxNode.rows > maxFontSie;
341 uint16_t offset = 0;
342 if (isEmoijLarge) {
343 // If the emoji is higher than the text
344 if (emoijMaxNode.top >= maxFontSie) {
345 offset = emoijMaxNode.top - maxFontSie;
346 }
347 } else {
348 // If text are higher than emoji
349 if (maxFontSie >= emoijMaxNode.rows) {
350 // should top - ros.
351 offset = maxFontSie - emoijMaxNode.rows;
352 }
353 }
354 return offset;
355 }
356
GetLineMaxHeight(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t & letterIndex,SpannableString * spannableString)357 uint16_t UIFontBitmap::GetLineMaxHeight(const char* text,
358 uint16_t lineLength,
359 uint16_t fontId,
360 uint8_t fontSize,
361 uint16_t& letterIndex,
362 SpannableString* spannableString)
363 {
364 uint16_t maxHeight = GetHeight(fontId, fontSize);
365 if (spannableString == nullptr) {
366 return maxHeight;
367 }
368
369 uint32_t i = 0;
370 while (i < lineLength) {
371 TypedText::GetUTF8Next(text, i, i);
372 if (spannableString != nullptr && spannableString->GetSpannable(letterIndex)) {
373 int16_t spannableHeight = 0;
374 spannableString->GetFontHeight(letterIndex, spannableHeight, fontId, fontSize);
375 uint16_t tempHeight = static_cast<uint16_t>(spannableHeight);
376 maxHeight = tempHeight > maxHeight ? tempHeight : maxHeight;
377 }
378 letterIndex++;
379 if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
380 break;
381 }
382 }
383
384 return maxHeight;
385 }
386
SetPsramMemory(uintptr_t psramAddr,uint32_t psramLen)387 void UIFontBitmap::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
388 {
389 BaseFont::SetPsramMemory(psramAddr, psramLen);
390 FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
391 }
392 } // namespace OHOS
393