pdfium_render/pdf/document/page/
objects.rs1pub mod common;
5pub(crate) mod private; use crate::bindgen::{FPDF_DOCUMENT, FPDF_PAGE};
8use crate::error::{PdfiumError, PdfiumInternalError};
9use crate::pdf::document::page::object::group::PdfPageGroupObject;
10use crate::pdf::document::page::object::ownership::PdfPageObjectOwnership;
11use crate::pdf::document::page::object::private::internal::PdfPageObjectPrivate;
12use crate::pdf::document::page::object::x_object_form::PdfPageXObjectFormObject;
13use crate::pdf::document::page::object::PdfPageObject;
14use crate::pdf::document::page::objects::common::{
15 PdfPageObjectIndex, PdfPageObjectsCommon, PdfPageObjectsIterator,
16};
17use crate::pdf::document::page::objects::private::internal::PdfPageObjectsPrivate;
18use crate::pdf::document::page::PdfPageIndexCache;
19use crate::pdf::document::PdfDocument;
20use crate::pdfium::PdfiumLibraryBindingsAccessor;
21use std::marker::PhantomData;
22use std::os::raw::c_int;
23
24#[cfg(doc)]
25use {
26 crate::pdf::document::page::object::PdfPageObjectType, crate::pdf::document::page::PdfPage,
27 crate::pdf::document::page::PdfPageContentRegenerationStrategy,
28};
29
30pub struct PdfPageObjects<'a> {
40 document_handle: FPDF_DOCUMENT,
41 page_handle: FPDF_PAGE,
42 ownership: PdfPageObjectOwnership,
43 lifetime: PhantomData<&'a FPDF_PAGE>,
44}
45
46impl<'a> PdfPageObjects<'a> {
47 #[inline]
48 pub(crate) fn from_pdfium(document_handle: FPDF_DOCUMENT, page_handle: FPDF_PAGE) -> Self {
49 Self {
50 document_handle,
51 page_handle,
52 ownership: PdfPageObjectOwnership::owned_by_page(document_handle, page_handle),
53 lifetime: PhantomData,
54 }
55 }
56
57 #[inline]
59 pub(crate) fn document_handle(&self) -> FPDF_DOCUMENT {
60 self.document_handle
61 }
62
63 #[inline]
65 pub(crate) fn page_handle(&self) -> FPDF_PAGE {
66 self.page_handle
67 }
68
69 pub fn create_group<F>(&'a self, predicate: F) -> Result<PdfPageGroupObject<'a>, PdfiumError>
72 where
73 F: Fn(&PdfPageObject) -> bool,
74 {
75 let mut result = self.create_empty_group();
76
77 for mut object in self.iter().filter(predicate) {
78 result.push(&mut object)?;
79 }
80
81 Ok(result)
82 }
83
84 #[inline]
88 pub fn create_empty_group(&self) -> PdfPageGroupObject<'a> {
89 PdfPageGroupObject::from_pdfium(self.document_handle(), self.page_handle())
90 }
91
92 pub fn copy_into_x_object_form_object(
95 &self,
96 destination: &mut PdfDocument<'a>,
97 ) -> Result<PdfPageObject<'a>, PdfiumError> {
98 let page_index =
99 PdfPageIndexCache::get_index_for_page(self.document_handle(), self.page_handle());
100
101 match page_index {
102 Some(page_index) => {
103 let x_object = unsafe {
104 self.bindings().FPDF_NewXObjectFromPage(
105 destination.handle(),
106 self.document_handle(),
107 page_index as c_int,
108 )
109 };
110
111 let object_handle =
112 unsafe { self.bindings().FPDF_NewFormObjectFromXObject(x_object) };
113 if object_handle.is_null() {
114 return Err(PdfiumError::PdfiumLibraryInternalError(
115 crate::error::PdfiumInternalError::Unknown,
116 ));
117 }
118
119 let object = PdfPageXObjectFormObject::from_pdfium(
120 object_handle,
121 PdfPageObjectOwnership::owned_by_document(destination.handle()),
122 );
123
124 unsafe {
125 self.bindings().FPDF_CloseXObject(x_object);
126 }
127
128 Ok(PdfPageObject::XObjectForm(object))
129 }
130 None => Err(PdfiumError::SourcePageIndexNotInCache),
131 }
132 }
133
134 #[cfg(any(
135 feature = "pdfium_future",
136 feature = "pdfium_7763",
137 feature = "pdfium_7543",
138 feature = "pdfium_7350"
139 ))]
140 #[inline]
149 pub fn insert_object_at_index(
150 &mut self,
151 index: PdfPageObjectIndex,
152 mut object: PdfPageObject<'a>,
153 ) -> Result<PdfPageObject<'a>, PdfiumError> {
154 object.insert_object_on_page(self, index).map(|_| object)
155 }
156}
157
158impl<'a> PdfPageObjectsPrivate<'a> for PdfPageObjects<'a> {
159 #[inline]
160 fn ownership(&self) -> &PdfPageObjectOwnership {
161 &self.ownership
162 }
163
164 #[inline]
165 fn len_impl(&self) -> PdfPageObjectIndex {
166 (unsafe { self.bindings().FPDFPage_CountObjects(self.page_handle) }) as PdfPageObjectIndex
167 }
168
169 fn get_impl(&self, index: PdfPageObjectIndex) -> Result<PdfPageObject<'a>, PdfiumError> {
170 let object_handle = unsafe {
171 self.bindings()
172 .FPDFPage_GetObject(self.page_handle, index as c_int)
173 };
174
175 if object_handle.is_null() {
176 if index >= self.len() {
177 Err(PdfiumError::PageObjectIndexOutOfBounds)
178 } else {
179 Err(PdfiumError::PdfiumLibraryInternalError(
180 PdfiumInternalError::Unknown,
181 ))
182 }
183 } else {
184 Ok(PdfPageObject::from_pdfium(
185 object_handle,
186 *self.ownership(),
187 self.bindings(),
188 ))
189 }
190 }
191
192 #[inline]
193 fn iter_impl(&'a self) -> PdfPageObjectsIterator<'a> {
194 PdfPageObjectsIterator::new(self)
195 }
196
197 #[inline]
198 fn add_object_impl(
199 &mut self,
200 mut object: PdfPageObject<'a>,
201 ) -> Result<PdfPageObject<'a>, PdfiumError> {
202 object.add_object_to_page(self).map(|_| object)
203 }
204
205 #[inline]
206 fn remove_object_impl(
207 &mut self,
208 mut object: PdfPageObject<'a>,
209 ) -> Result<PdfPageObject<'a>, PdfiumError> {
210 object.remove_object_from_page().map(|_| object)
211 }
212}
213
214impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfPageObjects<'a> {}
215
216#[cfg(feature = "thread_safe")]
217unsafe impl<'a> Send for PdfPageObjects<'a> {}
218
219#[cfg(feature = "thread_safe")]
220unsafe impl<'a> Sync for PdfPageObjects<'a> {}