code wiki / _hdl_build / nx_browser_darkmode_gate.nx

nx_browser_darkmode_gate.nx source

↩ module page · 138 lines · 7364 B

1// nx_browser_darkmode_gate.nx -- DARK MODE (the "OLED look" the operator framed the visual push around), 2// a UX-census ADMIT flipped by BUILD + evidence. Renders the SAME bench page through the real core in LIGHT 3// (dark_mode=0) and DARK (dark_mode=1); proves: (T1) the light page is majority-LIGHT; (T2) the dark page is 4// majority-DARK -- the theme actually FLIPPED (CAN-FAIL control: if the flag did nothing the two renders would 5// be identical and this fails); (T3) dark page still has LIGHT TEXT ink (readable, not an all-black void); 6// (T4) the browser chrome went dark too (coherent, not a light bar on a dark page); (T5) evidence PNGs written 7// (light + dark + a side-by-side) for the eyeball. license_tier: ORIGINAL expect_exit: 0 8import "nx_browser_render.nx" 9import "nx_gate_verdict.nx" 10 11func dm_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func dm_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 } 13 14const DM_W: i64 = 900 15 16func dm_render(html: *u8, hlen: i64, dark: i64, hout: *i64) -> *u8 { 17 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 18 page.raw = html 19 page.raw_len = hlen 20 page.dark_mode = dark // set BEFORE br_layout (it picks the default CSS) 21 br_layout(page, DM_W/2) 22 page.vec_headings = 1 23 var H: i64 = (page.page_h + NX_CHROME_H + 40) * 2 24 if H > 1400 { H = 1400 } 25 let fb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer 26 let px: *u8 = sys_mmap(DM_W*H*4 + 64) 27 nx_framebuffer_init(fb, px, DM_W, H) 28 var url: *u8 = "nishi://reader\x00" as *u8 29 if dark == 1 { url = "nishi://reader (dark)\x00" as *u8 } 30 br_draw_fb(fb, page, DM_W/2, url, 21, 2) 31 hout[0] = H 32 return px 33} 34// count pixels darker than lum L and lighter than lum L, in the PAGE area (below the chrome) 35func dm_counts(px: *u8, W: i64, H: i64, out: *i64) -> i64 { 36 var dark: i64=0 37 var light: i64=0 38 var lightink: i64=0 39 let y0: i64 = NX_CHROME_H*2 + 4 40 var y: i64=y0 41 while y<H { 42 var x: i64=0 43 while x<W { 44 let o: i64=(y*W+x)*4 45 let lum: i64=(2126*(px[o] as i64)+7152*(px[o+1] as i64)+722*(px[o+2] as i64))/10000 46 if lum < 60 { dark=dark+1 } 47 if lum > 200 { light=light+1 } 48 if lum > 150 { if lum < 245 { lightink=lightink+1 } } // light-gray text ink (not pure white) 49 x=x+1 50 } 51 y=y+1 52 } 53 out[0]=dark; out[1]=light; out[2]=lightink 54 return 0 55} 56func dm_rgb_write(px: *u8, W: i64, H: i64, path: *u8) -> i64 { 57 let rgb: *u8 = sys_mmap(W*H*3+64) 58 var p: i64=0 59 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 } 60 nx_png_write_rgb(path, rgb, W, H) 61 return 0 62} 63// chrome-bar mean luminance (top strip) -- proves the chrome darkened too 64func dm_chrome_lum(px: *u8, W: i64) -> i64 { 65 var s: i64=0 66 var n: i64=0 67 var y: i64=2 68 while y<NX_CHROME_H*2-2 { var x: i64=0; while x<W { let o: i64=(y*W+x)*4; s=s+(2126*(px[o] as i64)+7152*(px[o+1] as i64)+722*(px[o+2] as i64))/10000; n=n+1; x=x+8 } y=y+2 } 69 if n>0 { return s/n } else { return 0 } 70} 71 72func main() -> i64 { 73 dm_puts("DARK MODE gate: the OLED reader theme through the real core, with a can-fail control\n" as *u8) 74 let lp: *i64 = sys_mmap(16) as *i64 75 let html: *u8 = sys_read_file("knowledge/status/ocr_bench_page.html\x00" as *u8, lp) 76 if lp[0] <= 0 { dm_puts("darkmode: no bench page\n" as *u8); sys_exit(1); return 1 } 77 78 let hl: *i64 = sys_mmap(16) as *i64 79 let hd: *i64 = sys_mmap(16) as *i64 80 let lpx: *u8 = dm_render(html, lp[0], 0, hl) 81 let dpx: *u8 = dm_render(html, lp[0], 1, hd) 82 let lc: *i64 = sys_mmap(32) as *i64 83 let dc: *i64 = sys_mmap(32) as *i64 84 dm_counts(lpx, DM_W, hl[0], lc) 85 dm_counts(dpx, DM_W, hd[0], dc) 86 dm_puts(" light page: dark-px=" as *u8); dm_num(lc[0]); dm_puts(" light-px=" as *u8); dm_num(lc[1]); dm_puts("\n" as *u8) 87 dm_puts(" dark page: dark-px=" as *u8); dm_num(dc[0]); dm_puts(" light-px=" as *u8); dm_num(dc[1]); dm_puts(" light-ink=" as *u8); dm_num(dc[2]); dm_puts("\n" as *u8) 88 let lchrome: i64 = dm_chrome_lum(lpx, DM_W) 89 let dchrome: i64 = dm_chrome_lum(dpx, DM_W) 90 dm_puts(" chrome-bar mean lum: light=" as *u8); dm_num(lchrome); dm_puts(" dark=" as *u8); dm_num(dchrome); dm_puts("\n" as *u8) 91 92 var pass: i64=0 93 var ttl: i64=0 94 ttl=ttl+1; dm_puts(" T1 light page is majority-LIGHT (light>dark): " as *u8); if lc[1] > lc[0]*4 { pass=pass+1; dm_puts("PASS\n" as *u8) } else { dm_puts("FAIL\n" as *u8) } 95 ttl=ttl+1; dm_puts(" T2 dark page is majority-DARK (theme FLIPPED, can-fail): " as *u8); if dc[0] > dc[1]*4 { pass=pass+1; dm_puts("PASS\n" as *u8) } else { dm_puts("FAIL\n" as *u8) } 96 ttl=ttl+1; dm_puts(" T3 dark page has LIGHT TEXT ink (readable, not a void): " as *u8); if dc[2] > 2000 { pass=pass+1; dm_puts("PASS\n" as *u8) } else { dm_puts("FAIL\n" as *u8) } 97 ttl=ttl+1; dm_puts(" T4 chrome went dark too (dark bar << light bar lum): " as *u8); if dchrome < 90 { if lchrome > 180 { pass=pass+1; dm_puts("PASS\n" as *u8) } else { dm_puts("FAIL\n" as *u8) } } else { dm_puts("FAIL\n" as *u8) } 98 99 dm_rgb_write(lpx, DM_W, hl[0], "knowledge/status/darkmode_light.png\x00" as *u8) 100 dm_rgb_write(dpx, DM_W, hd[0], "knowledge/status/darkmode_dark.png\x00" as *u8) 101 // side-by-side (light left, dark right) into one PNG 102 var CH: i64 = hl[0] 103 if hd[0] < CH { CH = hd[0] } 104 let cw: i64 = DM_W*2 + 20 105 let comp: *u8 = sys_mmap(cw*CH*3 + 64) 106 var q: i64=0 107 while q<cw*CH*3 { comp[q]=30 as u8; q=q+1 } 108 var yy: i64=0 109 while yy<CH { 110 var xx: i64=0 111 while xx<DM_W { 112 let lo: i64=(yy*DM_W+xx)*4 113 let co: i64=(yy*cw+xx)*3 114 comp[co]=lpx[lo]; comp[co+1]=lpx[lo+1]; comp[co+2]=lpx[lo+2] 115 let ro: i64=(yy*cw+(xx+DM_W+20))*3 116 comp[ro]=dpx[lo]; comp[ro+1]=dpx[lo+1]; comp[ro+2]=dpx[lo+2] 117 xx=xx+1 118 } 119 yy=yy+1 120 } 121 nx_png_write_rgb("knowledge/status/darkmode_compare.png\x00" as *u8, comp, cw, CH) 122 let clp: *i64 = sys_mmap(16) as *i64 123 clp[0]=0-1 124 let cb: *u8 = sys_read_file("knowledge/status/darkmode_compare.png\x00" as *u8, clp) 125 ttl=ttl+1; dm_puts(" T5 evidence PNGs written (light+dark+compare " as *u8); dm_num(clp[0]); dm_puts("B): " as *u8) 126 if clp[0] > 5000 { pass=pass+1; dm_puts("PASS\n" as *u8) } else { dm_puts("FAIL\n" as *u8) } 127 128 dm_puts("BROWSER-DARKMODE-GATE passed " as *u8); dm_num(pass); dm_puts("/" as *u8); dm_num(ttl) 129 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 130 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 131 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 132 let ctr__dry: *i64 = gv_ctr() 133 ctr__dry[0] = pass 134 ctr__dry[1] = ttl 135 let rc__dry: i64 = gv_verdict("BROWSER-DARKMODE-GATE" as *u8, ctr__dry, "dark mode works; see knowledge/status/darkmode_compare.png)" as *u8) 136 sys_exit(rc__dry) 137 return rc__dry 138}