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