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_
11IFX_FontMgr* IFX_FontMgr::Create(FX_LPEnumAllFonts pEnumerator,
12                                 FX_LPMatchFont pMatcher,
13                                 void* pUserData) {
14  return new CFX_StdFontMgrImp(pEnumerator, pMatcher, pUserData);
15}
16CFX_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}
39CFX_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}
56IFX_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}
82IFX_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_
90IFX_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}
153IFX_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}
160IFX_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}
189IFX_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}
205IFX_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}
222IFX_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}
252IFX_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}
282void 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}
291void 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}
305void 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}
318FX_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}
358FX_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}
416int32_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}
436FX_LPMatchFont FX_GetDefFontMatchor() {
437  return FX_DefFontMatcher;
438}
439FX_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}
456static 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}
479static 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}
495FX_LPEnumAllFonts FX_GetDefFontEnumerator() {
496  return FX_EnumGdiFonts;
497}
498#else
499const 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};
509CFX_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}
514CFX_ByteString CFX_FontSourceEnum_File::GetNextFile() {
515Restart:
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}
573FX_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}
580IFX_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}
587IFX_FontSourceEnum* FX_CreateDefaultFontSourceEnum() {
588  return (IFX_FontSourceEnum*)new CFX_FontSourceEnum_File;
589}
590IFX_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}
604CFX_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
611FX_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}
650void 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}
700IFX_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}
707IFX_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}
714IFX_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}
721IFX_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}
728IFX_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}
766IFX_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}
772IFX_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}
829FX_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;
852BadRet:
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}
864FX_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}
879IFX_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}
885IFX_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}
901IFX_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}
919IFX_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}
935IFX_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}
981extern "C" {
982unsigned 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}
996void _ftStreamClose(FXFT_Stream stream) {}
997};
998
999FXFT_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
1034int32_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}
1067struct FX_BitCodePage {
1068  FX_WORD wBit;
1069  FX_WORD wCodePage;
1070};
1071static 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};
1084FX_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}
1093FX_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}
1100int32_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}
1182void 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}
1209void 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}
1245void 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}
1286FX_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]))
1310void 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
1348struct FX_BIT2CHARSET {
1349  FX_WORD wBit;
1350  FX_WORD wCharset;
1351};
1352FX_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};
1370FX_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};
1388FX_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};
1398FX_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  }
1414void 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
1432void 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}
1450void CFX_FontMgrImp::NormalizeFontName(CFX_WideString& FontName) {
1451  FontName.MakeLower();
1452  FontName.Remove(' ');
1453  FontName.Remove('-');
1454}
1455int32_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