typst_library/visualize/image/
pdf.rs1use std::hash::{Hash, Hasher};
2use std::sync::Arc;
3
4use hayro_syntax::page::Page;
5use hayro_syntax::{LoadPdfError, Pdf};
6
7use crate::foundations::Bytes;
8
9#[derive(Clone, Hash)]
11pub struct PdfDocument(Arc<DocumentRepr>);
12
13struct DocumentRepr {
15 pdf: Arc<Pdf>,
16 data: Bytes,
17}
18
19impl PdfDocument {
20 #[comemo::memoize]
22 #[typst_macros::time(name = "load pdf document")]
23 pub fn new(data: Bytes) -> Result<PdfDocument, LoadPdfError> {
24 let pdf = Arc::new(Pdf::new(Arc::new(data.clone()))?);
25 Ok(Self(Arc::new(DocumentRepr { data, pdf })))
26 }
27
28 pub fn pdf(&self) -> &Arc<Pdf> {
30 &self.0.pdf
31 }
32
33 pub fn num_pages(&self) -> usize {
35 self.0.pdf.pages().len()
36 }
37}
38
39impl Hash for DocumentRepr {
40 fn hash<H: Hasher>(&self, state: &mut H) {
41 self.data.hash(state);
42 }
43}
44
45#[derive(Clone, Hash)]
47pub struct PdfImage(Arc<ImageRepr>);
48
49struct ImageRepr {
51 document: PdfDocument,
52 page_index: usize,
53 width: f32,
54 height: f32,
55}
56
57impl PdfImage {
58 #[comemo::memoize]
62 pub fn new(document: PdfDocument, page_index: usize) -> Option<PdfImage> {
63 let (width, height) = document.0.pdf.pages().get(page_index)?.render_dimensions();
64 Some(Self(Arc::new(ImageRepr { document, page_index, width, height })))
65 }
66
67 pub fn document(&self) -> &PdfDocument {
69 &self.0.document
70 }
71
72 pub fn page(&self) -> &Page<'_> {
74 &self.document().pdf().pages()[self.0.page_index]
75 }
76
77 pub fn width(&self) -> f32 {
79 self.0.width
80 }
81
82 pub fn height(&self) -> f32 {
84 self.0.height
85 }
86
87 pub fn page_index(&self) -> usize {
89 self.0.page_index
90 }
91}
92
93impl Hash for ImageRepr {
94 fn hash<H: Hasher>(&self, state: &mut H) {
95 self.document.hash(state);
96 self.page_index.hash(state);
97 }
98}