• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ARGBToColorRef(FX_ARGB argb)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 
CPDFSDK_Widget(CPDF_Annot * pAnnot,CPDFSDK_PageView * pPageView,CPDFSDK_InterForm * pInterForm)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 
~CPDFSDK_Widget()70 CPDFSDK_Widget::~CPDFSDK_Widget() {}
71 
72 #ifdef PDF_ENABLE_XFA
GetMixXFAWidget() const73 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 
GetGroupMixXFAWidget()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 
GetXFAWidgetHandler() const110 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 
GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT)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 
GetXFAEventType(CPDF_AAction::AActionType eAAT,bool bWillCommit)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 
HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT)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 
OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,PDFSDK_FieldAction & data,CPDFSDK_PageView * pPageView)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 
Synchronize(bool bSynchronizeElse)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 
SynchronizeXFAValue()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 
SynchronizeXFAItems()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 
SynchronizeXFAValue(CXFA_FFDocView * pXFADocView,CXFA_FFWidget * hWidget,CPDF_FormField * pFormField,CPDF_FormControl * pFormControl)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 
SynchronizeXFAItems(CXFA_FFDocView * pXFADocView,CXFA_FFWidget * hWidget,CPDF_FormField * pFormField,CPDF_FormControl * pFormControl)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 
IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode)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 
GetFieldType() const500 int CPDFSDK_Widget::GetFieldType() const {
501   CPDF_FormField* pField = GetFormField();
502   return pField ? pField->GetFieldType() : FIELDTYPE_UNKNOWN;
503 }
504 
IsAppearanceValid()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 
GetLayoutOrder() const515 int CPDFSDK_Widget::GetLayoutOrder() const {
516   return 2;
517 }
518 
GetFieldFlags() const519 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 
IsSignatureWidget() const527 bool CPDFSDK_Widget::IsSignatureWidget() const {
528   return GetFieldType() == FIELDTYPE_SIGNATURE;
529 }
530 
GetFormField() const531 CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
532   CPDF_FormControl* pControl = GetFormControl();
533   return pControl ? pControl->GetField() : nullptr;
534 }
535 
GetFormControl() const536 CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
537   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
538   return pPDFInterForm->GetControlByDict(GetAnnotDict());
539 }
540 
GetFormControl(CPDF_InterForm * pInterForm,const CPDF_Dictionary * pAnnotDict)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 
GetRotate() const548 int CPDFSDK_Widget::GetRotate() const {
549   CPDF_FormControl* pCtrl = GetFormControl();
550   return pCtrl->GetRotation() % 360;
551 }
552 
553 #ifdef PDF_ENABLE_XFA
GetName() const554 CFX_WideString CPDFSDK_Widget::GetName() const {
555   CPDF_FormField* pFormField = GetFormField();
556   return pFormField->GetFullName();
557 }
558 #endif  // PDF_ENABLE_XFA
559 
GetFillColor(FX_COLORREF & color) const560 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 
GetBorderColor(FX_COLORREF & color) const567 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 
GetTextColor(FX_COLORREF & color) const574 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 
GetFontSize() const587 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 
GetSelectedIndex(int nIndex) const597 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
GetValue(bool bDisplay) const611 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