// Copyright 2016 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fxge/cfx_fontmapper.h" #include #include #include #include #include #include #include "build/build_config.h" #include "core/fxcrt/fx_codepage.h" #include "core/fxcrt/fx_memory_wrappers.h" #include "core/fxge/cfx_fontmgr.h" #include "core/fxge/cfx_substfont.h" #include "core/fxge/fx_font.h" #include "core/fxge/systemfontinfo_iface.h" #include "third_party/base/stl_util.h" namespace { const int kNumStandardFonts = 14; static_assert(CFX_FontMapper::kDingbats + 1 == kNumStandardFonts, "StandardFont enum count mismatch"); const char* const g_Base14FontNames[kNumStandardFonts] = { "Courier", "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique", "Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Oblique", "Times-Roman", "Times-Bold", "Times-BoldItalic", "Times-Italic", "Symbol", "ZapfDingbats", }; struct AltFontName { const char* m_pName; // Raw, POD struct. CFX_FontMapper::StandardFont m_Index; }; const AltFontName g_AltFontNames[] = { {"Arial", CFX_FontMapper::kHelvetica}, {"Arial,Bold", CFX_FontMapper::kHelveticaBold}, {"Arial,BoldItalic", CFX_FontMapper::kHelveticaBoldOblique}, {"Arial,Italic", CFX_FontMapper::kHelveticaOblique}, {"Arial-Bold", CFX_FontMapper::kHelveticaBold}, {"Arial-BoldItalic", CFX_FontMapper::kHelveticaBoldOblique}, {"Arial-BoldItalicMT", CFX_FontMapper::kHelveticaBoldOblique}, {"Arial-BoldMT", CFX_FontMapper::kHelveticaBold}, {"Arial-Italic", CFX_FontMapper::kHelveticaOblique}, {"Arial-ItalicMT", CFX_FontMapper::kHelveticaOblique}, {"ArialBold", CFX_FontMapper::kHelveticaBold}, {"ArialBoldItalic", CFX_FontMapper::kHelveticaBoldOblique}, {"ArialItalic", CFX_FontMapper::kHelveticaOblique}, {"ArialMT", CFX_FontMapper::kHelvetica}, {"ArialMT,Bold", CFX_FontMapper::kHelveticaBold}, {"ArialMT,BoldItalic", CFX_FontMapper::kHelveticaBoldOblique}, {"ArialMT,Italic", CFX_FontMapper::kHelveticaOblique}, {"ArialRoundedMTBold", CFX_FontMapper::kHelveticaBold}, {"Courier", CFX_FontMapper::kCourier}, {"Courier,Bold", CFX_FontMapper::kCourierBold}, {"Courier,BoldItalic", CFX_FontMapper::kCourierBoldOblique}, {"Courier,Italic", CFX_FontMapper::kCourierOblique}, {"Courier-Bold", CFX_FontMapper::kCourierBold}, {"Courier-BoldOblique", CFX_FontMapper::kCourierBoldOblique}, {"Courier-Oblique", CFX_FontMapper::kCourierOblique}, {"CourierBold", CFX_FontMapper::kCourierBold}, {"CourierBoldItalic", CFX_FontMapper::kCourierBoldOblique}, {"CourierItalic", CFX_FontMapper::kCourierOblique}, {"CourierNew", CFX_FontMapper::kCourier}, {"CourierNew,Bold", CFX_FontMapper::kCourierBold}, {"CourierNew,BoldItalic", CFX_FontMapper::kCourierBoldOblique}, {"CourierNew,Italic", CFX_FontMapper::kCourierOblique}, {"CourierNew-Bold", CFX_FontMapper::kCourierBold}, {"CourierNew-BoldItalic", CFX_FontMapper::kCourierBoldOblique}, {"CourierNew-Italic", CFX_FontMapper::kCourierOblique}, {"CourierNewBold", CFX_FontMapper::kCourierBold}, {"CourierNewBoldItalic", CFX_FontMapper::kCourierBoldOblique}, {"CourierNewItalic", CFX_FontMapper::kCourierOblique}, {"CourierNewPS-BoldItalicMT", CFX_FontMapper::kCourierBoldOblique}, {"CourierNewPS-BoldMT", CFX_FontMapper::kCourierBold}, {"CourierNewPS-ItalicMT", CFX_FontMapper::kCourierOblique}, {"CourierNewPSMT", CFX_FontMapper::kCourier}, {"CourierStd", CFX_FontMapper::kCourier}, {"CourierStd-Bold", CFX_FontMapper::kCourierBold}, {"CourierStd-BoldOblique", CFX_FontMapper::kCourierBoldOblique}, {"CourierStd-Oblique", CFX_FontMapper::kCourierOblique}, {"Helvetica", CFX_FontMapper::kHelvetica}, {"Helvetica,Bold", CFX_FontMapper::kHelveticaBold}, {"Helvetica,BoldItalic", CFX_FontMapper::kHelveticaBoldOblique}, {"Helvetica,Italic", CFX_FontMapper::kHelveticaOblique}, {"Helvetica-Bold", CFX_FontMapper::kHelveticaBold}, {"Helvetica-BoldItalic", CFX_FontMapper::kHelveticaBoldOblique}, {"Helvetica-BoldOblique", CFX_FontMapper::kHelveticaBoldOblique}, {"Helvetica-Italic", CFX_FontMapper::kHelveticaOblique}, {"Helvetica-Oblique", CFX_FontMapper::kHelveticaOblique}, {"HelveticaBold", CFX_FontMapper::kHelveticaBold}, {"HelveticaBoldItalic", CFX_FontMapper::kHelveticaBoldOblique}, {"HelveticaItalic", CFX_FontMapper::kHelveticaOblique}, {"Symbol", CFX_FontMapper::kSymbol}, {"SymbolMT", CFX_FontMapper::kSymbol}, {"Times-Bold", CFX_FontMapper::kTimesBold}, {"Times-BoldItalic", CFX_FontMapper::kTimesBoldOblique}, {"Times-Italic", CFX_FontMapper::kTimesOblique}, {"Times-Roman", CFX_FontMapper::kTimes}, {"TimesBold", CFX_FontMapper::kTimesBold}, {"TimesBoldItalic", CFX_FontMapper::kTimesBoldOblique}, {"TimesItalic", CFX_FontMapper::kTimesOblique}, {"TimesNewRoman", CFX_FontMapper::kTimes}, {"TimesNewRoman,Bold", CFX_FontMapper::kTimesBold}, {"TimesNewRoman,BoldItalic", CFX_FontMapper::kTimesBoldOblique}, {"TimesNewRoman,Italic", CFX_FontMapper::kTimesOblique}, {"TimesNewRoman-Bold", CFX_FontMapper::kTimesBold}, {"TimesNewRoman-BoldItalic", CFX_FontMapper::kTimesBoldOblique}, {"TimesNewRoman-Italic", CFX_FontMapper::kTimesOblique}, {"TimesNewRomanBold", CFX_FontMapper::kTimesBold}, {"TimesNewRomanBoldItalic", CFX_FontMapper::kTimesBoldOblique}, {"TimesNewRomanItalic", CFX_FontMapper::kTimesOblique}, {"TimesNewRomanPS", CFX_FontMapper::kTimes}, {"TimesNewRomanPS-Bold", CFX_FontMapper::kTimesBold}, {"TimesNewRomanPS-BoldItalic", CFX_FontMapper::kTimesBoldOblique}, {"TimesNewRomanPS-BoldItalicMT", CFX_FontMapper::kTimesBoldOblique}, {"TimesNewRomanPS-BoldMT", CFX_FontMapper::kTimesBold}, {"TimesNewRomanPS-Italic", CFX_FontMapper::kTimesOblique}, {"TimesNewRomanPS-ItalicMT", CFX_FontMapper::kTimesOblique}, {"TimesNewRomanPSMT", CFX_FontMapper::kTimes}, {"TimesNewRomanPSMT,Bold", CFX_FontMapper::kTimesBold}, {"TimesNewRomanPSMT,BoldItalic", CFX_FontMapper::kTimesBoldOblique}, {"TimesNewRomanPSMT,Italic", CFX_FontMapper::kTimesOblique}, {"ZapfDingbats", CFX_FontMapper::kDingbats}, }; struct AltFontFamily { const char* m_pFontName; // Raw, POD struct. const char* m_pFontFamily; // Raw, POD struct. }; const AltFontFamily g_AltFontFamilies[] = { {"AGaramondPro", "Adobe Garamond Pro"}, {"BankGothicBT-Medium", "BankGothic Md BT"}, {"ForteMT", "Forte"}, }; #if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ const char kNarrowFamily[] = "LiberationSansNarrow"; #elif defined(OS_ANDROID) const char kNarrowFamily[] = "RobotoCondensed"; #else const char kNarrowFamily[] = "ArialNarrow"; #endif // _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ ByteString TT_NormalizeName(const char* family) { ByteString norm(family); norm.Remove(' '); norm.Remove('-'); norm.Remove(','); auto pos = norm.Find('+'); if (pos.has_value() && pos.value() != 0) norm = norm.First(pos.value()); norm.MakeLower(); return norm; } void GetFontFamily(uint32_t nStyle, ByteString* fontName) { if (fontName->Contains("Script")) { if (FontStyleIsForceBold(nStyle)) *fontName = "ScriptMTBold"; else if (fontName->Contains("Palace")) *fontName = "PalaceScriptMT"; else if (fontName->Contains("French")) *fontName = "FrenchScriptMT"; else if (fontName->Contains("FreeStyle")) *fontName = "FreeStyleScript"; return; } for (const auto& alternate : g_AltFontFamilies) { if (fontName->Contains(alternate.m_pFontName)) { *fontName = alternate.m_pFontFamily; return; } } } ByteString ParseStyle(const char* pStyle, int iLen, int iIndex) { std::ostringstream buf; if (!iLen || iLen <= iIndex) return ByteString(buf); while (iIndex < iLen) { if (pStyle[iIndex] == ',') break; buf << pStyle[iIndex]; ++iIndex; } return ByteString(buf); } const struct FX_FontStyle { const char* name; size_t len; uint32_t style; } g_FontStyles[] = { {"Bold", 4, FXFONT_FORCE_BOLD}, {"Italic", 6, FXFONT_ITALIC}, {"BoldItalic", 10, FXFONT_FORCE_BOLD | FXFONT_ITALIC}, {"Reg", 3, FXFONT_NORMAL}, {"Regular", 7, FXFONT_NORMAL}, }; // std::tuple GetStyleType(const ByteString& bsStyle, bool bReverse) { if (bsStyle.IsEmpty()) return std::make_tuple(false, FXFONT_NORMAL, 0); for (int i = FX_ArraySize(g_FontStyles) - 1; i >= 0; --i) { const FX_FontStyle* pStyle = g_FontStyles + i; if (!pStyle || pStyle->len > bsStyle.GetLength()) continue; if (bReverse) { if (bsStyle.Last(pStyle->len).Compare(pStyle->name) == 0) return std::make_tuple(true, pStyle->style, pStyle->len); } else { if (bsStyle.First(pStyle->len).Compare(pStyle->name) == 0) return std::make_tuple(true, pStyle->style, pStyle->len); } } return std::make_tuple(false, FXFONT_NORMAL, 0); } bool CheckSupportThirdPartFont(const ByteString& name, int* PitchFamily) { if (name != "MyriadPro") return false; *PitchFamily &= ~FXFONT_FF_ROMAN; return true; } void UpdatePitchFamily(uint32_t flags, int* PitchFamily) { if (FontStyleIsSerif(flags)) *PitchFamily |= FXFONT_FF_ROMAN; if (FontStyleIsScript(flags)) *PitchFamily |= FXFONT_FF_SCRIPT; if (FontStyleIsFixedPitch(flags)) *PitchFamily |= FXFONT_FF_FIXEDPITCH; } } // namespace CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) : m_pFontMgr(mgr) {} CFX_FontMapper::~CFX_FontMapper() = default; void CFX_FontMapper::SetSystemFontInfo( std::unique_ptr pFontInfo) { if (!pFontInfo) return; m_pFontInfo = std::move(pFontInfo); } uint32_t CFX_FontMapper::GetChecksumFromTT(void* hFont) { uint32_t buffer[256]; m_pFontInfo->GetFontData( hFont, kTableTTCF, pdfium::as_writable_bytes(pdfium::make_span(buffer))); uint32_t checksum = 0; for (auto x : buffer) checksum += x; return checksum; } ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, {}); if (!size) return ByteString(); std::vector buffer(size); uint32_t bytes_read = m_pFontInfo->GetFontData(hFont, kTableNAME, buffer); return bytes_read == size ? GetNameFromTT(buffer, 6) : ByteString(); } void CFX_FontMapper::AddInstalledFont(const ByteString& name, int charset) { if (!m_pFontInfo) return; m_FaceArray.push_back({name, static_cast(charset)}); if (name == m_LastFamily) return; bool bLocalized = std::any_of(name.begin(), name.end(), [](const char& c) { return static_cast(c) > 0x80; }); if (bLocalized) { void* hFont = m_pFontInfo->GetFont(name.c_str()); if (!hFont) { hFont = m_pFontInfo->MapFont(0, 0, FX_CHARSET_Default, 0, name.c_str()); if (!hFont) return; } ByteString new_name = GetPSNameFromTT(hFont); if (!new_name.IsEmpty()) m_LocalizedTTFonts.push_back(std::make_pair(new_name, name)); m_pFontInfo->DeleteFont(hFont); } m_InstalledTTFonts.push_back(name); m_LastFamily = name; } void CFX_FontMapper::LoadInstalledFonts() { if (!m_pFontInfo || m_bListLoaded) return; m_pFontInfo->EnumFontList(this); m_bListLoaded = true; } ByteString CFX_FontMapper::MatchInstalledFonts(const ByteString& norm_name) { LoadInstalledFonts(); int i; for (i = pdfium::CollectionSize(m_InstalledTTFonts) - 1; i >= 0; i--) { ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str()); if (norm1 == norm_name) return m_InstalledTTFonts[i]; } for (i = pdfium::CollectionSize(m_LocalizedTTFonts) - 1; i >= 0; i--) { ByteString norm1 = TT_NormalizeName(m_LocalizedTTFonts[i].first.c_str()); if (norm1 == norm_name) return m_LocalizedTTFonts[i].second; } return ByteString(); } RetainPtr CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, int iBaseFont, int italic_angle, int weight, int pitch_family) { if (iBaseFont < kNumStandardFonts) { if (m_FoxitFaces[iBaseFont]) return m_FoxitFaces[iBaseFont]; Optional> font_data = m_pFontMgr->GetBuiltinFont(iBaseFont); if (font_data.has_value()) { m_FoxitFaces[iBaseFont] = m_pFontMgr->NewFixedFace(nullptr, font_data.value(), 0); return m_FoxitFaces[iBaseFont]; } } pSubstFont->m_bFlagMM = true; pSubstFont->m_ItalicAngle = italic_angle; if (weight) pSubstFont->m_Weight = weight; if (FontFamilyIsRoman(pitch_family)) { pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; pSubstFont->m_Family = "Chrome Serif"; if (!m_MMFaces[1]) { m_MMFaces[1] = m_pFontMgr->NewFixedFace( nullptr, m_pFontMgr->GetBuiltinFont(14).value(), 0); } return m_MMFaces[1]; } pSubstFont->m_Family = "Chrome Sans"; if (!m_MMFaces[0]) { m_MMFaces[0] = m_pFontMgr->NewFixedFace( nullptr, m_pFontMgr->GetBuiltinFont(15).value(), 0); } return m_MMFaces[0]; } RetainPtr CFX_FontMapper::FindSubstFont(const ByteString& name, bool bTrueType, uint32_t flags, int weight, int italic_angle, int CharsetCP, CFX_SubstFont* pSubstFont) { if (weight == 0) weight = FXFONT_FW_NORMAL; if (!(flags & FXFONT_USEEXTERNATTR)) { weight = FXFONT_FW_NORMAL; italic_angle = 0; } ByteString SubstName = name; SubstName.Remove(' '); if (bTrueType && name.GetLength() > 0 && name[0] == '@') SubstName = name.Last(name.GetLength() - 1); GetStandardFontName(&SubstName); if (SubstName == "Symbol" && !bTrueType) { pSubstFont->m_Family = "Chrome Symbol"; pSubstFont->m_Charset = FX_CHARSET_Symbol; return UseInternalSubst(pSubstFont, 12, italic_angle, weight, 0); } if (SubstName == "ZapfDingbats") { pSubstFont->m_Family = "Chrome Dingbats"; pSubstFont->m_Charset = FX_CHARSET_Symbol; return UseInternalSubst(pSubstFont, 13, italic_angle, weight, 0); } int iBaseFont = 0; ByteString family; ByteString style; bool bHasComma = false; bool bHasHyphen = false; { Optional pos = SubstName.Find(",", 0); if (pos.has_value()) { family = SubstName.First(pos.value()); GetStandardFontName(&family); style = SubstName.Last(SubstName.GetLength() - (pos.value() + 1)); bHasComma = true; } else { family = SubstName; } } for (; iBaseFont < 12; iBaseFont++) { if (family == ByteStringView(g_Base14FontNames[iBaseFont])) break; } int PitchFamily = 0; uint32_t nStyle = FXFONT_NORMAL; bool bStyleAvail = false; if (iBaseFont < 12) { if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) nStyle |= FXFONT_FORCE_BOLD; if ((iBaseFont % 4) / 2) nStyle |= FXFONT_ITALIC; if (iBaseFont < 4) PitchFamily |= FXFONT_FF_FIXEDPITCH; if (iBaseFont >= 8) PitchFamily |= FXFONT_FF_ROMAN; } else { iBaseFont = kNumStandardFonts; if (!bHasComma) { Optional pos = family.ReverseFind('-'); if (pos.has_value()) { style = family.Last(family.GetLength() - (pos.value() + 1)); family = family.First(pos.value()); bHasHyphen = true; } } if (!bHasHyphen) { int nLen = family.GetLength(); bool hasStyleType; uint32_t styleType; size_t len; std::tie(hasStyleType, styleType, len) = GetStyleType(family, true); if (hasStyleType) { family = family.First(nLen - len); nStyle |= styleType; } } UpdatePitchFamily(flags, &PitchFamily); } const int old_weight = weight; if (FontStyleIsForceBold(nStyle)) weight = FXFONT_FW_BOLD; if (!style.IsEmpty()) { int nLen = style.GetLength(); const char* pStyle = style.c_str(); int i = 0; bool bFirstItem = true; ByteString buf; while (i < nLen) { buf = ParseStyle(pStyle, nLen, i); bool hasStyleType; uint32_t styleType; size_t len; std::tie(hasStyleType, styleType, len) = GetStyleType(buf, false); if ((i && !bStyleAvail) || (!i && !hasStyleType)) { family = SubstName; iBaseFont = kNumStandardFonts; break; } if (hasStyleType) bStyleAvail = true; if (FontStyleIsForceBold(styleType)) { // If we're already bold, then we're double bold, use special weight. if (FontStyleIsForceBold(nStyle)) { weight = FXFONT_FW_BOLD_BOLD; } else { weight = FXFONT_FW_BOLD; nStyle |= FXFONT_FORCE_BOLD; } bFirstItem = false; } if (FontStyleIsItalic(styleType) && FontStyleIsForceBold(styleType)) { nStyle |= FXFONT_ITALIC; } else if (FontStyleIsItalic(styleType)) { if (bFirstItem) { nStyle |= FXFONT_ITALIC; } else { family = SubstName; iBaseFont = kNumStandardFonts; } break; } i += buf.GetLength() + 1; } } if (!m_pFontInfo) { return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily); } int Charset = FX_CHARSET_ANSI; if (CharsetCP) Charset = FX_GetCharsetFromCodePage(CharsetCP); else if (iBaseFont == kNumStandardFonts && FontStyleIsSymbolic(flags)) Charset = FX_CHARSET_Symbol; const bool bCJK = FX_CharSetIsCJK(Charset); bool bItalic = FontStyleIsItalic(nStyle); GetFontFamily(nStyle, &family); ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str())); if (match.IsEmpty() && family != SubstName && (!bHasComma && (!bHasHyphen || (bHasHyphen && !bStyleAvail)))) { match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str())); } if (match.IsEmpty() && iBaseFont >= kNumStandardFonts) { if (!bCJK) { if (!CheckSupportThirdPartFont(family, &PitchFamily)) { bItalic = italic_angle != 0; weight = old_weight; } Optional pos = SubstName.Find("Narrow"); if (pos.has_value() && pos.value() != 0) family = kNarrowFamily; pos = SubstName.Find("Condensed"); if (pos.has_value() && pos.value() != 0) family = kNarrowFamily; } else { pSubstFont->m_bSubstCJK = true; if (nStyle) pSubstFont->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL; if (FontStyleIsItalic(nStyle)) pSubstFont->m_bItalicCJK = true; } } else { italic_angle = 0; if (nStyle == FXFONT_NORMAL) weight = FXFONT_FW_NORMAL; } if (!match.IsEmpty() || iBaseFont < kNumStandardFonts) { if (!match.IsEmpty()) family = match; if (iBaseFont < kNumStandardFonts) { if (nStyle && !(iBaseFont % 4)) { if (FontStyleIsForceBold(nStyle) && FontStyleIsItalic(nStyle)) iBaseFont += 2; else if (FontStyleIsForceBold(nStyle)) iBaseFont += 1; else if (FontStyleIsItalic(nStyle)) iBaseFont += 3; } family = g_Base14FontNames[iBaseFont]; } } else if (FontStyleIsItalic(flags)) { bItalic = true; } void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, family.c_str()); if (!hFont) { if (bCJK) { bItalic = italic_angle != 0; weight = old_weight; } if (!match.IsEmpty()) { hFont = m_pFontInfo->GetFont(match.c_str()); if (!hFont) { return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily); } } else { if (Charset == FX_CHARSET_Symbol) { #if defined(OS_MACOSX) || defined(OS_ANDROID) if (SubstName == "Symbol") { pSubstFont->m_Family = "Chrome Symbol"; pSubstFont->m_Charset = FX_CHARSET_Symbol; return UseInternalSubst(pSubstFont, 12, italic_angle, old_weight, PitchFamily); } #endif return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont); } if (Charset == FX_CHARSET_ANSI) { return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily); } auto it = std::find_if(m_FaceArray.begin(), m_FaceArray.end(), [Charset](const FaceData& face) { return face.charset == static_cast(Charset); }); if (it == m_FaceArray.end()) { return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily); } hFont = m_pFontInfo->GetFont(it->name.c_str()); } } if (!hFont) return nullptr; m_pFontInfo->GetFaceName(hFont, &SubstName); if (Charset == FX_CHARSET_Default) m_pFontInfo->GetFontCharset(hFont, &Charset); uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, {}); uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, {}); if (font_size == 0 && ttc_size == 0) { m_pFontInfo->DeleteFont(hFont); return nullptr; } RetainPtr face; if (ttc_size) face = GetCachedTTCFace(hFont, ttc_size, font_size); else face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); if (!face) { m_pFontInfo->DeleteFont(hFont); return nullptr; } pSubstFont->m_Family = SubstName; pSubstFont->m_Charset = Charset; bool bNeedUpdateWeight = false; if (FXFT_Is_Face_Bold(face->GetRec())) bNeedUpdateWeight = weight != FXFONT_FW_BOLD; else bNeedUpdateWeight = weight != FXFONT_FW_NORMAL; if (bNeedUpdateWeight) pSubstFont->m_Weight = weight; if (bItalic && !FXFT_Is_Face_Italic(face->GetRec())) { if (italic_angle == 0) italic_angle = -12; else if (abs(italic_angle) < 5) italic_angle = 0; pSubstFont->m_ItalicAngle = italic_angle; } m_pFontInfo->DeleteFont(hFont); return face; } int CFX_FontMapper::GetFaceSize() const { return pdfium::CollectionSize(m_FaceArray); } #ifdef PDF_ENABLE_XFA std::unique_ptr CFX_FontMapper::RawBytesForIndex( uint32_t index, size_t* returned_length) { if (!m_pFontInfo) return nullptr; void* hFont = m_pFontInfo->MapFont(0, 0, FX_CHARSET_Default, 0, GetFaceName(index).c_str()); if (!hFont) return nullptr; uint32_t required_size = m_pFontInfo->GetFontData(hFont, 0, {}); if (required_size == 0) return nullptr; std::unique_ptr pBuffer( FX_Alloc(uint8_t, required_size + 1)); *returned_length = m_pFontInfo->GetFontData(hFont, 0, {pBuffer.get(), required_size}); return pBuffer; } #endif // PDF_ENABLE_XFA bool CFX_FontMapper::IsBuiltinFace(const RetainPtr& face) const { for (size_t i = 0; i < MM_FACE_COUNT; ++i) { if (m_MMFaces[i] == face) return true; } for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) { if (m_FoxitFaces[i] == face) return true; } return false; } RetainPtr CFX_FontMapper::GetCachedTTCFace(void* hFont, uint32_t ttc_size, uint32_t font_size) { uint32_t checksum = GetChecksumFromTT(hFont); RetainPtr pFontDesc = m_pFontMgr->GetCachedTTCFontDesc(ttc_size, checksum); if (!pFontDesc) { std::unique_ptr pFontData( FX_Alloc(uint8_t, ttc_size)); m_pFontInfo->GetFontData(hFont, kTableTTCF, {pFontData.get(), ttc_size}); pFontDesc = m_pFontMgr->AddCachedTTCFontDesc( ttc_size, checksum, std::move(pFontData), ttc_size); } ASSERT(ttc_size >= font_size); uint32_t font_offset = ttc_size - font_size; int face_index = GetTTCIndex(pFontDesc->FontData().first(ttc_size), font_offset); RetainPtr pFace(pFontDesc->GetFace(face_index)); if (pFace) return pFace; pFace = m_pFontMgr->NewFixedFace( pFontDesc, pFontDesc->FontData().first(ttc_size), face_index); if (!pFace) return nullptr; pFontDesc->SetFace(face_index, pFace.Get()); return pFace; } RetainPtr CFX_FontMapper::GetCachedFace(void* hFont, ByteString SubstName, int weight, bool bItalic, uint32_t font_size) { RetainPtr pFontDesc = m_pFontMgr->GetCachedFontDesc(SubstName, weight, bItalic); if (!pFontDesc) { std::unique_ptr pFontData( FX_Alloc(uint8_t, font_size)); m_pFontInfo->GetFontData(hFont, 0, {pFontData.get(), font_size}); pFontDesc = m_pFontMgr->AddCachedFontDesc(SubstName, weight, bItalic, std::move(pFontData), font_size); } RetainPtr pFace(pFontDesc->GetFace(0)); if (pFace) return pFace; pFace = m_pFontMgr->NewFixedFace(pFontDesc, pFontDesc->FontData().first(font_size), m_pFontInfo->GetFaceIndex(hFont)); if (!pFace) return nullptr; pFontDesc->SetFace(0, pFace.Get()); return pFace; } // static Optional CFX_FontMapper::GetStandardFontName( ByteString* name) { const auto* end = std::end(g_AltFontNames); const auto* found = std::lower_bound(std::begin(g_AltFontNames), end, name->c_str(), [](const AltFontName& element, const char* name) { return FXSYS_stricmp(element.m_pName, name) < 0; }); if (found == end || FXSYS_stricmp(found->m_pName, name->c_str())) return {}; *name = g_Base14FontNames[static_cast(found->m_Index)]; return found->m_Index; } // static bool CFX_FontMapper::IsSymbolicFont(StandardFont font) { return font == StandardFont::kSymbol || font == StandardFont::kDingbats; } // static bool CFX_FontMapper::IsFixedFont(StandardFont font) { return font == StandardFont::kCourier || font == StandardFont::kCourierBold || font == StandardFont::kCourierBoldOblique || font == StandardFont::kCourierOblique; }