• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_parser.h"
17 
18 #include <codecvt>
19 #include <iomanip>
20 #include <securec.h>
21 
22 #include "font_config.h"
23 #include "texgine/utils/exlog.h"
24 
25 namespace OHOS {
26 namespace Rosen {
27 namespace TextEngine {
28 #define SUCCESSED 0
29 #define FAILED 1
30 
31 #define FONT_CONFIG_FILE  "/system/fonts/visibility_list.json"
32 
33 #define HALF(a) ((a) / 2)
34 
35 // "weight" and "italic" will assigned value 0 and 1, -1 used to exclude unassigned
FontDescriptor()36 FontParser::FontDescriptor::FontDescriptor(): path(""), postScriptName(""), fullName(""),
37     fontFamily(""), fontSubfamily(""), weight(-1), width(0), italic(-1), monoSpace(0), symbolic(0)
38 {
39 }
40 
FontParser()41 FontParser::FontParser()
42 {
43     data_ = nullptr;
44     length_ = 0;
45     FontConfig fontConfig(FONT_CONFIG_FILE);
46     fontSet_ = fontConfig.GetFontSet();
47 }
48 
ProcessCmapTable(const struct CmapTables * cmapTable,FontParser::FontDescriptor & fontDescriptor)49 void FontParser::ProcessCmapTable(const struct CmapTables* cmapTable, FontParser::FontDescriptor& fontDescriptor)
50 {
51     for (auto i = 0; i < cmapTable->numTables.Get(); ++i) {
52         const auto& record = cmapTable->encodingRecords[i];
53         FontParser::PlatformId platformId = static_cast<FontParser::PlatformId>(record.platformID.Get());
54         FontParser::EncodingIdWin encodingId = static_cast<FontParser::EncodingIdWin>(record.encodingID.Get());
55         if (platformId == FontParser::PlatformId::WINDOWS && encodingId == FontParser::EncodingIdWin::SYMBOL) {
56             fontDescriptor.symbolic = true;
57             break;
58         }
59     }
60 }
61 
GetStringFromNameId(FontParser::NameId nameId,const std::string & nameString,FontParser::FontDescriptor & fontDescriptor)62 void FontParser::GetStringFromNameId(FontParser::NameId nameId, const std::string& nameString,
63     FontParser::FontDescriptor& fontDescriptor)
64 {
65     switch (nameId) {
66         case FontParser::NameId::FONT_FAMILY: {
67             if (fontDescriptor.fontFamily.size() == 0) {
68                 fontDescriptor.fontFamily = nameString;
69             }
70             break;
71         }
72         case FontParser::NameId::FONT_SUBFAMILY: {
73             if (fontDescriptor.fontSubfamily.size() == 0) {
74                 fontDescriptor.fontSubfamily = nameString;
75             }
76             break;
77         }
78         case FontParser::NameId::FULL_NAME: {
79             if (fontDescriptor.fullName.size() == 0) {
80                 fontDescriptor.fullName = nameString;
81             }
82             break;
83         }
84         case FontParser::NameId::POSTSCRIPT_NAME: {
85             if (fontDescriptor.postScriptName.size() == 0) {
86                 fontDescriptor.postScriptName = nameString;
87             }
88             break;
89         }
90         default: {
91             break;
92         }
93     }
94 }
95 
ProcessNameTable(const struct NameTable * nameTable,FontParser::FontDescriptor & fontDescriptor) const96 int FontParser::ProcessNameTable(const struct NameTable* nameTable, FontParser::FontDescriptor& fontDescriptor) const
97 {
98     auto count = nameTable->count.Get();
99     auto storageOffset = nameTable->storageOffset.Get();
100     auto stringStorage = data_ + storageOffset;
101     for (int i = 0; i < count; ++i) {
102         if (nameTable->nameRecord[i].stringOffset.Get() == 0 || nameTable->nameRecord[i].length.Get() == 0) {
103             continue;
104         }
105         FontParser::NameId nameId = static_cast<FontParser::NameId>(nameTable->nameRecord[i].nameId.Get());
106         FontParser::PlatformId platformId =
107             static_cast<FontParser::PlatformId>(nameTable->nameRecord[i].platformId.Get());
108         auto len = nameTable->nameRecord[i].length.Get();
109         auto stringOffset = nameTable->nameRecord[i].stringOffset.Get();
110         const char* data = stringStorage + stringOffset;
111         if (platformId == FontParser::PlatformId::MACINTOSH) {
112             std::string nameString(data, len);
113             GetStringFromNameId(nameId, nameString, fontDescriptor);
114         } else if (platformId == FontParser::PlatformId::WINDOWS) {
115             char* buffer = new (std::nothrow) char[len]();
116             if (buffer == nullptr) {
117                 return FAILED;
118             }
119             if (memcpy_s(buffer, len, data, len) != EOK) {
120                 LOGSO_FUNC_LINE(ERROR) << "memcpy failed";
121                 delete[] buffer;
122                 return FAILED;
123             }
124             const char16_t* strPtr = reinterpret_cast<const char16_t*>(buffer);
125             const std::u16string u16str(strPtr, strPtr + HALF(len));
126             std::wstring_convert<std::codecvt_utf16<char16_t>, char16_t> converter;
127             const std::string name = converter.to_bytes(u16str);
128             std::vector<char> vec(name.begin(), name.end());
129             vec.erase(std::remove(vec.begin(), vec.end(), '\0'), vec.end());
130             std::string nameString = std::string(vec.begin(), vec.end());
131             GetStringFromNameId(nameId, nameString, fontDescriptor);
132             delete[] buffer;
133         }
134     }
135 
136     return SUCCESSED;
137 }
138 
ProcessPostTable(const struct PostTable * postTable,FontParser::FontDescriptor & fontDescriptor)139 void FontParser::ProcessPostTable(const struct PostTable* postTable, FontParser::FontDescriptor& fontDescriptor)
140 {
141     if (postTable->italicAngle.Get() != 0) {
142         fontDescriptor.italic = 1; // means support italics
143     } else {
144         fontDescriptor.italic = 0;
145     }
146     if (postTable->isFixedPitch.Get() == 1) {
147         fontDescriptor.monoSpace = true;
148     }
149 }
150 
ParseCmapTable(sk_sp<SkTypeface> typeface,FontParser::FontDescriptor & fontDescriptor)151 int FontParser::ParseCmapTable(sk_sp<SkTypeface> typeface, FontParser::FontDescriptor& fontDescriptor)
152 {
153     auto tag = HB_TAG('c', 'm', 'a', 'p');
154     auto size = typeface->getTableSize(tag);
155     if (size <= 0) {
156         LOGSO_FUNC_LINE(ERROR) << "haven't cmap";
157         return FAILED;
158     }
159     std::unique_ptr<char[]> tableData = nullptr;
160     tableData = std::make_unique<char[]>(size);
161     auto retTableData = typeface->getTableData(tag, 0, size, tableData.get());
162     if (size != retTableData) {
163         LOGSO_FUNC_LINE(ERROR) <<"get table data failed size: " << size << ", ret: " << retTableData;
164         return FAILED;
165     }
166     hb_blob_t* hblob = nullptr;
167     hblob = hb_blob_create(
168         reinterpret_cast<const char*>(tableData.get()), size, HB_MEMORY_MODE_WRITABLE, tableData.get(), nullptr);
169     if (hblob == nullptr) {
170         LOGSO_FUNC_LINE(ERROR) << "hblob is nullptr";
171         return FAILED;
172     }
173     data_ = hb_blob_get_data(hblob, nullptr);
174     length_ = hb_blob_get_length(hblob);
175     auto parseCmap = std::make_shared<CmapTableParser>(data_, length_);
176     auto cmapTable = parseCmap->Parse(data_, length_);
177     ProcessCmapTable(cmapTable, fontDescriptor);
178 
179     return SUCCESSED;
180 }
181 
ParseNameTable(sk_sp<SkTypeface> typeface,FontParser::FontDescriptor & fontDescriptor)182 int FontParser::ParseNameTable(sk_sp<SkTypeface> typeface, FontParser::FontDescriptor& fontDescriptor)
183 {
184     auto tag = HB_TAG('n', 'a', 'm', 'e');
185     auto size = typeface->getTableSize(tag);
186     if (size <= 0) {
187         LOGSO_FUNC_LINE(ERROR) << "haven't name";
188         return FAILED;
189     }
190     std::unique_ptr<char[]> tableData = nullptr;
191     tableData = std::make_unique<char[]>(size);
192     auto retTableData = typeface->getTableData(tag, 0, size, tableData.get());
193     if (size != retTableData) {
194         LOGSO_FUNC_LINE(ERROR) <<"get table data failed size: " << size << ", ret: " << retTableData;
195         return FAILED;
196     }
197     hb_blob_t* hblob = nullptr;
198     hblob = hb_blob_create(
199         reinterpret_cast<const char*>(tableData.get()), size, HB_MEMORY_MODE_WRITABLE, tableData.get(), nullptr);
200     if (hblob == nullptr) {
201         LOGSO_FUNC_LINE(ERROR) << "hblob is nullptr";
202         return FAILED;
203     }
204     data_ = hb_blob_get_data(hblob, nullptr);
205     length_ = hb_blob_get_length(hblob);
206     auto parseName = std::make_shared<NameTableParser>(data_, length_);
207     auto nameTable = parseName->Parse(data_, length_);
208     int ret = ProcessNameTable(nameTable, fontDescriptor);
209     if (ret != SUCCESSED) {
210         LOGSO_FUNC_LINE(ERROR) << "process name table failed";
211         return FAILED;
212     }
213 
214     return SUCCESSED;
215 }
216 
ParsePostTable(sk_sp<SkTypeface> typeface,FontParser::FontDescriptor & fontDescriptor)217 int FontParser::ParsePostTable(sk_sp<SkTypeface> typeface, FontParser::FontDescriptor& fontDescriptor)
218 {
219     auto tag = HB_TAG('p', 'o', 's', 't');
220     auto size = typeface->getTableSize(tag);
221     if (size <= 0) {
222         LOGSO_FUNC_LINE(ERROR) << "haven't post";
223         return FAILED;
224     }
225     std::unique_ptr<char[]> tableData = nullptr;
226     tableData = std::make_unique<char[]>(size);
227     auto retTableData = typeface->getTableData(tag, 0, size, tableData.get());
228     if (size != retTableData) {
229         LOGSO_FUNC_LINE(ERROR) <<"get table data failed size: " << size << ", ret: " << retTableData;
230         return FAILED;
231     }
232     hb_blob_t* hblob = nullptr;
233     hblob = hb_blob_create(
234         reinterpret_cast<const char*>(tableData.get()), size, HB_MEMORY_MODE_WRITABLE, tableData.get(), nullptr);
235     if (hblob == nullptr) {
236         LOGSO_FUNC_LINE(ERROR) << "hblob is nullptr";
237         return FAILED;
238     }
239     data_ = hb_blob_get_data(hblob, nullptr);
240     length_ = hb_blob_get_length(hblob);
241     auto parsePost = std::make_shared<PostTableParser>(data_, length_);
242     auto postTable = parsePost->Parse(data_, length_);
243     ProcessPostTable(postTable, fontDescriptor);
244 
245     return SUCCESSED;
246 }
247 
ParseTable(sk_sp<SkTypeface> typeface,FontParser::FontDescriptor & fontDescriptor)248 int FontParser::ParseTable(sk_sp<SkTypeface> typeface, FontParser::FontDescriptor& fontDescriptor)
249 {
250     if (ParseCmapTable(typeface, fontDescriptor) != SUCCESSED) {
251         LOGSO_FUNC_LINE(ERROR) << "parse cmap failed";
252         return FAILED;
253     }
254     if (ParseNameTable(typeface, fontDescriptor) != SUCCESSED) {
255         LOGSO_FUNC_LINE(ERROR) << "parse name failed";
256         return FAILED;
257     }
258     if (ParsePostTable(typeface, fontDescriptor) != SUCCESSED) {
259         LOGSO_FUNC_LINE(ERROR) << "parse post failed";
260         return FAILED;
261     }
262 
263     return SUCCESSED;
264 }
265 
SetFontDescriptor()266 int FontParser::SetFontDescriptor()
267 {
268     for (unsigned int i = 0; i < fontSet_.size(); ++i) {
269         FontParser::FontDescriptor fontDescriptor;
270         fontDescriptor.path = fontSet_[i];
271         const char* path = fontSet_[i].c_str();
272         auto typeface = SkTypeface::MakeFromFile(path);
273         if (typeface == nullptr) {
274             LOGSO_FUNC_LINE(ERROR) << "typeface is nullptr, can not parse: " << fontDescriptor.path;
275             continue;
276         }
277         auto fontStyle = typeface->fontStyle();
278         fontDescriptor.weight = fontStyle.weight();
279         fontDescriptor.width = fontStyle.width();
280         if (ParseTable(typeface, fontDescriptor) !=  SUCCESSED) {
281             LOGSO_FUNC_LINE(ERROR) << "parse table failed";
282             return FAILED;
283         }
284         visibilityFonts_.emplace_back(fontDescriptor);
285     }
286 
287     return SUCCESSED;
288 }
289 
GetVisibilityFonts()290 std::vector<FontParser::FontDescriptor> FontParser::GetVisibilityFonts()
291 {
292     if (SetFontDescriptor() != SUCCESSED) {
293         LOGSO_FUNC_LINE(ERROR) << "set visibility font descriptor failed";
294     }
295 
296     return visibilityFonts_;
297 }
298 } // namespace TextEngine
299 } // namespace Rosen
300 } // namespace OHOS
301