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 CPDF_FormControl::CPDF_FormControl(CPDF_FormField* pField, CPDF_Dictionary* pWidgetDict)
      9 {
     10     m_pField = pField;
     11     m_pWidgetDict = pWidgetDict;
     12     m_pForm = m_pField->m_pForm;
     13 }
     14 CFX_FloatRect CPDF_FormControl::GetRect()
     15 {
     16     return m_pWidgetDict->GetRect("Rect");
     17 }
     18 CFX_ByteString CPDF_FormControl::GetOnStateName()
     19 {
     20     ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
     21     CFX_ByteString csOn;
     22     CPDF_Dictionary* pAP = m_pWidgetDict->GetDict("AP");
     23     if (pAP == NULL) {
     24         return csOn;
     25     }
     26     CPDF_Dictionary* pN = pAP->GetDict("N");
     27     if (pN == NULL) {
     28         return csOn;
     29     }
     30     FX_POSITION pos = pN->GetStartPos();
     31     while (pos) {
     32         pN->GetNextElement(pos, csOn);
     33         if (csOn != "Off") {
     34             return csOn;
     35         }
     36     }
     37     return CFX_ByteString();
     38 }
     39 void CPDF_FormControl::SetOnStateName(const CFX_ByteString& csOn)
     40 {
     41     ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
     42     CFX_ByteString csValue = csOn;
     43     if (csValue.IsEmpty()) {
     44         csValue = "Yes";
     45     }
     46     if (csValue == "Off") {
     47         csValue = "Yes";
     48     }
     49     CFX_ByteString csAS = m_pWidgetDict->GetString("AS", "Off");
     50     if (csAS != "Off") {
     51         m_pWidgetDict->SetAtName("AS", csValue);
     52     }
     53     CPDF_Dictionary* pAP = m_pWidgetDict->GetDict("AP");
     54     if (pAP == NULL) {
     55         return;
     56     }
     57     FX_POSITION pos1 = pAP->GetStartPos();
     58     while (pos1) {
     59         CFX_ByteString csKey1;
     60         CPDF_Object* pObj1 = pAP->GetNextElement(pos1, csKey1);
     61         if (pObj1 == NULL) {
     62             continue;
     63         }
     64         CPDF_Object* pObjDirect1 = pObj1->GetDirect();
     65         if (pObjDirect1->GetType() != PDFOBJ_DICTIONARY) {
     66             continue;
     67         }
     68         CPDF_Dictionary* pSubDict = (CPDF_Dictionary*)pObjDirect1;
     69         FX_POSITION pos2 = pSubDict->GetStartPos();
     70         while (pos2) {
     71             CFX_ByteString csKey2;
     72             CPDF_Object* pObj2 = pSubDict->GetNextElement(pos2, csKey2);
     73             if (pObj2 == NULL) {
     74                 continue;
     75             }
     76             if (csKey2 != "Off") {
     77                 pSubDict->ReplaceKey(csKey2, csValue);
     78                 break;
     79             }
     80         }
     81     }
     82 }
     83 CFX_ByteString CPDF_FormControl::GetCheckedAPState()
     84 {
     85     ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
     86     CFX_ByteString csOn = GetOnStateName();
     87     if (GetType() == CPDF_FormField::RadioButton || GetType() == CPDF_FormField::CheckBox) {
     88         CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pField->m_pDict, "Opt");
     89         if (pOpt != NULL && pOpt->GetType() == PDFOBJ_ARRAY) {
     90             int iIndex = m_pField->GetControlIndex(this);
     91             csOn.Format("%d", iIndex);
     92         }
     93     }
     94     if (csOn.IsEmpty()) {
     95         csOn = "Yes";
     96     }
     97     return csOn;
     98 }
     99 CFX_WideString CPDF_FormControl::GetExportValue()
    100 {
    101     ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
    102     CFX_ByteString csOn = GetOnStateName();
    103     if (GetType() == CPDF_FormField::RadioButton || GetType() == CPDF_FormField::CheckBox) {
    104         CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pField->m_pDict, "Opt");
    105         if (pOpt != NULL && pOpt->GetType() == PDFOBJ_ARRAY) {
    106             int iIndex = m_pField->GetControlIndex(this);
    107             csOn = ((CPDF_Array*)pOpt)->GetString(iIndex);
    108         }
    109     }
    110     if (csOn.IsEmpty()) {
    111         csOn = "Yes";
    112     }
    113     CFX_WideString csWOn = PDF_DecodeText(csOn);
    114     return csWOn;
    115 }
    116 FX_BOOL CPDF_FormControl::IsChecked()
    117 {
    118     ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
    119     CFX_ByteString csOn = GetOnStateName();
    120     CFX_ByteString csAS = m_pWidgetDict->GetString("AS");
    121     return csAS == csOn;
    122 }
    123 FX_BOOL CPDF_FormControl::IsDefaultChecked()
    124 {
    125     ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
    126     CPDF_Object* pDV = FPDF_GetFieldAttr(m_pField->m_pDict, "DV");
    127     if (pDV == NULL) {
    128         return FALSE;
    129     }
    130     CFX_ByteString csDV = pDV->GetString();
    131     CFX_ByteString csOn = GetOnStateName();
    132     return (csDV == csOn);
    133 }
    134 void CPDF_FormControl::CheckControl(FX_BOOL bChecked)
    135 {
    136     ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
    137     CFX_ByteString csOn = GetOnStateName();
    138     CFX_ByteString csOldAS = m_pWidgetDict->GetString("AS", "Off");
    139     CFX_ByteString csAS = "Off";
    140     if (bChecked) {
    141         csAS = csOn;
    142     }
    143     if (csOldAS == csAS) {
    144         return;
    145     }
    146     m_pWidgetDict->SetAtName("AS", csAS);
    147     m_pForm->m_bUpdated = TRUE;
    148 }
    149 CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, CPDF_Annot::AppearanceMode mode);
    150 void CPDF_FormControl::DrawControl(CFX_RenderDevice* pDevice, CFX_AffineMatrix* pMatrix, CPDF_Page* pPage,
    151                                    CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions)
    152 {
    153     if (m_pWidgetDict->GetInteger("F") & ANNOTFLAG_HIDDEN) {
    154         return;
    155     }
    156     CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pWidgetDict, mode);
    157     if (pStream == NULL) {
    158         return;
    159     }
    160     CFX_FloatRect form_bbox = pStream->GetDict()->GetRect("BBox");
    161     CFX_AffineMatrix form_matrix = pStream->GetDict()->GetMatrix("Matrix");
    162     form_matrix.TransformRect(form_bbox);
    163     CFX_FloatRect arect = m_pWidgetDict->GetRect("Rect");
    164     CFX_AffineMatrix matrix;
    165     matrix.MatchRect(arect, form_bbox);
    166     matrix.Concat(*pMatrix);
    167     CPDF_Form form(m_pField->m_pForm->m_pDocument, m_pField->m_pForm->m_pFormDict->GetDict("DR"), pStream);
    168     form.ParseContent(NULL, NULL, NULL, NULL);
    169     CPDF_RenderContext context;
    170     context.Create(pPage);
    171     context.DrawObjectList(pDevice, &form, &matrix, pOptions);
    172 }
    173 const FX_CHAR* g_sHighlightingMode[] = {"N", "I", "O", "P", "T", ""};
    174 CPDF_FormControl::HighlightingMode CPDF_FormControl::GetHighlightingMode()
    175 {
    176     if (m_pWidgetDict == NULL) {
    177         return Invert;
    178     }
    179     CFX_ByteString csH = m_pWidgetDict->GetString("H", "I");
    180     int i = 0;
    181     while (g_sHighlightingMode[i][0] != '\0') {
    182         if (csH.Equal(g_sHighlightingMode[i])) {
    183             return (HighlightingMode)i;
    184         }
    185         i ++;
    186     }
    187     return Invert;
    188 }
    189 CPDF_ApSettings CPDF_FormControl::GetMK(FX_BOOL bCreate)
    190 {
    191     if (!m_pWidgetDict) {
    192         return NULL;
    193     }
    194     CPDF_ApSettings mk = m_pWidgetDict->GetDict(FX_BSTRC("MK"));
    195     if (!mk && bCreate) {
    196         mk = CPDF_Dictionary::Create();
    197         if (mk == NULL) {
    198             return NULL;
    199         }
    200         m_pWidgetDict->SetAt(FX_BSTRC("MK"), mk);
    201     }
    202     return mk;
    203 }
    204 FX_BOOL CPDF_FormControl::HasMKEntry(CFX_ByteString csEntry)
    205 {
    206     CPDF_ApSettings mk = GetMK(FALSE);
    207     return mk.HasMKEntry(csEntry);
    208 }
    209 int CPDF_FormControl::GetRotation()
    210 {
    211     CPDF_ApSettings mk = GetMK(FALSE);
    212     return mk.GetRotation();
    213 }
    214 FX_ARGB CPDF_FormControl::GetColor(int& iColorType, CFX_ByteString csEntry)
    215 {
    216     CPDF_ApSettings mk = GetMK(FALSE);
    217     return mk.GetColor(iColorType, csEntry);
    218 }
    219 FX_FLOAT CPDF_FormControl::GetOriginalColor(int index, CFX_ByteString csEntry)
    220 {
    221     CPDF_ApSettings mk = GetMK(FALSE);
    222     return mk.GetOriginalColor(index, csEntry);
    223 }
    224 void CPDF_FormControl::GetOriginalColor(int& iColorType, FX_FLOAT fc[4], CFX_ByteString csEntry)
    225 {
    226     CPDF_ApSettings mk = GetMK(FALSE);
    227     mk.GetOriginalColor(iColorType, fc, csEntry);
    228 }
    229 CFX_WideString CPDF_FormControl::GetCaption(CFX_ByteString csEntry)
    230 {
    231     CPDF_ApSettings mk = GetMK(FALSE);
    232     return mk.GetCaption(csEntry);
    233 }
    234 CPDF_Stream* CPDF_FormControl::GetIcon(CFX_ByteString csEntry)
    235 {
    236     CPDF_ApSettings mk = GetMK(FALSE);
    237     return mk.GetIcon(csEntry);
    238 }
    239 CPDF_IconFit CPDF_FormControl::GetIconFit()
    240 {
    241     CPDF_ApSettings mk = GetMK(FALSE);
    242     return mk.GetIconFit();
    243 }
    244 int CPDF_FormControl::GetTextPosition()
    245 {
    246     CPDF_ApSettings mk = GetMK(FALSE);
    247     return mk.GetTextPosition();
    248 }
    249 CPDF_Action CPDF_FormControl::GetAction()
    250 {
    251     if (m_pWidgetDict == NULL) {
    252         return NULL;
    253     }
    254     if (m_pWidgetDict->KeyExist("A")) {
    255         return m_pWidgetDict->GetDict("A");
    256     } else {
    257         CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "A");
    258         if (pObj == NULL) {
    259             return NULL;
    260         }
    261         return pObj->GetDict();
    262     }
    263 }
    264 CPDF_AAction CPDF_FormControl::GetAdditionalAction()
    265 {
    266     if (m_pWidgetDict == NULL) {
    267         return NULL;
    268     }
    269     if (m_pWidgetDict->KeyExist("AA")) {
    270         return m_pWidgetDict->GetDict("AA");
    271     } else {
    272         return m_pField->GetAdditionalAction();
    273     }
    274 }
    275 CPDF_DefaultAppearance CPDF_FormControl::GetDefaultAppearance()
    276 {
    277     if (m_pWidgetDict == NULL) {
    278         return CFX_ByteString();
    279     }
    280     if (m_pWidgetDict->KeyExist("DA")) {
    281         return m_pWidgetDict->GetString("DA");
    282     } else {
    283         CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "DA");
    284         if (pObj == NULL) {
    285             return m_pField->m_pForm->GetDefaultAppearance();
    286         }
    287         return pObj->GetString();
    288     }
    289 }
    290 CPDF_Font* CPDF_FormControl::GetDefaultControlFont()
    291 {
    292     CPDF_DefaultAppearance cDA = GetDefaultAppearance();
    293     CFX_ByteString csFontNameTag;
    294     FX_FLOAT fFontSize;
    295     cDA.GetFont(csFontNameTag, fFontSize);
    296     if (csFontNameTag.IsEmpty()) {
    297         return NULL;
    298     }
    299     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pWidgetDict, "DR");
    300     if (pObj != NULL && pObj->GetType() == PDFOBJ_DICTIONARY) {
    301         CPDF_Dictionary* pFonts = ((CPDF_Dictionary*)pObj)->GetDict("Font");
    302         if (pFonts != NULL) {
    303             CPDF_Dictionary *pElement = pFonts->GetDict(csFontNameTag);
    304             CPDF_Font *pFont = m_pField->m_pForm->m_pDocument->LoadFont(pElement);
    305             if (pFont != NULL) {
    306                 return pFont;
    307             }
    308         }
    309     }
    310     CPDF_Font *pFont = m_pField->m_pForm->GetFormFont(csFontNameTag);
    311     if (pFont != NULL) {
    312         return pFont;
    313     }
    314     CPDF_Dictionary *pPageDict = m_pWidgetDict->GetDict("P");
    315     pObj = FPDF_GetFieldAttr(pPageDict, "Resources");
    316     if (pObj != NULL && pObj->GetType() == PDFOBJ_DICTIONARY) {
    317         CPDF_Dictionary* pFonts = ((CPDF_Dictionary*)pObj)->GetDict("Font");
    318         if (pFonts != NULL) {
    319             CPDF_Dictionary *pElement = pFonts->GetDict(csFontNameTag);
    320             CPDF_Font *pFont = m_pField->m_pForm->m_pDocument->LoadFont(pElement);
    321             if (pFont != NULL) {
    322                 return pFont;
    323             }
    324         }
    325     }
    326     return NULL;
    327 }
    328 int CPDF_FormControl::GetControlAlignment()
    329 {
    330     if (m_pWidgetDict == NULL) {
    331         return 0;
    332     }
    333     if (m_pWidgetDict->KeyExist("Q")) {
    334         return m_pWidgetDict->GetInteger("Q", 0);
    335     } else {
    336         CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "Q");
    337         if (pObj == NULL) {
    338             return m_pField->m_pForm->GetFormAlignment();
    339         }
    340         return pObj->GetInteger();
    341     }
    342 }
    343 FX_BOOL CPDF_ApSettings::HasMKEntry(FX_BSTR csEntry)
    344 {
    345     if (m_pDict == NULL) {
    346         return FALSE;
    347     }
    348     return m_pDict->KeyExist(csEntry);
    349 }
    350 int CPDF_ApSettings::GetRotation()
    351 {
    352     if (m_pDict == NULL) {
    353         return 0;
    354     }
    355     return m_pDict->GetInteger(FX_BSTRC("R"));
    356 }
    357 FX_ARGB CPDF_ApSettings::GetColor(int& iColorType, FX_BSTR csEntry)
    358 {
    359     iColorType = COLORTYPE_TRANSPARENT;
    360     if (m_pDict == NULL) {
    361         return 0;
    362     }
    363     FX_ARGB color = 0;
    364     CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
    365     if (pEntry == NULL) {
    366         return color;
    367     }
    368     FX_DWORD dwCount = pEntry->GetCount();
    369     if (dwCount == 1) {
    370         iColorType = COLORTYPE_GRAY;
    371         FX_FLOAT g = pEntry->GetNumber(0) * 255;
    372         color = ArgbEncode(255, (int)g, (int)g, (int)g);
    373     } else if (dwCount == 3) {
    374         iColorType = COLORTYPE_RGB;
    375         FX_FLOAT r = pEntry->GetNumber(0) * 255;
    376         FX_FLOAT g = pEntry->GetNumber(1) * 255;
    377         FX_FLOAT b = pEntry->GetNumber(2) * 255;
    378         color = ArgbEncode(255, (int)r, (int)g, (int)b);
    379     } else if (dwCount == 4) {
    380         iColorType = COLORTYPE_CMYK;
    381         FX_FLOAT c = pEntry->GetNumber(0);
    382         FX_FLOAT m = pEntry->GetNumber(1);
    383         FX_FLOAT y = pEntry->GetNumber(2);
    384         FX_FLOAT k = pEntry->GetNumber(3);
    385         FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k);
    386         FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k);
    387         FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k);
    388         color = ArgbEncode(255, (int)(r * 255), (int)(g * 255), (int)(b * 255));
    389     }
    390     return color;
    391 }
    392 FX_FLOAT CPDF_ApSettings::GetOriginalColor(int index, FX_BSTR csEntry)
    393 {
    394     if (m_pDict == NULL) {
    395         return 0;
    396     }
    397     CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
    398     if (pEntry != NULL) {
    399         return pEntry->GetNumber(index);
    400     }
    401     return 0;
    402 }
    403 void CPDF_ApSettings::GetOriginalColor(int& iColorType, FX_FLOAT fc[4], FX_BSTR csEntry)
    404 {
    405     iColorType = COLORTYPE_TRANSPARENT;
    406     for (int i = 0; i < 4; i ++) {
    407         fc[i] = 0;
    408     }
    409     if (m_pDict == NULL) {
    410         return;
    411     }
    412     CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
    413     if (pEntry == NULL) {
    414         return;
    415     }
    416     FX_DWORD dwCount = pEntry->GetCount();
    417     if (dwCount == 1) {
    418         iColorType = COLORTYPE_GRAY;
    419         fc[0] = pEntry->GetNumber(0);
    420     } else if (dwCount == 3) {
    421         iColorType = COLORTYPE_RGB;
    422         fc[0] = pEntry->GetNumber(0);
    423         fc[1] = pEntry->GetNumber(1);
    424         fc[2] = pEntry->GetNumber(2);
    425     } else if (dwCount == 4) {
    426         iColorType = COLORTYPE_CMYK;
    427         fc[0] = pEntry->GetNumber(0);
    428         fc[1] = pEntry->GetNumber(1);
    429         fc[2] = pEntry->GetNumber(2);
    430         fc[3] = pEntry->GetNumber(3);
    431     }
    432 }
    433 CFX_WideString CPDF_ApSettings::GetCaption(FX_BSTR csEntry)
    434 {
    435     CFX_WideString csCaption;
    436     if (m_pDict == NULL) {
    437         return csCaption;
    438     }
    439     return m_pDict->GetUnicodeText(csEntry);
    440 }
    441 CPDF_Stream* CPDF_ApSettings::GetIcon(FX_BSTR csEntry)
    442 {
    443     if (m_pDict == NULL) {
    444         return NULL;
    445     }
    446     return m_pDict->GetStream(csEntry);
    447 }
    448 CPDF_IconFit CPDF_ApSettings::GetIconFit()
    449 {
    450     if (m_pDict == NULL) {
    451         return NULL;
    452     }
    453     return m_pDict->GetDict(FX_BSTRC("IF"));
    454 }
    455 int CPDF_ApSettings::GetTextPosition()
    456 {
    457     if (m_pDict == NULL) {
    458         return TEXTPOS_CAPTION;
    459     }
    460     return m_pDict->GetInteger(FX_BSTRC("TP"), TEXTPOS_CAPTION);
    461 }
    462