xref: /aosp_15_r20/external/pdfium/fpdfsdk/fpdf_formfill.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2014 The PDFium Authors
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 "public/fpdf_formfill.h"
8 
9 #include <memory>
10 #include <utility>
11 
12 #include "constants/form_fields.h"
13 #include "core/fpdfapi/page/cpdf_annotcontext.h"
14 #include "core/fpdfapi/page/cpdf_occontext.h"
15 #include "core/fpdfapi/page/cpdf_page.h"
16 #include "core/fpdfapi/parser/cpdf_dictionary.h"
17 #include "core/fpdfapi/parser/cpdf_document.h"
18 #include "core/fpdfapi/parser/cpdf_stream.h"
19 #include "core/fpdfapi/render/cpdf_renderoptions.h"
20 #include "core/fpdfdoc/cpdf_formcontrol.h"
21 #include "core/fpdfdoc/cpdf_formfield.h"
22 #include "core/fpdfdoc/cpdf_interactiveform.h"
23 #include "core/fxge/cfx_defaultrenderdevice.h"
24 #include "core/fxge/dib/cfx_dibitmap.h"
25 #include "fpdfsdk/cpdfsdk_annot.h"
26 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
27 #include "fpdfsdk/cpdfsdk_helpers.h"
28 #include "fpdfsdk/cpdfsdk_interactiveform.h"
29 #include "fpdfsdk/cpdfsdk_pageview.h"
30 #include "public/fpdfview.h"
31 
32 #ifdef PDF_ENABLE_XFA
33 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
34 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
35 #endif  // PDF_ENABLE_XFA
36 
37 #if defined(_SKIA_SUPPORT_)
38 class SkCanvas;
39 #endif  // defined(_SKIA_SUPPORT_)
40 
41 #ifdef PDF_ENABLE_XFA
42 static_assert(static_cast<int>(AlertButton::kDefault) ==
43                   JSPLATFORM_ALERT_BUTTON_DEFAULT,
44               "Default alert button types must match");
45 static_assert(static_cast<int>(AlertButton::kOK) == JSPLATFORM_ALERT_BUTTON_OK,
46               "OK alert button types must match");
47 static_assert(static_cast<int>(AlertButton::kOKCancel) ==
48                   JSPLATFORM_ALERT_BUTTON_OKCANCEL,
49               "OKCancel alert button types must match");
50 static_assert(static_cast<int>(AlertButton::kYesNo) ==
51                   JSPLATFORM_ALERT_BUTTON_YESNO,
52               "YesNo alert button types must match");
53 static_assert(static_cast<int>(AlertButton::kYesNoCancel) ==
54                   JSPLATFORM_ALERT_BUTTON_YESNOCANCEL,
55               "YesNoCancel alert button types must match");
56 
57 static_assert(static_cast<int>(AlertIcon::kDefault) ==
58                   JSPLATFORM_ALERT_ICON_DEFAULT,
59               "Default alert icon types must match");
60 static_assert(static_cast<int>(AlertIcon::kError) ==
61                   JSPLATFORM_ALERT_ICON_ERROR,
62               "Error alert icon types must match");
63 static_assert(static_cast<int>(AlertIcon::kWarning) ==
64                   JSPLATFORM_ALERT_ICON_WARNING,
65               "Warning alert icon types must match");
66 static_assert(static_cast<int>(AlertIcon::kQuestion) ==
67                   JSPLATFORM_ALERT_ICON_QUESTION,
68               "Question alert icon types must match");
69 static_assert(static_cast<int>(AlertIcon::kStatus) ==
70                   JSPLATFORM_ALERT_ICON_STATUS,
71               "Status alert icon types must match");
72 static_assert(static_cast<int>(AlertIcon::kAsterisk) ==
73                   JSPLATFORM_ALERT_ICON_ASTERISK,
74               "Asterisk alert icon types must match");
75 
76 static_assert(static_cast<int>(AlertReturn::kOK) == JSPLATFORM_ALERT_RETURN_OK,
77               "OK alert return types must match");
78 static_assert(static_cast<int>(AlertReturn::kCancel) ==
79                   JSPLATFORM_ALERT_RETURN_CANCEL,
80               "Cancel alert return types must match");
81 static_assert(static_cast<int>(AlertReturn::kNo) == JSPLATFORM_ALERT_RETURN_NO,
82               "No alert return types must match");
83 static_assert(static_cast<int>(AlertReturn::kYes) ==
84                   JSPLATFORM_ALERT_RETURN_YES,
85               "Yes alert return types must match");
86 
87 static_assert(static_cast<int>(FormType::kNone) == FORMTYPE_NONE,
88               "None form types must match");
89 static_assert(static_cast<int>(FormType::kAcroForm) == FORMTYPE_ACRO_FORM,
90               "AcroForm form types must match");
91 static_assert(static_cast<int>(FormType::kXFAFull) == FORMTYPE_XFA_FULL,
92               "XFA full form types must match");
93 static_assert(static_cast<int>(FormType::kXFAForeground) ==
94                   FORMTYPE_XFA_FOREGROUND,
95               "XFA foreground form types must match");
96 #endif  // PDF_ENABLE_XFA
97 
98 static_assert(static_cast<int>(FormFieldType::kUnknown) ==
99                   FPDF_FORMFIELD_UNKNOWN,
100               "Unknown form field types must match");
101 static_assert(static_cast<int>(FormFieldType::kPushButton) ==
102                   FPDF_FORMFIELD_PUSHBUTTON,
103               "PushButton form field types must match");
104 static_assert(static_cast<int>(FormFieldType::kCheckBox) ==
105                   FPDF_FORMFIELD_CHECKBOX,
106               "CheckBox form field types must match");
107 static_assert(static_cast<int>(FormFieldType::kRadioButton) ==
108                   FPDF_FORMFIELD_RADIOBUTTON,
109               "RadioButton form field types must match");
110 static_assert(static_cast<int>(FormFieldType::kComboBox) ==
111                   FPDF_FORMFIELD_COMBOBOX,
112               "ComboBox form field types must match");
113 static_assert(static_cast<int>(FormFieldType::kListBox) ==
114                   FPDF_FORMFIELD_LISTBOX,
115               "ListBox form field types must match");
116 static_assert(static_cast<int>(FormFieldType::kTextField) ==
117                   FPDF_FORMFIELD_TEXTFIELD,
118               "TextField form field types must match");
119 static_assert(static_cast<int>(FormFieldType::kSignature) ==
120                   FPDF_FORMFIELD_SIGNATURE,
121               "Signature form field types must match");
122 #ifdef PDF_ENABLE_XFA
123 static_assert(static_cast<int>(FormFieldType::kXFA) == FPDF_FORMFIELD_XFA,
124               "XFA form field types must match");
125 static_assert(static_cast<int>(FormFieldType::kXFA_CheckBox) ==
126                   FPDF_FORMFIELD_XFA_CHECKBOX,
127               "XFA CheckBox form field types must match");
128 static_assert(static_cast<int>(FormFieldType::kXFA_ComboBox) ==
129                   FPDF_FORMFIELD_XFA_COMBOBOX,
130               "XFA ComboBox form field types must match");
131 static_assert(static_cast<int>(FormFieldType::kXFA_ImageField) ==
132                   FPDF_FORMFIELD_XFA_IMAGEFIELD,
133               "XFA ImageField form field types must match");
134 static_assert(static_cast<int>(FormFieldType::kXFA_ListBox) ==
135                   FPDF_FORMFIELD_XFA_LISTBOX,
136               "XFA ListBox form field types must match");
137 static_assert(static_cast<int>(FormFieldType::kXFA_PushButton) ==
138                   FPDF_FORMFIELD_XFA_PUSHBUTTON,
139               "XFA PushButton form field types must match");
140 static_assert(static_cast<int>(FormFieldType::kXFA_Signature) ==
141                   FPDF_FORMFIELD_XFA_SIGNATURE,
142               "XFA Signature form field types must match");
143 static_assert(static_cast<int>(FormFieldType::kXFA_TextField) ==
144                   FPDF_FORMFIELD_XFA_TEXTFIELD,
145               "XFA TextField form field types must match");
146 #endif  // PDF_ENABLE_XFA
147 static_assert(kFormFieldTypeCount == FPDF_FORMFIELD_COUNT,
148               "Number of form field types must match");
149 
150 static_assert(static_cast<int>(CPDF_AAction::kCloseDocument) ==
151                   FPDFDOC_AACTION_WC,
152               "CloseDocument action must match");
153 static_assert(static_cast<int>(CPDF_AAction::kSaveDocument) ==
154                   FPDFDOC_AACTION_WS,
155               "SaveDocument action must match");
156 static_assert(static_cast<int>(CPDF_AAction::kDocumentSaved) ==
157                   FPDFDOC_AACTION_DS,
158               "DocumentSaved action must match");
159 static_assert(static_cast<int>(CPDF_AAction::kPrintDocument) ==
160                   FPDFDOC_AACTION_WP,
161               "PrintDocument action must match");
162 static_assert(static_cast<int>(CPDF_AAction::kDocumentPrinted) ==
163                   FPDFDOC_AACTION_DP,
164               "DocumentPrinted action must match");
165 
166 namespace {
167 
FormHandleToPageView(FPDF_FORMHANDLE hHandle,FPDF_PAGE fpdf_page)168 CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle,
169                                        FPDF_PAGE fpdf_page) {
170   IPDF_Page* pPage = IPDFPageFromFPDFPage(fpdf_page);
171   if (!pPage)
172     return nullptr;
173 
174   CPDFSDK_FormFillEnvironment* pFormFillEnv =
175       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
176   return pFormFillEnv ? pFormFillEnv->GetOrCreatePageView(pPage) : nullptr;
177 }
178 
179 // Returns true if formfill version is correctly set. See |version| in
180 // FPDF_FORMFILLINFO for details regarding correct version.
CheckFormfillVersion(FPDF_FORMFILLINFO * formInfo)181 bool CheckFormfillVersion(FPDF_FORMFILLINFO* formInfo) {
182   if (!formInfo || formInfo->version < 1 || formInfo->version > 2)
183     return false;
184 
185 #ifdef PDF_ENABLE_XFA
186   if (formInfo->version != 2)
187     return false;
188 #endif  // PDF_ENABLE_XFA
189 
190   return true;
191 }
192 
193 }  // namespace
194 
195 FPDF_EXPORT int FPDF_CALLCONV
FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,double page_x,double page_y)196 FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
197                              FPDF_PAGE page,
198                              double page_x,
199                              double page_y) {
200   const CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
201   if (pPage) {
202     CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
203     if (!pForm)
204       return -1;
205 
206     const CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
207     const CPDF_FormControl* pFormCtrl = pPDFForm->GetControlAtPoint(
208         pPage,
209         CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
210         nullptr);
211     if (!pFormCtrl)
212       return -1;
213     const CPDF_FormField* pFormField = pFormCtrl->GetField();
214     return pFormField ? static_cast<int>(pFormField->GetFieldType()) : -1;
215   }
216 
217 #ifdef PDF_ENABLE_XFA
218   const CPDFXFA_Page* pXFAPage = ToXFAPage(IPDFPageFromFPDFPage(page));
219   if (pXFAPage) {
220     return pXFAPage->HasFormFieldAtPoint(
221         CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)));
222   }
223 #endif  // PDF_ENABLE_XFA
224 
225   return -1;
226 }
227 
228 FPDF_EXPORT int FPDF_CALLCONV
FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,double page_x,double page_y)229 FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,
230                                 FPDF_PAGE page,
231                                 double page_x,
232                                 double page_y) {
233   CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
234   if (!pForm)
235     return -1;
236 
237   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
238   if (!pPage)
239     return -1;
240 
241   CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
242   int z_order = -1;
243   pPDFForm->GetControlAtPoint(
244       pPage, CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
245       &z_order);
246   return z_order;
247 }
248 
249 FPDF_EXPORT FPDF_FORMHANDLE FPDF_CALLCONV
FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document,FPDF_FORMFILLINFO * formInfo)250 FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document,
251                                 FPDF_FORMFILLINFO* formInfo) {
252   if (!CheckFormfillVersion(formInfo))
253     return nullptr;
254 
255   auto* pDocument = CPDFDocumentFromFPDFDocument(document);
256   if (!pDocument)
257     return nullptr;
258 
259 #ifdef PDF_ENABLE_XFA
260   CPDFXFA_Context* pContext = nullptr;
261   if (!formInfo->xfa_disabled) {
262     if (!pDocument->GetExtension()) {
263       pDocument->SetExtension(std::make_unique<CPDFXFA_Context>(pDocument));
264     }
265 
266     // If the CPDFXFA_Context has a FormFillEnvironment already then we've done
267     // this and can just return the old Env. Otherwise, we'll end up setting a
268     // new environment into the XFADocument and, that could get weird.
269     pContext = static_cast<CPDFXFA_Context*>(pDocument->GetExtension());
270     if (pContext->GetFormFillEnv()) {
271       return FPDFFormHandleFromCPDFSDKFormFillEnvironment(
272           pContext->GetFormFillEnv());
273     }
274   }
275 #endif  // PDF_ENABLE_XFA
276 
277   auto pFormFillEnv =
278       std::make_unique<CPDFSDK_FormFillEnvironment>(pDocument, formInfo);
279 
280 #ifdef PDF_ENABLE_XFA
281   if (pContext)
282     pContext->SetFormFillEnv(pFormFillEnv.get());
283 #endif  // PDF_ENABLE_XFA
284 
285   ReportUnsupportedXFA(pDocument);
286 
287   return FPDFFormHandleFromCPDFSDKFormFillEnvironment(
288       pFormFillEnv.release());  // Caller takes ownership.
289 }
290 
291 FPDF_EXPORT void FPDF_CALLCONV
FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle)292 FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) {
293   if (!hHandle)
294     return;
295 
296   // Take back ownership of the form fill environment. This is the inverse of
297   // FPDFDOC_InitFormFillEnvironment() above.
298   std::unique_ptr<CPDFSDK_FormFillEnvironment> pFormFillEnv(
299       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle));
300 
301 #ifdef PDF_ENABLE_XFA
302   // Reset the focused annotations and remove the SDK document from the
303   // XFA document.
304   pFormFillEnv->ClearAllFocusedAnnots();
305   // If the document was closed first, it's possible the XFA document
306   // is now a nullptr.
307   auto* pContext =
308       static_cast<CPDFXFA_Context*>(pFormFillEnv->GetDocExtension());
309   if (pContext)
310     pContext->SetFormFillEnv(nullptr);
311 #endif  // PDF_ENABLE_XFA
312 }
313 
FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)314 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,
315                                                      FPDF_PAGE page,
316                                                      int modifier,
317                                                      double page_x,
318                                                      double page_y) {
319   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
320   return pPageView &&
321          pPageView->OnMouseMove(
322              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier),
323              CFX_PointF(page_x, page_y));
324 }
325 
326 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FORM_OnMouseWheel(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,const FS_POINTF * page_coord,int delta_x,int delta_y)327 FORM_OnMouseWheel(FPDF_FORMHANDLE hHandle,
328                   FPDF_PAGE page,
329                   int modifier,
330                   const FS_POINTF* page_coord,
331                   int delta_x,
332                   int delta_y) {
333   if (!page_coord)
334     return false;
335 
336   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
337   return pPageView &&
338          pPageView->OnMouseWheel(
339              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier),
340              CFXPointFFromFSPointF(*page_coord), CFX_Vector(delta_x, delta_y));
341 }
342 
FORM_OnFocus(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)343 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnFocus(FPDF_FORMHANDLE hHandle,
344                                                  FPDF_PAGE page,
345                                                  int modifier,
346                                                  double page_x,
347                                                  double page_y) {
348   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
349   return pPageView &&
350          pPageView->OnFocus(
351              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier),
352              CFX_PointF(page_x, page_y));
353 }
354 
FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)355 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,
356                                                        FPDF_PAGE page,
357                                                        int modifier,
358                                                        double page_x,
359                                                        double page_y) {
360 #ifdef PDF_ENABLE_CLICK_LOGGING
361   fprintf(stderr, "mousedown,left,%d,%d\n", static_cast<int>(round(page_x)),
362           static_cast<int>(round(page_y)));
363 #endif  // PDF_ENABLE_CLICK_LOGGING
364   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
365   return pPageView &&
366          pPageView->OnLButtonDown(
367              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier),
368              CFX_PointF(page_x, page_y));
369 }
370 
FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)371 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,
372                                                      FPDF_PAGE page,
373                                                      int modifier,
374                                                      double page_x,
375                                                      double page_y) {
376 #ifdef PDF_ENABLE_CLICK_LOGGING
377   fprintf(stderr, "mouseup,left,%d,%d\n", static_cast<int>(round(page_x)),
378           static_cast<int>(round(page_y)));
379 #endif  // PDF_ENABLE_CLICK_LOGGING
380   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
381   return pPageView &&
382          pPageView->OnLButtonUp(
383              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier),
384              CFX_PointF(page_x, page_y));
385 }
386 
387 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FORM_OnLButtonDoubleClick(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)388 FORM_OnLButtonDoubleClick(FPDF_FORMHANDLE hHandle,
389                           FPDF_PAGE page,
390                           int modifier,
391                           double page_x,
392                           double page_y) {
393 #ifdef PDF_ENABLE_CLICK_LOGGING
394   fprintf(stderr, "mousedown,doubleleft,%d,%d\n",
395           static_cast<int>(round(page_x)), static_cast<int>(round(page_y)));
396 #endif  // PDF_ENABLE_CLICK_LOGGING
397   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
398   return pPageView &&
399          pPageView->OnLButtonDblClk(
400              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier),
401              CFX_PointF(page_x, page_y));
402 }
403 
FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)404 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,
405                                                        FPDF_PAGE page,
406                                                        int modifier,
407                                                        double page_x,
408                                                        double page_y) {
409 #ifdef PDF_ENABLE_CLICK_LOGGING
410   fprintf(stderr, "mousedown,right,%d,%d\n", static_cast<int>(round(page_x)),
411           static_cast<int>(round(page_y)));
412 #endif  // PDF_ENABLE_CLICK_LOGGING
413   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
414   return pPageView &&
415          pPageView->OnRButtonDown(
416              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier),
417              CFX_PointF(page_x, page_y));
418 }
419 
FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)420 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,
421                                                      FPDF_PAGE page,
422                                                      int modifier,
423                                                      double page_x,
424                                                      double page_y) {
425 #ifdef PDF_ENABLE_CLICK_LOGGING
426   fprintf(stderr, "mouseup,right,%d,%d\n", static_cast<int>(round(page_x)),
427           static_cast<int>(round(page_y)));
428 #endif  // PDF_ENABLE_CLICK_LOGGING
429   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
430   return pPageView &&
431          pPageView->OnRButtonUp(
432              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier),
433              CFX_PointF(page_x, page_y));
434 }
435 
FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nKeyCode,int modifier)436 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,
437                                                    FPDF_PAGE page,
438                                                    int nKeyCode,
439                                                    int modifier) {
440   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
441   return pPageView &&
442          pPageView->OnKeyDown(
443              static_cast<FWL_VKEYCODE>(nKeyCode),
444              Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier));
445 }
446 
FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nKeyCode,int modifier)447 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,
448                                                  FPDF_PAGE page,
449                                                  int nKeyCode,
450                                                  int modifier) {
451   return false;
452 }
453 
FORM_OnChar(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nChar,int modifier)454 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnChar(FPDF_FORMHANDLE hHandle,
455                                                 FPDF_PAGE page,
456                                                 int nChar,
457                                                 int modifier) {
458   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
459   return pPageView &&
460          pPageView->OnChar(
461              nChar, Mask<FWL_EVENTFLAG>::FromUnderlyingUnchecked(modifier));
462 }
463 
464 FPDF_EXPORT unsigned long FPDF_CALLCONV
FORM_GetFocusedText(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,void * buffer,unsigned long buflen)465 FORM_GetFocusedText(FPDF_FORMHANDLE hHandle,
466                     FPDF_PAGE page,
467                     void* buffer,
468                     unsigned long buflen) {
469   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
470   if (!pPageView)
471     return 0;
472 
473   return Utf16EncodeMaybeCopyAndReturnLength(pPageView->GetFocusedFormText(),
474                                              buffer, buflen);
475 }
476 
477 FPDF_EXPORT unsigned long FPDF_CALLCONV
FORM_GetSelectedText(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,void * buffer,unsigned long buflen)478 FORM_GetSelectedText(FPDF_FORMHANDLE hHandle,
479                      FPDF_PAGE page,
480                      void* buffer,
481                      unsigned long buflen) {
482   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
483   if (!pPageView)
484     return 0;
485 
486   return Utf16EncodeMaybeCopyAndReturnLength(pPageView->GetSelectedText(),
487                                              buffer, buflen);
488 }
489 
490 FPDF_EXPORT void FPDF_CALLCONV
FORM_ReplaceAndKeepSelection(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,FPDF_WIDESTRING wsText)491 FORM_ReplaceAndKeepSelection(FPDF_FORMHANDLE hHandle,
492                              FPDF_PAGE page,
493                              FPDF_WIDESTRING wsText) {
494   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
495   if (!pPageView)
496     return;
497 
498   pPageView->ReplaceAndKeepSelection(WideStringFromFPDFWideString(wsText));
499 }
500 
FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,FPDF_WIDESTRING wsText)501 FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle,
502                                                      FPDF_PAGE page,
503                                                      FPDF_WIDESTRING wsText) {
504   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
505   if (!pPageView)
506     return;
507 
508   pPageView->ReplaceSelection(WideStringFromFPDFWideString(wsText));
509 }
510 
FORM_SelectAllText(FPDF_FORMHANDLE hHandle,FPDF_PAGE page)511 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_SelectAllText(FPDF_FORMHANDLE hHandle,
512                                                        FPDF_PAGE page) {
513   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
514   return pPageView && pPageView->SelectAllText();
515 }
516 
FORM_CanUndo(FPDF_FORMHANDLE hHandle,FPDF_PAGE page)517 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_CanUndo(FPDF_FORMHANDLE hHandle,
518                                                  FPDF_PAGE page) {
519   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
520   if (!pPageView)
521     return false;
522   return pPageView->CanUndo();
523 }
524 
FORM_CanRedo(FPDF_FORMHANDLE hHandle,FPDF_PAGE page)525 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_CanRedo(FPDF_FORMHANDLE hHandle,
526                                                  FPDF_PAGE page) {
527   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
528   if (!pPageView)
529     return false;
530   return pPageView->CanRedo();
531 }
532 
FORM_Undo(FPDF_FORMHANDLE hHandle,FPDF_PAGE page)533 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_Undo(FPDF_FORMHANDLE hHandle,
534                                               FPDF_PAGE page) {
535   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
536   if (!pPageView)
537     return false;
538   return pPageView->Undo();
539 }
540 
FORM_Redo(FPDF_FORMHANDLE hHandle,FPDF_PAGE page)541 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_Redo(FPDF_FORMHANDLE hHandle,
542                                               FPDF_PAGE page) {
543   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
544   if (!pPageView)
545     return false;
546   return pPageView->Redo();
547 }
548 
549 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle)550 FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) {
551   CPDFSDK_FormFillEnvironment* pFormFillEnv =
552       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
553   if (!pFormFillEnv)
554     return false;
555   return pFormFillEnv->KillFocusAnnot({});
556 }
557 
558 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FORM_GetFocusedAnnot(FPDF_FORMHANDLE handle,int * page_index,FPDF_ANNOTATION * annot)559 FORM_GetFocusedAnnot(FPDF_FORMHANDLE handle,
560                      int* page_index,
561                      FPDF_ANNOTATION* annot) {
562   if (!page_index || !annot)
563     return false;
564 
565   CPDFSDK_FormFillEnvironment* form_fill_env =
566       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(handle);
567   if (!form_fill_env)
568     return false;
569 
570   // Set |page_index| and |annot| to default values. This is returned when there
571   // is no focused annotation.
572   *page_index = -1;
573   *annot = nullptr;
574 
575   CPDFSDK_Annot* cpdfsdk_annot = form_fill_env->GetFocusAnnot();
576   if (!cpdfsdk_annot)
577     return true;
578 
579   // TODO(crbug.com/pdfium/1482): Handle XFA case.
580   if (cpdfsdk_annot->AsXFAWidget())
581     return true;
582 
583   CPDFSDK_PageView* page_view = cpdfsdk_annot->GetPageView();
584   if (!page_view->IsValid())
585     return true;
586 
587   IPDF_Page* page = cpdfsdk_annot->GetPage();
588   if (!page)
589     return true;
590 
591   RetainPtr<CPDF_Dictionary> annot_dict =
592       cpdfsdk_annot->GetPDFAnnot()->GetMutableAnnotDict();
593   auto annot_context =
594       std::make_unique<CPDF_AnnotContext>(std::move(annot_dict), page);
595 
596   *page_index = page_view->GetPageIndex();
597   // Caller takes ownership.
598   *annot = FPDFAnnotationFromCPDFAnnotContext(annot_context.release());
599   return true;
600 }
601 
602 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FORM_SetFocusedAnnot(FPDF_FORMHANDLE handle,FPDF_ANNOTATION annot)603 FORM_SetFocusedAnnot(FPDF_FORMHANDLE handle, FPDF_ANNOTATION annot) {
604   CPDFSDK_FormFillEnvironment* form_fill_env =
605       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(handle);
606   if (!form_fill_env)
607     return false;
608 
609   CPDF_AnnotContext* annot_context = CPDFAnnotContextFromFPDFAnnotation(annot);
610   if (!annot_context)
611     return false;
612 
613   CPDFSDK_PageView* page_view =
614       form_fill_env->GetOrCreatePageView(annot_context->GetPage());
615   if (!page_view->IsValid())
616     return false;
617 
618   RetainPtr<CPDF_Dictionary> annot_dict = annot_context->GetMutableAnnotDict();
619   ObservedPtr<CPDFSDK_Annot> cpdfsdk_annot(
620       page_view->GetAnnotByDict(annot_dict.Get()));
621   if (!cpdfsdk_annot)
622     return false;
623 
624   return form_fill_env->SetFocusAnnot(cpdfsdk_annot);
625 }
626 
FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,FPDF_BITMAP bitmap,FPDF_PAGE page,int start_x,int start_y,int size_x,int size_y,int rotate,int flags)627 FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
628                                             FPDF_BITMAP bitmap,
629                                             FPDF_PAGE page,
630                                             int start_x,
631                                             int start_y,
632                                             int size_x,
633                                             int size_y,
634                                             int rotate,
635                                             int flags) {
636   if (!hHandle)
637   return;
638 
639   IPDF_Page* pPage = IPDFPageFromFPDFPage(page);
640   if (!pPage)
641   return;
642 
643   CPDF_Document* pPDFDoc = pPage->GetDocument();
644   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
645 
646   const FX_RECT rect(start_x, start_y, start_x + size_x, start_y + size_y);
647   CFX_Matrix matrix = pPage->GetDisplayMatrix(rect, rotate);
648 
649   auto pDevice = std::make_unique<CFX_DefaultRenderDevice>();
650   #if defined(_SKIA_SUPPORT_)
651   if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer() && canvas) {
652       pDevice->AttachCanvas(reinterpret_cast<SkCanvas*>(canvas));
653   }
654   #endif
655 
656   RetainPtr<CFX_DIBitmap> holder(CFXDIBitmapFromFPDFBitmap(bitmap));
657   pDevice->AttachWithRgbByteOrder(holder, !!(flags & FPDF_REVERSE_BYTE_ORDER));
658   {
659   CFX_RenderDevice::StateRestorer restorer(pDevice.get());
660   pDevice->SetClip_Rect(rect);
661 
662   CPDF_RenderOptions options;
663   options.GetOptions().bClearType = !!(flags & FPDF_LCD_TEXT);
664 
665   // Grayscale output
666   if (flags & FPDF_GRAYSCALE)
667   options.SetColorMode(CPDF_RenderOptions::kGray);
668 
669   options.SetDrawAnnots(flags & FPDF_ANNOT);
670   options.SetOCContext(
671           pdfium::MakeRetain<CPDF_OCContext>(pPDFDoc, CPDF_OCContext::kView));
672 
673   if (pPageView)
674       pPageView->PageView_OnDraw(pDevice.get(), matrix, &options, rect);
675   }
676 }
677 
FPDF_FFLDrawWithMatrix(FPDF_FORMHANDLE hHandle,FPDF_BITMAP bitmap,FPDF_PAGE page,const FS_MATRIX * matrix,const FS_RECTF * clipping,int flags)678 FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDrawWithMatrix(FPDF_FORMHANDLE hHandle,
679                                             FPDF_BITMAP bitmap,
680                                             FPDF_PAGE page,
681                                             const FS_MATRIX* matrix,
682                                             const FS_RECTF* clipping,
683                                             int flags) {
684   if (!hHandle)
685   return;
686 
687   IPDF_Page* pPage = IPDFPageFromFPDFPage(page);
688   if (!pPage)
689   return;
690 
691   CPDF_Document* pPDFDoc = pPage->GetDocument();
692   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
693 
694   CFX_FloatRect clipping_rect;
695   if (clipping)
696   clipping_rect = CFXFloatRectFromFSRectF(*clipping);
697   FX_RECT clip_rect = clipping_rect.ToFxRect();
698 
699   const FX_RECT rect(0, 0, pPage->GetPageWidth(), pPage->GetPageHeight());
700   CFX_Matrix transform_matrix = pPage->GetDisplayMatrix(rect, 0);
701   if (matrix)
702       transform_matrix *= CFXMatrixFromFSMatrix(*matrix);
703 
704   auto pDevice = std::make_unique<CFX_DefaultRenderDevice>();
705   #if defined(_SKIA_SUPPORT_)
706   if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer() && canvas) {
707       pDevice->AttachCanvas(reinterpret_cast<SkCanvas*>(canvas));
708   }
709   #endif
710 
711   RetainPtr<CFX_DIBitmap> holder(CFXDIBitmapFromFPDFBitmap(bitmap));
712   pDevice->AttachWithRgbByteOrder(holder, !!(flags & FPDF_REVERSE_BYTE_ORDER));
713   {
714   CFX_RenderDevice::StateRestorer restorer(pDevice.get());
715   pDevice->SetClip_Rect(clip_rect);
716 
717   CPDF_RenderOptions options;
718   options.GetOptions().bClearType = !!(flags & FPDF_LCD_TEXT);
719 
720   // Grayscale output
721   if (flags & FPDF_GRAYSCALE)
722   options.SetColorMode(CPDF_RenderOptions::kGray);
723 
724   options.SetDrawAnnots(flags & FPDF_ANNOT);
725   options.SetOCContext(
726           pdfium::MakeRetain<CPDF_OCContext>(pPDFDoc, CPDF_OCContext::kView));
727 
728   if (pPageView)
729       pPageView->PageView_OnDraw(pDevice.get(), transform_matrix, &options, clip_rect);
730   }
731 }
732 
733 #if defined(_SKIA_SUPPORT_)
FPDF_FFLDrawSkia(FPDF_FORMHANDLE hHandle,FPDF_SKIA_CANVAS canvas,FPDF_PAGE page,int start_x,int start_y,int size_x,int size_y,int rotate,int flags)734 FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDrawSkia(FPDF_FORMHANDLE hHandle,
735                                                 FPDF_SKIA_CANVAS canvas,
736                                                 FPDF_PAGE page,
737                                                 int start_x,
738                                                 int start_y,
739                                                 int size_x,
740                                                 int size_y,
741                                                 int rotate,
742                                                 int flags) {
743   FFLCommon(hHandle, nullptr, canvas, page, start_x, start_y, size_x, size_y,
744             rotate, flags);
745 }
746 #endif
747 
748 FPDF_EXPORT void FPDF_CALLCONV
FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,int fieldType,unsigned long color)749 FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,
750                                 int fieldType,
751                                 unsigned long color) {
752   CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
753   if (!pForm)
754     return;
755 
756   absl::optional<FormFieldType> cast_input =
757       CPDF_FormField::IntToFormFieldType(fieldType);
758   if (!cast_input.has_value())
759     return;
760 
761   if (cast_input.value() == FormFieldType::kUnknown) {
762     pForm->SetAllHighlightColors(static_cast<FX_COLORREF>(color));
763   } else {
764     pForm->SetHighlightColor(static_cast<FX_COLORREF>(color),
765                              cast_input.value());
766   }
767 }
768 
769 FPDF_EXPORT void FPDF_CALLCONV
FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle,unsigned char alpha)770 FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha) {
771   if (CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle))
772     pForm->SetHighlightAlpha(alpha);
773 }
774 
775 FPDF_EXPORT void FPDF_CALLCONV
FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle)776 FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
777   if (CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle))
778     pForm->RemoveAllHighLights();
779 }
780 
FORM_OnAfterLoadPage(FPDF_PAGE page,FPDF_FORMHANDLE hHandle)781 FPDF_EXPORT void FPDF_CALLCONV FORM_OnAfterLoadPage(FPDF_PAGE page,
782                                                     FPDF_FORMHANDLE hHandle) {
783   if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page))
784     pPageView->SetValid(true);
785 }
786 
FORM_OnBeforeClosePage(FPDF_PAGE page,FPDF_FORMHANDLE hHandle)787 FPDF_EXPORT void FPDF_CALLCONV FORM_OnBeforeClosePage(FPDF_PAGE page,
788                                                       FPDF_FORMHANDLE hHandle) {
789   CPDFSDK_FormFillEnvironment* pFormFillEnv =
790       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
791   if (!pFormFillEnv)
792     return;
793 
794   IPDF_Page* pPage = IPDFPageFromFPDFPage(page);
795   if (!pPage)
796     return;
797 
798   CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage);
799   if (pPageView) {
800     pPageView->SetValid(false);
801     // RemovePageView() takes care of the delete for us.
802     pFormFillEnv->RemovePageView(pPage);
803   }
804 }
805 
806 FPDF_EXPORT void FPDF_CALLCONV
FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle)807 FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) {
808   CPDFSDK_FormFillEnvironment* pFormFillEnv =
809       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
810   if (pFormFillEnv && pFormFillEnv->IsJSPlatformPresent())
811     pFormFillEnv->ProcJavascriptAction();
812 }
813 
814 FPDF_EXPORT void FPDF_CALLCONV
FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle)815 FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) {
816   CPDFSDK_FormFillEnvironment* pFormFillEnv =
817       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
818   if (pFormFillEnv)
819     pFormFillEnv->ProcOpenAction();
820 }
821 
FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,int aaType)822 FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,
823                                                       int aaType) {
824   CPDFSDK_FormFillEnvironment* pFormFillEnv =
825       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
826   if (!pFormFillEnv)
827     return;
828 
829   CPDF_Document* pDoc = pFormFillEnv->GetPDFDocument();
830   const CPDF_Dictionary* pDict = pDoc->GetRoot();
831   if (!pDict)
832     return;
833 
834   CPDF_AAction aa(pDict->GetDictFor(pdfium::form_fields::kAA));
835   auto type = static_cast<CPDF_AAction::AActionType>(aaType);
836   if (aa.ActionExist(type))
837     pFormFillEnv->DoActionDocument(aa.GetAction(type), type);
838 }
839 
FORM_DoPageAAction(FPDF_PAGE page,FPDF_FORMHANDLE hHandle,int aaType)840 FPDF_EXPORT void FPDF_CALLCONV FORM_DoPageAAction(FPDF_PAGE page,
841                                                   FPDF_FORMHANDLE hHandle,
842                                                   int aaType) {
843   CPDFSDK_FormFillEnvironment* pFormFillEnv =
844       CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
845   if (!pFormFillEnv)
846     return;
847 
848   IPDF_Page* pPage = IPDFPageFromFPDFPage(page);
849   CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page);
850   if (!pPDFPage)
851     return;
852 
853   if (!pFormFillEnv->GetPageView(pPage))
854     return;
855 
856   CPDF_AAction aa(pPDFPage->GetDict()->GetDictFor(pdfium::form_fields::kAA));
857   CPDF_AAction::AActionType type = aaType == FPDFPAGE_AACTION_OPEN
858                                        ? CPDF_AAction::kOpenPage
859                                        : CPDF_AAction::kClosePage;
860   if (aa.ActionExist(type))
861     pFormFillEnv->DoActionPage(aa.GetAction(type), type);
862 }
863 
864 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FORM_SetIndexSelected(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int index,FPDF_BOOL selected)865 FORM_SetIndexSelected(FPDF_FORMHANDLE hHandle,
866                       FPDF_PAGE page,
867                       int index,
868                       FPDF_BOOL selected) {
869   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
870   return pPageView && pPageView->SetIndexSelected(index, selected);
871 }
872 
873 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FORM_IsIndexSelected(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int index)874 FORM_IsIndexSelected(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int index) {
875   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
876   return pPageView && pPageView->IsIndexSelected(index);
877 }
878