Chromium Code Reviews| 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 |