1use pdf_syntax::object::dict::keys::*;
4use pdf_syntax::object::{Array, Dict, Name, Rect};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum AnnotationType {
9 Text,
11 Link,
13 FreeText,
15 Line,
17 Square,
19 Circle,
21 Polygon,
23 PolyLine,
25 Highlight,
27 Underline,
29 Squiggly,
31 StrikeOut,
33 Stamp,
35 Caret,
37 Ink,
39 Popup,
41 FileAttachment,
43 Sound,
45 Widget,
47 Watermark,
49 Redact,
51 Movie,
53 Unknown,
55}
56
57impl AnnotationType {
58 pub fn from_name(name: &[u8]) -> Self {
60 match name {
61 b"Text" => Self::Text,
62 b"Link" => Self::Link,
63 b"FreeText" => Self::FreeText,
64 b"Line" => Self::Line,
65 b"Square" => Self::Square,
66 b"Circle" => Self::Circle,
67 b"Polygon" => Self::Polygon,
68 b"PolyLine" => Self::PolyLine,
69 b"Highlight" => Self::Highlight,
70 b"Underline" => Self::Underline,
71 b"Squiggly" => Self::Squiggly,
72 b"StrikeOut" => Self::StrikeOut,
73 b"Stamp" => Self::Stamp,
74 b"Caret" => Self::Caret,
75 b"Ink" => Self::Ink,
76 b"Popup" => Self::Popup,
77 b"FileAttachment" => Self::FileAttachment,
78 b"Sound" => Self::Sound,
79 b"Widget" => Self::Widget,
80 b"Watermark" => Self::Watermark,
81 b"Redact" => Self::Redact,
82 b"Movie" => Self::Movie,
83 _ => Self::Unknown,
84 }
85 }
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub struct AnnotationFlags(pub u32);
91
92impl AnnotationFlags {
93 pub fn invisible(&self) -> bool {
95 self.0 & (1 << 0) != 0
96 }
97 pub fn hidden(&self) -> bool {
99 self.0 & (1 << 1) != 0
100 }
101 pub fn print(&self) -> bool {
103 self.0 & (1 << 2) != 0
104 }
105 pub fn no_zoom(&self) -> bool {
107 self.0 & (1 << 3) != 0
108 }
109 pub fn no_rotate(&self) -> bool {
111 self.0 & (1 << 4) != 0
112 }
113 pub fn no_view(&self) -> bool {
115 self.0 & (1 << 5) != 0
116 }
117 pub fn read_only(&self) -> bool {
119 self.0 & (1 << 6) != 0
120 }
121 pub fn locked(&self) -> bool {
123 self.0 & (1 << 7) != 0
124 }
125 pub fn toggle_no_view(&self) -> bool {
127 self.0 & (1 << 8) != 0
128 }
129 pub fn locked_contents(&self) -> bool {
131 self.0 & (1 << 9) != 0
132 }
133}
134
135#[derive(Debug, Clone)]
137pub struct BorderStyle {
138 pub width: f32,
140 pub style: BorderStyleType,
142 pub dash_pattern: Vec<f32>,
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq)]
148pub enum BorderStyleType {
149 Solid,
151 Dashed,
153 Beveled,
155 Inset,
157 Underline,
159}
160
161impl BorderStyle {
162 pub fn from_dict(dict: &Dict<'_>) -> Self {
164 let width = dict.get::<f32>(W).unwrap_or(1.0);
165 let style = dict
166 .get::<Name>(S)
167 .map(|n| match n.as_ref() {
168 b"D" => BorderStyleType::Dashed,
169 b"B" => BorderStyleType::Beveled,
170 b"I" => BorderStyleType::Inset,
171 b"U" => BorderStyleType::Underline,
172 _ => BorderStyleType::Solid,
173 })
174 .unwrap_or(BorderStyleType::Solid);
175 let dash_pattern = dict
176 .get::<Array<'_>>(D)
177 .map(|arr| arr.iter::<f32>().collect())
178 .unwrap_or_else(|| vec![3.0]);
179 Self {
180 width,
181 style,
182 dash_pattern,
183 }
184 }
185}
186
187#[derive(Debug, Clone)]
189pub enum Color {
190 Transparent,
192 Gray(f32),
194 Rgb(f32, f32, f32),
196 Cmyk(f32, f32, f32, f32),
198}
199
200impl Color {
201 pub fn from_array(arr: &Array<'_>) -> Self {
203 let values: Vec<f32> = arr.iter::<f32>().collect();
204 match values.len() {
205 0 => Self::Transparent,
206 1 => Self::Gray(values[0]),
207 3 => Self::Rgb(values[0], values[1], values[2]),
208 4 => Self::Cmyk(values[0], values[1], values[2], values[3]),
209 _ => Self::Transparent,
210 }
211 }
212}
213
214#[derive(Debug, Clone)]
216pub struct BorderEffect {
217 pub style: BorderEffectStyle,
219 pub intensity: f32,
221}
222
223#[derive(Debug, Clone, Copy, PartialEq, Eq)]
225pub enum BorderEffectStyle {
226 None,
228 Cloudy,
230}
231
232impl BorderEffect {
233 pub fn from_dict(dict: &Dict<'_>) -> Self {
235 let style = dict
236 .get::<Name>(S)
237 .map(|n| match n.as_ref() {
238 b"C" => BorderEffectStyle::Cloudy,
239 _ => BorderEffectStyle::None,
240 })
241 .unwrap_or(BorderEffectStyle::None);
242 let intensity = dict.get::<f32>(I).unwrap_or(0.0);
243 Self { style, intensity }
244 }
245}
246
247#[derive(Debug, Clone)]
249pub struct QuadPoints {
250 pub points: Vec<f32>,
252}
253
254impl QuadPoints {
255 pub fn from_array(arr: &Array<'_>) -> Self {
257 Self {
258 points: arr.iter::<f32>().collect(),
259 }
260 }
261
262 pub fn bounding_rects(&self) -> Vec<Rect> {
264 self.points
265 .chunks_exact(8)
266 .map(|chunk| {
267 let xs = [chunk[0], chunk[2], chunk[4], chunk[6]];
268 let ys = [chunk[1], chunk[3], chunk[5], chunk[7]];
269 let x0 = xs.iter().copied().reduce(f32::min).unwrap_or(0.0) as f64;
270 let y0 = ys.iter().copied().reduce(f32::min).unwrap_or(0.0) as f64;
271 let x1 = xs.iter().copied().reduce(f32::max).unwrap_or(0.0) as f64;
272 let y1 = ys.iter().copied().reduce(f32::max).unwrap_or(0.0) as f64;
273 Rect::new(x0, y0, x1, y1)
274 })
275 .collect()
276 }
277}
278
279#[derive(Debug, Clone, Copy, PartialEq, Eq)]
281pub enum LineEnding {
282 None,
284 Square,
286 Circle,
288 Diamond,
290 OpenArrow,
292 ClosedArrow,
294 Butt,
296 ROpenArrow,
298 RClosedArrow,
300 Slash,
302}
303
304impl LineEnding {
305 pub fn from_name(name: &[u8]) -> Self {
307 match name {
308 b"Square" => Self::Square,
309 b"Circle" => Self::Circle,
310 b"Diamond" => Self::Diamond,
311 b"OpenArrow" => Self::OpenArrow,
312 b"ClosedArrow" => Self::ClosedArrow,
313 b"Butt" => Self::Butt,
314 b"ROpenArrow" => Self::ROpenArrow,
315 b"RClosedArrow" => Self::RClosedArrow,
316 b"Slash" => Self::Slash,
317 _ => Self::None,
318 }
319 }
320}