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