Skip to content

Commit

Permalink
PDF/A docs (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
reknih authored Sep 4, 2024
1 parent f809ed8 commit e931e5d
Show file tree
Hide file tree
Showing 11 changed files with 344 additions and 13 deletions.
10 changes: 10 additions & 0 deletions src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,22 +186,32 @@ pub enum ActionType {
/// Go to a destination in another document.
RemoteGoTo,
/// Launch an application.
///
/// This action type is forbidden in PDF/A.
Launch,
/// Open a URI.
Uri,
/// Set an annotation's hidden flag. PDF 1.2+.
SubmitForm,
/// Set form fields to their default values. PDF 1.2+.
///
/// This action type is forbidden in PDF/A.
ResetForm,
/// Import form field values from a file. PDF 1.2+.
///
/// This action type is forbidden in PDF/A.
ImportData,
/// Execute a JavaScript action. PDF 1.2+.
///
/// See Adobe's
/// [JavaScript for Acrobat API Reference](https://opensource.adobe.com/dc-acrobat-sdk-docs/acrobatsdk/pdfs/acrobatsdk_jsapiref.pdf)
/// and ISO 21757.
///
/// This action type is forbidden in PDF/A.
JavaScript,
/// A rendition action to control the playing of multimedia content. PDF 1.5+.
///
/// This action type is forbidden in PDF/A.
Rendition,
}

Expand Down
27 changes: 27 additions & 0 deletions src/annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ impl<'a> Annotation<'a> {
}

/// Write the `/F` attribute.
///
/// Required for all annotations in PDF/A except for `Popup`.
pub fn flags(&mut self, flags: AnnotationFlags) -> &mut Self {
self.pair(Name(b"F"), flags.bits() as i32);
self
Expand All @@ -66,6 +68,8 @@ impl<'a> Annotation<'a> {
/// Start writing the `/AP` dictionary to set how the annotation shall
/// be presented visually. If this dictionary contains sub dictionaries,
/// [`Self::appearance_state`] must be set. PDF 1.2+.
///
/// Required for many annotations in PDF/A.
pub fn appearance(&mut self) -> Appearance<'_> {
self.insert(Name(b"AP")).start()
}
Expand Down Expand Up @@ -147,12 +151,16 @@ impl<'a> Annotation<'a> {

/// Start writing the `/A` dictionary. Only permissible for the subtypes
/// `Link` and `Widget`.
///
/// Note that this attribute is forbidden in PDF/A.
pub fn action(&mut self) -> Action<'_> {
self.insert(Name(b"A")).start()
}

/// Start writing the `/AA` dictionary. Only permissible for the subtype
/// `Widget`. PDF 1.3+.
///
/// Note that this attribute is forbidden in PDF/A.
pub fn additional_actions(&mut self) -> AdditionalActions<'_> {
self.insert(Name(b"AA")).start()
}
Expand Down Expand Up @@ -246,10 +254,15 @@ pub enum AnnotationType {
/// Strike out the text on the page. PDF 1.3+.
StrikeOut,
/// A reference to another file. PDF 1.3+.
///
/// Note that this annotation type is forbidden in PDF/A-1 and restricted in
/// other PDF/A parts.
FileAttachment,
/// A widget annotation. PDF 1.2+.
Widget,
/// A screen annotation. PDF 1.5+.
///
/// Note that this annotation type is forbidden in PDF/A.
Screen,
}

Expand Down Expand Up @@ -326,20 +339,32 @@ bitflags::bitflags! {
/// This will hide the annotation if the viewer does not recognize its
/// subtype. Otherwise, it will be rendered as specified in its appearance
/// stream.
///
/// Must not be set for PDF/A.
const INVISIBLE = 1 << 0;
/// This hides the annotation from view and disallows interaction. PDF 1.2+.
///
/// Must not be set for PDF/A.
const HIDDEN = 1 << 1;
/// Print the annotation. If not set, it will be always hidden on print.
/// PDF 1.2+.
///
/// Must be set for PDF/A.
const PRINT = 1 << 2;
/// Do not zoom the annotation appearance if the document is zoomed in.
/// PDF 1.3+.
///
/// Must be set for text annotations in PDF/A.
const NO_ZOOM = 1 << 3;
/// Do not rotate the annotation appearance if the document is zoomed in.
/// PDF 1.3+.
///
/// Must be set for text annotations in PDF/A.
const NO_ROTATE = 1 << 4;
/// Do not view the annotation on screen. It may still show on print.
/// PDF 1.3+.
///
/// Must not be set for PDF/A.
const NO_VIEW = 1 << 5;
/// Do not allow interactions. PDF 1.3+.
const READ_ONLY = 1 << 6;
Expand All @@ -348,6 +373,8 @@ bitflags::bitflags! {
const LOCKED = 1 << 7;
/// Invert the interpretation of the `no_view` flag for certain events.
/// PDF 1.5+.
///
/// Must not be set for PDF/A.
const TOGGLE_NO_VIEW = 1 << 8;
/// Do not allow content changes. PDF 1.7+.
const LOCKED_CONTENTS = 1 << 9;
Expand Down
14 changes: 12 additions & 2 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,11 @@ impl ColorSpace<'_> {
}

/// Device color spaces.
///
/// Please note that the use of the device color spaces is restricted by several
/// PDF standards such as PDF/A, PDF/X, et cetera. Their appearance will be
/// governed by any applicable [output intent](crate::writers::OutputIntent) and
/// default color spaces.
impl ColorSpace<'_> {
/// Write a `DeviceRGB` color space.
pub fn device_rgb(self) {
Expand Down Expand Up @@ -647,7 +652,8 @@ impl DeviceNAttrs<'_> {
/// Start writing the `/Colorants` dictionary. Its keys are the colorant
/// names and its values are separation color space arrays.
///
/// Required if the `/Subtype` attribute is `NChannel`.
/// Required if the `/Subtype` attribute is `NChannel`. Required for spot
/// colors in PDF/A-2, PDF/A-3, and PDF/A-4.
pub fn colorants(&mut self) -> TypedDict<'_, Dict> {
self.dict.insert(Name(b"Colorants")).dict().typed()
}
Expand Down Expand Up @@ -1234,7 +1240,7 @@ impl SeparationInfo<'_> {
/// Writer for an _output intent dictionary_. PDF 1.4+.
///
/// This describes the output conditions under which the document may be
/// rendered.
/// rendered. Encouraged by PDF/A.
pub struct OutputIntent<'a> {
dict: Dict<'a>,
}
Expand Down Expand Up @@ -1289,6 +1295,8 @@ impl OutputIntent<'_> {
/// Required if `/OutputConditionIdentifier` does not contain a well-known
/// identifier for the output condition.
/// Must reference an [ICC profile](IccProfile) stream.
///
/// Required for PDF/A. The profile must have the `prtr` or `mntr` tag.
pub fn dest_output_profile(&mut self, profile: Ref) -> &mut Self {
self.dict.pair(Name(b"DestOutputProfile"), profile);
self
Expand All @@ -1300,6 +1308,8 @@ pub enum OutputIntentSubtype<'a> {
/// `GTS_PDFX`
PDFX,
/// `GTS_PDFA1`
///
/// This is the right value for PDF/A-1 through PDF/A-4.
PDFA,
/// `ISO_PDFE1`
PDFE,
Expand Down
25 changes: 24 additions & 1 deletion src/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ impl Content {
}
}

// TODO: Inline images.
// TODO: Inline images. Also check clause 6.1.10 of PDF/A-2 spec.

/// XObjects.
impl Content {
Expand Down Expand Up @@ -992,6 +992,8 @@ impl<'a> PropertyList<'a> {
deref!('a, PropertyList<'a> => Dict<'a>, dict);

/// Writer for an _actifact property list dictionary_. PDF 1.4+.
///
/// Required for marking up pagination artifacts in some PDF/A profiles.
pub struct Artifact<'a> {
dict: Dict<'a>,
}
Expand Down Expand Up @@ -1342,6 +1344,8 @@ impl<'a> ExtGraphicsState<'a> {

/// Write the `OPM` attribute to set the overprint mode for components that
/// have been zeroed out. PDF 1.3+.
///
/// Note that this attribute is restricted by PDF/A.
pub fn overprint_mode(&mut self, mode: OverprintMode) -> &mut Self {
self.pair(Name(b"OPM"), mode.to_int());
self
Expand Down Expand Up @@ -1385,6 +1389,8 @@ impl<'a> ExtGraphicsState<'a> {
}

/// Write the `TR` attribute to set the transfer function.
///
/// Note that this key is illegal in PDF/A.
pub fn transfer(&mut self, func: Ref) -> &mut Self {
self.pair(Name(b"TR"), func);
self
Expand All @@ -1398,6 +1404,8 @@ impl<'a> ExtGraphicsState<'a> {
}

/// Write the `HT` attribute to set the halftone.
///
/// Note that this value may be ignored in PDF/A.
pub fn halftone(&mut self, ht: Ref) -> &mut Self {
self.pair(Name(b"HT"), ht);
self
Expand All @@ -1411,6 +1419,8 @@ impl<'a> ExtGraphicsState<'a> {
}

/// Write the `FL` attribute to set the flatness tolerance. PDF 1.3+.
///
/// Note that this key may be ignored in PDF/A.
pub fn flatness(&mut self, tolerance: f32) -> &mut Self {
self.pair(Name(b"FL"), tolerance);
self
Expand All @@ -1429,30 +1439,40 @@ impl<'a> ExtGraphicsState<'a> {
}

/// Write the `BM` attribute to set the blend mode. PDF 1.4+.
///
/// Note that this key is restricted in PDF/A-1.
pub fn blend_mode(&mut self, mode: BlendMode) -> &mut Self {
self.pair(Name(b"BM"), mode.to_name());
self
}

/// Start writing the `SMask` attribute. PDF 1.4+.
///
/// Note that this key is forbidden in PDF/A-1.
pub fn soft_mask(&mut self) -> SoftMask<'_> {
self.insert(Name(b"SMask")).start()
}

/// Write the `SMask` attribute using a name. PDF 1.4+.
///
/// Note that this key is forbidden in PDF/A-1.
pub fn soft_mask_name(&mut self, mask: Name) -> &mut Self {
self.pair(Name(b"SMask"), mask);
self
}

/// Write the `CA` attribute to set the stroking alpha constant. PDF 1.4+.
///
/// Note that this key is restricted in PDF/A-1.
pub fn stroking_alpha(&mut self, alpha: f32) -> &mut Self {
self.pair(Name(b"CA"), alpha);
self
}

/// Write the `ca` attribute to set the non-stroking alpha constant. PDF
/// 1.4+.
///
/// Note that this key is restricted in PDF/A-1.
pub fn non_stroking_alpha(&mut self, alpha: f32) -> &mut Self {
self.pair(Name(b"ca"), alpha);
self
Expand Down Expand Up @@ -1529,6 +1549,9 @@ pub enum OverprintMode {
/// An overprint operation will only discard the underlying colorant
/// component (e.g. cyan in CMYK) if the new corresponding colorant is
/// non-zero.
///
/// Note that this value is forbidden by PDF/A for ICCBased color spaces
/// when overprinting is enabled.
IgnoreZeroChannel,
}

Expand Down
5 changes: 4 additions & 1 deletion src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ impl<'a> FileSpec<'a> {
///
/// This only sets an embedded file for the `F` attribute corresponding to
/// the [`path`](Self::path) method. You will need to write this dictionary
/// manually if you need to set `UF`.
/// manually if you need to set `UF` which is required in PDF/A-3.
///
/// Note that this key is forbidden in PDF/A-1 and restricted in PDF/A-2 and
/// PDF/A-4.
pub fn embedded_file(&mut self, id: Ref) -> &mut Self {
self.insert(Name(b"EF")).dict().pair(Name(b"F"), id);
self
Expand Down
Loading

0 comments on commit e931e5d

Please sign in to comment.