• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 PDFium Authors. All rights reserved.
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 #define FPF_SKIAMATCHWEIGHT_NAME1 62
10 #define FPF_SKIAMATCHWEIGHT_NAME2 60
11 #define FPF_SKIAMATCHWEIGHT_1 16
12 #define FPF_SKIAMATCHWEIGHT_2 8
13 
14 #include <algorithm>
15 
16 #include "core/fxcrt/fx_codepage.h"
17 #include "core/fxcrt/fx_extension.h"
18 #include "core/fxcrt/fx_memory.h"
19 #include "core/fxcrt/fx_system.h"
20 #include "core/fxge/android/cfpf_skiafont.h"
21 #include "core/fxge/android/cfpf_skiafontdescriptor.h"
22 #include "core/fxge/android/cfpf_skiapathfont.h"
23 #include "core/fxge/fx_freetype.h"
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
FPF_SkiaStream_Read(FXFT_Stream stream,unsigned long offset,unsigned char * buffer,unsigned long count)28 static unsigned long FPF_SkiaStream_Read(FXFT_Stream stream,
29                                          unsigned long offset,
30                                          unsigned char* buffer,
31                                          unsigned long count) {
32   if (count == 0)
33     return 0;
34 
35   IFX_SeekableReadStream* pFileRead =
36       static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer);
37   if (!pFileRead)
38     return 0;
39 
40   if (!pFileRead->ReadBlock(buffer, (FX_FILESIZE)offset,
41                             static_cast<size_t>(count)))
42     return 0;
43 
44   return count;
45 }
46 
FPF_SkiaStream_Close(FXFT_Stream stream)47 static void FPF_SkiaStream_Close(FXFT_Stream stream) {}
48 #ifdef __cplusplus
49 };
50 #endif
51 
52 namespace {
53 
54 struct FPF_SKIAFONTMAP {
55   uint32_t dwFamily;
56   uint32_t dwSubSt;
57 };
58 
59 const FPF_SKIAFONTMAP g_SkiaFontmap[] = {
60     {0x58c5083, 0xc8d2e345},  {0x5dfade2, 0xe1633081},
61     {0x684317d, 0xe1633081},  {0x14ee2d13, 0xc8d2e345},
62     {0x3918fe2d, 0xbbeeec72}, {0x3b98b31c, 0xe1633081},
63     {0x3d49f40e, 0xe1633081}, {0x432c41c5, 0xe1633081},
64     {0x491b6ad0, 0xe1633081}, {0x5612cab1, 0x59b9f8f1},
65     {0x779ce19d, 0xc8d2e345}, {0x7cc9510b, 0x59b9f8f1},
66     {0x83746053, 0xbbeeec72}, {0xaaa60c03, 0xbbeeec72},
67     {0xbf85ff26, 0xe1633081}, {0xc04fe601, 0xbbeeec72},
68     {0xca3812d5, 0x59b9f8f1}, {0xca383e15, 0x59b9f8f1},
69     {0xcad5eaf6, 0x59b9f8f1}, {0xcb7a04c8, 0xc8d2e345},
70     {0xfb4ce0de, 0xe1633081},
71 };
72 
73 const FPF_SKIAFONTMAP g_SkiaSansFontMap[] = {
74     {0x58c5083, 0xd5b8d10f},  {0x14ee2d13, 0xd5b8d10f},
75     {0x779ce19d, 0xd5b8d10f}, {0xcb7a04c8, 0xd5b8d10f},
76     {0xfb4ce0de, 0xd5b8d10f},
77 };
78 
FPF_SkiaGetSubstFont(uint32_t dwHash,const FPF_SKIAFONTMAP * skFontMap,size_t length)79 uint32_t FPF_SkiaGetSubstFont(uint32_t dwHash,
80                               const FPF_SKIAFONTMAP* skFontMap,
81                               size_t length) {
82   const FPF_SKIAFONTMAP* pEnd = skFontMap + length;
83   const FPF_SKIAFONTMAP* pFontMap = std::lower_bound(
84       skFontMap, pEnd, dwHash, [](const FPF_SKIAFONTMAP& item, uint32_t hash) {
85         return item.dwFamily < hash;
86       });
87   if (pFontMap < pEnd && pFontMap->dwFamily == dwHash)
88     return pFontMap->dwSubSt;
89   return 0;
90 }
91 
FPF_GetHashCode_StringA(const char * pStr,int32_t iLength)92 uint32_t FPF_GetHashCode_StringA(const char* pStr, int32_t iLength) {
93   if (!pStr)
94     return 0;
95   if (iLength < 0)
96     iLength = strlen(pStr);
97   const char* pStrEnd = pStr + iLength;
98   uint32_t uHashCode = 0;
99   while (pStr < pStrEnd)
100     uHashCode = 31 * uHashCode + FXSYS_tolower(*pStr++);
101   return uHashCode;
102 }
103 
104 enum FPF_SKIACHARSET {
105   FPF_SKIACHARSET_Ansi = 1 << 0,
106   FPF_SKIACHARSET_Default = 1 << 1,
107   FPF_SKIACHARSET_Symbol = 1 << 2,
108   FPF_SKIACHARSET_ShiftJIS = 1 << 3,
109   FPF_SKIACHARSET_Korean = 1 << 4,
110   FPF_SKIACHARSET_Johab = 1 << 5,
111   FPF_SKIACHARSET_GB2312 = 1 << 6,
112   FPF_SKIACHARSET_BIG5 = 1 << 7,
113   FPF_SKIACHARSET_Greek = 1 << 8,
114   FPF_SKIACHARSET_Turkish = 1 << 9,
115   FPF_SKIACHARSET_Vietnamese = 1 << 10,
116   FPF_SKIACHARSET_Hebrew = 1 << 11,
117   FPF_SKIACHARSET_Arabic = 1 << 12,
118   FPF_SKIACHARSET_Baltic = 1 << 13,
119   FPF_SKIACHARSET_Cyrillic = 1 << 14,
120   FPF_SKIACHARSET_Thai = 1 << 15,
121   FPF_SKIACHARSET_EeasternEuropean = 1 << 16,
122   FPF_SKIACHARSET_PC = 1 << 17,
123   FPF_SKIACHARSET_OEM = 1 << 18,
124 };
125 
FPF_SkiaGetCharset(uint8_t uCharset)126 uint32_t FPF_SkiaGetCharset(uint8_t uCharset) {
127   switch (uCharset) {
128     case FX_CHARSET_ANSI:
129       return FPF_SKIACHARSET_Ansi;
130     case FX_CHARSET_Default:
131       return FPF_SKIACHARSET_Default;
132     case FX_CHARSET_Symbol:
133       return FPF_SKIACHARSET_Symbol;
134     case FX_CHARSET_ShiftJIS:
135       return FPF_SKIACHARSET_ShiftJIS;
136     case FX_CHARSET_Hangul:
137       return FPF_SKIACHARSET_Korean;
138     case FX_CHARSET_ChineseSimplified:
139       return FPF_SKIACHARSET_GB2312;
140     case FX_CHARSET_ChineseTraditional:
141       return FPF_SKIACHARSET_BIG5;
142     case FX_CHARSET_MSWin_Greek:
143       return FPF_SKIACHARSET_Greek;
144     case FX_CHARSET_MSWin_Turkish:
145       return FPF_SKIACHARSET_Turkish;
146     case FX_CHARSET_MSWin_Hebrew:
147       return FPF_SKIACHARSET_Hebrew;
148     case FX_CHARSET_MSWin_Arabic:
149       return FPF_SKIACHARSET_Arabic;
150     case FX_CHARSET_MSWin_Baltic:
151       return FPF_SKIACHARSET_Baltic;
152     case FX_CHARSET_MSWin_Cyrillic:
153       return FPF_SKIACHARSET_Cyrillic;
154     case FX_CHARSET_Thai:
155       return FPF_SKIACHARSET_Thai;
156     case FX_CHARSET_MSWin_EasternEuropean:
157       return FPF_SKIACHARSET_EeasternEuropean;
158   }
159   return FPF_SKIACHARSET_Default;
160 }
161 
FPF_SKIANormalizeFontName(const ByteStringView & bsfamily)162 uint32_t FPF_SKIANormalizeFontName(const ByteStringView& bsfamily) {
163   uint32_t dwHash = 0;
164   int32_t iLength = bsfamily.GetLength();
165   const char* pBuffer = bsfamily.unterminated_c_str();
166   for (int32_t i = 0; i < iLength; i++) {
167     char ch = pBuffer[i];
168     if (ch == ' ' || ch == '-' || ch == ',')
169       continue;
170     dwHash = 31 * dwHash + FXSYS_tolower(ch);
171   }
172   return dwHash;
173 }
174 
FPF_SKIAGetFamilyHash(const ByteStringView & bsFamily,uint32_t dwStyle,uint8_t uCharset)175 uint32_t FPF_SKIAGetFamilyHash(const ByteStringView& bsFamily,
176                                uint32_t dwStyle,
177                                uint8_t uCharset) {
178   ByteString bsFont(bsFamily);
179   if (FontStyleIsBold(dwStyle))
180     bsFont += "Bold";
181   if (FontStyleIsItalic(dwStyle))
182     bsFont += "Italic";
183   if (FontStyleIsSerif(dwStyle))
184     bsFont += "Serif";
185   bsFont += uCharset;
186   return FPF_GetHashCode_StringA(bsFont.c_str(), bsFont.GetLength());
187 }
188 
FPF_SkiaIsCJK(uint8_t uCharset)189 bool FPF_SkiaIsCJK(uint8_t uCharset) {
190   return (uCharset == FX_CHARSET_ChineseSimplified) ||
191          (uCharset == FX_CHARSET_ChineseTraditional) ||
192          (uCharset == FX_CHARSET_Hangul) || (uCharset == FX_CHARSET_ShiftJIS);
193 }
194 
FPF_SkiaMaybeSymbol(const ByteStringView & bsFacename)195 bool FPF_SkiaMaybeSymbol(const ByteStringView& bsFacename) {
196   ByteString bsName(bsFacename);
197   bsName.MakeLower();
198   return bsName.Contains("symbol");
199 }
200 
FPF_SkiaMaybeArabic(const ByteStringView & bsFacename)201 bool FPF_SkiaMaybeArabic(const ByteStringView& bsFacename) {
202   ByteString bsName(bsFacename);
203   bsName.MakeLower();
204   return bsName.Contains("arabic");
205 }
206 
207 const uint32_t g_FPFSkiaFontCharsets[] = {
208     FPF_SKIACHARSET_Ansi,
209     FPF_SKIACHARSET_EeasternEuropean,
210     FPF_SKIACHARSET_Cyrillic,
211     FPF_SKIACHARSET_Greek,
212     FPF_SKIACHARSET_Turkish,
213     FPF_SKIACHARSET_Hebrew,
214     FPF_SKIACHARSET_Arabic,
215     FPF_SKIACHARSET_Baltic,
216     0,
217     0,
218     0,
219     0,
220     0,
221     0,
222     0,
223     0,
224     FPF_SKIACHARSET_Thai,
225     FPF_SKIACHARSET_ShiftJIS,
226     FPF_SKIACHARSET_GB2312,
227     FPF_SKIACHARSET_Korean,
228     FPF_SKIACHARSET_BIG5,
229     FPF_SKIACHARSET_Johab,
230     0,
231     0,
232     0,
233     0,
234     0,
235     0,
236     0,
237     0,
238     FPF_SKIACHARSET_OEM,
239     FPF_SKIACHARSET_Symbol,
240 };
241 
FPF_SkiaGetFaceCharset(TT_OS2 * pOS2)242 uint32_t FPF_SkiaGetFaceCharset(TT_OS2* pOS2) {
243   uint32_t dwCharset = 0;
244   if (pOS2) {
245     for (int32_t i = 0; i < 32; i++) {
246       if (pOS2->ulCodePageRange1 & (1 << i))
247         dwCharset |= g_FPFSkiaFontCharsets[i];
248     }
249   }
250   dwCharset |= FPF_SKIACHARSET_Default;
251   return dwCharset;
252 }
253 
254 }  // namespace
255 
CFPF_SkiaFontMgr()256 CFPF_SkiaFontMgr::CFPF_SkiaFontMgr() : m_bLoaded(false), m_FTLibrary(nullptr) {}
257 
~CFPF_SkiaFontMgr()258 CFPF_SkiaFontMgr::~CFPF_SkiaFontMgr() {
259   for (const auto& pair : m_FamilyFonts) {
260     if (pair.second)
261       pair.second->Release();
262   }
263   m_FamilyFonts.clear();
264   for (auto it = m_FontFaces.begin(); it != m_FontFaces.end(); ++it)
265     delete *it;
266   m_FontFaces.clear();
267   if (m_FTLibrary)
268     FXFT_Done_FreeType(m_FTLibrary);
269 }
270 
InitFTLibrary()271 bool CFPF_SkiaFontMgr::InitFTLibrary() {
272   if (!m_FTLibrary)
273     FXFT_Init_FreeType(&m_FTLibrary);
274   return !!m_FTLibrary;
275 }
276 
LoadSystemFonts()277 void CFPF_SkiaFontMgr::LoadSystemFonts() {
278   if (m_bLoaded)
279     return;
280   ScanPath("/system/fonts");
281   m_bLoaded = true;
282 }
283 
CreateFont(const ByteStringView & bsFamilyname,uint8_t uCharset,uint32_t dwStyle,uint32_t dwMatch)284 CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(const ByteStringView& bsFamilyname,
285                                             uint8_t uCharset,
286                                             uint32_t dwStyle,
287                                             uint32_t dwMatch) {
288   uint32_t dwHash = FPF_SKIAGetFamilyHash(bsFamilyname, dwStyle, uCharset);
289   auto it = m_FamilyFonts.find(dwHash);
290   if (it != m_FamilyFonts.end() && it->second)
291     return it->second->Retain();
292 
293   uint32_t dwFaceName = FPF_SKIANormalizeFontName(bsFamilyname);
294   uint32_t dwSubst = FPF_SkiaGetSubstFont(dwFaceName, g_SkiaFontmap,
295                                           FX_ArraySize(g_SkiaFontmap));
296   uint32_t dwSubstSans = FPF_SkiaGetSubstFont(dwFaceName, g_SkiaSansFontMap,
297                                               FX_ArraySize(g_SkiaSansFontMap));
298   bool bMaybeSymbol = FPF_SkiaMaybeSymbol(bsFamilyname);
299   if (uCharset != FX_CHARSET_MSWin_Arabic &&
300       FPF_SkiaMaybeArabic(bsFamilyname)) {
301     uCharset = FX_CHARSET_MSWin_Arabic;
302   } else if (uCharset == FX_CHARSET_ANSI &&
303              (dwMatch & FPF_MATCHFONT_REPLACEANSI)) {
304     uCharset = FX_CHARSET_Default;
305   }
306   int32_t nExpectVal = FPF_SKIAMATCHWEIGHT_NAME1 + FPF_SKIAMATCHWEIGHT_1 * 3 +
307                        FPF_SKIAMATCHWEIGHT_2 * 2;
308   CFPF_SkiaFontDescriptor* pBestFontDes = nullptr;
309   int32_t nMax = -1;
310   int32_t nGlyphNum = 0;
311   for (auto it = m_FontFaces.rbegin(); it != m_FontFaces.rend(); ++it) {
312     CFPF_SkiaPathFont* pFontDes = static_cast<CFPF_SkiaPathFont*>(*it);
313     if (!(pFontDes->m_dwCharsets & FPF_SkiaGetCharset(uCharset)))
314       continue;
315     int32_t nFind = 0;
316     uint32_t dwSysFontName = FPF_SKIANormalizeFontName(pFontDes->m_pFamily);
317     if (dwFaceName == dwSysFontName)
318       nFind += FPF_SKIAMATCHWEIGHT_NAME1;
319     bool bMatchedName = (nFind == FPF_SKIAMATCHWEIGHT_NAME1);
320     if (FontStyleIsBold(dwStyle) == FontStyleIsBold(pFontDes->m_dwStyle))
321       nFind += FPF_SKIAMATCHWEIGHT_1;
322     if (FontStyleIsItalic(dwStyle) == FontStyleIsItalic(pFontDes->m_dwStyle))
323       nFind += FPF_SKIAMATCHWEIGHT_1;
324     if (FontStyleIsFixedPitch(dwStyle) ==
325         FontStyleIsFixedPitch(pFontDes->m_dwStyle)) {
326       nFind += FPF_SKIAMATCHWEIGHT_2;
327     }
328     if (FontStyleIsSerif(dwStyle) == FontStyleIsSerif(pFontDes->m_dwStyle))
329       nFind += FPF_SKIAMATCHWEIGHT_1;
330     if (FontStyleIsScript(dwStyle) == FontStyleIsScript(pFontDes->m_dwStyle))
331       nFind += FPF_SKIAMATCHWEIGHT_2;
332     if (dwSubst == dwSysFontName || dwSubstSans == dwSysFontName) {
333       nFind += FPF_SKIAMATCHWEIGHT_NAME2;
334       bMatchedName = true;
335     }
336     if (uCharset == FX_CHARSET_Default || bMaybeSymbol) {
337       if (nFind > nMax && bMatchedName) {
338         nMax = nFind;
339         pBestFontDes = *it;
340       }
341     } else if (FPF_SkiaIsCJK(uCharset)) {
342       if (bMatchedName || pFontDes->m_iGlyphNum > nGlyphNum) {
343         pBestFontDes = *it;
344         nGlyphNum = pFontDes->m_iGlyphNum;
345       }
346     } else if (nFind > nMax) {
347       nMax = nFind;
348       pBestFontDes = *it;
349     }
350     if (nExpectVal <= nFind) {
351       pBestFontDes = *it;
352       break;
353     }
354   }
355   if (pBestFontDes) {
356     CFPF_SkiaFont* pFont = new CFPF_SkiaFont;
357     if (pFont->InitFont(this, pBestFontDes, bsFamilyname, dwStyle, uCharset)) {
358       m_FamilyFonts[dwHash] = pFont;
359       return pFont->Retain();
360     }
361     pFont->Release();
362   }
363   return nullptr;
364 }
365 
GetFontFace(const RetainPtr<IFX_SeekableReadStream> & pFileRead,int32_t iFaceIndex)366 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(
367     const RetainPtr<IFX_SeekableReadStream>& pFileRead,
368     int32_t iFaceIndex) {
369   if (!pFileRead)
370     return nullptr;
371   if (pFileRead->GetSize() == 0)
372     return nullptr;
373   if (iFaceIndex < 0)
374     return nullptr;
375   FXFT_StreamRec streamRec;
376   memset(&streamRec, 0, sizeof(FXFT_StreamRec));
377   streamRec.size = pFileRead->GetSize();
378   streamRec.descriptor.pointer = static_cast<void*>(pFileRead.Get());
379   streamRec.read = FPF_SkiaStream_Read;
380   streamRec.close = FPF_SkiaStream_Close;
381   FXFT_Open_Args args;
382   args.flags = FT_OPEN_STREAM;
383   args.stream = &streamRec;
384   FXFT_Face face;
385   if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face))
386     return nullptr;
387   FXFT_Set_Pixel_Sizes(face, 0, 64);
388   return face;
389 }
390 
GetFontFace(const ByteStringView & bsFile,int32_t iFaceIndex)391 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(const ByteStringView& bsFile,
392                                         int32_t iFaceIndex) {
393   if (bsFile.IsEmpty())
394     return nullptr;
395   if (iFaceIndex < 0)
396     return nullptr;
397   FXFT_Open_Args args;
398   args.flags = FT_OPEN_PATHNAME;
399   args.pathname = const_cast<FT_String*>(bsFile.unterminated_c_str());
400   FXFT_Face face;
401   if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face))
402     return nullptr;
403   FXFT_Set_Pixel_Sizes(face, 0, 64);
404   return face;
405 }
406 
GetFontFace(const uint8_t * pBuffer,size_t szBuffer,int32_t iFaceIndex)407 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(const uint8_t* pBuffer,
408                                         size_t szBuffer,
409                                         int32_t iFaceIndex) {
410   if (!pBuffer || szBuffer < 1)
411     return nullptr;
412   if (iFaceIndex < 0)
413     return nullptr;
414   FXFT_Open_Args args;
415   args.flags = FT_OPEN_MEMORY;
416   args.memory_base = pBuffer;
417   args.memory_size = szBuffer;
418   FXFT_Face face;
419   if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face))
420     return nullptr;
421   FXFT_Set_Pixel_Sizes(face, 0, 64);
422   return face;
423 }
424 
ScanPath(const ByteString & path)425 void CFPF_SkiaFontMgr::ScanPath(const ByteString& path) {
426   DIR* handle = FX_OpenFolder(path.c_str());
427   if (!handle)
428     return;
429   ByteString filename;
430   bool bFolder = false;
431   while (FX_GetNextFile(handle, &filename, &bFolder)) {
432     if (bFolder) {
433       if (filename == "." || filename == "..")
434         continue;
435     } else {
436       ByteString ext = filename.Right(4);
437       ext.MakeLower();
438       if (ext != ".ttf" && ext != ".ttc" && ext != ".otf")
439         continue;
440     }
441     ByteString fullpath(path);
442     fullpath += "/";
443     fullpath += filename;
444     if (bFolder)
445       ScanPath(fullpath);
446     else
447       ScanFile(fullpath);
448   }
449   FX_CloseFolder(handle);
450 }
451 
ScanFile(const ByteString & file)452 void CFPF_SkiaFontMgr::ScanFile(const ByteString& file) {
453   FXFT_Face face = GetFontFace(file.AsStringView());
454   if (!face)
455     return;
456   CFPF_SkiaPathFont* pFontDesc = new CFPF_SkiaPathFont;
457   pFontDesc->SetPath(file.c_str());
458   ReportFace(face, pFontDesc);
459   m_FontFaces.push_back(pFontDesc);
460   FXFT_Done_Face(face);
461 }
462 
ReportFace(FXFT_Face face,CFPF_SkiaFontDescriptor * pFontDesc)463 void CFPF_SkiaFontMgr::ReportFace(FXFT_Face face,
464                                   CFPF_SkiaFontDescriptor* pFontDesc) {
465   if (!face || !pFontDesc)
466     return;
467   pFontDesc->SetFamily(FXFT_Get_Face_Family_Name(face));
468   if (FXFT_Is_Face_Bold(face))
469     pFontDesc->m_dwStyle |= FXFONT_BOLD;
470   if (FXFT_Is_Face_Italic(face))
471     pFontDesc->m_dwStyle |= FXFONT_ITALIC;
472   if (FT_IS_FIXED_WIDTH(face))
473     pFontDesc->m_dwStyle |= FXFONT_FIXED_PITCH;
474   TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
475   if (pOS2) {
476     if (pOS2->ulCodePageRange1 & (1 << 31))
477       pFontDesc->m_dwStyle |= FXFONT_SYMBOLIC;
478     if (pOS2->panose[0] == 2) {
479       uint8_t uSerif = pOS2->panose[1];
480       if ((uSerif > 1 && uSerif < 10) || uSerif > 13)
481         pFontDesc->m_dwStyle |= FXFONT_SERIF;
482     }
483   }
484   if (pOS2 && (pOS2->ulCodePageRange1 & (1 << 31)))
485     pFontDesc->m_dwStyle |= FXFONT_SYMBOLIC;
486   pFontDesc->m_dwCharsets = FPF_SkiaGetFaceCharset(pOS2);
487   pFontDesc->m_iFaceIndex = face->face_index;
488   pFontDesc->m_iGlyphNum = face->num_glyphs;
489 }
490