pdfium_render/pdf/document/page/
struct_tree.rs1use crate::bindgen::FPDF_STRUCTTREE;
4use crate::bindings::PdfiumLibraryBindings;
5use crate::pdf::document::page::struct_element::PdfStructElement;
6use std::os::raw::c_int;
7
8pub struct PdfStructTree<'a> {
18 tree_handle: FPDF_STRUCTTREE,
19 bindings: &'a dyn PdfiumLibraryBindings,
20}
21
22impl<'a> PdfStructTree<'a> {
23 pub(crate) fn from_pdfium(tree_handle: FPDF_STRUCTTREE, bindings: &'a dyn PdfiumLibraryBindings) -> Self {
24 Self { tree_handle, bindings }
25 }
26
27 pub fn children_count(&self) -> usize {
29 let count = self.bindings.FPDF_StructTree_CountChildren(self.tree_handle);
30 if count < 0 { 0 } else { count as usize }
31 }
32
33 pub fn child_at_index(&self, index: usize) -> Option<PdfStructElement<'_>> {
36 let handle = self
37 .bindings
38 .FPDF_StructTree_GetChildAtIndex(self.tree_handle, index as c_int);
39 if handle.is_null() {
40 None
41 } else {
42 Some(PdfStructElement::from_pdfium(handle, self.bindings))
43 }
44 }
45
46 pub fn children(&self) -> PdfStructTreeChildrenIterator<'_> {
48 PdfStructTreeChildrenIterator {
49 tree: self,
50 count: self.children_count(),
51 index: 0,
52 }
53 }
54
55 pub fn iter(&self) -> PdfStructTreeIterator<'_> {
60 let mut stack = Vec::new();
61 let count = self.children_count();
62 for i in (0..count).rev() {
63 if let Some(child) = self.child_at_index(i) {
64 stack.push((child, 0usize));
65 }
66 }
67 PdfStructTreeIterator { stack }
68 }
69}
70
71impl Drop for PdfStructTree<'_> {
72 fn drop(&mut self) {
73 self.bindings.FPDF_StructTree_Close(self.tree_handle);
74 }
75}
76
77pub struct PdfStructTreeChildrenIterator<'a> {
79 tree: &'a PdfStructTree<'a>,
80 count: usize,
81 index: usize,
82}
83
84impl<'a> Iterator for PdfStructTreeChildrenIterator<'a> {
85 type Item = PdfStructElement<'a>;
86
87 fn next(&mut self) -> Option<Self::Item> {
88 while self.index < self.count {
89 let current = self.index;
90 self.index += 1;
91 if let Some(child) = self.tree.child_at_index(current) {
92 return Some(child);
93 }
94 }
95 None
96 }
97}
98
99pub struct PdfStructTreeIterator<'a> {
104 stack: Vec<(PdfStructElement<'a>, usize)>,
105}
106
107impl<'a> Iterator for PdfStructTreeIterator<'a> {
108 type Item = (PdfStructElement<'a>, usize);
109
110 fn next(&mut self) -> Option<Self::Item> {
111 let (element, depth) = self.stack.pop()?;
112
113 let child_count = element.children_count();
114 for i in (0..child_count).rev() {
115 if let Some(child) = element.child_at_index(i) {
116 self.stack.push((child, depth + 1));
117 }
118 }
119
120 Some((element, depth))
121 }
122}