use crate::bindgen::FS_RECTF;
use crate::bindings::PdfiumLibraryBindings;
use crate::error::PdfiumError;
use crate::pdf::document::page::text::segment::PdfPageTextSegment;
use crate::pdf::document::page::text::PdfPageText;
use crate::pdf::rect::PdfRect;
use std::ops::{Range, RangeInclusive};
use std::os::raw::c_int;
#[cfg(doc)]
use {
crate::pdf::document::page::object::text::PdfPageTextObject,
crate::pdf::document::page::PdfPage,
};
pub type PdfPageTextSegmentIndex = usize;
pub struct PdfPageTextSegments<'a> {
text: &'a PdfPageText<'a>,
start: i32,
characters: i32,
bindings: &'a dyn PdfiumLibraryBindings,
}
impl<'a> PdfPageTextSegments<'a> {
#[inline]
pub(crate) fn new(
text: &'a PdfPageText<'a>,
start: i32,
characters: i32,
bindings: &'a dyn PdfiumLibraryBindings,
) -> Self {
PdfPageTextSegments {
text,
start,
characters,
bindings,
}
}
#[inline]
pub fn len(&self) -> PdfPageTextSegmentIndex {
(unsafe {
self.bindings.FPDFText_CountRects(
self.text.text_page_handle(),
self.start,
self.characters,
)
}) as PdfPageTextSegmentIndex
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn as_range(&self) -> Range<PdfPageTextSegmentIndex> {
0..self.len()
}
#[inline]
pub fn as_range_inclusive(&self) -> RangeInclusive<PdfPageTextSegmentIndex> {
if self.is_empty() {
0..=0
} else {
0..=(self.len() - 1)
}
}
#[inline]
pub fn get(
&self,
index: PdfPageTextSegmentIndex,
) -> Result<PdfPageTextSegment<'_>, PdfiumError> {
if index >= self.len() {
return Err(PdfiumError::TextSegmentIndexOutOfBounds);
}
let mut left = 0.0;
let mut bottom = 0.0;
let mut right = 0.0;
let mut top = 0.0;
let result = unsafe {
self.bindings.FPDFText_GetRect(
self.text.text_page_handle(),
index as c_int,
&mut left,
&mut top,
&mut right,
&mut bottom,
)
};
PdfRect::from_pdfium_as_result(
result,
FS_RECTF {
left: left as f32,
top: top as f32,
right: right as f32,
bottom: bottom as f32,
},
self.bindings,
)
.map(|rect| PdfPageTextSegment::from_pdfium(self.text, rect))
}
#[inline]
pub fn iter(&self) -> PdfPageTextSegmentsIterator<'_> {
PdfPageTextSegmentsIterator::new(self)
}
}
pub struct PdfPageTextSegmentsIterator<'a> {
segments: &'a PdfPageTextSegments<'a>,
next_index: PdfPageTextSegmentIndex,
}
impl<'a> PdfPageTextSegmentsIterator<'a> {
#[inline]
pub(crate) fn new(segments: &'a PdfPageTextSegments<'a>) -> Self {
PdfPageTextSegmentsIterator {
segments,
next_index: 0,
}
}
}
impl<'a> Iterator for PdfPageTextSegmentsIterator<'a> {
type Item = PdfPageTextSegment<'a>;
fn next(&mut self) -> Option<Self::Item> {
let next = self.segments.get(self.next_index);
self.next_index += 1;
next.ok()
}
}