oxidize_pdf/
document.rs

1use crate::error::Result;
2use crate::objects::{Object, ObjectId};
3use crate::page::Page;
4use crate::writer::PdfWriter;
5use std::collections::HashMap;
6
7/// A PDF document that can contain multiple pages and metadata.
8/// 
9/// # Example
10/// 
11/// ```rust
12/// use oxidize_pdf::{Document, Page};
13/// 
14/// let mut doc = Document::new();
15/// doc.set_title("My Document");
16/// doc.set_author("John Doe");
17/// 
18/// let page = Page::a4();
19/// doc.add_page(page);
20/// 
21/// doc.save("output.pdf").unwrap();
22/// ```
23pub struct Document {
24    pub(crate) pages: Vec<Page>,
25    pub(crate) objects: HashMap<ObjectId, Object>,
26    pub(crate) next_object_id: u32,
27    pub(crate) metadata: DocumentMetadata,
28}
29
30/// Metadata for a PDF document.
31#[derive(Debug, Clone)]
32pub struct DocumentMetadata {
33    /// Document title
34    pub title: Option<String>,
35    /// Document author
36    pub author: Option<String>,
37    /// Document subject
38    pub subject: Option<String>,
39    /// Document keywords
40    pub keywords: Option<String>,
41    /// Software that created the original document
42    pub creator: Option<String>,
43    /// Software that produced the PDF
44    pub producer: Option<String>,
45}
46
47impl Default for DocumentMetadata {
48    fn default() -> Self {
49        Self {
50            title: None,
51            author: None,
52            subject: None,
53            keywords: None,
54            creator: Some("oxidize_pdf".to_string()),
55            producer: Some("oxidize_pdf".to_string()),
56        }
57    }
58}
59
60impl Document {
61    /// Creates a new empty PDF document.
62    pub fn new() -> Self {
63        Self {
64            pages: Vec::new(),
65            objects: HashMap::new(),
66            next_object_id: 1,
67            metadata: DocumentMetadata::default(),
68        }
69    }
70    
71    /// Adds a page to the document.
72    pub fn add_page(&mut self, page: Page) {
73        self.pages.push(page);
74    }
75    
76    /// Sets the document title.
77    pub fn set_title(&mut self, title: impl Into<String>) {
78        self.metadata.title = Some(title.into());
79    }
80    
81    /// Sets the document author.
82    pub fn set_author(&mut self, author: impl Into<String>) {
83        self.metadata.author = Some(author.into());
84    }
85    
86    /// Sets the document subject.
87    pub fn set_subject(&mut self, subject: impl Into<String>) {
88        self.metadata.subject = Some(subject.into());
89    }
90    
91    /// Sets the document keywords.
92    pub fn set_keywords(&mut self, keywords: impl Into<String>) {
93        self.metadata.keywords = Some(keywords.into());
94    }
95    
96    /// Saves the document to a file.
97    /// 
98    /// # Errors
99    /// 
100    /// Returns an error if the file cannot be created or written.
101    pub fn save(&mut self, path: impl AsRef<std::path::Path>) -> Result<()> {
102        let mut writer = PdfWriter::new(path)?;
103        writer.write_document(self)?;
104        Ok(())
105    }
106    
107    /// Writes the document to a buffer.
108    /// 
109    /// # Errors
110    /// 
111    /// Returns an error if the PDF cannot be generated.
112    pub fn write(&mut self, buffer: &mut Vec<u8>) -> Result<()> {
113        let mut writer = PdfWriter::new_with_writer(buffer);
114        writer.write_document(self)?;
115        Ok(())
116    }
117    
118    pub(crate) fn allocate_object_id(&mut self) -> ObjectId {
119        let id = ObjectId::new(self.next_object_id, 0);
120        self.next_object_id += 1;
121        id
122    }
123    
124    pub(crate) fn add_object(&mut self, obj: Object) -> ObjectId {
125        let id = self.allocate_object_id();
126        self.objects.insert(id, obj);
127        id
128    }
129}
130
131impl Default for Document {
132    fn default() -> Self {
133        Self::new()
134    }
135}