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