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.h"
17#include "common/text.h"
18#include "font/ui_font_cache.h"
19#include "font/font_ram_allocator.h"
20#if defined(ENABLE_VECTOR_FONT) && ENABLE_VECTOR_FONT
21#include "font/ui_font_vector.h"
22#endif
23#if defined(ENABLE_BITMAP_FONT) && ENABLE_BITMAP_FONT
24#include "font/ui_font_bitmap.h"
25#endif
26#include "graphic_config.h"
27#if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
28#include "font/ui_multi_font_manager.h"
29#endif
30
31namespace OHOS {
32bool UIFont::setFontAllocFlag_ = false;
33UIFont::UIFont() : instance_(nullptr), defaultInstance_(nullptr) {}
34
35UIFont::~UIFont() {}
36
37UIFont* UIFont::GetInstance()
38{
39    static UIFont instance;
40#if defined(ENABLE_BITMAP_FONT) && ENABLE_BITMAP_FONT
41    if (instance.instance_ == nullptr) {
42        instance.defaultInstance_ = new UIFontBitmap();
43        instance.instance_ = instance.defaultInstance_;
44        setFontAllocFlag_ = true;
45    }
46#endif
47#if defined(ENABLE_VECTOR_FONT) && ENABLE_VECTOR_FONT
48    if (instance.instance_ == nullptr) {
49        instance.defaultInstance_ = new UIFontVector();
50        instance.instance_ = instance.defaultInstance_;
51        setFontAllocFlag_ = true;
52    }
53#endif
54    return &instance;
55}
56
57void UIFont::SetFont(BaseFont* font)
58{
59    if (font != nullptr) {
60        if (defaultInstance_ != nullptr && setFontAllocFlag_) {
61            delete defaultInstance_;
62            defaultInstance_ = nullptr;
63            setFontAllocFlag_ = false;
64        }
65        defaultInstance_ = font;
66        instance_ = font;
67    }
68}
69
70BaseFont* UIFont::GetFont()
71{
72    return instance_;
73}
74
75#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
76void UIFont::SetBitmapFont(BaseFont* font)
77{
78    if (font == nullptr) {
79        return;
80    }
81    GetBitmapInstance()->SetFont(font);
82}
83
84UIFont* UIFont::GetBitmapInstance()
85{
86    static UIFont instance;
87    if (instance.instance_ == nullptr) {
88        instance.defaultInstance_ = new UIFontBitmap();
89        instance.instance_ = instance.defaultInstance_;
90        setFontAllocFlag_ = true;
91    }
92    return &instance;
93}
94#endif
95
96void UIFont::SetFontFileOffset(uint32_t offset)
97{
98#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
99    GetBitmapInstance()->GetFont()->SetFontFileOffset(offset);
100#else
101    instance_->SetFontFileOffset(offset);
102#endif
103}
104
105int8_t UIFont::SetCurrentLangId(uint8_t langId)
106{
107#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
108    return GetBitmapInstance()->GetFont()->SetCurrentLangId(langId);
109#else
110    return instance_->SetCurrentLangId(langId);
111#endif
112}
113
114uint8_t UIFont::GetCurrentLangId() const
115{
116#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
117    return GetBitmapInstance()->GetFont()->GetCurrentLangId();
118#else
119    return instance_->GetCurrentLangId();
120#endif
121}
122
123int8_t  UIFont::SetFontPath(const char* path, BaseFont::FontType type)
124{
125#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
126    if (type == BaseFont::FontType::VECTOR_FONT) {
127        return instance_->SetFontPath(path, type);
128    }
129    return GetBitmapInstance()->GetFont()->SetFontPath(path, type);
130#else
131    return instance_->SetFontPath(path, type);
132#endif
133}
134
135int8_t UIFont::GetTextUtf8(uint16_t textId, uint8_t** utf8Addr, uint16_t& utf8Len) const
136{
137#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
138    return GetBitmapInstance()->GetFont()->GetTextUtf8(textId, utf8Addr, utf8Len);
139#else
140    return instance_->GetTextUtf8(textId, utf8Addr, utf8Len);
141#endif
142}
143
144int8_t UIFont::GetTextParam(uint16_t textId, UITextLanguageTextParam& param) const
145{
146#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
147    return GetBitmapInstance()->GetFont()->GetTextParam(textId, param);
148#else
149    return instance_->GetTextParam(textId, param);
150#endif
151}
152
153int8_t UIFont::GetWildCardStaticStr(uint16_t textId,
154                                    UITextWildcardStaticType type,
155                                    uint8_t** strAddr,
156                                    uint16_t& strLen) const
157{
158#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
159    return GetBitmapInstance()->GetFont()->GetWildCardStaticStr(textId, type, strAddr, strLen);
160#else
161    return instance_->GetWildCardStaticStr(textId, type, strAddr, strLen);
162#endif
163}
164
165int8_t UIFont::GetCodePoints(uint16_t textId, uint32_t** codePoints, uint16_t& codePointsNum) const
166{
167#if (defined(ENABLE_MIX_FONT) && (ENABLE_MIX_FONT == 1))
168    return GetBitmapInstance()->GetFont()->GetCodePoints(textId, codePoints, codePointsNum);
169#else
170    return instance_->GetCodePoints(textId, codePoints, codePointsNum);
171#endif
172}
173
174uint8_t* UIFont::GetBitmap(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize,
175                           uint8_t shapingFont)
176{
177    uint8_t* bitmap = nullptr;
178#if ENABLE_MULTI_FONT
179    // shaping font is in search list, search shaping font first
180    if (shapingFont > 1) {
181        bitmap = instance_->GetBitmap(unicode, glyphNode, shapingFont, fontSize);
182        if (bitmap != nullptr) {
183            return bitmap;
184        }
185    }
186#endif
187    bitmap = instance_->GetBitmap(unicode, glyphNode, fontId, fontSize);
188    if (bitmap != nullptr) {
189        return bitmap;
190    }
191#if ENABLE_MULTI_FONT
192    uint16_t* searchLists = nullptr;
193    int32_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
194    int32_t currentIndex = 0;
195    if ((searchLists == nullptr) || (listSize == 0)) {
196        return nullptr;
197    }
198    do {
199        bitmap = instance_->GetBitmap(unicode, glyphNode, searchLists[currentIndex], fontSize);
200        if (bitmap != nullptr) {
201            return bitmap;
202        }
203        // switch to next search List
204        currentIndex++;
205    } while ((currentIndex < listSize) && (searchLists != nullptr));
206#endif
207    return nullptr;
208}
209
210int8_t UIFont::GetGlyphNode(uint32_t unicode, GlyphNode& glyphNode, uint16_t fontId, uint8_t fontSize)
211{
212    int8_t result = instance_->GetGlyphNode(unicode, glyphNode, fontId, fontSize);
213    if (result == RET_VALUE_OK) {
214        return result;
215    }
216
217#if defined(ENABLE_MULTI_FONT) && ENABLE_MULTI_FONT
218    uint16_t* searchLists = nullptr;
219    int32_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
220    if ((searchLists == nullptr) || (listSize == 0)) {
221        return INVALID_RET_VALUE;
222    }
223    int32_t currentIndex = 0;
224    do {
225        result = instance_->GetGlyphNode(unicode, glyphNode, searchLists[currentIndex], fontSize);
226        if (result == RET_VALUE_OK) {
227            return result;
228        }
229        currentIndex++;
230    } while ((currentIndex < listSize) && (searchLists != nullptr));
231#endif
232    return INVALID_RET_VALUE;
233}
234
235uint16_t UIFont::GetWidth(uint32_t unicode, uint16_t fontId, uint8_t fontSize, uint8_t shapingId)
236{
237    int16_t result;
238#if ENABLE_MULTI_FONT
239    if (shapingId > 1) {
240        result = instance_->GetWidth(unicode, shapingId, fontSize);
241        if (result >= 0) {
242            return result;
243        }
244    }
245#endif
246    result = instance_->GetWidth(unicode, fontId, fontSize);
247    if (result >= 0) {
248        return result;
249    }
250
251#if ENABLE_MULTI_FONT
252    uint16_t* searchLists = nullptr;
253    int32_t listSize = UIMultiFontManager::GetInstance()->GetSearchFontList(fontId, &searchLists);
254    if ((searchLists == nullptr) || (listSize == 0)) {
255        return 0;
256    }
257    int32_t currentIndex = 0;
258    do {
259        result = instance_->GetWidth(unicode, searchLists[currentIndex], fontSize);
260        if (result >= 0) {
261            return result;
262        }
263        currentIndex++;
264    } while ((currentIndex < listSize) && (searchLists != nullptr));
265#endif
266    return 0;
267}
268
269uint16_t UIFont::GetLineMaxHeight(const char* text, uint16_t lineLength, uint16_t fontId, uint8_t fontSize,
270                                  uint16_t letterIndex, SpannableString* spannableString)
271{
272    return instance_->GetLineMaxHeight(text, lineLength, fontId, fontSize, letterIndex, spannableString);
273}
274} // namespace OHOS
275