use std::sync::Arc;
use pdfrum_common::PageIndex;
use crate::{
Annotation, Document, Page, PageImage, PageLink, Pixmap, RasterBackend, RenderOptions,
RenderSession, Result, Rotation, TextPage, Word,
};
#[derive(Debug, Clone)]
pub struct OwnedPage {
doc: Arc<Document>,
page: PageRecord,
}
#[derive(Debug, Clone)]
struct PageRecord {
dict: Arc<pdfrum_parser::PageDict>,
index: PageIndex,
media_box: kurbo::Rect,
crop_box: kurbo::Rect,
rotation: Rotation,
}
impl OwnedPage {
pub(crate) fn load(doc: &Arc<Document>, index: PageIndex) -> Result<OwnedPage> {
let page = doc.page(index)?;
Ok(OwnedPage {
page: PageRecord {
dict: page.dict,
index: page.index,
media_box: page.media_box,
crop_box: page.crop_box,
rotation: page.rotation,
},
doc: Arc::clone(doc),
})
}
fn page(&self) -> Page<'_> {
Page {
doc: &self.doc,
dict: Arc::clone(&self.page.dict),
index: self.page.index,
media_box: self.page.media_box,
crop_box: self.page.crop_box,
rotation: self.page.rotation,
}
}
#[must_use]
pub fn document(&self) -> &Arc<Document> {
&self.doc
}
#[must_use]
pub fn index(&self) -> PageIndex {
self.page.index
}
#[must_use]
pub fn width(&self) -> f64 {
self.page().width()
}
#[must_use]
pub fn height(&self) -> f64 {
self.page().height()
}
#[must_use]
pub fn media_box(&self) -> kurbo::Rect {
self.page.media_box
}
#[must_use]
pub fn crop_box(&self) -> kurbo::Rect {
self.page.crop_box
}
#[must_use]
pub fn bleed_box(&self) -> Option<kurbo::Rect> {
self.page().bleed_box()
}
#[must_use]
pub fn trim_box(&self) -> Option<kurbo::Rect> {
self.page().trim_box()
}
#[must_use]
pub fn art_box(&self) -> Option<kurbo::Rect> {
self.page().art_box()
}
#[must_use]
pub fn rotation(&self) -> Rotation {
self.page.rotation
}
pub fn render<B: RasterBackend>(&self, backend: &B, options: &RenderOptions) -> Result<Pixmap> {
self.page().render(backend, options)
}
pub fn render_on<B: RasterBackend>(
&self,
backend: &B,
options: &RenderOptions,
session: &mut RenderSession,
) -> Result<Pixmap> {
self.page().render_on(backend, options, session)
}
#[must_use]
pub fn text(&self) -> TextPage {
self.page().text()
}
#[must_use]
pub fn text_on(&self, session: &mut RenderSession) -> TextPage {
self.page().text_on(session)
}
#[must_use]
pub fn words(&self) -> Vec<Word> {
self.page().words()
}
#[must_use]
pub fn annotations(&self) -> Vec<Annotation<'_>> {
self.page().annotations()
}
#[must_use]
pub fn links(&self) -> Vec<pdfrum_doc::Link> {
self.page().links()
}
#[must_use]
pub fn page_links(&self) -> Vec<PageLink> {
self.page().page_links()
}
#[must_use]
pub fn images(&self) -> Vec<PageImage> {
self.page().images()
}
#[must_use]
pub fn structure(&self) -> Option<pdfrum_doc::structure::StructTree> {
self.page().structure()
}
#[cfg(feature = "markdown")]
#[must_use]
pub fn markdown(&self) -> String {
self.page().markdown()
}
#[cfg(feature = "markdown")]
#[must_use]
pub fn markdown_blocks(&self) -> Vec<crate::Block> {
self.page().markdown_blocks()
}
#[cfg(feature = "markdown")]
#[must_use]
pub fn layout_text(&self) -> String {
self.page().layout_text()
}
}
impl Document {
pub fn page_owned(self: &Arc<Self>, index: impl Into<PageIndex>) -> Result<OwnedPage> {
OwnedPage::load(self, index.into())
}
pub fn pages_owned(self: &Arc<Self>) -> impl Iterator<Item = Result<OwnedPage>> + 'static {
let doc = Arc::clone(self);
(0..self.page_count()).map(move |index| doc.page_owned(index))
}
}