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 0;
     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(bsFont.c_str(), 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*)(FX_UINTPTR)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 = new CFPF_SkiaFont;
    356         if (pFont->InitFont(this, pFontDes, bsFamilyname, dwStyle, uCharset)) {
    357             m_FamilyFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
    358             return pFont->Retain();
    359         }
    360         pFont->Release();
    361     }
    362     return NULL;
    363 }
    364 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(IFX_FileRead *pFileRead, FX_INT32 iFaceIndex)
    365 {
    366     if (!pFileRead) {
    367         return NULL;
    368     }
    369     if (pFileRead->GetSize() == 0) {
    370         return NULL;
    371     }
    372     if (iFaceIndex < 0) {
    373         return NULL;
    374     }
    375     FXFT_StreamRec streamRec;
    376     FXSYS_memset32(&streamRec, 0, sizeof(FXFT_StreamRec));
    377     streamRec.size = pFileRead->GetSize();
    378     streamRec.descriptor.pointer = pFileRead;
    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 NULL;
    387     }
    388     FXFT_Set_Pixel_Sizes(face, 0, 64);
    389     return face;
    390 }
    391 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(FX_BSTR bsFile, FX_INT32 iFaceIndex )
    392 {
    393     if (bsFile.IsEmpty()) {
    394         return NULL;
    395     }
    396     if (iFaceIndex < 0) {
    397         return NULL;
    398     }
    399     FXFT_Open_Args args;
    400     args.flags = FT_OPEN_PATHNAME;
    401     args.pathname = (FT_String*)bsFile.GetCStr();
    402     FXFT_Face face;
    403     if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) {
    404         return FALSE;
    405     }
    406     FXFT_Set_Pixel_Sizes(face, 0, 64);
    407     return face;
    408 }
    409 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(FX_LPCBYTE pBuffer, size_t szBuffer, FX_INT32 iFaceIndex )
    410 {
    411     if (!pBuffer || szBuffer < 1) {
    412         return NULL;
    413     }
    414     if (iFaceIndex < 0) {
    415         return NULL;
    416     }
    417     FXFT_Open_Args args;
    418     args.flags = FT_OPEN_MEMORY;
    419     args.memory_base = pBuffer;
    420     args.memory_size = szBuffer;
    421     FXFT_Face face;
    422     if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) {
    423         return FALSE;
    424     }
    425     FXFT_Set_Pixel_Sizes(face, 0, 64);
    426     return face;
    427 }
    428 void CFPF_SkiaFontMgr::ScanPath(FX_BSTR path)
    429 {
    430     void *handle = FX_OpenFolder(path.GetCStr());
    431     if (!handle) {
    432         return;
    433     }
    434     CFX_ByteString filename;
    435     FX_BOOL	bFolder = FALSE;
    436     while (FX_GetNextFile(handle, filename, bFolder)) {
    437         if (bFolder) {
    438             if (filename == FX_BSTRC(".") || filename == FX_BSTRC("..")) {
    439                 continue;
    440             }
    441         } else {
    442             CFX_ByteString ext = filename.Right(4);
    443             ext.MakeLower();
    444             if (ext != FX_BSTRC(".ttf") && ext != FX_BSTRC(".ttc")) {
    445                 continue;
    446             }
    447         }
    448         CFX_ByteString fullpath = path;
    449         fullpath += "/";
    450         fullpath += filename;
    451         if (bFolder) {
    452             ScanPath(fullpath);
    453         } else {
    454             ScanFile(fullpath);
    455         }
    456     }
    457     FX_CloseFolder(handle);
    458 }
    459 void CFPF_SkiaFontMgr::ScanFile(FX_BSTR file)
    460 {
    461     FXFT_Face face = GetFontFace(file);
    462     if (face) {
    463         CFPF_SkiaPathFont *pFontDesc = new CFPF_SkiaPathFont;
    464         pFontDesc->SetPath(file.GetCStr());
    465         ReportFace(face, pFontDesc);
    466         m_FontFaces.Add(pFontDesc);
    467         FXFT_Done_Face(face);
    468     }
    469 }
    470 static const FX_DWORD g_FPFSkiaFontCharsets [] = {
    471     FPF_SKIACHARSET_Ansi,
    472     FPF_SKIACHARSET_EeasternEuropean,
    473     FPF_SKIACHARSET_Cyrillic,
    474     FPF_SKIACHARSET_Greek,
    475     FPF_SKIACHARSET_Turkish,
    476     FPF_SKIACHARSET_Hebrew,
    477     FPF_SKIACHARSET_Arabic,
    478     FPF_SKIACHARSET_Baltic,
    479     0,
    480     0,
    481     0,
    482     0,
    483     0,
    484     0,
    485     0,
    486     0,
    487     FPF_SKIACHARSET_Thai,
    488     FPF_SKIACHARSET_ShiftJIS,
    489     FPF_SKIACHARSET_GB2312,
    490     FPF_SKIACHARSET_Korean,
    491     FPF_SKIACHARSET_BIG5,
    492     FPF_SKIACHARSET_Johab,
    493     0,
    494     0,
    495     0,
    496     0,
    497     0,
    498     0,
    499     0,
    500     0,
    501     FPF_SKIACHARSET_OEM,
    502     FPF_SKIACHARSET_Symbol,
    503 };
    504 static FX_DWORD FPF_SkiaGetFaceCharset(TT_OS2 *pOS2)
    505 {
    506     FX_DWORD dwCharset = 0;
    507     if (pOS2) {
    508         for (FX_INT32 i = 0; i < 32; i++) {
    509             if (pOS2->ulCodePageRange1 & (1 << i)) {
    510                 dwCharset |= g_FPFSkiaFontCharsets[i];
    511             }
    512         }
    513     }
    514     dwCharset |= FPF_SKIACHARSET_Default;
    515     return dwCharset;
    516 }
    517 void CFPF_SkiaFontMgr::ReportFace(FXFT_Face face, CFPF_SkiaFontDescriptor *pFontDesc)
    518 {
    519     if (!face || !pFontDesc) {
    520         return;
    521     }
    522     pFontDesc->SetFamily(FXFT_Get_Face_Family_Name(face));
    523     if (FXFT_Is_Face_Bold(face))	{
    524         pFontDesc->m_dwStyle |= FXFONT_BOLD;
    525     }
    526     if (FXFT_Is_Face_Italic(face))	{
    527         pFontDesc->m_dwStyle |= FXFONT_ITALIC;
    528     }
    529     if (FT_IS_FIXED_WIDTH(face))	{
    530         pFontDesc->m_dwStyle |= FXFONT_FIXED_PITCH;
    531     }
    532     TT_OS2 *pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
    533     if (pOS2) {
    534         if (pOS2->ulCodePageRange1 & (1 << 31)) {
    535             pFontDesc->m_dwStyle |= FXFONT_SYMBOLIC;
    536         }
    537         if (pOS2->panose[0] == 2) {
    538             FX_BYTE uSerif = pOS2->panose[1];
    539             if ((uSerif > 1 && uSerif < 10) || uSerif > 13) {
    540                 pFontDesc->m_dwStyle |= FXFONT_SERIF;
    541             }
    542         }
    543     }
    544     if (pOS2 && (pOS2->ulCodePageRange1 & (1 << 31))) {
    545         pFontDesc->m_dwStyle |= FXFONT_SYMBOLIC;
    546     }
    547     pFontDesc->m_dwCharsets = FPF_SkiaGetFaceCharset(pOS2);
    548     pFontDesc->m_iFaceIndex = face->face_index;
    549     pFontDesc->m_iGlyphNum = face->num_glyphs;
    550 }
    551 void CFPF_SkiaFontMgr::OutputSystemFonts()
    552 {
    553 }
    554 #endif
    555