1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../../include/fxge/fx_ge.h"
8 #include "../../../include/fxge/fx_freetype.h"
10 #define GET_TT_SHORT(w) (FX_WORD)(((w)[0] << 8) | (w)[1])
11 #define GET_TT_LONG(w) (FX_DWORD)(((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
12 CFX_SubstFont::CFX_SubstFont()
19 m_bSubstOfCJK = FALSE;
23 CTTFontDesc::~CTTFontDesc()
26 if (m_SingleFace.m_pFace) {
27 FXFT_Done_Face(m_SingleFace.m_pFace);
29 } else if (m_Type == 2) {
30 for (int i = 0; i < 16; i ++)
31 if (m_TTCFace.m_pFaces[i]) {
32 FXFT_Done_Face(m_TTCFace.m_pFaces[i]);
39 FX_BOOL CTTFontDesc::ReleaseFace(FXFT_Face face)
42 if (m_SingleFace.m_pFace != face) {
45 } else if (m_Type == 2) {
47 for (i = 0; i < 16; i ++)
48 if (m_TTCFace.m_pFaces[i] == face) {
62 CFX_FontMgr::CFX_FontMgr()
64 m_pBuiltinMapper = new CFX_FontMapper;
65 m_pBuiltinMapper->m_pFontMgr = this;
68 FXSYS_memset32(m_ExternalFonts, 0, sizeof m_ExternalFonts);
70 CFX_FontMgr::~CFX_FontMgr()
72 if (m_pBuiltinMapper) {
73 delete m_pBuiltinMapper;
77 FXFT_Done_FreeType(m_FTLibrary);
80 void CFX_FontMgr::InitFTLibrary()
82 if (m_FTLibrary == NULL) {
83 FXFT_Init_FreeType(&m_FTLibrary);
86 void CFX_FontMgr::FreeCache()
88 FX_POSITION pos = m_FaceMap.GetStartPosition();
92 m_FaceMap.GetNextAssoc(pos, Key, (void*&)face);
95 m_FaceMap.RemoveAll();
97 void CFX_FontMgr::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo)
99 m_pBuiltinMapper->SetSystemFontInfo(pFontInfo);
101 FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, FX_BOOL bTrueType,
102 FX_DWORD flags, int weight, int italic_angle, int CharsetCP, CFX_SubstFont* pSubstFont)
104 if (m_FTLibrary == NULL) {
105 FXFT_Init_FreeType(&m_FTLibrary);
108 FXFT_Face face = m_pExtMapper->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle,
109 CharsetCP, pSubstFont);
114 return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle,
115 CharsetCP, pSubstFont);
117 FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name,
118 int weight, FX_BOOL bItalic, FX_LPBYTE& pFontData)
120 CFX_ByteString key(face_name);
122 key += CFX_ByteString::FormatInteger(weight);
123 key += bItalic ? 'I' : 'N';
124 CTTFontDesc* pFontDesc = NULL;
125 m_FaceMap.Lookup(key, (void*&)pFontDesc);
127 pFontData = pFontDesc->m_pFontData;
128 pFontDesc->m_RefCount ++;
129 return pFontDesc->m_SingleFace.m_pFace;
133 FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name,
134 int weight, FX_BOOL bItalic, FX_LPBYTE pData, FX_DWORD size, int face_index)
136 CTTFontDesc* pFontDesc = new CTTFontDesc;
137 pFontDesc->m_Type = 1;
138 pFontDesc->m_SingleFace.m_pFace = NULL;
139 pFontDesc->m_SingleFace.m_bBold = weight;
140 pFontDesc->m_SingleFace.m_bItalic = bItalic;
141 pFontDesc->m_pFontData = pData;
142 pFontDesc->m_RefCount = 1;
143 FXFT_Library library;
144 if (m_FTLibrary == NULL) {
145 FXFT_Init_FreeType(&m_FTLibrary);
147 library = m_FTLibrary;
148 int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &pFontDesc->m_SingleFace.m_pFace);
153 ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace.m_pFace, 64, 64);
158 CFX_ByteString key(face_name);
160 key += CFX_ByteString::FormatInteger(weight);
161 key += bItalic ? 'I' : 'N';
162 m_FaceMap.SetAt(key, pFontDesc);
163 return pFontDesc->m_SingleFace.m_pFace;
165 const FX_LPCSTR g_Base14FontNames[14] = {
168 "Courier-BoldOblique",
172 "Helvetica-BoldOblique",
181 const struct _AltFontName {
182 const FX_CHAR* m_pName;
188 {"Arial,BoldItalic", 6},
191 {"Arial-BoldItalic", 6},
192 {"Arial-BoldItalicMT", 6},
195 {"Arial-ItalicMT", 7},
197 {"ArialBoldItalic", 6},
201 {"ArialMT,BoldItalic", 6},
202 {"ArialMT,Italic", 7},
203 {"ArialRoundedMTBold", 5},
206 {"Courier,BoldItalic", 2},
207 {"Courier,Italic", 3},
209 {"Courier-BoldOblique", 2},
210 {"Courier-Oblique", 3},
212 {"CourierBoldItalic", 2},
213 {"CourierItalic", 3},
215 {"CourierNew,Bold", 1},
216 {"CourierNew,BoldItalic", 2},
217 {"CourierNew,Italic", 3},
218 {"CourierNew-Bold", 1},
219 {"CourierNew-BoldItalic", 2},
220 {"CourierNew-Italic", 3},
221 {"CourierNewBold", 1},
222 {"CourierNewBoldItalic", 2},
223 {"CourierNewItalic", 3},
224 {"CourierNewPS-BoldItalicMT", 2},
225 {"CourierNewPS-BoldMT", 1},
226 {"CourierNewPS-ItalicMT", 3},
227 {"CourierNewPSMT", 0},
229 {"CourierStd-Bold", 1},
230 {"CourierStd-BoldOblique", 2},
231 {"CourierStd-Oblique", 3},
233 {"Helvetica,Bold", 5},
234 {"Helvetica,BoldItalic", 6},
235 {"Helvetica,Italic", 7},
236 {"Helvetica-Bold", 5},
237 {"Helvetica-BoldItalic", 6},
238 {"Helvetica-BoldOblique", 6},
239 {"Helvetica-Italic", 7},
240 {"Helvetica-Oblique", 7},
241 {"HelveticaBold", 5},
242 {"HelveticaBoldItalic", 6},
243 {"HelveticaItalic", 7},
247 {"Times-BoldItalic", 10},
248 {"Times-Italic", 11},
251 {"TimesBoldItalic", 10},
253 {"TimesNewRoman", 8},
254 {"TimesNewRoman,Bold", 9},
255 {"TimesNewRoman,BoldItalic", 10},
256 {"TimesNewRoman,Italic", 11},
257 {"TimesNewRoman-Bold", 9},
258 {"TimesNewRoman-BoldItalic", 10},
259 {"TimesNewRoman-Italic", 11},
260 {"TimesNewRomanBold", 9},
261 {"TimesNewRomanBoldItalic", 10},
262 {"TimesNewRomanItalic", 11},
263 {"TimesNewRomanPS", 8},
264 {"TimesNewRomanPS-Bold", 9},
265 {"TimesNewRomanPS-BoldItalic", 10},
266 {"TimesNewRomanPS-BoldItalicMT", 10},
267 {"TimesNewRomanPS-BoldMT", 9},
268 {"TimesNewRomanPS-Italic", 11},
269 {"TimesNewRomanPS-ItalicMT", 11},
270 {"TimesNewRomanPSMT", 8},
271 {"TimesNewRomanPSMT,Bold", 9},
272 {"TimesNewRomanPSMT,BoldItalic", 10},
273 {"TimesNewRomanPSMT,Italic", 11},
274 {"ZapfDingbats", 13},
277 static int compareString(const void* key, const void* element)
279 return FXSYS_stricmp((FX_LPCSTR)key, ((_AltFontName*)element)->m_pName);
282 int _PDF_GetStandardFontName(CFX_ByteString& name)
284 _AltFontName* found = (_AltFontName*)FXSYS_bsearch(name.c_str(), g_AltFontNames,
285 sizeof g_AltFontNames / sizeof (_AltFontName), sizeof (_AltFontName), compareString);
289 name = g_Base14FontNames[found->m_Index];
290 return found->m_Index;
292 int GetTTCIndex(FX_LPCBYTE pFontData, FX_DWORD ttc_size, FX_DWORD font_offset)
295 FX_LPCBYTE p = pFontData + 8;
296 FX_DWORD nfont = GET_TT_LONG(p);
298 for (index = 0; index < nfont; index ++) {
299 p = pFontData + 12 + index * 4;
300 if (GET_TT_LONG(p) == font_offset) {
311 FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, FX_DWORD checksum,
312 int font_offset, FX_LPBYTE& pFontData)
315 key.Format("%d:%d", ttc_size, checksum);
316 CTTFontDesc* pFontDesc = NULL;
317 m_FaceMap.Lookup(key, (void*&)pFontDesc);
318 if (pFontDesc == NULL) {
321 pFontData = pFontDesc->m_pFontData;
322 pFontDesc->m_RefCount ++;
323 int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);
324 if (pFontDesc->m_TTCFace.m_pFaces[face_index] == NULL) {
325 pFontDesc->m_TTCFace.m_pFaces[face_index] = GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);
327 return pFontDesc->m_TTCFace.m_pFaces[face_index];
329 FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, FX_DWORD checksum,
330 FX_LPBYTE pData, FX_DWORD size, int font_offset)
333 key.Format("%d:%d", ttc_size, checksum);
334 CTTFontDesc* pFontDesc = new CTTFontDesc;
335 pFontDesc->m_Type = 2;
336 pFontDesc->m_pFontData = pData;
337 for (int i = 0; i < 16; i ++) {
338 pFontDesc->m_TTCFace.m_pFaces[i] = NULL;
340 pFontDesc->m_RefCount ++;
341 key.Format("%d:%d", ttc_size, checksum);
342 m_FaceMap.SetAt(key, pFontDesc);
343 int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);
344 pFontDesc->m_TTCFace.m_pFaces[face_index] = GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);
345 return pFontDesc->m_TTCFace.m_pFaces[face_index];
347 FXFT_Face CFX_FontMgr::GetFixedFace(FX_LPCBYTE pData, FX_DWORD size, int face_index)
349 FXFT_Library library;
350 if (m_FTLibrary == NULL) {
351 FXFT_Init_FreeType(&m_FTLibrary);
353 library = m_FTLibrary;
354 FXFT_Face face = NULL;
355 int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &face);
359 ret = FXFT_Set_Pixel_Sizes(face, 64, 64);
365 FXFT_Face CFX_FontMgr::GetFileFace(FX_LPCSTR filename, int face_index)
367 FXFT_Library library;
368 if (m_FTLibrary == NULL) {
369 FXFT_Init_FreeType(&m_FTLibrary);
371 library = m_FTLibrary;
372 FXFT_Face face = NULL;
373 int ret = FXFT_New_Face(library, filename, face_index, &face);
377 ret = FXFT_Set_Pixel_Sizes(face, 64, 64);
383 void CFX_FontMgr::ReleaseFace(FXFT_Face face)
388 FX_POSITION pos = m_FaceMap.GetStartPosition();
392 m_FaceMap.GetNextAssoc(pos, Key, (void*&)ttface);
393 if (ttface->ReleaseFace(face)) {
394 m_FaceMap.RemoveKey(Key);
399 extern const unsigned char g_FoxitFixedItalicFontData [18746];
400 extern const unsigned char g_FoxitFixedFontData [17597];
401 extern const unsigned char g_FoxitSansItalicFontData [16339];
402 extern const unsigned char g_FoxitSansFontData [15025];
403 extern const unsigned char g_FoxitSerifItalicFontData [21227];
404 extern const unsigned char g_FoxitSerifFontData [19469];
405 extern const unsigned char g_FoxitFixedBoldItalicFontData [19151];
406 extern const unsigned char g_FoxitFixedBoldFontData [18055];
407 extern const unsigned char g_FoxitSansBoldItalicFontData [16418];
408 extern const unsigned char g_FoxitSansBoldFontData [16344];
409 extern const unsigned char g_FoxitSerifBoldItalicFontData [20733];
410 extern const unsigned char g_FoxitSerifBoldFontData [19395];
411 extern const unsigned char g_FoxitSymbolFontData[16729];
412 extern const unsigned char g_FoxitDingbatsFontData[29513];
413 extern const unsigned char g_FoxitSerifMMFontData[113417];
414 extern const unsigned char g_FoxitSansMMFontData[66919];
416 const FoxitFonts g_FoxitFonts[14] = {
417 {g_FoxitFixedFontData, 17597},
418 {g_FoxitFixedBoldFontData, 18055},
419 {g_FoxitFixedBoldItalicFontData, 19151},
420 {g_FoxitFixedItalicFontData, 18746},
421 {g_FoxitSansFontData, 15025},
422 {g_FoxitSansBoldFontData, 16344},
423 {g_FoxitSansBoldItalicFontData, 16418},
424 {g_FoxitSansItalicFontData, 16339},
425 {g_FoxitSerifFontData, 19469},
426 {g_FoxitSerifBoldFontData, 19395},
427 {g_FoxitSerifBoldItalicFontData, 20733},
428 {g_FoxitSerifItalicFontData, 21227},
429 {g_FoxitSymbolFontData, 16729},
430 {g_FoxitDingbatsFontData, 29513},
432 void _FPDFAPI_GetInternalFontData(int id, FX_LPCBYTE& data, FX_DWORD& size)
434 CFX_GEModule::Get()->GetFontMgr()->GetStandardFont(data, size, id);
436 FX_BOOL CFX_FontMgr::GetStandardFont(FX_LPCBYTE& pFontData, FX_DWORD& size, int index)
438 if (index > 15 || index < 0) {
444 pFontData = g_FoxitSerifMMFontData;
447 pFontData = g_FoxitSansMMFontData;
451 pFontData = g_FoxitFonts[index].m_pFontData;
452 size = g_FoxitFonts[index].m_dwSize;
457 CFX_FontMapper::CFX_FontMapper()
459 FXSYS_memset32(m_FoxitFaces, 0, sizeof m_FoxitFaces);
460 m_MMFaces[0] = m_MMFaces[1] = NULL;
462 m_bListLoaded = FALSE;
463 m_pFontEnumerator = NULL;
465 CFX_FontMapper::~CFX_FontMapper()
467 for (int i = 0; i < 14; i ++)
468 if (m_FoxitFaces[i]) {
469 FXFT_Done_Face(m_FoxitFaces[i]);
472 FXFT_Done_Face(m_MMFaces[0]);
475 FXFT_Done_Face(m_MMFaces[1]);
478 m_pFontInfo->Release();
481 void CFX_FontMapper::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo)
483 if (pFontInfo == NULL) {
487 m_pFontInfo->Release();
489 m_pFontInfo = pFontInfo;
491 static CFX_ByteString _TT_NormalizeName(FX_LPCSTR family)
493 CFX_ByteString norm(family, -1);
497 int pos = norm.Find('+');
499 norm = norm.Left(pos);
504 CFX_ByteString _FPDF_GetNameFromTT(FX_LPCBYTE name_table, FX_DWORD name_id)
506 FX_LPCBYTE ptr = name_table + 2;
507 int name_count = GET_TT_SHORT(ptr);
508 int string_offset = GET_TT_SHORT(ptr + 2);
509 FX_LPCBYTE string_ptr = name_table + string_offset;
511 for (int i = 0; i < name_count; i ++) {
512 if (GET_TT_SHORT(ptr + 6) == name_id && GET_TT_SHORT(ptr) == 1 && GET_TT_SHORT(ptr + 2) == 0) {
513 return CFX_ByteStringC(string_ptr + GET_TT_SHORT(ptr + 10), GET_TT_SHORT(ptr + 8));
517 return CFX_ByteString();
519 static CFX_ByteString _FPDF_ReadStringFromFile(FXSYS_FILE* pFile, FX_DWORD size)
521 CFX_ByteString buffer;
522 if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) {
523 return CFX_ByteString();
525 buffer.ReleaseBuffer(size);
528 CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile, FX_LPCBYTE pTables, FX_DWORD nTables, FX_DWORD tag)
530 for (FX_DWORD i = 0; i < nTables; i ++) {
531 FX_LPCBYTE p = pTables + i * 16;
532 if (GET_TT_LONG(p) == tag) {
533 FX_DWORD offset = GET_TT_LONG(p + 8);
534 FX_DWORD size = GET_TT_LONG(p + 12);
535 FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
536 return _FPDF_ReadStringFromFile(pFile, size);
539 return CFX_ByteString();
541 CFX_ByteString _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile, FX_LPCBYTE pTables, FX_DWORD nTables, FX_DWORD tag)
543 for (FX_DWORD i = 0; i < nTables; i ++) {
544 FX_LPCBYTE p = pTables + i * 16;
545 if (GET_TT_LONG(p) == tag) {
546 FX_DWORD offset = GET_TT_LONG(p + 8);
547 FX_DWORD size = GET_TT_LONG(p + 12);
548 CFX_ByteString buffer;
549 if (!pFile->ReadBlock(buffer.GetBuffer(size), offset, size)) {
550 return CFX_ByteString();
552 buffer.ReleaseBuffer(size);
556 return CFX_ByteString();
558 CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont)
560 if (m_pFontInfo == NULL) {
563 CFX_ByteString result;
564 FX_DWORD size = m_pFontInfo->GetFontData(hFont, 0x6e616d65, NULL, 0);
566 FX_LPBYTE buffer = FX_Alloc(FX_BYTE, size);
567 m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size);
568 result = _FPDF_GetNameFromTT(buffer, 6);
573 void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset)
575 if (m_pFontInfo == NULL) {
578 if (m_CharsetArray.Find((FX_DWORD)charset) == -1) {
579 m_CharsetArray.Add((FX_DWORD)charset);
580 m_FaceArray.Add(name);
582 if (name == m_LastFamily) {
585 FX_LPCBYTE ptr = name;
586 FX_BOOL bLocalized = FALSE;
587 for (int i = 0; i < name.GetLength(); i ++)
593 void* hFont = m_pFontInfo->GetFont(name);
596 hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, bExact);
601 CFX_ByteString new_name = GetPSNameFromTT(hFont);
602 if (!new_name.IsEmpty()) {
603 new_name.Insert(0, ' ');
604 m_InstalledTTFonts.Add(new_name);
606 m_pFontInfo->DeleteFont(hFont);
608 m_InstalledTTFonts.Add(name);
611 void CFX_FontMapper::LoadInstalledFonts()
613 if (m_pFontInfo == NULL) {
622 m_pFontInfo->EnumFontList(this);
623 m_bListLoaded = TRUE;
625 CFX_ByteString CFX_FontMapper::MatchInstalledFonts(const CFX_ByteString& norm_name)
627 LoadInstalledFonts();
629 for (i = m_InstalledTTFonts.GetSize() - 1; i >= 0; i --) {
630 CFX_ByteString norm1 = _TT_NormalizeName(m_InstalledTTFonts[i]);
631 if (norm1 == norm_name) {
636 return CFX_ByteString();
638 CFX_ByteString match = m_InstalledTTFonts[i];
639 if (match[0] == ' ') {
640 match = m_InstalledTTFonts[i + 1];
644 typedef struct _CHARSET_MAP_ {
648 static const CHARSET_MAP g_Codepage2CharsetTable[] = {
681 FX_BYTE _GetCharsetFromCodePage(FX_WORD codepage)
683 FX_INT32 iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1;
684 FXSYS_assert(iEnd >= 0);
685 FX_INT32 iStart = 0, iMid;
687 iMid = (iStart + iEnd) / 2;
688 const CHARSET_MAP & cp = g_Codepage2CharsetTable[iMid];
689 if (codepage == cp.codepage) {
691 } else if (codepage < cp.codepage) {
696 } while (iStart <= iEnd);
699 FX_DWORD _GetCodePageRangeFromCharset(int charset)
701 if (charset == FXFONT_EASTEUROPE_CHARSET) {
704 if (charset == FXFONT_GREEK_CHARSET) {
707 if (charset == FXFONT_TURKISH_CHARSET) {
710 if (charset == FXFONT_HEBREW_CHARSET) {
713 if (charset == FXFONT_ARABIC_CHARSET) {
716 if (charset == FXFONT_BALTIC_CHARSET) {
719 if (charset == FXFONT_THAI_CHARSET) {
722 if (charset == FXFONT_SHIFTJIS_CHARSET) {
725 if (charset == FXFONT_GB2312_CHARSET) {
728 if (charset == FXFONT_CHINESEBIG5_CHARSET) {
731 if (charset == FXFONT_HANGEUL_CHARSET) {
734 if (charset == FXFONT_SYMBOL_CHARSET) {
739 FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, int iBaseFont, int italic_angle, int weight, int picthfamily)
741 if (iBaseFont < 12) {
742 if (m_FoxitFaces[iBaseFont]) {
743 return m_FoxitFaces[iBaseFont];
745 FX_LPCBYTE pFontData = NULL;
747 if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) {
748 m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
749 return m_FoxitFaces[iBaseFont];
752 pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM;
753 pSubstFont->m_ItalicAngle = italic_angle;
755 pSubstFont->m_Weight = weight;
757 if (picthfamily & FXFONT_FF_ROMAN) {
758 pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;
759 pSubstFont->m_Family = "Chrome Serif";
763 FX_LPCBYTE pFontData = NULL;
765 m_pFontMgr->GetStandardFont(pFontData, size, 14);
766 m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
769 pSubstFont->m_Family = "Chrome Sans";
773 FX_LPCBYTE pFontData = NULL;
775 m_pFontMgr->GetStandardFont(pFontData, size, 15);
776 m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
779 const struct _AltFontFamily {
780 FX_LPCSTR m_pFontName;
781 FX_LPCSTR m_pFontFamily;
783 g_AltFontFamilies[] = {
784 {"AGaramondPro", "Adobe Garamond Pro"},
785 {"BankGothicBT-Medium", "BankGothic Md BT"},
786 {"ForteMT", "Forte"},
789 static int compareFontFamilyString(const void* key, const void* element)
791 CFX_ByteString str_key((FX_LPCSTR)key);
792 if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) {
795 return FXSYS_stricmp((FX_LPCSTR)key, ((_AltFontFamily*)element)->m_pFontName);
798 #define FX_FONT_STYLE_None 0x00
799 #define FX_FONT_STYLE_Bold 0x01
800 #define FX_FONT_STYLE_Italic 0x02
801 #define FX_FONT_STYLE_BoldBold 0x04
802 static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle)
804 if (fontName.Find("Script") >= 0) {
805 if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) {
806 fontName = "ScriptMTBold";
807 } else if (fontName.Find("Palace") >= 0) {
808 fontName = "PalaceScriptMT";
809 } else if (fontName.Find("French") >= 0) {
810 fontName = "FrenchScriptMT";
811 } else if (fontName.Find("FreeStyle") >= 0) {
812 fontName = "FreeStyleScript";
816 _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch(fontName.c_str(), g_AltFontFamilies,
817 sizeof g_AltFontFamilies / sizeof (_AltFontFamily), sizeof (_AltFontFamily), compareFontFamilyString);
821 return found->m_pFontFamily;
823 typedef struct _FX_FontStyle {
827 const FX_FontStyle g_FontStyles[] = {
830 { "BoldItalic", 10 },
834 CFX_ByteString ParseStyle(FX_LPCSTR pStyle, int iLen, int iIndex)
837 if (!iLen || iLen <= iIndex) {
838 return buf.GetByteString();
840 while (iIndex < iLen) {
841 if (pStyle[iIndex] == ',') {
844 buf.AppendChar(pStyle[iIndex]);
847 return buf.GetByteString();
849 FX_INT32 GetStyleType(const CFX_ByteString &bsStyle, FX_BOOL bRevert)
851 FX_INT32 iLen = bsStyle.GetLength();
855 int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle);
856 const FX_FontStyle *pStyle = NULL;
857 for (int i = iSize - 1; i >= 0; --i) {
858 pStyle = g_FontStyles + i;
859 if (!pStyle || pStyle->len > iLen) {
863 if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) {
867 if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) {
874 FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int &PitchFamily)
876 if (name == FX_BSTRC("MyriadPro")) {
877 PitchFamily &= ~FXFONT_FF_ROMAN;
882 FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, FX_BOOL bTrueType, FX_DWORD flags,
883 int weight, int italic_angle, int WindowCP, CFX_SubstFont* pSubstFont)
885 if (!(flags & FXFONT_USEEXTERNATTR)) {
886 weight = FXFONT_FW_NORMAL;
889 CFX_ByteString SubstName = name;
890 SubstName.Remove(0x20);
892 if (name[0] == '@') {
893 SubstName = name.Mid(1);
896 _PDF_GetStandardFontName(SubstName);
897 if (SubstName == FX_BSTRC("Symbol") && !bTrueType) {
898 pSubstFont->m_Family = "Chrome Symbol";
899 pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
900 pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
901 if (m_FoxitFaces[12]) {
902 return m_FoxitFaces[12];
904 FX_LPCBYTE pFontData = NULL;
906 m_pFontMgr->GetStandardFont(pFontData, size, 12);
907 m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
908 return m_FoxitFaces[12];
910 if (SubstName == FX_BSTRC("ZapfDingbats")) {
911 pSubstFont->m_Family = "Chrome Dingbats";
912 pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
913 pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
914 if (m_FoxitFaces[13]) {
915 return m_FoxitFaces[13];
917 FX_LPCBYTE pFontData = NULL;
919 m_pFontMgr->GetStandardFont(pFontData, size, 13);
920 m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
921 return m_FoxitFaces[13];
924 CFX_ByteString family, style;
925 FX_BOOL bHasComma = FALSE;
926 FX_BOOL bHasHypen = FALSE;
927 int find = SubstName.Find(FX_BSTRC(","), 0);
929 family = SubstName.Left(find);
930 _PDF_GetStandardFontName(family);
931 style = SubstName.Mid(find + 1);
936 for (; iBaseFont < 12; iBaseFont ++)
937 if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) {
941 FX_BOOL bItalic = FALSE;
943 FX_BOOL bStyleAvail = FALSE;
944 if (iBaseFont < 12) {
945 family = g_Base14FontNames[iBaseFont];
946 if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) {
947 nStyle |= FX_FONT_STYLE_Bold;
949 if ((iBaseFont % 4) / 2) {
950 nStyle |= FX_FONT_STYLE_Italic;
953 PitchFamily |= FXFONT_FF_FIXEDPITCH;
955 if (iBaseFont >= 8) {
956 PitchFamily |= FXFONT_FF_ROMAN;
960 find = family.ReverseFind('-');
962 style = family.Mid(find + 1);
963 family = family.Left(find);
968 int nLen = family.GetLength();
969 FX_INT32 nRet = GetStyleType(family, TRUE);
971 family = family.Left(nLen - g_FontStyles[nRet].len);
973 nStyle |= FX_FONT_STYLE_Bold;
976 nStyle |= FX_FONT_STYLE_Italic;
979 nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic);
983 if (flags & FXFONT_SERIF) {
984 PitchFamily |= FXFONT_FF_ROMAN;
986 if (flags & FXFONT_SCRIPT) {
987 PitchFamily |= FXFONT_FF_SCRIPT;
989 if (flags & FXFONT_FIXED_PITCH) {
990 PitchFamily |= FXFONT_FF_FIXEDPITCH;
993 if (!style.IsEmpty()) {
994 int nLen = style.GetLength();
995 FX_LPCSTR pStyle = style;
997 FX_BOOL bFirstItem = TRUE;
1000 buf = ParseStyle(pStyle, nLen, i);
1001 FX_INT32 nRet = GetStyleType(buf, FALSE);
1002 if ((i && !bStyleAvail) || (!i && nRet < 0)) {
1006 } else if (nRet >= 0) {
1010 if (nStyle & FX_FONT_STYLE_Bold) {
1011 nStyle |= FX_FONT_STYLE_BoldBold;
1013 nStyle |= FX_FONT_STYLE_Bold;
1019 nStyle |= FX_FONT_STYLE_Italic;
1027 nStyle |= FX_FONT_STYLE_Italic;
1028 if (nStyle & FX_FONT_STYLE_Bold) {
1029 nStyle |= FX_FONT_STYLE_BoldBold;
1031 nStyle |= FX_FONT_STYLE_Bold;
1035 i += buf.GetLength() + 1;
1038 weight = weight ? weight : FXFONT_FW_NORMAL;
1039 int old_weight = weight;
1041 weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
1043 if (nStyle & FX_FONT_STYLE_Italic) {
1046 FX_BOOL bCJK = FALSE;
1047 FX_BOOL bExact = FALSE;
1048 int Charset = FXFONT_ANSI_CHARSET;
1050 Charset = _GetCharsetFromCodePage(WindowCP);
1051 } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) {
1052 Charset = FXFONT_SYMBOL_CHARSET;
1054 if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET ||
1055 Charset == FXFONT_HANGEUL_CHARSET || Charset == FXFONT_CHINESEBIG5_CHARSET) {
1058 if (m_pFontInfo == NULL) {
1059 pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1060 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
1062 family = _GetFontFamily(family, nStyle);
1063 CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family));
1064 if (match.IsEmpty() && family != SubstName && (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) {
1065 match = MatchInstalledFonts(_TT_NormalizeName(SubstName));
1067 if (match.IsEmpty() && iBaseFont >= 12) {
1069 if (!CheckSupportThirdPartFont(family, PitchFamily)) {
1070 if (italic_angle != 0) {
1075 weight = old_weight;
1078 pSubstFont->m_bSubstOfCJK = TRUE;
1080 pSubstFont->m_WeightCJK = weight;
1082 pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL;
1084 if (nStyle & FX_FONT_STYLE_Italic) {
1085 pSubstFont->m_bItlicCJK = TRUE;
1090 weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
1092 if (!match.IsEmpty() || iBaseFont < 12) {
1093 pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
1094 if (!match.IsEmpty()) {
1097 if (iBaseFont < 12) {
1098 if (nStyle && !(iBaseFont % 4)) {
1099 if ((nStyle & 0x3) == 1) {
1102 if ((nStyle & 0x3) == 2) {
1105 if ((nStyle & 0x3) == 3) {
1109 if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) {
1110 if (m_FoxitFaces[iBaseFont]) {
1111 return m_FoxitFaces[iBaseFont];
1113 m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData,
1114 m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0);
1115 if (m_FoxitFaces[iBaseFont]) {
1116 return m_FoxitFaces[iBaseFont];
1119 family = g_Base14FontNames[iBaseFont];
1121 pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1124 if (flags & FXFONT_ITALIC) {
1128 bExact = !match.IsEmpty();
1129 void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, family, bExact);
1131 pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT;
1133 if (hFont == NULL) {
1135 if (italic_angle != 0) {
1140 weight = old_weight;
1142 if (!match.IsEmpty()) {
1143 hFont = m_pFontInfo->GetFont(match);
1144 if (hFont == NULL) {
1145 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
1148 if (Charset == FXFONT_SYMBOL_CHARSET) {
1149 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
1150 if (SubstName == FX_BSTRC("Symbol")) {
1151 pSubstFont->m_Family = "Chrome Symbol";
1152 pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1153 pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET;
1154 if (m_FoxitFaces[12]) {
1155 return m_FoxitFaces[12];
1157 FX_LPCBYTE pFontData = NULL;
1159 m_pFontMgr->GetStandardFont(pFontData, size, 12);
1160 m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0);
1161 return m_FoxitFaces[12];
1163 pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;
1164 return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont);
1167 pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL;
1168 return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont);
1171 if (Charset == FXFONT_ANSI_CHARSET) {
1172 pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD;
1173 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
1175 int index = m_CharsetArray.Find(Charset);
1177 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily);
1179 hFont = m_pFontInfo->GetFont(m_FaceArray[index]);
1183 pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont);
1184 if (hFont == NULL) {
1187 m_pFontInfo->GetFaceName(hFont, SubstName);
1188 if (Charset == FXFONT_DEFAULT_CHARSET) {
1189 m_pFontInfo->GetFontCharset(hFont, Charset);
1191 FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0);
1192 FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0);
1193 if(font_size == 0 && ttc_size == 0) {
1194 m_pFontInfo->DeleteFont(hFont);
1197 FXFT_Face face = NULL;
1200 m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024);
1201 FX_DWORD checksum = 0;
1202 for (int i = 0; i < 256; i ++) {
1203 checksum += ((FX_DWORD*)temp)[i];
1205 FX_LPBYTE pFontData;
1206 face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, pFontData);
1208 pFontData = FX_Alloc(FX_BYTE, ttc_size);
1209 m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size);
1210 face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size,
1211 ttc_size - font_size);
1214 FX_LPBYTE pFontData;
1215 face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData);
1217 pFontData = FX_Alloc(FX_BYTE, font_size);
1218 m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size);
1219 face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, font_size, m_pFontInfo->GetFaceIndex(hFont));
1223 m_pFontInfo->DeleteFont(hFont);
1226 pSubstFont->m_Family = SubstName;
1227 pSubstFont->m_Charset = Charset;
1228 FX_BOOL bNeedUpdateWeight = FALSE;
1229 if (FXFT_Is_Face_Bold(face)) {
1230 if (weight == FXFONT_FW_BOLD) {
1231 bNeedUpdateWeight = FALSE;
1233 bNeedUpdateWeight = TRUE;
1236 if (weight == FXFONT_FW_NORMAL) {
1237 bNeedUpdateWeight = FALSE;
1239 bNeedUpdateWeight = TRUE;
1242 if (bNeedUpdateWeight) {
1243 pSubstFont->m_Weight = weight;
1245 if (bItalic && !FXFT_Is_Face_Italic(face)) {
1246 if (italic_angle == 0) {
1248 } else if (FXSYS_abs(italic_angle) < 5) {
1251 pSubstFont->m_ItalicAngle = italic_angle;
1253 m_pFontInfo->DeleteFont(hFont);
1257 unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset,
1258 unsigned char* buffer, unsigned long count);
1259 void _FTStreamClose(FXFT_Stream stream);
1261 CFontFileFaceInfo::CFontFileFaceInfo()
1272 CFontFileFaceInfo::~CFontFileFaceInfo()
1275 FXFT_Done_Face(m_Face);
1279 extern FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream);
1280 #if _FX_OS_ == _FX_ANDROID_
1281 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault()
1286 CFX_FolderFontInfo::CFX_FolderFontInfo()
1289 CFX_FolderFontInfo::~CFX_FolderFontInfo()
1291 FX_POSITION pos = m_FontList.GetStartPosition();
1295 m_FontList.GetNextAssoc(pos, key, value);
1296 delete (CFontFaceInfo*)value;
1299 void CFX_FolderFontInfo::AddPath(FX_BSTR path)
1301 m_PathList.Add(path);
1303 void CFX_FolderFontInfo::Release()
1307 FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper)
1309 m_pMapper = pMapper;
1310 for (int i = 0; i < m_PathList.GetSize(); i ++) {
1311 ScanPath(m_PathList[i]);
1315 void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path)
1317 void* handle = FX_OpenFolder(path);
1318 if (handle == NULL) {
1321 CFX_ByteString filename;
1323 while (FX_GetNextFile(handle, filename, bFolder)) {
1325 if (filename == "." || filename == "..") {
1329 CFX_ByteString ext = filename.Right(4);
1331 if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") {
1335 CFX_ByteString fullpath = path;
1336 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
1341 fullpath += filename;
1348 FX_CloseFolder(handle);
1350 void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path)
1352 FXSYS_FILE* pFile = FXSYS_fopen(path, "rb");
1353 if (pFile == NULL) {
1356 FXSYS_fseek(pFile, 0, FXSYS_SEEK_END);
1357 FX_DWORD filesize = FXSYS_ftell(pFile);
1359 FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET);
1360 size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile);
1362 FXSYS_fclose(pFile);
1366 if (GET_TT_LONG(buffer) == 0x74746366) {
1367 FX_DWORD nFaces = GET_TT_LONG(buffer + 8);
1368 if (nFaces > FX_DWORD_MAX / 4) {
1369 FXSYS_fclose(pFile);
1372 FX_DWORD face_bytes = nFaces * 4;
1373 FX_LPBYTE offsets = FX_Alloc(FX_BYTE, face_bytes);
1374 readCnt = FXSYS_fread(offsets, face_bytes, 1, pFile);
1375 if (readCnt != face_bytes) {
1377 FXSYS_fclose(pFile);
1380 for (FX_DWORD i = 0; i < nFaces; i ++) {
1381 FX_LPBYTE p = offsets + i * 4;
1382 ReportFace(path, pFile, filesize, GET_TT_LONG(p));
1386 ReportFace(path, pFile, filesize, 0);
1388 FXSYS_fclose(pFile);
1390 void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path, FXSYS_FILE* pFile, FX_DWORD filesize, FX_DWORD offset)
1392 FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
1394 if (!FXSYS_fread(buffer, 12, 1, pFile)) {
1397 FX_DWORD nTables = GET_TT_SHORT(buffer + 4);
1398 CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16);
1399 if (tables.IsEmpty()) {
1402 CFX_ByteString names = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65);
1403 CFX_ByteString facename = _FPDF_GetNameFromTT(names, 1);
1404 CFX_ByteString style = _FPDF_GetNameFromTT(names, 2);
1405 if (style != "Regular") {
1406 facename += " " + style;
1409 if (m_FontList.Lookup(facename, p)) {
1412 CFontFaceInfo* pInfo = new CFontFaceInfo;
1413 pInfo->m_FilePath = path;
1414 pInfo->m_FaceName = facename;
1415 pInfo->m_FontTables = tables;
1416 pInfo->m_FontOffset = offset;
1417 pInfo->m_FileSize = filesize;
1418 pInfo->m_Charsets = 0;
1419 CFX_ByteString os2 = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32);
1420 if (os2.GetLength() >= 86) {
1421 FX_LPCBYTE p = (FX_LPCBYTE)os2 + 78;
1422 FX_DWORD codepages = GET_TT_LONG(p);
1423 if (codepages & (1 << 17)) {
1424 m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET);
1425 pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS;
1427 if (codepages & (1 << 18)) {
1428 m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET);
1429 pInfo->m_Charsets |= CHARSET_FLAG_GB;
1431 if (codepages & (1 << 20)) {
1432 m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET);
1433 pInfo->m_Charsets |= CHARSET_FLAG_BIG5;
1435 if ((codepages & (1 << 19)) || (codepages & (1 << 21))) {
1436 m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET);
1437 pInfo->m_Charsets |= CHARSET_FLAG_KOREAN;
1439 if (codepages & (1 << 31)) {
1440 m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET);
1441 pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL;
1444 m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET);
1445 pInfo->m_Charsets |= CHARSET_FLAG_ANSI;
1446 pInfo->m_Styles = 0;
1447 if (style.Find(FX_BSTRC("Bold")) > -1) {
1448 pInfo->m_Styles |= FXFONT_BOLD;
1450 if (style.Find(FX_BSTRC("Italic")) > -1 || style.Find(FX_BSTRC("Oblique")) > -1) {
1451 pInfo->m_Styles |= FXFONT_ITALIC;
1453 if (facename.Find(FX_BSTRC("Serif")) > -1) {
1454 pInfo->m_Styles |= FXFONT_SERIF;
1456 m_FontList.SetAt(facename, pInfo);
1458 void* CFX_FolderFontInfo::MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, FX_LPCSTR family, FX_BOOL& bExact)
1462 void* CFX_FolderFontInfo::GetFont(FX_LPCSTR face)
1465 if (!m_FontList.Lookup(face, p)) {
1470 FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont, FX_DWORD table, FX_LPBYTE buffer, FX_DWORD size)
1472 if (hFont == NULL) {
1475 CFontFaceInfo* pFont = (CFontFaceInfo*)hFont;
1476 FXSYS_FILE* pFile = NULL;
1478 pFile = FXSYS_fopen(pFont->m_FilePath, "rb");
1479 if (pFile == NULL) {
1483 FX_DWORD datasize = 0;
1486 datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize;
1488 } else if (table == 0x74746366) {
1489 datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0;
1492 FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16;
1493 for (FX_DWORD i = 0; i < nTables; i ++) {
1494 FX_LPCBYTE p = (FX_LPCBYTE)pFont->m_FontTables + i * 16;
1495 if (GET_TT_LONG(p) == table) {
1496 offset = GET_TT_LONG(p + 8);
1497 datasize = GET_TT_LONG(p + 12);
1501 if (datasize && size >= datasize && pFile) {
1502 FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
1503 FXSYS_fread(buffer, datasize, 1, pFile);
1506 FXSYS_fclose(pFile);
1510 void CFX_FolderFontInfo::DeleteFont(void* hFont)
1513 FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name)
1515 if (hFont == NULL) {
1518 CFontFaceInfo* pFont = (CFontFaceInfo*)hFont;
1519 name = pFont->m_FaceName;
1522 FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset)