pdfluent_lopdf/
incremental_document.rs1use crate::{Dictionary, Document, Object, ObjectId, Result};
2
3#[derive(Debug, Clone)]
4pub struct IncrementalDocument {
5 bytes_documents: Vec<u8>,
7
8 prev_documents: Document,
11
12 pub new_document: Document,
14}
15
16impl IncrementalDocument {
17 pub fn new() -> Self {
19 Self {
20 bytes_documents: Vec::new(),
21 prev_documents: Document::new(),
22 new_document: Document::new(),
23 }
24 }
25
26 pub fn create_from(prev_bytes: Vec<u8>, prev_documents: Document) -> Self {
31 Self {
32 bytes_documents: prev_bytes,
33 new_document: Document::new_from_prev(&prev_documents),
34 prev_documents,
35 }
36 }
37
38 pub fn get_prev_documents(&self) -> &Document {
40 &self.prev_documents
41 }
42
43 pub fn get_prev_documents_bytes(&self) -> &[u8] {
45 &self.bytes_documents
46 }
47
48 pub fn opt_clone_object_to_new_document(&mut self, object_id: ObjectId) -> Result<()> {
53 if !self.new_document.has_object(object_id) {
54 let old_object = self.prev_documents.get_object(object_id)?;
55 self.new_document.set_object(object_id, old_object.clone());
56 }
57 Ok(())
58 }
59
60 pub fn get_or_create_resources(&mut self, page_id: ObjectId) -> Result<&mut Object> {
64 self.opt_clone_object_to_new_document(page_id)?;
65 let resources_id = {
66 let page = self
67 .new_document
68 .get_object(page_id)
69 .and_then(Object::as_dict)?;
70 if page.has(b"Resources") {
71 page.get(b"Resources").and_then(Object::as_reference).ok()
72 } else {
73 None
74 }
75 };
76 if let Some(res_id) = resources_id {
77 self.opt_clone_object_to_new_document(res_id)?;
78 return self.new_document.get_object_mut(res_id);
79 }
80 let page = self
81 .new_document
82 .get_object_mut(page_id)
83 .and_then(Object::as_dict_mut)?;
84 if !page.has(b"Resources") {
85 page.set(b"Resources", Dictionary::new());
86 }
87 page.get_mut(b"Resources")
88 }
89
90 pub fn add_xobject<N: Into<Vec<u8>>>(
94 &mut self,
95 page_id: ObjectId,
96 xobject_name: N,
97 xobject_id: ObjectId,
98 ) -> Result<()> {
99 if let Ok(resources) = self
100 .get_or_create_resources(page_id)
101 .and_then(Object::as_dict_mut)
102 {
103 if !resources.has(b"XObject") {
104 resources.set("XObject", Dictionary::new());
105 }
106 let mut xobjects = resources.get_mut(b"XObject")?;
107 if let Object::Reference(xobjects_ref_id) = xobjects {
108 let mut xobjects_id = *xobjects_ref_id;
109 while let Object::Reference(id) = self.new_document.get_object(xobjects_id)? {
110 xobjects_id = *id;
111 }
112 xobjects = self.new_document.get_object_mut(xobjects_id)?;
113 }
114 let xobjects = Object::as_dict_mut(xobjects)?;
115 xobjects.set(xobject_name, Object::Reference(xobject_id));
116 }
117 Ok(())
118 }
119
120 pub fn add_graphics_state<N: Into<Vec<u8>>>(
124 &mut self,
125 page_id: ObjectId,
126 gs_name: N,
127 gs_id: ObjectId,
128 ) -> Result<()> {
129 if let Ok(resources) = self
130 .get_or_create_resources(page_id)
131 .and_then(Object::as_dict_mut)
132 {
133 if !resources.has(b"ExtGState") {
134 resources.set("ExtGState", Dictionary::new());
135 }
136 let states = resources
137 .get_mut(b"ExtGState")
138 .and_then(Object::as_dict_mut)?;
139 states.set(gs_name, Object::Reference(gs_id));
140 }
141 Ok(())
142 }
143}
144
145impl Default for IncrementalDocument {
146 fn default() -> Self {
147 Self::new()
148 }
149}