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