• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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