pdf/
encoding.rs

1use std::collections::HashMap;
2use istring::SmallString;
3use crate as pdf;
4use crate::object::{Object, Resolve, ObjectWrite, DeepClone};
5use crate::primitive::{Primitive, Dictionary};
6use crate::error::{Result};
7use datasize::DataSize;
8
9#[derive(Debug, Clone, DataSize)]
10pub struct Encoding {
11    pub base: BaseEncoding,
12    pub differences: HashMap<u32, SmallString>,
13}
14
15#[derive(Object, ObjectWrite, Debug, Clone, Eq, PartialEq, DataSize)]
16pub enum BaseEncoding {
17    StandardEncoding,
18    SymbolEncoding,
19    MacRomanEncoding,
20    WinAnsiEncoding,
21    MacExpertEncoding,
22    #[pdf(name = "Identity-H")]
23    IdentityH,
24    None,
25
26    #[pdf(other)]
27    Other(String),
28}
29impl Object for Encoding {
30    fn from_primitive(p: Primitive, resolve: &impl Resolve) -> Result<Self> {
31        match p {
32            name @ Primitive::Name(_) => { 
33                Ok(Encoding {
34                base: BaseEncoding::from_primitive(name, resolve)?,
35                differences: HashMap::new(),
36                })
37            }
38            Primitive::Dictionary(mut dict) => {
39                let base = match dict.remove("BaseEncoding") {
40                    Some(p) => BaseEncoding::from_primitive(p, resolve)?,
41                    None => BaseEncoding::None
42                };
43                let mut gid = 0;
44                let mut differences = HashMap::new();
45                if let Some(p) = dict.remove("Differences") {
46                    for part in p.resolve(resolve)?.into_array()? {
47                        match part {
48                            Primitive::Integer(code) => {
49                                gid = code as u32;
50                            }
51                            Primitive::Name(name) => {
52                                differences.insert(gid, name);
53                                gid += 1;
54                            }
55                            _ => bail!("Unknown part primitive in dictionary: {:?}", part),
56                        }
57                    }
58                }
59                Ok(Encoding { base, differences })
60            }
61            Primitive::Reference(r) => Self::from_primitive(resolve.resolve(r)?, resolve),
62            Primitive::Stream(s) => Self::from_primitive(Primitive::Dictionary(s.info), resolve),
63            _ => bail!("Unknown element: {:?}", p),
64        }
65    }
66}
67impl ObjectWrite for Encoding {
68    fn to_primitive(&self, update: &mut impl pdf::object::Updater) -> Result<Primitive> {
69        let base = self.base.to_primitive(update)?;
70        if self.differences.len() == 0 {
71            Ok(base)
72        } else {
73            let mut list = vec![];
74
75            let mut diff_list: Vec<_> = self.differences.iter().collect();
76            diff_list.sort();
77            let mut last = None;
78
79            for &(&gid, name) in diff_list.iter() {
80                if !last.map(|n| n + 1 == gid).unwrap_or(false) {
81                    list.push(Primitive::Integer(gid as i32));
82                }
83
84                list.push(Primitive::Name(name.clone()));
85
86                last = Some(gid);
87            }
88
89            let mut dict = Dictionary::new();
90            dict.insert("BaseEncoding", base);
91            dict.insert("Differences", Primitive::Array(list));
92            Ok(Primitive::Dictionary(dict))
93        }
94    }
95}
96impl Encoding {
97    pub fn standard() -> Encoding {
98        Encoding {
99            base: BaseEncoding::StandardEncoding,
100            differences: HashMap::new()
101        }
102    }
103}
104impl DeepClone for Encoding {
105    fn deep_clone(&self, cloner: &mut impl pdf::object::Cloner) -> Result<Self> {
106        Ok(self.clone())
107    }
108}