Skip to main content

pdfium_render/pdf/document/page/
annotations.rs

1//! Defines the [PdfPageAnnotations] struct, exposing functionality related to the
2//! annotations that have been added to a single `PdfPage`.
3
4use crate::bindgen::{FPDF_ANNOTATION, FPDF_DOCUMENT, FPDF_FORMHANDLE, FPDF_PAGE};
5use crate::error::{PdfiumError, PdfiumInternalError};
6use crate::pdf::color::PdfColor;
7use crate::pdf::document::page::annotation::free_text::PdfPageFreeTextAnnotation;
8use crate::pdf::document::page::annotation::highlight::PdfPageHighlightAnnotation;
9use crate::pdf::document::page::annotation::ink::PdfPageInkAnnotation;
10use crate::pdf::document::page::annotation::link::PdfPageLinkAnnotation;
11use crate::pdf::document::page::annotation::popup::PdfPagePopupAnnotation;
12use crate::pdf::document::page::annotation::private::internal::PdfPageAnnotationPrivate;
13use crate::pdf::document::page::annotation::square::PdfPageSquareAnnotation;
14use crate::pdf::document::page::annotation::squiggly::PdfPageSquigglyAnnotation;
15use crate::pdf::document::page::annotation::stamp::PdfPageStampAnnotation;
16use crate::pdf::document::page::annotation::strikeout::PdfPageStrikeoutAnnotation;
17use crate::pdf::document::page::annotation::text::PdfPageTextAnnotation;
18use crate::pdf::document::page::annotation::underline::PdfPageUnderlineAnnotation;
19use crate::pdf::document::page::annotation::{
20    PdfPageAnnotation, PdfPageAnnotationCommon, PdfPageAnnotationType,
21};
22use crate::pdf::document::page::object::{PdfPageObject, PdfPageObjectCommon};
23use crate::pdf::document::page::{PdfPage, PdfPageContentRegenerationStrategy, PdfPageIndexCache};
24use crate::pdf::quad_points::PdfQuadPoints;
25use crate::pdfium::PdfiumLibraryBindingsAccessor;
26use chrono::prelude::*;
27use std::marker::PhantomData;
28use std::ops::Range;
29use std::os::raw::c_int;
30
31/// The zero-based index of a single [PdfPageAnnotation] inside its containing
32/// [PdfPageAnnotations] collection.
33pub type PdfPageAnnotationIndex = usize;
34
35/// The annotations that have been added to a single `PdfPage`.
36pub struct PdfPageAnnotations<'a> {
37    document_handle: FPDF_DOCUMENT,
38    page_handle: FPDF_PAGE,
39    form_handle: Option<FPDF_FORMHANDLE>,
40    lifetime: PhantomData<&'a FPDF_PAGE>,
41}
42
43impl<'a> PdfPageAnnotations<'a> {
44    #[inline]
45    pub(crate) fn from_pdfium(
46        document_handle: FPDF_DOCUMENT,
47        page_handle: FPDF_PAGE,
48        form_handle: Option<FPDF_FORMHANDLE>,
49    ) -> Self {
50        PdfPageAnnotations {
51            document_handle,
52            page_handle,
53            form_handle,
54            lifetime: PhantomData,
55        }
56    }
57
58    /// Returns the internal `FPDF_DOCUMENT` handle of the [PdfDocument] containing this
59    /// [PdfPageAnnotations] collection.
60    #[inline]
61    pub(crate) fn document_handle(&self) -> FPDF_DOCUMENT {
62        self.document_handle
63    }
64
65    /// Returns the internal `FPDF_PAGE` handle of the [PdfPage] containing this
66    /// [PdfPageAnnotations] collection.
67    #[inline]
68    pub(crate) fn page_handle(&self) -> FPDF_PAGE {
69        self.page_handle
70    }
71
72    /// Returns the total number of annotations that have been added to the containing `PdfPage`.
73    #[inline]
74    pub fn len(&self) -> PdfPageAnnotationIndex {
75        (unsafe { self.bindings().FPDFPage_GetAnnotCount(self.page_handle) })
76            as PdfPageAnnotationIndex
77    }
78
79    /// Returns true if this [PdfPageAnnotations] collection is empty.
80    #[inline]
81    pub fn is_empty(&self) -> bool {
82        self.len() == 0
83    }
84
85    /// Returns a Range from 0..(number of annotations) for this [PdfPageAnnotations] collection.
86    #[inline]
87    pub fn as_range(&self) -> Range<PdfPageAnnotationIndex> {
88        0..self.len()
89    }
90
91    /// Returns a single [PdfPageAnnotation] from this [PdfPageAnnotations] collection.
92    pub fn get(&self, index: PdfPageAnnotationIndex) -> Result<PdfPageAnnotation<'a>, PdfiumError> {
93        if index >= self.len() {
94            return Err(PdfiumError::PageAnnotationIndexOutOfBounds);
95        }
96
97        let annotation_handle = unsafe {
98            self.bindings()
99                .FPDFPage_GetAnnot(self.page_handle, index as c_int)
100        };
101
102        if annotation_handle.is_null() {
103            Err(PdfiumError::PdfiumLibraryInternalError(
104                PdfiumInternalError::Unknown,
105            ))
106        } else {
107            Ok(PdfPageAnnotation::from_pdfium(
108                self.document_handle,
109                self.page_handle,
110                annotation_handle,
111                self.form_handle,
112                self.bindings(),
113            ))
114        }
115    }
116
117    /// Returns the first [PdfPageAnnotation] in this [PdfPageAnnotations] collection.
118    #[inline]
119    pub fn first(&self) -> Result<PdfPageAnnotation<'a>, PdfiumError> {
120        if !self.is_empty() {
121            self.get(0)
122        } else {
123            Err(PdfiumError::NoAnnotationsInCollection)
124        }
125    }
126
127    /// Returns the last [PdfPageAnnotation] in this [PdfPageAnnotations] collection.
128    #[inline]
129    pub fn last(&self) -> Result<PdfPageAnnotation<'a>, PdfiumError> {
130        if !self.is_empty() {
131            self.get(self.len() - 1)
132        } else {
133            Err(PdfiumError::NoAnnotationsInCollection)
134        }
135    }
136
137    /// Returns an iterator over all the annotations in this [PdfPageAnnotations] collection.
138    #[inline]
139    pub fn iter(&self) -> PdfPageAnnotationsIterator<'_> {
140        PdfPageAnnotationsIterator::new(self)
141    }
142
143    /// Creates a new annotation of the given [PdfPageAnnotationType] by passing the result of calling
144    /// `FPDFPage_CreateAnnot()` to an annotation constructor function.
145    ///
146    /// If the containing `PdfPage` has a content regeneration strategy of
147    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
148    /// will be triggered on the page.
149    pub(crate) fn create_annotation<T: PdfPageAnnotationCommon>(
150        &mut self,
151        annotation_type: PdfPageAnnotationType,
152        constructor: fn(FPDF_DOCUMENT, FPDF_PAGE, FPDF_ANNOTATION) -> T,
153    ) -> Result<T, PdfiumError> {
154        let handle = unsafe {
155            self.bindings()
156                .FPDFPage_CreateAnnot(self.page_handle(), annotation_type.as_pdfium())
157        };
158
159        if handle.is_null() {
160            Err(PdfiumError::PdfiumLibraryInternalError(
161                PdfiumInternalError::Unknown,
162            ))
163        } else {
164            let mut annotation = constructor(self.document_handle(), self.page_handle(), handle);
165
166            annotation
167                .set_creation_date(Utc::now())
168                .and_then(|()| {
169                    if let Some(content_regeneration_strategy) =
170                        PdfPageIndexCache::get_content_regeneration_strategy_for_page(
171                            self.document_handle(),
172                            self.page_handle(),
173                        )
174                    {
175                        if content_regeneration_strategy
176                            == PdfPageContentRegenerationStrategy::AutomaticOnEveryChange
177                        {
178                            PdfPage::regenerate_content_immut_for_handle(
179                                self.page_handle(),
180                                self.bindings(),
181                            )
182                        } else {
183                            Ok(())
184                        }
185                    } else {
186                        Err(PdfiumError::SourcePageIndexNotInCache)
187                    }
188                })
189                .map(|()| annotation)
190        }
191    }
192
193    /// Creates a new [PdfPageFreeTextAnnotation] containing the given text in this
194    /// [PdfPageAnnotations] collection, returning the newly created annotation.
195    ///
196    /// If the containing `PdfPage` has a content regeneration strategy of
197    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
198    /// will be triggered on the page.
199    #[inline]
200    pub fn create_free_text_annotation(
201        &mut self,
202        text: &str,
203    ) -> Result<PdfPageFreeTextAnnotation<'a>, PdfiumError> {
204        let mut annotation = self.create_annotation(
205            PdfPageAnnotationType::FreeText,
206            PdfPageFreeTextAnnotation::from_pdfium,
207        )?;
208
209        annotation.set_contents(text)?;
210
211        Ok(annotation)
212    }
213
214    /// Creates a new [PdfPageHighlightAnnotation] annotation in this [PdfPageAnnotations] collection,
215    /// returning the newly created annotation.
216    ///
217    /// If the containing `PdfPage` has a content regeneration strategy of
218    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
219    /// will be triggered on the page.
220    #[inline]
221    pub fn create_highlight_annotation(
222        &mut self,
223    ) -> Result<PdfPageHighlightAnnotation<'a>, PdfiumError> {
224        self.create_annotation(
225            PdfPageAnnotationType::Highlight,
226            PdfPageHighlightAnnotation::from_pdfium,
227        )
228    }
229
230    /// Creates a new [PdfPageInkAnnotation] in this [PdfPageAnnotations] collection,
231    /// returning the newly created annotation.
232    ///
233    /// If the containing `PdfPage` has a content regeneration strategy of
234    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
235    /// will be triggered on the page.
236    #[inline]
237    pub fn create_ink_annotation(&mut self) -> Result<PdfPageInkAnnotation<'a>, PdfiumError> {
238        self.create_annotation(
239            PdfPageAnnotationType::Ink,
240            PdfPageInkAnnotation::from_pdfium,
241        )
242    }
243
244    /// Creates a new [PdfPageLinkAnnotation] with the given URI in this [PdfPageAnnotations]
245    /// collection, returning the newly created annotation.
246    ///
247    /// If the containing `PdfPage` has a content regeneration strategy of
248    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
249    /// will be triggered on the page.
250    pub fn create_link_annotation(
251        &mut self,
252        uri: &str,
253    ) -> Result<PdfPageLinkAnnotation<'a>, PdfiumError> {
254        let mut annotation = self.create_annotation(
255            PdfPageAnnotationType::Link,
256            PdfPageLinkAnnotation::from_pdfium,
257        )?;
258
259        annotation.set_link(uri)?;
260
261        Ok(annotation)
262    }
263
264    /// Creates a new [PdfPagePopupAnnotation] annotation in this [PdfPageAnnotations] collection,
265    /// returning the newly created annotation.
266    ///
267    /// If the containing `PdfPage` has a content regeneration strategy of
268    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
269    /// will be triggered on the page.
270    #[inline]
271    pub fn create_popup_annotation(&mut self) -> Result<PdfPagePopupAnnotation<'a>, PdfiumError> {
272        self.create_annotation(
273            PdfPageAnnotationType::Popup,
274            PdfPagePopupAnnotation::from_pdfium,
275        )
276    }
277
278    /// Creates a new [PdfPageSquareAnnotation] annotation in this [PdfPageAnnotations] collection,
279    /// returning the newly created annotation.
280    ///
281    /// If the containing `PdfPage` has a content regeneration strategy of
282    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
283    /// will be triggered on the page.
284    #[inline]
285    pub fn create_square_annotation(&mut self) -> Result<PdfPageSquareAnnotation<'a>, PdfiumError> {
286        self.create_annotation(
287            PdfPageAnnotationType::Square,
288            PdfPageSquareAnnotation::from_pdfium,
289        )
290    }
291
292    /// Creates a new [PdfPageSquigglyAnnotation] annotation in this [PdfPageAnnotations] collection,
293    /// returning the newly created annotation.
294    ///
295    /// If the containing `PdfPage` has a content regeneration strategy of
296    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
297    /// will be triggered on the page.
298    #[inline]
299    pub fn create_squiggly_annotation(
300        &mut self,
301    ) -> Result<PdfPageSquigglyAnnotation<'a>, PdfiumError> {
302        self.create_annotation(
303            PdfPageAnnotationType::Squiggly,
304            PdfPageSquigglyAnnotation::from_pdfium,
305        )
306    }
307
308    /// Creates a new [PdfPageStampAnnotation] annotation in this [PdfPageAnnotations] collection,
309    /// returning the newly created annotation.
310    ///
311    /// If the containing `PdfPage` has a content regeneration strategy of
312    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
313    /// will be triggered on the page.
314    #[inline]
315    pub fn create_stamp_annotation(&mut self) -> Result<PdfPageStampAnnotation<'a>, PdfiumError> {
316        self.create_annotation(
317            PdfPageAnnotationType::Stamp,
318            PdfPageStampAnnotation::from_pdfium,
319        )
320    }
321
322    /// Creates a new [PdfPageStrikeoutAnnotation] annotation in this [PdfPageAnnotations] collection,
323    /// returning the newly created annotation.
324    ///
325    /// If the containing `PdfPage` has a content regeneration strategy of
326    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
327    /// will be triggered on the page.
328    #[inline]
329    pub fn create_strikeout_annotation(
330        &mut self,
331    ) -> Result<PdfPageStrikeoutAnnotation<'a>, PdfiumError> {
332        self.create_annotation(
333            PdfPageAnnotationType::Strikeout,
334            PdfPageStrikeoutAnnotation::from_pdfium,
335        )
336    }
337
338    /// Creates a new [PdfPageTextAnnotation] containing the given text in this [PdfPageAnnotations]
339    /// collection, returning the newly created annotation.
340    ///
341    /// If the containing `PdfPage` has a content regeneration strategy of
342    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
343    /// will be triggered on the page.
344    #[inline]
345    pub fn create_text_annotation(
346        &mut self,
347        text: &str,
348    ) -> Result<PdfPageTextAnnotation<'a>, PdfiumError> {
349        let mut annotation = self.create_annotation(
350            PdfPageAnnotationType::Text,
351            PdfPageTextAnnotation::from_pdfium,
352        )?;
353
354        annotation.set_contents(text)?;
355
356        Ok(annotation)
357    }
358
359    /// Creates a new [PdfPageUnderlineAnnotation] annotation in this [PdfPageAnnotations] collection,
360    /// returning the newly created annotation.
361    ///
362    /// If the containing `PdfPage` has a content regeneration strategy of
363    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
364    /// will be triggered on the page.
365    #[inline]
366    pub fn create_underline_annotation(
367        &mut self,
368    ) -> Result<PdfPageUnderlineAnnotation<'a>, PdfiumError> {
369        self.create_annotation(
370            PdfPageAnnotationType::Underline,
371            PdfPageUnderlineAnnotation::from_pdfium,
372        )
373    }
374
375    // Convenience functions for creating and positioning markup annotations
376    // in a single function call.
377
378    /// Creates a new [PdfPageSquigglyAnnotation] annotation and positions it underneath the given
379    /// [PdfPageObject], coloring it with the given [PdfColor].
380    ///
381    /// If the given contents string is supplied, the annotation will be additionally configured
382    /// so that when the given [PdfPageObject] is clicked in a conforming PDF viewer, the given
383    /// contents string will be displayed in a popup window.
384    ///
385    /// If the containing `PdfPage` has a content regeneration strategy of
386    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
387    /// will be triggered on the page.
388    #[inline]
389    pub fn create_squiggly_annotation_under_object(
390        &mut self,
391        object: &PdfPageObject,
392        color: PdfColor,
393        contents: Option<&str>,
394    ) -> Result<PdfPageSquigglyAnnotation<'a>, PdfiumError> {
395        let mut annotation = self.create_squiggly_annotation()?;
396
397        // The annotation will not display if it is not positioned.
398
399        let bounds = object.bounds()?;
400
401        annotation.set_position(bounds.left(), bounds.bottom())?;
402        annotation.set_stroke_color(color)?;
403
404        const SQUIGGLY_HEIGHT: f32 = 12.0;
405
406        let annotation_top = bounds.bottom().value - 5.0;
407        let annotation_bottom = annotation_top - SQUIGGLY_HEIGHT;
408
409        annotation
410            .attachment_points_mut()
411            .create_attachment_point_at_end(PdfQuadPoints::new_from_values(
412                bounds.left().value,
413                annotation_bottom,
414                bounds.right().value,
415                annotation_bottom,
416                bounds.right().value,
417                annotation_top,
418                bounds.left().value,
419                annotation_top,
420            ))?;
421
422        if let Some(contents) = contents {
423            annotation.set_width(bounds.width())?;
424            annotation.set_height(bounds.height())?;
425            annotation.set_contents(contents)?;
426        }
427
428        Ok(annotation)
429    }
430
431    /// Creates a new [PdfPageUnderlineAnnotation] annotation and positions it underneath the given
432    /// [PdfPageObject], coloring it with the given [PdfColor].
433    ///
434    /// If the given contents string is supplied, the annotation will be additionally configured
435    /// so that when the given [PdfPageObject] is clicked in a conforming PDF viewer, the given
436    /// contents string will be displayed in a popup window.
437    ///
438    /// If the containing `PdfPage` has a content regeneration strategy of
439    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
440    /// will be triggered on the page.
441    #[inline]
442    pub fn create_underline_annotation_under_object(
443        &mut self,
444        object: &PdfPageObject,
445        color: PdfColor,
446        contents: Option<&str>,
447    ) -> Result<PdfPageUnderlineAnnotation<'a>, PdfiumError> {
448        let mut annotation = self.create_underline_annotation()?;
449
450        // The annotation will not display if it is not positioned.
451
452        let bounds = object.bounds()?;
453
454        annotation.set_position(bounds.left(), bounds.bottom())?;
455        annotation.set_stroke_color(color)?;
456        annotation
457            .attachment_points_mut()
458            .create_attachment_point_at_end(bounds)?;
459
460        if let Some(contents) = contents {
461            annotation.set_width(bounds.width())?;
462            annotation.set_height(bounds.height())?;
463            annotation.set_contents(contents)?;
464        }
465
466        Ok(annotation)
467    }
468
469    /// Creates a new [PdfPageStrikeoutAnnotation] annotation and vertically positions it in the
470    /// center the given [PdfPageObject], coloring it with the given [PdfColor].
471    ///
472    /// If the given contents string is supplied, the annotation will be additionally configured
473    /// so that when the given [PdfPageObject] is clicked in a conforming PDF viewer, the given
474    /// contents string will be displayed in a popup window.
475    ///
476    /// If the containing `PdfPage` has a content regeneration strategy of
477    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
478    /// will be triggered on the page.
479    #[inline]
480    pub fn create_strikeout_annotation_through_object(
481        &mut self,
482        object: &PdfPageObject,
483        color: PdfColor,
484        contents: Option<&str>,
485    ) -> Result<PdfPageStrikeoutAnnotation<'a>, PdfiumError> {
486        let mut annotation = self.create_strikeout_annotation()?;
487
488        // The annotation will not display if it is not positioned.
489
490        let bounds = object.bounds()?;
491
492        annotation.set_position(bounds.left(), bounds.bottom())?;
493        annotation.set_stroke_color(color)?;
494        annotation
495            .attachment_points_mut()
496            .create_attachment_point_at_end(bounds)?;
497
498        if let Some(contents) = contents {
499            annotation.set_width(bounds.width())?;
500            annotation.set_height(bounds.height())?;
501            annotation.set_contents(contents)?;
502        }
503
504        Ok(annotation)
505    }
506
507    /// Creates a new [PdfPageHighlightAnnotation] annotation and positions it so as to cover
508    /// the given [PdfPageObject], coloring it with the given [PdfColor].
509    ///
510    /// If the given contents string is supplied, the annotation will be additionally configured
511    /// so that when the given [PdfPageObject] is clicked in a conforming PDF viewer, the given
512    /// contents string will be displayed in a popup window.
513    ///
514    /// If the containing `PdfPage` has a content regeneration strategy of
515    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
516    /// will be triggered on the page.
517    #[inline]
518    pub fn create_highlight_annotation_over_object(
519        &mut self,
520        object: &PdfPageObject,
521        color: PdfColor,
522        contents: Option<&str>,
523    ) -> Result<PdfPageHighlightAnnotation<'a>, PdfiumError> {
524        let mut annotation = self.create_highlight_annotation()?;
525
526        // The annotation will not display if it is not positioned.
527
528        let bounds = object.bounds()?;
529
530        annotation.set_position(bounds.left(), bounds.bottom())?;
531        annotation.set_stroke_color(color)?;
532        annotation
533            .attachment_points_mut()
534            .create_attachment_point_at_end(bounds)?;
535
536        if let Some(contents) = contents {
537            annotation.set_width(bounds.width())?;
538            annotation.set_height(bounds.height())?;
539            annotation.set_contents(contents)?;
540        }
541
542        Ok(annotation)
543    }
544
545    /// Removes the given [PdfPageAnnotation] from this [PdfPageAnnotations] collection,
546    /// consuming the [PdfPageAnnotation].
547    ///
548    /// If the containing `PdfPage` has a content regeneration strategy of
549    /// `PdfPageContentRegenerationStrategy::AutomaticOnEveryChange` then content regeneration
550    /// will be triggered on the page.
551    pub fn delete_annotation(
552        &mut self,
553        annotation: PdfPageAnnotation<'a>,
554    ) -> Result<(), PdfiumError> {
555        let index = unsafe {
556            self.bindings()
557                .FPDFPage_GetAnnotIndex(self.page_handle(), annotation.handle())
558        };
559
560        if index == -1 {
561            return Err(PdfiumError::PageAnnotationIndexOutOfBounds);
562        }
563
564        if self.bindings().is_true(unsafe {
565            self.bindings()
566                .FPDFPage_RemoveAnnot(self.page_handle(), index)
567        }) {
568            if let Some(content_regeneration_strategy) =
569                PdfPageIndexCache::get_content_regeneration_strategy_for_page(
570                    self.document_handle(),
571                    self.page_handle(),
572                )
573            {
574                if content_regeneration_strategy
575                    == PdfPageContentRegenerationStrategy::AutomaticOnEveryChange
576                {
577                    PdfPage::regenerate_content_immut_for_handle(
578                        self.page_handle(),
579                        self.bindings(),
580                    )
581                } else {
582                    Ok(())
583                }
584            } else {
585                Err(PdfiumError::SourcePageIndexNotInCache)
586            }
587        } else {
588            Err(PdfiumError::PdfiumLibraryInternalError(
589                PdfiumInternalError::Unknown,
590            ))
591        }
592    }
593}
594
595impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfPageAnnotations<'a> {}
596
597#[cfg(feature = "thread_safe")]
598unsafe impl<'a> Send for PdfPageAnnotations<'a> {}
599
600#[cfg(feature = "thread_safe")]
601unsafe impl<'a> Sync for PdfPageAnnotations<'a> {}
602
603/// An iterator over all the [PdfPageAnnotation] objects in a [PdfPageAnnotations] collection.
604pub struct PdfPageAnnotationsIterator<'a> {
605    annotations: &'a PdfPageAnnotations<'a>,
606    next_index: PdfPageAnnotationIndex,
607}
608
609impl<'a> PdfPageAnnotationsIterator<'a> {
610    #[inline]
611    pub(crate) fn new(annotations: &'a PdfPageAnnotations<'a>) -> Self {
612        PdfPageAnnotationsIterator {
613            annotations,
614            next_index: 0,
615        }
616    }
617}
618
619impl<'a> Iterator for PdfPageAnnotationsIterator<'a> {
620    type Item = PdfPageAnnotation<'a>;
621
622    fn next(&mut self) -> Option<Self::Item> {
623        let next = self.annotations.get(self.next_index);
624
625        self.next_index += 1;
626
627        next.ok()
628    }
629}