1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fpdfsdk/cpdfsdk_widget.h"
8
9 #include <memory>
10 #include <sstream>
11
12 #include "constants/annotation_common.h"
13 #include "core/fpdfapi/parser/cpdf_array.h"
14 #include "core/fpdfapi/parser/cpdf_dictionary.h"
15 #include "core/fpdfapi/parser/cpdf_document.h"
16 #include "core/fpdfapi/parser/cpdf_reference.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fpdfapi/parser/cpdf_string.h"
19 #include "core/fpdfdoc/cba_fontmap.h"
20 #include "core/fpdfdoc/cpdf_defaultappearance.h"
21 #include "core/fpdfdoc/cpdf_formcontrol.h"
22 #include "core/fpdfdoc/cpdf_formfield.h"
23 #include "core/fpdfdoc/cpdf_iconfit.h"
24 #include "core/fpdfdoc/cpdf_interactiveform.h"
25 #include "core/fxge/cfx_graphstatedata.h"
26 #include "core/fxge/cfx_pathdata.h"
27 #include "core/fxge/cfx_renderdevice.h"
28 #include "fpdfsdk/cpdfsdk_actionhandler.h"
29 #include "fpdfsdk/cpdfsdk_appstream.h"
30 #include "fpdfsdk/cpdfsdk_fieldaction.h"
31 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
32 #include "fpdfsdk/cpdfsdk_interactiveform.h"
33 #include "fpdfsdk/cpdfsdk_pageview.h"
34 #include "fpdfsdk/pwl/cpwl_edit.h"
35
36 #ifdef PDF_ENABLE_XFA
37 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
38 #include "xfa/fxfa/cxfa_eventparam.h"
39 #include "xfa/fxfa/cxfa_ffdocview.h"
40 #include "xfa/fxfa/cxfa_ffwidget.h"
41 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
42 #include "xfa/fxfa/parser/cxfa_node.h"
43 #endif // PDF_ENABLE_XFA
44
CPDFSDK_Widget(CPDF_Annot * pAnnot,CPDFSDK_PageView * pPageView,CPDFSDK_InteractiveForm * pInteractiveForm)45 CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot,
46 CPDFSDK_PageView* pPageView,
47 CPDFSDK_InteractiveForm* pInteractiveForm)
48 : CPDFSDK_BAAnnot(pAnnot, pPageView),
49 m_pInteractiveForm(pInteractiveForm) {}
50
51 CPDFSDK_Widget::~CPDFSDK_Widget() = default;
52
53 #ifdef PDF_ENABLE_XFA
GetMixXFAWidget() const54 CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const {
55 CPDF_Document::Extension* pContext =
56 m_pPageView->GetFormFillEnv()->GetDocExtension();
57 if (!pContext || !pContext->ContainsExtensionForegroundForm())
58 return nullptr;
59
60 CXFA_FFDocView* pDocView =
61 static_cast<CPDFXFA_Context*>(pContext)->GetXFADocView();
62 if (!pDocView)
63 return nullptr;
64
65 WideString sName;
66 if (GetFieldType() == FormFieldType::kRadioButton) {
67 sName = GetAnnotName();
68 if (sName.IsEmpty())
69 sName = GetName();
70 } else {
71 sName = GetName();
72 }
73
74 if (sName.IsEmpty())
75 return nullptr;
76
77 return pDocView->GetWidgetByName(sName, nullptr);
78 }
79
GetGroupMixXFAWidget() const80 CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() const {
81 CPDF_Document::Extension* pContext =
82 m_pPageView->GetFormFillEnv()->GetDocExtension();
83 if (!pContext || !pContext->ContainsExtensionForegroundForm())
84 return nullptr;
85
86 CXFA_FFDocView* pDocView =
87 static_cast<CPDFXFA_Context*>(pContext)->GetXFADocView();
88 if (!pDocView)
89 return nullptr;
90
91 WideString sName = GetName();
92 return !sName.IsEmpty() ? pDocView->GetWidgetByName(sName, nullptr) : nullptr;
93 }
94
GetXFAWidgetHandler() const95 CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
96 CPDF_Document::Extension* pContext =
97 m_pPageView->GetFormFillEnv()->GetDocExtension();
98 if (!pContext || !pContext->ContainsExtensionForegroundForm())
99 return nullptr;
100
101 if (!m_pWidgetHandler) {
102 CXFA_FFDocView* pDocView =
103 static_cast<CPDFXFA_Context*>(pContext)->GetXFADocView();
104 if (pDocView)
105 m_pWidgetHandler = pDocView->GetWidgetHandler();
106 }
107 return m_pWidgetHandler.Get();
108 }
109
GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT)110 static XFA_EVENTTYPE GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT) {
111 XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
112
113 switch (eXFAAAT) {
114 case PDFSDK_XFA_Click:
115 eEventType = XFA_EVENT_Click;
116 break;
117 case PDFSDK_XFA_Full:
118 eEventType = XFA_EVENT_Full;
119 break;
120 case PDFSDK_XFA_PreOpen:
121 eEventType = XFA_EVENT_PreOpen;
122 break;
123 case PDFSDK_XFA_PostOpen:
124 eEventType = XFA_EVENT_PostOpen;
125 break;
126 }
127
128 return eEventType;
129 }
130
GetXFAEventType(CPDF_AAction::AActionType eAAT,bool bWillCommit)131 static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT,
132 bool bWillCommit) {
133 XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
134
135 switch (eAAT) {
136 case CPDF_AAction::kCursorEnter:
137 eEventType = XFA_EVENT_MouseEnter;
138 break;
139 case CPDF_AAction::kCursorExit:
140 eEventType = XFA_EVENT_MouseExit;
141 break;
142 case CPDF_AAction::kButtonDown:
143 eEventType = XFA_EVENT_MouseDown;
144 break;
145 case CPDF_AAction::kButtonUp:
146 eEventType = XFA_EVENT_MouseUp;
147 break;
148 case CPDF_AAction::kGetFocus:
149 eEventType = XFA_EVENT_Enter;
150 break;
151 case CPDF_AAction::kLoseFocus:
152 eEventType = XFA_EVENT_Exit;
153 break;
154 case CPDF_AAction::kPageOpen:
155 case CPDF_AAction::kPageClose:
156 case CPDF_AAction::kPageVisible:
157 case CPDF_AAction::kPageInvisible:
158 break;
159 case CPDF_AAction::kKeyStroke:
160 if (!bWillCommit)
161 eEventType = XFA_EVENT_Change;
162 break;
163 case CPDF_AAction::kValidate:
164 eEventType = XFA_EVENT_Validate;
165 break;
166 case CPDF_AAction::kOpenPage:
167 case CPDF_AAction::kClosePage:
168 case CPDF_AAction::kFormat:
169 case CPDF_AAction::kCalculate:
170 case CPDF_AAction::kCloseDocument:
171 case CPDF_AAction::kSaveDocument:
172 case CPDF_AAction::kDocumentSaved:
173 case CPDF_AAction::kPrintDocument:
174 case CPDF_AAction::kDocumentPrinted:
175 break;
176 case CPDF_AAction::kDocumentOpen:
177 case CPDF_AAction::kNumberOfActions:
178 NOTREACHED();
179 break;
180 }
181
182 return eEventType;
183 }
184
HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) const185 bool CPDFSDK_Widget::HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) const {
186 ObservedPtr<CXFA_FFWidget> pWidget(GetMixXFAWidget());
187 if (!pWidget)
188 return false;
189
190 CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler();
191 if (!pXFAWidgetHandler)
192 return false;
193
194 XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
195 if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
196 GetFieldType() == FormFieldType::kRadioButton) {
197 CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget();
198 if (hGroupWidget &&
199 hGroupWidget->HasEventUnderHandler(eEventType, pXFAWidgetHandler)) {
200 return true;
201 }
202 }
203
204 // Check |pWidget| again because JS may have destroyed it in the block above.
205 return pWidget &&
206 pWidget->HasEventUnderHandler(eEventType, pXFAWidgetHandler);
207 }
208
OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,CPDFSDK_FieldAction * data,CPDFSDK_PageView * pPageView)209 bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
210 CPDFSDK_FieldAction* data,
211 CPDFSDK_PageView* pPageView) {
212 auto* pContext = static_cast<CPDFXFA_Context*>(
213 m_pPageView->GetFormFillEnv()->GetDocExtension());
214 if (!pContext)
215 return false;
216
217 ObservedPtr<CXFA_FFWidget> pWidget(GetMixXFAWidget());
218 if (!pWidget)
219 return false;
220
221 XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
222 if (eEventType == XFA_EVENT_Unknown)
223 return false;
224
225 CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler();
226 if (!pXFAWidgetHandler)
227 return false;
228
229 CXFA_EventParam param;
230 param.m_eType = eEventType;
231 param.m_wsChange = data->sChange;
232 param.m_iCommitKey = 0;
233 param.m_bShift = data->bShift;
234 param.m_iSelStart = data->nSelStart;
235 param.m_iSelEnd = data->nSelEnd;
236 param.m_wsFullText = data->sValue;
237 param.m_bKeyDown = data->bKeyDown;
238 param.m_bModifier = data->bModifier;
239 param.m_wsPrevText = data->sValue;
240 if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
241 GetFieldType() == FormFieldType::kRadioButton) {
242 CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget();
243 if (hGroupWidget &&
244 !hGroupWidget->ProcessEventUnderHandler(¶m, pXFAWidgetHandler)) {
245 return false;
246 }
247 }
248
249 // Check |pWidget| again because JS may have destroyed it in the block above.
250 if (!pWidget)
251 return false;
252
253 bool ret = pWidget->ProcessEventUnderHandler(¶m, pXFAWidgetHandler);
254 if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
255 pDocView->UpdateDocView();
256
257 return ret;
258 }
259
Synchronize(bool bSynchronizeElse)260 void CPDFSDK_Widget::Synchronize(bool bSynchronizeElse) {
261 CXFA_FFWidget* hWidget = GetMixXFAWidget();
262 if (!hWidget)
263 return;
264
265 CXFA_Node* node = hWidget->GetNode();
266 if (!node->IsWidgetReady())
267 return;
268
269 CPDF_FormField* pFormField = GetFormField();
270 switch (GetFieldType()) {
271 case FormFieldType::kCheckBox:
272 case FormFieldType::kRadioButton: {
273 CPDF_FormControl* pFormCtrl = GetFormControl();
274 XFA_CHECKSTATE eCheckState =
275 pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off;
276 node->SetCheckState(eCheckState, true);
277 break;
278 }
279 case FormFieldType::kTextField:
280 node->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
281 break;
282 case FormFieldType::kComboBox:
283 case FormFieldType::kListBox: {
284 node->ClearAllSelections();
285
286 for (int i = 0; i < pFormField->CountSelectedItems(); ++i) {
287 int nIndex = pFormField->GetSelectedIndex(i);
288 if (nIndex > -1 && nIndex < node->CountChoiceListItems(false))
289 node->SetItemState(nIndex, true, false, false, true);
290 }
291 if (GetFieldType() == FormFieldType::kComboBox)
292 node->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
293 break;
294 }
295 default:
296 break;
297 }
298
299 if (bSynchronizeElse) {
300 auto* context = static_cast<CPDFXFA_Context*>(
301 m_pPageView->GetFormFillEnv()->GetDocExtension());
302 context->GetXFADocView()->ProcessValueChanged(node);
303 }
304 }
305 #endif // PDF_ENABLE_XFA
306
IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode)307 bool CPDFSDK_Widget::IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode) {
308 const CPDF_Dictionary* pAP =
309 GetAnnotDict()->GetDictFor(pdfium::annotation::kAP);
310 if (!pAP)
311 return false;
312
313 // Choose the right sub-ap
314 const char* ap_entry = "N";
315 if (mode == CPDF_Annot::Down)
316 ap_entry = "D";
317 else if (mode == CPDF_Annot::Rollover)
318 ap_entry = "R";
319 if (!pAP->KeyExist(ap_entry))
320 ap_entry = "N";
321
322 // Get the AP stream or subdirectory
323 const CPDF_Object* pSub = pAP->GetDirectObjectFor(ap_entry);
324 if (!pSub)
325 return false;
326
327 FormFieldType fieldType = GetFieldType();
328 switch (fieldType) {
329 case FormFieldType::kPushButton:
330 case FormFieldType::kComboBox:
331 case FormFieldType::kListBox:
332 case FormFieldType::kTextField:
333 case FormFieldType::kSignature:
334 return pSub->IsStream();
335 case FormFieldType::kCheckBox:
336 case FormFieldType::kRadioButton:
337 if (const CPDF_Dictionary* pSubDict = pSub->AsDictionary()) {
338 return !!pSubDict->GetStreamFor(GetAppState());
339 }
340 return false;
341 default:
342 return true;
343 }
344 }
345
GetFieldType() const346 FormFieldType CPDFSDK_Widget::GetFieldType() const {
347 CPDF_FormField* pField = GetFormField();
348 return pField ? pField->GetFieldType() : FormFieldType::kUnknown;
349 }
350
IsAppearanceValid()351 bool CPDFSDK_Widget::IsAppearanceValid() {
352 #ifdef PDF_ENABLE_XFA
353 CPDF_Document::Extension* pContext =
354 m_pPageView->GetFormFillEnv()->GetDocExtension();
355 if (pContext && pContext->ContainsExtensionFullForm())
356 return true;
357 #endif // PDF_ENABLE_XFA
358 return CPDFSDK_BAAnnot::IsAppearanceValid();
359 }
360
GetLayoutOrder() const361 int CPDFSDK_Widget::GetLayoutOrder() const {
362 return 2;
363 }
364
GetFieldFlags() const365 int CPDFSDK_Widget::GetFieldFlags() const {
366 return GetFormField()->GetFieldFlags();
367 }
368
IsSignatureWidget() const369 bool CPDFSDK_Widget::IsSignatureWidget() const {
370 return GetFieldType() == FormFieldType::kSignature;
371 }
372
GetFormField() const373 CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
374 CPDF_FormControl* pControl = GetFormControl();
375 return pControl ? pControl->GetField() : nullptr;
376 }
377
GetFormControl() const378 CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
379 CPDF_InteractiveForm* pPDFInteractiveForm =
380 m_pInteractiveForm->GetInteractiveForm();
381 return pPDFInteractiveForm->GetControlByDict(GetAnnotDict());
382 }
383
GetRotate() const384 int CPDFSDK_Widget::GetRotate() const {
385 CPDF_FormControl* pCtrl = GetFormControl();
386 return pCtrl->GetRotation() % 360;
387 }
388
389 #ifdef PDF_ENABLE_XFA
GetName() const390 WideString CPDFSDK_Widget::GetName() const {
391 return GetFormField()->GetFullName();
392 }
393 #endif // PDF_ENABLE_XFA
394
GetFillColor() const395 Optional<FX_COLORREF> CPDFSDK_Widget::GetFillColor() const {
396 CPDF_FormControl* pFormCtrl = GetFormControl();
397 int iColorType = 0;
398 FX_COLORREF color = ArgbToColorRef(pFormCtrl->GetBackgroundColor(iColorType));
399 if (iColorType == CFX_Color::kTransparent)
400 return {};
401 return color;
402 }
403
GetBorderColor() const404 Optional<FX_COLORREF> CPDFSDK_Widget::GetBorderColor() const {
405 CPDF_FormControl* pFormCtrl = GetFormControl();
406 int iColorType = 0;
407 FX_COLORREF color = ArgbToColorRef(pFormCtrl->GetBorderColor(iColorType));
408 if (iColorType == CFX_Color::kTransparent)
409 return {};
410 return color;
411 }
412
GetTextColor() const413 Optional<FX_COLORREF> CPDFSDK_Widget::GetTextColor() const {
414 CPDF_FormControl* pFormCtrl = GetFormControl();
415 CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
416 FX_ARGB argb;
417 Optional<CFX_Color::Type> iColorType;
418 std::tie(iColorType, argb) = da.GetColor();
419 if (!iColorType.has_value())
420 return {};
421
422 FX_COLORREF color = ArgbToColorRef(argb);
423 if (iColorType.value() == CFX_Color::kTransparent)
424 return {};
425 return color;
426 }
427
GetFontSize() const428 float CPDFSDK_Widget::GetFontSize() const {
429 CPDF_FormControl* pFormCtrl = GetFormControl();
430 CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance();
431 float fFontSize;
432 pDa.GetFont(&fFontSize);
433 return fFontSize;
434 }
435
GetSelectedIndex(int nIndex) const436 int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const {
437 #ifdef PDF_ENABLE_XFA
438 if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
439 CXFA_Node* node = hWidget->GetNode();
440 if (node->IsWidgetReady()) {
441 if (nIndex < node->CountSelectedItems())
442 return node->GetSelectedItem(nIndex);
443 }
444 }
445 #endif // PDF_ENABLE_XFA
446 CPDF_FormField* pFormField = GetFormField();
447 return pFormField->GetSelectedIndex(nIndex);
448 }
449
GetValue() const450 WideString CPDFSDK_Widget::GetValue() const {
451 #ifdef PDF_ENABLE_XFA
452 if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
453 CXFA_Node* node = hWidget->GetNode();
454 if (node->IsWidgetReady())
455 return node->GetValue(XFA_VALUEPICTURE_Display);
456 }
457 #endif // PDF_ENABLE_XFA
458 CPDF_FormField* pFormField = GetFormField();
459 return pFormField->GetValue();
460 }
461
GetDefaultValue() const462 WideString CPDFSDK_Widget::GetDefaultValue() const {
463 CPDF_FormField* pFormField = GetFormField();
464 return pFormField->GetDefaultValue();
465 }
466
GetOptionLabel(int nIndex) const467 WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
468 CPDF_FormField* pFormField = GetFormField();
469 return pFormField->GetOptionLabel(nIndex);
470 }
471
CountOptions() const472 int CPDFSDK_Widget::CountOptions() const {
473 CPDF_FormField* pFormField = GetFormField();
474 return pFormField->CountOptions();
475 }
476
IsOptionSelected(int nIndex) const477 bool CPDFSDK_Widget::IsOptionSelected(int nIndex) const {
478 #ifdef PDF_ENABLE_XFA
479 if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
480 CXFA_Node* node = hWidget->GetNode();
481 if (node->IsWidgetReady()) {
482 if (nIndex > -1 && nIndex < node->CountChoiceListItems(false))
483 return node->GetItemState(nIndex);
484
485 return false;
486 }
487 }
488 #endif // PDF_ENABLE_XFA
489 CPDF_FormField* pFormField = GetFormField();
490 return pFormField->IsItemSelected(nIndex);
491 }
492
GetTopVisibleIndex() const493 int CPDFSDK_Widget::GetTopVisibleIndex() const {
494 CPDF_FormField* pFormField = GetFormField();
495 return pFormField->GetTopVisibleIndex();
496 }
497
IsChecked() const498 bool CPDFSDK_Widget::IsChecked() const {
499 #ifdef PDF_ENABLE_XFA
500 if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
501 CXFA_Node* node = hWidget->GetNode();
502 if (node->IsWidgetReady())
503 return node->GetCheckState() == XFA_CHECKSTATE_On;
504 }
505 #endif // PDF_ENABLE_XFA
506 CPDF_FormControl* pFormCtrl = GetFormControl();
507 return pFormCtrl->IsChecked();
508 }
509
GetAlignment() const510 int CPDFSDK_Widget::GetAlignment() const {
511 CPDF_FormControl* pFormCtrl = GetFormControl();
512 return pFormCtrl->GetControlAlignment();
513 }
514
GetMaxLen() const515 int CPDFSDK_Widget::GetMaxLen() const {
516 CPDF_FormField* pFormField = GetFormField();
517 return pFormField->GetMaxLen();
518 }
519
SetCheck(bool bChecked,NotificationOption notify)520 void CPDFSDK_Widget::SetCheck(bool bChecked, NotificationOption notify) {
521 CPDF_FormControl* pFormCtrl = GetFormControl();
522 CPDF_FormField* pFormField = pFormCtrl->GetField();
523 pFormField->CheckControl(pFormField->GetControlIndex(pFormCtrl), bChecked,
524 notify);
525 #ifdef PDF_ENABLE_XFA
526 if (!IsWidgetAppearanceValid(CPDF_Annot::Normal))
527 ResetXFAAppearance(true);
528 if (notify == NotificationOption::kDoNotNotify)
529 Synchronize(true);
530 #endif // PDF_ENABLE_XFA
531 }
532
SetValue(const WideString & sValue,NotificationOption notify)533 void CPDFSDK_Widget::SetValue(const WideString& sValue,
534 NotificationOption notify) {
535 CPDF_FormField* pFormField = GetFormField();
536 pFormField->SetValue(sValue, notify);
537 #ifdef PDF_ENABLE_XFA
538 if (notify == NotificationOption::kDoNotNotify)
539 Synchronize(true);
540 #endif // PDF_ENABLE_XFA
541 }
542
SetOptionSelection(int index,bool bSelected,NotificationOption notify)543 void CPDFSDK_Widget::SetOptionSelection(int index,
544 bool bSelected,
545 NotificationOption notify) {
546 CPDF_FormField* pFormField = GetFormField();
547 pFormField->SetItemSelection(index, bSelected, notify);
548 #ifdef PDF_ENABLE_XFA
549 if (notify == NotificationOption::kDoNotNotify)
550 Synchronize(true);
551 #endif // PDF_ENABLE_XFA
552 }
553
ClearSelection(NotificationOption notify)554 void CPDFSDK_Widget::ClearSelection(NotificationOption notify) {
555 CPDF_FormField* pFormField = GetFormField();
556 pFormField->ClearSelection(notify);
557 #ifdef PDF_ENABLE_XFA
558 if (notify == NotificationOption::kDoNotNotify)
559 Synchronize(true);
560 #endif // PDF_ENABLE_XFA
561 }
562
SetTopVisibleIndex(int index)563 void CPDFSDK_Widget::SetTopVisibleIndex(int index) {}
564
SetAppModified()565 void CPDFSDK_Widget::SetAppModified() {
566 m_bAppModified = true;
567 }
568
ClearAppModified()569 void CPDFSDK_Widget::ClearAppModified() {
570 m_bAppModified = false;
571 }
572
IsAppModified() const573 bool CPDFSDK_Widget::IsAppModified() const {
574 return m_bAppModified;
575 }
576
577 #ifdef PDF_ENABLE_XFA
ResetXFAAppearance(bool bValueChanged)578 void CPDFSDK_Widget::ResetXFAAppearance(bool bValueChanged) {
579 switch (GetFieldType()) {
580 case FormFieldType::kTextField:
581 case FormFieldType::kComboBox: {
582 ResetAppearance(OnFormat(), true);
583 break;
584 }
585 default:
586 ResetAppearance(pdfium::nullopt, false);
587 break;
588 }
589 }
590 #endif // PDF_ENABLE_XFA
591
ResetAppearance(Optional<WideString> sValue,bool bValueChanged)592 void CPDFSDK_Widget::ResetAppearance(Optional<WideString> sValue,
593 bool bValueChanged) {
594 SetAppModified();
595
596 m_nAppearanceAge++;
597 if (bValueChanged)
598 m_nValueAge++;
599
600 CPDFSDK_AppStream appStream(this, GetAPDict());
601 switch (GetFieldType()) {
602 case FormFieldType::kPushButton:
603 appStream.SetAsPushButton();
604 break;
605 case FormFieldType::kCheckBox:
606 appStream.SetAsCheckBox();
607 break;
608 case FormFieldType::kRadioButton:
609 appStream.SetAsRadioButton();
610 break;
611 case FormFieldType::kComboBox:
612 appStream.SetAsComboBox(sValue);
613 break;
614 case FormFieldType::kListBox:
615 appStream.SetAsListBox();
616 break;
617 case FormFieldType::kTextField:
618 appStream.SetAsTextField(sValue);
619 break;
620 default:
621 break;
622 }
623
624 m_pAnnot->ClearCachedAP();
625 }
626
OnFormat()627 Optional<WideString> CPDFSDK_Widget::OnFormat() {
628 CPDF_FormField* pFormField = GetFormField();
629 ASSERT(pFormField);
630 return m_pInteractiveForm->OnFormat(pFormField);
631 }
632
ResetFieldAppearance()633 void CPDFSDK_Widget::ResetFieldAppearance() {
634 CPDF_FormField* pFormField = GetFormField();
635 ASSERT(pFormField);
636 m_pInteractiveForm->ResetFieldAppearance(pFormField, pdfium::nullopt);
637 }
638
DrawAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device,CPDF_Annot::AppearanceMode mode,const CPDF_RenderOptions * pOptions)639 void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice,
640 const CFX_Matrix& mtUser2Device,
641 CPDF_Annot::AppearanceMode mode,
642 const CPDF_RenderOptions* pOptions) {
643 FormFieldType fieldType = GetFieldType();
644
645 if ((fieldType == FormFieldType::kCheckBox ||
646 fieldType == FormFieldType::kRadioButton) &&
647 mode == CPDF_Annot::Normal &&
648 !IsWidgetAppearanceValid(CPDF_Annot::Normal)) {
649 CFX_GraphStateData gsd;
650 gsd.m_LineWidth = 0.0f;
651
652 CFX_PathData pathData;
653 pathData.AppendFloatRect(GetRect());
654 pDevice->DrawPath(&pathData, &mtUser2Device, &gsd, 0, 0xFFAAAAAA,
655 FXFILL_ALTERNATE);
656 } else {
657 CPDFSDK_BAAnnot::DrawAppearance(pDevice, mtUser2Device, mode, pOptions);
658 }
659 }
660
UpdateField()661 void CPDFSDK_Widget::UpdateField() {
662 CPDF_FormField* pFormField = GetFormField();
663 ASSERT(pFormField);
664 m_pInteractiveForm->UpdateField(pFormField);
665 }
666
DrawShadow(CFX_RenderDevice * pDevice,CPDFSDK_PageView * pPageView)667 void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice,
668 CPDFSDK_PageView* pPageView) {
669 FormFieldType fieldType = GetFieldType();
670 if (!m_pInteractiveForm->IsNeedHighLight(fieldType))
671 return;
672
673 CFX_Matrix page2device = pPageView->GetCurrentMatrix();
674 CFX_FloatRect rcDevice = GetRect();
675 CFX_PointF tmp =
676 page2device.Transform(CFX_PointF(rcDevice.left, rcDevice.bottom));
677 rcDevice.left = tmp.x;
678 rcDevice.bottom = tmp.y;
679
680 tmp = page2device.Transform(CFX_PointF(rcDevice.right, rcDevice.top));
681 rcDevice.right = tmp.x;
682 rcDevice.top = tmp.y;
683 rcDevice.Normalize();
684
685 pDevice->FillRect(
686 rcDevice.ToFxRect(),
687 AlphaAndColorRefToArgb(
688 static_cast<int>(m_pInteractiveForm->GetHighlightAlpha()),
689 m_pInteractiveForm->GetHighlightColor(fieldType)));
690 }
691
GetClientRect() const692 CFX_FloatRect CPDFSDK_Widget::GetClientRect() const {
693 CFX_FloatRect rcWindow = GetRotatedRect();
694 float fBorderWidth = GetBorderWidth();
695 switch (GetBorderStyle()) {
696 case BorderStyle::BEVELED:
697 case BorderStyle::INSET:
698 fBorderWidth *= 2.0f;
699 break;
700 default:
701 break;
702 }
703 return rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
704 }
705
GetRotatedRect() const706 CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const {
707 CFX_FloatRect rectAnnot = GetRect();
708 float fWidth = rectAnnot.Width();
709 float fHeight = rectAnnot.Height();
710
711 CPDF_FormControl* pControl = GetFormControl();
712 CFX_FloatRect rcPWLWindow;
713 switch (abs(pControl->GetRotation() % 360)) {
714 case 0:
715 case 180:
716 default:
717 rcPWLWindow = CFX_FloatRect(0, 0, fWidth, fHeight);
718 break;
719 case 90:
720 case 270:
721 rcPWLWindow = CFX_FloatRect(0, 0, fHeight, fWidth);
722 break;
723 }
724
725 return rcPWLWindow;
726 }
727
GetMatrix() const728 CFX_Matrix CPDFSDK_Widget::GetMatrix() const {
729 CFX_Matrix mt;
730 CPDF_FormControl* pControl = GetFormControl();
731 CFX_FloatRect rcAnnot = GetRect();
732 float fWidth = rcAnnot.Width();
733 float fHeight = rcAnnot.Height();
734
735 switch (abs(pControl->GetRotation() % 360)) {
736 default:
737 case 0:
738 break;
739 case 90:
740 mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0);
741 break;
742 case 180:
743 mt = CFX_Matrix(-1, 0, 0, -1, fWidth, fHeight);
744 break;
745 case 270:
746 mt = CFX_Matrix(0, -1, 1, 0, 0, fHeight);
747 break;
748 }
749
750 return mt;
751 }
752
GetTextPWLColor() const753 CFX_Color CPDFSDK_Widget::GetTextPWLColor() const {
754 CFX_Color crText = CFX_Color(CFX_Color::kGray, 0);
755
756 CPDF_FormControl* pFormCtrl = GetFormControl();
757 CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
758
759 float fc[4];
760 Optional<CFX_Color::Type> iColorType = da.GetColor(fc);
761 if (iColorType)
762 crText = CFX_Color(*iColorType, fc[0], fc[1], fc[2], fc[3]);
763
764 return crText;
765 }
766
GetBorderPWLColor() const767 CFX_Color CPDFSDK_Widget::GetBorderPWLColor() const {
768 CFX_Color crBorder;
769
770 CPDF_FormControl* pFormCtrl = GetFormControl();
771 int32_t iColorType;
772 float fc[4];
773 pFormCtrl->GetOriginalBorderColor(iColorType, fc);
774 if (iColorType > 0)
775 crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
776
777 return crBorder;
778 }
779
GetFillPWLColor() const780 CFX_Color CPDFSDK_Widget::GetFillPWLColor() const {
781 CFX_Color crFill;
782
783 CPDF_FormControl* pFormCtrl = GetFormControl();
784 int32_t iColorType;
785 float fc[4];
786 pFormCtrl->GetOriginalBackgroundColor(iColorType, fc);
787 if (iColorType > 0)
788 crFill = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
789
790 return crFill;
791 }
792
OnAAction(CPDF_AAction::AActionType type,CPDFSDK_FieldAction * data,CPDFSDK_PageView * pPageView)793 bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
794 CPDFSDK_FieldAction* data,
795 CPDFSDK_PageView* pPageView) {
796 CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv();
797
798 #ifdef PDF_ENABLE_XFA
799 auto* pContext =
800 static_cast<CPDFXFA_Context*>(pFormFillEnv->GetDocExtension());
801 if (pContext) {
802 CXFA_FFWidget* hWidget = GetMixXFAWidget();
803 if (hWidget) {
804 XFA_EVENTTYPE eEventType = GetXFAEventType(type, data->bWillCommit);
805 if (eEventType != XFA_EVENT_Unknown) {
806 if (CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) {
807 CXFA_EventParam param;
808 param.m_eType = eEventType;
809 param.m_wsChange = data->sChange;
810 param.m_iCommitKey = 0;
811 param.m_bShift = data->bShift;
812 param.m_iSelStart = data->nSelStart;
813 param.m_iSelEnd = data->nSelEnd;
814 param.m_wsFullText = data->sValue;
815 param.m_bKeyDown = data->bKeyDown;
816 param.m_bModifier = data->bModifier;
817 param.m_wsPrevText = data->sValue;
818 bool ret =
819 hWidget->ProcessEventUnderHandler(¶m, pXFAWidgetHandler);
820 if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
821 pDocView->UpdateDocView();
822 if (ret)
823 return true;
824 }
825 }
826 }
827 }
828 #endif // PDF_ENABLE_XFA
829
830 CPDF_Action action = GetAAction(type);
831 if (action.GetType() != CPDF_Action::Unknown) {
832 pFormFillEnv->GetActionHandler()->DoAction_Field(action, type, pFormFillEnv,
833 GetFormField(), data);
834 }
835 return false;
836 }
837
GetAAction(CPDF_AAction::AActionType eAAT)838 CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) {
839 switch (eAAT) {
840 case CPDF_AAction::kCursorEnter:
841 case CPDF_AAction::kCursorExit:
842 case CPDF_AAction::kButtonDown:
843 case CPDF_AAction::kButtonUp:
844 case CPDF_AAction::kGetFocus:
845 case CPDF_AAction::kLoseFocus:
846 case CPDF_AAction::kPageOpen:
847 case CPDF_AAction::kPageClose:
848 case CPDF_AAction::kPageVisible:
849 case CPDF_AAction::kPageInvisible:
850 return CPDFSDK_BAAnnot::GetAAction(eAAT);
851
852 case CPDF_AAction::kKeyStroke:
853 case CPDF_AAction::kFormat:
854 case CPDF_AAction::kValidate:
855 case CPDF_AAction::kCalculate: {
856 CPDF_FormField* pField = GetFormField();
857 if (pField->GetAdditionalAction().GetDict())
858 return pField->GetAdditionalAction().GetAction(eAAT);
859 return CPDFSDK_BAAnnot::GetAAction(eAAT);
860 }
861 default:
862 break;
863 }
864
865 return CPDF_Action(nullptr);
866 }
867
GetAlternateName() const868 WideString CPDFSDK_Widget::GetAlternateName() const {
869 CPDF_FormField* pFormField = GetFormField();
870 return pFormField->GetAlternateName();
871 }
872