1 // Copyright 2016 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fxge/android/cfpf_skiafontmgr.h"
8
9 #include <algorithm>
10 #include <iterator>
11 #include <utility>
12
13 #include "core/fxcrt/fx_codepage.h"
14 #include "core/fxcrt/fx_extension.h"
15 #include "core/fxcrt/fx_folder.h"
16 #include "core/fxcrt/fx_system.h"
17 #include "core/fxge/android/cfpf_skiafont.h"
18 #include "core/fxge/android/cfpf_skiapathfont.h"
19 #include "core/fxge/freetype/fx_freetype.h"
20 #include "core/fxge/fx_font.h"
21 #include "third_party/base/containers/adapters.h"
22
23 namespace {
24
25 constexpr int FPF_SKIAMATCHWEIGHT_NAME1 = 62;
26 constexpr int FPF_SKIAMATCHWEIGHT_NAME2 = 60;
27 constexpr int FPF_SKIAMATCHWEIGHT_1 = 16;
28 constexpr int FPF_SKIAMATCHWEIGHT_2 = 8;
29
30 struct FPF_SKIAFONTMAP {
31 uint32_t dwFamily;
32 uint32_t dwSubSt;
33 };
34
35 const FPF_SKIAFONTMAP kSkiaFontmap[] = {
36 {0x58c5083, 0xc8d2e345}, {0x5dfade2, 0xe1633081},
37 {0x684317d, 0xe1633081}, {0x14ee2d13, 0xc8d2e345},
38 {0x3918fe2d, 0xbbeeec72}, {0x3b98b31c, 0xe1633081},
39 {0x3d49f40e, 0xe1633081}, {0x432c41c5, 0xe1633081},
40 {0x491b6ad0, 0xe1633081}, {0x5612cab1, 0x59b9f8f1},
41 {0x779ce19d, 0xc8d2e345}, {0x7cc9510b, 0x59b9f8f1},
42 {0x83746053, 0xbbeeec72}, {0xaaa60c03, 0xbbeeec72},
43 {0xbf85ff26, 0xe1633081}, {0xc04fe601, 0xbbeeec72},
44 {0xca3812d5, 0x59b9f8f1}, {0xca383e15, 0x59b9f8f1},
45 {0xcad5eaf6, 0x59b9f8f1}, {0xcb7a04c8, 0xc8d2e345},
46 {0xfb4ce0de, 0xe1633081},
47 };
48
49 const FPF_SKIAFONTMAP kSkiaSansFontMap[] = {
50 {0x58c5083, 0xd5b8d10f}, {0x14ee2d13, 0xd5b8d10f},
51 {0x779ce19d, 0xd5b8d10f}, {0xcb7a04c8, 0xd5b8d10f},
52 {0xfb4ce0de, 0xd5b8d10f},
53 };
54
FPF_SkiaGetSubstFont(uint32_t dwHash,const FPF_SKIAFONTMAP * skFontMap,size_t length)55 uint32_t FPF_SkiaGetSubstFont(uint32_t dwHash,
56 const FPF_SKIAFONTMAP* skFontMap,
57 size_t length) {
58 const FPF_SKIAFONTMAP* pEnd = skFontMap + length;
59 const FPF_SKIAFONTMAP* pFontMap = std::lower_bound(
60 skFontMap, pEnd, dwHash, [](const FPF_SKIAFONTMAP& item, uint32_t hash) {
61 return item.dwFamily < hash;
62 });
63 if (pFontMap < pEnd && pFontMap->dwFamily == dwHash)
64 return pFontMap->dwSubSt;
65 return 0;
66 }
67
68 enum FPF_SKIACHARSET {
69 FPF_SKIACHARSET_Ansi = 1 << 0,
70 FPF_SKIACHARSET_Default = 1 << 1,
71 FPF_SKIACHARSET_Symbol = 1 << 2,
72 FPF_SKIACHARSET_ShiftJIS = 1 << 3,
73 FPF_SKIACHARSET_Korean = 1 << 4,
74 FPF_SKIACHARSET_Johab = 1 << 5,
75 FPF_SKIACHARSET_GB2312 = 1 << 6,
76 FPF_SKIACHARSET_BIG5 = 1 << 7,
77 FPF_SKIACHARSET_Greek = 1 << 8,
78 FPF_SKIACHARSET_Turkish = 1 << 9,
79 FPF_SKIACHARSET_Vietnamese = 1 << 10,
80 FPF_SKIACHARSET_Hebrew = 1 << 11,
81 FPF_SKIACHARSET_Arabic = 1 << 12,
82 FPF_SKIACHARSET_Baltic = 1 << 13,
83 FPF_SKIACHARSET_Cyrillic = 1 << 14,
84 FPF_SKIACHARSET_Thai = 1 << 15,
85 FPF_SKIACHARSET_EeasternEuropean = 1 << 16,
86 FPF_SKIACHARSET_PC = 1 << 17,
87 FPF_SKIACHARSET_OEM = 1 << 18,
88 };
89
FPF_SkiaGetCharset(FX_Charset uCharset)90 uint32_t FPF_SkiaGetCharset(FX_Charset uCharset) {
91 switch (uCharset) {
92 case FX_Charset::kANSI:
93 return FPF_SKIACHARSET_Ansi;
94 case FX_Charset::kDefault:
95 return FPF_SKIACHARSET_Default;
96 case FX_Charset::kSymbol:
97 return FPF_SKIACHARSET_Symbol;
98 case FX_Charset::kShiftJIS:
99 return FPF_SKIACHARSET_ShiftJIS;
100 case FX_Charset::kHangul:
101 return FPF_SKIACHARSET_Korean;
102 case FX_Charset::kChineseSimplified:
103 return FPF_SKIACHARSET_GB2312;
104 case FX_Charset::kChineseTraditional:
105 return FPF_SKIACHARSET_BIG5;
106 case FX_Charset::kMSWin_Greek:
107 return FPF_SKIACHARSET_Greek;
108 case FX_Charset::kMSWin_Turkish:
109 return FPF_SKIACHARSET_Turkish;
110 case FX_Charset::kMSWin_Hebrew:
111 return FPF_SKIACHARSET_Hebrew;
112 case FX_Charset::kMSWin_Arabic:
113 return FPF_SKIACHARSET_Arabic;
114 case FX_Charset::kMSWin_Baltic:
115 return FPF_SKIACHARSET_Baltic;
116 case FX_Charset::kMSWin_Cyrillic:
117 return FPF_SKIACHARSET_Cyrillic;
118 case FX_Charset::kThai:
119 return FPF_SKIACHARSET_Thai;
120 case FX_Charset::kMSWin_EasternEuropean:
121 return FPF_SKIACHARSET_EeasternEuropean;
122 default:
123 return FPF_SKIACHARSET_Default;
124 }
125 }
126
FPF_SKIANormalizeFontName(ByteStringView bsFamily)127 uint32_t FPF_SKIANormalizeFontName(ByteStringView bsFamily) {
128 uint32_t uHashCode = 0;
129 for (unsigned char ch : bsFamily) {
130 if (ch == ' ' || ch == '-' || ch == ',')
131 continue;
132 uHashCode = 31 * uHashCode + tolower(ch);
133 }
134 return uHashCode;
135 }
136
FPF_SKIAGetFamilyHash(ByteStringView bsFamily,uint32_t dwStyle,FX_Charset uCharset)137 uint32_t FPF_SKIAGetFamilyHash(ByteStringView bsFamily,
138 uint32_t dwStyle,
139 FX_Charset uCharset) {
140 ByteString bsFont(bsFamily);
141 if (FontStyleIsForceBold(dwStyle))
142 bsFont += "Bold";
143 if (FontStyleIsItalic(dwStyle))
144 bsFont += "Italic";
145 if (FontStyleIsSerif(dwStyle))
146 bsFont += "Serif";
147 bsFont += static_cast<uint8_t>(uCharset);
148 return FX_HashCode_GetA(bsFont.AsStringView());
149 }
150
FPF_SkiaIsCJK(FX_Charset uCharset)151 bool FPF_SkiaIsCJK(FX_Charset uCharset) {
152 return FX_CharSetIsCJK(uCharset);
153 }
154
FPF_SkiaMaybeSymbol(ByteStringView bsFacename)155 bool FPF_SkiaMaybeSymbol(ByteStringView bsFacename) {
156 ByteString bsName(bsFacename);
157 bsName.MakeLower();
158 return bsName.Contains("symbol");
159 }
160
FPF_SkiaMaybeArabic(ByteStringView bsFacename)161 bool FPF_SkiaMaybeArabic(ByteStringView bsFacename) {
162 ByteString bsName(bsFacename);
163 bsName.MakeLower();
164 return bsName.Contains("arabic");
165 }
166
167 const uint32_t kFPFSkiaFontCharsets[] = {
168 FPF_SKIACHARSET_Ansi,
169 FPF_SKIACHARSET_EeasternEuropean,
170 FPF_SKIACHARSET_Cyrillic,
171 FPF_SKIACHARSET_Greek,
172 FPF_SKIACHARSET_Turkish,
173 FPF_SKIACHARSET_Hebrew,
174 FPF_SKIACHARSET_Arabic,
175 FPF_SKIACHARSET_Baltic,
176 0,
177 0,
178 0,
179 0,
180 0,
181 0,
182 0,
183 0,
184 FPF_SKIACHARSET_Thai,
185 FPF_SKIACHARSET_ShiftJIS,
186 FPF_SKIACHARSET_GB2312,
187 FPF_SKIACHARSET_Korean,
188 FPF_SKIACHARSET_BIG5,
189 FPF_SKIACHARSET_Johab,
190 0,
191 0,
192 0,
193 0,
194 0,
195 0,
196 0,
197 0,
198 FPF_SKIACHARSET_OEM,
199 FPF_SKIACHARSET_Symbol,
200 };
201
FPF_SkiaGetFaceCharset(TT_OS2 * pOS2)202 uint32_t FPF_SkiaGetFaceCharset(TT_OS2* pOS2) {
203 uint32_t dwCharset = 0;
204 if (pOS2) {
205 for (int32_t i = 0; i < 32; i++) {
206 if (pOS2->ulCodePageRange1 & (1 << i))
207 dwCharset |= kFPFSkiaFontCharsets[i];
208 }
209 }
210 dwCharset |= FPF_SKIACHARSET_Default;
211 return dwCharset;
212 }
213
214 } // namespace
215
216 CFPF_SkiaFontMgr::CFPF_SkiaFontMgr() = default;
217
~CFPF_SkiaFontMgr()218 CFPF_SkiaFontMgr::~CFPF_SkiaFontMgr() {
219 m_FamilyFonts.clear();
220 m_FontFaces.clear();
221 }
222
InitFTLibrary()223 bool CFPF_SkiaFontMgr::InitFTLibrary() {
224 if (m_FTLibrary)
225 return true;
226
227 FXFT_LibraryRec* pLibrary = nullptr;
228 FT_Init_FreeType(&pLibrary);
229 if (!pLibrary)
230 return false;
231
232 m_FTLibrary.reset(pLibrary);
233 return true;
234 }
235
LoadSystemFonts()236 void CFPF_SkiaFontMgr::LoadSystemFonts() {
237 if (m_bLoaded)
238 return;
239 ScanPath("/system/fonts");
240 m_bLoaded = true;
241 }
242
CreateFont(ByteStringView bsFamilyname,FX_Charset uCharset,uint32_t dwStyle)243 CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(ByteStringView bsFamilyname,
244 FX_Charset uCharset,
245 uint32_t dwStyle) {
246 uint32_t dwHash = FPF_SKIAGetFamilyHash(bsFamilyname, dwStyle, uCharset);
247 auto family_iter = m_FamilyFonts.find(dwHash);
248 if (family_iter != m_FamilyFonts.end())
249 return family_iter->second.get();
250
251 uint32_t dwFaceName = FPF_SKIANormalizeFontName(bsFamilyname);
252 uint32_t dwSubst =
253 FPF_SkiaGetSubstFont(dwFaceName, kSkiaFontmap, std::size(kSkiaFontmap));
254 uint32_t dwSubstSans = FPF_SkiaGetSubstFont(dwFaceName, kSkiaSansFontMap,
255 std::size(kSkiaSansFontMap));
256 bool bMaybeSymbol = FPF_SkiaMaybeSymbol(bsFamilyname);
257 if (uCharset != FX_Charset::kMSWin_Arabic &&
258 FPF_SkiaMaybeArabic(bsFamilyname)) {
259 uCharset = FX_Charset::kMSWin_Arabic;
260 } else if (uCharset == FX_Charset::kANSI) {
261 uCharset = FX_Charset::kDefault;
262 }
263 int32_t nExpectVal = FPF_SKIAMATCHWEIGHT_NAME1 + FPF_SKIAMATCHWEIGHT_1 * 3 +
264 FPF_SKIAMATCHWEIGHT_2 * 2;
265 const CFPF_SkiaPathFont* pBestFont = nullptr;
266 int32_t nMax = -1;
267 int32_t nGlyphNum = 0;
268 for (const std::unique_ptr<CFPF_SkiaPathFont>& font :
269 pdfium::base::Reversed(m_FontFaces)) {
270 if (!(font->charsets() & FPF_SkiaGetCharset(uCharset)))
271 continue;
272 int32_t nFind = 0;
273 uint32_t dwSysFontName = FPF_SKIANormalizeFontName(font->family());
274 if (dwFaceName == dwSysFontName)
275 nFind += FPF_SKIAMATCHWEIGHT_NAME1;
276 bool bMatchedName = (nFind == FPF_SKIAMATCHWEIGHT_NAME1);
277 if (FontStyleIsForceBold(dwStyle) == FontStyleIsForceBold(font->style()))
278 nFind += FPF_SKIAMATCHWEIGHT_1;
279 if (FontStyleIsItalic(dwStyle) == FontStyleIsItalic(font->style()))
280 nFind += FPF_SKIAMATCHWEIGHT_1;
281 if (FontStyleIsFixedPitch(dwStyle) ==
282 FontStyleIsFixedPitch(font->style())) {
283 nFind += FPF_SKIAMATCHWEIGHT_2;
284 }
285 if (FontStyleIsSerif(dwStyle) == FontStyleIsSerif(font->style()))
286 nFind += FPF_SKIAMATCHWEIGHT_1;
287 if (FontStyleIsScript(dwStyle) == FontStyleIsScript(font->style()))
288 nFind += FPF_SKIAMATCHWEIGHT_2;
289 if (dwSubst == dwSysFontName || dwSubstSans == dwSysFontName) {
290 nFind += FPF_SKIAMATCHWEIGHT_NAME2;
291 bMatchedName = true;
292 }
293 if (uCharset == FX_Charset::kDefault || bMaybeSymbol) {
294 if (nFind > nMax && bMatchedName) {
295 nMax = nFind;
296 pBestFont = font.get();
297 }
298 } else if (FPF_SkiaIsCJK(uCharset)) {
299 if (bMatchedName || font->glyph_num() > nGlyphNum) {
300 pBestFont = font.get();
301 nGlyphNum = font->glyph_num();
302 }
303 } else if (nFind > nMax) {
304 nMax = nFind;
305 pBestFont = font.get();
306 }
307 if (nExpectVal <= nFind) {
308 pBestFont = font.get();
309 break;
310 }
311 }
312 if (!pBestFont)
313 return nullptr;
314
315 auto font =
316 std::make_unique<CFPF_SkiaFont>(this, pBestFont, dwStyle, uCharset);
317 if (!font->IsValid())
318 return nullptr;
319
320 CFPF_SkiaFont* ret = font.get();
321 m_FamilyFonts[dwHash] = std::move(font);
322 return ret;
323 }
324
GetFontFace(ByteStringView bsFile,int32_t iFaceIndex)325 RetainPtr<CFX_Face> CFPF_SkiaFontMgr::GetFontFace(ByteStringView bsFile,
326 int32_t iFaceIndex) {
327 if (bsFile.IsEmpty())
328 return nullptr;
329
330 if (iFaceIndex < 0)
331 return nullptr;
332
333 FT_Open_Args args;
334 args.flags = FT_OPEN_PATHNAME;
335 args.pathname = const_cast<FT_String*>(bsFile.unterminated_c_str());
336 RetainPtr<CFX_Face> face =
337 CFX_Face::Open(m_FTLibrary.get(), &args, iFaceIndex);
338 if (!face)
339 return nullptr;
340
341 FT_Set_Pixel_Sizes(face->GetRec(), 0, 64);
342 return face;
343 }
344
ScanPath(const ByteString & path)345 void CFPF_SkiaFontMgr::ScanPath(const ByteString& path) {
346 std::unique_ptr<FX_Folder> handle = FX_Folder::OpenFolder(path);
347 if (!handle)
348 return;
349
350 ByteString filename;
351 bool bFolder = false;
352 while (handle->GetNextFile(&filename, &bFolder)) {
353 if (bFolder) {
354 if (filename == "." || filename == "..")
355 continue;
356 } else {
357 ByteString ext = filename.Last(4);
358 ext.MakeLower();
359 if (ext != ".ttf" && ext != ".ttc" && ext != ".otf")
360 continue;
361 }
362 ByteString fullpath(path);
363 fullpath += "/";
364 fullpath += filename;
365 if (bFolder)
366 ScanPath(fullpath);
367 else
368 ScanFile(fullpath);
369 }
370 }
371
ScanFile(const ByteString & file)372 void CFPF_SkiaFontMgr::ScanFile(const ByteString& file) {
373 RetainPtr<CFX_Face> face = GetFontFace(file.AsStringView(), 0);
374 if (!face)
375 return;
376
377 m_FontFaces.push_back(ReportFace(face, file));
378 }
379
ReportFace(RetainPtr<CFX_Face> face,const ByteString & file)380 std::unique_ptr<CFPF_SkiaPathFont> CFPF_SkiaFontMgr::ReportFace(
381 RetainPtr<CFX_Face> face,
382 const ByteString& file) {
383 uint32_t dwStyle = 0;
384 if (FXFT_Is_Face_Bold(face->GetRec()))
385 dwStyle |= FXFONT_FORCE_BOLD;
386 if (FXFT_Is_Face_Italic(face->GetRec()))
387 dwStyle |= FXFONT_ITALIC;
388 if (FT_IS_FIXED_WIDTH(face->GetRec()))
389 dwStyle |= FXFONT_FIXED_PITCH;
390 TT_OS2* pOS2 =
391 static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face->GetRec(), ft_sfnt_os2));
392 if (pOS2) {
393 if (pOS2->ulCodePageRange1 & (1 << 31))
394 dwStyle |= FXFONT_SYMBOLIC;
395 if (pOS2->panose[0] == 2) {
396 uint8_t uSerif = pOS2->panose[1];
397 if ((uSerif > 1 && uSerif < 10) || uSerif > 13)
398 dwStyle |= FXFONT_SERIF;
399 }
400 }
401 if (pOS2 && (pOS2->ulCodePageRange1 & (1 << 31)))
402 dwStyle |= FXFONT_SYMBOLIC;
403
404 return std::make_unique<CFPF_SkiaPathFont>(
405 file, FXFT_Get_Face_Family_Name(face->GetRec()), dwStyle,
406 face->GetRec()->face_index, FPF_SkiaGetFaceCharset(pOS2),
407 face->GetRec()->num_glyphs);
408 }
409