use pdfium_render::prelude::*;
use crate::error::Pdf2MdError;
use crate::pipeline::render::get_pdfium;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct PageMediaBox {
pub page_num: usize,
pub width_pt: f32,
pub height_pt: f32,
pub rotation: i16,
pub cropbox: Option<(f32, f32, f32, f32)>,
}
pub fn extract_page_media_boxes_from_bytes(
pdf_bytes: &[u8],
password: Option<&str>,
) -> Result<Vec<PageMediaBox>, Pdf2MdError> {
let pdfium = get_pdfium()?;
let document = pdfium
.load_pdf_from_byte_slice(pdf_bytes, password)
.map_err(|e| Pdf2MdError::Internal(format!("Failed to open PDF for page geometry: {e}")))?;
extract_from_document(&document)
}
fn extract_from_document(document: &PdfDocument<'_>) -> Result<Vec<PageMediaBox>, Pdf2MdError> {
let mut out = Vec::with_capacity(document.pages().len() as usize);
for (idx0, page) in document.pages().iter().enumerate() {
let width_pt = page.width().value.max(1.0);
let height_pt = page.height().value.max(1.0);
let rotation = page.rotation().map(|r| match r {
PdfPageRenderRotation::None => 0,
PdfPageRenderRotation::Degrees90 => 90,
PdfPageRenderRotation::Degrees180 => 180,
PdfPageRenderRotation::Degrees270 => 270,
}).unwrap_or(0);
out.push(PageMediaBox {
page_num: idx0 + 1,
width_pt,
height_pt,
rotation,
cropbox: None,
});
}
Ok(out)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rejects_non_pdf() {
let err = extract_page_media_boxes_from_bytes(b"not-a-pdf", None);
assert!(err.is_err());
}
}