nx_ttf_sdf.nx source
↩ module page · 202 lines · 10034 B
1// nx_ttf_sdf.nx -- L2 rung: SIGNED DISTANCE FIELD generator (resolution-independent glyph rendering, the non-neural
2// "beats a bitmap when scaling" technique). Parses our .ttf, decodes a glyph outline, computes a TINY signed
3// distance field (16x16 = 256 texels: each stores signed distance to nearest outline edge, - inside / + outside),
4// then RECONSTRUCTS the glyph CRISP at much larger output by bilinear-sampling that tiny field + soft threshold.
5// The point: 256 bytes -> a sharp glyph at ANY scale (a 16x16 BITMAP would be blocky; the SDF stays crisp). This
6// is what a GPU shader does with one small texture. Renders 'S'. 100% sovereign. expect_exit: 0 license_tier: ORIGINAL
7import "nx_syscalls_x86_64.nx"
8const K_MAGIC_32768: i64 = 32768
9const K_MAGIC_65536: i64 = 65536
10const K_MAGIC_16777216: i64 = 16777216
11const K_MAGIC_2048: i64 = 2048
12const K_MAGIC_1000000000: i64 = 1000000000
13const K_MAGIC_8192: i64 = 8192
14
15func sw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
16func sn(v: i64) -> i64 { let bb: *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{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 }
17func rd16(b: *u8, o: i64) -> i64 { return (b[o] as i64)*256 + (b[o+1] as i64) }
18func rd16s(b: *u8, o: i64) -> i64 { let v: i64=rd16(b,o); if v>=K_MAGIC_32768 { return v-K_MAGIC_65536 } return v }
19func rd32(b: *u8, o: i64) -> i64 { return (b[o] as i64)*K_MAGIC_16777216 + (b[o+1] as i64)*K_MAGIC_65536 + (b[o+2] as i64)*256 + (b[o+3] as i64) }
20func bit(f: i64, m: i64) -> i64 { if (f/m)%2 == 1 { return 1 } return 0 }
21func 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 }
22func find_table(b: *u8, t0: i64, t1: i64, t2: i64, t3: i64) -> i64 {
23 let nt: i64=rd16(b,4); var i: i64=0
24 while i<nt { let d: i64=12+i*16
25 if (b[d] as i64)==t0 { if (b[d+1] as i64)==t1 { if (b[d+2] as i64)==t2 { if (b[d+3] as i64)==t3 { return rd32(b,d+8) } } } }
26 i=i+1 }
27 return 0-1
28}
29func cmap_lookup(b: *u8, sub: i64, c: i64) -> i64 {
30 let segX2: i64=rd16(b,sub+6); let segCount: i64=segX2/2; var i: i64=0
31 while i<segCount {
32 let endc: i64=rd16(b,sub+14+i*2)
33 if endc>=c {
34 let startc: i64=rd16(b,sub+16+segX2+i*2)
35 if startc<=c { let iro: i64=rd16(b,sub+16+segX2*3+i*2)
36 if iro==0 { let delta: i64=rd16s(b,sub+16+segX2*2+i*2); return (c+delta)%K_MAGIC_65536 }
37 return 0 }
38 return 0 }
39 i=i+1 }
40 return 0
41}
42func glyph_edges(b: *u8, glyf: i64, loca: i64, locfmt: i64, gid: i64, ex0: *i64, ey0: *i64, ex1: *i64, ey1: *i64) -> i64 {
43 var g0: i64=0; var g1: i64=0
44 if locfmt==0 { g0=rd16(b,loca+gid*2)*2; g1=rd16(b,loca+gid*2+2)*2 } else { g0=rd32(b,loca+gid*4); g1=rd32(b,loca+gid*4+4) }
45 if g1<=g0 { return 0 }
46 let gp: i64=glyf+g0; let nc: i64=rd16s(b,gp)
47 if nc<=0 { return 0 }
48 let ep: *i64=sys_mmap(256) as *i64
49 var i: i64=0
50 while i<nc { ep[i]=rd16(b,gp+10+i*2); i=i+1 }
51 let np: i64=ep[nc-1]+1
52 let instr: i64=rd16(b,gp+10+nc*2)
53 var p: i64=gp+10+nc*2+2+instr
54 let FL: *i64=sys_mmap(K_MAGIC_2048) as *i64
55 let PX: *i64=sys_mmap(K_MAGIC_2048) as *i64
56 let PY: *i64=sys_mmap(K_MAGIC_2048) as *i64
57 let ON: *i64=sys_mmap(K_MAGIC_2048) as *i64
58 var fi: i64=0
59 while fi<np { let f: i64=b[p] as i64; p=p+1; FL[fi]=f; fi=fi+1
60 if bit(f,8)==1 { var rep: i64=b[p] as i64; p=p+1; while rep>0 { FL[fi]=f; fi=fi+1; rep=rep-1 } } }
61 var x: i64=0; i=0
62 while i<np { let f: i64=FL[i]
63 if bit(f,2)==1 { var dx: i64=b[p] as i64; p=p+1; if bit(f,16)==0 { dx=0-dx } x=x+dx }
64 else { if bit(f,16)==0 { x=x+rd16s(b,p); p=p+2 } }
65 PX[i]=x; i=i+1 }
66 var y: i64=0; i=0
67 while i<np { let f: i64=FL[i]
68 if bit(f,4)==1 { var dy: i64=b[p] as i64; p=p+1; if bit(f,32)==0 { dy=0-dy } y=y+dy }
69 else { if bit(f,32)==0 { y=y+rd16s(b,p); p=p+2 } }
70 PY[i]=y; ON[i]=bit(f,1); i=i+1 }
71 var ne: i64=0; var cs: i64=0; var ci: i64=0
72 while ci<nc {
73 let ce: i64=ep[ci]; let cnt: i64=ce-cs+1
74 var curx: i64=PX[cs]; var cury: i64=PY[cs]; var j: i64=1
75 while j<=cnt {
76 let idx: i64=cs + (j%cnt)
77 if ON[idx]==1 { ex0[ne]=curx; ey0[ne]=cury; ex1[ne]=PX[idx]; ey1[ne]=PY[idx]; ne=ne+1; curx=PX[idx]; cury=PY[idx]; j=j+1 }
78 else {
79 let eidx: i64=cs + ((j+1)%cnt)
80 let cxp: i64=PX[idx]; let cyp: i64=PY[idx]; let exp: i64=PX[eidx]; let eyp: i64=PY[eidx]
81 var t: i64=1; var pxp: i64=curx; var pyp: i64=cury
82 while t<=6 { let u: i64=6-t
83 let qx: i64=(u*u*curx + 2*u*t*cxp + t*t*exp)/36
84 let qy: i64=(u*u*cury + 2*u*t*cyp + t*t*eyp)/36
85 ex0[ne]=pxp; ey0[ne]=pyp; ex1[ne]=qx; ey1[ne]=qy; ne=ne+1; pxp=qx; pyp=qy; t=t+1 }
86 curx=exp; cury=eyp; j=j+2 }
87 }
88 cs=ce+1; ci=ci+1
89 }
90 return ne
91}
92func inside(gx: i64, gy: i64, ex0: *i64, ey0: *i64, ex1: *i64, ey1: *i64, ne: i64) -> i64 {
93 var w: i64=0; var i: i64=0
94 while i<ne { let y0: i64=ey0[i]; let y1: i64=ey1[i]; var dir: i64=0
95 if y0<=gy { if gy<y1 { dir=1 } }
96 if y1<=gy { if gy<y0 { dir=0-1 } }
97 if dir!=0 { let xc: i64=ex0[i] + (gy-y0)*(ex1[i]-ex0[i])/(y1-y0); if xc>gx { w=w+dir } }
98 i=i+1 }
99 if w!=0 { return 1 }
100 return 0
101}
102func seg_dist2(px: i64, py: i64, x0: i64, y0: i64, x1: i64, y1: i64) -> i64 {
103 let dx: i64=x1-x0; let dy: i64=y1-y0; let d2: i64=dx*dx+dy*dy
104 if d2==0 { let ax: i64=px-x0; let ay: i64=py-y0; return ax*ax+ay*ay }
105 var t: i64=(px-x0)*dx + (py-y0)*dy
106 if t<0 { t=0 } if t>d2 { t=d2 }
107 let projx: i64=x0 + t*dx/d2; let projy: i64=y0 + t*dy/d2
108 let ax: i64=px-projx; let ay: i64=py-projy
109 return ax*ax+ay*ay
110}
111// signed distance at (px,py): +outside / -inside
112func sdist(px: i64, py: i64, ex0: *i64, ey0: *i64, ex1: *i64, ey1: *i64, ne: i64) -> i64 {
113 var mind2: i64=K_MAGIC_1000000000; var i: i64=0
114 while i<ne { let d2: i64=seg_dist2(px,py, ex0[i],ey0[i],ex1[i],ey1[i]); if d2<mind2 { mind2=d2 } i=i+1 }
115 let d: i64=isqrt(mind2)
116 if inside(px,py,ex0,ey0,ex1,ey1,ne)==1 { return 0-d }
117 return d
118}
119
120func main() -> i64 {
121 let len_p: *i64 = sys_mmap(8) as *i64
122 let b: *u8 = sys_read_file_x86_64("web_assets/nishi_sans.ttf" as *u8, len_p)
123 if b == (0 as *u8) { sw("cannot read nishi_sans.ttf\n" as *u8); return 5 }
124 let glyf: i64=find_table(b, 103,108,121,102)
125 let loca: i64=find_table(b, 108,111,99,97)
126 let head: i64=find_table(b, 104,101,97,100)
127 let cmap: i64=find_table(b, 99,109,97,112)
128 let locfmt: i64=rd16s(b,head+50)
129 let sub: i64=cmap+rd32(b,cmap+8)
130
131 let ex0: *i64=sys_mmap(K_MAGIC_8192) as *i64
132 let ey0: *i64=sys_mmap(K_MAGIC_8192) as *i64
133 let ex1: *i64=sys_mmap(K_MAGIC_8192) as *i64
134 let ey1: *i64=sys_mmap(K_MAGIC_8192) as *i64
135 let gid: i64=cmap_lookup(b, sub, 83) // 'S'
136 let ne: i64=glyph_edges(b, glyf, loca, locfmt, gid, ex0, ey0, ex1, ey1)
137
138 // glyph bounds from edges
139 var bx0: i64=ex0[0]; var bx1: i64=ex0[0]; var by0: i64=ey0[0]; var by1: i64=ey0[0]
140 var i: i64=0
141 while i<ne {
142 if ex0[i]<bx0 { bx0=ex0[i] } if ex1[i]<bx0 { bx0=ex1[i] }
143 if ex0[i]>bx1 { bx1=ex0[i] } if ex1[i]>bx1 { bx1=ex1[i] }
144 if ey0[i]<by0 { by0=ey0[i] } if ey1[i]<by0 { by0=ey1[i] }
145 if ey0[i]>by1 { by1=ey0[i] } if ey1[i]>by1 { by1=ey1[i] }
146 i=i+1
147 }
148 let pad: i64=90
149 bx0=bx0-pad; bx1=bx1+pad; by0=by0-pad; by1=by1+pad
150 let bw: i64=bx1-bx0; let bh: i64=by1-by0
151
152 // BUILD the tiny SDF (GS x GS)
153 let GS: i64=16
154 let sd: *i64=sys_mmap(GS*GS*8) as *i64
155 var gj: i64=0
156 while gj<GS {
157 var gi: i64=0
158 while gi<GS {
159 let px: i64=bx0 + (gi*2+1)*bw/(GS*2)
160 let py: i64=by0 + (gj*2+1)*bh/(GS*2)
161 sd[gj*GS+gi]=sdist(px,py, ex0,ey0,ex1,ey1, ne)
162 gi=gi+1
163 }
164 gj=gj+1
165 }
166 sw("=== nx_ttf_sdf -- TINY " as *u8); sn(GS); sw("x" as *u8); sn(GS); sw(" signed distance field (" as *u8); sn(GS*GS); sw(" texels) reconstructed CRISP at large size ===\n" as *u8)
167
168 // RECONSTRUCT at high res by bilinear-sampling the tiny SDF + soft threshold
169 let OW: i64=52; let OH: i64=30
170 let ramp: *u8=" .:-=+*#%@" as *u8
171 let ew: i64=bw/OW + 1 // ~1 output-pixel edge softness
172 let line: *u8=sys_mmap(256)
173 var oy: i64=0
174 while oy<OH {
175 var ox: i64=0; var lp: i64=0
176 while ox<OW {
177 let gx: i64=bx0 + (ox*2+1)*bw/(OW*2)
178 let gy: i64=by1 - (oy*2+1)*bh/(OH*2)
179 // map to grid fixed-point (*256), minus half texel
180 var uf: i64=(gx-bx0)*GS*256/bw - 128
181 var vf: i64=(gy-by0)*GS*256/bh - 128
182 if uf<0 { uf=0 } if vf<0 { vf=0 }
183 var i0: i64=uf/256; var j0: i64=vf/256
184 if i0>GS-2 { i0=GS-2 } if j0>GS-2 { j0=GS-2 }
185 let fx: i64=uf-i0*256; let fy: i64=vf-j0*256
186 let s00: i64=sd[j0*GS+i0]; let s10: i64=sd[j0*GS+i0+1]; let s01: i64=sd[(j0+1)*GS+i0]; let s11: i64=sd[(j0+1)*GS+i0+1]
187 let a: i64=s00*(256-fx)/256 + s10*fx/256
188 let c: i64=s01*(256-fx)/256 + s11*fx/256
189 let sdv: i64=a*(256-fy)/256 + c*fy/256
190 // coverage from signed distance: inside(-) -> solid
191 var lvl: i64=(ew - sdv)*10/(2*ew)
192 if lvl<0 { lvl=0 } if lvl>9 { lvl=9 }
193 line[lp]=ramp[lvl]; lp=lp+1
194 ox=ox+1
195 }
196 line[lp]=10 as u8; lp=lp+1
197 sys_write(1, line, lp)
198 oy=oy+1
199 }
200 sw("=== " as *u8); sn(GS*GS); sw(" SDF bytes -> " as *u8); sn(OW*OH); sw("-pixel crisp glyph. A " as *u8); sn(GS); sw("x" as *u8); sn(GS); sw(" BITMAP would be blocky; the SDF stays sharp at any scale (GPU/HiDPI rung). ===\n" as *u8)
201 return 0
202}