use super::prelude::*;
#[derive(Debug, Object, ObjectWrite, DataSize, Clone, DeepClone)]
pub struct PatternDict {
#[pdf(key = "PaintType")]
pub paint_type: Option<i32>,
#[pdf(key = "TilingType")]
pub tiling_type: Option<i32>,
#[pdf(key = "BBox")]
pub bbox: Rectangle,
#[pdf(key = "XStep")]
pub x_step: f32,
#[pdf(key = "YStep")]
pub y_step: f32,
#[pdf(key = "Resources")]
pub resources: Ref<Resources>,
#[pdf(key = "Matrix")]
pub matrix: Option<Matrix>,
}
#[derive(Debug, DataSize)]
pub enum Pattern {
Dict(PatternDict),
Stream(PatternDict, Vec<Op>),
}
impl Pattern {
pub fn dict(&self) -> &PatternDict {
match *self {
Pattern::Dict(ref d) => d,
Pattern::Stream(ref d, _) => d,
}
}
}
impl Object for Pattern {
fn from_primitive(p: Primitive, resolve: &impl Resolve) -> Result<Self> {
let p = p.resolve(resolve)?;
match p {
Primitive::Dictionary(dict) => {
Ok(Pattern::Dict(PatternDict::from_dict(dict, resolve)?))
}
Primitive::Stream(s) => {
let stream: Stream<PatternDict> = Stream::from_stream(s, resolve)?;
let data = stream.data(resolve)?;
let ops = t!(parse_ops(&data, resolve));
let dict = stream.info.info;
Ok(Pattern::Stream(dict, ops))
}
p => Err(PdfError::UnexpectedPrimitive {
expected: "Dictionary or Stream",
found: p.get_debug_name(),
}),
}
}
}
impl ObjectWrite for Pattern {
fn to_primitive(&self, update: &mut impl Updater) -> Result<Primitive> {
match self {
Pattern::Dict(ref d) => d.to_primitive(update),
Pattern::Stream(ref d, ref ops) => {
let data = serialize_ops(ops)?;
let stream = Stream::new_with_filters(d.clone(), &data, vec![])?;
stream.to_primitive(update)
}
}
}
}
impl DeepClone for Pattern {
fn deep_clone(&self, cloner: &mut impl Cloner) -> Result<Self> {
match *self {
Pattern::Dict(ref d) => Ok(Pattern::Dict(d.deep_clone(cloner)?)),
Pattern::Stream(ref dict, ref ops) => {
let old_resources = cloner.get(dict.resources)?;
let mut resources = Resources::default();
let ops: Vec<Op> = ops
.iter()
.map(|op| deep_clone_op(op, cloner, &old_resources, &mut resources))
.collect::<Result<Vec<_>>>()?;
let dict = PatternDict {
resources: cloner.create(resources)?.get_ref(),
..*dict
};
Ok(Pattern::Stream(dict, ops))
}
}
}
}