Skip to main content

pdfium_render/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod bindgen {
4    #![allow(non_upper_case_globals)]
5    #![allow(non_camel_case_types)]
6    #![allow(non_snake_case)]
7    #![allow(dead_code)]
8
9    // Select the Pdfium FPDF_* API version to use based on crate feature flags.
10
11    #[cfg(feature = "pdfium_future")]
12    include!("bindgen/pdfium_future.rs");
13
14    #[cfg(feature = "pdfium_8125")]
15    include!("bindgen/pdfium_8125.rs");
16
17    #[cfg(feature = "pdfium_7881")]
18    include!("bindgen/pdfium_7881.rs");
19
20    #[cfg(feature = "pdfium_7763")]
21    include!("bindgen/pdfium_7763.rs");
22
23    #[cfg(feature = "pdfium_7543")]
24    include!("bindgen/pdfium_7543.rs");
25
26    #[cfg(feature = "pdfium_7350")]
27    include!("bindgen/pdfium_7350.rs");
28
29    #[cfg(feature = "pdfium_7215")]
30    include!("bindgen/pdfium_7215.rs");
31
32    #[cfg(feature = "pdfium_7123")]
33    include!("bindgen/pdfium_7123.rs");
34
35    #[cfg(feature = "pdfium_6996")]
36    include!("bindgen/pdfium_6996.rs");
37
38    #[cfg(feature = "pdfium_6721")]
39    include!("bindgen/pdfium_6721.rs");
40
41    #[cfg(feature = "pdfium_6666")]
42    include!("bindgen/pdfium_6666.rs");
43
44    #[cfg(feature = "pdfium_6611")]
45    include!("bindgen/pdfium_6611.rs");
46
47    #[cfg(feature = "pdfium_6569")]
48    include!("bindgen/pdfium_6569.rs");
49
50    #[cfg(feature = "pdfium_6555")]
51    include!("bindgen/pdfium_6555.rs");
52
53    #[cfg(feature = "pdfium_6490")]
54    include!("bindgen/pdfium_6490.rs");
55
56    #[cfg(feature = "pdfium_6406")]
57    include!("bindgen/pdfium_6406.rs");
58
59    #[cfg(feature = "pdfium_6337")]
60    include!("bindgen/pdfium_6337.rs");
61
62    #[cfg(feature = "pdfium_6295")]
63    include!("bindgen/pdfium_6295.rs");
64
65    #[cfg(feature = "pdfium_6259")]
66    include!("bindgen/pdfium_6259.rs");
67
68    #[cfg(feature = "pdfium_6164")]
69    include!("bindgen/pdfium_6164.rs");
70
71    #[cfg(feature = "pdfium_6124")]
72    include!("bindgen/pdfium_6124.rs");
73
74    #[cfg(feature = "pdfium_6110")]
75    include!("bindgen/pdfium_6110.rs");
76
77    #[cfg(feature = "pdfium_6084")]
78    include!("bindgen/pdfium_6084.rs");
79
80    #[cfg(feature = "pdfium_6043")]
81    include!("bindgen/pdfium_6043.rs");
82
83    #[cfg(feature = "pdfium_6015")]
84    include!("bindgen/pdfium_6015.rs");
85
86    #[cfg(feature = "pdfium_5961")]
87    include!("bindgen/pdfium_5961.rs");
88
89    pub(crate) type size_t = usize;
90}
91
92mod bindings;
93mod config;
94mod error;
95mod pdf;
96mod pdfium;
97mod utils;
98
99/// A prelude for conveniently importing all public `pdfium-render` definitions at once.
100///
101/// Usage:
102/// ```
103/// use pdfium_render::prelude::*;
104/// ```
105pub mod prelude {
106    pub use crate::{
107        bindings::*,
108        config::*,
109        error::*,
110        pdf::action::*,
111        pdf::appearance_mode::*,
112        pdf::bitmap::*,
113        pdf::color::*,
114        pdf::color_space::*,
115        pdf::destination::*,
116        pdf::document::attachment::*,
117        pdf::document::attachments::*,
118        pdf::document::bookmark::*,
119        pdf::document::bookmarks::*,
120        pdf::document::catalog::*,
121        pdf::document::fonts::*,
122        pdf::document::form::*,
123        pdf::document::metadata::*,
124        pdf::document::page::annotation::attachment_points::*,
125        pdf::document::page::annotation::circle::*,
126        pdf::document::page::annotation::free_text::*,
127        pdf::document::page::annotation::highlight::*,
128        pdf::document::page::annotation::ink::*,
129        pdf::document::page::annotation::link::*,
130        pdf::document::page::annotation::objects::*,
131        pdf::document::page::annotation::popup::*,
132        pdf::document::page::annotation::redacted::*,
133        pdf::document::page::annotation::square::*,
134        pdf::document::page::annotation::squiggly::*,
135        pdf::document::page::annotation::stamp::*,
136        pdf::document::page::annotation::strikeout::*,
137        pdf::document::page::annotation::text::*,
138        pdf::document::page::annotation::underline::*,
139        pdf::document::page::annotation::unsupported::*,
140        pdf::document::page::annotation::variable_text::*,
141        pdf::document::page::annotation::widget::*,
142        pdf::document::page::annotation::xfa_widget::*,
143        pdf::document::page::annotation::{
144            PdfPageAnnotation, PdfPageAnnotationCommon, PdfPageAnnotationType,
145        },
146        pdf::document::page::annotations::*,
147        pdf::document::page::boundaries::*,
148        pdf::document::page::field::button::*,
149        pdf::document::page::field::checkbox::*,
150        pdf::document::page::field::combo::*,
151        pdf::document::page::field::list::*,
152        pdf::document::page::field::option::*,
153        pdf::document::page::field::options::*,
154        pdf::document::page::field::radio::*,
155        pdf::document::page::field::signature::*,
156        pdf::document::page::field::text::*,
157        pdf::document::page::field::unknown::*,
158        pdf::document::page::field::{PdfFormField, PdfFormFieldCommon, PdfFormFieldType},
159        pdf::document::page::links::*,
160        pdf::document::page::object::content_mark::*,
161        pdf::document::page::object::group::*,
162        pdf::document::page::object::image::*,
163        pdf::document::page::object::path::*,
164        pdf::document::page::object::shading::*,
165        pdf::document::page::object::text::*,
166        pdf::document::page::object::unsupported::*,
167        pdf::document::page::object::x_object_form::*,
168        pdf::document::page::object::{
169            PdfPageObject, PdfPageObjectBlendMode, PdfPageObjectCommon, PdfPageObjectLineCap,
170            PdfPageObjectLineJoin, PdfPageObjectType,
171        },
172        pdf::document::page::objects::common::*,
173        pdf::document::page::objects::*,
174        pdf::document::page::render_config::*,
175        pdf::document::page::size::*,
176        pdf::document::page::structure_tree::*,
177        pdf::document::page::text::char::*,
178        pdf::document::page::text::chars::*,
179        pdf::document::page::text::search::*,
180        pdf::document::page::text::segment::*,
181        pdf::document::page::text::segments::*,
182        pdf::document::page::text::*,
183        pdf::document::page::{
184            PdfPage, PdfPageContentRegenerationStrategy, PdfPageOrientation, PdfPageRenderRotation,
185        },
186        pdf::document::pages::*,
187        pdf::document::permissions::*,
188        pdf::document::signature::*,
189        pdf::document::signatures::*,
190        pdf::document::{PdfDocument, PdfDocumentVersion},
191        pdf::font::glyph::*,
192        pdf::font::glyphs::*,
193        pdf::font::provider::*,
194        pdf::font::*,
195        pdf::link::*,
196        pdf::matrix::*,
197        pdf::path::clip_path::*,
198        pdf::path::segment::*,
199        pdf::path::segments::*,
200        pdf::points::*,
201        pdf::quad_points::*,
202        pdf::rect::*,
203        pdfium::*,
204    };
205}
206
207#[cfg(test)]
208mod tests {
209    use crate::prelude::*;
210    use crate::utils::test::test_bind_to_pdfium;
211    use image_025::ImageFormat;
212    use std::fs::File;
213    use std::path::Path;
214
215    #[test]
216    #[cfg(not(feature = "static"))]
217    fn test_readme_example() -> Result<(), PdfiumError> {
218        // Runs the code in the main example at the top of README.md.
219
220        fn export_pdf_to_jpegs(
221            path: &impl AsRef<Path>,
222            password: Option<&str>,
223        ) -> Result<(), PdfiumError> {
224            // Renders each page in the given test PDF file to a separate JPEG file.
225
226            // Bind to a Pdfium library in the same directory as our Rust executable.
227            // See the "Dynamic linking" section below.
228
229            let pdfium = Pdfium::default();
230
231            // Open the PDF document...
232
233            let document = pdfium.load_pdf_from_file(path, password)?;
234
235            // ... set rendering options that will apply to all pages...
236
237            let render_config = PdfRenderConfig::new()
238                .set_target_width(2000)
239                .set_maximum_height(2000)
240                .rotate_if_landscape(PdfPageRenderRotation::Degrees90, true);
241
242            // ... then render each page to a bitmap image, saving each image to a JPEG file.
243
244            for (index, page) in document.pages().iter().enumerate() {
245                page.render_with_config(&render_config)?
246                    .as_image()? // Renders this page to an Image::DynamicImage...
247                    .into_rgb8() // ... then converts it to an Image::Image ...
248                    .save_with_format(format!("test-page-{}.jpg", index), ImageFormat::Jpeg) // ... and saves it to a file.
249                    .map_err(|_| PdfiumError::ImageError)?;
250            }
251
252            Ok(())
253        }
254
255        export_pdf_to_jpegs(&"./test/export-test.pdf", None)
256    }
257
258    #[test]
259    #[cfg(not(feature = "static"))]
260    fn test_dynamic_bindings() -> Result<(), PdfiumError> {
261        let pdfium = Pdfium::default();
262
263        let document = pdfium.load_pdf_from_file("./test/form-test.pdf", None)?;
264
265        let render_config = PdfRenderConfig::new()
266            .set_target_width(2000)
267            .set_maximum_height(2000)
268            .rotate_if_landscape(PdfPageRenderRotation::Degrees90, true)
269            .render_form_data(true)
270            .render_annotations(true);
271
272        for (index, page) in document.pages().iter().enumerate() {
273            let result = page
274                .render_with_config(&render_config)?
275                .as_image()?
276                .into_rgb8()
277                .save_with_format(format!("form-test-page-{}.jpg", index), ImageFormat::Jpeg);
278
279            assert!(result.is_ok());
280        }
281
282        Ok(())
283    }
284
285    #[test]
286    #[cfg(feature = "static")]
287    fn test_static_bindings() {
288        // Simply checks that the static bindings contain no compilation errors.
289
290        Pdfium::bind_to_statically_linked_library().unwrap();
291    }
292
293    #[test]
294    fn test_reader_lifetime() -> Result<(), PdfiumError> {
295        // Confirms that a reader given to Pdfium::load_pdf_from_reader() does not need
296        // a lifetime longer than that of the PdfDocument it is used to create.
297
298        let pdfium = test_bind_to_pdfium();
299
300        let paths = ["test/form-test.pdf", "test/annotations-test.pdf"];
301
302        for path in paths {
303            let page_count = {
304                let reader = File::open(path).map_err(PdfiumError::IoError)?;
305
306                let document = pdfium.load_pdf_from_reader(reader, None)?;
307
308                document.pages().len()
309
310                // reader will be dropped here, immediately after document.
311            };
312
313            println!("{} has {} pages", path, page_count);
314        }
315
316        Ok(())
317    }
318}