1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use super::*;

/// Writer for a _transition dictionary_.
///
/// This struct is created by [`Page::transition`].
pub struct Transition<'a> {
    dict: Dict<'a>,
}

writer!(Transition: |obj| {
    let mut dict = obj.dict();
    dict.pair(Name(b"Type"), Name(b"Trans"));
    Self { dict }
});

impl<'a> Transition<'a> {
    /// Write the `/S` attribute to set the transition style.
    pub fn style(&mut self, kind: TransitionStyle) -> &mut Self {
        self.pair(Name(b"S"), kind.to_name());
        self
    }

    /// Write the `/D` attribute to set the transition duration.
    pub fn duration(&mut self, seconds: f32) -> &mut Self {
        self.pair(Name(b"D"), seconds);
        self
    }

    /// Write the `/Dm` attribute to set the transition direction. Will be
    /// horizontal if the argument is `false`.
    pub fn dimension(&mut self, vertical: bool) -> &mut Self {
        let name = if vertical { Name(b"V") } else { Name(b"H") };
        self.pair(Name(b"Dm"), name);
        self
    }

    /// Write the `/M` attribute to set the transition direction. Will be
    /// inwards if the argument is `false`.
    pub fn direction(&mut self, outward: bool) -> &mut Self {
        let name = if outward { Name(b"O") } else { Name(b"I") };
        self.pair(Name(b"M"), name);
        self
    }

    /// Write the `/Di` attribute to set the transition angle.
    pub fn angle(&mut self, angle: TransitionAngle) -> &mut Self {
        angle.write_to_obj(self.insert(Name(b"Di")));
        self
    }

    /// Write the `/SS` attribute to set the scale for the `Fly` transition.
    /// PDF 1.5+.
    pub fn scale(&mut self, scale: f32) -> &mut Self {
        self.pair(Name(b"SS"), scale);
        self
    }

    /// Write the `/B` attribute for the `Fly` transition. PDF 1.5+.
    pub fn opaque(&mut self, opaque: f32) -> &mut Self {
        self.pair(Name(b"F"), opaque);
        self
    }
}

deref!('a, Transition<'a> => Dict<'a>, dict);

/// A kind of page transition.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum TransitionStyle {
    /// Split the slide down the middle.
    Split,
    /// Multiple lines roll up the slide.
    Blinds,
    /// The new slide is revealed in a growing box.
    Box,
    /// Single line that sweeps across the slide.
    Wipe,
    /// Slide dissolves gradually.
    Dissolve,
    /// Like dissolve, but starts on one side.
    Glitter,
    /// No effect.
    R,
    /// Changes are flown in. PDF 1.5+.
    Fly,
    /// Old page slides out, new page slides in. PDF 1.5+.
    Push,
    /// New page slides in to cover the old one. PDF 1.5+.
    Cover,
    /// Old page slides out to uncover the new one. PDF 1.5+.
    Uncover,
    /// A cross-fade. PDF 1.5+.
    Fade,
}

impl TransitionStyle {
    pub(crate) fn to_name(self) -> Name<'static> {
        match self {
            Self::Split => Name(b"Split"),
            Self::Blinds => Name(b"Blinds"),
            Self::Box => Name(b"Box"),
            Self::Wipe => Name(b"Wipe"),
            Self::Dissolve => Name(b"Dissolve"),
            Self::Glitter => Name(b"Glitter"),
            Self::R => Name(b"R"),
            Self::Fly => Name(b"Fly"),
            Self::Push => Name(b"Push"),
            Self::Cover => Name(b"Cover"),
            Self::Uncover => Name(b"Uncover"),
            Self::Fade => Name(b"Fade"),
        }
    }
}

/// From where to where a page transition plays.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[allow(missing_docs)]
pub enum TransitionAngle {
    LeftToRight,
    BottomToTop,
    RightToLeft,
    TopToBottom,
    TopLeftToBottomRight,
    /// No direction. Only allowed if the transition style is `Fly`.
    None,
}

impl TransitionAngle {
    fn write_to_obj(&self, obj: Obj<'_>) {
        match self {
            Self::LeftToRight => obj.primitive(0),
            Self::BottomToTop => obj.primitive(90),
            Self::RightToLeft => obj.primitive(180),
            Self::TopToBottom => obj.primitive(270),
            Self::TopLeftToBottomRight => obj.primitive(315),
            Self::None => obj.primitive(Name(b"None")),
        }
    }
}