1 /*
2  * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "font/ui_font_bitmap.h"
17 
18 #include "draw/draw_utils.h"
19 #include "font/font_ram_allocator.h"
20 #include "font/ui_font.h"
21 #include "font/ui_font_adaptor.h"
22 #include "font/ui_font_builder.h"
23 #include "gfx_utils/file.h"
24 #include "gfx_utils/graphic_log.h"
25 #include "graphic_config.h"
26 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
27 #include "font/ui_multi_font_manager.h"
28 #endif
29 #if defined(ENABLE_SHAPING) && ENABLE_SHAPING
30 #include "font/ui_text_shaping.h"
31 #endif
32 #include "font/ui_font_cache_manager.h"
33 
34 namespace OHOS {
UIFontBitmap()35 UIFontBitmap::UIFontBitmap() : offset_(0), dynamicFont_() {}
36 
~UIFontBitmap()37 UIFontBitmap::~UIFontBitmap()
38 {
39     CloseFontFd();
40 }
41 
CloseFontFd()42 void UIFontBitmap::CloseFontFd()
43 {
44     for (uint16_t i = 0; i < dynamicFontFd_.Size(); i++) {
45         if (dynamicFontFd_[i] >= 0) {
46             close(dynamicFontFd_[i]);
47             dynamicFontFd_[i] = -1;
48         }
49     }
50 }
51 
IsVectorFont() const52 bool UIFontBitmap::IsVectorFont() const
53 {
54     return false;
55 }
56 
57 uint16_t
GetShapingFontId(char * text,uint8_t & ttfId,uint32_t & script,uint16_t fontId,uint8_t size) const58     UIFontBitmap::GetShapingFontId(char* text, uint8_t& ttfId, uint32_t& script, uint16_t fontId, uint8_t size) const
59 {
60 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
61     return UIMultiFontManager::GetInstance()->GetShapingFontId(text, fontId, ttfId, script);
62 #else
63     UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
64     if (fontParam == nullptr) {
65         return 0;
66     }
67     ttfId = fontParam->ttfId;
68     return fontParam->shaping;
69 #endif
70 }
71 
GetFontWeight(uint16_t fontId)72 uint8_t UIFontBitmap::GetFontWeight(uint16_t fontId)
73 {
74     UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
75     if (fontParam == nullptr) {
76         GRAPHIC_LOGE("UIFontBitmap::GetFontWeigh invalid fontId");
77         return 0;
78     }
79     return fontParam->fontWeight;
80 }
81 
SetFontPath(const char * path,FontType type)82 int8_t UIFontBitmap::SetFontPath(const char* path, FontType type)
83 {
84     if ((path == nullptr) || (type != DYNAMIC_FONT)) {
85         GRAPHIC_LOGE("UIFontBitmap::SetFontPath invalid parameter");
86         return INVALID_RET_VALUE;
87     }
88 #ifdef _WIN32
89     int32_t fontFd = open(path, O_RDONLY | O_BINARY);
90 #else
91     int32_t fontFd = open(path, O_RDONLY);
92 #endif
93     if (fontFd < 0) {
94         GRAPHIC_LOGE("UIFontBitmap::SetFontPath file Open failed");
95         return INVALID_RET_VALUE;
96     }
97 
98     int32_t ret = dynamicFont_.SetFile(path, fontFd, offset_, GlyphCacheType::CACHE_TYPE_DYNAMIC);
99     if (ret == INVALID_RET_VALUE) {
100         GRAPHIC_LOGE("GlyphsManager::SetFile failed");
101         close(fontFd);
102         return ret;
103     }
104     dynamicFontFd_.PushBack(fontFd);
105     return RET_VALUE_OK;
106 }
107 
GetHeight(uint16_t fontId,uint8_t fontSize)108 uint16_t UIFontBitmap::GetHeight(uint16_t fontId, uint8_t fontSize)
109 {
110     return dynamicFont_.GetFontHeight(fontId);
111 }
112 
GetFontId(const char * ttfName,uint8_t size) const113 uint16_t UIFontBitmap::GetFontId(const char* ttfName, uint8_t size) const
114 {
115     UIFontBuilder* fontBuilder = UIFontBuilder::GetInstance();
116     if (ttfName == nullptr) {
117         return fontBuilder->GetBitmapFontIdMax();
118     }
119     uint16_t id;
120     for (id = 0; id < fontBuilder->GetBitmapFontIdMax(); ++id) {
121         UITextLanguageFontParam* fontParam = fontBuilder->GetTextLangFontsTable(id);
122         if (fontParam != nullptr) {
123             if ((fontParam->size == size) && (strncmp(fontParam->ttfName, ttfName, TTF_NAME_LEN_MAX) == 0)) {
124                 break;
125             }
126         }
127     }
128     return id;
129 }
130 
GetWidth(uint32_t unicode,uint16_t fontId,uint8_t fontSize)131 int16_t UIFontBitmap::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize)
132 {
133     return GetWidthInFontId(unicode, fontId);
134 }
135 
GetBitmap(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)136 uint8_t* UIFontBitmap::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
137 {
138     return SearchInFont(unicode, glyphNode, fontId);
139 }
140 
IsEmojiFont(uint16_t fontId)141 bool UIFontBitmap::IsEmojiFont(uint16_t fontId)
142 {
143     return false;
144 }
145 
GetFontHeader(FontHeader & fontHeader,uint16_t fontId,uint8_t fontSize)146 int8_t UIFontBitmap::GetFontHeader(FontHeader& fontHeader, uint16_t fontId, uint8_t fontSize)
147 {
148     const FontHeader* header = dynamicFont_.GetFontHeader(fontId);
149     if (header != nullptr) {
150         fontHeader = *header;
151         return RET_VALUE_OK;
152     }
153     return INVALID_RET_VALUE;
154 }
155 
156 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
GetMultiGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)157 int8_t UIFontBitmap::GetMultiGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
158 {
159     int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
160     if (ret == RET_VALUE_OK) {
161         return ret;
162     }
163 
164     uint16_t* searchLists = nullptr;
165     int8_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
166     int8_t currentIndex = 0;
167     if ((searchLists == nullptr) || (listSize == 0)) {
168         return INVALID_RET_VALUE;
169     }
170     do {
171         ret = GetGlyphNode(unicode, glyphNode, searchLists[currentIndex]);
172         if (ret != INVALID_RET_VALUE) {
173             return ret;
174         }
175         // switch to next search List
176         currentIndex++;
177     } while ((currentIndex < listSize) && (searchLists != nullptr));
178     return INVALID_RET_VALUE;
179 }
180 #endif
181 
GetGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)182 int8_t UIFontBitmap::GetGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
183 {
184     const GlyphNode* node = dynamicFont_.GetGlyphNode(unicode, fontId);
185     if (node != nullptr) {
186         glyphNode = *node;
187         return RET_VALUE_OK;
188     }
189     GRAPHIC_LOGE("UIFontBitmap::GetGlyphNode get glyphNode failed");
190     return INVALID_RET_VALUE;
191 }
192 
GetGlyphNodeFromFile(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)193 int8_t UIFontBitmap::GetGlyphNodeFromFile(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
194 {
195     const GlyphNode* node = dynamicFont_.GetGlyphNodeFromFiles(unicode, fontId);
196     if (node != nullptr) {
197         glyphNode = *node;
198         return RET_VALUE_OK;
199     }
200     return INVALID_RET_VALUE;
201 }
202 
GetFontVersion(FontType type,const char * path,char * version,uint8_t len)203 int8_t UIFontBitmap::GetFontVersion(FontType type, const char* path, char* version, uint8_t len)
204 {
205     if (type != DYNAMIC_FONT) {
206         return INVALID_RET_VALUE;
207     }
208     return dynamicFont_.GetFontVersion(path, version, len);
209 }
210 
SetCurrentLangId(uint8_t langId)211 int8_t UIFontBitmap::SetCurrentLangId(uint8_t langId)
212 {
213     GRAPHIC_LOGE("UIFontBitmap::SetCurrentLangId start");
214     UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
215 
216     if (fontCacheManager->GlyphsCacheInit() != RET_VALUE_OK) {
217         GRAPHIC_LOGE("UIFontCacheManager::GlyphsCacheInit init failed");
218         return INVALID_RET_VALUE;
219     }
220 
221     fontCacheManager->BitmapCacheInit();
222     return RET_VALUE_OK;
223 }
224 
GetFontInfo(uint16_t fontId) const225 UITextLanguageFontParam* UIFontBitmap::GetFontInfo(uint16_t fontId) const
226 {
227     return UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
228 }
229 
GetDynamicFontBitmap(uint32_t unicode,BufferInfo & bufInfo,uint16_t fontId)230 int8_t UIFontBitmap::GetDynamicFontBitmap(uint32_t unicode, BufferInfo& bufInfo, uint16_t fontId)
231 {
232     return dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
233 }
234 
GetCacheBitmap(uint16_t fontId,uint32_t unicode)235 uint8_t* UIFontBitmap::GetCacheBitmap(uint16_t fontId, uint32_t unicode)
236 {
237     TextStyle textStyle = TEXT_STYLE_NORMAL;
238     return UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode, textStyle);
239 }
240 
PutCacheSpace(uint8_t * addr)241 void UIFontBitmap::PutCacheSpace(uint8_t* addr)
242 {
243     UIFontCacheManager::GetInstance()->PutSpace(addr);
244 }
245 
GetDynamicFontWidth(uint32_t unicode,uint16_t fontId)246 int16_t UIFontBitmap::GetDynamicFontWidth(uint32_t unicode, uint16_t fontId)
247 {
248     return dynamicFont_.GetFontWidth(unicode, fontId);
249 }
250 
SearchInFont(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)251 uint8_t* UIFontBitmap::SearchInFont(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
252 {
253     GraphicLockGuard guard(lock_);
254     UIFontCacheManager* fontCacheManager =  UIFontCacheManager::GetInstance();
255     if (fontCacheManager->GetBitmapCache() == nullptr) {
256         return nullptr;
257     }
258     if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
259         GRAPHIC_LOGE("UIFontBitmap::SearchInFont fontId and unicode not match");
260         return nullptr;
261     }
262     int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
263     if (ret != RET_VALUE_OK) {
264         return nullptr;
265     }
266     TextStyle textStyle = TEXT_STYLE_NORMAL;
267     uint8_t* bitmap = fontCacheManager->GetBitmap(fontId, unicode, textStyle);
268     if (bitmap != nullptr) {
269         if (glyphNode.dataFlag == glyphNode.fontId && fontId == glyphNode.fontId) {
270             return bitmap;
271         } else {
272             GRAPHIC_LOGE("DataFlag of bitmap node not equal to fontId.");
273         }
274     }
275     if (glyphNode.kernOff <= glyphNode.dataOff) {
276         return nullptr;
277     }
278     ColorMode mode = UIFont::GetInstance()->GetColorType(fontId);
279     BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(fontId, unicode, mode, glyphNode, false, textStyle);
280     ret = dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
281     if (ret == RET_VALUE_OK) {
282         return reinterpret_cast<uint8_t*>(bufInfo.virAddr);
283     }
284     PutCacheSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
285     return nullptr;
286 }
287 
GetWidthInFontId(uint32_t unicode,uint16_t fontId)288 int16_t UIFontBitmap::GetWidthInFontId(uint32_t unicode, uint16_t fontId)
289 {
290     if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
291         GRAPHIC_LOGE("UIFontBitmap::GetWidthInFontId fontId and unicode not match");
292         return INVALID_RET_VALUE;
293     }
294     return GetDynamicFontWidth(unicode, fontId);
295 }
296 
SetFontFileOffset(uint32_t offset)297 void UIFontBitmap::SetFontFileOffset(uint32_t offset)
298 {
299     offset_ = offset;
300 }
301 
GetOffsetPosY(const char * text,uint16_t lineLength,bool & isEmoijLarge,uint16_t fontId,uint8_t fontSize)302 uint16_t UIFontBitmap::GetOffsetPosY(const char* text,
303                                      uint16_t lineLength,
304                                      bool& isEmoijLarge,
305                                      uint16_t fontId,
306                                      uint8_t fontSize)
307 {
308     uint32_t i = 0;
309     uint16_t textNum = 0;
310     uint16_t emojiNum = 0;
311 
312     uint16_t loopNum = 0;
313     GlyphNode glyphNode;
314     GlyphNode emoijMaxNode = {};
315     uint8_t maxFontSie = fontSize;
316     while (i < lineLength) {
317         uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
318 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
319         uint8_t ret = GetMultiGlyphNode(unicode, glyphNode, fontId);
320 #else
321         uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
322 #endif
323         if (ret == RET_VALUE_OK) {
324             uint8_t weight = GetFontWeight(glyphNode.fontId);
325             if (weight >= 16) { // 16: bit rgb565 rgba8888
326                 emoijMaxNode = glyphNode.rows > emoijMaxNode.rows ? glyphNode : emoijMaxNode;
327                 emojiNum++;
328             } else {
329                 textNum++;
330             }
331             loopNum++;
332         }
333     }
334     // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
335     // The number of words is the same as the number of cycles, which means that this line is all words
336     if ((emojiNum == loopNum) || (textNum == loopNum)) {
337         isEmoijLarge = true;
338         return 0;
339     }
340     isEmoijLarge = emoijMaxNode.rows > maxFontSie;
341     uint16_t offset = 0;
342     if (isEmoijLarge) {
343         // If the emoji is higher than the text
344         if (emoijMaxNode.top >= maxFontSie) {
345             offset = emoijMaxNode.top - maxFontSie;
346         }
347     } else {
348         // If text are higher than emoji
349         if (maxFontSie >= emoijMaxNode.rows) {
350             // should top - ros.
351             offset = maxFontSie - emoijMaxNode.rows;
352         }
353     }
354     return offset;
355 }
356 
GetLineMaxHeight(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t & letterIndex,SpannableString * spannableString)357 uint16_t UIFontBitmap::GetLineMaxHeight(const char* text,
358                                         uint16_t lineLength,
359                                         uint16_t fontId,
360                                         uint8_t fontSize,
361                                         uint16_t& letterIndex,
362                                         SpannableString* spannableString)
363 {
364     uint16_t maxHeight = GetHeight(fontId, fontSize);
365     if (spannableString == nullptr) {
366         return maxHeight;
367     }
368 
369     uint32_t i = 0;
370     while (i < lineLength) {
371         TypedText::GetUTF8Next(text, i, i);
372         if (spannableString != nullptr && spannableString->GetSpannable(letterIndex)) {
373             int16_t spannableHeight = 0;
374             spannableString->GetFontHeight(letterIndex, spannableHeight, fontId, fontSize);
375             uint16_t tempHeight = static_cast<uint16_t>(spannableHeight);
376             maxHeight = tempHeight > maxHeight ? tempHeight : maxHeight;
377         }
378         letterIndex++;
379         if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
380             break;
381         }
382     }
383 
384     return maxHeight;
385 }
386 
SetPsramMemory(uintptr_t psramAddr,uint32_t psramLen)387 void UIFontBitmap::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
388 {
389     BaseFont::SetPsramMemory(psramAddr, psramLen);
390     FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
391 }
392 } // namespace OHOS
393