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