1 // Copyright 2014 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 "fpdfsdk/include/formfiller/FFL_CBA_Fontmap.h" 8 9 #include "core/include/fpdfapi/fpdf_page.h" 10 #include "fpdfsdk/include/fsdk_baseannot.h" 11 12 CBA_FontMap::CBA_FontMap(CPDFSDK_Annot* pAnnot, 13 IFX_SystemHandler* pSystemHandler) 14 : CPWL_FontMap(pSystemHandler), 15 m_pDocument(NULL), 16 m_pAnnotDict(NULL), 17 m_pDefaultFont(NULL), 18 m_sAPType("N") { 19 CPDF_Page* pPage = pAnnot->GetPDFPage(); 20 21 m_pDocument = pPage->m_pDocument; 22 m_pAnnotDict = pAnnot->GetPDFAnnot()->GetAnnotDict(); 23 Initialize(); 24 } 25 26 CBA_FontMap::~CBA_FontMap() {} 27 28 void CBA_FontMap::Reset() { 29 Empty(); 30 m_pDefaultFont = NULL; 31 m_sDefaultFontName = ""; 32 } 33 34 void CBA_FontMap::Initialize() { 35 int32_t nCharset = DEFAULT_CHARSET; 36 37 if (!m_pDefaultFont) { 38 m_pDefaultFont = GetAnnotDefaultFont(m_sDefaultFontName); 39 if (m_pDefaultFont) { 40 if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont()) { 41 nCharset = pSubstFont->m_Charset; 42 } else { 43 if (m_sDefaultFontName == "Wingdings" || 44 m_sDefaultFontName == "Wingdings2" || 45 m_sDefaultFontName == "Wingdings3" || 46 m_sDefaultFontName == "Webdings") 47 nCharset = SYMBOL_CHARSET; 48 else 49 nCharset = ANSI_CHARSET; 50 } 51 AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset); 52 AddFontToAnnotDict(m_pDefaultFont, m_sDefaultFontName); 53 } 54 } 55 56 if (nCharset != ANSI_CHARSET) 57 CPWL_FontMap::Initialize(); 58 } 59 60 void CBA_FontMap::SetDefaultFont(CPDF_Font* pFont, 61 const CFX_ByteString& sFontName) { 62 ASSERT(pFont != NULL); 63 64 if (m_pDefaultFont) 65 return; 66 67 m_pDefaultFont = pFont; 68 m_sDefaultFontName = sFontName; 69 70 int32_t nCharset = DEFAULT_CHARSET; 71 if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont()) 72 nCharset = pSubstFont->m_Charset; 73 AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset); 74 } 75 76 CPDF_Font* CBA_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, 77 int32_t nCharset) { 78 ASSERT(m_pAnnotDict != NULL); 79 80 if (m_pAnnotDict->GetString("Subtype") == "Widget") { 81 CPDF_Document* pDocument = GetDocument(); 82 ASSERT(pDocument != NULL); 83 84 CPDF_Dictionary* pRootDict = pDocument->GetRoot(); 85 if (!pRootDict) 86 return NULL; 87 88 CPDF_Dictionary* pAcroFormDict = pRootDict->GetDict("AcroForm"); 89 if (!pAcroFormDict) 90 return NULL; 91 92 CPDF_Dictionary* pDRDict = pAcroFormDict->GetDict("DR"); 93 if (!pDRDict) 94 return NULL; 95 96 return FindResFontSameCharset(pDRDict, sFontAlias, nCharset); 97 } 98 99 return NULL; 100 } 101 102 CPDF_Document* CBA_FontMap::GetDocument() { 103 return m_pDocument; 104 } 105 106 CPDF_Font* CBA_FontMap::FindResFontSameCharset(CPDF_Dictionary* pResDict, 107 CFX_ByteString& sFontAlias, 108 int32_t nCharset) { 109 if (!pResDict) 110 return NULL; 111 112 CPDF_Document* pDocument = GetDocument(); 113 ASSERT(pDocument != NULL); 114 115 CPDF_Dictionary* pFonts = pResDict->GetDict("Font"); 116 if (!pFonts) 117 return NULL; 118 119 CPDF_Font* pFind = NULL; 120 121 for (const auto& it : *pFonts) { 122 const CFX_ByteString& csKey = it.first; 123 CPDF_Object* pObj = it.second; 124 if (!pObj) 125 continue; 126 127 CPDF_Dictionary* pElement = ToDictionary(pObj->GetDirect()); 128 if (!pElement) 129 continue; 130 if (pElement->GetString("Type") != "Font") 131 continue; 132 133 CPDF_Font* pFont = pDocument->LoadFont(pElement); 134 if (!pFont) 135 continue; 136 const CFX_SubstFont* pSubst = pFont->GetSubstFont(); 137 if (!pSubst) 138 continue; 139 if (pSubst->m_Charset == nCharset) { 140 sFontAlias = csKey; 141 pFind = pFont; 142 } 143 } 144 return pFind; 145 } 146 147 void CBA_FontMap::AddedFont(CPDF_Font* pFont, 148 const CFX_ByteString& sFontAlias) { 149 AddFontToAnnotDict(pFont, sFontAlias); 150 } 151 152 void CBA_FontMap::AddFontToAnnotDict(CPDF_Font* pFont, 153 const CFX_ByteString& sAlias) { 154 if (!pFont) 155 return; 156 157 ASSERT(m_pAnnotDict != NULL); 158 ASSERT(m_pDocument != NULL); 159 160 CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDict("AP"); 161 162 if (!pAPDict) { 163 pAPDict = new CPDF_Dictionary; 164 m_pAnnotDict->SetAt("AP", pAPDict); 165 } 166 167 // to avoid checkbox and radiobutton 168 CPDF_Object* pObject = pAPDict->GetElement(m_sAPType); 169 if (ToDictionary(pObject)) 170 return; 171 172 CPDF_Stream* pStream = pAPDict->GetStream(m_sAPType); 173 if (!pStream) { 174 pStream = new CPDF_Stream(NULL, 0, NULL); 175 int32_t objnum = m_pDocument->AddIndirectObject(pStream); 176 pAPDict->SetAtReference(m_sAPType, m_pDocument, objnum); 177 } 178 179 CPDF_Dictionary* pStreamDict = pStream->GetDict(); 180 181 if (!pStreamDict) { 182 pStreamDict = new CPDF_Dictionary; 183 pStream->InitStream(NULL, 0, pStreamDict); 184 } 185 186 if (pStreamDict) { 187 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources"); 188 if (!pStreamResList) { 189 pStreamResList = new CPDF_Dictionary(); 190 pStreamDict->SetAt("Resources", pStreamResList); 191 } 192 193 if (pStreamResList) { 194 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font"); 195 if (!pStreamResFontList) { 196 pStreamResFontList = new CPDF_Dictionary; 197 int32_t objnum = m_pDocument->AddIndirectObject(pStreamResFontList); 198 pStreamResList->SetAtReference("Font", m_pDocument, objnum); 199 } 200 if (!pStreamResFontList->KeyExist(sAlias)) 201 pStreamResFontList->SetAtReference(sAlias, m_pDocument, 202 pFont->GetFontDict()); 203 } 204 } 205 } 206 207 CPDF_Font* CBA_FontMap::GetAnnotDefaultFont(CFX_ByteString& sAlias) { 208 ASSERT(m_pAnnotDict != NULL); 209 ASSERT(m_pDocument != NULL); 210 211 CPDF_Dictionary* pAcroFormDict = NULL; 212 213 FX_BOOL bWidget = (m_pAnnotDict->GetString("Subtype") == "Widget"); 214 215 if (bWidget) { 216 if (CPDF_Dictionary* pRootDict = m_pDocument->GetRoot()) 217 pAcroFormDict = pRootDict->GetDict("AcroForm"); 218 } 219 220 CFX_ByteString sDA; 221 CPDF_Object* pObj; 222 if ((pObj = FPDF_GetFieldAttr(m_pAnnotDict, "DA"))) 223 sDA = pObj->GetString(); 224 225 if (bWidget) { 226 if (sDA.IsEmpty()) { 227 pObj = FPDF_GetFieldAttr(pAcroFormDict, "DA"); 228 sDA = pObj ? pObj->GetString() : CFX_ByteString(); 229 } 230 } 231 232 CPDF_Dictionary* pFontDict = NULL; 233 234 if (!sDA.IsEmpty()) { 235 CPDF_SimpleParser syntax(sDA); 236 syntax.FindTagParam("Tf", 2); 237 CFX_ByteString sFontName = syntax.GetWord(); 238 sAlias = PDF_NameDecode(sFontName).Mid(1); 239 240 if (CPDF_Dictionary* pDRDict = m_pAnnotDict->GetDict("DR")) 241 if (CPDF_Dictionary* pDRFontDict = pDRDict->GetDict("Font")) 242 pFontDict = pDRFontDict->GetDict(sAlias); 243 244 if (!pFontDict) 245 if (CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDict("AP")) 246 if (CPDF_Dictionary* pNormalDict = pAPDict->GetDict("N")) 247 if (CPDF_Dictionary* pNormalResDict = 248 pNormalDict->GetDict("Resources")) 249 if (CPDF_Dictionary* pResFontDict = pNormalResDict->GetDict("Font")) 250 pFontDict = pResFontDict->GetDict(sAlias); 251 252 if (bWidget) { 253 if (!pFontDict) { 254 if (pAcroFormDict) { 255 if (CPDF_Dictionary* pDRDict = pAcroFormDict->GetDict("DR")) 256 if (CPDF_Dictionary* pDRFontDict = pDRDict->GetDict("Font")) 257 pFontDict = pDRFontDict->GetDict(sAlias); 258 } 259 } 260 } 261 } 262 263 return pFontDict ? m_pDocument->LoadFont(pFontDict) : nullptr; 264 } 265 266 void CBA_FontMap::SetAPType(const CFX_ByteString& sAPType) { 267 m_sAPType = sAPType; 268 269 Reset(); 270 Initialize(); 271 } 272