use crate::{Dictionary, Document, Error, Object, ObjectId, Result};
#[derive(Debug, Clone)]
pub struct IncrementalDocument {
bytes_documents: Vec<u8>,
prev_documents: Document,
pub new_document: Document,
}
impl IncrementalDocument {
pub fn new() -> Self {
Self {
bytes_documents: Vec::new(),
prev_documents: Document::new(),
new_document: Document::new(),
}
}
pub fn create_from(prev_bytes: Vec<u8>, prev_documents: Document) -> Self {
Self {
bytes_documents: prev_bytes,
new_document: Document::new_from_prev(&prev_documents),
prev_documents,
}
}
pub fn get_prev_documents(&self) -> &Document {
&self.prev_documents
}
pub fn get_prev_documents_bytes(&self) -> &[u8] {
&self.bytes_documents
}
pub fn opt_clone_object_to_new_document(&mut self, object_id: ObjectId) -> Result<()> {
if !self.new_document.has_object(object_id) {
let old_object = self.prev_documents.get_object(object_id)?;
self.new_document.set_object(object_id, old_object.clone());
}
Ok(())
}
fn get_or_create_resources_mut(&mut self, page_id: ObjectId) -> Result<&mut Object> {
let page = self
.new_document
.get_object_mut(page_id)
.and_then(Object::as_dict_mut)?;
if page.has(b"Resources") {
if let Ok(_res_id) = page.get(b"Resources").and_then(Object::as_reference) {
Err(Error::ObjectNotFound)
} else {
page.get_mut(b"Resources")
}
} else {
page.set("Resources", Dictionary::new());
page.get_mut(b"Resources")
}
}
pub fn get_or_create_resources(&mut self, page_id: ObjectId) -> Result<&mut Object> {
self.opt_clone_object_to_new_document(page_id)?;
let resources_id = {
let page = self.new_document.get_object(page_id).and_then(Object::as_dict)?;
if page.has(b"Resources") {
page.get(b"Resources").and_then(Object::as_reference).ok()
} else {
None
}
};
match resources_id {
Some(res_id) => {
self.opt_clone_object_to_new_document(res_id)?;
self.new_document.get_object_mut(res_id)
}
None => self.get_or_create_resources_mut(page_id),
}
}
pub fn add_xobject<N: Into<Vec<u8>>>(
&mut self, page_id: ObjectId, xobject_name: N, xobject_id: ObjectId,
) -> Result<()> {
if let Ok(resources) = self.get_or_create_resources(page_id).and_then(Object::as_dict_mut) {
if !resources.has(b"XObject") {
resources.set("XObject", Dictionary::new());
}
let mut xobjects = resources.get_mut(b"XObject")?;
if let Object::Reference(xobjects_ref_id) = xobjects {
let mut xobjects_id = *xobjects_ref_id;
while let Object::Reference(id) = self.new_document.get_object(xobjects_id)? {
xobjects_id = *id;
}
xobjects = self.new_document.get_object_mut(xobjects_id)?;
}
let xobjects = Object::as_dict_mut(xobjects)?;
xobjects.set(xobject_name, Object::Reference(xobject_id));
}
Ok(())
}
pub fn add_graphics_state<N: Into<Vec<u8>>>(
&mut self, page_id: ObjectId, gs_name: N, gs_id: ObjectId,
) -> Result<()> {
if let Ok(resources) = self.get_or_create_resources(page_id).and_then(Object::as_dict_mut) {
if !resources.has(b"ExtGState") {
resources.set("ExtGState", Dictionary::new());
}
let states = resources.get_mut(b"ExtGState").and_then(Object::as_dict_mut)?;
states.set(gs_name, Object::Reference(gs_id));
}
Ok(())
}
}
impl Default for IncrementalDocument {
fn default() -> Self {
Self::new()
}
}