Home | History | Annotate | Download | only in fpdfdoc
      1 // Copyright 2016 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 "core/fpdfdoc/cpdf_interform.h"
      8 
      9 #include <utility>
     10 #include <vector>
     11 
     12 #include "core/fpdfapi/font/cpdf_font.h"
     13 #include "core/fpdfapi/font/cpdf_fontencoding.h"
     14 #include "core/fpdfapi/page/cpdf_page.h"
     15 #include "core/fpdfapi/parser/cfdf_document.h"
     16 #include "core/fpdfapi/parser/cpdf_array.h"
     17 #include "core/fpdfapi/parser/cpdf_document.h"
     18 #include "core/fpdfapi/parser/cpdf_name.h"
     19 #include "core/fpdfapi/parser/cpdf_reference.h"
     20 #include "core/fpdfapi/parser/cpdf_string.h"
     21 #include "core/fpdfdoc/cpdf_filespec.h"
     22 #include "core/fpdfdoc/cpdf_formcontrol.h"
     23 #include "core/fxge/cfx_substfont.h"
     24 #include "core/fxge/fx_font.h"
     25 #include "third_party/base/stl_util.h"
     26 
     27 namespace {
     28 
     29 const int nMaxRecursion = 32;
     30 
     31 const struct SupportFieldEncoding {
     32   const FX_CHAR* m_name;
     33   uint16_t m_codePage;
     34 } g_fieldEncoding[] = {
     35     {"BigFive", 950},
     36     {"GBK", 936},
     37     {"Shift-JIS", 932},
     38     {"UHC", 949},
     39 };
     40 
     41 CFX_WideString GetFieldValue(const CPDF_Dictionary& pFieldDict,
     42                              const CFX_ByteString& bsEncoding) {
     43   const CFX_ByteString csBValue = pFieldDict.GetStringFor("V");
     44   for (const auto& encoding : g_fieldEncoding) {
     45     if (bsEncoding == encoding.m_name)
     46       return CFX_WideString::FromCodePage(csBValue.AsStringC(),
     47                                           encoding.m_codePage);
     48   }
     49   CFX_ByteString csTemp = csBValue.Left(2);
     50   if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF")
     51     return PDF_DecodeText(csBValue);
     52   return CFX_WideString::FromLocal(csBValue.AsStringC());
     53 }
     54 
     55 void AddFont(CPDF_Dictionary*& pFormDict,
     56              CPDF_Document* pDocument,
     57              const CPDF_Font* pFont,
     58              CFX_ByteString& csNameTag);
     59 
     60 void InitDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) {
     61   if (!pDocument)
     62     return;
     63 
     64   if (!pFormDict) {
     65     pFormDict = pDocument->NewIndirect<CPDF_Dictionary>();
     66     pDocument->GetRoot()->SetNewFor<CPDF_Reference>("AcroForm", pDocument,
     67                                                     pFormDict->GetObjNum());
     68   }
     69 
     70   CFX_ByteString csDA;
     71   if (!pFormDict->KeyExist("DR")) {
     72     CFX_ByteString csBaseName;
     73     CFX_ByteString csDefault;
     74     uint8_t charSet = CPDF_InterForm::GetNativeCharSet();
     75     CPDF_Font* pFont = CPDF_InterForm::AddStandardFont(pDocument, "Helvetica");
     76     if (pFont) {
     77       AddFont(pFormDict, pDocument, pFont, csBaseName);
     78       csDefault = csBaseName;
     79     }
     80     if (charSet != FXFONT_ANSI_CHARSET) {
     81       CFX_ByteString csFontName =
     82           CPDF_InterForm::GetNativeFont(charSet, nullptr);
     83       if (!pFont || csFontName != "Helvetica") {
     84         pFont = CPDF_InterForm::AddNativeFont(pDocument);
     85         if (pFont) {
     86           csBaseName = "";
     87           AddFont(pFormDict, pDocument, pFont, csBaseName);
     88           csDefault = csBaseName;
     89         }
     90       }
     91     }
     92     if (pFont)
     93       csDA = "/" + PDF_NameEncode(csDefault) + " 0 Tf";
     94   }
     95   if (!csDA.IsEmpty())
     96     csDA += " ";
     97 
     98   csDA += "0 g";
     99   if (!pFormDict->KeyExist("DA"))
    100     pFormDict->SetNewFor<CPDF_String>("DA", csDA, false);
    101 }
    102 
    103 CPDF_Font* GetFont(CPDF_Dictionary* pFormDict,
    104                    CPDF_Document* pDocument,
    105                    CFX_ByteString csNameTag) {
    106   CFX_ByteString csAlias = PDF_NameDecode(csNameTag);
    107   if (!pFormDict || csAlias.IsEmpty())
    108     return nullptr;
    109 
    110   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
    111   if (!pDR)
    112     return nullptr;
    113 
    114   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
    115   if (!pFonts)
    116     return nullptr;
    117 
    118   CPDF_Dictionary* pElement = pFonts->GetDictFor(csAlias);
    119   if (!pElement)
    120     return nullptr;
    121 
    122   if (pElement->GetStringFor("Type") == "Font")
    123     return pDocument->LoadFont(pElement);
    124   return nullptr;
    125 }
    126 
    127 CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict,
    128                          CPDF_Document* pDocument,
    129                          uint8_t charSet,
    130                          CFX_ByteString& csNameTag) {
    131   if (!pFormDict)
    132     return nullptr;
    133 
    134   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
    135   if (!pDR)
    136     return nullptr;
    137 
    138   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
    139   if (!pFonts)
    140     return nullptr;
    141 
    142   for (const auto& it : *pFonts) {
    143     const CFX_ByteString& csKey = it.first;
    144     if (!it.second)
    145       continue;
    146 
    147     CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
    148     if (!pElement)
    149       continue;
    150     if (pElement->GetStringFor("Type") != "Font")
    151       continue;
    152     CPDF_Font* pFind = pDocument->LoadFont(pElement);
    153     if (!pFind)
    154       continue;
    155 
    156     CFX_SubstFont* pSubst = pFind->GetSubstFont();
    157     if (!pSubst)
    158       continue;
    159 
    160     if (pSubst->m_Charset == (int)charSet) {
    161       csNameTag = csKey;
    162       return pFind;
    163     }
    164   }
    165   return nullptr;
    166 }
    167 
    168 bool FindFont(CPDF_Dictionary* pFormDict,
    169               const CPDF_Font* pFont,
    170               CFX_ByteString& csNameTag) {
    171   if (!pFormDict || !pFont)
    172     return false;
    173 
    174   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
    175   if (!pDR)
    176     return false;
    177 
    178   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
    179   if (!pFonts)
    180     return false;
    181 
    182   for (const auto& it : *pFonts) {
    183     const CFX_ByteString& csKey = it.first;
    184     if (!it.second)
    185       continue;
    186     CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
    187     if (!pElement)
    188       continue;
    189     if (pElement->GetStringFor("Type") != "Font")
    190       continue;
    191     if (pFont->GetFontDict() == pElement) {
    192       csNameTag = csKey;
    193       return true;
    194     }
    195   }
    196   return false;
    197 }
    198 
    199 bool FindFont(CPDF_Dictionary* pFormDict,
    200               CPDF_Document* pDocument,
    201               CFX_ByteString csFontName,
    202               CPDF_Font*& pFont,
    203               CFX_ByteString& csNameTag) {
    204   if (!pFormDict)
    205     return false;
    206 
    207   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
    208   if (!pDR)
    209     return false;
    210 
    211   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
    212   if (!pFonts)
    213     return false;
    214   if (csFontName.GetLength() > 0)
    215     csFontName.Remove(' ');
    216 
    217   for (const auto& it : *pFonts) {
    218     const CFX_ByteString& csKey = it.first;
    219     if (!it.second)
    220       continue;
    221 
    222     CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
    223     if (!pElement)
    224       continue;
    225     if (pElement->GetStringFor("Type") != "Font")
    226       continue;
    227     pFont = pDocument->LoadFont(pElement);
    228     if (!pFont)
    229       continue;
    230 
    231     CFX_ByteString csBaseFont;
    232     csBaseFont = pFont->GetBaseFont();
    233     csBaseFont.Remove(' ');
    234     if (csBaseFont == csFontName) {
    235       csNameTag = csKey;
    236       return true;
    237     }
    238   }
    239   return false;
    240 }
    241 
    242 void AddFont(CPDF_Dictionary*& pFormDict,
    243              CPDF_Document* pDocument,
    244              const CPDF_Font* pFont,
    245              CFX_ByteString& csNameTag) {
    246   if (!pFont)
    247     return;
    248   if (!pFormDict)
    249     InitDict(pFormDict, pDocument);
    250 
    251   CFX_ByteString csTag;
    252   if (FindFont(pFormDict, pFont, csTag)) {
    253     csNameTag = csTag;
    254     return;
    255   }
    256   if (!pFormDict)
    257     InitDict(pFormDict, pDocument);
    258 
    259   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
    260   if (!pDR)
    261     pDR = pFormDict->SetNewFor<CPDF_Dictionary>("DR");
    262 
    263   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
    264   if (!pFonts)
    265     pFonts = pDR->SetNewFor<CPDF_Dictionary>("Font");
    266 
    267   if (csNameTag.IsEmpty())
    268     csNameTag = pFont->GetBaseFont();
    269 
    270   csNameTag.Remove(' ');
    271   csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4,
    272                                                       csNameTag.c_str());
    273   pFonts->SetNewFor<CPDF_Reference>(csNameTag, pDocument,
    274                                     pFont->GetFontDict()->GetObjNum());
    275 }
    276 
    277 CPDF_Font* AddNativeFont(CPDF_Dictionary*& pFormDict,
    278                          CPDF_Document* pDocument,
    279                          uint8_t charSet,
    280                          CFX_ByteString& csNameTag) {
    281   if (!pFormDict)
    282     InitDict(pFormDict, pDocument);
    283 
    284   CFX_ByteString csTemp;
    285   CPDF_Font* pFont = GetNativeFont(pFormDict, pDocument, charSet, csTemp);
    286   if (pFont) {
    287     csNameTag = csTemp;
    288     return pFont;
    289   }
    290   CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr);
    291   if (!csFontName.IsEmpty() &&
    292       FindFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) {
    293     return pFont;
    294   }
    295   pFont = CPDF_InterForm::AddNativeFont(charSet, pDocument);
    296   if (pFont)
    297     AddFont(pFormDict, pDocument, pFont, csNameTag);
    298 
    299   return pFont;
    300 }
    301 
    302 class CFieldNameExtractor {
    303  public:
    304   explicit CFieldNameExtractor(const CFX_WideString& full_name)
    305       : m_FullName(full_name) {
    306     m_pCur = m_FullName.c_str();
    307     m_pEnd = m_pCur + m_FullName.GetLength();
    308   }
    309 
    310   void GetNext(const FX_WCHAR*& pSubName, FX_STRSIZE& size) {
    311     pSubName = m_pCur;
    312     while (m_pCur < m_pEnd && m_pCur[0] != L'.')
    313       m_pCur++;
    314 
    315     size = (FX_STRSIZE)(m_pCur - pSubName);
    316     if (m_pCur < m_pEnd && m_pCur[0] == L'.')
    317       m_pCur++;
    318   }
    319 
    320  protected:
    321   CFX_WideString m_FullName;
    322   const FX_WCHAR* m_pCur;
    323   const FX_WCHAR* m_pEnd;
    324 };
    325 
    326 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    327 typedef struct {
    328   bool bFind;
    329   LOGFONTA lf;
    330 } PDF_FONTDATA;
    331 
    332 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe,
    333                                       NEWTEXTMETRICEX* lpntme,
    334                                       DWORD FontType,
    335                                       LPARAM lParam) {
    336   if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@'))
    337     return 1;
    338 
    339   PDF_FONTDATA* pData = (PDF_FONTDATA*)lParam;
    340   memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA));
    341   pData->bFind = true;
    342   return 0;
    343 }
    344 
    345 bool RetrieveSpecificFont(LOGFONTA& lf) {
    346   PDF_FONTDATA fd;
    347   memset(&fd, 0, sizeof(PDF_FONTDATA));
    348   HDC hDC = ::GetDC(nullptr);
    349   EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd,
    350                       0);
    351   ::ReleaseDC(nullptr, hDC);
    352   if (fd.bFind)
    353     memcpy(&lf, &fd.lf, sizeof(LOGFONTA));
    354 
    355   return fd.bFind;
    356 }
    357 
    358 bool RetrieveSpecificFont(uint8_t charSet,
    359                           uint8_t pitchAndFamily,
    360                           LPCSTR pcsFontName,
    361                           LOGFONTA& lf) {
    362   memset(&lf, 0, sizeof(LOGFONTA));
    363   lf.lfCharSet = charSet;
    364   lf.lfPitchAndFamily = pitchAndFamily;
    365   if (pcsFontName) {
    366     // TODO(dsinclair): Should this be strncpy?
    367     // NOLINTNEXTLINE(runtime/printf)
    368     strcpy(lf.lfFaceName, pcsFontName);
    369   }
    370   return RetrieveSpecificFont(lf);
    371 }
    372 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    373 
    374 int CompareFieldName(const CFX_WideString& name1, const CFX_WideString& name2) {
    375   const FX_WCHAR* ptr1 = name1.c_str();
    376   const FX_WCHAR* ptr2 = name2.c_str();
    377   if (name1.GetLength() == name2.GetLength())
    378     return name1 == name2 ? 1 : 0;
    379 
    380   int i = 0;
    381   while (ptr1[i] == ptr2[i])
    382     i++;
    383   if (i == name1.GetLength())
    384     return 2;
    385   if (i == name2.GetLength())
    386     return 3;
    387   return 0;
    388 }
    389 
    390 }  // namespace
    391 
    392 class CFieldTree {
    393  public:
    394   class Node {
    395    public:
    396     Node() : m_pField(nullptr) {}
    397     Node(const CFX_WideString& short_name, CPDF_FormField* pField)
    398         : m_ShortName(short_name), m_pField(pField) {}
    399     ~Node() {}
    400 
    401     void AddChildNode(Node* pNode) { m_Children.push_back(pNode); }
    402 
    403     size_t GetChildrenCount() const { return m_Children.size(); }
    404 
    405     Node* GetChildAt(size_t i) { return m_Children[i]; }
    406     const Node* GetChildAt(size_t i) const { return m_Children[i]; }
    407 
    408     CPDF_FormField* GetFieldAtIndex(size_t index) {
    409       size_t nFieldsToGo = index;
    410       return GetFieldInternal(&nFieldsToGo);
    411     }
    412 
    413     size_t CountFields() const { return CountFieldsInternal(0); }
    414 
    415     void SetField(CPDF_FormField* pField) { m_pField = pField; }
    416 
    417     CPDF_FormField* GetField() { return m_pField; }
    418     const CPDF_FormField* GetField() const { return m_pField; }
    419 
    420     const CFX_WideString& GetShortName() const { return m_ShortName; }
    421 
    422    private:
    423     CPDF_FormField* GetFieldInternal(size_t* pFieldsToGo) {
    424       if (m_pField) {
    425         if (*pFieldsToGo == 0)
    426           return m_pField;
    427 
    428         --*pFieldsToGo;
    429       }
    430       for (size_t i = 0; i < GetChildrenCount(); ++i) {
    431         CPDF_FormField* pField = GetChildAt(i)->GetFieldInternal(pFieldsToGo);
    432         if (pField)
    433           return pField;
    434       }
    435       return nullptr;
    436     }
    437 
    438     size_t CountFieldsInternal(int nLevel) const {
    439       if (nLevel > nMaxRecursion)
    440         return 0;
    441 
    442       size_t count = 0;
    443       if (m_pField)
    444         ++count;
    445 
    446       for (size_t i = 0; i < GetChildrenCount(); ++i)
    447         count += GetChildAt(i)->CountFieldsInternal(nLevel + 1);
    448       return count;
    449     }
    450 
    451     std::vector<Node*> m_Children;
    452     CFX_WideString m_ShortName;
    453     CPDF_FormField* m_pField;
    454   };
    455 
    456   CFieldTree();
    457   ~CFieldTree();
    458 
    459   void SetField(const CFX_WideString& full_name, CPDF_FormField* pField);
    460   CPDF_FormField* GetField(const CFX_WideString& full_name);
    461   void RemoveAll();
    462 
    463   Node* FindNode(const CFX_WideString& full_name);
    464   Node* AddChild(Node* pParent,
    465                  const CFX_WideString& short_name,
    466                  CPDF_FormField* pField);
    467   void RemoveNode(Node* pNode, int nLevel = 0);
    468 
    469   Node* Lookup(Node* pParent, const CFX_WideString& short_name);
    470 
    471   Node m_Root;
    472 };
    473 
    474 CFieldTree::CFieldTree() {}
    475 
    476 CFieldTree::~CFieldTree() {
    477   RemoveAll();
    478 }
    479 
    480 CFieldTree::Node* CFieldTree::AddChild(Node* pParent,
    481                                        const CFX_WideString& short_name,
    482                                        CPDF_FormField* pField) {
    483   if (!pParent)
    484     return nullptr;
    485 
    486   Node* pNode = new Node(short_name, pField);
    487   pParent->AddChildNode(pNode);
    488   return pNode;
    489 }
    490 
    491 void CFieldTree::RemoveNode(Node* pNode, int nLevel) {
    492   if (!pNode)
    493     return;
    494 
    495   if (nLevel <= nMaxRecursion) {
    496     for (size_t i = 0; i < pNode->GetChildrenCount(); ++i)
    497       RemoveNode(pNode->GetChildAt(i), nLevel + 1);
    498   }
    499   delete pNode;
    500 }
    501 
    502 CFieldTree::Node* CFieldTree::Lookup(Node* pParent,
    503                                      const CFX_WideString& short_name) {
    504   if (!pParent)
    505     return nullptr;
    506 
    507   for (size_t i = 0; i < pParent->GetChildrenCount(); ++i) {
    508     Node* pNode = pParent->GetChildAt(i);
    509     if (pNode->GetShortName() == short_name)
    510       return pNode;
    511   }
    512   return nullptr;
    513 }
    514 
    515 void CFieldTree::RemoveAll() {
    516   for (size_t i = 0; i < m_Root.GetChildrenCount(); ++i)
    517     RemoveNode(m_Root.GetChildAt(i));
    518 }
    519 
    520 void CFieldTree::SetField(const CFX_WideString& full_name,
    521                           CPDF_FormField* pField) {
    522   if (full_name.IsEmpty())
    523     return;
    524 
    525   CFieldNameExtractor name_extractor(full_name);
    526   const FX_WCHAR* pName;
    527   FX_STRSIZE nLength;
    528   name_extractor.GetNext(pName, nLength);
    529   Node* pNode = &m_Root;
    530   Node* pLast = nullptr;
    531   while (nLength > 0) {
    532     pLast = pNode;
    533     CFX_WideString name = CFX_WideString(pName, nLength);
    534     pNode = Lookup(pLast, name);
    535     if (!pNode)
    536       pNode = AddChild(pLast, name, nullptr);
    537 
    538     name_extractor.GetNext(pName, nLength);
    539   }
    540   if (pNode != &m_Root)
    541     pNode->SetField(pField);
    542 }
    543 
    544 CPDF_FormField* CFieldTree::GetField(const CFX_WideString& full_name) {
    545   if (full_name.IsEmpty())
    546     return nullptr;
    547 
    548   CFieldNameExtractor name_extractor(full_name);
    549   const FX_WCHAR* pName;
    550   FX_STRSIZE nLength;
    551   name_extractor.GetNext(pName, nLength);
    552   Node* pNode = &m_Root;
    553   Node* pLast = nullptr;
    554   while (nLength > 0 && pNode) {
    555     pLast = pNode;
    556     CFX_WideString name = CFX_WideString(pName, nLength);
    557     pNode = Lookup(pLast, name);
    558     name_extractor.GetNext(pName, nLength);
    559   }
    560   return pNode ? pNode->GetField() : nullptr;
    561 }
    562 
    563 CFieldTree::Node* CFieldTree::FindNode(const CFX_WideString& full_name) {
    564   if (full_name.IsEmpty())
    565     return nullptr;
    566 
    567   CFieldNameExtractor name_extractor(full_name);
    568   const FX_WCHAR* pName;
    569   FX_STRSIZE nLength;
    570   name_extractor.GetNext(pName, nLength);
    571   Node* pNode = &m_Root;
    572   Node* pLast = nullptr;
    573   while (nLength > 0 && pNode) {
    574     pLast = pNode;
    575     CFX_WideString name = CFX_WideString(pName, nLength);
    576     pNode = Lookup(pLast, name);
    577     name_extractor.GetNext(pName, nLength);
    578   }
    579   return pNode;
    580 }
    581 
    582 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict,
    583                                   CPDF_Document* pDocument,
    584                                   CFX_ByteString& csNameTag) {
    585   uint8_t charSet = CPDF_InterForm::GetNativeCharSet();
    586   return AddNativeFont(pFormDict, pDocument, charSet, csNameTag);
    587 }
    588 
    589 // static
    590 uint8_t CPDF_InterForm::GetNativeCharSet() {
    591 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    592   uint8_t charSet = FXFONT_ANSI_CHARSET;
    593   UINT iCodePage = ::GetACP();
    594   switch (iCodePage) {
    595     case 932:
    596       charSet = FXFONT_SHIFTJIS_CHARSET;
    597       break;
    598     case 936:
    599       charSet = FXFONT_GB2312_CHARSET;
    600       break;
    601     case 950:
    602       charSet = FXFONT_CHINESEBIG5_CHARSET;
    603       break;
    604     case 1252:
    605       charSet = FXFONT_ANSI_CHARSET;
    606       break;
    607     case 874:
    608       charSet = FXFONT_THAI_CHARSET;
    609       break;
    610     case 949:
    611       charSet = FXFONT_HANGUL_CHARSET;
    612       break;
    613     case 1200:
    614       charSet = FXFONT_ANSI_CHARSET;
    615       break;
    616     case 1250:
    617       charSet = FXFONT_EASTEUROPE_CHARSET;
    618       break;
    619     case 1251:
    620       charSet = FXFONT_RUSSIAN_CHARSET;
    621       break;
    622     case 1253:
    623       charSet = FXFONT_GREEK_CHARSET;
    624       break;
    625     case 1254:
    626       charSet = FXFONT_TURKISH_CHARSET;
    627       break;
    628     case 1255:
    629       charSet = FXFONT_HEBREW_CHARSET;
    630       break;
    631     case 1256:
    632       charSet = FXFONT_ARABIC_CHARSET;
    633       break;
    634     case 1257:
    635       charSet = FXFONT_BALTIC_CHARSET;
    636       break;
    637     case 1258:
    638       charSet = FXFONT_VIETNAMESE_CHARSET;
    639       break;
    640     case 1361:
    641       charSet = FXFONT_JOHAB_CHARSET;
    642       break;
    643   }
    644   return charSet;
    645 #else
    646   return 0;
    647 #endif
    648 }
    649 
    650 CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument)
    651     : m_pDocument(pDocument),
    652       m_pFormDict(nullptr),
    653       m_pFieldTree(new CFieldTree),
    654       m_pFormNotify(nullptr) {
    655   CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
    656   if (!pRoot)
    657     return;
    658 
    659   m_pFormDict = pRoot->GetDictFor("AcroForm");
    660   if (!m_pFormDict)
    661     return;
    662 
    663   CPDF_Array* pFields = m_pFormDict->GetArrayFor("Fields");
    664   if (!pFields)
    665     return;
    666 
    667   for (size_t i = 0; i < pFields->GetCount(); ++i)
    668     LoadField(pFields->GetDictAt(i), 0);
    669 }
    670 
    671 CPDF_InterForm::~CPDF_InterForm() {
    672   m_ControlMap.clear();
    673   size_t nCount = m_pFieldTree->m_Root.CountFields();
    674   for (size_t i = 0; i < nCount; ++i)
    675     delete m_pFieldTree->m_Root.GetFieldAtIndex(i);
    676 }
    677 
    678 bool CPDF_InterForm::s_bUpdateAP = true;
    679 
    680 bool CPDF_InterForm::IsUpdateAPEnabled() {
    681   return s_bUpdateAP;
    682 }
    683 
    684 void CPDF_InterForm::SetUpdateAP(bool bUpdateAP) {
    685   s_bUpdateAP = bUpdateAP;
    686 }
    687 
    688 CFX_ByteString CPDF_InterForm::GenerateNewResourceName(
    689     const CPDF_Dictionary* pResDict,
    690     const FX_CHAR* csType,
    691     int iMinLen,
    692     const FX_CHAR* csPrefix) {
    693   CFX_ByteString csStr = csPrefix;
    694   CFX_ByteString csBType = csType;
    695   if (csStr.IsEmpty()) {
    696     if (csBType == "ExtGState")
    697       csStr = "GS";
    698     else if (csBType == "ColorSpace")
    699       csStr = "CS";
    700     else if (csBType == "Font")
    701       csStr = "ZiTi";
    702     else
    703       csStr = "Res";
    704   }
    705   CFX_ByteString csTmp = csStr;
    706   int iCount = csStr.GetLength();
    707   int m = 0;
    708   if (iMinLen > 0) {
    709     csTmp = "";
    710     while (m < iMinLen && m < iCount)
    711       csTmp += csStr[m++];
    712     while (m < iMinLen) {
    713       csTmp += '0' + m % 10;
    714       m++;
    715     }
    716   } else {
    717     m = iCount;
    718   }
    719   if (!pResDict)
    720     return csTmp;
    721 
    722   CPDF_Dictionary* pDict = pResDict->GetDictFor(csType);
    723   if (!pDict)
    724     return csTmp;
    725 
    726   int num = 0;
    727   CFX_ByteString bsNum;
    728   while (true) {
    729     CFX_ByteString csKey = csTmp + bsNum;
    730     if (!pDict->KeyExist(csKey))
    731       return csKey;
    732     if (m < iCount)
    733       csTmp += csStr[m++];
    734     else
    735       bsNum.Format("%d", num++);
    736 
    737     m++;
    738   }
    739   return csTmp;
    740 }
    741 
    742 CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument,
    743                                            CFX_ByteString csFontName) {
    744   if (!pDocument || csFontName.IsEmpty())
    745     return nullptr;
    746 
    747   if (csFontName == "ZapfDingbats")
    748     return pDocument->AddStandardFont(csFontName.c_str(), nullptr);
    749 
    750   CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI);
    751   return pDocument->AddStandardFont(csFontName.c_str(), &encoding);
    752 }
    753 
    754 CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) {
    755   CFX_ByteString csFontName;
    756 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    757   LOGFONTA lf = {};
    758   if (charSet == FXFONT_ANSI_CHARSET) {
    759     csFontName = "Helvetica";
    760     return csFontName;
    761   }
    762   bool bRet = false;
    763   if (charSet == FXFONT_SHIFTJIS_CHARSET) {
    764     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
    765                                 "MS Mincho", lf);
    766   } else if (charSet == FXFONT_GB2312_CHARSET) {
    767     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun",
    768                                 lf);
    769   } else if (charSet == FXFONT_CHINESEBIG5_CHARSET) {
    770     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU",
    771                                 lf);
    772   }
    773   if (!bRet) {
    774     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
    775                                 "Arial Unicode MS", lf);
    776   }
    777   if (!bRet) {
    778     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
    779                                 "Microsoft Sans Serif", lf);
    780   }
    781   if (!bRet) {
    782     bRet =
    783         RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, nullptr, lf);
    784   }
    785   if (bRet) {
    786     if (pLogFont)
    787       memcpy(pLogFont, &lf, sizeof(LOGFONTA));
    788 
    789     csFontName = lf.lfFaceName;
    790     return csFontName;
    791   }
    792 #endif
    793   return csFontName;
    794 }
    795 
    796 CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet,
    797                                          CPDF_Document* pDocument) {
    798   if (!pDocument)
    799     return nullptr;
    800 
    801 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    802   LOGFONTA lf;
    803   CFX_ByteString csFontName = GetNativeFont(charSet, &lf);
    804   if (!csFontName.IsEmpty()) {
    805     if (csFontName == "Helvetica")
    806       return AddStandardFont(pDocument, csFontName);
    807     return pDocument->AddWindowsFont(&lf, false, true);
    808   }
    809 #endif
    810   return nullptr;
    811 }
    812 
    813 CPDF_Font* CPDF_InterForm::AddNativeFont(CPDF_Document* pDocument) {
    814   return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr;
    815 }
    816 
    817 bool CPDF_InterForm::ValidateFieldName(
    818     CFX_WideString& csNewFieldName,
    819     int iType,
    820     const CPDF_FormField* pExcludedField,
    821     const CPDF_FormControl* pExcludedControl) const {
    822   if (csNewFieldName.IsEmpty())
    823     return false;
    824 
    825   int iPos = 0;
    826   int iLength = csNewFieldName.GetLength();
    827   CFX_WideString csSub;
    828   while (true) {
    829     while (iPos < iLength &&
    830            (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) {
    831       iPos++;
    832     }
    833     if (iPos < iLength && !csSub.IsEmpty())
    834       csSub += L'.';
    835     while (iPos < iLength && csNewFieldName[iPos] != L'.')
    836       csSub += csNewFieldName[iPos++];
    837     for (int i = csSub.GetLength() - 1; i > -1; i--) {
    838       if (csSub[i] != L' ' && csSub[i] != L'.')
    839         break;
    840 
    841       csSub.SetAt(i, L'\0');
    842     }
    843     size_t dwCount = m_pFieldTree->m_Root.CountFields();
    844     for (size_t m = 0; m < dwCount; ++m) {
    845       CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(m);
    846       if (!pField)
    847         continue;
    848       if (pField == pExcludedField) {
    849         if (!pExcludedControl || pField->CountControls() < 2)
    850           continue;
    851       }
    852       CFX_WideString csFullName = pField->GetFullName();
    853       int iRet = CompareFieldName(csSub, csFullName);
    854       if (iRet == 1) {
    855         if (pField->GetFieldType() != iType)
    856           return false;
    857       } else if (iRet == 2 && csSub == csNewFieldName) {
    858         if (csFullName[iPos] == L'.')
    859           return false;
    860       } else if (iRet == 3 && csSub == csNewFieldName) {
    861         if (csNewFieldName[csFullName.GetLength()] == L'.')
    862           return false;
    863       }
    864     }
    865     if (iPos >= iLength)
    866       break;
    867   }
    868   if (csSub.IsEmpty())
    869     return false;
    870 
    871   csNewFieldName = csSub;
    872   return true;
    873 }
    874 
    875 size_t CPDF_InterForm::CountFields(const CFX_WideString& csFieldName) const {
    876   if (csFieldName.IsEmpty())
    877     return m_pFieldTree->m_Root.CountFields();
    878 
    879   CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName);
    880   return pNode ? pNode->CountFields() : 0;
    881 }
    882 
    883 CPDF_FormField* CPDF_InterForm::GetField(
    884     uint32_t index,
    885     const CFX_WideString& csFieldName) const {
    886   if (csFieldName.IsEmpty())
    887     return m_pFieldTree->m_Root.GetFieldAtIndex(index);
    888 
    889   CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName);
    890   return pNode ? pNode->GetFieldAtIndex(index) : nullptr;
    891 }
    892 
    893 CPDF_FormField* CPDF_InterForm::GetFieldByDict(
    894     CPDF_Dictionary* pFieldDict) const {
    895   if (!pFieldDict)
    896     return nullptr;
    897 
    898   CFX_WideString csWName = FPDF_GetFullName(pFieldDict);
    899   return m_pFieldTree->GetField(csWName);
    900 }
    901 
    902 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage,
    903                                                     const CFX_PointF& point,
    904 
    905                                                     int* z_order) const {
    906   CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayFor("Annots");
    907   if (!pAnnotList)
    908     return nullptr;
    909 
    910   for (size_t i = pAnnotList->GetCount(); i > 0; --i) {
    911     size_t annot_index = i - 1;
    912     CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(annot_index);
    913     if (!pAnnot)
    914       continue;
    915 
    916     const auto it = m_ControlMap.find(pAnnot);
    917     if (it == m_ControlMap.end())
    918       continue;
    919 
    920     CPDF_FormControl* pControl = it->second.get();
    921     if (!pControl->GetRect().Contains(point))
    922       continue;
    923 
    924     if (z_order)
    925       *z_order = static_cast<int>(annot_index);
    926     return pControl;
    927   }
    928   return nullptr;
    929 }
    930 
    931 CPDF_FormControl* CPDF_InterForm::GetControlByDict(
    932     const CPDF_Dictionary* pWidgetDict) const {
    933   const auto it = m_ControlMap.find(pWidgetDict);
    934   return it != m_ControlMap.end() ? it->second.get() : nullptr;
    935 }
    936 
    937 bool CPDF_InterForm::NeedConstructAP() const {
    938   return m_pFormDict && m_pFormDict->GetBooleanFor("NeedAppearances");
    939 }
    940 
    941 int CPDF_InterForm::CountFieldsInCalculationOrder() {
    942   if (!m_pFormDict)
    943     return 0;
    944 
    945   CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
    946   return pArray ? pArray->GetCount() : 0;
    947 }
    948 
    949 CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index) {
    950   if (!m_pFormDict || index < 0)
    951     return nullptr;
    952 
    953   CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
    954   if (!pArray)
    955     return nullptr;
    956 
    957   CPDF_Dictionary* pElement = ToDictionary(pArray->GetDirectObjectAt(index));
    958   return pElement ? GetFieldByDict(pElement) : nullptr;
    959 }
    960 
    961 int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) {
    962   if (!m_pFormDict || !pField)
    963     return -1;
    964 
    965   CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
    966   if (!pArray)
    967     return -1;
    968 
    969   for (size_t i = 0; i < pArray->GetCount(); i++) {
    970     CPDF_Object* pElement = pArray->GetDirectObjectAt(i);
    971     if (pElement == pField->m_pDict)
    972       return i;
    973   }
    974   return -1;
    975 }
    976 
    977 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag) {
    978   return GetFont(m_pFormDict, m_pDocument, csNameTag);
    979 }
    980 
    981 CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() const {
    982   if (!m_pFormDict)
    983     return CPDF_DefaultAppearance();
    984   return CPDF_DefaultAppearance(m_pFormDict->GetStringFor("DA"));
    985 }
    986 
    987 int CPDF_InterForm::GetFormAlignment() const {
    988   return m_pFormDict ? m_pFormDict->GetIntegerFor("Q", 0) : 0;
    989 }
    990 
    991 bool CPDF_InterForm::ResetForm(const std::vector<CPDF_FormField*>& fields,
    992                                bool bIncludeOrExclude,
    993                                bool bNotify) {
    994   if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0)
    995     return false;
    996 
    997   size_t nCount = m_pFieldTree->m_Root.CountFields();
    998   for (size_t i = 0; i < nCount; ++i) {
    999     CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
   1000     if (!pField)
   1001       continue;
   1002 
   1003     if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField))
   1004       pField->ResetField(bNotify);
   1005   }
   1006   if (bNotify && m_pFormNotify)
   1007     m_pFormNotify->AfterFormReset(this);
   1008   return true;
   1009 }
   1010 
   1011 bool CPDF_InterForm::ResetForm(bool bNotify) {
   1012   if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0)
   1013     return false;
   1014 
   1015   size_t nCount = m_pFieldTree->m_Root.CountFields();
   1016   for (size_t i = 0; i < nCount; ++i) {
   1017     CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
   1018     if (!pField)
   1019       continue;
   1020 
   1021     pField->ResetField(bNotify);
   1022   }
   1023   if (bNotify && m_pFormNotify)
   1024     m_pFormNotify->AfterFormReset(this);
   1025   return true;
   1026 }
   1027 
   1028 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) {
   1029   if (nLevel > nMaxRecursion)
   1030     return;
   1031   if (!pFieldDict)
   1032     return;
   1033 
   1034   uint32_t dwParentObjNum = pFieldDict->GetObjNum();
   1035   CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids");
   1036   if (!pKids) {
   1037     AddTerminalField(pFieldDict);
   1038     return;
   1039   }
   1040 
   1041   CPDF_Dictionary* pFirstKid = pKids->GetDictAt(0);
   1042   if (!pFirstKid)
   1043     return;
   1044 
   1045   if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) {
   1046     for (size_t i = 0; i < pKids->GetCount(); i++) {
   1047       CPDF_Dictionary* pChildDict = pKids->GetDictAt(i);
   1048       if (pChildDict) {
   1049         if (pChildDict->GetObjNum() != dwParentObjNum)
   1050           LoadField(pChildDict, nLevel + 1);
   1051       }
   1052     }
   1053   } else {
   1054     AddTerminalField(pFieldDict);
   1055   }
   1056 }
   1057 
   1058 bool CPDF_InterForm::HasXFAForm() const {
   1059   return m_pFormDict && m_pFormDict->GetArrayFor("XFA");
   1060 }
   1061 
   1062 void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) {
   1063   CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
   1064   if (!pPageDict)
   1065     return;
   1066 
   1067   CPDF_Array* pAnnots = pPageDict->GetArrayFor("Annots");
   1068   if (!pAnnots)
   1069     return;
   1070 
   1071   for (size_t i = 0; i < pAnnots->GetCount(); i++) {
   1072     CPDF_Dictionary* pAnnot = pAnnots->GetDictAt(i);
   1073     if (pAnnot && pAnnot->GetStringFor("Subtype") == "Widget")
   1074       LoadField(pAnnot, 0);
   1075   }
   1076 }
   1077 
   1078 CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) {
   1079   if (!pFieldDict->KeyExist("FT")) {
   1080     // Key "FT" is required for terminal fields, it is also inheritable.
   1081     CPDF_Dictionary* pParentDict = pFieldDict->GetDictFor("Parent");
   1082     if (!pParentDict || !pParentDict->KeyExist("FT"))
   1083       return nullptr;
   1084   }
   1085 
   1086   CPDF_Dictionary* pDict = pFieldDict;
   1087   CFX_WideString csWName = FPDF_GetFullName(pFieldDict);
   1088   if (csWName.IsEmpty())
   1089     return nullptr;
   1090 
   1091   CPDF_FormField* pField = nullptr;
   1092   pField = m_pFieldTree->GetField(csWName);
   1093   if (!pField) {
   1094     CPDF_Dictionary* pParent = pFieldDict;
   1095     if (!pFieldDict->KeyExist("T") &&
   1096         pFieldDict->GetStringFor("Subtype") == "Widget") {
   1097       pParent = pFieldDict->GetDictFor("Parent");
   1098       if (!pParent)
   1099         pParent = pFieldDict;
   1100     }
   1101 
   1102     if (pParent && pParent != pFieldDict && !pParent->KeyExist("FT")) {
   1103       if (pFieldDict->KeyExist("FT")) {
   1104         CPDF_Object* pFTValue = pFieldDict->GetDirectObjectFor("FT");
   1105         if (pFTValue)
   1106           pParent->SetFor("FT", pFTValue->Clone());
   1107       }
   1108 
   1109       if (pFieldDict->KeyExist("Ff")) {
   1110         CPDF_Object* pFfValue = pFieldDict->GetDirectObjectFor("Ff");
   1111         if (pFfValue)
   1112           pParent->SetFor("Ff", pFfValue->Clone());
   1113       }
   1114     }
   1115 
   1116     pField = new CPDF_FormField(this, pParent);
   1117     CPDF_Object* pTObj = pDict->GetObjectFor("T");
   1118     if (ToReference(pTObj)) {
   1119       std::unique_ptr<CPDF_Object> pClone = pTObj->CloneDirectObject();
   1120       if (pClone)
   1121         pDict->SetFor("T", std::move(pClone));
   1122       else
   1123         pDict->SetNewFor<CPDF_Name>("T", "");
   1124     }
   1125     m_pFieldTree->SetField(csWName, pField);
   1126   }
   1127 
   1128   CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids");
   1129   if (pKids) {
   1130     for (size_t i = 0; i < pKids->GetCount(); i++) {
   1131       CPDF_Dictionary* pKid = pKids->GetDictAt(i);
   1132       if (!pKid)
   1133         continue;
   1134       if (pKid->GetStringFor("Subtype") != "Widget")
   1135         continue;
   1136 
   1137       AddControl(pField, pKid);
   1138     }
   1139   } else {
   1140     if (pFieldDict->GetStringFor("Subtype") == "Widget")
   1141       AddControl(pField, pFieldDict);
   1142   }
   1143   return pField;
   1144 }
   1145 
   1146 CPDF_FormControl* CPDF_InterForm::AddControl(CPDF_FormField* pField,
   1147                                              CPDF_Dictionary* pWidgetDict) {
   1148   const auto it = m_ControlMap.find(pWidgetDict);
   1149   if (it != m_ControlMap.end())
   1150     return it->second.get();
   1151 
   1152   auto pNew = pdfium::MakeUnique<CPDF_FormControl>(pField, pWidgetDict);
   1153   CPDF_FormControl* pControl = pNew.get();
   1154   m_ControlMap[pWidgetDict] = std::move(pNew);
   1155   pField->m_ControlList.push_back(pControl);
   1156   return pControl;
   1157 }
   1158 
   1159 bool CPDF_InterForm::CheckRequiredFields(
   1160     const std::vector<CPDF_FormField*>* fields,
   1161     bool bIncludeOrExclude) const {
   1162   size_t nCount = m_pFieldTree->m_Root.CountFields();
   1163   for (size_t i = 0; i < nCount; ++i) {
   1164     CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
   1165     if (!pField)
   1166       continue;
   1167 
   1168     int32_t iType = pField->GetType();
   1169     if (iType == CPDF_FormField::PushButton ||
   1170         iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) {
   1171       continue;
   1172     }
   1173     uint32_t dwFlags = pField->GetFieldFlags();
   1174     // TODO(thestig): Look up these magic numbers and add constants for them.
   1175     if (dwFlags & FORMFLAG_NOEXPORT)
   1176       continue;
   1177 
   1178     bool bFind = true;
   1179     if (fields)
   1180       bFind = pdfium::ContainsValue(*fields, pField);
   1181     if (bIncludeOrExclude == bFind) {
   1182       CPDF_Dictionary* pFieldDict = pField->m_pDict;
   1183       if ((dwFlags & FORMFLAG_REQUIRED) != 0 &&
   1184           pFieldDict->GetStringFor("V").IsEmpty()) {
   1185         return false;
   1186       }
   1187     }
   1188   }
   1189   return true;
   1190 }
   1191 
   1192 std::unique_ptr<CFDF_Document> CPDF_InterForm::ExportToFDF(
   1193     const CFX_WideStringC& pdf_path,
   1194     bool bSimpleFileSpec) const {
   1195   std::vector<CPDF_FormField*> fields;
   1196   size_t nCount = m_pFieldTree->m_Root.CountFields();
   1197   for (size_t i = 0; i < nCount; ++i)
   1198     fields.push_back(m_pFieldTree->m_Root.GetFieldAtIndex(i));
   1199   return ExportToFDF(pdf_path, fields, true, bSimpleFileSpec);
   1200 }
   1201 
   1202 std::unique_ptr<CFDF_Document> CPDF_InterForm::ExportToFDF(
   1203     const CFX_WideStringC& pdf_path,
   1204     const std::vector<CPDF_FormField*>& fields,
   1205     bool bIncludeOrExclude,
   1206     bool bSimpleFileSpec) const {
   1207   std::unique_ptr<CFDF_Document> pDoc = CFDF_Document::CreateNewDoc();
   1208   if (!pDoc)
   1209     return nullptr;
   1210 
   1211   CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDictFor("FDF");
   1212   if (!pdf_path.IsEmpty()) {
   1213     if (bSimpleFileSpec) {
   1214       CFX_WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path);
   1215       pMainDict->SetNewFor<CPDF_String>(
   1216           "F", CFX_ByteString::FromUnicode(wsFilePath), false);
   1217       pMainDict->SetNewFor<CPDF_String>("UF", PDF_EncodeText(wsFilePath),
   1218                                         false);
   1219     } else {
   1220       CPDF_FileSpec filespec(pDoc->GetByteStringPool());
   1221       filespec.SetFileName(pdf_path);
   1222       pMainDict->SetFor("F", pdfium::WrapUnique(filespec.GetObj()));
   1223     }
   1224   }
   1225 
   1226   CPDF_Array* pFields = pMainDict->SetNewFor<CPDF_Array>("Fields");
   1227   size_t nCount = m_pFieldTree->m_Root.CountFields();
   1228   for (size_t i = 0; i < nCount; ++i) {
   1229     CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
   1230     if (!pField || pField->GetType() == CPDF_FormField::PushButton)
   1231       continue;
   1232 
   1233     uint32_t dwFlags = pField->GetFieldFlags();
   1234     if (dwFlags & 0x04)
   1235       continue;
   1236 
   1237     if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) {
   1238       if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetStringFor("V").IsEmpty())
   1239         continue;
   1240 
   1241       CFX_WideString fullname = FPDF_GetFullName(pField->GetFieldDict());
   1242       auto pFieldDict =
   1243           pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool());
   1244       pFieldDict->SetNewFor<CPDF_String>("T", fullname);
   1245       if (pField->GetType() == CPDF_FormField::CheckBox ||
   1246           pField->GetType() == CPDF_FormField::RadioButton) {
   1247         CFX_WideString csExport = pField->GetCheckValue(false);
   1248         CFX_ByteString csBExport = PDF_EncodeText(csExport);
   1249         CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt");
   1250         if (pOpt)
   1251           pFieldDict->SetNewFor<CPDF_String>("V", csBExport, false);
   1252         else
   1253           pFieldDict->SetNewFor<CPDF_Name>("V", csBExport);
   1254       } else {
   1255         CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V");
   1256         if (pV)
   1257           pFieldDict->SetFor("V", pV->CloneDirectObject());
   1258       }
   1259       pFields->Add(std::move(pFieldDict));
   1260     }
   1261   }
   1262   return pDoc;
   1263 }
   1264 
   1265 void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict,
   1266                                      const CFX_WideString& parent_name,
   1267                                      bool bNotify,
   1268                                      int nLevel) {
   1269   CFX_WideString name;
   1270   if (!parent_name.IsEmpty())
   1271     name = parent_name + L".";
   1272 
   1273   name += pFieldDict->GetUnicodeTextFor("T");
   1274   CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids");
   1275   if (pKids) {
   1276     for (size_t i = 0; i < pKids->GetCount(); i++) {
   1277       CPDF_Dictionary* pKid = pKids->GetDictAt(i);
   1278       if (!pKid)
   1279         continue;
   1280       if (nLevel <= nMaxRecursion)
   1281         FDF_ImportField(pKid, name, bNotify, nLevel + 1);
   1282     }
   1283     return;
   1284   }
   1285   if (!pFieldDict->KeyExist("V"))
   1286     return;
   1287 
   1288   CPDF_FormField* pField = m_pFieldTree->GetField(name);
   1289   if (!pField)
   1290     return;
   1291 
   1292   CFX_WideString csWValue = GetFieldValue(*pFieldDict, m_bsEncoding);
   1293   int iType = pField->GetFieldType();
   1294   if (bNotify && m_pFormNotify) {
   1295     if (iType == FIELDTYPE_LISTBOX) {
   1296       if (m_pFormNotify->BeforeSelectionChange(pField, csWValue) < 0)
   1297         return;
   1298     } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
   1299       if (m_pFormNotify->BeforeValueChange(pField, csWValue) < 0)
   1300         return;
   1301     }
   1302   }
   1303   pField->SetValue(csWValue);
   1304   CPDF_FormField::Type eType = pField->GetType();
   1305   if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) &&
   1306       pFieldDict->KeyExist("Opt")) {
   1307     pField->m_pDict->SetFor(
   1308         "Opt", pFieldDict->GetDirectObjectFor("Opt")->CloneDirectObject());
   1309   }
   1310 
   1311   if (bNotify && m_pFormNotify) {
   1312     if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON)
   1313       m_pFormNotify->AfterCheckedStatusChange(pField);
   1314     else if (iType == FIELDTYPE_LISTBOX)
   1315       m_pFormNotify->AfterSelectionChange(pField);
   1316     else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD)
   1317       m_pFormNotify->AfterValueChange(pField);
   1318   }
   1319 }
   1320 
   1321 void CPDF_InterForm::SetFormNotify(IPDF_FormNotify* pNotify) {
   1322   m_pFormNotify = pNotify;
   1323 }
   1324