1use std::ptr;
2
3use crate::action_goto::PdfActionGoTo;
4use crate::action_url::PdfActionUrl;
5use crate::border::PdfBorder;
6use crate::error::Result;
7use crate::ffi;
8use crate::handle::ObjectHandle;
9use crate::types::{PdfAnnotationInfo, PdfRect};
10use crate::util::{c_string, option_c_string, parse_json};
11
12#[derive(Debug, Clone)]
13pub struct PdfAnnotation {
14 handle: ObjectHandle,
15}
16
17impl PdfAnnotation {
18 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
19 Self { handle }
20 }
21
22 pub fn new(bounds: PdfRect, annotation_type: &str) -> Result<Self> {
23 let annotation_type = c_string(annotation_type)?;
24 let mut out_annotation = ptr::null_mut();
25 let mut out_error = ptr::null_mut();
26 let status = unsafe {
27 ffi::pdf_annotation_new(
28 bounds.x,
29 bounds.y,
30 bounds.width,
31 bounds.height,
32 annotation_type.as_ptr(),
33 &mut out_annotation,
34 &mut out_error,
35 )
36 };
37 crate::util::status_result(status, out_error)?;
38 Ok(Self::from_handle(crate::util::required_handle(
39 out_annotation,
40 "PDFAnnotation",
41 )?))
42 }
43
44 pub fn info(&self) -> Result<PdfAnnotationInfo> {
45 parse_json(
46 unsafe { ffi::pdf_annotation_info_json(self.handle.as_ptr()) },
47 "PDFAnnotation",
48 )
49 }
50
51 pub fn set_contents(&self, value: Option<&str>) -> Result<()> {
52 let value = option_c_string(value)?;
53 let mut out_error = ptr::null_mut();
54 let status = unsafe {
55 ffi::pdf_annotation_set_contents(
56 self.handle.as_ptr(),
57 value.as_ref().map_or(ptr::null(), |value| value.as_ptr()),
58 &mut out_error,
59 )
60 };
61 crate::util::status_result(status, out_error)
62 }
63
64 pub fn set_highlighted(&self, value: bool) {
65 unsafe { ffi::pdf_annotation_set_highlighted(self.handle.as_ptr(), i32::from(value)) };
66 }
67
68 #[must_use]
69 pub fn border(&self) -> Option<PdfBorder> {
70 let ptr = unsafe { ffi::pdf_annotation_border(self.handle.as_ptr()) };
71 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfBorder::from_handle)
72 }
73
74 pub fn set_border(&self, border: Option<&PdfBorder>) -> Result<()> {
75 let mut out_error = ptr::null_mut();
76 let status = unsafe {
77 ffi::pdf_annotation_set_border(
78 self.handle.as_ptr(),
79 border.map_or(ptr::null_mut(), PdfBorder::as_handle_ptr),
80 &mut out_error,
81 )
82 };
83 crate::util::status_result(status, out_error)
84 }
85
86 #[must_use]
87 pub fn action_url(&self) -> Option<PdfActionUrl> {
88 let ptr = unsafe { ffi::pdf_annotation_action_url(self.handle.as_ptr()) };
89 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfActionUrl::from_handle)
90 }
91
92 pub fn set_action_url(&self, action: Option<&PdfActionUrl>) -> Result<()> {
93 let mut out_error = ptr::null_mut();
94 let status = unsafe {
95 ffi::pdf_annotation_set_action_url(
96 self.handle.as_ptr(),
97 action.map_or(ptr::null_mut(), PdfActionUrl::as_handle_ptr),
98 &mut out_error,
99 )
100 };
101 crate::util::status_result(status, out_error)
102 }
103
104 #[must_use]
105 pub fn action_goto(&self) -> Option<PdfActionGoTo> {
106 let ptr = unsafe { ffi::pdf_annotation_action_goto(self.handle.as_ptr()) };
107 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfActionGoTo::from_handle)
108 }
109
110 pub fn set_action_goto(&self, action: Option<&PdfActionGoTo>) -> Result<()> {
111 let mut out_error = ptr::null_mut();
112 let status = unsafe {
113 ffi::pdf_annotation_set_action_goto(
114 self.handle.as_ptr(),
115 action.map_or(ptr::null_mut(), PdfActionGoTo::as_handle_ptr),
116 &mut out_error,
117 )
118 };
119 crate::util::status_result(status, out_error)
120 }
121
122 pub(crate) fn as_handle_ptr(&self) -> *mut core::ffi::c_void {
123 self.handle.as_ptr()
124 }
125}