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.new_document.get_object(page_id).and_then(Object::as_dict)?;
67 if page.has(b"Resources") {
68 page.get(b"Resources").and_then(Object::as_reference).ok()
69 } else {
70 None
71 }
72 };
73 if let Some(res_id) = resources_id {
74 self.opt_clone_object_to_new_document(res_id)?;
75 return self.new_document.get_object_mut(res_id);
76 }
77 let page = self
78 .new_document
79 .get_object_mut(page_id)
80 .and_then(Object::as_dict_mut)?;
81 if !page.has(b"Resources") {
82 page.set(b"Resources", Dictionary::new());
83 }
84 page.get_mut(b"Resources")
85 }
86
87 pub fn add_xobject<N: Into<Vec<u8>>>(
91 &mut self, page_id: ObjectId, xobject_name: N, xobject_id: ObjectId,
92 ) -> Result<()> {
93 if let Ok(resources) = self.get_or_create_resources(page_id).and_then(Object::as_dict_mut) {
94 if !resources.has(b"XObject") {
95 resources.set("XObject", Dictionary::new());
96 }
97 let mut xobjects = resources.get_mut(b"XObject")?;
98 if let Object::Reference(xobjects_ref_id) = xobjects {
99 let mut xobjects_id = *xobjects_ref_id;
100 while let Object::Reference(id) = self.new_document.get_object(xobjects_id)? {
101 xobjects_id = *id;
102 }
103 xobjects = self.new_document.get_object_mut(xobjects_id)?;
104 }
105 let xobjects = Object::as_dict_mut(xobjects)?;
106 xobjects.set(xobject_name, Object::Reference(xobject_id));
107 }
108 Ok(())
109 }
110
111 pub fn add_graphics_state<N: Into<Vec<u8>>>(
115 &mut self, page_id: ObjectId, gs_name: N, gs_id: ObjectId,
116 ) -> Result<()> {
117 if let Ok(resources) = self.get_or_create_resources(page_id).and_then(Object::as_dict_mut) {
118 if !resources.has(b"ExtGState") {
119 resources.set("ExtGState", Dictionary::new());
120 }
121 let states = resources.get_mut(b"ExtGState").and_then(Object::as_dict_mut)?;
122 states.set(gs_name, Object::Reference(gs_id));
123 }
124 Ok(())
125 }
126}
127
128impl Default for IncrementalDocument {
129 fn default() -> Self {
130 Self::new()
131 }
132}