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