pdfium_render/pdf/document/page/text/
chars.rs1use crate::bindgen::{FPDF_DOCUMENT, FPDF_PAGE, FPDF_TEXTPAGE};
5use crate::bindings::PdfiumLibraryBindings;
6use crate::error::PdfiumError;
7use crate::pdf::document::page::text::char::PdfPageTextChar;
8use crate::pdf::document::page::PdfPageText;
9use crate::pdf::points::PdfPoints;
10
11#[cfg(doc)]
12use crate::pdf::document::page::PdfPage;
13
14pub type PdfPageTextCharIndex = usize;
16
17pub struct PdfPageTextChars<'a> {
19 document_handle: FPDF_DOCUMENT,
20 page_handle: FPDF_PAGE,
21 text_page_handle: FPDF_TEXTPAGE,
22 char_indices: Vec<i32>,
23 bindings: &'a dyn PdfiumLibraryBindings,
24}
25
26impl<'a> PdfPageTextChars<'a> {
27 #[inline]
28 pub(crate) fn new(
29 document_handle: FPDF_DOCUMENT,
30 page_handle: FPDF_PAGE,
31 text_page_handle: FPDF_TEXTPAGE,
32 char_indices: Vec<i32>,
33 bindings: &'a dyn PdfiumLibraryBindings,
34 ) -> Self {
35 PdfPageTextChars {
36 document_handle,
37 page_handle,
38 text_page_handle,
39 char_indices,
40 bindings,
41 }
42 }
43
44 #[inline]
47 pub(crate) fn document_handle(&self) -> FPDF_DOCUMENT {
48 self.document_handle
49 }
50
51 #[inline]
54 pub(crate) fn page_handle(&self) -> FPDF_PAGE {
55 self.page_handle
56 }
57
58 #[inline]
60 pub(crate) fn text_page_handle(&self) -> FPDF_TEXTPAGE {
61 self.text_page_handle
62 }
63
64 #[inline]
66 pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
67 self.bindings
68 }
69
70 #[inline]
73 pub fn first_char_index(&self) -> Option<PdfPageTextCharIndex> {
74 self.char_indices
75 .first()
76 .map(|index| *index as PdfPageTextCharIndex)
77 }
78
79 #[inline]
81 pub fn len(&self) -> PdfPageTextCharIndex {
82 self.char_indices.len()
83 }
84
85 #[inline]
88 pub fn last_char_index(&self) -> Option<PdfPageTextCharIndex> {
89 self.char_indices
90 .last()
91 .map(|index| *index as PdfPageTextCharIndex)
92 }
93
94 #[inline]
96 pub fn is_empty(&self) -> bool {
97 self.len() == 0
98 }
99
100 #[inline]
102 pub fn get(&self, index: PdfPageTextCharIndex) -> Result<PdfPageTextChar, PdfiumError> {
103 match self.char_indices.get(index) {
104 Some(index) => Ok(PdfPageTextChar::from_pdfium(
105 self.document_handle(),
106 self.page_handle(),
107 self.text_page_handle(),
108 *index,
109 self.bindings(),
110 )),
111 None => Err(PdfiumError::CharIndexOutOfBounds),
112 }
113 }
114
115 #[inline]
117 pub fn get_char_at_point(&self, x: PdfPoints, y: PdfPoints) -> Option<PdfPageTextChar> {
118 self.get_char_near_point(x, PdfPoints::ZERO, y, PdfPoints::ZERO)
119 }
120
121 #[inline]
125 pub fn get_char_near_point(
126 &self,
127 x: PdfPoints,
128 tolerance_x: PdfPoints,
129 y: PdfPoints,
130 tolerance_y: PdfPoints,
131 ) -> Option<PdfPageTextChar> {
132 PdfPageText::get_char_index_near_point(
133 self.text_page_handle(),
134 x,
135 tolerance_x,
136 y,
137 tolerance_y,
138 self.bindings(),
139 )
140 .ok_or(PdfiumError::CharIndexOutOfBounds)
141 .and_then(|index| self.get(index))
142 .ok()
143 }
144
145 #[inline]
147 pub fn iter(&self) -> PdfPageTextCharsIterator {
148 PdfPageTextCharsIterator::new(self)
149 }
150}
151
152pub struct PdfPageTextCharsIterator<'a> {
154 chars: &'a PdfPageTextChars<'a>,
155 next_index: PdfPageTextCharIndex,
156}
157
158impl<'a> PdfPageTextCharsIterator<'a> {
159 #[inline]
160 pub(crate) fn new(chars: &'a PdfPageTextChars) -> Self {
161 PdfPageTextCharsIterator {
162 chars,
163 next_index: 0,
164 }
165 }
166}
167
168impl<'a> Iterator for PdfPageTextCharsIterator<'a> {
169 type Item = PdfPageTextChar<'a>;
170
171 fn next(&mut self) -> Option<Self::Item> {
172 let next = self.chars.get(self.next_index);
173
174 self.next_index += 1;
175
176 next.ok()
177 }
178}