code wiki / _hdl_build / nx_font_baseline_census.nx

nx_font_baseline_census.nx source

↩ module page · 160 lines · 8651 B

1// nx_font_baseline_census.nx -- the PROFESSIONAL-CONSISTENCY benchmark for the pioneer font: how much do the 2// letters BOUNCE off the baseline? Amateur type has a wandering baseline; professional type is dead-flat (round 3// letters overshoot by a small CONSTANT). Renders an all-x-height word ("consensus" -- no ascenders/descenders, 4// so every glyph's bottom IS the baseline) in OUR font and Chrome's Arial; segments letters by white-column 5// gaps; measures each letter's bottom row; reports the STANDARD DEVIATION of the bottoms, normalized by letter 6// height (permille) -> the bounce. Lower = more professional. LIAR-KILL: a synthetic ALIGNED row of bars must 7// read ~0 bounce and a deliberately BOUNCY row must read high -- else the metric is broken. license_tier: 8// ORIGINAL expect_exit: 0 9import "nx_img_bytes_to_rgb.nx" 10const K_MAGIC_2126: i64 = 2126 11const K_MAGIC_7152: i64 = 7152 12const K_MAGIC_10000: i64 = 10000 13 14func fb_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 15func fb_num(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} 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 } 16func fb_lum(rgb: *u8, o: i64) -> i64 { return (K_MAGIC_2126*(rgb[o] as i64)+K_MAGIC_7152*(rgb[o+1] as i64)+722*(rgb[o+2] as i64))/K_MAGIC_10000 } 17func fb_isqrt(n: i64) -> i64 { if n<=0 { return 0 } var x: i64=n; var y: i64=(x+1)/2; while y<x { x=y; y=(x+n/x)/2 } return x } 18 19// segment the ink into letters (by white-column gaps) and measure the STD of letter-bottoms / letter-height, 20// in permille. out[0]=bounce_permille out[1]=nletters out[2]=mean_height_px. Returns 0 ok, -1 fail. 21func fb_measure(rgb: *u8, w: i64, h: i64, out: *i64) -> i64 { 22 // per-column: does it have ink, and what is its bottom-most ink row / top-most 23 let colink: *i64 = sys_mmap(8*(w+4)) as *i64 24 let colbot: *i64 = sys_mmap(8*(w+4)) as *i64 25 let coltop: *i64 = sys_mmap(8*(w+4)) as *i64 26 var x: i64=0 27 while x<w { 28 var has: i64=0; var bot: i64=0-1; var top: i64=h 29 var y: i64=0 30 while y<h { if fb_lum(rgb,(y*w+x)*3) < 128 { has=1; if y>bot { bot=y }; if y<top { top=y } } y=y+1 } 31 colink[x]=has; colbot[x]=bot; coltop[x]=top 32 x=x+1 33 } 34 // walk columns; a letter = a run of ink columns; a gap of >=4 white columns ends a letter 35 let bots: *i64 = sys_mmap(8*256) as *i64 36 let hts: *i64 = sys_mmap(8*256) as *i64 37 var nl: i64=0 38 var inrun: i64=0 39 var runbot: i64=0-1 40 var runtop: i64=h 41 var gap: i64=0 42 x=0 43 while x<w { 44 if colink[x]==1 { 45 if inrun==0 { inrun=1; runbot=0-1; runtop=h } 46 if colbot[x]>runbot { runbot=colbot[x] } 47 if coltop[x]<runtop { runtop=coltop[x] } 48 gap=0 49 } else { 50 if inrun==1 { 51 gap=gap+1 52 if gap>=4 { // letter ended 53 if nl<256 { bots[nl]=runbot; hts[nl]=runbot-runtop; nl=nl+1 } 54 inrun=0 55 } 56 } 57 } 58 x=x+1 59 } 60 if inrun==1 { if nl<256 { bots[nl]=runbot; hts[nl]=runbot-runtop; nl=nl+1 } } 61 out[1]=nl 62 if nl<3 { out[0]=0; out[2]=0; return 0-1 } 63 // mean bottom + mean height 64 var sb: i64=0; var sh: i64=0 65 var i: i64=0 66 while i<nl { sb=sb+bots[i]; sh=sh+hts[i]; i=i+1 } 67 let mb: i64=sb/nl 68 let mh: i64=sh/nl 69 out[2]=mh 70 // variance of bottoms 71 var vs: i64=0 72 i=0 73 while i<nl { let dd: i64=bots[i]-mb; vs=vs+dd*dd; i=i+1 } 74 let sd: i64=fb_isqrt(vs/nl) 75 if mh<=0 { out[0]=0; return 0 } 76 out[0]=(sd*1000)/mh // bounce = baseline-STD / letter-height, permille 77 return 0 78} 79func fb_load(path: *u8, wh: *i64) -> *u8 { 80 let lp: *i64=sys_mmap(16) as *i64; lp[0]=0-1 81 let raw: *u8=sys_read_file(path, lp) 82 if lp[0]<=0 { return 0 as *u8 } 83 return nx_img_bytes_to_rgb(raw, lp[0], wh) 84} 85// synthetic row of N bars; jitter=max baseline wobble px (0=aligned). Into rgb (white bg). 86func fb_make_bars(rgb: *u8, w: i64, h: i64, n: i64, jitter: i64) -> i64 { 87 var i: i64=0 88 while i<w*h*3 { rgb[i]=255 as u8; i=i+1 } 89 let bw: i64=40 90 let step: i64=w/n 91 var k: i64=0 92 while k<n { 93 let x0: i64=k*step+20 94 var jb: i64=0 95 if jitter>0 { jb=(k*37)%jitter } // deterministic pseudo-wobble 96 let ytop: i64=60 97 let ybot: i64=h-40-jb 98 var yy: i64=ytop 99 while yy<ybot { var xx: i64=x0; while xx<x0+bw { let o: i64=(yy*w+xx)*3; rgb[o]=20 as u8; rgb[o+1]=20 as u8; rgb[o+2]=43 as u8; xx=xx+1 } yy=yy+1 } 100 k=k+1 101 } 102 return 0 103} 104 105func main() -> i64 { 106 fb_puts("=== nx_font_baseline_census -- baseline BOUNCE (professional consistency) vs Chrome ===\n" as *u8) 107 let W: i64=1000 108 let H: i64=300 109 let rgb: *u8=sys_mmap(W*H*3+64) 110 let sa: *i64=sys_mmap(32) as *i64 111 let sb2: *i64=sys_mmap(32) as *i64 112 // LIAR-KILL: aligned bars vs bouncy bars 113 fb_make_bars(rgb, W, H, 9, 0) 114 fb_measure(rgb, W, H, sa) 115 fb_make_bars(rgb, W, H, 9, 60) 116 fb_measure(rgb, W, H, sb2) 117 fb_puts(" synthetic ALIGNED bars bounce=" as *u8); fb_num(sa[0]); fb_puts(" permille BOUNCY bars bounce=" as *u8); fb_num(sb2[0]); fb_puts(" permille\n" as *u8) 118 var metric_ok: i64=0 119 if sb2[0] > sa[0]+40 { metric_ok=1 } 120 if metric_ok==0 { fb_puts(" LIAR-KILL FIRED: metric can't tell aligned from bouncy -> INVALID\nNX-FONT-BASELINE: BROKEN\n" as *u8); sys_exit(1); return 1 } 121 fb_puts(" metric liar-kill: PASS (bouncy reads >aligned+40 -> the metric measures baseline bounce)\n" as *u8) 122 123 let owh: *i64=sys_mmap(16) as *i64 124 let cwh: *i64=sys_mmap(16) as *i64 125 let orgb: *u8=fb_load("knowledge/status/typeq_base_ours.png\x00" as *u8, owh) 126 let crgb: *u8=fb_load("knowledge/status/typeq_base_chrome.png\x00" as *u8, cwh) 127 let so: *i64=sys_mmap(32) as *i64 128 let sc: *i64=sys_mmap(32) as *i64 129 so[0]=0-1; sc[0]=0-1 130 if orgb!=(0 as *u8) { fb_measure(orgb, owh[0], owh[1], so) } 131 if crgb!=(0 as *u8) { fb_measure(crgb, cwh[0], cwh[1], sc) } 132 fb_puts(" ours bounce=" as *u8); fb_num(so[0]); fb_puts(" permille (letters=" as *u8); fb_num(so[1]); fb_puts(", h=" as *u8); fb_num(so[2]); fb_puts("px)\n" as *u8) 133 fb_puts(" chrome bounce=" as *u8); fb_num(sc[0]); fb_puts(" permille (letters=" as *u8); fb_num(sc[1]); fb_puts(", h=" as *u8); fb_num(sc[2]); fb_puts("px)\n" as *u8) 134 135 var pass: i64=0; var ttl: i64=0 136 ttl=ttl+1; if metric_ok==1 { pass=pass+1 } 137 ttl=ttl+1; fb_puts(" C2 both words segmented (>=7 letters each): " as *u8); if so[1]>=7 { if sc[1]>=7 { pass=pass+1; fb_puts("PASS\n" as *u8) } else { fb_puts("FAIL\n" as *u8) } } else { fb_puts("FAIL\n" as *u8) } 138 if so[0]>=0 { if sc[0]>=0 { 139 fb_puts(" >>> our baseline bounce " as *u8); fb_num(so[0]); fb_puts(" vs Chrome " as *u8); fb_num(sc[0]); fb_puts(" permille -- " as *u8) 140 if so[0] <= sc[0]+15 { fb_puts("PROFESSIONAL-FLAT (within ~15permille of Chrome), MEASURED\n" as *u8) } 141 else { fb_puts("still BOUNCY vs Chrome (gap " as *u8); fb_num(so[0]-sc[0]); fb_puts(") -- normalize more round-letter overshoots\n" as *u8) } 142 } } 143 // benchmark log line (composed by nx_font_pioneer_benchmark) 144 let lg: *u8 = sys_mmap(128) 145 var lo: i64 = 0 146 let pfx: *u8 = "FONT-BASELINE ours=\x00" as *u8 147 while pfx[lo] != (0 as u8) { lg[lo]=pfx[lo]; lo=lo+1 } 148 var mv: i64 = so[0]; if mv<0 { mv=0 } 149 let t2: *u8 = sys_mmap(24); var k2: i64=0; if mv==0 { t2[0]=48 as u8; k2=1 } while mv>0 { t2[k2]=(48+(mv%10)) as u8; mv=mv/10; k2=k2+1 } var z: i64=0; while z<k2 { lg[lo]=t2[k2-1-z]; lo=lo+1; z=z+1 } 150 let sfx: *u8 = " chrome=\x00" as *u8; var si: i64=0; while sfx[si]!=(0 as u8) { lg[lo]=sfx[si]; lo=lo+1; si=si+1 } 151 var cv: i64 = sc[0]; if cv<0 { cv=0 } 152 let t3: *u8 = sys_mmap(24); var k3: i64=0; if cv==0 { t3[0]=48 as u8; k3=1 } while cv>0 { t3[k3]=(48+(cv%10)) as u8; cv=cv/10; k3=k3+1 } z=0; while z<k3 { lg[lo]=t3[k3-1-z]; lo=lo+1; z=z+1 } 153 lg[lo]=10 as u8; lo=lo+1 154 let bfd: i64 = sys_openat_wr("knowledge/status/font_baseline.log\x00" as *u8, 0x1a4) 155 if bfd > 0 { sys_write(bfd, lg, lo); sys_close(bfd) } 156 157 fb_puts("FONT-BASELINE-CENSUS-GATE passed " as *u8); fb_num(pass); fb_puts("/" as *u8); fb_num(ttl) 158 if pass==ttl { fb_puts(" verdict=GREEN (baseline consistency MEASURED, liar-killed)\n" as *u8); sys_exit(0); return 0 } 159 fb_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1 160}