Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 20 additions & 49 deletions crates/pdf-annotation-types/src/action.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use pdf_object::{
dictionary::Dictionary, error::ObjectError, object_resolver::ObjectResolver,
object_variant::ObjectVariant,
dictionary::Dictionary, error::ObjectError, object_lookup::ObjectLookupExt,
object_resolver::ObjectResolver, object_variant::ObjectVariant,
};

use crate::{
Expand Down Expand Up @@ -108,17 +108,11 @@ impl AnnotationAction {
key: &'static str,
objects: &dyn ObjectResolver,
) -> Result<Option<Self>, AnnotationError> {
let Some(value) = dictionary.get(key) else {
let Some(action_dictionary) = dictionary.optional_dictionary(key, objects)? else {
return Ok(None);
};

let action_dictionary = value.try_dictionary(objects)?.clone();
let action_type = action_dictionary
.get_or_err("S")?
.try_str(objects)?
.into_owned();

let action = match action_type.as_ref() {
let action = match action_dictionary.required_str("S", objects)? {
"GoTo" => Self::GoTo {
destination: AnnotationDestination::from_object(
action_dictionary.get_or_err("D")?,
Expand All @@ -135,23 +129,15 @@ impl AnnotationAction {
.get("D")
.map(|value| AnnotationDestination::from_object(value, "D", objects))
.transpose()?,
new_window: action_dictionary
.get("NewWindow")
.map(|value| value.try_boolean(objects))
.transpose()?,
new_window: action_dictionary.optional_boolean("NewWindow", objects)?,
},
"URI" => Self::Uri {
uri: action_dictionary
.get_or_err("URI")?
.try_bytes_vec(objects)?,
is_map: action_dictionary
.get("IsMap")
.map(|value| value.try_boolean(objects))
.transpose()?,
uri: action_dictionary.required_bytes_vec("URI", objects)?,
is_map: action_dictionary.optional_boolean("IsMap", objects)?,
},
"Launch" => Self::Launch {
file_specification: FileSpecification::from_dictionary(
&action_dictionary,
action_dictionary,
"F",
objects,
)?,
Expand All @@ -161,26 +147,20 @@ impl AnnotationAction {
.transpose()?,
},
"Named" => Self::Named {
name: action_dictionary.get_or_err("N")?.try_bytes_vec(objects)?,
name: action_dictionary.required_bytes_vec("N", objects)?,
},
"SubmitForm" => Self::SubmitForm {
file_specification: FileSpecification::from_dictionary(
&action_dictionary,
action_dictionary,
"F",
objects,
)?,
fields: name_list(&action_dictionary, "Fields", objects)?,
flags: action_dictionary
.get("Flags")
.map(|value| value.try_number::<i32>(objects))
.transpose()?,
fields: name_list(action_dictionary, "Fields", objects)?,
flags: action_dictionary.optional_number::<i32>("Flags", objects)?,
},
"ResetForm" => Self::ResetForm {
fields: name_list(&action_dictionary, "Fields", objects)?,
flags: action_dictionary
.get("Flags")
.map(|value| value.try_number::<i32>(objects))
.transpose()?,
fields: name_list(action_dictionary, "Fields", objects)?,
flags: action_dictionary.optional_number::<i32>("Flags", objects)?,
},
"ImportData" => Self::ImportData {
file_specification: FileSpecification::from_object(
Expand All @@ -192,31 +172,22 @@ impl AnnotationAction {
script: javascript_bytes(action_dictionary.get_or_err("JS")?, objects)?,
},
"SetOCGState" => Self::SetOCGState {
state: name_list(&action_dictionary, "State", objects)?.unwrap_or_default(),
preserve_rb: action_dictionary
.get("PreserveRB")
.map(|value| value.try_boolean(objects))
.transpose()?,
state: name_list(action_dictionary, "State", objects)?.unwrap_or_default(),
preserve_rb: action_dictionary.optional_boolean("PreserveRB", objects)?,
},
"Rendition" => Self::Rendition {
operation: action_dictionary
.get("OP")
.map(|value| value.try_number::<i32>(objects))
.transpose()?,
rendition: Rendition::from_dictionary(&action_dictionary, objects)?,
operation: action_dictionary.optional_number::<i32>("OP", objects)?,
rendition: Rendition::from_dictionary(action_dictionary, objects)?,
},
"Trans" => Self::Trans {
transition: action_dictionary
.get("Trans")
.map(|value| helpers::dictionary(value, objects))
.transpose()?,
duration: action_dictionary
.get("D")
.map(|value| value.try_number::<f32>(objects))
.transpose()?,
duration: action_dictionary.optional_number::<f32>("D", objects)?,
},
"GoTo3DView" => Self::GoTo3DView {
view: three_d_view(&action_dictionary, "TA", objects)?,
view: three_d_view(action_dictionary, "TA", objects)?,
},
other => Self::Unknown {
action_type: other.to_owned(),
Expand Down
38 changes: 12 additions & 26 deletions crates/pdf-annotation-types/src/annotation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use pdf_content_stream::ContentStreamIdAllocator;
use pdf_graphics::rect::Rect;
use pdf_object::{dictionary::Dictionary, object_resolver::ObjectResolver};
use pdf_object::{
dictionary::Dictionary, object_lookup::ObjectLookupExt, object_resolver::ObjectResolver,
};
use pdf_resources::{object_reader::ReadCycleTracker, resource_cache::ResourceCache};

use crate::{
Expand Down Expand Up @@ -82,8 +84,8 @@ impl Annotation {
// Some PDFs omit `/Type` on annotation dictionaries even though the
// entry is nominally expected to be `/Annot`, so only validate it when
// the key is actually present.
if let Some(annotation_type) = dictionary.get("Type") {
match annotation_type.try_str(objects)?.as_ref() {
if let Some(annotation_type) = dictionary.optional_str("Type", objects)? {
match annotation_type {
"Annot" => {}
other => {
return Err(AnnotationError::InvalidEntry {
Expand All @@ -96,10 +98,7 @@ impl Annotation {

// `/Subtype` identifies the concrete annotation kind and is required
// for dispatching to the subtype-specific parser.
let subtype = dictionary
.get_or_err("Subtype")?
.try_str(objects)?
.into_owned();
let subtype = dictionary.required_str("Subtype", objects)?.to_owned();

let rect = dictionary
.get("Rect")
Expand All @@ -118,26 +117,13 @@ impl Annotation {

let kind = AnnotationKind::from_dictionary(&subtype, dictionary, objects)?;

let contents = dictionary
.get("Contents")
.map(|value| value.try_bytes_vec(objects))
.transpose()?;
let name = dictionary
.get("NM")
.map(|value| value.try_bytes_vec(objects))
.transpose()?;
let flags = dictionary
.get("F")
.map(|value| value.try_number::<i32>(objects))
.transpose()?;
let contents = dictionary.optional_bytes_vec("Contents", objects)?;
let name = dictionary.optional_bytes_vec("NM", objects)?;
let flags = dictionary.optional_number::<i32>("F", objects)?;
let appearance_state = dictionary
.get("AS")
.map(|value| value.try_str(objects).map(|s| s.into_owned()))
.transpose()?;
let struct_parent = dictionary
.get("StructParent")
.map(|value| value.try_number::<usize>(objects))
.transpose()?;
.optional_str("AS", objects)?
.map(|s| s.to_owned());
let struct_parent = dictionary.optional_number::<usize>("StructParent", objects)?;

let appearance = AppearanceDictionary::from_dictionary(
dictionary,
Expand Down
9 changes: 5 additions & 4 deletions crates/pdf-annotation-types/src/annotation_border.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use pdf_object::{dictionary::Dictionary, object_resolver::ObjectResolver};
use pdf_object::{
dictionary::Dictionary, object_lookup::ObjectLookupExt, object_resolver::ObjectResolver,
};

use crate::AnnotationError;

Expand All @@ -19,12 +21,11 @@ impl AnnotationBorder {
dictionary: &Dictionary,
objects: &dyn ObjectResolver,
) -> Result<Option<Self>, AnnotationError> {
let Some(value) = dictionary.get("Border") else {
let Some(value) = dictionary.optional_array("Border", objects)? else {
return Ok(None);
};

let [horizontal_radius, vertical_radius, width, rest @ ..] = value.try_array(objects)?
else {
let [horizontal_radius, vertical_radius, width, rest @ ..] = value else {
return Err(AnnotationError::InvalidEntry {
entry: "Border",
reason: "expected an array with at least 3 numbers".to_owned(),
Expand Down
24 changes: 7 additions & 17 deletions crates/pdf-annotation-types/src/appearance_characteristics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use pdf_object::{dictionary::Dictionary, object_resolver::ObjectResolver};
use pdf_object::{
dictionary::Dictionary, object_lookup::ObjectLookupExt, object_resolver::ObjectResolver,
};

use crate::{AnnotationColor, AnnotationError};

Expand Down Expand Up @@ -28,24 +30,12 @@ impl AppearanceCharacteristics {
};

let dictionary = value.try_dictionary(objects)?;
let rotation = dictionary
.get("R")
.map(|value| value.try_number::<i32>(objects))
.transpose()?;
let rotation = dictionary.optional_number::<i32>("R", objects)?;
let border_color = AnnotationColor::from_dictionary(dictionary, "BC", objects)?;
let background_color = AnnotationColor::from_dictionary(dictionary, "BG", objects)?;
let normal_caption = dictionary
.get("CA")
.map(|value| value.try_bytes_vec(objects))
.transpose()?;
let rollover_caption = dictionary
.get("RC")
.map(|value| value.try_bytes_vec(objects))
.transpose()?;
let alternate_caption = dictionary
.get("AC")
.map(|value| value.try_bytes_vec(objects))
.transpose()?;
let normal_caption = dictionary.optional_bytes_vec("CA", objects)?;
let rollover_caption = dictionary.optional_bytes_vec("RC", objects)?;
let alternate_caption = dictionary.optional_bytes_vec("AC", objects)?;

Ok(Some(Self {
rotation,
Expand Down
15 changes: 5 additions & 10 deletions crates/pdf-annotation-types/src/border_effect.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use pdf_object::{dictionary::Dictionary, object_resolver::ObjectResolver};
use pdf_object::{
dictionary::Dictionary, object_lookup::ObjectLookupExt, object_resolver::ObjectResolver,
};

use crate::{AnnotationError, BorderEffectStyle};

Expand All @@ -23,16 +25,9 @@ impl BorderEffect {
let dictionary = value.try_dictionary(objects)?;
let style = dictionary
.get("S")
.map(|value| {
value
.try_str(objects)
.map(|name| BorderEffectStyle::from(name.as_ref()))
})
.transpose()?;
let intensity = dictionary
.get("I")
.map(|value| value.try_number::<f32>(objects))
.map(|value| value.try_str(objects).map(BorderEffectStyle::from))
.transpose()?;
let intensity = dictionary.optional_number::<f32>("I", objects)?;

Ok(Some(Self { style, intensity }))
}
Expand Down
20 changes: 6 additions & 14 deletions crates/pdf-annotation-types/src/border_style.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use pdf_object::{dictionary::Dictionary, object_resolver::ObjectResolver};
use pdf_object::{
dictionary::Dictionary, object_lookup::ObjectLookupExt, object_resolver::ObjectResolver,
};

use crate::{AnnotationError, BorderStyleName};

Expand All @@ -23,22 +25,12 @@ impl BorderStyle {
};

let dictionary = value.try_dictionary(objects)?;
let width = dictionary
.get("W")
.map(|value| value.try_number::<f32>(objects))
.transpose()?;
let width = dictionary.optional_number::<f32>("W", objects)?;
let style = dictionary
.get("S")
.map(|value| {
value
.try_str(objects)
.map(|name| BorderStyleName::from(name.as_ref()))
})
.transpose()?;
let dash_pattern = dictionary
.get("D")
.map(|value| value.try_vec_of::<f32>(objects))
.map(|value| value.try_str(objects).map(BorderStyleName::from))
.transpose()?;
let dash_pattern = dictionary.optional_vec_of::<f32>("D", objects)?;

Ok(Some(Self {
width,
Expand Down
Loading
Loading