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