1use std::hash::{Hash, Hasher};
2use std::sync::Arc;
3
4use ecow::EcoVec;
5use typst_library::diag::SourceResult;
6use typst_library::engine::Engine;
7use typst_library::foundations::{Content, Output, Smart, StyleChain, Target};
8use typst_library::introspection::Introspector;
9use typst_library::layout::{Abs, Frame, Sides};
10use typst_library::model::{Document, DocumentInfo, Numbering};
11use typst_library::visualize::{Color, Paint};
12
13use crate::PagedIntrospector;
14
15#[derive(Debug, Clone)]
17pub struct PagedDocument {
18 pages: EcoVec<Page>,
19 info: DocumentInfo,
20 introspector: Arc<PagedIntrospector>,
21}
22
23impl PagedDocument {
24 pub fn new(pages: EcoVec<Page>, info: DocumentInfo) -> Self {
28 let introspector = PagedIntrospector::new(&pages);
29 Self { pages, info, introspector: Arc::new(introspector) }
30 }
31
32 pub fn pages(&self) -> &[Page] {
34 &self.pages
35 }
36
37 pub fn info_mut(&mut self) -> &mut DocumentInfo {
39 &mut self.info
40 }
41
42 pub fn introspector(&self) -> &Arc<PagedIntrospector> {
44 &self.introspector
45 }
46}
47
48impl Hash for PagedDocument {
49 fn hash<H: Hasher>(&self, state: &mut H) {
50 self.pages.hash(state);
53 self.info.hash(state);
54 }
55}
56
57impl Document for PagedDocument {
58 fn info(&self) -> &DocumentInfo {
59 &self.info
60 }
61}
62
63impl Output for PagedDocument {
64 fn introspector(&self) -> &dyn Introspector {
65 self.introspector.as_ref()
66 }
67
68 fn target() -> Target {
69 Target::Paged
70 }
71
72 fn create(
73 engine: &mut Engine,
74 content: &Content,
75 styles: StyleChain,
76 ) -> SourceResult<Self> {
77 crate::layout_document(engine, content, styles)
78 }
79}
80
81#[derive(Debug, Clone, Hash)]
83pub struct Page {
84 pub frame: Frame,
86 pub bleed: Sides<Abs>,
89 pub fill: Smart<Option<Paint>>,
98 pub numbering: Option<Numbering>,
100 pub supplement: Content,
102 pub number: u64,
105}
106
107impl Page {
108 pub fn fill_or_transparent(&self) -> Option<Paint> {
112 self.fill.clone().unwrap_or(None)
113 }
114
115 pub fn fill_or_white(&self) -> Option<Paint> {
119 self.fill.clone().unwrap_or_else(|| Some(Color::WHITE.into()))
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_paged_document_is_send_and_sync() {
129 fn ensure_send_and_sync<T: Send + Sync>() {}
130 ensure_send_and_sync::<PagedDocument>();
131 }
132}