feat(pdf): searchable text layer with per-style subset font embedding

Real BT/Tj text objects ride alongside the vector outlines (Tr 3,
zero visual change): runs preserved at layout time, TTF styles embedded
as allsorts subsets with ToUnicode, width-matched Tm, clip-culled.
WireModel literals moved to ..Default::default() tails.
This commit is contained in:
Karim Jerbi committed 2026-10-01 23:30:35 +01:00
1 parent 443b935a3f
commit 02c470aac7
44 files changed
+1534 -127

No files matched your search

+23
View File
@@ -347,6 +347,29 @@ impl Scene {
out.pattern_stations.clear();
}
out.text_verts = projected_text;
// Searchable runs ride the same projection through the shared
// helper (origin map + height/advance scale), then cull by
// run-rect overlap — a run straddling the viewport edge is
// kept, where origin-only culling would drop visible text.
out.searchable_text = wire.searchable_text.clone();
out.map_searchable_runs(
&|p| {
let q = proj_abs(p[0], p[1], p[2]);
[q[0] as f64, q[1] as f64, q[2] as f64]
},
scale as f64,
0.0,
);
out.searchable_text.retain(|run| {
run.origin.iter().all(|v| v.is_finite())
&& crate::scene::model::wire_model::run_rect_overlap(
[run.origin[0], run.origin[1]],
run.rotation,
run.adv_width as f64,
run.height as f64,
[vp_x0 as f64, vp_y0 as f64, vp_x1 as f64, vp_y1 as f64],
)
});
// Paper coordinates are small sheet units — no relative-to-eye
// residual is needed, and keeping the model wire's points_low
// here would add a model-scale offset to the paper points.