From de65cd7e509cd162c1d4839e3cc67ed1888f8149 Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Tue, 6 Oct 2026 14:33:59 +0300 Subject: [PATCH 1/2] Text: stroke font space widths of the reference The SHX names the embedded LFF fonts stand in for (txt, monotxt, simplex, romans, romand, romanc, complex, italic, gdt, isocp) use the space advance of the reference's fonts. Co-Authored-By: Claude Opus 5.5 --- src/scene/text/lff.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/scene/text/lff.rs b/src/scene/text/lff.rs index 0fe1f877b..3314d9b11 100644 --- a/src/scene/text/lff.rs +++ b/src/scene/text/lff.rs @@ -87,6 +87,22 @@ const ALIASES: &[(&str, &str)] = &[ ("EXTFONT", "unicode"), ]; +/// The space advance of the reference's stroke fonts, in glyph units (cap +/// height 9), measured from their text extents: the SHX names these LFF +/// fonts stand in for keep the reference's word gaps. +const SHX_SPACE: &[(&str, f32)] = &[ + ("TXT", 9.0), + ("MONOTXT", 9.0), + ("SIMPLEX", 9.0 * 19.0 / 21.0), + ("ROMANS", 9.0), + ("ROMAND", 9.0), + ("ROMANC", 9.0), + ("COMPLEX", 9.0), + ("ITALIC", 9.0), + ("GDT", 9.0), + ("ISOCP", 3.6), +]; + // ── Public types ────────────────────────────────────────────────────────── /// One glyph: a list of open 2-D polyline strokes in glyph units. @@ -163,6 +179,12 @@ fn fonts_map() -> &'static HashMap { map.insert(alias.to_ascii_uppercase(), f); } } + // Those names keep the reference font's space width. + for (name, word) in SHX_SPACE { + if let Some(f) = map.get_mut(*name) { + f.word_spacing = *word; + } + } map }) } From c83d37b24d2b34a44310611eb11427987a22de19 Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Tue, 6 Oct 2026 15:17:39 +0300 Subject: [PATCH 2/2] Text: stroke font character advances of the reference txt, simplex and romans keep the reference fonts' printable ASCII pen advances, so lines measure, wrap and align like the reference. Co-Authored-By: Claude Opus 5.5 --- src/scene/text/lff.rs | 98 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/scene/text/lff.rs b/src/scene/text/lff.rs index 3314d9b11..1b11ca98d 100644 --- a/src/scene/text/lff.rs +++ b/src/scene/text/lff.rs @@ -103,6 +103,91 @@ const SHX_SPACE: &[(&str, f32)] = &[ ("ISOCP", 3.6), ]; +/// The pen advance of each printable ASCII character of the reference's +/// stroke fonts, in glyph units (cap height 9), measured from their text +/// extents: the SHX names these LFF fonts stand in for keep the reference's +/// character widths, so lines measure, wrap and align like the reference. +const SHX_ADVANCE: &[(&str, &[(u32, f32)])] = &[ + ( + "TXT", + &[ + (33, 3.0000), (34, 6.0000), (35, 9.0000), (36, 9.0000), (38, 9.0000), (39, 4.5000), + (40, 6.0000), (41, 6.0000), (42, 9.0000), (43, 9.0000), (44, 4.5000), (45, 9.0000), + (46, 3.0000), (47, 9.0000), (48, 7.5000), (49, 6.0000), (50, 9.0000), (51, 9.0000), + (52, 9.0000), (53, 9.0000), (54, 9.0000), (55, 9.0000), (56, 9.0000), (57, 9.0000), + (58, 3.0000), (59, 4.5000), (60, 7.5000), (61, 9.0000), (62, 7.5000), (63, 7.5000), + (64, 9.0000), (65, 9.0000), (66, 9.0000), (67, 9.0000), (68, 9.0000), (69, 9.0000), + (70, 9.0000), (71, 9.0000), (72, 9.0000), (73, 6.0000), (74, 9.0000), (75, 9.0000), + (76, 9.0000), (77, 9.0000), (78, 9.0000), (79, 9.0000), (80, 9.0000), (81, 9.0000), + (82, 9.0000), (83, 9.0000), (84, 9.0000), (85, 9.0000), (86, 12.0000), (87, 12.0000), + (88, 9.0000), (89, 9.0000), (90, 9.0000), (91, 6.0000), (92, 9.0000), (93, 6.0000), + (94, 9.0000), (95, 9.0000), (96, 4.5000), (97, 9.0000), (98, 9.0000), (99, 9.0000), + (100, 9.0000), (101, 9.0000), (102, 9.0000), (103, 9.0000), (104, 9.0000), (105, 3.0000), + (106, 7.5000), (107, 9.0000), (108, 4.5000), (109, 9.0000), (110, 9.0000), (111, 9.0000), + (112, 9.0000), (113, 9.0000), (114, 9.0000), (115, 9.0000), (116, 9.0000), (117, 9.0000), + (118, 9.0000), (119, 9.0000), (120, 9.0000), (121, 9.0000), (122, 9.0000), (123, 6.0000), + (124, 3.0000), (125, 6.0000), (126, 9.0000), + ], + ), + ( + "SIMPLEX", + &[ + (33, 5.5714), (34, 6.4286), (35, 8.1429), (36, 8.5714), (38, 11.1429), (39, 3.8571), + (40, 6.0000), (41, 6.0000), (42, 6.8571), (43, 11.1429), (44, 4.2857), (45, 11.1429), + (46, 4.2857), (47, 9.4286), (48, 8.5714), (49, 6.8571), (50, 8.5714), (51, 8.5714), + (52, 8.5714), (53, 8.5714), (54, 8.5714), (55, 8.5714), (56, 8.5714), (57, 8.5714), + (58, 6.4286), (59, 6.0000), (60, 8.5714), (61, 11.1429), (62, 8.5714), (63, 7.7143), + (64, 10.2857), (65, 9.4286), (66, 9.0000), (67, 9.0000), (68, 9.0000), (69, 8.1429), + (70, 7.7143), (71, 9.0000), (72, 9.4286), (73, 3.4286), (74, 6.8571), (75, 9.0000), + (76, 7.2857), (77, 10.2857), (78, 9.4286), (79, 9.4286), (80, 9.0000), (81, 9.4286), + (82, 9.0000), (83, 8.5714), (84, 7.7143), (85, 9.4286), (86, 8.5714), (87, 10.2857), + (88, 8.5714), (89, 8.5714), (90, 8.5714), (91, 6.4286), (92, 9.4286), (93, 5.1429), + (94, 8.5714), (95, 10.2857), (96, 3.8571), (97, 8.1429), (98, 8.1429), (99, 7.7143), + (100, 8.1429), (101, 7.7143), (102, 5.1429), (103, 8.1429), (104, 8.1429), (105, 3.4286), + (106, 4.2857), (107, 7.2857), (108, 3.4286), (109, 12.8571), (110, 8.1429), (111, 8.1429), + (112, 8.1429), (113, 8.1429), (114, 5.5714), (115, 7.2857), (116, 6.0000), (117, 8.1429), + (118, 6.8571), (119, 9.4286), (120, 7.2857), (121, 6.8571), (122, 7.2857), (123, 5.1429), + (124, 3.0000), (125, 4.7143), (126, 11.1429), + ], + ), + ( + "ROMANS", + &[ + (33, 4.2857), (34, 6.0000), (35, 9.0000), (36, 8.5714), (38, 11.1429), (39, 4.2857), + (40, 6.0000), (41, 6.0000), (42, 6.8571), (43, 11.1429), (44, 4.2857), (45, 11.1429), + (46, 4.2857), (47, 9.4286), (48, 8.5714), (49, 8.5714), (50, 8.5714), (51, 8.5714), + (52, 8.5714), (53, 8.5714), (54, 8.5714), (55, 8.5714), (56, 8.5714), (57, 8.5714), + (58, 4.2857), (59, 4.2857), (60, 10.2857), (61, 11.1429), (62, 10.2857), (63, 7.7143), + (64, 11.5714), (65, 7.7143), (66, 9.0000), (67, 9.0000), (68, 9.0000), (69, 8.1429), + (70, 7.7143), (71, 9.0000), (72, 9.4286), (73, 3.4286), (74, 6.8571), (75, 9.0000), + (76, 7.2857), (77, 10.2857), (78, 9.4286), (79, 9.4286), (80, 9.0000), (81, 9.4286), + (82, 9.0000), (83, 8.5714), (84, 6.8571), (85, 9.4286), (86, 7.7143), (87, 10.2857), + (88, 8.5714), (89, 7.7143), (90, 8.5714), (91, 6.0000), (92, 9.4286), (93, 5.5714), + (94, 9.4286), (95, 10.2857), (96, 5.1429), (97, 8.1429), (98, 8.1429), (99, 7.7143), + (100, 8.1429), (101, 7.7143), (102, 5.1429), (103, 8.1429), (104, 8.1429), (105, 3.4286), + (106, 4.2857), (107, 7.2857), (108, 3.4286), (109, 12.8571), (110, 8.1429), (111, 8.1429), + (112, 8.1429), (113, 8.1429), (114, 5.5714), (115, 7.2857), (116, 5.1429), (117, 8.1429), + (118, 6.8571), (119, 9.4286), (120, 7.2857), (121, 6.8571), (122, 7.2857), (123, 6.0000), + (124, 3.4286), (125, 6.0000), (126, 11.1429), (33, 4.2857), (34, 6.0000), (35, 9.0000), + (36, 8.5714), (38, 11.1429), (39, 4.2857), (40, 6.0000), (41, 6.0000), (42, 6.8571), + (43, 11.1429), (44, 4.2857), (45, 11.1429), (46, 4.2857), (47, 9.4286), (48, 8.5714), + (49, 8.5714), (50, 8.5714), (51, 8.5714), (52, 8.5714), (53, 8.5714), (54, 8.5714), + (55, 8.5714), (56, 8.5714), (57, 8.5714), (58, 4.2857), (59, 4.2857), (60, 10.2857), + (61, 11.1429), (62, 10.2857), (63, 7.7143), (64, 11.5714), (65, 7.7143), (66, 9.0000), + (67, 9.0000), (68, 9.0000), (69, 8.1429), (70, 7.7143), (71, 9.0000), (72, 9.4286), + (73, 3.4286), (74, 6.8571), (75, 9.0000), (76, 7.2857), (77, 10.2857), (78, 9.4286), + (79, 9.4286), (80, 9.0000), (81, 9.4286), (82, 9.0000), (83, 8.5714), (84, 6.8571), + (85, 9.4286), (86, 7.7143), (87, 10.2857), (88, 8.5714), (89, 7.7143), (90, 8.5714), + (91, 6.0000), (92, 9.4286), (93, 5.5714), (94, 9.4286), (95, 10.2857), (96, 5.1429), + (97, 8.1429), (98, 8.1429), (99, 7.7143), (100, 8.1429), (101, 7.7143), (102, 5.1429), + (103, 8.1429), (104, 8.1429), (105, 3.4286), (106, 4.2857), (107, 7.2857), (108, 3.4286), + (109, 12.8571), (110, 8.1429), (111, 8.1429), (112, 8.1429), (113, 8.1429), (114, 5.5714), + (115, 7.2857), (116, 5.1429), (117, 8.1429), (118, 6.8571), (119, 9.4286), (120, 7.2857), + (121, 6.8571), (122, 7.2857), (123, 6.0000), (124, 3.4286), (125, 6.0000), (126, 11.1429), + ], + ), +]; + // ── Public types ────────────────────────────────────────────────────────── /// One glyph: a list of open 2-D polyline strokes in glyph units. @@ -179,12 +264,23 @@ fn fonts_map() -> &'static HashMap { map.insert(alias.to_ascii_uppercase(), f); } } - // Those names keep the reference font's space width. + // Those names keep the reference font's space width and character + // advances (a glyph's advance plus the letter spacing). for (name, word) in SHX_SPACE { if let Some(f) = map.get_mut(*name) { f.word_spacing = *word; } } + for (name, advances) in SHX_ADVANCE { + if let Some(f) = map.get_mut(*name) { + let spacing = f.letter_spacing; + for (code, advance) in advances.iter() { + if let Some(glyph) = char::from_u32(*code).and_then(|c| f.glyphs.get_mut(&c)) { + glyph.advance = (advance - spacing).max(0.0); + } + } + } + } map }) }