use crate::bindgen::{
FORMTYPE_ACRO_FORM, FORMTYPE_NONE, FORMTYPE_XFA_FOREGROUND, FORMTYPE_XFA_FULL, FPDF_DOCUMENT,
FPDF_FORMFIELD_CHECKBOX, FPDF_FORMFIELD_COMBOBOX, FPDF_FORMFIELD_LISTBOX,
FPDF_FORMFIELD_PUSHBUTTON, FPDF_FORMFIELD_RADIOBUTTON, FPDF_FORMFIELD_SIGNATURE,
FPDF_FORMFIELD_TEXTFIELD, FPDF_FORMFIELD_UNKNOWN, FPDF_FORMFILLINFO, FPDF_FORMHANDLE,
};
use crate::bindings::PdfiumLibraryBindings;
use crate::error::PdfiumError;
use std::ops::DerefMut;
use std::pin::Pin;
use std::ptr::null_mut;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum PdfFormType {
None = FORMTYPE_NONE as isize,
Acrobat = FORMTYPE_ACRO_FORM as isize,
XfaFull = FORMTYPE_XFA_FULL as isize,
XfaForeground = FORMTYPE_XFA_FOREGROUND as isize,
}
impl PdfFormType {
#[inline]
pub(crate) fn from_pdfium(form_type: u32) -> Result<PdfFormType, PdfiumError> {
match form_type {
FORMTYPE_NONE => Ok(PdfFormType::None),
FORMTYPE_ACRO_FORM => Ok(PdfFormType::Acrobat),
FORMTYPE_XFA_FULL => Ok(PdfFormType::XfaFull),
FORMTYPE_XFA_FOREGROUND => Ok(PdfFormType::XfaForeground),
_ => Err(PdfiumError::UnknownFormType),
}
}
#[inline]
#[allow(dead_code)]
pub(crate) fn as_pdfium(&self) -> u32 {
match self {
PdfFormType::None => FORMTYPE_NONE,
PdfFormType::Acrobat => FORMTYPE_ACRO_FORM,
PdfFormType::XfaFull => FORMTYPE_XFA_FULL,
PdfFormType::XfaForeground => FORMTYPE_XFA_FOREGROUND,
}
}
}
pub enum PdfFormFieldType {
Unknown = FPDF_FORMFIELD_UNKNOWN as isize,
PushButton = FPDF_FORMFIELD_PUSHBUTTON as isize,
Checkbox = FPDF_FORMFIELD_CHECKBOX as isize,
RadioButton = FPDF_FORMFIELD_RADIOBUTTON as isize,
ComboBox = FPDF_FORMFIELD_COMBOBOX as isize,
ListBox = FPDF_FORMFIELD_LISTBOX as isize,
TextField = FPDF_FORMFIELD_TEXTFIELD as isize,
Signature = FPDF_FORMFIELD_SIGNATURE as isize,
}
impl PdfFormFieldType {
#[inline]
#[allow(dead_code)]
pub(crate) fn from_pdfium(form_field_type: u32) -> Result<PdfFormFieldType, PdfiumError> {
match form_field_type {
FPDF_FORMFIELD_UNKNOWN => Ok(PdfFormFieldType::Unknown),
FPDF_FORMFIELD_PUSHBUTTON => Ok(PdfFormFieldType::PushButton),
FPDF_FORMFIELD_CHECKBOX => Ok(PdfFormFieldType::Checkbox),
FPDF_FORMFIELD_RADIOBUTTON => Ok(PdfFormFieldType::RadioButton),
FPDF_FORMFIELD_COMBOBOX => Ok(PdfFormFieldType::ComboBox),
FPDF_FORMFIELD_LISTBOX => Ok(PdfFormFieldType::ListBox),
FPDF_FORMFIELD_TEXTFIELD => Ok(PdfFormFieldType::TextField),
FPDF_FORMFIELD_SIGNATURE => Ok(PdfFormFieldType::Signature),
_ => Err(PdfiumError::UnknownFormFieldType),
}
}
#[inline]
#[allow(dead_code)]
pub(crate) fn as_pdfium(&self) -> u32 {
match self {
PdfFormFieldType::Unknown => FPDF_FORMFIELD_UNKNOWN,
PdfFormFieldType::PushButton => FPDF_FORMFIELD_PUSHBUTTON,
PdfFormFieldType::Checkbox => FPDF_FORMFIELD_CHECKBOX,
PdfFormFieldType::RadioButton => FPDF_FORMFIELD_RADIOBUTTON,
PdfFormFieldType::ComboBox => FPDF_FORMFIELD_COMBOBOX,
PdfFormFieldType::ListBox => FPDF_FORMFIELD_LISTBOX,
PdfFormFieldType::TextField => FPDF_FORMFIELD_TEXTFIELD,
PdfFormFieldType::Signature => FPDF_FORMFIELD_SIGNATURE,
}
}
}
pub struct PdfForm<'a> {
form_handle: FPDF_FORMHANDLE,
document_handle: FPDF_DOCUMENT,
#[allow(dead_code)]
form_fill_info: Pin<Box<FPDF_FORMFILLINFO>>,
bindings: &'a dyn PdfiumLibraryBindings,
}
impl<'a> PdfForm<'a> {
#[inline]
pub(crate) fn from_pdfium(
document_handle: FPDF_DOCUMENT,
bindings: &'a dyn PdfiumLibraryBindings,
) -> Option<Self> {
let mut form_fill_info = Box::pin(FPDF_FORMFILLINFO {
version: 2,
Release: None,
FFI_Invalidate: None,
FFI_OutputSelectedRect: None,
FFI_SetCursor: None,
FFI_SetTimer: None,
FFI_KillTimer: None,
FFI_GetLocalTime: None,
FFI_OnChange: None,
FFI_GetPage: None,
FFI_GetCurrentPage: None,
FFI_GetRotation: None,
FFI_ExecuteNamedAction: None,
FFI_SetTextFieldFocus: None,
FFI_DoURIAction: None,
FFI_DoGoToAction: None,
m_pJsPlatform: null_mut(),
xfa_disabled: 0,
FFI_DisplayCaret: None,
FFI_GetCurrentPageIndex: None,
FFI_SetCurrentPage: None,
FFI_GotoURL: None,
FFI_GetPageViewRect: None,
FFI_PageEvent: None,
FFI_PopupMenu: None,
FFI_OpenFile: None,
FFI_EmailTo: None,
FFI_UploadTo: None,
FFI_GetPlatform: None,
FFI_GetLanguage: None,
FFI_DownloadFromURL: None,
FFI_PostRequestURL: None,
FFI_PutRequestURL: None,
FFI_OnFocusChange: None,
FFI_DoURIActionWithKeyboardModifier: None,
});
let form_handle =
bindings.FPDFDOC_InitFormFillEnvironment(document_handle, form_fill_info.deref_mut());
if !form_handle.is_null() && bindings.get_pdfium_last_error().is_none() {
let form = PdfForm {
form_handle,
document_handle,
form_fill_info,
bindings,
};
if form.form_type() != PdfFormType::None {
Some(form)
} else {
None
}
} else {
None
}
}
#[inline]
pub(crate) fn handle(&self) -> &FPDF_FORMHANDLE {
&self.form_handle
}
#[inline]
pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
self.bindings
}
#[inline]
pub fn form_type(&self) -> PdfFormType {
PdfFormType::from_pdfium(self.bindings.FPDF_GetFormType(self.document_handle) as u32)
.unwrap()
}
}
impl<'a> Drop for PdfForm<'a> {
#[inline]
fn drop(&mut self) {
self.bindings
.FPDFDOC_ExitFormFillEnvironment(self.form_handle);
}
}