pdfium_render/pdf/
link.rs1use crate::bindgen::{FPDF_DOCUMENT, FPDF_LINK, FS_RECTF};
5use crate::error::PdfiumError;
6use crate::pdf::action::PdfAction;
7use crate::pdf::destination::PdfDestination;
8use crate::pdf::rect::PdfRect;
9use crate::pdfium::PdfiumLibraryBindingsAccessor;
10use std::marker::PhantomData;
11
12#[cfg(doc)]
13use {
14 crate::pdf::action::PdfActionType, crate::pdf::document::bookmark::PdfBookmark,
15 crate::pdf::document::page::annotation::PdfPageAnnotation, crate::pdf::document::page::PdfPage,
16};
17
18pub struct PdfLink<'a> {
24 handle: FPDF_LINK,
25 document: FPDF_DOCUMENT,
26 lifetime: PhantomData<&'a FPDF_LINK>,
27}
28
29impl<'a> PdfLink<'a> {
30 #[inline]
31 pub(crate) fn from_pdfium(handle: FPDF_LINK, document: FPDF_DOCUMENT) -> Self {
32 PdfLink {
33 handle,
34 document,
35 lifetime: PhantomData,
36 }
37 }
38
39 #[inline]
41 pub(crate) fn handle(&self) -> FPDF_LINK {
42 self.handle
43 }
44
45 pub fn action(&self) -> Option<PdfAction<'a>> {
52 let handle = unsafe { self.bindings().FPDFLink_GetAction(self.handle()) };
53
54 if handle.is_null() {
55 None
56 } else {
57 Some(PdfAction::from_pdfium(
58 handle,
59 self.document,
60 self.bindings(),
61 ))
62 }
63 }
64
65 pub fn destination(&self) -> Option<PdfDestination<'a>> {
70 let handle = unsafe {
71 self.bindings()
72 .FPDFLink_GetDest(self.document, self.handle())
73 };
74
75 if handle.is_null() {
76 None
77 } else {
78 Some(PdfDestination::from_pdfium(self.document, handle))
79 }
80 }
81
82 pub fn rect(&self) -> Result<PdfRect, PdfiumError> {
85 let mut rect = FS_RECTF {
86 left: 0.0,
87 top: 0.0,
88 right: 0.0,
89 bottom: 0.0,
90 };
91
92 PdfRect::from_pdfium_as_result(
93 unsafe {
94 self.bindings()
95 .FPDFLink_GetAnnotRect(self.handle(), &mut rect)
96 },
97 rect,
98 self.bindings(),
99 )
100 }
101}
102
103impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfLink<'a> {}
104
105#[cfg(feature = "thread_safe")]
106unsafe impl<'a> Send for PdfLink<'a> {}
107
108#[cfg(feature = "thread_safe")]
109unsafe impl<'a> Sync for PdfLink<'a> {}
110
111#[cfg(test)]
112mod tests {
113 use crate::prelude::*;
114 use crate::utils::test::test_bind_to_pdfium;
115
116 #[test]
117 fn test_link_rect() -> Result<(), PdfiumError> {
118 let pdfium = test_bind_to_pdfium();
119
120 let document = pdfium.load_pdf_from_file("./test/links-test.pdf", None)?;
123
124 const EXPECTED: PdfRect = PdfRect::new_from_values(733.3627, 207.85417, 757.6127, 333.1458);
125
126 const ABS_ERR: PdfPoints = PdfPoints::new(f32::EPSILON * 1000.);
130
131 let actual = document
132 .pages()
133 .iter()
134 .next()
135 .unwrap()
136 .links()
137 .iter()
138 .next()
139 .unwrap()
140 .rect()?;
141
142 assert!((actual.top() - EXPECTED.top()).abs() < ABS_ERR);
143 assert!((actual.bottom() - EXPECTED.bottom()).abs() < ABS_ERR);
144 assert!((actual.left() - EXPECTED.left()).abs() < ABS_ERR);
145 assert!((actual.right() - EXPECTED.right()).abs() < ABS_ERR);
146
147 Ok(())
148 }
149}