pub mod backend;
pub mod backends;
pub mod config;
mod convenience;
pub mod error;
pub mod traits;
pub use backend::RenderBackend;
pub use config::{Background, ImageFormat, RenderConfig};
pub use convenience::{render_all_pages_to_dir, render_page, render_page_to_png};
pub use error::{RenderError, Result};
pub use traits::{PdfRenderer, RenderedImage};
#[cfg(test)]
mod tests {
#![allow(clippy::similar_names, clippy::float_cmp)]
use super::*;
fn make_test_pdf_bytes() -> Vec<u8> {
let mut doc = lopdf::Document::new();
let content_id = doc.add_object(lopdf::Object::Stream(lopdf::Stream::new(
lopdf::Dictionary::new(),
b"BT /F1 12 Tf 72 700 Td (Hello) Tj ET".to_vec(),
)));
let mut font_dict = lopdf::Dictionary::new();
font_dict.set("Type", lopdf::Object::Name(b"Font".to_vec()));
font_dict.set("Subtype", lopdf::Object::Name(b"Type1".to_vec()));
font_dict.set("BaseFont", lopdf::Object::Name(b"Helvetica".to_vec()));
let font_id = doc.add_object(lopdf::Object::Dictionary(font_dict));
let mut resources = lopdf::Dictionary::new();
let mut fonts = lopdf::Dictionary::new();
fonts.set("F1", lopdf::Object::Reference(font_id));
resources.set("Font", lopdf::Object::Dictionary(fonts));
let resources_id = doc.add_object(lopdf::Object::Dictionary(resources));
let mut page_dict = lopdf::Dictionary::new();
page_dict.set("Type", lopdf::Object::Name(b"Page".to_vec()));
page_dict.set(
"MediaBox",
lopdf::Object::Array(vec![0.into(), 0.into(), 595.into(), 842.into()]),
);
page_dict.set("Contents", lopdf::Object::Reference(content_id));
page_dict.set("Resources", lopdf::Object::Reference(resources_id));
let page_id = doc.add_object(lopdf::Object::Dictionary(page_dict));
let mut pages_dict = lopdf::Dictionary::new();
pages_dict.set("Type", lopdf::Object::Name(b"Pages".to_vec()));
pages_dict.set(
"Kids",
lopdf::Object::Array(vec![lopdf::Object::Reference(page_id)]),
);
pages_dict.set("Count", lopdf::Object::Integer(1));
let pages_id = doc.add_object(lopdf::Object::Dictionary(pages_dict));
let mut catalog = lopdf::Dictionary::new();
catalog.set("Type", lopdf::Object::Name(b"Catalog".to_vec()));
catalog.set("Pages", lopdf::Object::Reference(pages_id));
let catalog_id = doc.add_object(lopdf::Object::Dictionary(catalog));
doc.trailer
.set("Root", lopdf::Object::Reference(catalog_id));
let mut buf = Vec::new();
doc.save_to(&mut buf).unwrap();
buf
}
#[test]
fn test_render_page_to_png_convenience() {
let bytes = make_test_pdf_bytes();
let dir = std::env::temp_dir().join("easypdf_render_lib_test");
let _ = std::fs::remove_dir_all(&dir);
let pdf_path = dir.join("test.pdf");
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(&pdf_path, &bytes).unwrap();
let output = dir.join("page_0.png");
render_page_to_png(&pdf_path, 0, &output, 72).unwrap();
assert!(output.exists());
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn test_render_all_pages_to_dir() {
let bytes = make_test_pdf_bytes();
let dir = std::env::temp_dir().join("easypdf_render_all_test");
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
let pdf_path = dir.join("test.pdf");
std::fs::write(&pdf_path, &bytes).unwrap();
let out_dir = dir.join("output");
let paths = render_all_pages_to_dir(&pdf_path, &out_dir, 72).unwrap();
assert_eq!(paths.len(), 1);
assert!(paths[0].exists());
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn test_render_page_in_memory() {
let bytes = make_test_pdf_bytes();
let dir = std::env::temp_dir().join("easypdf_render_mem_test");
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
let pdf_path = dir.join("test.pdf");
std::fs::write(&pdf_path, &bytes).unwrap();
let config = RenderConfig {
dpi: 72,
..RenderConfig::default()
};
let img = render_page(&pdf_path, 0, &config).unwrap();
assert!(img.width > 0);
assert!(img.height > 0);
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn test_default_backend_is_text() {
let backend = RenderBackend::default_backend();
assert_eq!(backend, RenderBackend::Text);
}
#[test]
fn test_backend_display() {
assert_eq!(RenderBackend::Text.to_string(), "text");
assert_eq!(RenderBackend::Pdfium.to_string(), "pdfium");
}
#[test]
fn test_text_backend_is_available() {
assert!(RenderBackend::Text.is_available());
}
#[test]
fn test_pdfium_backend_not_available_without_feature() {
#[cfg(not(feature = "pdfium"))]
assert!(!RenderBackend::Pdfium.is_available());
}
}