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