Skip to content

Commit

Permalink
Optionify password params and put displaying stuff behind feature (#13)
Browse files Browse the repository at this point in the history
* what the action doing?

* action

* Update rust.yml

* hopefully works ™️

* github actions runs my code (and not me)

* no more C_NULL

* hopefully fix again

* GitHub runs my code (and not me) P:2

* GitHub actions
assisted refactoring (GAAR)

* also build crate in release mode in CI

* Revert rust.yml

* Change expect messages

* Change version to `0.4.0`

* make rendering stuff behind a `render` feature

* Why was that there LOL

* fix tests failing when render feature is not enabled

* Clean code a little bit

---------

Co-authored-by: RealPacket <never>
  • Loading branch information
RealPacket committed Jan 11, 2024
1 parent 5461041 commit 84e0d87
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 27 deletions.
15 changes: 10 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
[package]
authors = ["Marc Brinkmann <git@marcbrinkmann.de>",
"Denys Vitali <denys@denv.it>"]
authors = [
"Marc Brinkmann <git@marcbrinkmann.de>",
"Denys Vitali <denys@denv.it>",
]
name = "poppler"
license = "GPL-2.0"
version = "0.3.2"
version = "0.4.0"
description = "Wrapper for the GPL-licensed Poppler PDF rendering library."
repository = "https://github.com/DMSrs/poppler-rs"
edition = "2018"

[features]
render = ["dep:cairo-rs"]

[dependencies]
cairo-rs = { version = "0.15", features = ["png", "pdf"] }
glib = "0.15"
cairo-rs = { version = "0.18.5", features = ["png", "pdf"], optional = true }
glib = "0.18.5"
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# poppler-rs

[![poppler](https://img.shields.io/crates/v/poppler.svg)](https://crates.io/crates/poppler)
[![Documentation](https://img.shields.io/static/v1.svg?label=documentation&message=docs.rs&color=blue)](https://docs.rs/poppler/*/poppler/)

[libpoppler](https://poppler.freedesktop.org/) is a library for rendering PDF files, this are Rust bindings to it. It uses [cairo](https://crates.io/crates/cairo-rs) for rendering, as a result PDF content can be drawn onto a number of surfaces, including SVG, PDF or PNG.
[libpoppler](https://poppler.freedesktop.org/) is a library for rendering PDF files,
this crate is Rust bindings to it.

It uses [cairo](https://crates.io/crates/cairo-rs) for rendering,
as a result PDF content can be drawn onto a number of surfaces, including SVG, PDF or PNG.

**Warning**: libpoppler is based on the GPL-licensed [xpdf-3.0](http://www.foolabs.com/xpdf/) and is unlikely to ever be released under a different license. As a result, every program or library linking against this crate *must* be GPL licensed as well.
> [!WARNING]
> libpoppler is based on the GPL-licensed [xpdf-3.0](http://www.foolabs.com/xpdf/)
> and is unlikely to ever be released under a different license.
> As a result, every program or library linking against this crate *must* be GPL licensed as well.
The crate has only been tested on Linux; ensure that `libpoppler-glib` is installed to use it.
9 changes: 8 additions & 1 deletion src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,15 @@ extern "C" {
width: *mut c_double,
height: *mut c_double,
);

#[cfg(feature = "render")]
pub fn poppler_page_render(page: *mut PopplerPage, cairo: *mut cairo::ffi::cairo_t);
pub fn poppler_page_render_for_printing(page: *mut PopplerPage, cairo: *mut cairo::ffi::cairo_t);

#[cfg(feature = "render")]
pub fn poppler_page_render_for_printing(
page: *mut PopplerPage,
cairo: *mut cairo::ffi::cairo_t,
);

pub fn poppler_page_get_text(page: *mut PopplerPage) -> *mut c_char;
}
68 changes: 49 additions & 19 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ pub struct PopplerPage(*mut ffi::PopplerPage);
impl PopplerDocument {
pub fn new_from_file<P: AsRef<path::Path>>(
p: P,
password: &str,
password: Option<&str>,
) -> Result<PopplerDocument, glib::error::Error> {
let pw = CString::new(password).map_err(|_| {
let pw = CString::new(if password.is_none() {
""
} else {
password.expect("password.is_none() is false, but apparently it's lying.")
})
.map_err(|_| {
glib::error::Error::new(
glib::FileError::Inval,
"Password invalid (possibly contains NUL characters)",
Expand All @@ -33,15 +38,20 @@ impl PopplerDocument {
}
pub fn new_from_data(
data: &mut [u8],
password: &str,
password: Option<&str>,
) -> Result<PopplerDocument, glib::error::Error> {
if data.is_empty() {
return Err(glib::error::Error::new(
glib::FileError::Inval,
"data is empty",
));
}
let pw = CString::new(password).map_err(|_| {
let pw = CString::new(if password.is_none() {
""
} else {
password.expect("password.is_none() is false, but apparently it's lying.")
})
.map_err(|_| {
glib::error::Error::new(
glib::FileError::Inval,
"Password invalid (possibly contains NUL characters)",
Expand Down Expand Up @@ -123,11 +133,13 @@ impl PopplerPage {
(width, height)
}

#[cfg(feature = "render")]
pub fn render(&self, ctx: &cairo::Context) {
let ctx_raw = ctx.to_raw_none();
unsafe { ffi::poppler_page_render(self.0, ctx_raw) }
}

#[cfg(feature = "render")]
pub fn render_for_printing(&self, ctx: &cairo::Context) {
let ctx_raw = ctx.to_raw_none();
unsafe { ffi::poppler_page_render_for_printing(self.0, ctx_raw) }
Expand All @@ -145,46 +157,56 @@ impl PopplerPage {
mod tests {
use crate::PopplerDocument;
use crate::PopplerPage;
#[cfg(feature = "render")]
use cairo::Context;
#[cfg(feature = "render")]
use cairo::Format;
#[cfg(feature = "render")]
use cairo::ImageSurface;
use std::{fs::File, io::Read};

#[test]
fn test1() {
let filename = "test.pdf";
let doc = PopplerDocument::new_from_file(filename, "").unwrap();
let doc = PopplerDocument::new_from_file(filename, None).unwrap();
let num_pages = doc.get_n_pages();

println!("Document has {} page(s)", num_pages);

#[cfg(feature = "render")]
let surface = cairo::PdfSurface::new(420.0, 595.0, "output.pdf").unwrap();
#[cfg(feature = "render")]
let ctx = Context::new(&surface).unwrap();

// FIXME: move iterator to poppler
for page_num in 0..num_pages {
let page = doc.get_page(page_num).unwrap();
let (w, h) = page.get_size();
println!("page {} has size {}, {}", page_num, w, h);
surface.set_size(w, h).unwrap();

ctx.save().unwrap();
page.render(&ctx);
#[cfg(feature = "render")]
(|page: &PopplerPage, ctx: &Context| {
surface.set_size(w, h).unwrap();
ctx.save().unwrap();
page.render(ctx);
})(&page, &ctx);

println!("Text: {:?}", page.get_text().unwrap_or(""));

ctx.restore().unwrap();
ctx.show_page().unwrap();
#[cfg(feature = "render")]
(|ctx: &Context| {
ctx.restore().unwrap();
ctx.show_page().unwrap();
})(&ctx);
}
// g_object_unref (page);
//surface.write_to_png("file.png");
#[cfg(feature = "render")]
surface.finish();
}

#[test]
fn test2_from_file() {
let path = "test.pdf";
let doc: PopplerDocument = PopplerDocument::new_from_file(path, "upw").unwrap();
let doc: PopplerDocument = PopplerDocument::new_from_file(path, Some("upw")).unwrap();
let num_pages = doc.get_n_pages();
let title = doc.get_title().unwrap();
let metadata = doc.get_metadata();
Expand All @@ -208,15 +230,22 @@ mod tests {

assert_eq!(title, "This is a test PDF file");

#[cfg(feature = "render")]
let surface = ImageSurface::create(Format::ARgb32, w as i32, h as i32).unwrap();
#[cfg(feature = "render")]
let ctx = Context::new(&surface).unwrap();

ctx.save().unwrap();
page.render(&ctx);
ctx.restore().unwrap();
ctx.show_page().unwrap();
#[cfg(feature = "render")]
(|page: &PopplerPage, ctx: &Context| {
ctx.save().unwrap();
page.render(ctx);
ctx.restore().unwrap();
ctx.show_page().unwrap();
})(&page, &ctx);

#[cfg(feature = "render")]
let mut f: File = File::create("out.png").unwrap();
#[cfg(feature = "render")]
surface.write_to_png(&mut f).expect("Unable to write PNG");
}
#[test]
Expand All @@ -225,7 +254,8 @@ mod tests {
let mut file = File::open(path).unwrap();
let mut data: Vec<u8> = Vec::new();
file.read_to_end(&mut data).unwrap();
let doc: PopplerDocument = PopplerDocument::new_from_data(&mut data[..], "upw").unwrap();
let doc: PopplerDocument =
PopplerDocument::new_from_data(&mut data[..], Some("upw")).unwrap();
let num_pages = doc.get_n_pages();
let title = doc.get_title().unwrap();
let metadata = doc.get_metadata();
Expand All @@ -252,6 +282,6 @@ mod tests {
fn test3() {
let mut data = vec![];

assert!(PopplerDocument::new_from_data(&mut data[..], "upw").is_err());
assert!(PopplerDocument::new_from_data(&mut data[..], Some("upw")).is_err());
}
}

0 comments on commit 84e0d87

Please sign in to comment.