• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetShapingFontId(char * text,uint8_t & ttfId,uint32_t & script,uint16_t fontId,uint8_t size) const516 uint16_t UIFontVector::GetShapingFontId(char* text, uint8_t& ttfId, uint32_t& script,
517                                         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         if (!UIMultiFontManager::GetInstance()->IsNeedShaping(text, ttfId, script)) {
526             return 0; // 0 means  no need to shape
527         }
528         uint16_t* searchLists = nullptr;
529         int8_t length = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
530         const UITextLanguageFontParam* fontParam2 = nullptr;
531         for (uint8_t i = 0; i < length; i++) {
532             fontParam2 = GetFontInfo(searchLists[i]);
533             if (fontParam2 == nullptr) {
534                 continue;
535             }
536             if (fontParam2->ttfId == ttfId) {
537                 return fontParam2->shaping;
538             }
539         }
540         return 0;
541     }
542     ttfId = fontParam1->ttfId;
543 
544 #if defined(ENABLE_SHAPING) && ENABLE_SHAPING
545     script = UIMultiFontManager::GetInstance()->GetScriptByTtfId(ttfId);
546 #endif
547     return fontParam1->shaping;
548 #else
549     const UITextLanguageFontParam* fontInfo = GetFontInfo(fontId);
550     if (fontInfo == nullptr) {
551         return 0;
552     }
553     ttfId = fontInfo->ttfId;
554     return fontInfo->shaping;
555 #endif
556 }
557 
GetFontId(const char * ttfName,uint8_t fontSize) const558 uint16_t UIFontVector::GetFontId(const char* ttfName, uint8_t fontSize) const
559 {
560     if (ttfName != nullptr) {
561         int32_t i = 0;
562         while (i < FONT_ID_MAX) {
563             if ((fontInfo_[i].ttfName != nullptr) && (strstr(fontInfo_[i].ttfName, ttfName) != nullptr)) {
564                 return static_cast<uint8_t>(i);
565             }
566             i++;
567         }
568     }
569 
570     return FONT_ID_MAX;
571 }
572 
GetFontId(uint32_t unicode) const573 uint16_t UIFontVector::GetFontId(uint32_t unicode) const
574 {
575     int32_t i = 0;
576     uint8_t ttfId = ((unicode >> 24) & 0x1F); // 24: Whether 25 ~29 bit storage is ttfId 0x1F:5bit
577     while (i < FONT_ID_MAX) {
578         if (fontInfo_[i].ttfName == nullptr) {
579             i++;
580             continue;
581         }
582         if (fontInfo_[i].ttfId == ttfId) {
583             return i;
584         }
585         i++;
586     }
587     return FONT_INVALID_TTF_ID;
588 }
589 
GetWidth(uint32_t unicode,uint16_t fontId,uint8_t fontSize)590 int16_t UIFontVector::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize)
591 {
592     if ((fontId >= FONT_ID_MAX) || (fontSize == 0)) {
593         return INVALID_RET_VALUE;
594     }
595 
596     GlyphNode node;
597     int8_t ret = GetGlyphNode(unicode, node, fontId, fontSize);
598     if (ret != RET_VALUE_OK) {
599         return INVALID_RET_VALUE;
600     }
601     return node.advance;
602 }
603 
GetFontHeader(FontHeader & fontHeader,uint16_t fontId,uint8_t fontSize)604 int8_t UIFontVector::GetFontHeader(FontHeader& fontHeader, uint16_t fontId, uint8_t fontSize)
605 {
606     FaceInfo faceInfo;
607     int8_t ret = GetFaceInfo(fontId, fontSize, faceInfo);
608     if (ret != RET_VALUE_OK) {
609         return INVALID_RET_VALUE;
610     }
611     if (!freeTypeInited_ || (faceInfo.face == nullptr)) {
612         return INVALID_RET_VALUE;
613     }
614 
615     fontHeader.ascender = static_cast<int16_t>(faceInfo.face->size->metrics.ascender / FONT_PIXEL_IN_POINT);
616     fontHeader.descender = static_cast<int16_t>(faceInfo.face->size->metrics.descender / FONT_PIXEL_IN_POINT);
617     fontHeader.fontHeight = static_cast<uint16_t>(faceInfo.face->size->metrics.height / FONT_PIXEL_IN_POINT);
618     return RET_VALUE_OK;
619 }
620 
SaveGlyphNode(uint32_t unicode,uint16_t fontKey,Metric * metric)621 void UIFontVector::SaveGlyphNode(uint32_t unicode, uint16_t fontKey, Metric *metric)
622 {
623     GlyphCacheNode* node = UIFontCacheManager::GetInstance()->GetNodeCacheSpace(unicode, fontKey);
624     if (node == nullptr) {
625         return;
626     }
627     node->node.left = metric->left;
628     node->node.top = metric->top;
629     node->node.cols = metric->cols;
630     node->node.rows = metric->rows;
631     node->node.advance = metric->advance;
632     node->node.unicode = unicode;
633     node->node.fontId = fontKey;
634 }
635 
GetGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)636 int8_t UIFontVector::GetGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
637 {
638     // get glyph from glyph cache
639     uint16_t fontKey = GetKey(fontId, fontSize);
640     GlyphCacheNode* cacheNode =
641         UIFontCacheManager::GetInstance()->GetNodeFromCache(unicode, fontKey, GlyphCacheType::CACHE_TYPE_NONE);
642     if (cacheNode != nullptr) {
643         glyphNode = cacheNode->node;
644         return RET_VALUE_OK;
645     }
646 
647 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
648     uint8_t* bitmap = UIFontCacheManager::GetInstance()->GetBitmap(fontKey, unicode, glyphNode.textStyle);
649 #else
650     uint8_t* bitmap = UIFontCacheManager::GetInstance()->GetBitmap(fontKey, unicode);
651 #endif
652     if (bitmap != nullptr) {
653         Metric* f = reinterpret_cast<Metric*>(bitmap);
654         glyphNode.left = f->left;
655         glyphNode.top = f->top;
656         glyphNode.cols = f->cols;
657         glyphNode.rows = f->rows;
658         glyphNode.advance = f->advance;
659         glyphNode.fontId = fontId;
660 
661         SaveGlyphNode(unicode, fontKey, f);
662         return RET_VALUE_OK;
663     }
664 
665     FaceInfo faceInfo;
666     int8_t ret = GetFaceInfo(fontId, fontSize, faceInfo);
667     if (ret != RET_VALUE_OK) {
668         return INVALID_RET_VALUE;
669     }
670     if (faceInfo.face == nullptr) {
671         return INVALID_RET_VALUE;
672     }
673 
674     int8_t error = LoadGlyphIntoFace(fontId, fontSize, unicode, glyphNode);
675     if (error != RET_VALUE_OK) {
676         return INVALID_RET_VALUE;
677     }
678 
679     return RET_VALUE_OK;
680 }
681 
GetBitmap(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)682 uint8_t* UIFontVector::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
683 {
684     uint16_t fontKey = GetKey(fontId, fontSize);
685 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
686     uint8_t* bitmap = UIFontCacheManager::GetInstance()->GetBitmap(fontKey, unicode, glyphNode.textStyle);
687 #else
688     uint8_t* bitmap = UIFontCacheManager::GetInstance()->GetBitmap(fontKey, unicode);
689 #endif
690     if (bitmap != nullptr) {
691         Metric* f = reinterpret_cast<Metric*>(bitmap);
692         glyphNode.left = f->left;
693         glyphNode.top = f->top;
694         glyphNode.cols = f->cols;
695         glyphNode.rows = f->rows;
696         glyphNode.advance = f->advance;
697         glyphNode.fontId = fontId;
698         SaveGlyphNode(unicode, fontKey, f);
699         return bitmap + sizeof(Metric);
700     }
701 
702     FaceInfo faceInfo;
703     int8_t ret = GetFaceInfo(fontId, fontSize, faceInfo);
704     if (ret != RET_VALUE_OK) {
705         return nullptr;
706     }
707     if (faceInfo.face == nullptr) {
708         return nullptr;
709     }
710 
711     int8_t error = LoadGlyphIntoFace(fontId, fontSize, unicode, glyphNode);
712     if (error != RET_VALUE_OK) {
713         return nullptr;
714     }
715 
716 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
717     bitmap = UIFontCacheManager::GetInstance()->GetBitmap(fontKey, unicode, glyphNode.textStyle);
718 #else
719     bitmap = UIFontCacheManager::GetInstance()->GetBitmap(fontKey, unicode);
720 #endif
721     if (bitmap != nullptr) {
722         return bitmap + sizeof(Metric);
723     } else {
724         return nullptr;
725     }
726 }
727 
IsEmojiFont(uint16_t fontId)728 bool UIFontVector::IsEmojiFont(uint16_t fontId)
729 {
730     if (fontId >= FONT_ID_MAX) {
731         return false;
732     }
733     return (fontInfo_[fontId].fontWeight >= 16); // 16: rgb color font
734 }
735 
736 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
SetItaly(FT_GlyphSlot slot)737 void UIFontVector::SetItaly(FT_GlyphSlot slot)
738 {
739     if (slot->format != FT_GLYPH_FORMAT_OUTLINE) {
740         GRAPHIC_LOGE("SetItaly error");
741         return;
742     }
743     float lean = 0.2f; // Slope of word
744     FT_Matrix matrix;
745     matrix.xx = 0x10000L; // Staggered matrix along x-axis
746     matrix.xy = lean * 0x10000L;
747     matrix.yx = 0;
748     matrix.yy = 0x10000L; // Staggered matrix along y-axis
749     FT_Outline outline = slot->outline;
750     FT_Outline_Transform(&outline, &matrix);
751 }
752 
SetBold(uint16_t fontId)753 void UIFontVector::SetBold(uint16_t fontId)
754 {
755     int32_t error;
756     FT_GlyphSlot slot = ftFaces_[fontId]->glyph;
757     // some reasonable strength, copied from freeType
758     FT_Pos xBold = FT_MulFix(ftFaces_[fontId]->units_per_EM, ftFaces_[fontId]->size->metrics.y_scale) / 24;
759     FT_Pos yBold = xBold;
760     if (ftFaces_[fontId]->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
761         FT_BBox oldBox;
762         FT_Outline_Get_CBox(&slot->outline, &oldBox);
763         error = FT_Outline_Embolden(&slot->outline, xBold);
764         if (error != 0) {
765             GRAPHIC_LOGE("SetBold error");
766             return;
767         }
768     } else if (ftFaces_[fontId]->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
769         FT_Library ftLibrary = slot->library;
770         error = FT_Bitmap_Embolden(ftLibrary, &slot->bitmap, xBold, yBold);
771         if (error != 0) {
772             GRAPHIC_LOGE("SetBold error");
773             return;
774         }
775     }
776 }
777 #endif
778 
LoadGlyphIntoFace(uint16_t & fontId,uint8_t fontSize,uint32_t unicode,GlyphNode & glyphNode)779 int8_t UIFontVector::LoadGlyphIntoFace(uint16_t& fontId, uint8_t fontSize, uint32_t unicode, GlyphNode& glyphNode)
780 {
781     int32_t error;
782     if (IsGlyphFont(unicode) != 0) {
783         if (fontId >= FONT_ID_MAX || fontId != GetFontId(unicode)) {
784             return INVALID_RET_VALUE;
785         }
786         error = FT_Load_Glyph(ftFaces_[fontId], unicode & (0xFFFFFF), FT_LOAD_RENDER);
787     } else {
788         if (IsEmojiFont(fontId)) {
789             error = FT_Load_Char(ftFaces_[fontId], unicode, FT_LOAD_COLOR);
790         } else {
791             error = FT_Load_Char(ftFaces_[fontId], unicode, FT_LOAD_RENDER);
792         }
793     }
794     if ((error != 0) || (ftFaces_[fontId]->glyph->glyph_index == 0)) {
795         return INVALID_RET_VALUE;
796     }
797 
798     FaceInfo faceInfo;
799     faceInfo.key = GetKey(fontId, fontSize);
800     faceInfo.face = ftFaces_[fontId];
801 
802     glyphNode.left = faceInfo.face->glyph->bitmap_left;
803     glyphNode.top = faceInfo.face->glyph->bitmap_top;
804     glyphNode.cols = faceInfo.face->glyph->bitmap.width;
805     glyphNode.rows = faceInfo.face->glyph->bitmap.rows;
806     glyphNode.advance = static_cast<uint16_t>(faceInfo.face->glyph->advance.x / FONT_PIXEL_IN_POINT);
807     glyphNode.fontId = fontId;
808 
809 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
810     SetFace(faceInfo, unicode, glyphNode.textStyle);
811 #else
812     SetFace(faceInfo, unicode);
813 #endif
814     return RET_VALUE_OK;
815 }
816 
817 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
LoadGlyphIntoFace(uint16_t & fontId,uint32_t unicode,FT_Face face,TextStyle textStyle)818 int8_t UIFontVector::LoadGlyphIntoFace(uint16_t& fontId, uint32_t unicode, FT_Face face, TextStyle textStyle)
819 {
820     int32_t error;
821     if (IsGlyphFont(unicode) != 0) {
822         if (fontId != GetFontId(unicode)) {
823             return INVALID_RET_VALUE;
824         }
825         unicode = unicode & (0xFFFFFF); // Whether 0 ~24 bit storage is unicode
826         error = FT_Load_Glyph(ftFaces_[fontId], unicode, FT_LOAD_RENDER);
827     } else {
828         if (IsEmojiFont(fontId)) {
829             error = FT_Load_Char(ftFaces_[fontId], unicode, FT_LOAD_COLOR);
830         } else {
831             error = FT_Load_Char(ftFaces_[fontId], unicode, FT_LOAD_RENDER);
832         }
833     }
834     if ((error != 0) || (ftFaces_[fontId]->glyph->glyph_index == 0)) {
835         return INVALID_RET_VALUE;
836     }
837     if (textStyle == TEXT_STYLE_ITALIC) {
838         SetItaly(ftFaces_[fontId]->glyph);
839     } else if (textStyle == TEXT_STYLE_BOLD) {
840         SetBold(fontId);
841     } else if (textStyle == TEXT_STYLE_BOLD_ITALIC) {
842         SetItaly(ftFaces_[fontId]->glyph);
843         SetBold(fontId);
844     }
845     if (ftFaces_[fontId]->glyph->format != FT_GLYPH_FORMAT_BITMAP) {
846         error = FT_Render_Glyph(ftFaces_[fontId]->glyph, FT_RENDER_MODE_NORMAL);
847     }
848     if ((error != 0) || (ftFaces_[fontId]->glyph->glyph_index == 0)) {
849         return INVALID_RET_VALUE;
850     }
851     return RET_VALUE_OK;
852 }
853 #endif
854 
IsGlyphFont(uint32_t unicode)855 uint8_t UIFontVector::IsGlyphFont(uint32_t unicode)
856 {
857     uint16_t unicodeFontId = GetFontId(unicode);
858     if (unicodeFontId == FONT_INVALID_TTF_ID) {
859         return 0;
860     } else {
861         return fontInfo_[unicodeFontId].shaping;
862     }
863 }
864 
SetFace(FaceInfo & faceInfo,uint32_t unicode)865 void UIFontVector::SetFace(FaceInfo& faceInfo, uint32_t unicode)
866 {
867 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
868     SetFace(faceInfo, unicode, TEXT_STYLE_NORMAL);
869 #else
870     Metric* f = reinterpret_cast<Metric*>(UIMalloc(sizeof(Metric)));
871     if (f == nullptr) {
872         return;
873     }
874     f->advance = static_cast<uint16_t>(faceInfo.face->glyph->advance.x / FONT_PIXEL_IN_POINT);
875     f->left = faceInfo.face->glyph->bitmap_left;
876     f->top = faceInfo.face->glyph->bitmap_top;
877     f->cols = faceInfo.face->glyph->bitmap.width;
878     f->rows = faceInfo.face->glyph->bitmap.rows;
879 
880     // cache glyph
881     SaveGlyphNode(unicode, faceInfo.key, f);
882 
883     int16_t pixSize;
884     ColorMode mode;
885     if (faceInfo.face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
886         pixSize = 0x04; // 4 Byte
887         mode = ARGB8888;
888     } else {
889         pixSize = 1;
890         mode = A8;
891     }
892 
893     GlyphNode glyphNode;
894     glyphNode.left = f->left;
895     glyphNode.top = f->top;
896     glyphNode.cols = f->cols;
897     glyphNode.rows = f->rows;
898     glyphNode.advance = f->advance;
899     glyphNode.unicode = unicode;
900     glyphNode.fontId = faceInfo.key;
901     BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(faceInfo.key, unicode, mode, glyphNode, true);
902     uint32_t bitmapSize = bufInfo.stride * bufInfo.height;
903     uint32_t rawSize = glyphNode.cols * glyphNode.rows * pixSize;
904 
905     if (bufInfo.virAddr != nullptr) {
906         if (memcpy_s(bufInfo.virAddr, sizeof(Metric), f, sizeof(Metric)) != EOK) {
907             UIFontCacheManager::GetInstance()->PutSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
908             UIFree(f);
909             return;
910         }
911         if ((faceInfo.face->glyph->bitmap.buffer != nullptr) &&
912             (memcpy_s(reinterpret_cast<uint8_t*>(bufInfo.virAddr) + sizeof(Metric), bitmapSize,
913                       faceInfo.face->glyph->bitmap.buffer, rawSize) != EOK)) {
914             UIFontCacheManager::GetInstance()->PutSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
915             UIFree(f);
916             return;
917         }
918         UIFontAllocator::RearrangeBitmap(bufInfo, rawSize, true);
919         ClearFontGlyph(faceInfo.face);
920     }
921     UIFree(f);
922 #endif
923 }
924 
925 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
SetFace(FaceInfo & faceInfo,uint32_t unicode,TextStyle textStyle)926 void UIFontVector::SetFace(FaceInfo& faceInfo, uint32_t unicode, TextStyle textStyle)
927 {
928     Metric f;
929     f.advance = static_cast<uint16_t>(faceInfo.face->glyph->advance.x / FONT_PIXEL_IN_POINT);
930     f.left = faceInfo.face->glyph->bitmap_left;
931     f.top = faceInfo.face->glyph->bitmap_top;
932     f.cols = faceInfo.face->glyph->bitmap.width;
933     f.rows = faceInfo.face->glyph->bitmap.rows;
934 
935     // cache glyph
936     SaveGlyphNode(unicode, faceInfo.key, &f);
937 
938     int16_t pixSize = 1;
939     if (faceInfo.face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
940         pixSize = 0x04; // 4 Byte
941     }
942     uint32_t bitmapSize = faceInfo.face->glyph->bitmap.width * faceInfo.face->glyph->bitmap.rows * pixSize;
943     // cache bitmap
944     uint8_t* bitmap =
945         UIFontCacheManager::GetInstance()->GetSpace(faceInfo.key, unicode, bitmapSize + sizeof(Metric), textStyle);
946     if (bitmap != nullptr) {
947         if (memcpy_s(bitmap, sizeof(Metric), &f, sizeof(Metric)) != EOK) {
948             UIFontCacheManager::GetInstance()->PutSpace(bitmap);
949             return;
950         }
951         if (memcpy_s(bitmap + sizeof(Metric), bitmapSize, faceInfo.face->glyph->bitmap.buffer, bitmapSize) != EOK) {
952             UIFontCacheManager::GetInstance()->PutSpace(bitmap);
953             return;
954         }
955         ClearFontGlyph(faceInfo.face);
956     }
957 }
958 #endif
959 
ClearFontGlyph(FT_Face face)960 void UIFontVector::ClearFontGlyph(FT_Face face)
961 {
962     if ((face != nullptr) && (face->glyph != nullptr)) {
963         // free unicode buffer immediately to save memory in multi font file load
964         // if not, it will be freed in next glyph load
965         ft_glyphslot_free_bitmap(face->glyph);
966         FT_Outline_Done(face->glyph->library, &face->glyph->outline);
967         if (face->glyph->internal != nullptr) {
968             FT_GlyphLoader_Reset(face->glyph->internal->loader);
969         }
970     }
971 }
972 
GetKey(uint16_t fontId,uint8_t size)973 inline uint16_t UIFontVector::GetKey(uint16_t fontId, uint8_t size)
974 {
975     return ((static_cast<uint16_t>(fontId)) << 8) + size; // fontId store at the (8+1)th bit
976 }
977 
GetOffsetPosY(const char * text,uint16_t lineLength,bool & isEmojiLarge,uint16_t fontId,uint8_t fontSize)978 uint16_t UIFontVector::GetOffsetPosY(const char* text,
979                                      uint16_t lineLength,
980                                      bool& isEmojiLarge,
981                                      uint16_t fontId,
982                                      uint8_t fontSize)
983 {
984     if (!freeTypeInited_) {
985         return INVALID_RET_VALUE;
986     }
987     uint32_t i = 0;
988     uint16_t textNum = 0;
989     uint16_t emojiNum = 0;
990     uint16_t loopNum = 0;
991     GlyphNode glyphNode;
992     GlyphNode emojiMaxNode = {};
993     uint8_t maxFontSize = fontSize;
994     while (i < lineLength) {
995         uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
996         uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
997         if (ret == RET_VALUE_OK) {
998             uint8_t weight = GetFontWeight(glyphNode.fontId);
999             // 16: bit rgb565 rgba8888
1000             if (weight >= 16) {
1001                 emojiMaxNode = glyphNode.rows > emojiMaxNode.rows ? glyphNode : emojiMaxNode;
1002                 emojiNum++;
1003             } else {
1004                 textNum++;
1005             }
1006             loopNum++;
1007         }
1008     }
1009     // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
1010     // The number of words is the same as the number of cycles, which means that this line is all words
1011     if ((emojiNum == loopNum) || (textNum == loopNum)) {
1012         isEmojiLarge = true;
1013         return 0;
1014     }
1015     isEmojiLarge = emojiMaxNode.rows > maxFontSize;
1016     uint16_t offset = 0;
1017     if (isEmojiLarge) {
1018         // If the emoji is higher than the text
1019         if (emojiMaxNode.top >= maxFontSize) {
1020             offset = emojiMaxNode.top - maxFontSize;
1021         }
1022     } else {
1023         // If text are higher than emoji
1024         if (maxFontSize >= emojiMaxNode.rows) {
1025             offset = maxFontSize - emojiMaxNode.rows;
1026         }
1027     }
1028     return offset;
1029 }
1030 
GetLineMaxHeight(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t & letterIndex,SizeSpan * sizeSpans)1031 uint16_t UIFontVector::GetLineMaxHeight(const char* text,
1032                                         uint16_t lineLength,
1033                                         uint16_t fontId,
1034                                         uint8_t fontSize,
1035                                         uint16_t& letterIndex,
1036                                         SizeSpan* sizeSpans)
1037 {
1038     if (!freeTypeInited_) {
1039         return INVALID_RET_VALUE;
1040     }
1041     uint32_t i = 0;
1042     uint16_t textNum = 0;
1043     uint16_t emojiNum = 0;
1044     uint16_t loopNum = 0;
1045     uint16_t maxHeight = GetHeight(fontId, fontSize);
1046     while (i < lineLength) {
1047         uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
1048         TypedText::IsColourWord(unicode, fontId, fontSize) ? emojiNum++ : textNum++;
1049         loopNum++;
1050         if (sizeSpans != nullptr && sizeSpans[letterIndex].isSizeSpan) {
1051             uint16_t spannableHeight = 0;
1052             if (sizeSpans[letterIndex].height == 0) {
1053                 spannableHeight = GetHeight(sizeSpans[letterIndex].fontId, sizeSpans[letterIndex].size);
1054                 sizeSpans[letterIndex].height = spannableHeight;
1055             } else {
1056                 spannableHeight = sizeSpans[letterIndex].height;
1057             }
1058             maxHeight = spannableHeight > maxHeight ? spannableHeight : maxHeight;
1059         }
1060         letterIndex++;
1061         if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
1062             break;
1063         }
1064     }
1065     return GetMaxSubLineHeight(textNum, loopNum, maxHeight, emojiNum);
1066 }
1067 
GetMaxSubLineHeight(uint16_t textNum,uint16_t loopNum,uint16_t maxHeight,uint16_t emojiNum)1068 uint16_t UIFontVector::GetMaxSubLineHeight(uint16_t textNum, uint16_t loopNum, uint16_t maxHeight, uint16_t emojiNum)
1069 {
1070     // The number of words is the same as the number of cycles, which means that this line is all words
1071     if (textNum == loopNum) {
1072         for (uint8_t i = 0; i < currentFontInfoNum_; i++) {
1073             if (!IsEmojiFont(i)) {
1074                 uint16_t height = static_cast<uint16_t>(ftFaces_[i]->size->metrics.height / FONT_PIXEL_IN_POINT);
1075                 if (height > maxHeight) {
1076                     maxHeight = height;
1077                 }
1078                 return maxHeight;
1079             }
1080         }
1081     }
1082     // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
1083     if (emojiNum == loopNum) {
1084         for (uint8_t i = 0; i < currentFontInfoNum_; i++) {
1085             if (IsEmojiFont(i)) {
1086                 return static_cast<uint16_t>(ftFaces_[i]->size->metrics.height / FONT_PIXEL_IN_POINT);
1087             }
1088         }
1089     }
1090     // A line has both emoji and words
1091     if ((textNum > 0) && (emojiNum > 0)) {
1092         for (uint8_t i = 0; i < currentFontInfoNum_; i++) {
1093             uint16_t tmpHeight = static_cast<uint16_t>(ftFaces_[i]->size->metrics.height / FONT_PIXEL_IN_POINT);
1094             maxHeight = tmpHeight > maxHeight ? tmpHeight : maxHeight;
1095         }
1096     }
1097     return maxHeight;
1098 }
1099 
SetPsramMemory(uintptr_t psramAddr,uint32_t psramLen)1100 void UIFontVector::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
1101 {
1102     BaseFont::SetPsramMemory(psramAddr, psramLen);
1103     FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
1104 }
1105 
SetCurrentLangId(uint8_t langId)1106 int8_t UIFontVector::SetCurrentLangId(uint8_t langId)
1107 {
1108     FontRamAllocator::GetInstance().ClearRam();
1109 #if defined(ENABLE_SHAPING) && ENABLE_SHAPING
1110     UITextShaping::GetInstance()->ClearTtfHeader();
1111 #endif
1112     UIFontCacheManager::GetInstance()->ClearCacheFlag();
1113     UIFontCacheManager::GetInstance()->BitmapCacheClear();
1114 
1115     if (UIFontCacheManager::GetInstance()->GlyphsCacheInit() != RET_VALUE_OK) {
1116         GRAPHIC_LOGE("UIFontCacheManager::GlyphsCacheInit init failed");
1117         return INVALID_RET_VALUE;
1118     }
1119 
1120     UIFontCacheManager::GetInstance()->BitmapCacheInit();
1121     return RET_VALUE_OK;
1122 }
1123 } // namespace OHOS
1124