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