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 
     11 #include "core/fpdfapi/parser/cpdf_array.h"
     12 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     13 #include "core/fpdfapi/parser/cpdf_document.h"
     14 #include "core/fpdfapi/parser/cpdf_reference.h"
     15 #include "core/fpdfapi/parser/cpdf_stream.h"
     16 #include "core/fpdfapi/parser/cpdf_string.h"
     17 #include "core/fpdfdoc/cpdf_defaultappearance.h"
     18 #include "core/fpdfdoc/cpdf_formcontrol.h"
     19 #include "core/fpdfdoc/cpdf_formfield.h"
     20 #include "core/fpdfdoc/cpdf_iconfit.h"
     21 #include "core/fpdfdoc/cpdf_interform.h"
     22 #include "core/fxge/cfx_graphstatedata.h"
     23 #include "core/fxge/cfx_pathdata.h"
     24 #include "core/fxge/cfx_renderdevice.h"
     25 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
     26 #include "fpdfsdk/cpdfsdk_interform.h"
     27 #include "fpdfsdk/cpdfsdk_pageview.h"
     28 #include "fpdfsdk/formfiller/cba_fontmap.h"
     29 #include "fpdfsdk/fsdk_actionhandler.h"
     30 #include "fpdfsdk/fsdk_define.h"
     31 #include "fpdfsdk/fxedit/fxet_edit.h"
     32 #include "fpdfsdk/pdfwindow/PWL_Edit.h"
     33 #include "fpdfsdk/pdfwindow/PWL_Utils.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/fxfa_widget.h"
     39 #include "xfa/fxfa/xfa_ffdocview.h"
     40 #include "xfa/fxfa/xfa_ffwidget.h"
     41 #include "xfa/fxfa/xfa_ffwidgethandler.h"
     42 #endif  // PDF_ENABLE_XFA
     43 
     44 namespace {
     45 
     46 // Convert a FX_ARGB to a FX_COLORREF.
     47 FX_COLORREF ARGBToColorRef(FX_ARGB argb) {
     48   return (((static_cast<uint32_t>(argb) & 0x00FF0000) >> 16) |
     49           (static_cast<uint32_t>(argb) & 0x0000FF00) |
     50           ((static_cast<uint32_t>(argb) & 0x000000FF) << 16));
     51 }
     52 
     53 }  // namespace
     54 
     55 CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot,
     56                                CPDFSDK_PageView* pPageView,
     57                                CPDFSDK_InterForm* pInterForm)
     58     : CPDFSDK_BAAnnot(pAnnot, pPageView),
     59       m_pInterForm(pInterForm),
     60       m_nAppAge(0),
     61       m_nValueAge(0)
     62 #ifdef PDF_ENABLE_XFA
     63       ,
     64       m_hMixXFAWidget(nullptr),
     65       m_pWidgetHandler(nullptr)
     66 #endif  // PDF_ENABLE_XFA
     67 {
     68 }
     69 
     70 CPDFSDK_Widget::~CPDFSDK_Widget() {}
     71 
     72 #ifdef PDF_ENABLE_XFA
     73 CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const {
     74   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
     75   if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) {
     76     if (!m_hMixXFAWidget) {
     77       if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) {
     78         CFX_WideString sName;
     79         if (GetFieldType() == FIELDTYPE_RADIOBUTTON) {
     80           sName = GetAnnotName();
     81           if (sName.IsEmpty())
     82             sName = GetName();
     83         } else {
     84           sName = GetName();
     85         }
     86 
     87         if (!sName.IsEmpty())
     88           m_hMixXFAWidget = pDocView->GetWidgetByName(sName, nullptr);
     89       }
     90     }
     91     return m_hMixXFAWidget;
     92   }
     93 
     94   return nullptr;
     95 }
     96 
     97 CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() {
     98   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
     99   if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) {
    100     if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) {
    101       CFX_WideString sName = GetName();
    102       if (!sName.IsEmpty())
    103         return pDocView->GetWidgetByName(sName, nullptr);
    104     }
    105   }
    106 
    107   return nullptr;
    108 }
    109 
    110 CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
    111   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    112   if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) {
    113     if (!m_pWidgetHandler) {
    114       if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
    115         m_pWidgetHandler = pDocView->GetWidgetHandler();
    116     }
    117     return m_pWidgetHandler;
    118   }
    119 
    120   return nullptr;
    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       break;
    169     case CPDF_AAction::PageClose:
    170       break;
    171     case CPDF_AAction::PageVisible:
    172       break;
    173     case CPDF_AAction::PageInvisible:
    174       break;
    175     case CPDF_AAction::KeyStroke:
    176       if (!bWillCommit)
    177         eEventType = XFA_EVENT_Change;
    178       break;
    179     case CPDF_AAction::Validate:
    180       eEventType = XFA_EVENT_Validate;
    181       break;
    182     case CPDF_AAction::OpenPage:
    183     case CPDF_AAction::ClosePage:
    184     case CPDF_AAction::Format:
    185     case CPDF_AAction::Calculate:
    186     case CPDF_AAction::CloseDocument:
    187     case CPDF_AAction::SaveDocument:
    188     case CPDF_AAction::DocumentSaved:
    189     case CPDF_AAction::PrintDocument:
    190     case CPDF_AAction::DocumentPrinted:
    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   CXFA_WidgetAcc* pAcc;
    209   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
    210       GetFieldType() == FIELDTYPE_RADIOBUTTON) {
    211     if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
    212       pAcc = hGroupWidget->GetDataAcc();
    213       if (pXFAWidgetHandler->HasEvent(pAcc, eEventType))
    214         return true;
    215     }
    216   }
    217 
    218   pAcc = hWidget->GetDataAcc();
    219   return pXFAWidgetHandler->HasEvent(pAcc, 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 (int i = 0; i < data.sChange.GetLength(); i++)
    254     param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
    255   param.m_wsPrevText = data.sValue;
    256 
    257   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
    258       GetFieldType() == FIELDTYPE_RADIOBUTTON) {
    259     if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
    260       CXFA_WidgetAcc* pAcc = hGroupWidget->GetDataAcc();
    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->GetDataAcc();
    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->GetDataAcc();
    284   if (!pWidgetAcc)
    285     return;
    286 
    287   CPDF_FormField* pFormField = GetFormField();
    288   switch (GetFieldType()) {
    289     case FIELDTYPE_CHECKBOX:
    290     case FIELDTYPE_RADIOBUTTON: {
    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 FIELDTYPE_TEXTFIELD:
    298       pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit);
    299       break;
    300     case FIELDTYPE_LISTBOX: {
    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())
    306           pWidgetAcc->SetItemState(nIndex, true, false, false, true);
    307       }
    308       break;
    309     }
    310     case FIELDTYPE_COMBOBOX: {
    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())
    316           pWidgetAcc->SetItemState(nIndex, true, false, false, true);
    317       }
    318       pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit);
    319       break;
    320     }
    321   }
    322 
    323   if (bSynchronizeElse)
    324     pWidgetAcc->ProcessValueChanged();
    325 }
    326 
    327 void CPDFSDK_Widget::SynchronizeXFAValue() {
    328   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    329   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
    330   if (!pXFADocView)
    331     return;
    332 
    333   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    334     if (GetXFAWidgetHandler()) {
    335       CPDFSDK_Widget::SynchronizeXFAValue(pXFADocView, hWidget, GetFormField(),
    336                                           GetFormControl());
    337     }
    338   }
    339 }
    340 
    341 void CPDFSDK_Widget::SynchronizeXFAItems() {
    342   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    343   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
    344   if (!pXFADocView)
    345     return;
    346 
    347   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    348     if (GetXFAWidgetHandler())
    349       SynchronizeXFAItems(pXFADocView, hWidget, GetFormField(), nullptr);
    350   }
    351 }
    352 
    353 void CPDFSDK_Widget::SynchronizeXFAValue(CXFA_FFDocView* pXFADocView,
    354                                          CXFA_FFWidget* hWidget,
    355                                          CPDF_FormField* pFormField,
    356                                          CPDF_FormControl* pFormControl) {
    357   ASSERT(hWidget);
    358   ASSERT(pFormControl);
    359 
    360   switch (pFormField->GetFieldType()) {
    361     case FIELDTYPE_CHECKBOX: {
    362       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    363         pFormField->CheckControl(
    364             pFormField->GetControlIndex(pFormControl),
    365             pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true);
    366       }
    367       break;
    368     }
    369     case FIELDTYPE_RADIOBUTTON: {
    370       // TODO(weili): Check whether we need to handle checkbox and radio
    371       // button differently, otherwise, merge these two cases.
    372       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    373         pFormField->CheckControl(
    374             pFormField->GetControlIndex(pFormControl),
    375             pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true);
    376       }
    377       break;
    378     }
    379     case FIELDTYPE_TEXTFIELD: {
    380       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    381         CFX_WideString sValue;
    382         pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display);
    383         pFormField->SetValue(sValue, true);
    384       }
    385       break;
    386     }
    387     case FIELDTYPE_LISTBOX: {
    388       pFormField->ClearSelection(false);
    389 
    390       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    391         for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
    392           int nIndex = pWidgetAcc->GetSelectedItem(i);
    393 
    394           if (nIndex > -1 && nIndex < pFormField->CountOptions()) {
    395             pFormField->SetItemSelection(nIndex, true, true);
    396           }
    397         }
    398       }
    399       break;
    400     }
    401     case FIELDTYPE_COMBOBOX: {
    402       pFormField->ClearSelection(false);
    403 
    404       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    405         for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
    406           int nIndex = pWidgetAcc->GetSelectedItem(i);
    407 
    408           if (nIndex > -1 && nIndex < pFormField->CountOptions()) {
    409             pFormField->SetItemSelection(nIndex, true, true);
    410           }
    411         }
    412 
    413         CFX_WideString sValue;
    414         pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display);
    415         pFormField->SetValue(sValue, true);
    416       }
    417       break;
    418     }
    419   }
    420 }
    421 
    422 void CPDFSDK_Widget::SynchronizeXFAItems(CXFA_FFDocView* pXFADocView,
    423                                          CXFA_FFWidget* hWidget,
    424                                          CPDF_FormField* pFormField,
    425                                          CPDF_FormControl* pFormControl) {
    426   ASSERT(hWidget);
    427 
    428   switch (pFormField->GetFieldType()) {
    429     case FIELDTYPE_LISTBOX: {
    430       pFormField->ClearSelection(false);
    431       pFormField->ClearOptions(true);
    432 
    433       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    434         for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz; i++) {
    435           CFX_WideString swText;
    436           pWidgetAcc->GetChoiceListItem(swText, i);
    437 
    438           pFormField->InsertOption(swText, i, true);
    439         }
    440       }
    441       break;
    442     }
    443     case FIELDTYPE_COMBOBOX: {
    444       pFormField->ClearSelection(false);
    445       pFormField->ClearOptions(false);
    446 
    447       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    448         for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz; i++) {
    449           CFX_WideString swText;
    450           pWidgetAcc->GetChoiceListItem(swText, i);
    451 
    452           pFormField->InsertOption(swText, i, false);
    453         }
    454       }
    455 
    456       pFormField->SetValue(L"", true);
    457       break;
    458     }
    459   }
    460 }
    461 #endif  // PDF_ENABLE_XFA
    462 
    463 bool CPDFSDK_Widget::IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode) {
    464   CPDF_Dictionary* pAP = m_pAnnot->GetAnnotDict()->GetDictFor("AP");
    465   if (!pAP)
    466     return false;
    467 
    468   // Choose the right sub-ap
    469   const FX_CHAR* ap_entry = "N";
    470   if (mode == CPDF_Annot::Down)
    471     ap_entry = "D";
    472   else if (mode == CPDF_Annot::Rollover)
    473     ap_entry = "R";
    474   if (!pAP->KeyExist(ap_entry))
    475     ap_entry = "N";
    476 
    477   // Get the AP stream or subdirectory
    478   CPDF_Object* psub = pAP->GetDirectObjectFor(ap_entry);
    479   if (!psub)
    480     return false;
    481 
    482   int nFieldType = GetFieldType();
    483   switch (nFieldType) {
    484     case FIELDTYPE_PUSHBUTTON:
    485     case FIELDTYPE_COMBOBOX:
    486     case FIELDTYPE_LISTBOX:
    487     case FIELDTYPE_TEXTFIELD:
    488     case FIELDTYPE_SIGNATURE:
    489       return psub->IsStream();
    490     case FIELDTYPE_CHECKBOX:
    491     case FIELDTYPE_RADIOBUTTON:
    492       if (CPDF_Dictionary* pSubDict = psub->AsDictionary()) {
    493         return !!pSubDict->GetStreamFor(GetAppState());
    494       }
    495       return false;
    496   }
    497   return true;
    498 }
    499 
    500 int CPDFSDK_Widget::GetFieldType() const {
    501   CPDF_FormField* pField = GetFormField();
    502   return pField ? pField->GetFieldType() : FIELDTYPE_UNKNOWN;
    503 }
    504 
    505 bool CPDFSDK_Widget::IsAppearanceValid() {
    506 #ifdef PDF_ENABLE_XFA
    507   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
    508   int nDocType = pContext->GetDocType();
    509   if (nDocType != DOCTYPE_PDF && nDocType != DOCTYPE_STATIC_XFA)
    510     return true;
    511 #endif  // PDF_ENABLE_XFA
    512   return CPDFSDK_BAAnnot::IsAppearanceValid();
    513 }
    514 
    515 int CPDFSDK_Widget::GetLayoutOrder() const {
    516   return 2;
    517 }
    518 
    519 int CPDFSDK_Widget::GetFieldFlags() const {
    520   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
    521   CPDF_FormControl* pFormControl =
    522       pPDFInterForm->GetControlByDict(m_pAnnot->GetAnnotDict());
    523   CPDF_FormField* pFormField = pFormControl->GetField();
    524   return pFormField->GetFieldFlags();
    525 }
    526 
    527 bool CPDFSDK_Widget::IsSignatureWidget() const {
    528   return GetFieldType() == FIELDTYPE_SIGNATURE;
    529 }
    530 
    531 CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
    532   CPDF_FormControl* pControl = GetFormControl();
    533   return pControl ? pControl->GetField() : nullptr;
    534 }
    535 
    536 CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
    537   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
    538   return pPDFInterForm->GetControlByDict(GetAnnotDict());
    539 }
    540 
    541 CPDF_FormControl* CPDFSDK_Widget::GetFormControl(
    542     CPDF_InterForm* pInterForm,
    543     const CPDF_Dictionary* pAnnotDict) {
    544   ASSERT(pAnnotDict);
    545   return pInterForm->GetControlByDict(pAnnotDict);
    546 }
    547 
    548 int CPDFSDK_Widget::GetRotate() const {
    549   CPDF_FormControl* pCtrl = GetFormControl();
    550   return pCtrl->GetRotation() % 360;
    551 }
    552 
    553 #ifdef PDF_ENABLE_XFA
    554 CFX_WideString CPDFSDK_Widget::GetName() const {
    555   CPDF_FormField* pFormField = GetFormField();
    556   return pFormField->GetFullName();
    557 }
    558 #endif  // PDF_ENABLE_XFA
    559 
    560 bool CPDFSDK_Widget::GetFillColor(FX_COLORREF& color) const {
    561   CPDF_FormControl* pFormCtrl = GetFormControl();
    562   int iColorType = 0;
    563   color = ARGBToColorRef(pFormCtrl->GetBackgroundColor(iColorType));
    564   return iColorType != COLORTYPE_TRANSPARENT;
    565 }
    566 
    567 bool CPDFSDK_Widget::GetBorderColor(FX_COLORREF& color) const {
    568   CPDF_FormControl* pFormCtrl = GetFormControl();
    569   int iColorType = 0;
    570   color = ARGBToColorRef(pFormCtrl->GetBorderColor(iColorType));
    571   return iColorType != COLORTYPE_TRANSPARENT;
    572 }
    573 
    574 bool CPDFSDK_Widget::GetTextColor(FX_COLORREF& color) const {
    575   CPDF_FormControl* pFormCtrl = GetFormControl();
    576   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
    577   if (!da.HasColor())
    578     return false;
    579 
    580   FX_ARGB argb;
    581   int iColorType = COLORTYPE_TRANSPARENT;
    582   da.GetColor(argb, iColorType);
    583   color = ARGBToColorRef(argb);
    584   return iColorType != COLORTYPE_TRANSPARENT;
    585 }
    586 
    587 FX_FLOAT CPDFSDK_Widget::GetFontSize() const {
    588   CPDF_FormControl* pFormCtrl = GetFormControl();
    589   CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance();
    590   CFX_ByteString csFont = "";
    591   FX_FLOAT fFontSize = 0.0f;
    592   pDa.GetFont(csFont, fFontSize);
    593 
    594   return fFontSize;
    595 }
    596 
    597 int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const {
    598 #ifdef PDF_ENABLE_XFA
    599   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    600     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    601       if (nIndex < pWidgetAcc->CountSelectedItems())
    602         return pWidgetAcc->GetSelectedItem(nIndex);
    603     }
    604   }
    605 #endif  // PDF_ENABLE_XFA
    606   CPDF_FormField* pFormField = GetFormField();
    607   return pFormField->GetSelectedIndex(nIndex);
    608 }
    609 
    610 #ifdef PDF_ENABLE_XFA
    611 CFX_WideString CPDFSDK_Widget::GetValue(bool bDisplay) const {
    612   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
    613     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
    614       CFX_WideString sValue;
    615       pWidgetAcc->GetValue(
    616           sValue, bDisplay ? XFA_VALUEPICTURE_Display : XFA_VALUEPICTURE_Edit);
    617       return sValue;
    618     }
    619   }
    620 #else
    621 CFX_WideString CPDFSDK_Widget::GetValue() const {
    622 #endif  // PDF_ENABLE_XFA
    623   CPDF_FormField* pFormField = GetFormField();
    624   return pFormField->GetValue();
    625 }
    626 
    627 CFX_WideString CPDFSDK_Widget::GetDefaultValue() const {
    628   CPDF_FormField* pFormField = GetFormField();
    629   return pFormField->GetDefaultValue();
    630 }
    631 
    632 CFX_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->GetDataAcc()) {
    646       if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems())
    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->GetDataAcc())
    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 CFX_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 CFX_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 FIELDTYPE_TEXTFIELD:
    744     case FIELDTYPE_COMBOBOX: {
    745       bool bFormatted = false;
    746       CFX_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 CFX_WideString* sValue,
    758                                      bool bValueChanged) {
    759   SetAppModified();
    760 
    761   m_nAppAge++;
    762   if (m_nAppAge > 999999)
    763     m_nAppAge = 0;
    764   if (bValueChanged)
    765     m_nValueAge++;
    766 
    767   int nFieldType = GetFieldType();
    768 
    769   switch (nFieldType) {
    770     case FIELDTYPE_PUSHBUTTON:
    771       ResetAppearance_PushButton();
    772       break;
    773     case FIELDTYPE_CHECKBOX:
    774       ResetAppearance_CheckBox();
    775       break;
    776     case FIELDTYPE_RADIOBUTTON:
    777       ResetAppearance_RadioButton();
    778       break;
    779     case FIELDTYPE_COMBOBOX:
    780       ResetAppearance_ComboBox(sValue);
    781       break;
    782     case FIELDTYPE_LISTBOX:
    783       ResetAppearance_ListBox();
    784       break;
    785     case FIELDTYPE_TEXTFIELD:
    786       ResetAppearance_TextField(sValue);
    787       break;
    788   }
    789 
    790   m_pAnnot->ClearCachedAP();
    791 }
    792 
    793 CFX_WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) {
    794   CPDF_FormField* pFormField = GetFormField();
    795   ASSERT(pFormField);
    796   return m_pInterForm->OnFormat(pFormField, bFormatted);
    797 }
    798 
    799 void CPDFSDK_Widget::ResetFieldAppearance(bool bValueChanged) {
    800   CPDF_FormField* pFormField = GetFormField();
    801   ASSERT(pFormField);
    802   m_pInterForm->ResetFieldAppearance(pFormField, nullptr, bValueChanged);
    803 }
    804 
    805 void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice,
    806                                     const CFX_Matrix* pUser2Device,
    807                                     CPDF_Annot::AppearanceMode mode,
    808                                     const CPDF_RenderOptions* pOptions) {
    809   int nFieldType = GetFieldType();
    810 
    811   if ((nFieldType == FIELDTYPE_CHECKBOX ||
    812        nFieldType == FIELDTYPE_RADIOBUTTON) &&
    813       mode == CPDF_Annot::Normal &&
    814       !IsWidgetAppearanceValid(CPDF_Annot::Normal)) {
    815     CFX_PathData pathData;
    816 
    817     CFX_FloatRect rcAnnot = GetRect();
    818 
    819     pathData.AppendRect(rcAnnot.left, rcAnnot.bottom, rcAnnot.right,
    820                         rcAnnot.top);
    821 
    822     CFX_GraphStateData gsd;
    823     gsd.m_LineWidth = 0.0f;
    824 
    825     pDevice->DrawPath(&pathData, pUser2Device, &gsd, 0, 0xFFAAAAAA,
    826                       FXFILL_ALTERNATE);
    827   } else {
    828     CPDFSDK_BAAnnot::DrawAppearance(pDevice, pUser2Device, mode, pOptions);
    829   }
    830 }
    831 
    832 void CPDFSDK_Widget::UpdateField() {
    833   CPDF_FormField* pFormField = GetFormField();
    834   ASSERT(pFormField);
    835   m_pInterForm->UpdateField(pFormField);
    836 }
    837 
    838 void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice,
    839                                 CPDFSDK_PageView* pPageView) {
    840   int nFieldType = GetFieldType();
    841   if (!m_pInterForm->IsNeedHighLight(nFieldType))
    842     return;
    843 
    844   CFX_Matrix page2device;
    845   pPageView->GetCurrentMatrix(page2device);
    846 
    847   CFX_FloatRect rcDevice = GetRect();
    848   CFX_PointF tmp =
    849       page2device.Transform(CFX_PointF(rcDevice.left, rcDevice.bottom));
    850   rcDevice.left = tmp.x;
    851   rcDevice.bottom = tmp.y;
    852 
    853   tmp = page2device.Transform(CFX_PointF(rcDevice.right, rcDevice.top));
    854   rcDevice.right = tmp.x;
    855   rcDevice.top = tmp.y;
    856   rcDevice.Normalize();
    857 
    858   FX_RECT rcDev = rcDevice.ToFxRect();
    859   pDevice->FillRect(
    860       &rcDev, ArgbEncode(static_cast<int>(m_pInterForm->GetHighlightAlpha()),
    861                          m_pInterForm->GetHighlightColor(nFieldType)));
    862 }
    863 
    864 void CPDFSDK_Widget::ResetAppearance_PushButton() {
    865   CPDF_FormControl* pControl = GetFormControl();
    866   CFX_FloatRect rcWindow = GetRotatedRect();
    867   int32_t nLayout = 0;
    868   switch (pControl->GetTextPosition()) {
    869     case TEXTPOS_ICON:
    870       nLayout = PPBL_ICON;
    871       break;
    872     case TEXTPOS_BELOW:
    873       nLayout = PPBL_ICONTOPLABELBOTTOM;
    874       break;
    875     case TEXTPOS_ABOVE:
    876       nLayout = PPBL_LABELTOPICONBOTTOM;
    877       break;
    878     case TEXTPOS_RIGHT:
    879       nLayout = PPBL_ICONLEFTLABELRIGHT;
    880       break;
    881     case TEXTPOS_LEFT:
    882       nLayout = PPBL_LABELLEFTICONRIGHT;
    883       break;
    884     case TEXTPOS_OVERLAID:
    885       nLayout = PPBL_LABELOVERICON;
    886       break;
    887     default:
    888       nLayout = PPBL_LABEL;
    889       break;
    890   }
    891 
    892   CPWL_Color crBackground;
    893   CPWL_Color crBorder;
    894   int iColorType;
    895   FX_FLOAT fc[4];
    896   pControl->GetOriginalBackgroundColor(iColorType, fc);
    897   if (iColorType > 0)
    898     crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
    899 
    900   pControl->GetOriginalBorderColor(iColorType, fc);
    901   if (iColorType > 0)
    902     crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
    903 
    904   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
    905   CPWL_Dash dsBorder(3, 0, 0);
    906   CPWL_Color crLeftTop;
    907   CPWL_Color crRightBottom;
    908 
    909   BorderStyle nBorderStyle = GetBorderStyle();
    910   switch (nBorderStyle) {
    911     case BorderStyle::DASH:
    912       dsBorder = CPWL_Dash(3, 3, 0);
    913       break;
    914     case BorderStyle::BEVELED:
    915       fBorderWidth *= 2;
    916       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
    917       crRightBottom = crBackground / 2.0f;
    918       break;
    919     case BorderStyle::INSET:
    920       fBorderWidth *= 2;
    921       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
    922       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
    923       break;
    924     default:
    925       break;
    926   }
    927 
    928   CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
    929 
    930   CPWL_Color crText(COLORTYPE_GRAY, 0);
    931 
    932   FX_FLOAT fFontSize = 12.0f;
    933   CFX_ByteString csNameTag;
    934 
    935   CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
    936   if (da.HasColor()) {
    937     da.GetColor(iColorType, fc);
    938     crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
    939   }
    940 
    941   if (da.HasFont())
    942     da.GetFont(csNameTag, fFontSize);
    943 
    944   CFX_WideString csWCaption;
    945   CFX_WideString csNormalCaption, csRolloverCaption, csDownCaption;
    946 
    947   if (pControl->HasMKEntry("CA"))
    948     csNormalCaption = pControl->GetNormalCaption();
    949 
    950   if (pControl->HasMKEntry("RC"))
    951     csRolloverCaption = pControl->GetRolloverCaption();
    952 
    953   if (pControl->HasMKEntry("AC"))
    954     csDownCaption = pControl->GetDownCaption();
    955 
    956   CPDF_Stream* pNormalIcon = nullptr;
    957   CPDF_Stream* pRolloverIcon = nullptr;
    958   CPDF_Stream* pDownIcon = nullptr;
    959 
    960   if (pControl->HasMKEntry("I"))
    961     pNormalIcon = pControl->GetNormalIcon();
    962 
    963   if (pControl->HasMKEntry("RI"))
    964     pRolloverIcon = pControl->GetRolloverIcon();
    965 
    966   if (pControl->HasMKEntry("IX"))
    967     pDownIcon = pControl->GetDownIcon();
    968 
    969   if (pNormalIcon) {
    970     if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) {
    971       if (pImageDict->GetStringFor("Name").IsEmpty())
    972         pImageDict->SetNewFor<CPDF_String>("Name", "ImgA", false);
    973     }
    974   }
    975 
    976   if (pRolloverIcon) {
    977     if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) {
    978       if (pImageDict->GetStringFor("Name").IsEmpty())
    979         pImageDict->SetNewFor<CPDF_String>("Name", "ImgB", false);
    980     }
    981   }
    982 
    983   if (pDownIcon) {
    984     if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) {
    985       if (pImageDict->GetStringFor("Name").IsEmpty())
    986         pImageDict->SetNewFor<CPDF_String>("Name", "ImgC", false);
    987     }
    988   }
    989 
    990   CPDF_IconFit iconFit = pControl->GetIconFit();
    991 
    992   CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler());
    993   font_map.SetAPType("N");
    994 
    995   CFX_ByteString csAP =
    996       CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
    997       CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
    998                                      crLeftTop, crRightBottom, nBorderStyle,
    999                                      dsBorder) +
   1000       CPWL_Utils::GetPushButtonAppStream(
   1001           iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map,
   1002           pNormalIcon, iconFit, csNormalCaption, crText, fFontSize, nLayout);
   1003 
   1004   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP);
   1005   if (pNormalIcon)
   1006     AddImageToAppearance("N", pNormalIcon);
   1007 
   1008   CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode();
   1009   if (eHLM == CPDF_FormControl::Push || eHLM == CPDF_FormControl::Toggle) {
   1010     if (csRolloverCaption.IsEmpty() && !pRolloverIcon) {
   1011       csRolloverCaption = csNormalCaption;
   1012       pRolloverIcon = pNormalIcon;
   1013     }
   1014 
   1015     font_map.SetAPType("R");
   1016 
   1017     csAP = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
   1018            CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
   1019                                           crLeftTop, crRightBottom,
   1020                                           nBorderStyle, dsBorder) +
   1021            CPWL_Utils::GetPushButtonAppStream(
   1022                iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map,
   1023                pRolloverIcon, iconFit, csRolloverCaption, crText, fFontSize,
   1024                nLayout);
   1025 
   1026     WriteAppearance("R", GetRotatedRect(), GetMatrix(), csAP);
   1027     if (pRolloverIcon)
   1028       AddImageToAppearance("R", pRolloverIcon);
   1029 
   1030     if (csDownCaption.IsEmpty() && !pDownIcon) {
   1031       csDownCaption = csNormalCaption;
   1032       pDownIcon = pNormalIcon;
   1033     }
   1034 
   1035     switch (nBorderStyle) {
   1036       case BorderStyle::BEVELED: {
   1037         CPWL_Color crTemp = crLeftTop;
   1038         crLeftTop = crRightBottom;
   1039         crRightBottom = crTemp;
   1040         break;
   1041       }
   1042       case BorderStyle::INSET: {
   1043         crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
   1044         crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
   1045         break;
   1046       }
   1047       default:
   1048         break;
   1049     }
   1050 
   1051     font_map.SetAPType("D");
   1052 
   1053     csAP = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
   1054            CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
   1055                                           crLeftTop, crRightBottom,
   1056                                           nBorderStyle, dsBorder) +
   1057            CPWL_Utils::GetPushButtonAppStream(
   1058                iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map,
   1059                pDownIcon, iconFit, csDownCaption, crText, fFontSize, nLayout);
   1060 
   1061     WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP);
   1062     if (pDownIcon)
   1063       AddImageToAppearance("D", pDownIcon);
   1064   } else {
   1065     RemoveAppearance("D");
   1066     RemoveAppearance("R");
   1067   }
   1068 }
   1069 
   1070 void CPDFSDK_Widget::ResetAppearance_CheckBox() {
   1071   CPDF_FormControl* pControl = GetFormControl();
   1072   CPWL_Color crBackground, crBorder, crText;
   1073   int iColorType;
   1074   FX_FLOAT fc[4];
   1075 
   1076   pControl->GetOriginalBackgroundColor(iColorType, fc);
   1077   if (iColorType > 0)
   1078     crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1079 
   1080   pControl->GetOriginalBorderColor(iColorType, fc);
   1081   if (iColorType > 0)
   1082     crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1083 
   1084   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
   1085   CPWL_Dash dsBorder(3, 0, 0);
   1086   CPWL_Color crLeftTop, crRightBottom;
   1087 
   1088   BorderStyle nBorderStyle = GetBorderStyle();
   1089   switch (nBorderStyle) {
   1090     case BorderStyle::DASH:
   1091       dsBorder = CPWL_Dash(3, 3, 0);
   1092       break;
   1093     case BorderStyle::BEVELED:
   1094       fBorderWidth *= 2;
   1095       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
   1096       crRightBottom = crBackground / 2.0f;
   1097       break;
   1098     case BorderStyle::INSET:
   1099       fBorderWidth *= 2;
   1100       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
   1101       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
   1102       break;
   1103     default:
   1104       break;
   1105   }
   1106 
   1107   CFX_FloatRect rcWindow = GetRotatedRect();
   1108   CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
   1109   CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
   1110   if (da.HasColor()) {
   1111     da.GetColor(iColorType, fc);
   1112     crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1113   }
   1114 
   1115   int32_t nStyle = 0;
   1116   CFX_WideString csWCaption = pControl->GetNormalCaption();
   1117   if (csWCaption.GetLength() > 0) {
   1118     switch (csWCaption[0]) {
   1119       case L'l':
   1120         nStyle = PCS_CIRCLE;
   1121         break;
   1122       case L'8':
   1123         nStyle = PCS_CROSS;
   1124         break;
   1125       case L'u':
   1126         nStyle = PCS_DIAMOND;
   1127         break;
   1128       case L'n':
   1129         nStyle = PCS_SQUARE;
   1130         break;
   1131       case L'H':
   1132         nStyle = PCS_STAR;
   1133         break;
   1134       default:  // L'4'
   1135         nStyle = PCS_CHECK;
   1136         break;
   1137     }
   1138   } else {
   1139     nStyle = PCS_CHECK;
   1140   }
   1141 
   1142   CFX_ByteString csAP_N_ON =
   1143       CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
   1144       CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
   1145                                      crLeftTop, crRightBottom, nBorderStyle,
   1146                                      dsBorder);
   1147 
   1148   CFX_ByteString csAP_N_OFF = csAP_N_ON;
   1149 
   1150   switch (nBorderStyle) {
   1151     case BorderStyle::BEVELED: {
   1152       CPWL_Color crTemp = crLeftTop;
   1153       crLeftTop = crRightBottom;
   1154       crRightBottom = crTemp;
   1155       break;
   1156     }
   1157     case BorderStyle::INSET: {
   1158       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
   1159       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
   1160       break;
   1161     }
   1162     default:
   1163       break;
   1164   }
   1165 
   1166   CFX_ByteString csAP_D_ON =
   1167       CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
   1168       CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
   1169                                      crLeftTop, crRightBottom, nBorderStyle,
   1170                                      dsBorder);
   1171 
   1172   CFX_ByteString csAP_D_OFF = csAP_D_ON;
   1173 
   1174   csAP_N_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText);
   1175   csAP_D_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText);
   1176 
   1177   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON,
   1178                   pControl->GetCheckedAPState());
   1179   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off");
   1180 
   1181   WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON,
   1182                   pControl->GetCheckedAPState());
   1183   WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off");
   1184 
   1185   CFX_ByteString csAS = GetAppState();
   1186   if (csAS.IsEmpty())
   1187     SetAppState("Off");
   1188 }
   1189 
   1190 void CPDFSDK_Widget::ResetAppearance_RadioButton() {
   1191   CPDF_FormControl* pControl = GetFormControl();
   1192   CPWL_Color crBackground, crBorder, crText;
   1193   int iColorType;
   1194   FX_FLOAT fc[4];
   1195 
   1196   pControl->GetOriginalBackgroundColor(iColorType, fc);
   1197   if (iColorType > 0)
   1198     crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1199 
   1200   pControl->GetOriginalBorderColor(iColorType, fc);
   1201   if (iColorType > 0)
   1202     crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1203 
   1204   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
   1205   CPWL_Dash dsBorder(3, 0, 0);
   1206   CPWL_Color crLeftTop;
   1207   CPWL_Color crRightBottom;
   1208   BorderStyle nBorderStyle = GetBorderStyle();
   1209   switch (nBorderStyle) {
   1210     case BorderStyle::DASH:
   1211       dsBorder = CPWL_Dash(3, 3, 0);
   1212       break;
   1213     case BorderStyle::BEVELED:
   1214       fBorderWidth *= 2;
   1215       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
   1216       crRightBottom = crBackground / 2.0f;
   1217       break;
   1218     case BorderStyle::INSET:
   1219       fBorderWidth *= 2;
   1220       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
   1221       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
   1222       break;
   1223     default:
   1224       break;
   1225   }
   1226 
   1227   CFX_FloatRect rcWindow = GetRotatedRect();
   1228   CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
   1229 
   1230   CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
   1231   if (da.HasColor()) {
   1232     da.GetColor(iColorType, fc);
   1233     crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1234   }
   1235 
   1236   int32_t nStyle = 0;
   1237   CFX_WideString csWCaption = pControl->GetNormalCaption();
   1238   if (csWCaption.GetLength() > 0) {
   1239     switch (csWCaption[0]) {
   1240       default:  // L'l':
   1241         nStyle = PCS_CIRCLE;
   1242         break;
   1243       case L'8':
   1244         nStyle = PCS_CROSS;
   1245         break;
   1246       case L'u':
   1247         nStyle = PCS_DIAMOND;
   1248         break;
   1249       case L'n':
   1250         nStyle = PCS_SQUARE;
   1251         break;
   1252       case L'H':
   1253         nStyle = PCS_STAR;
   1254         break;
   1255       case L'4':
   1256         nStyle = PCS_CHECK;
   1257         break;
   1258     }
   1259   } else {
   1260     nStyle = PCS_CIRCLE;
   1261   }
   1262 
   1263   CFX_ByteString csAP_N_ON;
   1264 
   1265   CFX_FloatRect rcCenter =
   1266       CPWL_Utils::DeflateRect(CPWL_Utils::GetCenterSquare(rcWindow), 1.0f);
   1267 
   1268   if (nStyle == PCS_CIRCLE) {
   1269     if (nBorderStyle == BorderStyle::BEVELED) {
   1270       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
   1271       crRightBottom = crBackground - 0.25f;
   1272     } else if (nBorderStyle == BorderStyle::INSET) {
   1273       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5f);
   1274       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75f);
   1275     }
   1276 
   1277     csAP_N_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBackground) +
   1278                 CPWL_Utils::GetCircleBorderAppStream(
   1279                     rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom,
   1280                     nBorderStyle, dsBorder);
   1281   } else {
   1282     csAP_N_ON = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
   1283                 CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
   1284                                                crLeftTop, crRightBottom,
   1285                                                nBorderStyle, dsBorder);
   1286   }
   1287 
   1288   CFX_ByteString csAP_N_OFF = csAP_N_ON;
   1289 
   1290   switch (nBorderStyle) {
   1291     case BorderStyle::BEVELED: {
   1292       CPWL_Color crTemp = crLeftTop;
   1293       crLeftTop = crRightBottom;
   1294       crRightBottom = crTemp;
   1295       break;
   1296     }
   1297     case BorderStyle::INSET: {
   1298       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
   1299       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
   1300       break;
   1301     }
   1302     default:
   1303       break;
   1304   }
   1305 
   1306   CFX_ByteString csAP_D_ON;
   1307 
   1308   if (nStyle == PCS_CIRCLE) {
   1309     CPWL_Color crBK = crBackground - 0.25f;
   1310     if (nBorderStyle == BorderStyle::BEVELED) {
   1311       crLeftTop = crBackground - 0.25f;
   1312       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
   1313       crBK = crBackground;
   1314     } else if (nBorderStyle == BorderStyle::INSET) {
   1315       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
   1316       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
   1317     }
   1318 
   1319     csAP_D_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBK) +
   1320                 CPWL_Utils::GetCircleBorderAppStream(
   1321                     rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom,
   1322                     nBorderStyle, dsBorder);
   1323   } else {
   1324     csAP_D_ON =
   1325         CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
   1326         CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
   1327                                        crLeftTop, crRightBottom, nBorderStyle,
   1328                                        dsBorder);
   1329   }
   1330 
   1331   CFX_ByteString csAP_D_OFF = csAP_D_ON;
   1332 
   1333   csAP_N_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText);
   1334   csAP_D_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText);
   1335 
   1336   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON,
   1337                   pControl->GetCheckedAPState());
   1338   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off");
   1339 
   1340   WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON,
   1341                   pControl->GetCheckedAPState());
   1342   WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off");
   1343 
   1344   CFX_ByteString csAS = GetAppState();
   1345   if (csAS.IsEmpty())
   1346     SetAppState("Off");
   1347 }
   1348 
   1349 void CPDFSDK_Widget::ResetAppearance_ComboBox(const CFX_WideString* sValue) {
   1350   CPDF_FormControl* pControl = GetFormControl();
   1351   CPDF_FormField* pField = pControl->GetField();
   1352   CFX_ByteTextBuf sBody, sLines;
   1353 
   1354   CFX_FloatRect rcClient = GetClientRect();
   1355   CFX_FloatRect rcButton = rcClient;
   1356   rcButton.left = rcButton.right - 13;
   1357   rcButton.Normalize();
   1358 
   1359   std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
   1360   pEdit->EnableRefresh(false);
   1361 
   1362   CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler());
   1363   pEdit->SetFontMap(&font_map);
   1364 
   1365   CFX_FloatRect rcEdit = rcClient;
   1366   rcEdit.right = rcButton.left;
   1367   rcEdit.Normalize();
   1368 
   1369   pEdit->SetPlateRect(rcEdit);
   1370   pEdit->SetAlignmentV(1, true);
   1371 
   1372   FX_FLOAT fFontSize = GetFontSize();
   1373   if (IsFloatZero(fFontSize))
   1374     pEdit->SetAutoFontSize(true, true);
   1375   else
   1376     pEdit->SetFontSize(fFontSize);
   1377 
   1378   pEdit->Initialize();
   1379 
   1380   if (sValue) {
   1381     pEdit->SetText(*sValue);
   1382   } else {
   1383     int32_t nCurSel = pField->GetSelectedIndex(0);
   1384     if (nCurSel < 0)
   1385       pEdit->SetText(pField->GetValue());
   1386     else
   1387       pEdit->SetText(pField->GetOptionLabel(nCurSel));
   1388   }
   1389 
   1390   CFX_FloatRect rcContent = pEdit->GetContentRect();
   1391 
   1392   CFX_ByteString sEdit =
   1393       CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF());
   1394   if (sEdit.GetLength() > 0) {
   1395     sBody << "/Tx BMC\n"
   1396           << "q\n";
   1397     if (rcContent.Width() > rcEdit.Width() ||
   1398         rcContent.Height() > rcEdit.Height()) {
   1399       sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width()
   1400             << " " << rcEdit.Height() << " re\nW\nn\n";
   1401     }
   1402 
   1403     CPWL_Color crText = GetTextPWLColor();
   1404     sBody << "BT\n"
   1405           << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n"
   1406           << "Q\nEMC\n";
   1407   }
   1408 
   1409   sBody << CPWL_Utils::GetDropButtonAppStream(rcButton);
   1410 
   1411   CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
   1412                        sLines.AsStringC() + sBody.AsStringC();
   1413 
   1414   WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
   1415 }
   1416 
   1417 void CPDFSDK_Widget::ResetAppearance_ListBox() {
   1418   CPDF_FormControl* pControl = GetFormControl();
   1419   CPDF_FormField* pField = pControl->GetField();
   1420   CFX_FloatRect rcClient = GetClientRect();
   1421   CFX_ByteTextBuf sBody, sLines;
   1422 
   1423   std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
   1424   pEdit->EnableRefresh(false);
   1425 
   1426   CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler());
   1427   pEdit->SetFontMap(&font_map);
   1428 
   1429   pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f));
   1430 
   1431   FX_FLOAT fFontSize = GetFontSize();
   1432 
   1433   pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize);
   1434 
   1435   pEdit->Initialize();
   1436 
   1437   CFX_ByteTextBuf sList;
   1438   FX_FLOAT fy = rcClient.top;
   1439 
   1440   int32_t nTop = pField->GetTopVisibleIndex();
   1441   int32_t nCount = pField->CountOptions();
   1442   int32_t nSelCount = pField->CountSelectedItems();
   1443 
   1444   for (int32_t i = nTop; i < nCount; ++i) {
   1445     bool bSelected = false;
   1446     for (int32_t j = 0; j < nSelCount; ++j) {
   1447       if (pField->GetSelectedIndex(j) == i) {
   1448         bSelected = true;
   1449         break;
   1450       }
   1451     }
   1452 
   1453     pEdit->SetText(pField->GetOptionLabel(i));
   1454 
   1455     CFX_FloatRect rcContent = pEdit->GetContentRect();
   1456     FX_FLOAT fItemHeight = rcContent.Height();
   1457 
   1458     if (bSelected) {
   1459       CFX_FloatRect rcItem =
   1460           CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy);
   1461       sList << "q\n"
   1462             << CPWL_Utils::GetColorAppStream(
   1463                    CPWL_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f,
   1464                               113.0f / 255.0f),
   1465                    true)
   1466             << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width()
   1467             << " " << rcItem.Height() << " re f\n"
   1468             << "Q\n";
   1469 
   1470       sList << "BT\n"
   1471             << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY, 1),
   1472                                              true)
   1473             << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy))
   1474             << "ET\n";
   1475     } else {
   1476       CPWL_Color crText = GetTextPWLColor();
   1477       sList << "BT\n"
   1478             << CPWL_Utils::GetColorAppStream(crText, true)
   1479             << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy))
   1480             << "ET\n";
   1481     }
   1482 
   1483     fy -= fItemHeight;
   1484   }
   1485 
   1486   if (sList.GetSize() > 0) {
   1487     sBody << "/Tx BMC\n"
   1488           << "q\n"
   1489           << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width()
   1490           << " " << rcClient.Height() << " re\nW\nn\n";
   1491     sBody << sList << "Q\nEMC\n";
   1492   }
   1493 
   1494   CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
   1495                        sLines.AsStringC() + sBody.AsStringC();
   1496 
   1497   WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
   1498 }
   1499 
   1500 void CPDFSDK_Widget::ResetAppearance_TextField(const CFX_WideString* sValue) {
   1501   CPDF_FormControl* pControl = GetFormControl();
   1502   CPDF_FormField* pField = pControl->GetField();
   1503   CFX_ByteTextBuf sBody, sLines;
   1504 
   1505   std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
   1506   pEdit->EnableRefresh(false);
   1507 
   1508   CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler());
   1509   pEdit->SetFontMap(&font_map);
   1510 
   1511   CFX_FloatRect rcClient = GetClientRect();
   1512   pEdit->SetPlateRect(rcClient);
   1513   pEdit->SetAlignmentH(pControl->GetControlAlignment(), true);
   1514 
   1515   uint32_t dwFieldFlags = pField->GetFieldFlags();
   1516   bool bMultiLine = (dwFieldFlags >> 12) & 1;
   1517 
   1518   if (bMultiLine) {
   1519     pEdit->SetMultiLine(true, true);
   1520     pEdit->SetAutoReturn(true, true);
   1521   } else {
   1522     pEdit->SetAlignmentV(1, true);
   1523   }
   1524 
   1525   uint16_t subWord = 0;
   1526   if ((dwFieldFlags >> 13) & 1) {
   1527     subWord = '*';
   1528     pEdit->SetPasswordChar(subWord, true);
   1529   }
   1530 
   1531   int nMaxLen = pField->GetMaxLen();
   1532   bool bCharArray = (dwFieldFlags >> 24) & 1;
   1533   FX_FLOAT fFontSize = GetFontSize();
   1534 
   1535 #ifdef PDF_ENABLE_XFA
   1536   CFX_WideString sValueTmp;
   1537   if (!sValue && GetMixXFAWidget()) {
   1538     sValueTmp = GetValue(true);
   1539     sValue = &sValueTmp;
   1540   }
   1541 #endif  // PDF_ENABLE_XFA
   1542 
   1543   if (nMaxLen > 0) {
   1544     if (bCharArray) {
   1545       pEdit->SetCharArray(nMaxLen);
   1546 
   1547       if (IsFloatZero(fFontSize)) {
   1548         fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0),
   1549                                                         rcClient, nMaxLen);
   1550       }
   1551     } else {
   1552       if (sValue)
   1553         nMaxLen = sValue->GetLength();
   1554       pEdit->SetLimitChar(nMaxLen);
   1555     }
   1556   }
   1557 
   1558   if (IsFloatZero(fFontSize))
   1559     pEdit->SetAutoFontSize(true, true);
   1560   else
   1561     pEdit->SetFontSize(fFontSize);
   1562 
   1563   pEdit->Initialize();
   1564   pEdit->SetText(sValue ? *sValue : pField->GetValue());
   1565 
   1566   CFX_FloatRect rcContent = pEdit->GetContentRect();
   1567   CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(
   1568       pEdit.get(), CFX_PointF(), nullptr, !bCharArray, subWord);
   1569 
   1570   if (sEdit.GetLength() > 0) {
   1571     sBody << "/Tx BMC\n"
   1572           << "q\n";
   1573     if (rcContent.Width() > rcClient.Width() ||
   1574         rcContent.Height() > rcClient.Height()) {
   1575       sBody << rcClient.left << " " << rcClient.bottom << " "
   1576             << rcClient.Width() << " " << rcClient.Height() << " re\nW\nn\n";
   1577     }
   1578     CPWL_Color crText = GetTextPWLColor();
   1579     sBody << "BT\n"
   1580           << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n"
   1581           << "Q\nEMC\n";
   1582   }
   1583 
   1584   if (bCharArray) {
   1585     switch (GetBorderStyle()) {
   1586       case BorderStyle::SOLID: {
   1587         CFX_ByteString sColor =
   1588             CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false);
   1589         if (sColor.GetLength() > 0) {
   1590           sLines << "q\n"
   1591                  << GetBorderWidth() << " w\n"
   1592                  << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false)
   1593                  << " 2 J 0 j\n";
   1594 
   1595           for (int32_t i = 1; i < nMaxLen; ++i) {
   1596             sLines << rcClient.left +
   1597                           ((rcClient.right - rcClient.left) / nMaxLen) * i
   1598                    << " " << rcClient.bottom << " m\n"
   1599                    << rcClient.left +
   1600                           ((rcClient.right - rcClient.left) / nMaxLen) * i
   1601                    << " " << rcClient.top << " l S\n";
   1602           }
   1603 
   1604           sLines << "Q\n";
   1605         }
   1606         break;
   1607       }
   1608       case BorderStyle::DASH: {
   1609         CFX_ByteString sColor =
   1610             CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false);
   1611         if (sColor.GetLength() > 0) {
   1612           CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0);
   1613 
   1614           sLines << "q\n"
   1615                  << GetBorderWidth() << " w\n"
   1616                  << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false)
   1617                  << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] "
   1618                  << dsBorder.nPhase << " d\n";
   1619 
   1620           for (int32_t i = 1; i < nMaxLen; ++i) {
   1621             sLines << rcClient.left +
   1622                           ((rcClient.right - rcClient.left) / nMaxLen) * i
   1623                    << " " << rcClient.bottom << " m\n"
   1624                    << rcClient.left +
   1625                           ((rcClient.right - rcClient.left) / nMaxLen) * i
   1626                    << " " << rcClient.top << " l S\n";
   1627           }
   1628 
   1629           sLines << "Q\n";
   1630         }
   1631         break;
   1632       }
   1633       default:
   1634         break;
   1635     }
   1636   }
   1637 
   1638   CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
   1639                        sLines.AsStringC() + sBody.AsStringC();
   1640   WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
   1641 }
   1642 
   1643 CFX_FloatRect CPDFSDK_Widget::GetClientRect() const {
   1644   CFX_FloatRect rcWindow = GetRotatedRect();
   1645   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
   1646   switch (GetBorderStyle()) {
   1647     case BorderStyle::BEVELED:
   1648     case BorderStyle::INSET:
   1649       fBorderWidth *= 2.0f;
   1650       break;
   1651     default:
   1652       break;
   1653   }
   1654 
   1655   return CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
   1656 }
   1657 
   1658 CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const {
   1659   CFX_FloatRect rectAnnot = GetRect();
   1660   FX_FLOAT fWidth = rectAnnot.right - rectAnnot.left;
   1661   FX_FLOAT fHeight = rectAnnot.top - rectAnnot.bottom;
   1662 
   1663   CPDF_FormControl* pControl = GetFormControl();
   1664   CFX_FloatRect rcPDFWindow;
   1665   switch (abs(pControl->GetRotation() % 360)) {
   1666     case 0:
   1667     case 180:
   1668     default:
   1669       rcPDFWindow = CFX_FloatRect(0, 0, fWidth, fHeight);
   1670       break;
   1671     case 90:
   1672     case 270:
   1673       rcPDFWindow = CFX_FloatRect(0, 0, fHeight, fWidth);
   1674       break;
   1675   }
   1676 
   1677   return rcPDFWindow;
   1678 }
   1679 
   1680 CFX_ByteString CPDFSDK_Widget::GetBackgroundAppStream() const {
   1681   CPWL_Color crBackground = GetFillPWLColor();
   1682   if (crBackground.nColorType != COLORTYPE_TRANSPARENT)
   1683     return CPWL_Utils::GetRectFillAppStream(GetRotatedRect(), crBackground);
   1684 
   1685   return "";
   1686 }
   1687 
   1688 CFX_ByteString CPDFSDK_Widget::GetBorderAppStream() const {
   1689   CFX_FloatRect rcWindow = GetRotatedRect();
   1690   CPWL_Color crBorder = GetBorderPWLColor();
   1691   CPWL_Color crBackground = GetFillPWLColor();
   1692   CPWL_Color crLeftTop, crRightBottom;
   1693 
   1694   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
   1695   CPWL_Dash dsBorder(3, 0, 0);
   1696 
   1697   BorderStyle nBorderStyle = GetBorderStyle();
   1698   switch (nBorderStyle) {
   1699     case BorderStyle::DASH:
   1700       dsBorder = CPWL_Dash(3, 3, 0);
   1701       break;
   1702     case BorderStyle::BEVELED:
   1703       fBorderWidth *= 2;
   1704       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
   1705       crRightBottom = crBackground / 2.0f;
   1706       break;
   1707     case BorderStyle::INSET:
   1708       fBorderWidth *= 2;
   1709       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
   1710       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
   1711       break;
   1712     default:
   1713       break;
   1714   }
   1715 
   1716   return CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
   1717                                         crLeftTop, crRightBottom, nBorderStyle,
   1718                                         dsBorder);
   1719 }
   1720 
   1721 CFX_Matrix CPDFSDK_Widget::GetMatrix() const {
   1722   CFX_Matrix mt;
   1723   CPDF_FormControl* pControl = GetFormControl();
   1724   CFX_FloatRect rcAnnot = GetRect();
   1725   FX_FLOAT fWidth = rcAnnot.right - rcAnnot.left;
   1726   FX_FLOAT fHeight = rcAnnot.top - rcAnnot.bottom;
   1727 
   1728   switch (abs(pControl->GetRotation() % 360)) {
   1729     case 0:
   1730     default:
   1731       mt = CFX_Matrix(1, 0, 0, 1, 0, 0);
   1732       break;
   1733     case 90:
   1734       mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0);
   1735       break;
   1736     case 180:
   1737       mt = CFX_Matrix(-1, 0, 0, -1, fWidth, fHeight);
   1738       break;
   1739     case 270:
   1740       mt = CFX_Matrix(0, -1, 1, 0, 0, fHeight);
   1741       break;
   1742   }
   1743 
   1744   return mt;
   1745 }
   1746 
   1747 CPWL_Color CPDFSDK_Widget::GetTextPWLColor() const {
   1748   CPWL_Color crText = CPWL_Color(COLORTYPE_GRAY, 0);
   1749 
   1750   CPDF_FormControl* pFormCtrl = GetFormControl();
   1751   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
   1752   if (da.HasColor()) {
   1753     int32_t iColorType;
   1754     FX_FLOAT fc[4];
   1755     da.GetColor(iColorType, fc);
   1756     crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1757   }
   1758 
   1759   return crText;
   1760 }
   1761 
   1762 CPWL_Color CPDFSDK_Widget::GetBorderPWLColor() const {
   1763   CPWL_Color crBorder;
   1764 
   1765   CPDF_FormControl* pFormCtrl = GetFormControl();
   1766   int32_t iColorType;
   1767   FX_FLOAT fc[4];
   1768   pFormCtrl->GetOriginalBorderColor(iColorType, fc);
   1769   if (iColorType > 0)
   1770     crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1771 
   1772   return crBorder;
   1773 }
   1774 
   1775 CPWL_Color CPDFSDK_Widget::GetFillPWLColor() const {
   1776   CPWL_Color crFill;
   1777 
   1778   CPDF_FormControl* pFormCtrl = GetFormControl();
   1779   int32_t iColorType;
   1780   FX_FLOAT fc[4];
   1781   pFormCtrl->GetOriginalBackgroundColor(iColorType, fc);
   1782   if (iColorType > 0)
   1783     crFill = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
   1784 
   1785   return crFill;
   1786 }
   1787 
   1788 void CPDFSDK_Widget::AddImageToAppearance(const CFX_ByteString& sAPType,
   1789                                           CPDF_Stream* pImage) {
   1790   CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP");
   1791   CPDF_Stream* pStream = pAPDict->GetStreamFor(sAPType);
   1792   CPDF_Dictionary* pStreamDict = pStream->GetDict();
   1793   CFX_ByteString sImageAlias = "IMG";
   1794 
   1795   if (CPDF_Dictionary* pImageDict = pImage->GetDict()) {
   1796     sImageAlias = pImageDict->GetStringFor("Name");
   1797     if (sImageAlias.IsEmpty())
   1798       sImageAlias = "IMG";
   1799   }
   1800 
   1801   CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
   1802   CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources");
   1803   if (!pStreamResList)
   1804     pStreamResList = pStreamDict->SetNewFor<CPDF_Dictionary>("Resources");
   1805 
   1806   CPDF_Dictionary* pXObject =
   1807       pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
   1808   pXObject->SetNewFor<CPDF_Reference>(sImageAlias, pDoc, pImage->GetObjNum());
   1809 }
   1810 
   1811 void CPDFSDK_Widget::RemoveAppearance(const CFX_ByteString& sAPType) {
   1812   if (CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"))
   1813     pAPDict->RemoveFor(sAPType);
   1814 }
   1815 
   1816 bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
   1817                                PDFSDK_FieldAction& data,
   1818                                CPDFSDK_PageView* pPageView) {
   1819   CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv();
   1820 
   1821 #ifdef PDF_ENABLE_XFA
   1822   CPDFXFA_Context* pContext = pFormFillEnv->GetXFAContext();
   1823   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
   1824     XFA_EVENTTYPE eEventType = GetXFAEventType(type, data.bWillCommit);
   1825 
   1826     if (eEventType != XFA_EVENT_Unknown) {
   1827       if (CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) {
   1828         CXFA_EventParam param;
   1829         param.m_eType = eEventType;
   1830         param.m_wsChange = data.sChange;
   1831         param.m_iCommitKey = data.nCommitKey;
   1832         param.m_bShift = data.bShift;
   1833         param.m_iSelStart = data.nSelStart;
   1834         param.m_iSelEnd = data.nSelEnd;
   1835         param.m_wsFullText = data.sValue;
   1836         param.m_bKeyDown = data.bKeyDown;
   1837         param.m_bModifier = data.bModifier;
   1838         param.m_wsNewText = data.sValue;
   1839         if (data.nSelEnd > data.nSelStart)
   1840           param.m_wsNewText.Delete(data.nSelStart,
   1841                                    data.nSelEnd - data.nSelStart);
   1842         for (int i = data.sChange.GetLength() - 1; i >= 0; i--)
   1843           param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
   1844         param.m_wsPrevText = data.sValue;
   1845 
   1846         CXFA_WidgetAcc* pAcc = hWidget->GetDataAcc();
   1847         param.m_pTarget = pAcc;
   1848         int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
   1849 
   1850         if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
   1851           pDocView->UpdateDocView();
   1852 
   1853         if (nRet == XFA_EVENTERROR_Success)
   1854           return true;
   1855       }
   1856     }
   1857   }
   1858 #endif  // PDF_ENABLE_XFA
   1859 
   1860   CPDF_Action action = GetAAction(type);
   1861   if (action.GetDict() && action.GetType() != CPDF_Action::Unknown) {
   1862     CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHander();
   1863     return pActionHandler->DoAction_Field(action, type, pFormFillEnv,
   1864                                           GetFormField(), data);
   1865   }
   1866   return false;
   1867 }
   1868 
   1869 CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) {
   1870   switch (eAAT) {
   1871     case CPDF_AAction::CursorEnter:
   1872     case CPDF_AAction::CursorExit:
   1873     case CPDF_AAction::ButtonDown:
   1874     case CPDF_AAction::ButtonUp:
   1875     case CPDF_AAction::GetFocus:
   1876     case CPDF_AAction::LoseFocus:
   1877     case CPDF_AAction::PageOpen:
   1878     case CPDF_AAction::PageClose:
   1879     case CPDF_AAction::PageVisible:
   1880     case CPDF_AAction::PageInvisible:
   1881       return CPDFSDK_BAAnnot::GetAAction(eAAT);
   1882 
   1883     case CPDF_AAction::KeyStroke:
   1884     case CPDF_AAction::Format:
   1885     case CPDF_AAction::Validate:
   1886     case CPDF_AAction::Calculate: {
   1887       CPDF_FormField* pField = GetFormField();
   1888       if (pField->GetAdditionalAction().GetDict())
   1889         return pField->GetAdditionalAction().GetAction(eAAT);
   1890       return CPDFSDK_BAAnnot::GetAAction(eAAT);
   1891     }
   1892     default:
   1893       break;
   1894   }
   1895 
   1896   return CPDF_Action();
   1897 }
   1898 
   1899 CFX_WideString CPDFSDK_Widget::GetAlternateName() const {
   1900   CPDF_FormField* pFormField = GetFormField();
   1901   return pFormField->GetAlternateName();
   1902 }
   1903 
   1904 int32_t CPDFSDK_Widget::GetAppearanceAge() const {
   1905   return m_nAppAge;
   1906 }
   1907 
   1908 int32_t CPDFSDK_Widget::GetValueAge() const {
   1909   return m_nValueAge;
   1910 }
   1911