Home | History | Annotate | Download | only in fpdfsdk
      1 // Copyright 2016 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 "fpdfsdk/cpdfsdk_widget.h"
      8 
      9 #include <memory>
     10 #include <sstream>
     11 
     12 #include "core/fpdfapi/parser/cpdf_array.h"
     13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     14 #include "core/fpdfapi/parser/cpdf_document.h"
     15 #include "core/fpdfapi/parser/cpdf_reference.h"
     16 #include "core/fpdfapi/parser/cpdf_stream.h"
     17 #include "core/fpdfapi/parser/cpdf_string.h"
     18 #include "core/fpdfdoc/cpdf_defaultappearance.h"
     19 #include "core/fpdfdoc/cpdf_formcontrol.h"
     20 #include "core/fpdfdoc/cpdf_formfield.h"
     21 #include "core/fpdfdoc/cpdf_iconfit.h"
     22 #include "core/fpdfdoc/cpdf_interform.h"
     23 #include "core/fxge/cfx_graphstatedata.h"
     24 #include "core/fxge/cfx_pathdata.h"
     25 #include "core/fxge/cfx_renderdevice.h"
     26 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
     27 #include "fpdfsdk/cpdfsdk_interform.h"
     28 #include "fpdfsdk/cpdfsdk_pageview.h"
     29 #include "fpdfsdk/formfiller/cba_fontmap.h"
     30 #include "fpdfsdk/fsdk_actionhandler.h"
     31 #include "fpdfsdk/fsdk_define.h"
     32 #include "fpdfsdk/pwl/cpwl_appstream.h"
     33 #include "fpdfsdk/pwl/cpwl_edit.h"
     34 
     35 #ifdef PDF_ENABLE_XFA
     36 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
     37 #include "xfa/fxfa/cxfa_eventparam.h"
     38 #include "xfa/fxfa/cxfa_ffdocview.h"
     39 #include "xfa/fxfa/cxfa_ffwidget.h"
     40 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
     41 #include "xfa/fxfa/cxfa_widgetacc.h"
     42 #include "xfa/fxfa/parser/cxfa_node.h"
     43 #endif  // PDF_ENABLE_XFA
     44 
     45 namespace {
     46 
     47 // Convert a FX_ARGB to a FX_COLORREF.
     48 FX_COLORREF ARGBToColorRef(FX_ARGB argb) {
     49   return (((static_cast<uint32_t>(argb) & 0x00FF0000) >> 16) |
     50           (static_cast<uint32_t>(argb) & 0x0000FF00) |
     51           ((static_cast<uint32_t>(argb) & 0x000000FF) << 16));
     52 }
     53 
     54 }  // namespace
     55 
     56 CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot,
     57                                CPDFSDK_PageView* pPageView,
     58                                CPDFSDK_InterForm* pInterForm)
     59     : CPDFSDK_BAAnnot(pAnnot, pPageView),
     60       m_pInterForm(pInterForm),
     61       m_nAppearanceAge(0),
     62       m_nValueAge(0)
     63 #ifdef PDF_ENABLE_XFA
     64       ,
     65       m_hMixXFAWidget(nullptr),
     66       m_pWidgetHandler(nullptr)
     67 #endif  // PDF_ENABLE_XFA
     68 {
     69 }
     70 
     71 CPDFSDK_Widget::~CPDFSDK_Widget() {}
     72 
     73 #ifdef PDF_ENABLE_XFA
     74 CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const {
     75   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
     76   if (pContext->GetFormType() == FormType::kXFAForeground) {
     77     if (!m_hMixXFAWidget) {
     78       if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) {
     79         WideString sName;
     80         if (GetFieldType() == FormFieldType::kRadioButton) {
     81           sName = GetAnnotName();
     82           if (sName.IsEmpty())
     83             sName = GetName();
     84         } else {
     85           sName = GetName();
     86         }
     87 
     88         if (!sName.IsEmpty())
     89           m_hMixXFAWidget = pDocView->GetWidgetByName(sName, nullptr);
     90       }
     91     }
     92     return m_hMixXFAWidget.Get();
     93   }
     94   return nullptr;
     95 }
     96 
     97 CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() {
     98   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
     99   if (pContext->GetFormType() != FormType::kXFAForeground)
    100     return nullptr;
    101 
    102   CXFA_FFDocView* pDocView = pContext->GetXFADocView();
    103   if (!pDocView)
    104     return nullptr;
    105 
    106   WideString sName = GetName();
    107   return !sName.IsEmpty() ? pDocView->GetWidgetByName(sName, nullptr) : nullptr;
    108 }
    109 
    110 CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
    111   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    112   if (pContext->GetFormType() != FormType::kXFAForeground)
    113     return nullptr;
    114 
    115   if (!m_pWidgetHandler) {
    116     CXFA_FFDocView* pDocView = pContext->GetXFADocView();
    117     if (pDocView)
    118       m_pWidgetHandler = pDocView->GetWidgetHandler();
    119   }
    120   return m_pWidgetHandler.Get();
    121 }
    122 
    123 static XFA_EVENTTYPE GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT) {
    124   XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
    125 
    126   switch (eXFAAAT) {
    127     case PDFSDK_XFA_Click:
    128       eEventType = XFA_EVENT_Click;
    129       break;
    130     case PDFSDK_XFA_Full:
    131       eEventType = XFA_EVENT_Full;
    132       break;
    133     case PDFSDK_XFA_PreOpen:
    134       eEventType = XFA_EVENT_PreOpen;
    135       break;
    136     case PDFSDK_XFA_PostOpen:
    137       eEventType = XFA_EVENT_PostOpen;
    138       break;
    139   }
    140 
    141   return eEventType;
    142 }
    143 
    144 static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT,
    145                                      bool bWillCommit) {
    146   XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
    147 
    148   switch (eAAT) {
    149     case CPDF_AAction::CursorEnter:
    150       eEventType = XFA_EVENT_MouseEnter;
    151       break;
    152     case CPDF_AAction::CursorExit:
    153       eEventType = XFA_EVENT_MouseExit;
    154       break;
    155     case CPDF_AAction::ButtonDown:
    156       eEventType = XFA_EVENT_MouseDown;
    157       break;
    158     case CPDF_AAction::ButtonUp:
    159       eEventType = XFA_EVENT_MouseUp;
    160       break;
    161     case CPDF_AAction::GetFocus:
    162       eEventType = XFA_EVENT_Enter;
    163       break;
    164     case CPDF_AAction::LoseFocus:
    165       eEventType = XFA_EVENT_Exit;
    166       break;
    167     case CPDF_AAction::PageOpen:
    168     case CPDF_AAction::PageClose:
    169     case CPDF_AAction::PageVisible:
    170     case CPDF_AAction::PageInvisible:
    171       break;
    172     case CPDF_AAction::KeyStroke:
    173       if (!bWillCommit)
    174         eEventType = XFA_EVENT_Change;
    175       break;
    176     case CPDF_AAction::Validate:
    177       eEventType = XFA_EVENT_Validate;
    178       break;
    179     case CPDF_AAction::OpenPage:
    180     case CPDF_AAction::ClosePage:
    181     case CPDF_AAction::Format:
    182     case CPDF_AAction::Calculate:
    183     case CPDF_AAction::CloseDocument:
    184     case CPDF_AAction::SaveDocument:
    185     case CPDF_AAction::DocumentSaved:
    186     case CPDF_AAction::PrintDocument:
    187     case CPDF_AAction::DocumentPrinted:
    188       break;
    189     case CPDF_AAction::NumberOfActions:
    190       NOTREACHED();
    191       break;
    192   }
    193 
    194   return eEventType;
    195 }
    196 
    197 bool CPDFSDK_Widget::HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) {
    198   CXFA_FFWidget* hWidget = GetMixXFAWidget();
    199   if (!hWidget)
    200     return false;
    201 
    202   CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler();
    203   if (!pXFAWidgetHandler)
    204     return false;
    205 
    206   XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
    207 
    208   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
    209       GetFieldType() == FormFieldType::kRadioButton) {
    210     if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
    211       if (pXFAWidgetHandler->HasEvent(hGroupWidget->GetNode()->GetWidgetAcc(),
    212                                       eEventType)) {
    213         return true;
    214       }
    215     }
    216   }
    217 
    218   return pXFAWidgetHandler->HasEvent(hWidget->GetNode()->GetWidgetAcc(),
    219                                      eEventType);
    220 }
    221 
    222 bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
    223                                   PDFSDK_FieldAction& data,
    224                                   CPDFSDK_PageView* pPageView) {
    225   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    226 
    227   CXFA_FFWidget* hWidget = GetMixXFAWidget();
    228   if (!hWidget)
    229     return false;
    230 
    231   XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
    232   if (eEventType == XFA_EVENT_Unknown)
    233     return false;
    234 
    235   CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler();
    236   if (!pXFAWidgetHandler)
    237     return false;
    238 
    239   CXFA_EventParam param;
    240   param.m_eType = eEventType;
    241   param.m_wsChange = data.sChange;
    242   param.m_iCommitKey = data.nCommitKey;
    243   param.m_bShift = data.bShift;
    244   param.m_iSelStart = data.nSelStart;
    245   param.m_iSelEnd = data.nSelEnd;
    246   param.m_wsFullText = data.sValue;
    247   param.m_bKeyDown = data.bKeyDown;
    248   param.m_bModifier = data.bModifier;
    249   param.m_wsNewText = data.sValue;
    250   if (data.nSelEnd > data.nSelStart)
    251     param.m_wsNewText.Delete(data.nSelStart, data.nSelEnd - data.nSelStart);
    252 
    253   for (const auto& c : data.sChange)
    254     param.m_wsNewText.Insert(data.nSelStart, c);
    255 
    256   param.m_wsPrevText = data.sValue;
    257   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
    258       GetFieldType() == FormFieldType::kRadioButton) {
    259     if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
    260       CXFA_WidgetAcc* pAcc = hGroupWidget->GetNode()->GetWidgetAcc();
    261       param.m_pTarget = pAcc;
    262       if (pXFAWidgetHandler->ProcessEvent(pAcc, &param) !=
    263           XFA_EVENTERROR_Success) {
    264         return false;
    265       }
    266     }
    267   }
    268   CXFA_WidgetAcc* pAcc = hWidget->GetNode()->GetWidgetAcc();
    269   param.m_pTarget = pAcc;
    270   int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
    271 
    272   if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
    273     pDocView->UpdateDocView();
    274 
    275   return nRet == XFA_EVENTERROR_Success;
    276 }
    277 
    278 void CPDFSDK_Widget::Synchronize(bool bSynchronizeElse) {
    279   CXFA_FFWidget* hWidget = GetMixXFAWidget();
    280   if (!hWidget)
    281     return;
    282 
    283   CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc();
    284   if (!pWidgetAcc)
    285     return;
    286 
    287   CPDF_FormField* pFormField = GetFormField();
    288   switch (GetFieldType()) {
    289     case FormFieldType::kCheckBox:
    290     case FormFieldType::kRadioButton: {
    291       CPDF_FormControl* pFormCtrl = GetFormControl();
    292       XFA_CHECKSTATE eCheckState =
    293           pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off;
    294       pWidgetAcc->SetCheckState(eCheckState, true);
    295       break;
    296     }
    297     case FormFieldType::kTextField:
    298       pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
    299       break;
    300     case FormFieldType::kListBox: {
    301       pWidgetAcc->ClearAllSelections();
    302 
    303       for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
    304         int nIndex = pFormField->GetSelectedIndex(i);
    305         if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
    306           pWidgetAcc->SetItemState(nIndex, true, false, false, true);
    307       }
    308       break;
    309     }
    310     case FormFieldType::kComboBox: {
    311       pWidgetAcc->ClearAllSelections();
    312 
    313       for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
    314         int nIndex = pFormField->GetSelectedIndex(i);
    315         if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
    316           pWidgetAcc->SetItemState(nIndex, true, false, false, true);
    317       }
    318       pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
    319       break;
    320     }
    321     default:
    322       break;
    323   }
    324 
    325   if (bSynchronizeElse) {
    326     CPDFXFA_Context* context = m_pPageView->GetFormFillEnv()->GetXFAContext();
    327     context->GetXFADocView()->ProcessValueChanged(pWidgetAcc);
    328   }
    329 }
    330 
    331 void CPDFSDK_Widget::SynchronizeXFAValue() {
    332   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    333   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
    334   if (!pXFADocView)
    335     return;
    336 
    337   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    338     if (GetXFAWidgetHandler()) {
    339       CPDFSDK_Widget::SynchronizeXFAValue(pXFADocView, hWidget, GetFormField(),
    340                                           GetFormControl());
    341     }
    342   }
    343 }
    344 
    345 void CPDFSDK_Widget::SynchronizeXFAItems() {
    346   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    347   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
    348   if (!pXFADocView)
    349     return;
    350 
    351   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    352     if (GetXFAWidgetHandler())
    353       SynchronizeXFAItems(pXFADocView, hWidget, GetFormField(), nullptr);
    354   }
    355 }
    356 
    357 void CPDFSDK_Widget::SynchronizeXFAValue(CXFA_FFDocView* pXFADocView,
    358                                          CXFA_FFWidget* hWidget,
    359                                          CPDF_FormField* pFormField,
    360                                          CPDF_FormControl* pFormControl) {
    361   ASSERT(hWidget);
    362   ASSERT(pFormControl);
    363 
    364   switch (pFormField->GetFieldType()) {
    365     case FormFieldType::kCheckBox: {
    366       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    367         pFormField->CheckControl(
    368             pFormField->GetControlIndex(pFormControl),
    369             pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true);
    370       }
    371       break;
    372     }
    373     case FormFieldType::kRadioButton: {
    374       // TODO(weili): Check whether we need to handle checkbox and radio
    375       // button differently, otherwise, merge these two cases.
    376       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    377         pFormField->CheckControl(
    378             pFormField->GetControlIndex(pFormControl),
    379             pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true);
    380       }
    381       break;
    382     }
    383     case FormFieldType::kTextField: {
    384       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    385         pFormField->SetValue(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display),
    386                              true);
    387       }
    388       break;
    389     }
    390     case FormFieldType::kListBox: {
    391       pFormField->ClearSelection(false);
    392 
    393       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    394         for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
    395           int nIndex = pWidgetAcc->GetSelectedItem(i);
    396 
    397           if (nIndex > -1 && nIndex < pFormField->CountOptions()) {
    398             pFormField->SetItemSelection(nIndex, true, true);
    399           }
    400         }
    401       }
    402       break;
    403     }
    404     case FormFieldType::kComboBox: {
    405       pFormField->ClearSelection(false);
    406 
    407       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    408         for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
    409           int nIndex = pWidgetAcc->GetSelectedItem(i);
    410 
    411           if (nIndex > -1 && nIndex < pFormField->CountOptions()) {
    412             pFormField->SetItemSelection(nIndex, true, true);
    413           }
    414         }
    415         pFormField->SetValue(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display),
    416                              true);
    417       }
    418       break;
    419     }
    420     default:
    421       break;
    422   }
    423 }
    424 
    425 void CPDFSDK_Widget::SynchronizeXFAItems(CXFA_FFDocView* pXFADocView,
    426                                          CXFA_FFWidget* hWidget,
    427                                          CPDF_FormField* pFormField,
    428                                          CPDF_FormControl* pFormControl) {
    429   ASSERT(hWidget);
    430 
    431   switch (pFormField->GetFieldType()) {
    432     case FormFieldType::kListBox: {
    433       pFormField->ClearSelection(false);
    434       pFormField->ClearOptions(true);
    435 
    436       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    437         for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz;
    438              i++) {
    439           pFormField->InsertOption(
    440               pWidgetAcc->GetChoiceListItem(i, false).value_or(L""), i, true);
    441         }
    442       }
    443       break;
    444     }
    445     case FormFieldType::kComboBox: {
    446       pFormField->ClearSelection(false);
    447       pFormField->ClearOptions(false);
    448 
    449       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    450         for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz;
    451              i++) {
    452           pFormField->InsertOption(
    453               pWidgetAcc->GetChoiceListItem(i, false).value_or(L""), i, false);
    454         }
    455       }
    456 
    457       pFormField->SetValue(L"", true);
    458       break;
    459     }
    460     default:
    461       break;
    462   }
    463 }
    464 #endif  // PDF_ENABLE_XFA
    465 
    466 bool CPDFSDK_Widget::IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode) {
    467   CPDF_Dictionary* pAP = m_pAnnot->GetAnnotDict()->GetDictFor("AP");
    468   if (!pAP)
    469     return false;
    470 
    471   // Choose the right sub-ap
    472   const char* ap_entry = "N";
    473   if (mode == CPDF_Annot::Down)
    474     ap_entry = "D";
    475   else if (mode == CPDF_Annot::Rollover)
    476     ap_entry = "R";
    477   if (!pAP->KeyExist(ap_entry))
    478     ap_entry = "N";
    479 
    480   // Get the AP stream or subdirectory
    481   CPDF_Object* psub = pAP->GetDirectObjectFor(ap_entry);
    482   if (!psub)
    483     return false;
    484 
    485   FormFieldType fieldType = GetFieldType();
    486   switch (fieldType) {
    487     case FormFieldType::kPushButton:
    488     case FormFieldType::kComboBox:
    489     case FormFieldType::kListBox:
    490     case FormFieldType::kTextField:
    491     case FormFieldType::kSignature:
    492       return psub->IsStream();
    493     case FormFieldType::kCheckBox:
    494     case FormFieldType::kRadioButton:
    495       if (CPDF_Dictionary* pSubDict = psub->AsDictionary()) {
    496         return !!pSubDict->GetStreamFor(GetAppState());
    497       }
    498       return false;
    499     default:
    500       return true;
    501   }
    502 }
    503 
    504 FormFieldType CPDFSDK_Widget::GetFieldType() const {
    505   CPDF_FormField* pField = GetFormField();
    506   return pField ? pField->GetFieldType() : FormFieldType::kUnknown;
    507 }
    508 
    509 bool CPDFSDK_Widget::IsAppearanceValid() {
    510 #ifdef PDF_ENABLE_XFA
    511   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    512   FormType formType = pContext->GetFormType();
    513   if (formType == FormType::kXFAFull)
    514     return true;
    515 #endif  // PDF_ENABLE_XFA
    516   return CPDFSDK_BAAnnot::IsAppearanceValid();
    517 }
    518 
    519 int CPDFSDK_Widget::GetLayoutOrder() const {
    520   return 2;
    521 }
    522 
    523 int CPDFSDK_Widget::GetFieldFlags() const {
    524   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
    525   CPDF_FormControl* pFormControl =
    526       pPDFInterForm->GetControlByDict(m_pAnnot->GetAnnotDict());
    527   CPDF_FormField* pFormField = pFormControl->GetField();
    528   return pFormField->GetFieldFlags();
    529 }
    530 
    531 bool CPDFSDK_Widget::IsSignatureWidget() const {
    532   return GetFieldType() == FormFieldType::kSignature;
    533 }
    534 
    535 CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
    536   CPDF_FormControl* pControl = GetFormControl();
    537   return pControl ? pControl->GetField() : nullptr;
    538 }
    539 
    540 CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
    541   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
    542   return pPDFInterForm->GetControlByDict(GetAnnotDict());
    543 }
    544 
    545 CPDF_FormControl* CPDFSDK_Widget::GetFormControl(
    546     CPDF_InterForm* pInterForm,
    547     const CPDF_Dictionary* pAnnotDict) {
    548   ASSERT(pAnnotDict);
    549   return pInterForm->GetControlByDict(pAnnotDict);
    550 }
    551 
    552 int CPDFSDK_Widget::GetRotate() const {
    553   CPDF_FormControl* pCtrl = GetFormControl();
    554   return pCtrl->GetRotation() % 360;
    555 }
    556 
    557 #ifdef PDF_ENABLE_XFA
    558 WideString CPDFSDK_Widget::GetName() const {
    559   CPDF_FormField* pFormField = GetFormField();
    560   return pFormField->GetFullName();
    561 }
    562 #endif  // PDF_ENABLE_XFA
    563 
    564 bool CPDFSDK_Widget::GetFillColor(FX_COLORREF& color) const {
    565   CPDF_FormControl* pFormCtrl = GetFormControl();
    566   int iColorType = 0;
    567   color = ARGBToColorRef(pFormCtrl->GetBackgroundColor(iColorType));
    568   return iColorType != CFX_Color::kTransparent;
    569 }
    570 
    571 bool CPDFSDK_Widget::GetBorderColor(FX_COLORREF& color) const {
    572   CPDF_FormControl* pFormCtrl = GetFormControl();
    573   int iColorType = 0;
    574   color = ARGBToColorRef(pFormCtrl->GetBorderColor(iColorType));
    575   return iColorType != CFX_Color::kTransparent;
    576 }
    577 
    578 bool CPDFSDK_Widget::GetTextColor(FX_COLORREF& color) const {
    579   CPDF_FormControl* pFormCtrl = GetFormControl();
    580   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
    581   if (!da.HasColor())
    582     return false;
    583 
    584   FX_ARGB argb;
    585   int iColorType = CFX_Color::kTransparent;
    586   da.GetColor(argb, iColorType);
    587   color = ARGBToColorRef(argb);
    588   return iColorType != CFX_Color::kTransparent;
    589 }
    590 
    591 float CPDFSDK_Widget::GetFontSize() const {
    592   CPDF_FormControl* pFormCtrl = GetFormControl();
    593   CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance();
    594   float fFontSize;
    595   pDa.GetFont(&fFontSize);
    596   return fFontSize;
    597 }
    598 
    599 int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const {
    600 #ifdef PDF_ENABLE_XFA
    601   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    602     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    603       if (nIndex < pWidgetAcc->CountSelectedItems())
    604         return pWidgetAcc->GetSelectedItem(nIndex);
    605     }
    606   }
    607 #endif  // PDF_ENABLE_XFA
    608   CPDF_FormField* pFormField = GetFormField();
    609   return pFormField->GetSelectedIndex(nIndex);
    610 }
    611 
    612 #ifdef PDF_ENABLE_XFA
    613 WideString CPDFSDK_Widget::GetValue(bool bDisplay) const {
    614   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    615     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    616       return pWidgetAcc->GetValue(bDisplay ? XFA_VALUEPICTURE_Display
    617                                            : XFA_VALUEPICTURE_Edit);
    618     }
    619   }
    620 #else
    621 WideString CPDFSDK_Widget::GetValue() const {
    622 #endif  // PDF_ENABLE_XFA
    623   CPDF_FormField* pFormField = GetFormField();
    624   return pFormField->GetValue();
    625 }
    626 
    627 WideString CPDFSDK_Widget::GetDefaultValue() const {
    628   CPDF_FormField* pFormField = GetFormField();
    629   return pFormField->GetDefaultValue();
    630 }
    631 
    632 WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
    633   CPDF_FormField* pFormField = GetFormField();
    634   return pFormField->GetOptionLabel(nIndex);
    635 }
    636 
    637 int CPDFSDK_Widget::CountOptions() const {
    638   CPDF_FormField* pFormField = GetFormField();
    639   return pFormField->CountOptions();
    640 }
    641 
    642 bool CPDFSDK_Widget::IsOptionSelected(int nIndex) const {
    643 #ifdef PDF_ENABLE_XFA
    644   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    645     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
    646       if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
    647         return pWidgetAcc->GetItemState(nIndex);
    648 
    649       return false;
    650     }
    651   }
    652 #endif  // PDF_ENABLE_XFA
    653   CPDF_FormField* pFormField = GetFormField();
    654   return pFormField->IsItemSelected(nIndex);
    655 }
    656 
    657 int CPDFSDK_Widget::GetTopVisibleIndex() const {
    658   CPDF_FormField* pFormField = GetFormField();
    659   return pFormField->GetTopVisibleIndex();
    660 }
    661 
    662 bool CPDFSDK_Widget::IsChecked() const {
    663 #ifdef PDF_ENABLE_XFA
    664   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    665     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc())
    666       return pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On;
    667   }
    668 #endif  // PDF_ENABLE_XFA
    669   CPDF_FormControl* pFormCtrl = GetFormControl();
    670   return pFormCtrl->IsChecked();
    671 }
    672 
    673 int CPDFSDK_Widget::GetAlignment() const {
    674   CPDF_FormControl* pFormCtrl = GetFormControl();
    675   return pFormCtrl->GetControlAlignment();
    676 }
    677 
    678 int CPDFSDK_Widget::GetMaxLen() const {
    679   CPDF_FormField* pFormField = GetFormField();
    680   return pFormField->GetMaxLen();
    681 }
    682 
    683 void CPDFSDK_Widget::SetCheck(bool bChecked, bool bNotify) {
    684   CPDF_FormControl* pFormCtrl = GetFormControl();
    685   CPDF_FormField* pFormField = pFormCtrl->GetField();
    686   pFormField->CheckControl(pFormField->GetControlIndex(pFormCtrl), bChecked,
    687                            bNotify);
    688 #ifdef PDF_ENABLE_XFA
    689   if (!IsWidgetAppearanceValid(CPDF_Annot::Normal))
    690     ResetAppearance(true);
    691   if (!bNotify)
    692     Synchronize(true);
    693 #endif  // PDF_ENABLE_XFA
    694 }
    695 
    696 void CPDFSDK_Widget::SetValue(const WideString& sValue, bool bNotify) {
    697   CPDF_FormField* pFormField = GetFormField();
    698   pFormField->SetValue(sValue, bNotify);
    699 #ifdef PDF_ENABLE_XFA
    700   if (!bNotify)
    701     Synchronize(true);
    702 #endif  // PDF_ENABLE_XFA
    703 }
    704 
    705 void CPDFSDK_Widget::SetDefaultValue(const WideString& sValue) {}
    706 void CPDFSDK_Widget::SetOptionSelection(int index,
    707                                         bool bSelected,
    708                                         bool bNotify) {
    709   CPDF_FormField* pFormField = GetFormField();
    710   pFormField->SetItemSelection(index, bSelected, bNotify);
    711 #ifdef PDF_ENABLE_XFA
    712   if (!bNotify)
    713     Synchronize(true);
    714 #endif  // PDF_ENABLE_XFA
    715 }
    716 
    717 void CPDFSDK_Widget::ClearSelection(bool bNotify) {
    718   CPDF_FormField* pFormField = GetFormField();
    719   pFormField->ClearSelection(bNotify);
    720 #ifdef PDF_ENABLE_XFA
    721   if (!bNotify)
    722     Synchronize(true);
    723 #endif  // PDF_ENABLE_XFA
    724 }
    725 
    726 void CPDFSDK_Widget::SetTopVisibleIndex(int index) {}
    727 
    728 void CPDFSDK_Widget::SetAppModified() {
    729   m_bAppModified = true;
    730 }
    731 
    732 void CPDFSDK_Widget::ClearAppModified() {
    733   m_bAppModified = false;
    734 }
    735 
    736 bool CPDFSDK_Widget::IsAppModified() const {
    737   return m_bAppModified;
    738 }
    739 
    740 #ifdef PDF_ENABLE_XFA
    741 void CPDFSDK_Widget::ResetAppearance(bool bValueChanged) {
    742   switch (GetFieldType()) {
    743     case FormFieldType::kTextField:
    744     case FormFieldType::kComboBox: {
    745       bool bFormatted = false;
    746       WideString sValue = OnFormat(bFormatted);
    747       ResetAppearance(bFormatted ? &sValue : nullptr, true);
    748       break;
    749     }
    750     default:
    751       ResetAppearance(nullptr, false);
    752       break;
    753   }
    754 }
    755 #endif  // PDF_ENABLE_XFA
    756 
    757 void CPDFSDK_Widget::ResetAppearance(const WideString* sValue,
    758                                      bool bValueChanged) {
    759   SetAppModified();
    760 
    761   m_nAppearanceAge++;
    762   if (bValueChanged)
    763     m_nValueAge++;
    764 
    765   CPWL_AppStream appStream(this, GetAPDict());
    766   switch (GetFieldType()) {
    767     case FormFieldType::kPushButton:
    768       appStream.SetAsPushButton();
    769       break;
    770     case FormFieldType::kCheckBox:
    771       appStream.SetAsCheckBox();
    772       break;
    773     case FormFieldType::kRadioButton:
    774       appStream.SetAsRadioButton();
    775       break;
    776     case FormFieldType::kComboBox:
    777       appStream.SetAsComboBox(sValue);
    778       break;
    779     case FormFieldType::kListBox:
    780       appStream.SetAsListBox();
    781       break;
    782     case FormFieldType::kTextField:
    783       appStream.SetAsTextField(sValue);
    784       break;
    785     default:
    786       break;
    787   }
    788 
    789   m_pAnnot->ClearCachedAP();
    790 }
    791 
    792 WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) {
    793   CPDF_FormField* pFormField = GetFormField();
    794   ASSERT(pFormField);
    795   return m_pInterForm->OnFormat(pFormField, bFormatted);
    796 }
    797 
    798 void CPDFSDK_Widget::ResetFieldAppearance(bool bValueChanged) {
    799   CPDF_FormField* pFormField = GetFormField();
    800   ASSERT(pFormField);
    801   m_pInterForm->ResetFieldAppearance(pFormField, nullptr, bValueChanged);
    802 }
    803 
    804 void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice,
    805                                     const CFX_Matrix& mtUser2Device,
    806                                     CPDF_Annot::AppearanceMode mode,
    807                                     const CPDF_RenderOptions* pOptions) {
    808   FormFieldType fieldType = GetFieldType();
    809 
    810   if ((fieldType == FormFieldType::kCheckBox ||
    811        fieldType == FormFieldType::kRadioButton) &&
    812       mode == CPDF_Annot::Normal &&
    813       !IsWidgetAppearanceValid(CPDF_Annot::Normal)) {
    814     CFX_PathData pathData;
    815 
    816     CFX_FloatRect rcAnnot = GetRect();
    817 
    818     pathData.AppendRect(rcAnnot.left, rcAnnot.bottom, rcAnnot.right,
    819                         rcAnnot.top);
    820 
    821     CFX_GraphStateData gsd;
    822     gsd.m_LineWidth = 0.0f;
    823 
    824     pDevice->DrawPath(&pathData, &mtUser2Device, &gsd, 0, 0xFFAAAAAA,
    825                       FXFILL_ALTERNATE);
    826   } else {
    827     CPDFSDK_BAAnnot::DrawAppearance(pDevice, mtUser2Device, mode, pOptions);
    828   }
    829 }
    830 
    831 void CPDFSDK_Widget::UpdateField() {
    832   CPDF_FormField* pFormField = GetFormField();
    833   ASSERT(pFormField);
    834   m_pInterForm->UpdateField(pFormField);
    835 }
    836 
    837 void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice,
    838                                 CPDFSDK_PageView* pPageView) {
    839   FormFieldType fieldType = GetFieldType();
    840   if (!m_pInterForm->IsNeedHighLight(fieldType))
    841     return;
    842 
    843   CFX_Matrix page2device;
    844   pPageView->GetCurrentMatrix(page2device);
    845 
    846   CFX_FloatRect rcDevice = GetRect();
    847   CFX_PointF tmp =
    848       page2device.Transform(CFX_PointF(rcDevice.left, rcDevice.bottom));
    849   rcDevice.left = tmp.x;
    850   rcDevice.bottom = tmp.y;
    851 
    852   tmp = page2device.Transform(CFX_PointF(rcDevice.right, rcDevice.top));
    853   rcDevice.right = tmp.x;
    854   rcDevice.top = tmp.y;
    855   rcDevice.Normalize();
    856 
    857   FX_RECT rcDev = rcDevice.ToFxRect();
    858   pDevice->FillRect(
    859       &rcDev, ArgbEncode(static_cast<int>(m_pInterForm->GetHighlightAlpha()),
    860                          m_pInterForm->GetHighlightColor(fieldType)));
    861 }
    862 
    863 CFX_FloatRect CPDFSDK_Widget::GetClientRect() const {
    864   CFX_FloatRect rcWindow = GetRotatedRect();
    865   float fBorderWidth = (float)GetBorderWidth();
    866   switch (GetBorderStyle()) {
    867     case BorderStyle::BEVELED:
    868     case BorderStyle::INSET:
    869       fBorderWidth *= 2.0f;
    870       break;
    871     default:
    872       break;
    873   }
    874   return rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
    875 }
    876 
    877 CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const {
    878   CFX_FloatRect rectAnnot = GetRect();
    879   float fWidth = rectAnnot.right - rectAnnot.left;
    880   float fHeight = rectAnnot.top - rectAnnot.bottom;
    881 
    882   CPDF_FormControl* pControl = GetFormControl();
    883   CFX_FloatRect rcPDFWindow;
    884   switch (abs(pControl->GetRotation() % 360)) {
    885     case 0:
    886     case 180:
    887     default:
    888       rcPDFWindow = CFX_FloatRect(0, 0, fWidth, fHeight);
    889       break;
    890     case 90:
    891     case 270:
    892       rcPDFWindow = CFX_FloatRect(0, 0, fHeight, fWidth);
    893       break;
    894   }
    895 
    896   return rcPDFWindow;
    897 }
    898 
    899 CFX_Matrix CPDFSDK_Widget::GetMatrix() const {
    900   CFX_Matrix mt;
    901   CPDF_FormControl* pControl = GetFormControl();
    902   CFX_FloatRect rcAnnot = GetRect();
    903   float fWidth = rcAnnot.right - rcAnnot.left;
    904   float fHeight = rcAnnot.top - rcAnnot.bottom;
    905 
    906   switch (abs(pControl->GetRotation() % 360)) {
    907     default:
    908     case 0:
    909       break;
    910     case 90:
    911       mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0);
    912       break;
    913     case 180:
    914       mt = CFX_Matrix(-1, 0, 0, -1, fWidth, fHeight);
    915       break;
    916     case 270:
    917       mt = CFX_Matrix(0, -1, 1, 0, 0, fHeight);
    918       break;
    919   }
    920 
    921   return mt;
    922 }
    923 
    924 CFX_Color CPDFSDK_Widget::GetTextPWLColor() const {
    925   CFX_Color crText = CFX_Color(CFX_Color::kGray, 0);
    926 
    927   CPDF_FormControl* pFormCtrl = GetFormControl();
    928   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
    929   if (da.HasColor()) {
    930     int32_t iColorType;
    931     float fc[4];
    932     da.GetColor(iColorType, fc);
    933     crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
    934   }
    935 
    936   return crText;
    937 }
    938 
    939 CFX_Color CPDFSDK_Widget::GetBorderPWLColor() const {
    940   CFX_Color crBorder;
    941 
    942   CPDF_FormControl* pFormCtrl = GetFormControl();
    943   int32_t iColorType;
    944   float fc[4];
    945   pFormCtrl->GetOriginalBorderColor(iColorType, fc);
    946   if (iColorType > 0)
    947     crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
    948 
    949   return crBorder;
    950 }
    951 
    952 CFX_Color CPDFSDK_Widget::GetFillPWLColor() const {
    953   CFX_Color crFill;
    954 
    955   CPDF_FormControl* pFormCtrl = GetFormControl();
    956   int32_t iColorType;
    957   float fc[4];
    958   pFormCtrl->GetOriginalBackgroundColor(iColorType, fc);
    959   if (iColorType > 0)
    960     crFill = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
    961 
    962   return crFill;
    963 }
    964 
    965 bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
    966                                PDFSDK_FieldAction& data,
    967                                CPDFSDK_PageView* pPageView) {
    968   CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv();
    969 
    970 #ifdef PDF_ENABLE_XFA
    971   CPDFXFA_Context* pContext = pFormFillEnv->GetXFAContext();
    972   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    973     XFA_EVENTTYPE eEventType = GetXFAEventType(type, data.bWillCommit);
    974 
    975     if (eEventType != XFA_EVENT_Unknown) {
    976       if (CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) {
    977         CXFA_EventParam param;
    978         param.m_eType = eEventType;
    979         param.m_wsChange = data.sChange;
    980         param.m_iCommitKey = data.nCommitKey;
    981         param.m_bShift = data.bShift;
    982         param.m_iSelStart = data.nSelStart;
    983         param.m_iSelEnd = data.nSelEnd;
    984         param.m_wsFullText = data.sValue;
    985         param.m_bKeyDown = data.bKeyDown;
    986         param.m_bModifier = data.bModifier;
    987         param.m_wsNewText = data.sValue;
    988         if (data.nSelEnd > data.nSelStart)
    989           param.m_wsNewText.Delete(data.nSelStart,
    990                                    data.nSelEnd - data.nSelStart);
    991         for (int i = data.sChange.GetLength() - 1; i >= 0; i--)
    992           param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
    993         param.m_wsPrevText = data.sValue;
    994 
    995         CXFA_WidgetAcc* pAcc = hWidget->GetNode()->GetWidgetAcc();
    996         param.m_pTarget = pAcc;
    997         int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
    998 
    999         if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
   1000           pDocView->UpdateDocView();
   1001 
   1002         if (nRet == XFA_EVENTERROR_Success)
   1003           return true;
   1004       }
   1005     }
   1006   }
   1007 #endif  // PDF_ENABLE_XFA
   1008 
   1009   CPDF_Action action = GetAAction(type);
   1010   if (action.GetDict() && action.GetType() != CPDF_Action::Unknown) {
   1011     CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler();
   1012     return pActionHandler->DoAction_Field(action, type, pFormFillEnv,
   1013                                           GetFormField(), data);
   1014   }
   1015   return false;
   1016 }
   1017 
   1018 CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) {
   1019   switch (eAAT) {
   1020     case CPDF_AAction::CursorEnter:
   1021     case CPDF_AAction::CursorExit:
   1022     case CPDF_AAction::ButtonDown:
   1023     case CPDF_AAction::ButtonUp:
   1024     case CPDF_AAction::GetFocus:
   1025     case CPDF_AAction::LoseFocus:
   1026     case CPDF_AAction::PageOpen:
   1027     case CPDF_AAction::PageClose:
   1028     case CPDF_AAction::PageVisible:
   1029     case CPDF_AAction::PageInvisible:
   1030       return CPDFSDK_BAAnnot::GetAAction(eAAT);
   1031 
   1032     case CPDF_AAction::KeyStroke:
   1033     case CPDF_AAction::Format:
   1034     case CPDF_AAction::Validate:
   1035     case CPDF_AAction::Calculate: {
   1036       CPDF_FormField* pField = GetFormField();
   1037       if (pField->GetAdditionalAction().GetDict())
   1038         return pField->GetAdditionalAction().GetAction(eAAT);
   1039       return CPDFSDK_BAAnnot::GetAAction(eAAT);
   1040     }
   1041     default:
   1042       break;
   1043   }
   1044 
   1045   return CPDF_Action(nullptr);
   1046 }
   1047 
   1048 WideString CPDFSDK_Widget::GetAlternateName() const {
   1049   CPDF_FormField* pFormField = GetFormField();
   1050   return pFormField->GetAlternateName();
   1051 }
   1052