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
44namespace {
45
46// Convert a FX_ARGB to a FX_COLORREF.
47FX_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
55CPDFSDK_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
70CPDFSDK_Widget::~CPDFSDK_Widget() {}
71
72#ifdef PDF_ENABLE_XFA
73CXFA_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
97CXFA_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
110CXFA_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
123static 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
144static 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
197bool 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
222bool 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
278void 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
327void 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
341void 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
353void 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
422void 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
463bool 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
500int CPDFSDK_Widget::GetFieldType() const {
501  CPDF_FormField* pField = GetFormField();
502  return pField ? pField->GetFieldType() : FIELDTYPE_UNKNOWN;
503}
504
505bool 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
515int CPDFSDK_Widget::GetLayoutOrder() const {
516  return 2;
517}
518
519int 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
527bool CPDFSDK_Widget::IsSignatureWidget() const {
528  return GetFieldType() == FIELDTYPE_SIGNATURE;
529}
530
531CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
532  CPDF_FormControl* pControl = GetFormControl();
533  return pControl ? pControl->GetField() : nullptr;
534}
535
536CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
537  CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
538  return pPDFInterForm->GetControlByDict(GetAnnotDict());
539}
540
541CPDF_FormControl* CPDFSDK_Widget::GetFormControl(
542    CPDF_InterForm* pInterForm,
543    const CPDF_Dictionary* pAnnotDict) {
544  ASSERT(pAnnotDict);
545  return pInterForm->GetControlByDict(pAnnotDict);
546}
547
548int CPDFSDK_Widget::GetRotate() const {
549  CPDF_FormControl* pCtrl = GetFormControl();
550  return pCtrl->GetRotation() % 360;
551}
552
553#ifdef PDF_ENABLE_XFA
554CFX_WideString CPDFSDK_Widget::GetName() const {
555  CPDF_FormField* pFormField = GetFormField();
556  return pFormField->GetFullName();
557}
558#endif  // PDF_ENABLE_XFA
559
560bool 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
567bool 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
574bool 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
587FX_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
597int 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
611CFX_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
621CFX_WideString CPDFSDK_Widget::GetValue() const {
622#endif  // PDF_ENABLE_XFA
623  CPDF_FormField* pFormField = GetFormField();
624  return pFormField->GetValue();
625}
626
627CFX_WideString CPDFSDK_Widget::GetDefaultValue() const {
628  CPDF_FormField* pFormField = GetFormField();
629  return pFormField->GetDefaultValue();
630}
631
632CFX_WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
633  CPDF_FormField* pFormField = GetFormField();
634  return pFormField->GetOptionLabel(nIndex);
635}
636
637int CPDFSDK_Widget::CountOptions() const {
638  CPDF_FormField* pFormField = GetFormField();
639  return pFormField->CountOptions();
640}
641
642bool 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
657int CPDFSDK_Widget::GetTopVisibleIndex() const {
658  CPDF_FormField* pFormField = GetFormField();
659  return pFormField->GetTopVisibleIndex();
660}
661
662bool 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
673int CPDFSDK_Widget::GetAlignment() const {
674  CPDF_FormControl* pFormCtrl = GetFormControl();
675  return pFormCtrl->GetControlAlignment();
676}
677
678int CPDFSDK_Widget::GetMaxLen() const {
679  CPDF_FormField* pFormField = GetFormField();
680  return pFormField->GetMaxLen();
681}
682
683void 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
696void 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
705void CPDFSDK_Widget::SetDefaultValue(const CFX_WideString& sValue) {}
706void 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
717void 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
726void CPDFSDK_Widget::SetTopVisibleIndex(int index) {}
727
728void CPDFSDK_Widget::SetAppModified() {
729  m_bAppModified = true;
730}
731
732void CPDFSDK_Widget::ClearAppModified() {
733  m_bAppModified = false;
734}
735
736bool CPDFSDK_Widget::IsAppModified() const {
737  return m_bAppModified;
738}
739
740#ifdef PDF_ENABLE_XFA
741void 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
757void 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
793CFX_WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) {
794  CPDF_FormField* pFormField = GetFormField();
795  ASSERT(pFormField);
796  return m_pInterForm->OnFormat(pFormField, bFormatted);
797}
798
799void CPDFSDK_Widget::ResetFieldAppearance(bool bValueChanged) {
800  CPDF_FormField* pFormField = GetFormField();
801  ASSERT(pFormField);
802  m_pInterForm->ResetFieldAppearance(pFormField, nullptr, bValueChanged);
803}
804
805void 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
832void CPDFSDK_Widget::UpdateField() {
833  CPDF_FormField* pFormField = GetFormField();
834  ASSERT(pFormField);
835  m_pInterForm->UpdateField(pFormField);
836}
837
838void 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
864void 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
1070void 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
1190void 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
1349void 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
1417void 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
1500void 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
1643CFX_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
1658CFX_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
1680CFX_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
1688CFX_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
1721CFX_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
1747CPWL_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
1762CPWL_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
1775CPWL_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
1788void 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
1811void CPDFSDK_Widget::RemoveAppearance(const CFX_ByteString& sAPType) {
1812  if (CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"))
1813    pAPDict->RemoveFor(sAPType);
1814}
1815
1816bool 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
1869CPDF_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
1899CFX_WideString CPDFSDK_Widget::GetAlternateName() const {
1900  CPDF_FormField* pFormField = GetFormField();
1901  return pFormField->GetAlternateName();
1902}
1903
1904int32_t CPDFSDK_Widget::GetAppearanceAge() const {
1905  return m_nAppAge;
1906}
1907
1908int32_t CPDFSDK_Widget::GetValueAge() const {
1909  return m_nValueAge;
1910}
1911