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