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 UIFontCacheManager::GetInstance()->BitmapCacheInit();
214 return RET_VALUE_OK;
215 }
216
GetFontInfo(uint16_t fontId) const217 UITextLanguageFontParam* UIFontBitmap::GetFontInfo(uint16_t fontId) const
218 {
219 return UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
220 }
221
GetDynamicFontBitmap(uint32_t unicode,BufferInfo & bufInfo,uint16_t fontId)222 int8_t UIFontBitmap::GetDynamicFontBitmap(uint32_t unicode, BufferInfo& bufInfo, uint16_t fontId)
223 {
224 return dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
225 }
226
GetCacheBitmap(uint16_t fontId,uint32_t unicode)227 uint8_t* UIFontBitmap::GetCacheBitmap(uint16_t fontId, uint32_t unicode)
228 {
229 return UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode);
230 }
231
PutCacheSpace(uint8_t * addr)232 void UIFontBitmap::PutCacheSpace(uint8_t* addr)
233 {
234 UIFontCacheManager::GetInstance()->PutSpace(addr);
235 }
236
GetDynamicFontWidth(uint32_t unicode,uint16_t fontId)237 int16_t UIFontBitmap::GetDynamicFontWidth(uint32_t unicode, uint16_t fontId)
238 {
239 return dynamicFont_.GetFontWidth(unicode, fontId);
240 }
241
SearchInFont(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)242 uint8_t* UIFontBitmap::SearchInFont(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
243 {
244 GraphicLockGuard guard(lock_);
245 UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
246 if (fontCacheManager->GetBitmapCache() == nullptr) {
247 return nullptr;
248 }
249 if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
250 GRAPHIC_LOGE("UIFontBitmap::SearchInFont fontId and unicode not match");
251 return nullptr;
252 }
253 int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
254 if (ret != RET_VALUE_OK) {
255 return nullptr;
256 }
257 uint8_t* bitmap = fontCacheManager->GetBitmap(fontId, unicode);
258 if (bitmap != nullptr) {
259 if (glyphNode.dataFlag == glyphNode.fontId && fontId == glyphNode.fontId) {
260 return bitmap;
261 } else {
262 GRAPHIC_LOGE("DataFlag of bitmap node not equal to fontId.");
263 }
264 }
265 if (glyphNode.kernOff <= glyphNode.dataOff) {
266 return nullptr;
267 }
268 ColorMode mode = UIFont::GetInstance()->GetColorType(fontId);
269 BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(fontId, unicode, mode, glyphNode, false);
270 ret = dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
271 if (ret == RET_VALUE_OK) {
272 return reinterpret_cast<uint8_t*>(bufInfo.virAddr);
273 }
274 PutCacheSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
275 return nullptr;
276 }
277
GetWidthInFontId(uint32_t unicode,uint16_t fontId)278 int16_t UIFontBitmap::GetWidthInFontId(uint32_t unicode, uint16_t fontId)
279 {
280 if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
281 GRAPHIC_LOGE("UIFontBitmap::GetWidthInFontId fontId and unicode not match");
282 return INVALID_RET_VALUE;
283 }
284 return GetDynamicFontWidth(unicode, fontId);
285 }
286
SetFontFileOffset(uint32_t offset)287 void UIFontBitmap::SetFontFileOffset(uint32_t offset)
288 {
289 offset_ = offset;
290 }
291
GetOffsetPosY(const char * text,uint16_t lineLength,bool & isEmoijLarge,uint16_t fontId,uint8_t fontSize)292 uint16_t UIFontBitmap::GetOffsetPosY(const char* text,
293 uint16_t lineLength,
294 bool& isEmoijLarge,
295 uint16_t fontId,
296 uint8_t fontSize)
297 {
298 uint32_t i = 0;
299 uint16_t textNum = 0;
300 uint16_t emojiNum = 0;
301
302 uint16_t loopNum = 0;
303 GlyphNode glyphNode;
304 GlyphNode emoijMaxNode = {};
305 uint8_t maxFontSie = fontSize;
306 while (i < lineLength) {
307 uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
308 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
309 uint8_t ret = GetMultiGlyphNode(unicode, glyphNode, fontId);
310 #else
311 uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
312 #endif
313 if (ret == RET_VALUE_OK) {
314 uint8_t weight = GetFontWeight(glyphNode.fontId);
315 if (weight >= 16) { // 16: bit rgb565 rgba8888
316 emoijMaxNode = glyphNode.rows > emoijMaxNode.rows ? glyphNode : emoijMaxNode;
317 emojiNum++;
318 } else {
319 textNum++;
320 }
321 loopNum++;
322 }
323 }
324 // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
325 // The number of words is the same as the number of cycles, which means that this line is all words
326 if ((emojiNum == loopNum) || (textNum == loopNum)) {
327 isEmoijLarge = true;
328 return 0;
329 }
330 isEmoijLarge = emoijMaxNode.rows > maxFontSie;
331 uint16_t offset = 0;
332 if (isEmoijLarge) {
333 // If the emoji is higher than the text
334 if (emoijMaxNode.top >= maxFontSie) {
335 offset = emoijMaxNode.top - maxFontSie;
336 }
337 } else {
338 // If text are higher than emoji
339 if (maxFontSie >= emoijMaxNode.rows) {
340 // should top - ros.
341 offset = maxFontSie - emoijMaxNode.rows;
342 }
343 }
344 return offset;
345 }
346
GetLineMaxHeight(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t & letterIndex,SizeSpan * sizeSpans)347 uint16_t UIFontBitmap::GetLineMaxHeight(const char* text,
348 uint16_t lineLength,
349 uint16_t fontId,
350 uint8_t fontSize,
351 uint16_t& letterIndex,
352 SizeSpan* sizeSpans)
353 {
354 uint16_t maxHeight = GetHeight(fontId, fontSize);
355 if (sizeSpans == nullptr) {
356 return maxHeight;
357 }
358
359 uint32_t i = 0;
360 while (i < lineLength) {
361 TypedText::GetUTF8Next(text, i, i);
362 if (sizeSpans != nullptr && sizeSpans[letterIndex].isSizeSpan) {
363 uint16_t spannableHeight = 0;
364 if (sizeSpans[letterIndex].height == 0) {
365 spannableHeight = GetHeight(sizeSpans[letterIndex].fontId, sizeSpans[letterIndex].size);
366 sizeSpans[letterIndex].height = spannableHeight;
367 } else {
368 spannableHeight = sizeSpans[letterIndex].height;
369 }
370 maxHeight = spannableHeight > maxHeight ? spannableHeight : maxHeight;
371 }
372
373 letterIndex++;
374 if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
375 break;
376 }
377 }
378
379 return maxHeight;
380 }
381
SetPsramMemory(uintptr_t psramAddr,uint32_t psramLen)382 void UIFontBitmap::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
383 {
384 BaseFont::SetPsramMemory(psramAddr, psramLen);
385 FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
386 }
387 } // namespace OHOS
388