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