forked from 1b-agent/opencadstudio-upstream
feat(text): read unifont and big-font .shx files; pair a style's big font
`shx.rs` only accepted the classic `AutoCAD-86 shapes 1.x` container, so every modern Autodesk font (`txt.shx`, `simplex.shx`, `romans.shx`, … are `unifont 1.0`) and every Asian big font (`chineset.shx`, `hztxt.shx`, `bigfont.shx` — `bigfont 1.0`) was rejected and text fell back to the LFF substitutes and TrueType fallback glyphs. Drawings authored with SHX big fonts (the norm for Chinese / Japanese / Korean sheets) never showed their real glyphs. - Parse all three containers. Unifont glyphs are keyed by Unicode; big-font glyphs by their double-byte code from a sparse hash table of (code, length, offset) entries. Big fonts reference subshapes with a two-byte `7, 0, hi, lo`. - `bigfont_glyph` encodes a character with encoding_rs (Big5 / GBK / Shift_JIS / EUC-KR, most likely first for the file name) and takes the first code the font has. - `Face::WithBig` pairs a style's big font with its primary face: full-width characters come from the big font, everything else from the primary — how a STYLE with a "Big Font" behaves in AutoCAD. `resolve_text_style` resolves `big_font_file` like the primary (next to the drawing, then the user fonts folder) and rides it along in the font name. - The missing-fonts dialog lists unresolvable big fonts too. Unit tests cover a synthetic big font (Big5 lookup, cap-height scaling, no aliasing of unknown codes), a synthetic unifont, and the pairing. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
1 parent
0b522ceb86
commit
ff4981ffe6
6 files changed
+351
-35
No files matched your search
+15
-12
@@ -70,18 +70,21 @@ pub fn missing_shx_fonts(doc: &CadDocument) -> Vec<String> {
|
||||
.map(Path::new)
|
||||
.and_then(|p| p.parent());
|
||||
for style in doc.text_styles.iter() {
|
||||
let file = style.font_file.trim();
|
||||
if file.is_empty() || !file.to_ascii_lowercase().ends_with(".shx") {
|
||||
continue;
|
||||
}
|
||||
let resolved = crate::io::resolve_image_file(file, base).is_some()
|
||||
|| local_font_file(file).is_some();
|
||||
if resolved {
|
||||
continue;
|
||||
}
|
||||
let name = file.rsplit(['/', '\\']).next().unwrap_or(file).to_string();
|
||||
if !missing.iter().any(|m| m.eq_ignore_ascii_case(&name)) {
|
||||
missing.push(name);
|
||||
// The primary font and the big font (Asian double-byte glyphs) are
|
||||
// both plain .shx files the style depends on.
|
||||
for file in [style.font_file.trim(), style.big_font_file.trim()] {
|
||||
if file.is_empty() || !file.to_ascii_lowercase().ends_with(".shx") {
|
||||
continue;
|
||||
}
|
||||
let resolved = crate::io::resolve_image_file(file, base).is_some()
|
||||
|| local_font_file(file).is_some();
|
||||
if resolved {
|
||||
continue;
|
||||
}
|
||||
let name = file.rsplit(['/', '\\']).next().unwrap_or(file).to_string();
|
||||
if !missing.iter().any(|m| m.eq_ignore_ascii_case(&name)) {
|
||||
missing.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
missing.sort_by_key(|name| name.to_ascii_lowercase());
|
||||
|
||||
Reference in new issue
Block a user