use pdf_syntax::object::dict::keys::*;
use pdf_syntax::object::{Array, Dict, Name, Rect};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AnnotationType {
Text,
Link,
FreeText,
Line,
Square,
Circle,
Polygon,
PolyLine,
Highlight,
Underline,
Squiggly,
StrikeOut,
Stamp,
Caret,
Ink,
Popup,
FileAttachment,
Sound,
Widget,
Watermark,
Redact,
Movie,
Unknown,
}
impl AnnotationType {
pub fn from_name(name: &[u8]) -> Self {
match name {
b"Text" => Self::Text,
b"Link" => Self::Link,
b"FreeText" => Self::FreeText,
b"Line" => Self::Line,
b"Square" => Self::Square,
b"Circle" => Self::Circle,
b"Polygon" => Self::Polygon,
b"PolyLine" => Self::PolyLine,
b"Highlight" => Self::Highlight,
b"Underline" => Self::Underline,
b"Squiggly" => Self::Squiggly,
b"StrikeOut" => Self::StrikeOut,
b"Stamp" => Self::Stamp,
b"Caret" => Self::Caret,
b"Ink" => Self::Ink,
b"Popup" => Self::Popup,
b"FileAttachment" => Self::FileAttachment,
b"Sound" => Self::Sound,
b"Widget" => Self::Widget,
b"Watermark" => Self::Watermark,
b"Redact" => Self::Redact,
b"Movie" => Self::Movie,
_ => Self::Unknown,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AnnotationFlags(pub u32);
impl AnnotationFlags {
pub fn invisible(&self) -> bool {
self.0 & (1 << 0) != 0
}
pub fn hidden(&self) -> bool {
self.0 & (1 << 1) != 0
}
pub fn print(&self) -> bool {
self.0 & (1 << 2) != 0
}
pub fn no_zoom(&self) -> bool {
self.0 & (1 << 3) != 0
}
pub fn no_rotate(&self) -> bool {
self.0 & (1 << 4) != 0
}
pub fn no_view(&self) -> bool {
self.0 & (1 << 5) != 0
}
pub fn read_only(&self) -> bool {
self.0 & (1 << 6) != 0
}
pub fn locked(&self) -> bool {
self.0 & (1 << 7) != 0
}
pub fn toggle_no_view(&self) -> bool {
self.0 & (1 << 8) != 0
}
pub fn locked_contents(&self) -> bool {
self.0 & (1 << 9) != 0
}
}
#[derive(Debug, Clone)]
pub struct BorderStyle {
pub width: f32,
pub style: BorderStyleType,
pub dash_pattern: Vec<f32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BorderStyleType {
Solid,
Dashed,
Beveled,
Inset,
Underline,
}
impl BorderStyle {
pub fn from_dict(dict: &Dict<'_>) -> Self {
let width = dict.get::<f32>(W).unwrap_or(1.0);
let style = dict
.get::<Name>(S)
.map(|n| match n.as_ref() {
b"D" => BorderStyleType::Dashed,
b"B" => BorderStyleType::Beveled,
b"I" => BorderStyleType::Inset,
b"U" => BorderStyleType::Underline,
_ => BorderStyleType::Solid,
})
.unwrap_or(BorderStyleType::Solid);
let dash_pattern = dict
.get::<Array<'_>>(D)
.map(|arr| arr.iter::<f32>().collect())
.unwrap_or_else(|| vec![3.0]);
Self {
width,
style,
dash_pattern,
}
}
}
#[derive(Debug, Clone)]
pub enum Color {
Transparent,
Gray(f32),
Rgb(f32, f32, f32),
Cmyk(f32, f32, f32, f32),
}
impl Color {
pub fn from_array(arr: &Array<'_>) -> Self {
let values: Vec<f32> = arr.iter::<f32>().collect();
match values.len() {
0 => Self::Transparent,
1 => Self::Gray(values[0]),
3 => Self::Rgb(values[0], values[1], values[2]),
4 => Self::Cmyk(values[0], values[1], values[2], values[3]),
_ => Self::Transparent,
}
}
}
#[derive(Debug, Clone)]
pub struct BorderEffect {
pub style: BorderEffectStyle,
pub intensity: f32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BorderEffectStyle {
None,
Cloudy,
}
impl BorderEffect {
pub fn from_dict(dict: &Dict<'_>) -> Self {
let style = dict
.get::<Name>(S)
.map(|n| match n.as_ref() {
b"C" => BorderEffectStyle::Cloudy,
_ => BorderEffectStyle::None,
})
.unwrap_or(BorderEffectStyle::None);
let intensity = dict.get::<f32>(I).unwrap_or(0.0);
Self { style, intensity }
}
}
#[derive(Debug, Clone)]
pub struct QuadPoints {
pub points: Vec<f32>,
}
impl QuadPoints {
pub fn from_array(arr: &Array<'_>) -> Self {
Self {
points: arr.iter::<f32>().collect(),
}
}
pub fn bounding_rects(&self) -> Vec<Rect> {
self.points
.chunks_exact(8)
.map(|chunk| {
let xs = [chunk[0], chunk[2], chunk[4], chunk[6]];
let ys = [chunk[1], chunk[3], chunk[5], chunk[7]];
let x0 = xs.iter().copied().reduce(f32::min).unwrap_or(0.0) as f64;
let y0 = ys.iter().copied().reduce(f32::min).unwrap_or(0.0) as f64;
let x1 = xs.iter().copied().reduce(f32::max).unwrap_or(0.0) as f64;
let y1 = ys.iter().copied().reduce(f32::max).unwrap_or(0.0) as f64;
Rect::new(x0, y0, x1, y1)
})
.collect()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LineEnding {
None,
Square,
Circle,
Diamond,
OpenArrow,
ClosedArrow,
Butt,
ROpenArrow,
RClosedArrow,
Slash,
}
impl LineEnding {
pub fn from_name(name: &[u8]) -> Self {
match name {
b"Square" => Self::Square,
b"Circle" => Self::Circle,
b"Diamond" => Self::Diamond,
b"OpenArrow" => Self::OpenArrow,
b"ClosedArrow" => Self::ClosedArrow,
b"Butt" => Self::Butt,
b"ROpenArrow" => Self::ROpenArrow,
b"RClosedArrow" => Self::RClosedArrow,
b"Slash" => Self::Slash,
_ => Self::None,
}
}
}