* Copyright (c) 2020-2021 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_multi_font_manager.h"
#include "common/typed_text.h"
#include "font/ui_font.h"
#include "gfx_utils/mem_api.h"
#include "securec.h"
#if ENABLE_SHAPING
#include "font/ui_text_shaping.h"
#endif
#if ENABLE_MULTI_FONT
namespace OHOS {
UIMultiFontManager::UIMultiFontManager()
: arbicTtfId_(0), thaiTtfId_(0), myanmarTtfId_(0),
devanagariTtfId_(0), hebrewTtfId_(0),
bengaliTtfId_(0), topIndex_(0)
{
const UITextLanguageFontParam* fontParam = nullptr;
uint16_t totalFontId = UIFontBuilder::GetInstance()->GetTotalFontId();
for (uint16_t i = 0; i < totalFontId; i++) {
fontParam = UIFont::GetInstance()->GetFontInfo(i);
if (fontParam == nullptr) {
continue;
}
if (!fontParam->shaping) {
continue;
}
if (strstr(fontParam->ttfName, ARABIC_LANG) != nullptr) {
arbicTtfId_ = fontParam->ttfId;
} else if (strstr(fontParam->ttfName, THAI_LANG) != nullptr) {
thaiTtfId_ = fontParam->ttfId;
} else if (strstr(fontParam->ttfName, MYAN_LANG) != nullptr) {
myanmarTtfId_ = fontParam->ttfId;
} else if (strstr(fontParam->ttfName, DVCARI_LANG) != nullptr) {
devanagariTtfId_ = fontParam->ttfId;
} else if (strstr(fontParam->ttfName, HBREW_LANG) != nullptr) {
hebrewTtfId_ = fontParam->ttfId;
} else if (strstr(fontParam->ttfName, BENGALI_LANG) != nullptr) {
bengaliTtfId_ = fontParam->ttfId;
}
}
fontIdIndex_ = static_cast<uint8_t*>(UIMalloc(totalFontId));
if (fontIdIndex_ == nullptr) {
return;
}
for (uint16_t index = 0; index < totalFontId; index++) {
fontIdIndex_[index] = MAX_FONT_SEARCH_NUM;
}
for (uint8_t index = 0; index < MAX_FONT_SEARCH_NUM; index++) {
fontNodes_[index].fontIds = nullptr;
fontNodes_[index].size = 0;
}
}
UIMultiFontManager::~UIMultiFontManager()
{
UIFree(fontIdIndex_);
fontIdIndex_ = nullptr;
}
int8_t UIMultiFontManager::AddNewFont(uint16_t fontListId, uint16_t* fontIds, int8_t size, uint8_t fontIndex)
{
fontNodes_[fontIndex].fontIds = static_cast<uint16_t*>(UIMalloc(size * sizeof(uint16_t)));
if (fontNodes_[fontIndex].fontIds == nullptr) {
return fontIndex;
}
fontIdIndex_[fontListId] = fontIndex;
(void)memcpy_s(fontNodes_[fontIndex].fontIds, size * sizeof(uint16_t), fontIds, size * sizeof(uint16_t));
fontNodes_[fontIndex].size = size;
return fontIndex + 1;
}
int8_t UIMultiFontManager::UpdateFont(uint16_t fontListId, uint16_t* fontIds, uint8_t size)
{
uint8_t index = fontIdIndex_[fontListId];
if (index < topIndex_) {
UIFree(fontNodes_[index].fontIds);
fontNodes_[index].fontIds = nullptr;
} else {
index = topIndex_;
}
uint8_t nextIndex = AddNewFont(fontListId, fontIds, size, index);
if (topIndex_ < nextIndex) {
topIndex_ = nextIndex;
}
return (fontNodes_[index].fontIds == nullptr) ? INVALID_RET_VALUE : RET_VALUE_OK;
}
void UIMultiFontManager::UpdateScript(UITextLanguageFontParam& fonts)
{
if (strstr(fonts.ttfName, ARABIC_LANG) != nullptr) {
arbicTtfId_ = fonts.ttfId;
} else if (strstr(fonts.ttfName, THAI_LANG) != nullptr) {
thaiTtfId_ = fonts.ttfId;
} else if (strstr(fonts.ttfName, MYAN_LANG) != nullptr) {
myanmarTtfId_ = fonts.ttfId;
} else if (strstr(fonts.ttfName, DVCARI_LANG) != nullptr) {
devanagariTtfId_ = fonts.ttfId;
} else if (strstr(fonts.ttfName, HBREW_LANG) != nullptr) {
hebrewTtfId_ = fonts.ttfId;
} else if (strstr(fonts.ttfName, BENGALI_LANG) != nullptr) {
bengaliTtfId_ = fonts.ttfId;
}
}
UIMultiFontManager* UIMultiFontManager::GetInstance()
{
static UIMultiFontManager instance;
return &instance;
}
void UIMultiFontManager::ClearSearchFontList()
{
uint16_t totalFontId = UIFontBuilder::GetInstance()->GetTotalFontId();
for (uint16_t index = 0; index < totalFontId; index++) {
fontIdIndex_[index] = MAX_FONT_SEARCH_NUM;
}
for (auto &node : fontNodes_) {
UIFree(node.fontIds);
node.fontIds = nullptr;
node.size = 0;
}
topIndex_ = 0;
}
int8_t UIMultiFontManager::SetSearchFontList(uint16_t fontListId, uint16_t* fontIds, uint8_t size)
{
if ((fontListId >= UIFontBuilder::GetInstance()->GetTotalFontId()) || (fontIds == nullptr) || (size == 0) ||
(fontIdIndex_ == nullptr) || (topIndex_ >= MAX_FONT_SEARCH_NUM)) {
return INVALID_RET_VALUE;
}
return UpdateFont(fontListId, fontIds, size);
}
int32_t UIMultiFontManager::GetSearchFontList(uint16_t fontListId, uint16_t** fontIds)
{
if ((fontListId >= UIFontBuilder::GetInstance()->GetTotalFontId()) || (fontIds == nullptr) ||
(fontIdIndex_ == nullptr) || (fontIdIndex_[fontListId] >= MAX_FONT_SEARCH_NUM)) {
return static_cast<uint32_t>(INVALID_RET_VALUE);
}
*fontIds = fontNodes_[fontIdIndex_[fontListId]].fontIds;
return static_cast<uint32_t>(fontNodes_[fontIdIndex_[fontListId]].size);
}
bool UIMultiFontManager::IsNeedShaping(const char *text, uint8_t &ttfId, uint32_t &script)
{
if (text == nullptr) {
return false;
}
uint32_t i = 0;
while (text[i] != '\0') {
uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
if (IsShapingLetter(unicode, ttfId)) {
#if ENABLE_SHAPING
script = GetScriptByTtfId(ttfId);
#endif
return true;
}
}
return false;
}
uint16_t UIMultiFontManager::GetShapingFontId(const char* text, uint16_t fontId, uint8_t& ttfId, uint32_t& script)
{
UIFont* fontEngine = UIFont::GetInstance();
const UITextLanguageFontParam* fontParam1 = fontEngine->GetFontInfo(fontId);
if (fontParam1 == nullptr) {
return DEFAULT_SHAPING_ID;
}
if (!fontParam1->shaping) {
if (!IsNeedShaping(text, ttfId, script)) {
return 0;
}
uint16_t* searchLists = nullptr;
int32_t length = GetSearchFontList(fontId, &searchLists);
const UITextLanguageFontParam* fontParam2 = nullptr;
for (uint16_t i = 0; i < length; i++) {
fontParam2 = fontEngine->GetFontInfo(searchLists[i]);
if (fontParam2 == nullptr) {
continue;
}
if (fontParam2->ttfId == ttfId) {
return searchLists[i];
}
}
return 0;
}
ttfId = fontParam1->ttfId;
#if ENABLE_SHAPING
script = GetScriptByTtfId(ttfId);
#endif
return DEFAULT_SHAPING_ID;
}
int8_t UIMultiFontManager::IsShapingLetter(uint32_t unicode, uint8_t &ttfId)
{
if ((unicode <= 0x06FF) && (unicode >= 0x0600)) {
ttfId = arbicTtfId_;
return ttfId != 0;
}
if ((unicode <= 0x0E7F) && (unicode >= 0x0E00)) {
ttfId = thaiTtfId_;
return ttfId != 0;
}
if ((unicode <= 0x097F) && (unicode >= 0x0900)) {
ttfId = devanagariTtfId_;
return ttfId != 0;
}
if ((unicode <= 0x05FF) && (unicode >= 0x0590)) {
ttfId = hebrewTtfId_;
return ttfId != 0;
}
if ((unicode <= 0x109F) && (unicode >= 0x1000)) {
ttfId = myanmarTtfId_;
return ttfId != 0;
}
if ((unicode <= 0x9FF) && (unicode >= 0x980)) {
ttfId = bengaliTtfId_;
return ttfId != 0;
}
return false;
}
#if ENABLE_SHAPING
uint32_t UIMultiFontManager::GetScriptByTtfId(uint8_t ttfId)
{
if (ttfId == arbicTtfId_) {
return SHAPING_SCRIPT_ARABIC;
}
if (ttfId == thaiTtfId_) {
return SHAPING_SCRIPT_THAI;
}
if (ttfId == devanagariTtfId_) {
return SHAPING_SCRIPT_DEVANAGARI;
}
if (ttfId == hebrewTtfId_) {
return SHAPING_SCRIPT_HEBREW;
}
if (ttfId == myanmarTtfId_) {
return SHAPING_SCRIPT_MYANMAR;
}
if (ttfId == bengaliTtfId_) {
return SHAPING_SCRIPT_BENGALI;
}
return SHAPING_SCRIPT_INVALID;
}
#endif
}
#endif