#![cfg_attr(not(feature = "std"), no_std)]
#![deny(unsafe_code)]
#[cfg(not(feature = "std"))]
extern crate alloc;
pub mod iff;
pub mod error;
pub(crate) mod info;
#[path = "zp/mod.rs"]
#[allow(dead_code)]
pub(crate) mod zp_impl;
#[allow(dead_code)]
pub mod bzz_new;
#[path = "jb2_new.rs"]
pub mod jb2_new;
#[path = "iw44_new.rs"]
pub mod iw44_new;
pub mod djvu_document;
pub mod djvu_render;
pub mod text;
pub mod annotation;
pub mod metadata;
#[cfg(feature = "std")]
pub mod pdf;
#[cfg(feature = "tiff")]
pub mod tiff_export;
#[cfg(feature = "async")]
pub mod djvu_async;
#[cfg(feature = "image")]
pub mod image_compat;
#[cfg(feature = "std")]
pub mod ocr_export;
pub use error::{BzzError, DjVuError, IffError, Iw44Error, Jb2Error};
pub use djvu_document::{DjVuBookmark, DjVuDocument, DjVuPage, DocError};
pub use info::{PageInfo, Rotation};
#[doc(hidden)]
pub(crate) mod bitmap;
#[cfg(feature = "std")]
#[doc(hidden)]
pub mod document;
#[cfg(feature = "std")]
#[doc(hidden)]
pub mod iw44;
#[cfg(feature = "std")]
#[doc(hidden)]
pub mod jb2;
#[doc(hidden)]
pub(crate) mod pixmap;
#[cfg(feature = "std")]
#[doc(hidden)]
pub mod render;
#[cfg(feature = "std")]
#[doc(hidden)]
#[path = "zp_legacy/mod.rs"]
pub mod zp;
pub use bitmap::Bitmap;
pub use pixmap::{GrayPixmap, Pixmap};
#[cfg(feature = "std")]
pub use document::{Bookmark, TextLayer, TextZone, TextZoneKind};
#[cfg(feature = "std")]
pub use error::LegacyError as Error;
#[cfg(feature = "std")]
pub struct Document {
doc: document::Document,
}
#[cfg(feature = "std")]
impl Document {
pub fn open(path: impl AsRef<std::path::Path>) -> Result<Self, Error> {
let data = std::fs::read(path.as_ref())
.map_err(|e| Error::FormatError(format!("failed to read file: {}", e)))?;
Self::from_bytes(data)
}
pub fn from_reader(reader: impl std::io::Read) -> Result<Self, Error> {
let mut reader = reader;
let mut data = Vec::new();
reader
.read_to_end(&mut data)
.map_err(|e| Error::FormatError(format!("failed to read: {}", e)))?;
Self::from_bytes(data)
}
pub fn from_bytes(data: Vec<u8>) -> Result<Self, Error> {
let doc = document::Document::parse(&data)?;
Ok(Document { doc })
}
pub fn bookmarks(&self) -> Result<Vec<Bookmark>, Error> {
self.doc.bookmarks()
}
pub fn page_count(&self) -> usize {
self.doc.page_count()
}
pub fn page(&self, index: usize) -> Result<Page<'_>, Error> {
let inner = self.doc.page(index)?;
Ok(Page {
width: inner.info.width,
height: inner.info.height,
dpi: inner.info.dpi,
rotation: inner.info.rotation,
index,
doc: self,
})
}
}
#[cfg(feature = "std")]
pub struct Page<'a> {
width: u16,
height: u16,
dpi: u16,
rotation: document::Rotation,
index: usize,
doc: &'a Document,
}
#[cfg(feature = "std")]
impl<'a> Page<'a> {
pub fn width(&self) -> u32 {
self.width as u32
}
pub fn height(&self) -> u32 {
self.height as u32
}
pub fn display_width(&self) -> u32 {
match self.rotation {
document::Rotation::Cw90 | document::Rotation::Cw270 => self.height as u32,
_ => self.width as u32,
}
}
pub fn display_height(&self) -> u32 {
match self.rotation {
document::Rotation::Cw90 | document::Rotation::Cw270 => self.width as u32,
_ => self.height as u32,
}
}
pub fn dpi(&self) -> u16 {
self.dpi
}
pub fn index(&self) -> usize {
self.index
}
pub fn rotation(&self) -> document::Rotation {
self.rotation
}
pub fn decode_mask(&self) -> Result<Option<Bitmap>, Error> {
let page = self.doc.doc.page(self.index)?;
page.decode_mask()
}
pub fn render(&self) -> Result<Pixmap, Error> {
let page = self.doc.doc.page(self.index)?;
render::render(&page)
}
pub fn render_to_size(&self, width: u32, height: u32) -> Result<Pixmap, Error> {
let page = self.doc.doc.page(self.index)?;
render::render_to_size(&page, width, height)
}
pub fn render_bold(&self, dilate_passes: u32) -> Result<Pixmap, Error> {
let page = self.doc.doc.page(self.index)?;
render::render_to_size_bold(
&page,
page.info.width as u32,
page.info.height as u32,
dilate_passes,
)
}
pub fn render_to_size_bold(
&self,
width: u32,
height: u32,
dilate_passes: u32,
) -> Result<Pixmap, Error> {
let page = self.doc.doc.page(self.index)?;
render::render_to_size_bold(&page, width, height, dilate_passes)
}
pub fn render_aa(&self, width: u32, height: u32, boldness: f32) -> Result<Pixmap, Error> {
let page = self.doc.doc.page(self.index)?;
render::render_aa(&page, width, height, boldness)
}
pub fn thumbnail(&self) -> Result<Option<Pixmap>, Error> {
self.doc.doc.thumbnail(self.index)
}
pub fn text_layer(&self) -> Result<Option<TextLayer>, Error> {
let page = self.doc.doc.page(self.index)?;
page.text_layer()
}
pub fn text(&self) -> Result<Option<String>, Error> {
Ok(self.text_layer()?.map(|tl| tl.text))
}
pub fn render_scaled_coarse(&self, scale: f32) -> Result<Option<Pixmap>, Error> {
let dw = self.display_width();
let dh = self.display_height();
let w = ((dw as f32 * scale).round() as u32).max(1);
let h = ((dh as f32 * scale).round() as u32).max(1);
let (tw, th) = match self.rotation {
document::Rotation::Cw90 | document::Rotation::Cw270 => (h, w),
_ => (w, h),
};
let page = self.doc.doc.page(self.index)?;
render::render_to_size_coarse(&page, tw, th)
}
pub fn render_scaled_progressive(&self, scale: f32) -> Result<Vec<Pixmap>, Error> {
let dw = self.display_width();
let dh = self.display_height();
let w = ((dw as f32 * scale).round() as u32).max(1);
let h = ((dh as f32 * scale).round() as u32).max(1);
let (tw, th) = match self.rotation {
document::Rotation::Cw90 | document::Rotation::Cw270 => (h, w),
_ => (w, h),
};
let page = self.doc.doc.page(self.index)?;
render::render_to_size_progressive(&page, tw, th)
}
pub fn render_scaled(&self, scale: f32) -> Result<Pixmap, Error> {
let dw = self.display_width();
let dh = self.display_height();
let w = ((dw as f32 * scale).round() as u32).max(1);
let h = ((dh as f32 * scale).round() as u32).max(1);
let (tw, th) = match self.rotation {
document::Rotation::Cw90 | document::Rotation::Cw270 => (h, w),
_ => (w, h),
};
let page = self.doc.doc.page(self.index)?;
render::render_to_size(&page, tw, th)
}
}
#[cfg(feature = "std")]
#[allow(dead_code)]
const _: () = {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
fn assertions() {
assert_send::<Document>();
assert_sync::<Document>();
}
};