1use crate::bindgen::{FPDF_BOOL, FPDF_PAGE, FS_RECTF};
5use crate::bindings::PdfiumLibraryBindings;
6use crate::error::PdfiumError;
7use crate::pdf::rect::PdfRect;
8use std::os::raw::c_float;
9
10#[cfg(doc)]
11use crate::pdf::document::page::PdfPage;
12
13#[derive(Debug, Copy, Clone, PartialEq)]
15pub enum PdfPageBoundaryBoxType {
16 Media,
17 Art,
18 Bleed,
19 Trim,
20 Crop,
21 Bounding,
22}
23
24#[derive(Debug, Copy, Clone, PartialEq)]
26pub struct PdfPageBoundaryBox {
27 pub box_type: PdfPageBoundaryBoxType,
28 pub bounds: PdfRect,
29}
30
31impl PdfPageBoundaryBox {
32 #[inline]
33 pub(crate) fn new(boundary: PdfPageBoundaryBoxType, bounds: PdfRect) -> Self {
34 Self {
35 box_type: boundary,
36 bounds,
37 }
38 }
39}
40
41pub struct PdfPageBoundaries<'a> {
63 page_handle: FPDF_PAGE,
64 bindings: &'a dyn PdfiumLibraryBindings,
65}
66
67impl<'a> PdfPageBoundaries<'a> {
68 #[inline]
69 pub(crate) fn from_pdfium(
70 page_handle: FPDF_PAGE,
71 bindings: &'a dyn PdfiumLibraryBindings,
72 ) -> Self {
73 Self {
74 page_handle,
75 bindings,
76 }
77 }
78
79 #[inline]
81 pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
82 self.bindings
83 }
84
85 #[inline]
88 pub fn get(&self, boundary: PdfPageBoundaryBoxType) -> Result<PdfPageBoundaryBox, PdfiumError> {
89 match boundary {
90 PdfPageBoundaryBoxType::Media => self.media(),
91 PdfPageBoundaryBoxType::Art => self.art(),
92 PdfPageBoundaryBoxType::Bleed => self.bleed(),
93 PdfPageBoundaryBoxType::Trim => self.trim(),
94 PdfPageBoundaryBoxType::Crop => self.crop(),
95 PdfPageBoundaryBoxType::Bounding => self.bounding(),
96 }
97 }
98
99 #[inline]
102 pub fn set(
103 &mut self,
104 box_type: PdfPageBoundaryBoxType,
105 rect: PdfRect,
106 ) -> Result<(), PdfiumError> {
107 match box_type {
108 PdfPageBoundaryBoxType::Media => self.set_media(rect),
109 PdfPageBoundaryBoxType::Art => self.set_art(rect),
110 PdfPageBoundaryBoxType::Bleed => self.set_bleed(rect),
111 PdfPageBoundaryBoxType::Trim => self.set_trim(rect),
112 PdfPageBoundaryBoxType::Crop => self.set_crop(rect),
113 PdfPageBoundaryBoxType::Bounding => Ok(()), }
115 }
116
117 #[inline]
121 pub fn media(&self) -> Result<PdfPageBoundaryBox, PdfiumError> {
122 self.get_bounding_box_rect(|page, left, bottom, right, top| {
123 self.bindings
124 .FPDFPage_GetMediaBox(page, left, bottom, right, top)
125 })
126 .map(|rect| PdfPageBoundaryBox::new(PdfPageBoundaryBoxType::Media, rect))
127 }
128
129 pub fn set_media(&mut self, rect: PdfRect) -> Result<(), PdfiumError> {
131 self.bindings.FPDFPage_SetMediaBox(
132 self.page_handle,
133 rect.left().value,
134 rect.bottom().value,
135 rect.right().value,
136 rect.top().value,
137 );
138
139 Ok(())
140 }
141
142 #[inline]
146 pub fn art(&self) -> Result<PdfPageBoundaryBox, PdfiumError> {
147 self.get_bounding_box_rect(|page, left, bottom, right, top| {
148 self.bindings
149 .FPDFPage_GetArtBox(page, left, bottom, right, top)
150 })
151 .map(|rect| PdfPageBoundaryBox::new(PdfPageBoundaryBoxType::Art, rect))
152 }
153
154 pub fn set_art(&mut self, rect: PdfRect) -> Result<(), PdfiumError> {
156 self.bindings.FPDFPage_SetArtBox(
157 self.page_handle,
158 rect.left().value,
159 rect.bottom().value,
160 rect.right().value,
161 rect.top().value,
162 );
163
164 Ok(())
165 }
166
167 #[inline]
171 pub fn bleed(&self) -> Result<PdfPageBoundaryBox, PdfiumError> {
172 self.get_bounding_box_rect(|page, left, bottom, right, top| {
173 self.bindings
174 .FPDFPage_GetBleedBox(page, left, bottom, right, top)
175 })
176 .map(|rect| PdfPageBoundaryBox::new(PdfPageBoundaryBoxType::Bleed, rect))
177 }
178
179 pub fn set_bleed(&mut self, rect: PdfRect) -> Result<(), PdfiumError> {
181 self.bindings.FPDFPage_SetBleedBox(
182 self.page_handle,
183 rect.left().value,
184 rect.bottom().value,
185 rect.right().value,
186 rect.top().value,
187 );
188
189 Ok(())
190 }
191
192 #[inline]
196 pub fn trim(&self) -> Result<PdfPageBoundaryBox, PdfiumError> {
197 self.get_bounding_box_rect(|page, left, bottom, right, top| {
198 self.bindings
199 .FPDFPage_GetTrimBox(page, left, bottom, right, top)
200 })
201 .map(|rect| PdfPageBoundaryBox::new(PdfPageBoundaryBoxType::Trim, rect))
202 }
203
204 pub fn set_trim(&mut self, rect: PdfRect) -> Result<(), PdfiumError> {
206 self.bindings.FPDFPage_SetTrimBox(
207 self.page_handle,
208 rect.left().value,
209 rect.bottom().value,
210 rect.right().value,
211 rect.top().value,
212 );
213
214 Ok(())
215 }
216
217 #[inline]
220 pub fn crop(&self) -> Result<PdfPageBoundaryBox, PdfiumError> {
221 self.get_bounding_box_rect(|page, left, bottom, right, top| {
222 self.bindings
223 .FPDFPage_GetCropBox(page, left, bottom, right, top)
224 })
225 .map(|rect| PdfPageBoundaryBox::new(PdfPageBoundaryBoxType::Crop, rect))
226 }
227
228 pub fn set_crop(&mut self, rect: PdfRect) -> Result<(), PdfiumError> {
230 self.bindings.FPDFPage_SetCropBox(
231 self.page_handle,
232 rect.left().value,
233 rect.bottom().value,
234 rect.right().value,
235 rect.top().value,
236 );
237
238 Ok(())
239 }
240
241 #[inline]
246 pub fn bounding(&self) -> Result<PdfPageBoundaryBox, PdfiumError> {
247 let mut rect = FS_RECTF {
248 left: 0.0,
249 top: 0.0,
250 right: 0.0,
251 bottom: 0.0,
252 };
253
254 let result = self
255 .bindings
256 .FPDF_GetPageBoundingBox(self.page_handle, &mut rect);
257
258 PdfRect::from_pdfium_as_result(result, rect, self.bindings)
259 .map(|rect| PdfPageBoundaryBox::new(PdfPageBoundaryBoxType::Bounding, rect))
260 }
261
262 #[inline]
264 fn get_bounding_box_rect<F>(&self, f: F) -> Result<PdfRect, PdfiumError>
265 where
266 F: FnOnce(FPDF_PAGE, *mut c_float, *mut c_float, *mut c_float, *mut c_float) -> FPDF_BOOL,
267 {
268 let mut left = 0_f32;
269 let mut bottom = 0_f32;
270 let mut right = 0_f32;
271 let mut top = 0_f32;
272
273 let result = f(
274 self.page_handle,
275 &mut left,
276 &mut bottom,
277 &mut right,
278 &mut top,
279 );
280
281 PdfRect::from_pdfium_as_result(
282 result,
283 FS_RECTF {
284 left,
285 top,
286 right,
287 bottom,
288 },
289 self.bindings,
290 )
291 }
292
293 pub fn iter(&'a self) -> PageBoundaryIterator<'a> {
298 PageBoundaryIterator::new(self)
299 }
300}
301
302pub struct PageBoundaryIterator<'a> {
307 boundaries: &'a PdfPageBoundaries<'a>,
308 next_index: usize,
309}
310
311impl<'a> PageBoundaryIterator<'a> {
312 #[inline]
313 pub(crate) fn new(boundaries: &'a PdfPageBoundaries<'a>) -> Self {
314 Self {
315 boundaries,
316 next_index: 0,
317 }
318 }
319}
320
321impl<'a> Iterator for PageBoundaryIterator<'a> {
322 type Item = PdfPageBoundaryBox;
323
324 fn next(&mut self) -> Option<Self::Item> {
325 let mut next = None;
326
327 while self.next_index < 5 && next.is_none() {
328 next = match self.next_index {
329 0 => self.boundaries.get(PdfPageBoundaryBoxType::Media).ok(),
330 1 => self.boundaries.get(PdfPageBoundaryBoxType::Art).ok(),
331 2 => self.boundaries.get(PdfPageBoundaryBoxType::Bleed).ok(),
332 3 => self.boundaries.get(PdfPageBoundaryBoxType::Trim).ok(),
333 4 => self.boundaries.get(PdfPageBoundaryBoxType::Crop).ok(),
334 5 => self.boundaries.get(PdfPageBoundaryBoxType::Bounding).ok(),
335 _ => None,
336 };
337
338 self.next_index += 1;
339 }
340
341 next
342 }
343}