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 34namespace OHOS { 35UIFontBitmap::UIFontBitmap() : offset_(0), dynamicFont_() {} 36 37UIFontBitmap::~UIFontBitmap() 38{ 39 CloseFontFd(); 40} 41 42void 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 52bool UIFontBitmap::IsVectorFont() const 53{ 54 return false; 55} 56 57uint16_t 58 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 72uint8_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 82int8_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 108uint16_t UIFontBitmap::GetHeight(uint16_t fontId, uint8_t fontSize) 109{ 110 return dynamicFont_.GetFontHeight(fontId); 111} 112 113uint16_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 131int16_t UIFontBitmap::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize) 132{ 133 return GetWidthInFontId(unicode, fontId); 134} 135 136uint8_t* UIFontBitmap::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize) 137{ 138 return SearchInFont(unicode, glyphNode, fontId); 139} 140 141bool UIFontBitmap::IsEmojiFont(uint16_t fontId) 142{ 143 return false; 144} 145 146int8_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 157int8_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 182int8_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 193int8_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 203int8_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 211int8_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 225UITextLanguageFontParam* UIFontBitmap::GetFontInfo(uint16_t fontId) const 226{ 227 return UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId); 228} 229 230int8_t UIFontBitmap::GetDynamicFontBitmap(uint32_t unicode, BufferInfo& bufInfo, uint16_t fontId) 231{ 232 return dynamicFont_.GetBitmap(unicode, bufInfo, fontId); 233} 234 235uint8_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 241void UIFontBitmap::PutCacheSpace(uint8_t* addr) 242{ 243 UIFontCacheManager::GetInstance()->PutSpace(addr); 244} 245 246int16_t UIFontBitmap::GetDynamicFontWidth(uint32_t unicode, uint16_t fontId) 247{ 248 return dynamicFont_.GetFontWidth(unicode, fontId); 249} 250 251uint8_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 288int16_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 297void UIFontBitmap::SetFontFileOffset(uint32_t offset) 298{ 299 offset_ = offset; 300} 301 302uint16_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 357uint16_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 387void 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