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