Skip to content

Commit

Permalink
Progressing 137
Browse files Browse the repository at this point in the history
  • Loading branch information
Alastair Carey committed Aug 17, 2024
1 parent 9a8552c commit fc0efe5
Show file tree
Hide file tree
Showing 6 changed files with 613 additions and 9 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ functions specific to interactive scripting, user interaction, and printing.
* Releases numbered 0.8.x aim to progressively add support for all remaining Pdfium editing functions to `pdfium-render`.
* Releases numbered 0.9.x aim to fill any remaining gaps in the high-level interface prior to 1.0.

There are 377 `FPDF_*` functions in the Pdfium API. As of version 0.8.25, 338 (90%) have
There are 408 `FPDF_*` functions in the Pdfium API. As of version 0.8.25, 346 (85%) have
bindings available in `PdfiumLibraryBindings`, with the functionality of the majority of these
available via the `pdfium-render` high-level interface.

Expand All @@ -368,8 +368,10 @@ at <https://github.com/ajrcarey/pdfium-render/issues>.
## Version history

* 0.8.25: adds bindings for `FPDFAnnot_GetFormAdditionalActionJavaScript()`,
`FPDFAnnot_GetFormFieldAlternateName()`, `FPDFAnnot_GetFileAttachment()`, and
`FPDFAnnot_AddFileAttachment()`.
`FPDFAnnot_GetFormFieldAlternateName()`, `FPDFAnnot_GetFileAttachment()`,
`FPDFAnnot_AddFileAttachment()`, `FPDFAvail_Create()`, `FPDFAvail_Destroy()`,
`FPDFAvail_IsDocAvail()`, `FPDFAvail_GetDocument()`, `FPDFAvail_GetFirstPageNum()`,
`FPDFAvail_IsPageAvail()`, `FPDFAvail_IsFormAvail()`, and `FPDFAvail_IsLinearized()` functions.
* 0.8.24: introduces crate feature flags for selecting Pdfium API versions to use in
`PdfiumLibraryBindings`; reworked `build.rs` to output bindings for multiple sets of Pdfium header
files; reworks bindings implementations to differentiate between API versions that include the
Expand Down
158 changes: 157 additions & 1 deletion src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@ pub mod version;

use crate::bindgen::{
size_t, FPDFANNOT_COLORTYPE, FPDF_ACTION, FPDF_ANNOTATION, FPDF_ANNOTATION_SUBTYPE,
FPDF_ANNOT_APPEARANCEMODE, FPDF_ATTACHMENT, FPDF_BITMAP, FPDF_BOOKMARK, FPDF_BOOL,
FPDF_ANNOT_APPEARANCEMODE, FPDF_ATTACHMENT, FPDF_AVAIL, FPDF_BITMAP, FPDF_BOOKMARK, FPDF_BOOL,
FPDF_CLIPPATH, FPDF_DEST, FPDF_DOCUMENT, FPDF_DUPLEXTYPE, FPDF_DWORD, FPDF_FILEACCESS,
FPDF_FILEIDTYPE, FPDF_FILEWRITE, FPDF_FONT, FPDF_FORMFILLINFO, FPDF_FORMHANDLE, FPDF_GLYPHPATH,
FPDF_IMAGEOBJ_METADATA, FPDF_LINK, FPDF_OBJECT_TYPE, FPDF_PAGE, FPDF_PAGELINK, FPDF_PAGEOBJECT,
FPDF_PAGEOBJECTMARK, FPDF_PAGERANGE, FPDF_PATHSEGMENT, FPDF_SCHHANDLE, FPDF_SIGNATURE,
FPDF_STRUCTELEMENT, FPDF_STRUCTTREE, FPDF_TEXTPAGE, FPDF_TEXT_RENDERMODE, FPDF_WCHAR,
FPDF_WIDESTRING, FS_FLOAT, FS_MATRIX, FS_POINTF, FS_QUADPOINTSF, FS_RECTF, FS_SIZEF,
FX_DOWNLOADHINTS, FX_FILEAVAIL,
};
use crate::bindings::version::PdfiumApiVersion;
use crate::error::{PdfiumError, PdfiumInternalError};
Expand Down Expand Up @@ -264,6 +265,161 @@ pub trait PdfiumLibraryBindings {
fileVersion: c_int,
) -> FPDF_BOOL;

/// Create a document availability provider.
///
/// `file_avail` - pointer to file availability interface.
///
/// `file` - pointer to a file access interface.
///
/// Returns a handle to the document availability provider, or `NULL` on error.
///
/// [PdfiumLibraryBindings::FPDFAvail_Destroy] must be called when done with the
/// availability provider.
#[allow(non_snake_case)]
fn FPDFAvail_Create(
&self,
file_avail: *mut FX_FILEAVAIL,
file: *mut FPDF_FILEACCESS,
) -> FPDF_AVAIL;

/// Destroy the `avail` document availability provider.
///
/// `avail` - handle to document availability provider to be destroyed.
#[allow(non_snake_case)]
fn FPDFAvail_Destroy(&self, avail: FPDF_AVAIL);

/// Checks if the document is ready for loading; if not, gets download hints.
///
/// `avail` - handle to document availability provider.
///
/// `hints` - pointer to a download hints interface.
///
/// Returns one of:
///
/// `PDF_DATA_ERROR`: A common error is returned. Data availability unknown.
///
/// `PDF_DATA_NOTAVAIL`: Data not yet available.
///
/// `PDF_DATA_AVAIL`: Data available.
///
/// Applications should call this function whenever new data arrives, and process
/// all the generated download hints, if any, until the function returns
/// `PDF_DATA_ERROR` or `PDF_DATA_AVAIL`.
///
/// If `hints` is `NULL`, the function just checks current document availability.
///
/// Once all data is available, call [PdfiumLibraryBindings::FPDFAvail_GetDocument] to get
/// a document handle.
#[allow(non_snake_case)]
fn FPDFAvail_IsDocAvail(&self, avail: FPDF_AVAIL, hints: *mut FX_DOWNLOADHINTS) -> c_int;

/// Get document from the availability provider.
///
/// `avail` - handle to document availability provider.
///
/// `password` - password for decrypting the PDF file. Optional.
///
/// Returns a handle to the document.
///
/// When [PdfiumLibraryBindings::FPDFAvail_IsDocAvail] returns `TRUE`, call
/// [PdfiumLibraryBindings::FPDFAvail_GetDocument] to\n retrieve the document handle.
/// See the comments for [PdfiumLibraryBindings::FPDF_LoadDocument] regarding the encoding
/// for `password`.
#[allow(non_snake_case)]
fn FPDFAvail_GetDocument(&self, avail: FPDF_AVAIL, password: Option<&str>) -> FPDF_DOCUMENT;

/// Get the page number for the first available page in a linearized PDF.
///
/// `doc` - document handle.
///
/// Returns the zero-based index for the first available page.
///
/// For most linearized PDFs, the first available page will be the first page,
/// however, some PDFs might make another page the first available page.
///
/// For non-linearized PDFs, this function will always return zero.
#[allow(non_snake_case)]
fn FPDFAvail_GetFirstPageNum(&self, doc: FPDF_DOCUMENT) -> c_int;

/// Check if `page_index` is ready for loading, if not, get the `FX_DOWNLOADHINTS`.
///
/// `avail` - handle to document availability provider.
///
/// `page_index` - index number of the page. Zero for the first page.
///
/// `hints` - pointer to a download hints interface. Populated if
/// `page_index` is not available.
///
/// Returns one of:
///
/// `PDF_DATA_ERROR`: A common error is returned. Data availability unknown.
///
/// `PDF_DATA_NOTAVAIL`: Data not yet available.
///
/// `PDF_DATA_AVAIL`: Data available.
///
/// This function can be called only after [PdfiumLibraryBindings::FPDFAvail_GetDocument]
/// is called. Applications should call this function whenever new data arrives and process
/// all the generated download `hints`, if any, until this function returns `PDF_DATA_ERROR`
/// or `PDF_DATA_AVAIL`. Applications can then perform page loading.
///
/// If `hints` is `NULL`, the function just check current availability of specified page.
#[allow(non_snake_case)]
fn FPDFAvail_IsPageAvail(
&self,
avail: FPDF_AVAIL,
page_index: c_int,
hints: *mut FX_DOWNLOADHINTS,
) -> c_int;

/// Check if form data is ready for initialization; if not, get the `FX_DOWNLOADHINTS`.
///
/// `avail` - handle to document availability provider.
///
/// `hints` - pointer to a download hints interface. Populated if form is not
/// ready for initialization.
///
/// Returns one of:
///
/// `PDF_FORM_ERROR`: A common error, in general incorrect parameters.
///
/// `PDF_FORM_NOTAVAIL`: Data not available.
///
/// `PDF_FORM_AVAIL`: Data available.
///
/// `PDF_FORM_NOTEXIST`: No form data.
///
/// This function can be called only after [PdfiumLibraryBindings::FPDFAvail_GetDocument]
/// is called. The application should call this function whenever new data arrives and
/// process all the generated download `hints`, if any, until the function returns
/// `PDF_FORM_ERROR`, `PDF_FORM_AVAIL` or `PDF_FORM_NOTEXIST`.
///
/// If `hints` is `NULL`, the function just check current form availability.
///
/// Applications can then perform page loading. It is recommend to call
/// [PdfiumLibraryBindings::FPDFDOC_InitFormFillEnvironment] when `PDF_FORM_AVAIL` is returned.
#[allow(non_snake_case)]
fn FPDFAvail_IsFormAvail(&self, avail: FPDF_AVAIL, hints: *mut FX_DOWNLOADHINTS) -> c_int;

/// Check whether a document is a linearized PDF.
///
/// `avail` - handle to document availability provider.
///
/// Returns one of:
///
/// `PDF_LINEARIZED`
///
/// `PDF_NOT_LINEARIZED`
///
/// `PDF_LINEARIZATION_UNKNOWN`
///
/// [PdfiumLibraryBindings::FPDFAvail_IsLinearized] will return `PDF_LINEARIZED` or
/// `PDF_NOT_LINEARIZED` once we have received 1kb of data. If the file's size is less
/// than 1kb, it returns `PDF_LINEARIZATION_UNKNOWN` as there is insufficient information
// to determine if the PDF is linearlized.
#[allow(non_snake_case)]
fn FPDFAvail_IsLinearized(&self, avail: FPDF_AVAIL) -> c_int;

#[allow(non_snake_case)]
fn FPDF_CloseDocument(&self, document: FPDF_DOCUMENT);

Expand Down
89 changes: 87 additions & 2 deletions src/bindings/dynamic.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::bindgen::{
size_t, FPDFANNOT_COLORTYPE, FPDF_ACTION, FPDF_ANNOTATION, FPDF_ANNOTATION_SUBTYPE,
FPDF_ANNOT_APPEARANCEMODE, FPDF_ATTACHMENT, FPDF_BITMAP, FPDF_BOOKMARK, FPDF_BOOL,
FPDF_ANNOT_APPEARANCEMODE, FPDF_ATTACHMENT, FPDF_AVAIL, FPDF_BITMAP, FPDF_BOOKMARK, FPDF_BOOL,
FPDF_BYTESTRING, FPDF_CLIPPATH, FPDF_DEST, FPDF_DOCUMENT, FPDF_DUPLEXTYPE, FPDF_DWORD,
FPDF_FILEACCESS, FPDF_FILEIDTYPE, FPDF_FILEWRITE, FPDF_FONT, FPDF_FORMFILLINFO,
FPDF_FORMHANDLE, FPDF_GLYPHPATH, FPDF_IMAGEOBJ_METADATA, FPDF_LINK, FPDF_OBJECT_TYPE,
FPDF_PAGE, FPDF_PAGELINK, FPDF_PAGEOBJECT, FPDF_PAGEOBJECTMARK, FPDF_PAGERANGE,
FPDF_PATHSEGMENT, FPDF_SCHHANDLE, FPDF_SIGNATURE, FPDF_STRING, FPDF_STRUCTELEMENT,
FPDF_STRUCTTREE, FPDF_TEXTPAGE, FPDF_TEXT_RENDERMODE, FPDF_WCHAR, FPDF_WIDESTRING, FS_FLOAT,
FS_MATRIX, FS_POINTF, FS_QUADPOINTSF, FS_RECTF, FS_SIZEF,
FS_MATRIX, FS_POINTF, FS_QUADPOINTSF, FS_RECTF, FS_SIZEF, FX_DOWNLOADHINTS, FX_FILEAVAIL,
};
use crate::bindings::PdfiumLibraryBindings;
use libloading::Library;
Expand Down Expand Up @@ -50,6 +50,24 @@ pub(crate) struct DynamicPdfiumBindings {
flags: FPDF_DWORD,
fileVersion: c_int,
) -> FPDF_BOOL,
extern_FPDFAvail_Create: unsafe extern "C" fn(
file_avail: *mut FX_FILEAVAIL,
file: *mut FPDF_FILEACCESS,
) -> FPDF_AVAIL,
extern_FPDFAvail_Destroy: unsafe extern "C" fn(avail: FPDF_AVAIL),
extern_FPDFAvail_IsDocAvail:
unsafe extern "C" fn(avail: FPDF_AVAIL, hints: *mut FX_DOWNLOADHINTS) -> c_int,
extern_FPDFAvail_GetDocument:
unsafe extern "C" fn(avail: FPDF_AVAIL, password: FPDF_BYTESTRING) -> FPDF_DOCUMENT,
extern_FPDFAvail_GetFirstPageNum: unsafe extern "C" fn(doc: FPDF_DOCUMENT) -> c_int,
extern_FPDFAvail_IsPageAvail: unsafe extern "C" fn(
avail: FPDF_AVAIL,
page_index: c_int,
hints: *mut FX_DOWNLOADHINTS,
) -> c_int,
extern_FPDFAvail_IsFormAvail:
unsafe extern "C" fn(avail: FPDF_AVAIL, hints: *mut FX_DOWNLOADHINTS) -> c_int,
extern_FPDFAvail_IsLinearized: unsafe extern "C" fn(avail: FPDF_AVAIL) -> c_int,
extern_FPDF_CloseDocument: unsafe extern "C" fn(document: FPDF_DOCUMENT),
extern_FPDF_DeviceToPage: unsafe extern "C" fn(
page: FPDF_PAGE,
Expand Down Expand Up @@ -1272,6 +1290,14 @@ impl DynamicPdfiumBindings {
extern_FPDF_LoadCustomDocument: *(library.get(b"FPDF_LoadCustomDocument\0")?),
extern_FPDF_SaveAsCopy: *(library.get(b"FPDF_SaveAsCopy\0")?),
extern_FPDF_SaveWithVersion: *(library.get(b"FPDF_SaveWithVersion\0")?),
extern_FPDFAvail_Create: *(library.get(b"FPDFAvail_Create\0")?),
extern_FPDFAvail_Destroy: *(library.get(b"FPDFAvail_Destroy\0")?),
extern_FPDFAvail_IsDocAvail: *(library.get(b"FPDFAvail_IsDocAvail\0")?),
extern_FPDFAvail_GetDocument: *(library.get(b"FPDFAvail_GetDocument\0")?),
extern_FPDFAvail_GetFirstPageNum: *(library.get(b"FPDFAvail_GetFirstPageNum\0")?),
extern_FPDFAvail_IsPageAvail: *(library.get(b"FPDFAvail_IsPageAvail\0")?),
extern_FPDFAvail_IsFormAvail: *(library.get(b"FPDFAvail_IsFormAvail\0")?),
extern_FPDFAvail_IsLinearized: *(library.get(b"FPDFAvail_IsLinearized\0")?),
extern_FPDF_CloseDocument: *(library.get(b"FPDF_CloseDocument\0")?),
extern_FPDF_DeviceToPage: *(library.get(b"FPDF_DeviceToPage\0")?),
extern_FPDF_PageToDevice: *(library.get(b"FPDF_PageToDevice\0")?),
Expand Down Expand Up @@ -1844,6 +1870,65 @@ impl PdfiumLibraryBindings for DynamicPdfiumBindings {
unsafe { (self.extern_FPDF_SaveWithVersion)(document, pFileWrite, flags, fileVersion) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDFAvail_Create(
&self,
file_avail: *mut FX_FILEAVAIL,
file: *mut FPDF_FILEACCESS,
) -> FPDF_AVAIL {
unsafe { (self.extern_FPDFAvail_Create)(file_avail, file) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDFAvail_Destroy(&self, avail: FPDF_AVAIL) {
unsafe { (self.extern_FPDFAvail_Destroy)(avail) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDFAvail_IsDocAvail(&self, avail: FPDF_AVAIL, hints: *mut FX_DOWNLOADHINTS) -> c_int {
unsafe { (self.extern_FPDFAvail_IsDocAvail)(avail, hints) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDFAvail_GetDocument(&self, avail: FPDF_AVAIL, password: Option<&str>) -> FPDF_DOCUMENT {
let c_password = CString::new(password.unwrap_or("")).unwrap();

unsafe { (self.extern_FPDFAvail_GetDocument)(avail, c_password.as_ptr()) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDFAvail_GetFirstPageNum(&self, doc: FPDF_DOCUMENT) -> c_int {
unsafe { (self.extern_FPDFAvail_GetFirstPageNum)(doc) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDFAvail_IsPageAvail(
&self,
avail: FPDF_AVAIL,
page_index: c_int,
hints: *mut FX_DOWNLOADHINTS,
) -> c_int {
unsafe { (self.extern_FPDFAvail_IsPageAvail)(avail, page_index, hints) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDFAvail_IsFormAvail(&self, avail: FPDF_AVAIL, hints: *mut FX_DOWNLOADHINTS) -> c_int {
unsafe { (self.extern_FPDFAvail_IsFormAvail)(avail, hints) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDFAvail_IsLinearized(&self, avail: FPDF_AVAIL) -> c_int {
unsafe { (self.extern_FPDFAvail_IsLinearized)(avail) }
}

#[inline]
#[allow(non_snake_case)]
fn FPDF_CloseDocument(&self, document: FPDF_DOCUMENT) {
Expand Down
Loading

0 comments on commit fc0efe5

Please sign in to comment.