blob: 4b2a1422d2d7c30248616f6be535dd2539c01ecd [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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/fgas/font/fgas_stdfontmgr.h"
8
Dan Sinclaira8a28e02016-03-23 15:41:39 -04009#include "core/fxcrt/include/fx_stream.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040010#include "xfa/fgas/crt/fgas_codepage.h"
11#include "xfa/fgas/font/fgas_fontutils.h"
12
13#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
dsinclair2d4a4fc2016-04-11 06:35:30 -070014IFX_FontMgr* IFX_FontMgr::Create(FX_LPEnumAllFonts pEnumerator) {
15 return new CFX_StdFontMgrImp(pEnumerator);
Dan Sinclair1770c022016-03-14 14:14:16 -040016}
dsinclair2d4a4fc2016-04-11 06:35:30 -070017CFX_StdFontMgrImp::CFX_StdFontMgrImp(FX_LPEnumAllFonts pEnumerator)
18 : m_pEnumerator(pEnumerator),
Dan Sinclair1770c022016-03-14 14:14:16 -040019 m_FontFaces(),
20 m_Fonts(),
21 m_CPFonts(8),
22 m_FamilyFonts(16),
23 m_UnicodeFonts(16),
24 m_BufferFonts(4),
25 m_FileFonts(4),
26 m_StreamFonts(4),
dsinclair2d4a4fc2016-04-11 06:35:30 -070027 m_DeriveFonts(4) {
Dan Sinclair1770c022016-03-14 14:14:16 -040028 if (m_pEnumerator != NULL) {
dsinclair2d4a4fc2016-04-11 06:35:30 -070029 m_pEnumerator(m_FontFaces, NULL, 0xFEFF);
Dan Sinclair1770c022016-03-14 14:14:16 -040030 }
Dan Sinclair1770c022016-03-14 14:14:16 -040031}
dsinclair2d4a4fc2016-04-11 06:35:30 -070032
Dan Sinclair1770c022016-03-14 14:14:16 -040033CFX_StdFontMgrImp::~CFX_StdFontMgrImp() {
34 m_FontFaces.RemoveAll();
35 m_CPFonts.RemoveAll();
36 m_FamilyFonts.RemoveAll();
37 m_UnicodeFonts.RemoveAll();
38 m_BufferFonts.RemoveAll();
39 m_FileFonts.RemoveAll();
40 m_StreamFonts.RemoveAll();
41 m_DeriveFonts.RemoveAll();
42 for (int32_t i = m_Fonts.GetUpperBound(); i >= 0; i--) {
43 IFX_Font* pFont = (IFX_Font*)m_Fonts[i];
44 if (pFont != NULL) {
45 pFont->Release();
46 }
47 }
48 m_Fonts.RemoveAll();
49}
50IFX_Font* CFX_StdFontMgrImp::GetDefFontByCodePage(
Tom Sepez62a70f92016-03-21 15:00:20 -070051 uint16_t wCodePage,
tsepez736f28a2016-03-25 14:19:51 -070052 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -040053 const FX_WCHAR* pszFontFamily) {
tsepez736f28a2016-03-25 14:19:51 -070054 uint32_t dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
Dan Sinclair1770c022016-03-14 14:14:16 -040055 IFX_Font* pFont = NULL;
56 if (m_CPFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) {
57 return pFont ? LoadFont(pFont, dwFontStyles, wCodePage) : NULL;
58 }
dsinclair2d4a4fc2016-04-11 06:35:30 -070059 FX_FONTDESCRIPTOR const* pFD;
Dan Sinclair1770c022016-03-14 14:14:16 -040060 if ((pFD = FindFont(pszFontFamily, dwFontStyles, TRUE, wCodePage)) == NULL) {
61 if ((pFD = FindFont(NULL, dwFontStyles, TRUE, wCodePage)) == NULL) {
62 if ((pFD = FindFont(NULL, dwFontStyles, FALSE, wCodePage)) == NULL)
63 return NULL;
64 }
65 }
66 FXSYS_assert(pFD != NULL);
67 pFont = IFX_Font::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
68 if (pFont != NULL) {
69 m_Fonts.Add(pFont);
70 m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
71 dwHash = FGAS_GetFontFamilyHash(pFD->wsFontFace, dwFontStyles, wCodePage);
72 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
73 return LoadFont(pFont, dwFontStyles, wCodePage);
74 }
75 return NULL;
76}
77IFX_Font* CFX_StdFontMgrImp::GetDefFontByCharset(
78 uint8_t nCharset,
tsepez736f28a2016-03-25 14:19:51 -070079 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -040080 const FX_WCHAR* pszFontFamily) {
81 return GetDefFontByCodePage(FX_GetCodePageFromCharset(nCharset), dwFontStyles,
82 pszFontFamily);
83}
84
85IFX_Font* CFX_StdFontMgrImp::GetDefFontByUnicode(
86 FX_WCHAR wUnicode,
tsepez736f28a2016-03-25 14:19:51 -070087 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -040088 const FX_WCHAR* pszFontFamily) {
89 const FGAS_FONTUSB* pRet = FGAS_GetUnicodeBitField(wUnicode);
90 if (pRet->wBitField == 999)
91 return nullptr;
92
tsepez736f28a2016-03-25 14:19:51 -070093 uint32_t dwHash =
Dan Sinclair1770c022016-03-14 14:14:16 -040094 FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, pRet->wBitField);
95 IFX_Font* pFont = nullptr;
96 if (m_UnicodeFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont))
97 return pFont ? LoadFont(pFont, dwFontStyles, pRet->wCodePage) : nullptr;
98
dsinclair2d4a4fc2016-04-11 06:35:30 -070099 FX_FONTDESCRIPTOR const* pFD =
Dan Sinclair1770c022016-03-14 14:14:16 -0400100 FindFont(pszFontFamily, dwFontStyles, FALSE, pRet->wCodePage,
101 pRet->wBitField, wUnicode);
102 if (!pFD && pszFontFamily) {
103 pFD = FindFont(nullptr, dwFontStyles, FALSE, pRet->wCodePage,
104 pRet->wBitField, wUnicode);
105 }
106 if (!pFD)
107 return nullptr;
108
Tom Sepez62a70f92016-03-21 15:00:20 -0700109 uint16_t wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
Dan Sinclair1770c022016-03-14 14:14:16 -0400110 const FX_WCHAR* pFontFace = pFD->wsFontFace;
111 pFont = IFX_Font::LoadFont(pFontFace, dwFontStyles, wCodePage, this);
112 if (pFont) {
113 m_Fonts.Add(pFont);
114 m_UnicodeFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
115 dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
116 m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
117 dwHash = FGAS_GetFontFamilyHash(pFontFace, dwFontStyles, wCodePage);
118 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
119 return LoadFont(pFont, dwFontStyles, wCodePage);
120 }
121 return nullptr;
122}
123
124IFX_Font* CFX_StdFontMgrImp::GetDefFontByLanguage(
Tom Sepez62a70f92016-03-21 15:00:20 -0700125 uint16_t wLanguage,
tsepez736f28a2016-03-25 14:19:51 -0700126 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400127 const FX_WCHAR* pszFontFamily) {
128 return GetDefFontByCodePage(FX_GetDefCodePageByLanguage(wLanguage),
129 dwFontStyles, pszFontFamily);
130}
131IFX_Font* CFX_StdFontMgrImp::LoadFont(const FX_WCHAR* pszFontFamily,
tsepez736f28a2016-03-25 14:19:51 -0700132 uint32_t dwFontStyles,
Tom Sepez62a70f92016-03-21 15:00:20 -0700133 uint16_t wCodePage) {
tsepez736f28a2016-03-25 14:19:51 -0700134 uint32_t dwHash =
Dan Sinclair1770c022016-03-14 14:14:16 -0400135 FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, wCodePage);
136 IFX_Font* pFont = NULL;
137 if (m_FamilyFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) {
138 return pFont ? LoadFont(pFont, dwFontStyles, wCodePage) : NULL;
139 }
dsinclair2d4a4fc2016-04-11 06:35:30 -0700140 FX_FONTDESCRIPTOR const* pFD = NULL;
Dan Sinclair1770c022016-03-14 14:14:16 -0400141 if ((pFD = FindFont(pszFontFamily, dwFontStyles, TRUE, wCodePage)) == NULL) {
142 if ((pFD = FindFont(pszFontFamily, dwFontStyles, FALSE, wCodePage)) ==
143 NULL) {
144 return NULL;
145 }
146 }
147 FXSYS_assert(pFD != NULL);
148 if (wCodePage == 0xFFFF) {
149 wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
150 }
151 pFont = IFX_Font::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
152 if (pFont != NULL) {
153 m_Fonts.Add(pFont);
154 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
155 dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
156 m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
157 return LoadFont(pFont, dwFontStyles, wCodePage);
158 }
159 return NULL;
160}
161IFX_Font* CFX_StdFontMgrImp::LoadFont(const uint8_t* pBuffer, int32_t iLength) {
162 FXSYS_assert(pBuffer != NULL && iLength > 0);
163 IFX_Font* pFont = NULL;
164 if (m_BufferFonts.Lookup((void*)pBuffer, (void*&)pFont)) {
165 if (pFont != NULL) {
166 return pFont->Retain();
167 }
168 }
169 pFont = IFX_Font::LoadFont(pBuffer, iLength, this);
170 if (pFont != NULL) {
171 m_Fonts.Add(pFont);
172 m_BufferFonts.SetAt((void*)pBuffer, pFont);
173 return pFont->Retain();
174 }
175 return NULL;
176}
177IFX_Font* CFX_StdFontMgrImp::LoadFont(const FX_WCHAR* pszFileName) {
178 FXSYS_assert(pszFileName != NULL);
tsepezb6853cf2016-04-25 11:23:43 -0700179 uint32_t dwHash = FX_HashCode_GetW(pszFileName, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400180 IFX_Font* pFont = NULL;
181 if (m_FileFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) {
182 if (pFont != NULL) {
183 return pFont->Retain();
184 }
185 }
186 pFont = IFX_Font::LoadFont(pszFileName, NULL);
187 if (pFont != NULL) {
188 m_Fonts.Add(pFont);
189 m_FileFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
190 return pFont->Retain();
191 }
192 return NULL;
193}
194IFX_Font* CFX_StdFontMgrImp::LoadFont(IFX_Stream* pFontStream,
195 const FX_WCHAR* pszFontAlias,
tsepez736f28a2016-03-25 14:19:51 -0700196 uint32_t dwFontStyles,
Tom Sepez62a70f92016-03-21 15:00:20 -0700197 uint16_t wCodePage,
Dan Sinclair1770c022016-03-14 14:14:16 -0400198 FX_BOOL bSaveStream) {
199 FXSYS_assert(pFontStream != NULL && pFontStream->GetLength() > 0);
200 IFX_Font* pFont = NULL;
201 if (m_StreamFonts.Lookup((void*)pFontStream, (void*&)pFont)) {
202 if (pFont != NULL) {
203 if (pszFontAlias != NULL) {
tsepez736f28a2016-03-25 14:19:51 -0700204 uint32_t dwHash =
Dan Sinclair1770c022016-03-14 14:14:16 -0400205 FGAS_GetFontFamilyHash(pszFontAlias, dwFontStyles, wCodePage);
206 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
207 }
208 return LoadFont(pFont, dwFontStyles, wCodePage);
209 }
210 }
211 pFont = IFX_Font::LoadFont(pFontStream, this, bSaveStream);
212 if (pFont != NULL) {
213 m_Fonts.Add(pFont);
214 m_StreamFonts.SetAt((void*)pFontStream, (void*)pFont);
215 if (pszFontAlias != NULL) {
tsepez736f28a2016-03-25 14:19:51 -0700216 uint32_t dwHash =
Dan Sinclair1770c022016-03-14 14:14:16 -0400217 FGAS_GetFontFamilyHash(pszFontAlias, dwFontStyles, wCodePage);
218 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
219 }
220 return LoadFont(pFont, dwFontStyles, wCodePage);
221 }
222 return NULL;
223}
224IFX_Font* CFX_StdFontMgrImp::LoadFont(IFX_Font* pSrcFont,
tsepez736f28a2016-03-25 14:19:51 -0700225 uint32_t dwFontStyles,
Tom Sepez62a70f92016-03-21 15:00:20 -0700226 uint16_t wCodePage) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400227 FXSYS_assert(pSrcFont != NULL);
228 if (pSrcFont->GetFontStyles() == dwFontStyles) {
229 return pSrcFont->Retain();
230 }
231 void* buffer[3] = {pSrcFont, (void*)(uintptr_t)dwFontStyles,
232 (void*)(uintptr_t)wCodePage};
tsepezb6853cf2016-04-25 11:23:43 -0700233 uint32_t dwHash = FX_HashCode_GetA(
234 CFX_ByteStringC((uint8_t*)buffer, sizeof(buffer)), false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400235 IFX_Font* pFont = NULL;
236 if (m_DeriveFonts.GetCount() > 0) {
237 m_DeriveFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont);
238 if (pFont != NULL) {
239 return pFont->Retain();
240 }
241 }
242 pFont = pSrcFont->Derive(dwFontStyles, wCodePage);
243 if (pFont != NULL) {
244 m_DeriveFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont);
245 int32_t index = m_Fonts.Find(pFont);
246 if (index < 0) {
247 m_Fonts.Add(pFont);
248 pFont->Retain();
249 }
250 return pFont;
251 }
252 return NULL;
253}
254void CFX_StdFontMgrImp::ClearFontCache() {
255 int32_t iCount = m_Fonts.GetSize();
256 for (int32_t i = 0; i < iCount; i++) {
257 IFX_Font* pFont = (IFX_Font*)m_Fonts[i];
258 if (pFont != NULL) {
259 pFont->Reset();
260 }
261 }
262}
263void CFX_StdFontMgrImp::RemoveFont(CFX_MapPtrToPtr& fontMap, IFX_Font* pFont) {
264 FX_POSITION pos = fontMap.GetStartPosition();
265 void* pKey;
266 void* pFind;
267 while (pos != NULL) {
268 pFind = NULL;
269 fontMap.GetNextAssoc(pos, pKey, pFind);
270 if (pFind != (void*)pFont) {
271 continue;
272 }
273 fontMap.RemoveKey(pKey);
274 break;
275 }
276}
277void CFX_StdFontMgrImp::RemoveFont(IFX_Font* pFont) {
278 RemoveFont(m_CPFonts, pFont);
279 RemoveFont(m_FamilyFonts, pFont);
280 RemoveFont(m_UnicodeFonts, pFont);
281 RemoveFont(m_BufferFonts, pFont);
282 RemoveFont(m_FileFonts, pFont);
283 RemoveFont(m_StreamFonts, pFont);
284 RemoveFont(m_DeriveFonts, pFont);
285 int32_t iFind = m_Fonts.Find(pFont);
286 if (iFind > -1) {
287 m_Fonts.RemoveAt(iFind, 1);
288 }
289}
dsinclair2d4a4fc2016-04-11 06:35:30 -0700290FX_FONTDESCRIPTOR const* CFX_StdFontMgrImp::FindFont(
291 const FX_WCHAR* pszFontFamily,
292 uint32_t dwFontStyles,
293 uint32_t dwMatchFlags,
294 uint16_t wCodePage,
295 uint32_t dwUSB,
296 FX_WCHAR wUnicode) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400297 FX_FONTMATCHPARAMS params;
298 FXSYS_memset(&params, 0, sizeof(params));
299 params.dwUSB = dwUSB;
300 params.wUnicode = wUnicode;
301 params.wCodePage = wCodePage;
302 params.pwsFamily = pszFontFamily;
303 params.dwFontStyles = dwFontStyles;
304 params.dwMatchFlags = dwMatchFlags;
dsinclair2d4a4fc2016-04-11 06:35:30 -0700305 FX_FONTDESCRIPTOR const* pDesc = FX_DefFontMatcher(&params, m_FontFaces);
Dan Sinclair1770c022016-03-14 14:14:16 -0400306 if (pDesc) {
307 return pDesc;
308 }
309 if (pszFontFamily && m_pEnumerator) {
310 CFX_FontDescriptors namedFonts;
dsinclair2d4a4fc2016-04-11 06:35:30 -0700311 m_pEnumerator(namedFonts, pszFontFamily, wUnicode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400312 params.pwsFamily = NULL;
dsinclair2d4a4fc2016-04-11 06:35:30 -0700313 pDesc = FX_DefFontMatcher(&params, namedFonts);
Dan Sinclair1770c022016-03-14 14:14:16 -0400314 if (pDesc == NULL) {
315 return NULL;
316 }
317 for (int32_t i = m_FontFaces.GetSize() - 1; i >= 0; i--) {
dsinclair2d4a4fc2016-04-11 06:35:30 -0700318 FX_FONTDESCRIPTOR const* pMatch = m_FontFaces.GetPtrAt(i);
Dan Sinclair1770c022016-03-14 14:14:16 -0400319 if (*pMatch == *pDesc) {
320 return pMatch;
321 }
322 }
323 int index = m_FontFaces.Add(*pDesc);
324 return m_FontFaces.GetPtrAt(index);
325 }
326 return NULL;
327}
dsinclair2d4a4fc2016-04-11 06:35:30 -0700328FX_FONTDESCRIPTOR const* FX_DefFontMatcher(FX_LPFONTMATCHPARAMS pParams,
329 const CFX_FontDescriptors& fonts) {
330 FX_FONTDESCRIPTOR const* pBestFont = NULL;
Dan Sinclair1770c022016-03-14 14:14:16 -0400331 int32_t iBestSimilar = 0;
332 FX_BOOL bMatchStyle =
333 (pParams->dwMatchFlags & FX_FONTMATCHPARA_MacthStyle) > 0;
334 int32_t iCount = fonts.GetSize();
335 for (int32_t i = 0; i < iCount; ++i) {
dsinclair2d4a4fc2016-04-11 06:35:30 -0700336 FX_FONTDESCRIPTOR const* pFont = fonts.GetPtrAt(i);
Dan Sinclair1770c022016-03-14 14:14:16 -0400337 if ((pFont->dwFontStyles & FX_FONTSTYLE_BoldItalic) ==
338 FX_FONTSTYLE_BoldItalic) {
339 continue;
340 }
341 if (pParams->pwsFamily) {
342 if (FXSYS_wcsicmp(pParams->pwsFamily, pFont->wsFontFace)) {
343 continue;
344 }
345 if (pFont->uCharSet == FX_CHARSET_Symbol) {
346 return pFont;
347 }
348 }
349 if (pFont->uCharSet == FX_CHARSET_Symbol) {
350 continue;
351 }
352 if (pParams->wCodePage != 0xFFFF) {
353 if (FX_GetCodePageFromCharset(pFont->uCharSet) != pParams->wCodePage) {
354 continue;
355 }
356 } else {
357 if (pParams->dwUSB < 128) {
tsepez736f28a2016-03-25 14:19:51 -0700358 uint32_t dwByte = pParams->dwUSB / 32;
359 uint32_t dwUSB = 1 << (pParams->dwUSB % 32);
Dan Sinclair1770c022016-03-14 14:14:16 -0400360 if ((pFont->FontSignature.fsUsb[dwByte] & dwUSB) == 0) {
361 continue;
362 }
363 }
364 }
365 if (bMatchStyle) {
366 if ((pFont->dwFontStyles & 0x0F) == (pParams->dwFontStyles & 0x0F)) {
367 return pFont;
368 } else {
369 continue;
370 }
371 }
372 if (pParams->pwsFamily != NULL) {
373 if (FXSYS_wcsicmp(pParams->pwsFamily, pFont->wsFontFace) == 0) {
374 return pFont;
375 }
376 }
377 int32_t iSimilarValue = FX_GetSimilarValue(pFont, pParams->dwFontStyles);
378 if (iBestSimilar < iSimilarValue) {
379 iBestSimilar = iSimilarValue;
380 pBestFont = pFont;
381 }
382 }
383 return iBestSimilar < 1 ? NULL : pBestFont;
384}
dsinclair2d4a4fc2016-04-11 06:35:30 -0700385int32_t FX_GetSimilarValue(FX_FONTDESCRIPTOR const* pFont,
386 uint32_t dwFontStyles) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400387 int32_t iValue = 0;
388 if ((dwFontStyles & FX_FONTSTYLE_Symbolic) ==
389 (pFont->dwFontStyles & FX_FONTSTYLE_Symbolic)) {
390 iValue += 64;
391 }
392 if ((dwFontStyles & FX_FONTSTYLE_FixedPitch) ==
393 (pFont->dwFontStyles & FX_FONTSTYLE_FixedPitch)) {
394 iValue += 32;
395 }
396 if ((dwFontStyles & FX_FONTSTYLE_Serif) ==
397 (pFont->dwFontStyles & FX_FONTSTYLE_Serif)) {
398 iValue += 16;
399 }
400 if ((dwFontStyles & FX_FONTSTYLE_Script) ==
401 (pFont->dwFontStyles & FX_FONTSTYLE_Script)) {
402 iValue += 8;
403 }
404 return iValue;
405}
406FX_LPMatchFont FX_GetDefFontMatchor() {
407 return FX_DefFontMatcher;
408}
tsepez736f28a2016-03-25 14:19:51 -0700409uint32_t FX_GetGdiFontStyles(const LOGFONTW& lf) {
410 uint32_t dwStyles = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400411 if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH) {
412 dwStyles |= FX_FONTSTYLE_FixedPitch;
413 }
414 uint8_t nFamilies = lf.lfPitchAndFamily & 0xF0;
415 if (nFamilies == FF_ROMAN) {
416 dwStyles |= FX_FONTSTYLE_Serif;
417 }
418 if (nFamilies == FF_SCRIPT) {
419 dwStyles |= FX_FONTSTYLE_Script;
420 }
421 if (lf.lfCharSet == SYMBOL_CHARSET) {
422 dwStyles |= FX_FONTSTYLE_Symbolic;
423 }
424 return dwStyles;
425}
426static int32_t CALLBACK FX_GdiFontEnumProc(ENUMLOGFONTEX* lpelfe,
427 NEWTEXTMETRICEX* lpntme,
428 DWORD dwFontType,
429 LPARAM lParam) {
430 if (dwFontType != TRUETYPE_FONTTYPE) {
431 return 1;
432 }
433 const LOGFONTW& lf = ((LPENUMLOGFONTEXW)lpelfe)->elfLogFont;
434 if (lf.lfFaceName[0] == L'@') {
435 return 1;
436 }
dsinclair2d4a4fc2016-04-11 06:35:30 -0700437 FX_FONTDESCRIPTOR* pFont = FX_Alloc(FX_FONTDESCRIPTOR, 1);
Dan Sinclair1770c022016-03-14 14:14:16 -0400438 FXSYS_memset(pFont, 0, sizeof(FX_FONTDESCRIPTOR));
439 pFont->uCharSet = lf.lfCharSet;
440 pFont->dwFontStyles = FX_GetGdiFontStyles(lf);
441 FXSYS_wcsncpy(pFont->wsFontFace, (const FX_WCHAR*)lf.lfFaceName, 31);
442 pFont->wsFontFace[31] = 0;
443 FXSYS_memcpy(&pFont->FontSignature, &lpntme->ntmFontSig,
444 sizeof(lpntme->ntmFontSig));
445 ((CFX_FontDescriptors*)lParam)->Add(*pFont);
446 FX_Free(pFont);
447 return 1;
448}
449static void FX_EnumGdiFonts(CFX_FontDescriptors& fonts,
Dan Sinclair1770c022016-03-14 14:14:16 -0400450 const FX_WCHAR* pwsFaceName,
451 FX_WCHAR wUnicode) {
452 HDC hDC = ::GetDC(NULL);
453 LOGFONTW lfFind;
454 FXSYS_memset(&lfFind, 0, sizeof(lfFind));
455 lfFind.lfCharSet = DEFAULT_CHARSET;
456 if (pwsFaceName) {
457 FXSYS_wcsncpy((FX_WCHAR*)lfFind.lfFaceName, pwsFaceName, 31);
458 lfFind.lfFaceName[31] = 0;
459 }
460 EnumFontFamiliesExW(hDC, (LPLOGFONTW)&lfFind,
461 (FONTENUMPROCW)FX_GdiFontEnumProc, (LPARAM)&fonts, 0);
462 ::ReleaseDC(NULL, hDC);
463}
464FX_LPEnumAllFonts FX_GetDefFontEnumerator() {
465 return FX_EnumGdiFonts;
466}
467#else
468const FX_CHAR* g_FontFolders[] = {
469#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
470 "/usr/share/fonts", "/usr/share/X11/fonts/Type1",
471 "/usr/share/X11/fonts/TTF", "/usr/local/share/fonts",
472#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
473 "~/Library/Fonts", "/Library/Fonts", "/System/Library/Fonts",
474#elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
475 "/system/fonts",
476#endif
477};
478
479CFX_FontSourceEnum_File::CFX_FontSourceEnum_File() {
480 for (size_t i = 0; i < FX_ArraySize(g_FontFolders); ++i)
481 m_FolderPaths.Add(g_FontFolders[i]);
482}
483
484CFX_ByteString CFX_FontSourceEnum_File::GetNextFile() {
485Restart:
486 void* pCurHandle =
487 m_FolderQueue.GetSize() == 0
488 ? NULL
489 : m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->pFileHandle;
490 if (NULL == pCurHandle) {
491 if (m_FolderPaths.GetSize() < 1) {
492 return "";
493 }
tsepezb4c9f3f2016-04-13 15:41:21 -0700494 pCurHandle =
495 FX_OpenFolder(m_FolderPaths[m_FolderPaths.GetSize() - 1].c_str());
Dan Sinclair1770c022016-03-14 14:14:16 -0400496 FX_HandleParentPath hpp;
497 hpp.pFileHandle = pCurHandle;
498 hpp.bsParentPath = m_FolderPaths[m_FolderPaths.GetSize() - 1];
499 m_FolderQueue.Add(hpp);
500 }
501 CFX_ByteString bsName;
502 FX_BOOL bFolder;
503 CFX_ByteString bsFolderSpearator =
504 CFX_ByteString::FromUnicode(CFX_WideString(FX_GetFolderSeparator()));
505 while (TRUE) {
506 if (!FX_GetNextFile(pCurHandle, bsName, bFolder)) {
507 FX_CloseFolder(pCurHandle);
508 m_FolderQueue.RemoveAt(m_FolderQueue.GetSize() - 1);
509 if (m_FolderQueue.GetSize() == 0) {
510 m_FolderPaths.RemoveAt(m_FolderPaths.GetSize() - 1);
511 if (m_FolderPaths.GetSize() == 0) {
512 return "";
513 } else {
514 goto Restart;
515 }
516 }
517 pCurHandle =
518 m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->pFileHandle;
519 continue;
520 }
521 if (bsName == "." || bsName == "..") {
522 continue;
523 }
524 if (bFolder) {
525 FX_HandleParentPath hpp;
526 hpp.bsParentPath =
527 m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->bsParentPath +
528 bsFolderSpearator + bsName;
tsepezb4c9f3f2016-04-13 15:41:21 -0700529 hpp.pFileHandle = FX_OpenFolder(hpp.bsParentPath.c_str());
Dan Sinclair1770c022016-03-14 14:14:16 -0400530 if (hpp.pFileHandle == NULL) {
531 continue;
532 }
533 m_FolderQueue.Add(hpp);
534 pCurHandle = hpp.pFileHandle;
535 continue;
536 }
537 bsName =
538 m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->bsParentPath +
539 bsFolderSpearator + bsName;
540 break;
541 }
542 return bsName;
543}
dsinclair2d4a4fc2016-04-11 06:35:30 -0700544FX_POSITION CFX_FontSourceEnum_File::GetStartPosition() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400545 m_wsNext = GetNextFile().UTF8Decode();
546 if (0 == m_wsNext.GetLength()) {
547 return (FX_POSITION)0;
548 }
549 return (FX_POSITION)-1;
550}
dsinclair2d4a4fc2016-04-11 06:35:30 -0700551
552IFX_FileAccess* CFX_FontSourceEnum_File::GetNext(FX_POSITION& pos) {
tsepez4c3debb2016-04-08 12:20:38 -0700553 IFX_FileAccess* pAccess = FX_CreateDefaultFileAccess(m_wsNext.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -0400554 m_wsNext = GetNextFile().UTF8Decode();
555 pos = 0 != m_wsNext.GetLength() ? pAccess : NULL;
556 return (IFX_FileAccess*)pAccess;
557}
558IFX_FontSourceEnum* FX_CreateDefaultFontSourceEnum() {
559 return (IFX_FontSourceEnum*)new CFX_FontSourceEnum_File;
560}
dsinclair2d4a4fc2016-04-11 06:35:30 -0700561IFX_FontMgr* IFX_FontMgr::Create(IFX_FontSourceEnum* pFontEnum) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400562 if (NULL == pFontEnum) {
563 return NULL;
564 }
dsinclair2d4a4fc2016-04-11 06:35:30 -0700565 CFX_FontMgrImp* pFontMgr = new CFX_FontMgrImp(pFontEnum);
Dan Sinclair1770c022016-03-14 14:14:16 -0400566 if (pFontMgr->EnumFonts()) {
567 return pFontMgr;
568 }
569 delete pFontMgr;
570 return NULL;
571}
dsinclair2d4a4fc2016-04-11 06:35:30 -0700572CFX_FontMgrImp::CFX_FontMgrImp(IFX_FontSourceEnum* pFontEnum)
573 : m_pFontSource(pFontEnum) {}
Dan Sinclair1770c022016-03-14 14:14:16 -0400574
575FX_BOOL CFX_FontMgrImp::EnumFontsFromFontMapper() {
576 CFX_FontMapper* pFontMapper =
577 CFX_GEModule::Get()->GetFontMgr()->GetBuiltinMapper();
578 if (!pFontMapper)
579 return FALSE;
dsinclairea982382016-04-12 10:51:04 -0700580
Dan Sinclair1770c022016-03-14 14:14:16 -0400581 IFX_SystemFontInfo* pSystemFontInfo = pFontMapper->GetSystemFontInfo();
582 if (!pSystemFontInfo)
583 return FALSE;
dsinclairea982382016-04-12 10:51:04 -0700584
Dan Sinclair1770c022016-03-14 14:14:16 -0400585 pSystemFontInfo->EnumFontList(pFontMapper);
586 for (int32_t i = 0; i < pFontMapper->GetFaceSize(); ++i) {
587 IFX_FileRead* pFontStream =
588 CreateFontStream(pFontMapper, pSystemFontInfo, i);
589 if (!pFontStream)
590 continue;
dsinclairea982382016-04-12 10:51:04 -0700591
Dan Sinclair1770c022016-03-14 14:14:16 -0400592 CFX_WideString wsFaceName =
593 CFX_WideString::FromLocal(pFontMapper->GetFaceName(i).c_str());
594 RegisterFaces(pFontStream, &wsFaceName);
595 pFontStream->Release();
596 }
597 if (m_InstalledFonts.GetSize() == 0)
598 return FALSE;
dsinclairea982382016-04-12 10:51:04 -0700599
Dan Sinclair1770c022016-03-14 14:14:16 -0400600 return TRUE;
601}
dsinclairea982382016-04-12 10:51:04 -0700602
Dan Sinclair1770c022016-03-14 14:14:16 -0400603FX_BOOL CFX_FontMgrImp::EnumFontsFromFiles() {
604 CFX_GEModule::Get()->GetFontMgr()->InitFTLibrary();
605 FX_POSITION pos = m_pFontSource->GetStartPosition();
606 IFX_FileAccess* pFontSource = nullptr;
607 IFX_FileRead* pFontStream = nullptr;
608 while (pos) {
609 pFontSource = m_pFontSource->GetNext(pos);
610 pFontStream = pFontSource->CreateFileStream(FX_FILEMODE_ReadOnly);
611 if (!pFontStream) {
612 pFontSource->Release();
613 continue;
614 }
615 RegisterFaces(pFontStream, nullptr);
616 pFontStream->Release();
617 pFontSource->Release();
618 }
619 if (m_InstalledFonts.GetSize() == 0)
620 return FALSE;
621 return TRUE;
622}
623FX_BOOL CFX_FontMgrImp::EnumFonts() {
624 if (EnumFontsFromFontMapper())
625 return TRUE;
626 return EnumFontsFromFiles();
627}
628void CFX_FontMgrImp::Release() {
629 for (int32_t i = 0; i < m_InstalledFonts.GetSize(); i++) {
630 delete m_InstalledFonts[i];
631 }
632 FX_POSITION pos = m_Hash2CandidateList.GetStartPosition();
633 while (pos) {
tsepez736f28a2016-03-25 14:19:51 -0700634 uint32_t dwHash;
Dan Sinclair1770c022016-03-14 14:14:16 -0400635 CFX_FontDescriptorInfos* pDescs;
636 m_Hash2CandidateList.GetNextAssoc(pos, dwHash, pDescs);
637 if (NULL != pDescs) {
638 delete pDescs;
639 }
640 }
641 pos = m_Hash2Fonts.GetStartPosition();
642 while (pos) {
tsepez736f28a2016-03-25 14:19:51 -0700643 uint32_t dwHash;
Dan Sinclair1770c022016-03-14 14:14:16 -0400644 CFX_ArrayTemplate<IFX_Font*>* pFonts;
645 m_Hash2Fonts.GetNextAssoc(pos, dwHash, pFonts);
646 if (NULL != pFonts) {
647 delete pFonts;
648 }
649 }
650 m_Hash2Fonts.RemoveAll();
651 pos = m_Hash2FileAccess.GetStartPosition();
652 while (pos) {
tsepez736f28a2016-03-25 14:19:51 -0700653 uint32_t dwHash;
Dan Sinclair1770c022016-03-14 14:14:16 -0400654 IFX_FileAccess* pFileAccess;
655 m_Hash2FileAccess.GetNextAssoc(pos, dwHash, pFileAccess);
656 if (NULL != pFileAccess) {
657 pFileAccess->Release();
658 }
659 }
660 pos = m_FileAccess2IFXFont.GetStartPosition();
661 while (pos) {
tsepez736f28a2016-03-25 14:19:51 -0700662 uint32_t dwHash;
Dan Sinclair1770c022016-03-14 14:14:16 -0400663 IFX_Font* pFont;
664 m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pFont);
665 if (NULL != pFont) {
666 pFont->Release();
667 }
668 }
669 pos = m_IFXFont2FileRead.GetStartPosition();
670 while (pos) {
671 IFX_Font* pFont;
672 IFX_FileRead* pFileRead;
673 m_IFXFont2FileRead.GetNextAssoc(pos, pFont, pFileRead);
674 pFileRead->Release();
675 }
676 delete this;
677}
Tom Sepez62a70f92016-03-21 15:00:20 -0700678IFX_Font* CFX_FontMgrImp::GetDefFontByCodePage(uint16_t wCodePage,
tsepez736f28a2016-03-25 14:19:51 -0700679 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400680 const FX_WCHAR* pszFontFamily) {
dsinclair2d4a4fc2016-04-11 06:35:30 -0700681 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400682}
683IFX_Font* CFX_FontMgrImp::GetDefFontByCharset(uint8_t nCharset,
tsepez736f28a2016-03-25 14:19:51 -0700684 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400685 const FX_WCHAR* pszFontFamily) {
dsinclair2d4a4fc2016-04-11 06:35:30 -0700686 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400687}
688IFX_Font* CFX_FontMgrImp::GetDefFontByUnicode(FX_WCHAR wUnicode,
tsepez736f28a2016-03-25 14:19:51 -0700689 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400690 const FX_WCHAR* pszFontFamily) {
dsinclair2d4a4fc2016-04-11 06:35:30 -0700691 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400692}
Tom Sepez62a70f92016-03-21 15:00:20 -0700693IFX_Font* CFX_FontMgrImp::GetDefFontByLanguage(uint16_t wLanguage,
tsepez736f28a2016-03-25 14:19:51 -0700694 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400695 const FX_WCHAR* pszFontFamily) {
dsinclair2d4a4fc2016-04-11 06:35:30 -0700696 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400697}
dsinclairea982382016-04-12 10:51:04 -0700698
Tom Sepez62a70f92016-03-21 15:00:20 -0700699IFX_Font* CFX_FontMgrImp::GetFontByCodePage(uint16_t wCodePage,
tsepez736f28a2016-03-25 14:19:51 -0700700 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400701 const FX_WCHAR* pszFontFamily) {
702 CFX_ByteString bsHash;
703 bsHash.Format("%d, %d", wCodePage, dwFontStyles);
704 bsHash += CFX_WideString(pszFontFamily).UTF8Encode();
tsepezb6853cf2016-04-25 11:23:43 -0700705 uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false);
dsinclairea982382016-04-12 10:51:04 -0700706 CFX_ArrayTemplate<IFX_Font*>* pFonts = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400707 if (m_Hash2Fonts.Lookup(dwHash, pFonts)) {
dsinclairea982382016-04-12 10:51:04 -0700708 if (!pFonts)
709 return nullptr;
710
711 if (pFonts->GetSize() != 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400712 return pFonts->GetAt(0)->Retain();
Dan Sinclair1770c022016-03-14 14:14:16 -0400713 }
dsinclairea982382016-04-12 10:51:04 -0700714
Dan Sinclair1770c022016-03-14 14:14:16 -0400715 if (!pFonts)
716 pFonts = new CFX_ArrayTemplate<IFX_Font*>;
dsinclairea982382016-04-12 10:51:04 -0700717
Dan Sinclair1770c022016-03-14 14:14:16 -0400718 m_Hash2Fonts.SetAt(dwHash, pFonts);
dsinclairea982382016-04-12 10:51:04 -0700719 CFX_FontDescriptorInfos* sortedFonts = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400720 if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) {
721 sortedFonts = new CFX_FontDescriptorInfos;
722 MatchFonts(*sortedFonts, wCodePage, dwFontStyles,
723 CFX_WideString(pszFontFamily), 0);
724 m_Hash2CandidateList.SetAt(dwHash, sortedFonts);
725 }
dsinclairea982382016-04-12 10:51:04 -0700726 if (sortedFonts->GetSize() == 0)
727 return nullptr;
728
Dan Sinclair1770c022016-03-14 14:14:16 -0400729 CFX_FontDescriptor* pDesc = sortedFonts->GetAt(0).pFont;
dsinclairea982382016-04-12 10:51:04 -0700730 IFX_Font* pFont =
731 pDesc->m_pFileAccess
732 ? LoadFont(pDesc->m_pFileAccess, pDesc->m_nFaceIndex, nullptr)
733 : LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr);
734 if (pFont)
Dan Sinclair1770c022016-03-14 14:14:16 -0400735 pFont->SetLogicalFontStyle(dwFontStyles);
dsinclairea982382016-04-12 10:51:04 -0700736
Dan Sinclair1770c022016-03-14 14:14:16 -0400737 pFonts->Add(pFont);
738 return pFont;
739}
740IFX_Font* CFX_FontMgrImp::GetFontByCharset(uint8_t nCharset,
tsepez736f28a2016-03-25 14:19:51 -0700741 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400742 const FX_WCHAR* pszFontFamily) {
743 return GetFontByCodePage(FX_GetCodePageFromCharset(nCharset), dwFontStyles,
744 pszFontFamily);
745}
746IFX_Font* CFX_FontMgrImp::GetFontByUnicode(FX_WCHAR wUnicode,
tsepez736f28a2016-03-25 14:19:51 -0700747 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400748 const FX_WCHAR* pszFontFamily) {
749 IFX_Font* pFont = nullptr;
750 if (m_FailedUnicodes2NULL.Lookup(wUnicode, pFont))
751 return nullptr;
752 const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wUnicode);
Tom Sepez62a70f92016-03-21 15:00:20 -0700753 uint16_t wCodePage = x ? x->wCodePage : 0xFFFF;
754 uint16_t wBitField = x ? x->wBitField : 0x03E7;
Dan Sinclair1770c022016-03-14 14:14:16 -0400755 CFX_ByteString bsHash;
756 if (wCodePage == 0xFFFF)
757 bsHash.Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles);
758 else
759 bsHash.Format("%d, %d", wCodePage, dwFontStyles);
760 bsHash += CFX_WideString(pszFontFamily).UTF8Encode();
tsepezb6853cf2016-04-25 11:23:43 -0700761 uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400762 CFX_ArrayTemplate<IFX_Font*>* pFonts = nullptr;
763 if (m_Hash2Fonts.Lookup(dwHash, pFonts)) {
764 if (!pFonts)
765 return nullptr;
766 for (int32_t i = 0; i < pFonts->GetSize(); ++i) {
767 if (VerifyUnicode(pFonts->GetAt(i), wUnicode))
768 return pFonts->GetAt(i)->Retain();
769 }
770 }
771 if (!pFonts)
772 pFonts = new CFX_ArrayTemplate<IFX_Font*>;
773 m_Hash2Fonts.SetAt(dwHash, pFonts);
774 CFX_FontDescriptorInfos* sortedFonts = nullptr;
775 if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) {
776 sortedFonts = new CFX_FontDescriptorInfos;
777 MatchFonts(*sortedFonts, wCodePage, dwFontStyles,
778 CFX_WideString(pszFontFamily), wUnicode);
779 m_Hash2CandidateList.SetAt(dwHash, sortedFonts);
780 }
781 for (int32_t i = 0; i < sortedFonts->GetSize(); ++i) {
782 CFX_FontDescriptor* pDesc = sortedFonts->GetAt(i).pFont;
783 if (!VerifyUnicode(pDesc, wUnicode))
784 continue;
785 if (pDesc->m_pFileAccess)
786 pFont = LoadFont(pDesc->m_pFileAccess, pDesc->m_nFaceIndex, nullptr);
787 else
788 pFont = LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr);
789 if (!pFont)
790 continue;
791 pFont->SetLogicalFontStyle(dwFontStyles);
792 pFonts->Add(pFont);
793 return pFont;
794 }
795 if (!pszFontFamily)
796 m_FailedUnicodes2NULL.SetAt(wUnicode, nullptr);
797 return nullptr;
798}
799FX_BOOL CFX_FontMgrImp::VerifyUnicode(CFX_FontDescriptor* pDesc,
800 FX_WCHAR wcUnicode) {
801 IFX_FileRead* pFileRead = nullptr;
802 if (pDesc->m_pFileAccess)
803 pFileRead = pDesc->m_pFileAccess->CreateFileStream(FX_FILEMODE_ReadOnly);
804 else
805 pFileRead = CreateFontStream(pDesc->m_wsFaceName.UTF8Encode());
806 if (!pFileRead)
807 return FALSE;
808 FXFT_Face pFace = LoadFace(pFileRead, pDesc->m_nFaceIndex);
809 FT_Error retCharmap = FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE);
810 FT_Error retIndex = FXFT_Get_Char_Index(pFace, wcUnicode);
811 pFileRead->Release();
812 if (!pFace)
813 return FALSE;
814 if (FXFT_Get_Face_External_Stream(pFace))
815 FXFT_Clear_Face_External_Stream(pFace);
816 FXFT_Done_Face(pFace);
817 return !retCharmap && retIndex;
818}
dsinclairea982382016-04-12 10:51:04 -0700819
Dan Sinclair1770c022016-03-14 14:14:16 -0400820FX_BOOL CFX_FontMgrImp::VerifyUnicode(IFX_Font* pFont, FX_WCHAR wcUnicode) {
dsinclairea982382016-04-12 10:51:04 -0700821 if (!pFont)
Dan Sinclair1770c022016-03-14 14:14:16 -0400822 return FALSE;
dsinclairea982382016-04-12 10:51:04 -0700823
Dan Sinclair1770c022016-03-14 14:14:16 -0400824 FXFT_Face pFace = ((CFX_Font*)pFont->GetDevFont())->GetFace();
825 FXFT_CharMap charmap = FXFT_Get_Face_Charmap(pFace);
dsinclairea982382016-04-12 10:51:04 -0700826 if (FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE) != 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400827 return FALSE;
dsinclairea982382016-04-12 10:51:04 -0700828
829 if (FXFT_Get_Char_Index(pFace, wcUnicode) == 0) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400830 FXFT_Set_Charmap(pFace, charmap);
831 return FALSE;
832 }
833 return TRUE;
834}
dsinclairea982382016-04-12 10:51:04 -0700835
Tom Sepez62a70f92016-03-21 15:00:20 -0700836IFX_Font* CFX_FontMgrImp::GetFontByLanguage(uint16_t wLanguage,
tsepez736f28a2016-03-25 14:19:51 -0700837 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -0400838 const FX_WCHAR* pszFontFamily) {
839 return GetFontByCodePage(FX_GetDefCodePageByLanguage(wLanguage), dwFontStyles,
840 pszFontFamily);
841}
dsinclairea982382016-04-12 10:51:04 -0700842
Dan Sinclair1770c022016-03-14 14:14:16 -0400843IFX_Font* CFX_FontMgrImp::LoadFont(const uint8_t* pBuffer,
844 int32_t iLength,
845 int32_t iFaceIndex,
846 int32_t* pFaceCount) {
847 void* Hash[2] = {(void*)(uintptr_t)pBuffer, (void*)(uintptr_t)iLength};
tsepez736f28a2016-03-25 14:19:51 -0700848 uint32_t dwHash =
tsepezb6853cf2016-04-25 11:23:43 -0700849 FX_HashCode_GetA(CFX_ByteStringC((uint8_t*)Hash, sizeof(Hash)), false);
dsinclairea982382016-04-12 10:51:04 -0700850 IFX_FileAccess* pFontAccess = nullptr;
851 m_Hash2FileAccess.Lookup(dwHash, pFontAccess);
852 return pFontAccess ? LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE)
853 : nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400854}
dsinclairea982382016-04-12 10:51:04 -0700855
Dan Sinclair1770c022016-03-14 14:14:16 -0400856IFX_Font* CFX_FontMgrImp::LoadFont(const FX_WCHAR* pszFileName,
857 int32_t iFaceIndex,
858 int32_t* pFaceCount) {
859 CFX_ByteString bsHash;
860 bsHash += CFX_WideString(pszFileName).UTF8Encode();
dsinclairea982382016-04-12 10:51:04 -0700861
tsepezb6853cf2016-04-25 11:23:43 -0700862 uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false);
dsinclairea982382016-04-12 10:51:04 -0700863 IFX_FileAccess* pFontAccess = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400864 if (!m_Hash2FileAccess.Lookup(dwHash, pFontAccess)) {
865 pFontAccess = FX_CreateDefaultFileAccess(pszFileName);
866 m_Hash2FileAccess.SetAt(dwHash, pFontAccess);
867 }
dsinclairea982382016-04-12 10:51:04 -0700868
869 return pFontAccess ? LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE)
870 : nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400871}
dsinclairea982382016-04-12 10:51:04 -0700872
Dan Sinclair1770c022016-03-14 14:14:16 -0400873IFX_Font* CFX_FontMgrImp::LoadFont(IFX_Stream* pFontStream,
874 int32_t iFaceIndex,
875 int32_t* pFaceCount,
876 FX_BOOL bSaveStream) {
877 void* Hash[1] = {(void*)(uintptr_t)pFontStream};
tsepez736f28a2016-03-25 14:19:51 -0700878 uint32_t dwHash =
tsepezb6853cf2016-04-25 11:23:43 -0700879 FX_HashCode_GetA(CFX_ByteStringC((uint8_t*)Hash, sizeof(Hash)), false);
dsinclairea982382016-04-12 10:51:04 -0700880 IFX_FileAccess* pFontAccess = nullptr;
881 m_Hash2FileAccess.Lookup(dwHash, pFontAccess);
882
883 return pFontAccess ? LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE)
884 : nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400885}
dsinclairea982382016-04-12 10:51:04 -0700886
Dan Sinclair1770c022016-03-14 14:14:16 -0400887IFX_Font* CFX_FontMgrImp::LoadFont(IFX_FileAccess* pFontAccess,
888 int32_t iFaceIndex,
889 int32_t* pFaceCount,
890 FX_BOOL bWantCache) {
tsepez736f28a2016-03-25 14:19:51 -0700891 uint32_t dwHash = 0;
dsinclairea982382016-04-12 10:51:04 -0700892 IFX_Font* pFont = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400893 if (bWantCache) {
894 CFX_ByteString bsHash;
895 bsHash.Format("%d, %d", (uintptr_t)pFontAccess, iFaceIndex);
tsepezb6853cf2016-04-25 11:23:43 -0700896 dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400897 if (m_FileAccess2IFXFont.Lookup(dwHash, pFont)) {
dsinclairea982382016-04-12 10:51:04 -0700898 if (pFont) {
899 if (pFaceCount)
Dan Sinclair1770c022016-03-14 14:14:16 -0400900 *pFaceCount = ((CFX_Font*)pFont->GetDevFont())->GetFace()->num_faces;
Dan Sinclair1770c022016-03-14 14:14:16 -0400901 return pFont->Retain();
902 }
903 }
904 }
dsinclairea982382016-04-12 10:51:04 -0700905
Dan Sinclair1770c022016-03-14 14:14:16 -0400906 CFX_Font* pInternalFont = new CFX_Font;
907 IFX_FileRead* pFontStream =
908 pFontAccess->CreateFileStream(FX_FILEMODE_ReadOnly);
dsinclairea982382016-04-12 10:51:04 -0700909 if (!pFontStream) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400910 delete pInternalFont;
dsinclairea982382016-04-12 10:51:04 -0700911 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400912 }
913 if (!pInternalFont->LoadFile(pFontStream, iFaceIndex)) {
914 delete pInternalFont;
915 pFontStream->Release();
dsinclairea982382016-04-12 10:51:04 -0700916 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400917 }
918 pFont = IFX_Font::LoadFont(pInternalFont, this, TRUE);
dsinclairea982382016-04-12 10:51:04 -0700919 if (!pFont) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400920 delete pInternalFont;
921 pFontStream->Release();
dsinclairea982382016-04-12 10:51:04 -0700922 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400923 }
dsinclairea982382016-04-12 10:51:04 -0700924 if (bWantCache)
Dan Sinclair1770c022016-03-14 14:14:16 -0400925 m_FileAccess2IFXFont.SetAt(dwHash, pFont);
dsinclairea982382016-04-12 10:51:04 -0700926
Dan Sinclair1770c022016-03-14 14:14:16 -0400927 m_IFXFont2FileRead.SetAt(pFont, pFontStream);
dsinclairea982382016-04-12 10:51:04 -0700928 if (pFaceCount)
Dan Sinclair1770c022016-03-14 14:14:16 -0400929 *pFaceCount = ((CFX_Font*)pFont->GetDevFont())->GetFace()->num_faces;
dsinclairea982382016-04-12 10:51:04 -0700930
Dan Sinclair1770c022016-03-14 14:14:16 -0400931 return pFont;
932}
dsinclairea982382016-04-12 10:51:04 -0700933
Dan Sinclair1770c022016-03-14 14:14:16 -0400934IFX_Font* CFX_FontMgrImp::LoadFont(const CFX_WideString& wsFaceName,
935 int32_t iFaceIndex,
936 int32_t* pFaceCount) {
937 CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
938 CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper();
939 if (!pFontMapper)
940 return nullptr;
dsinclairea982382016-04-12 10:51:04 -0700941
Dan Sinclair1770c022016-03-14 14:14:16 -0400942 IFX_SystemFontInfo* pSystemFontInfo = pFontMapper->GetSystemFontInfo();
943 if (!pSystemFontInfo)
944 return nullptr;
dsinclairea982382016-04-12 10:51:04 -0700945
Dan Sinclair1770c022016-03-14 14:14:16 -0400946 IFX_FileRead* pFontStream = CreateFontStream(wsFaceName.UTF8Encode());
947 if (!pFontStream)
948 return nullptr;
dsinclairea982382016-04-12 10:51:04 -0700949
Dan Sinclair1770c022016-03-14 14:14:16 -0400950 if (!LoadFace(pFontStream, 0)) {
951 pFontStream->Release();
952 return nullptr;
953 }
dsinclairea982382016-04-12 10:51:04 -0700954
Dan Sinclair1770c022016-03-14 14:14:16 -0400955 CFX_Font* pInternalFont = new CFX_Font();
956 if (!pInternalFont->LoadFile(pFontStream, iFaceIndex)) {
957 pFontStream->Release();
958 return nullptr;
959 }
dsinclairea982382016-04-12 10:51:04 -0700960
Dan Sinclair1770c022016-03-14 14:14:16 -0400961 IFX_Font* pFont = IFX_Font::LoadFont(pInternalFont, this, FALSE);
962 if (!pFont) {
963 pFontStream->Release();
964 return nullptr;
965 }
dsinclairea982382016-04-12 10:51:04 -0700966
Dan Sinclair1770c022016-03-14 14:14:16 -0400967 m_IFXFont2FileRead.SetAt(pFont, pFontStream);
968 if (pFaceCount)
969 *pFaceCount = ((CFX_Font*)pFont->GetDevFont())->GetFace()->num_faces;
dsinclairea982382016-04-12 10:51:04 -0700970
Dan Sinclair1770c022016-03-14 14:14:16 -0400971 return pFont;
972}
dsinclairea982382016-04-12 10:51:04 -0700973
Dan Sinclair1770c022016-03-14 14:14:16 -0400974extern "C" {
dsinclairea982382016-04-12 10:51:04 -0700975
Dan Sinclair1770c022016-03-14 14:14:16 -0400976unsigned long _ftStreamRead(FXFT_Stream stream,
977 unsigned long offset,
978 unsigned char* buffer,
979 unsigned long count) {
dsinclairea982382016-04-12 10:51:04 -0700980 if (count == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400981 return 0;
dsinclairea982382016-04-12 10:51:04 -0700982
Dan Sinclair1770c022016-03-14 14:14:16 -0400983 IFX_FileRead* pFile = (IFX_FileRead*)stream->descriptor.pointer;
984 int res = pFile->ReadBlock(buffer, offset, count);
dsinclairea982382016-04-12 10:51:04 -0700985 if (res)
Dan Sinclair1770c022016-03-14 14:14:16 -0400986 return count;
Dan Sinclair1770c022016-03-14 14:14:16 -0400987 return 0;
988}
dsinclairea982382016-04-12 10:51:04 -0700989
Dan Sinclair1770c022016-03-14 14:14:16 -0400990void _ftStreamClose(FXFT_Stream stream) {}
dsinclairea982382016-04-12 10:51:04 -0700991
992}; // extern "C"
Dan Sinclair1770c022016-03-14 14:14:16 -0400993
994FXFT_Face CFX_FontMgrImp::LoadFace(IFX_FileRead* pFontStream,
995 int32_t iFaceIndex) {
996 if (!pFontStream)
997 return nullptr;
998
999 CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
1000 pFontMgr->InitFTLibrary();
1001 FXFT_Library library = pFontMgr->GetFTLibrary();
1002 if (!library)
1003 return nullptr;
1004
1005 FXFT_Stream ftStream = FX_Alloc(FXFT_StreamRec, 1);
1006 FXSYS_memset(ftStream, 0, sizeof(FXFT_StreamRec));
dsinclairea982382016-04-12 10:51:04 -07001007 ftStream->base = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001008 ftStream->descriptor.pointer = pFontStream;
1009 ftStream->pos = 0;
1010 ftStream->size = (unsigned long)pFontStream->GetSize();
1011 ftStream->read = _ftStreamRead;
1012 ftStream->close = _ftStreamClose;
1013
1014 FXFT_Open_Args ftArgs;
1015 FXSYS_memset(&ftArgs, 0, sizeof(FXFT_Open_Args));
1016 ftArgs.flags |= FT_OPEN_STREAM;
1017 ftArgs.stream = ftStream;
1018
dsinclairea982382016-04-12 10:51:04 -07001019 FXFT_Face pFace = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001020 if (FXFT_Open_Face(library, &ftArgs, iFaceIndex, &pFace)) {
1021 FX_Free(ftStream);
1022 return nullptr;
1023 }
1024
1025 FXFT_Set_Pixel_Sizes(pFace, 0, 64);
1026 return pFace;
1027}
1028
1029IFX_FileRead* CFX_FontMgrImp::CreateFontStream(
1030 CFX_FontMapper* pFontMapper,
1031 IFX_SystemFontInfo* pSystemFontInfo,
tsepez736f28a2016-03-25 14:19:51 -07001032 uint32_t index) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001033 int iExact = 0;
tsepezb4c9f3f2016-04-13 15:41:21 -07001034 void* hFont =
1035 pSystemFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0,
1036 pFontMapper->GetFaceName(index).c_str(), iExact);
Dan Sinclair1770c022016-03-14 14:14:16 -04001037 if (!hFont)
1038 return nullptr;
dsinclairea982382016-04-12 10:51:04 -07001039
tsepez736f28a2016-03-25 14:19:51 -07001040 uint32_t dwFileSize = pSystemFontInfo->GetFontData(hFont, 0, nullptr, 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04001041 if (dwFileSize == 0)
1042 return nullptr;
dsinclairea982382016-04-12 10:51:04 -07001043
Dan Sinclair1770c022016-03-14 14:14:16 -04001044 uint8_t* pBuffer = FX_Alloc(uint8_t, dwFileSize + 1);
1045 dwFileSize = pSystemFontInfo->GetFontData(hFont, 0, pBuffer, dwFileSize);
dsinclairea982382016-04-12 10:51:04 -07001046
Dan Sinclair1770c022016-03-14 14:14:16 -04001047 return FX_CreateMemoryStream(pBuffer, dwFileSize, TRUE);
1048}
1049
1050IFX_FileRead* CFX_FontMgrImp::CreateFontStream(
1051 const CFX_ByteString& bsFaceName) {
1052 CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
1053 CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper();
dsinclairea982382016-04-12 10:51:04 -07001054
Dan Sinclair1770c022016-03-14 14:14:16 -04001055 if (!pFontMapper)
1056 return nullptr;
dsinclairea982382016-04-12 10:51:04 -07001057
Dan Sinclair1770c022016-03-14 14:14:16 -04001058 IFX_SystemFontInfo* pSystemFontInfo = pFontMapper->GetSystemFontInfo();
1059 if (!pSystemFontInfo)
1060 return nullptr;
dsinclairea982382016-04-12 10:51:04 -07001061
Dan Sinclair1770c022016-03-14 14:14:16 -04001062 pSystemFontInfo->EnumFontList(pFontMapper);
1063 for (int32_t i = 0; i < pFontMapper->GetFaceSize(); ++i) {
1064 if (pFontMapper->GetFaceName(i) == bsFaceName)
1065 return CreateFontStream(pFontMapper, pSystemFontInfo, i);
1066 }
1067 return nullptr;
1068}
1069int32_t CFX_FontMgrImp::MatchFonts(CFX_FontDescriptorInfos& MatchedFonts,
Tom Sepez62a70f92016-03-21 15:00:20 -07001070 uint16_t wCodePage,
tsepez736f28a2016-03-25 14:19:51 -07001071 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -04001072 const CFX_WideString& FontName,
1073 FX_WCHAR wcUnicode) {
1074 MatchedFonts.RemoveAll();
1075 CFX_WideString wsNormalizedFontName = FontName;
dsinclairea982382016-04-12 10:51:04 -07001076
1077 CFX_FontDescriptor* pFont = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001078 int32_t nCount = m_InstalledFonts.GetSize();
1079 for (int32_t i = 0; i < nCount; i++) {
1080 pFont = m_InstalledFonts[i];
1081 int32_t nPenalty = CalcPenalty(pFont, wCodePage, dwFontStyles,
1082 wsNormalizedFontName, wcUnicode);
dsinclairea982382016-04-12 10:51:04 -07001083 if (nPenalty >= 0xffff)
Dan Sinclair1770c022016-03-14 14:14:16 -04001084 continue;
dsinclairea982382016-04-12 10:51:04 -07001085
Dan Sinclair1770c022016-03-14 14:14:16 -04001086 FX_FontDescriptorInfo FontInfo;
1087 FontInfo.pFont = pFont;
1088 FontInfo.nPenalty = nPenalty;
1089 MatchedFonts.Add(FontInfo);
dsinclairea982382016-04-12 10:51:04 -07001090 if (MatchedFonts.GetSize() == 0xffff)
Dan Sinclair1770c022016-03-14 14:14:16 -04001091 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04001092 }
dsinclairea982382016-04-12 10:51:04 -07001093 if (MatchedFonts.GetSize() == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001094 return 0;
dsinclairea982382016-04-12 10:51:04 -07001095
Dan Sinclair1770c022016-03-14 14:14:16 -04001096 CFX_SSortTemplate<FX_FontDescriptorInfo> ssort;
1097 ssort.ShellSort(MatchedFonts.GetData(), MatchedFonts.GetSize());
1098 return MatchedFonts.GetSize();
1099}
dsinclairea982382016-04-12 10:51:04 -07001100
Dan Sinclair1770c022016-03-14 14:14:16 -04001101struct FX_BitCodePage {
Tom Sepez62a70f92016-03-21 15:00:20 -07001102 uint16_t wBit;
1103 uint16_t wCodePage;
Dan Sinclair1770c022016-03-14 14:14:16 -04001104};
1105static const FX_BitCodePage g_Bit2CodePage[] = {
1106 {0, 1252}, {1, 1250}, {2, 1251}, {3, 1253}, {4, 1254}, {5, 1255},
1107 {6, 1256}, {7, 1257}, {8, 1258}, {9, 0}, {10, 0}, {11, 0},
1108 {12, 0}, {13, 0}, {14, 0}, {15, 0}, {16, 874}, {17, 932},
1109 {18, 936}, {19, 949}, {20, 950}, {21, 1361}, {22, 0}, {23, 0},
1110 {24, 0}, {25, 0}, {26, 0}, {27, 0}, {28, 0}, {29, 0},
1111 {30, 0}, {31, 0}, {32, 0}, {33, 0}, {34, 0}, {35, 0},
1112 {36, 0}, {37, 0}, {38, 0}, {39, 0}, {40, 0}, {41, 0},
1113 {42, 0}, {43, 0}, {44, 0}, {45, 0}, {46, 0}, {47, 0},
1114 {48, 869}, {49, 866}, {50, 865}, {51, 864}, {52, 863}, {53, 862},
1115 {54, 861}, {55, 860}, {56, 857}, {57, 855}, {58, 852}, {59, 775},
1116 {60, 737}, {61, 708}, {62, 850}, {63, 437},
1117};
1118
Tom Sepez62a70f92016-03-21 15:00:20 -07001119uint16_t FX_GetCodePageBit(uint16_t wCodePage) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001120 for (size_t i = 0; i < FX_ArraySize(g_Bit2CodePage); ++i) {
1121 if (g_Bit2CodePage[i].wCodePage == wCodePage)
1122 return g_Bit2CodePage[i].wBit;
1123 }
Tom Sepez62a70f92016-03-21 15:00:20 -07001124 return (uint16_t)-1;
Dan Sinclair1770c022016-03-14 14:14:16 -04001125}
1126
Tom Sepez62a70f92016-03-21 15:00:20 -07001127uint16_t FX_GetUnicodeBit(FX_WCHAR wcUnicode) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001128 const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wcUnicode);
1129 return x ? x->wBitField : 999;
1130}
1131
1132int32_t CFX_FontMgrImp::CalcPenalty(CFX_FontDescriptor* pInstalled,
Tom Sepez62a70f92016-03-21 15:00:20 -07001133 uint16_t wCodePage,
tsepez736f28a2016-03-25 14:19:51 -07001134 uint32_t dwFontStyles,
Dan Sinclair1770c022016-03-14 14:14:16 -04001135 const CFX_WideString& FontName,
1136 FX_WCHAR wcUnicode) {
1137 int32_t nPenalty = 30000;
1138 if (0 != FontName.GetLength()) {
1139 if (FontName != pInstalled->m_wsFaceName) {
1140 int32_t i;
1141 for (i = 0; i < pInstalled->m_wsFamilyNames.GetSize(); i++) {
1142 if (pInstalled->m_wsFamilyNames[i] == FontName) {
1143 break;
1144 }
1145 }
1146 if (i == pInstalled->m_wsFamilyNames.GetSize()) {
1147 nPenalty += 0xFFFF;
1148 } else {
1149 nPenalty -= 28000;
1150 }
1151 } else {
1152 nPenalty -= 30000;
1153 }
1154 if (30000 == nPenalty &&
1155 0 == IsPartName(pInstalled->m_wsFaceName, FontName)) {
1156 int32_t i;
1157 for (i = 0; i < pInstalled->m_wsFamilyNames.GetSize(); i++) {
1158 if (0 != IsPartName(pInstalled->m_wsFamilyNames[i], FontName)) {
1159 break;
1160 }
1161 }
1162 if (i == pInstalled->m_wsFamilyNames.GetSize()) {
1163 nPenalty += 0xFFFF;
1164 } else {
1165 nPenalty -= 26000;
1166 }
1167 } else {
1168 nPenalty -= 27000;
1169 }
1170 }
tsepez736f28a2016-03-25 14:19:51 -07001171 uint32_t dwStyleMask = pInstalled->m_dwFontStyles ^ dwFontStyles;
Dan Sinclair1770c022016-03-14 14:14:16 -04001172 if (dwStyleMask & FX_FONTSTYLE_Bold) {
1173 nPenalty += 4500;
1174 }
1175 if (dwStyleMask & FX_FONTSTYLE_FixedPitch) {
1176 nPenalty += 10000;
1177 }
1178 if (dwStyleMask & FX_FONTSTYLE_Italic) {
1179 nPenalty += 10000;
1180 }
1181 if (dwStyleMask & FX_FONTSTYLE_Serif) {
1182 nPenalty += 500;
1183 }
1184 if (dwStyleMask & FX_FONTSTYLE_Symbolic) {
1185 nPenalty += 0xFFFF;
1186 }
1187 if (nPenalty >= 0xFFFF) {
1188 return 0xFFFF;
1189 }
Tom Sepez62a70f92016-03-21 15:00:20 -07001190 uint16_t wBit =
1191 ((0 == wCodePage || 0xFFFF == wCodePage) ? (uint16_t)-1
Dan Sinclair1770c022016-03-14 14:14:16 -04001192 : FX_GetCodePageBit(wCodePage));
Tom Sepez62a70f92016-03-21 15:00:20 -07001193 if (wBit != (uint16_t)-1) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001194 FXSYS_assert(wBit < 64);
1195 if (0 == (pInstalled->m_dwCsb[wBit / 32] & (1 << (wBit % 32)))) {
1196 nPenalty += 0xFFFF;
1197 } else {
1198 nPenalty -= 60000;
1199 }
1200 }
1201 wBit =
Tom Sepez62a70f92016-03-21 15:00:20 -07001202 ((0 == wcUnicode || 0xFFFE == wcUnicode) ? (uint16_t)999
Dan Sinclair1770c022016-03-14 14:14:16 -04001203 : FX_GetUnicodeBit(wcUnicode));
Tom Sepez62a70f92016-03-21 15:00:20 -07001204 if (wBit != (uint16_t)999) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001205 FXSYS_assert(wBit < 128);
1206 if (0 == (pInstalled->m_dwUsb[wBit / 32] & (1 << (wBit % 32)))) {
1207 nPenalty += 0xFFFF;
1208 } else {
1209 nPenalty -= 60000;
1210 }
1211 }
1212 return nPenalty;
1213}
1214void CFX_FontMgrImp::ClearFontCache() {
1215 FX_POSITION pos = m_Hash2CandidateList.GetStartPosition();
1216 while (pos) {
tsepez736f28a2016-03-25 14:19:51 -07001217 uint32_t dwHash;
Dan Sinclair1770c022016-03-14 14:14:16 -04001218 CFX_FontDescriptorInfos* pDescs;
1219 m_Hash2CandidateList.GetNextAssoc(pos, dwHash, pDescs);
1220 if (NULL != pDescs) {
1221 delete pDescs;
1222 }
1223 }
1224 pos = m_FileAccess2IFXFont.GetStartPosition();
1225 while (pos) {
tsepez736f28a2016-03-25 14:19:51 -07001226 uint32_t dwHash;
Dan Sinclair1770c022016-03-14 14:14:16 -04001227 IFX_Font* pFont;
1228 m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pFont);
1229 if (NULL != pFont) {
1230 pFont->Release();
1231 }
1232 }
1233 pos = m_IFXFont2FileRead.GetStartPosition();
1234 while (pos) {
1235 IFX_Font* pFont;
1236 IFX_FileRead* pFileRead;
1237 m_IFXFont2FileRead.GetNextAssoc(pos, pFont, pFileRead);
1238 pFileRead->Release();
1239 }
1240}
1241void CFX_FontMgrImp::RemoveFont(IFX_Font* pEFont) {
1242 if (NULL == pEFont) {
1243 return;
1244 }
1245 IFX_FileRead* pFileRead;
1246 if (m_IFXFont2FileRead.Lookup(pEFont, pFileRead)) {
1247 pFileRead->Release();
1248 m_IFXFont2FileRead.RemoveKey(pEFont);
1249 }
1250 FX_POSITION pos;
1251 pos = m_FileAccess2IFXFont.GetStartPosition();
1252 while (pos) {
tsepez736f28a2016-03-25 14:19:51 -07001253 uint32_t dwHash;
Dan Sinclair1770c022016-03-14 14:14:16 -04001254 IFX_Font* pCFont;
1255 m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pCFont);
1256 if (pCFont == pEFont) {
1257 m_FileAccess2IFXFont.RemoveKey(dwHash);
1258 break;
1259 }
1260 }
1261 pos = m_Hash2Fonts.GetStartPosition();
1262 while (pos) {
tsepez736f28a2016-03-25 14:19:51 -07001263 uint32_t dwHash;
Dan Sinclair1770c022016-03-14 14:14:16 -04001264 CFX_ArrayTemplate<IFX_Font*>* pFonts;
1265 m_Hash2Fonts.GetNextAssoc(pos, dwHash, pFonts);
1266 if (NULL != pFonts) {
1267 for (int32_t i = 0; i < pFonts->GetSize(); i++) {
1268 if (pFonts->GetAt(i) == pEFont) {
1269 pFonts->SetAt(i, NULL);
1270 }
1271 }
1272 } else {
1273 m_Hash2Fonts.RemoveKey(dwHash);
1274 }
1275 }
1276}
dsinclairea982382016-04-12 10:51:04 -07001277
Dan Sinclair1770c022016-03-14 14:14:16 -04001278void CFX_FontMgrImp::RegisterFace(FXFT_Face pFace,
1279 CFX_FontDescriptors& Fonts,
1280 const CFX_WideString* pFaceName,
1281 IFX_FileAccess* pFontAccess) {
dsinclairea982382016-04-12 10:51:04 -07001282 if ((pFace->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001283 return;
dsinclairea982382016-04-12 10:51:04 -07001284
Dan Sinclair1770c022016-03-14 14:14:16 -04001285 CFX_FontDescriptor* pFont = new CFX_FontDescriptor;
1286 pFont->m_dwFontStyles |= FXFT_Is_Face_Bold(pFace) ? FX_FONTSTYLE_Bold : 0;
1287 pFont->m_dwFontStyles |= FXFT_Is_Face_Italic(pFace) ? FX_FONTSTYLE_Italic : 0;
1288 pFont->m_dwFontStyles |= GetFlags(pFace);
dsinclairea982382016-04-12 10:51:04 -07001289
Tom Sepez62a70f92016-03-21 15:00:20 -07001290 CFX_ArrayTemplate<uint16_t> Charsets;
Dan Sinclair1770c022016-03-14 14:14:16 -04001291 GetCharsets(pFace, Charsets);
1292 GetUSBCSB(pFace, pFont->m_dwUsb, pFont->m_dwCsb);
dsinclairea982382016-04-12 10:51:04 -07001293
Dan Sinclair1770c022016-03-14 14:14:16 -04001294 FT_ULong dwTag;
dsinclairea982382016-04-12 10:51:04 -07001295 uint8_t* pTable = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001296 FT_ENC_TAG(dwTag, 'n', 'a', 'm', 'e');
dsinclairea982382016-04-12 10:51:04 -07001297
1298 unsigned long nLength = 0;
1299 unsigned int error = FXFT_Load_Sfnt_Table(pFace, dwTag, 0, nullptr, &nLength);
1300 if (error == 0 && nLength != 0) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001301 pTable = FX_Alloc(uint8_t, nLength);
dsinclairea982382016-04-12 10:51:04 -07001302 error = FXFT_Load_Sfnt_Table(pFace, dwTag, 0, pTable, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04001303 if (0 != error) {
1304 FX_Free(pTable);
dsinclairea982382016-04-12 10:51:04 -07001305 pTable = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001306 }
1307 }
1308 GetNames(pTable, pFont->m_wsFamilyNames);
dsinclairea982382016-04-12 10:51:04 -07001309 if (pTable)
Dan Sinclair1770c022016-03-14 14:14:16 -04001310 FX_Free(pTable);
dsinclairea982382016-04-12 10:51:04 -07001311
Dan Sinclair1770c022016-03-14 14:14:16 -04001312 pFont->m_wsFamilyNames.Add(CFX_ByteString(pFace->family_name).UTF8Decode());
dsinclairea982382016-04-12 10:51:04 -07001313 pFont->m_wsFaceName =
1314 pFaceName ? *pFaceName
1315 : CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(pFace));
Dan Sinclair1770c022016-03-14 14:14:16 -04001316 pFont->m_nFaceIndex = pFace->face_index;
dsinclairea982382016-04-12 10:51:04 -07001317 pFont->m_pFileAccess = pFontAccess ? pFontAccess->Retain() : nullptr;
1318
Dan Sinclair1770c022016-03-14 14:14:16 -04001319 Fonts.Add(pFont);
1320}
dsinclairea982382016-04-12 10:51:04 -07001321
Dan Sinclair1770c022016-03-14 14:14:16 -04001322void CFX_FontMgrImp::RegisterFaces(IFX_FileRead* pFontStream,
1323 const CFX_WideString* pFaceName) {
1324 int32_t index = 0;
1325 int32_t num_faces = 0;
1326 do {
1327 FXFT_Face pFace = LoadFace(pFontStream, index++);
1328 if (!pFace)
1329 continue;
1330 // All faces keep number of faces. It can be retrieved from any one face.
dsinclairea982382016-04-12 10:51:04 -07001331 if (num_faces == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001332 num_faces = pFace->num_faces;
1333 RegisterFace(pFace, m_InstalledFonts, pFaceName, nullptr);
1334 if (FXFT_Get_Face_External_Stream(pFace))
1335 FXFT_Clear_Face_External_Stream(pFace);
1336 FXFT_Done_Face(pFace);
1337 } while (index < num_faces);
1338}
tsepez736f28a2016-03-25 14:19:51 -07001339uint32_t CFX_FontMgrImp::GetFlags(FXFT_Face pFace) {
1340 uint32_t flag = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001341 if (FT_IS_FIXED_WIDTH(pFace)) {
1342 flag |= FX_FONTSTYLE_FixedPitch;
1343 }
1344 TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
1345 if (!pOS2) {
1346 return flag;
1347 }
1348 if (pOS2->ulCodePageRange1 & (1 << 31)) {
1349 flag |= FX_FONTSTYLE_Symbolic;
1350 }
1351 if (pOS2->panose[0] == 2) {
1352 uint8_t uSerif = pOS2->panose[1];
1353 if ((uSerif > 1 && uSerif < 10) || uSerif > 13) {
1354 flag |= FX_FONTSTYLE_Serif;
1355 }
1356 }
1357 return flag;
1358}
1359#define GetUInt8(p) ((uint8_t)((p)[0]))
1360#define GetUInt16(p) ((uint16_t)((p)[0] << 8 | (p)[1]))
1361#define GetUInt32(p) \
1362 ((uint32_t)((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]))
1363void CFX_FontMgrImp::GetNames(const uint8_t* name_table,
1364 CFX_WideStringArray& Names) {
1365 if (NULL == name_table) {
1366 return;
1367 }
1368 uint8_t* lpTable = (uint8_t*)name_table;
1369 CFX_WideString wsFamily;
1370 uint8_t* sp = lpTable + 2;
1371 uint8_t* lpNameRecord = lpTable + 6;
1372 uint16_t nNameCount = GetUInt16(sp);
1373 uint8_t* lpStr = lpTable + GetUInt16(sp + 2);
1374 for (uint16_t j = 0; j < nNameCount; j++) {
1375 uint16_t nNameID = GetUInt16(lpNameRecord + j * 12 + 6);
1376 if (nNameID != 1) {
1377 continue;
1378 }
1379 uint16_t nPlatformID = GetUInt16(lpNameRecord + j * 12 + 0);
1380 uint16_t nNameLength = GetUInt16(lpNameRecord + j * 12 + 8);
1381 uint16_t nNameOffset = GetUInt16(lpNameRecord + j * 12 + 10);
tsepez774bdde2016-04-14 09:49:44 -07001382 wsFamily.clear();
Dan Sinclair1770c022016-03-14 14:14:16 -04001383 if (nPlatformID != 1) {
1384 for (uint16_t k = 0; k < nNameLength / 2; k++) {
1385 FX_WCHAR wcTemp = GetUInt16(lpStr + nNameOffset + k * 2);
1386 wsFamily += wcTemp;
1387 }
1388 Names.Add(wsFamily);
1389 } else {
1390 for (uint16_t k = 0; k < nNameLength; k++) {
1391 FX_WCHAR wcTemp = GetUInt8(lpStr + nNameOffset + k);
1392 wsFamily += wcTemp;
1393 }
1394 Names.Add(wsFamily);
1395 }
1396 }
1397}
1398#undef GetUInt8
1399#undef GetUInt16
1400#undef GetUInt32
1401struct FX_BIT2CHARSET {
Tom Sepez62a70f92016-03-21 15:00:20 -07001402 uint16_t wBit;
1403 uint16_t wCharset;
Dan Sinclair1770c022016-03-14 14:14:16 -04001404};
1405FX_BIT2CHARSET g_FX_Bit2Charset1[16] = {
1406 {1 << 0, FX_CHARSET_ANSI},
1407 {1 << 1, FX_CHARSET_MSWin_EasterEuropean},
1408 {1 << 2, FX_CHARSET_MSWin_Cyrillic},
1409 {1 << 3, FX_CHARSET_MSWin_Greek},
1410 {1 << 4, FX_CHARSET_MSWin_Turkish},
1411 {1 << 5, FX_CHARSET_MSWin_Hebrew},
1412 {1 << 6, FX_CHARSET_MSWin_Arabic},
1413 {1 << 7, FX_CHARSET_MSWin_Baltic},
1414 {1 << 8, FX_CHARSET_MSWin_Vietnamese},
1415 {1 << 9, FX_CHARSET_Default},
1416 {1 << 10, FX_CHARSET_Default},
1417 {1 << 11, FX_CHARSET_Default},
1418 {1 << 12, FX_CHARSET_Default},
1419 {1 << 13, FX_CHARSET_Default},
1420 {1 << 14, FX_CHARSET_Default},
1421 {1 << 15, FX_CHARSET_Default},
1422};
1423FX_BIT2CHARSET g_FX_Bit2Charset2[16] = {
1424 {1 << 0, FX_CHARSET_Thai},
1425 {1 << 1, FX_CHARSET_ShiftJIS},
1426 {1 << 2, FX_CHARSET_ChineseSimplified},
1427 {1 << 3, FX_CHARSET_Korean},
1428 {1 << 4, FX_CHARSET_ChineseTriditional},
1429 {1 << 5, FX_CHARSET_Johab},
1430 {1 << 6, FX_CHARSET_Default},
1431 {1 << 7, FX_CHARSET_Default},
1432 {1 << 8, FX_CHARSET_Default},
1433 {1 << 9, FX_CHARSET_Default},
1434 {1 << 10, FX_CHARSET_Default},
1435 {1 << 11, FX_CHARSET_Default},
1436 {1 << 12, FX_CHARSET_Default},
1437 {1 << 13, FX_CHARSET_Default},
1438 {1 << 14, FX_CHARSET_OEM},
1439 {1 << 15, FX_CHARSET_Symbol},
1440};
1441FX_BIT2CHARSET g_FX_Bit2Charset3[16] = {
1442 {1 << 0, FX_CHARSET_Default}, {1 << 1, FX_CHARSET_Default},
1443 {1 << 2, FX_CHARSET_Default}, {1 << 3, FX_CHARSET_Default},
1444 {1 << 4, FX_CHARSET_Default}, {1 << 5, FX_CHARSET_Default},
1445 {1 << 6, FX_CHARSET_Default}, {1 << 7, FX_CHARSET_Default},
1446 {1 << 8, FX_CHARSET_Default}, {1 << 9, FX_CHARSET_Default},
1447 {1 << 10, FX_CHARSET_Default}, {1 << 11, FX_CHARSET_Default},
1448 {1 << 12, FX_CHARSET_Default}, {1 << 13, FX_CHARSET_Default},
1449 {1 << 14, FX_CHARSET_Default}, {1 << 15, FX_CHARSET_Default},
1450};
1451FX_BIT2CHARSET g_FX_Bit2Charset4[16] = {
1452 {1 << 0, FX_CHARSET_Default}, {1 << 1, FX_CHARSET_Default},
1453 {1 << 2, FX_CHARSET_Default}, {1 << 3, FX_CHARSET_Default},
1454 {1 << 4, FX_CHARSET_Default}, {1 << 5, FX_CHARSET_Default},
1455 {1 << 6, FX_CHARSET_Default}, {1 << 7, FX_CHARSET_Default},
1456 {1 << 8, FX_CHARSET_Default}, {1 << 9, FX_CHARSET_Default},
1457 {1 << 10, FX_CHARSET_Default}, {1 << 11, FX_CHARSET_Default},
1458 {1 << 12, FX_CHARSET_Default}, {1 << 13, FX_CHARSET_Default},
1459 {1 << 14, FX_CHARSET_Default}, {1 << 15, FX_CHARSET_US},
1460};
1461#define CODEPAGERANGE_IMPLEMENT(n) \
1462 for (int32_t i = 0; i < 16; i++) { \
1463 if ((a##n & g_FX_Bit2Charset##n[i].wBit) != 0) { \
1464 Charsets.Add(g_FX_Bit2Charset##n[i].wCharset); \
1465 } \
1466 }
Tom Sepez62a70f92016-03-21 15:00:20 -07001467void CFX_FontMgrImp::GetCharsets(FXFT_Face pFace,
1468 CFX_ArrayTemplate<uint16_t>& Charsets) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001469 Charsets.RemoveAll();
1470 TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
1471 if (NULL != pOS2) {
Tom Sepez62a70f92016-03-21 15:00:20 -07001472 uint16_t a1, a2, a3, a4;
Dan Sinclair1770c022016-03-14 14:14:16 -04001473 a1 = pOS2->ulCodePageRange1 & 0x0000ffff;
1474 CODEPAGERANGE_IMPLEMENT(1);
1475 a2 = (pOS2->ulCodePageRange1 >> 16) & 0x0000ffff;
1476 CODEPAGERANGE_IMPLEMENT(2);
1477 a3 = pOS2->ulCodePageRange2 & 0x0000ffff;
1478 CODEPAGERANGE_IMPLEMENT(3);
1479 a4 = (pOS2->ulCodePageRange2 >> 16) & 0x0000ffff;
1480 CODEPAGERANGE_IMPLEMENT(4);
1481 } else {
1482 Charsets.Add(FX_CHARSET_Default);
1483 }
1484}
1485#undef CODEPAGERANGE_IMPLEMENT
tsepez736f28a2016-03-25 14:19:51 -07001486void CFX_FontMgrImp::GetUSBCSB(FXFT_Face pFace, uint32_t* USB, uint32_t* CSB) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001487 TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
1488 if (NULL != pOS2) {
1489 USB[0] = pOS2->ulUnicodeRange1;
1490 USB[1] = pOS2->ulUnicodeRange2;
1491 USB[2] = pOS2->ulUnicodeRange3;
1492 USB[3] = pOS2->ulUnicodeRange4;
1493 CSB[0] = pOS2->ulCodePageRange1;
1494 CSB[1] = pOS2->ulCodePageRange2;
1495 } else {
1496 USB[0] = 0;
1497 USB[1] = 0;
1498 USB[2] = 0;
1499 USB[3] = 0;
1500 CSB[0] = 0;
1501 CSB[1] = 0;
1502 }
1503}
1504int32_t CFX_FontMgrImp::IsPartName(const CFX_WideString& Name1,
1505 const CFX_WideString& Name2) {
tsepezbd9748d2016-04-13 21:40:19 -07001506 if (Name1.Find(Name2.c_str()) != -1) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001507 return 1;
1508 }
1509 return 0;
1510}
1511#endif