rust_pdf_box/interactive/
annotation.rs1use crate::content::color::Color;
2use crate::cos::document::COSDocument;
3use crate::cos::object::{COSArray, COSDictionary, COSName, COSString, ObjectId};
4use crate::pd::page::PDPage;
5use crate::pd::rectangle::PDRectangle;
6
7#[derive(Debug, Clone, PartialEq)]
8pub enum AnnotationType {
9 Link { uri: String },
10 Highlight,
11 Underline,
12 Text { comment: String },
13 Stamp { name: String },
14}
15
16#[derive(Debug, Clone)]
18pub struct PDAnnotation {
19 pub rect: PDRectangle,
20 pub annotation_type: AnnotationType,
21 pub color: Option<Color>,
22 pub contents: Option<String>,
23}
24
25impl PDAnnotation {
26 pub fn link(rect: PDRectangle, uri: impl Into<String>) -> Self {
28 Self {
29 rect,
30 annotation_type: AnnotationType::Link { uri: uri.into() },
31 color: Some(Color::rgb(0.0, 0.4, 0.8)),
32 contents: None,
33 }
34 }
35
36 pub fn highlight(rect: PDRectangle, comment: Option<String>) -> Self {
38 Self {
39 rect,
40 annotation_type: AnnotationType::Highlight,
41 color: Some(Color::rgb(1.0, 1.0, 0.0)), contents: comment,
43 }
44 }
45
46 pub fn attach_to_page(&self, page: &mut PDPage, cos_doc: &mut COSDocument) -> ObjectId {
48 let mut dict = COSDictionary::new();
49 dict.set("Type", COSName::new("Annot"));
50 dict.set("Rect", self.rect);
51
52 if let Some(c) = self.color {
53 if let Color::Rgb(r, g, b) = c {
54 let mut c_arr = COSArray::new();
55 c_arr.push(r);
56 c_arr.push(g);
57 c_arr.push(b);
58 dict.set("C", c_arr);
59 }
60 }
61
62 if let Some(ref text) = self.contents {
63 dict.set("Contents", COSString::literal(text.clone().into_bytes()));
64 }
65
66 match &self.annotation_type {
67 AnnotationType::Link { uri } => {
68 dict.set("Subtype", COSName::new("Link"));
69 let mut action = COSDictionary::new();
70 action.set("Type", COSName::new("Action"));
71 action.set("S", COSName::new("URI"));
72 action.set("URI", COSString::literal(uri.clone().into_bytes()));
73 dict.set("A", action);
74 dict.set("F", 4); }
76 AnnotationType::Highlight => {
77 dict.set("Subtype", COSName::new("Highlight"));
78 }
79 AnnotationType::Underline => {
80 dict.set("Subtype", COSName::new("Underline"));
81 }
82 AnnotationType::Text { comment } => {
83 dict.set("Subtype", COSName::new("Text"));
84 dict.set("Contents", COSString::literal(comment.clone().into_bytes()));
85 }
86 AnnotationType::Stamp { name } => {
87 dict.set("Subtype", COSName::new("Stamp"));
88 dict.set("Name", COSName::new(name));
89 }
90 }
91
92 let annot_id = cos_doc.add_object(dict);
93
94 let mut annots = page.dict.get_array("Annots").cloned().unwrap_or_default();
95 annots.push(annot_id);
96 page.dict.set("Annots", annots);
97
98 annot_id
99 }
100}