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 "common/typed_text.h"
17 #include "font/ui_font.h"
18 #include "font/ui_font_adaptor.h"
19 #include "gfx_utils/graphic_log.h"
20 #include "gfx_utils/mem_api.h"
21 #include "gfx_utils/transform.h"
22 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
23 #include "font/ui_multi_font_manager.h"
24 #endif
25 
26 namespace OHOS {
27 #ifndef _FONT_TOOL
GetTextSize(const char * text,uint16_t fontId,uint8_t fontSize,int16_t letterSpace,int16_t lineHeight,int16_t maxWidth,int8_t lineSpace,SpannableString * spannableString,bool eliminateTrailingSpaces)28 Point TypedText::GetTextSize(const char* text, uint16_t fontId, uint8_t fontSize, int16_t letterSpace,
29                              int16_t lineHeight, int16_t maxWidth, int8_t lineSpace, SpannableString* spannableString,
30                              bool eliminateTrailingSpaces)
31 {
32     Point size{0, 0};
33 
34     if (text == nullptr) {
35         return size;
36     }
37 
38     uint32_t lineBegin = 0;
39     uint32_t newLineBegin = 0;
40     uint16_t letterHeight = UIFont::GetInstance()->GetHeight(fontId, fontSize);
41     bool hasLineHeight = (lineHeight != 0);
42     uint16_t curLineHeight;
43     uint16_t letterIndex = 0;
44     int16_t curLetterHeight = 0;
45     while (text[lineBegin] != '\0') {
46         int16_t lineWidth = maxWidth;
47         newLineBegin += UIFontAdaptor::GetNextLineAndWidth(&text[lineBegin], fontId, fontSize, letterSpace, lineWidth,
48                                                            curLetterHeight, letterIndex, spannableString, false,
49                                                            0xFFFF, eliminateTrailingSpaces);
50         if (!hasLineHeight) {
51             curLineHeight = curLetterHeight + lineSpace;
52         } else {
53             curLineHeight = lineHeight;
54         }
55 
56         if (newLineBegin == lineBegin) {
57             break;
58         }
59         size.y += curLineHeight;
60         size.x = MATH_MAX(lineWidth, size.x);
61         lineBegin = newLineBegin;
62     }
63 
64     if ((lineBegin != 0) && ((text[lineBegin - 1] == '\n') || (text[lineBegin - 1] == '\r'))) {
65         if (!hasLineHeight) {
66             size.y += letterHeight + lineSpace;
67         } else {
68             size.y += lineHeight;
69         }
70     }
71 
72     if (!hasLineHeight) {
73         size.y = (size.y == 0) ? letterHeight : (size.y - lineSpace);
74     } else {
75         if (size.y == 0) {
76             size.y = lineHeight;
77         }
78     }
79     return size;
80 }
81 
GetArcTextRect(const char * text,uint16_t fontId,uint8_t fontSize,const Point & arcCenter,int16_t letterSpace,TextOrientation orientation,const ArcTextInfo & arcTextInfo)82 Rect TypedText::GetArcTextRect(const char* text,
83                                uint16_t fontId,
84                                uint8_t fontSize,
85                                const Point& arcCenter,
86                                int16_t letterSpace,
87                                TextOrientation orientation,
88                                const ArcTextInfo& arcTextInfo)
89 {
90     if ((text == nullptr) || (arcTextInfo.lineStart == arcTextInfo.lineEnd) || (arcTextInfo.radius == 0)) {
91         GRAPHIC_LOGE("TypedText::GetArcTextRect invalid parameter\n");
92         return Rect();
93     }
94 
95     uint16_t letterHeight = UIFont::GetInstance()->GetHeight(fontId, fontSize);
96     bool xorFlag = (orientation == TextOrientation::INSIDE) ^ (arcTextInfo.direct == TEXT_DIRECT_LTR);
97     float posX = 0;
98     float posY = 0;
99     uint32_t i = arcTextInfo.lineStart;
100     float angle = arcTextInfo.startAngle;
101     Rect rect;
102     Rect rectLetter;
103     TransformMap transform;
104     while (i < arcTextInfo.lineEnd) {
105         uint32_t tmp = i;
106         uint32_t letter = GetUTF8Next(text, tmp, i);
107         if (letter == 0) {
108             continue;
109         }
110         if ((letter == '\r') || (letter == '\n')) {
111             break;
112         }
113         uint16_t letterWidth = UIFont::GetInstance()->GetWidth(letter, fontId, fontSize, 0);
114         if (tmp == arcTextInfo.lineStart) {
115             angle += xorFlag ? GetAngleForArcLen(static_cast<float>(letterWidth), letterHeight, arcTextInfo.radius,
116                                                  arcTextInfo.direct, orientation) : 0;
117             GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
118             rect.SetPosition(MATH_ROUND(posX), MATH_ROUND(posY));
119         }
120         rectLetter.SetPosition(MATH_ROUND(posX), MATH_ROUND(posY));
121         rectLetter.Resize(letterWidth, letterHeight);
122         transform.SetTransMapRect(rectLetter);
123 
124         uint16_t arcLen = letterWidth + letterSpace;
125         if (arcLen == 0) {
126             continue;
127         }
128         float incrementAngle = GetAngleForArcLen(static_cast<float>(arcLen), letterHeight, arcTextInfo.radius,
129                                                  arcTextInfo.direct, orientation);
130         float rotateAngle =
131             (orientation == TextOrientation::INSIDE) ? angle : (angle - SEMICIRCLE_IN_DEGREE);
132         // 2: letterWidth's half
133         float fineTuningAngle = incrementAngle * (static_cast<float>(letterWidth) / (2 * arcLen));
134         rotateAngle += (xorFlag ? -fineTuningAngle : fineTuningAngle);
135 
136         transform.Rotate(MATH_ROUND(rotateAngle), Vector2<float>(0, 0));
137         rect.Join(rect, transform.GetBoxRect());
138 
139         angle += incrementAngle;
140         GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
141     }
142     return rect;
143 }
144 
GetAngleForArcLen(float len,uint16_t height,uint16_t radius,UITextLanguageDirect direct,TextOrientation orientation)145 float TypedText::GetAngleForArcLen(float len,
146                                    uint16_t height,
147                                    uint16_t radius,
148                                    UITextLanguageDirect direct,
149                                    TextOrientation orientation)
150 {
151     if (radius == 0) {
152         return 0;
153     }
154     float realRadius =
155         static_cast<float>((orientation == TextOrientation::OUTSIDE) ? (radius + height) : radius);
156     float angle = static_cast<float>(len * SEMICIRCLE_IN_DEGREE) / (UI_PI * realRadius);
157     return (direct == TEXT_DIRECT_LTR) ? angle : -angle;
158 }
159 
GetAngleForArcLen(uint16_t letterWidth,int16_t letterSpace,uint16_t radius)160 float TypedText::GetAngleForArcLen(uint16_t letterWidth, int16_t letterSpace, uint16_t radius)
161 {
162     if (radius == 0) {
163         return 0.0f;
164     }
165     const float FLOATING_POINT_TWO = 2.0f;
166     float angle = (letterWidth + letterSpace) / (FLOATING_POINT_TWO * radius * UI_PI) * CIRCLE_IN_DEGREE;
167     return angle;
168 }
169 
GetArcLetterPos(const Point & arcCenter,uint16_t radius,float angle,float & posX,float & posY)170 void TypedText::GetArcLetterPos(const Point& arcCenter, uint16_t radius, float angle, float& posX, float& posY)
171 {
172     posX = arcCenter.x + (static_cast<float>(radius) * Sin(angle));
173     posY = arcCenter.y - (static_cast<float>(radius) * Sin(angle + QUARTER_IN_DEGREE));
174 }
175 
GetNextLine(const char * text,uint16_t fontId,uint8_t fontSize,int16_t letterSpace,int16_t maxWidth)176 uint32_t TypedText::GetNextLine(const char* text, uint16_t fontId, uint8_t fontSize, int16_t letterSpace,
177                                 int16_t maxWidth)
178 {
179     uint32_t index = 0;
180     if ((text == nullptr) || (GetWrapPoint(text, index) &&
181         (TypedText::GetTextWidth(text, fontId, fontSize, index, letterSpace) <= maxWidth))) {
182         return index;
183     }
184     uint32_t lastBreakPos = 0;
185     uint32_t tmp = 0;
186     while (true) {
187         int16_t curW = TypedText::GetTextWidth(text, fontId, fontSize, index, letterSpace);
188         if (curW > maxWidth) {
189             index = lastBreakPos;
190             if (lastBreakPos == 0) {
191                 curW = 0;
192                 uint32_t i = 0;
193                 while (text[i] != '\0') {
194                     tmp = i;
195                     uint32_t letter = TypedText::GetUTF8Next(text, tmp, i);
196                     uint16_t letterWidth = UIFont::GetInstance()->GetWidth(letter, fontId, fontSize, 0);
197                     curW += letterWidth;
198                     if (letterWidth > 0) {
199                         curW += letterSpace;
200                     }
201                     if (curW > maxWidth) {
202                         index = lastBreakPos;
203                         return index;
204                     }
205                     lastBreakPos = i;
206                 }
207             }
208             break;
209         }
210         if ((index > 0) && (index < strlen(text)) && ((text[index - 1] == '\r') || (text[index - 1] == '\n'))) {
211             break;
212         }
213         lastBreakPos = index;
214         if (text[index] == '\0') {
215             break;
216         }
217         if (GetWrapPoint(text + index, tmp) &&
218             (TypedText::GetTextWidth(text, fontId, fontSize, index + tmp, letterSpace) <= maxWidth)) {
219             return index + tmp;
220         }
221         index += tmp;
222         if (lastBreakPos == index) {
223             break;
224         }
225     }
226     return index;
227 }
228 
GetWrapPoint(const char * text,uint32_t & breakPoint)229 bool TypedText::GetWrapPoint(const char* text, uint32_t& breakPoint)
230 {
231     breakPoint = 0;
232     uint32_t j = 0;
233     if (text == nullptr) {
234         return true;
235     }
236 
237     while (text[breakPoint] != '\0') {
238         uint32_t letter = GetUTF8Next(text, breakPoint, j);
239         breakPoint = j;
240         if ((letter == ' ') || (letter == '.') || (letter == ',') || (letter == '!') || (letter == '=')
241             || (letter == '?')) {
242             return false;
243         }
244         if (letter == '\n') {
245             return true;
246         }
247         if ((letter == '\r') && (GetUTF8Next(text, breakPoint, j) == '\n')) {
248             breakPoint = j;
249             return true;
250         }
251     }
252     return false;
253 }
254 
GetTextWidth(const char * text,uint16_t fontId,uint8_t fontSize,uint16_t length,int16_t letterSpace,uint16_t beginUTF8Index,uint16_t count)255 int16_t TypedText::GetTextWidth(const char* text,
256                                 uint16_t fontId,
257                                 uint8_t fontSize,
258                                 uint16_t length,
259                                 int16_t letterSpace,
260                                 uint16_t beginUTF8Index,
261                                 uint16_t count)
262 {
263     if ((text == nullptr) || (length == 0) || (length > strlen(text))) {
264         GRAPHIC_LOGE("TypedText::GetTextWidth invalid parameter\n");
265         return 0;
266     }
267 
268     uint32_t byteIndex = GetByteIndexFromUTF8Id(text, beginUTF8Index);
269     uint16_t width = 0;
270 
271     while (byteIndex < length) {
272         uint32_t letter = GetUTF8Next(text, byteIndex, byteIndex);
273         if ((letter == 0) || (letter == '\n') || (letter == '\r')) {
274             continue;
275         }
276         uint16_t charWidth = UIFont::GetInstance()->GetWidth(letter, fontId, fontSize, 0);
277         width += charWidth + letterSpace;
278         count--;
279         if (count == 0) {
280             break;
281         }
282     }
283     if (width > 0) {
284         width -= letterSpace;
285     }
286     return width;
287 }
288 #endif // _FONT_TOOL
289 
GetUTF8OneCharacterSize(const char * str)290 uint8_t TypedText::GetUTF8OneCharacterSize(const char* str)
291 {
292     if (str == nullptr) {
293         return 0;
294     }
295     if ((str[0] & 0x80) == 0) {
296         return 1;
297     } else if ((str[0] & 0xE0) == 0xC0) {
298         return 2; // 2: 2 bytes
299     } else if ((str[0] & 0xF0) == 0xE0) {
300         return 3; // 3: 3 bytes
301     } else if ((str[0] & 0xF8) == 0xF0) {
302         return 4; // 4: 4 bytes
303     }
304     return 0;
305 }
306 
GetUTF8Next(const char * text,uint32_t i,uint32_t & j)307 uint32_t TypedText::GetUTF8Next(const char* text, uint32_t i, uint32_t& j)
308 {
309     uint32_t unicode = 0;
310     if (text == nullptr) {
311         return 0;
312     }
313 
314     j = i;
315     uint8_t lettetSize = GetUTF8OneCharacterSize(text + i);
316     switch (lettetSize) {
317         case 1:
318             unicode = text[j];
319             break;
320         case 2: // 2: letter size
321             unicode = static_cast<uint32_t>(text[j] & 0x1F) << UTF8_TO_UNICODE_SHIFT1;
322             j++;
323             if ((text[j] & 0xC0) != 0x80) {
324                 return 0;
325             }
326             unicode += (text[j] & 0x3F);
327             break;
328         case 3: // 3: letter size
329             unicode = static_cast<uint32_t>(text[j] & 0x0F) << UTF8_TO_UNICODE_SHIFT2;
330             unicode += static_cast<uint32_t>(text[++j] & 0x3F) << UTF8_TO_UNICODE_SHIFT1;
331             unicode += (text[++j] & 0x3F);
332             break;
333         case 4: // 4: letter size
334             unicode = static_cast<uint32_t>(text[j] & 0x07) << UTF8_TO_UNICODE_SHIFT3;
335             unicode += static_cast<uint32_t>(text[++j] & 0x3F) << UTF8_TO_UNICODE_SHIFT2;
336             unicode += static_cast<uint32_t>(text[++j] & 0x3F) << UTF8_TO_UNICODE_SHIFT1;
337             unicode += text[++j] & 0x3F;
338             break;
339         default:
340             break;
341     }
342     j++;
343     return unicode;
344 }
345 
GetByteIndexFromUTF8Id(const char * text,uint32_t utf8Id)346 uint32_t TypedText::GetByteIndexFromUTF8Id(const char* text, uint32_t utf8Id)
347 {
348     if (text == nullptr) {
349         GRAPHIC_LOGE("TypedText::GetByteIndexFromUTF8Id text invalid parameter\n");
350         return 0;
351     }
352     uint32_t byteIndex = 0;
353     for (uint32_t i = 0; i < utf8Id; i++) {
354         byteIndex += GetUTF8OneCharacterSize(&text[byteIndex]);
355     }
356 
357     return byteIndex;
358 }
359 
GetUTF8CharacterSize(const char * text,uint32_t byteIndex)360 uint32_t TypedText::GetUTF8CharacterSize(const char* text, uint32_t byteIndex)
361 {
362     uint32_t i = 0;
363     uint32_t size = 0;
364 
365     if (text == nullptr) {
366         GRAPHIC_LOGE("TypedText::GetUTF8CharacterSize text invalid parameter\n");
367         return 0;
368     }
369     while ((i < byteIndex) && (text[i] != '\0')) {
370         GetUTF8Next(text, i, i);
371         size++;
372     }
373 
374     return size;
375 }
376 
Utf8ToUtf16(const char * utf8Str,uint16_t * utf16Str,uint32_t len)377 void TypedText::Utf8ToUtf16(const char* utf8Str, uint16_t* utf16Str, uint32_t len)
378 {
379     if ((utf8Str == nullptr) || (utf16Str == nullptr)) {
380         GRAPHIC_LOGE("utf8Str or u16Str is null");
381         return;
382     }
383 
384     uint32_t i = 0;
385     uint32_t cnt = 0;
386     while (utf8Str[i] != '\0') {
387         uint32_t unicode = GetUTF8Next(utf8Str, i, i);
388         if (cnt < len) {
389             if (unicode <= MAX_UINT16_LOW_SCOPE) {
390                 utf16Str[cnt] = (unicode & MAX_UINT16_LOW_SCOPE);
391             } else if (unicode <= MAX_UINT16_HIGH_SCOPE) {
392                 if (cnt + 1 < len) {
393                     utf16Str[cnt] = static_cast<uint16_t>(UTF16_LOW_PARAM + (unicode & UTF16_LOW_MASK)); // low
394                     cnt++;
395                     utf16Str[cnt] = static_cast<uint16_t>(UTF16_HIGH_PARAM1 + (unicode >> UTF16_HIGH_SHIFT) -
396                                                           UTF16_HIGH_PARAM2); // high
397                 }
398             } else {
399                 GRAPHIC_LOGE("Invalid unicode");
400                 return;
401             }
402             cnt++;
403         }
404     }
405 }
406 
Utf16ToUtf32Word(const uint16_t * src,uint32_t & des)407 int32_t TypedText::Utf16ToUtf32Word(const uint16_t* src, uint32_t& des)
408 {
409     if (!src) {
410         return -1; // invalid
411     }
412 
413     uint16_t w1 = src[0];
414     uint16_t flag = w1 & UTF16_MASK;
415     if (flag == UTF16_LOW_PARAM) {
416         uint16_t w2 = src[1];
417         flag = w2 & UTF16_MASK;
418         if (flag == UTF16_HIGH_PARAM1) {
419             des = (w1 & UTF16_LOW_MASK) + (((w2 & UTF16_LOW_MASK) + UTF16_HIGH_PARAM2) << UTF16_HIGH_SHIFT);
420             return 2; // 2 : used length
421         }
422         return -1;
423     } else if (flag == UTF16_HIGH_PARAM1) {
424         uint16_t w2 = src[1];
425         flag = w2 & UTF16_MASK;
426         if (flag == UTF16_LOW_PARAM) {
427             des = (w2 & UTF16_LOW_MASK) + (((w1 & UTF16_LOW_MASK) + UTF16_HIGH_PARAM2) << UTF16_HIGH_SHIFT);
428             return 2; // 2 : used length
429         }
430         return -1;
431     } else {
432         des = w1;
433         return 1;
434     }
435 }
436 
Utf16ToUtf32(const uint16_t * utf16Str,uint32_t * utf32Str,uint32_t len)437 uint16_t TypedText::Utf16ToUtf32(const uint16_t* utf16Str, uint32_t* utf32Str, uint32_t len)
438 {
439     if (!utf16Str || (!utf32Str)) {
440         return 0;
441     }
442 
443     uint16_t utf32Len = 0;
444     while (len > 0) {
445         uint32_t tmp;
446         int32_t length = Utf16ToUtf32Word(utf16Str, tmp);
447         if (length == -1) {
448             utf32Str = nullptr;
449             return 0;
450         }
451         len -= length;
452         if (utf32Str) {
453             (*utf32Str) = tmp;
454             ++utf32Str;
455             ++utf32Len;
456         }
457         utf16Str += length;
458     }
459     return utf32Len;
460 }
461 
GetUtf16Cnt(const char * utf8Str,uint32_t maxLength)462 uint32_t TypedText::GetUtf16Cnt(const char* utf8Str, uint32_t maxLength)
463 {
464     if (utf8Str == nullptr) {
465         return 0;
466     }
467     uint32_t len = 0;
468     uint32_t i = 0;
469 
470     while (utf8Str[i] != '\0' && i < maxLength) {
471         uint32_t unicode = GetUTF8Next(utf8Str, i, i);
472         if (unicode <= MAX_UINT16_LOW_SCOPE) {
473             len++;
474         } else if (unicode <= MAX_UINT16_HIGH_SCOPE) {
475             len += 2; // 2: low and high, two uint16_t numbers
476         } else {
477             GRAPHIC_LOGE("Invalid unicode");
478             return 0;
479         }
480     }
481     return len;
482 }
483 
IsEmoji(uint32_t codePoint)484 bool TypedText::IsEmoji(uint32_t codePoint)
485 {
486     // Miscellaneous symbols and symbol fonts
487     return (codePoint >= 0x2600 && codePoint <= 0x27BF) || codePoint == 0x303D || codePoint == 0x2049 ||
488             codePoint == 0x203C || (codePoint >= 0x2000 && codePoint <= 0x200F) ||
489             (codePoint >= 0x2028 && codePoint <= 0x202F) || codePoint == 0x205F ||
490             // Area occupied by punctuation, Alphabetic symbol
491             (codePoint >= 0x2065 && codePoint <= 0x206F) || (codePoint >= 0x2100 && codePoint <= 0x214F) ||
492             // Various technical symbols, Arrow A
493             (codePoint >= 0x2300 && codePoint <= 0x23FF) || (codePoint >= 0x2B00 && codePoint <= 0x2BFF) ||
494             // Arrow B,Chinese symbols
495             (codePoint >= 0x2900 && codePoint <= 0x297F) || (codePoint >= 0x3200 && codePoint <= 0x32FF) ||
496             // High and low substitution reserved area, Private reserved area
497             (codePoint >= 0xD800 && codePoint <= 0xDFFF) || (codePoint >= 0xE000 && codePoint <= 0xF8FF) ||
498             // Mutation selector, Plane above the second plane,char can't be saved, all can be transferred
499             (codePoint >= 0xFE00 && codePoint <= 0xFE0F) || codePoint >= 0x10000;
500 }
501 
IsEmojiModifier(uint32_t codePoint)502 bool TypedText::IsEmojiModifier(uint32_t codePoint)
503 {
504     return (codePoint >= 0x1F3FB && codePoint <= 0x1F3FF);
505 }
506 
507 // Based on Emoji_Modifier_Base from
IsEmojiBase(uint32_t codePoint)508 bool TypedText::IsEmojiBase(uint32_t codePoint)
509 {
510     if (codePoint >= 0x261D && codePoint <= 0x270D) {
511         return (codePoint == 0x261D || codePoint == 0x26F9 || (codePoint >= 0x270A && codePoint <= 0x270D));
512     } else if (codePoint >= 0x1F385 && codePoint <= 0x1F93E) {
513         return (codePoint == 0x1F385 || (codePoint >= 0x1F3C3 && codePoint <= 0x1F3C4) ||
514                 (codePoint >= 0x1F3CA && codePoint <= 0x1F3CB) || (codePoint >= 0x1F442 && codePoint <= 0x1F443) ||
515                 (codePoint >= 0x1F446 && codePoint <= 0x1F450) || (codePoint >= 0x1F466 && codePoint <= 0x1F469) ||
516                 codePoint == 0x1F46E || (codePoint >= 0x1F470 && codePoint <= 0x1F478) || codePoint == 0x1F47C ||
517                 (codePoint >= 0x1F481 && codePoint <= 0x1F483) || (codePoint >= 0x1F485 && codePoint <= 0x1F487) ||
518                 codePoint == 0x1F4AA || codePoint == 0x1F575 || codePoint == 0x1F57A || codePoint == 0x1F590 ||
519                 (codePoint >= 0x1F595 && codePoint <= 0x1F596) || (codePoint >= 0x1F645 && codePoint <= 0x1F647) ||
520                 (codePoint >= 0x1F64B && codePoint <= 0x1F64F) || codePoint == 0x1F6A3 ||
521                 (codePoint >= 0x1F6B4 && codePoint <= 0x1F6B6) || codePoint == 0x1F6C0 ||
522                 (codePoint >= 0x1F918 && codePoint <= 0x1F91E) || codePoint == 0x1F926 || codePoint == 0x1F930 ||
523                 (codePoint >= 0x1F933 && codePoint <= 0x1F939) || (codePoint >= 0x1F93B && codePoint <= 0x1F93E));
524     } else {
525         return false;
526     }
527 }
528 
IsColourWord(uint32_t codePoint,uint16_t fontId,uint8_t fontSize)529 bool TypedText::IsColourWord(uint32_t codePoint, uint16_t fontId, uint8_t fontSize)
530 {
531     bool hasColor = false;
532     UIFont* font = UIFont::GetInstance();
533     uint8_t weight = font->GetFontWeight(fontId);
534     if (weight >= 16) { // 16: rgb565->16 rgba8888->32 font with rgba
535         hasColor = true;
536     } else {
537 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
538         uint16_t* searchLists = nullptr;
539         int8_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
540         if ((listSize > 0) && (searchLists != nullptr)) {
541             int8_t currentIndex = 0;
542             do {
543                 weight = font->GetFontWeight(searchLists[currentIndex]);
544                 if (weight >= 16) { // 16: rgb565->16 rgba8888->32 font with rgba
545                     hasColor = true;
546                     break;
547                 }
548                 currentIndex++;
549             } while ((currentIndex < listSize) && (searchLists != nullptr));
550         }
551 #endif
552     }
553     if (!hasColor) {
554         return false;
555     }
556     GlyphNode glyphNode;
557     int8_t ret = font->GetGlyphNode(codePoint, glyphNode, fontId, fontSize);
558     if (ret != RET_VALUE_OK) {
559         GRAPHIC_LOGE("Failed to get glyphNode for color word");
560         return false;
561     }
562 
563     weight = font->GetFontWeight(glyphNode.fontId);
564     return (weight >= 16); // 16: rgb565->16 rgba8888->32 font with rgba
565 }
566 } // namespace OHOS
567