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) {
    252         return CPDF_Action();
    253     }
    254     if (m_pWidgetDict->KeyExist("A")) {
    255         return CPDF_Action(m_pWidgetDict->GetDict("A"));
    256     }
    257     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "A");
    258     if (!pObj) {
    259         return CPDF_Action();
    260     }
    261     return CPDF_Action(pObj->GetDict());
    262 }
    263 CPDF_AAction CPDF_FormControl::GetAdditionalAction()
    264 {
    265     if (m_pWidgetDict == NULL) {
    266         return NULL;
    267     }
    268     if (m_pWidgetDict->KeyExist("AA")) {
    269         return m_pWidgetDict->GetDict("AA");
    270     } else {
    271         return m_pField->GetAdditionalAction();
    272     }
    273 }
    274 CPDF_DefaultAppearance CPDF_FormControl::GetDefaultAppearance()
    275 {
    276     if (m_pWidgetDict == NULL) {
    277         return CFX_ByteString();
    278     }
    279     if (m_pWidgetDict->KeyExist("DA")) {
    280         return m_pWidgetDict->GetString("DA");
    281     } else {
    282         CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "DA");
    283         if (pObj == NULL) {
    284             return m_pField->m_pForm->GetDefaultAppearance();
    285         }
    286         return pObj->GetString();
    287     }
    288 }
    289 CPDF_Font* CPDF_FormControl::GetDefaultControlFont()
    290 {
    291     CPDF_DefaultAppearance cDA = GetDefaultAppearance();
    292     CFX_ByteString csFontNameTag;
    293     FX_FLOAT fFontSize;
    294     cDA.GetFont(csFontNameTag, fFontSize);
    295     if (csFontNameTag.IsEmpty()) {
    296         return NULL;
    297     }
    298     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pWidgetDict, "DR");
    299     if (pObj != NULL && pObj->GetType() == PDFOBJ_DICTIONARY) {
    300         CPDF_Dictionary* pFonts = ((CPDF_Dictionary*)pObj)->GetDict("Font");
    301         if (pFonts != NULL) {
    302             CPDF_Dictionary *pElement = pFonts->GetDict(csFontNameTag);
    303             CPDF_Font *pFont = m_pField->m_pForm->m_pDocument->LoadFont(pElement);
    304             if (pFont != NULL) {
    305                 return pFont;
    306             }
    307         }
    308     }
    309     CPDF_Font *pFont = m_pField->m_pForm->GetFormFont(csFontNameTag);
    310     if (pFont != NULL) {
    311         return pFont;
    312     }
    313     CPDF_Dictionary *pPageDict = m_pWidgetDict->GetDict("P");
    314     pObj = FPDF_GetFieldAttr(pPageDict, "Resources");
    315     if (pObj != NULL && pObj->GetType() == PDFOBJ_DICTIONARY) {
    316         CPDF_Dictionary* pFonts = ((CPDF_Dictionary*)pObj)->GetDict("Font");
    317         if (pFonts != NULL) {
    318             CPDF_Dictionary *pElement = pFonts->GetDict(csFontNameTag);
    319             CPDF_Font *pFont = m_pField->m_pForm->m_pDocument->LoadFont(pElement);
    320             if (pFont != NULL) {
    321                 return pFont;
    322             }
    323         }
    324     }
    325     return NULL;
    326 }
    327 int CPDF_FormControl::GetControlAlignment()
    328 {
    329     if (m_pWidgetDict == NULL) {
    330         return 0;
    331     }
    332     if (m_pWidgetDict->KeyExist("Q")) {
    333         return m_pWidgetDict->GetInteger("Q", 0);
    334     } else {
    335         CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "Q");
    336         if (pObj == NULL) {
    337             return m_pField->m_pForm->GetFormAlignment();
    338         }
    339         return pObj->GetInteger();
    340     }
    341 }
    342 FX_BOOL CPDF_ApSettings::HasMKEntry(FX_BSTR csEntry)
    343 {
    344     if (m_pDict == NULL) {
    345         return FALSE;
    346     }
    347     return m_pDict->KeyExist(csEntry);
    348 }
    349 int CPDF_ApSettings::GetRotation()
    350 {
    351     if (m_pDict == NULL) {
    352         return 0;
    353     }
    354     return m_pDict->GetInteger(FX_BSTRC("R"));
    355 }
    356 FX_ARGB CPDF_ApSettings::GetColor(int& iColorType, FX_BSTR csEntry)
    357 {
    358     iColorType = COLORTYPE_TRANSPARENT;
    359     if (m_pDict == NULL) {
    360         return 0;
    361     }
    362     FX_ARGB color = 0;
    363     CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
    364     if (pEntry == NULL) {
    365         return color;
    366     }
    367     FX_DWORD dwCount = pEntry->GetCount();
    368     if (dwCount == 1) {
    369         iColorType = COLORTYPE_GRAY;
    370         FX_FLOAT g = pEntry->GetNumber(0) * 255;
    371         color = ArgbEncode(255, (int)g, (int)g, (int)g);
    372     } else if (dwCount == 3) {
    373         iColorType = COLORTYPE_RGB;
    374         FX_FLOAT r = pEntry->GetNumber(0) * 255;
    375         FX_FLOAT g = pEntry->GetNumber(1) * 255;
    376         FX_FLOAT b = pEntry->GetNumber(2) * 255;
    377         color = ArgbEncode(255, (int)r, (int)g, (int)b);
    378     } else if (dwCount == 4) {
    379         iColorType = COLORTYPE_CMYK;
    380         FX_FLOAT c = pEntry->GetNumber(0);
    381         FX_FLOAT m = pEntry->GetNumber(1);
    382         FX_FLOAT y = pEntry->GetNumber(2);
    383         FX_FLOAT k = pEntry->GetNumber(3);
    384         FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k);
    385         FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k);
    386         FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k);
    387         color = ArgbEncode(255, (int)(r * 255), (int)(g * 255), (int)(b * 255));
    388     }
    389     return color;
    390 }
    391 FX_FLOAT CPDF_ApSettings::GetOriginalColor(int index, FX_BSTR csEntry)
    392 {
    393     if (m_pDict == NULL) {
    394         return 0;
    395     }
    396     CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
    397     if (pEntry != NULL) {
    398         return pEntry->GetNumber(index);
    399     }
    400     return 0;
    401 }
    402 void CPDF_ApSettings::GetOriginalColor(int& iColorType, FX_FLOAT fc[4], FX_BSTR csEntry)
    403 {
    404     iColorType = COLORTYPE_TRANSPARENT;
    405     for (int i = 0; i < 4; i ++) {
    406         fc[i] = 0;
    407     }
    408     if (m_pDict == NULL) {
    409         return;
    410     }
    411     CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
    412     if (pEntry == NULL) {
    413         return;
    414     }
    415     FX_DWORD dwCount = pEntry->GetCount();
    416     if (dwCount == 1) {
    417         iColorType = COLORTYPE_GRAY;
    418         fc[0] = pEntry->GetNumber(0);
    419     } else if (dwCount == 3) {
    420         iColorType = COLORTYPE_RGB;
    421         fc[0] = pEntry->GetNumber(0);
    422         fc[1] = pEntry->GetNumber(1);
    423         fc[2] = pEntry->GetNumber(2);
    424     } else if (dwCount == 4) {
    425         iColorType = COLORTYPE_CMYK;
    426         fc[0] = pEntry->GetNumber(0);
    427         fc[1] = pEntry->GetNumber(1);
    428         fc[2] = pEntry->GetNumber(2);
    429         fc[3] = pEntry->GetNumber(3);
    430     }
    431 }
    432 CFX_WideString CPDF_ApSettings::GetCaption(FX_BSTR csEntry)
    433 {
    434     CFX_WideString csCaption;
    435     if (m_pDict == NULL) {
    436         return csCaption;
    437     }
    438     return m_pDict->GetUnicodeText(csEntry);
    439 }
    440 CPDF_Stream* CPDF_ApSettings::GetIcon(FX_BSTR csEntry)
    441 {
    442     if (m_pDict == NULL) {
    443         return NULL;
    444     }
    445     return m_pDict->GetStream(csEntry);
    446 }
    447 CPDF_IconFit CPDF_ApSettings::GetIconFit()
    448 {
    449     if (m_pDict == NULL) {
    450         return NULL;
    451     }
    452     return m_pDict->GetDict(FX_BSTRC("IF"));
    453 }
    454 int CPDF_ApSettings::GetTextPosition()
    455 {
    456     if (m_pDict == NULL) {
    457         return TEXTPOS_CAPTION;
    458     }
    459     return m_pDict->GetInteger(FX_BSTRC("TP"), TEXTPOS_CAPTION);
    460 }
    461