code wiki / _hdl_build / nx_ocr_bench_render.nx

nx_ocr_bench_render.nx source

↩ module page · 63 lines · 4010 B

1// nx_ocr_bench_render.nx -- OCR-LEGIBILITY harness, OUR side: render the bench page through the REAL 2// browser core (br_layout -> CSS cascade -> box layout -> br_draw_fb paint) exactly as the shipping 3// shot path does, at TWO zooms: scale=1 (100%, the honest apples-to-apples vs Chrome/Edge at the same 4// 1000px viewport) and scale=2 (200% zoom row, labeled separately). The browser-chrome strip is whited 5// out so the URL-bar text can't pollute the OCR of PAGE content. Outputs: 6// knowledge/status/ocr_bench_ours.png (scale 1) 7// knowledge/status/ocr_bench_ours2x.png (scale 2, supplementary labeled row) 8// The OCR judge (Windows.Media.Ocr -- a 3rd-party MEASURING INSTRUMENT, same instrument for all sides, 9// like qemu/openssl oracles) + the sovereign scorer live in the census organ. license_tier: ORIGINAL 10// expect_exit: 0 11import "nx_browser_render.nx" 12import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 13const K_MAGIC_1500: i64 = 1500 14 15func ob_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 16// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 17// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 18// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 19// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 20func ob_num(v: i64) -> i64 { nxi_out(v); return 0 } 21 22// render `page` (already laid out at layout-width lw) into a (lw*scale) x H png at `path`. 23func ob_shot(page: *Page, lw: i64, scale: i64, path: *u8) -> i64 { 24 let W: i64 = lw*scale 25 var H: i64 = (page.page_h + NX_CHROME_H + 40) * scale 26 if H > K_MAGIC_1500*scale { H = K_MAGIC_1500*scale } 27 let fb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer 28 let px: *u8 = sys_mmap(W*H*4 + 64) 29 nx_framebuffer_init(fb, px, W, H) 30 br_draw_fb(fb, page, lw, "bench\x00" as *u8, 5, scale) 31 // white out the browser chrome so URL-bar/button glyphs can't pollute the PAGE-content OCR 32 nx_paint_solid_rect(fb, 0, 0, W, NX_CHROME_H*scale, br_color_from_int(0x00FFFFFF)) 33 let rgb: *u8 = sys_mmap(W*H*3 + 64) 34 var p: i64 = 0 35 while p < W*H { rgb[p*3]=px[p*4]; rgb[p*3+1]=px[p*4+1]; rgb[p*3+2]=px[p*4+2]; p=p+1 } 36 nx_png_write_rgb(path, rgb, W, H) 37 return H 38} 39 40func main() -> i64 { 41 let lp: *i64 = sys_mmap(16) as *i64 42 let html: *u8 = sys_read_file("knowledge/status/ocr_bench_page.html\x00" as *u8, lp) 43 if lp[0] <= 0 { ob_puts("ocr_bench_render: no bench page\n" as *u8); return 1 } 44 // NEW DEFAULT (the legibility fix, zero shared-layout edits): lay out at HALF the viewport and paint 45 // at scale=2 -> the SAME 1000px-wide 100%-zoom image, but body glyphs render 16px (Chrome's default) 46 // in an ~55-char column instead of 8px in a 100-char wall. The OCR judge grades it below. 47 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 48 page.raw = html 49 page.raw_len = lp[0] 50 br_layout(page, 500) 51 page.vec_headings = 2 // 2 = vector font for HEADINGS **and body** (kill the bitmap typewriter) 52 if page.ok != 1 { ob_puts("ocr_bench_render: layout failed\n" as *u8); return 2 } 53 ob_puts("ocr_bench_render[new-16px]: boxes=" as *u8); ob_num(page.tree.count); ob_puts(" page_h=" as *u8); ob_num(page.page_h); ob_puts("\n" as *u8) 54 let h1: i64 = ob_shot(page, 500, 2, "knowledge/status/ocr_bench_ours.png\x00" as *u8) 55 // the PRIOR baseline (8px body @100%) kept as a labeled comparison row 56 let page2: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 57 page2.raw = html 58 page2.raw_len = lp[0] 59 br_layout(page2, 1000) 60 let h2: i64 = ob_shot(page2, 1000, 1, "knowledge/status/ocr_bench_old8.png\x00" as *u8) 61 ob_puts("ocr_bench_render: wrote ocr_bench_ours.png [16px default] (1000x" as *u8); ob_num(h1); ob_puts(") + ocr_bench_old8.png [old 8px] (1000x" as *u8); ob_num(h2); ob_puts(")\n" as *u8) 62 return 0 63}