code wiki / _hdl_build / nx_aatext_proof.nx
nx_aatext_proof.nx source
↩ module page · 108 lines · 4421 B
1// nx_aatext_proof.nx -- prove GRAYSCALE-AA text from the full-ASCII 8x8 font via coverage supersampling,
2// vs the current 1-bit blocky render. Same string, 3 rows: 8px 1:1, 16px blocky, 16px coverage-AA. If the
3// AA row reads clearly smoother, this is the drop-in quality jump for the browser (full ASCII, no new font).
4import "nx_syscalls.nx"
5import "nx_font8x8.nx"
6import "nx_png_write.nx"
7
8func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
9
10// alpha-blend ink (r,g,b) onto the RGBA buffer at (x,y) with coverage a (0..255)
11func blend(px: *u8, W: i64, H: i64, x: i64, y: i64, r: i64, g: i64, b: i64, a: i64) -> i64 {
12 if x < 0 { return 0 }
13 if x >= W { return 0 }
14 if y < 0 { return 0 }
15 if y >= H { return 0 }
16 let o: i64 = (y * W + x) * 4
17 let ia: i64 = 255 - a
18 px[o+0] = (((px[o+0] & 0xff) * ia) + (r * a)) / 255
19 px[o+1] = (((px[o+1] & 0xff) * ia) + (g * a)) / 255
20 px[o+2] = (((px[o+2] & 0xff) * ia) + (b * a)) / 255
21 px[o+3] = 255 as u8
22 return 0
23}
24
25// 1-bit blocky: each 8x8 font pixel -> blk x blk solid block (the current br_paint_text2x style)
26func draw_blocky(px: *u8, W: i64, H: i64, ft8: *u8, x: i64, y: i64, s: *u8, n: i64, blk: i64, r: i64, g: i64, b: i64) -> i64 {
27 var i: i64 = 0
28 while i < n {
29 let ch: i64 = s[i] & 0xff
30 let cx: i64 = x + i * 9 * blk
31 if ch >= 0x20 { if ch <= 0x7E {
32 let go: i64 = (ch - 0x20) * 8
33 var row: i64 = 0
34 while row < 8 {
35 let bits: i64 = ft8[go + row] & 0xff
36 var col: i64 = 0
37 while col < 8 {
38 if ((bits >> col) & 1) == 1 {
39 var yy: i64 = 0
40 while yy < blk { var xx: i64 = 0; while xx < blk { blend(px, W, H, cx + col*blk + xx, y + row*blk + yy, r, g, b, 255); xx = xx + 1 } yy = yy + 1 }
41 }
42 col = col + 1
43 }
44 row = row + 1
45 }
46 } }
47 i = i + 1
48 }
49 return 0
50}
51
52// coverage-AA: render each 8x8 glyph at `psz` px with SSxSS supersampling -> grayscale coverage -> blend
53func draw_aa(px: *u8, W: i64, H: i64, ft8: *u8, x: i64, y: i64, s: *u8, n: i64, psz: i64, adv: i64, r: i64, g: i64, b: i64) -> i64 {
54 let SS: i64 = 4
55 var i: i64 = 0
56 while i < n {
57 let ch: i64 = s[i] & 0xff
58 let cx: i64 = x + i * adv
59 if ch >= 0x20 { if ch <= 0x7E {
60 let go: i64 = (ch - 0x20) * 8
61 var ty: i64 = 0
62 while ty < psz {
63 var tx: i64 = 0
64 while tx < psz {
65 var cov: i64 = 0
66 var sy: i64 = 0
67 while sy < SS {
68 var sx: i64 = 0
69 while sx < SS {
70 let subx: i64 = tx * SS + sx
71 let suby: i64 = ty * SS + sy
72 let srcx: i64 = (subx * 8) / (psz * SS)
73 let srcy: i64 = (suby * 8) / (psz * SS)
74 let bits: i64 = ft8[go + srcy] & 0xff
75 if ((bits >> srcx) & 1) == 1 { cov = cov + 1 }
76 sx = sx + 1
77 }
78 sy = sy + 1
79 }
80 if cov > 0 { blend(px, W, H, cx + tx, y + ty, r, g, b, (cov * 255) / (SS * SS)) }
81 tx = tx + 1
82 }
83 ty = ty + 1
84 }
85 } }
86 i = i + 1
87 }
88 return 0
89}
90
91func main() -> i64 {
92 let W: i64 = 900
93 let H: i64 = 220
94 let px: *u8 = sys_mmap(W * H * 4)
95 var i: i64 = 0
96 while i < W * H * 4 { px[i] = 255 as u8; i = i + 1 }
97 let ft8: *u8 = font8x8_table()
98 let s: *u8 = "The quick brown fox -- Nishi Browser 2026 s-class\x00" as *u8
99 let n: i64 = slen(s)
100 draw_blocky(px, W, H, ft8, 12, 20, s, n, 1, 20, 20, 24) // row 1: 8px 1:1 (current small render)
101 draw_blocky(px, W, H, ft8, 12, 80, s, n, 2, 20, 20, 24) // row 2: 16px blocky
102 draw_aa(px, W, H, ft8, 12, 150, s, n, 16, 18, 20, 20, 24) // row 3: 16px coverage-AA
103 let rgb: *u8 = sys_mmap(W * H * 3)
104 var j: i64 = 0
105 while j < W * H { rgb[j*3+0] = px[j*4+0]; rgb[j*3+1] = px[j*4+1]; rgb[j*3+2] = px[j*4+2]; j = j + 1 }
106 nx_png_write_rgb("_offc/aatext.png\x00" as *u8, rgb, W, H)
107 return 0
108}