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