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
GetShapingFontId(char * text,uint8_t & ttfId,uint32_t & script,uint16_t fontId,uint8_t size) const57 uint16_t UIFontBitmap::GetShapingFontId(char* text, uint8_t& ttfId, uint32_t& script,
58 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 if (ttfName == nullptr) {
116 return UIFontBuilder::GetInstance()->GetBitmapFontIdMax();
117 }
118 uint16_t id;
119 for (id = 0; id < UIFontBuilder::GetInstance()->GetBitmapFontIdMax(); ++id) {
120 UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(id);
121 if (fontParam != nullptr) {
122 if ((fontParam->size == size) && (strncmp(fontParam->ttfName, ttfName, TTF_NAME_LEN_MAX) == 0)) {
123 break;
124 }
125 }
126 }
127 return id;
128 }
129
GetWidth(uint32_t unicode,uint16_t fontId,uint8_t fontSize)130 int16_t UIFontBitmap::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize)
131 {
132 return GetWidthInFontId(unicode, fontId);
133 }
134
GetBitmap(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)135 uint8_t* UIFontBitmap::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
136 {
137 return SearchInFont(unicode, glyphNode, fontId);
138 }
139
IsEmojiFont(uint16_t fontId)140 bool UIFontBitmap::IsEmojiFont(uint16_t fontId)
141 {
142 return false;
143 }
144
GetFontHeader(FontHeader & fontHeader,uint16_t fontId,uint8_t fontSize)145 int8_t UIFontBitmap::GetFontHeader(FontHeader& fontHeader, uint16_t fontId, uint8_t fontSize)
146 {
147 const FontHeader* header = dynamicFont_.GetFontHeader(fontId);
148 if (header != nullptr) {
149 fontHeader = *header;
150 return RET_VALUE_OK;
151 }
152 return INVALID_RET_VALUE;
153 }
154
155 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
GetMultiGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)156 int8_t UIFontBitmap::GetMultiGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
157 {
158 int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
159 if (ret == RET_VALUE_OK) {
160 return ret;
161 }
162
163 uint16_t* searchLists = nullptr;
164 int8_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
165 int8_t currentIndex = 0;
166 if ((searchLists == nullptr) || (listSize == 0)) {
167 return INVALID_RET_VALUE;
168 }
169 do {
170 ret = GetGlyphNode(unicode, glyphNode, searchLists[currentIndex]);
171 if (ret != INVALID_RET_VALUE) {
172 return ret;
173 }
174 // switch to next search List
175 currentIndex++;
176 } while ((currentIndex < listSize) && (searchLists != nullptr));
177 return INVALID_RET_VALUE;
178 }
179 #endif
180
GetGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)181 int8_t UIFontBitmap::GetGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
182 {
183 const GlyphNode* node = dynamicFont_.GetGlyphNode(unicode, fontId);
184 if (node != nullptr) {
185 glyphNode = *node;
186 return RET_VALUE_OK;
187 }
188 GRAPHIC_LOGE("UIFontBitmap::GetGlyphNode get glyphNode failed");
189 return INVALID_RET_VALUE;
190 }
191
GetGlyphNodeFromFile(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)192 int8_t UIFontBitmap::GetGlyphNodeFromFile(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
193 {
194 const GlyphNode* node = dynamicFont_.GetGlyphNodeFromFiles(unicode, fontId);
195 if (node != nullptr) {
196 glyphNode = *node;
197 return RET_VALUE_OK;
198 }
199 return INVALID_RET_VALUE;
200 }
201
GetFontVersion(FontType type,const char * path,char * version,uint8_t len)202 int8_t UIFontBitmap::GetFontVersion(FontType type, const char* path, char* version, uint8_t len)
203 {
204 if (type != DYNAMIC_FONT) {
205 return INVALID_RET_VALUE;
206 }
207 return dynamicFont_.GetFontVersion(path, version, len);
208 }
209
SetCurrentLangId(uint8_t langId)210 int8_t UIFontBitmap::SetCurrentLangId(uint8_t langId)
211 {
212 UIFontCacheManager::GetInstance()->BitmapCacheInit();
213 return RET_VALUE_OK;
214 }
215
GetFontInfo(uint16_t fontId) const216 UITextLanguageFontParam* UIFontBitmap::GetFontInfo(uint16_t fontId) const
217 {
218 return UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
219 }
220
GetDynamicFontBitmap(uint32_t unicode,BufferInfo & bufInfo,uint16_t fontId)221 int8_t UIFontBitmap::GetDynamicFontBitmap(uint32_t unicode, BufferInfo& bufInfo, uint16_t fontId)
222 {
223 return dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
224 }
225
GetCacheBitmap(uint16_t fontId,uint32_t unicode)226 uint8_t* UIFontBitmap::GetCacheBitmap(uint16_t fontId, uint32_t unicode)
227 {
228 return UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode);
229 }
230
PutCacheSpace(uint8_t * addr)231 void UIFontBitmap::PutCacheSpace(uint8_t* addr)
232 {
233 UIFontCacheManager::GetInstance()->PutSpace(addr);
234 }
235
GetDynamicFontWidth(uint32_t unicode,uint16_t fontId)236 int16_t UIFontBitmap::GetDynamicFontWidth(uint32_t unicode, uint16_t fontId)
237 {
238 return dynamicFont_.GetFontWidth(unicode, fontId);
239 }
240
SearchInFont(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)241 uint8_t* UIFontBitmap::SearchInFont(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
242 {
243 GraphicLockGuard guard(lock_);
244 if (UIFontCacheManager::GetInstance()->GetBitmapCache() == nullptr) {
245 return nullptr;
246 }
247 if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
248 GRAPHIC_LOGE("UIFontBitmap::SearchInFont fontId and unicode not match");
249 return nullptr;
250 }
251 int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
252 if (ret != RET_VALUE_OK) {
253 return nullptr;
254 }
255 uint8_t* bitmap = UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode);
256 if (bitmap != nullptr) {
257 if (glyphNode.dataFlag == glyphNode.fontId && fontId == glyphNode.fontId) {
258 return bitmap;
259 } else {
260 GRAPHIC_LOGE("DataFlag of bitmap node not equal to fontId.");
261 }
262 }
263 if (glyphNode.kernOff <= glyphNode.dataOff) {
264 return nullptr;
265 }
266 ColorMode mode = UIFont::GetInstance()->GetColorType(fontId);
267 BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(fontId, unicode, mode, glyphNode, false);
268 ret = dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
269 if (ret == RET_VALUE_OK) {
270 return reinterpret_cast<uint8_t*>(bufInfo.virAddr);
271 }
272 PutCacheSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
273 return nullptr;
274 }
275
GetWidthInFontId(uint32_t unicode,uint16_t fontId)276 int16_t UIFontBitmap::GetWidthInFontId(uint32_t unicode, uint16_t fontId)
277 {
278 if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
279 GRAPHIC_LOGE("UIFontBitmap::GetWidthInFontId fontId and unicode not match");
280 return INVALID_RET_VALUE;
281 }
282 return GetDynamicFontWidth(unicode, fontId);
283 }
284
SetFontFileOffset(uint32_t offset)285 void UIFontBitmap::SetFontFileOffset(uint32_t offset)
286 {
287 offset_ = offset;
288 }
289
GetOffsetPosY(const char * text,uint16_t lineLength,bool & isEmoijLarge,uint16_t fontId,uint8_t fontSize)290 uint16_t UIFontBitmap::GetOffsetPosY(const char* text,
291 uint16_t lineLength,
292 bool& isEmoijLarge,
293 uint16_t fontId,
294 uint8_t fontSize)
295 {
296 uint32_t i = 0;
297 uint16_t textNum = 0;
298 uint16_t emojiNum = 0;
299
300 uint16_t loopNum = 0;
301 GlyphNode glyphNode;
302 GlyphNode emoijMaxNode = {};
303 uint8_t maxFontSie = fontSize;
304 while (i < lineLength) {
305 uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
306 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
307 uint8_t ret = GetMultiGlyphNode(unicode, glyphNode, fontId);
308 #else
309 uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
310 #endif
311 if (ret == RET_VALUE_OK) {
312 uint8_t weight = GetFontWeight(glyphNode.fontId);
313 if (weight >= 16) { // 16: bit rgb565 rgba8888
314 emoijMaxNode = glyphNode.rows > emoijMaxNode.rows ? glyphNode : emoijMaxNode;
315 emojiNum++;
316 } else {
317 textNum++;
318 }
319 loopNum++;
320 }
321 }
322 // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
323 // The number of words is the same as the number of cycles, which means that this line is all words
324 if ((emojiNum == loopNum) || (textNum == loopNum)) {
325 isEmoijLarge = true;
326 return 0;
327 }
328 isEmoijLarge = emoijMaxNode.rows > maxFontSie;
329 uint16_t offset = 0;
330 if (isEmoijLarge) {
331 // If the emoji is higher than the text
332 if (emoijMaxNode.top >= maxFontSie) {
333 offset = emoijMaxNode.top - maxFontSie;
334 }
335 } else {
336 // If text are higher than emoji
337 if (maxFontSie >= emoijMaxNode.rows) {
338 // should top - ros.
339 offset = maxFontSie - emoijMaxNode.rows;
340 }
341 }
342 return offset;
343 }
344
GetLineMaxHeight(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t & letterIndex,SizeSpan * sizeSpans)345 uint16_t UIFontBitmap::GetLineMaxHeight(const char* text,
346 uint16_t lineLength,
347 uint16_t fontId,
348 uint8_t fontSize,
349 uint16_t& letterIndex,
350 SizeSpan* sizeSpans)
351 {
352 uint16_t maxHeight = GetHeight(fontId, fontSize);
353 if (sizeSpans == nullptr) {
354 return maxHeight;
355 }
356
357 uint32_t i = 0;
358 while (i < lineLength) {
359 TypedText::GetUTF8Next(text, i, i);
360 if (sizeSpans != nullptr && sizeSpans[letterIndex].isSizeSpan) {
361 uint16_t spannableHeight = 0;
362 if (sizeSpans[letterIndex].height == 0) {
363 spannableHeight = GetHeight(sizeSpans[letterIndex].fontId, sizeSpans[letterIndex].size);
364 sizeSpans[letterIndex].height = spannableHeight;
365 } else {
366 spannableHeight = sizeSpans[letterIndex].height;
367 }
368 maxHeight = spannableHeight > maxHeight ? spannableHeight : maxHeight;
369 }
370
371 letterIndex++;
372 if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
373 break;
374 }
375 }
376
377 return maxHeight;
378 }
379
SetPsramMemory(uintptr_t psramAddr,uint32_t psramLen)380 void UIFontBitmap::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
381 {
382 BaseFont::SetPsramMemory(psramAddr, psramLen);
383 FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
384 }
385 } // namespace OHOS
386