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