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