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}