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