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