var Typr = {}; Typr["parse"] = function(buff) { var readFont = function(data, idx, offset,tmap) { var bin = Typr["B"]; var T = Typr["T"]; var prsr = { "cmap":T.cmap, "head":T.head, "hhea":T.hhea, "maxp":T.maxp, "hmtx":T.hmtx, "name":T.name, "OS/2":T.OS2, "post":T.post, "loca":T.loca, "kern":T.kern, "glyf":T.glyf, "CFF ":T.CFF, /* "GPOS", "GSUB", "GDEF",*/ "CBLC":T.CBLC, "CBDT":T.CBDT, "SVG ":T.SVG, "COLR":T.colr, "CPAL":T.cpal, "sbix":T.sbix //"VORG", }; var obj = {"_data":data, "_index":idx, "_offset":offset}; for(var t in prsr) { var tab = Typr["findTable"](data, t, offset); if(tab) { var off=tab[0], tobj = tmap[off]; if(tobj==null) tobj = prsr[t].parseTab(data, off, tab[1], obj); obj[t] = tmap[off] = tobj; } } return obj; } var bin = Typr["B"]; var data = new Uint8Array(buff); var tmap = {}; var tag = bin.readASCII(data, 0, 4); if(tag=="ttcf") { var offset = 4; var majV = bin.readUshort(data, offset); offset+=2; var minV = bin.readUshort(data, offset); offset+=2; var numF = bin.readUint (data, offset); offset+=4; var fnts = []; for(var i=0; i=buff.length) throw "error"; var a = Typr["B"].t.uint8; a[0] = buff[p+3]; a[1] = buff[p+2]; a[2] = buff[p+1]; a[3] = buff[p]; return Typr["B"].t.int32[0]; }, readInt8 : function(buff, p) { //if(p>=buff.length) throw "error"; var a = Typr["B"].t.uint8; a[0] = buff[p]; return Typr["B"].t.int8[0]; }, readShort : function(buff, p) { //if(p>=buff.length) throw "error"; var a = Typr["B"].t.uint16; a[0] = (buff[p]<<8) | buff[p+1]; return Typr["B"].t.int16[0]; }, readUshort : function(buff, p) { //if(p>=buff.length) throw "error"; return (buff[p]<<8) | buff[p+1]; }, writeUshort : function(buff, p, n) { buff[p] = (n>>8)&255; buff[p+1] = n&255; }, readUshorts : function(buff, p, len) { var arr = []; for(var i=0; i=buff.length) throw "error"; var a = Typr["B"].t.uint8; a[3] = buff[p]; a[2] = buff[p+1]; a[1] = buff[p+2]; a[0] = buff[p+3]; return Typr["B"].t.uint32[0]; }, writeUint: function(buff, p, n) { buff[p] = (n>>24)&255; buff[p+1] = (n>>16)&255; buff[p+2] = (n>>8)&255; buff[p+3] = (n>>0)&255; }, readUint64 : function(buff, p) { //if(p>=buff.length) throw "error"; return (Typr["B"].readUint(buff, p)*(0xffffffff+1)) + Typr["B"].readUint(buff, p+4); }, readASCII : function(buff, p, l) // l : length in Characters (not Bytes) { //if(p>=buff.length) throw "error"; var s = ""; for(var i = 0; i < l; i++) s += String.fromCharCode(buff[p+i]); return s; }, writeASCII : function(buff, p, s) // l : length in Characters (not Bytes) { for(var i = 0; i < s.length; i++) buff[p+i] = s.charCodeAt(i); }, readUnicode : function(buff, p, l) { //if(p>=buff.length) throw "error"; var s = ""; for(var i = 0; i < l; i++) { var c = (buff[p++]<<8) | buff[p++]; s += String.fromCharCode(c); } return s; }, _tdec : window["TextDecoder"] ? new window["TextDecoder"]() : null, readUTF8 : function(buff, p, l) { var tdec = Typr["B"]._tdec; if(tdec && p==0 && l==buff.length) return tdec["decode"](buff); return Typr["B"].readASCII(buff,p,l); }, readBytes : function(buff, p, l) { //if(p>=buff.length) throw "error"; var arr = []; for(var i=0; i=buff.length) throw "error"; var s = []; for(var i = 0; i < l; i++) s.push(String.fromCharCode(buff[p+i])); return s; }, t : function() { var ab = new ArrayBuffer(8); return { buff : ab, int8 : new Int8Array (ab), uint8 : new Uint8Array (ab), int16 : new Int16Array (ab), uint16 : new Uint16Array(ab), int32 : new Int32Array (ab), uint32 : new Uint32Array(ab) } }() }; Typr["T"].CFF = { parseTab : function(data, offset, length) { var bin = Typr["B"]; var CFF = Typr["T"].CFF; data = new Uint8Array(data.buffer, offset, length); offset = 0; // Header var major = data[offset]; offset++; var minor = data[offset]; offset++; var hdrSize = data[offset]; offset++; var offsize = data[offset]; offset++; //console.log(major, minor, hdrSize, offsize); // Name INDEX var ninds = []; offset = CFF.readIndex(data, offset, ninds); var names = []; for(var i=0; i 255 ) return -1; return Typr["T"].CFF.glyphByUnicode(cff, Typr["T"].CFF.tableSE[charcode]); }, /*readEncoding : function(data, offset, num) { var bin = Typr["B"]; var array = ['.notdef']; var format = data[offset]; offset++; //console.log("Encoding"); //console.log(format); if(format==0) { var nCodes = data[offset]; offset++; for(var i=0; i>4, nib1 = b&0xf; if(nib0 != 0xf) nibs.push(nib0); if(nib1!=0xf) nibs.push(nib1); if(nib1==0xf) break; } var s = ""; var chars = [0,1,2,3,4,5,6,7,8,9,".","e","e-","reserved","-","endOfNumber"]; for(var i=0; i>>1; obj.searchRange = rU(data, offset); offset+=2; obj.entrySelector = rU(data, offset); offset+=2; obj.rangeShift = rU(data, offset); offset+=2; obj.endCount = rUs(data, offset, segCount); offset += segCount*2; offset+=2; obj.startCount = rUs(data, offset, segCount); offset += segCount*2; obj.idDelta = []; for(var i=0; i>>1); //offset += segCount*2; return obj; }, parse6 : function(data, offset, obj) { var bin = Typr["B"]; var offset0 = offset; offset+=2; var length = bin.readUshort(data, offset); offset+=2; var language = bin.readUshort(data, offset); offset+=2; obj.firstCode = bin.readUshort(data, offset); offset+=2; var entryCount = bin.readUshort(data, offset); offset+=2; obj.glyphIdArray = []; for(var i=0; i=gl.xMax || gl.yMin>=gl.yMax) return null; if(gl.noc>0) { gl.endPts = []; for(var i=0; i>>8; /* I have seen format 128 once, that's why I do */ format &= 0xf; if(format==0) offset = kern.readFormat0(data, offset, map); //else throw "unknown kern table format: "+format; } return map; }, parseV1 : function(data, offset, length, font) { var bin = Typr["B"], kern=Typr["T"].kern; var version = bin.readFixed(data, offset); // 0x00010000 var nTables = bin.readUint (data, offset+4); offset+=8; var map = {glyph1: [], rval:[]}; for(var i=0; i