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(feature = "pdfium_future", feature = "pdfium_7350"))]
135 #[inline]
144 pub fn insert_object_at_index(
145 &mut self,
146 index: PdfPageObjectIndex,
147 mut object: PdfPageObject<'a>,
148 ) -> Result<PdfPageObject<'a>, PdfiumError> {
149 object.insert_object_on_page(self, index).map(|_| object)
150 }
151}
152
153impl<'a> PdfPageObjectsPrivate<'a> for PdfPageObjects<'a> {
154 #[inline]
155 fn ownership(&self) -> &PdfPageObjectOwnership {
156 &self.ownership
157 }
158
159 #[inline]
160 fn len_impl(&self) -> PdfPageObjectIndex {
161 (unsafe { self.bindings().FPDFPage_CountObjects(self.page_handle) }) as PdfPageObjectIndex
162 }
163
164 fn get_impl(&self, index: PdfPageObjectIndex) -> Result<PdfPageObject<'a>, PdfiumError> {
165 let object_handle = unsafe {
166 self.bindings()
167 .FPDFPage_GetObject(self.page_handle, index as c_int)
168 };
169
170 if object_handle.is_null() {
171 if index >= self.len() {
172 Err(PdfiumError::PageObjectIndexOutOfBounds)
173 } else {
174 Err(PdfiumError::PdfiumLibraryInternalError(
175 PdfiumInternalError::Unknown,
176 ))
177 }
178 } else {
179 Ok(PdfPageObject::from_pdfium(
180 object_handle,
181 *self.ownership(),
182 self.bindings(),
183 ))
184 }
185 }
186
187 #[inline]
188 fn iter_impl(&'a self) -> PdfPageObjectsIterator<'a> {
189 PdfPageObjectsIterator::new(self)
190 }
191
192 #[inline]
193 fn add_object_impl(
194 &mut self,
195 mut object: PdfPageObject<'a>,
196 ) -> Result<PdfPageObject<'a>, PdfiumError> {
197 object.add_object_to_page(self).map(|_| object)
198 }
199
200 #[inline]
201 fn remove_object_impl(
202 &mut self,
203 mut object: PdfPageObject<'a>,
204 ) -> Result<PdfPageObject<'a>, PdfiumError> {
205 object.remove_object_from_page().map(|_| object)
206 }
207}
208
209impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfPageObjects<'a> {}
210
211#[cfg(feature = "thread_safe")]
212unsafe impl<'a> Send for PdfPageObjects<'a> {}
213
214#[cfg(feature = "thread_safe")]
215unsafe impl<'a> Sync for PdfPageObjects<'a> {}