• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 "core/fxge/ge/cfx_folderfontinfo.h"
8 
9 #include <limits>
10 
11 #include "core/fxge/cfx_fontmapper.h"
12 #include "core/fxge/fx_font.h"
13 
14 #include "third_party/base/stl_util.h"
15 
16 namespace {
17 
18 const struct {
19   const FX_CHAR* m_pName;
20   const FX_CHAR* m_pSubstName;
21 } Base14Substs[] = {
22     {"Courier", "Courier New"},
23     {"Courier-Bold", "Courier New Bold"},
24     {"Courier-BoldOblique", "Courier New Bold Italic"},
25     {"Courier-Oblique", "Courier New Italic"},
26     {"Helvetica", "Arial"},
27     {"Helvetica-Bold", "Arial Bold"},
28     {"Helvetica-BoldOblique", "Arial Bold Italic"},
29     {"Helvetica-Oblique", "Arial Italic"},
30     {"Times-Roman", "Times New Roman"},
31     {"Times-Bold", "Times New Roman Bold"},
32     {"Times-BoldItalic", "Times New Roman Bold Italic"},
33     {"Times-Italic", "Times New Roman Italic"},
34 };
35 
FPDF_ReadStringFromFile(FXSYS_FILE * pFile,uint32_t size)36 CFX_ByteString FPDF_ReadStringFromFile(FXSYS_FILE* pFile, uint32_t size) {
37   CFX_ByteString buffer;
38   if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile))
39     return CFX_ByteString();
40   buffer.ReleaseBuffer(size);
41   return buffer;
42 }
43 
FPDF_LoadTableFromTT(FXSYS_FILE * pFile,const uint8_t * pTables,uint32_t nTables,uint32_t tag)44 CFX_ByteString FPDF_LoadTableFromTT(FXSYS_FILE* pFile,
45                                     const uint8_t* pTables,
46                                     uint32_t nTables,
47                                     uint32_t tag) {
48   for (uint32_t i = 0; i < nTables; i++) {
49     const uint8_t* p = pTables + i * 16;
50     if (GET_TT_LONG(p) == tag) {
51       uint32_t offset = GET_TT_LONG(p + 8);
52       uint32_t size = GET_TT_LONG(p + 12);
53       FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
54       return FPDF_ReadStringFromFile(pFile, size);
55     }
56   }
57   return CFX_ByteString();
58 }
59 
GetCharset(int charset)60 uint32_t GetCharset(int charset) {
61   switch (charset) {
62     case FXFONT_SHIFTJIS_CHARSET:
63       return CHARSET_FLAG_SHIFTJIS;
64     case FXFONT_GB2312_CHARSET:
65       return CHARSET_FLAG_GB;
66     case FXFONT_CHINESEBIG5_CHARSET:
67       return CHARSET_FLAG_BIG5;
68     case FXFONT_HANGUL_CHARSET:
69       return CHARSET_FLAG_KOREAN;
70     case FXFONT_SYMBOL_CHARSET:
71       return CHARSET_FLAG_SYMBOL;
72     case FXFONT_ANSI_CHARSET:
73       return CHARSET_FLAG_ANSI;
74     default:
75       break;
76   }
77   return 0;
78 }
79 
GetSimilarValue(int weight,bool bItalic,int pitch_family,uint32_t style)80 int32_t GetSimilarValue(int weight,
81                         bool bItalic,
82                         int pitch_family,
83                         uint32_t style) {
84   int32_t iSimilarValue = 0;
85   if (!!(style & FXFONT_BOLD) == (weight > 400))
86     iSimilarValue += 16;
87   if (!!(style & FXFONT_ITALIC) == bItalic)
88     iSimilarValue += 16;
89   if (!!(style & FXFONT_SERIF) == !!(pitch_family & FXFONT_FF_ROMAN))
90     iSimilarValue += 16;
91   if (!!(style & FXFONT_SCRIPT) == !!(pitch_family & FXFONT_FF_SCRIPT))
92     iSimilarValue += 8;
93   if (!!(style & FXFONT_FIXED_PITCH) ==
94       !!(pitch_family & FXFONT_FF_FIXEDPITCH)) {
95     iSimilarValue += 8;
96   }
97   return iSimilarValue;
98 }
99 
100 }  // namespace
101 
CFX_FolderFontInfo()102 CFX_FolderFontInfo::CFX_FolderFontInfo() {}
103 
~CFX_FolderFontInfo()104 CFX_FolderFontInfo::~CFX_FolderFontInfo() {
105   for (const auto& pair : m_FontList)
106     delete pair.second;
107 }
108 
AddPath(const CFX_ByteStringC & path)109 void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) {
110   m_PathList.push_back(CFX_ByteString(path));
111 }
112 
EnumFontList(CFX_FontMapper * pMapper)113 bool CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) {
114   m_pMapper = pMapper;
115   for (const auto& path : m_PathList)
116     ScanPath(path);
117   return true;
118 }
119 
ScanPath(const CFX_ByteString & path)120 void CFX_FolderFontInfo::ScanPath(const CFX_ByteString& path) {
121   FX_FileHandle* handle = FX_OpenFolder(path.c_str());
122   if (!handle)
123     return;
124 
125   CFX_ByteString filename;
126   bool bFolder;
127   while (FX_GetNextFile(handle, &filename, &bFolder)) {
128     if (bFolder) {
129       if (filename == "." || filename == "..")
130         continue;
131     } else {
132       CFX_ByteString ext = filename.Right(4);
133       ext.MakeUpper();
134       if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC")
135         continue;
136     }
137 
138     CFX_ByteString fullpath = path;
139 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
140     fullpath += "\\";
141 #else
142     fullpath += "/";
143 #endif
144 
145     fullpath += filename;
146     bFolder ? ScanPath(fullpath) : ScanFile(fullpath);
147   }
148   FX_CloseFolder(handle);
149 }
150 
ScanFile(const CFX_ByteString & path)151 void CFX_FolderFontInfo::ScanFile(const CFX_ByteString& path) {
152   FXSYS_FILE* pFile = FXSYS_fopen(path.c_str(), "rb");
153   if (!pFile)
154     return;
155 
156   FXSYS_fseek(pFile, 0, FXSYS_SEEK_END);
157 
158   uint32_t filesize = FXSYS_ftell(pFile);
159   uint8_t buffer[16];
160   FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET);
161 
162   size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile);
163   if (readCnt != 1) {
164     FXSYS_fclose(pFile);
165     return;
166   }
167 
168   if (GET_TT_LONG(buffer) == kTableTTCF) {
169     uint32_t nFaces = GET_TT_LONG(buffer + 8);
170     if (nFaces > std::numeric_limits<uint32_t>::max() / 4) {
171       FXSYS_fclose(pFile);
172       return;
173     }
174     uint32_t face_bytes = nFaces * 4;
175     uint8_t* offsets = FX_Alloc(uint8_t, face_bytes);
176     readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile);
177     if (readCnt != face_bytes) {
178       FX_Free(offsets);
179       FXSYS_fclose(pFile);
180       return;
181     }
182     for (uint32_t i = 0; i < nFaces; i++) {
183       uint8_t* p = offsets + i * 4;
184       ReportFace(path, pFile, filesize, GET_TT_LONG(p));
185     }
186     FX_Free(offsets);
187   } else {
188     ReportFace(path, pFile, filesize, 0);
189   }
190   FXSYS_fclose(pFile);
191 }
192 
ReportFace(const CFX_ByteString & path,FXSYS_FILE * pFile,uint32_t filesize,uint32_t offset)193 void CFX_FolderFontInfo::ReportFace(const CFX_ByteString& path,
194                                     FXSYS_FILE* pFile,
195                                     uint32_t filesize,
196                                     uint32_t offset) {
197   FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET);
198   char buffer[16];
199   if (!FXSYS_fread(buffer, 12, 1, pFile))
200     return;
201 
202   uint32_t nTables = GET_TT_SHORT(buffer + 4);
203   CFX_ByteString tables = FPDF_ReadStringFromFile(pFile, nTables * 16);
204   if (tables.IsEmpty())
205     return;
206 
207   CFX_ByteString names =
208       FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x6e616d65);
209   if (names.IsEmpty())
210     return;
211 
212   CFX_ByteString facename =
213       GetNameFromTT(names.raw_str(), names.GetLength(), 1);
214   if (facename.IsEmpty())
215     return;
216 
217   CFX_ByteString style = GetNameFromTT(names.raw_str(), names.GetLength(), 2);
218   if (style != "Regular")
219     facename += " " + style;
220 
221   if (pdfium::ContainsKey(m_FontList, facename))
222     return;
223 
224   CFX_FontFaceInfo* pInfo =
225       new CFX_FontFaceInfo(path, facename, tables, offset, filesize);
226   CFX_ByteString os2 =
227       FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x4f532f32);
228   if (os2.GetLength() >= 86) {
229     const uint8_t* p = os2.raw_str() + 78;
230     uint32_t codepages = GET_TT_LONG(p);
231     if (codepages & (1 << 17)) {
232       m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET);
233       pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS;
234     }
235     if (codepages & (1 << 18)) {
236       m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET);
237       pInfo->m_Charsets |= CHARSET_FLAG_GB;
238     }
239     if (codepages & (1 << 20)) {
240       m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET);
241       pInfo->m_Charsets |= CHARSET_FLAG_BIG5;
242     }
243     if ((codepages & (1 << 19)) || (codepages & (1 << 21))) {
244       m_pMapper->AddInstalledFont(facename, FXFONT_HANGUL_CHARSET);
245       pInfo->m_Charsets |= CHARSET_FLAG_KOREAN;
246     }
247     if (codepages & (1 << 31)) {
248       m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET);
249       pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL;
250     }
251   }
252   m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET);
253   pInfo->m_Charsets |= CHARSET_FLAG_ANSI;
254   pInfo->m_Styles = 0;
255   if (style.Find("Bold") > -1)
256     pInfo->m_Styles |= FXFONT_BOLD;
257   if (style.Find("Italic") > -1 || style.Find("Oblique") > -1)
258     pInfo->m_Styles |= FXFONT_ITALIC;
259   if (facename.Find("Serif") > -1)
260     pInfo->m_Styles |= FXFONT_SERIF;
261 
262   m_FontList[facename] = pInfo;
263 }
264 
GetSubstFont(const CFX_ByteString & face)265 void* CFX_FolderFontInfo::GetSubstFont(const CFX_ByteString& face) {
266   for (size_t iBaseFont = 0; iBaseFont < FX_ArraySize(Base14Substs);
267        iBaseFont++) {
268     if (face == Base14Substs[iBaseFont].m_pName)
269       return GetFont(Base14Substs[iBaseFont].m_pSubstName);
270   }
271   return nullptr;
272 }
273 
FindFont(int weight,bool bItalic,int charset,int pitch_family,const FX_CHAR * family,bool bMatchName)274 void* CFX_FolderFontInfo::FindFont(int weight,
275                                    bool bItalic,
276                                    int charset,
277                                    int pitch_family,
278                                    const FX_CHAR* family,
279                                    bool bMatchName) {
280   CFX_FontFaceInfo* pFind = nullptr;
281   if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH))
282     return GetFont("Courier New");
283   uint32_t charset_flag = GetCharset(charset);
284   int32_t iBestSimilar = 0;
285   for (const auto& it : m_FontList) {
286     const CFX_ByteString& bsName = it.first;
287     CFX_FontFaceInfo* pFont = it.second;
288     if (!(pFont->m_Charsets & charset_flag) &&
289         charset != FXFONT_DEFAULT_CHARSET) {
290       continue;
291     }
292     int32_t index = bsName.Find(family);
293     if (bMatchName && index < 0)
294       continue;
295     int32_t iSimilarValue =
296         GetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles);
297     if (iSimilarValue > iBestSimilar) {
298       iBestSimilar = iSimilarValue;
299       pFind = pFont;
300     }
301   }
302   return pFind;
303 }
304 
MapFont(int weight,bool bItalic,int charset,int pitch_family,const FX_CHAR * family,int & iExact)305 void* CFX_FolderFontInfo::MapFont(int weight,
306                                   bool bItalic,
307                                   int charset,
308                                   int pitch_family,
309                                   const FX_CHAR* family,
310                                   int& iExact) {
311   return nullptr;
312 }
313 
314 #ifdef PDF_ENABLE_XFA
MapFontByUnicode(uint32_t dwUnicode,int weight,bool bItalic,int pitch_family)315 void* CFX_FolderFontInfo::MapFontByUnicode(uint32_t dwUnicode,
316                                            int weight,
317                                            bool bItalic,
318                                            int pitch_family) {
319   return nullptr;
320 }
321 #endif  // PDF_ENABLE_XFA
322 
GetFont(const FX_CHAR * face)323 void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) {
324   auto it = m_FontList.find(face);
325   return it != m_FontList.end() ? it->second : nullptr;
326 }
327 
GetFontData(void * hFont,uint32_t table,uint8_t * buffer,uint32_t size)328 uint32_t CFX_FolderFontInfo::GetFontData(void* hFont,
329                                          uint32_t table,
330                                          uint8_t* buffer,
331                                          uint32_t size) {
332   if (!hFont)
333     return 0;
334 
335   const CFX_FontFaceInfo* pFont = static_cast<CFX_FontFaceInfo*>(hFont);
336   uint32_t datasize = 0;
337   uint32_t offset = 0;
338   if (table == 0) {
339     datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize;
340   } else if (table == kTableTTCF) {
341     datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0;
342   } else {
343     uint32_t nTables = pFont->m_FontTables.GetLength() / 16;
344     for (uint32_t i = 0; i < nTables; i++) {
345       const uint8_t* p = pFont->m_FontTables.raw_str() + i * 16;
346       if (GET_TT_LONG(p) == table) {
347         offset = GET_TT_LONG(p + 8);
348         datasize = GET_TT_LONG(p + 12);
349       }
350     }
351   }
352 
353   if (!datasize || size < datasize)
354     return datasize;
355 
356   FXSYS_FILE* pFile = FXSYS_fopen(pFont->m_FilePath.c_str(), "rb");
357   if (!pFile)
358     return 0;
359 
360   if (FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET) < 0 ||
361       FXSYS_fread(buffer, datasize, 1, pFile) != 1) {
362     datasize = 0;
363   }
364   FXSYS_fclose(pFile);
365   return datasize;
366 }
367 
DeleteFont(void * hFont)368 void CFX_FolderFontInfo::DeleteFont(void* hFont) {}
GetFaceName(void * hFont,CFX_ByteString & name)369 bool CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) {
370   if (!hFont)
371     return false;
372   CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont;
373   name = pFont->m_FaceName;
374   return true;
375 }
376 
GetFontCharset(void * hFont,int & charset)377 bool CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) {
378   return false;
379 }
380