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