use crate::{image_xobject::ImageXObject, rectangle::Rectangle, Error, InsertImage};
use lopdf::{
content::{Content, Operation},
ObjectId,
};
use std::io::Read;
#[allow(dead_code)]
pub trait InsertImageToPage: InsertImage {
fn add_xobject<N: Into<Vec<u8>>>(
&mut self,
page_id: ObjectId,
xobject_name: N,
xobject_id: ObjectId,
) -> Result<(), Error>;
fn opt_clone_object_to_new_document(&mut self, object_id: ObjectId) -> Result<(), Error>;
fn add_to_page_content(
&mut self,
page_id: ObjectId,
content: Content<Vec<Operation>>,
) -> Result<(), Error>;
fn add_image<R: Read>(
&mut self,
image_reader: R,
image_name: &str,
page_id: ObjectId,
rect: Rectangle,
) -> Result<ObjectId, Error> {
let image_decoder = png::Decoder::new(image_reader);
let (mut image_xobject, mask_xobject) = ImageXObject::try_from(image_decoder)?;
if let Some(mask_xobject) = mask_xobject {
let mask_xobject_id = self.add_object(mask_xobject);
image_xobject.s_mask = Some(mask_xobject_id);
}
let image_xobject_id = self.add_object(image_xobject);
self.add_xobject(page_id, image_name, image_xobject_id)?;
self.add_image_to_page_stream(image_name, page_id, rect)?;
Ok(image_xobject_id)
}
fn add_image_to_page_only(
&mut self,
image_xobject_id: ObjectId,
image_name: &str,
page_id: ObjectId,
rect: Rectangle,
) -> Result<ObjectId, Error> {
self.add_xobject(page_id, image_name, image_xobject_id)?;
self.add_image_to_page_stream(image_name, page_id, rect)?;
Ok(image_xobject_id)
}
fn add_image_to_page_stream(
&mut self,
xobject_name: &str,
page_id: ObjectId,
rect: Rectangle,
) -> Result<(), Error> {
use lopdf::Object::*;
let mut content = Content {
operations: Vec::<Operation>::new(),
};
let position = (rect.x1, rect.y1);
let size = (rect.x2 - rect.x1, rect.y2 - rect.y1);
content.operations.push(Operation::new("q", vec![]));
content.operations.push(Operation::new(
"cm",
vec![
size.0.into(),
0i32.into(),
0i32.into(),
size.1.into(),
position.0.into(),
position.1.into(),
],
));
content.operations.push(Operation::new(
"Do",
vec![Name(xobject_name.as_bytes().to_vec())],
));
content.operations.push(Operation::new("Q", vec![]));
self.opt_clone_object_to_new_document(page_id)?;
self.add_to_page_content(page_id, content)?;
Ok(())
}
}