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