nx_font_ttf_emit.nx source
↩ module page · 231 lines · 14186 B
1// nx_font_ttf_emit.nx -- R2 of the sovereign-font ladder (the KEYSTONE): serialize the R1 glyph outline model
2// into a REAL TrueType .ttf (sfnt: OS/2 cmap glyf head hhea hmtx loca maxp name post, big-endian, per-table
3// checksums + head.checkSumAdjustment) -> web_assets/nishi.ttf. Then SELF-VALIDATE by re-parsing the emitted
4// bytes (sfntVersion, numTables, every dir offset/length in bounds, every table checksum recomputed [head
5// special], and the whole-file checksum == 0xB1B0AFBA) -> sovereign verification, not assumed. Glyphs:
6// .notdef space H I T, in-house designs, 1000-EM. license_tier: ORIGINAL expect_exit: 0
7import "nx_syscalls_x86_64.nx"
8const MAGIC_MAGIC_65536: i64 = 65536
9const MAGIC_MAGIC_16777216: i64 = 16777216
10const MAGIC_MAGIC_4294967296: i64 = 4294967296
11const MAGIC_MAGIC_4096: i64 = 4096
12const MAGIC_MAGIC_16384: i64 = 16384
13const MAGIC_MAGIC_65535: i64 = 65535
14const MAGIC_MAGIC_65505: i64 = 65505
15const MAGIC_MAGIC_65466: i64 = 65466
16const MAGIC_MAGIC_65456: i64 = 65456
17const MAGIC_MAGIC_1594834165: i64 = 1594834165
18const MAGIC_MAGIC_1033: i64 = 1033
19const MAGIC_MAGIC_196608: i64 = 196608
20
21const MAGIC_ADJ: i64 = 2981146554 // 0xB1B0AFBA
22
23func sw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
24func 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 }
25
26func si16(v: i64) -> i64 { if v<0 { return v+MAGIC_MAGIC_65536 } return v }
27func w8(b: *u8, o: i64, v: i64) -> i64 { b[o]=(v%256) as u8; return o+1 }
28func w16(b: *u8, o: i64, v: i64) -> i64 { b[o]=((v/256)%256) as u8; b[o+1]=(v%256) as u8; return o+2 }
29func w32(b: *u8, o: i64, v: i64) -> i64 { b[o]=((v/MAGIC_MAGIC_16777216)%256) as u8; b[o+1]=((v/MAGIC_MAGIC_65536)%256) as u8; b[o+2]=((v/256)%256) as u8; b[o+3]=(v%256) as u8; return o+4 }
30func r16(b: *u8, o: i64) -> i64 { return (b[o] as i64)*256 + (b[o+1] as i64) }
31func r32(b: *u8, o: i64) -> i64 { return (b[o] as i64)*MAGIC_MAGIC_16777216 + (b[o+1] as i64)*MAGIC_MAGIC_65536 + (b[o+2] as i64)*256 + (b[o+3] as i64) }
32func align4(o: i64) -> i64 { while o%4 != 0 { o=o+1 } return o }
33func csum(b: *u8, off: i64, len: i64) -> i64 { var s: i64=0; var i: i64=off; while i < off+len { s = (s + r32(b,i)) % MAGIC_MAGIC_4294967296; i=i+4 } return s }
34func utf16be(b: *u8, o: i64, s: *u8) -> i64 { var oo: i64=o; var i: i64=0; while s[i]!=(0 as u8) { oo=w8(b,oo,0); oo=w8(b,oo,s[i] as i64); i=i+1 } return oo }
35
36// glyph fills (in-house designs, 1000-EM) -> ep[], px[], py[], meta[0]=nc meta[1]=np
37func fill_notdef(ep: *i64, px: *i64, py: *i64, meta: *i64) -> i64 { px[0]=80;py[0]=0;px[1]=520;py[1]=0;px[2]=520;py[2]=700;px[3]=80;py[3]=700; ep[0]=3;meta[0]=1;meta[1]=4; return 0 }
38func fill_space(ep: *i64, px: *i64, py: *i64, meta: *i64) -> i64 { meta[0]=0;meta[1]=0; return 0 }
39func fill_H(ep: *i64, px: *i64, py: *i64, meta: *i64) -> i64 {
40 px[0]=130;py[0]=0;px[1]=290;py[1]=0;px[2]=290;py[2]=700;px[3]=130;py[3]=700
41 px[4]=440;py[4]=0;px[5]=600;py[5]=0;px[6]=600;py[6]=700;px[7]=440;py[7]=700
42 px[8]=290;py[8]=290;px[9]=440;py[9]=290;px[10]=440;py[10]=410;px[11]=290;py[11]=410
43 ep[0]=3;ep[1]=7;ep[2]=11;meta[0]=3;meta[1]=12; return 0 }
44func fill_I(ep: *i64, px: *i64, py: *i64, meta: *i64) -> i64 { px[0]=250;py[0]=0;px[1]=400;py[1]=0;px[2]=400;py[2]=700;px[3]=250;py[3]=700; ep[0]=3;meta[0]=1;meta[1]=4; return 0 }
45func fill_T(ep: *i64, px: *i64, py: *i64, meta: *i64) -> i64 {
46 px[0]=60;py[0]=560;px[1]=660;py[1]=560;px[2]=660;py[2]=700;px[3]=60;py[3]=700
47 px[4]=290;py[4]=0;px[5]=430;py[5]=0;px[6]=430;py[6]=560;px[7]=290;py[7]=560
48 ep[0]=3;ep[1]=7;meta[0]=2;meta[1]=8; return 0 }
49
50// append one glyph's glyf record to g at go; return new go (even-padded). empty glyph -> unchanged.
51func append_glyph(g: *u8, go: i64, ep: *i64, px: *i64, py: *i64, meta: *i64) -> i64 {
52 let nc: i64=meta[0]; let np: i64=meta[1]
53 if nc==0 { return go }
54 var xmin: i64=px[0]; var xmax: i64=px[0]; var ymin: i64=py[0]; var ymax: i64=py[0]
55 var i: i64=0
56 while i<np { if px[i]<xmin{xmin=px[i]} if px[i]>xmax{xmax=px[i]} if py[i]<ymin{ymin=py[i]} if py[i]>ymax{ymax=py[i]} i=i+1 }
57 var o: i64=go
58 o=w16(g,o,si16(nc)); o=w16(g,o,si16(xmin)); o=w16(g,o,si16(ymin)); o=w16(g,o,si16(xmax)); o=w16(g,o,si16(ymax))
59 i=0; while i<nc { o=w16(g,o,ep[i]); i=i+1 }
60 o=w16(g,o,0) // instructionLength
61 i=0; while i<np { o=w8(g,o,1); i=i+1 } // flags: all on-curve (long-form coords)
62 var prev: i64=0; i=0; while i<np { o=w16(g,o,si16(px[i]-prev)); prev=px[i]; i=i+1 }
63 prev=0; i=0; while i<np { o=w16(g,o,si16(py[i]-prev)); prev=py[i]; i=i+1 }
64 if o%2 != 0 { o=w8(g,o,0) }
65 return o
66}
67
68func main() -> i64 {
69 let ep: *i64=sys_mmap(64) as *i64
70 let px: *i64=sys_mmap(512) as *i64
71 let py: *i64=sys_mmap(512) as *i64
72 let meta: *i64=sys_mmap(16) as *i64
73 let g: *u8=sys_mmap(MAGIC_MAGIC_4096)
74 let goff: *i64=sys_mmap(64) as *i64
75
76 // ---- build glyf blob + per-glyph offsets (glyphs: 0 .notdef, 1 space, 2 H, 3 I, 4 T) ----
77 var go: i64=0
78 goff[0]=go; fill_notdef(ep,px,py,meta); go=append_glyph(g,go,ep,px,py,meta)
79 goff[1]=go; fill_space(ep,px,py,meta); go=append_glyph(g,go,ep,px,py,meta)
80 goff[2]=go; fill_H(ep,px,py,meta); go=append_glyph(g,go,ep,px,py,meta)
81 goff[3]=go; fill_I(ep,px,py,meta); go=append_glyph(g,go,ep,px,py,meta)
82 goff[4]=go; fill_T(ep,px,py,meta); go=append_glyph(g,go,ep,px,py,meta)
83 goff[5]=go // total glyf length
84 let glyf_len: i64=go
85
86 let buf: *u8=sys_mmap(MAGIC_MAGIC_16384)
87 let toff: *i64=sys_mmap(128) as *i64
88 let tlen: *i64=sys_mmap(128) as *i64
89 let tcs: *i64=sys_mmap(128) as *i64
90 let NT: i64=10
91 var o: i64=12 + 16*NT // tables start after header+dir
92
93 // ---- table 0: OS/2 (v4, 96 bytes) ----
94 o=align4(o); toff[0]=o
95 o=w16(buf,o,4); o=w16(buf,o,si16(600)); o=w16(buf,o,400); o=w16(buf,o,5); o=w16(buf,o,0)
96 o=w16(buf,o,si16(650));o=w16(buf,o,si16(700));o=w16(buf,o,si16(0));o=w16(buf,o,si16(140))
97 o=w16(buf,o,si16(650));o=w16(buf,o,si16(700));o=w16(buf,o,si16(0));o=w16(buf,o,si16(480))
98 o=w16(buf,o,si16(50));o=w16(buf,o,si16(260)); o=w16(buf,o,si16(0))
99 var pi: i64=0; while pi<10 { o=w8(buf,o,0); pi=pi+1 }
100 o=w32(buf,o,0);o=w32(buf,o,0);o=w32(buf,o,0);o=w32(buf,o,0)
101 o=w8(buf,o,78);o=w8(buf,o,73);o=w8(buf,o,83);o=w8(buf,o,72) // NISH
102 o=w16(buf,o,64); o=w16(buf,o,32); o=w16(buf,o,84)
103 o=w16(buf,o,si16(800));o=w16(buf,o,si16(-200));o=w16(buf,o,si16(0))
104 o=w16(buf,o,800);o=w16(buf,o,200)
105 o=w32(buf,o,1);o=w32(buf,o,0)
106 o=w16(buf,o,si16(500));o=w16(buf,o,si16(700)); o=w16(buf,o,0);o=w16(buf,o,32);o=w16(buf,o,1)
107 tlen[0]=o-toff[0]; o=align4(o); tcs[0]=csum(buf,toff[0],o-toff[0])
108
109 // ---- table 1: cmap (format 4, 60 bytes) ----
110 o=align4(o); toff[1]=o
111 o=w16(buf,o,0); o=w16(buf,o,1) // version, numTables
112 o=w16(buf,o,3); o=w16(buf,o,1); o=w32(buf,o,12) // platform3 enc1 offset12
113 o=w16(buf,o,4); o=w16(buf,o,48); o=w16(buf,o,0) // format, length, language
114 o=w16(buf,o,8); o=w16(buf,o,8); o=w16(buf,o,2); o=w16(buf,o,0) // segCountX2, searchRange, entrySelector, rangeShift
115 o=w16(buf,o,32); o=w16(buf,o,73); o=w16(buf,o,84); o=w16(buf,o,MAGIC_MAGIC_65535) // endCode
116 o=w16(buf,o,0) // reservedPad
117 o=w16(buf,o,32); o=w16(buf,o,72); o=w16(buf,o,84); o=w16(buf,o,MAGIC_MAGIC_65535) // startCode
118 o=w16(buf,o,MAGIC_MAGIC_65505); o=w16(buf,o,MAGIC_MAGIC_65466); o=w16(buf,o,MAGIC_MAGIC_65456); o=w16(buf,o,1) // idDelta
119 o=w16(buf,o,0); o=w16(buf,o,0); o=w16(buf,o,0); o=w16(buf,o,0) // idRangeOffset
120 tlen[1]=o-toff[1]; o=align4(o); tcs[1]=csum(buf,toff[1],o-toff[1])
121
122 // ---- table 2: glyf ----
123 o=align4(o); toff[2]=o
124 var gi: i64=0; while gi<glyf_len { buf[o]=g[gi]; o=o+1; gi=gi+1 }
125 tlen[2]=o-toff[2]; o=align4(o); tcs[2]=csum(buf,toff[2],o-toff[2])
126
127 // ---- table 3: head (54 bytes) ----
128 o=align4(o); toff[3]=o
129 o=w32(buf,o,MAGIC_MAGIC_65536); o=w32(buf,o,MAGIC_MAGIC_65536); o=w32(buf,o,0); o=w32(buf,o,MAGIC_MAGIC_1594834165) // version, rev, checkSumAdjustment(0), magic 0x5F0F3CF5
130 o=w16(buf,o,11); o=w16(buf,o,1000) // flags, unitsPerEm
131 o=w32(buf,o,0);o=w32(buf,o,0); o=w32(buf,o,0);o=w32(buf,o,0) // created, modified
132 o=w16(buf,o,si16(0));o=w16(buf,o,si16(0));o=w16(buf,o,720);o=w16(buf,o,700) // bbox
133 o=w16(buf,o,0); o=w16(buf,o,8); o=w16(buf,o,2); o=w16(buf,o,0); o=w16(buf,o,0) // macStyle, lowestRecPPEM, dirHint, locFormat(short), glyphDataFormat
134 tlen[3]=o-toff[3]; o=align4(o); tcs[3]=csum(buf,toff[3],o-toff[3])
135
136 // ---- table 4: hhea (36 bytes) ----
137 o=align4(o); toff[4]=o
138 o=w32(buf,o,MAGIC_MAGIC_65536); o=w16(buf,o,si16(800)); o=w16(buf,o,si16(-200)); o=w16(buf,o,si16(0))
139 o=w16(buf,o,720); o=w16(buf,o,si16(0)); o=w16(buf,o,si16(0)); o=w16(buf,o,si16(720))
140 o=w16(buf,o,si16(1)); o=w16(buf,o,si16(0)); o=w16(buf,o,si16(0))
141 o=w16(buf,o,0);o=w16(buf,o,0);o=w16(buf,o,0);o=w16(buf,o,0)
142 o=w16(buf,o,si16(0)); o=w16(buf,o,5)
143 tlen[4]=o-toff[4]; o=align4(o); tcs[4]=csum(buf,toff[4],o-toff[4])
144
145 // ---- table 5: hmtx (5 metrics, 20 bytes) ----
146 o=align4(o); toff[5]=o
147 o=w16(buf,o,600);o=w16(buf,o,si16(80)); o=w16(buf,o,400);o=w16(buf,o,si16(0)); o=w16(buf,o,700);o=w16(buf,o,si16(130)); o=w16(buf,o,550);o=w16(buf,o,si16(250)); o=w16(buf,o,720);o=w16(buf,o,si16(60))
148 tlen[5]=o-toff[5]; o=align4(o); tcs[5]=csum(buf,toff[5],o-toff[5])
149
150 // ---- table 6: loca (short, 6 x u16) ----
151 o=align4(o); toff[6]=o
152 var li: i64=0; while li<6 { o=w16(buf,o,goff[li]/2); li=li+1 }
153 tlen[6]=o-toff[6]; o=align4(o); tcs[6]=csum(buf,toff[6],o-toff[6])
154
155 // ---- table 7: maxp (v1.0, 32 bytes) ----
156 o=align4(o); toff[7]=o
157 o=w32(buf,o,MAGIC_MAGIC_65536); o=w16(buf,o,5); o=w16(buf,o,12); o=w16(buf,o,3)
158 o=w16(buf,o,0);o=w16(buf,o,0); o=w16(buf,o,2); o=w16(buf,o,0);o=w16(buf,o,0);o=w16(buf,o,0);o=w16(buf,o,0);o=w16(buf,o,0);o=w16(buf,o,0);o=w16(buf,o,0);o=w16(buf,o,0)
159 tlen[7]=o-toff[7]; o=align4(o); tcs[7]=csum(buf,toff[7],o-toff[7])
160
161 // ---- table 8: name (4 records, UTF-16BE) ----
162 o=align4(o); toff[8]=o
163 o=w16(buf,o,0); o=w16(buf,o,4); o=w16(buf,o,54) // format, count, stringOffset
164 o=w16(buf,o,3);o=w16(buf,o,1);o=w16(buf,o,MAGIC_MAGIC_1033);o=w16(buf,o,1);o=w16(buf,o,20);o=w16(buf,o,0) // id1 family
165 o=w16(buf,o,3);o=w16(buf,o,1);o=w16(buf,o,MAGIC_MAGIC_1033);o=w16(buf,o,2);o=w16(buf,o,14);o=w16(buf,o,20) // id2 subfamily
166 o=w16(buf,o,3);o=w16(buf,o,1);o=w16(buf,o,MAGIC_MAGIC_1033);o=w16(buf,o,4);o=w16(buf,o,20);o=w16(buf,o,0) // id4 full
167 o=w16(buf,o,3);o=w16(buf,o,1);o=w16(buf,o,MAGIC_MAGIC_1033);o=w16(buf,o,6);o=w16(buf,o,18);o=w16(buf,o,34) // id6 postscript
168 o=utf16be(buf,o,"Nishi Sans" as *u8); o=utf16be(buf,o,"Regular" as *u8); o=utf16be(buf,o,"NishiSans" as *u8)
169 tlen[8]=o-toff[8]; o=align4(o); tcs[8]=csum(buf,toff[8],o-toff[8])
170
171 // ---- table 9: post (v3.0, 32 bytes) ----
172 o=align4(o); toff[9]=o
173 o=w32(buf,o,MAGIC_MAGIC_196608); o=w32(buf,o,0); o=w16(buf,o,si16(-100)); o=w16(buf,o,50); o=w32(buf,o,0);o=w32(buf,o,0);o=w32(buf,o,0);o=w32(buf,o,0);o=w32(buf,o,0)
174 tlen[9]=o-toff[9]; o=align4(o); tcs[9]=csum(buf,toff[9],o-toff[9])
175
176 let total: i64=o
177
178 // ---- header ----
179 var h: i64=0
180 h=w32(buf,h,MAGIC_MAGIC_65536); h=w16(buf,h,NT); h=w16(buf,h,128); h=w16(buf,h,3); h=w16(buf,h,32)
181 // ---- table directory (sorted): tags for indices 0..9 ----
182 // 0 OS/2 1 cmap 2 glyf 3 head 4 hhea 5 hmtx 6 loca 7 maxp 8 name 9 post
183 let tags: *u8 = "OS/2cmapglyfheadhheahmtxlocamaxpnamepost" as *u8
184 var d: i64=12
185 var ti: i64=0
186 while ti<NT {
187 buf[d]=tags[ti*4]; buf[d+1]=tags[ti*4+1]; buf[d+2]=tags[ti*4+2]; buf[d+3]=tags[ti*4+3]
188 w32(buf,d+4,tcs[ti]); w32(buf,d+8,toff[ti]); w32(buf,d+12,tlen[ti])
189 d=d+16; ti=ti+1
190 }
191
192 // ---- checkSumAdjustment: whole-file sum with adj=0, then adj = MAGIC - sum ----
193 let fsum0: i64 = csum(buf,0,total)
194 var adj: i64 = MAGIC_ADJ - fsum0
195 if adj < 0 { adj = adj + MAGIC_MAGIC_4294967296 }
196 w32(buf, toff[3]+8, adj)
197
198 // ---- write file ----
199 let fd: i64 = sys_openat_wr("web_assets/nishi.ttf" as *u8, 420)
200 if fd < 0 { sw("SAVE-FAIL\n" as *u8); return 6 }
201 sys_write(fd, buf, total); sys_close(fd)
202 sw("nx_font_ttf_emit: wrote web_assets/nishi.ttf bytes=" as *u8); sn(total); sw("\n" as *u8)
203
204 // ---- SELF-VALIDATE (re-parse the emitted bytes) ----
205 var ok: i64=1
206 if r32(buf,0)!=MAGIC_MAGIC_65536 { ok=0; sw(" FAIL sfntVersion\n" as *u8) }
207 if r16(buf,4)!=NT { ok=0; sw(" FAIL numTables\n" as *u8) }
208 var v: i64=0
209 while v<NT {
210 let eoff: i64 = r32(buf,12+v*16+8)
211 let elen: i64 = r32(buf,12+v*16+12)
212 if eoff+elen > total { ok=0; sw(" FAIL bounds t" as *u8); sn(v); sw("\n" as *u8) }
213 // recompute checksum (head special: zero its adj field for the recompute)
214 var save: i64=0
215 if v==3 { save = r32(buf, toff[3]+8); w32(buf, toff[3]+8, 0) }
216 let rc: i64 = csum(buf, eoff, align4(eoff+elen)-eoff)
217 if v==3 { w32(buf, toff[3]+8, save) }
218 if rc != r32(buf,12+v*16+4) { ok=0; sw(" FAIL checksum t" as *u8); sn(v); sw("\n" as *u8) }
219 v=v+1
220 }
221 let fsum1: i64 = csum(buf,0,total)
222 sw(" whole-file checksum=" as *u8); sn(fsum1); sw(" (must == " as *u8); sn(MAGIC_ADJ); sw(")\n" as *u8)
223 if fsum1 != MAGIC_ADJ { ok=0 }
224 // functional: cmap subtable format==4, endCode[0]==0x20
225 if r16(buf, toff[1]+12) != 4 { ok=0; sw(" FAIL cmap format\n" as *u8) }
226
227 if ok==1 { sw("VERDICT: GREEN (structurally-valid sovereign .ttf; self-validated round-trip; browser-render = operator opens the test page)\n" as *u8); sys_exit(0) }
228 sw("VERDICT: RED (self-validation failed)\n" as *u8)
229 sys_exit(1)
230 return 1
231}