use crate::bindgen::{FPDF_DOCUMENT, FPDF_LINK, FS_RECTF};
use crate::error::PdfiumError;
use crate::pdf::action::PdfAction;
use crate::pdf::destination::PdfDestination;
use crate::pdf::rect::PdfRect;
use crate::pdfium::PdfiumLibraryBindingsAccessor;
use std::marker::PhantomData;
#[cfg(doc)]
use {
crate::pdf::action::PdfActionType, crate::pdf::document::bookmark::PdfBookmark,
crate::pdf::document::page::annotation::PdfPageAnnotation, crate::pdf::document::page::PdfPage,
};
pub struct PdfLink<'a> {
handle: FPDF_LINK,
document: FPDF_DOCUMENT,
lifetime: PhantomData<&'a FPDF_LINK>,
}
impl<'a> PdfLink<'a> {
#[inline]
pub(crate) fn from_pdfium(handle: FPDF_LINK, document: FPDF_DOCUMENT) -> Self {
PdfLink {
handle,
document,
lifetime: PhantomData,
}
}
#[inline]
pub(crate) fn handle(&self) -> FPDF_LINK {
self.handle
}
pub fn action(&self) -> Option<PdfAction<'a>> {
let handle = unsafe { self.bindings().FPDFLink_GetAction(self.handle()) };
if handle.is_null() {
None
} else {
Some(PdfAction::from_pdfium(
handle,
self.document,
self.bindings(),
))
}
}
pub fn destination(&self) -> Option<PdfDestination<'a>> {
let handle = unsafe {
self.bindings()
.FPDFLink_GetDest(self.document, self.handle())
};
if handle.is_null() {
None
} else {
Some(PdfDestination::from_pdfium(self.document, handle))
}
}
pub fn rect(&self) -> Result<PdfRect, PdfiumError> {
let mut rect = FS_RECTF {
left: 0.0,
top: 0.0,
right: 0.0,
bottom: 0.0,
};
PdfRect::from_pdfium_as_result(
unsafe {
self.bindings()
.FPDFLink_GetAnnotRect(self.handle(), &mut rect)
},
rect,
self.bindings(),
)
}
}
impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfLink<'a> {}
#[cfg(feature = "thread_safe")]
unsafe impl<'a> Send for PdfLink<'a> {}
#[cfg(feature = "thread_safe")]
unsafe impl<'a> Sync for PdfLink<'a> {}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use crate::utils::test::test_bind_to_pdfium;
#[test]
fn test_link_rect() -> Result<(), PdfiumError> {
let pdfium = test_bind_to_pdfium();
let document = pdfium.load_pdf_from_file("./test/links-test.pdf", None)?;
const EXPECTED: PdfRect = PdfRect::new_from_values(733.3627, 207.85417, 757.6127, 333.1458);
const ABS_ERR: PdfPoints = PdfPoints::new(f32::EPSILON * 1000.);
let actual = document
.pages()
.iter()
.next()
.unwrap()
.links()
.iter()
.next()
.unwrap()
.rect()?;
assert!((actual.top() - EXPECTED.top()).abs() < ABS_ERR);
assert!((actual.bottom() - EXPECTED.bottom()).abs() < ABS_ERR);
assert!((actual.left() - EXPECTED.left()).abs() < ABS_ERR);
assert!((actual.right() - EXPECTED.right()).abs() < ABS_ERR);
Ok(())
}
}