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