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