Home | History | Annotate | Download | only in fpdfdoc
      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 
     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 }
     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 }
     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 }
     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 }
     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 }
     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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    653 FX_BOOL CPDF_IconFit::IsProportionalScale() {
    654   if (!m_pDict) {
    655     return TRUE;
    656   }
    657   return m_pDict->GetString("S", "P") != "A";
    658 }
    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 }
    675 FX_BOOL CPDF_IconFit::GetFittingBounds() {
    676   if (!m_pDict) {
    677     return FALSE;
    678   }
    679   return m_pDict->GetBoolean("FB");
    680 }
    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 }
    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