1use crate::annotation::Annotation;
4use crate::types::*;
5use pdf_syntax::object::dict::keys::*;
6use pdf_syntax::object::{Array, Dict, Name, Rect};
7
8#[derive(Debug)]
10pub struct LineAnnotation {
11 pub endpoints: Option<[f32; 4]>,
13 pub line_endings: (LineEnding, LineEnding),
15 pub caption: bool,
17 pub caption_offset: Option<[f32; 2]>,
19 pub leader_line: f32,
21 pub leader_line_extension: f32,
23 pub leader_line_offset: f32,
25}
26
27impl LineAnnotation {
28 pub fn from_annot(annot: &Annotation<'_>) -> Self {
30 let dict = annot.dict();
31 let endpoints = dict.get::<Array<'_>>(L).and_then(|arr| {
32 let mut iter = arr.iter::<f32>();
33 Some([iter.next()?, iter.next()?, iter.next()?, iter.next()?])
34 });
35 let line_endings = parse_line_endings(dict);
36 let caption = dict.get::<bool>(CAP).unwrap_or(false);
37 let caption_offset = dict.get::<Array<'_>>(CO).and_then(|arr| {
38 let mut iter = arr.iter::<f32>();
39 Some([iter.next()?, iter.next()?])
40 });
41 let leader_line = dict.get::<f32>(LL).unwrap_or(0.0);
42 let leader_line_extension = dict.get::<f32>(LLE).unwrap_or(0.0);
43 let leader_line_offset = dict.get::<f32>(LLO).unwrap_or(0.0);
44 Self {
45 endpoints,
46 line_endings,
47 caption,
48 caption_offset,
49 leader_line,
50 leader_line_extension,
51 leader_line_offset,
52 }
53 }
54}
55
56#[derive(Debug)]
58pub struct SquareCircleAnnotation {
59 pub is_circle: bool,
61 pub rd: Option<Rect>,
63}
64
65impl SquareCircleAnnotation {
66 pub fn from_annot(annot: &Annotation<'_>) -> Self {
68 let is_circle = annot.annotation_type() == AnnotationType::Circle;
69 let rd = annot.dict().get::<Rect>(RD);
70 Self { is_circle, rd }
71 }
72}
73
74#[derive(Debug)]
76pub struct PolygonAnnotation {
77 pub closed: bool,
79 pub vertices: Vec<f32>,
81 pub line_endings: (LineEnding, LineEnding),
83}
84
85impl PolygonAnnotation {
86 pub fn from_annot(annot: &Annotation<'_>) -> Self {
88 let dict = annot.dict();
89 let closed = annot.annotation_type() == AnnotationType::Polygon;
90 let vertices = dict
91 .get::<Array<'_>>(VERTICES)
92 .map(|arr| arr.iter::<f32>().collect())
93 .unwrap_or_default();
94 let line_endings = parse_line_endings(dict);
95 Self {
96 closed,
97 vertices,
98 line_endings,
99 }
100 }
101}
102
103#[derive(Debug)]
105pub struct InkAnnotation {
106 pub ink_list: Vec<Vec<f32>>,
108}
109
110impl InkAnnotation {
111 pub fn from_annot(annot: &Annotation<'_>) -> Self {
113 let dict = annot.dict();
114 let ink_list = dict
115 .get::<Array<'_>>(INKLIST)
116 .map(|outer| {
117 outer
118 .iter::<Array<'_>>()
119 .map(|inner| inner.iter::<f32>().collect())
120 .collect()
121 })
122 .unwrap_or_default();
123 Self { ink_list }
124 }
125}
126
127fn parse_line_endings(dict: &Dict<'_>) -> (LineEnding, LineEnding) {
129 dict.get::<Array<'_>>(LE)
130 .and_then(|arr| {
131 let mut iter = arr.iter::<Name>();
132 let start = iter.next().map(|n| LineEnding::from_name(n.as_ref()))?;
133 let end = iter.next().map(|n| LineEnding::from_name(n.as_ref()))?;
134 Some((start, end))
135 })
136 .unwrap_or((LineEnding::None, LineEnding::None))
137}