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_vector.h"
17
18 #include <freetype/ftbitmap.h>
19 #include <freetype/ftoutln.h>
20 #include <freetype/internal/ftobjs.h>
21 #include <freetype/internal/ftstream.h>
22 #include <freetype/tttags.h>
23
24 #include "common/typed_text.h"
25 #include "draw/draw_utils.h"
26 #include "font/font_ram_allocator.h"
27 #include "gfx_utils/file.h"
28 #include "gfx_utils/graphic_log.h"
29 #include "graphic_config.h"
30 #include "securec.h"
31 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
32 #include "font/ui_multi_font_manager.h"
33 #endif
34 #if defined(ENABLE_SHAPING) && ENABLE_SHAPING
35 #include "font/ui_text_shaping.h"
36 #endif
37 #include "font/ui_font_cache_manager.h"
38
39 namespace OHOS {
UIFontVector()40 UIFontVector::UIFontVector()
41 {
42 #ifdef _WIN32
43 ttfDir_ = _pgmptr;
44 size_t len = ttfDir_.size();
45 size_t pos = ttfDir_.find_last_of('\\');
46 if (pos != std::string::npos) {
47 ttfDir_.replace((pos + 1), (len - pos), VECTOR_FONT_DIR);
48 }
49 #else
50 ttfDir_ = VECTOR_FONT_DIR;
51 #endif // _WIN32
52 ftLibrary_ = nullptr;
53 freeTypeInited_ = ((FT_Init_FreeType(&ftLibrary_) == 0) ? true : false);
54 }
55
~UIFontVector()56 UIFontVector::~UIFontVector()
57 {
58 if (freeTypeInited_) {
59 FT_Done_FreeType(ftLibrary_);
60 freeTypeInited_ = false;
61 UnregisterFontInfo(DEFAULT_VECTOR_FONT_FILENAME);
62 }
63 }
64
IsColorEmojiFont(FT_Face & face)65 bool UIFontVector::IsColorEmojiFont(FT_Face& face)
66 {
67 static const uint32_t tag = FT_MAKE_TAG('C', 'B', 'D', 'T');
68 FT_ULong length = 0;
69 FT_Load_Sfnt_Table(face, tag, 0, nullptr, &length);
70 if (length) {
71 return true;
72 }
73 return false;
74 }
75
SetupColorFont(FT_Face face,uint8_t fontSize)76 int8_t SetupColorFont(FT_Face face, uint8_t fontSize)
77 {
78 if (face->num_fixed_sizes == 0) {
79 return INVALID_RET_VALUE;
80 }
81 FT_Int bestMatch = 0;
82 int32_t diff = MATH_ABS(fontSize - face->available_sizes[0].width);
83 for (int32_t i = 1; i < face->num_fixed_sizes; ++i) {
84 int32_t ndiff = MATH_ABS(fontSize - face->available_sizes[i].width);
85 if (ndiff < diff) {
86 bestMatch = i;
87 diff = ndiff;
88 }
89 }
90 return FT_Select_Size(face, bestMatch); // FT_Match_Size
91 }
92
RegisterFontInfo(const char * ttfName,uint8_t shaping)93 uint8_t UIFontVector::RegisterFontInfo(const char* ttfName, uint8_t shaping)
94 {
95 if ((ttfName == nullptr) || !freeTypeInited_) {
96 return FONT_INVALID_TTF_ID;
97 }
98
99 int32_t j = 0;
100 while (j < FONT_ID_MAX) {
101 if ((fontInfo_[j].ttfName != nullptr) && !strncmp(fontInfo_[j].ttfName, ttfName, TTF_NAME_LEN_MAX)) {
102 return j;
103 } else if (fontInfo_[j].ttfName == nullptr) {
104 std::string ttfPath = ttfDir_;
105 ttfPath.append(ttfName);
106 int32_t error = FT_New_Face(ftLibrary_, ttfPath.c_str(), 0, &ftFaces_[j]);
107 if (error != 0) {
108 return FONT_INVALID_TTF_ID;
109 }
110 fontInfo_[j].ttfName = ttfName;
111 fontInfo_[j].shaping = shaping;
112 fontInfo_[j].ttfId = j;
113 fontInfo_[j].ttcIndex = FONT_TTC_MAX;
114 currentFontInfoNum_ = j + 1;
115 if (IsColorEmojiFont(ftFaces_[j])) {
116 fontInfo_[j].fontWeight = BPP_BIT_32;
117 } else {
118 fontInfo_[j].fontWeight = BPP_BIT_8;
119 }
120 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
121 UIMultiFontManager::GetInstance()->UpdateScript(fontInfo_[j]);
122 #endif
123 return j;
124 }
125 j++;
126 }
127 return FONT_INVALID_TTF_ID;
128 }
129
RegisterFontInfo(const UITextLanguageFontParam * fontsTable,uint8_t num)130 uint8_t UIFontVector::RegisterFontInfo(const UITextLanguageFontParam* fontsTable, uint8_t num)
131 {
132 if (fontsTable == nullptr) {
133 return FONT_INVALID_TTF_ID;
134 }
135 uint8_t count = 0;
136 for (uint8_t i = 0; i < num; i++) {
137 uint8_t result = RegisterFontInfo(fontsTable[i].ttfName, fontsTable[i].shaping);
138 if (result == FONT_INVALID_TTF_ID) {
139 continue;
140 }
141 count++;
142 }
143 return count;
144 }
145
146 // Note: when use ttc font file, freetype should export FT_Stream_New/FT_Stream_Free function
RegisterTtcFontInfo(const char * ttcName,const TtfInfo * ttfInfo,uint8_t count)147 uint8_t UIFontVector::RegisterTtcFontInfo(const char* ttcName, const TtfInfo* ttfInfo, uint8_t count)
148 {
149 if ((ttcName == nullptr) || !freeTypeInited_) {
150 return FONT_INVALID_TTF_ID;
151 }
152
153 int32_t i = 0;
154 int32_t error = 0;
155 int32_t ttfIdx = 0;
156 while (i < FONT_TTC_MAX) {
157 if ((ttcInfos_[i].ttcName != nullptr) && !strncmp(ttcInfos_[i].ttcName, ttcName, TTF_NAME_LEN_MAX)) {
158 return i;
159 } else if (ttcInfos_[i].ttcName == nullptr) {
160 std::string ttcPath = ttfDir_;
161 ttcPath.append(ttcName);
162 FT_Open_Args args = {FT_OPEN_PATHNAME, nullptr, 0, const_cast<char*>(ttcPath.c_str()),
163 nullptr, nullptr, 0, nullptr};
164 error = FT_Stream_New(ftLibrary_, &args, &ttcInfos_[i].stream);
165 if (error != 0) {
166 return FONT_INVALID_TTF_ID;
167 }
168 ttcInfos_[i].ttcName = ttcName;
169 args = {FT_OPEN_STREAM, nullptr, 0, nullptr, ttcInfos_[i].stream, nullptr, 0, nullptr};
170 for (uint8_t j = 0; j < count; j++) {
171 while ((ttfIdx < FONT_ID_MAX) && fontInfo_[ttfIdx].ttfName != nullptr) {
172 ttfIdx++;
173 }
174
175 if (ttfIdx >= FONT_ID_MAX) {
176 return FONT_INVALID_TTF_ID;
177 }
178 error = FT_Open_Face(ftLibrary_, &args, j, &ftFaces_[ttfIdx]);
179 if (error != 0) {
180 continue;
181 }
182 fontInfo_[ttfIdx].ttfName = ttfInfo[j].ttfName;
183 fontInfo_[ttfIdx].shaping = ttfInfo[j].shaping;
184 fontInfo_[ttfIdx].ttfId = ttfIdx;
185 fontInfo_[ttfIdx].ttfIndex = j;
186 fontInfo_[ttfIdx].ttcIndex = i;
187 if (IsColorEmojiFont(ftFaces_[ttfIdx])) {
188 fontInfo_[ttfIdx].fontWeight = BPP_BIT_32;
189 } else {
190 fontInfo_[ttfIdx].fontWeight = BPP_BIT_8;
191 }
192 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
193 UIMultiFontManager::GetInstance()->UpdateScript(fontInfo_[ttfIdx]);
194 #endif
195 }
196 return i;
197 }
198 i++;
199 }
200 return FONT_INVALID_TTF_ID;
201 }
202
UnregisterTtcFontInfo(const char * ttcName,const TtfInfo * ttfInfo,uint8_t count)203 uint8_t UIFontVector::UnregisterTtcFontInfo(const char* ttcName, const TtfInfo* ttfInfo, uint8_t count)
204 {
205 if (ttcName == nullptr || ttfInfo == nullptr) {
206 return FONT_INVALID_TTF_ID;
207 }
208
209 uint8_t i = 0;
210 while (i < FONT_TTC_MAX) {
211 if ((ttcInfos_[i].ttcName != nullptr) && !strncmp(ttcInfos_[i].ttcName, ttcName, TTF_NAME_LEN_MAX)) {
212 for (uint8_t j = 0; j < count; j++) {
213 UnregisterFontInfo(ttfInfo[j].ttfName);
214 }
215 FT_Stream_Free(ttcInfos_[i].stream, 1);
216 ttcInfos_[i].ttcName = nullptr;
217 ttcInfos_[i].stream = nullptr;
218 return i;
219 }
220 i++;
221 }
222 return FONT_INVALID_TTF_ID;
223 }
224
UnregisterFontInfo(const UITextLanguageFontParam * fontsTable,uint8_t num)225 uint8_t UIFontVector::UnregisterFontInfo(const UITextLanguageFontParam* fontsTable, uint8_t num)
226 {
227 if (fontsTable == nullptr) {
228 return 0;
229 }
230 uint8_t count = 0;
231 for (uint8_t i = 0; i < num; i++) {
232 uint8_t result = UnregisterFontInfo(fontsTable[i].ttfName);
233 if (result == FONT_INVALID_TTF_ID) {
234 return FONT_INVALID_TTF_ID;
235 }
236 count++;
237 }
238 return count;
239 }
UnregisterFontInfo(const char * ttfName)240 uint8_t UIFontVector::UnregisterFontInfo(const char* ttfName)
241 {
242 if (ttfName != nullptr) {
243 int32_t i = 0;
244 while (i < FONT_ID_MAX) {
245 if ((fontInfo_[i].ttfName != nullptr) && !strncmp(fontInfo_[i].ttfName, ttfName, TTF_NAME_LEN_MAX)) {
246 fontInfo_[i].ttfName = nullptr;
247 FT_Done_Face(ftFaces_[i]);
248 ftFaces_[i] = nullptr;
249 fontSize_[i] = 0;
250 return static_cast<uint8_t>(i);
251 }
252 i++;
253 }
254 }
255 return FONT_INVALID_TTF_ID;
256 }
257
GetFontInfo(uint16_t fontId) const258 const UITextLanguageFontParam* UIFontVector::GetFontInfo(uint16_t fontId) const
259 {
260 if (fontId < FONT_ID_MAX) {
261 return static_cast<const UITextLanguageFontParam*>(&fontInfo_[fontId]);
262 }
263 return nullptr;
264 }
265
OpenVectorFont(uint8_t ttfId)266 int32_t UIFontVector::OpenVectorFont(uint8_t ttfId)
267 {
268 int32_t i = 0;
269 int32_t fp = 0;
270 while (i < FONT_ID_MAX) {
271 if (fontInfo_[i].ttfName == nullptr) {
272 i++;
273 continue;
274 }
275 if (fontInfo_[i].ttfId == ttfId) {
276 std::string ttfPath = ttfDir_;
277 ttfPath.append(fontInfo_[i].ttfName);
278 #ifdef _WIN32
279 fp = open(ttfPath.c_str(), O_RDONLY | O_BINARY);
280 #else
281 fp = open(ttfPath.c_str(), O_RDONLY);
282 #endif
283 return fp;
284 }
285 i++;
286 }
287 return -1;
288 }
GetTtfInfo(uint8_t ttfId,uint8_t * ttfBuffer,uint32_t ttfBufferSize,TtfHeader & ttfHeader)289 bool UIFontVector::GetTtfInfo(uint8_t ttfId, uint8_t* ttfBuffer, uint32_t ttfBufferSize, TtfHeader& ttfHeader)
290 {
291 if ((ttfBuffer == nullptr) || (ttfBufferSize == 0)) {
292 return false;
293 }
294 for (int16_t i = 0; i < FONT_ID_MAX; i++) {
295 if (fontInfo_[i].ttfName == nullptr) {
296 continue;
297 }
298 if (fontInfo_[i].ttfId == ttfId) {
299 if (fontInfo_[i].ttcIndex != FONT_TTC_MAX) {
300 return GetTtfInfoFromTtc(ttfBuffer, ttfBufferSize, ttfHeader, fontInfo_[i]);
301 } else {
302 return GetTtfInfoFromTtf(ttfBuffer, ttfBufferSize, ttfHeader, fontInfo_[i]);
303 }
304 }
305 }
306 return false;
307 }
308
GetTtfInfoFromTtf(uint8_t * ttfBuffer,uint32_t ttfBufferSize,TtfHeader & ttfHeader,UITextLanguageFontParam fontInfo)309 bool UIFontVector::GetTtfInfoFromTtf(uint8_t* ttfBuffer,
310 uint32_t ttfBufferSize,
311 TtfHeader& ttfHeader,
312 UITextLanguageFontParam fontInfo)
313 {
314 if ((ttfBuffer == nullptr) || (ttfBufferSize == 0)) {
315 return false;
316 }
317 std::string ttfPath = ttfDir_;
318 ttfPath.append(fontInfo.ttfName);
319 int32_t fpTtf = 0;
320 #ifdef _WIN32
321 fpTtf = open(ttfPath.c_str(), O_RDONLY | O_BINARY);
322 #else
323 fpTtf = open(ttfPath.c_str(), O_RDONLY);
324 #endif
325 if (fpTtf < 0) {
326 return false;
327 }
328 int32_t headerLength = lseek(fpTtf, 0, SEEK_END);
329 if (headerLength < 0) {
330 return false;
331 }
332 ttfHeader.len = static_cast<uint32_t>(headerLength);
333 if (ttfHeader.len > ttfBufferSize) {
334 close(fpTtf);
335 return false;
336 }
337 int32_t ret = lseek(fpTtf, 0, SEEK_SET);
338 if (ret != 0) {
339 close(fpTtf);
340 return false;
341 }
342 ret = read(fpTtf, reinterpret_cast<void*>(ttfBuffer), ttfHeader.len);
343 if (ret != headerLength) {
344 close(fpTtf);
345 return false;
346 }
347 close(fpTtf);
348 return true;
349 }
350
351 struct TtcHeader {
352 uint32_t ttcTag;
353 uint16_t major;
354 uint16_t minor;
355 int32_t numFonts;
356 };
GetTtfInfoFromTtc(uint8_t * ttfBuffer,uint32_t ttfBufferSize,TtfHeader & ttfHeader,UITextLanguageFontParam fontInfo)357 bool UIFontVector::GetTtfInfoFromTtc(uint8_t* ttfBuffer,
358 uint32_t ttfBufferSize,
359 TtfHeader& ttfHeader,
360 UITextLanguageFontParam fontInfo)
361 {
362 if ((ttfBuffer == nullptr) || (ttfBufferSize == 0) || (fontInfo.ttcIndex >= FONT_TTC_MAX)) {
363 return false;
364 }
365 FT_Stream stream = ttcInfos_[fontInfo.ttcIndex].stream;
366 if (stream == nullptr) {
367 return false;
368 }
369
370 FT_Error error = FT_Err_Ok;
371 if (FT_STREAM_SEEK(0)) {
372 return false;
373 }
374
375 // read ttc header
376 TtcHeader header = {};
377 static const FT_Frame_Field ttcHeaderFields[] = {
378 #undef FT_STRUCTURE
379 #define FT_STRUCTURE TtcHeader
380 FT_FRAME_START(12), // 12: see ttc header
381 FT_FRAME_ULONG(ttcTag), FT_FRAME_LONG(numFonts), FT_FRAME_END};
382 if (FT_STREAM_READ_FIELDS(ttcHeaderFields, &header)) {
383 return false;
384 }
385
386 // check if ttc file
387 if (header.ttcTag != TTAG_ttcf) { // 'ttcf' - TTC file
388 return false;
389 }
390
391 uint8_t ttfIndex = fontInfo.ttfIndex;
392 if (ttfIndex >= header.numFonts) {
393 // invalid index
394 return false;
395 }
396
397 // change position to the ttf offset
398 if (FT_STREAM_SKIP(4 * ttfIndex)) { // 4: table dictionary offset length
399 return false;
400 }
401
402 // get the ttf length
403 uint32_t ttfOffset;
404 if (FT_READ_ULONG(ttfOffset)) {
405 return false;
406 }
407 uint32_t ttfLength = 0;
408 FT_ULong ttcLength = stream->size;
409 if (ttcLength < ttfOffset) {
410 return false;
411 }
412 if (ttfIndex + 1 == header.numFonts) {
413 ttfLength = ttcLength - ttfOffset;
414 } else {
415 uint32_t nextTtfOffset;
416 if (FT_READ_ULONG(nextTtfOffset)) {
417 return false;
418 }
419 ttfLength = nextTtfOffset - ttfOffset;
420 }
421 if (ttfLength > ttfBufferSize) {
422 return false;
423 }
424 if (FT_STREAM_SEEK(ttfOffset) || FT_STREAM_READ(ttfBuffer, ttfLength)) {
425 return false;
426 }
427 ttfHeader.len = ttfLength;
428
429 // read number of tables
430 uint16_t numTables;
431 if (FT_STREAM_SEEK(ttfOffset + 4) || FT_READ_USHORT(numTables)) { // 4: sfntVersion length
432 return false;
433 }
434
435 // change the offset of the ttf tableRecord compare with ttfOffset from ttc header
436 uint32_t* p = reinterpret_cast<uint32_t*>(ttfBuffer + 20); // 20: 12(TableDirectory) + 8(tableTag and checksum)
437 for (uint16_t i = 0; i < numTables; i++) {
438 p[0] = FT_PEEK_ULONG(p) - ttfOffset;
439 p[0] = FT_PEEK_ULONG(p);
440 p += 4; // 4: Table Record size
441 }
442 return true;
443 }
IsVectorFont() const444 bool UIFontVector::IsVectorFont() const
445 {
446 return true;
447 }
448
GetFontWeight(uint16_t fontId)449 uint8_t UIFontVector::GetFontWeight(uint16_t fontId)
450 {
451 if (fontId >= FONT_ID_MAX) {
452 return BPP_BIT_8;
453 }
454
455 return fontInfo_[fontId].fontWeight;
456 }
457
SetFontPath(const char * path,FontType type)458 int8_t UIFontVector::SetFontPath(const char* path, FontType type)
459 {
460 if (path == nullptr) {
461 return INVALID_RET_VALUE;
462 }
463 ttfDir_ = path;
464 return RET_VALUE_OK;
465 }
466
GetFaceInfo(uint16_t fontId,uint8_t fontSize,FaceInfo & faceInfo)467 int8_t UIFontVector::GetFaceInfo(uint16_t fontId, uint8_t fontSize, FaceInfo& faceInfo)
468 {
469 if ((fontId >= FONT_ID_MAX) || (fontSize == 0)) {
470 return INVALID_RET_VALUE;
471 }
472
473 faceInfo.key = GetKey(fontId, fontSize);
474 faceInfo.face = ftFaces_[fontId];
475
476 if (fontSize_[fontId] == fontSize) {
477 return RET_VALUE_OK;
478 }
479 const UITextLanguageFontParam* fontInfo = GetFontInfo(fontId);
480 if ((fontInfo == nullptr) || (fontInfo->ttfName == nullptr)) {
481 return INVALID_RET_VALUE;
482 }
483
484 if (!freeTypeInited_) {
485 return INVALID_RET_VALUE;
486 }
487
488 // Set the size
489 int8_t ret;
490 if (IsEmojiFont(fontId)) {
491 ret = SetupColorFont(ftFaces_[fontId], fontSize);
492 } else {
493 ret = FT_Set_Char_Size(faceInfo.face, fontSize * FONT_PIXEL_IN_POINT, 0, 0, 0);
494 }
495
496 if (ret != 0) {
497 return INVALID_RET_VALUE;
498 }
499 fontSize_[fontId] = fontSize;
500 return RET_VALUE_OK;
501 }
502
GetHeight(uint16_t fontId,uint8_t fontSize)503 uint16_t UIFontVector::GetHeight(uint16_t fontId, uint8_t fontSize)
504 {
505 FaceInfo faceInfo;
506 int8_t ret = GetFaceInfo(fontId, fontSize, faceInfo);
507 if (ret != RET_VALUE_OK) {
508 return INVALID_RET_VALUE;
509 }
510 if (!freeTypeInited_ || (faceInfo.face == nullptr)) {
511 return 0;
512 }
513 return static_cast<uint16_t>(faceInfo.face->size->metrics.height / FONT_PIXEL_IN_POINT);
514 }
515
516 uint16_t
GetShapingFontId(char * text,uint8_t & ttfId,uint32_t & script,uint16_t fontId,uint8_t size) const517 UIFontVector::GetShapingFontId(char* text, uint8_t& ttfId, uint32_t& script, uint16_t fontId, uint8_t size) const
518 {
519 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
520 const UITextLanguageFontParam* fontParam1 = GetFontInfo(fontId);
521 if (fontParam1 == nullptr) {
522 return 0;
523 }
524 if (fontParam1->shaping == 0) {
525 UIMultiFontManager* multiFontManager = UIMultiFontManager::GetInstance();
526 if (!multiFontManager->IsNeedShaping(text, ttfId, script)) {
527 return 0; // 0 means no need to shape
528 }
529 uint16_t* searchLists = nullptr;
530 int8_t length = multiFontManager->GetSearchFontList(fontId, &searchLists);
531 const UITextLanguageFontParam* fontParam2 = nullptr;
532 for (uint8_t i = 0; i < length; i++) {
533 fontParam2 = GetFontInfo(searchLists[i]);
534 if (fontParam2 == nullptr) {
535 continue;
536 }
537 if (fontParam2->ttfId == ttfId) {
538 return fontParam2->shaping;
539 }
540 }
541 return 0;
542 }
543 ttfId = fontParam1->ttfId;
544
545 #if defined(ENABLE_SHAPING) && ENABLE_SHAPING
546 script = UIMultiFontManager::GetInstance()->GetScriptByTtfId(ttfId);
547 #endif
548 return fontParam1->shaping;
549 #else
550 const UITextLanguageFontParam* fontInfo = GetFontInfo(fontId);
551 if (fontInfo == nullptr) {
552 return 0;
553 }
554 ttfId = fontInfo->ttfId;
555 return fontInfo->shaping;
556 #endif
557 }
558
GetFontId(const char * ttfName,uint8_t fontSize) const559 uint16_t UIFontVector::GetFontId(const char* ttfName, uint8_t fontSize) const
560 {
561 if (ttfName != nullptr) {
562 int32_t i = 0;
563 while (i < FONT_ID_MAX) {
564 if ((fontInfo_[i].ttfName != nullptr) && (strstr(fontInfo_[i].ttfName, ttfName) != nullptr)) {
565 return static_cast<uint8_t>(i);
566 }
567 i++;
568 }
569 }
570
571 return FONT_ID_MAX;
572 }
573
GetFontId(uint32_t unicode) const574 uint16_t UIFontVector::GetFontId(uint32_t unicode) const
575 {
576 int32_t i = 0;
577 uint8_t ttfId = ((unicode >> 24) & 0x1F); // 24: Whether 25 ~29 bit storage is ttfId 0x1F:5bit
578 while (i < FONT_ID_MAX) {
579 if (fontInfo_[i].ttfName == nullptr) {
580 i++;
581 continue;
582 }
583 if (fontInfo_[i].ttfId == ttfId) {
584 return i;
585 }
586 i++;
587 }
588 return FONT_INVALID_TTF_ID;
589 }
590
GetWidth(uint32_t unicode,uint16_t fontId,uint8_t fontSize)591 int16_t UIFontVector::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize)
592 {
593 if ((fontId >= FONT_ID_MAX) || (fontSize == 0)) {
594 return INVALID_RET_VALUE;
595 }
596
597 GlyphNode node;
598 int8_t ret = GetGlyphNode(unicode, node, fontId, fontSize);
599 if (ret != RET_VALUE_OK) {
600 return INVALID_RET_VALUE;
601 }
602 return node.advance;
603 }
604
GetFontHeader(FontHeader & fontHeader,uint16_t fontId,uint8_t fontSize)605 int8_t UIFontVector::GetFontHeader(FontHeader& fontHeader, uint16_t fontId, uint8_t fontSize)
606 {
607 FaceInfo faceInfo;
608 int8_t ret = GetFaceInfo(fontId, fontSize, faceInfo);
609 if (ret != RET_VALUE_OK) {
610 return INVALID_RET_VALUE;
611 }
612 if (!freeTypeInited_ || (faceInfo.face == nullptr)) {
613 return INVALID_RET_VALUE;
614 }
615
616 fontHeader.ascender = static_cast<int16_t>(faceInfo.face->size->metrics.ascender / FONT_PIXEL_IN_POINT);
617 fontHeader.descender = static_cast<int16_t>(faceInfo.face->size->metrics.descender / FONT_PIXEL_IN_POINT);
618 fontHeader.fontHeight = static_cast<uint16_t>(faceInfo.face->size->metrics.height / FONT_PIXEL_IN_POINT);
619 return RET_VALUE_OK;
620 }
621
SaveGlyphNode(uint32_t unicode,uint16_t fontKey,Metric * metric)622 void UIFontVector::SaveGlyphNode(uint32_t unicode, uint16_t fontKey, Metric *metric)
623 {
624 GlyphCacheNode* node = UIFontCacheManager::GetInstance()->GetNodeCacheSpace(unicode, fontKey);
625 if (node == nullptr) {
626 return;
627 }
628 node->node.left = metric->left;
629 node->node.top = metric->top;
630 node->node.cols = metric->cols;
631 node->node.rows = metric->rows;
632 node->node.advance = metric->advance;
633 node->node.unicode = unicode;
634 node->node.fontId = fontKey;
635 }
636
GetGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)637 int8_t UIFontVector::GetGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
638 {
639 // get glyph from glyph cache
640 uint16_t fontKey = GetKey(fontId, fontSize);
641 UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
642 GlyphCacheNode* cacheNode =
643 fontCacheManager->GetNodeFromCache(unicode, fontKey, GlyphCacheType::CACHE_TYPE_NONE);
644 if (cacheNode != nullptr) {
645 glyphNode = cacheNode->node;
646 return RET_VALUE_OK;
647 }
648
649 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
650 uint8_t* bitmap = fontCacheManager->GetBitmap(fontKey, unicode, glyphNode.textStyle);
651 #else
652 uint8_t* bitmap = fontCacheManager->GetBitmap(fontKey, unicode);
653 #endif
654 if (bitmap != nullptr) {
655 Metric* f = reinterpret_cast<Metric*>(bitmap);
656 glyphNode.left = f->left;
657 glyphNode.top = f->top;
658 glyphNode.cols = f->cols;
659 glyphNode.rows = f->rows;
660 glyphNode.advance = f->advance;
661 glyphNode.fontId = fontId;
662
663 SaveGlyphNode(unicode, fontKey, f);
664 return RET_VALUE_OK;
665 }
666
667 FaceInfo faceInfo;
668 int8_t ret = GetFaceInfo(fontId, fontSize, faceInfo);
669 if (ret != RET_VALUE_OK) {
670 return INVALID_RET_VALUE;
671 }
672 if (faceInfo.face == nullptr) {
673 return INVALID_RET_VALUE;
674 }
675
676 int8_t error = LoadGlyphIntoFace(fontId, fontSize, unicode, glyphNode);
677 if (error != RET_VALUE_OK) {
678 return INVALID_RET_VALUE;
679 }
680
681 return RET_VALUE_OK;
682 }
683
GetBitmap(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)684 uint8_t* UIFontVector::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
685 {
686 uint16_t fontKey = GetKey(fontId, fontSize);
687 UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
688 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
689 uint8_t* bitmap = fontCacheManager->GetBitmap(fontKey, unicode, glyphNode.textStyle);
690 #else
691 uint8_t* bitmap = fontCacheManager->GetBitmap(fontKey, unicode);
692 #endif
693 if (bitmap != nullptr) {
694 Metric* f = reinterpret_cast<Metric*>(bitmap);
695 glyphNode.left = f->left;
696 glyphNode.top = f->top;
697 glyphNode.cols = f->cols;
698 glyphNode.rows = f->rows;
699 glyphNode.advance = f->advance;
700 glyphNode.fontId = fontId;
701 SaveGlyphNode(unicode, fontKey, f);
702 return bitmap + sizeof(Metric);
703 }
704
705 FaceInfo faceInfo;
706 int8_t ret = GetFaceInfo(fontId, fontSize, faceInfo);
707 if (ret != RET_VALUE_OK) {
708 return nullptr;
709 }
710 if (faceInfo.face == nullptr) {
711 return nullptr;
712 }
713
714 int8_t error = LoadGlyphIntoFace(fontId, fontSize, unicode, glyphNode);
715 if (error != RET_VALUE_OK) {
716 return nullptr;
717 }
718
719 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
720 bitmap = fontCacheManager->GetBitmap(fontKey, unicode, glyphNode.textStyle);
721 #else
722 bitmap = fontCacheManager->GetBitmap(fontKey, unicode);
723 #endif
724 if (bitmap != nullptr) {
725 return bitmap + sizeof(Metric);
726 } else {
727 return nullptr;
728 }
729 }
730
IsEmojiFont(uint16_t fontId)731 bool UIFontVector::IsEmojiFont(uint16_t fontId)
732 {
733 if (fontId >= FONT_ID_MAX) {
734 return false;
735 }
736 return (fontInfo_[fontId].fontWeight >= 16); // 16: rgb color font
737 }
738
739 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
SetItaly(FT_GlyphSlot slot)740 void UIFontVector::SetItaly(FT_GlyphSlot slot)
741 {
742 if (slot->format != FT_GLYPH_FORMAT_OUTLINE) {
743 GRAPHIC_LOGE("SetItaly error");
744 return;
745 }
746 float lean = 0.2f; // Slope of word
747 FT_Matrix matrix;
748 matrix.xx = 0x10000L; // Staggered matrix along x-axis
749 matrix.xy = lean * 0x10000L;
750 matrix.yx = 0;
751 matrix.yy = 0x10000L; // Staggered matrix along y-axis
752 FT_Outline outline = slot->outline;
753 FT_Outline_Transform(&outline, &matrix);
754 }
755
SetBold(uint16_t fontId)756 void UIFontVector::SetBold(uint16_t fontId)
757 {
758 int32_t error;
759 FT_GlyphSlot slot = ftFaces_[fontId]->glyph;
760 // some reasonable strength, copied from freeType
761 FT_Pos xBold = FT_MulFix(ftFaces_[fontId]->units_per_EM, ftFaces_[fontId]->size->metrics.y_scale) / 24;
762 FT_Pos yBold = xBold;
763 if (ftFaces_[fontId]->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
764 FT_BBox oldBox;
765 FT_Outline_Get_CBox(&slot->outline, &oldBox);
766 error = FT_Outline_Embolden(&slot->outline, xBold);
767 if (error != 0) {
768 GRAPHIC_LOGE("SetBold error");
769 return;
770 }
771 } else if (ftFaces_[fontId]->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
772 FT_Library ftLibrary = slot->library;
773 error = FT_Bitmap_Embolden(ftLibrary, &slot->bitmap, xBold, yBold);
774 if (error != 0) {
775 GRAPHIC_LOGE("SetBold error");
776 return;
777 }
778 }
779 }
780 #endif
781
LoadGlyphIntoFace(uint16_t & fontId,uint8_t fontSize,uint32_t unicode,GlyphNode & glyphNode)782 int8_t UIFontVector::LoadGlyphIntoFace(uint16_t& fontId, uint8_t fontSize, uint32_t unicode, GlyphNode& glyphNode)
783 {
784 int32_t error;
785 if (IsGlyphFont(unicode) != 0) {
786 if (fontId >= FONT_ID_MAX || fontId != GetFontId(unicode)) {
787 return INVALID_RET_VALUE;
788 }
789 error = FT_Load_Glyph(ftFaces_[fontId], unicode & (0xFFFFFF), FT_LOAD_RENDER);
790 } else {
791 if (IsEmojiFont(fontId)) {
792 error = FT_Load_Char(ftFaces_[fontId], unicode, FT_LOAD_COLOR);
793 } else {
794 error = FT_Load_Char(ftFaces_[fontId], unicode, FT_LOAD_RENDER);
795 }
796 }
797 if ((error != 0) || (ftFaces_[fontId]->glyph->glyph_index == 0)) {
798 return INVALID_RET_VALUE;
799 }
800
801 FaceInfo faceInfo;
802 faceInfo.key = GetKey(fontId, fontSize);
803 faceInfo.face = ftFaces_[fontId];
804
805 glyphNode.left = faceInfo.face->glyph->bitmap_left;
806 glyphNode.top = faceInfo.face->glyph->bitmap_top;
807 glyphNode.cols = faceInfo.face->glyph->bitmap.width;
808 glyphNode.rows = faceInfo.face->glyph->bitmap.rows;
809 glyphNode.advance = static_cast<uint16_t>(faceInfo.face->glyph->advance.x / FONT_PIXEL_IN_POINT);
810 glyphNode.fontId = fontId;
811
812 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
813 SetFace(faceInfo, unicode, glyphNode.textStyle);
814 #else
815 SetFace(faceInfo, unicode);
816 #endif
817 return RET_VALUE_OK;
818 }
819
820 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
LoadGlyphIntoFace(uint16_t & fontId,uint32_t unicode,FT_Face face,TextStyle textStyle)821 int8_t UIFontVector::LoadGlyphIntoFace(uint16_t& fontId, uint32_t unicode, FT_Face face, TextStyle textStyle)
822 {
823 int32_t error;
824 if (IsGlyphFont(unicode) != 0) {
825 if (fontId != GetFontId(unicode)) {
826 return INVALID_RET_VALUE;
827 }
828 unicode = unicode & (0xFFFFFF); // Whether 0 ~24 bit storage is unicode
829 error = FT_Load_Glyph(ftFaces_[fontId], unicode, FT_LOAD_RENDER);
830 } else {
831 if (IsEmojiFont(fontId)) {
832 error = FT_Load_Char(ftFaces_[fontId], unicode, FT_LOAD_COLOR);
833 } else {
834 error = FT_Load_Char(ftFaces_[fontId], unicode, FT_LOAD_RENDER);
835 }
836 }
837 if ((error != 0) || (ftFaces_[fontId]->glyph->glyph_index == 0)) {
838 return INVALID_RET_VALUE;
839 }
840 if (textStyle == TEXT_STYLE_ITALIC) {
841 SetItaly(ftFaces_[fontId]->glyph);
842 } else if (textStyle == TEXT_STYLE_BOLD) {
843 SetBold(fontId);
844 } else if (textStyle == TEXT_STYLE_BOLD_ITALIC) {
845 SetItaly(ftFaces_[fontId]->glyph);
846 SetBold(fontId);
847 }
848 if (ftFaces_[fontId]->glyph->format != FT_GLYPH_FORMAT_BITMAP) {
849 error = FT_Render_Glyph(ftFaces_[fontId]->glyph, FT_RENDER_MODE_NORMAL);
850 }
851 if ((error != 0) || (ftFaces_[fontId]->glyph->glyph_index == 0)) {
852 return INVALID_RET_VALUE;
853 }
854 return RET_VALUE_OK;
855 }
856 #endif
857
IsGlyphFont(uint32_t unicode)858 uint8_t UIFontVector::IsGlyphFont(uint32_t unicode)
859 {
860 uint16_t unicodeFontId = GetFontId(unicode);
861 if (unicodeFontId == FONT_INVALID_TTF_ID) {
862 return 0;
863 } else {
864 return fontInfo_[unicodeFontId].shaping;
865 }
866 }
867
SetFace(FaceInfo & faceInfo,uint32_t unicode)868 void UIFontVector::SetFace(FaceInfo& faceInfo, uint32_t unicode)
869 {
870 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
871 SetFace(faceInfo, unicode, TEXT_STYLE_NORMAL);
872 #else
873 Metric* f = reinterpret_cast<Metric*>(UIMalloc(sizeof(Metric)));
874 if (f == nullptr) {
875 return;
876 }
877 f->advance = static_cast<uint16_t>(faceInfo.face->glyph->advance.x / FONT_PIXEL_IN_POINT);
878 f->left = faceInfo.face->glyph->bitmap_left;
879 f->top = faceInfo.face->glyph->bitmap_top;
880 f->cols = faceInfo.face->glyph->bitmap.width;
881 f->rows = faceInfo.face->glyph->bitmap.rows;
882
883 // cache glyph
884 SaveGlyphNode(unicode, faceInfo.key, f);
885
886 int16_t pixSize;
887 ColorMode mode;
888 if (faceInfo.face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
889 pixSize = 0x04; // 4 Byte
890 mode = ARGB8888;
891 } else {
892 pixSize = 1;
893 mode = A8;
894 }
895
896 GlyphNode glyphNode;
897 glyphNode.left = f->left;
898 glyphNode.top = f->top;
899 glyphNode.cols = f->cols;
900 glyphNode.rows = f->rows;
901 glyphNode.advance = f->advance;
902 glyphNode.unicode = unicode;
903 glyphNode.fontId = faceInfo.key;
904 BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(faceInfo.key, unicode, mode, glyphNode, true);
905 uint32_t bitmapSize = bufInfo.stride * bufInfo.height;
906 uint32_t rawSize = glyphNode.cols * glyphNode.rows * pixSize;
907
908 if (bufInfo.virAddr != nullptr) {
909 if (memcpy_s(bufInfo.virAddr, sizeof(Metric), f, sizeof(Metric)) != EOK) {
910 UIFontCacheManager::GetInstance()->PutSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
911 UIFree(f);
912 return;
913 }
914 if ((faceInfo.face->glyph->bitmap.buffer != nullptr) &&
915 (memcpy_s(reinterpret_cast<uint8_t*>(bufInfo.virAddr) + sizeof(Metric), bitmapSize,
916 faceInfo.face->glyph->bitmap.buffer, rawSize) != EOK)) {
917 UIFontCacheManager::GetInstance()->PutSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
918 UIFree(f);
919 return;
920 }
921 UIFontAllocator::RearrangeBitmap(bufInfo, rawSize, true);
922 ClearFontGlyph(faceInfo.face);
923 }
924 UIFree(f);
925 #endif
926 }
927
928 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
SetFace(FaceInfo & faceInfo,uint32_t unicode,TextStyle textStyle)929 void UIFontVector::SetFace(FaceInfo& faceInfo, uint32_t unicode, TextStyle textStyle)
930 {
931 Metric f;
932 f.advance = static_cast<uint16_t>(faceInfo.face->glyph->advance.x / FONT_PIXEL_IN_POINT);
933 f.left = faceInfo.face->glyph->bitmap_left;
934 f.top = faceInfo.face->glyph->bitmap_top;
935 f.cols = faceInfo.face->glyph->bitmap.width;
936 f.rows = faceInfo.face->glyph->bitmap.rows;
937
938 // cache glyph
939 SaveGlyphNode(unicode, faceInfo.key, &f);
940
941 int16_t pixSize = 1;
942 if (faceInfo.face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
943 pixSize = 0x04; // 4 Byte
944 }
945 uint32_t bitmapSize = faceInfo.face->glyph->bitmap.width * faceInfo.face->glyph->bitmap.rows * pixSize;
946 // cache bitmap
947 UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
948 uint8_t* bitmap =
949 fontCacheManager->GetSpace(faceInfo.key, unicode, bitmapSize + sizeof(Metric), textStyle);
950 if (bitmap != nullptr) {
951 if (memcpy_s(bitmap, sizeof(Metric), &f, sizeof(Metric)) != EOK) {
952 fontCacheManager->PutSpace(bitmap);
953 return;
954 }
955 if ((faceInfo.face->glyph->bitmap.buffer != nullptr) &&
956 (memcpy_s(bitmap + sizeof(Metric), bitmapSize, faceInfo.face->glyph->bitmap.buffer, bitmapSize) != EOK)) {
957 fontCacheManager->PutSpace(bitmap);
958 return;
959 }
960 ClearFontGlyph(faceInfo.face);
961 }
962 }
963 #endif
964
ClearFontGlyph(FT_Face face)965 void UIFontVector::ClearFontGlyph(FT_Face face)
966 {
967 if ((face != nullptr) && (face->glyph != nullptr)) {
968 // free unicode buffer immediately to save memory in multi font file load
969 // if not, it will be freed in next glyph load
970 ft_glyphslot_free_bitmap(face->glyph);
971 FT_Outline_Done(face->glyph->library, &face->glyph->outline);
972 if (face->glyph->internal != nullptr) {
973 FT_GlyphLoader_Reset(face->glyph->internal->loader);
974 }
975 }
976 }
977
GetKey(uint16_t fontId,uint8_t size)978 inline uint16_t UIFontVector::GetKey(uint16_t fontId, uint8_t size)
979 {
980 return ((static_cast<uint16_t>(fontId)) << 8) + size; // fontId store at the (8+1)th bit
981 }
982
GetOffsetPosY(const char * text,uint16_t lineLength,bool & isEmojiLarge,uint16_t fontId,uint8_t fontSize)983 uint16_t UIFontVector::GetOffsetPosY(const char* text,
984 uint16_t lineLength,
985 bool& isEmojiLarge,
986 uint16_t fontId,
987 uint8_t fontSize)
988 {
989 if (!freeTypeInited_) {
990 return INVALID_RET_VALUE;
991 }
992 uint32_t i = 0;
993 uint16_t textNum = 0;
994 uint16_t emojiNum = 0;
995 uint16_t loopNum = 0;
996 GlyphNode glyphNode;
997 GlyphNode emojiMaxNode = {};
998 uint8_t maxFontSize = fontSize;
999 while (i < lineLength) {
1000 uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
1001 uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
1002 if (ret == RET_VALUE_OK) {
1003 uint8_t weight = GetFontWeight(glyphNode.fontId);
1004 // 16: bit rgb565 rgba8888
1005 if (weight >= 16) {
1006 emojiMaxNode = glyphNode.rows > emojiMaxNode.rows ? glyphNode : emojiMaxNode;
1007 emojiNum++;
1008 } else {
1009 textNum++;
1010 }
1011 loopNum++;
1012 }
1013 }
1014 // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
1015 // The number of words is the same as the number of cycles, which means that this line is all words
1016 if ((emojiNum == loopNum) || (textNum == loopNum)) {
1017 isEmojiLarge = true;
1018 return 0;
1019 }
1020 isEmojiLarge = emojiMaxNode.rows > maxFontSize;
1021 uint16_t offset = 0;
1022 if (isEmojiLarge) {
1023 // If the emoji is higher than the text
1024 if (emojiMaxNode.top >= maxFontSize) {
1025 offset = emojiMaxNode.top - maxFontSize;
1026 }
1027 } else {
1028 // If text are higher than emoji
1029 if (maxFontSize >= emojiMaxNode.rows) {
1030 offset = maxFontSize - emojiMaxNode.rows;
1031 }
1032 }
1033 return offset;
1034 }
1035
GetLineMaxHeight(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t & letterIndex,SizeSpan * sizeSpans)1036 uint16_t UIFontVector::GetLineMaxHeight(const char* text,
1037 uint16_t lineLength,
1038 uint16_t fontId,
1039 uint8_t fontSize,
1040 uint16_t& letterIndex,
1041 SizeSpan* sizeSpans)
1042 {
1043 if (!freeTypeInited_) {
1044 return INVALID_RET_VALUE;
1045 }
1046 uint32_t i = 0;
1047 uint16_t textNum = 0;
1048 uint16_t emojiNum = 0;
1049 uint16_t loopNum = 0;
1050 uint16_t maxHeight = GetHeight(fontId, fontSize);
1051 while (i < lineLength) {
1052 uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
1053 TypedText::IsColourWord(unicode, fontId, fontSize) ? emojiNum++ : textNum++;
1054 loopNum++;
1055 if (sizeSpans != nullptr && sizeSpans[letterIndex].isSizeSpan) {
1056 uint16_t spannableHeight = 0;
1057 if (sizeSpans[letterIndex].height == 0) {
1058 spannableHeight = GetHeight(sizeSpans[letterIndex].fontId, sizeSpans[letterIndex].size);
1059 sizeSpans[letterIndex].height = spannableHeight;
1060 } else {
1061 spannableHeight = sizeSpans[letterIndex].height;
1062 }
1063 maxHeight = spannableHeight > maxHeight ? spannableHeight : maxHeight;
1064 }
1065 letterIndex++;
1066 if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
1067 break;
1068 }
1069 }
1070 return GetMaxSubLineHeight(textNum, loopNum, maxHeight, emojiNum);
1071 }
1072
GetMaxSubLineHeight(uint16_t textNum,uint16_t loopNum,uint16_t maxHeight,uint16_t emojiNum)1073 uint16_t UIFontVector::GetMaxSubLineHeight(uint16_t textNum, uint16_t loopNum, uint16_t maxHeight, uint16_t emojiNum)
1074 {
1075 // The number of words is the same as the number of cycles, which means that this line is all words
1076 if (textNum == loopNum) {
1077 for (uint8_t i = 0; i < currentFontInfoNum_; i++) {
1078 if (!IsEmojiFont(i)) {
1079 uint16_t height = static_cast<uint16_t>(ftFaces_[i]->size->metrics.height / FONT_PIXEL_IN_POINT);
1080 if (height > maxHeight) {
1081 maxHeight = height;
1082 }
1083 return maxHeight;
1084 }
1085 }
1086 }
1087 // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
1088 if (emojiNum == loopNum) {
1089 for (uint8_t i = 0; i < currentFontInfoNum_; i++) {
1090 if (IsEmojiFont(i)) {
1091 return static_cast<uint16_t>(ftFaces_[i]->size->metrics.height / FONT_PIXEL_IN_POINT);
1092 }
1093 }
1094 }
1095 // A line has both emoji and words
1096 if ((textNum > 0) && (emojiNum > 0)) {
1097 for (uint8_t i = 0; i < currentFontInfoNum_; i++) {
1098 uint16_t tmpHeight = static_cast<uint16_t>(ftFaces_[i]->size->metrics.height / FONT_PIXEL_IN_POINT);
1099 maxHeight = tmpHeight > maxHeight ? tmpHeight : maxHeight;
1100 }
1101 }
1102 return maxHeight;
1103 }
1104
SetPsramMemory(uintptr_t psramAddr,uint32_t psramLen)1105 void UIFontVector::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
1106 {
1107 BaseFont::SetPsramMemory(psramAddr, psramLen);
1108 FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
1109 }
1110
SetCurrentLangId(uint8_t langId)1111 int8_t UIFontVector::SetCurrentLangId(uint8_t langId)
1112 {
1113 FontRamAllocator::GetInstance().ClearRam();
1114 #if defined(ENABLE_SHAPING) && ENABLE_SHAPING
1115 UITextShaping::GetInstance()->ClearTtfHeader();
1116 #endif
1117 UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
1118 fontCacheManager->ClearCacheFlag();
1119 fontCacheManager->BitmapCacheClear();
1120
1121 if (fontCacheManager->GlyphsCacheInit() != RET_VALUE_OK) {
1122 GRAPHIC_LOGE("UIFontCacheManager::GlyphsCacheInit init failed");
1123 return INVALID_RET_VALUE;
1124 }
1125
1126 fontCacheManager->BitmapCacheInit();
1127 return RET_VALUE_OK;
1128 }
1129 } // namespace OHOS
1130