* Copyright (c) 2020-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "font/ui_font_bitmap.h"
#include "draw/draw_utils.h"
#include "font/font_ram_allocator.h"
#include "font/ui_font.h"
#include "font/ui_font_adaptor.h"
#include "font/ui_font_builder.h"
#include "gfx_utils/file.h"
#include "gfx_utils/graphic_log.h"
#include "graphic_config.h"
#if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
#include "font/ui_multi_font_manager.h"
#endif
#if defined(ENABLE_SHAPING) && ENABLE_SHAPING
#include "font/ui_text_shaping.h"
#endif
#include "font/ui_font_cache_manager.h"
namespace OHOS {
UIFontBitmap::UIFontBitmap() : offset_(0), dynamicFont_() {}
UIFontBitmap::~UIFontBitmap()
{
CloseFontFd();
}
void UIFontBitmap::CloseFontFd()
{
for (uint16_t i = 0; i < dynamicFontFd_.Size(); i++) {
if (dynamicFontFd_[i] >= 0) {
close(dynamicFontFd_[i]);
dynamicFontFd_[i] = -1;
}
}
}
bool UIFontBitmap::IsVectorFont() const
{
return false;
}
uint16_t
UIFontBitmap::GetShapingFontId(char* text, uint8_t& ttfId, uint32_t& script, uint16_t fontId, uint8_t size) const
{
#if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
return UIMultiFontManager::GetInstance()->GetShapingFontId(text, fontId, ttfId, script);
#else
UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
if (fontParam == nullptr) {
return 0;
}
ttfId = fontParam->ttfId;
return fontParam->shaping;
#endif
}
uint8_t UIFontBitmap::GetFontWeight(uint16_t fontId)
{
UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
if (fontParam == nullptr) {
GRAPHIC_LOGE("UIFontBitmap::GetFontWeigh invalid fontId");
return 0;
}
return fontParam->fontWeight;
}
int8_t UIFontBitmap::SetFontPath(const char* path, FontType type)
{
if ((path == nullptr) || (type != DYNAMIC_FONT)) {
GRAPHIC_LOGE("UIFontBitmap::SetFontPath invalid parameter");
return INVALID_RET_VALUE;
}
#ifdef _WIN32
int32_t fontFd = open(path, O_RDONLY | O_BINARY);
#else
int32_t fontFd = open(path, O_RDONLY);
#endif
if (fontFd < 0) {
GRAPHIC_LOGE("UIFontBitmap::SetFontPath file Open failed");
return INVALID_RET_VALUE;
}
int32_t ret = dynamicFont_.SetFile(path, fontFd, offset_, GlyphCacheType::CACHE_TYPE_DYNAMIC);
if (ret == INVALID_RET_VALUE) {
GRAPHIC_LOGE("GlyphsManager::SetFile failed");
close(fontFd);
return ret;
}
dynamicFontFd_.PushBack(fontFd);
return RET_VALUE_OK;
}
uint16_t UIFontBitmap::GetHeight(uint16_t fontId, uint8_t fontSize)
{
return dynamicFont_.GetFontHeight(fontId);
}
uint16_t UIFontBitmap::GetFontId(const char* ttfName, uint8_t size) const
{
UIFontBuilder* fontBuilder = UIFontBuilder::GetInstance();
if (ttfName == nullptr) {
return fontBuilder->GetBitmapFontIdMax();
}
uint16_t id;
for (id = 0; id < fontBuilder->GetBitmapFontIdMax(); ++id) {
UITextLanguageFontParam* fontParam = fontBuilder->GetTextLangFontsTable(id);
if (fontParam != nullptr) {
if ((fontParam->size == size) && (strncmp(fontParam->ttfName, ttfName, TTF_NAME_LEN_MAX) == 0)) {
break;
}
}
}
return id;
}
int16_t UIFontBitmap::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize)
{
return GetWidthInFontId(unicode, fontId);
}
uint8_t* UIFontBitmap::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
{
return SearchInFont(unicode, glyphNode, fontId);
}
bool UIFontBitmap::IsEmojiFont(uint16_t fontId)
{
return false;
}
int8_t UIFontBitmap::GetFontHeader(FontHeader& fontHeader, uint16_t fontId, uint8_t fontSize)
{
const FontHeader* header = dynamicFont_.GetFontHeader(fontId);
if (header != nullptr) {
fontHeader = *header;
return RET_VALUE_OK;
}
return INVALID_RET_VALUE;
}
#if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
int8_t UIFontBitmap::GetMultiGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
{
int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
if (ret == RET_VALUE_OK) {
return ret;
}
uint16_t* searchLists = nullptr;
int8_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
int8_t currentIndex = 0;
if ((searchLists == nullptr) || (listSize == 0)) {
return INVALID_RET_VALUE;
}
do {
ret = GetGlyphNode(unicode, glyphNode, searchLists[currentIndex]);
if (ret != INVALID_RET_VALUE) {
return ret;
}
currentIndex++;
} while ((currentIndex < listSize) && (searchLists != nullptr));
return INVALID_RET_VALUE;
}
#endif
int8_t UIFontBitmap::GetGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
{
const GlyphNode* node = dynamicFont_.GetGlyphNode(unicode, fontId);
if (node != nullptr) {
glyphNode = *node;
return RET_VALUE_OK;
}
GRAPHIC_LOGE("UIFontBitmap::GetGlyphNode get glyphNode failed");
return INVALID_RET_VALUE;
}
int8_t UIFontBitmap::GetGlyphNodeFromFile(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
{
const GlyphNode* node = dynamicFont_.GetGlyphNodeFromFiles(unicode, fontId);
if (node != nullptr) {
glyphNode = *node;
return RET_VALUE_OK;
}
return INVALID_RET_VALUE;
}
int8_t UIFontBitmap::GetFontVersion(FontType type, const char* path, char* version, uint8_t len)
{
if (type != DYNAMIC_FONT) {
return INVALID_RET_VALUE;
}
return dynamicFont_.GetFontVersion(path, version, len);
}
int8_t UIFontBitmap::SetCurrentLangId(uint8_t langId)
{
GRAPHIC_LOGE("UIFontBitmap::SetCurrentLangId start");
UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
if (fontCacheManager->GlyphsCacheInit() != RET_VALUE_OK) {
GRAPHIC_LOGE("UIFontCacheManager::GlyphsCacheInit init failed");
return INVALID_RET_VALUE;
}
fontCacheManager->BitmapCacheInit();
return RET_VALUE_OK;
}
UITextLanguageFontParam* UIFontBitmap::GetFontInfo(uint16_t fontId) const
{
return UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId);
}
int8_t UIFontBitmap::GetDynamicFontBitmap(uint32_t unicode, BufferInfo& bufInfo, uint16_t fontId)
{
return dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
}
uint8_t* UIFontBitmap::GetCacheBitmap(uint16_t fontId, uint32_t unicode)
{
TextStyle textStyle = TEXT_STYLE_NORMAL;
return UIFontCacheManager::GetInstance()->GetBitmap(fontId, unicode, textStyle);
}
void UIFontBitmap::PutCacheSpace(uint8_t* addr)
{
UIFontCacheManager::GetInstance()->PutSpace(addr);
}
int16_t UIFontBitmap::GetDynamicFontWidth(uint32_t unicode, uint16_t fontId)
{
return dynamicFont_.GetFontWidth(unicode, fontId);
}
uint8_t* UIFontBitmap::SearchInFont(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId)
{
GraphicLockGuard guard(lock_);
UIFontCacheManager* fontCacheManager = UIFontCacheManager::GetInstance();
if (fontCacheManager->GetBitmapCache() == nullptr) {
return nullptr;
}
if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
GRAPHIC_LOGE("UIFontBitmap::SearchInFont fontId and unicode not match");
return nullptr;
}
int8_t ret = GetGlyphNode(unicode, glyphNode, fontId);
if (ret != RET_VALUE_OK) {
return nullptr;
}
TextStyle textStyle = TEXT_STYLE_NORMAL;
uint8_t* bitmap = fontCacheManager->GetBitmap(fontId, unicode, textStyle);
if (bitmap != nullptr) {
if (glyphNode.dataFlag == glyphNode.fontId && fontId == glyphNode.fontId) {
return bitmap;
} else {
GRAPHIC_LOGE("DataFlag of bitmap node not equal to fontId.");
}
}
if (glyphNode.kernOff <= glyphNode.dataOff) {
return nullptr;
}
ColorMode mode = UIFont::GetInstance()->GetColorType(fontId);
BufferInfo bufInfo = UIFontAllocator::GetCacheBuffer(fontId, unicode, mode, glyphNode, false, textStyle);
ret = dynamicFont_.GetBitmap(unicode, bufInfo, fontId);
if (ret == RET_VALUE_OK) {
return reinterpret_cast<uint8_t*>(bufInfo.virAddr);
}
PutCacheSpace(reinterpret_cast<uint8_t*>(bufInfo.virAddr));
return nullptr;
}
int16_t UIFontBitmap::GetWidthInFontId(uint32_t unicode, uint16_t fontId)
{
if (!UIFontAdaptor::IsSameTTFId(fontId, unicode)) {
GRAPHIC_LOGE("UIFontBitmap::GetWidthInFontId fontId and unicode not match");
return INVALID_RET_VALUE;
}
return GetDynamicFontWidth(unicode, fontId);
}
void UIFontBitmap::SetFontFileOffset(uint32_t offset)
{
offset_ = offset;
}
uint16_t UIFontBitmap::GetOffsetPosY(const char* text,
uint16_t lineLength,
bool& isEmoijLarge,
uint16_t fontId,
uint8_t fontSize)
{
uint32_t i = 0;
uint16_t textNum = 0;
uint16_t emojiNum = 0;
uint16_t loopNum = 0;
GlyphNode glyphNode;
GlyphNode emoijMaxNode = {};
uint8_t maxFontSie = fontSize;
while (i < lineLength) {
uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
#if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
uint8_t ret = GetMultiGlyphNode(unicode, glyphNode, fontId);
#else
uint8_t ret = GetGlyphNode(unicode, glyphNode, fontId, fontSize);
#endif
if (ret == RET_VALUE_OK) {
uint8_t weight = GetFontWeight(glyphNode.fontId);
if (weight >= 16) {
emoijMaxNode = glyphNode.rows > emoijMaxNode.rows ? glyphNode : emoijMaxNode;
emojiNum++;
} else {
textNum++;
}
loopNum++;
}
}
if ((emojiNum == loopNum) || (textNum == loopNum)) {
isEmoijLarge = true;
return 0;
}
isEmoijLarge = emoijMaxNode.rows > maxFontSie;
uint16_t offset = 0;
if (isEmoijLarge) {
if (emoijMaxNode.top >= maxFontSie) {
offset = emoijMaxNode.top - maxFontSie;
}
} else {
if (maxFontSie >= emoijMaxNode.rows) {
offset = maxFontSie - emoijMaxNode.rows;
}
}
return offset;
}
uint16_t UIFontBitmap::GetLineMaxHeight(const char* text,
uint16_t lineLength,
uint16_t fontId,
uint8_t fontSize,
uint16_t& letterIndex,
SpannableString* spannableString)
{
uint16_t maxHeight = GetHeight(fontId, fontSize);
if (spannableString == nullptr) {
return maxHeight;
}
uint32_t i = 0;
while (i < lineLength) {
TypedText::GetUTF8Next(text, i, i);
if (spannableString != nullptr && spannableString->GetSpannable(letterIndex)) {
int16_t spannableHeight = 0;
spannableString->GetFontHeight(letterIndex, spannableHeight, fontId, fontSize);
uint16_t tempHeight = static_cast<uint16_t>(spannableHeight);
maxHeight = tempHeight > maxHeight ? tempHeight : maxHeight;
}
letterIndex++;
if (i > 0 && ((text[i - 1] == '\r') || (text[i - 1] == '\n'))) {
break;
}
}
return maxHeight;
}
void UIFontBitmap::SetPsramMemory(uintptr_t psramAddr, uint32_t psramLen)
{
BaseFont::SetPsramMemory(psramAddr, psramLen);
FontRamAllocator::GetInstance().SetRamAddr(psramAddr, psramLen);
}
}