Skip to content

Commit

Permalink
Adopt the Appearance Streams implementation from PR typst#25 (typst#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
awehrfritz committed Feb 12, 2024
1 parent 9d308f1 commit 8cb4be1
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 15 deletions.
2 changes: 1 addition & 1 deletion examples/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ fn main() -> std::io::Result<()> {
annotation.subtype(AnnotationType::Screen);
annotation.rect(bbox);
annotation.page(page_id);
annotation.normal_appearance(form_xobject_id);
annotation.appearance().normal().stream(form_xobject_id);

// Write a rendition action for the screen annotation.
let mut action = annotation.action();
Expand Down
88 changes: 75 additions & 13 deletions src/annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,14 @@ impl<'a> Annotation<'a> {
self
}

/// Write the `/P` attribute to provide a reference to the page object with
/// which this annotation is associated. Required and only permissible for
/// the subtype `Screen`. PDF 1.5+.
/// Write the `/P` attribute. This provides an indirect reference to the
/// page object with which this annotation is associated. Required for the
/// subtype `Screen` associated with rendition actions. PDF 1.3+.
pub fn page(&mut self, id: Ref) -> &mut Self {
self.pair(Name(b"P"), id);
self
}

/// Write the `/N` attribute inside the `/AP` dictionary to provide the
/// visual appearance for a screen annotation. For now, this sets only the
/// normal appearance as a reference to a [`FormXObject`]. Only permissible
/// for the subtype `Screen`. PDF 1.5+.
pub fn normal_appearance(&mut self, id: Ref) -> &mut Self {
self.insert(Name(b"AP")).dict()
.pair(Name(b"N"), id);
self
}

/// Write the `/NM` attribute. This uniquely identifies the annotation on the
/// page. PDF 1.3+.
pub fn name(&mut self, text: TextStr) -> &mut Self {
Expand All @@ -73,6 +63,21 @@ impl<'a> Annotation<'a> {
self
}

/// 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+.
pub fn appearance(&mut self) -> Appearance<'_> {
self.insert(Name(b"AP")).start()
}

/// Write the `/AS` attribute to set the annotation's current appearance
/// state from the `/AP` subdictionary. Must be set if [`Self::appearance`]
/// has one or more subdictionaries. PDF 1.2+.
pub fn appearance_state(&mut self, name: Name) -> &mut Self {
self.pair(Name(b"AS"), name);
self
}

/// Write the `/Border` attribute. This describes the look of the border
/// around the annotation, including width and horizontal and vertical
/// border radii. The function may also receive a dash pattern which
Expand Down Expand Up @@ -621,6 +626,63 @@ impl HighlightEffect {
}
}

/// Writer for an _appearance dictionary_.
///
/// This struct is created by [`Annotation::appearance`].
pub struct Appearance<'a> {
dict: Dict<'a>,
}

writer!(Appearance: |obj| Self { dict: obj.dict() });

impl<'a> Appearance<'a> {
/// Start writing the `/N` stream or dictionary to set the annotation's
/// normal appearance.
pub fn normal(&mut self) -> AppearanceEntry<'_> {
self.insert(Name(b"N")).start()
}

/// Start writing the `/R` stream or dictionary to set the annotation's
/// rollover (hover) appearance.
pub fn rollover(&mut self) -> AppearanceEntry<'_> {
self.insert(Name(b"R")).start()
}

/// Start writing the `/D` stream or dictionary to set the annotation's
/// alternate (down) appearance.
pub fn alternate(&mut self) -> AppearanceEntry<'_> {
self.insert(Name(b"D")).start()
}
}

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

/// Writer for an _appearance stream_ or an _appearance subdictionary_.
///
/// This struct is created by [`Appearance::normal`], [`Appearance::rollover`]
/// and [`Appearance::alternate`].
pub struct AppearanceEntry<'a> {
obj: Obj<'a>,
}

writer!(AppearanceEntry: |obj| Self { obj });

impl<'a> AppearanceEntry<'a> {
/// Write an indirect reference to a [`FormXObject`] containing the
/// appearance stream.
pub fn stream(self, id: Ref) {
self.obj.primitive(id);
}

/// Start writing an appearance subdictionary containing indirect references
/// to [`FormXObject`]s for each appearance state.
pub fn streams(self) -> TypedDict<'a, Ref> {
self.obj.dict().typed()
}
}

deref!('a, AppearanceEntry<'a> => Obj<'a>, obj);

/// Writer for an _border style dictionary_.
///
/// This struct is created by [`Annotation::border_style`].
Expand Down
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ mod xobject;
pub mod writers {
use super::*;
pub use actions::{Action, AdditionalActions, Fields};
pub use annotations::{Annotation, AppearanceCharacteristics, BorderStyle, IconFit};
pub use annotations::{
Annotation, Appearance, AppearanceCharacteristics, AppearanceEntry, BorderStyle,
IconFit,
};
pub use attributes::{
Attributes, FieldAttributes, LayoutAttributes, ListAttributes, TableAttributes,
UserProperty,
Expand Down

0 comments on commit 8cb4be1

Please sign in to comment.