cpdfsdk_widget.cpp revision 4d3acf4ec42bf6e838f9060103aff98fbf170794
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_FloatRect rc = GetRect();
845  FX_COLORREF color = m_pInterForm->GetHighlightColor(nFieldType);
846  uint8_t alpha = m_pInterForm->GetHighlightAlpha();
847
848  CFX_FloatRect rcDevice;
849  CFX_Matrix page2device;
850  pPageView->GetCurrentMatrix(page2device);
851  page2device.Transform(((FX_FLOAT)rc.left), ((FX_FLOAT)rc.bottom),
852                        rcDevice.left, rcDevice.bottom);
853  page2device.Transform(((FX_FLOAT)rc.right), ((FX_FLOAT)rc.top),
854                        rcDevice.right, rcDevice.top);
855
856  rcDevice.Normalize();
857
858  FX_ARGB argb = ArgbEncode((int)alpha, color);
859  FX_RECT rcDev((int)rcDevice.left, (int)rcDevice.top, (int)rcDevice.right,
860                (int)rcDevice.bottom);
861  pDevice->FillRect(&rcDev, argb);
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, crBorder;
893
894  int iColorType;
895  FX_FLOAT fc[4];
896
897  pControl->GetOriginalBackgroundColor(iColorType, fc);
898  if (iColorType > 0)
899    crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
900
901  pControl->GetOriginalBorderColor(iColorType, fc);
902  if (iColorType > 0)
903    crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
904
905  FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
906  CPWL_Dash dsBorder(3, 0, 0);
907  CPWL_Color crLeftTop, 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 = CPWL_Utils::DevideColor(crBackground, 2);
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(
1054               rcWindow, CPWL_Utils::SubstractColor(crBackground, 0.25f)) +
1055           CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1056                                          crLeftTop, crRightBottom,
1057                                          nBorderStyle, dsBorder) +
1058           CPWL_Utils::GetPushButtonAppStream(
1059               iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map,
1060               pDownIcon, iconFit, csDownCaption, crText, fFontSize, nLayout);
1061
1062    WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP);
1063    if (pDownIcon)
1064      AddImageToAppearance("D", pDownIcon);
1065  } else {
1066    RemoveAppearance("D");
1067    RemoveAppearance("R");
1068  }
1069}
1070
1071void CPDFSDK_Widget::ResetAppearance_CheckBox() {
1072  CPDF_FormControl* pControl = GetFormControl();
1073  CPWL_Color crBackground, crBorder, crText;
1074  int iColorType;
1075  FX_FLOAT fc[4];
1076
1077  pControl->GetOriginalBackgroundColor(iColorType, fc);
1078  if (iColorType > 0)
1079    crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1080
1081  pControl->GetOriginalBorderColor(iColorType, fc);
1082  if (iColorType > 0)
1083    crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1084
1085  FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
1086  CPWL_Dash dsBorder(3, 0, 0);
1087  CPWL_Color crLeftTop, crRightBottom;
1088
1089  BorderStyle nBorderStyle = GetBorderStyle();
1090  switch (nBorderStyle) {
1091    case BorderStyle::DASH:
1092      dsBorder = CPWL_Dash(3, 3, 0);
1093      break;
1094    case BorderStyle::BEVELED:
1095      fBorderWidth *= 2;
1096      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
1097      crRightBottom = CPWL_Utils::DevideColor(crBackground, 2);
1098      break;
1099    case BorderStyle::INSET:
1100      fBorderWidth *= 2;
1101      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
1102      crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
1103      break;
1104    default:
1105      break;
1106  }
1107
1108  CFX_FloatRect rcWindow = GetRotatedRect();
1109  CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
1110
1111  CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
1112  if (da.HasColor()) {
1113    da.GetColor(iColorType, fc);
1114    crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1115  }
1116
1117  int32_t nStyle = 0;
1118
1119  CFX_WideString csWCaption = pControl->GetNormalCaption();
1120  if (csWCaption.GetLength() > 0) {
1121    switch (csWCaption[0]) {
1122      case L'l':
1123        nStyle = PCS_CIRCLE;
1124        break;
1125      case L'8':
1126        nStyle = PCS_CROSS;
1127        break;
1128      case L'u':
1129        nStyle = PCS_DIAMOND;
1130        break;
1131      case L'n':
1132        nStyle = PCS_SQUARE;
1133        break;
1134      case L'H':
1135        nStyle = PCS_STAR;
1136        break;
1137      default:  // L'4'
1138        nStyle = PCS_CHECK;
1139        break;
1140    }
1141  } else {
1142    nStyle = PCS_CHECK;
1143  }
1144
1145  CFX_ByteString csAP_N_ON =
1146      CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
1147      CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1148                                     crLeftTop, crRightBottom, nBorderStyle,
1149                                     dsBorder);
1150
1151  CFX_ByteString csAP_N_OFF = csAP_N_ON;
1152
1153  switch (nBorderStyle) {
1154    case BorderStyle::BEVELED: {
1155      CPWL_Color crTemp = crLeftTop;
1156      crLeftTop = crRightBottom;
1157      crRightBottom = crTemp;
1158      break;
1159    }
1160    case BorderStyle::INSET: {
1161      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
1162      crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1163      break;
1164    }
1165    default:
1166      break;
1167  }
1168
1169  CFX_ByteString csAP_D_ON =
1170      CPWL_Utils::GetRectFillAppStream(
1171          rcWindow, CPWL_Utils::SubstractColor(crBackground, 0.25f)) +
1172      CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1173                                     crLeftTop, crRightBottom, nBorderStyle,
1174                                     dsBorder);
1175
1176  CFX_ByteString csAP_D_OFF = csAP_D_ON;
1177
1178  csAP_N_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText);
1179  csAP_D_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText);
1180
1181  WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON,
1182                  pControl->GetCheckedAPState());
1183  WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off");
1184
1185  WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON,
1186                  pControl->GetCheckedAPState());
1187  WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off");
1188
1189  CFX_ByteString csAS = GetAppState();
1190  if (csAS.IsEmpty())
1191    SetAppState("Off");
1192}
1193
1194void CPDFSDK_Widget::ResetAppearance_RadioButton() {
1195  CPDF_FormControl* pControl = GetFormControl();
1196  CPWL_Color crBackground, crBorder, crText;
1197  int iColorType;
1198  FX_FLOAT fc[4];
1199
1200  pControl->GetOriginalBackgroundColor(iColorType, fc);
1201  if (iColorType > 0)
1202    crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1203
1204  pControl->GetOriginalBorderColor(iColorType, fc);
1205  if (iColorType > 0)
1206    crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1207
1208  FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
1209  CPWL_Dash dsBorder(3, 0, 0);
1210  CPWL_Color crLeftTop, crRightBottom;
1211
1212  BorderStyle nBorderStyle = GetBorderStyle();
1213  switch (nBorderStyle) {
1214    case BorderStyle::DASH:
1215      dsBorder = CPWL_Dash(3, 3, 0);
1216      break;
1217    case BorderStyle::BEVELED:
1218      fBorderWidth *= 2;
1219      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
1220      crRightBottom = CPWL_Utils::DevideColor(crBackground, 2);
1221      break;
1222    case BorderStyle::INSET:
1223      fBorderWidth *= 2;
1224      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
1225      crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
1226      break;
1227    default:
1228      break;
1229  }
1230
1231  CFX_FloatRect rcWindow = GetRotatedRect();
1232  CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
1233
1234  CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
1235  if (da.HasColor()) {
1236    da.GetColor(iColorType, fc);
1237    crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1238  }
1239
1240  int32_t nStyle = 0;
1241
1242  CFX_WideString csWCaption = pControl->GetNormalCaption();
1243  if (csWCaption.GetLength() > 0) {
1244    switch (csWCaption[0]) {
1245      default:  // L'l':
1246        nStyle = PCS_CIRCLE;
1247        break;
1248      case L'8':
1249        nStyle = PCS_CROSS;
1250        break;
1251      case L'u':
1252        nStyle = PCS_DIAMOND;
1253        break;
1254      case L'n':
1255        nStyle = PCS_SQUARE;
1256        break;
1257      case L'H':
1258        nStyle = PCS_STAR;
1259        break;
1260      case L'4':
1261        nStyle = PCS_CHECK;
1262        break;
1263    }
1264  } else {
1265    nStyle = PCS_CIRCLE;
1266  }
1267
1268  CFX_ByteString csAP_N_ON;
1269
1270  CFX_FloatRect rcCenter =
1271      CPWL_Utils::DeflateRect(CPWL_Utils::GetCenterSquare(rcWindow), 1.0f);
1272
1273  if (nStyle == PCS_CIRCLE) {
1274    if (nBorderStyle == BorderStyle::BEVELED) {
1275      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
1276      crRightBottom = CPWL_Utils::SubstractColor(crBackground, 0.25f);
1277    } else if (nBorderStyle == BorderStyle::INSET) {
1278      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5f);
1279      crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75f);
1280    }
1281
1282    csAP_N_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBackground) +
1283                CPWL_Utils::GetCircleBorderAppStream(
1284                    rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom,
1285                    nBorderStyle, dsBorder);
1286  } else {
1287    csAP_N_ON = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
1288                CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1289                                               crLeftTop, crRightBottom,
1290                                               nBorderStyle, dsBorder);
1291  }
1292
1293  CFX_ByteString csAP_N_OFF = csAP_N_ON;
1294
1295  switch (nBorderStyle) {
1296    case BorderStyle::BEVELED: {
1297      CPWL_Color crTemp = crLeftTop;
1298      crLeftTop = crRightBottom;
1299      crRightBottom = crTemp;
1300      break;
1301    }
1302    case BorderStyle::INSET: {
1303      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
1304      crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1305      break;
1306    }
1307    default:
1308      break;
1309  }
1310
1311  CFX_ByteString csAP_D_ON;
1312
1313  if (nStyle == PCS_CIRCLE) {
1314    CPWL_Color crBK = CPWL_Utils::SubstractColor(crBackground, 0.25f);
1315    if (nBorderStyle == BorderStyle::BEVELED) {
1316      crLeftTop = CPWL_Utils::SubstractColor(crBackground, 0.25f);
1317      crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1318      crBK = crBackground;
1319    } else if (nBorderStyle == BorderStyle::INSET) {
1320      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
1321      crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1322    }
1323
1324    csAP_D_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBK) +
1325                CPWL_Utils::GetCircleBorderAppStream(
1326                    rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom,
1327                    nBorderStyle, dsBorder);
1328  } else {
1329    csAP_D_ON = CPWL_Utils::GetRectFillAppStream(
1330                    rcWindow, CPWL_Utils::SubstractColor(crBackground, 0.25f)) +
1331                CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1332                                               crLeftTop, crRightBottom,
1333                                               nBorderStyle, dsBorder);
1334  }
1335
1336  CFX_ByteString csAP_D_OFF = csAP_D_ON;
1337
1338  csAP_N_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText);
1339  csAP_D_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText);
1340
1341  WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON,
1342                  pControl->GetCheckedAPState());
1343  WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off");
1344
1345  WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON,
1346                  pControl->GetCheckedAPState());
1347  WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off");
1348
1349  CFX_ByteString csAS = GetAppState();
1350  if (csAS.IsEmpty())
1351    SetAppState("Off");
1352}
1353
1354void CPDFSDK_Widget::ResetAppearance_ComboBox(const CFX_WideString* sValue) {
1355  CPDF_FormControl* pControl = GetFormControl();
1356  CPDF_FormField* pField = pControl->GetField();
1357  CFX_ByteTextBuf sBody, sLines;
1358
1359  CFX_FloatRect rcClient = GetClientRect();
1360  CFX_FloatRect rcButton = rcClient;
1361  rcButton.left = rcButton.right - 13;
1362  rcButton.Normalize();
1363
1364  std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
1365  pEdit->EnableRefresh(false);
1366
1367  CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler());
1368  pEdit->SetFontMap(&font_map);
1369
1370  CFX_FloatRect rcEdit = rcClient;
1371  rcEdit.right = rcButton.left;
1372  rcEdit.Normalize();
1373
1374  pEdit->SetPlateRect(rcEdit);
1375  pEdit->SetAlignmentV(1, true);
1376
1377  FX_FLOAT fFontSize = GetFontSize();
1378  if (IsFloatZero(fFontSize))
1379    pEdit->SetAutoFontSize(true, true);
1380  else
1381    pEdit->SetFontSize(fFontSize);
1382
1383  pEdit->Initialize();
1384
1385  if (sValue) {
1386    pEdit->SetText(*sValue);
1387  } else {
1388    int32_t nCurSel = pField->GetSelectedIndex(0);
1389    if (nCurSel < 0)
1390      pEdit->SetText(pField->GetValue());
1391    else
1392      pEdit->SetText(pField->GetOptionLabel(nCurSel));
1393  }
1394
1395  CFX_FloatRect rcContent = pEdit->GetContentRect();
1396
1397  CFX_ByteString sEdit =
1398      CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_FloatPoint());
1399  if (sEdit.GetLength() > 0) {
1400    sBody << "/Tx BMC\n"
1401          << "q\n";
1402    if (rcContent.Width() > rcEdit.Width() ||
1403        rcContent.Height() > rcEdit.Height()) {
1404      sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width()
1405            << " " << rcEdit.Height() << " re\nW\nn\n";
1406    }
1407
1408    CPWL_Color crText = GetTextPWLColor();
1409    sBody << "BT\n"
1410          << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n"
1411          << "Q\nEMC\n";
1412  }
1413
1414  sBody << CPWL_Utils::GetDropButtonAppStream(rcButton);
1415
1416  CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
1417                       sLines.AsStringC() + sBody.AsStringC();
1418
1419  WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
1420}
1421
1422void CPDFSDK_Widget::ResetAppearance_ListBox() {
1423  CPDF_FormControl* pControl = GetFormControl();
1424  CPDF_FormField* pField = pControl->GetField();
1425  CFX_FloatRect rcClient = GetClientRect();
1426  CFX_ByteTextBuf sBody, sLines;
1427
1428  std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
1429  pEdit->EnableRefresh(false);
1430
1431  CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler());
1432  pEdit->SetFontMap(&font_map);
1433
1434  pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f));
1435
1436  FX_FLOAT fFontSize = GetFontSize();
1437
1438  pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize);
1439
1440  pEdit->Initialize();
1441
1442  CFX_ByteTextBuf sList;
1443  FX_FLOAT fy = rcClient.top;
1444
1445  int32_t nTop = pField->GetTopVisibleIndex();
1446  int32_t nCount = pField->CountOptions();
1447  int32_t nSelCount = pField->CountSelectedItems();
1448
1449  for (int32_t i = nTop; i < nCount; ++i) {
1450    bool bSelected = false;
1451    for (int32_t j = 0; j < nSelCount; ++j) {
1452      if (pField->GetSelectedIndex(j) == i) {
1453        bSelected = true;
1454        break;
1455      }
1456    }
1457
1458    pEdit->SetText(pField->GetOptionLabel(i));
1459
1460    CFX_FloatRect rcContent = pEdit->GetContentRect();
1461    FX_FLOAT fItemHeight = rcContent.Height();
1462
1463    if (bSelected) {
1464      CFX_FloatRect rcItem =
1465          CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy);
1466      sList << "q\n"
1467            << CPWL_Utils::GetColorAppStream(
1468                   CPWL_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f,
1469                              113.0f / 255.0f),
1470                   true)
1471            << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width()
1472            << " " << rcItem.Height() << " re f\n"
1473            << "Q\n";
1474
1475      sList << "BT\n"
1476            << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY, 1),
1477                                             true)
1478            << CPWL_Utils::GetEditAppStream(pEdit.get(),
1479                                            CFX_FloatPoint(0.0f, fy))
1480            << "ET\n";
1481    } else {
1482      CPWL_Color crText = GetTextPWLColor();
1483      sList << "BT\n"
1484            << CPWL_Utils::GetColorAppStream(crText, true)
1485            << CPWL_Utils::GetEditAppStream(pEdit.get(),
1486                                            CFX_FloatPoint(0.0f, fy))
1487            << "ET\n";
1488    }
1489
1490    fy -= fItemHeight;
1491  }
1492
1493  if (sList.GetSize() > 0) {
1494    sBody << "/Tx BMC\n"
1495          << "q\n"
1496          << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width()
1497          << " " << rcClient.Height() << " re\nW\nn\n";
1498    sBody << sList << "Q\nEMC\n";
1499  }
1500
1501  CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
1502                       sLines.AsStringC() + sBody.AsStringC();
1503
1504  WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
1505}
1506
1507void CPDFSDK_Widget::ResetAppearance_TextField(const CFX_WideString* sValue) {
1508  CPDF_FormControl* pControl = GetFormControl();
1509  CPDF_FormField* pField = pControl->GetField();
1510  CFX_ByteTextBuf sBody, sLines;
1511
1512  std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
1513  pEdit->EnableRefresh(false);
1514
1515  CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler());
1516  pEdit->SetFontMap(&font_map);
1517
1518  CFX_FloatRect rcClient = GetClientRect();
1519  pEdit->SetPlateRect(rcClient);
1520  pEdit->SetAlignmentH(pControl->GetControlAlignment(), true);
1521
1522  uint32_t dwFieldFlags = pField->GetFieldFlags();
1523  bool bMultiLine = (dwFieldFlags >> 12) & 1;
1524
1525  if (bMultiLine) {
1526    pEdit->SetMultiLine(true, true);
1527    pEdit->SetAutoReturn(true, true);
1528  } else {
1529    pEdit->SetAlignmentV(1, true);
1530  }
1531
1532  uint16_t subWord = 0;
1533  if ((dwFieldFlags >> 13) & 1) {
1534    subWord = '*';
1535    pEdit->SetPasswordChar(subWord, true);
1536  }
1537
1538  int nMaxLen = pField->GetMaxLen();
1539  bool bCharArray = (dwFieldFlags >> 24) & 1;
1540  FX_FLOAT fFontSize = GetFontSize();
1541
1542#ifdef PDF_ENABLE_XFA
1543  CFX_WideString sValueTmp;
1544  if (!sValue && GetMixXFAWidget()) {
1545    sValueTmp = GetValue(true);
1546    sValue = &sValueTmp;
1547  }
1548#endif  // PDF_ENABLE_XFA
1549
1550  if (nMaxLen > 0) {
1551    if (bCharArray) {
1552      pEdit->SetCharArray(nMaxLen);
1553
1554      if (IsFloatZero(fFontSize)) {
1555        fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0),
1556                                                        rcClient, nMaxLen);
1557      }
1558    } else {
1559      if (sValue)
1560        nMaxLen = sValue->GetLength();
1561      pEdit->SetLimitChar(nMaxLen);
1562    }
1563  }
1564
1565  if (IsFloatZero(fFontSize))
1566    pEdit->SetAutoFontSize(true, true);
1567  else
1568    pEdit->SetFontSize(fFontSize);
1569
1570  pEdit->Initialize();
1571  pEdit->SetText(sValue ? *sValue : pField->GetValue());
1572
1573  CFX_FloatRect rcContent = pEdit->GetContentRect();
1574  CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(
1575      pEdit.get(), CFX_FloatPoint(), nullptr, !bCharArray, subWord);
1576
1577  if (sEdit.GetLength() > 0) {
1578    sBody << "/Tx BMC\n"
1579          << "q\n";
1580    if (rcContent.Width() > rcClient.Width() ||
1581        rcContent.Height() > rcClient.Height()) {
1582      sBody << rcClient.left << " " << rcClient.bottom << " "
1583            << rcClient.Width() << " " << rcClient.Height() << " re\nW\nn\n";
1584    }
1585    CPWL_Color crText = GetTextPWLColor();
1586    sBody << "BT\n"
1587          << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n"
1588          << "Q\nEMC\n";
1589  }
1590
1591  if (bCharArray) {
1592    switch (GetBorderStyle()) {
1593      case BorderStyle::SOLID: {
1594        CFX_ByteString sColor =
1595            CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false);
1596        if (sColor.GetLength() > 0) {
1597          sLines << "q\n"
1598                 << GetBorderWidth() << " w\n"
1599                 << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false)
1600                 << " 2 J 0 j\n";
1601
1602          for (int32_t i = 1; i < nMaxLen; ++i) {
1603            sLines << rcClient.left +
1604                          ((rcClient.right - rcClient.left) / nMaxLen) * i
1605                   << " " << rcClient.bottom << " m\n"
1606                   << rcClient.left +
1607                          ((rcClient.right - rcClient.left) / nMaxLen) * i
1608                   << " " << rcClient.top << " l S\n";
1609          }
1610
1611          sLines << "Q\n";
1612        }
1613        break;
1614      }
1615      case BorderStyle::DASH: {
1616        CFX_ByteString sColor =
1617            CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false);
1618        if (sColor.GetLength() > 0) {
1619          CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0);
1620
1621          sLines << "q\n"
1622                 << GetBorderWidth() << " w\n"
1623                 << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false)
1624                 << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] "
1625                 << dsBorder.nPhase << " d\n";
1626
1627          for (int32_t i = 1; i < nMaxLen; ++i) {
1628            sLines << rcClient.left +
1629                          ((rcClient.right - rcClient.left) / nMaxLen) * i
1630                   << " " << rcClient.bottom << " m\n"
1631                   << rcClient.left +
1632                          ((rcClient.right - rcClient.left) / nMaxLen) * i
1633                   << " " << rcClient.top << " l S\n";
1634          }
1635
1636          sLines << "Q\n";
1637        }
1638        break;
1639      }
1640      default:
1641        break;
1642    }
1643  }
1644
1645  CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
1646                       sLines.AsStringC() + sBody.AsStringC();
1647  WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
1648}
1649
1650CFX_FloatRect CPDFSDK_Widget::GetClientRect() const {
1651  CFX_FloatRect rcWindow = GetRotatedRect();
1652  FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
1653  switch (GetBorderStyle()) {
1654    case BorderStyle::BEVELED:
1655    case BorderStyle::INSET:
1656      fBorderWidth *= 2.0f;
1657      break;
1658    default:
1659      break;
1660  }
1661
1662  return CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
1663}
1664
1665CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const {
1666  CFX_FloatRect rectAnnot = GetRect();
1667  FX_FLOAT fWidth = rectAnnot.right - rectAnnot.left;
1668  FX_FLOAT fHeight = rectAnnot.top - rectAnnot.bottom;
1669
1670  CPDF_FormControl* pControl = GetFormControl();
1671  CFX_FloatRect rcPDFWindow;
1672  switch (abs(pControl->GetRotation() % 360)) {
1673    case 0:
1674    case 180:
1675    default:
1676      rcPDFWindow = CFX_FloatRect(0, 0, fWidth, fHeight);
1677      break;
1678    case 90:
1679    case 270:
1680      rcPDFWindow = CFX_FloatRect(0, 0, fHeight, fWidth);
1681      break;
1682  }
1683
1684  return rcPDFWindow;
1685}
1686
1687CFX_ByteString CPDFSDK_Widget::GetBackgroundAppStream() const {
1688  CPWL_Color crBackground = GetFillPWLColor();
1689  if (crBackground.nColorType != COLORTYPE_TRANSPARENT)
1690    return CPWL_Utils::GetRectFillAppStream(GetRotatedRect(), crBackground);
1691
1692  return "";
1693}
1694
1695CFX_ByteString CPDFSDK_Widget::GetBorderAppStream() const {
1696  CFX_FloatRect rcWindow = GetRotatedRect();
1697  CPWL_Color crBorder = GetBorderPWLColor();
1698  CPWL_Color crBackground = GetFillPWLColor();
1699  CPWL_Color crLeftTop, crRightBottom;
1700
1701  FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
1702  CPWL_Dash dsBorder(3, 0, 0);
1703
1704  BorderStyle nBorderStyle = GetBorderStyle();
1705  switch (nBorderStyle) {
1706    case BorderStyle::DASH:
1707      dsBorder = CPWL_Dash(3, 3, 0);
1708      break;
1709    case BorderStyle::BEVELED:
1710      fBorderWidth *= 2;
1711      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
1712      crRightBottom = CPWL_Utils::DevideColor(crBackground, 2);
1713      break;
1714    case BorderStyle::INSET:
1715      fBorderWidth *= 2;
1716      crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
1717      crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
1718      break;
1719    default:
1720      break;
1721  }
1722
1723  return CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1724                                        crLeftTop, crRightBottom, nBorderStyle,
1725                                        dsBorder);
1726}
1727
1728CFX_Matrix CPDFSDK_Widget::GetMatrix() const {
1729  CFX_Matrix mt;
1730  CPDF_FormControl* pControl = GetFormControl();
1731  CFX_FloatRect rcAnnot = GetRect();
1732  FX_FLOAT fWidth = rcAnnot.right - rcAnnot.left;
1733  FX_FLOAT fHeight = rcAnnot.top - rcAnnot.bottom;
1734
1735  switch (abs(pControl->GetRotation() % 360)) {
1736    case 0:
1737    default:
1738      mt = CFX_Matrix(1, 0, 0, 1, 0, 0);
1739      break;
1740    case 90:
1741      mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0);
1742      break;
1743    case 180:
1744      mt = CFX_Matrix(-1, 0, 0, -1, fWidth, fHeight);
1745      break;
1746    case 270:
1747      mt = CFX_Matrix(0, -1, 1, 0, 0, fHeight);
1748      break;
1749  }
1750
1751  return mt;
1752}
1753
1754CPWL_Color CPDFSDK_Widget::GetTextPWLColor() const {
1755  CPWL_Color crText = CPWL_Color(COLORTYPE_GRAY, 0);
1756
1757  CPDF_FormControl* pFormCtrl = GetFormControl();
1758  CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
1759  if (da.HasColor()) {
1760    int32_t iColorType;
1761    FX_FLOAT fc[4];
1762    da.GetColor(iColorType, fc);
1763    crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1764  }
1765
1766  return crText;
1767}
1768
1769CPWL_Color CPDFSDK_Widget::GetBorderPWLColor() const {
1770  CPWL_Color crBorder;
1771
1772  CPDF_FormControl* pFormCtrl = GetFormControl();
1773  int32_t iColorType;
1774  FX_FLOAT fc[4];
1775  pFormCtrl->GetOriginalBorderColor(iColorType, fc);
1776  if (iColorType > 0)
1777    crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1778
1779  return crBorder;
1780}
1781
1782CPWL_Color CPDFSDK_Widget::GetFillPWLColor() const {
1783  CPWL_Color crFill;
1784
1785  CPDF_FormControl* pFormCtrl = GetFormControl();
1786  int32_t iColorType;
1787  FX_FLOAT fc[4];
1788  pFormCtrl->GetOriginalBackgroundColor(iColorType, fc);
1789  if (iColorType > 0)
1790    crFill = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1791
1792  return crFill;
1793}
1794
1795void CPDFSDK_Widget::AddImageToAppearance(const CFX_ByteString& sAPType,
1796                                          CPDF_Stream* pImage) {
1797  CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP");
1798  CPDF_Stream* pStream = pAPDict->GetStreamFor(sAPType);
1799  CPDF_Dictionary* pStreamDict = pStream->GetDict();
1800  CFX_ByteString sImageAlias = "IMG";
1801
1802  if (CPDF_Dictionary* pImageDict = pImage->GetDict()) {
1803    sImageAlias = pImageDict->GetStringFor("Name");
1804    if (sImageAlias.IsEmpty())
1805      sImageAlias = "IMG";
1806  }
1807
1808  CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
1809  CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources");
1810  if (!pStreamResList)
1811    pStreamResList = pStreamDict->SetNewFor<CPDF_Dictionary>("Resources");
1812
1813  CPDF_Dictionary* pXObject =
1814      pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
1815  pXObject->SetNewFor<CPDF_Reference>(sImageAlias, pDoc, pImage->GetObjNum());
1816}
1817
1818void CPDFSDK_Widget::RemoveAppearance(const CFX_ByteString& sAPType) {
1819  if (CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"))
1820    pAPDict->RemoveFor(sAPType);
1821}
1822
1823bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
1824                               PDFSDK_FieldAction& data,
1825                               CPDFSDK_PageView* pPageView) {
1826  CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv();
1827
1828#ifdef PDF_ENABLE_XFA
1829  CPDFXFA_Context* pContext = pFormFillEnv->GetXFAContext();
1830  if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
1831    XFA_EVENTTYPE eEventType = GetXFAEventType(type, data.bWillCommit);
1832
1833    if (eEventType != XFA_EVENT_Unknown) {
1834      if (CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) {
1835        CXFA_EventParam param;
1836        param.m_eType = eEventType;
1837        param.m_wsChange = data.sChange;
1838        param.m_iCommitKey = data.nCommitKey;
1839        param.m_bShift = data.bShift;
1840        param.m_iSelStart = data.nSelStart;
1841        param.m_iSelEnd = data.nSelEnd;
1842        param.m_wsFullText = data.sValue;
1843        param.m_bKeyDown = data.bKeyDown;
1844        param.m_bModifier = data.bModifier;
1845        param.m_wsNewText = data.sValue;
1846        if (data.nSelEnd > data.nSelStart)
1847          param.m_wsNewText.Delete(data.nSelStart,
1848                                   data.nSelEnd - data.nSelStart);
1849        for (int i = data.sChange.GetLength() - 1; i >= 0; i--)
1850          param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
1851        param.m_wsPrevText = data.sValue;
1852
1853        CXFA_WidgetAcc* pAcc = hWidget->GetDataAcc();
1854        param.m_pTarget = pAcc;
1855        int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
1856
1857        if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
1858          pDocView->UpdateDocView();
1859
1860        if (nRet == XFA_EVENTERROR_Success)
1861          return true;
1862      }
1863    }
1864  }
1865#endif  // PDF_ENABLE_XFA
1866
1867  CPDF_Action action = GetAAction(type);
1868  if (action.GetDict() && action.GetType() != CPDF_Action::Unknown) {
1869    CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHander();
1870    return pActionHandler->DoAction_Field(action, type, pFormFillEnv,
1871                                          GetFormField(), data);
1872  }
1873  return false;
1874}
1875
1876CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) {
1877  switch (eAAT) {
1878    case CPDF_AAction::CursorEnter:
1879    case CPDF_AAction::CursorExit:
1880    case CPDF_AAction::ButtonDown:
1881    case CPDF_AAction::ButtonUp:
1882    case CPDF_AAction::GetFocus:
1883    case CPDF_AAction::LoseFocus:
1884    case CPDF_AAction::PageOpen:
1885    case CPDF_AAction::PageClose:
1886    case CPDF_AAction::PageVisible:
1887    case CPDF_AAction::PageInvisible:
1888      return CPDFSDK_BAAnnot::GetAAction(eAAT);
1889
1890    case CPDF_AAction::KeyStroke:
1891    case CPDF_AAction::Format:
1892    case CPDF_AAction::Validate:
1893    case CPDF_AAction::Calculate: {
1894      CPDF_FormField* pField = GetFormField();
1895      if (pField->GetAdditionalAction().GetDict())
1896        return pField->GetAdditionalAction().GetAction(eAAT);
1897      return CPDFSDK_BAAnnot::GetAAction(eAAT);
1898    }
1899    default:
1900      break;
1901  }
1902
1903  return CPDF_Action();
1904}
1905
1906CFX_WideString CPDFSDK_Widget::GetAlternateName() const {
1907  CPDF_FormField* pFormField = GetFormField();
1908  return pFormField->GetAlternateName();
1909}
1910
1911int32_t CPDFSDK_Widget::GetAppearanceAge() const {
1912  return m_nAppAge;
1913}
1914
1915int32_t CPDFSDK_Widget::GetValueAge() const {
1916  return m_nValueAge;
1917}
1918
1919bool CPDFSDK_Widget::HitTest(FX_FLOAT pageX, FX_FLOAT pageY) {
1920  CPDF_Annot* pAnnot = GetPDFAnnot();
1921  CFX_FloatRect annotRect = pAnnot->GetRect();
1922  if (!annotRect.Contains(pageX, pageY))
1923    return false;
1924
1925  if (!IsVisible())
1926    return false;
1927
1928  if ((GetFieldFlags() & FIELDFLAG_READONLY) == FIELDFLAG_READONLY)
1929    return false;
1930
1931  return true;
1932}
1933