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 "core/fxge/include/cfx_folderfontinfo.h" |
| 8 |
| 9 #include "core/fxge/include/cfx_fontmapper.h" |
| 10 #include "core/fxge/include/fx_font.h" |
| 11 |
| 12 #include "third_party/base/stl_util.h" |
| 13 |
| 14 namespace { |
| 15 |
| 16 const struct { |
| 17 const FX_CHAR* m_pName; |
| 18 const FX_CHAR* m_pSubstName; |
| 19 } Base14Substs[] = { |
| 20 {"Courier", "Courier New"}, |
| 21 {"Courier-Bold", "Courier New Bold"}, |
| 22 {"Courier-BoldOblique", "Courier New Bold Italic"}, |
| 23 {"Courier-Oblique", "Courier New Italic"}, |
| 24 {"Helvetica", "Arial"}, |
| 25 {"Helvetica-Bold", "Arial Bold"}, |
| 26 {"Helvetica-BoldOblique", "Arial Bold Italic"}, |
| 27 {"Helvetica-Oblique", "Arial Italic"}, |
| 28 {"Times-Roman", "Times New Roman"}, |
| 29 {"Times-Bold", "Times New Roman Bold"}, |
| 30 {"Times-BoldItalic", "Times New Roman Bold Italic"}, |
| 31 {"Times-Italic", "Times New Roman Italic"}, |
| 32 }; |
| 33 |
| 34 const uint32_t kTableTTCF = FXDWORD_GET_MSBFIRST("ttcf"); |
| 35 |
| 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 |
| 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 |
| 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_HANGEUL_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 |
| 80 int32_t GetSimilarValue(int weight, |
| 81 FX_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 |
| 102 CFX_FolderFontInfo::CFX_FolderFontInfo() {} |
| 103 |
| 104 CFX_FolderFontInfo::~CFX_FolderFontInfo() { |
| 105 for (const auto& pair : m_FontList) |
| 106 delete pair.second; |
| 107 } |
| 108 |
| 109 void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) { |
| 110 m_PathList.push_back(CFX_ByteString(path)); |
| 111 } |
| 112 |
| 113 FX_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 |
| 120 void CFX_FolderFontInfo::ScanPath(const CFX_ByteString& path) { |
| 121 void* handle = FX_OpenFolder(path.c_str()); |
| 122 if (!handle) |
| 123 return; |
| 124 |
| 125 CFX_ByteString filename; |
| 126 FX_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 |
| 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 |
| 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_HANGEUL_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 |
| 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 |
| 274 void* CFX_FolderFontInfo::FindFont(int weight, |
| 275 FX_BOOL bItalic, |
| 276 int charset, |
| 277 int pitch_family, |
| 278 const FX_CHAR* family, |
| 279 FX_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 |
| 305 void* CFX_FolderFontInfo::MapFont(int weight, |
| 306 FX_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 |
| 315 void* CFX_FolderFontInfo::MapFontByUnicode(uint32_t dwUnicode, |
| 316 int weight, |
| 317 FX_BOOL bItalic, |
| 318 int pitch_family) { |
| 319 return nullptr; |
| 320 } |
| 321 #endif // PDF_ENABLE_XFA |
| 322 |
| 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 |
| 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 |
| 368 void CFX_FolderFontInfo::DeleteFont(void* hFont) {} |
| 369 FX_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 |
| 377 FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) { |
| 378 return FALSE; |
| 379 } |
OLD | NEW |