Add new public APIs to find the z-order for links and widgets.
[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     CPDF_Object* pDirect = pObj->GetDirect();
294     if (pDirect != NULL && pDirect->GetType() == PDFOBJ_DICTIONARY) {
295       if (((CPDF_Dictionary*)pDirect)->GetString("Type") == "Font") {
296         dwCount++;
297       }
298     }
299   }
300   return dwCount;
301 }
302 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict,
303                             CPDF_Document* pDocument,
304                             FX_DWORD index,
305                             CFX_ByteString& csNameTag) {
306   if (pFormDict == NULL) {
307     return NULL;
308   }
309   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
310   if (pDR == NULL) {
311     return NULL;
312   }
313   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
314   if (pFonts == NULL) {
315     return NULL;
316   }
317   FX_DWORD dwCount = 0;
318   FX_POSITION pos = pFonts->GetStartPos();
319   while (pos) {
320     CPDF_Object* pObj = NULL;
321     CFX_ByteString csKey;
322     pObj = pFonts->GetNextElement(pos, csKey);
323     if (pObj == NULL) {
324       continue;
325     }
326     CPDF_Object* pDirect = pObj->GetDirect();
327     if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
328       continue;
329     }
330     CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
331     if (pElement->GetString("Type") != "Font") {
332       continue;
333     }
334     if (dwCount == index) {
335       csNameTag = csKey;
336       return pDocument->LoadFont(pElement);
337     }
338     dwCount++;
339   }
340   return NULL;
341 }
342 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict,
343                             CPDF_Document* pDocument,
344                             CFX_ByteString csNameTag) {
345   CFX_ByteString csAlias = PDF_NameDecode(csNameTag);
346   if (pFormDict == NULL || csAlias.IsEmpty()) {
347     return NULL;
348   }
349   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
350   if (pDR == NULL) {
351     return NULL;
352   }
353   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
354   if (pFonts == NULL) {
355     return NULL;
356   }
357   CPDF_Dictionary* pElement = pFonts->GetDict(csAlias);
358   if (pElement == NULL) {
359     return NULL;
360   }
361   if (pElement->GetString("Type") == "Font") {
362     return pDocument->LoadFont(pElement);
363   }
364   return NULL;
365 }
366 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict,
367                             CPDF_Document* pDocument,
368                             CFX_ByteString csFontName,
369                             CFX_ByteString& csNameTag) {
370   if (pFormDict == NULL || csFontName.IsEmpty()) {
371     return NULL;
372   }
373   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
374   if (pDR == NULL) {
375     return NULL;
376   }
377   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
378   if (pFonts == NULL) {
379     return NULL;
380   }
381   FX_POSITION pos = pFonts->GetStartPos();
382   while (pos) {
383     CPDF_Object* pObj = NULL;
384     CFX_ByteString csKey;
385     pObj = pFonts->GetNextElement(pos, csKey);
386     if (pObj == NULL) {
387       continue;
388     }
389     CPDF_Object* pDirect = pObj->GetDirect();
390     if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
391       continue;
392     }
393     CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
394     if (pElement->GetString("Type") != "Font") {
395       continue;
396     }
397     CPDF_Font* pFind = pDocument->LoadFont(pElement);
398     if (pFind == NULL) {
399       continue;
400     }
401     CFX_ByteString csBaseFont;
402     csBaseFont = pFind->GetBaseFont();
403     csBaseFont.Remove(' ');
404     if (csBaseFont == csFontName) {
405       csNameTag = csKey;
406       return pFind;
407     }
408   }
409   return NULL;
410 }
411 CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict,
412                                   CPDF_Document* pDocument,
413                                   uint8_t charSet,
414                                   CFX_ByteString& csNameTag) {
415   if (pFormDict == NULL) {
416     return NULL;
417   }
418   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
419   if (pDR == NULL) {
420     return NULL;
421   }
422   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
423   if (pFonts == NULL) {
424     return NULL;
425   }
426   FX_POSITION pos = pFonts->GetStartPos();
427   while (pos) {
428     CPDF_Object* pObj = NULL;
429     CFX_ByteString csKey;
430     pObj = pFonts->GetNextElement(pos, csKey);
431     if (pObj == NULL) {
432       continue;
433     }
434     CPDF_Object* pDirect = pObj->GetDirect();
435     if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
436       continue;
437     }
438     CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
439     if (pElement->GetString("Type") != "Font") {
440       continue;
441     }
442     CPDF_Font* pFind = pDocument->LoadFont(pElement);
443     if (pFind == NULL) {
444       continue;
445     }
446     CFX_SubstFont* pSubst = (CFX_SubstFont*)pFind->GetSubstFont();
447     if (pSubst == NULL) {
448       continue;
449     }
450     if (pSubst->m_Charset == (int)charSet) {
451       csNameTag = csKey;
452       return pFind;
453     }
454   }
455   return NULL;
456 }
457 CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict,
458                                   CPDF_Document* pDocument,
459                                   CFX_ByteString& csNameTag) {
460   csNameTag = "";
461   uint8_t charSet = CPDF_InterForm::GetNativeCharSet();
462   CFX_SubstFont* pSubst;
463   CPDF_Font* pFont = GetDefaultInterFormFont(pFormDict, pDocument);
464   if (pFont != NULL) {
465     pSubst = (CFX_SubstFont*)pFont->GetSubstFont();
466     if (pSubst != NULL && pSubst->m_Charset == (int)charSet) {
467       FindInterFormFont(pFormDict, pFont, csNameTag);
468       return pFont;
469     }
470   }
471   return GetNativeInterFormFont(pFormDict, pDocument, charSet, csNameTag);
472 }
473 FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict,
474                           const CPDF_Font* pFont,
475                           CFX_ByteString& csNameTag) {
476   if (pFormDict == NULL || pFont == NULL) {
477     return FALSE;
478   }
479   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
480   if (pDR == NULL) {
481     return FALSE;
482   }
483   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
484   if (pFonts == NULL) {
485     return FALSE;
486   }
487   FX_POSITION pos = pFonts->GetStartPos();
488   while (pos) {
489     CPDF_Object* pObj = NULL;
490     CFX_ByteString csKey;
491     pObj = pFonts->GetNextElement(pos, csKey);
492     if (pObj == NULL) {
493       continue;
494     }
495     CPDF_Object* pDirect = pObj->GetDirect();
496     if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
497       continue;
498     }
499     CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
500     if (pElement->GetString("Type") != "Font") {
501       continue;
502     }
503     if (pFont->GetFontDict() == pElement) {
504       csNameTag = csKey;
505       return TRUE;
506     }
507   }
508   return FALSE;
509 }
510 FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict,
511                           CPDF_Document* pDocument,
512                           CFX_ByteString csFontName,
513                           CPDF_Font*& pFont,
514                           CFX_ByteString& csNameTag) {
515   if (pFormDict == NULL) {
516     return FALSE;
517   }
518   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
519   if (pDR == NULL) {
520     return FALSE;
521   }
522   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
523   if (pFonts == NULL) {
524     return FALSE;
525   }
526   if (csFontName.GetLength() > 0) {
527     csFontName.Remove(' ');
528   }
529   FX_POSITION pos = pFonts->GetStartPos();
530   while (pos) {
531     CPDF_Object* pObj = NULL;
532     CFX_ByteString csKey, csTmp;
533     pObj = pFonts->GetNextElement(pos, csKey);
534     if (pObj == NULL) {
535       continue;
536     }
537     CPDF_Object* pDirect = pObj->GetDirect();
538     if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
539       continue;
540     }
541     CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
542     if (pElement->GetString("Type") != "Font") {
543       continue;
544     }
545     pFont = pDocument->LoadFont(pElement);
546     if (pFont == NULL) {
547       continue;
548     }
549     CFX_ByteString csBaseFont;
550     csBaseFont = pFont->GetBaseFont();
551     csBaseFont.Remove(' ');
552     if (csBaseFont == csFontName) {
553       csNameTag = csKey;
554       return TRUE;
555     }
556   }
557   return FALSE;
558 }
559 void AddInterFormFont(CPDF_Dictionary*& pFormDict,
560                       CPDF_Document* pDocument,
561                       const CPDF_Font* pFont,
562                       CFX_ByteString& csNameTag) {
563   if (pFont == NULL) {
564     return;
565   }
566   if (pFormDict == NULL) {
567     InitInterFormDict(pFormDict, pDocument);
568   }
569   CFX_ByteString csTag;
570   if (FindInterFormFont(pFormDict, pFont, csTag)) {
571     csNameTag = csTag;
572     return;
573   }
574   if (pFormDict == NULL) {
575     InitInterFormDict(pFormDict, pDocument);
576   }
577   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
578   if (pDR == NULL) {
579     pDR = CPDF_Dictionary::Create();
580     if (pDR == NULL) {
581       return;
582     }
583     pFormDict->SetAt("DR", pDR);
584   }
585   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
586   if (pFonts == NULL) {
587     pFonts = CPDF_Dictionary::Create();
588     pDR->SetAt("Font", pFonts);
589   }
590   if (csNameTag.IsEmpty()) {
591     csNameTag = pFont->GetBaseFont();
592   }
593   csNameTag.Remove(' ');
594   csNameTag =
595       CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, csNameTag);
596   pFonts->SetAtReference(csNameTag, pDocument, pFont->GetFontDict());
597 }
598 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict,
599                                   CPDF_Document* pDocument,
600                                   uint8_t charSet,
601                                   CFX_ByteString& csNameTag) {
602   if (pFormDict == NULL) {
603     InitInterFormDict(pFormDict, pDocument);
604   }
605   CFX_ByteString csTemp;
606   CPDF_Font* pFont =
607       GetNativeInterFormFont(pFormDict, pDocument, charSet, csTemp);
608   if (pFont != NULL) {
609     csNameTag = csTemp;
610     return pFont;
611   }
612   CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet);
613   if (!csFontName.IsEmpty()) {
614     if (FindInterFormFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) {
615       return pFont;
616     }
617   }
618   pFont = CPDF_InterForm::AddNativeFont(charSet, pDocument);
619   if (pFont != NULL) {
620     AddInterFormFont(pFormDict, pDocument, pFont, csNameTag);
621   }
622   return pFont;
623 }
624 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict,
625                                   CPDF_Document* pDocument,
626                                   CFX_ByteString& csNameTag) {
627   uint8_t charSet = CPDF_InterForm::GetNativeCharSet();
628   return AddNativeInterFormFont(pFormDict, pDocument, charSet, csNameTag);
629 }
630 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont) {
631   if (pFormDict == NULL || pFont == NULL) {
632     return;
633   }
634   CFX_ByteString csTag;
635   if (!FindInterFormFont(pFormDict, pFont, csTag)) {
636     return;
637   }
638   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
639   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
640   pFonts->RemoveAt(csTag);
641 }
642 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag) {
643   if (pFormDict == NULL || csNameTag.IsEmpty()) {
644     return;
645   }
646   CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
647   if (pDR == NULL) {
648     return;
649   }
650   CPDF_Dictionary* pFonts = pDR->GetDict("Font");
651   if (pFonts == NULL) {
652     return;
653   }
654   pFonts->RemoveAt(csNameTag);
655 }
656 CPDF_Font* GetDefaultInterFormFont(CPDF_Dictionary* pFormDict,
657                                    CPDF_Document* pDocument) {
658   if (pFormDict == NULL) {
659     return NULL;
660   }
661   CPDF_DefaultAppearance cDA = pFormDict->GetString("DA");
662   CFX_ByteString csFontNameTag;
663   FX_FLOAT fFontSize;
664   cDA.GetFont(csFontNameTag, fFontSize);
665   return GetInterFormFont(pFormDict, pDocument, csFontNameTag);
666 }
667 CPDF_IconFit::ScaleMethod CPDF_IconFit::GetScaleMethod() {
668   if (!m_pDict) {
669     return Always;
670   }
671   CFX_ByteString csSW = m_pDict->GetString("SW", "A");
672   if (csSW == "B") {
673     return Bigger;
674   }
675   if (csSW == "S") {
676     return Smaller;
677   }
678   if (csSW == "N") {
679     return Never;
680   }
681   return Always;
682 }
683 FX_BOOL CPDF_IconFit::IsProportionalScale() {
684   if (m_pDict == NULL) {
685     return TRUE;
686   }
687   return m_pDict->GetString("S", "P") != "A";
688 }
689 void CPDF_IconFit::GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom) {
690   fLeft = fBottom = 0.5;
691   if (m_pDict == NULL) {
692     return;
693   }
694   CPDF_Array* pA = m_pDict->GetArray("A");
695   if (pA != NULL) {
696     FX_DWORD dwCount = pA->GetCount();
697     if (dwCount > 0) {
698       fLeft = pA->GetNumber(0);
699     }
700     if (dwCount > 1) {
701       fBottom = pA->GetNumber(1);
702     }
703   }
704 }
705 FX_BOOL CPDF_IconFit::GetFittingBounds() {
706   if (m_pDict == NULL) {
707     return FALSE;
708   }
709   return m_pDict->GetBoolean("FB");
710 }
711 void SaveCheckedFieldStatus(CPDF_FormField* pField,
712                             CFX_ByteArray& statusArray) {
713   int iCount = pField->CountControls();
714   for (int i = 0; i < iCount; i++) {
715     CPDF_FormControl* pControl = pField->GetControl(i);
716     if (pControl == NULL) {
717       continue;
718     }
719     statusArray.Add(pControl->IsChecked() ? 1 : 0);
720   }
721 }
722 CPDF_Object* FPDF_GetFieldAttr(CPDF_Dictionary* pFieldDict,
723                                const FX_CHAR* name,
724                                int nLevel) {
725   if (nLevel > FPDFDOC_UTILS_MAXRECURSION) {
726     return NULL;
727   }
728   if (pFieldDict == NULL) {
729     return NULL;
730   }
731   CPDF_Object* pAttr = pFieldDict->GetElementValue(name);
732   if (pAttr) {
733     return pAttr;
734   }
735   CPDF_Dictionary* pParent = pFieldDict->GetDict("Parent");
736   if (pParent == NULL) {
737     return NULL;
738   }
739   return FPDF_GetFieldAttr(pParent, name, nLevel + 1);
740 }