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