pdf_writer/
object.rs

1use std::convert::TryFrom;
2use std::marker::PhantomData;
3use std::mem::ManuallyDrop;
4use std::num::NonZeroI32;
5
6use super::*;
7
8/// A primitive PDF object.
9pub trait Primitive {
10    /// Write the object into a buffer.
11    fn write(self, buf: &mut Vec<u8>);
12}
13
14impl<T: Primitive> Primitive for &T
15where
16    T: Copy,
17{
18    #[inline]
19    fn write(self, buf: &mut Vec<u8>) {
20        (*self).write(buf);
21    }
22}
23
24impl Primitive for bool {
25    #[inline]
26    fn write(self, buf: &mut Vec<u8>) {
27        if self {
28            buf.extend(b"true");
29        } else {
30            buf.extend(b"false");
31        }
32    }
33}
34
35impl Primitive for i32 {
36    #[inline]
37    fn write(self, buf: &mut Vec<u8>) {
38        buf.push_int(self);
39    }
40}
41
42impl Primitive for f32 {
43    #[inline]
44    fn write(self, buf: &mut Vec<u8>) {
45        buf.push_float(self);
46    }
47}
48
49/// A string object (any byte sequence).
50///
51/// This is written as `(Thing)`.
52#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
53pub struct Str<'a>(pub &'a [u8]);
54
55impl Str<'_> {
56    /// Whether the parentheses in the byte string are balanced.
57    fn is_balanced(self) -> bool {
58        let mut depth = 0;
59        for &byte in self.0 {
60            match byte {
61                b'(' => depth += 1,
62                b')' if depth > 0 => depth -= 1,
63                b')' => return false,
64                _ => {}
65            }
66        }
67        depth == 0
68    }
69}
70
71impl Primitive for Str<'_> {
72    fn write(self, buf: &mut Vec<u8>) {
73        // We use:
74        // - Literal strings for ASCII with nice escape sequences to make it
75        //   also be represented fully in visible ASCII. We also escape
76        //   parentheses because they are delimiters.
77        // - Hex strings for anything non-ASCII.
78        if self.0.iter().all(|b| b.is_ascii()) {
79            buf.reserve(self.0.len());
80            buf.push(b'(');
81
82            let mut balanced = None;
83            for &byte in self.0 {
84                match byte {
85                    b'(' | b')' => {
86                        if !*balanced
87                            .get_or_insert_with(|| byte != b')' && self.is_balanced())
88                        {
89                            buf.push(b'\\');
90                        }
91                        buf.push(byte);
92                    }
93                    b'\\' => buf.extend(br"\\"),
94                    b' '..=b'~' => buf.push(byte),
95                    b'\n' => buf.extend(br"\n"),
96                    b'\r' => buf.extend(br"\r"),
97                    b'\t' => buf.extend(br"\t"),
98                    b'\x08' => buf.extend(br"\b"),
99                    b'\x0c' => buf.extend(br"\f"),
100                    _ => {
101                        buf.push(b'\\');
102                        buf.push_octal(byte);
103                    }
104                }
105            }
106
107            buf.push(b')');
108        } else {
109            buf.reserve(2 + 2 * self.0.len());
110            buf.push(b'<');
111
112            for &byte in self.0 {
113                buf.push_hex(byte);
114            }
115
116            buf.push(b'>');
117        }
118    }
119}
120
121/// A unicode text string object.
122///
123/// This is written as a [`Str`] containing either bare ASCII (if possible) or a
124/// byte order mark followed by UTF-16-BE bytes.
125#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
126pub struct TextStr<'a>(pub &'a str);
127
128impl Primitive for TextStr<'_> {
129    fn write(self, buf: &mut Vec<u8>) {
130        // ASCII and PDFDocEncoding match for 32 up to 126.
131        if self.0.bytes().all(|b| matches!(b, 32..=126)) {
132            Str(self.0.as_bytes()).write(buf);
133        } else {
134            buf.reserve(6 + 4 * self.0.len());
135            buf.push(b'<');
136            buf.push_hex(254);
137            buf.push_hex(255);
138            for value in self.0.encode_utf16() {
139                buf.push_hex_u16(value);
140            }
141            buf.push(b'>');
142        }
143    }
144}
145
146/// A name object.
147///
148/// Written as `/Thing`.
149#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
150pub struct Name<'a>(pub &'a [u8]);
151
152impl Primitive for Name<'_> {
153    fn write(self, buf: &mut Vec<u8>) {
154        buf.reserve(1 + self.0.len());
155        buf.push(b'/');
156        for &byte in self.0 {
157            // - Number sign shall use hexadecimal escape
158            // - Regular characters within the range exlacamation mark .. tilde
159            //   can be written directly
160            if byte != b'#' && matches!(byte, b'!'..=b'~') && is_regular_character(byte) {
161                buf.push(byte);
162            } else {
163                buf.push(b'#');
164                buf.push_hex(byte);
165            }
166        }
167    }
168}
169
170/// Regular characters are a PDF concept.
171fn is_regular_character(byte: u8) -> bool {
172    !matches!(
173        byte,
174        b'\0'
175            | b'\t'
176            | b'\n'
177            | b'\x0C'
178            | b'\r'
179            | b' '
180            | b'('
181            | b')'
182            | b'<'
183            | b'>'
184            | b'['
185            | b']'
186            | b'{'
187            | b'}'
188            | b'/'
189            | b'%'
190    )
191}
192
193/// The null object.
194#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
195pub struct Null;
196
197impl Primitive for Null {
198    #[inline]
199    fn write(self, buf: &mut Vec<u8>) {
200        buf.extend(b"null");
201    }
202}
203
204/// A reference to an indirect object.
205#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
206pub struct Ref(NonZeroI32);
207
208impl Ref {
209    /// Create a new indirect reference.
210    ///
211    /// The provided value must be greater than zero.
212    ///
213    /// Panics if `id` is out of the valid range.
214    #[inline]
215    #[track_caller]
216    pub const fn new(id: i32) -> Ref {
217        let option = if id > 0 { NonZeroI32::new(id) } else { None };
218        match option {
219            Some(val) => Self(val),
220            None => panic!("indirect reference out of valid range"),
221        }
222    }
223
224    /// Return the underlying number as a primitive type.
225    #[inline]
226    pub const fn get(self) -> i32 {
227        self.0.get()
228    }
229
230    /// The next consecutive ID.
231    #[inline]
232    pub const fn next(self) -> Self {
233        Self::new(self.get() + 1)
234    }
235
236    /// Increase this ID by one and return the old one. Useful to turn this ID
237    /// into a bump allocator of sorts.
238    #[inline]
239    pub fn bump(&mut self) -> Self {
240        let prev = *self;
241        *self = self.next();
242        prev
243    }
244}
245
246impl Primitive for Ref {
247    #[inline]
248    fn write(self, buf: &mut Vec<u8>) {
249        buf.push_int(self.0.get());
250        buf.extend(b" 0 R");
251    }
252}
253
254/// A rectangle, specified by two opposite corners.
255#[derive(Debug, Copy, Clone, PartialEq)]
256pub struct Rect {
257    /// The x-coordinate of the first (typically, lower-left) corner.
258    pub x1: f32,
259    /// The y-coordinate of the first (typically, lower-left) corner.
260    pub y1: f32,
261    /// The x-coordinate of the second (typically, upper-right) corner.
262    pub x2: f32,
263    /// The y-coordinate of the second (typically, upper-right) corner.
264    pub y2: f32,
265}
266
267impl Rect {
268    /// Create a new rectangle from four coordinate values.
269    #[inline]
270    pub fn new(x1: f32, y1: f32, x2: f32, y2: f32) -> Self {
271        Self { x1, y1, x2, y2 }
272    }
273
274    /// Convert this rectangle into 8 floats describing the four corners of the
275    /// rectangle in counterclockwise order.
276    #[inline]
277    pub fn to_quad_points(self) -> [f32; 8] {
278        [self.x1, self.y1, self.x2, self.y1, self.x2, self.y2, self.x1, self.y2]
279    }
280}
281
282impl Primitive for Rect {
283    #[inline]
284    fn write(self, buf: &mut Vec<u8>) {
285        buf.push(b'[');
286        buf.push_val(self.x1);
287        buf.push(b' ');
288        buf.push_val(self.y1);
289        buf.push(b' ');
290        buf.push_val(self.x2);
291        buf.push(b' ');
292        buf.push_val(self.y2);
293        buf.push(b']');
294    }
295}
296
297/// A date, written as a text string.
298///
299/// A field is only respected if all superior fields are supplied. For example,
300/// to set the minute, the hour, day, etc. have to be set. Similarly, in order
301/// for the time zone information to be written, all time information (including
302/// seconds) must be written. `utc_offset_minute` is optional if supplying time
303/// zone info. It must only be used to specify sub-hour time zone offsets.
304#[derive(Debug, Copy, Clone, Eq, PartialEq)]
305pub struct Date {
306    /// The year (0-9999).
307    year: u16,
308    /// The month (0-11).
309    month: Option<u8>,
310    /// The month (0-30).
311    day: Option<u8>,
312    /// The hour (0-23).
313    hour: Option<u8>,
314    /// The minute (0-59).
315    minute: Option<u8>,
316    /// The second (0-59).
317    second: Option<u8>,
318    /// The hour offset from UTC (-23 through 23).
319    utc_offset_hour: Option<i8>,
320    /// The minute offset from UTC (0-59). Will carry over the sign from
321    /// `utc_offset_hour`.
322    utc_offset_minute: u8,
323}
324
325impl Date {
326    /// Create a new, minimal date. The year will be clamped within the range
327    /// 0-9999.
328    #[inline]
329    pub fn new(year: u16) -> Self {
330        Self {
331            year: year.min(9999),
332            month: None,
333            day: None,
334            hour: None,
335            minute: None,
336            second: None,
337            utc_offset_hour: None,
338            utc_offset_minute: 0,
339        }
340    }
341
342    /// Add the month field. It will be clamped within the range 1-12.
343    #[inline]
344    pub fn month(mut self, month: u8) -> Self {
345        self.month = Some(month.clamp(1, 12));
346        self
347    }
348
349    /// Add the day field. It will be clamped within the range 1-31.
350    #[inline]
351    pub fn day(mut self, day: u8) -> Self {
352        self.day = Some(day.clamp(1, 31));
353        self
354    }
355
356    /// Add the hour field. It will be clamped within the range 0-23.
357    #[inline]
358    pub fn hour(mut self, hour: u8) -> Self {
359        self.hour = Some(hour.min(23));
360        self
361    }
362
363    /// Add the minute field. It will be clamped within the range 0-59.
364    #[inline]
365    pub fn minute(mut self, minute: u8) -> Self {
366        self.minute = Some(minute.min(59));
367        self
368    }
369
370    /// Add the second field. It will be clamped within the range 0-59.
371    #[inline]
372    pub fn second(mut self, second: u8) -> Self {
373        self.second = Some(second.min(59));
374        self
375    }
376
377    /// Add the offset from UTC in hours. If not specified, the time will be
378    /// assumed to be local to the viewer's time zone. It will be clamped within
379    /// the range -23-23.
380    #[inline]
381    pub fn utc_offset_hour(mut self, hour: i8) -> Self {
382        self.utc_offset_hour = Some(hour.clamp(-23, 23));
383        self
384    }
385
386    /// Add the offset from UTC in minutes. This will have the same sign as set in
387    /// [`Self::utc_offset_hour`]. It will be clamped within the range 0-59.
388    #[inline]
389    pub fn utc_offset_minute(mut self, minute: u8) -> Self {
390        self.utc_offset_minute = minute.min(59);
391        self
392    }
393}
394
395impl Primitive for Date {
396    fn write(self, buf: &mut Vec<u8>) {
397        buf.extend(b"(D:");
398
399        (|| {
400            write!(buf, "{:04}", self.year).unwrap();
401            write!(buf, "{:02}", self.month?).unwrap();
402            write!(buf, "{:02}", self.day?).unwrap();
403            write!(buf, "{:02}", self.hour?).unwrap();
404            write!(buf, "{:02}", self.minute?).unwrap();
405            write!(buf, "{:02}", self.second?).unwrap();
406            let utc_offset_hour = self.utc_offset_hour?;
407            if utc_offset_hour == 0 && self.utc_offset_minute == 0 {
408                buf.push(b'Z');
409            } else {
410                write!(buf, "{:+03}'{:02}", utc_offset_hour, self.utc_offset_minute)
411                    .unwrap();
412            }
413            Some(())
414        })();
415
416        buf.push(b')');
417    }
418}
419
420/// Writer for an arbitrary object.
421#[must_use = "not consuming this leaves the writer in an inconsistent state"]
422pub struct Obj<'a> {
423    buf: &'a mut Vec<u8>,
424    indirect: bool,
425    indent: u8,
426}
427
428impl<'a> Obj<'a> {
429    /// Start a new direct object.
430    #[inline]
431    pub(crate) fn direct(buf: &'a mut Vec<u8>, indent: u8) -> Self {
432        Self { buf, indirect: false, indent }
433    }
434
435    /// Start a new indirect object.
436    #[inline]
437    pub(crate) fn indirect(buf: &'a mut Vec<u8>, id: Ref) -> Self {
438        buf.push_int(id.get());
439        buf.extend(b" 0 obj\n");
440        Self { buf, indirect: true, indent: 0 }
441    }
442
443    /// Write a primitive object.
444    #[inline]
445    pub fn primitive<T: Primitive>(self, value: T) {
446        value.write(self.buf);
447        if self.indirect {
448            self.buf.extend(b"\nendobj\n\n");
449        }
450    }
451
452    /// Start writing an array.
453    #[inline]
454    pub fn array(self) -> Array<'a> {
455        self.start()
456    }
457
458    /// Start writing a dictionary.
459    #[inline]
460    pub fn dict(self) -> Dict<'a> {
461        self.start()
462    }
463
464    /// Start writing with an arbitrary writer.
465    ///
466    /// For example, using this, you could write a Type 1 font directly into
467    /// a page's resource directionary.
468    /// ```
469    /// use pdf_writer::{Pdf, Ref, Name, writers::Type1Font};
470    ///
471    /// let mut pdf = Pdf::new();
472    /// pdf.page(Ref::new(1))
473    ///     .resources()
474    ///     .fonts()
475    ///     .insert(Name(b"F1"))
476    ///     .start::<Type1Font>()
477    ///     .base_font(Name(b"Helvetica"));
478    /// ```
479    #[inline]
480    pub fn start<W: Writer<'a>>(self) -> W {
481        W::start(self)
482    }
483}
484
485/// A writer for a specific type of PDF object.
486pub trait Writer<'a> {
487    /// Start writing the object.
488    fn start(obj: Obj<'a>) -> Self;
489}
490
491/// Rewrites a writer's lifetime.
492///
493/// This is a workaround to ignore the `'b` lifetime in a
494/// `TypedArray<'a, SomeWriter<'b>>` because that lifetime is meaningless. What
495/// we actually want is each item's `SomeWriter` to borrow from the array itself.
496pub trait Rewrite<'a> {
497    /// The writer with the rewritten lifetime.
498    type Output: Writer<'a>;
499}
500
501/// Writer for an array.
502pub struct Array<'a> {
503    buf: &'a mut Vec<u8>,
504    indirect: bool,
505    indent: u8,
506    len: i32,
507}
508
509writer!(Array: |obj| {
510    obj.buf.push(b'[');
511    Self {
512        buf: obj.buf,
513        indirect: obj.indirect,
514        indent: obj.indent,
515        len: 0,
516    }
517});
518
519impl<'a> Array<'a> {
520    /// The number of written items.
521    #[inline]
522    pub fn len(&self) -> i32 {
523        self.len
524    }
525
526    /// Whether no items have been written so far.
527    #[inline]
528    pub fn is_empty(&self) -> bool {
529        self.len == 0
530    }
531
532    /// Start writing an arbitrary item.
533    #[inline]
534    pub fn push(&mut self) -> Obj<'_> {
535        if self.len != 0 {
536            self.buf.push(b' ');
537        }
538        self.len += 1;
539        Obj::direct(self.buf, self.indent)
540    }
541
542    /// Write an item with a primitive value.
543    ///
544    /// This is a shorthand for `array.push().primitive(value)`.
545    #[inline]
546    pub fn item<T: Primitive>(&mut self, value: T) -> &mut Self {
547        self.push().primitive(value);
548        self
549    }
550
551    /// Write a sequence of items with primitive values.
552    #[inline]
553    pub fn items<T: Primitive>(
554        &mut self,
555        values: impl IntoIterator<Item = T>,
556    ) -> &mut Self {
557        for value in values {
558            self.item(value);
559        }
560        self
561    }
562
563    /// Convert into a typed version.
564    #[inline]
565    pub fn typed<T>(self) -> TypedArray<'a, T> {
566        TypedArray::wrap(self)
567    }
568}
569
570impl Drop for Array<'_> {
571    #[inline]
572    fn drop(&mut self) {
573        self.buf.push(b']');
574        if self.indirect {
575            self.buf.extend(b"\nendobj\n\n");
576        }
577    }
578}
579
580/// Writer for an array of items of a fixed type.
581pub struct TypedArray<'a, T> {
582    array: Array<'a>,
583    phantom: PhantomData<fn() -> T>,
584}
585
586impl<'a, T> Writer<'a> for TypedArray<'a, T> {
587    fn start(obj: Obj<'a>) -> Self {
588        Self { array: obj.array(), phantom: PhantomData }
589    }
590}
591
592impl<'a, T> Rewrite<'a> for TypedArray<'_, T> {
593    type Output = TypedArray<'a, T>;
594}
595
596impl<'a, T> TypedArray<'a, T> {
597    /// Wrap an array to make it type-safe.
598    #[inline]
599    pub fn wrap(array: Array<'a>) -> Self {
600        Self { array, phantom: PhantomData }
601    }
602
603    /// The number of written items.
604    #[inline]
605    pub fn len(&self) -> i32 {
606        self.array.len()
607    }
608
609    /// Whether no items have been written so far.
610    #[inline]
611    pub fn is_empty(&self) -> bool {
612        self.len() == 0
613    }
614
615    /// Write an item.
616    #[inline]
617    pub fn item(&mut self, value: T) -> &mut Self
618    where
619        T: Primitive,
620    {
621        self.array.item(value);
622        self
623    }
624
625    /// Write a sequence of items.
626    #[inline]
627    pub fn items(&mut self, values: impl IntoIterator<Item = T>) -> &mut Self
628    where
629        T: Primitive,
630    {
631        self.array.items(values);
632        self
633    }
634
635    /// Start writing an item with the typed writer.
636    ///
637    /// Returns `T` but with its lifetime rewritten from `'a` to `'b`.
638    #[inline]
639    pub fn push<'b>(&'b mut self) -> <T as Rewrite<'b>>::Output
640    where
641        T: Writer<'a> + Rewrite<'b>,
642    {
643        <T as Rewrite>::Output::start(self.array.push())
644    }
645}
646
647/// Writer for a dictionary.
648pub struct Dict<'a> {
649    buf: &'a mut Vec<u8>,
650    indirect: bool,
651    indent: u8,
652    len: i32,
653}
654
655writer!(Dict: |obj| {
656    obj.buf.extend(b"<<");
657    Self {
658        buf: obj.buf,
659        indirect: obj.indirect,
660        indent: obj.indent.saturating_add(2),
661        len: 0,
662    }
663});
664
665impl<'a> Dict<'a> {
666    /// The number of written pairs.
667    #[inline]
668    pub fn len(&self) -> i32 {
669        self.len
670    }
671
672    /// Whether no pairs have been written so far.
673    #[inline]
674    pub fn is_empty(&self) -> bool {
675        self.len == 0
676    }
677
678    /// Start writing a pair with an arbitrary value.
679    #[inline]
680    pub fn insert(&mut self, key: Name) -> Obj<'_> {
681        self.len += 1;
682        self.buf.push(b'\n');
683
684        for _ in 0..self.indent {
685            self.buf.push(b' ');
686        }
687
688        self.buf.push_val(key);
689        self.buf.push(b' ');
690
691        Obj::direct(self.buf, self.indent)
692    }
693
694    /// Write a pair with a primitive value.
695    ///
696    /// This is a shorthand for `dict.insert(key).primitive(value)`.
697    #[inline]
698    pub fn pair<T: Primitive>(&mut self, key: Name, value: T) -> &mut Self {
699        self.insert(key).primitive(value);
700        self
701    }
702
703    /// Write a sequence of pairs with primitive values.
704    pub fn pairs<'n, T: Primitive>(
705        &mut self,
706        pairs: impl IntoIterator<Item = (Name<'n>, T)>,
707    ) -> &mut Self {
708        for (key, value) in pairs {
709            self.pair(key, value);
710        }
711        self
712    }
713
714    /// Convert into a typed version.
715    #[inline]
716    pub fn typed<T>(self) -> TypedDict<'a, T> {
717        TypedDict::wrap(self)
718    }
719}
720
721impl Drop for Dict<'_> {
722    #[inline]
723    fn drop(&mut self) {
724        if self.len != 0 {
725            self.buf.push(b'\n');
726            for _ in 0..self.indent - 2 {
727                self.buf.push(b' ');
728            }
729        }
730        self.buf.extend(b">>");
731        if self.indirect {
732            self.buf.extend(b"\nendobj\n\n");
733        }
734    }
735}
736
737/// Writer for a dictionary mapping to a fixed type.
738pub struct TypedDict<'a, T> {
739    dict: Dict<'a>,
740    phantom: PhantomData<fn() -> T>,
741}
742
743impl<'a, T> Writer<'a> for TypedDict<'a, T> {
744    fn start(obj: Obj<'a>) -> Self {
745        Self { dict: obj.dict(), phantom: PhantomData }
746    }
747}
748
749impl<'a, T> Rewrite<'a> for TypedDict<'_, T> {
750    type Output = TypedDict<'a, T>;
751}
752
753impl<'a, T> TypedDict<'a, T> {
754    /// Wrap a dictionary to make it type-safe.
755    #[inline]
756    pub fn wrap(dict: Dict<'a>) -> Self {
757        Self { dict, phantom: PhantomData }
758    }
759
760    /// The number of written pairs.
761    #[inline]
762    pub fn len(&self) -> i32 {
763        self.dict.len()
764    }
765
766    /// Whether no pairs have been written so far.
767    #[inline]
768    pub fn is_empty(&self) -> bool {
769        self.len() == 0
770    }
771
772    /// Write a key-value pair.
773    #[inline]
774    pub fn pair(&mut self, key: Name, value: T) -> &mut Self
775    where
776        T: Primitive,
777    {
778        self.dict.pair(key, value);
779        self
780    }
781
782    /// Write a sequence of key-value pairs.
783    #[inline]
784    pub fn pairs<'n>(
785        &mut self,
786        pairs: impl IntoIterator<Item = (Name<'n>, T)>,
787    ) -> &mut Self
788    where
789        T: Primitive,
790    {
791        self.dict.pairs(pairs);
792        self
793    }
794
795    /// Start writing a pair with the typed writer.
796    ///
797    /// Returns `T` but with its lifetime rewritten from `'a` to `'b`.
798    #[inline]
799    pub fn insert<'b>(&'b mut self, key: Name) -> <T as Rewrite<'b>>::Output
800    where
801        T: Writer<'a> + Rewrite<'b>,
802    {
803        <T as Rewrite>::Output::start(self.dict.insert(key))
804    }
805}
806
807/// Writer for an indirect stream object.
808pub struct Stream<'a> {
809    dict: ManuallyDrop<Dict<'a>>,
810    data: &'a [u8],
811}
812
813impl<'a> Stream<'a> {
814    /// Start writing a stream.
815    ///
816    /// Panics if the object writer is not indirect or the stream length exceeds
817    /// `i32::MAX`.
818    pub(crate) fn start(obj: Obj<'a>, data: &'a [u8]) -> Self {
819        assert!(obj.indirect);
820
821        let mut dict = obj.dict();
822        dict.pair(
823            Name(b"Length"),
824            i32::try_from(data.len()).unwrap_or_else(|_| {
825                panic!("data length (is `{}`) must be <= i32::MAX", data.len());
826            }),
827        );
828
829        Self { dict: ManuallyDrop::new(dict), data }
830    }
831
832    /// Write the `/Filter` attribute.
833    pub fn filter(&mut self, filter: Filter) -> &mut Self {
834        self.pair(Name(b"Filter"), filter.to_name());
835        self
836    }
837
838    /// Start writing the `/DecodeParms` attribute.
839    ///
840    /// This is a dictionary that specifies parameters to be used in decoding
841    /// the stream data using the filter specified by the
842    /// [`/Filter`](Self::filter) attribute.
843    pub fn decode_parms(&mut self) -> DecodeParms<'_> {
844        self.insert(Name(b"DecodeParms")).start()
845    }
846}
847
848impl Drop for Stream<'_> {
849    fn drop(&mut self) {
850        self.dict.buf.extend(b"\n>>");
851        self.dict.buf.extend(b"\nstream\n");
852        self.dict.buf.extend(self.data.as_ref());
853        self.dict.buf.extend(b"\nendstream");
854        self.dict.buf.extend(b"\nendobj\n\n");
855    }
856}
857
858deref!('a, Stream<'a> => Dict<'a>, dict);
859
860/// A compression filter for a stream.
861#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
862#[allow(missing_docs)]
863pub enum Filter {
864    AsciiHexDecode,
865    Ascii85Decode,
866    /// Lempel-Ziv-Welch (LZW) compression.
867    ///
868    /// Note that this filter is forbidden in PDF/A.
869    LzwDecode,
870    FlateDecode,
871    RunLengthDecode,
872    CcittFaxDecode,
873    Jbig2Decode,
874    /// Decodes JPEG/JFIF files with a SOF0, SOF1, or (PDF 1.3+) SOF2 marker.
875    ///
876    /// See ISO 32000-1:2008, Section 7.4.8 and Adobe Technical Note #5116.
877    DctDecode,
878    /// Decodes JPEG2000 files with a JPX baseline marker.
879    ///
880    /// Note that additional restrictions are imposed by PDF/A and PDF/X.
881    JpxDecode,
882    /// Encrypt the stream.
883    ///
884    /// Note that this filter is restricted in PDF/A.
885    Crypt,
886}
887
888impl Filter {
889    pub(crate) fn to_name(self) -> Name<'static> {
890        match self {
891            Self::AsciiHexDecode => Name(b"ASCIIHexDecode"),
892            Self::Ascii85Decode => Name(b"ASCII85Decode"),
893            Self::LzwDecode => Name(b"LZWDecode"),
894            Self::FlateDecode => Name(b"FlateDecode"),
895            Self::RunLengthDecode => Name(b"RunLengthDecode"),
896            Self::CcittFaxDecode => Name(b"CCITTFaxDecode"),
897            Self::Jbig2Decode => Name(b"JBIG2Decode"),
898            Self::DctDecode => Name(b"DCTDecode"),
899            Self::JpxDecode => Name(b"JPXDecode"),
900            Self::Crypt => Name(b"Crypt"),
901        }
902    }
903}
904
905/// Writer for an _filter decode parameters dictionary_.
906///
907/// This struct is created by [`Stream::decode_parms`].
908pub struct DecodeParms<'a> {
909    dict: Dict<'a>,
910}
911
912writer!(DecodeParms: |obj| Self { dict: obj.dict() });
913
914/// Properties for `FlateDecode` and `LzwDecode`.
915impl DecodeParms<'_> {
916    /// Write the `/Predictor` attribute for `FlateDecode` and `LzwDecode`.
917    ///
918    /// No predictor is used by default.
919    pub fn predictor(&mut self, predictor: Predictor) -> &mut Self {
920        self.pair(Name(b"Predictor"), predictor.to_i32());
921        self
922    }
923
924    /// Write the `/Colors` attribute for `FlateDecode` and `LzwDecode`.
925    ///
926    /// Must be greater than 0. [`/Predictor`](Self::predictor) must be set.
927    /// Defaults to 1.
928    pub fn colors(&mut self, colors: i32) -> &mut Self {
929        if colors <= 0 {
930            panic!("`Colors` must be greater than 0");
931        }
932
933        self.pair(Name(b"Colors"), colors);
934        self
935    }
936
937    /// Write the `/BitsPerComponent` attribute for `FlateDecode` and
938    /// `LzwDecode`.
939    ///
940    /// Must be one of 1, 2, 4, 8, or 16. [`/Predictor`](Self::predictor) must
941    /// be set. Defaults to 8.
942    pub fn bits_per_component(&mut self, bits: i32) -> &mut Self {
943        if ![1, 2, 4, 8, 16].contains(&bits) {
944            panic!("`BitsPerComponent` must be one of 1, 2, 4, 8, or 16");
945        }
946
947        self.pair(Name(b"BitsPerComponent"), bits);
948        self
949    }
950
951    /// Write the `/Columns` attribute for `FlateDecode` and `LzwDecode` or
952    /// `CcittFaxDecode`.
953    ///
954    /// When used with `FlateDecode` and `LzwDecode`, it indicates the number of
955    /// samples in each row. In that case, [`/Predictor`](Self::predictor) must
956    /// be set and the default is 1.
957    ///
958    /// When used with `CcittFaxDecode` it denominates the width of the image in
959    /// pixels and defaults to 1728.
960    pub fn columns(&mut self, columns: i32) -> &mut Self {
961        self.pair(Name(b"Columns"), columns);
962        self
963    }
964
965    /// Write the `/EarlyChange` attribute for `LzwDecode`.
966    ///
967    /// If `true` (1), the code length increases one code earlier, if `false`
968    /// (0), length change is postponed as long as possible.
969    ///
970    /// Defaults to 1.
971    pub fn early_change(&mut self, early_change: bool) -> &mut Self {
972        self.pair(Name(b"EarlyChange"), if early_change { 1 } else { 0 });
973        self
974    }
975}
976
977/// Properties for `CcittFaxDecode`. Also see [`Self::columns`].
978impl DecodeParms<'_> {
979    /// Write the `/K` attribute for `CcittFaxDecode`.
980    ///
981    /// Defaults to 0.
982    pub fn k(&mut self, k: i32) -> &mut Self {
983        self.pair(Name(b"K"), k);
984        self
985    }
986
987    /// Write the `/EndOfLine` attribute for `CcittFaxDecode`.
988    ///
989    /// Whether the EOL bit pattern is present in the encoding. Defaults to
990    /// `false`.
991    pub fn end_of_line(&mut self, eol: bool) -> &mut Self {
992        self.pair(Name(b"EndOfLine"), eol);
993        self
994    }
995
996    /// Write the `/EncodedByteAlign` attribute for `CcittFaxDecode`.
997    ///
998    /// Whether to expect zero bits before each encoded line. Defaults to
999    /// `false`.
1000    pub fn encoded_byte_align(&mut self, encoded_byte_align: bool) -> &mut Self {
1001        self.pair(Name(b"EncodedByteAlign"), encoded_byte_align);
1002        self
1003    }
1004
1005    /// Write the `/Rows` attribute for `CcittFaxDecode`.
1006    ///
1007    /// The image's height. Defaults to 0.
1008    pub fn rows(&mut self, rows: i32) -> &mut Self {
1009        self.pair(Name(b"Rows"), rows);
1010        self
1011    }
1012
1013    /// Write the `/EndOfBlock` attribute for `CcittFaxDecode`.
1014    ///
1015    /// Whether to expect an EOB code at the end of the data. Defaults to
1016    /// `true`.
1017    pub fn end_of_block(&mut self, end_of_block: bool) -> &mut Self {
1018        self.pair(Name(b"EndOfBlock"), end_of_block);
1019        self
1020    }
1021
1022    /// Write the `/BlackIs1` attribute for `CcittFaxDecode`.
1023    ///
1024    /// Whether to invert the bits in the image. Defaults to `false`.
1025    pub fn black_is_1(&mut self, black_is_1: bool) -> &mut Self {
1026        self.pair(Name(b"BlackIs1"), black_is_1);
1027        self
1028    }
1029
1030    /// Write the `/DamagedRowsBeforeError` attribute for `CcittFaxDecode`.
1031    ///
1032    /// How many damaged rows are allowed before an error is raised. Defaults to
1033    /// 0.
1034    pub fn damaged_rows_before_error(&mut self, count: i32) -> &mut Self {
1035        self.pair(Name(b"DamagedRowsBeforeError"), count);
1036        self
1037    }
1038}
1039
1040/// Properties for `Jbig2Decode`.
1041impl DecodeParms<'_> {
1042    /// Write the `/JBIG2Globals` attribute for `Jbig2Decode`.
1043    ///
1044    /// A reference to a stream containing global segments.
1045    pub fn jbig2_globals(&mut self, globals: Ref) -> &mut Self {
1046        self.pair(Name(b"JBIG2Globals"), globals);
1047        self
1048    }
1049}
1050
1051/// Properties for `JpxDecode`.
1052impl DecodeParms<'_> {
1053    /// Write the `/ColorTransform` attribute for `JpxDecode`.
1054    ///
1055    /// How to handle color data. If `true` (1), images with three color
1056    /// channels shall be decoded from the YCbCr space and images with four
1057    /// color channels are decoded from YCbCrK. If `false` (0), no
1058    /// transformation is applied. The default depends on the `APP14` marker in
1059    /// the data stream.
1060    pub fn color_transform(&mut self, color_transform: bool) -> &mut Self {
1061        self.pair(Name(b"ColorTransform"), if color_transform { 1 } else { 0 });
1062        self
1063    }
1064}
1065
1066/// Properties for `Crypt`.
1067impl DecodeParms<'_> {
1068    /// Write the `/Type` attribute for `Crypt` as `CryptFilterDecodeParms`.
1069    pub fn crypt_type(&mut self) -> &mut Self {
1070        self.pair(Name(b"Type"), Name(b"CryptFilterDecodeParms"));
1071        self
1072    }
1073
1074    /// Write the `/Name` attribute for `Crypt`.
1075    ///
1076    /// The name of the crypt filter corresponding to a `CF` entry of the
1077    /// encryption dictionary.
1078    pub fn name(&mut self, name: Name) -> &mut Self {
1079        self.pair(Name(b"Name"), name);
1080        self
1081    }
1082}
1083
1084deref!('a, DecodeParms<'a> => Dict<'a>, dict);
1085
1086/// Which kind of predictor to use for a `FlateDecode` or `LzwDecode` stream.
1087#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1088#[allow(missing_docs)]
1089pub enum Predictor {
1090    /// No prediction.
1091    None,
1092    /// TIFF Predictor 2.
1093    Tiff,
1094    PngNone,
1095    PngSub,
1096    PngUp,
1097    PngAverage,
1098    PngPaeth,
1099    PngOptimum,
1100}
1101
1102impl Predictor {
1103    /// Convert the predictor to its integer representation according to ISO
1104    /// 32000-2:2020, Table E.
1105    fn to_i32(self) -> i32 {
1106        match self {
1107            Self::None => 1,
1108            Self::Tiff => 2,
1109            Self::PngNone => 10,
1110            Self::PngSub => 11,
1111            Self::PngUp => 12,
1112            Self::PngAverage => 13,
1113            Self::PngPaeth => 14,
1114            Self::PngOptimum => 15,
1115        }
1116    }
1117}
1118
1119/// Writer for a _name tree node_.
1120///
1121/// Name trees associate a large number of names with PDF objects. They are
1122/// lexically ordered search trees. Root nodes may directly contain all leafs,
1123/// however, this might degrade performance for very large numbers of
1124/// name-object pairs.
1125///
1126/// For each node, either the `/Kids` or `/Names` attribute must be set, but
1127/// never both.
1128pub struct NameTree<'a, T> {
1129    dict: Dict<'a>,
1130    phantom: PhantomData<T>,
1131}
1132
1133impl<'a, T> Writer<'a> for NameTree<'a, T> {
1134    fn start(obj: Obj<'a>) -> Self {
1135        Self { dict: obj.dict(), phantom: PhantomData }
1136    }
1137}
1138
1139impl<'a, T> Rewrite<'a> for NameTree<'_, T> {
1140    type Output = NameTree<'a, T>;
1141}
1142
1143impl<T> NameTree<'_, T> {
1144    /// Start writing the `/Kids` attribute with the children of this node.
1145    pub fn kids(&mut self) -> TypedArray<'_, Ref> {
1146        self.dict.insert(Name(b"Kids")).array().typed()
1147    }
1148
1149    /// Start writing the `/Names` attribute to set the immediate name-to-object
1150    /// mappings of this node.
1151    pub fn names(&mut self) -> NameTreeEntries<'_, T> {
1152        self.dict.insert(Name(b"Names")).start()
1153    }
1154
1155    /// Write the `/Limits` array to set the range of names in this node. This
1156    /// is required for every node except the root node.
1157    pub fn limits(&mut self, min: Name, max: Name) -> &mut Self {
1158        self.dict.insert(Name(b"Limits")).array().typed().items([min, max]);
1159        self
1160    }
1161}
1162
1163/// Writer for a _name tree names_ array.
1164///
1165/// The children must be added in ascending lexical order. Their minimum and
1166/// maximum keys must not exceed the `/Limits` property of the parent [`NameTree`]
1167/// node. This struct is created by [`NameTree::names`].
1168pub struct NameTreeEntries<'a, T> {
1169    arr: Array<'a>,
1170    phantom: PhantomData<T>,
1171}
1172
1173impl<'a, T> Writer<'a> for NameTreeEntries<'a, T> {
1174    fn start(obj: Obj<'a>) -> Self {
1175        Self { arr: obj.array(), phantom: PhantomData }
1176    }
1177}
1178
1179impl<'a, T> Rewrite<'a> for NameTreeEntries<'_, T> {
1180    type Output = NameTreeEntries<'a, T>;
1181}
1182
1183impl<T> NameTreeEntries<'_, T>
1184where
1185    T: Primitive,
1186{
1187    /// Insert a name-value pair.
1188    pub fn insert(&mut self, key: Str, value: T) -> &mut Self {
1189        self.arr.item(key);
1190        self.arr.item(value);
1191        self
1192    }
1193}
1194
1195/// Writer for a _number tree node_.
1196///
1197/// Number trees associate a many integers with PDF objects. They are search
1198/// trees in ascending order. Root nodes may directly contain all leafs,
1199/// however, this might degrade performance for very large numbers of
1200/// integer-object pairs.
1201///
1202/// For each node, either the `/Kids` or `/Nums` attribute must be set, but
1203/// never both.
1204pub struct NumberTree<'a, T> {
1205    dict: Dict<'a>,
1206    phantom: PhantomData<T>,
1207}
1208
1209impl<'a, T> Writer<'a> for NumberTree<'a, T> {
1210    fn start(obj: Obj<'a>) -> Self {
1211        Self { dict: obj.dict(), phantom: PhantomData }
1212    }
1213}
1214
1215impl<'a, T> Rewrite<'a> for NumberTree<'_, T> {
1216    type Output = NumberTree<'a, T>;
1217}
1218
1219impl<T> NumberTree<'_, T> {
1220    /// Start writing the `/Kids` attribute with the children of this node.
1221    pub fn kids(&mut self) -> TypedArray<'_, Ref> {
1222        self.dict.insert(Name(b"Kids")).array().typed()
1223    }
1224
1225    /// Start writing the `/Nums` attribute to set the immediate
1226    /// number-to-object mappings of this node.
1227    pub fn nums(&mut self) -> NumberTreeEntries<'_, T> {
1228        self.dict.insert(Name(b"Nums")).start()
1229    }
1230
1231    /// Write the `/Limits` array to set the range of numbers in this node. This
1232    /// is required for every node except the root node.
1233    pub fn limits(&mut self, min: i32, max: i32) -> &mut Self {
1234        self.dict.insert(Name(b"Limits")).array().typed().items([min, max]);
1235        self
1236    }
1237}
1238
1239/// Writer for a _number tree numbers_ array.
1240///
1241/// The children must be added in ascending order. Their minimum and
1242/// maximum keys must not exceed the `/Limits` property of the parent [`NumberTree`]
1243/// node. This struct is created by [`NumberTree::nums`].
1244pub struct NumberTreeEntries<'a, T> {
1245    arr: Array<'a>,
1246    phantom: PhantomData<T>,
1247}
1248
1249impl<'a, T> Writer<'a> for NumberTreeEntries<'a, T> {
1250    fn start(obj: Obj<'a>) -> Self {
1251        Self { arr: obj.array(), phantom: PhantomData }
1252    }
1253}
1254
1255impl<'a, T> Rewrite<'a> for NumberTreeEntries<'_, T> {
1256    type Output = NumberTreeEntries<'a, T>;
1257}
1258
1259impl<T> NumberTreeEntries<'_, T>
1260where
1261    T: Primitive,
1262{
1263    /// Insert a number-value pair.
1264    pub fn insert(&mut self, key: i32, value: T) -> &mut Self {
1265        self.arr.item(key);
1266        self.arr.item(value);
1267        self
1268    }
1269}
1270
1271/// Finish objects in postfix-style.
1272///
1273/// In many cases you can use writers in builder-pattern style so that they are
1274/// automatically dropped at the appropriate time. Sometimes though you need to
1275/// bind a writer to a variable and still want to regain access to the
1276/// [`Pdf`] in the same scope. In that case, you need to manually invoke
1277/// the writer's `Drop` implementation. You can of course, just write
1278/// `drop(array)` to finish your array, but you might find it more aesthetically
1279/// pleasing to write `array.finish()`. That's what this trait is for.
1280///
1281/// ```
1282/// # use pdf_writer::{Pdf, Ref, Finish, Name, Str};
1283/// # let mut pdf = Pdf::new();
1284/// let mut array = pdf.indirect(Ref::new(1)).array();
1285/// array.push().dict().pair(Name(b"Key"), Str(b"Value"));
1286/// array.item(2);
1287/// array.finish(); // instead of drop(array)
1288///
1289/// // Do more stuff with `pdf` ...
1290/// ```
1291pub trait Finish: Sized {
1292    /// Does nothing but move `self`, equivalent to [`drop`].
1293    #[inline]
1294    fn finish(self) {}
1295}
1296
1297impl<T> Finish for T {}
1298
1299#[cfg(test)]
1300mod tests {
1301    use super::*;
1302
1303    #[test]
1304    fn test_primitive_objects() {
1305        // Test really simple objects.
1306        test_primitive!(true, b"true");
1307        test_primitive!(false, b"false");
1308        test_primitive!(78, b"78");
1309        test_primitive!(4.22, b"4.22");
1310        test_primitive!(1.184e-7, b"0.0000001184");
1311        test_primitive!(4.2e13, b"42000000000000");
1312        test_primitive!(Ref::new(7), b"7 0 R");
1313        test_primitive!(Null, b"null");
1314
1315        // Test strings.
1316        test_primitive!(Str(b"Hello, World!"), b"(Hello, World!)");
1317        test_primitive!(Str(b"()"), br"(())");
1318        test_primitive!(Str(b")()"), br"(\)\(\))");
1319        test_primitive!(Str(b"()(())"), br"(()(()))");
1320        test_primitive!(Str(b"(()))"), br"(\(\(\)\)\))");
1321        test_primitive!(Str(b"\\"), br"(\\)");
1322        test_primitive!(Str(b"\n\ta"), br"(\n\ta)");
1323        test_primitive!(Str(br"\n"), br"(\\n)");
1324        test_primitive!(Str(b"a\x14b"), br"(a\024b)");
1325        test_primitive!(Str(b"\xFF\xAA"), b"<FFAA>");
1326        test_primitive!(Str(b"\x0A\x7F\x1F"), br"(\n\177\037)");
1327
1328        // Test text strings.
1329        test_primitive!(TextStr("Hallo"), b"(Hallo)");
1330        test_primitive!(TextStr("😀!"), b"<FEFFD83DDE000021>");
1331
1332        // Test names.
1333        test_primitive!(Name(b"Filter"), b"/Filter");
1334        test_primitive!(Name(b"A B"), br"/A#20B");
1335        test_primitive!(Name(b"~+c"), br"/~+c");
1336        test_primitive!(Name(b"/A-B"), br"/#2FA-B");
1337        test_primitive!(Name(b"<A>"), br"/#3CA#3E");
1338        test_primitive!(Name(b"#"), br"/#23");
1339        test_primitive!(Name(b"\n"), br"/#0A");
1340    }
1341
1342    #[test]
1343    fn test_dates() {
1344        test_primitive!(Date::new(2021), b"(D:2021)");
1345        test_primitive!(Date::new(2021).month(30), b"(D:202112)");
1346
1347        let date = Date::new(2020).month(3).day(17).hour(1).minute(2).second(3);
1348        test_primitive!(date, b"(D:20200317010203)");
1349        test_primitive!(date.utc_offset_hour(0), b"(D:20200317010203Z)");
1350        test_primitive!(date.utc_offset_hour(4), b"(D:20200317010203+04'00)");
1351        test_primitive!(
1352            date.utc_offset_hour(-17).utc_offset_minute(10),
1353            b"(D:20200317010203-17'10)"
1354        );
1355    }
1356
1357    #[test]
1358    fn test_arrays() {
1359        test_obj!(|obj| obj.array(), b"[]");
1360        test_obj!(|obj| obj.array().item(12).item(Null), b"[12 null]");
1361        test_obj!(|obj| obj.array().typed().items(vec![1, 2, 3]), b"[1 2 3]");
1362        test_obj!(
1363            |obj| {
1364                let mut array = obj.array();
1365                array.push().array().typed().items(vec![1, 2]);
1366                array.item(3);
1367            },
1368            b"[[1 2] 3]",
1369        );
1370    }
1371
1372    #[test]
1373    fn test_dicts() {
1374        test_obj!(|obj| obj.dict(), b"<<>>");
1375        test_obj!(
1376            |obj| obj.dict().pair(Name(b"Quality"), Name(b"Good")),
1377            b"<<\n  /Quality /Good\n>>",
1378        );
1379        test_obj!(
1380            |obj| {
1381                obj.dict().pair(Name(b"A"), 1).pair(Name(b"B"), 2);
1382            },
1383            b"<<\n  /A 1\n  /B 2\n>>",
1384        );
1385    }
1386
1387    #[test]
1388    fn test_streams() {
1389        let mut w = Pdf::new();
1390        w.stream(Ref::new(1), &b"Hi there!"[..]).filter(Filter::Crypt);
1391        test!(
1392            w.finish(),
1393            b"%PDF-1.7\n%\x80\x80\x80\x80\n",
1394            b"1 0 obj",
1395            b"<<\n  /Length 9\n  /Filter /Crypt\n>>",
1396            b"stream",
1397            b"Hi there!",
1398            b"endstream",
1399            b"endobj\n",
1400            b"xref",
1401            b"0 2",
1402            b"0000000000 65535 f\r",
1403            b"0000000016 00000 n\r",
1404            b"trailer",
1405            b"<<\n  /Size 2\n>>",
1406            b"startxref\n94\n%%EOF",
1407        )
1408    }
1409}