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