• 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 
GetShapingFontId(char * text,uint8_t & ttfId,uint32_t & script,uint16_t fontId,uint8_t size) const57 uint16_t UIFontBitmap::GetShapingFontId(char* text, uint8_t& ttfId, uint32_t& script,
58                                        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     if (ttfName == nullptr) {
116         return UIFontBuilder::GetInstance()->GetBitmapFontIdMax();
117     }
118     uint16_t id;
119     for (id = 0; id < UIFontBuilder::GetInstance()->GetBitmapFontIdMax(); ++id) {
120         UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(id);
121         if (fontParam != nullptr) {
122             if ((fontParam->size == size) && (strncmp(fontParam->ttfName, ttfName, TTF_NAME_LEN_MAX) == 0)) {
123                 break;
124             }
125         }
126     }
127     return id;
128 }
129 
GetWidth(uint32_t unicode,uint16_t fontId,uint8_t fontSize)130 int16_t UIFontBitmap::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize)
131 {
132     return GetWidthInFontId(unicode, fontId);
133 }
134 
GetBitmap(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)135 uint8_t* UIFontBitmap::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
136 {
137     return SearchInFont(unicode, glyphNode, fontId);
138 }
139 
IsEmojiFont(uint16_t fontId)140 bool UIFontBitmap::IsEmojiFont(uint16_t fontId)
141 {
142     return false;
143 }
144 
GetFontHeader(FontHeader & fontHeader,uint16_t fontId,uint8_t fontSize)145 int8_t UIFontBitmap::GetFontHeader(FontHeader& fontHeader, uint16_t fontId, uint8_t fontSize)
146 {
147     const FontHeader* header = dynamicFont_.GetFontHeader(fontId);
148     if (header != nullptr) {
149         fontHeader = *header;
150         return RET_VALUE_OK;
151     }
152     return INVALID_RET_VALUE;
153 }
154 
155 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
GetMultiGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)156 int8_t UIFontBitmap::GetMultiGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
157 {
158     int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
159     if (ret == RET_VALUE_OK) {
160         return ret;
161     }
162 
163     uint16_t* searchLists = nullptr;
164     int8_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
165     int8_t currentIndex = 0;
166     if ((searchLists == nullptr) || (listSize == 0)) {
167         return INVALID_RET_VALUE;
168     }
169     do {
170         ret = GetGlyphNode(unicode, glyphNode, searchLists[currentIndex]);
171         if (ret != INVALID_RET_VALUE) {
172             return ret;
173         }
174         // switch to next search List
175         currentIndex++;
176     } while ((currentIndex < listSize) && (searchLists != nullptr));
177     return INVALID_RET_VALUE;
178 }
179 #endif
180 
GetGlyphNode(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId,uint8_t fontSize)181 int8_t UIFontBitmap::GetGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
182 {
183     const GlyphNode* node = dynamicFont_.GetGlyphNode(unicode, fontId);
184     if (node != nullptr) {
185         glyphNode = *node;
186         return RET_VALUE_OK;
187     }
188     GRAPHIC_LOGE("UIFontBitmap::GetGlyphNode get glyphNode failed");
189     return INVALID_RET_VALUE;
190 }
191 
GetGlyphNodeFromFile(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)192 int8_t UIFontBitmap::GetGlyphNodeFromFile(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
193 {
194     const GlyphNode* node = dynamicFont_.GetGlyphNodeFromFiles(unicode, fontId);
195     if (node != nullptr) {
196         glyphNode = *node;
197         return RET_VALUE_OK;
198     }
199     return INVALID_RET_VALUE;
200 }
201 
GetFontVersion(FontType type,const char * path,char * version,uint8_t len)202 int8_t UIFontBitmap::GetFontVersion(FontType type, const char* path, char* version, uint8_t len)
203 {
204     if (type != DYNAMIC_FONT) {
205         return INVALID_RET_VALUE;
206     }
207     return dynamicFont_.GetFontVersion(path, version, len);
208 }
209 
SetCurrentLangId(uint8_t langId)210 int8_t UIFontBitmap::SetCurrentLangId(uint8_t langId)
211 {
212     UIFontCacheManager::GetInstance()->BitmapCacheInit();
213     return RET_VALUE_OK;
214 }
215 
GetFontInfo(uint16_t fontId) const216 UITextLanguageFontParam* UIFontBitmap::GetFontInfo(uint16_t fontId) const
217 {
218     return UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
219 }
220 
GetDynamicFontBitmap(uint32_t unicode,BufferInfo & bufInfo,uint16_t fontId)221 int8_t UIFontBitmap::GetDynamicFontBitmap(uint32_t unicode, BufferInfo& bufInfo, uint16_t fontId)
222 {
223     return dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
224 }
225 
GetCacheBitmap(uint16_t fontId,uint32_t unicode)226 uint8_t* UIFontBitmap::GetCacheBitmap(uint16_t fontId, uint32_t unicode)
227 {
228     return UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode);
229 }
230 
PutCacheSpace(uint8_t * addr)231 void UIFontBitmap::PutCacheSpace(uint8_t* addr)
232 {
233     UIFontCacheManager::GetInstance()->PutSpace(addr);
234 }
235 
GetDynamicFontWidth(uint32_t unicode,uint16_t fontId)236 int16_t UIFontBitmap::GetDynamicFontWidth(uint32_t unicode, uint16_t fontId)
237 {
238     return dynamicFont_.GetFontWidth(unicode, fontId);
239 }
240 
SearchInFont(uint32_t unicode,GlyphNode & glyphNode,uint16_t fontId)241 uint8_t* UIFontBitmap::SearchInFont(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
242 {
243     GraphicLockGuard guard(lock_);
244     if (UIFontCacheManager::GetInstance()->GetBitmapCache() == nullptr) {
245         return nullptr;
246     }
247     if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
248         GRAPHIC_LOGE("UIFontBitmap::SearchInFont fontId and unicode not match");
249         return nullptr;
250     }
251     int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
252     if (ret != RET_VALUE_OK) {
253         return nullptr;
254     }
255     uint8_t* bitmap = UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode);
256     if (bitmap != nullptr) {
257         if (glyphNode.dataFlag == glyphNode.fontId && fontId == glyphNode.fontId) {
258             return bitmap;
259         } else {
260             GRAPHIC_LOGE("DataFlag of bitmap node not equal to fontId.");
261         }
262     }
263     if (glyphNode.kernOff <= glyphNode.dataOff) {
264         return nullptr;
265     }
266     ColorMode mode = UIFont::GetInstance()->GetColorType(fontId);
267     BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(fontId, unicode, mode, glyphNode, false);
268     ret = dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
269     if (ret == RET_VALUE_OK) {
270         return reinterpret_cast<uint8_t*>(bufInfo.virAddr);
271     }
272     PutCacheSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
273     return nullptr;
274 }
275 
GetWidthInFontId(uint32_t unicode,uint16_t fontId)276 int16_t UIFontBitmap::GetWidthInFontId(uint32_t unicode, uint16_t fontId)
277 {
278     if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
279         GRAPHIC_LOGE("UIFontBitmap::GetWidthInFontId fontId and unicode not match");
280         return INVALID_RET_VALUE;
281     }
282     return GetDynamicFontWidth(unicode, fontId);
283 }
284 
SetFontFileOffset(uint32_t offset)285 void UIFontBitmap::SetFontFileOffset(uint32_t offset)
286 {
287     offset_ = offset;
288 }
289 
GetOffsetPosY(const char * text,uint16_t lineLength,bool & isEmoijLarge,uint16_t fontId,uint8_t fontSize)290 uint16_t UIFontBitmap::GetOffsetPosY(const char* text,
291                                      uint16_t lineLength,
292                                      bool& isEmoijLarge,
293                                      uint16_t fontId,
294                                      uint8_t fontSize)
295 {
296     uint32_t i = 0;
297     uint16_t textNum = 0;
298     uint16_t emojiNum = 0;
299 
300     uint16_t loopNum = 0;
301     GlyphNode glyphNode;
302     GlyphNode emoijMaxNode = {};
303     uint8_t maxFontSie = fontSize;
304     while (i < lineLength) {
305         uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
306 #if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
307         uint8_t ret = GetMultiGlyphNode(unicode, glyphNode, fontId);
308 #else
309         uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
310 #endif
311         if (ret == RET_VALUE_OK) {
312             uint8_t weight = GetFontWeight(glyphNode.fontId);
313             if (weight >= 16) { // 16: bit rgb565 rgba8888
314                 emoijMaxNode = glyphNode.rows > emoijMaxNode.rows ? glyphNode : emoijMaxNode;
315                 emojiNum++;
316             } else {
317                 textNum++;
318             }
319             loopNum++;
320         }
321     }
322     // The number of emoji is the same as the number of cycles, indicating that this line is all emoji
323     // The number of words is the same as the number of cycles, which means that this line is all words
324     if ((emojiNum == loopNum) || (textNum == loopNum)) {
325         isEmoijLarge = true;
326         return 0;
327     }
328     isEmoijLarge = emoijMaxNode.rows > maxFontSie;
329     uint16_t offset = 0;
330     if (isEmoijLarge) {
331         // If the emoji is higher than the text
332         if (emoijMaxNode.top >= maxFontSie) {
333             offset = emoijMaxNode.top - maxFontSie;
334         }
335     } else {
336         // If text are higher than emoji
337         if (maxFontSie >= emoijMaxNode.rows) {
338             // should top - ros.
339             offset = maxFontSie - emoijMaxNode.rows;
340         }
341     }
342     return offset;
343 }
344 
GetLineMaxHeight(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t & letterIndex,SizeSpan * sizeSpans)345 uint16_t UIFontBitmap::GetLineMaxHeight(const char* text,
346                                         uint16_t lineLength,
347                                         uint16_t fontId,
348                                         uint8_t fontSize,
349                                         uint16_t& letterIndex,
350                                         SizeSpan* sizeSpans)
351 {
352     uint16_t maxHeight = GetHeight(fontId, fontSize);
353     if (sizeSpans == nullptr) {
354         return maxHeight;
355     }
356 
357     uint32_t i = 0;
358     while (i < lineLength) {
359         TypedText::GetUTF8Next(text, i, i);
360         if (sizeSpans != nullptr && sizeSpans[letterIndex].isSizeSpan) {
361             uint16_t spannableHeight = 0;
362             if (sizeSpans[letterIndex].height == 0) {
363                 spannableHeight = GetHeight(sizeSpans[letterIndex].fontId, sizeSpans[letterIndex].size);
364                 sizeSpans[letterIndex].height = spannableHeight;
365             } else {
366                 spannableHeight = sizeSpans[letterIndex].height;
367             }
368             maxHeight = spannableHeight > maxHeight ? spannableHeight : maxHeight;
369         }
370 
371         letterIndex++;
372         if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
373             break;
374         }
375     }
376 
377     return maxHeight;
378 }
379 
SetPsramMemory(uintptr_t psramAddr,uint32_t psramLen)380 void UIFontBitmap::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
381 {
382     BaseFont::SetPsramMemory(psramAddr, psramLen);
383     FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
384 }
385 } // namespace OHOS
386