This commit is contained in:
Jacob Lifshay 2026-01-02 07:34:40 -08:00
parent 9e090a66a3
commit 718de40b09
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ

View file

@ -5,8 +5,11 @@ use crate::quad_tree::QuadTree;
use non_nan_float::NonNaNF32;
use std::{
borrow::Borrow,
cell::RefCell,
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
fmt,
num::NonZero,
rc::Rc,
sync::OnceLock,
};
@ -96,6 +99,15 @@ macro_rules! make_enum_font {
}
impl $Font {
fn new(font_name: &str, size: NonNaNF32) -> Self {
match (font_name, size.get()) {
$($(($known_font_name, $known_font_size) => Self::$KnownFont,)*)*
_ => Self::Other {
font_name: Box::from(font_name),
size,
}
}
}
const fn size(&self) -> f32 {
match *self {
Self::$Other { size, .. } => size.get(),
@ -535,7 +547,6 @@ impl Font {
struct Char {
font: Font,
text: String,
adv: NonNaNF32,
min_x: NonNaNF32,
min_y: NonNaNF32,
max_x: NonNaNF32,
@ -1711,4 +1722,178 @@ impl TextSection {
}
}
fn main() {}
#[derive(Clone, Debug, Default)]
struct MyDevice {
chars: Rc<RefCell<Vec<Char>>>,
}
impl MyDevice {
fn text(&mut self, text: &mupdf::Text, cmt: mupdf::Matrix) {
for span in text.spans() {
let span_font = span.font();
let font_name = span_font.name();
const ROUND_FACTOR: f32 = 1000.0;
let Some(size) =
NonNaNF32::new((span.trm().expansion() * ROUND_FACTOR).round() / ROUND_FACTOR)
else {
continue;
};
let font = Font::new(font_name, size);
for item in span.items() {
let Some(ch) = u32::try_from(item.ucs())
.ok()
.and_then(|v| char::try_from(v).ok())
else {
continue;
};
let mut m = span.trm();
m.e = item.x();
m.f = item.y();
m.concat(cmt);
let (min_x, min_y, max_x, max_y) = match span.wmode() {
mupdf::WriteMode::Horizontal => {
todo!();
}
mupdf::WriteMode::Vertical => todo!(),
};
self.chars.borrow_mut().push(Char {
font,
text: String::from(ch),
min_x,
min_y,
max_x,
max_y,
});
}
}
}
}
impl mupdf::NativeDevice for MyDevice {
fn fill_path(
&mut self,
path: &mupdf::Path,
even_odd: bool,
cmt: mupdf::Matrix,
color_space: &mupdf::Colorspace,
color: &[f32],
alpha: f32,
cp: mupdf::ColorParams,
) {
// TODO
}
fn stroke_path(
&mut self,
path: &mupdf::Path,
stroke_state: &mupdf::StrokeState,
cmt: mupdf::Matrix,
color_space: &mupdf::Colorspace,
color: &[f32],
alpha: f32,
cp: mupdf::ColorParams,
) {
// TODO
}
fn clip_path(
&mut self,
path: &mupdf::Path,
even_odd: bool,
cmt: mupdf::Matrix,
scissor: mupdf::Rect,
) {
// TODO
}
fn clip_stroke_path(
&mut self,
path: &mupdf::Path,
stroke_state: &mupdf::StrokeState,
cmt: mupdf::Matrix,
scissor: mupdf::Rect,
) {
// TODO
}
fn fill_text(
&mut self,
text: &mupdf::Text,
cmt: mupdf::Matrix,
_color_space: &mupdf::Colorspace,
_color: &[f32],
_alpha: f32,
_cp: mupdf::ColorParams,
) {
self.text(text, cmt);
}
fn stroke_text(
&mut self,
text: &mupdf::Text,
_stroke_state: &mupdf::StrokeState,
cmt: mupdf::Matrix,
_color_space: &mupdf::Colorspace,
_color: &[f32],
_alpha: f32,
_cp: mupdf::ColorParams,
) {
self.text(text, cmt);
}
fn clip_text(&mut self, text: &mupdf::Text, cmt: mupdf::Matrix, _scissor: mupdf::Rect) {
self.text(text, cmt);
}
fn clip_stroke_text(
&mut self,
text: &mupdf::Text,
_stroke_state: &mupdf::StrokeState,
cmt: mupdf::Matrix,
_scissor: mupdf::Rect,
) {
self.text(text, cmt);
}
fn ignore_text(&mut self, text: &mupdf::Text, cmt: mupdf::Matrix) {
self.text(text, cmt);
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
let page_numbers: Option<Box<dyn Iterator<Item = NonZero<u32>>>> = if 2 < args.len() {
Some(if let Some((start, end)) = args[2].split_once(":") {
let start: NonZero<u32> = start.trim().parse()?;
let end: NonZero<u32> = end.trim().parse()?;
Box::new(
(start.get()..end.get()).map(|v| NonZero::new(v).expect("known to be non-zero")),
)
} else {
Box::new(
Result::<BTreeSet<NonZero<u32>>, _>::from_iter(
args[2].split(",").map(|v| v.trim().parse()),
)?
.into_iter(),
)
})
} else {
None
};
let document = mupdf::Document::open(&args[1])?;
let pages: Vec<_> = document.pages()?.collect::<Result<_, _>>()?;
let page_numbers = page_numbers.unwrap_or_else(|| {
Box::new(
(0..pages.len()).map(|i| NonZero::new((i + 1) as u32).expect("known to be non-zero")),
)
});
for page_num in page_numbers {
let device = MyDevice::default();
pages[page_num.get() as usize - 1].run(
&mupdf::Device::from_native(device.clone())?,
&mupdf::Matrix::IDENTITY,
)?;
println!("{device:?}");
}
Ok(())
}