Skip to main content

pdfium_render/pdf/document/page/annotation/
objects.rs

1//! Defines the [PdfPageAnnotationObjects] struct, exposing functionality related to the
2//! page objects contained within a single `PdfPageAnnotation`.
3
4use crate::bindgen::{FPDF_ANNOTATION, FPDF_DOCUMENT, FPDF_PAGE};
5use crate::error::{PdfiumError, PdfiumInternalError};
6use crate::pdf::document::page::object::ownership::PdfPageObjectOwnership;
7use crate::pdf::document::page::object::private::internal::PdfPageObjectPrivate;
8use crate::pdf::document::page::object::PdfPageObject;
9use crate::pdf::document::page::objects::common::{
10    PdfPageObjectIndex, PdfPageObjectsCommon, PdfPageObjectsIterator,
11};
12use crate::pdf::document::page::objects::private::internal::PdfPageObjectsPrivate;
13use crate::pdfium::PdfiumLibraryBindingsAccessor;
14use std::marker::PhantomData;
15use std::os::raw::c_int;
16
17/// The page objects contained within a single `PdfPageAnnotation`.
18///
19/// Content in an annotation is structured as a stream of [PdfPageObject] objects of different types:
20/// text objects, image objects, path objects, and so on.
21///
22/// Note that Pdfium does not support or recognize all PDF page object types. For instance,
23/// Pdfium does not currently support or recognize the External Object ("XObject") page object type
24/// supported by Adobe Acrobat and Foxit's commercial PDF SDK. In these cases, Pdfium will return
25/// `PdfPageObjectType::Unsupported`.
26///
27/// Page objects can be retrieved from any type of `PdfPageAnnotation`, but Pdfium currently
28/// only permits adding new page objects to, or removing existing page objects from, annotations
29/// of types `PdfPageAnnotationType::Ink` and `PdfPageAnnotationType::Stamp`. All other annotation
30/// types are read-only.
31pub struct PdfPageAnnotationObjects<'a> {
32    annotation_handle: FPDF_ANNOTATION,
33    ownership: PdfPageObjectOwnership,
34    lifetime: PhantomData<&'a FPDF_ANNOTATION>,
35}
36
37impl<'a> PdfPageAnnotationObjects<'a> {
38    #[inline]
39    pub(crate) fn from_pdfium(
40        document_handle: FPDF_DOCUMENT,
41        page_handle: FPDF_PAGE,
42        annotation_handle: FPDF_ANNOTATION,
43    ) -> Self {
44        Self {
45            annotation_handle,
46            ownership: PdfPageObjectOwnership::owned_by_attached_annotation(
47                document_handle,
48                page_handle,
49                annotation_handle,
50            ),
51            lifetime: PhantomData,
52        }
53    }
54
55    /// Returns the internal `FPDF_ANNOTATION` handle for the [PdfPageAnnotation] containing
56    /// this [PdfPageAnnotationObjects] collection.
57    #[inline]
58    pub(crate) fn annotation_handle(&self) -> FPDF_ANNOTATION {
59        self.annotation_handle
60    }
61}
62
63impl<'a> PdfPageObjectsPrivate<'a> for PdfPageAnnotationObjects<'a> {
64    #[inline]
65    fn ownership(&self) -> &PdfPageObjectOwnership {
66        &self.ownership
67    }
68
69    #[inline]
70    fn len_impl(&self) -> PdfPageObjectIndex {
71        (unsafe {
72            self.bindings()
73                .FPDFAnnot_GetObjectCount(self.annotation_handle())
74        }) as PdfPageObjectIndex
75    }
76
77    fn get_impl(&self, index: PdfPageObjectIndex) -> Result<PdfPageObject<'a>, PdfiumError> {
78        let object_handle = unsafe {
79            self.bindings()
80                .FPDFAnnot_GetObject(self.annotation_handle(), index as c_int)
81        };
82
83        if object_handle.is_null() {
84            if index >= self.len() {
85                Err(PdfiumError::PageObjectIndexOutOfBounds)
86            } else {
87                Err(PdfiumError::PdfiumLibraryInternalError(
88                    PdfiumInternalError::Unknown,
89                ))
90            }
91        } else {
92            Ok(PdfPageObject::from_pdfium(
93                object_handle,
94                *self.ownership(),
95                self.bindings(),
96            ))
97        }
98    }
99
100    #[inline]
101    fn iter_impl(&'a self) -> PdfPageObjectsIterator<'a> {
102        PdfPageObjectsIterator::new(self)
103    }
104
105    #[inline]
106    fn add_object_impl(
107        &mut self,
108        mut object: PdfPageObject<'a>,
109    ) -> Result<PdfPageObject<'a>, PdfiumError> {
110        object.add_object_to_annotation(self).map(|_| object)
111    }
112
113    #[inline]
114    fn remove_object_impl(
115        &mut self,
116        mut object: PdfPageObject<'a>,
117    ) -> Result<PdfPageObject<'a>, PdfiumError> {
118        object.remove_object_from_annotation().map(|_| object)
119    }
120}
121
122impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfPageAnnotationObjects<'a> {}
123
124#[cfg(feature = "thread_safe")]
125unsafe impl<'a> Send for PdfPageAnnotationObjects<'a> {}
126
127#[cfg(feature = "thread_safe")]
128unsafe impl<'a> Sync for PdfPageAnnotationObjects<'a> {}