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 "xfa/src/fgas/src/fgas_base.h"
8 #include "fx_stdfontmgr.h"
9 #include "fx_fontutils.h"
10 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
Create(FX_LPEnumAllFonts pEnumerator,FX_LPMatchFont pMatcher,void * pUserData)11 IFX_FontMgr* IFX_FontMgr::Create(FX_LPEnumAllFonts pEnumerator,
12                                  FX_LPMatchFont pMatcher,
13                                  void* pUserData) {
14   return new CFX_StdFontMgrImp(pEnumerator, pMatcher, pUserData);
15 }
CFX_StdFontMgrImp(FX_LPEnumAllFonts pEnumerator,FX_LPMatchFont pMatcher,void * pUserData)16 CFX_StdFontMgrImp::CFX_StdFontMgrImp(FX_LPEnumAllFonts pEnumerator,
17                                      FX_LPMatchFont pMatcher,
18                                      void* pUserData)
19     : m_pMatcher(pMatcher),
20       m_pEnumerator(pEnumerator),
21       m_FontFaces(),
22       m_Fonts(),
23       m_CPFonts(8),
24       m_FamilyFonts(16),
25       m_UnicodeFonts(16),
26       m_BufferFonts(4),
27       m_FileFonts(4),
28       m_StreamFonts(4),
29       m_DeriveFonts(4),
30       m_pUserData(pUserData) {
31   if (m_pEnumerator != NULL) {
32     m_pEnumerator(m_FontFaces, m_pUserData, NULL, 0xFEFF);
33   }
34   if (m_pMatcher == NULL) {
35     m_pMatcher = FX_DefFontMatcher;
36   }
37   FXSYS_assert(m_pMatcher != NULL);
38 }
~CFX_StdFontMgrImp()39 CFX_StdFontMgrImp::~CFX_StdFontMgrImp() {
40   m_FontFaces.RemoveAll();
41   m_CPFonts.RemoveAll();
42   m_FamilyFonts.RemoveAll();
43   m_UnicodeFonts.RemoveAll();
44   m_BufferFonts.RemoveAll();
45   m_FileFonts.RemoveAll();
46   m_StreamFonts.RemoveAll();
47   m_DeriveFonts.RemoveAll();
48   for (int32_t i = m_Fonts.GetUpperBound(); i >= 0; i--) {
49     IFX_Font* pFont = (IFX_Font*)m_Fonts[i];
50     if (pFont != NULL) {
51       pFont->Release();
52     }
53   }
54   m_Fonts.RemoveAll();
55 }
GetDefFontByCodePage(FX_WORD wCodePage,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)56 IFX_Font* CFX_StdFontMgrImp::GetDefFontByCodePage(
57     FX_WORD wCodePage,
58     FX_DWORD dwFontStyles,
59     const FX_WCHAR* pszFontFamily) {
60   FX_DWORD dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
61   IFX_Font* pFont = NULL;
62   if (m_CPFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) {
63     return pFont ? LoadFont(pFont, dwFontStyles, wCodePage) : NULL;
64   }
65   FX_LPCFONTDESCRIPTOR pFD;
66   if ((pFD = FindFont(pszFontFamily, dwFontStyles, TRUE, wCodePage)) == NULL)
67     if ((pFD = FindFont(NULL, dwFontStyles, TRUE, wCodePage)) == NULL)
68       if ((pFD = FindFont(NULL, dwFontStyles, FALSE, wCodePage)) == NULL) {
69         return NULL;
70       }
71   FXSYS_assert(pFD != NULL);
72   pFont = IFX_Font::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
73   if (pFont != NULL) {
74     m_Fonts.Add(pFont);
75     m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
76     dwHash = FGAS_GetFontFamilyHash(pFD->wsFontFace, dwFontStyles, wCodePage);
77     m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
78     return LoadFont(pFont, dwFontStyles, wCodePage);
79   }
80   return NULL;
81 }
GetDefFontByCharset(uint8_t nCharset,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)82 IFX_Font* CFX_StdFontMgrImp::GetDefFontByCharset(
83     uint8_t nCharset,
84     FX_DWORD dwFontStyles,
85     const FX_WCHAR* pszFontFamily) {
86   return GetDefFontByCodePage(FX_GetCodePageFromCharset(nCharset), dwFontStyles,
87                               pszFontFamily);
88 }
89 #define _FX_USEGASFONTMGR_
GetDefFontByUnicode(FX_WCHAR wUnicode,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)90 IFX_Font* CFX_StdFontMgrImp::GetDefFontByUnicode(
91     FX_WCHAR wUnicode,
92     FX_DWORD dwFontStyles,
93     const FX_WCHAR* pszFontFamily) {
94   FGAS_LPCFONTUSB pRet = FGAS_GetUnicodeBitField(wUnicode);
95   if (pRet->wBitField == 999) {
96     return NULL;
97   }
98   FX_DWORD dwHash =
99       FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, pRet->wBitField);
100   IFX_Font* pFont = NULL;
101   if (m_UnicodeFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) {
102     return pFont ? LoadFont(pFont, dwFontStyles, pRet->wCodePage) : NULL;
103   }
104 #ifdef _FX_USEGASFONTMGR_
105   FX_LPCFONTDESCRIPTOR pFD =
106       FindFont(pszFontFamily, dwFontStyles, FALSE, pRet->wCodePage,
107                pRet->wBitField, wUnicode);
108   if (pFD == NULL && pszFontFamily) {
109     pFD = FindFont(NULL, dwFontStyles, FALSE, pRet->wCodePage, pRet->wBitField,
110                    wUnicode);
111   }
112   if (pFD == NULL) {
113     return NULL;
114   }
115   FXSYS_assert(pFD);
116   FX_WORD wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
117   const FX_WCHAR* pFontFace = pFD->wsFontFace;
118   pFont = IFX_Font::LoadFont(pFontFace, dwFontStyles, wCodePage, this);
119 #else
120   CFX_FontMapper* pBuiltinMapper =
121       CFX_GEModule::Get()->GetFontMgr()->m_pBuiltinMapper;
122   if (pBuiltinMapper == NULL) {
123     return NULL;
124   }
125   int32_t iWeight =
126       (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
127   int italic_angle = 0;
128   FXFT_Face ftFace = pBuiltinMapper->FindSubstFontByUnicode(
129       wUnicode, dwFontStyles, iWeight, italic_angle);
130   if (ftFace == NULL) {
131     return NULL;
132   }
133   CFX_Font* pFXFont = new CFX_Font;
134   pFXFont->m_Face = ftFace;
135   pFXFont->m_pFontData = FXFT_Get_Face_Stream_Base(ftFace);
136   pFXFont->m_dwSize = FXFT_Get_Face_Stream_Size(ftFace);
137   pFont = IFX_Font::LoadFont(pFXFont, this);
138   FX_WORD wCodePage = pRet->wCodePage;
139   CFX_WideString wsPsName = pFXFont->GetPsName();
140   const FX_WCHAR* pFontFace = wsPsName;
141 #endif
142   if (pFont != NULL) {
143     m_Fonts.Add(pFont);
144     m_UnicodeFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
145     dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
146     m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
147     dwHash = FGAS_GetFontFamilyHash(pFontFace, dwFontStyles, wCodePage);
148     m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
149     return LoadFont(pFont, dwFontStyles, wCodePage);
150   }
151   return NULL;
152 }
GetDefFontByLanguage(FX_WORD wLanguage,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)153 IFX_Font* CFX_StdFontMgrImp::GetDefFontByLanguage(
154     FX_WORD wLanguage,
155     FX_DWORD dwFontStyles,
156     const FX_WCHAR* pszFontFamily) {
157   return GetDefFontByCodePage(FX_GetDefCodePageByLanguage(wLanguage),
158                               dwFontStyles, pszFontFamily);
159 }
LoadFont(const FX_WCHAR * pszFontFamily,FX_DWORD dwFontStyles,FX_WORD wCodePage)160 IFX_Font* CFX_StdFontMgrImp::LoadFont(const FX_WCHAR* pszFontFamily,
161                                       FX_DWORD dwFontStyles,
162                                       FX_WORD wCodePage) {
163   FX_DWORD dwHash =
164       FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, wCodePage);
165   IFX_Font* pFont = NULL;
166   if (m_FamilyFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) {
167     return pFont ? LoadFont(pFont, dwFontStyles, wCodePage) : NULL;
168   }
169   FX_LPCFONTDESCRIPTOR pFD = NULL;
170   if ((pFD = FindFont(pszFontFamily, dwFontStyles, TRUE, wCodePage)) == NULL)
171     if ((pFD = FindFont(pszFontFamily, dwFontStyles, FALSE, wCodePage)) ==
172         NULL) {
173       return NULL;
174     }
175   FXSYS_assert(pFD != NULL);
176   if (wCodePage == 0xFFFF) {
177     wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
178   }
179   pFont = IFX_Font::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
180   if (pFont != NULL) {
181     m_Fonts.Add(pFont);
182     m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
183     dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
184     m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
185     return LoadFont(pFont, dwFontStyles, wCodePage);
186   }
187   return NULL;
188 }
LoadFont(const uint8_t * pBuffer,int32_t iLength)189 IFX_Font* CFX_StdFontMgrImp::LoadFont(const uint8_t* pBuffer, int32_t iLength) {
190   FXSYS_assert(pBuffer != NULL && iLength > 0);
191   IFX_Font* pFont = NULL;
192   if (m_BufferFonts.Lookup((void*)pBuffer, (void*&)pFont)) {
193     if (pFont != NULL) {
194       return pFont->Retain();
195     }
196   }
197   pFont = IFX_Font::LoadFont(pBuffer, iLength, this);
198   if (pFont != NULL) {
199     m_Fonts.Add(pFont);
200     m_BufferFonts.SetAt((void*)pBuffer, pFont);
201     return pFont->Retain();
202   }
203   return NULL;
204 }
LoadFont(const FX_WCHAR * pszFileName)205 IFX_Font* CFX_StdFontMgrImp::LoadFont(const FX_WCHAR* pszFileName) {
206   FXSYS_assert(pszFileName != NULL);
207   FX_DWORD dwHash = FX_HashCode_String_GetW(pszFileName, -1);
208   IFX_Font* pFont = NULL;
209   if (m_FileFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) {
210     if (pFont != NULL) {
211       return pFont->Retain();
212     }
213   }
214   pFont = IFX_Font::LoadFont(pszFileName, NULL);
215   if (pFont != NULL) {
216     m_Fonts.Add(pFont);
217     m_FileFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
218     return pFont->Retain();
219   }
220   return NULL;
221 }
LoadFont(IFX_Stream * pFontStream,const FX_WCHAR * pszFontAlias,FX_DWORD dwFontStyles,FX_WORD wCodePage,FX_BOOL bSaveStream)222 IFX_Font* CFX_StdFontMgrImp::LoadFont(IFX_Stream* pFontStream,
223                                       const FX_WCHAR* pszFontAlias,
224                                       FX_DWORD dwFontStyles,
225                                       FX_WORD wCodePage,
226                                       FX_BOOL bSaveStream) {
227   FXSYS_assert(pFontStream != NULL && pFontStream->GetLength() > 0);
228   IFX_Font* pFont = NULL;
229   if (m_StreamFonts.Lookup((void*)pFontStream, (void*&)pFont)) {
230     if (pFont != NULL) {
231       if (pszFontAlias != NULL) {
232         FX_DWORD dwHash =
233             FGAS_GetFontFamilyHash(pszFontAlias, dwFontStyles, wCodePage);
234         m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
235       }
236       return LoadFont(pFont, dwFontStyles, wCodePage);
237     }
238   }
239   pFont = IFX_Font::LoadFont(pFontStream, this, bSaveStream);
240   if (pFont != NULL) {
241     m_Fonts.Add(pFont);
242     m_StreamFonts.SetAt((void*)pFontStream, (void*)pFont);
243     if (pszFontAlias != NULL) {
244       FX_DWORD dwHash =
245           FGAS_GetFontFamilyHash(pszFontAlias, dwFontStyles, wCodePage);
246       m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
247     }
248     return LoadFont(pFont, dwFontStyles, wCodePage);
249   }
250   return NULL;
251 }
LoadFont(IFX_Font * pSrcFont,FX_DWORD dwFontStyles,FX_WORD wCodePage)252 IFX_Font* CFX_StdFontMgrImp::LoadFont(IFX_Font* pSrcFont,
253                                       FX_DWORD dwFontStyles,
254                                       FX_WORD wCodePage) {
255   FXSYS_assert(pSrcFont != NULL);
256   if (pSrcFont->GetFontStyles() == dwFontStyles) {
257     return pSrcFont->Retain();
258   }
259   void* buffer[3] = {pSrcFont, (void*)(uintptr_t)dwFontStyles,
260                      (void*)(uintptr_t)wCodePage};
261   FX_DWORD dwHash =
262       FX_HashCode_String_GetA((const FX_CHAR*)buffer, 3 * sizeof(void*));
263   IFX_Font* pFont = NULL;
264   if (m_DeriveFonts.GetCount() > 0) {
265     m_DeriveFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont);
266     if (pFont != NULL) {
267       return pFont->Retain();
268     }
269   }
270   pFont = pSrcFont->Derive(dwFontStyles, wCodePage);
271   if (pFont != NULL) {
272     m_DeriveFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
273     int32_t index = m_Fonts.Find(pFont);
274     if (index < 0) {
275       m_Fonts.Add(pFont);
276       pFont->Retain();
277     }
278     return pFont;
279   }
280   return NULL;
281 }
ClearFontCache()282 void CFX_StdFontMgrImp::ClearFontCache() {
283   int32_t iCount = m_Fonts.GetSize();
284   for (int32_t i = 0; i < iCount; i++) {
285     IFX_Font* pFont = (IFX_Font*)m_Fonts[i];
286     if (pFont != NULL) {
287       pFont->Reset();
288     }
289   }
290 }
RemoveFont(CFX_MapPtrToPtr & fontMap,IFX_Font * pFont)291 void CFX_StdFontMgrImp::RemoveFont(CFX_MapPtrToPtr& fontMap, IFX_Font* pFont) {
292   FX_POSITION pos = fontMap.GetStartPosition();
293   void* pKey;
294   void* pFind;
295   while (pos != NULL) {
296     pFind = NULL;
297     fontMap.GetNextAssoc(pos, pKey, pFind);
298     if (pFind != (void*)pFont) {
299       continue;
300     }
301     fontMap.RemoveKey(pKey);
302     break;
303   }
304 }
RemoveFont(IFX_Font * pFont)305 void CFX_StdFontMgrImp::RemoveFont(IFX_Font* pFont) {
306   RemoveFont(m_CPFonts, pFont);
307   RemoveFont(m_FamilyFonts, pFont);
308   RemoveFont(m_UnicodeFonts, pFont);
309   RemoveFont(m_BufferFonts, pFont);
310   RemoveFont(m_FileFonts, pFont);
311   RemoveFont(m_StreamFonts, pFont);
312   RemoveFont(m_DeriveFonts, pFont);
313   int32_t iFind = m_Fonts.Find(pFont);
314   if (iFind > -1) {
315     m_Fonts.RemoveAt(iFind, 1);
316   }
317 }
FindFont(const FX_WCHAR * pszFontFamily,FX_DWORD dwFontStyles,FX_DWORD dwMatchFlags,FX_WORD wCodePage,FX_DWORD dwUSB,FX_WCHAR wUnicode)318 FX_LPCFONTDESCRIPTOR CFX_StdFontMgrImp::FindFont(const FX_WCHAR* pszFontFamily,
319                                                  FX_DWORD dwFontStyles,
320                                                  FX_DWORD dwMatchFlags,
321                                                  FX_WORD wCodePage,
322                                                  FX_DWORD dwUSB,
323                                                  FX_WCHAR wUnicode) {
324   if (m_pMatcher == NULL) {
325     return NULL;
326   }
327   FX_FONTMATCHPARAMS params;
328   FX_memset(&params, 0, sizeof(params));
329   params.dwUSB = dwUSB;
330   params.wUnicode = wUnicode;
331   params.wCodePage = wCodePage;
332   params.pwsFamily = pszFontFamily;
333   params.dwFontStyles = dwFontStyles;
334   params.dwMatchFlags = dwMatchFlags;
335   FX_LPCFONTDESCRIPTOR pDesc = m_pMatcher(&params, m_FontFaces, m_pUserData);
336   if (pDesc) {
337     return pDesc;
338   }
339   if (pszFontFamily && m_pEnumerator) {
340     CFX_FontDescriptors namedFonts;
341     m_pEnumerator(namedFonts, m_pUserData, pszFontFamily, wUnicode);
342     params.pwsFamily = NULL;
343     pDesc = m_pMatcher(&params, namedFonts, m_pUserData);
344     if (pDesc == NULL) {
345       return NULL;
346     }
347     for (int32_t i = m_FontFaces.GetSize() - 1; i >= 0; i--) {
348       FX_LPCFONTDESCRIPTOR pMatch = m_FontFaces.GetPtrAt(i);
349       if (*pMatch == *pDesc) {
350         return pMatch;
351       }
352     }
353     int index = m_FontFaces.Add(*pDesc);
354     return m_FontFaces.GetPtrAt(index);
355   }
356   return NULL;
357 }
FX_DefFontMatcher(FX_LPFONTMATCHPARAMS pParams,const CFX_FontDescriptors & fonts,void * pUserData)358 FX_LPCFONTDESCRIPTOR FX_DefFontMatcher(FX_LPFONTMATCHPARAMS pParams,
359                                        const CFX_FontDescriptors& fonts,
360                                        void* pUserData) {
361   FX_LPCFONTDESCRIPTOR pBestFont = NULL;
362   int32_t iBestSimilar = 0;
363   FX_BOOL bMatchStyle =
364       (pParams->dwMatchFlags & FX_FONTMATCHPARA_MacthStyle) > 0;
365   int32_t iCount = fonts.GetSize();
366   for (int32_t i = 0; i < iCount; ++i) {
367     FX_LPCFONTDESCRIPTOR pFont = fonts.GetPtrAt(i);
368     if ((pFont->dwFontStyles & FX_FONTSTYLE_BoldItalic) ==
369         FX_FONTSTYLE_BoldItalic) {
370       continue;
371     }
372     if (pParams->pwsFamily) {
373       if (FXSYS_wcsicmp(pParams->pwsFamily, pFont->wsFontFace)) {
374         continue;
375       }
376       if (pFont->uCharSet == FX_CHARSET_Symbol) {
377         return pFont;
378       }
379     }
380     if (pFont->uCharSet == FX_CHARSET_Symbol) {
381       continue;
382     }
383     if (pParams->wCodePage != 0xFFFF) {
384       if (FX_GetCodePageFromCharset(pFont->uCharSet) != pParams->wCodePage) {
385         continue;
386       }
387     } else {
388       if (pParams->dwUSB < 128) {
389         FX_DWORD dwByte = pParams->dwUSB / 32;
390         FX_DWORD dwUSB = 1 << (pParams->dwUSB % 32);
391         if ((pFont->FontSignature.fsUsb[dwByte] & dwUSB) == 0) {
392           continue;
393         }
394       }
395     }
396     if (bMatchStyle) {
397       if ((pFont->dwFontStyles & 0x0F) == (pParams->dwFontStyles & 0x0F)) {
398         return pFont;
399       } else {
400         continue;
401       }
402     }
403     if (pParams->pwsFamily != NULL) {
404       if (FXSYS_wcsicmp(pParams->pwsFamily, pFont->wsFontFace) == 0) {
405         return pFont;
406       }
407     }
408     int32_t iSimilarValue = FX_GetSimilarValue(pFont, pParams->dwFontStyles);
409     if (iBestSimilar < iSimilarValue) {
410       iBestSimilar = iSimilarValue;
411       pBestFont = pFont;
412     }
413   }
414   return iBestSimilar < 1 ? NULL : pBestFont;
415 }
FX_GetSimilarValue(FX_LPCFONTDESCRIPTOR pFont,FX_DWORD dwFontStyles)416 int32_t FX_GetSimilarValue(FX_LPCFONTDESCRIPTOR pFont, FX_DWORD dwFontStyles) {
417   int32_t iValue = 0;
418   if ((dwFontStyles & FX_FONTSTYLE_Symbolic) ==
419       (pFont->dwFontStyles & FX_FONTSTYLE_Symbolic)) {
420     iValue += 64;
421   }
422   if ((dwFontStyles & FX_FONTSTYLE_FixedPitch) ==
423       (pFont->dwFontStyles & FX_FONTSTYLE_FixedPitch)) {
424     iValue += 32;
425   }
426   if ((dwFontStyles & FX_FONTSTYLE_Serif) ==
427       (pFont->dwFontStyles & FX_FONTSTYLE_Serif)) {
428     iValue += 16;
429   }
430   if ((dwFontStyles & FX_FONTSTYLE_Script) ==
431       (pFont->dwFontStyles & FX_FONTSTYLE_Script)) {
432     iValue += 8;
433   }
434   return iValue;
435 }
FX_GetDefFontMatchor()436 FX_LPMatchFont FX_GetDefFontMatchor() {
437   return FX_DefFontMatcher;
438 }
FX_GetGdiFontStyles(const LOGFONTW & lf)439 FX_DWORD FX_GetGdiFontStyles(const LOGFONTW& lf) {
440   FX_DWORD dwStyles = 0;
441   if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH) {
442     dwStyles |= FX_FONTSTYLE_FixedPitch;
443   }
444   uint8_t nFamilies = lf.lfPitchAndFamily & 0xF0;
445   if (nFamilies == FF_ROMAN) {
446     dwStyles |= FX_FONTSTYLE_Serif;
447   }
448   if (nFamilies == FF_SCRIPT) {
449     dwStyles |= FX_FONTSTYLE_Script;
450   }
451   if (lf.lfCharSet == SYMBOL_CHARSET) {
452     dwStyles |= FX_FONTSTYLE_Symbolic;
453   }
454   return dwStyles;
455 }
FX_GdiFontEnumProc(ENUMLOGFONTEX * lpelfe,NEWTEXTMETRICEX * lpntme,DWORD dwFontType,LPARAM lParam)456 static int32_t CALLBACK FX_GdiFontEnumProc(ENUMLOGFONTEX* lpelfe,
457                                            NEWTEXTMETRICEX* lpntme,
458                                            DWORD dwFontType,
459                                            LPARAM lParam) {
460   if (dwFontType != TRUETYPE_FONTTYPE) {
461     return 1;
462   }
463   const LOGFONTW& lf = ((LPENUMLOGFONTEXW)lpelfe)->elfLogFont;
464   if (lf.lfFaceName[0] == L'@') {
465     return 1;
466   }
467   FX_LPFONTDESCRIPTOR pFont = FX_Alloc(FX_FONTDESCRIPTOR, 1);
468   FXSYS_memset(pFont, 0, sizeof(FX_FONTDESCRIPTOR));
469   pFont->uCharSet = lf.lfCharSet;
470   pFont->dwFontStyles = FX_GetGdiFontStyles(lf);
471   FXSYS_wcsncpy(pFont->wsFontFace, (const FX_WCHAR*)lf.lfFaceName, 31);
472   pFont->wsFontFace[31] = 0;
473   FX_memcpy(&pFont->FontSignature, &lpntme->ntmFontSig,
474             sizeof(lpntme->ntmFontSig));
475   ((CFX_FontDescriptors*)lParam)->Add(*pFont);
476   FX_Free(pFont);
477   return 1;
478 }
FX_EnumGdiFonts(CFX_FontDescriptors & fonts,void * pUserData,const FX_WCHAR * pwsFaceName,FX_WCHAR wUnicode)479 static void FX_EnumGdiFonts(CFX_FontDescriptors& fonts,
480                             void* pUserData,
481                             const FX_WCHAR* pwsFaceName,
482                             FX_WCHAR wUnicode) {
483   HDC hDC = ::GetDC(NULL);
484   LOGFONTW lfFind;
485   FX_memset(&lfFind, 0, sizeof(lfFind));
486   lfFind.lfCharSet = DEFAULT_CHARSET;
487   if (pwsFaceName) {
488     FXSYS_wcsncpy((FX_WCHAR*)lfFind.lfFaceName, pwsFaceName, 31);
489     lfFind.lfFaceName[31] = 0;
490   }
491   EnumFontFamiliesExW(hDC, (LPLOGFONTW)&lfFind,
492                       (FONTENUMPROCW)FX_GdiFontEnumProc, (LPARAM)&fonts, 0);
493   ::ReleaseDC(NULL, hDC);
494 }
FX_GetDefFontEnumerator()495 FX_LPEnumAllFonts FX_GetDefFontEnumerator() {
496   return FX_EnumGdiFonts;
497 }
498 #else
499 const FX_CHAR* g_FontFolders[] = {
500 #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
501     "/usr/share/fonts", "/usr/share/X11/fonts/Type1",
502     "/usr/share/X11/fonts/TTF", "/usr/local/share/fonts",
503 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
504     "~/Library/Fonts", "/Library/Fonts", "/System/Library/Fonts",
505 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
506     "/system/fonts",
507 #endif
508 };
CFX_FontSourceEnum_File()509 CFX_FontSourceEnum_File::CFX_FontSourceEnum_File() {
510   for (int32_t i = 0; i < sizeof(g_FontFolders) / sizeof(const FX_CHAR*); i++) {
511     m_FolderPaths.Add(g_FontFolders[i]);
512   }
513 }
GetNextFile()514 CFX_ByteString CFX_FontSourceEnum_File::GetNextFile() {
515 Restart:
516   void* pCurHandle =
517       m_FolderQueue.GetSize() == 0
518           ? NULL
519           : m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->pFileHandle;
520   if (NULL == pCurHandle) {
521     if (m_FolderPaths.GetSize() < 1) {
522       return "";
523     }
524     pCurHandle = FX_OpenFolder(m_FolderPaths[m_FolderPaths.GetSize() - 1]);
525     FX_HandleParentPath hpp;
526     hpp.pFileHandle = pCurHandle;
527     hpp.bsParentPath = m_FolderPaths[m_FolderPaths.GetSize() - 1];
528     m_FolderQueue.Add(hpp);
529   }
530   CFX_ByteString bsName;
531   FX_BOOL bFolder;
532   CFX_ByteString bsFolderSpearator =
533       CFX_ByteString::FromUnicode(CFX_WideString(FX_GetFolderSeparator()));
534   while (TRUE) {
535     if (!FX_GetNextFile(pCurHandle, bsName, bFolder)) {
536       FX_CloseFolder(pCurHandle);
537       m_FolderQueue.RemoveAt(m_FolderQueue.GetSize() - 1);
538       if (m_FolderQueue.GetSize() == 0) {
539         m_FolderPaths.RemoveAt(m_FolderPaths.GetSize() - 1);
540         if (m_FolderPaths.GetSize() == 0) {
541           return "";
542         } else {
543           goto Restart;
544         }
545       }
546       pCurHandle =
547           m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->pFileHandle;
548       continue;
549     }
550     if (bsName == "." || bsName == "..") {
551       continue;
552     }
553     if (bFolder) {
554       FX_HandleParentPath hpp;
555       hpp.bsParentPath =
556           m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->bsParentPath +
557           bsFolderSpearator + bsName;
558       hpp.pFileHandle = FX_OpenFolder(hpp.bsParentPath);
559       if (hpp.pFileHandle == NULL) {
560         continue;
561       }
562       m_FolderQueue.Add(hpp);
563       pCurHandle = hpp.pFileHandle;
564       continue;
565     }
566     bsName =
567         m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->bsParentPath +
568         bsFolderSpearator + bsName;
569     break;
570   }
571   return bsName;
572 }
GetStartPosition(void * pUserData)573 FX_POSITION CFX_FontSourceEnum_File::GetStartPosition(void* pUserData) {
574   m_wsNext = GetNextFile().UTF8Decode();
575   if (0 == m_wsNext.GetLength()) {
576     return (FX_POSITION)0;
577   }
578   return (FX_POSITION)-1;
579 }
GetNext(FX_POSITION & pos,void * pUserData)580 IFX_FileAccess* CFX_FontSourceEnum_File::GetNext(FX_POSITION& pos,
581                                                  void* pUserData) {
582   IFX_FileAccess* pAccess = FX_CreateDefaultFileAccess(m_wsNext);
583   m_wsNext = GetNextFile().UTF8Decode();
584   pos = 0 != m_wsNext.GetLength() ? pAccess : NULL;
585   return (IFX_FileAccess*)pAccess;
586 }
FX_CreateDefaultFontSourceEnum()587 IFX_FontSourceEnum* FX_CreateDefaultFontSourceEnum() {
588   return (IFX_FontSourceEnum*)new CFX_FontSourceEnum_File;
589 }
Create(IFX_FontSourceEnum * pFontEnum,IFX_FontMgrDelegate * pDelegate,void * pUserData)590 IFX_FontMgr* IFX_FontMgr::Create(IFX_FontSourceEnum* pFontEnum,
591                                  IFX_FontMgrDelegate* pDelegate,
592                                  void* pUserData) {
593   if (NULL == pFontEnum) {
594     return NULL;
595   }
596   CFX_FontMgrImp* pFontMgr =
597       new CFX_FontMgrImp(pFontEnum, pDelegate, pUserData);
598   if (pFontMgr->EnumFonts()) {
599     return pFontMgr;
600   }
601   delete pFontMgr;
602   return NULL;
603 }
CFX_FontMgrImp(IFX_FontSourceEnum * pFontEnum,IFX_FontMgrDelegate * pDelegate,void * pUserData)604 CFX_FontMgrImp::CFX_FontMgrImp(IFX_FontSourceEnum* pFontEnum,
605                                IFX_FontMgrDelegate* pDelegate,
606                                void* pUserData)
607     : m_pFontSource(pFontEnum),
608       m_pDelegate(pDelegate),
609       m_pUserData(pUserData) {}
610 
EnumFonts()611 FX_BOOL CFX_FontMgrImp::EnumFonts() {
612   CFX_GEModule::Get()->GetFontMgr()->InitFTLibrary();
613   FXFT_Face pFace = NULL;
614   FX_POSITION pos = m_pFontSource->GetStartPosition();
615   IFX_FileAccess* pFontSource = NULL;
616   IFX_FileRead* pFontStream = NULL;
617   while (pos) {
618     pFontSource = m_pFontSource->GetNext(pos);
619     pFontStream = pFontSource->CreateFileStream(FX_FILEMODE_ReadOnly);
620     if (NULL == pFontStream) {
621       pFontSource->Release();
622       continue;
623     }
624     if (NULL == (pFace = LoadFace(pFontStream, 0))) {
625       pFontStream->Release();
626       pFontSource->Release();
627       continue;
628     }
629     int32_t nFaceCount = pFace->num_faces;
630     ReportFace(pFace, m_InstalledFonts, pFontSource);
631     if (FXFT_Get_Face_External_Stream(pFace)) {
632       FXFT_Clear_Face_External_Stream(pFace);
633     }
634     FXFT_Done_Face(pFace);
635     for (int32_t i = 1; i < nFaceCount; i++) {
636       if (NULL == (pFace = LoadFace(pFontStream, i))) {
637         continue;
638       }
639       ReportFace(pFace, m_InstalledFonts, pFontSource);
640       if (FXFT_Get_Face_External_Stream(pFace)) {
641         FXFT_Clear_Face_External_Stream(pFace);
642       }
643       FXFT_Done_Face(pFace);
644     }
645     pFontStream->Release();
646     pFontSource->Release();
647   }
648   return TRUE;
649 }
Release()650 void CFX_FontMgrImp::Release() {
651   for (int32_t i = 0; i < m_InstalledFonts.GetSize(); i++) {
652     delete m_InstalledFonts[i];
653   }
654   FX_POSITION pos = m_Hash2CandidateList.GetStartPosition();
655   while (pos) {
656     FX_DWORD dwHash;
657     CFX_FontDescriptorInfos* pDescs;
658     m_Hash2CandidateList.GetNextAssoc(pos, dwHash, pDescs);
659     if (NULL != pDescs) {
660       delete pDescs;
661     }
662   }
663   pos = m_Hash2Fonts.GetStartPosition();
664   while (pos) {
665     FX_DWORD dwHash;
666     CFX_ArrayTemplate<IFX_Font*>* pFonts;
667     m_Hash2Fonts.GetNextAssoc(pos, dwHash, pFonts);
668     if (NULL != pFonts) {
669       delete pFonts;
670     }
671   }
672   m_Hash2Fonts.RemoveAll();
673   pos = m_Hash2FileAccess.GetStartPosition();
674   while (pos) {
675     FX_DWORD dwHash;
676     IFX_FileAccess* pFileAccess;
677     m_Hash2FileAccess.GetNextAssoc(pos, dwHash, pFileAccess);
678     if (NULL != pFileAccess) {
679       pFileAccess->Release();
680     }
681   }
682   pos = m_FileAccess2IFXFont.GetStartPosition();
683   while (pos) {
684     FX_DWORD dwHash;
685     IFX_Font* pFont;
686     m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pFont);
687     if (NULL != pFont) {
688       pFont->Release();
689     }
690   }
691   pos = m_IFXFont2FileRead.GetStartPosition();
692   while (pos) {
693     IFX_Font* pFont;
694     IFX_FileRead* pFileRead;
695     m_IFXFont2FileRead.GetNextAssoc(pos, pFont, pFileRead);
696     pFileRead->Release();
697   }
698   delete this;
699 }
GetDefFontByCodePage(FX_WORD wCodePage,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)700 IFX_Font* CFX_FontMgrImp::GetDefFontByCodePage(FX_WORD wCodePage,
701                                                FX_DWORD dwFontStyles,
702                                                const FX_WCHAR* pszFontFamily) {
703   return NULL == m_pDelegate ? NULL : m_pDelegate->GetDefFontByCodePage(
704                                           this, wCodePage, dwFontStyles,
705                                           pszFontFamily);
706 }
GetDefFontByCharset(uint8_t nCharset,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)707 IFX_Font* CFX_FontMgrImp::GetDefFontByCharset(uint8_t nCharset,
708                                               FX_DWORD dwFontStyles,
709                                               const FX_WCHAR* pszFontFamily) {
710   return NULL == m_pDelegate ? NULL
711                              : m_pDelegate->GetDefFontByCharset(
712                                    this, nCharset, dwFontStyles, pszFontFamily);
713 }
GetDefFontByUnicode(FX_WCHAR wUnicode,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)714 IFX_Font* CFX_FontMgrImp::GetDefFontByUnicode(FX_WCHAR wUnicode,
715                                               FX_DWORD dwFontStyles,
716                                               const FX_WCHAR* pszFontFamily) {
717   return NULL == m_pDelegate ? NULL
718                              : m_pDelegate->GetDefFontByUnicode(
719                                    this, wUnicode, dwFontStyles, pszFontFamily);
720 }
GetDefFontByLanguage(FX_WORD wLanguage,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)721 IFX_Font* CFX_FontMgrImp::GetDefFontByLanguage(FX_WORD wLanguage,
722                                                FX_DWORD dwFontStyles,
723                                                const FX_WCHAR* pszFontFamily) {
724   return NULL == m_pDelegate ? NULL : m_pDelegate->GetDefFontByLanguage(
725                                           this, wLanguage, dwFontStyles,
726                                           pszFontFamily);
727 }
GetFontByCodePage(FX_WORD wCodePage,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)728 IFX_Font* CFX_FontMgrImp::GetFontByCodePage(FX_WORD wCodePage,
729                                             FX_DWORD dwFontStyles,
730                                             const FX_WCHAR* pszFontFamily) {
731   CFX_ByteString bsHash;
732   bsHash.Format("%d, %d", wCodePage, dwFontStyles);
733   bsHash += CFX_WideString(pszFontFamily).UTF8Encode();
734   FX_DWORD dwHash = FX_HashCode_String_GetA(bsHash, bsHash.GetLength());
735   CFX_ArrayTemplate<IFX_Font*>* pFonts = NULL;
736   IFX_Font* pFont = NULL;
737   if (m_Hash2Fonts.Lookup(dwHash, pFonts)) {
738     if (NULL == pFonts) {
739       return NULL;
740     }
741     if (0 != pFonts->GetSize()) {
742       return pFonts->GetAt(0)->Retain();
743     }
744   }
745   if (!pFonts)
746     pFonts = new CFX_ArrayTemplate<IFX_Font*>;
747   m_Hash2Fonts.SetAt(dwHash, pFonts);
748   CFX_FontDescriptorInfos* sortedFonts = NULL;
749   if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) {
750     sortedFonts = new CFX_FontDescriptorInfos;
751     MatchFonts(*sortedFonts, wCodePage, dwFontStyles,
752                CFX_WideString(pszFontFamily), 0);
753     m_Hash2CandidateList.SetAt(dwHash, sortedFonts);
754   }
755   if (sortedFonts->GetSize() == 0) {
756     return NULL;
757   }
758   CFX_FontDescriptor* pDesc = sortedFonts->GetAt(0).pFont;
759   pFont = LoadFont(pDesc->m_pFileAccess, pDesc->m_nFaceIndex, NULL);
760   if (NULL != pFont) {
761     pFont->SetLogicalFontStyle(dwFontStyles);
762   }
763   pFonts->Add(pFont);
764   return pFont;
765 }
GetFontByCharset(uint8_t nCharset,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)766 IFX_Font* CFX_FontMgrImp::GetFontByCharset(uint8_t nCharset,
767                                            FX_DWORD dwFontStyles,
768                                            const FX_WCHAR* pszFontFamily) {
769   return GetFontByCodePage(FX_GetCodePageFromCharset(nCharset), dwFontStyles,
770                            pszFontFamily);
771 }
GetFontByUnicode(FX_WCHAR wUnicode,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)772 IFX_Font* CFX_FontMgrImp::GetFontByUnicode(FX_WCHAR wUnicode,
773                                            FX_DWORD dwFontStyles,
774                                            const FX_WCHAR* pszFontFamily) {
775   IFX_Font* pFont = NULL;
776   if (m_FailedUnicodes2NULL.Lookup(wUnicode, pFont)) {
777     return NULL;
778   }
779   FGAS_LPCFONTUSB x = FGAS_GetUnicodeBitField(wUnicode);
780   FX_WORD wCodePage = NULL == x ? 0xFFFF : x->wCodePage;
781   FX_WORD wBitField = NULL == x ? 999 : x->wBitField;
782   CFX_ByteString bsHash;
783   if (wCodePage == 0xFFFF) {
784     bsHash.Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles);
785   } else {
786     bsHash.Format("%d, %d", wCodePage, dwFontStyles);
787   }
788   bsHash += CFX_WideString(pszFontFamily).UTF8Encode();
789   FX_DWORD dwHash = FX_HashCode_String_GetA(bsHash, bsHash.GetLength());
790   CFX_ArrayTemplate<IFX_Font*>* pFonts = NULL;
791   if (m_Hash2Fonts.Lookup(dwHash, pFonts)) {
792     if (NULL == pFonts) {
793       return NULL;
794     }
795     if (0 != pFonts->GetSize()) {
796       for (int32_t i = 0; i < pFonts->GetSize(); i++) {
797         if (VerifyUnicode(pFonts->GetAt(i), wUnicode)) {
798           return pFonts->GetAt(i)->Retain();
799         }
800       }
801     }
802   }
803   if (!pFonts)
804     pFonts = new CFX_ArrayTemplate<IFX_Font*>;
805   m_Hash2Fonts.SetAt(dwHash, pFonts);
806   CFX_FontDescriptorInfos* sortedFonts = NULL;
807   if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) {
808     sortedFonts = new CFX_FontDescriptorInfos;
809     MatchFonts(*sortedFonts, wCodePage, dwFontStyles,
810                CFX_WideString(pszFontFamily), wUnicode);
811     m_Hash2CandidateList.SetAt(dwHash, sortedFonts);
812   }
813   for (int32_t i = 0; i < sortedFonts->GetSize(); i++) {
814     CFX_FontDescriptor* pDesc = sortedFonts->GetAt(i).pFont;
815     if (VerifyUnicode(pDesc, wUnicode)) {
816       pFont = LoadFont(pDesc->m_pFileAccess, pDesc->m_nFaceIndex, NULL);
817       if (NULL != pFont) {
818         pFont->SetLogicalFontStyle(dwFontStyles);
819       }
820       pFonts->Add(pFont);
821       return pFont;
822     }
823   }
824   if (NULL == pszFontFamily) {
825     m_FailedUnicodes2NULL.SetAt(wUnicode, NULL);
826   }
827   return NULL;
828 }
VerifyUnicode(CFX_FontDescriptor * pDesc,FX_WCHAR wcUnicode)829 FX_BOOL CFX_FontMgrImp::VerifyUnicode(CFX_FontDescriptor* pDesc,
830                                       FX_WCHAR wcUnicode) {
831   IFX_FileRead* pFileRead =
832       pDesc->m_pFileAccess->CreateFileStream(FX_FILEMODE_ReadOnly);
833   if (NULL == pFileRead) {
834     return FALSE;
835   }
836   FXFT_Face pFace = LoadFace(pFileRead, pDesc->m_nFaceIndex);
837   if (NULL == pFace) {
838     goto BadRet;
839   }
840   if (0 != FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE)) {
841     goto BadRet;
842   }
843   if (0 == FXFT_Get_Char_Index(pFace, wcUnicode)) {
844     goto BadRet;
845   }
846   pFileRead->Release();
847   if (FXFT_Get_Face_External_Stream(pFace)) {
848     FXFT_Clear_Face_External_Stream(pFace);
849   }
850   FXFT_Done_Face(pFace);
851   return TRUE;
852 BadRet:
853   if (NULL != pFileRead) {
854     pFileRead->Release();
855   }
856   if (NULL != pFace) {
857     if (FXFT_Get_Face_External_Stream(pFace)) {
858       FXFT_Clear_Face_External_Stream(pFace);
859     }
860     FXFT_Done_Face(pFace);
861   }
862   return FALSE;
863 }
VerifyUnicode(IFX_Font * pFont,FX_WCHAR wcUnicode)864 FX_BOOL CFX_FontMgrImp::VerifyUnicode(IFX_Font* pFont, FX_WCHAR wcUnicode) {
865   if (NULL == pFont) {
866     return FALSE;
867   }
868   FXFT_Face pFace = ((CFX_Font*)pFont->GetDevFont())->GetFace();
869   FXFT_CharMap charmap = FXFT_Get_Face_Charmap(pFace);
870   if (0 != FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE)) {
871     return FALSE;
872   }
873   if (0 == FXFT_Get_Char_Index(pFace, wcUnicode)) {
874     FXFT_Set_Charmap(pFace, charmap);
875     return FALSE;
876   }
877   return TRUE;
878 }
GetFontByLanguage(FX_WORD wLanguage,FX_DWORD dwFontStyles,const FX_WCHAR * pszFontFamily)879 IFX_Font* CFX_FontMgrImp::GetFontByLanguage(FX_WORD wLanguage,
880                                             FX_DWORD dwFontStyles,
881                                             const FX_WCHAR* pszFontFamily) {
882   return GetFontByCodePage(FX_GetDefCodePageByLanguage(wLanguage), dwFontStyles,
883                            pszFontFamily);
884 }
LoadFont(const uint8_t * pBuffer,int32_t iLength,int32_t iFaceIndex,int32_t * pFaceCount)885 IFX_Font* CFX_FontMgrImp::LoadFont(const uint8_t* pBuffer,
886                                    int32_t iLength,
887                                    int32_t iFaceIndex,
888                                    int32_t* pFaceCount) {
889   void* Hash[2] = {(void*)(uintptr_t)pBuffer, (void*)(uintptr_t)iLength};
890   FX_DWORD dwHash =
891       FX_HashCode_String_GetA((const FX_CHAR*)Hash, 2 * sizeof(void*));
892   IFX_FileAccess* pFontAccess = NULL;
893   if (!m_Hash2FileAccess.Lookup(dwHash, pFontAccess)) {
894   }
895   if (NULL != pFontAccess) {
896     return LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE);
897   } else {
898     return NULL;
899   }
900 }
LoadFont(const FX_WCHAR * pszFileName,int32_t iFaceIndex,int32_t * pFaceCount)901 IFX_Font* CFX_FontMgrImp::LoadFont(const FX_WCHAR* pszFileName,
902                                    int32_t iFaceIndex,
903                                    int32_t* pFaceCount) {
904   CFX_ByteString bsHash;
905   bsHash += CFX_WideString(pszFileName).UTF8Encode();
906   FX_DWORD dwHash =
907       FX_HashCode_String_GetA((const FX_CHAR*)bsHash, bsHash.GetLength());
908   IFX_FileAccess* pFontAccess = NULL;
909   if (!m_Hash2FileAccess.Lookup(dwHash, pFontAccess)) {
910     pFontAccess = FX_CreateDefaultFileAccess(pszFileName);
911     m_Hash2FileAccess.SetAt(dwHash, pFontAccess);
912   }
913   if (NULL != pFontAccess) {
914     return LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE);
915   } else {
916     return NULL;
917   }
918 }
LoadFont(IFX_Stream * pFontStream,int32_t iFaceIndex,int32_t * pFaceCount,FX_BOOL bSaveStream)919 IFX_Font* CFX_FontMgrImp::LoadFont(IFX_Stream* pFontStream,
920                                    int32_t iFaceIndex,
921                                    int32_t* pFaceCount,
922                                    FX_BOOL bSaveStream) {
923   void* Hash[1] = {(void*)(uintptr_t)pFontStream};
924   FX_DWORD dwHash =
925       FX_HashCode_String_GetA((const FX_CHAR*)Hash, 1 * sizeof(void*));
926   IFX_FileAccess* pFontAccess = NULL;
927   if (!m_Hash2FileAccess.Lookup(dwHash, pFontAccess)) {
928   }
929   if (NULL != pFontAccess) {
930     return LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE);
931   } else {
932     return NULL;
933   }
934 }
LoadFont(IFX_FileAccess * pFontAccess,int32_t iFaceIndex,int32_t * pFaceCount,FX_BOOL bWantCache)935 IFX_Font* CFX_FontMgrImp::LoadFont(IFX_FileAccess* pFontAccess,
936                                    int32_t iFaceIndex,
937                                    int32_t* pFaceCount,
938                                    FX_BOOL bWantCache) {
939   FX_DWORD dwHash = 0;
940   IFX_Font* pFont = NULL;
941   if (bWantCache) {
942     CFX_ByteString bsHash;
943     bsHash.Format("%d, %d", (uintptr_t)pFontAccess, iFaceIndex);
944     dwHash = FX_HashCode_String_GetA(bsHash, bsHash.GetLength());
945     if (m_FileAccess2IFXFont.Lookup(dwHash, pFont)) {
946       if (NULL != pFont) {
947         if (NULL != pFaceCount) {
948           *pFaceCount = ((CFX_Font*)pFont->GetDevFont())->GetFace()->num_faces;
949         }
950         return pFont->Retain();
951       }
952     }
953   }
954   CFX_Font* pInternalFont = new CFX_Font;
955   IFX_FileRead* pFontStream =
956       pFontAccess->CreateFileStream(FX_FILEMODE_ReadOnly);
957   if (NULL == pFontStream) {
958     delete pInternalFont;
959     return NULL;
960   }
961   if (!pInternalFont->LoadFile(pFontStream, iFaceIndex)) {
962     delete pInternalFont;
963     pFontStream->Release();
964     return NULL;
965   }
966   pFont = IFX_Font::LoadFont(pInternalFont, this, TRUE);
967   if (NULL == pFont) {
968     delete pInternalFont;
969     pFontStream->Release();
970     return NULL;
971   }
972   if (bWantCache) {
973     m_FileAccess2IFXFont.SetAt(dwHash, pFont);
974   }
975   m_IFXFont2FileRead.SetAt(pFont, pFontStream);
976   if (NULL != pFaceCount) {
977     *pFaceCount = ((CFX_Font*)pFont->GetDevFont())->GetFace()->num_faces;
978   }
979   return pFont;
980 }
981 extern "C" {
_ftStreamRead(FXFT_Stream stream,unsigned long offset,unsigned char * buffer,unsigned long count)982 unsigned long _ftStreamRead(FXFT_Stream stream,
983                             unsigned long offset,
984                             unsigned char* buffer,
985                             unsigned long count) {
986   if (count == 0) {
987     return 0;
988   }
989   IFX_FileRead* pFile = (IFX_FileRead*)stream->descriptor.pointer;
990   int res = pFile->ReadBlock(buffer, offset, count);
991   if (res) {
992     return count;
993   }
994   return 0;
995 }
_ftStreamClose(FXFT_Stream stream)996 void _ftStreamClose(FXFT_Stream stream) {}
997 };
998 
LoadFace(IFX_FileRead * pFontStream,int32_t iFaceIndex)999 FXFT_Face CFX_FontMgrImp::LoadFace(IFX_FileRead* pFontStream,
1000                                    int32_t iFaceIndex) {
1001   if (!pFontStream)
1002     return nullptr;
1003 
1004   CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
1005   pFontMgr->InitFTLibrary();
1006   FXFT_Library library = pFontMgr->GetFTLibrary();
1007   if (!library)
1008     return nullptr;
1009 
1010   FXFT_Stream ftStream = FX_Alloc(FXFT_StreamRec, 1);
1011   FXSYS_memset(ftStream, 0, sizeof(FXFT_StreamRec));
1012   ftStream->base = NULL;
1013   ftStream->descriptor.pointer = pFontStream;
1014   ftStream->pos = 0;
1015   ftStream->size = (unsigned long)pFontStream->GetSize();
1016   ftStream->read = _ftStreamRead;
1017   ftStream->close = _ftStreamClose;
1018 
1019   FXFT_Open_Args ftArgs;
1020   FXSYS_memset(&ftArgs, 0, sizeof(FXFT_Open_Args));
1021   ftArgs.flags |= FT_OPEN_STREAM;
1022   ftArgs.stream = ftStream;
1023 
1024   FXFT_Face pFace = NULL;
1025   if (FXFT_Open_Face(library, &ftArgs, iFaceIndex, &pFace)) {
1026     FX_Free(ftStream);
1027     return nullptr;
1028   }
1029 
1030   FXFT_Set_Pixel_Sizes(pFace, 0, 64);
1031   return pFace;
1032 }
1033 
MatchFonts(CFX_FontDescriptorInfos & MatchedFonts,FX_WORD wCodePage,FX_DWORD dwFontStyles,const CFX_WideString & FontName,FX_WCHAR wcUnicode)1034 int32_t CFX_FontMgrImp::MatchFonts(CFX_FontDescriptorInfos& MatchedFonts,
1035                                    FX_WORD wCodePage,
1036                                    FX_DWORD dwFontStyles,
1037                                    const CFX_WideString& FontName,
1038                                    FX_WCHAR wcUnicode) {
1039   MatchedFonts.RemoveAll();
1040   CFX_WideString wsNormalizedFontName = FontName;
1041   NormalizeFontName(wsNormalizedFontName);
1042   static const int32_t nMax = 0xffff;
1043   CFX_FontDescriptor* pFont = NULL;
1044   int32_t nCount = m_InstalledFonts.GetSize();
1045   for (int32_t i = 0; i < nCount; i++) {
1046     pFont = m_InstalledFonts[i];
1047     int32_t nPenalty = CalcPenalty(pFont, wCodePage, dwFontStyles,
1048                                    wsNormalizedFontName, wcUnicode);
1049     if (nPenalty >= 0xFFFF) {
1050       continue;
1051     }
1052     FX_FontDescriptorInfo FontInfo;
1053     FontInfo.pFont = pFont;
1054     FontInfo.nPenalty = nPenalty;
1055     MatchedFonts.Add(FontInfo);
1056     if (MatchedFonts.GetSize() == nMax) {
1057       break;
1058     }
1059   }
1060   if (MatchedFonts.GetSize() == 0) {
1061     return 0;
1062   }
1063   CFX_SSortTemplate<FX_FontDescriptorInfo> ssort;
1064   ssort.ShellSort(MatchedFonts.GetData(), MatchedFonts.GetSize());
1065   return MatchedFonts.GetSize();
1066 }
1067 struct FX_BitCodePage {
1068   FX_WORD wBit;
1069   FX_WORD wCodePage;
1070 };
1071 static const FX_BitCodePage g_Bit2CodePage[] = {
1072     {0, 1252}, {1, 1250}, {2, 1251}, {3, 1253},  {4, 1254}, {5, 1255},
1073     {6, 1256}, {7, 1257}, {8, 1258}, {9, 0},     {10, 0},   {11, 0},
1074     {12, 0},   {13, 0},   {14, 0},   {15, 0},    {16, 874}, {17, 932},
1075     {18, 936}, {19, 949}, {20, 950}, {21, 1361}, {22, 0},   {23, 0},
1076     {24, 0},   {25, 0},   {26, 0},   {27, 0},    {28, 0},   {29, 0},
1077     {30, 0},   {31, 0},   {32, 0},   {33, 0},    {34, 0},   {35, 0},
1078     {36, 0},   {37, 0},   {38, 0},   {39, 0},    {40, 0},   {41, 0},
1079     {42, 0},   {43, 0},   {44, 0},   {45, 0},    {46, 0},   {47, 0},
1080     {48, 869}, {49, 866}, {50, 865}, {51, 864},  {52, 863}, {53, 862},
1081     {54, 861}, {55, 860}, {56, 857}, {57, 855},  {58, 852}, {59, 775},
1082     {60, 737}, {61, 708}, {62, 850}, {63, 437},
1083 };
FX_GetCodePageBit(FX_WORD wCodePage)1084 FX_WORD FX_GetCodePageBit(FX_WORD wCodePage) {
1085   for (int32_t i = 0; i < sizeof(g_Bit2CodePage) / sizeof(FX_BitCodePage);
1086        i++) {
1087     if (g_Bit2CodePage[i].wCodePage == wCodePage) {
1088       return g_Bit2CodePage[i].wBit;
1089     }
1090   }
1091   return (FX_WORD)-1;
1092 }
FX_GetUnicodeBit(FX_WCHAR wcUnicode)1093 FX_WORD FX_GetUnicodeBit(FX_WCHAR wcUnicode) {
1094   FGAS_LPCFONTUSB x = FGAS_GetUnicodeBitField(wcUnicode);
1095   if (NULL == x) {
1096     return 999;
1097   }
1098   return x->wBitField;
1099 }
CalcPenalty(CFX_FontDescriptor * pInstalled,FX_WORD wCodePage,FX_DWORD dwFontStyles,const CFX_WideString & FontName,FX_WCHAR wcUnicode)1100 int32_t CFX_FontMgrImp::CalcPenalty(CFX_FontDescriptor* pInstalled,
1101                                     FX_WORD wCodePage,
1102                                     FX_DWORD dwFontStyles,
1103                                     const CFX_WideString& FontName,
1104                                     FX_WCHAR wcUnicode) {
1105   int32_t nPenalty = 30000;
1106   if (0 != FontName.GetLength()) {
1107     if (FontName != pInstalled->m_wsFaceName) {
1108       int32_t i;
1109       for (i = 0; i < pInstalled->m_wsFamilyNames.GetSize(); i++) {
1110         if (pInstalled->m_wsFamilyNames[i] == FontName) {
1111           break;
1112         }
1113       }
1114       if (i == pInstalled->m_wsFamilyNames.GetSize()) {
1115         nPenalty += 0xFFFF;
1116       } else {
1117         nPenalty -= 28000;
1118       }
1119     } else {
1120       nPenalty -= 30000;
1121     }
1122     if (30000 == nPenalty &&
1123         0 == IsPartName(pInstalled->m_wsFaceName, FontName)) {
1124       int32_t i;
1125       for (i = 0; i < pInstalled->m_wsFamilyNames.GetSize(); i++) {
1126         if (0 != IsPartName(pInstalled->m_wsFamilyNames[i], FontName)) {
1127           break;
1128         }
1129       }
1130       if (i == pInstalled->m_wsFamilyNames.GetSize()) {
1131         nPenalty += 0xFFFF;
1132       } else {
1133         nPenalty -= 26000;
1134       }
1135     } else {
1136       nPenalty -= 27000;
1137     }
1138   }
1139   FX_DWORD dwStyleMask = pInstalled->m_dwFontStyles ^ dwFontStyles;
1140   if (dwStyleMask & FX_FONTSTYLE_Bold) {
1141     nPenalty += 4500;
1142   }
1143   if (dwStyleMask & FX_FONTSTYLE_FixedPitch) {
1144     nPenalty += 10000;
1145   }
1146   if (dwStyleMask & FX_FONTSTYLE_Italic) {
1147     nPenalty += 10000;
1148   }
1149   if (dwStyleMask & FX_FONTSTYLE_Serif) {
1150     nPenalty += 500;
1151   }
1152   if (dwStyleMask & FX_FONTSTYLE_Symbolic) {
1153     nPenalty += 0xFFFF;
1154   }
1155   if (nPenalty >= 0xFFFF) {
1156     return 0xFFFF;
1157   }
1158   FX_WORD wBit =
1159       ((0 == wCodePage || 0xFFFF == wCodePage) ? (FX_WORD)-1
1160                                                : FX_GetCodePageBit(wCodePage));
1161   if (wBit != (FX_WORD)-1) {
1162     FXSYS_assert(wBit < 64);
1163     if (0 == (pInstalled->m_dwCsb[wBit / 32] & (1 << (wBit % 32)))) {
1164       nPenalty += 0xFFFF;
1165     } else {
1166       nPenalty -= 60000;
1167     }
1168   }
1169   wBit =
1170       ((0 == wcUnicode || 0xFFFE == wcUnicode) ? (FX_WORD)999
1171                                                : FX_GetUnicodeBit(wcUnicode));
1172   if (wBit != (FX_WORD)999) {
1173     FXSYS_assert(wBit < 128);
1174     if (0 == (pInstalled->m_dwUsb[wBit / 32] & (1 << (wBit % 32)))) {
1175       nPenalty += 0xFFFF;
1176     } else {
1177       nPenalty -= 60000;
1178     }
1179   }
1180   return nPenalty;
1181 }
ClearFontCache()1182 void CFX_FontMgrImp::ClearFontCache() {
1183   FX_POSITION pos = m_Hash2CandidateList.GetStartPosition();
1184   while (pos) {
1185     FX_DWORD dwHash;
1186     CFX_FontDescriptorInfos* pDescs;
1187     m_Hash2CandidateList.GetNextAssoc(pos, dwHash, pDescs);
1188     if (NULL != pDescs) {
1189       delete pDescs;
1190     }
1191   }
1192   pos = m_FileAccess2IFXFont.GetStartPosition();
1193   while (pos) {
1194     FX_DWORD dwHash;
1195     IFX_Font* pFont;
1196     m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pFont);
1197     if (NULL != pFont) {
1198       pFont->Release();
1199     }
1200   }
1201   pos = m_IFXFont2FileRead.GetStartPosition();
1202   while (pos) {
1203     IFX_Font* pFont;
1204     IFX_FileRead* pFileRead;
1205     m_IFXFont2FileRead.GetNextAssoc(pos, pFont, pFileRead);
1206     pFileRead->Release();
1207   }
1208 }
RemoveFont(IFX_Font * pEFont)1209 void CFX_FontMgrImp::RemoveFont(IFX_Font* pEFont) {
1210   if (NULL == pEFont) {
1211     return;
1212   }
1213   IFX_FileRead* pFileRead;
1214   if (m_IFXFont2FileRead.Lookup(pEFont, pFileRead)) {
1215     pFileRead->Release();
1216     m_IFXFont2FileRead.RemoveKey(pEFont);
1217   }
1218   FX_POSITION pos;
1219   pos = m_FileAccess2IFXFont.GetStartPosition();
1220   while (pos) {
1221     FX_DWORD dwHash;
1222     IFX_Font* pCFont;
1223     m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pCFont);
1224     if (pCFont == pEFont) {
1225       m_FileAccess2IFXFont.RemoveKey(dwHash);
1226       break;
1227     }
1228   }
1229   pos = m_Hash2Fonts.GetStartPosition();
1230   while (pos) {
1231     FX_DWORD dwHash;
1232     CFX_ArrayTemplate<IFX_Font*>* pFonts;
1233     m_Hash2Fonts.GetNextAssoc(pos, dwHash, pFonts);
1234     if (NULL != pFonts) {
1235       for (int32_t i = 0; i < pFonts->GetSize(); i++) {
1236         if (pFonts->GetAt(i) == pEFont) {
1237           pFonts->SetAt(i, NULL);
1238         }
1239       }
1240     } else {
1241       m_Hash2Fonts.RemoveKey(dwHash);
1242     }
1243   }
1244 }
ReportFace(FXFT_Face pFace,CFX_FontDescriptors & Fonts,IFX_FileAccess * pFontAccess)1245 void CFX_FontMgrImp::ReportFace(FXFT_Face pFace,
1246                                 CFX_FontDescriptors& Fonts,
1247                                 IFX_FileAccess* pFontAccess) {
1248   if (0 == (pFace->face_flags & FT_FACE_FLAG_SCALABLE)) {
1249     return;
1250   }
1251   CFX_FontDescriptor* pFont = new CFX_FontDescriptor;
1252   pFont->m_dwFontStyles |= FXFT_Is_Face_Bold(pFace) ? FX_FONTSTYLE_Bold : 0;
1253   pFont->m_dwFontStyles |= FXFT_Is_Face_Italic(pFace) ? FX_FONTSTYLE_Italic : 0;
1254   pFont->m_dwFontStyles |= GetFlags(pFace);
1255   CFX_WordArray Charsets;
1256   GetCharsets(pFace, Charsets);
1257   GetUSBCSB(pFace, pFont->m_dwUsb, pFont->m_dwCsb);
1258   unsigned long nLength = 0;
1259   FT_ULong dwTag;
1260   uint8_t* pTable = NULL;
1261   FT_ENC_TAG(dwTag, 'n', 'a', 'm', 'e');
1262   unsigned int error = FXFT_Load_Sfnt_Table(pFace, dwTag, 0, NULL, &nLength);
1263   if (0 == error && 0 != nLength) {
1264     pTable = FX_Alloc(uint8_t, nLength);
1265     error = FXFT_Load_Sfnt_Table(pFace, dwTag, 0, pTable, NULL);
1266     if (0 != error) {
1267       FX_Free(pTable);
1268       pTable = NULL;
1269     }
1270   }
1271   GetNames(pTable, pFont->m_wsFamilyNames);
1272   if (NULL != pTable) {
1273     FX_Free(pTable);
1274   }
1275   pFont->m_wsFamilyNames.Add(CFX_ByteString(pFace->family_name).UTF8Decode());
1276   pFont->m_wsFaceName =
1277       CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(pFace));
1278   pFont->m_nFaceIndex = pFace->face_index;
1279   pFont->m_pFileAccess = pFontAccess->Retain();
1280   NormalizeFontName(pFont->m_wsFaceName);
1281   for (int32_t i = 0; i < pFont->m_wsFamilyNames.GetSize(); i++) {
1282     NormalizeFontName(pFont->m_wsFamilyNames[i]);
1283   }
1284   Fonts.Add(pFont);
1285 }
GetFlags(FXFT_Face pFace)1286 FX_DWORD CFX_FontMgrImp::GetFlags(FXFT_Face pFace) {
1287   FX_DWORD flag = 0;
1288   if (FT_IS_FIXED_WIDTH(pFace)) {
1289     flag |= FX_FONTSTYLE_FixedPitch;
1290   }
1291   TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
1292   if (!pOS2) {
1293     return flag;
1294   }
1295   if (pOS2->ulCodePageRange1 & (1 << 31)) {
1296     flag |= FX_FONTSTYLE_Symbolic;
1297   }
1298   if (pOS2->panose[0] == 2) {
1299     uint8_t uSerif = pOS2->panose[1];
1300     if ((uSerif > 1 && uSerif < 10) || uSerif > 13) {
1301       flag |= FX_FONTSTYLE_Serif;
1302     }
1303   }
1304   return flag;
1305 }
1306 #define GetUInt8(p) ((uint8_t)((p)[0]))
1307 #define GetUInt16(p) ((uint16_t)((p)[0] << 8 | (p)[1]))
1308 #define GetUInt32(p) \
1309   ((uint32_t)((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]))
GetNames(const uint8_t * name_table,CFX_WideStringArray & Names)1310 void CFX_FontMgrImp::GetNames(const uint8_t* name_table,
1311                               CFX_WideStringArray& Names) {
1312   if (NULL == name_table) {
1313     return;
1314   }
1315   uint8_t* lpTable = (uint8_t*)name_table;
1316   CFX_WideString wsFamily;
1317   uint8_t* sp = lpTable + 2;
1318   uint8_t* lpNameRecord = lpTable + 6;
1319   uint16_t nNameCount = GetUInt16(sp);
1320   uint8_t* lpStr = lpTable + GetUInt16(sp + 2);
1321   for (uint16_t j = 0; j < nNameCount; j++) {
1322     uint16_t nNameID = GetUInt16(lpNameRecord + j * 12 + 6);
1323     if (nNameID != 1) {
1324       continue;
1325     }
1326     uint16_t nPlatformID = GetUInt16(lpNameRecord + j * 12 + 0);
1327     uint16_t nNameLength = GetUInt16(lpNameRecord + j * 12 + 8);
1328     uint16_t nNameOffset = GetUInt16(lpNameRecord + j * 12 + 10);
1329     wsFamily.Empty();
1330     if (nPlatformID != 1) {
1331       for (uint16_t k = 0; k < nNameLength / 2; k++) {
1332         FX_WCHAR wcTemp = GetUInt16(lpStr + nNameOffset + k * 2);
1333         wsFamily += wcTemp;
1334       }
1335       Names.Add(wsFamily);
1336     } else {
1337       for (uint16_t k = 0; k < nNameLength; k++) {
1338         FX_WCHAR wcTemp = GetUInt8(lpStr + nNameOffset + k);
1339         wsFamily += wcTemp;
1340       }
1341       Names.Add(wsFamily);
1342     }
1343   }
1344 }
1345 #undef GetUInt8
1346 #undef GetUInt16
1347 #undef GetUInt32
1348 struct FX_BIT2CHARSET {
1349   FX_WORD wBit;
1350   FX_WORD wCharset;
1351 };
1352 FX_BIT2CHARSET g_FX_Bit2Charset1[16] = {
1353     {1 << 0, FX_CHARSET_ANSI},
1354     {1 << 1, FX_CHARSET_MSWin_EasterEuropean},
1355     {1 << 2, FX_CHARSET_MSWin_Cyrillic},
1356     {1 << 3, FX_CHARSET_MSWin_Greek},
1357     {1 << 4, FX_CHARSET_MSWin_Turkish},
1358     {1 << 5, FX_CHARSET_MSWin_Hebrew},
1359     {1 << 6, FX_CHARSET_MSWin_Arabic},
1360     {1 << 7, FX_CHARSET_MSWin_Baltic},
1361     {1 << 8, FX_CHARSET_MSWin_Vietnamese},
1362     {1 << 9, FX_CHARSET_Default},
1363     {1 << 10, FX_CHARSET_Default},
1364     {1 << 11, FX_CHARSET_Default},
1365     {1 << 12, FX_CHARSET_Default},
1366     {1 << 13, FX_CHARSET_Default},
1367     {1 << 14, FX_CHARSET_Default},
1368     {1 << 15, FX_CHARSET_Default},
1369 };
1370 FX_BIT2CHARSET g_FX_Bit2Charset2[16] = {
1371     {1 << 0, FX_CHARSET_Thai},
1372     {1 << 1, FX_CHARSET_ShiftJIS},
1373     {1 << 2, FX_CHARSET_ChineseSimplified},
1374     {1 << 3, FX_CHARSET_Korean},
1375     {1 << 4, FX_CHARSET_ChineseTriditional},
1376     {1 << 5, FX_CHARSET_Johab},
1377     {1 << 6, FX_CHARSET_Default},
1378     {1 << 7, FX_CHARSET_Default},
1379     {1 << 8, FX_CHARSET_Default},
1380     {1 << 9, FX_CHARSET_Default},
1381     {1 << 10, FX_CHARSET_Default},
1382     {1 << 11, FX_CHARSET_Default},
1383     {1 << 12, FX_CHARSET_Default},
1384     {1 << 13, FX_CHARSET_Default},
1385     {1 << 14, FX_CHARSET_OEM},
1386     {1 << 15, FX_CHARSET_Symbol},
1387 };
1388 FX_BIT2CHARSET g_FX_Bit2Charset3[16] = {
1389     {1 << 0, FX_CHARSET_Default},  {1 << 1, FX_CHARSET_Default},
1390     {1 << 2, FX_CHARSET_Default},  {1 << 3, FX_CHARSET_Default},
1391     {1 << 4, FX_CHARSET_Default},  {1 << 5, FX_CHARSET_Default},
1392     {1 << 6, FX_CHARSET_Default},  {1 << 7, FX_CHARSET_Default},
1393     {1 << 8, FX_CHARSET_Default},  {1 << 9, FX_CHARSET_Default},
1394     {1 << 10, FX_CHARSET_Default}, {1 << 11, FX_CHARSET_Default},
1395     {1 << 12, FX_CHARSET_Default}, {1 << 13, FX_CHARSET_Default},
1396     {1 << 14, FX_CHARSET_Default}, {1 << 15, FX_CHARSET_Default},
1397 };
1398 FX_BIT2CHARSET g_FX_Bit2Charset4[16] = {
1399     {1 << 0, FX_CHARSET_Default},  {1 << 1, FX_CHARSET_Default},
1400     {1 << 2, FX_CHARSET_Default},  {1 << 3, FX_CHARSET_Default},
1401     {1 << 4, FX_CHARSET_Default},  {1 << 5, FX_CHARSET_Default},
1402     {1 << 6, FX_CHARSET_Default},  {1 << 7, FX_CHARSET_Default},
1403     {1 << 8, FX_CHARSET_Default},  {1 << 9, FX_CHARSET_Default},
1404     {1 << 10, FX_CHARSET_Default}, {1 << 11, FX_CHARSET_Default},
1405     {1 << 12, FX_CHARSET_Default}, {1 << 13, FX_CHARSET_Default},
1406     {1 << 14, FX_CHARSET_Default}, {1 << 15, FX_CHARSET_US},
1407 };
1408 #define CODEPAGERANGE_IMPLEMENT(n)                   \
1409   for (int32_t i = 0; i < 16; i++) {                 \
1410     if ((a##n & g_FX_Bit2Charset##n[i].wBit) != 0) { \
1411       Charsets.Add(g_FX_Bit2Charset##n[i].wCharset); \
1412     }                                                \
1413   }
GetCharsets(FXFT_Face pFace,CFX_WordArray & Charsets)1414 void CFX_FontMgrImp::GetCharsets(FXFT_Face pFace, CFX_WordArray& Charsets) {
1415   Charsets.RemoveAll();
1416   TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
1417   if (NULL != pOS2) {
1418     FX_WORD a1, a2, a3, a4;
1419     a1 = pOS2->ulCodePageRange1 & 0x0000ffff;
1420     CODEPAGERANGE_IMPLEMENT(1);
1421     a2 = (pOS2->ulCodePageRange1 >> 16) & 0x0000ffff;
1422     CODEPAGERANGE_IMPLEMENT(2);
1423     a3 = pOS2->ulCodePageRange2 & 0x0000ffff;
1424     CODEPAGERANGE_IMPLEMENT(3);
1425     a4 = (pOS2->ulCodePageRange2 >> 16) & 0x0000ffff;
1426     CODEPAGERANGE_IMPLEMENT(4);
1427   } else {
1428     Charsets.Add(FX_CHARSET_Default);
1429   }
1430 }
1431 #undef CODEPAGERANGE_IMPLEMENT
GetUSBCSB(FXFT_Face pFace,FX_DWORD * USB,FX_DWORD * CSB)1432 void CFX_FontMgrImp::GetUSBCSB(FXFT_Face pFace, FX_DWORD* USB, FX_DWORD* CSB) {
1433   TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
1434   if (NULL != pOS2) {
1435     USB[0] = pOS2->ulUnicodeRange1;
1436     USB[1] = pOS2->ulUnicodeRange2;
1437     USB[2] = pOS2->ulUnicodeRange3;
1438     USB[3] = pOS2->ulUnicodeRange4;
1439     CSB[0] = pOS2->ulCodePageRange1;
1440     CSB[1] = pOS2->ulCodePageRange2;
1441   } else {
1442     USB[0] = 0;
1443     USB[1] = 0;
1444     USB[2] = 0;
1445     USB[3] = 0;
1446     CSB[0] = 0;
1447     CSB[1] = 0;
1448   }
1449 }
NormalizeFontName(CFX_WideString & FontName)1450 void CFX_FontMgrImp::NormalizeFontName(CFX_WideString& FontName) {
1451   FontName.MakeLower();
1452   FontName.Remove(' ');
1453   FontName.Remove('-');
1454 }
IsPartName(const CFX_WideString & Name1,const CFX_WideString & Name2)1455 int32_t CFX_FontMgrImp::IsPartName(const CFX_WideString& Name1,
1456                                    const CFX_WideString& Name2) {
1457   if (Name1.Find((const FX_WCHAR*)Name2) != -1) {
1458     return 1;
1459   }
1460   return 0;
1461 }
1462 #endif
1463