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