• 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_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     UIFontCacheManager::GetInstance()->BitmapCacheInit();
214     return RET_VALUE_OK;
215 }
216 
GetFontInfo(uint16_t fontId) const217 UITextLanguageFontParam* UIFontBitmap::GetFontInfo(uint16_t fontId) const
218 {
219     return UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
220 }
221 
GetDynamicFontBitmap(uint32_t unicode,BufferInfo & bufInfo,uint16_t fontId)222 int8_t UIFontBitmap::GetDynamicFontBitmap(uint32_t unicode, BufferInfo& bufInfo, uint16_t fontId)
223 {
224     return dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
225 }
226 
GetCacheBitmap(uint16_t fontId,uint32_t unicode)227 uint8_t* UIFontBitmap::GetCacheBitmap(uint16_t fontId, uint32_t unicode)
228 {
229     return UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode);
230 }
231 
PutCacheSpace(uint8_t * addr)232 void UIFontBitmap::PutCacheSpace(uint8_t* addr)
233 {
234     UIFontCacheManager::GetInstance()->PutSpace(addr);
235 }
236 
GetDynamicFontWidth(uint32_t unicode,uint16_t fontId)237 int16_t UIFontBitmap::GetDynamicFontWidth(uint32_t unicode, uint16_t fontId)
238 {
239     return dynamicFont_.GetFontWidth(unicode, fontId);
240 }
241 
SearchInFont(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)242 uint8_t* UIFontBitmap::SearchInFont(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
243 {
244     GraphicLockGuard guard(lock_);
245     UIFontCacheManager* fontCacheManager =  UIFontCacheManager::GetInstance();
246     if (fontCacheManager->GetBitmapCache() == nullptr) {
247         return nullptr;
248     }
249     if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
250         GRAPHIC_LOGE("UIFontBitmap::SearchInFont fontId and unicode not match");
251         return nullptr;
252     }
253     int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
254     if (ret != RET_VALUE_OK) {
255         return nullptr;
256     }
257     uint8_t* bitmap = fontCacheManager->GetBitmap(fontId, unicode);
258     if (bitmap != nullptr) {
259         if (glyphNode.dataFlag == glyphNode.fontId && fontId == glyphNode.fontId) {
260             return bitmap;
261         } else {
262             GRAPHIC_LOGE("DataFlag of bitmap node not equal to fontId.");
263         }
264     }
265     if (glyphNode.kernOff <= glyphNode.dataOff) {
266         return nullptr;
267     }
268     ColorMode mode = UIFont::GetInstance()->GetColorType(fontId);
269     BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(fontId, unicode, mode, glyphNode, false);
270     ret = dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
271     if (ret == RET_VALUE_OK) {
272         return reinterpret_cast<uint8_t*>(bufInfo.virAddr);
273     }
274     PutCacheSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
275     return nullptr;
276 }
277 
GetWidthInFontId(uint32_t unicode,uint16_t fontId)278 int16_t UIFontBitmap::GetWidthInFontId(uint32_t unicode, uint16_t fontId)
279 {
280     if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
281         GRAPHIC_LOGE("UIFontBitmap::GetWidthInFontId fontId and unicode not match");
282         return INVALID_RET_VALUE;
283     }
284     return GetDynamicFontWidth(unicode, fontId);
285 }
286 
SetFontFileOffset(uint32_t offset)287 void UIFontBitmap::SetFontFileOffset(uint32_t offset)
288 {
289     offset_ = offset;
290 }
291 
GetOffsetPosY(const char * text,uint16_t lineLength,bool & isEmoijLarge,uint16_t fontId,uint8_t fontSize)292 uint16_t UIFontBitmap::GetOffsetPosY(const char* text,
293                                      uint16_t lineLength,
294                                      bool& isEmoijLarge,
295                                      uint16_t fontId,
296                                      uint8_t fontSize)
297 {
298     uint32_t i = 0;
299     uint16_t textNum = 0;
300     uint16_t emojiNum = 0;
301 
302     uint16_t loopNum = 0;
303     GlyphNode glyphNode;
304     GlyphNode emoijMaxNode = {};
305     uint8_t maxFontSie = fontSize;
306     while (i < lineLength) {
307         uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
308 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
309         uint8_t ret = GetMultiGlyphNode(unicode, glyphNode, fontId);
310 #else
311         uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
312 #endif
313         if (ret == RET_VALUE_OK) {
314             uint8_t weight = GetFontWeight(glyphNode.fontId);
315             if (weight >= 16) { // 16: bit rgb565 rgba8888
316                 emoijMaxNode = glyphNode.rows > emoijMaxNode.rows ? glyphNode : emoijMaxNode;
317                 emojiNum++;
318             } else {
319                 textNum++;
320             }
321             loopNum++;
322         }
323     }
324     // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
325     // The number of words is the same as the number of cycles, which means that this line is all words
326     if ((emojiNum == loopNum) || (textNum == loopNum)) {
327         isEmoijLarge = true;
328         return 0;
329     }
330     isEmoijLarge = emoijMaxNode.rows > maxFontSie;
331     uint16_t offset = 0;
332     if (isEmoijLarge) {
333         // If the emoji is higher than the text
334         if (emoijMaxNode.top >= maxFontSie) {
335             offset = emoijMaxNode.top - maxFontSie;
336         }
337     } else {
338         // If text are higher than emoji
339         if (maxFontSie >= emoijMaxNode.rows) {
340             // should top - ros.
341             offset = maxFontSie - emoijMaxNode.rows;
342         }
343     }
344     return offset;
345 }
346 
GetLineMaxHeight(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t & letterIndex,SizeSpan * sizeSpans)347 uint16_t UIFontBitmap::GetLineMaxHeight(const char* text,
348                                         uint16_t lineLength,
349                                         uint16_t fontId,
350                                         uint8_t fontSize,
351                                         uint16_t& letterIndex,
352                                         SizeSpan* sizeSpans)
353 {
354     uint16_t maxHeight = GetHeight(fontId, fontSize);
355     if (sizeSpans == nullptr) {
356         return maxHeight;
357     }
358 
359     uint32_t i = 0;
360     while (i < lineLength) {
361         TypedText::GetUTF8Next(text, i, i);
362         if (sizeSpans != nullptr && sizeSpans[letterIndex].isSizeSpan) {
363             uint16_t spannableHeight = 0;
364             if (sizeSpans[letterIndex].height == 0) {
365                 spannableHeight = GetHeight(sizeSpans[letterIndex].fontId, sizeSpans[letterIndex].size);
366                 sizeSpans[letterIndex].height = spannableHeight;
367             } else {
368                 spannableHeight = sizeSpans[letterIndex].height;
369             }
370             maxHeight = spannableHeight > maxHeight ? spannableHeight : maxHeight;
371         }
372 
373         letterIndex++;
374         if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
375             break;
376         }
377     }
378 
379     return maxHeight;
380 }
381 
SetPsramMemory(uintptr_t psramAddr,uint32_t psramLen)382 void UIFontBitmap::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
383 {
384     BaseFont::SetPsramMemory(psramAddr, psramLen);
385     FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
386 }
387 } // namespace OHOS
388