pub mod geometric;
pub mod simple;
pub mod structure_tree;
pub mod xycut;
pub use geometric::GeometricStrategy;
pub use simple::SimpleStrategy;
pub use structure_tree::StructureTreeStrategy;
pub use xycut::XYCutStrategy;
use crate::error::Result;
use crate::geometry::Rect;
use crate::layout::TextSpan;
use crate::pipeline::config::ReadingOrderStrategyType;
use crate::pipeline::OrderedTextSpan;
pub trait ReadingOrderStrategy: Send + Sync {
fn apply(
&self,
spans: Vec<TextSpan>,
context: &ReadingOrderContext,
) -> Result<Vec<OrderedTextSpan>>;
fn name(&self) -> &'static str;
}
#[derive(Debug, Default)]
pub struct ReadingOrderContext {
pub page_number: u32,
pub page_bbox: Option<Rect>,
pub has_structure_tree: bool,
pub mcid_order: Option<Vec<u32>>,
pub suspects: bool,
}
impl ReadingOrderContext {
pub fn new() -> Self {
Self::default()
}
pub fn with_page(mut self, page_number: u32) -> Self {
self.page_number = page_number;
self
}
pub fn with_bbox(mut self, bbox: Rect) -> Self {
self.page_bbox = Some(bbox);
self
}
pub fn with_mcid_order(mut self, mcid_order: Vec<u32>) -> Self {
self.has_structure_tree = true;
self.mcid_order = Some(mcid_order);
self
}
pub fn with_suspects(mut self, suspects: bool) -> Self {
self.suspects = suspects;
self
}
}
pub fn create_strategy(
config: &crate::pipeline::ReadingOrderConfig,
) -> Box<dyn ReadingOrderStrategy> {
match config.strategy {
ReadingOrderStrategyType::StructureTreeFirst => Box::new(StructureTreeStrategy::new()),
ReadingOrderStrategyType::Geometric => Box::new(GeometricStrategy::new()),
ReadingOrderStrategyType::XYCut => Box::new(XYCutStrategy::new()),
ReadingOrderStrategyType::Simple => Box::new(SimpleStrategy),
}
}