Initial commit.
[pdfium.git] / core / src / fpdfdoc / doc_utils.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/fpdfdoc/fpdf_doc.h"\r
8 static const int FPDFDOC_UTILS_MAXRECURSION = 32;\r
9 CFX_WideString  GetFullName(CPDF_Dictionary* pFieldDict);\r
10 void                    InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument);\r
11 FX_DWORD                CountInterFormFonts(CPDF_Dictionary* pFormDict);\r
12 CPDF_Font*              GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_DWORD index, CFX_ByteString& csNameTag);\r
13 CPDF_Font*              GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csNameTag);\r
14 CPDF_Font*              GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CFX_ByteString& csNameTag);\r
15 CPDF_Font*              GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);\r
16 CPDF_Font*              GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);\r
17 FX_BOOL                 FindInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont, CFX_ByteString& csNameTag);\r
18 FX_BOOL                 FindInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag);\r
19 void                    AddInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, CFX_ByteString& csNameTag);\r
20 CPDF_Font*              AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);\r
21 CPDF_Font*              AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);\r
22 void                    RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont);\r
23 void                    RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag);\r
24 CPDF_Font*              GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument);\r
25 void                    SetDefaultInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont);\r
26 void                    SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray);\r
27 FX_BOOL                 NeedPDFEncodeForFieldFullName(const CFX_WideString& csFieldName);\r
28 FX_BOOL                 NeedPDFEncodeForFieldTree(CPDF_Dictionary* pFieldDict, int nLevel = 0);\r
29 void                    EncodeFieldName(const CFX_WideString& csName, CFX_ByteString& csT);\r
30 void                    UpdateEncodeFieldName(CPDF_Dictionary* pFieldDict, int nLevel = 0);\r
31 CFX_WideString GetFullName(CPDF_Dictionary* pFieldDict)\r
32 {\r
33     CFX_WideString full_name;\r
34     CPDF_Dictionary* pLevel = pFieldDict;\r
35     while (pLevel) {\r
36         CFX_WideString short_name = pLevel->GetUnicodeText("T");\r
37         if (short_name != L"") {\r
38             if (full_name == L"") {\r
39                 full_name = short_name;\r
40             } else {\r
41                 full_name = short_name + L"." + full_name;\r
42             }\r
43         }\r
44         pLevel = pLevel->GetDict("Parent");\r
45     }\r
46     return full_name;\r
47 }\r
48 FX_BOOL CPDF_DefaultAppearance::HasFont()\r
49 {\r
50     if (m_csDA.IsEmpty()) {\r
51         return FALSE;\r
52     }\r
53     CPDF_SimpleParser syntax(m_csDA);\r
54     return syntax.FindTagParam("Tf", 2);\r
55 }\r
56 CFX_ByteString CPDF_DefaultAppearance::GetFontString()\r
57 {\r
58     CFX_ByteString csFont;\r
59     if (m_csDA.IsEmpty()) {\r
60         return csFont;\r
61     }\r
62     CPDF_SimpleParser syntax(m_csDA);\r
63     if (syntax.FindTagParam("Tf", 2)) {\r
64         csFont += (CFX_ByteString)syntax.GetWord();\r
65         csFont += " ";\r
66         csFont += (CFX_ByteString)syntax.GetWord();\r
67         csFont += " ";\r
68         csFont += (CFX_ByteString)syntax.GetWord();\r
69     }\r
70     return csFont;\r
71 }\r
72 void CPDF_DefaultAppearance::GetFont(CFX_ByteString& csFontNameTag, FX_FLOAT& fFontSize)\r
73 {\r
74     csFontNameTag = "";\r
75     fFontSize = 0;\r
76     if (m_csDA.IsEmpty()) {\r
77         return;\r
78     }\r
79     CPDF_SimpleParser syntax(m_csDA);\r
80     if (syntax.FindTagParam("Tf", 2)) {\r
81         csFontNameTag = (CFX_ByteString)syntax.GetWord();\r
82         csFontNameTag.Delete(0, 1);\r
83         fFontSize = FX_atof((CFX_ByteString)syntax.GetWord());\r
84     }\r
85     csFontNameTag = PDF_NameDecode(csFontNameTag);\r
86 }\r
87 FX_BOOL CPDF_DefaultAppearance::HasColor(FX_BOOL bStrokingOperation)\r
88 {\r
89     if (m_csDA.IsEmpty()) {\r
90         return FALSE;\r
91     }\r
92     CPDF_SimpleParser syntax(m_csDA);\r
93     if (syntax.FindTagParam(bStrokingOperation ? "G" : "g", 1)) {\r
94         return TRUE;\r
95     }\r
96     syntax.SetPos(0);\r
97     if (syntax.FindTagParam(bStrokingOperation ? "RG" : "rg", 3)) {\r
98         return TRUE;\r
99     }\r
100     syntax.SetPos(0);\r
101     return syntax.FindTagParam(bStrokingOperation ? "K" : "k", 4);\r
102 }\r
103 CFX_ByteString CPDF_DefaultAppearance::GetColorString(FX_BOOL bStrokingOperation)\r
104 {\r
105     CFX_ByteString csColor;\r
106     if (m_csDA.IsEmpty()) {\r
107         return csColor;\r
108     }\r
109     CPDF_SimpleParser syntax(m_csDA);\r
110     if (syntax.FindTagParam(bStrokingOperation ? "G" : "g", 1)) {\r
111         csColor += (CFX_ByteString)syntax.GetWord();\r
112         csColor += " ";\r
113         csColor += (CFX_ByteString)syntax.GetWord();\r
114         return csColor;\r
115     }\r
116     syntax.SetPos(0);\r
117     if (syntax.FindTagParam(bStrokingOperation ? "RG" : "rg", 3)) {\r
118         csColor += (CFX_ByteString)syntax.GetWord();\r
119         csColor += " ";\r
120         csColor += (CFX_ByteString)syntax.GetWord();\r
121         csColor += " ";\r
122         csColor += (CFX_ByteString)syntax.GetWord();\r
123         csColor += " ";\r
124         csColor += (CFX_ByteString)syntax.GetWord();\r
125         return csColor;\r
126     }\r
127     syntax.SetPos(0);\r
128     if (syntax.FindTagParam(bStrokingOperation ? "K" : "k", 4)) {\r
129         csColor += (CFX_ByteString)syntax.GetWord();\r
130         csColor += " ";\r
131         csColor += (CFX_ByteString)syntax.GetWord();\r
132         csColor += " ";\r
133         csColor += (CFX_ByteString)syntax.GetWord();\r
134         csColor += " ";\r
135         csColor += (CFX_ByteString)syntax.GetWord();\r
136         csColor += " ";\r
137         csColor += (CFX_ByteString)syntax.GetWord();\r
138     }\r
139     return csColor;\r
140 }\r
141 void CPDF_DefaultAppearance::GetColor(int& iColorType, FX_FLOAT fc[4], FX_BOOL bStrokingOperation)\r
142 {\r
143     iColorType = COLORTYPE_TRANSPARENT;\r
144     for (int c = 0; c < 4; c ++) {\r
145         fc[c] = 0;\r
146     }\r
147     if (m_csDA.IsEmpty()) {\r
148         return;\r
149     }\r
150     CPDF_SimpleParser syntax(m_csDA);\r
151     if (syntax.FindTagParam(bStrokingOperation ? "G" : "g", 1)) {\r
152         iColorType = COLORTYPE_GRAY;\r
153         fc[0] = FX_atof((CFX_ByteString)syntax.GetWord());\r
154         return;\r
155     }\r
156     syntax.SetPos(0);\r
157     if (syntax.FindTagParam(bStrokingOperation ? "RG" : "rg", 3)) {\r
158         iColorType = COLORTYPE_RGB;\r
159         fc[0] = FX_atof((CFX_ByteString)syntax.GetWord());\r
160         fc[1] = FX_atof((CFX_ByteString)syntax.GetWord());\r
161         fc[2] = FX_atof((CFX_ByteString)syntax.GetWord());\r
162         return;\r
163     }\r
164     syntax.SetPos(0);\r
165     if (syntax.FindTagParam(bStrokingOperation ? "K" : "k", 4)) {\r
166         iColorType = COLORTYPE_CMYK;\r
167         fc[0] = FX_atof((CFX_ByteString)syntax.GetWord());\r
168         fc[1] = FX_atof((CFX_ByteString)syntax.GetWord());\r
169         fc[2] = FX_atof((CFX_ByteString)syntax.GetWord());\r
170         fc[3] = FX_atof((CFX_ByteString)syntax.GetWord());\r
171     }\r
172 }\r
173 void CPDF_DefaultAppearance::GetColor(FX_ARGB& color, int& iColorType, FX_BOOL bStrokingOperation)\r
174 {\r
175     color = 0;\r
176     iColorType = COLORTYPE_TRANSPARENT;\r
177     if (m_csDA.IsEmpty()) {\r
178         return;\r
179     }\r
180     CPDF_SimpleParser syntax(m_csDA);\r
181     if (syntax.FindTagParam(bStrokingOperation ? "G" : "g", 1)) {\r
182         iColorType = COLORTYPE_GRAY;\r
183         FX_FLOAT g = FX_atof((CFX_ByteString)syntax.GetWord()) * 255 + 0.5f;\r
184         color = ArgbEncode(255, (int)g, (int)g, (int)g);\r
185         return;\r
186     }\r
187     syntax.SetPos(0);\r
188     if (syntax.FindTagParam(bStrokingOperation ? "RG" : "rg", 3)) {\r
189         iColorType = COLORTYPE_RGB;\r
190         FX_FLOAT r = FX_atof((CFX_ByteString)syntax.GetWord()) * 255 + 0.5f;\r
191         FX_FLOAT g = FX_atof((CFX_ByteString)syntax.GetWord()) * 255 + 0.5f;\r
192         FX_FLOAT b = FX_atof((CFX_ByteString)syntax.GetWord()) * 255 + 0.5f;\r
193         color = ArgbEncode(255, (int)r, (int)g, (int)b);\r
194         return;\r
195     }\r
196     syntax.SetPos(0);\r
197     if (syntax.FindTagParam(bStrokingOperation ? "K" : "k", 4)) {\r
198         iColorType = COLORTYPE_CMYK;\r
199         FX_FLOAT c = FX_atof((CFX_ByteString)syntax.GetWord());\r
200         FX_FLOAT m = FX_atof((CFX_ByteString)syntax.GetWord());\r
201         FX_FLOAT y = FX_atof((CFX_ByteString)syntax.GetWord());\r
202         FX_FLOAT k = FX_atof((CFX_ByteString)syntax.GetWord());\r
203         FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k);\r
204         FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k);\r
205         FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k);\r
206         color = ArgbEncode(255, (int)(r * 255 + 0.5f), (int)(g * 255 + 0.5f), (int)(b * 255 + 0.5f));\r
207     }\r
208 }\r
209 FX_BOOL CPDF_DefaultAppearance::HasTextMatrix()\r
210 {\r
211     if (m_csDA.IsEmpty()) {\r
212         return FALSE;\r
213     }\r
214     CPDF_SimpleParser syntax(m_csDA);\r
215     return syntax.FindTagParam("Tm", 6);\r
216 }\r
217 CFX_ByteString CPDF_DefaultAppearance::GetTextMatrixString()\r
218 {\r
219     CFX_ByteString csTM;\r
220     if (m_csDA.IsEmpty()) {\r
221         return csTM;\r
222     }\r
223     CPDF_SimpleParser syntax(m_csDA);\r
224     if (syntax.FindTagParam("Tm", 6)) {\r
225         for (int i = 0; i < 6; i ++) {\r
226             csTM += (CFX_ByteString)syntax.GetWord();\r
227             csTM += " ";\r
228         }\r
229         csTM += (CFX_ByteString)syntax.GetWord();\r
230     }\r
231     return csTM;\r
232 }\r
233 CFX_AffineMatrix CPDF_DefaultAppearance::GetTextMatrix()\r
234 {\r
235     CFX_AffineMatrix tm;\r
236     if (m_csDA.IsEmpty()) {\r
237         return tm;\r
238     }\r
239     CPDF_SimpleParser syntax(m_csDA);\r
240     if (syntax.FindTagParam("Tm", 6)) {\r
241         FX_FLOAT f[6];\r
242         for (int i = 0; i < 6; i ++) {\r
243             f[i] = FX_atof((CFX_ByteString)syntax.GetWord());\r
244         }\r
245         tm.Set(f[0], f[1], f[2], f[3], f[4], f[5]);\r
246     }\r
247     return tm;\r
248 }\r
249 void InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument)\r
250 {\r
251     if (pDocument == NULL) {\r
252         return;\r
253     }\r
254     if (pFormDict == NULL) {\r
255         pFormDict = CPDF_Dictionary::Create();\r
256         if (pFormDict == NULL) {\r
257             return;\r
258         }\r
259         FX_DWORD dwObjNum = pDocument->AddIndirectObject(pFormDict);\r
260         CPDF_Dictionary* pRoot = pDocument->GetRoot();\r
261         pRoot->SetAtReference("AcroForm", pDocument, dwObjNum);\r
262     }\r
263     CFX_ByteString csDA;\r
264     if (!pFormDict->KeyExist("DR")) {\r
265         CPDF_Font* pFont = NULL;\r
266         CFX_ByteString csBaseName, csDefault;\r
267         FX_BYTE charSet = CPDF_InterForm::GetNativeCharSet();\r
268         pFont = CPDF_InterForm::AddStandardFont(pDocument, "Helvetica");\r
269         if (pFont != NULL) {\r
270             AddInterFormFont(pFormDict, pDocument, pFont, csBaseName);\r
271             csDefault = csBaseName;\r
272         }\r
273         if (charSet != 0) {\r
274             CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, NULL);\r
275             if (pFont == NULL || csFontName != "Helvetica") {\r
276                 pFont = CPDF_InterForm::AddNativeFont(pDocument);\r
277                 if (pFont != NULL) {\r
278                     csBaseName = "";\r
279                     AddInterFormFont(pFormDict, pDocument, pFont, csBaseName);\r
280                     csDefault = csBaseName;\r
281                 }\r
282             }\r
283         }\r
284         if (pFont != NULL) {\r
285             csDA = "/" + PDF_NameEncode(csDefault) + " 0 Tf";\r
286         }\r
287     }\r
288     if (!csDA.IsEmpty()) {\r
289         csDA += " ";\r
290     }\r
291     csDA += "0 g";\r
292     if (!pFormDict->KeyExist("DA")) {\r
293         pFormDict->SetAtString("DA", csDA);\r
294     }\r
295 }\r
296 FX_DWORD CountInterFormFonts(CPDF_Dictionary* pFormDict)\r
297 {\r
298     if (pFormDict == NULL) {\r
299         return 0;\r
300     }\r
301     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
302     if (pDR == NULL) {\r
303         return 0;\r
304     }\r
305     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
306     if (pFonts == NULL) {\r
307         return 0;\r
308     }\r
309     FX_DWORD dwCount = 0;\r
310     FX_POSITION pos = pFonts->GetStartPos();\r
311     while (pos) {\r
312         CPDF_Object* pObj = NULL;\r
313         CFX_ByteString csKey;\r
314         pObj = pFonts->GetNextElement(pos, csKey);\r
315         if (pObj == NULL) {\r
316             continue;\r
317         }\r
318         CPDF_Object* pDirect = pObj->GetDirect();\r
319         if (pDirect != NULL && pDirect->GetType() == PDFOBJ_DICTIONARY) {\r
320             if (((CPDF_Dictionary*)pDirect)->GetString("Type") == "Font") {\r
321                 dwCount ++;\r
322             }\r
323         }\r
324     }\r
325     return dwCount;\r
326 }\r
327 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_DWORD index, CFX_ByteString& csNameTag)\r
328 {\r
329     if (pFormDict == NULL) {\r
330         return NULL;\r
331     }\r
332     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
333     if (pDR == NULL) {\r
334         return NULL;\r
335     }\r
336     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
337     if (pFonts == NULL) {\r
338         return NULL;\r
339     }\r
340     FX_DWORD dwCount = 0;\r
341     FX_POSITION pos = pFonts->GetStartPos();\r
342     while (pos) {\r
343         CPDF_Object* pObj = NULL;\r
344         CFX_ByteString csKey;\r
345         pObj = pFonts->GetNextElement(pos, csKey);\r
346         if (pObj == NULL) {\r
347             continue;\r
348         }\r
349         CPDF_Object* pDirect = pObj->GetDirect();\r
350         if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {\r
351             continue;\r
352         }\r
353         CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;\r
354         if (pElement->GetString("Type") != "Font") {\r
355             continue;\r
356         }\r
357         if (dwCount == index) {\r
358             csNameTag = csKey;\r
359             return pDocument->LoadFont(pElement);\r
360         }\r
361         dwCount ++;\r
362     }\r
363     return NULL;\r
364 }\r
365 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csNameTag)\r
366 {\r
367     CFX_ByteString csAlias = PDF_NameDecode(csNameTag);\r
368     if (pFormDict == NULL || csAlias.IsEmpty()) {\r
369         return NULL;\r
370     }\r
371     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
372     if (pDR == NULL) {\r
373         return NULL;\r
374     }\r
375     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
376     if (pFonts == NULL) {\r
377         return NULL;\r
378     }\r
379     CPDF_Dictionary* pElement = pFonts->GetDict(csAlias);\r
380     if (pElement == NULL) {\r
381         return NULL;\r
382     }\r
383     if (pElement->GetString("Type") == "Font") {\r
384         return pDocument->LoadFont(pElement);\r
385     }\r
386     return NULL;\r
387 }\r
388 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CFX_ByteString& csNameTag)\r
389 {\r
390     if (pFormDict == NULL || csFontName.IsEmpty()) {\r
391         return NULL;\r
392     }\r
393     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
394     if (pDR == NULL) {\r
395         return NULL;\r
396     }\r
397     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
398     if (pFonts == NULL) {\r
399         return NULL;\r
400     }\r
401     FX_POSITION pos = pFonts->GetStartPos();\r
402     while (pos) {\r
403         CPDF_Object* pObj = NULL;\r
404         CFX_ByteString csKey;\r
405         pObj = pFonts->GetNextElement(pos, csKey);\r
406         if (pObj == NULL) {\r
407             continue;\r
408         }\r
409         CPDF_Object* pDirect = pObj->GetDirect();\r
410         if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {\r
411             continue;\r
412         }\r
413         CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;\r
414         if (pElement->GetString("Type") != "Font") {\r
415             continue;\r
416         }\r
417         CPDF_Font* pFind = pDocument->LoadFont(pElement);\r
418         if (pFind == NULL) {\r
419             continue;\r
420         }\r
421         CFX_ByteString csBaseFont;\r
422         csBaseFont = pFind->GetBaseFont();\r
423         csBaseFont.Remove(' ');\r
424         if (csBaseFont == csFontName) {\r
425             csNameTag = csKey;\r
426             return pFind;\r
427         }\r
428     }\r
429     return NULL;\r
430 }\r
431 CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag)\r
432 {\r
433     if (pFormDict == NULL) {\r
434         return NULL;\r
435     }\r
436     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
437     if (pDR == NULL) {\r
438         return NULL;\r
439     }\r
440     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
441     if (pFonts == NULL) {\r
442         return NULL;\r
443     }\r
444     FX_POSITION pos = pFonts->GetStartPos();\r
445     while (pos) {\r
446         CPDF_Object* pObj = NULL;\r
447         CFX_ByteString csKey;\r
448         pObj = pFonts->GetNextElement(pos, csKey);\r
449         if (pObj == NULL) {\r
450             continue;\r
451         }\r
452         CPDF_Object* pDirect = pObj->GetDirect();\r
453         if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {\r
454             continue;\r
455         }\r
456         CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;\r
457         if (pElement->GetString("Type") != "Font") {\r
458             continue;\r
459         }\r
460         CPDF_Font* pFind = pDocument->LoadFont(pElement);\r
461         if (pFind == NULL) {\r
462             continue;\r
463         }\r
464         CFX_SubstFont* pSubst = (CFX_SubstFont*)pFind->GetSubstFont();\r
465         if (pSubst == NULL) {\r
466             continue;\r
467         }\r
468         if (pSubst->m_Charset == (int)charSet) {\r
469             csNameTag = csKey;\r
470             return pFind;\r
471         }\r
472     }\r
473     return NULL;\r
474 }\r
475 CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag)\r
476 {\r
477     csNameTag = "";\r
478     FX_BYTE charSet = CPDF_InterForm::GetNativeCharSet();\r
479     CFX_SubstFont* pSubst;\r
480     CPDF_Font* pFont = GetDefaultInterFormFont(pFormDict, pDocument);\r
481     if (pFont != NULL) {\r
482         pSubst = (CFX_SubstFont*)pFont->GetSubstFont();\r
483         if (pSubst != NULL && pSubst->m_Charset == (int)charSet) {\r
484             FindInterFormFont(pFormDict, pFont, csNameTag);\r
485             return pFont;\r
486         }\r
487     }\r
488     return GetNativeInterFormFont(pFormDict, pDocument, charSet, csNameTag);\r
489 }\r
490 FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont, CFX_ByteString& csNameTag)\r
491 {\r
492     if (pFormDict == NULL || pFont == NULL) {\r
493         return FALSE;\r
494     }\r
495     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
496     if (pDR == NULL) {\r
497         return FALSE;\r
498     }\r
499     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
500     if (pFonts == NULL) {\r
501         return FALSE;\r
502     }\r
503     FX_POSITION pos = pFonts->GetStartPos();\r
504     while (pos) {\r
505         CPDF_Object* pObj = NULL;\r
506         CFX_ByteString csKey;\r
507         pObj = pFonts->GetNextElement(pos, csKey);\r
508         if (pObj == NULL) {\r
509             continue;\r
510         }\r
511         CPDF_Object* pDirect = pObj->GetDirect();\r
512         if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {\r
513             continue;\r
514         }\r
515         CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;\r
516         if (pElement->GetString("Type") != "Font") {\r
517             continue;\r
518         }\r
519         if (pFont->GetFontDict() == pElement) {\r
520             csNameTag = csKey;\r
521             return TRUE;\r
522         }\r
523     }\r
524     return FALSE;\r
525 }\r
526 FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag)\r
527 {\r
528     if (pFormDict == NULL) {\r
529         return FALSE;\r
530     }\r
531     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
532     if (pDR == NULL) {\r
533         return FALSE;\r
534     }\r
535     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
536     if (pFonts == NULL) {\r
537         return FALSE;\r
538     }\r
539     if (csFontName.GetLength() > 0) {\r
540         csFontName.Remove(' ');\r
541     }\r
542     FX_POSITION pos = pFonts->GetStartPos();\r
543     while (pos) {\r
544         CPDF_Object* pObj = NULL;\r
545         CFX_ByteString csKey, csTmp;\r
546         pObj = pFonts->GetNextElement(pos, csKey);\r
547         if (pObj == NULL) {\r
548             continue;\r
549         }\r
550         CPDF_Object* pDirect = pObj->GetDirect();\r
551         if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {\r
552             continue;\r
553         }\r
554         CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;\r
555         if (pElement->GetString("Type") != "Font") {\r
556             continue;\r
557         }\r
558         pFont = pDocument->LoadFont(pElement);\r
559         if (pFont == NULL) {\r
560             continue;\r
561         }\r
562         CFX_ByteString csBaseFont;\r
563         csBaseFont = pFont->GetBaseFont();\r
564         csBaseFont.Remove(' ');\r
565         if (csBaseFont == csFontName) {\r
566             csNameTag = csKey;\r
567             return TRUE;\r
568         }\r
569     }\r
570     return FALSE;\r
571 }\r
572 void AddInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, CFX_ByteString& csNameTag)\r
573 {\r
574     if (pFont == NULL) {\r
575         return;\r
576     }\r
577     if (pFormDict == NULL) {\r
578         InitInterFormDict(pFormDict, pDocument);\r
579     }\r
580     CFX_ByteString csTag;\r
581     if (FindInterFormFont(pFormDict, pFont, csTag)) {\r
582         csNameTag = csTag;\r
583         return;\r
584     }\r
585     if (pFormDict == NULL) {\r
586         InitInterFormDict(pFormDict, pDocument);\r
587     }\r
588     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
589     if (pDR == NULL) {\r
590         pDR = CPDF_Dictionary::Create();\r
591         if (pDR == NULL) {\r
592             return;\r
593         }\r
594         pFormDict->SetAt("DR", pDR);\r
595     }\r
596     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
597     if (pFonts == NULL) {\r
598         pFonts = CPDF_Dictionary::Create();\r
599         pDR->SetAt("Font", pFonts);\r
600     }\r
601     if (csNameTag.IsEmpty()) {\r
602         csNameTag = pFont->GetBaseFont();\r
603     }\r
604     csNameTag.Remove(' ');\r
605     csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, csNameTag);\r
606     pFonts->SetAtReference(csNameTag, pDocument, pFont->GetFontDict());\r
607 }\r
608 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag)\r
609 {\r
610     if (pFormDict == NULL) {\r
611         InitInterFormDict(pFormDict, pDocument);\r
612     }\r
613     CFX_ByteString csTemp;\r
614     CPDF_Font* pFont = GetNativeInterFormFont(pFormDict, pDocument, charSet, csTemp);\r
615     if (pFont != NULL) {\r
616         csNameTag = csTemp;\r
617         return pFont;\r
618     }\r
619     CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet);\r
620     if (!csFontName.IsEmpty()) {\r
621         if (FindInterFormFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) {\r
622             return pFont;\r
623         }\r
624     }\r
625     pFont = CPDF_InterForm::AddNativeFont(charSet, pDocument);\r
626     if (pFont != NULL) {\r
627         AddInterFormFont(pFormDict, pDocument, pFont, csNameTag);\r
628     }\r
629     return pFont;\r
630 }\r
631 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag)\r
632 {\r
633     FX_BYTE charSet = CPDF_InterForm::GetNativeCharSet();\r
634     return AddNativeInterFormFont(pFormDict, pDocument, charSet, csNameTag);\r
635 }\r
636 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont)\r
637 {\r
638     if (pFormDict == NULL || pFont == NULL) {\r
639         return;\r
640     }\r
641     CFX_ByteString csTag;\r
642     if (!FindInterFormFont(pFormDict, pFont, csTag)) {\r
643         return;\r
644     }\r
645     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
646     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
647     pFonts->RemoveAt(csTag);\r
648 }\r
649 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag)\r
650 {\r
651     if (pFormDict == NULL || csNameTag.IsEmpty()) {\r
652         return;\r
653     }\r
654     CPDF_Dictionary* pDR = pFormDict->GetDict("DR");\r
655     if (pDR == NULL) {\r
656         return;\r
657     }\r
658     CPDF_Dictionary* pFonts = pDR->GetDict("Font");\r
659     if (pFonts == NULL) {\r
660         return;\r
661     }\r
662     pFonts->RemoveAt(csNameTag);\r
663 }\r
664 CPDF_Font* GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument)\r
665 {\r
666     if (pFormDict == NULL) {\r
667         return NULL;\r
668     }\r
669     CPDF_DefaultAppearance cDA = pFormDict->GetString("DA");\r
670     CFX_ByteString csFontNameTag;\r
671     FX_FLOAT fFontSize;\r
672     cDA.GetFont(csFontNameTag, fFontSize);\r
673     return GetInterFormFont(pFormDict, pDocument, csFontNameTag);\r
674 }\r
675 CPDF_IconFit::ScaleMethod CPDF_IconFit::GetScaleMethod()\r
676 {\r
677     if (m_pDict == NULL) {\r
678         return Always;\r
679     }\r
680     CFX_ByteString csSW = m_pDict->GetString("SW", "A");\r
681     if (csSW == "B") {\r
682         return Bigger;\r
683     } else if (csSW == "S") {\r
684         return Smaller;\r
685     } else if (csSW == "N") {\r
686         return Never;\r
687     }\r
688     return Always;\r
689 }\r
690 FX_BOOL CPDF_IconFit::IsProportionalScale()\r
691 {\r
692     if (m_pDict == NULL) {\r
693         return TRUE;\r
694     }\r
695     return m_pDict->GetString("S", "P") != "A";\r
696 }\r
697 void CPDF_IconFit::GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom)\r
698 {\r
699     fLeft = fBottom = 0.5;\r
700     if (m_pDict == NULL) {\r
701         return;\r
702     }\r
703     CPDF_Array* pA = m_pDict->GetArray("A");\r
704     if (pA != NULL) {\r
705         FX_DWORD dwCount = pA->GetCount();\r
706         if (dwCount > 0) {\r
707             fLeft = pA->GetNumber(0);\r
708         }\r
709         if (dwCount > 1) {\r
710             fBottom = pA->GetNumber(1);\r
711         }\r
712     }\r
713 }\r
714 FX_BOOL CPDF_IconFit::GetFittingBounds()\r
715 {\r
716     if (m_pDict == NULL) {\r
717         return FALSE;\r
718     }\r
719     return m_pDict->GetBoolean("FB");\r
720 }\r
721 void SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray)\r
722 {\r
723     int iCount = pField->CountControls();\r
724     for (int i = 0; i < iCount; i ++) {\r
725         CPDF_FormControl* pControl = pField->GetControl(i);\r
726         if (pControl == NULL) {\r
727             continue;\r
728         }\r
729         statusArray.Add(pControl->IsChecked() ? 1 : 0);\r
730     }\r
731 }\r
732 CPDF_Object* FPDF_GetFieldAttr(CPDF_Dictionary* pFieldDict, const FX_CHAR* name, int nLevel)\r
733 {\r
734     if (nLevel > FPDFDOC_UTILS_MAXRECURSION) {\r
735         return NULL;\r
736     }\r
737     if (pFieldDict == NULL) {\r
738         return NULL;\r
739     }\r
740     CPDF_Object* pAttr = pFieldDict->GetElementValue(name);\r
741     if (pAttr) {\r
742         return pAttr;\r
743     }\r
744     CPDF_Dictionary* pParent = pFieldDict->GetDict("Parent");\r
745     if (pParent == NULL) {\r
746         return NULL;\r
747     }\r
748     return FPDF_GetFieldAttr(pParent, name, nLevel + 1);\r
749 }\r