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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
//! Module regulating the comparison and feature sets / allowed plugins of a PDF document
//!
//! NOTE: All credit to Wikipedia:
//!
//! [PDF/X Versions](https://en.wikipedia.org/wiki/PDF/X)
//!
//! [PDF/A Versions](https://en.wikipedia.org/wiki/PDF/A)

/// List of (relevant) PDF versions
/// Please note the difference between **PDF/A** (archiving), **PDF/UA** (universal acessibility),
/// **PDF/X** (printing), **PDF/E** (engineering / CAD), **PDF/VT** (large volume transactions with
/// repeated content)
#[derive(Debug, PartialEq, Eq, Clone)]
#[allow(non_camel_case_types)]
pub enum PdfConformance {
    /// `PDF/A-1b` basic PDF, many features restricted
    A1B_2005_PDF_1_4,
    /// `PDF/A-1a` language specification, hierarchical document structure,
    /// character mappings to unicode, descriptive text for images
    A1A_2005_PDF_1_4,
    /// `PDF/A-2:2011` - JPEG compression, transpareny, layering, OpenType fonts
    A2_2011_PDF_1_7,
    /// `PDF/A-2a:2011`
    A2A_2011_PDF_1_7,
    /// `PDF/A-2b:2011`
    A2B_2011_PDF_1_7,
    /// `PDF/A-2u:2011` - requires all text to be Unicode
    A2U_2011_PDF_1_7,
    /// `PDF/A-3` - like A2 but with embedded files (XML, CAD, etc.)
    A3_2012_PDF_1_7,
    /// `PDF/UA-1` extra functions for accessibility (blind, screenreaders, search, dynamic layout)
    UA_2014_PDF_1_6,
    /// `PDF/X-1a:2001` no ICC profiles
    X1A_2001_PDF_1_3,
    /// `PDF/X-3:2002` allows CMYK, spot, calibrated (managed) RGB, CIELAB, + ICC Profiles
    X3_2002_PDF_1_3,
    /// `PDF/X-1a:2003` Revision of `PDF/X-1a:2001` based on PDF 1.4
    X1A_2003_PDF_1_4,
    /// `PDF/X-3:2003` Revision of `PDF/X-3:2002` based on PDF 1.4
    X3_2003_PDF_1_4,
    /// `PDF/X-4:2010` Colour-managed, CMYK, gray, RGB or spot colour data are supported
    /// as well as PDF transparency and optional content (layers)
    X4_2010_PDF_1_4,
    /// `PDF/X-4p:2010` Same as the above X-4:2010, but may reference an ICC profile from
    /// an external file, and it's based on PDF 1.6
    X4P_2010_PDF_1_6,
    /// `PDF/X-5g:2010` An extension of PDF/X-4 that enables the use of external graphical
    /// content. This can be described as OPI-like (Open Prepress Interface) workflows.
    /// Specifically this allows graphics to be referenced that are outside the PDF
    X5G_2010_PDF_1_6,
    /// `PDF/X-5pg` An extension of PDF/X-4p that enables the use of external graphical
    /// content in conjunction with a reference to an external ICC Profile for the output intent.
    X5PG_2010_PDF_1_6,
    /// `PDF/X-5n` An extension of PDF/X-4p that allows the externally supplied ICC
    /// Profile for the output intent to use a color space other than Greyscale, RGB and CMYK.
    X5N_2010_PDF_1_6,
    /// `PDF/E-1:2008` 3D Objects, geospatial, etc.
    E1_2008_PDF_1_6,
    /// `PDF/VT-1:2010` Basically a way to make a incomplete PDF as a template and the RIP program
    /// is set up in a way that it can easily inject data into the PDF, for high-throughput PDFs
    /// (like postcards, stamps), that require customization before printing
    VT_2010_PDF_1_4,
    /// Custom PDF conformance, to allow / disallow options. This allows for making very small
    /// documents, for example
    Custom(CustomPdfConformance),
}

/// Allows building custom conformance profiles. This is useful if you want very small documents for example and 
/// you don't __need__ conformance with any PDF standard, you just want a PDF file.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CustomPdfConformance {
    /// Identifier for this conformance
    /// 
    /// Default: __""__
    pub identifier: String,
    /// Does this standard allow 3d content?
    ///
    /// Default: __false__
    pub allows_3d_content: bool,
    /// Does this standard allow video content?
    ///
    /// Default: __false__
    pub allows_video_content: bool,
    /// Does this standard allow audio content
    ///
    /// Default: __false__
    pub allows_audio_content: bool,
    /// Does this standard allow enbedded JS?
    ///
    /// Default: __false__
    pub allows_embedded_javascript: bool,
    /// Does this standard allow enbedding JPEG files?
    ///
    /// Default: __true__
    pub allows_jpeg_content: bool,
    /// Does this standard require XMP metadata to be set?
    /// 
    /// Default: __true__
    pub requires_xmp_metadata: bool,
    /// Does this standard allow the default PDF fonts (Helvetica, etc.)
    /// 
    /// _(please don't enable this if you do any work that has to be printed accurately)_
    /// 
    /// Default: __false__
    pub allows_default_fonts: bool,
    /// Does this standard require an ICC profile to be embedded for color management?
    /// 
    /// Default: __true__
    pub requires_icc_profile: bool,
    /// Does this standard allow PDF layers?
    /// 
    /// Default: __true__
    pub allows_pdf_layers: bool,
}

impl Default for CustomPdfConformance {
    fn default() -> Self {
        CustomPdfConformance {
            identifier: "".into(),
            allows_3d_content: false,
            allows_video_content: false,
            allows_audio_content: false,
            allows_embedded_javascript: false,
            allows_jpeg_content: true,
            requires_xmp_metadata: true,
            allows_default_fonts: false,
            requires_icc_profile: true,
            allows_pdf_layers: true,
        }
    }
}

impl PdfConformance {

    /// Get the identifier string for PDF
    pub fn get_identifier_string(&self)
    -> String
    {
        // todo: these identifiers might not be correct in all cases
        let identifier = match *self {
            PdfConformance::A1B_2005_PDF_1_4  => "PDF/A-1b:2005",
            PdfConformance::A1A_2005_PDF_1_4  => "PDF/A-1a:2005",
            PdfConformance::A2_2011_PDF_1_7   => "PDF/A-2:2011",
            PdfConformance::A2A_2011_PDF_1_7  => "PDF/A-2a:2011",
            PdfConformance::A2B_2011_PDF_1_7  => "PDF/A-2b:2011",
            PdfConformance::A2U_2011_PDF_1_7  => "PDF/A-2u:2011",
            PdfConformance::A3_2012_PDF_1_7   => "PDF/A-3:2012",
            PdfConformance::UA_2014_PDF_1_6   => "PDF/UA",
            PdfConformance::X1A_2001_PDF_1_3  => "PDF/X-1a:2001",
            PdfConformance::X3_2002_PDF_1_3   => "PDF/X-3:2002",
            PdfConformance::X1A_2003_PDF_1_4  => "PDF/X-1a:2003",
            PdfConformance::X3_2003_PDF_1_4   => "PDF/X-3:2003",
            PdfConformance::X4_2010_PDF_1_4   => "PDF/X-4",
            PdfConformance::X4P_2010_PDF_1_6  => "PDF/X-4P",
            PdfConformance::X5G_2010_PDF_1_6  => "PDF/X-5G",
            PdfConformance::X5PG_2010_PDF_1_6 => "PDF/X-5PG",
            PdfConformance::X5N_2010_PDF_1_6  => "PDF/X-5N",
            PdfConformance::E1_2008_PDF_1_6   => "PDF/E-1",
            PdfConformance::VT_2010_PDF_1_4   => "PDF/VT",
            PdfConformance::Custom(ref c)     => &c.identifier,
        };

        identifier.to_string()
    }

    /// __STUB__: Detects if the PDF has 3D content, but the
    /// conformance to the given PDF standard does not allow it.
    pub fn is_3d_content_allowed(&self)
    -> bool
    {
        match *self {
           PdfConformance::E1_2008_PDF_1_6   => true,
           PdfConformance::Custom(ref c)     => c.allows_3d_content,
           _ => false,
        }
    }

    /// Does this conformance level allow video
    pub fn is_video_content_allowed(&self)
    -> bool
    {
        // todo
        match *self {
            PdfConformance::Custom(ref c) => c.allows_video_content,
            _                             => false,
        }
    }

    /// __STUB__: Detects if the PDF has audio content, but the
    /// conformance to the given PDF standard does not allow it.
    pub fn is_audio_content_allowed(&self)
    -> bool
    {
        // todo
        match *self {
            PdfConformance::Custom(ref c) => c.allows_audio_content,
            _                             => false,
        }
    }

    /// __STUB__: Detects if the PDF has 3D content, but the
    /// conformance to the given PDF standard does not allow it.
    pub fn is_javascript_content_allowed(&self)
    -> bool
    {
        // todo
        match *self {
            PdfConformance::Custom(ref c) => c.allows_embedded_javascript,
            _                         => false,
        }
    }

    /// __STUB__: Detects if the PDF has JPEG images, but the
    /// conformance to the given PDF standard does not allow it
    pub fn is_jpeg_content_allowed(&self)
    -> bool
    {
        // todo
        match *self {
            PdfConformance::Custom(ref c) => c.allows_jpeg_content,
            _                         => true,
        }
    }

    /// Detects if the PDF must have XMP metadata
    /// if it has to conform to the given PDF Standard
    #[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
    pub fn must_have_xmp_metadata(&self)
    -> bool
    {
        match *self {
            PdfConformance::X1A_2001_PDF_1_3  => { true },
            PdfConformance::X3_2002_PDF_1_3   => { true },
            PdfConformance::X1A_2003_PDF_1_4  => { true },
            PdfConformance::X3_2003_PDF_1_4   => { true },
            PdfConformance::X4_2010_PDF_1_4   => { true },
            PdfConformance::X4P_2010_PDF_1_6  => { true },
            PdfConformance::X5G_2010_PDF_1_6  => { true },
            PdfConformance::X5PG_2010_PDF_1_6 => { true },
            PdfConformance::Custom(ref c)     => { c.requires_xmp_metadata }
            _                                 => { false },
        }
    }

    /// Check if the conformance level must have an ICC Profile
    pub fn must_have_icc_profile(&self)
    -> bool
    {
        // todo
        match *self {
            PdfConformance::X1A_2001_PDF_1_3  => { false },
            PdfConformance::Custom(ref c)     => { c.requires_icc_profile }
            _                                 => { true },
        }
    }

    /// __STUB__: Detects if the PDF has layering (optional content groups),
    /// but the conformance to the given PDF standard does not allow it.
    #[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
    pub fn is_layering_allowed(&self)
    -> bool
    {
        match *self {
            PdfConformance::X1A_2001_PDF_1_3  => { false },
            PdfConformance::X3_2002_PDF_1_3   => { false },
            PdfConformance::X1A_2003_PDF_1_4  => { false },
            PdfConformance::X3_2003_PDF_1_4   => { false },
            PdfConformance::Custom(ref c)     => { c.allows_pdf_layers }
            _                                 => { true },
        }
    }
}