1use pdf_syntax::object::dict::keys::*;
10use pdf_syntax::object::{Array, Dict, Name, Rect};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum AnnotationType {
15 Text,
17 Link,
19 FreeText,
21 Line,
23 Square,
25 Circle,
27 Polygon,
29 PolyLine,
31 Highlight,
33 Underline,
35 Squiggly,
37 StrikeOut,
39 Stamp,
41 Caret,
43 Ink,
45 Popup,
47 FileAttachment,
49 Sound,
51 Widget,
53 Watermark,
55 Redact,
57 Movie,
59 Unknown,
61}
62
63impl AnnotationType {
64 pub fn from_name(name: &[u8]) -> Self {
66 match name {
67 b"Text" => Self::Text,
68 b"Link" => Self::Link,
69 b"FreeText" => Self::FreeText,
70 b"Line" => Self::Line,
71 b"Square" => Self::Square,
72 b"Circle" => Self::Circle,
73 b"Polygon" => Self::Polygon,
74 b"PolyLine" => Self::PolyLine,
75 b"Highlight" => Self::Highlight,
76 b"Underline" => Self::Underline,
77 b"Squiggly" => Self::Squiggly,
78 b"StrikeOut" => Self::StrikeOut,
79 b"Stamp" => Self::Stamp,
80 b"Caret" => Self::Caret,
81 b"Ink" => Self::Ink,
82 b"Popup" => Self::Popup,
83 b"FileAttachment" => Self::FileAttachment,
84 b"Sound" => Self::Sound,
85 b"Widget" => Self::Widget,
86 b"Watermark" => Self::Watermark,
87 b"Redact" => Self::Redact,
88 b"Movie" => Self::Movie,
89 _ => Self::Unknown,
90 }
91 }
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq)]
96pub struct AnnotationFlags(pub u32);
97
98impl AnnotationFlags {
99 pub fn invisible(&self) -> bool {
101 self.0 & (1 << 0) != 0
102 }
103 pub fn hidden(&self) -> bool {
105 self.0 & (1 << 1) != 0
106 }
107 pub fn print(&self) -> bool {
109 self.0 & (1 << 2) != 0
110 }
111 pub fn no_zoom(&self) -> bool {
113 self.0 & (1 << 3) != 0
114 }
115 pub fn no_rotate(&self) -> bool {
117 self.0 & (1 << 4) != 0
118 }
119 pub fn no_view(&self) -> bool {
121 self.0 & (1 << 5) != 0
122 }
123 pub fn read_only(&self) -> bool {
125 self.0 & (1 << 6) != 0
126 }
127 pub fn locked(&self) -> bool {
129 self.0 & (1 << 7) != 0
130 }
131 pub fn toggle_no_view(&self) -> bool {
133 self.0 & (1 << 8) != 0
134 }
135 pub fn locked_contents(&self) -> bool {
137 self.0 & (1 << 9) != 0
138 }
139}
140
141#[derive(Debug, Clone)]
143pub struct BorderStyle {
144 pub width: f32,
146 pub style: BorderStyleType,
148 pub dash_pattern: Vec<f32>,
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq)]
154pub enum BorderStyleType {
155 Solid,
157 Dashed,
159 Beveled,
161 Inset,
163 Underline,
165}
166
167impl BorderStyle {
168 pub fn from_dict(dict: &Dict<'_>) -> Self {
170 let width = dict.get::<f32>(W).unwrap_or(1.0);
171 let style = dict
172 .get::<Name>(S)
173 .map(|n| match n.as_ref() {
174 b"D" => BorderStyleType::Dashed,
175 b"B" => BorderStyleType::Beveled,
176 b"I" => BorderStyleType::Inset,
177 b"U" => BorderStyleType::Underline,
178 _ => BorderStyleType::Solid,
179 })
180 .unwrap_or(BorderStyleType::Solid);
181 let dash_pattern = dict
182 .get::<Array<'_>>(D)
183 .map(|arr| arr.iter::<f32>().collect())
184 .unwrap_or_else(|| vec![3.0]);
185 Self {
186 width,
187 style,
188 dash_pattern,
189 }
190 }
191}
192
193#[derive(Debug, Clone)]
195pub enum Color {
196 Transparent,
198 Gray(f32),
200 Rgb(f32, f32, f32),
202 Cmyk(f32, f32, f32, f32),
204}
205
206impl Color {
207 pub fn from_array(arr: &Array<'_>) -> Self {
209 let values: Vec<f32> = arr.iter::<f32>().collect();
210 match values.len() {
211 0 => Self::Transparent,
212 1 => Self::Gray(values[0]),
213 3 => Self::Rgb(values[0], values[1], values[2]),
214 4 => Self::Cmyk(values[0], values[1], values[2], values[3]),
215 _ => Self::Transparent,
216 }
217 }
218}
219
220#[derive(Debug, Clone)]
222pub struct BorderEffect {
223 pub style: BorderEffectStyle,
225 pub intensity: f32,
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq)]
231pub enum BorderEffectStyle {
232 None,
234 Cloudy,
236}
237
238impl BorderEffect {
239 pub fn from_dict(dict: &Dict<'_>) -> Self {
241 let style = dict
242 .get::<Name>(S)
243 .map(|n| match n.as_ref() {
244 b"C" => BorderEffectStyle::Cloudy,
245 _ => BorderEffectStyle::None,
246 })
247 .unwrap_or(BorderEffectStyle::None);
248 let intensity = dict.get::<f32>(I).unwrap_or(0.0);
249 Self { style, intensity }
250 }
251}
252
253#[derive(Debug, Clone)]
255pub struct QuadPoints {
256 pub points: Vec<f32>,
258}
259
260impl QuadPoints {
261 pub fn from_array(arr: &Array<'_>) -> Self {
263 Self {
264 points: arr.iter::<f32>().collect(),
265 }
266 }
267
268 pub fn bounding_rects(&self) -> Vec<Rect> {
270 self.points
271 .chunks_exact(8)
272 .map(|chunk| {
273 let xs = [chunk[0], chunk[2], chunk[4], chunk[6]];
274 let ys = [chunk[1], chunk[3], chunk[5], chunk[7]];
275 let x0 = xs.iter().copied().reduce(f32::min).unwrap_or(0.0) as f64;
276 let y0 = ys.iter().copied().reduce(f32::min).unwrap_or(0.0) as f64;
277 let x1 = xs.iter().copied().reduce(f32::max).unwrap_or(0.0) as f64;
278 let y1 = ys.iter().copied().reduce(f32::max).unwrap_or(0.0) as f64;
279 Rect::new(x0, y0, x1, y1)
280 })
281 .collect()
282 }
283}
284
285#[derive(Debug, Clone, Copy, PartialEq, Eq)]
287pub enum LineEnding {
288 None,
290 Square,
292 Circle,
294 Diamond,
296 OpenArrow,
298 ClosedArrow,
300 Butt,
302 ROpenArrow,
304 RClosedArrow,
306 Slash,
308}
309
310impl LineEnding {
311 pub fn from_name(name: &[u8]) -> Self {
313 match name {
314 b"Square" => Self::Square,
315 b"Circle" => Self::Circle,
316 b"Diamond" => Self::Diamond,
317 b"OpenArrow" => Self::OpenArrow,
318 b"ClosedArrow" => Self::ClosedArrow,
319 b"Butt" => Self::Butt,
320 b"ROpenArrow" => Self::ROpenArrow,
321 b"RClosedArrow" => Self::RClosedArrow,
322 b"Slash" => Self::Slash,
323 _ => Self::None,
324 }
325 }
326}