use crate::pdf::hierarchy::SegmentData;
#[derive(Debug, Clone)]
pub(crate) struct PdfLine {
pub segments: Vec<SegmentData>,
pub baseline_y: f32,
#[allow(dead_code)]
pub dominant_font_size: f32,
#[allow(dead_code)]
pub is_bold: bool,
pub is_monospace: bool,
}
#[derive(Debug, Clone)]
pub(crate) struct PdfParagraph {
pub text: String,
pub lines: Vec<PdfLine>,
pub dominant_font_size: f32,
pub heading_level: Option<u8>,
pub is_bold: bool,
pub is_list_item: bool,
pub is_code_block: bool,
pub is_formula: bool,
pub is_page_furniture: bool,
pub layout_class: Option<LayoutHintClass>,
pub layout_region_path: Option<LayoutRegionPath>,
pub caption_for: Option<usize>,
pub block_bbox: Option<(f32, f32, f32, f32)>,
pub word_count: usize,
}
impl PdfParagraph {
pub(crate) fn is_monospace_hint(&self) -> bool {
self.is_code_block
}
pub(crate) fn compute_word_count(text: &str, lines: &[PdfLine]) -> usize {
if !text.is_empty() {
text.split_whitespace().count()
} else {
lines
.iter()
.flat_map(|l| l.segments.iter())
.map(|s| s.text.split_whitespace().count())
.sum()
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[allow(dead_code)]
pub(crate) enum LayoutHintClass {
Title,
SectionHeader,
Code,
Formula,
ListItem,
Caption,
Footnote,
PageHeader,
PageFooter,
Table,
Picture,
DocumentIndex,
Form,
KeyValueRegion,
Text,
Other,
}
impl LayoutHintClass {
pub(crate) const fn is_wrapper(self) -> bool {
matches!(
self,
Self::Table | Self::Picture | Self::DocumentIndex | Self::Form | Self::KeyValueRegion
)
}
pub(crate) const fn label(self) -> &'static str {
match self {
Self::Title => "title",
Self::SectionHeader => "section_header",
Self::Code => "code",
Self::Formula => "formula",
Self::ListItem => "list_item",
Self::Caption => "caption",
Self::Footnote => "footnote",
Self::PageHeader => "page_header",
Self::PageFooter => "page_footer",
Self::Table => "table",
Self::Picture => "picture",
Self::DocumentIndex => "document_index",
Self::Form => "form",
Self::KeyValueRegion => "key_value_region",
Self::Text => "text",
Self::Other => "other",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct LayoutRegionTag {
pub(crate) id: usize,
pub(crate) class_name: Option<LayoutHintClass>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct LayoutRegionPath {
pub(crate) root: LayoutRegionTag,
pub(crate) child: Option<LayoutRegionTag>,
}
impl LayoutRegionPath {
pub(crate) fn tags(self) -> impl Iterator<Item = LayoutRegionTag> {
std::iter::once(self.root).chain(self.child)
}
}
#[derive(Debug, Clone)]
pub(crate) struct LayoutHint {
pub class_name: LayoutHintClass,
pub confidence: f32,
pub left: f32,
pub bottom: f32,
pub right: f32,
pub top: f32,
}
#[cfg(feature = "layout-detection")]
#[derive(Debug, Clone)]
pub struct PageLayoutResult {
pub page_width_pts: f32,
pub page_height_pts: f32,
}