Home | History | Annotate | Download | only in android
      1 // Copyright 2014 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 "fx_fpf.h"
      8 #if _FX_OS_ == _FX_ANDROID_
      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 #include "fpf_skiafontmgr.h"
     14 #include "fpf_skiafont.h"
     15 #ifdef __cplusplus
     16 extern "C" {
     17 #endif
     18 static unsigned long FPF_SkiaStream_Read(FXFT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count)
     19 {
     20     IFX_FileRead *pFileRead = (IFX_FileRead*)stream->descriptor.pointer;
     21     if (!pFileRead) {
     22         return 0;
     23     }
     24     if (count > 0) {
     25         if (pFileRead->ReadBlock(buffer, (FX_FILESIZE)offset, (size_t)count) != count) {
     26             return 0;
     27         }
     28     }
     29     return count;
     30 }
     31 static void FPF_SkiaStream_Close(FXFT_Stream stream)
     32 {
     33 }
     34 #ifdef __cplusplus
     35 };
     36 #endif
     37 typedef struct _FPF_SKIAFONTMAP {
     38     FX_DWORD	dwFamily;
     39     FX_DWORD	dwSubSt;
     40 } FPF_SKIAFONTMAP, *FPF_LPSKIAFONTMAP;
     41 typedef FPF_SKIAFONTMAP const * FPF_LPCSKIAFONTMAP;
     42 static const FPF_SKIAFONTMAP g_SkiaFontmap[] = {
     43     {0x58c5083,		0xc8d2e345},
     44     {0x5dfade2,		0xe1633081},
     45     {0x684317d,		0xe1633081},
     46     {0x14ee2d13,	0xc8d2e345},
     47     {0x3918fe2d,	0xbbeeec72},
     48     {0x3b98b31c,	0xe1633081},
     49     {0x3d49f40e,	0xe1633081},
     50     {0x432c41c5,	0xe1633081},
     51     {0x491b6ad0,	0xe1633081},
     52     {0x5612cab1,	0x59b9f8f1},
     53     {0x779ce19d,	0xc8d2e345},
     54     {0x7cc9510b,	0x59b9f8f1},
     55     {0x83746053,	0xbbeeec72},
     56     {0xaaa60c03,	0xbbeeec72},
     57     {0xbf85ff26,	0xe1633081},
     58     {0xc04fe601,	0xbbeeec72},
     59     {0xca3812d5,	0x59b9f8f1},
     60     {0xca383e15,	0x59b9f8f1},
     61     {0xcad5eaf6,	0x59b9f8f1},
     62     {0xcb7a04c8,	0xc8d2e345},
     63     {0xfb4ce0de,	0xe1633081},
     64 };
     65 FX_DWORD FPF_SkiaGetSubstFont(FX_DWORD dwHash)
     66 {
     67     FX_INT32 iStart = 0;
     68     FX_INT32 iEnd = sizeof(g_SkiaFontmap) / sizeof(FPF_SKIAFONTMAP);
     69     while (iStart <= iEnd) {
     70         FX_INT32 iMid = (iStart + iEnd) / 2;
     71         FPF_LPCSKIAFONTMAP pItem = &g_SkiaFontmap[iMid];
     72         if (dwHash < pItem->dwFamily) {
     73             iEnd = iMid - 1;
     74         } else if (dwHash > pItem->dwFamily) {
     75             iStart = iMid + 1;
     76         } else {
     77             return pItem->dwSubSt;
     78         }
     79     }
     80     return NULL;
     81 }
     82 static const FPF_SKIAFONTMAP g_SkiaSansFontMap[] = {
     83     {0x58c5083,		0xd5b8d10f},
     84     {0x14ee2d13,	0xd5b8d10f},
     85     {0x779ce19d,	0xd5b8d10f},
     86     {0xcb7a04c8,	0xd5b8d10f},
     87     {0xfb4ce0de,	0xd5b8d10f},
     88 };
     89 FX_DWORD FPF_SkiaGetSansFont(FX_DWORD dwHash)
     90 {
     91     FX_INT32 iStart = 0;
     92     FX_INT32 iEnd = sizeof(g_SkiaSansFontMap) / sizeof(FPF_SKIAFONTMAP);
     93     while (iStart <= iEnd) {
     94         FX_INT32 iMid = (iStart + iEnd) / 2;
     95         FPF_LPCSKIAFONTMAP pItem = &g_SkiaSansFontMap[iMid];
     96         if (dwHash < pItem->dwFamily) {
     97             iEnd = iMid - 1;
     98         } else if (dwHash > pItem->dwFamily) {
     99             iStart = iMid + 1;
    100         } else {
    101             return pItem->dwSubSt;
    102         }
    103     }
    104     return 0;
    105 }
    106 static FX_UINT32 FPF_GetHashCode_StringA(FX_LPCSTR pStr, FX_INT32 iLength, FX_BOOL bIgnoreCase = FALSE)
    107 {
    108     if (!pStr) {
    109         return 0;
    110     }
    111     if (iLength < 0) {
    112         iLength = FXSYS_strlen(pStr);
    113     }
    114     FX_LPCSTR pStrEnd = pStr + iLength;
    115     FX_UINT32 uHashCode = 0;
    116     if (bIgnoreCase) {
    117         while (pStr < pStrEnd) {
    118             uHashCode = 31 * uHashCode + FXSYS_tolower(*pStr++);
    119         }
    120     } else {
    121         while (pStr < pStrEnd) {
    122             uHashCode = 31 * uHashCode + *pStr ++;
    123         }
    124     }
    125     return uHashCode;
    126 }
    127 enum FPF_SKIACHARSET {
    128     FPF_SKIACHARSET_Ansi			= 1 << 0,
    129     FPF_SKIACHARSET_Default			= 1 << 1,
    130     FPF_SKIACHARSET_Symbol			= 1 << 2,
    131     FPF_SKIACHARSET_ShiftJIS		= 1 << 3,
    132     FPF_SKIACHARSET_Korean			= 1 << 4,
    133     FPF_SKIACHARSET_Johab			= 1 << 5,
    134     FPF_SKIACHARSET_GB2312			= 1 << 6,
    135     FPF_SKIACHARSET_BIG5			= 1 << 7,
    136     FPF_SKIACHARSET_Greek			= 1 << 8,
    137     FPF_SKIACHARSET_Turkish			= 1 << 9,
    138     FPF_SKIACHARSET_Vietnamese		= 1 << 10,
    139     FPF_SKIACHARSET_Hebrew			= 1 << 11,
    140     FPF_SKIACHARSET_Arabic			= 1 << 12,
    141     FPF_SKIACHARSET_Baltic			= 1 << 13,
    142     FPF_SKIACHARSET_Cyrillic		= 1 << 14,
    143     FPF_SKIACHARSET_Thai			= 1 << 15,
    144     FPF_SKIACHARSET_EeasternEuropean = 1 << 16,
    145     FPF_SKIACHARSET_PC				= 1 << 17,
    146     FPF_SKIACHARSET_OEM				= 1 << 18,
    147 };
    148 static FX_DWORD FPF_SkiaGetCharset(FX_BYTE uCharset)
    149 {
    150     switch (uCharset) {
    151         case FXFONT_ANSI_CHARSET:
    152             return FPF_SKIACHARSET_Ansi;
    153         case FXFONT_DEFAULT_CHARSET:
    154             return FPF_SKIACHARSET_Default;
    155         case FXFONT_SYMBOL_CHARSET:
    156             return FPF_SKIACHARSET_Symbol;
    157         case FXFONT_SHIFTJIS_CHARSET:
    158             return FPF_SKIACHARSET_ShiftJIS;
    159         case FXFONT_HANGEUL_CHARSET:
    160             return FPF_SKIACHARSET_Korean;
    161         case FXFONT_GB2312_CHARSET:
    162             return FPF_SKIACHARSET_GB2312;
    163         case FXFONT_CHINESEBIG5_CHARSET:
    164             return FPF_SKIACHARSET_BIG5;
    165         case FXFONT_GREEK_CHARSET:
    166             return FPF_SKIACHARSET_Greek;
    167         case FXFONT_TURKISH_CHARSET:
    168             return FPF_SKIACHARSET_Turkish;
    169         case FXFONT_HEBREW_CHARSET:
    170             return FPF_SKIACHARSET_Hebrew;
    171         case FXFONT_ARABIC_CHARSET:
    172             return FPF_SKIACHARSET_Arabic;
    173         case FXFONT_BALTIC_CHARSET:
    174             return FPF_SKIACHARSET_Baltic;
    175         case FXFONT_RUSSIAN_CHARSET:
    176             return FPF_SKIACHARSET_Cyrillic;
    177         case FXFONT_THAI_CHARSET:
    178             return FPF_SKIACHARSET_Thai;
    179         case FXFONT_EASTEUROPE_CHARSET:
    180             return FPF_SKIACHARSET_EeasternEuropean;
    181     }
    182     return FPF_SKIACHARSET_Default;
    183 }
    184 static FX_DWORD FPF_SKIANormalizeFontName(FX_BSTR bsfamily)
    185 {
    186     FX_DWORD dwHash = 0;
    187     FX_INT32 iLength = bsfamily.GetLength();
    188     FX_LPCSTR pBuffer = bsfamily.GetCStr();
    189     for (FX_INT32 i = 0; i < iLength; i++) {
    190         FX_CHAR ch = pBuffer[i];
    191         if (ch == ' ' || ch == '-' || ch == ',') {
    192             continue;
    193         }
    194         dwHash = 31 * dwHash + FXSYS_tolower(ch);
    195     }
    196     return dwHash;
    197 }
    198 static FX_DWORD	FPF_SKIAGetFamilyHash(FX_BSTR bsFamily, FX_DWORD dwStyle, FX_BYTE uCharset)
    199 {
    200     CFX_ByteString bsFont(bsFamily);
    201     if (dwStyle & FXFONT_BOLD) {
    202         bsFont += "Bold";
    203     }
    204     if (dwStyle & FXFONT_ITALIC) {
    205         bsFont += "Italic";
    206     }
    207     if (dwStyle & FXFONT_SERIF)	{
    208         bsFont += "Serif";
    209     }
    210     bsFont += uCharset;
    211     return FPF_GetHashCode_StringA((FX_LPCSTR)bsFont, bsFont.GetLength(), TRUE);
    212 }
    213 static FX_BOOL FPF_SkiaIsCJK(FX_BYTE uCharset)
    214 {
    215     return (uCharset == FXFONT_GB2312_CHARSET) || (uCharset == FXFONT_CHINESEBIG5_CHARSET)
    216            || (uCharset == FXFONT_HANGEUL_CHARSET) || (uCharset == FXFONT_SHIFTJIS_CHARSET);
    217 }
    218 static FX_BOOL FPF_SkiaMaybeSymbol(FX_BSTR bsFacename)
    219 {
    220     CFX_ByteString bsName = bsFacename;
    221     bsName.MakeLower();
    222     return bsName.Find("symbol") > -1;
    223 }
    224 static FX_BOOL FPF_SkiaMaybeArabic(FX_BSTR bsFacename)
    225 {
    226     CFX_ByteString bsName = bsFacename;
    227     bsName.MakeLower();
    228     return bsName.Find("arabic") > -1;
    229 }
    230 CFPF_SkiaFontMgr::CFPF_SkiaFontMgr()
    231     : m_bLoaded(FALSE), m_FTLibrary(NULL)
    232 {
    233 }
    234 CFPF_SkiaFontMgr::~CFPF_SkiaFontMgr()
    235 {
    236     void *pkey = NULL;
    237     CFPF_SkiaFont *pValue = NULL;
    238     FX_POSITION pos = m_FamilyFonts.GetStartPosition();
    239     while (pos) {
    240         m_FamilyFonts.GetNextAssoc(pos, pkey, (void*&)pValue);
    241         if (pValue) {
    242             pValue->Release();
    243         }
    244     }
    245     m_FamilyFonts.RemoveAll();
    246     for (FX_INT32 i = m_FontFaces.GetUpperBound(); i >= 0; i--) {
    247         CFPF_SkiaFontDescriptor *pFont = (CFPF_SkiaFontDescriptor*)m_FontFaces.ElementAt(i);
    248         if (pFont) {
    249             delete pFont;
    250         }
    251     }
    252     m_FontFaces.RemoveAll();
    253     if (m_FTLibrary) {
    254         FXFT_Done_FreeType(m_FTLibrary);
    255     }
    256 }
    257 FX_BOOL CFPF_SkiaFontMgr::InitFTLibrary()
    258 {
    259     if (m_FTLibrary == NULL) {
    260         FXFT_Init_FreeType(&m_FTLibrary);
    261     }
    262     return m_FTLibrary != NULL;
    263 }
    264 void CFPF_SkiaFontMgr::LoadSystemFonts()
    265 {
    266     if (m_bLoaded) {
    267         return;
    268     }
    269     ScanPath(FX_BSTRC("/system/fonts"));
    270     OutputSystemFonts();
    271     m_bLoaded = TRUE;
    272 }
    273 void CFPF_SkiaFontMgr::LoadPrivateFont(IFX_FileRead* pFontFile)
    274 {
    275 }
    276 void CFPF_SkiaFontMgr::LoadPrivateFont(FX_BSTR bsFileName)
    277 {
    278 }
    279 void CFPF_SkiaFontMgr::LoadPrivateFont(FX_LPVOID pBuffer, size_t szBuffer)
    280 {
    281 }
    282 IFPF_Font* CFPF_SkiaFontMgr::CreateFont(FX_BSTR bsFamilyname, FX_BYTE uCharset, FX_DWORD dwStyle, FX_DWORD dwMatch)
    283 {
    284     FX_DWORD dwHash = FPF_SKIAGetFamilyHash(bsFamilyname, dwStyle, uCharset);
    285     IFPF_Font *pFont = NULL;
    286     if (m_FamilyFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) {
    287         if (pFont) {
    288             return pFont->Retain();
    289         }
    290     }
    291     FX_DWORD dwFaceName = FPF_SKIANormalizeFontName(bsFamilyname);
    292     FX_DWORD dwSubst = FPF_SkiaGetSubstFont(dwFaceName);
    293     FX_DWORD dwSubstSans = FPF_SkiaGetSansFont(dwFaceName);
    294     FX_BOOL bMaybeSymbol = FPF_SkiaMaybeSymbol(bsFamilyname);
    295     if (uCharset != FXFONT_ARABIC_CHARSET && FPF_SkiaMaybeArabic(bsFamilyname)) {
    296         uCharset = FXFONT_ARABIC_CHARSET;
    297     } else if (uCharset == FXFONT_ANSI_CHARSET && (dwMatch & FPF_MATCHFONT_REPLACEANSI)) {
    298         uCharset = FXFONT_DEFAULT_CHARSET;
    299     }
    300     FX_INT32 nExpectVal = FPF_SKIAMATCHWEIGHT_NAME1 + FPF_SKIAMATCHWEIGHT_1 * 3 + FPF_SKIAMATCHWEIGHT_2 * 2;
    301     FX_INT32 nItem = -1;
    302     FX_INT32 nMax = -1;
    303     FX_INT32 nGlyphNum = 0;
    304     for (FX_INT32 i = m_FontFaces.GetUpperBound(); i >= 0; i--) {
    305         CFPF_SkiaPathFont *pFontDes = (CFPF_SkiaPathFont*)m_FontFaces.ElementAt(i);
    306         if(!(pFontDes->m_dwCharsets & FPF_SkiaGetCharset(uCharset))) {
    307             continue;
    308         }
    309         FX_INT32 nFind = 0;
    310         FX_DWORD dwSysFontName = FPF_SKIANormalizeFontName(pFontDes->m_pFamily);
    311         if (dwFaceName == dwSysFontName) {
    312             nFind += FPF_SKIAMATCHWEIGHT_NAME1;
    313         }
    314         FX_BOOL bMatchedName = (nFind == FPF_SKIAMATCHWEIGHT_NAME1);
    315         if ((dwStyle & FXFONT_BOLD) == (pFontDes->m_dwStyle & FXFONT_BOLD)) {
    316             nFind += FPF_SKIAMATCHWEIGHT_1;
    317         }
    318         if ((dwStyle & FXFONT_ITALIC) == (pFontDes->m_dwStyle & FXFONT_ITALIC)) {
    319             nFind += FPF_SKIAMATCHWEIGHT_1;
    320         }
    321         if ((dwStyle & FXFONT_FIXED_PITCH) == (pFontDes->m_dwStyle & FXFONT_FIXED_PITCH)) {
    322             nFind += FPF_SKIAMATCHWEIGHT_2;
    323         }
    324         if ((dwStyle & FXFONT_SERIF) == (pFontDes->m_dwStyle & FXFONT_SERIF)) {
    325             nFind += FPF_SKIAMATCHWEIGHT_1;
    326         }
    327         if ((dwStyle & FXFONT_SCRIPT) == (pFontDes->m_dwStyle & FXFONT_SCRIPT)) {
    328             nFind += FPF_SKIAMATCHWEIGHT_2;
    329         }
    330         if (dwSubst == dwSysFontName || dwSubstSans == dwSysFontName) {
    331             nFind += FPF_SKIAMATCHWEIGHT_NAME2;
    332             bMatchedName = TRUE;
    333         }
    334         if (uCharset == FXFONT_DEFAULT_CHARSET || bMaybeSymbol) {
    335             if (nFind > nMax && bMatchedName) {
    336                 nMax = nFind;
    337                 nItem = i;
    338             }
    339         } else if (FPF_SkiaIsCJK(uCharset)) {
    340             if (bMatchedName || pFontDes->m_iGlyphNum > nGlyphNum) {
    341                 nItem = i;
    342                 nGlyphNum = pFontDes->m_iGlyphNum;
    343             }
    344         } else if (nFind > nMax) {
    345             nMax = nFind;
    346             nItem = i;
    347         }
    348         if (nExpectVal <= nFind) {
    349             nItem = i;
    350             break;
    351         }
    352     }
    353     if (nItem > -1) {
    354         CFPF_SkiaFontDescriptor *pFontDes = (CFPF_SkiaFontDescriptor*)m_FontFaces.ElementAt(nItem);
    355         CFPF_SkiaFont *pFont = FX_NEW CFPF_SkiaFont;
    356         if (pFont) {
    357             if (pFont->InitFont(this, pFontDes, bsFamilyname, dwStyle, uCharset)) {
    358                 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
    359                 return pFont->Retain();
    360             }
    361             pFont->Release();
    362             pFont = NULL;
    363         }
    364         return pFont;
    365     }
    366     return NULL;
    367 }
    368 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(IFX_FileRead *pFileRead, FX_INT32 iFaceIndex)
    369 {
    370     if (!pFileRead) {
    371         return NULL;
    372     }
    373     if (pFileRead->GetSize() == 0) {
    374         return NULL;
    375     }
    376     if (iFaceIndex < 0) {
    377         return NULL;
    378     }
    379     FXFT_StreamRec streamRec;
    380     FXSYS_memset32(&streamRec, 0, sizeof(FXFT_StreamRec));
    381     streamRec.size = pFileRead->GetSize();
    382     streamRec.descriptor.pointer = pFileRead;
    383     streamRec.read = FPF_SkiaStream_Read;
    384     streamRec.close = FPF_SkiaStream_Close;
    385     FXFT_Open_Args args;
    386     args.flags = FT_OPEN_STREAM;
    387     args.stream = &streamRec;
    388     FXFT_Face face;
    389     if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) {
    390         return NULL;
    391     }
    392     FXFT_Set_Pixel_Sizes(face, 0, 64);
    393     return face;
    394 }
    395 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(FX_BSTR bsFile, FX_INT32 iFaceIndex )
    396 {
    397     if (bsFile.IsEmpty()) {
    398         return NULL;
    399     }
    400     if (iFaceIndex < 0) {
    401         return NULL;
    402     }
    403     FXFT_Open_Args args;
    404     args.flags = FT_OPEN_PATHNAME;
    405     args.pathname = (FT_String*)bsFile.GetCStr();
    406     FXFT_Face face;
    407     if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) {
    408         return FALSE;
    409     }
    410     FXFT_Set_Pixel_Sizes(face, 0, 64);
    411     return face;
    412 }
    413 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(FX_LPCBYTE pBuffer, size_t szBuffer, FX_INT32 iFaceIndex )
    414 {
    415     if (!pBuffer || szBuffer < 1) {
    416         return NULL;
    417     }
    418     if (iFaceIndex < 0) {
    419         return NULL;
    420     }
    421     FXFT_Open_Args args;
    422     args.flags = FT_OPEN_MEMORY;
    423     args.memory_base = pBuffer;
    424     args.memory_size = szBuffer;
    425     FXFT_Face face;
    426     if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) {
    427         return FALSE;
    428     }
    429     FXFT_Set_Pixel_Sizes(face, 0, 64);
    430     return face;
    431 }
    432 void CFPF_SkiaFontMgr::ScanPath(FX_BSTR path)
    433 {
    434     void *handle = FX_OpenFolder(path.GetCStr());
    435     if (!handle) {
    436         return;
    437     }
    438     CFX_ByteString filename;
    439     FX_BOOL	bFolder = FALSE;
    440     while (FX_GetNextFile(handle, filename, bFolder)) {
    441         if (bFolder) {
    442             if (filename == FX_BSTRC(".") || filename == FX_BSTRC("..")) {
    443                 continue;
    444             }
    445         } else {
    446             CFX_ByteString ext = filename.Right(4);
    447             ext.MakeLower();
    448             if (ext != FX_BSTRC(".ttf") && ext != FX_BSTRC(".ttc")) {
    449                 continue;
    450             }
    451         }
    452         CFX_ByteString fullpath = path;
    453         fullpath += "/";
    454         fullpath += filename;
    455         if (bFolder) {
    456             ScanPath(fullpath);
    457         } else {
    458             ScanFile(fullpath);
    459         }
    460     }
    461     FX_CloseFolder(handle);
    462 }
    463 void CFPF_SkiaFontMgr::ScanFile(FX_BSTR file)
    464 {
    465     FXFT_Face face = GetFontFace(file);
    466     if (face) {
    467         CFPF_SkiaPathFont *pFontDesc = FX_NEW CFPF_SkiaPathFont;
    468         if (!pFontDesc) {
    469             return;
    470         }
    471         pFontDesc->SetPath(file.GetCStr());
    472         ReportFace(face, pFontDesc);
    473         m_FontFaces.Add(pFontDesc);
    474         FXFT_Done_Face(face);
    475     }
    476 }
    477 static const FX_DWORD g_FPFSkiaFontCharsets [] = {
    478     FPF_SKIACHARSET_Ansi,
    479     FPF_SKIACHARSET_EeasternEuropean,
    480     FPF_SKIACHARSET_Cyrillic,
    481     FPF_SKIACHARSET_Greek,
    482     FPF_SKIACHARSET_Turkish,
    483     FPF_SKIACHARSET_Hebrew,
    484     FPF_SKIACHARSET_Arabic,
    485     FPF_SKIACHARSET_Baltic,
    486     0,
    487     0,
    488     0,
    489     0,
    490     0,
    491     0,
    492     0,
    493     0,
    494     FPF_SKIACHARSET_Thai,
    495     FPF_SKIACHARSET_ShiftJIS,
    496     FPF_SKIACHARSET_GB2312,
    497     FPF_SKIACHARSET_Korean,
    498     FPF_SKIACHARSET_BIG5,
    499     FPF_SKIACHARSET_Johab,
    500     0,
    501     0,
    502     0,
    503     0,
    504     0,
    505     0,
    506     0,
    507     0,
    508     FPF_SKIACHARSET_OEM,
    509     FPF_SKIACHARSET_Symbol,
    510 };
    511 static FX_DWORD FPF_SkiaGetFaceCharset(TT_OS2 *pOS2)
    512 {
    513     FX_DWORD dwCharset = 0;
    514     if (pOS2) {
    515         for (FX_INT32 i = 0; i < 32; i++) {
    516             if (pOS2->ulCodePageRange1 & (1 << i)) {
    517                 dwCharset |= g_FPFSkiaFontCharsets[i];
    518             }
    519         }
    520     }
    521     dwCharset |= FPF_SKIACHARSET_Default;
    522     return dwCharset;
    523 }
    524 void CFPF_SkiaFontMgr::ReportFace(FXFT_Face face, CFPF_SkiaFontDescriptor *pFontDesc)
    525 {
    526     if (!face || !pFontDesc) {
    527         return;
    528     }
    529     pFontDesc->SetFamily(FXFT_Get_Face_Family_Name(face));
    530     if (FXFT_Is_Face_Bold(face))	{
    531         pFontDesc->m_dwStyle |= FXFONT_BOLD;
    532     }
    533     if (FXFT_Is_Face_Italic(face))	{
    534         pFontDesc->m_dwStyle |= FXFONT_ITALIC;
    535     }
    536     if (FT_IS_FIXED_WIDTH(face))	{
    537         pFontDesc->m_dwStyle |= FXFONT_FIXED_PITCH;
    538     }
    539     TT_OS2 *pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
    540     if (pOS2) {
    541         if (pOS2->ulCodePageRange1 & (1 << 31)) {
    542             pFontDesc->m_dwStyle |= FXFONT_SYMBOLIC;
    543         }
    544         if (pOS2->panose[0] == 2) {
    545             FX_BYTE uSerif = pOS2->panose[1];
    546             if ((uSerif > 1 && uSerif < 10) || uSerif > 13) {
    547                 pFontDesc->m_dwStyle |= FXFONT_SERIF;
    548             }
    549         }
    550     }
    551     if (pOS2 && (pOS2->ulCodePageRange1 & (1 << 31))) {
    552         pFontDesc->m_dwStyle |= FXFONT_SYMBOLIC;
    553     }
    554     pFontDesc->m_dwCharsets = FPF_SkiaGetFaceCharset(pOS2);
    555     pFontDesc->m_iFaceIndex = face->face_index;
    556     pFontDesc->m_iGlyphNum = face->num_glyphs;
    557 }
    558 void CFPF_SkiaFontMgr::OutputSystemFonts()
    559 {
    560 }
    561 #endif
    562