pdf_create/
common.rs

1//! Common structs and enums
2
3use std::{collections::BTreeMap, fmt, io, ops::{Add, Deref, DerefMut, Mul}};
4
5//use pdf::primitive::PdfString;
6
7use crate::write::{Formatter, PdfName, Serialize};
8
9/// A PDF Byte string
10#[derive(Clone, Eq, PartialEq)]
11pub struct PdfString(Vec<u8>);
12
13impl PdfString {
14    /// Create a new string
15    pub fn new<S: AsRef<[u8]>>(string: S) -> Self {
16        Self(string.as_ref().to_vec())
17    }
18}
19
20impl PdfString {
21    /// Get a slice to the contained bytes
22    pub fn as_bytes(&self) -> &[u8] {
23        self.0.as_ref()
24    }
25
26    /// Get the contained byte buffer
27    pub fn into_bytes(self) -> Vec<u8> {
28        self.0
29    }
30}
31
32impl fmt::Debug for PdfString {
33    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        todo!()
35    }
36}
37
38/// A reference to an object
39#[derive(Debug, Copy, Clone, PartialEq, Eq)]
40pub struct ObjRef {
41    /// The index within the file
42    pub id: u64,
43    /// The generation number 
44    pub gen: u16,
45}
46
47/// The base encoding for a font
48#[derive(Debug, Copy, Clone)]
49pub enum BaseEncoding {
50    /// `MacRomanEncoding`
51    MacRomanEncoding,
52    /// `WinAnsiEncoding`
53    WinAnsiEncoding,
54    /// `MacExpertEncoding`
55    MacExpertEncoding,
56}
57
58impl Serialize for BaseEncoding {
59    fn write(&self, f: &mut Formatter) -> io::Result<()> {
60        match self {
61            Self::MacRomanEncoding => PdfName("MacRomanEncoding").write(f),
62            Self::WinAnsiEncoding => PdfName("WinAnsiEncoding").write(f),
63            Self::MacExpertEncoding => PdfName("MacExpertEncoding").write(f),
64        }
65    }
66}
67
68/// The style of a page label number
69#[derive(Debug, Clone)]
70pub enum PageLabelKind {
71    /// Arabic decimal numerals (1, 2, 3, 4, …)
72    Decimal,
73    /// Lowercase roman numerals (i, ii, iii, iv, …)
74    RomanLower,
75    /// Uppercase roman numerals (I, II, III, IV, …)
76    RomanUpper,
77    /// Lowercase letters (a-z, aa-zz, …)
78    AlphaLower,
79    /// Lowercase letters (a-z, aa-zz, …)
80    AlphaUpper,
81}
82
83impl Serialize for PageLabelKind {
84    fn write(&self, f: &mut Formatter) -> io::Result<()> {
85        match self {
86            Self::Decimal => PdfName("D").write(f),
87            Self::RomanLower => PdfName("r").write(f),
88            Self::RomanUpper => PdfName("R").write(f),
89            Self::AlphaLower => PdfName("a").write(f),
90            Self::AlphaUpper => PdfName("A").write(f),
91        }
92    }
93}
94
95/// Specification for the labels of a sequence of pages
96#[derive(Debug, Clone)]
97pub struct PageLabel {
98    /// Fixed string prepended to every number
99    pub prefix: PdfString,
100    /// The style of the number
101    pub kind: Option<PageLabelKind>,
102    /// The value for the number on the first page of the group
103    pub start: u32,
104}
105
106impl Serialize for PageLabel {
107    fn write(&self, f: &mut Formatter) -> io::Result<()> {
108        let mut dict = f.pdf_dict();
109        dict.field("Type", &PdfName("PageLabel"))?;
110        dict.opt_field("S", &self.kind)?;
111        dict.field("St", &self.start)?;
112        if !self.prefix.as_bytes().is_empty() {
113            dict.field("P", &self.prefix)?;
114        }
115        dict.finish()
116    }
117}
118
119struct BTreeSer<'a, A, B>(&'a BTreeMap<A, B>);
120
121impl<'a, A, B> Serialize for BTreeSer<'a, A, B>
122where
123    A: Serialize,
124    B: Serialize,
125{
126    fn write(&self, f: &mut Formatter) -> io::Result<()> {
127        let mut arr = f.pdf_arr();
128        for (key, value) in self.0 {
129            arr.entry(key)?;
130            arr.entry(value)?;
131        }
132        arr.finish()
133    }
134}
135
136/// A tree of numbers
137pub struct NumberTree<T> {
138    inner: BTreeMap<usize, T>,
139}
140
141impl<T> Default for NumberTree<T> {
142    fn default() -> Self {
143        Self::new()
144    }
145}
146
147impl<T> From<BTreeMap<usize, T>> for NumberTree<T> {
148    fn from(tree: BTreeMap<usize, T>) -> Self {
149        Self { inner: tree }
150    }
151}
152
153impl<T> NumberTree<T> {
154    /// Creates a new tree
155    pub fn new() -> Self {
156        Self {
157            inner: BTreeMap::new(),
158        }
159    }
160
161    /// Checks whether the tree is empty
162    pub fn is_empty(&self) -> bool {
163        self.inner.is_empty()
164    }
165
166    /// Inserts a node into the tree
167    pub fn insert(&mut self, key: usize, value: T) -> Option<T> {
168        self.inner.insert(key, value)
169    }
170}
171
172impl<T: Serialize> Serialize for NumberTree<T> {
173    fn write(&self, f: &mut Formatter) -> io::Result<()> {
174        f.pdf_dict().field("Nums", &BTreeSer(&self.inner))?.finish()
175    }
176}
177
178#[derive(Debug, Clone)]
179/// A vector of options
180pub struct SparseSet<T> {
181    inner: Vec<Option<T>>,
182}
183
184impl<T> Default for SparseSet<T> {
185    fn default() -> Self {
186        Self::new()
187    }
188}
189
190impl<T> Deref for SparseSet<T> {
191    type Target = Vec<Option<T>>;
192
193    fn deref(&self) -> &Self::Target {
194        &self.inner
195    }
196}
197
198impl<T> DerefMut for SparseSet<T> {
199    fn deref_mut(&mut self) -> &mut Self::Target {
200        &mut self.inner
201    }
202}
203
204impl<T> SparseSet<T> {
205    /// Creates a new sparse set
206    pub fn new() -> Self {
207        Self { inner: vec![] }
208    }
209}
210
211impl<T: Clone> SparseSet<T> {
212    /// Creates a new set
213    pub fn with_size(size: usize) -> Self {
214        Self {
215            inner: vec![None; size],
216        }
217    }
218}
219
220impl<T: Serialize> Serialize for SparseSet<T> {
221    fn write(&self, f: &mut Formatter) -> io::Result<()> {
222        let mut arr = f.pdf_arr();
223        let mut needs_number = true;
224        for (index, entry) in self.inner.iter().enumerate() {
225            if let Some(value) = entry {
226                if needs_number {
227                    arr.entry(&index)?;
228                    needs_number = false;
229                }
230                arr.entry(value)?;
231            } else {
232                needs_number = true;
233            }
234        }
235        arr.finish()
236    }
237}
238
239/// A font encoding
240#[derive(Debug, Clone)]
241pub struct Encoding<'a> {
242    /// The base encoding
243    pub base_encoding: Option<BaseEncoding>,
244    /// The differences from the base encoding
245    pub differences: Option<SparseSet<PdfName<'a>>>,
246}
247
248impl Serialize for Encoding<'_> {
249    fn write(&self, f: &mut Formatter) -> io::Result<()> {
250        f.pdf_dict()
251            .field("Type", &PdfName("Encoding"))?
252            .opt_field("BaseEncoding", &self.base_encoding)?
253            .opt_field("Differences", &self.differences)?
254            .finish()
255    }
256}
257
258/// A simple two-dimensional coordinate
259#[derive(Debug, Copy, Clone)]
260pub struct Point<P> {
261    /// Horizontal offset
262    pub x: P,
263    /// Vertical offset
264    pub y: P,
265}
266
267impl<P: Default> Default for Point<P> {
268    fn default() -> Self {
269        Self {
270            x: P::default(),
271            y: P::default(),
272        }
273    }
274}
275
276/// A primitive rectangle
277#[derive(Debug, Copy, Clone)]
278pub struct Rectangle<P> {
279    /// lower left
280    pub ll: Point<P>,
281    /// upper right
282    pub ur: Point<P>,
283}
284
285impl Rectangle<i32> {
286    /// The media box for A4 Paper (Portrait)
287    pub fn a4_media_box() -> Self {
288        Rectangle {
289            ll: Point { x: 0, y: 0 },
290            ur: Point { x: 592, y: 842 },
291        }
292    }
293}
294
295impl<P: Serialize> Serialize for Rectangle<P> {
296    fn write(&self, f: &mut Formatter) -> io::Result<()> {
297        f.pdf_arr()
298            .entry(&self.ll.x)?
299            .entry(&self.ll.y)?
300            .entry(&self.ur.x)?
301            .entry(&self.ur.y)?
302            .finish()
303    }
304}
305
306/// A font matrix
307///
308/// <pre style="line-height: 120%;">
309/// ⎛ a b 0 ⎞
310/// ⎜ c d 0 ⎟
311/// ⎝ e f 1 ⎠
312/// </pre>
313#[derive(Debug, Copy, Clone, PartialEq, Eq)]
314pub struct Matrix<P> {
315    /// M<sub>1,1</sub>
316    pub a: P,
317    /// M<sub>1,2</sub>
318    pub b: P,
319    /// M<sub>2,1</sub>
320    pub c: P,
321    /// M<sub>2,2</sub>
322    pub d: P,
323    /// M<sub>3,1</sub>
324    pub e: P,
325    /// M<sub>3,2</sub>
326    pub f: P,
327}
328
329impl<P> Mul for Matrix<P>
330where
331    P: Copy + Mul<Output = P> + Add<Output = P>,
332{
333    type Output = Self;
334
335    fn mul(self, rhs: Self) -> Self::Output {
336        Self {
337            a: self.a * rhs.a + self.b * rhs.c,
338            b: self.a * rhs.b + self.b * rhs.d,
339            c: self.c * rhs.a + self.d * rhs.c,
340            d: self.c * rhs.b + self.d * rhs.d,
341            e: self.e * rhs.a + self.f * rhs.c + rhs.e,
342            f: self.e * rhs.b + self.f * rhs.d + rhs.f,
343        }
344    }
345}
346
347/// A matrix
348impl Matrix<f32> {
349    /// ```
350    /// use pdf_create::common::Matrix;
351    /// let id = Matrix::<f32>::identity();
352    /// assert_eq!(id, id * id);
353    /// ```
354    pub fn identity() -> Self {
355        Self::scale(1.0, 1.0)
356    }
357
358    /// ```
359    /// use pdf_create::common::Matrix;
360    /// let id = Matrix::<f32>::identity();
361    /// let ivy = Matrix::<f32>::inverse_y();
362    /// assert_eq!(ivy, ivy * id);
363    /// assert_eq!(id, ivy * ivy);
364    /// ```
365    pub fn inverse_y() -> Self {
366        Self::scale(1.0, -1.0)
367    }
368
369    /// ```
370    /// use pdf_create::common::Matrix;
371    /// let id = Matrix::<f32>::identity();
372    /// let ivx = Matrix::<f32>::inverse_x();
373    /// assert_eq!(ivx, ivx * id);
374    /// assert_eq!(id, ivx * ivx);
375    /// ```
376    pub fn inverse_x() -> Self {
377        Self::scale(-1.0, 1.0)
378    }
379
380    /// Inverts both coordinates
381    pub fn inverse_xy() -> Self {
382        Self::scale(-1.0, -1.0)
383    }
384
385    /// ```
386    /// use pdf_create::common::Matrix;
387    /// let ty1 = Matrix::<f32>::translate(0.0, 3.0);
388    /// let ty2 = Matrix::<f32>::translate(0.0, 5.0);
389    /// let tx1 = Matrix::<f32>::translate(2.0, 0.0);
390    /// let tx2 = Matrix::<f32>::translate(7.0, 0.0);
391    /// let res = Matrix::<f32>::translate(9.0, 8.0);
392    /// assert_eq!(res, ty1 * ty2 * tx1 * tx2);
393    /// assert_eq!(res, ty1 * tx2 * ty2 * tx1);
394    /// ```
395    pub fn translate(x: f32, y: f32) -> Self {
396        Self {
397            a: 1.0,
398            b: 0.0,
399            c: 0.0,
400            d: 1.0,
401            e: x,
402            f: y,
403        }
404    }
405
406    /// Create a scaling matrix
407    pub fn scale(x: f32, y: f32) -> Self {
408        Self {
409            a: x,
410            b: 0.0,
411            c: 0.0,
412            d: y,
413            e: 0.0,
414            f: 0.0,
415        }
416    }
417
418    /// Create a default 1:1000 glyph matrix
419    pub fn default_glyph() -> Self {
420        Self::scale(0.0001, 0.0001)
421    }
422}
423
424impl<P: Serialize> Serialize for Matrix<P> {
425    fn write(&self, f: &mut Formatter) -> io::Result<()> {
426        f.pdf_arr()
427            .entry(&self.a)?
428            .entry(&self.b)?
429            .entry(&self.c)?
430            .entry(&self.d)?
431            .entry(&self.e)?
432            .entry(&self.f)?
433            .finish()
434    }
435}
436
437/// A dict is a map from strings to a type P
438pub type Dict<P> = BTreeMap<String, P>;
439
440impl<P: Serialize> Serialize for Dict<P> {
441    fn write(&self, f: &mut Formatter) -> io::Result<()> {
442        let mut dict = f.pdf_dict();
443        for (key, value) in self {
444            dict.field(key, value)?;
445        }
446        dict.finish()
447    }
448}
449
450/// Valid `ProcSet`s for PDF files
451pub enum ProcSet {
452    /// General PDFs procs
453    PDF,
454    /// Text procs
455    Text,
456    /// Black/White Images
457    ImageB,
458    /// Color Images
459    ImageC,
460    /// TODO: Check Docs
461    ImageI,
462}
463
464impl Serialize for ProcSet {
465    fn write(&self, f: &mut Formatter) -> io::Result<()> {
466        match self {
467            Self::PDF => PdfName("PDF").write(f),
468            Self::Text => PdfName("Text").write(f),
469            Self::ImageB => PdfName("ImageB").write(f),
470            Self::ImageC => PdfName("ImageC").write(f),
471            Self::ImageI => PdfName("ImageI").write(f),
472        }
473    }
474}
475
476/// Indicates whether the PDF is trapped
477#[derive(Debug, PartialEq, Eq)]
478#[allow(missing_docs)]
479pub enum Trapped {
480    True,
481    False,
482    Unknown,
483}
484
485impl Default for Trapped {
486    fn default() -> Self {
487        Trapped::Unknown
488    }
489}
490
491impl Serialize for Trapped {
492    fn write(&self, _f: &mut Formatter) -> io::Result<()> {
493        todo!()
494    }
495}