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::PdfPageText;
8use crate::pdf::document::page::text::char::PdfPageTextChar;
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.first().map(|index| *index as PdfPageTextCharIndex)
75 }
76
77 #[inline]
79 pub fn len(&self) -> PdfPageTextCharIndex {
80 self.char_indices.len()
81 }
82
83 #[inline]
86 pub fn last_char_index(&self) -> Option<PdfPageTextCharIndex> {
87 self.char_indices.last().map(|index| *index as PdfPageTextCharIndex)
88 }
89
90 #[inline]
92 pub fn is_empty(&self) -> bool {
93 self.len() == 0
94 }
95
96 #[inline]
98 pub fn get(&self, index: PdfPageTextCharIndex) -> Result<PdfPageTextChar<'_>, PdfiumError> {
99 match self.char_indices.get(index) {
100 Some(index) => Ok(PdfPageTextChar::from_pdfium(
101 self.document_handle(),
102 self.page_handle(),
103 self.text_page_handle(),
104 *index,
105 self.bindings(),
106 )),
107 None => Err(PdfiumError::CharIndexOutOfBounds),
108 }
109 }
110
111 #[inline]
113 pub fn get_char_at_point(&self, x: PdfPoints, y: PdfPoints) -> Option<PdfPageTextChar<'_>> {
114 self.get_char_near_point(x, PdfPoints::ZERO, y, PdfPoints::ZERO)
115 }
116
117 #[inline]
121 pub fn get_char_near_point(
122 &self,
123 x: PdfPoints,
124 tolerance_x: PdfPoints,
125 y: PdfPoints,
126 tolerance_y: PdfPoints,
127 ) -> Option<PdfPageTextChar<'_>> {
128 PdfPageText::get_char_index_near_point(self.text_page_handle(), x, tolerance_x, y, tolerance_y, self.bindings())
129 .ok_or(PdfiumError::CharIndexOutOfBounds)
130 .and_then(|index| self.get(index))
131 .ok()
132 }
133
134 #[inline]
136 pub fn iter(&self) -> PdfPageTextCharsIterator<'_> {
137 PdfPageTextCharsIterator::new(self)
138 }
139}
140
141pub struct PdfPageTextCharsIterator<'a> {
143 chars: &'a PdfPageTextChars<'a>,
144 next_index: PdfPageTextCharIndex,
145}
146
147impl<'a> PdfPageTextCharsIterator<'a> {
148 #[inline]
149 pub(crate) fn new(chars: &'a PdfPageTextChars) -> Self {
150 PdfPageTextCharsIterator { chars, next_index: 0 }
151 }
152}
153
154impl<'a> Iterator for PdfPageTextCharsIterator<'a> {
155 type Item = PdfPageTextChar<'a>;
156
157 fn next(&mut self) -> Option<Self::Item> {
158 let next = self.chars.get(self.next_index);
159
160 self.next_index += 1;
161
162 next.ok()
163 }
164}