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