code wiki / _hdl_build / nx_vecfont_body_bench.nx
nx_vecfont_body_bench.nx source
↩ module page · 114 lines · 8212 B
1// nx_vecfont_body_bench.nx -- decide the FONT arc with a measurement, not a guess. Renders the SAME
2// lowercase phrase through the sovereign stroke-VECTOR font (nx_font -> aa_raster) at HEADLINE size and
3// at BODY size, so we can see where the vector font wins (big = smooth curves shine) vs where it may lose
4// (small = no hinting, could blur below the crisp AA bitmap). Outputs two PNGs to eyeball + OCR + AA-measure.
5// This grounds "wire the vector font for headings, keep the bitmap for body" (the hybrid) with evidence.
6// expect_exit: 0 license_tier: ORIGINAL
7import "nx_font.nx"
8import "nx_aa_raster.nx"
9import "nx_png_write.nx"
10const K_MAGIC_400000: i64 = 400000
11const K_MAGIC_40000: i64 = 40000
12const K_MAGIC_1600: i64 = 1600
13const K_MAGIC_1400: i64 = 1400
14const K_MAGIC_1100: i64 = 1100
15const K_MAGIC_1500: i64 = 1500
16const K_MAGIC_1700: i64 = 1700
17const K_MAGIC_1550: i64 = 1550
18const K_MAGIC_1050: i64 = 1050
19const K_MAGIC_1250: i64 = 1250
20const K_MAGIC_2200: i64 = 2200
21
22func vb_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
23func vb_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
24func vb_num(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
25
26// render `text` at pixel-size px into a W x H white PNG at `path` (single line, dark text).
27func vb_render(text: *u8, n: i64, px: i64, W: i64, H: i64, path: *u8) -> i64 {
28 let ss: i64 = 4
29 let S: i64 = px * ss // em scale in the supersample grid
30 // stroke output arrays (generous)
31 let xs: *i64 = sys_mmap(8*K_MAGIC_400000) as *i64 // Chaikin-smoothed glyphs -> ~20 verts/point, full phrase
32 let ys: *i64 = sys_mmap(8*K_MAGIC_400000) as *i64
33 let cstart: *i64 = sys_mmap(8*K_MAGIC_40000) as *i64
34 let clen: *i64 = sys_mmap(8*K_MAGIC_40000) as *i64
35 let np: *i64 = sys_mmap(16) as *i64; np[0]=0
36 let nc: *i64 = sys_mmap(16) as *i64; nc[0]=0
37 // gs_stroke needs trig tables (cs/sn 12 steps) -- init like nx_vecphrase_proof
38 let cs: *i64 = sys_mmap(8*20) as *i64
39 let sn: *i64 = sys_mmap(8*20) as *i64
40 font_trig_init(cs, sn) // 16-gon table (matches gs_disc joins -> no wobble)
41 // emit the string at pen (margin, top) in the SUPERSAMPLE grid
42 font_text(text, n, xs, ys, cstart, clen, np, nc, cs, sn, 20*ss, 6*ss, S)
43 // rasterize into coverage (W x H), then blit onto white
44 let cov: *u8 = sys_mmap(W*H + 16)
45 aa_render(xs, ys, cstart, clen, nc[0], cov, W, H, ss)
46 let rgb: *u8 = sys_mmap(W*H*3 + 16)
47 var i: i64 = 0
48 while i < W*H*3 { rgb[i] = 255 as u8; i = i + 1 }
49 aa_blit(rgb, W, H, 0, 0, cov, W, H, 42, 42, 51) // dark #2a2a33
50 nx_png_write_rgb(path, rgb, W, H)
51 return 0
52}
53
54func main() -> i64 {
55 vb_puts("VECFONT body bench: the stroke-vector font at headline vs body size (where does it win?)\n" as *u8)
56 let phrase: *u8 = "the quick brown fox jumps over lazy dog\x00" as *u8
57 let n: i64 = vb_slen(phrase)
58 // HEADLINE: 40px (lowercase pangram)
59 vb_render(phrase, n, 40, K_MAGIC_1600, 70, "knowledge/status/vecfont_headline.png\x00" as *u8)
60 vb_puts(" wrote vecfont_headline.png (40px)\n" as *u8)
61 // CAPS + DIGITS headline (the NEW glyphs -- must OCR-read before wiring vector headings)
62 let caps: *u8 = "The Quick Brown Fox: 42 Books, 1970 Records!\x00" as *u8
63 vb_render(caps, vb_slen(caps), 40, K_MAGIC_1600, 70, "knowledge/status/vecfont_caps.png\x00" as *u8)
64 vb_puts(" wrote vecfont_caps.png (40px caps+digits+punct)\n" as *u8)
65 // BODY: 16px (the hard case -- no hinting)
66 vb_render(phrase, n, 16, 700, 32, "knowledge/status/vecfont_body.png\x00" as *u8)
67 vb_puts(" wrote vecfont_body.png (16px)\n" as *u8)
68 // TYPE-QUALITY reference: "Render legibility" isolated at ~72px caps (empx 116) to compare vs Chrome
69 let tq: *u8 = "Render legibility\x00" as *u8
70 vb_render(tq, vb_slen(tq), 116, K_MAGIC_1400, 190, "knowledge/status/typeq_ours.png\x00" as *u8)
71 vb_puts(" wrote typeq_ours.png (type-quality ref)\n" as *u8)
72 // CURVE-SMOOTHNESS reference: a big isolated "O" (closest glyph to a circle) for contour-turning analysis
73 vb_render("O\x00" as *u8, 1, 300, 380, 400, "knowledge/status/typeq_O_ours.png\x00" as *u8)
74 vb_puts(" wrote typeq_O_ours.png (big O for smoothness)\n" as *u8)
75 // BASELINE-CONSISTENCY reference: an all-x-height word (no ascenders/descenders) so every letter's bottom
76 // is the baseline -> the variance of letter-bottoms = the "bounce" (amateur) vs consistent (professional).
77 vb_render("consensus\x00" as *u8, 9, 120, K_MAGIC_1100, 200, "knowledge/status/typeq_base_ours.png\x00" as *u8)
78 vb_puts(" wrote typeq_base_ours.png (x-height word for baseline consistency)\n" as *u8)
79 // PEN-WEIGHT reference: an isolated 'l' (one pure stem -- no neighbors, no curves, no modulation) at the
80 // SAME em as the word render -> the unconfounded pen-width measure for the weight axis.
81 vb_render("l\x00" as *u8, 1, 116, 160, 190, "knowledge/status/typeq_l_ours.png\x00" as *u8)
82 vb_puts(" wrote typeq_l_ours.png (isolated stem for pen weight)\n" as *u8)
83 // KERNING specimen: the classically-risky pairs (T/V/W/Y/A/L overhangs + punctuation) at current metrics
84 let kp: *u8 = "To Ta Ty AV AW LT TT VA Yo Fa P. r; ty\x00" as *u8
85 vb_render(kp, vb_slen(kp), 90, K_MAGIC_1500, 160, "knowledge/status/typeq_kern_pairs.png\x00" as *u8)
86 vb_puts(" wrote typeq_kern_pairs.png (risky-pair specimen)\n" as *u8)
87 // debug: big isolated V (apex construction check)
88 vb_render("V\x00" as *u8, 1, 300, 380, 400, "knowledge/status/typeq_V_dbg.png\x00" as *u8)
89 vb_puts(" wrote typeq_V_dbg.png\n" as *u8)
90 // GEOMETRIC (machine-regular) specimen -- pangram for OCR + eyeball
91 font_spec_geo(1); font_spec_mod(100); font_spec_swell(100)
92 vb_render("the quick brown fox jumps over lazy dog\x00" as *u8, 39, 40, K_MAGIC_1700, 100, "knowledge/status/geo_specimen.png\x00" as *u8)
93 vb_render("sassafras mississippi bosses\x00" as *u8, 28, 120, K_MAGIC_1600, 220, "knowledge/status/geo_s_dbg.png\x00" as *u8) // isolate the s
94 vb_render("Hamburgevons 2026 quick\x00" as *u8, 23, 64, K_MAGIC_1400, 110, "knowledge/status/geo_vs_pro.png\x00" as *u8) // MATCH pro_compare.png 64px
95 vb_render("the quick brown fox jumps over the lazy dog\x00" as *u8, 43, 16, K_MAGIC_1500, 46, "knowledge/status/geo_body16.png\x00" as *u8)
96 vb_render("the quick brown fox jumps over the lazy dog\x00" as *u8, 43, 20, K_MAGIC_1700, 56, "knowledge/status/geo_body20.png\x00" as *u8)
97 vb_render("mg magnum eggnog\x00" as *u8, 16, 150, K_MAGIC_1550, 320, "knowledge/status/geo_mg_dbg.png\x00" as *u8) // isolate m + g
98 vb_render("gauge eggnog logo\x00" as *u8, 17, 110, K_MAGIC_1500, 250, "knowledge/status/geo_g_dbg.png\x00" as *u8) // g in word context
99 font_spec_reset()
100 vb_puts(" wrote geo_specimen.png + geo_s_dbg.png\n" as *u8)
101 // ★OCR SIZE-LADDER: the same pangram at body->headline sizes so the OCR judge says how small our font
102 // stays legible vs Chrome (a professional font degrades gracefully). Ground truth in the filenames.
103 let pg: *u8 = "the quick brown fox jumps over the lazy dog\x00" as *u8
104 let pn: i64 = vb_slen(pg)
105 vb_render(pg, pn, 10, 900, 30, "knowledge/status/ladder_ours_10.png\x00" as *u8)
106 vb_render(pg, pn, 12, K_MAGIC_1050, 36, "knowledge/status/ladder_ours_12.png\x00" as *u8)
107 vb_render(pg, pn, 14, K_MAGIC_1250, 42, "knowledge/status/ladder_ours_14.png\x00" as *u8)
108 vb_render(pg, pn, 16, K_MAGIC_1400, 46, "knowledge/status/ladder_ours_16.png\x00" as *u8)
109 vb_render(pg, pn, 20, K_MAGIC_1700, 56, "knowledge/status/ladder_ours_20.png\x00" as *u8)
110 vb_render(pg, pn, 26, K_MAGIC_2200, 72, "knowledge/status/ladder_ours_26.png\x00" as *u8)
111 vb_puts(" wrote ladder_ours_{10..26}.png\n" as *u8)
112 vb_puts("VECFONT-BENCH done -- OCR + eyeball both to decide headings-vector / body-bitmap hybrid\n" as *u8)
113 return 0
114}