Typr.js 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528
  1. var Typr = {};
  2. Typr["parse"] = function(buff)
  3. {
  4. var readFont = function(data, idx, offset,tmap) {
  5. var bin = Typr["B"];
  6. var T = Typr["T"];
  7. var prsr = {
  8. "cmap":T.cmap,
  9. "head":T.head,
  10. "hhea":T.hhea,
  11. "maxp":T.maxp,
  12. "hmtx":T.hmtx,
  13. "name":T.name,
  14. "OS/2":T.OS2,
  15. "post":T.post,
  16. "loca":T.loca,
  17. "kern":T.kern,
  18. "glyf":T.glyf,
  19. "CFF ":T.CFF,
  20. /*
  21. "GPOS",
  22. "GSUB",
  23. "GDEF",*/
  24. "CBLC":T.CBLC,
  25. "CBDT":T.CBDT,
  26. "SVG ":T.SVG,
  27. "COLR":T.colr,
  28. "CPAL":T.cpal,
  29. "sbix":T.sbix
  30. //"VORG",
  31. };
  32. var obj = {"_data":data, "_index":idx, "_offset":offset};
  33. for(var t in prsr) {
  34. var tab = Typr["findTable"](data, t, offset);
  35. if(tab) {
  36. var off=tab[0], tobj = tmap[off];
  37. if(tobj==null) tobj = prsr[t].parseTab(data, off, tab[1], obj);
  38. obj[t] = tmap[off] = tobj;
  39. }
  40. }
  41. return obj;
  42. }
  43. var bin = Typr["B"];
  44. var data = new Uint8Array(buff);
  45. var tmap = {};
  46. var tag = bin.readASCII(data, 0, 4);
  47. if(tag=="ttcf") {
  48. var offset = 4;
  49. var majV = bin.readUshort(data, offset); offset+=2;
  50. var minV = bin.readUshort(data, offset); offset+=2;
  51. var numF = bin.readUint (data, offset); offset+=4;
  52. var fnts = [];
  53. for(var i=0; i<numF; i++) {
  54. var foff = bin.readUint (data, offset); offset+=4;
  55. fnts.push(readFont(data, i, foff,tmap));
  56. }
  57. return fnts;
  58. }
  59. else return [readFont(data, 0, 0,tmap)];
  60. }
  61. Typr["findTable"] = function(data, tab, foff)
  62. {
  63. var bin = Typr["B"];
  64. var numTables = bin.readUshort(data, foff+4);
  65. var offset = foff+12;
  66. for(var i=0; i<numTables; i++)
  67. {
  68. var tag = bin.readASCII(data, offset, 4); //console.log(tag);
  69. var checkSum = bin.readUint (data, offset+ 4);
  70. var toffset = bin.readUint (data, offset+ 8);
  71. var length = bin.readUint (data, offset+12);
  72. if(tag==tab) return [toffset,length];
  73. offset+=16;
  74. }
  75. return null;
  76. }
  77. /*
  78. Typr["splitBy"] = function(data,tag) {
  79. data = new Uint8Array(data); console.log(data.slice(0,64));
  80. var bin = Typr["B"];
  81. var ttcf = bin.readASCII(data, 0, 4); if(ttcf!="ttcf") return {};
  82. var offset = 8;
  83. var numF = bin.readUint (data, offset); offset+=4;
  84. var colls = [], used={};
  85. for(var i=0; i<numF; i++) {
  86. var foff = bin.readUint (data, offset); offset+=4;
  87. var toff = Typr["findTable"](data,tag,foff)[0];
  88. if(used[toff]==null) used[toff] = [];
  89. used[toff].push([foff,bin.readUshort(data,foff+4)]); // font offset, numTables
  90. }
  91. for(var toff in used) {
  92. var offs = used[toff];
  93. var hlen = 12+4*offs.length;
  94. var out = new Uint8Array(hlen);
  95. for(var i=0; i<8; i++) out[i]=data[i];
  96. bin.writeUint(out,8,offs.length);
  97. for(var i=0; i<offs.length; i++) hlen += 12+offs[i][1]*16;
  98. var hdrs = [out], tabs = [], hoff=out.length, toff=hlen, noffs={};
  99. for(var i=0; i<offs.length; i++) {
  100. bin.writeUint(out, 12+i*4, hoff); hoff+=12+offs[i][1]*16;
  101. toff = Typr["_cutFont"](data, offs[i][0], hdrs, tabs, toff, noffs);
  102. }
  103. colls.push(Typr["_joinArrs"](hdrs.concat(tabs)));
  104. }
  105. return colls;
  106. }
  107. Typr["splitFonts"] = function(data) {
  108. data = new Uint8Array(data);
  109. var bin = Typr["B"];
  110. var ttcf = bin.readASCII(data, 0, 4); if(ttcf!="ttcf") return {};
  111. var offset = 8;
  112. var numF = bin.readUint (data, offset); offset+=4;
  113. var fnts = [];
  114. for(var i=0; i<numF; i++) {
  115. var foff = bin.readUint (data, offset); offset+=4;
  116. fnts.push(Typr._cutFont(data, foff));
  117. break;
  118. }
  119. return fnts;
  120. }
  121. Typr["_cutFont"] = function(data,foff,hdrs,tabs,toff, noffs) {
  122. var bin = Typr["B"];
  123. var numTables = bin.readUshort(data, foff+4);
  124. var out = new Uint8Array(12+numTables*16); hdrs.push(out);
  125. for(var i=0; i<12; i++) out[i]=data[foff+i]; //console.log(out);
  126. var off = 12;
  127. for(var i=0; i<numTables; i++)
  128. {
  129. var tag = bin.readASCII(data, foff+off, 4);
  130. var checkSum = bin.readUint (data, foff+off+ 4);
  131. var toffset = bin.readUint (data, foff+off+ 8);
  132. var length = bin.readUint (data, foff+off+12);
  133. while((length&3)!=0) length++;
  134. for(var j=0; j<16; j++) out[off+j]=data[foff+off+j];
  135. if(noffs[toffset]!=null) bin.writeUint(out,off+8,noffs[toffset]);
  136. else {
  137. noffs[toffset] = toff;
  138. bin.writeUint(out, off+8, toff);
  139. tabs.push(new Uint8Array(data.buffer, toffset, length)); toff+=length;
  140. }
  141. off+=16;
  142. }
  143. return toff;
  144. }
  145. Typr["_joinArrs"] = function(tabs) {
  146. var len = 0;
  147. for(var i=0; i<tabs.length; i++) len+=tabs[i].length;
  148. var out = new Uint8Array(len), ooff=0;
  149. for(var i=0; i<tabs.length; i++) {
  150. var tab = tabs[i];
  151. for(var j=0; j<tab.length; j++) out[ooff+j]=tab[j];
  152. ooff+=tab.length;
  153. }
  154. return out;
  155. }
  156. */
  157. Typr["T"]={};
  158. Typr["B"] = {
  159. readFixed : function(data, o)
  160. {
  161. return ((data[o]<<8) | data[o+1]) + (((data[o+2]<<8)|data[o+3])/(256*256+4));
  162. },
  163. readF2dot14 : function(data, o)
  164. {
  165. var num = Typr["B"].readShort(data, o);
  166. return num / 16384;
  167. },
  168. readInt : function(buff, p)
  169. {
  170. //if(p>=buff.length) throw "error";
  171. var a = Typr["B"].t.uint8;
  172. a[0] = buff[p+3];
  173. a[1] = buff[p+2];
  174. a[2] = buff[p+1];
  175. a[3] = buff[p];
  176. return Typr["B"].t.int32[0];
  177. },
  178. readInt8 : function(buff, p)
  179. {
  180. //if(p>=buff.length) throw "error";
  181. var a = Typr["B"].t.uint8;
  182. a[0] = buff[p];
  183. return Typr["B"].t.int8[0];
  184. },
  185. readShort : function(buff, p)
  186. {
  187. //if(p>=buff.length) throw "error";
  188. var a = Typr["B"].t.uint16;
  189. a[0] = (buff[p]<<8) | buff[p+1];
  190. return Typr["B"].t.int16[0];
  191. },
  192. readUshort : function(buff, p)
  193. {
  194. //if(p>=buff.length) throw "error";
  195. return (buff[p]<<8) | buff[p+1];
  196. },
  197. writeUshort : function(buff, p, n)
  198. {
  199. buff[p] = (n>>8)&255; buff[p+1] = n&255;
  200. },
  201. readUshorts : function(buff, p, len)
  202. {
  203. var arr = [];
  204. for(var i=0; i<len; i++) {
  205. var v = Typr["B"].readUshort(buff, p+i*2); //if(v==932) console.log(p+i*2);
  206. arr.push(v);
  207. }
  208. return arr;
  209. },
  210. readUint : function(buff, p)
  211. {
  212. //if(p>=buff.length) throw "error";
  213. var a = Typr["B"].t.uint8;
  214. a[3] = buff[p]; a[2] = buff[p+1]; a[1] = buff[p+2]; a[0] = buff[p+3];
  215. return Typr["B"].t.uint32[0];
  216. },
  217. writeUint: function(buff, p, n)
  218. {
  219. buff[p] = (n>>24)&255; buff[p+1] = (n>>16)&255; buff[p+2] = (n>>8)&255; buff[p+3] = (n>>0)&255;
  220. },
  221. readUint64 : function(buff, p)
  222. {
  223. //if(p>=buff.length) throw "error";
  224. return (Typr["B"].readUint(buff, p)*(0xffffffff+1)) + Typr["B"].readUint(buff, p+4);
  225. },
  226. readASCII : function(buff, p, l) // l : length in Characters (not Bytes)
  227. {
  228. //if(p>=buff.length) throw "error";
  229. var s = "";
  230. for(var i = 0; i < l; i++) s += String.fromCharCode(buff[p+i]);
  231. return s;
  232. },
  233. writeASCII : function(buff, p, s) // l : length in Characters (not Bytes)
  234. {
  235. for(var i = 0; i < s.length; i++)
  236. buff[p+i] = s.charCodeAt(i);
  237. },
  238. readUnicode : function(buff, p, l)
  239. {
  240. //if(p>=buff.length) throw "error";
  241. var s = "";
  242. for(var i = 0; i < l; i++)
  243. {
  244. var c = (buff[p++]<<8) | buff[p++];
  245. s += String.fromCharCode(c);
  246. }
  247. return s;
  248. },
  249. _tdec : window["TextDecoder"] ? new window["TextDecoder"]() : null,
  250. readUTF8 : function(buff, p, l) {
  251. var tdec = Typr["B"]._tdec;
  252. if(tdec && p==0 && l==buff.length) return tdec["decode"](buff);
  253. return Typr["B"].readASCII(buff,p,l);
  254. },
  255. readBytes : function(buff, p, l)
  256. {
  257. //if(p>=buff.length) throw "error";
  258. var arr = [];
  259. for(var i=0; i<l; i++) arr.push(buff[p+i]);
  260. return arr;
  261. },
  262. readASCIIArray : function(buff, p, l) // l : length in Characters (not Bytes)
  263. {
  264. //if(p>=buff.length) throw "error";
  265. var s = [];
  266. for(var i = 0; i < l; i++)
  267. s.push(String.fromCharCode(buff[p+i]));
  268. return s;
  269. },
  270. t : function() {
  271. var ab = new ArrayBuffer(8);
  272. return {
  273. buff : ab,
  274. int8 : new Int8Array (ab),
  275. uint8 : new Uint8Array (ab),
  276. int16 : new Int16Array (ab),
  277. uint16 : new Uint16Array(ab),
  278. int32 : new Int32Array (ab),
  279. uint32 : new Uint32Array(ab)
  280. }
  281. }()
  282. };
  283. Typr["T"].CFF = {
  284. parseTab : function(data, offset, length)
  285. {
  286. var bin = Typr["B"];
  287. var CFF = Typr["T"].CFF;
  288. data = new Uint8Array(data.buffer, offset, length);
  289. offset = 0;
  290. // Header
  291. var major = data[offset]; offset++;
  292. var minor = data[offset]; offset++;
  293. var hdrSize = data[offset]; offset++;
  294. var offsize = data[offset]; offset++;
  295. //console.log(major, minor, hdrSize, offsize);
  296. // Name INDEX
  297. var ninds = [];
  298. offset = CFF.readIndex(data, offset, ninds);
  299. var names = [];
  300. for(var i=0; i<ninds.length-1; i++) names.push(bin.readASCII(data, offset+ninds[i], ninds[i+1]-ninds[i]));
  301. offset += ninds[ninds.length-1];
  302. // Top DICT INDEX
  303. var tdinds = [];
  304. offset = CFF.readIndex(data, offset, tdinds); //console.log(tdinds);
  305. // Top DICT Data
  306. var topDicts = [];
  307. for(var i=0; i<tdinds.length-1; i++) topDicts.push( CFF.readDict(data, offset+tdinds[i], offset+tdinds[i+1]) );
  308. offset += tdinds[tdinds.length-1];
  309. var topdict = topDicts[0];
  310. //console.log(topdict);
  311. // String INDEX
  312. var sinds = [];
  313. offset = CFF.readIndex(data, offset, sinds);
  314. // String Data
  315. var strings = [];
  316. for(var i=0; i<sinds.length-1; i++) strings.push(bin.readASCII(data, offset+sinds[i], sinds[i+1]-sinds[i]));
  317. offset += sinds[sinds.length-1];
  318. // Global Subr INDEX (subroutines)
  319. CFF.readSubrs(data, offset, topdict);
  320. // charstrings
  321. if(topdict["CharStrings"]) topdict["CharStrings"] = CFF.readBytes(data, topdict["CharStrings"]);
  322. // CID font
  323. if(topdict["ROS"]) {
  324. offset = topdict["FDArray"];
  325. var fdind = [];
  326. offset = CFF.readIndex(data, offset, fdind);
  327. topdict["FDArray"] = [];
  328. for(var i=0; i<fdind.length-1; i++) {
  329. var dict = CFF.readDict(data, offset+fdind[i], offset+fdind[i+1]);
  330. CFF._readFDict(data, dict, strings);
  331. topdict["FDArray"].push( dict );
  332. }
  333. offset += fdind[fdind.length-1];
  334. offset = topdict["FDSelect"];
  335. topdict["FDSelect"] = [];
  336. var fmt = data[offset]; offset++;
  337. if(fmt==3) {
  338. var rns = bin.readUshort(data, offset); offset+=2;
  339. for(var i=0; i<rns+1; i++) {
  340. topdict["FDSelect"].push(bin.readUshort(data, offset), data[offset+2]); offset+=3;
  341. }
  342. }
  343. else throw fmt;
  344. }
  345. // Encoding
  346. //if(topdict["Encoding"]) topdict["Encoding"] = CFF.readEncoding(data, topdict["Encoding"], topdict["CharStrings"].length);
  347. // charset
  348. if(topdict["charset"] ) topdict["charset"] = CFF.readCharset (data, topdict["charset"] , topdict["CharStrings"].length);
  349. CFF._readFDict(data, topdict, strings);
  350. return topdict;
  351. },
  352. _readFDict : function(data, dict, ss) {
  353. var CFF = Typr["T"].CFF;
  354. var offset;
  355. if(dict["Private"]) {
  356. offset = dict["Private"][1];
  357. dict["Private"] = CFF.readDict(data, offset, offset+dict["Private"][0]);
  358. if(dict["Private"]["Subrs"]) CFF.readSubrs(data, offset+dict["Private"]["Subrs"], dict["Private"]);
  359. }
  360. for(var p in dict) if(["FamilyName","FontName","FullName","Notice","version","Copyright"].indexOf(p)!=-1) dict[p]=ss[dict[p] -426 + 35];
  361. },
  362. readSubrs : function(data, offset, obj)
  363. {
  364. obj["Subrs"] = Typr["T"].CFF.readBytes(data, offset);
  365. var bias, nSubrs = obj["Subrs"].length+1;
  366. if (false) bias = 0;
  367. else if (nSubrs < 1240) bias = 107;
  368. else if (nSubrs < 33900) bias = 1131;
  369. else bias = 32768;
  370. obj["Bias"] = bias;
  371. },
  372. readBytes : function(data, offset) {
  373. var bin = Typr["B"];
  374. var arr = [];
  375. offset = Typr["T"].CFF.readIndex(data, offset, arr);
  376. var subrs = [], arl = arr.length-1, no = data.byteOffset+offset;
  377. for(var i=0; i<arl; i++) {
  378. var ari = arr[i];
  379. subrs.push(new Uint8Array(data.buffer, no+ari, arr[i+1]-ari));
  380. }
  381. return subrs;
  382. },
  383. tableSE : [
  384. 0, 0, 0, 0, 0, 0, 0, 0,
  385. 0, 0, 0, 0, 0, 0, 0, 0,
  386. 0, 0, 0, 0, 0, 0, 0, 0,
  387. 0, 0, 0, 0, 0, 0, 0, 0,
  388. 1, 2, 3, 4, 5, 6, 7, 8,
  389. 9, 10, 11, 12, 13, 14, 15, 16,
  390. 17, 18, 19, 20, 21, 22, 23, 24,
  391. 25, 26, 27, 28, 29, 30, 31, 32,
  392. 33, 34, 35, 36, 37, 38, 39, 40,
  393. 41, 42, 43, 44, 45, 46, 47, 48,
  394. 49, 50, 51, 52, 53, 54, 55, 56,
  395. 57, 58, 59, 60, 61, 62, 63, 64,
  396. 65, 66, 67, 68, 69, 70, 71, 72,
  397. 73, 74, 75, 76, 77, 78, 79, 80,
  398. 81, 82, 83, 84, 85, 86, 87, 88,
  399. 89, 90, 91, 92, 93, 94, 95, 0,
  400. 0, 0, 0, 0, 0, 0, 0, 0,
  401. 0, 0, 0, 0, 0, 0, 0, 0,
  402. 0, 0, 0, 0, 0, 0, 0, 0,
  403. 0, 0, 0, 0, 0, 0, 0, 0,
  404. 0, 96, 97, 98, 99, 100, 101, 102,
  405. 103, 104, 105, 106, 107, 108, 109, 110,
  406. 0, 111, 112, 113, 114, 0, 115, 116,
  407. 117, 118, 119, 120, 121, 122, 0, 123,
  408. 0, 124, 125, 126, 127, 128, 129, 130,
  409. 131, 0, 132, 133, 0, 134, 135, 136,
  410. 137, 0, 0, 0, 0, 0, 0, 0,
  411. 0, 0, 0, 0, 0, 0, 0, 0,
  412. 0, 138, 0, 139, 0, 0, 0, 0,
  413. 140, 141, 142, 143, 0, 0, 0, 0,
  414. 0, 144, 0, 0, 0, 145, 0, 0,
  415. 146, 147, 148, 149, 0, 0, 0, 0
  416. ],
  417. glyphByUnicode : function(cff, code)
  418. {
  419. for(var i=0; i<cff["charset"].length; i++) if(cff["charset"][i]==code) return i;
  420. return -1;
  421. },
  422. glyphBySE : function(cff, charcode) // glyph by standard encoding
  423. {
  424. if ( charcode < 0 || charcode > 255 ) return -1;
  425. return Typr["T"].CFF.glyphByUnicode(cff, Typr["T"].CFF.tableSE[charcode]);
  426. },
  427. /*readEncoding : function(data, offset, num)
  428. {
  429. var bin = Typr["B"];
  430. var array = ['.notdef'];
  431. var format = data[offset]; offset++;
  432. //console.log("Encoding");
  433. //console.log(format);
  434. if(format==0)
  435. {
  436. var nCodes = data[offset]; offset++;
  437. for(var i=0; i<nCodes; i++) array.push(data[offset+i]);
  438. }
  439. /*
  440. else if(format==1 || format==2)
  441. {
  442. while(charset.length<num)
  443. {
  444. var first = bin.readUshort(data, offset); offset+=2;
  445. var nLeft=0;
  446. if(format==1) { nLeft = data[offset]; offset++; }
  447. else { nLeft = bin.readUshort(data, offset); offset+=2; }
  448. for(var i=0; i<=nLeft; i++) { charset.push(first); first++; }
  449. }
  450. }
  451. else throw "error: unknown encoding format: " + format;
  452. return array;
  453. },*/
  454. readCharset : function(data, offset, num)
  455. {
  456. var bin = Typr["B"];
  457. var charset = ['.notdef'];
  458. var format = data[offset]; offset++;
  459. if(format==0)
  460. {
  461. for(var i=0; i<num; i++)
  462. {
  463. var first = bin.readUshort(data, offset); offset+=2;
  464. charset.push(first);
  465. }
  466. }
  467. else if(format==1 || format==2)
  468. {
  469. while(charset.length<num)
  470. {
  471. var first = bin.readUshort(data, offset); offset+=2;
  472. var nLeft=0;
  473. if(format==1) { nLeft = data[offset]; offset++; }
  474. else { nLeft = bin.readUshort(data, offset); offset+=2; }
  475. for(var i=0; i<=nLeft; i++) { charset.push(first); first++; }
  476. }
  477. }
  478. else throw "error: format: " + format;
  479. return charset;
  480. },
  481. readIndex : function(data, offset, inds)
  482. {
  483. var bin = Typr["B"];
  484. var count = bin.readUshort(data, offset)+1; offset+=2;
  485. var offsize = data[offset]; offset++;
  486. if (offsize==1) for(var i=0; i<count; i++) inds.push( data[offset+i] );
  487. else if(offsize==2) for(var i=0; i<count; i++) inds.push( bin.readUshort(data, offset+i*2) );
  488. else if(offsize==3) for(var i=0; i<count; i++) inds.push( bin.readUint (data, offset+i*3 - 1) & 0x00ffffff );
  489. else if(offsize==4) for(var i=0; i<count; i++) inds.push( bin.readUint (data, offset+i*4) );
  490. else if(count!=1) throw "unsupported offset size: " + offsize + ", count: " + count;
  491. offset += count*offsize;
  492. return offset-1;
  493. },
  494. getCharString : function(data, offset, o)
  495. {
  496. var bin = Typr["B"];
  497. var b0 = data[offset], b1 = data[offset+1], b2 = data[offset+2], b3 = data[offset+3], b4=data[offset+4];
  498. var vs = 1;
  499. var op=null, val=null;
  500. // operand
  501. if(b0<=20) { op = b0; vs=1; }
  502. if(b0==12) { op = b0*100+b1; vs=2; }
  503. //if(b0==19 || b0==20) { op = b0/*+" "+b1*/; vs=2; }
  504. if(21 <=b0 && b0<= 27) { op = b0; vs=1; }
  505. if(b0==28) { val = bin.readShort(data,offset+1); vs=3; }
  506. if(29 <=b0 && b0<= 31) { op = b0; vs=1; }
  507. if(32 <=b0 && b0<=246) { val = b0-139; vs=1; }
  508. if(247<=b0 && b0<=250) { val = (b0-247)*256+b1+108; vs=2; }
  509. if(251<=b0 && b0<=254) { val =-(b0-251)*256-b1-108; vs=2; }
  510. if(b0==255) { val = bin.readInt(data, offset+1)/0xffff; vs=5; }
  511. o.val = val!=null ? val : "o"+op;
  512. o.size = vs;
  513. },
  514. readCharString : function(data, offset, length)
  515. {
  516. var end = offset + length;
  517. var bin = Typr["B"];
  518. var arr = [];
  519. while(offset<end)
  520. {
  521. var b0 = data[offset], b1 = data[offset+1], b2 = data[offset+2], b3 = data[offset+3], b4=data[offset+4];
  522. var vs = 1;
  523. var op=null, val=null;
  524. // operand
  525. if(b0<=20) { op = b0; vs=1; }
  526. if(b0==12) { op = b0*100+b1; vs=2; }
  527. if(b0==19 || b0==20) { op = b0/*+" "+b1*/; vs=2; }
  528. if(21 <=b0 && b0<= 27) { op = b0; vs=1; }
  529. if(b0==28) { val = bin.readShort(data,offset+1); vs=3; }
  530. if(29 <=b0 && b0<= 31) { op = b0; vs=1; }
  531. if(32 <=b0 && b0<=246) { val = b0-139; vs=1; }
  532. if(247<=b0 && b0<=250) { val = (b0-247)*256+b1+108; vs=2; }
  533. if(251<=b0 && b0<=254) { val =-(b0-251)*256-b1-108; vs=2; }
  534. if(b0==255) { val = bin.readInt(data, offset+1)/0xffff; vs=5; }
  535. arr.push(val!=null ? val : "o"+op);
  536. offset += vs;
  537. //var cv = arr[arr.length-1];
  538. //if(cv==undefined) throw "error";
  539. //console.log()
  540. }
  541. return arr;
  542. },
  543. readDict : function(data, offset, end)
  544. {
  545. var bin = Typr["B"];
  546. //var dict = [];
  547. var dict = {};
  548. var carr = [];
  549. while(offset<end)
  550. {
  551. var b0 = data[offset], b1 = data[offset+1], b2 = data[offset+2], b3 = data[offset+3], b4=data[offset+4];
  552. var vs = 1;
  553. var key=null, val=null;
  554. // operand
  555. if(b0==28) { val = bin.readShort(data,offset+1); vs=3; }
  556. if(b0==29) { val = bin.readInt (data,offset+1); vs=5; }
  557. if(32 <=b0 && b0<=246) { val = b0-139; vs=1; }
  558. if(247<=b0 && b0<=250) { val = (b0-247)*256+b1+108; vs=2; }
  559. if(251<=b0 && b0<=254) { val =-(b0-251)*256-b1-108; vs=2; }
  560. if(b0==255) { val = bin.readInt(data, offset+1)/0xffff; vs=5; throw "unknown number"; }
  561. if(b0==30)
  562. {
  563. var nibs = [];
  564. vs = 1;
  565. while(true)
  566. {
  567. var b = data[offset+vs]; vs++;
  568. var nib0 = b>>4, nib1 = b&0xf;
  569. if(nib0 != 0xf) nibs.push(nib0); if(nib1!=0xf) nibs.push(nib1);
  570. if(nib1==0xf) break;
  571. }
  572. var s = "";
  573. var chars = [0,1,2,3,4,5,6,7,8,9,".","e","e-","reserved","-","endOfNumber"];
  574. for(var i=0; i<nibs.length; i++) s += chars[nibs[i]];
  575. //console.log(nibs);
  576. val = parseFloat(s);
  577. }
  578. if(b0<=21) // operator
  579. {
  580. var keys = ["version", "Notice", "FullName", "FamilyName", "Weight", "FontBBox", "BlueValues", "OtherBlues", "FamilyBlues","FamilyOtherBlues",
  581. "StdHW", "StdVW", "escape", "UniqueID", "XUID", "charset", "Encoding", "CharStrings", "Private", "Subrs",
  582. "defaultWidthX", "nominalWidthX"];
  583. key = keys[b0]; vs=1;
  584. if(b0==12) {
  585. var keys = [ "Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition", "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix", "StrokeWidth", "BlueScale",
  586. "BlueShift", "BlueFuzz", "StemSnapH", "StemSnapV", "ForceBold", "","", "LanguageGroup", "ExpansionFactor", "initialRandomSeed",
  587. "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend", "","","", "","","",
  588. "ROS", "CIDFontVersion", "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase", "FDArray", "FDSelect", "FontName"];
  589. key = keys[b1]; vs=2;
  590. }
  591. }
  592. if(key!=null) { dict[key] = carr.length==1 ? carr[0] : carr; carr=[]; }
  593. else carr.push(val);
  594. offset += vs;
  595. }
  596. return dict;
  597. }
  598. };
  599. Typr["T"].cmap = {
  600. parseTab : function(data, offset, length)
  601. {
  602. var obj = {tables:[],ids:{},off:offset};
  603. data = new Uint8Array(data.buffer, offset, length);
  604. offset = 0;
  605. var offset0 = offset;
  606. var bin = Typr["B"], rU = bin.readUshort, cmap = Typr["T"].cmap;
  607. var version = rU(data, offset); offset += 2;
  608. var numTables = rU(data, offset); offset += 2;
  609. //console.log(version, numTables);
  610. var offs = [];
  611. for(var i=0; i<numTables; i++)
  612. {
  613. var platformID = rU(data, offset); offset += 2;
  614. var encodingID = rU(data, offset); offset += 2;
  615. var noffset = bin.readUint(data, offset); offset += 4;
  616. var id = "p"+platformID+"e"+encodingID;
  617. //console.log("cmap subtable", platformID, encodingID, noffset);
  618. var tind = offs.indexOf(noffset);
  619. if(tind==-1)
  620. {
  621. tind = obj.tables.length;
  622. var subt = {};
  623. offs.push(noffset);
  624. //var time = Date.now();
  625. var format = subt.format = rU(data, noffset);
  626. if (format== 0) subt = cmap.parse0(data, noffset, subt);
  627. //else if(format== 2) subt.off = noffset;
  628. else if(format== 4) subt = cmap.parse4(data, noffset, subt);
  629. else if(format== 6) subt = cmap.parse6(data, noffset, subt);
  630. else if(format==12) subt = cmap.parse12(data,noffset, subt);
  631. //console.log(format, Date.now()-time);
  632. //else console.log("unknown format: "+format, platformID, encodingID, noffset);
  633. obj.tables.push(subt);
  634. }
  635. if(obj.ids[id]!=null) console.log("multiple tables for one platform+encoding: "+id);
  636. obj.ids[id] = tind;
  637. }
  638. return obj;
  639. },
  640. parse0 : function(data, offset, obj)
  641. {
  642. var bin = Typr["B"];
  643. offset += 2;
  644. var len = bin.readUshort(data, offset); offset += 2;
  645. var lang = bin.readUshort(data, offset); offset += 2;
  646. obj.map = [];
  647. for(var i=0; i<len-6; i++) obj.map.push(data[offset+i]);
  648. return obj;
  649. },
  650. parse4 : function(data, offset, obj)
  651. {
  652. var bin = Typr["B"], rU = bin.readUshort, rUs = bin.readUshorts;
  653. var offset0 = offset;
  654. offset+=2;
  655. var length = rU(data, offset); offset+=2;
  656. var language = rU(data, offset); offset+=2;
  657. var segCountX2 = rU(data, offset); offset+=2;
  658. var segCount = segCountX2>>>1;
  659. obj.searchRange = rU(data, offset); offset+=2;
  660. obj.entrySelector = rU(data, offset); offset+=2;
  661. obj.rangeShift = rU(data, offset); offset+=2;
  662. obj.endCount = rUs(data, offset, segCount); offset += segCount*2;
  663. offset+=2;
  664. obj.startCount = rUs(data, offset, segCount); offset += segCount*2;
  665. obj.idDelta = [];
  666. for(var i=0; i<segCount; i++) {obj.idDelta.push(bin.readShort(data, offset)); offset+=2;}
  667. obj.idRangeOffset = rUs(data, offset, segCount); offset += segCount*2;
  668. obj.glyphIdArray = rUs(data, offset, ((offset0+length)-offset)>>>1); //offset += segCount*2;
  669. return obj;
  670. },
  671. parse6 : function(data, offset, obj)
  672. {
  673. var bin = Typr["B"];
  674. var offset0 = offset;
  675. offset+=2;
  676. var length = bin.readUshort(data, offset); offset+=2;
  677. var language = bin.readUshort(data, offset); offset+=2;
  678. obj.firstCode = bin.readUshort(data, offset); offset+=2;
  679. var entryCount = bin.readUshort(data, offset); offset+=2;
  680. obj.glyphIdArray = [];
  681. for(var i=0; i<entryCount; i++) {obj.glyphIdArray.push(bin.readUshort(data, offset)); offset+=2;}
  682. return obj;
  683. },
  684. parse12 : function(data, offset, obj)
  685. {
  686. var bin = Typr["B"], rU = bin.readUint;
  687. var offset0 = offset;
  688. offset+=4;
  689. var length = rU(data, offset); offset+=4;
  690. var lang = rU(data, offset); offset+=4;
  691. var nGroups= rU(data, offset)*3; offset+=4;
  692. var gps = obj.groups = new Uint32Array(nGroups);//new Uint32Array(data.slice(offset, offset+nGroups*12).buffer);
  693. for(var i=0; i<nGroups; i+=3) {
  694. gps[i ] = rU(data, offset+(i<<2) );
  695. gps[i+1] = rU(data, offset+(i<<2)+4);
  696. gps[i+2] = rU(data, offset+(i<<2)+8);
  697. }
  698. return obj;
  699. }
  700. };
  701. Typr["T"].CBLC = {
  702. parseTab : function(data, offset, length)
  703. {
  704. var bin = Typr["B"], ooff=offset;
  705. var maj = bin.readUshort(data,offset); offset+=2;
  706. var min = bin.readUshort(data,offset); offset+=2;
  707. var numSizes = bin.readUint (data,offset); offset+=4;
  708. var out = [];
  709. for(var i=0; i<numSizes; i++) {
  710. var off = bin.readUint (data,offset); offset+=4; // indexSubTableArrayOffset
  711. var siz = bin.readUint (data,offset); offset+=4; // indexTablesSize
  712. var num = bin.readUint (data,offset); offset+=4; // numberOfIndexSubTables
  713. offset+=4;
  714. offset+=2*12;
  715. var sGlyph = bin.readUshort(data,offset); offset+=2;
  716. var eGlyph = bin.readUshort(data,offset); offset+=2;
  717. //console.log(off,siz,num, sGlyph, eGlyph);
  718. offset+=4;
  719. var coff = ooff+off;
  720. for(var j=0; j<3; j++) {
  721. var fgI = bin.readUshort(data,coff); coff+=2;
  722. var lgI = bin.readUshort(data,coff); coff+=2;
  723. var nxt = bin.readUint (data,coff); coff+=4;
  724. var gcnt = lgI-fgI+1;
  725. //console.log(fgI, lgI, nxt); //if(nxt==0) break;
  726. var ioff = ooff+off+nxt;
  727. var inF = bin.readUshort(data,ioff); ioff+=2; if(inF!=1) throw inF;
  728. var imF = bin.readUshort(data,ioff); ioff+=2;
  729. var imgo = bin.readUint (data,ioff); ioff+=4;
  730. var oarr = [];
  731. for(var gi=0; gi<gcnt; gi++) {
  732. var sbitO = bin.readUint(data,ioff+gi*4); oarr.push(imgo+sbitO);
  733. //console.log("--",sbitO);
  734. }
  735. out.push([fgI,lgI,imF,oarr]);
  736. }
  737. }
  738. return out;
  739. }
  740. };
  741. Typr["T"].CBDT = {
  742. parseTab : function(data, offset, length)
  743. {
  744. var bin = Typr["B"];
  745. var ooff=offset;
  746. //var maj = bin.readUshort(data,offset); offset+=2;
  747. //var min = bin.readUshort(data,offset); offset+=2;
  748. return new Uint8Array(data.buffer, data.byteOffset+offset, length);
  749. }
  750. };
  751. Typr["T"].glyf = {
  752. parseTab : function(data, offset, length, font)
  753. {
  754. var obj = [], ng=font["maxp"]["numGlyphs"];
  755. for(var g=0; g<ng; g++) obj.push(null);
  756. return obj;
  757. },
  758. _parseGlyf : function(font, g)
  759. {
  760. var bin = Typr["B"];
  761. var data = font["_data"], loca=font["loca"];
  762. if(loca[g]==loca[g+1]) return null;
  763. var offset = Typr["findTable"](data, "glyf", font["_offset"])[0] + loca[g];
  764. var gl = {};
  765. gl.noc = bin.readShort(data, offset); offset+=2; // number of contours
  766. gl.xMin = bin.readShort(data, offset); offset+=2;
  767. gl.yMin = bin.readShort(data, offset); offset+=2;
  768. gl.xMax = bin.readShort(data, offset); offset+=2;
  769. gl.yMax = bin.readShort(data, offset); offset+=2;
  770. if(gl.xMin>=gl.xMax || gl.yMin>=gl.yMax) return null;
  771. if(gl.noc>0)
  772. {
  773. gl.endPts = [];
  774. for(var i=0; i<gl.noc; i++) { gl.endPts.push(bin.readUshort(data,offset)); offset+=2; }
  775. var instructionLength = bin.readUshort(data,offset); offset+=2;
  776. if((data.length-offset)<instructionLength) return null;
  777. gl.instructions = bin.readBytes(data, offset, instructionLength); offset+=instructionLength;
  778. var crdnum = gl.endPts[gl.noc-1]+1;
  779. gl.flags = [];
  780. for(var i=0; i<crdnum; i++ )
  781. {
  782. var flag = data[offset]; offset++;
  783. gl.flags.push(flag);
  784. if((flag&8)!=0)
  785. {
  786. var rep = data[offset]; offset++;
  787. for(var j=0; j<rep; j++) { gl.flags.push(flag); i++; }
  788. }
  789. }
  790. gl.xs = [];
  791. for(var i=0; i<crdnum; i++) {
  792. var i8=((gl.flags[i]&2)!=0), same=((gl.flags[i]&16)!=0);
  793. if(i8) { gl.xs.push(same ? data[offset] : -data[offset]); offset++; }
  794. else
  795. {
  796. if(same) gl.xs.push(0);
  797. else { gl.xs.push(bin.readShort(data, offset)); offset+=2; }
  798. }
  799. }
  800. gl.ys = [];
  801. for(var i=0; i<crdnum; i++) {
  802. var i8=((gl.flags[i]&4)!=0), same=((gl.flags[i]&32)!=0);
  803. if(i8) { gl.ys.push(same ? data[offset] : -data[offset]); offset++; }
  804. else
  805. {
  806. if(same) gl.ys.push(0);
  807. else { gl.ys.push(bin.readShort(data, offset)); offset+=2; }
  808. }
  809. }
  810. var x = 0, y = 0;
  811. for(var i=0; i<crdnum; i++) { x += gl.xs[i]; y += gl.ys[i]; gl.xs[i]=x; gl.ys[i]=y; }
  812. //console.log(endPtsOfContours, instructionLength, instructions, flags, xCoordinates, yCoordinates);
  813. }
  814. else
  815. {
  816. var ARG_1_AND_2_ARE_WORDS = 1<<0;
  817. var ARGS_ARE_XY_VALUES = 1<<1;
  818. var ROUND_XY_TO_GRID = 1<<2;
  819. var WE_HAVE_A_SCALE = 1<<3;
  820. var RESERVED = 1<<4;
  821. var MORE_COMPONENTS = 1<<5;
  822. var WE_HAVE_AN_X_AND_Y_SCALE= 1<<6;
  823. var WE_HAVE_A_TWO_BY_TWO = 1<<7;
  824. var WE_HAVE_INSTRUCTIONS = 1<<8;
  825. var USE_MY_METRICS = 1<<9;
  826. var OVERLAP_COMPOUND = 1<<10;
  827. var SCALED_COMPONENT_OFFSET = 1<<11;
  828. var UNSCALED_COMPONENT_OFFSET = 1<<12;
  829. gl.parts = [];
  830. var flags;
  831. do {
  832. flags = bin.readUshort(data, offset); offset += 2;
  833. var part = { m:{a:1,b:0,c:0,d:1,tx:0,ty:0}, p1:-1, p2:-1 }; gl.parts.push(part);
  834. part.glyphIndex = bin.readUshort(data, offset); offset += 2;
  835. if ( flags & ARG_1_AND_2_ARE_WORDS) {
  836. var arg1 = bin.readShort(data, offset); offset += 2;
  837. var arg2 = bin.readShort(data, offset); offset += 2;
  838. } else {
  839. var arg1 = bin.readInt8(data, offset); offset ++;
  840. var arg2 = bin.readInt8(data, offset); offset ++;
  841. }
  842. if(flags & ARGS_ARE_XY_VALUES) { part.m.tx = arg1; part.m.ty = arg2; }
  843. else { part.p1=arg1; part.p2=arg2; }
  844. //part.m.tx = arg1; part.m.ty = arg2;
  845. //else { throw "params are not XY values"; }
  846. if ( flags & WE_HAVE_A_SCALE ) {
  847. part.m.a = part.m.d = bin.readF2dot14(data, offset); offset += 2;
  848. } else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE ) {
  849. part.m.a = bin.readF2dot14(data, offset); offset += 2;
  850. part.m.d = bin.readF2dot14(data, offset); offset += 2;
  851. } else if ( flags & WE_HAVE_A_TWO_BY_TWO ) {
  852. part.m.a = bin.readF2dot14(data, offset); offset += 2;
  853. part.m.b = bin.readF2dot14(data, offset); offset += 2;
  854. part.m.c = bin.readF2dot14(data, offset); offset += 2;
  855. part.m.d = bin.readF2dot14(data, offset); offset += 2;
  856. }
  857. } while ( flags & MORE_COMPONENTS )
  858. if (flags & WE_HAVE_INSTRUCTIONS){
  859. var numInstr = bin.readUshort(data, offset); offset += 2;
  860. gl.instr = [];
  861. for(var i=0; i<numInstr; i++) { gl.instr.push(data[offset]); offset++; }
  862. }
  863. }
  864. return gl;
  865. }
  866. };
  867. Typr["T"].head = {
  868. parseTab : function(data, offset, length)
  869. {
  870. var bin = Typr["B"];
  871. var obj = {};
  872. var tableVersion = bin.readFixed(data, offset); offset += 4;
  873. obj["fontRevision"] = bin.readFixed(data, offset); offset += 4;
  874. var checkSumAdjustment = bin.readUint(data, offset); offset += 4;
  875. var magicNumber = bin.readUint(data, offset); offset += 4;
  876. obj["flags"] = bin.readUshort(data, offset); offset += 2;
  877. obj["unitsPerEm"] = bin.readUshort(data, offset); offset += 2;
  878. obj["created"] = bin.readUint64(data, offset); offset += 8;
  879. obj["modified"] = bin.readUint64(data, offset); offset += 8;
  880. obj["xMin"] = bin.readShort(data, offset); offset += 2;
  881. obj["yMin"] = bin.readShort(data, offset); offset += 2;
  882. obj["xMax"] = bin.readShort(data, offset); offset += 2;
  883. obj["yMax"] = bin.readShort(data, offset); offset += 2;
  884. obj["macStyle"] = bin.readUshort(data, offset); offset += 2;
  885. obj["lowestRecPPEM"] = bin.readUshort(data, offset); offset += 2;
  886. obj["fontDirectionHint"] = bin.readShort(data, offset); offset += 2;
  887. obj["indexToLocFormat"] = bin.readShort(data, offset); offset += 2;
  888. obj["glyphDataFormat"] = bin.readShort(data, offset); offset += 2;
  889. return obj;
  890. }
  891. };
  892. Typr["T"].hhea = {
  893. parseTab : function(data, offset, length)
  894. {
  895. var bin = Typr["B"];
  896. var obj = {};
  897. var tableVersion = bin.readFixed(data, offset); offset += 4;
  898. var keys = ["ascender","descender","lineGap",
  899. "advanceWidthMax","minLeftSideBearing","minRightSideBearing","xMaxExtent",
  900. "caretSlopeRise","caretSlopeRun","caretOffset",
  901. "res0","res1","res2","res3",
  902. "metricDataFormat","numberOfHMetrics" ];
  903. for(var i=0; i< keys.length; i++) {
  904. var key = keys[i];
  905. var func = (key=="advanceWidthMax" || key=="numberOfHMetrics")?bin.readUshort:bin.readShort;
  906. obj[key]=func(data,offset+i*2);
  907. }
  908. return obj;
  909. }
  910. };
  911. Typr["T"].hmtx = {
  912. parseTab : function(data, offset, length, font)
  913. {
  914. var bin = Typr["B"];
  915. var aWidth = [];
  916. var lsBearing = [];
  917. var nG = font["maxp"]["numGlyphs"], nH = font["hhea"]["numberOfHMetrics"];
  918. var aw = 0, lsb = 0, i=0;
  919. while(i<nH) { aw=bin.readUshort(data, offset+(i<<2)); lsb=bin.readShort(data, offset+(i<<2)+2); aWidth.push(aw); lsBearing.push(lsb); i++; }
  920. while(i<nG) { aWidth.push(aw); lsBearing.push(lsb); i++; }
  921. return {aWidth:aWidth, lsBearing:lsBearing};
  922. }
  923. };
  924. Typr["T"].kern = {
  925. parseTab : function(data, offset, length, font)
  926. {
  927. var bin = Typr["B"], kern=Typr["T"].kern;
  928. var version = bin.readUshort(data, offset);
  929. if(version==1) return kern.parseV1(data, offset, length, font);
  930. var nTables = bin.readUshort(data, offset+2); offset+=4;
  931. var map = {glyph1: [], rval:[]};
  932. for(var i=0; i<nTables; i++)
  933. {
  934. offset+=2; // skip version
  935. var length = bin.readUshort(data, offset); offset+=2;
  936. var coverage = bin.readUshort(data, offset); offset+=2;
  937. var format = coverage>>>8;
  938. /* I have seen format 128 once, that's why I do */ format &= 0xf;
  939. if(format==0) offset = kern.readFormat0(data, offset, map);
  940. //else throw "unknown kern table format: "+format;
  941. }
  942. return map;
  943. },
  944. parseV1 : function(data, offset, length, font)
  945. {
  946. var bin = Typr["B"], kern=Typr["T"].kern;
  947. var version = bin.readFixed(data, offset); // 0x00010000
  948. var nTables = bin.readUint (data, offset+4); offset+=8;
  949. var map = {glyph1: [], rval:[]};
  950. for(var i=0; i<nTables; i++)
  951. {
  952. var length = bin.readUint(data, offset); offset+=4;
  953. var coverage = bin.readUshort(data, offset); offset+=2;
  954. var tupleIndex = bin.readUshort(data, offset); offset+=2;
  955. var format = coverage&0xff;
  956. if(format==0) offset = kern.readFormat0(data, offset, map);
  957. //else throw "unknown kern table format: "+format;
  958. }
  959. return map;
  960. },
  961. readFormat0 : function(data, offset, map)
  962. {
  963. var bin = Typr["B"], rUs = bin.readUshort;
  964. var pleft = -1;
  965. var nPairs = rUs(data, offset);
  966. var searchRange = rUs(data, offset+2);
  967. var entrySelector = rUs(data, offset+4);
  968. var rangeShift = rUs(data, offset+6); offset+=8;
  969. for(var j=0; j<nPairs; j++)
  970. {
  971. var left = rUs(data, offset); offset+=2;
  972. var right = rUs(data, offset); offset+=2;
  973. var value = bin.readShort (data, offset); offset+=2;
  974. if(left!=pleft) { map.glyph1.push(left); map.rval.push({ glyph2:[], vals:[] }) }
  975. var rval = map.rval[map.rval.length-1];
  976. rval.glyph2.push(right); rval.vals.push(value);
  977. pleft = left;
  978. }
  979. return offset;
  980. }
  981. };
  982. Typr["T"].loca = {
  983. parseTab : function(data, offset, length, font)
  984. {
  985. var bin = Typr["B"];
  986. var obj = [];
  987. var ver = font["head"]["indexToLocFormat"];
  988. var len = font["maxp"]["numGlyphs"]+1;
  989. if(ver==0) for(var i=0; i<len; i++) obj.push(bin.readUshort(data, offset+(i<<1))<<1);
  990. if(ver==1) for(var i=0; i<len; i++) obj.push(bin.readUint (data, offset+(i<<2)) );
  991. return obj;
  992. }
  993. };
  994. Typr["T"].maxp = {
  995. parseTab : function(data, offset, length)
  996. {
  997. //console.log(data.length, offset, length);
  998. var bin = Typr["B"], rU=bin.readUshort;
  999. var obj = {};
  1000. // both versions 0.5 and 1.0
  1001. var ver = bin.readUint(data, offset); offset += 4;
  1002. obj["numGlyphs"] = rU(data, offset); offset += 2;
  1003. // only 1.0
  1004. /*
  1005. if(ver == 0x00010000) {
  1006. obj.maxPoints = rU(data, offset); offset += 2;
  1007. obj.maxContours = rU(data, offset); offset += 2;
  1008. obj.maxCompositePoints = rU(data, offset); offset += 2;
  1009. obj.maxCompositeContours = rU(data, offset); offset += 2;
  1010. obj.maxZones = rU(data, offset); offset += 2;
  1011. obj.maxTwilightPoints = rU(data, offset); offset += 2;
  1012. obj.maxStorage = rU(data, offset); offset += 2;
  1013. obj.maxFunctionDefs = rU(data, offset); offset += 2;
  1014. obj.maxInstructionDefs = rU(data, offset); offset += 2;
  1015. obj.maxStackElements = rU(data, offset); offset += 2;
  1016. obj.maxSizeOfInstructions = rU(data, offset); offset += 2;
  1017. obj.maxComponentElements = rU(data, offset); offset += 2;
  1018. obj.maxComponentDepth = rU(data, offset); offset += 2;
  1019. }
  1020. */
  1021. return obj;
  1022. }
  1023. };
  1024. Typr["T"].name = {
  1025. parseTab : function(data, offset, length)
  1026. {
  1027. var bin = Typr["B"];
  1028. var obj = {};
  1029. var format = bin.readUshort(data, offset); offset += 2;
  1030. var count = bin.readUshort(data, offset); offset += 2;
  1031. var stringOffset = bin.readUshort(data, offset); offset += 2;
  1032. //console.log(format,count);
  1033. var names = [
  1034. "copyright",
  1035. "fontFamily",
  1036. "fontSubfamily",
  1037. "ID",
  1038. "fullName",
  1039. "version",
  1040. "postScriptName",
  1041. "trademark",
  1042. "manufacturer",
  1043. "designer",
  1044. "description",
  1045. "urlVendor",
  1046. "urlDesigner",
  1047. "licence",
  1048. "licenceURL",
  1049. "---",
  1050. "typoFamilyName",
  1051. "typoSubfamilyName",
  1052. "compatibleFull",
  1053. "sampleText",
  1054. "postScriptCID",
  1055. "wwsFamilyName",
  1056. "wwsSubfamilyName",
  1057. "lightPalette",
  1058. "darkPalette"
  1059. ];
  1060. var offset0 = offset;
  1061. var rU = bin.readUshort;
  1062. for(var i=0; i<count; i++)
  1063. {
  1064. var platformID = rU(data, offset); offset += 2;
  1065. var encodingID = rU(data, offset); offset += 2;
  1066. var languageID = rU(data, offset); offset += 2;
  1067. var nameID = rU(data, offset); offset += 2;
  1068. var slen = rU(data, offset); offset += 2;
  1069. var noffset = rU(data, offset); offset += 2;
  1070. //console.log(platformID, encodingID, languageID.toString(16), nameID, length, noffset);
  1071. var soff = offset0 + count*12 + noffset;
  1072. var str;
  1073. if(false){}
  1074. else if(platformID == 0) str = bin.readUnicode(data, soff, slen/2);
  1075. else if(platformID == 3 && encodingID == 0) str = bin.readUnicode(data, soff, slen/2);
  1076. else if(platformID == 1 && encodingID ==25) str = bin.readUnicode(data, soff, slen/2);
  1077. else if(encodingID == 0) str = bin.readASCII (data, soff, slen);
  1078. else if(encodingID == 1) str = bin.readUnicode(data, soff, slen/2);
  1079. else if(encodingID == 3) str = bin.readUnicode(data, soff, slen/2);
  1080. else if(encodingID == 4) str = bin.readUnicode(data, soff, slen/2);
  1081. else if(encodingID == 5) str = bin.readUnicode(data, soff, slen/2);
  1082. else if(encodingID ==10) str = bin.readUnicode(data, soff, slen/2);
  1083. else if(platformID == 1) { str = bin.readASCII(data, soff, slen); console.log("reading unknown MAC encoding "+encodingID+" as ASCII") }
  1084. else {
  1085. console.log("unknown encoding "+encodingID + ", platformID: "+platformID);
  1086. str = bin.readASCII(data, soff, slen);
  1087. }
  1088. var tid = "p"+platformID+","+(languageID).toString(16);//Typr._platforms[platformID];
  1089. if(obj[tid]==null) obj[tid] = {};
  1090. obj[tid][names[nameID]] = str;
  1091. obj[tid]["_lang"] = languageID;
  1092. //console.log(tid, obj[tid]);
  1093. }
  1094. /*
  1095. if(format == 1)
  1096. {
  1097. var langTagCount = bin.readUshort(data, offset); offset += 2;
  1098. for(var i=0; i<langTagCount; i++)
  1099. {
  1100. var length = bin.readUshort(data, offset); offset += 2;
  1101. var noffset = bin.readUshort(data, offset); offset += 2;
  1102. }
  1103. }
  1104. */
  1105. var out = Typr["T"].name.selectOne(obj), ff="fontFamily";
  1106. if(out[ff]==null) for(var p in obj) if(obj[p][ff]!=null) out[ff]=obj[p][ff];
  1107. return out;
  1108. },
  1109. selectOne :function(obj) {
  1110. //console.log(obj);
  1111. var psn = "postScriptName";
  1112. for(var p in obj) if(obj[p][psn]!=null && obj[p]["_lang"]==0x0409) return obj[p]; // United States
  1113. for(var p in obj) if(obj[p][psn]!=null && obj[p]["_lang"]==0x0000) return obj[p]; // Universal
  1114. for(var p in obj) if(obj[p][psn]!=null && obj[p]["_lang"]==0x0c0c) return obj[p]; // Canada
  1115. for(var p in obj) if(obj[p][psn]!=null) return obj[p];
  1116. var out;
  1117. for(var p in obj) { out=obj[p]; break; }
  1118. console.log("returning name table with languageID "+ out._lang);
  1119. if(out[psn]==null && out["ID"]!=null) out[psn]=out["ID"];
  1120. return out;
  1121. }
  1122. }
  1123. Typr["T"].OS2 = {
  1124. parseTab : function(data, offset, length)
  1125. {
  1126. var bin = Typr["B"];
  1127. var ver = bin.readUshort(data, offset); offset += 2;
  1128. var OS2 = Typr["T"].OS2;
  1129. var obj = {};
  1130. if (ver==0) OS2.version0(data, offset, obj);
  1131. else if(ver==1) OS2.version1(data, offset, obj);
  1132. else if(ver==2 || ver==3 || ver==4) OS2.version2(data, offset, obj);
  1133. else if(ver==5) OS2.version5(data, offset, obj);
  1134. else throw "unknown OS/2 table version: "+ver;
  1135. return obj;
  1136. },
  1137. version0 : function(data, offset, obj)
  1138. {
  1139. var bin = Typr["B"];
  1140. obj["xAvgCharWidth"] = bin.readShort(data, offset); offset += 2;
  1141. obj["usWeightClass"] = bin.readUshort(data, offset); offset += 2;
  1142. obj["usWidthClass"] = bin.readUshort(data, offset); offset += 2;
  1143. obj["fsType"] = bin.readUshort(data, offset); offset += 2;
  1144. obj["ySubscriptXSize"] = bin.readShort(data, offset); offset += 2;
  1145. obj["ySubscriptYSize"] = bin.readShort(data, offset); offset += 2;
  1146. obj["ySubscriptXOffset"] = bin.readShort(data, offset); offset += 2;
  1147. obj["ySubscriptYOffset"] = bin.readShort(data, offset); offset += 2;
  1148. obj["ySuperscriptXSize"] = bin.readShort(data, offset); offset += 2;
  1149. obj["ySuperscriptYSize"] = bin.readShort(data, offset); offset += 2;
  1150. obj["ySuperscriptXOffset"] = bin.readShort(data, offset); offset += 2;
  1151. obj["ySuperscriptYOffset"] = bin.readShort(data, offset); offset += 2;
  1152. obj["yStrikeoutSize"] = bin.readShort(data, offset); offset += 2;
  1153. obj["yStrikeoutPosition"] = bin.readShort(data, offset); offset += 2;
  1154. obj["sFamilyClass"] = bin.readShort(data, offset); offset += 2;
  1155. obj["panose"] = bin.readBytes(data, offset, 10); offset += 10;
  1156. obj["ulUnicodeRange1"] = bin.readUint(data, offset); offset += 4;
  1157. obj["ulUnicodeRange2"] = bin.readUint(data, offset); offset += 4;
  1158. obj["ulUnicodeRange3"] = bin.readUint(data, offset); offset += 4;
  1159. obj["ulUnicodeRange4"] = bin.readUint(data, offset); offset += 4;
  1160. obj["achVendID"] = bin.readASCII(data, offset, 4); offset += 4;
  1161. obj["fsSelection"] = bin.readUshort(data, offset); offset += 2;
  1162. obj["usFirstCharIndex"] = bin.readUshort(data, offset); offset += 2;
  1163. obj["usLastCharIndex"] = bin.readUshort(data, offset); offset += 2;
  1164. obj["sTypoAscender"] = bin.readShort(data, offset); offset += 2;
  1165. obj["sTypoDescender"] = bin.readShort(data, offset); offset += 2;
  1166. obj["sTypoLineGap"] = bin.readShort(data, offset); offset += 2;
  1167. obj["usWinAscent"] = bin.readUshort(data, offset); offset += 2;
  1168. obj["usWinDescent"] = bin.readUshort(data, offset); offset += 2;
  1169. return offset;
  1170. },
  1171. version1 : function(data, offset, obj)
  1172. {
  1173. var bin = Typr["B"];
  1174. offset = Typr["T"].OS2.version0(data, offset, obj);
  1175. obj["ulCodePageRange1"] = bin.readUint(data, offset); offset += 4;
  1176. obj["ulCodePageRange2"] = bin.readUint(data, offset); offset += 4;
  1177. return offset;
  1178. },
  1179. version2 : function(data, offset, obj)
  1180. {
  1181. var bin = Typr["B"], rU=bin.readUshort;
  1182. offset = Typr["T"].OS2.version1(data, offset, obj);
  1183. obj["sxHeight"] = bin.readShort(data, offset); offset += 2;
  1184. obj["sCapHeight"] = bin.readShort(data, offset); offset += 2;
  1185. obj["usDefault"] = rU(data, offset); offset += 2;
  1186. obj["usBreak"] = rU(data, offset); offset += 2;
  1187. obj["usMaxContext"] = rU(data, offset); offset += 2;
  1188. return offset;
  1189. },
  1190. version5 : function(data, offset, obj)
  1191. {
  1192. var rU = Typr["B"].readUshort;
  1193. offset = Typr["T"].OS2.version2(data, offset, obj);
  1194. obj["usLowerOpticalPointSize"] = rU(data, offset); offset += 2;
  1195. obj["usUpperOpticalPointSize"] = rU(data, offset); offset += 2;
  1196. return offset;
  1197. }
  1198. }
  1199. Typr["T"].post = {
  1200. parseTab : function(data, offset, length)
  1201. {
  1202. var bin = Typr["B"];
  1203. var obj = {};
  1204. obj["version"] = bin.readFixed(data, offset); offset+=4;
  1205. obj["italicAngle"] = bin.readFixed(data, offset); offset+=4;
  1206. obj["underlinePosition"] = bin.readShort(data, offset); offset+=2;
  1207. obj["underlineThickness"] = bin.readShort(data, offset); offset+=2;
  1208. return obj;
  1209. }
  1210. };
  1211. Typr["T"].SVG = {
  1212. parseTab : function(data, offset, length)
  1213. {
  1214. var bin = Typr["B"];
  1215. var obj = { entries: []};
  1216. var offset0 = offset;
  1217. var tableVersion = bin.readUshort(data, offset); offset += 2;
  1218. var svgDocIndexOffset = bin.readUint(data, offset); offset += 4;
  1219. var reserved = bin.readUint(data, offset); offset += 4;
  1220. offset = svgDocIndexOffset + offset0;
  1221. var numEntries = bin.readUshort(data, offset); offset += 2;
  1222. for(var i=0; i<numEntries; i++)
  1223. {
  1224. var startGlyphID = bin.readUshort(data, offset); offset += 2;
  1225. var endGlyphID = bin.readUshort(data, offset); offset += 2;
  1226. var svgDocOffset = bin.readUint (data, offset); offset += 4;
  1227. var svgDocLength = bin.readUint (data, offset); offset += 4;
  1228. var sbuf = new Uint8Array(data.buffer, offset0 + svgDocOffset + svgDocIndexOffset, svgDocLength);
  1229. if(sbuf[0]==0x1f && sbuf[1]==0x8b && sbuf[2]==0x08) sbuf = pako["inflate"](sbuf);
  1230. var svg = bin.readUTF8(sbuf, 0, sbuf.length);
  1231. for(var f=startGlyphID; f<=endGlyphID; f++) {
  1232. obj.entries[f] = svg;
  1233. }
  1234. }
  1235. return obj;
  1236. }
  1237. };
  1238. Typr["T"].sbix = {
  1239. parseTab : function(data, offset, length, obj)
  1240. {
  1241. var numGlyphs = obj["maxp"]["numGlyphs"];
  1242. var ooff = offset;
  1243. var bin = Typr["B"];
  1244. //var ver = bin.readUshort(data,offset); offset+=2;
  1245. //var flg = bin.readUshort(data,offset); offset+=2;
  1246. var numStrikes = bin.readUint (data,offset+4);
  1247. var out = [];
  1248. for(var si=numStrikes-1; si<numStrikes; si++) {
  1249. var off = ooff+bin.readUint(data,offset+8+si*4);
  1250. //var ppem = bin.readUshort(data,off); off+=2;
  1251. //var ppi = bin.readUshort(data,off); off+=2;
  1252. for(var gi=0; gi<numGlyphs; gi++) {
  1253. var aoff = bin.readUint(data,off+4+gi*4);
  1254. var noff = bin.readUint(data,off+4+gi*4+4); if(aoff==noff) { out[gi]=null; continue; }
  1255. var go = off+aoff;
  1256. //var ooX = bin.readUshort(data,go);
  1257. //var ooY = bin.readUshort(data,go+2);
  1258. var tag = bin.readASCII(data,go+4,4); if(tag!="png ") throw tag;
  1259. out[gi] = new Uint8Array(data.buffer, data.byteOffset+go+8, noff-aoff-8);
  1260. }
  1261. }
  1262. return out;
  1263. }
  1264. };
  1265. Typr["T"].colr = {
  1266. parseTab : function(data, offset, length)
  1267. {
  1268. var bin = Typr["B"];
  1269. var ooff=offset;
  1270. offset+=2;
  1271. var num = bin.readUshort(data,offset); offset+=2;
  1272. var boff = bin.readUint(data,offset); offset+=4;
  1273. var loff = bin.readUint(data,offset); offset+=4;
  1274. var lnum = bin.readUshort(data,offset); offset+=2;
  1275. //console.log(num,boff,loff,lnum);
  1276. var base = {};
  1277. var coff = ooff+boff;
  1278. for(var i=0; i<num; i++) {
  1279. base["g"+bin.readUshort(data,coff)] = [ bin.readUshort(data,coff+2),bin.readUshort(data,coff+4)];
  1280. coff+=6;
  1281. }
  1282. var lays = [];
  1283. coff = ooff+loff;
  1284. for(var i=0; i<lnum; i++) {
  1285. lays.push(bin.readUshort(data,coff), bin.readUshort(data,coff+2)); coff+=4;
  1286. }
  1287. return [base,lays];
  1288. }
  1289. };
  1290. Typr["T"].cpal = {
  1291. parseTab : function(data, offset, length)
  1292. {
  1293. var bin = Typr["B"];
  1294. var ooff=offset;
  1295. var vsn = bin.readUshort(data,offset); offset+=2;
  1296. if(vsn==0) {
  1297. var ets = bin.readUshort(data,offset); offset+=2;
  1298. var pts = bin.readUshort(data,offset); offset+=2;
  1299. var tot = bin.readUshort(data,offset); offset+=2;
  1300. var fst = bin.readUint(data,offset); offset+=4;
  1301. return new Uint8Array(data.buffer,ooff+fst,tot*4);
  1302. /*
  1303. var coff=ooff+fst;
  1304. for(var i=0; i<tot; i++) {
  1305. console.log(data[coff],data[coff+1],data[coff+2],data[coff+3]);
  1306. coff+=4;
  1307. }
  1308. console.log(ets,pts,tot); */
  1309. }
  1310. else throw vsn;//console.log("unknown color palette",vsn);
  1311. }
  1312. };