pdfium_render/pdf/document/page/text/
chars.rs1use crate::bindgen::{FPDF_DOCUMENT, FPDF_PAGE, FPDF_TEXTPAGE};
5use crate::error::PdfiumError;
6use crate::pdf::document::page::text::char::PdfPageTextChar;
7use crate::pdf::document::page::PdfPageText;
8use crate::pdf::points::PdfPoints;
9use crate::pdfium::PdfiumLibraryBindingsAccessor;
10use std::marker::PhantomData;
11
12#[cfg(doc)]
13use crate::pdf::document::page::PdfPage;
14
15pub type PdfPageTextCharIndex = usize;
17
18pub struct PdfPageTextChars<'a> {
20 document_handle: FPDF_DOCUMENT,
21 page_handle: FPDF_PAGE,
22 text_page_handle: FPDF_TEXTPAGE,
23 char_indices: Vec<i32>,
24 lifetime: PhantomData<&'a FPDF_TEXTPAGE>,
25}
26
27impl<'a> PdfPageTextChars<'a> {
28 #[inline]
29 pub(crate) fn new(
30 document_handle: FPDF_DOCUMENT,
31 page_handle: FPDF_PAGE,
32 text_page_handle: FPDF_TEXTPAGE,
33 char_indices: Vec<i32>,
34 ) -> Self {
35 PdfPageTextChars {
36 document_handle,
37 page_handle,
38 text_page_handle,
39 char_indices,
40 lifetime: PhantomData,
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]
67 pub fn first_char_index(&self) -> Option<PdfPageTextCharIndex> {
68 self.char_indices
69 .first()
70 .map(|index| *index as PdfPageTextCharIndex)
71 }
72
73 #[inline]
75 pub fn len(&self) -> PdfPageTextCharIndex {
76 self.char_indices.len()
77 }
78
79 #[inline]
82 pub fn last_char_index(&self) -> Option<PdfPageTextCharIndex> {
83 self.char_indices
84 .last()
85 .map(|index| *index as PdfPageTextCharIndex)
86 }
87
88 #[inline]
90 pub fn is_empty(&self) -> bool {
91 self.len() == 0
92 }
93
94 #[inline]
96 pub fn get(&self, index: PdfPageTextCharIndex) -> Result<PdfPageTextChar<'_>, PdfiumError> {
97 match self.char_indices.get(index) {
98 Some(index) => Ok(PdfPageTextChar::from_pdfium(
99 self.document_handle(),
100 self.page_handle(),
101 self.text_page_handle(),
102 *index,
103 )),
104 None => Err(PdfiumError::CharIndexOutOfBounds),
105 }
106 }
107
108 #[inline]
110 pub fn get_char_at_point(&self, x: PdfPoints, y: PdfPoints) -> Option<PdfPageTextChar<'_>> {
111 self.get_char_near_point(x, PdfPoints::ZERO, y, PdfPoints::ZERO)
112 }
113
114 #[inline]
118 pub fn get_char_near_point(
119 &self,
120 x: PdfPoints,
121 tolerance_x: PdfPoints,
122 y: PdfPoints,
123 tolerance_y: PdfPoints,
124 ) -> Option<PdfPageTextChar<'_>> {
125 PdfPageText::get_char_index_near_point(
126 self.text_page_handle(),
127 x,
128 tolerance_x,
129 y,
130 tolerance_y,
131 self.bindings(),
132 )
133 .ok_or(PdfiumError::CharIndexOutOfBounds)
134 .and_then(|index| self.get(index))
135 .ok()
136 }
137
138 #[inline]
140 pub fn iter(&self) -> PdfPageTextCharsIterator<'_> {
141 PdfPageTextCharsIterator::new(self)
142 }
143}
144
145impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfPageTextChars<'a> {}
146
147#[cfg(feature = "thread_safe")]
148unsafe impl<'a> Send for PdfPageTextChars<'a> {}
149
150#[cfg(feature = "thread_safe")]
151unsafe impl<'a> Sync for PdfPageTextChars<'a> {}
152
153pub struct PdfPageTextCharsIterator<'a> {
155 chars: &'a PdfPageTextChars<'a>,
156 next_index: PdfPageTextCharIndex,
157}
158
159impl<'a> PdfPageTextCharsIterator<'a> {
160 #[inline]
161 pub(crate) fn new(chars: &'a PdfPageTextChars) -> Self {
162 PdfPageTextCharsIterator {
163 chars,
164 next_index: 0,
165 }
166 }
167}
168
169impl<'a> Iterator for PdfPageTextCharsIterator<'a> {
170 type Item = PdfPageTextChar<'a>;
171
172 fn next(&mut self) -> Option<Self::Item> {
173 let next = self.chars.get(self.next_index);
174
175 self.next_index += 1;
176
177 next.ok()
178 }
179}