code wiki / (root) / nx_font_ttf_emit.nx

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}