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/cfx_fontmapper.h" 8 9 #include <algorithm> 10 #include <memory> 11 #include <sstream> 12 #include <tuple> 13 #include <utility> 14 #include <vector> 15 16 #include "core/fxcrt/fx_codepage.h" 17 #include "core/fxge/cfx_fontmgr.h" 18 #include "core/fxge/cfx_substfont.h" 19 #include "core/fxge/fx_font.h" 20 #include "core/fxge/ifx_systemfontinfo.h" 21 #include "third_party/base/stl_util.h" 22 23 namespace { 24 25 const int kNumStandardFonts = 14; 26 27 const char* const g_Base14FontNames[kNumStandardFonts] = { 28 "Courier", 29 "Courier-Bold", 30 "Courier-BoldOblique", 31 "Courier-Oblique", 32 "Helvetica", 33 "Helvetica-Bold", 34 "Helvetica-BoldOblique", 35 "Helvetica-Oblique", 36 "Times-Roman", 37 "Times-Bold", 38 "Times-BoldItalic", 39 "Times-Italic", 40 "Symbol", 41 "ZapfDingbats", 42 }; 43 44 const struct AltFontName { 45 const char* m_pName; 46 int m_Index; 47 } g_AltFontNames[] = { 48 {"Arial", 4}, 49 {"Arial,Bold", 5}, 50 {"Arial,BoldItalic", 6}, 51 {"Arial,Italic", 7}, 52 {"Arial-Bold", 5}, 53 {"Arial-BoldItalic", 6}, 54 {"Arial-BoldItalicMT", 6}, 55 {"Arial-BoldMT", 5}, 56 {"Arial-Italic", 7}, 57 {"Arial-ItalicMT", 7}, 58 {"ArialBold", 5}, 59 {"ArialBoldItalic", 6}, 60 {"ArialItalic", 7}, 61 {"ArialMT", 4}, 62 {"ArialMT,Bold", 5}, 63 {"ArialMT,BoldItalic", 6}, 64 {"ArialMT,Italic", 7}, 65 {"ArialRoundedMTBold", 5}, 66 {"Courier", 0}, 67 {"Courier,Bold", 1}, 68 {"Courier,BoldItalic", 2}, 69 {"Courier,Italic", 3}, 70 {"Courier-Bold", 1}, 71 {"Courier-BoldOblique", 2}, 72 {"Courier-Oblique", 3}, 73 {"CourierBold", 1}, 74 {"CourierBoldItalic", 2}, 75 {"CourierItalic", 3}, 76 {"CourierNew", 0}, 77 {"CourierNew,Bold", 1}, 78 {"CourierNew,BoldItalic", 2}, 79 {"CourierNew,Italic", 3}, 80 {"CourierNew-Bold", 1}, 81 {"CourierNew-BoldItalic", 2}, 82 {"CourierNew-Italic", 3}, 83 {"CourierNewBold", 1}, 84 {"CourierNewBoldItalic", 2}, 85 {"CourierNewItalic", 3}, 86 {"CourierNewPS-BoldItalicMT", 2}, 87 {"CourierNewPS-BoldMT", 1}, 88 {"CourierNewPS-ItalicMT", 3}, 89 {"CourierNewPSMT", 0}, 90 {"CourierStd", 0}, 91 {"CourierStd-Bold", 1}, 92 {"CourierStd-BoldOblique", 2}, 93 {"CourierStd-Oblique", 3}, 94 {"Helvetica", 4}, 95 {"Helvetica,Bold", 5}, 96 {"Helvetica,BoldItalic", 6}, 97 {"Helvetica,Italic", 7}, 98 {"Helvetica-Bold", 5}, 99 {"Helvetica-BoldItalic", 6}, 100 {"Helvetica-BoldOblique", 6}, 101 {"Helvetica-Italic", 7}, 102 {"Helvetica-Oblique", 7}, 103 {"HelveticaBold", 5}, 104 {"HelveticaBoldItalic", 6}, 105 {"HelveticaItalic", 7}, 106 {"Symbol", 12}, 107 {"SymbolMT", 12}, 108 {"Times-Bold", 9}, 109 {"Times-BoldItalic", 10}, 110 {"Times-Italic", 11}, 111 {"Times-Roman", 8}, 112 {"TimesBold", 9}, 113 {"TimesBoldItalic", 10}, 114 {"TimesItalic", 11}, 115 {"TimesNewRoman", 8}, 116 {"TimesNewRoman,Bold", 9}, 117 {"TimesNewRoman,BoldItalic", 10}, 118 {"TimesNewRoman,Italic", 11}, 119 {"TimesNewRoman-Bold", 9}, 120 {"TimesNewRoman-BoldItalic", 10}, 121 {"TimesNewRoman-Italic", 11}, 122 {"TimesNewRomanBold", 9}, 123 {"TimesNewRomanBoldItalic", 10}, 124 {"TimesNewRomanItalic", 11}, 125 {"TimesNewRomanPS", 8}, 126 {"TimesNewRomanPS-Bold", 9}, 127 {"TimesNewRomanPS-BoldItalic", 10}, 128 {"TimesNewRomanPS-BoldItalicMT", 10}, 129 {"TimesNewRomanPS-BoldMT", 9}, 130 {"TimesNewRomanPS-Italic", 11}, 131 {"TimesNewRomanPS-ItalicMT", 11}, 132 {"TimesNewRomanPSMT", 8}, 133 {"TimesNewRomanPSMT,Bold", 9}, 134 {"TimesNewRomanPSMT,BoldItalic", 10}, 135 {"TimesNewRomanPSMT,Italic", 11}, 136 {"ZapfDingbats", 13}, 137 }; 138 139 const struct AltFontFamily { 140 const char* m_pFontName; 141 const char* m_pFontFamily; 142 } g_AltFontFamilies[] = { 143 {"AGaramondPro", "Adobe Garamond Pro"}, 144 {"BankGothicBT-Medium", "BankGothic Md BT"}, 145 {"ForteMT", "Forte"}, 146 }; 147 148 const struct CODEPAGE_MAP { 149 uint16_t codepage; 150 uint8_t charset; 151 } g_Codepage2CharsetTable[] = { 152 {0, 1}, {42, 2}, {437, 254}, {850, 255}, {874, 222}, 153 {932, 128}, {936, 134}, {949, 129}, {950, 136}, {1250, 238}, 154 {1251, 204}, {1252, 0}, {1253, 161}, {1254, 162}, {1255, 177}, 155 {1256, 178}, {1257, 186}, {1258, 163}, {1361, 130}, {10000, 77}, 156 {10001, 78}, {10002, 81}, {10003, 79}, {10004, 84}, {10005, 83}, 157 {10006, 85}, {10007, 89}, {10008, 80}, {10021, 87}, {10029, 88}, 158 {10081, 86}, 159 }; 160 161 ByteString TT_NormalizeName(const char* family) { 162 ByteString norm(family); 163 norm.Remove(' '); 164 norm.Remove('-'); 165 norm.Remove(','); 166 auto pos = norm.Find('+'); 167 if (pos.has_value() && pos.value() != 0) 168 norm = norm.Left(pos.value()); 169 norm.MakeLower(); 170 return norm; 171 } 172 173 uint8_t GetCharsetFromCodePage(uint16_t codepage) { 174 const CODEPAGE_MAP* pEnd = 175 g_Codepage2CharsetTable + FX_ArraySize(g_Codepage2CharsetTable); 176 const CODEPAGE_MAP* pCharmap = 177 std::lower_bound(g_Codepage2CharsetTable, pEnd, codepage, 178 [](const CODEPAGE_MAP& charset, uint16_t page) { 179 return charset.codepage < page; 180 }); 181 if (pCharmap < pEnd && codepage == pCharmap->codepage) 182 return pCharmap->charset; 183 return FX_CHARSET_Default; 184 } 185 186 void GetFontFamily(uint32_t nStyle, ByteString* fontName) { 187 if (fontName->Contains("Script")) { 188 if (FontStyleIsBold(nStyle)) 189 *fontName = "ScriptMTBold"; 190 else if (fontName->Contains("Palace")) 191 *fontName = "PalaceScriptMT"; 192 else if (fontName->Contains("French")) 193 *fontName = "FrenchScriptMT"; 194 else if (fontName->Contains("FreeStyle")) 195 *fontName = "FreeStyleScript"; 196 return; 197 } 198 for (const auto& alternate : g_AltFontFamilies) { 199 if (fontName->Contains(alternate.m_pFontName)) { 200 *fontName = alternate.m_pFontFamily; 201 return; 202 } 203 } 204 } 205 206 ByteString ParseStyle(const char* pStyle, int iLen, int iIndex) { 207 std::ostringstream buf; 208 if (!iLen || iLen <= iIndex) 209 return ByteString(buf); 210 while (iIndex < iLen) { 211 if (pStyle[iIndex] == ',') 212 break; 213 buf << pStyle[iIndex]; 214 ++iIndex; 215 } 216 return ByteString(buf); 217 } 218 219 const struct FX_FontStyle { 220 const char* name; 221 size_t len; 222 uint32_t style; 223 } g_FontStyles[] = { 224 {"Bold", 4, FXFONT_BOLD}, 225 {"Italic", 6, FXFONT_ITALIC}, 226 {"BoldItalic", 10, FXFONT_BOLD | FXFONT_ITALIC}, 227 {"Reg", 3, FXFONT_NORMAL}, 228 {"Regular", 7, FXFONT_NORMAL}, 229 }; 230 231 // <exists, index, length> 232 std::tuple<bool, uint32_t, size_t> GetStyleType(const ByteString& bsStyle, 233 bool bReverse) { 234 if (bsStyle.IsEmpty()) 235 return std::make_tuple(false, FXFONT_NORMAL, 0); 236 237 for (int i = FX_ArraySize(g_FontStyles) - 1; i >= 0; --i) { 238 const FX_FontStyle* pStyle = g_FontStyles + i; 239 if (!pStyle || pStyle->len > bsStyle.GetLength()) 240 continue; 241 242 if (bReverse) { 243 if (bsStyle.Right(pStyle->len).Compare(pStyle->name) == 0) 244 return std::make_tuple(true, pStyle->style, pStyle->len); 245 } else { 246 if (bsStyle.Left(pStyle->len).Compare(pStyle->name) == 0) 247 return std::make_tuple(true, pStyle->style, pStyle->len); 248 } 249 } 250 return std::make_tuple(false, FXFONT_NORMAL, 0); 251 } 252 253 bool CheckSupportThirdPartFont(const ByteString& name, int* PitchFamily) { 254 if (name != "MyriadPro") 255 return false; 256 *PitchFamily &= ~FXFONT_FF_ROMAN; 257 return true; 258 } 259 260 void UpdatePitchFamily(uint32_t flags, int* PitchFamily) { 261 if (FontStyleIsSerif(flags)) 262 *PitchFamily |= FXFONT_FF_ROMAN; 263 if (FontStyleIsScript(flags)) 264 *PitchFamily |= FXFONT_FF_SCRIPT; 265 if (FontStyleIsFixedPitch(flags)) 266 *PitchFamily |= FXFONT_FF_FIXEDPITCH; 267 } 268 269 } // namespace 270 271 CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) 272 : m_bListLoaded(false), m_pFontMgr(mgr) { 273 m_MMFaces[0] = nullptr; 274 m_MMFaces[1] = nullptr; 275 memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces)); 276 } 277 278 CFX_FontMapper::~CFX_FontMapper() { 279 for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) { 280 if (m_FoxitFaces[i]) 281 FXFT_Done_Face(m_FoxitFaces[i]); 282 } 283 if (m_MMFaces[0]) 284 FXFT_Done_Face(m_MMFaces[0]); 285 if (m_MMFaces[1]) 286 FXFT_Done_Face(m_MMFaces[1]); 287 } 288 289 void CFX_FontMapper::SetSystemFontInfo( 290 std::unique_ptr<IFX_SystemFontInfo> pFontInfo) { 291 if (!pFontInfo) 292 return; 293 294 m_pFontInfo = std::move(pFontInfo); 295 } 296 297 ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { 298 if (!m_pFontInfo) 299 return ByteString(); 300 301 uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, nullptr, 0); 302 if (!size) 303 return ByteString(); 304 305 std::vector<uint8_t> buffer(size); 306 uint8_t* buffer_ptr = buffer.data(); 307 uint32_t bytes_read = 308 m_pFontInfo->GetFontData(hFont, kTableNAME, buffer_ptr, size); 309 return bytes_read == size ? GetNameFromTT(buffer_ptr, bytes_read, 6) 310 : ByteString(); 311 } 312 313 void CFX_FontMapper::AddInstalledFont(const ByteString& name, int charset) { 314 if (!m_pFontInfo) 315 return; 316 317 m_FaceArray.push_back({name, static_cast<uint32_t>(charset)}); 318 if (name == m_LastFamily) 319 return; 320 321 bool bLocalized = std::any_of(name.begin(), name.end(), [](const char& c) { 322 return static_cast<uint8_t>(c) > 0x80; 323 }); 324 325 if (bLocalized) { 326 void* hFont = m_pFontInfo->GetFont(name.c_str()); 327 if (!hFont) { 328 hFont = m_pFontInfo->MapFont(0, 0, FX_CHARSET_Default, 0, name.c_str()); 329 if (!hFont) 330 return; 331 } 332 333 ByteString new_name = GetPSNameFromTT(hFont); 334 if (!new_name.IsEmpty()) 335 m_LocalizedTTFonts.push_back(std::make_pair(new_name, name)); 336 m_pFontInfo->DeleteFont(hFont); 337 } 338 m_InstalledTTFonts.push_back(name); 339 m_LastFamily = name; 340 } 341 342 void CFX_FontMapper::LoadInstalledFonts() { 343 if (!m_pFontInfo || m_bListLoaded) 344 return; 345 346 m_pFontInfo->EnumFontList(this); 347 m_bListLoaded = true; 348 } 349 350 ByteString CFX_FontMapper::MatchInstalledFonts(const ByteString& norm_name) { 351 LoadInstalledFonts(); 352 int i; 353 for (i = pdfium::CollectionSize<int>(m_InstalledTTFonts) - 1; i >= 0; i--) { 354 ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str()); 355 if (norm1 == norm_name) 356 return m_InstalledTTFonts[i]; 357 } 358 for (i = pdfium::CollectionSize<int>(m_LocalizedTTFonts) - 1; i >= 0; i--) { 359 ByteString norm1 = TT_NormalizeName(m_LocalizedTTFonts[i].first.c_str()); 360 if (norm1 == norm_name) 361 return m_LocalizedTTFonts[i].second; 362 } 363 return ByteString(); 364 } 365 366 FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, 367 int iBaseFont, 368 int italic_angle, 369 int weight, 370 int pitch_family) { 371 if (iBaseFont < kNumStandardFonts) { 372 if (m_FoxitFaces[iBaseFont]) 373 return m_FoxitFaces[iBaseFont]; 374 const uint8_t* pFontData = nullptr; 375 uint32_t size = 0; 376 if (m_pFontMgr->GetBuiltinFont(iBaseFont, &pFontData, &size)) { 377 m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); 378 return m_FoxitFaces[iBaseFont]; 379 } 380 } 381 pSubstFont->m_bFlagMM = true; 382 pSubstFont->m_ItalicAngle = italic_angle; 383 if (weight) 384 pSubstFont->m_Weight = weight; 385 if (FontFamilyIsRoman(pitch_family)) { 386 pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; 387 pSubstFont->m_Family = "Chrome Serif"; 388 if (m_MMFaces[1]) 389 return m_MMFaces[1]; 390 const uint8_t* pFontData = nullptr; 391 uint32_t size = 0; 392 m_pFontMgr->GetBuiltinFont(14, &pFontData, &size); 393 m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); 394 return m_MMFaces[1]; 395 } 396 pSubstFont->m_Family = "Chrome Sans"; 397 if (m_MMFaces[0]) 398 return m_MMFaces[0]; 399 const uint8_t* pFontData = nullptr; 400 uint32_t size = 0; 401 m_pFontMgr->GetBuiltinFont(15, &pFontData, &size); 402 m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); 403 return m_MMFaces[0]; 404 } 405 406 FXFT_Face CFX_FontMapper::FindSubstFont(const ByteString& name, 407 bool bTrueType, 408 uint32_t flags, 409 int weight, 410 int italic_angle, 411 int WindowCP, 412 CFX_SubstFont* pSubstFont) { 413 if (weight == 0) 414 weight = FXFONT_FW_NORMAL; 415 416 if (!(flags & FXFONT_USEEXTERNATTR)) { 417 weight = FXFONT_FW_NORMAL; 418 italic_angle = 0; 419 } 420 ByteString SubstName = name; 421 SubstName.Remove(' '); 422 if (bTrueType && name.GetLength() > 0 && name[0] == '@') 423 SubstName = name.Right(name.GetLength() - 1); 424 PDF_GetStandardFontName(&SubstName); 425 if (SubstName == "Symbol" && !bTrueType) { 426 pSubstFont->m_Family = "Chrome Symbol"; 427 pSubstFont->m_Charset = FX_CHARSET_Symbol; 428 return UseInternalSubst(pSubstFont, 12, italic_angle, weight, 0); 429 } 430 if (SubstName == "ZapfDingbats") { 431 pSubstFont->m_Family = "Chrome Dingbats"; 432 pSubstFont->m_Charset = FX_CHARSET_Symbol; 433 return UseInternalSubst(pSubstFont, 13, italic_angle, weight, 0); 434 } 435 int iBaseFont = 0; 436 ByteString family; 437 ByteString style; 438 bool bHasComma = false; 439 bool bHasHyphen = false; 440 auto pos = SubstName.Find(",", 0); 441 if (pos.has_value()) { 442 family = SubstName.Left(pos.value()); 443 PDF_GetStandardFontName(&family); 444 style = SubstName.Right(SubstName.GetLength() - (pos.value() + 1)); 445 bHasComma = true; 446 } else { 447 family = SubstName; 448 } 449 for (; iBaseFont < 12; iBaseFont++) { 450 if (family == ByteStringView(g_Base14FontNames[iBaseFont])) 451 break; 452 } 453 int PitchFamily = 0; 454 bool bItalic = false; 455 uint32_t nStyle = FXFONT_NORMAL; 456 bool bStyleAvail = false; 457 if (iBaseFont < 12) { 458 if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) 459 nStyle |= FXFONT_BOLD; 460 if ((iBaseFont % 4) / 2) 461 nStyle |= FXFONT_ITALIC; 462 if (iBaseFont < 4) 463 PitchFamily |= FXFONT_FF_FIXEDPITCH; 464 if (iBaseFont >= 8) 465 PitchFamily |= FXFONT_FF_ROMAN; 466 } else { 467 iBaseFont = kNumStandardFonts; 468 if (!bHasComma) { 469 pos = family.ReverseFind('-'); 470 if (pos.has_value()) { 471 style = family.Right(family.GetLength() - (pos.value() + 1)); 472 family = family.Left(pos.value()); 473 bHasHyphen = true; 474 } 475 } 476 if (!bHasHyphen) { 477 int nLen = family.GetLength(); 478 bool hasStyleType; 479 uint32_t styleType; 480 size_t len; 481 std::tie(hasStyleType, styleType, len) = GetStyleType(family, true); 482 if (hasStyleType) { 483 family = family.Left(nLen - len); 484 nStyle |= styleType; 485 } 486 } 487 UpdatePitchFamily(flags, &PitchFamily); 488 } 489 490 int old_weight = weight; 491 if (FontStyleIsBold(nStyle)) 492 weight = FXFONT_FW_BOLD; 493 494 if (!style.IsEmpty()) { 495 int nLen = style.GetLength(); 496 const char* pStyle = style.c_str(); 497 int i = 0; 498 bool bFirstItem = true; 499 ByteString buf; 500 while (i < nLen) { 501 buf = ParseStyle(pStyle, nLen, i); 502 503 bool hasStyleType; 504 uint32_t styleType; 505 size_t len; 506 std::tie(hasStyleType, styleType, len) = GetStyleType(buf, false); 507 if ((i && !bStyleAvail) || (!i && !hasStyleType)) { 508 family = SubstName; 509 iBaseFont = kNumStandardFonts; 510 break; 511 } 512 if (hasStyleType) 513 bStyleAvail = true; 514 515 if (FontStyleIsBold(styleType)) { 516 // If we're already bold, then we're double bold, use special weight. 517 if (FontStyleIsBold(nStyle)) { 518 weight = FXFONT_FW_BOLD_BOLD; 519 } else { 520 weight = FXFONT_FW_BOLD; 521 nStyle |= FXFONT_BOLD; 522 } 523 524 bFirstItem = false; 525 } 526 if (FontStyleIsItalic(styleType) && FontStyleIsBold(styleType)) { 527 nStyle |= FXFONT_ITALIC; 528 } else if (FontStyleIsItalic(styleType)) { 529 if (bFirstItem) { 530 nStyle |= FXFONT_ITALIC; 531 } else { 532 family = SubstName; 533 iBaseFont = kNumStandardFonts; 534 } 535 break; 536 } 537 i += buf.GetLength() + 1; 538 } 539 } 540 if (FontStyleIsItalic(nStyle)) 541 bItalic = true; 542 543 int Charset = FX_CHARSET_ANSI; 544 if (WindowCP) 545 Charset = GetCharsetFromCodePage(WindowCP); 546 else if (iBaseFont == kNumStandardFonts && FontStyleIsSymbolic(flags)) 547 Charset = FX_CHARSET_Symbol; 548 549 bool bCJK = (Charset == FX_CHARSET_ShiftJIS || 550 Charset == FX_CHARSET_ChineseSimplified || 551 Charset == FX_CHARSET_Hangul || 552 Charset == FX_CHARSET_ChineseTraditional); 553 if (!m_pFontInfo) { 554 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, 555 PitchFamily); 556 } 557 GetFontFamily(nStyle, &family); 558 ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str())); 559 if (match.IsEmpty() && family != SubstName && 560 (!bHasComma && (!bHasHyphen || (bHasHyphen && !bStyleAvail)))) { 561 match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str())); 562 } 563 if (match.IsEmpty() && iBaseFont >= kNumStandardFonts) { 564 if (!bCJK) { 565 if (!CheckSupportThirdPartFont(family, &PitchFamily)) { 566 bItalic = italic_angle != 0; 567 weight = old_weight; 568 } 569 #if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ 570 const char* narrow_family = "LiberationSansNarrow"; 571 #elif _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_ 572 const char* narrow_family = "RobotoCondensed"; 573 #else 574 const char* narrow_family = "ArialNarrow"; 575 #endif // _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ 576 auto pos = SubstName.Find("Narrow"); 577 if (pos.has_value() && pos.value() != 0) 578 family = narrow_family; 579 pos = SubstName.Find("Condensed"); 580 if (pos.has_value() && pos.value() != 0) 581 family = narrow_family; 582 } else { 583 pSubstFont->m_bSubstCJK = true; 584 if (nStyle) 585 pSubstFont->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL; 586 if (FontStyleIsItalic(nStyle)) 587 pSubstFont->m_bItalicCJK = true; 588 } 589 } else { 590 italic_angle = 0; 591 } 592 593 if (!match.IsEmpty() || iBaseFont < kNumStandardFonts) { 594 if (!match.IsEmpty()) 595 family = match; 596 if (iBaseFont < kNumStandardFonts) { 597 if (nStyle && !(iBaseFont % 4)) { 598 if (FontStyleIsBold(nStyle) && FontStyleIsItalic(nStyle)) 599 iBaseFont += 2; 600 else if (FontStyleIsBold(nStyle)) 601 iBaseFont += 1; 602 else if (FontStyleIsItalic(nStyle)) 603 iBaseFont += 3; 604 } 605 family = g_Base14FontNames[iBaseFont]; 606 } 607 } else if (FontStyleIsItalic(flags)) { 608 bItalic = true; 609 } 610 void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, 611 family.c_str()); 612 if (!hFont) { 613 #ifdef PDF_ENABLE_XFA 614 if (flags & FXFONT_EXACTMATCH) 615 return nullptr; 616 #endif // PDF_ENABLE_XFA 617 if (bCJK) { 618 bItalic = italic_angle != 0; 619 weight = old_weight; 620 } 621 if (!match.IsEmpty()) { 622 hFont = m_pFontInfo->GetFont(match.c_str()); 623 if (!hFont) { 624 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, 625 PitchFamily); 626 } 627 } else { 628 if (Charset == FX_CHARSET_Symbol) { 629 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || \ 630 _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_ 631 if (SubstName == "Symbol") { 632 pSubstFont->m_Family = "Chrome Symbol"; 633 pSubstFont->m_Charset = FX_CHARSET_Symbol; 634 return UseInternalSubst(pSubstFont, 12, italic_angle, old_weight, 635 PitchFamily); 636 } 637 #endif 638 return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, 639 weight, italic_angle, 0, pSubstFont); 640 } 641 if (Charset == FX_CHARSET_ANSI) { 642 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, 643 PitchFamily); 644 } 645 646 auto it = 647 std::find_if(m_FaceArray.begin(), m_FaceArray.end(), 648 [Charset](const FaceData& face) { 649 return face.charset == static_cast<uint32_t>(Charset); 650 }); 651 if (it == m_FaceArray.end()) { 652 return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, 653 PitchFamily); 654 } 655 hFont = m_pFontInfo->GetFont(it->name.c_str()); 656 } 657 } 658 if (!hFont) 659 return nullptr; 660 661 m_pFontInfo->GetFaceName(hFont, &SubstName); 662 if (Charset == FX_CHARSET_Default) 663 m_pFontInfo->GetFontCharset(hFont, &Charset); 664 uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, nullptr, 0); 665 uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); 666 if (font_size == 0 && ttc_size == 0) { 667 m_pFontInfo->DeleteFont(hFont); 668 return nullptr; 669 } 670 FXFT_Face face = nullptr; 671 if (ttc_size) 672 face = GetCachedTTCFace(hFont, kTableTTCF, ttc_size, font_size); 673 else 674 face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); 675 if (!face) { 676 m_pFontInfo->DeleteFont(hFont); 677 return nullptr; 678 } 679 pSubstFont->m_Family = SubstName; 680 pSubstFont->m_Charset = Charset; 681 bool bNeedUpdateWeight = false; 682 if (FXFT_Is_Face_Bold(face)) 683 bNeedUpdateWeight = weight != FXFONT_FW_BOLD; 684 else 685 bNeedUpdateWeight = weight != FXFONT_FW_NORMAL; 686 if (bNeedUpdateWeight) 687 pSubstFont->m_Weight = weight; 688 if (bItalic && !FXFT_Is_Face_Italic(face)) { 689 if (italic_angle == 0) 690 italic_angle = -12; 691 else if (abs(italic_angle) < 5) 692 italic_angle = 0; 693 pSubstFont->m_ItalicAngle = italic_angle; 694 } 695 m_pFontInfo->DeleteFont(hFont); 696 return face; 697 } 698 699 #ifdef PDF_ENABLE_XFA 700 FXFT_Face CFX_FontMapper::FindSubstFontByUnicode(uint32_t dwUnicode, 701 uint32_t flags, 702 int weight, 703 int italic_angle) { 704 if (!m_pFontInfo) 705 return nullptr; 706 707 bool bItalic = (flags & FXFONT_ITALIC) != 0; 708 int PitchFamily = 0; 709 UpdatePitchFamily(flags, &PitchFamily); 710 void* hFont = 711 m_pFontInfo->MapFontByUnicode(dwUnicode, weight, bItalic, PitchFamily); 712 if (!hFont) 713 return nullptr; 714 715 uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, nullptr, 0); 716 uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); 717 if (font_size == 0 && ttc_size == 0) { 718 m_pFontInfo->DeleteFont(hFont); 719 return nullptr; 720 } 721 FXFT_Face face = nullptr; 722 if (ttc_size) { 723 face = GetCachedTTCFace(hFont, 0x74746366, ttc_size, font_size); 724 } else { 725 ByteString SubstName; 726 m_pFontInfo->GetFaceName(hFont, &SubstName); 727 face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); 728 } 729 m_pFontInfo->DeleteFont(hFont); 730 return face; 731 } 732 #endif // PDF_ENABLE_XFA 733 734 int CFX_FontMapper::GetFaceSize() const { 735 return pdfium::CollectionSize<int>(m_FaceArray); 736 } 737 738 bool CFX_FontMapper::IsBuiltinFace(const FXFT_Face face) const { 739 for (size_t i = 0; i < MM_FACE_COUNT; ++i) { 740 if (m_MMFaces[i] == face) 741 return true; 742 } 743 for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) { 744 if (m_FoxitFaces[i] == face) 745 return true; 746 } 747 return false; 748 } 749 750 FXFT_Face CFX_FontMapper::GetCachedTTCFace(void* hFont, 751 const uint32_t tableTTCF, 752 uint32_t ttc_size, 753 uint32_t font_size) { 754 uint8_t buffer[1024]; 755 m_pFontInfo->GetFontData(hFont, tableTTCF, buffer, FX_ArraySize(buffer)); 756 uint32_t* pBuffer = reinterpret_cast<uint32_t*>(buffer); 757 uint32_t checksum = 0; 758 for (int i = 0; i < 256; i++) 759 checksum += pBuffer[i]; 760 uint8_t* pFontData; 761 FXFT_Face face = m_pFontMgr->GetCachedTTCFace( 762 ttc_size, checksum, ttc_size - font_size, &pFontData); 763 if (!face) { 764 pFontData = FX_Alloc(uint8_t, ttc_size); 765 m_pFontInfo->GetFontData(hFont, tableTTCF, pFontData, ttc_size); 766 face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size, 767 ttc_size - font_size); 768 } 769 return face; 770 } 771 772 FXFT_Face CFX_FontMapper::GetCachedFace(void* hFont, 773 ByteString SubstName, 774 int weight, 775 bool bItalic, 776 uint32_t font_size) { 777 uint8_t* pFontData; 778 FXFT_Face face = 779 m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, &pFontData); 780 if (!face) { 781 pFontData = FX_Alloc(uint8_t, font_size); 782 m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); 783 face = 784 m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, 785 font_size, m_pFontInfo->GetFaceIndex(hFont)); 786 } 787 return face; 788 } 789 790 int PDF_GetStandardFontName(ByteString* name) { 791 const auto* end = std::end(g_AltFontNames); 792 const auto* found = 793 std::lower_bound(std::begin(g_AltFontNames), end, name->c_str(), 794 [](const AltFontName& element, const char* name) { 795 return FXSYS_stricmp(element.m_pName, name) < 0; 796 }); 797 if (found == end || FXSYS_stricmp(found->m_pName, name->c_str())) 798 return -1; 799 800 *name = g_Base14FontNames[found->m_Index]; 801 return found->m_Index; 802 } 803