Fix warnings in android build, fix font rendering issue, fix issue 357588: wrong...
[pdfium.git] / core / src / fpdfdoc / doc_utils.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/fpdfdoc/fpdf_doc.h"
8 static const int FPDFDOC_UTILS_MAXRECURSION = 32;
9 CFX_WideString  GetFullName(CPDF_Dictionary* pFieldDict);
10 void                    InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument);
11 FX_DWORD                CountInterFormFonts(CPDF_Dictionary* pFormDict);
12 CPDF_Font*              GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_DWORD index, CFX_ByteString& csNameTag);
13 CPDF_Font*              GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csNameTag);
14 CPDF_Font*              GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CFX_ByteString& csNameTag);
15 CPDF_Font*              GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);
16 CPDF_Font*              GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
17 FX_BOOL                 FindInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont, CFX_ByteString& csNameTag);
18 FX_BOOL                 FindInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag);
19 void                    AddInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, CFX_ByteString& csNameTag);
20 CPDF_Font*              AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);
21 CPDF_Font*              AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
22 void                    RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont);
23 void                    RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag);
24 CPDF_Font*              GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument);
25 void                    SetDefaultInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont);
26 void                    SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray);
27 FX_BOOL                 NeedPDFEncodeForFieldFullName(const CFX_WideString& csFieldName);
28 FX_BOOL                 NeedPDFEncodeForFieldTree(CPDF_Dictionary* pFieldDict, int nLevel = 0);
29 void                    EncodeFieldName(const CFX_WideString& csName, CFX_ByteString& csT);
30 void                    UpdateEncodeFieldName(CPDF_Dictionary* pFieldDict, int nLevel = 0);
31 CFX_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 }
48 FX_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 }
56 CFX_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 }
72 void 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 }
87 FX_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 }
103 CFX_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 }
141 void 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 }
173 void 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 }
209 FX_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 }
217 CFX_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 }
233 CFX_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 }
249 void 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 }
296 FX_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 }
327 CPDF_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 }
365 CPDF_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 }
388 CPDF_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 }
431 CPDF_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 }
475 CPDF_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 }
490 FX_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 }
526 FX_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 }
572 void 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 }
608 CPDF_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 }
631 CPDF_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 }
636 void 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 }
649 void 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 }
664 CPDF_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 }
675 CPDF_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 }
690 FX_BOOL CPDF_IconFit::IsProportionalScale()
691 {
692     if (m_pDict == NULL) {
693         return TRUE;
694     }
695     return m_pDict->GetString("S", "P") != "A";
696 }
697 void 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 }
714 FX_BOOL CPDF_IconFit::GetFittingBounds()
715 {
716     if (m_pDict == NULL) {
717         return FALSE;
718     }
719     return m_pDict->GetBoolean("FB");
720 }
721 void 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 }
732 CPDF_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 }