pub mod common;
pub(crate) mod private;
use crate::bindgen::{FPDF_DOCUMENT, FPDF_PAGE};
use crate::error::{PdfiumError, PdfiumInternalError};
use crate::pdf::document::page::object::group::PdfPageGroupObject;
use crate::pdf::document::page::object::ownership::PdfPageObjectOwnership;
use crate::pdf::document::page::object::private::internal::PdfPageObjectPrivate;
use crate::pdf::document::page::object::x_object_form::PdfPageXObjectFormObject;
use crate::pdf::document::page::object::PdfPageObject;
use crate::pdf::document::page::objects::common::{
PdfPageObjectIndex, PdfPageObjectsCommon, PdfPageObjectsIterator,
};
use crate::pdf::document::page::objects::private::internal::PdfPageObjectsPrivate;
use crate::pdf::document::page::PdfPageIndexCache;
use crate::pdf::document::PdfDocument;
use crate::pdfium::PdfiumLibraryBindingsAccessor;
use std::marker::PhantomData;
use std::os::raw::c_int;
#[cfg(doc)]
use {
crate::pdf::document::page::object::PdfPageObjectType, crate::pdf::document::page::PdfPage,
crate::pdf::document::page::PdfPageContentRegenerationStrategy,
};
pub struct PdfPageObjects<'a> {
document_handle: FPDF_DOCUMENT,
page_handle: FPDF_PAGE,
ownership: PdfPageObjectOwnership,
lifetime: PhantomData<&'a FPDF_PAGE>,
}
impl<'a> PdfPageObjects<'a> {
#[inline]
pub(crate) fn from_pdfium(document_handle: FPDF_DOCUMENT, page_handle: FPDF_PAGE) -> Self {
Self {
document_handle,
page_handle,
ownership: PdfPageObjectOwnership::owned_by_page(document_handle, page_handle),
lifetime: PhantomData,
}
}
#[inline]
pub(crate) fn document_handle(&self) -> FPDF_DOCUMENT {
self.document_handle
}
#[inline]
pub(crate) fn page_handle(&self) -> FPDF_PAGE {
self.page_handle
}
pub fn create_group<F>(&'a self, predicate: F) -> Result<PdfPageGroupObject<'a>, PdfiumError>
where
F: Fn(&PdfPageObject) -> bool,
{
let mut result = self.create_empty_group();
for mut object in self.iter().filter(predicate) {
result.push(&mut object)?;
}
Ok(result)
}
#[inline]
pub fn create_empty_group(&self) -> PdfPageGroupObject<'a> {
PdfPageGroupObject::from_pdfium(self.document_handle(), self.page_handle())
}
pub fn copy_into_x_object_form_object(
&self,
destination: &mut PdfDocument<'a>,
) -> Result<PdfPageObject<'a>, PdfiumError> {
let page_index =
PdfPageIndexCache::get_index_for_page(self.document_handle(), self.page_handle());
match page_index {
Some(page_index) => {
let x_object = unsafe {
self.bindings().FPDF_NewXObjectFromPage(
destination.handle(),
self.document_handle(),
page_index as c_int,
)
};
let object_handle =
unsafe { self.bindings().FPDF_NewFormObjectFromXObject(x_object) };
if object_handle.is_null() {
return Err(PdfiumError::PdfiumLibraryInternalError(
crate::error::PdfiumInternalError::Unknown,
));
}
let object = PdfPageXObjectFormObject::from_pdfium(
object_handle,
PdfPageObjectOwnership::owned_by_document(destination.handle()),
);
unsafe {
self.bindings().FPDF_CloseXObject(x_object);
}
Ok(PdfPageObject::XObjectForm(object))
}
None => Err(PdfiumError::SourcePageIndexNotInCache),
}
}
#[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
#[inline]
pub fn insert_object_at_index(
&mut self,
index: PdfPageObjectIndex,
mut object: PdfPageObject<'a>,
) -> Result<PdfPageObject<'a>, PdfiumError> {
object.insert_object_on_page(self, index).map(|_| object)
}
}
impl<'a> PdfPageObjectsPrivate<'a> for PdfPageObjects<'a> {
#[inline]
fn ownership(&self) -> &PdfPageObjectOwnership {
&self.ownership
}
#[inline]
fn len_impl(&self) -> PdfPageObjectIndex {
(unsafe { self.bindings().FPDFPage_CountObjects(self.page_handle) }) as PdfPageObjectIndex
}
fn get_impl(&self, index: PdfPageObjectIndex) -> Result<PdfPageObject<'a>, PdfiumError> {
let object_handle = unsafe {
self.bindings()
.FPDFPage_GetObject(self.page_handle, index as c_int)
};
if object_handle.is_null() {
if index >= self.len() {
Err(PdfiumError::PageObjectIndexOutOfBounds)
} else {
Err(PdfiumError::PdfiumLibraryInternalError(
PdfiumInternalError::Unknown,
))
}
} else {
Ok(PdfPageObject::from_pdfium(
object_handle,
*self.ownership(),
self.bindings(),
))
}
}
#[inline]
fn iter_impl(&'a self) -> PdfPageObjectsIterator<'a> {
PdfPageObjectsIterator::new(self)
}
#[inline]
fn add_object_impl(
&mut self,
mut object: PdfPageObject<'a>,
) -> Result<PdfPageObject<'a>, PdfiumError> {
object.add_object_to_page(self).map(|_| object)
}
#[inline]
fn remove_object_impl(
&mut self,
mut object: PdfPageObject<'a>,
) -> Result<PdfPageObject<'a>, PdfiumError> {
object.remove_object_from_page().map(|_| object)
}
}
impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfPageObjects<'a> {}
#[cfg(feature = "thread_safe")]
unsafe impl<'a> Send for PdfPageObjects<'a> {}
#[cfg(feature = "thread_safe")]
unsafe impl<'a> Sync for PdfPageObjects<'a> {}