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