1 // Copyright 2017 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 "xfa/fgas/font/cfgas_pdffontmgr.h" 8 9 #include <algorithm> 10 11 #include "core/fpdfapi/font/cpdf_font.h" 12 #include "core/fpdfapi/parser/cpdf_document.h" 13 #include "xfa/fgas/font/cfgas_fontmgr.h" 14 #include "xfa/fgas/font/cfgas_gefont.h" 15 16 namespace { 17 18 // The 5 names per entry are: PsName, Normal, Bold, Italic, BoldItalic. 19 const char* const g_XFAPDFFontName[][5] = { 20 {"Adobe PI Std", "AdobePIStd", "AdobePIStd", "AdobePIStd", "AdobePIStd"}, 21 {"Myriad Pro Light", "MyriadPro-Light", "MyriadPro-Semibold", 22 "MyriadPro-LightIt", "MyriadPro-SemiboldIt"}, 23 }; 24 25 } // namespace 26 27 CFGAS_PDFFontMgr::CFGAS_PDFFontMgr(CPDF_Document* pDoc, CFGAS_FontMgr* pFontMgr) 28 : m_pDoc(pDoc), m_pFontMgr(pFontMgr) { 29 ASSERT(pDoc); 30 ASSERT(pFontMgr); 31 } 32 33 CFGAS_PDFFontMgr::~CFGAS_PDFFontMgr() {} 34 35 RetainPtr<CFGAS_GEFont> CFGAS_PDFFontMgr::FindFont(const ByteString& strPsName, 36 bool bBold, 37 bool bItalic, 38 CPDF_Font** pDstPDFFont, 39 bool bStrictMatch) { 40 CPDF_Dictionary* pFontSetDict = 41 m_pDoc->GetRoot()->GetDictFor("AcroForm")->GetDictFor("DR"); 42 if (!pFontSetDict) 43 return nullptr; 44 45 pFontSetDict = pFontSetDict->GetDictFor("Font"); 46 if (!pFontSetDict) 47 return nullptr; 48 49 ByteString name = strPsName; 50 name.Remove(' '); 51 for (const auto& it : *pFontSetDict) { 52 const ByteString& key = it.first; 53 CPDF_Object* pObj = it.second.get(); 54 if (!PsNameMatchDRFontName(name.AsStringView(), bBold, bItalic, key, 55 bStrictMatch)) { 56 continue; 57 } 58 CPDF_Dictionary* pFontDict = ToDictionary(pObj->GetDirect()); 59 if (!pFontDict || pFontDict->GetStringFor("Type") != "Font") 60 return nullptr; 61 62 CPDF_Font* pPDFFont = m_pDoc->LoadFont(pFontDict); 63 if (!pPDFFont) 64 return nullptr; 65 66 if (!pPDFFont->IsEmbedded()) { 67 *pDstPDFFont = pPDFFont; 68 return nullptr; 69 } 70 return CFGAS_GEFont::LoadFont(pPDFFont->GetFont(), m_pFontMgr.Get()); 71 } 72 return nullptr; 73 } 74 75 RetainPtr<CFGAS_GEFont> CFGAS_PDFFontMgr::GetFont( 76 const WideStringView& wsFontFamily, 77 uint32_t dwFontStyles, 78 CPDF_Font** pPDFFont, 79 bool bStrictMatch) { 80 uint32_t dwHashCode = FX_HashCode_GetW(wsFontFamily, false); 81 ByteString strKey = ByteString::Format("%u%u", dwHashCode, dwFontStyles); 82 auto it = m_FontMap.find(strKey); 83 if (it != m_FontMap.end()) 84 return it->second; 85 86 ByteString bsPsName = ByteString::FromUnicode(WideString(wsFontFamily)); 87 bool bBold = FontStyleIsBold(dwFontStyles); 88 bool bItalic = FontStyleIsItalic(dwFontStyles); 89 ByteString strFontName = PsNameToFontName(bsPsName, bBold, bItalic); 90 RetainPtr<CFGAS_GEFont> pFont = 91 FindFont(strFontName, bBold, bItalic, pPDFFont, bStrictMatch); 92 if (pFont) 93 m_FontMap[strKey] = pFont; 94 95 return pFont; 96 } 97 98 ByteString CFGAS_PDFFontMgr::PsNameToFontName(const ByteString& strPsName, 99 bool bBold, 100 bool bItalic) { 101 for (size_t i = 0; i < FX_ArraySize(g_XFAPDFFontName); ++i) { 102 if (strPsName == g_XFAPDFFontName[i][0]) { 103 size_t index = 1; 104 if (bBold) 105 ++index; 106 if (bItalic) 107 index += 2; 108 return g_XFAPDFFontName[i][index]; 109 } 110 } 111 return strPsName; 112 } 113 114 bool CFGAS_PDFFontMgr::PsNameMatchDRFontName(const ByteStringView& bsPsName, 115 bool bBold, 116 bool bItalic, 117 const ByteString& bsDRFontName, 118 bool bStrictMatch) { 119 ByteString bsDRName = bsDRFontName; 120 bsDRName.Remove('-'); 121 size_t iPsLen = bsPsName.GetLength(); 122 auto nIndex = bsDRName.Find(bsPsName); 123 if (nIndex.has_value() && !bStrictMatch) 124 return true; 125 126 if (!nIndex.has_value() || nIndex.value() != 0) 127 return false; 128 129 size_t iDifferLength = bsDRName.GetLength() - iPsLen; 130 if (iDifferLength > 1 || (bBold || bItalic)) { 131 auto iBoldIndex = bsDRName.Find("Bold"); 132 if (bBold != iBoldIndex.has_value()) 133 return false; 134 135 if (iBoldIndex.has_value()) { 136 iDifferLength = std::min(iDifferLength - 4, 137 bsDRName.GetLength() - iBoldIndex.value() - 4); 138 } 139 bool bItalicFont = true; 140 if (bsDRName.Contains("Italic")) 141 iDifferLength -= 6; 142 else if (bsDRName.Contains("It")) 143 iDifferLength -= 2; 144 else if (bsDRName.Contains("Oblique")) 145 iDifferLength -= 7; 146 else 147 bItalicFont = false; 148 149 if (bItalic != bItalicFont) 150 return false; 151 152 if (iDifferLength > 1) { 153 ByteString bsDRTailer = bsDRName.Right(iDifferLength); 154 if (bsDRTailer == "MT" || bsDRTailer == "PSMT" || 155 bsDRTailer == "Regular" || bsDRTailer == "Reg") { 156 return true; 157 } 158 if (iBoldIndex.has_value() || bItalicFont) 159 return false; 160 161 bool bMatch = false; 162 switch (bsPsName[iPsLen - 1]) { 163 case 'L': 164 if (bsDRName.Right(5) == "Light") 165 bMatch = true; 166 167 break; 168 case 'R': 169 if (bsDRName.Right(7) == "Regular" || bsDRName.Right(3) == "Reg") 170 bMatch = true; 171 172 break; 173 case 'M': 174 if (bsDRName.Right(5) == "Medium") 175 bMatch = true; 176 break; 177 default: 178 break; 179 } 180 return bMatch; 181 } 182 } 183 return true; 184 } 185 186 bool CFGAS_PDFFontMgr::GetCharWidth(const RetainPtr<CFGAS_GEFont>& pFont, 187 wchar_t wUnicode, 188 int32_t* pWidth) { 189 if (wUnicode != 0x20) 190 return false; 191 192 auto it = m_FDE2PDFFont.find(pFont); 193 if (it == m_FDE2PDFFont.end()) 194 return false; 195 196 CPDF_Font* pPDFFont = it->second; 197 *pWidth = pPDFFont->GetCharWidthF(pPDFFont->CharCodeFromUnicode(wUnicode)); 198 return true; 199 } 200 201 void CFGAS_PDFFontMgr::SetFont(const RetainPtr<CFGAS_GEFont>& pFont, 202 CPDF_Font* pPDFFont) { 203 m_FDE2PDFFont[pFont] = pPDFFont; 204 } 205