rapiddoc_native/
visual_text.rs1use crate::{
3 python_decimal, python_printable,
4 text_boundary::{python_alnum, python_digit, python_space},
5};
6pub use docvortex_core::text_pipeline::{TextChar, VisualTextRun};
7use std::sync::OnceLock;
8pub fn prepare(
9 chars: &[TextChar],
10 size: [f64; 2],
11 rotation: i32,
12 supported: &[f64],
13) -> Vec<VisualTextRun> {
14 static MATH: OnceLock<Vec<[u32; 2]>> = OnceLock::new();
15 let ranges =
16 MATH.get_or_init(|| serde_json::from_str(include_str!("visual_math.json")).unwrap());
17 let mut unicode = docvortex_core::text_pipeline::UnicodeProperties::default();
18 for c in chars
19 .iter()
20 .flat_map(|c| c.text.chars())
21 .filter(|c| !c.is_ascii())
22 {
23 unicode.0.entry(c).or_insert_with(|| {
24 let n = c as u32;
25 let i = ranges.partition_point(|r| r[0] <= n);
26 let math = i > 0 && n <= ranges[i - 1][1];
27 u8::from(python_alnum(c))
28 | (u8::from(python_digit(c)) << 1)
29 | (u8::from(math) << 2)
30 | (u8::from(python_space(c)) << 3)
31 | (u8::from(python_printable(c)) << 4)
32 | (u8::from(python_decimal(c).is_some()) << 5)
33 });
34 }
35 docvortex_core::text_pipeline::prepare_visual_lines(
36 chars,
37 size,
38 rotation,
39 supported,
40 &unicode,
41 &[],
42 )
43}
44pub type PairRecord = ([f64; 4], f64, f64, usize, bool, usize, usize);
45pub fn matches(records: Vec<PairRecord>) -> Option<Vec<(usize, usize, bool, bool)>> {
46 docvortex_core::inline_pairs::matches(records)
47}
48pub fn split_runs(
50 raw: Vec<Option<[f64; 4]>>,
51 overrides: Vec<Option<[f64; 4]>>,
52 flags: Vec<u8>,
53 size: [f64; 2],
54 angle: i32,
55) -> Option<Vec<(usize, usize, Option<[f64; 4]>)>> {
56 if raw.len() != flags.len()
57 || overrides.len() != flags.len()
58 || raw.len() > rapiddoc_core::resources::limit(20000)
59 {
60 return None;
61 }
62 Some(docvortex_core::geometry::visual_runs(
63 raw, overrides, flags, size, angle,
64 ))
65}