diff --git a/Common/FontsFreeType/Private/FreeType/base.js b/Common/FontsFreeType/Private/FreeType/base.js new file mode 100644 index 0000000000000000000000000000000000000000..0623129f2c2d678d1425524d578a6564e5d053aa --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/base.js @@ -0,0 +1,3553 @@ +/******************************************************************************/ +// stream +/******************************************************************************/ +function FT_Frame_Field(v,s,o) +{ + this.value = v; + this.size = s; + this.offset = o; +} +function FT_Stream(data, size) +{ + this.obj = null; + this.data = data; + this.size = size; + this.pos = 0; + this.cur = 0; + + this.Seek = function(_pos) + { + if (_pos > this.size) + return FT_Common.FT_Err_Invalid_Stream_Operation; + this.pos = _pos; + return FT_Common.FT_Err_Ok; + } + this.Skip = function(_skip) + { + if (_skip < 0) + return FT_Common.FT_Err_Invalid_Stream_Operation; + return this.Seek(this.pos + _skip); + } + this.Read = function(pointer, count) + { + return this.ReadAt(this.pos, pointer, count); + } + this.ReadArray = function(count) + { + var read_bytes = this.size - this.pos; + if (read_bytes > count) + read_bytes = count; + if (0 == read_bytes) + return null; + var a = new Array(read_bytes); + for (var i = 0;i<count;i++) + a[i] = this.data[this.pos+i]; + return a; + } + this.ReadAt = function(_pos, pointer, count) + { + if (_pos > this.size) + return FT_Common.FT_Err_Invalid_Stream_Operation; + var read_bytes = this.size - _pos; + if (read_bytes > count) + read_bytes = count; + + FT_Common.memcpy_p2(pointer,this.data,_pos,count); + + this.pos = _pos + read_bytes; + + if (read_bytes < count) + return FT_Common.FT_Err_Invalid_Stream_Operation; + + return FT_Common.FT_Err_Ok; + } + this.TryRead = function(pointer, count) + { + var read_bytes = 0; + if (this.pos < this.size) + return read_bytes; + read_bytes = this.size - this.pos; + if (read_bytes > count) + read_bytes = count; + + FT_Common.memcpy_p2(pointer,this.data,this.pos,count); + + this.pos += read_bytes; + return read_bytes; + } + + // 1 bytes + this.GetUChar = function() + { + if (this.cur >= this.size) + return 0; + return this.data[this.cur++]; + } + this.GetChar = function() + { + if (this.cur >= this.size) + return 0; + var m = this.data[this.cur++]; + if (m > FT_Common.m_c) + m -= FT_Common.a_c; + return m; + } + this.GetString1 = function(len) + { + if (this.cur + len > this.size) + return ""; + var t = ""; + for (var i = 0; i < len; i++) + t += String.fromCharCode(this.data[this.cur + i]); + this.cur += len; + return t; + } + this.ReadString1 = function(len) + { + if (this.pos + len > this.size) + return ""; + var t = ""; + for (var i = 0; i < len; i++) + t += String.fromCharCode(this.data[this.pos + i]); + this.pos += len; + return t; + } + + this.ReadUChar = function() + { + if (this.pos >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + return this.data[this.pos++]; + } + this.ReadChar = function() + { + if (this.pos >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + var m = this.data[this.pos++]; + if (m > FT_Common.m_c) + m -= FT_Common.a_c; + return m; + } + + // 2 byte + this.GetUShort = function() + { + if (this.cur + 1 >= this.size) + return 0; + return (this.data[this.cur++] << 8 | this.data[this.cur++]); + } + this.GetShort = function() + { + return FT_Common.UShort_To_Short(this.GetUShort()); + } + this.ReadUShort = function() + { + if (this.pos + 1 >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + return (this.data[this.pos++] << 8 | this.data[this.pos++]); + } + this.ReadShort = function() + { + return FT_Common.UShort_To_Short(this.ReadUShort()); + } + this.GetUShortLE = function() + { + if (this.cur + 1 >= this.size) + return 0; + return (this.data[this.cur++] | this.data[this.cur++] << 8); + } + this.GetShortLE = function() + { + return FT_Common.UShort_To_Short(this.GetUShortLE()); + } + this.ReadUShortLE = function() + { + if (this.pos + 1 >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + return (this.data[this.pos++] | this.data[this.pos++] << 8); + } + this.ReadShortLE = function() + { + return FT_Common.UShort_To_Short(this.ReadUShortLE()); + } + + // 4 byte + this.GetULong = function() + { + if (this.cur + 3 >= this.size) + return 0; + //return (this.data[this.cur++] << 24 | this.data[this.cur++] << 16 | this.data[this.cur++] << 8 | this.data[this.cur++]); + var s = (this.data[this.cur++] << 24 | this.data[this.cur++] << 16 | this.data[this.cur++] << 8 | this.data[this.cur++]); + if (s < 0) + s += FT_Common.a_i; + return s; + } + this.GetLong = function() + { + // 32-битные чиÑла - по умолчанию знаковые!!! + //return FT_Common.UintToInt(this.GetULong()); + return (this.data[this.cur++] << 24 | this.data[this.cur++] << 16 | this.data[this.cur++] << 8 | this.data[this.cur++]); + } + this.ReadULong = function() + { + if (this.pos + 3 >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + var s = (this.data[this.pos++] << 24 | this.data[this.pos++] << 16 | this.data[this.pos++] << 8 | this.data[this.pos++]); + if (s < 0) + s += FT_Common.a_i; + return s; + } + this.ReadLong = function() + { + // 32-битные чиÑла - по умолчанию знаковые!!! + //return FT_Common.Uint_To_int(this.ReadULong()); + if (this.pos + 3 >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + return (this.data[this.pos++] << 24 | this.data[this.pos++] << 16 | this.data[this.pos++] << 8 | this.data[this.pos++]); + } + + this.GetULongLE = function() + { + if (this.cur + 3 >= this.size) + return 0; + return (this.data[this.cur++] | this.data[this.cur++] << 8 | this.data[this.cur++] << 16 | this.data[this.cur++] << 24); + } + this.GetLongLE = function() + { + return FT_Common.Uint_To_int(this.GetULongLE()); + } + this.ReadULongLE = function() + { + if (this.pos + 3 >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + return (this.data[this.pos++] | this.data[this.pos++] << 8 | this.data[this.pos++] << 16 | this.data[this.pos++] << 24); + } + this.ReadLongLE = function() + { + return FT_Common.Uint_To_int(this.ReadULongLE()); + } + + // 3 byte + this.GetUOffset = function() + { + if (this.cur + 2 >= this.size) + return 0; + return (this.data[this.cur++] << 16 | this.data[this.cur++] << 8 | this.data[this.cur++]); + } + this.GetUOffsetLE = function() + { + if (this.cur + 2 >= this.size) + return 0; + return (this.data[this.cur++] | this.data[this.cur++] << 8 | this.data[this.cur++] << 16); + } + this.ReadUOffset = function() + { + if (this.pos + 2 >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + return (this.data[this.pos++] << 16 | this.data[this.pos++] << 8 | this.data[this.pos++]); + } + this.ReadUOffsetLE = function() + { + if (this.pos + 2 >= this.size) + { + FT_Error = FT_Common.FT_Err_Invalid_Stream_Operation; + return 0; + } + FT_Error = FT_Common.FT_Err_Ok; + return (this.data[this.pos++] | this.data[this.pos++] << 8 | this.data[this.pos++] << 16); + } + this.EnterFrame = function(count) + { + if (this.pos >= this.size || this.size - this.pos < count) + return FT_Common.FT_Err_Invalid_Stream_Operation; + + this.cur = this.pos; + this.pos += count; + return FT_Common.FT_Err_Ok; + } + this.ExtractFrame = function(count, pointer) + { + if (null == pointer) + pointer = new CPointer(); + + var err = this.EnterFrame(count); + if (err != FT_Common.FT_Err_Ok) + return err; + + pointer.data = this.data; + pointer.pos = this.cur; + + this.cur = 0; + return err; + } + this.ReleaseFrame = function() + { + } + this.ExitFrame = function() + { + this.cur = 0; + } + + this.ReadFields = function(arrayFields, structure) + { + // arrayFields : array {value, size, offset} + // structures : data pointer + var error = FT_Common.FT_Err_Ok; + var cursor = this.cur; + var frame_accessed = false; + + var data = null; + var pos = 0; + + var ind = 0; + do + { + var value; + var sign_shift; + + switch (arrayFields[ind].value) + { + case 4: /* access a new frame */ + error = this.EnterFrame(arrayFields[ind].offset); + if (error != FT_Common.FT_Err_Ok) + { + if (frame_accessed === true) + this.ExitFrame(); + return error; + } + + frame_accessed = true; + cursor = this.cur; + ind++; + continue; /* loop! */ + + case 24: /* read a byte sequence */ + case 25: /* skip some bytes */ + { + var len = arrayFields[ind].size; + if ( cursor + len > this.size ) + { + error = FT_Common.FT_Err_Invalid_Stream_Operation; + if (frame_accessed === true) + this.ExitFrame(); + return error; + } + + if ( arrayFields[ind] == 24 ) + { + data = structure.data; + pos = structure.pos + arrayFields[ind].offset; + + for (var i=0;i<len;i++) + data[i] = this.data[cursor+i]; + } + cursor += len; + ind++; + continue; + } + + case 8: + case 9: /* read a single byte */ + value = this.data[cursor++]; + sign_shift = 24; + break; + + case 13: + case 12: /* read a 2-byte big-endian short */ + value = this.data[cursor++] << 8 | this.data[cursor++]; + sign_shift = 16; + break; + + case 15: + case 14: /* read a 2-byte little-endian short */ + value = this.data[cursor++] | this.data[cursor++] << 8; + sign_shift = 16; + break; + + case 17: + case 16: /* read a 4-byte big-endian long */ + value = this.data[cursor++] << 24 | this.data[cursor++] << 16 | this.data[cursor++] << 8 | this.data[cursor++]; + sign_shift = 0; + break; + + case 19: + case 18: /* read a 4-byte little-endian long */ + value = this.data[cursor++] | this.data[cursor++] << 8 | this.data[cursor++] << 16 | this.data[cursor++] << 24; + sign_shift = 0; + break; + + case 21: + case 20: /* read a 3-byte big-endian long */ + value = this.data[cursor++] << 16 | this.data[cursor++] << 8 | this.data[cursor++]; + sign_shift = 8; + break; + + case 23: + case 22: /* read a 3-byte little-endian long */ + value = this.data[cursor++] | this.data[cursor++] << 8 | this.data[cursor++] << 16; + sign_shift = 8; + break; + + default: + /* otherwise, exit the loop */ + this.cur = cursor; + if (frame_accessed === true) + this.ExitFrame(); + return error; + } + + /* now, compute the signed value is necessary */ + if ( arrayFields[ind].value & 1 ) + value = (( value << sign_shift ) >>> sign_shift) & 0xFFFFFFFF; + + /* finally, store the value in the object */ + + data = structure.data; + pos = structure.pos + arrayFields[ind].offset; + switch (arrayFields[ind]) + { + case 1: + data[pos] = value & 0xFF; + break; + + case 2: + data[pos] = (value >>> 8)&0xFF; + data[pos+1] = value&0xFF; + break; + + case 4: + data[pos] = (value >>> 24)&0xFF; + data[pos+1] = (value >>> 16)&0xFF; + data[pos+2] = (value >>> 8)&0xFF; + data[pos+3] = value&0xFF; + break; + + default: + data[pos] = (value >>> 24)&0xFF; + data[pos+1] = (value >>> 16)&0xFF; + data[pos+2] = (value >>> 8)&0xFF; + data[pos+3] = value&0xFF; + } + + /* go to next field */ + ind++; + } + while ( 1 ); + + return error; + } + this.ReadFields2 = function(fields, structure) + { + // arrayFields : array {value, size, offset} + // structures : data pointer + var error = FT_Common.FT_Err_Ok; + var cursor = this.cur; + var frame_accessed = false; + + var data = null; + var pos = 0; + + var ind = 0; + do + { + var value; + var sign_shift; + + var fval = fields[ind]; + var fsize = fields[ind+1]; + var foffset = fields[ind+2]; + + switch (fval) + { + case 4: /* access a new frame */ + error = this.EnterFrame(foffset); + if (error != FT_Common.FT_Err_Ok) + { + if (frame_accessed === true) + this.ExitFrame(); + return error; + } + + frame_accessed = true; + cursor = this.cur; + ind+=3; + continue; /* loop! */ + + case 24: /* read a byte sequence */ + case 25: /* skip some bytes */ + { + if ( cursor + fsize > this.size ) + { + error = FT_Common.FT_Err_Invalid_Stream_Operation; + if (frame_accessed === true) + this.ExitFrame(); + return error; + } + + if ( fval == 24 ) + { + data = structure.data; + pos = structure.pos + arrayFields[ind].offset; + + for (var i=0;i<len;i++) + data[i] = this.data[cursor+i]; + } + cursor += fsize; + ind++; + continue; + } + + case 8: + case 9: /* read a single byte */ + value = this.data[cursor++]; + sign_shift = 24; + break; + + case 13: + case 12: /* read a 2-byte big-endian short */ + value = this.data[cursor++] << 8 | this.data[cursor++]; + sign_shift = 16; + break; + + case 15: + case 14: /* read a 2-byte little-endian short */ + value = this.data[cursor++] | this.data[cursor++] << 8; + sign_shift = 16; + break; + + case 17: + case 16: /* read a 4-byte big-endian long */ + value = this.data[cursor++] << 24 | this.data[cursor++] << 16 | this.data[cursor++] << 8 | this.data[cursor++]; + sign_shift = 0; + break; + + case 19: + case 18: /* read a 4-byte little-endian long */ + value = this.data[cursor++] | this.data[cursor++] << 8 | this.data[cursor++] << 16 | this.data[cursor++] << 24; + sign_shift = 0; + break; + + case 21: + case 20: /* read a 3-byte big-endian long */ + value = this.data[cursor++] << 16 | this.data[cursor++] << 8 | this.data[cursor++]; + sign_shift = 8; + break; + + case 23: + case 22: /* read a 3-byte little-endian long */ + value = this.data[cursor++] | this.data[cursor++] << 8 | this.data[cursor++] << 16; + sign_shift = 8; + break; + + default: + /* otherwise, exit the loop */ + this.cur = cursor; + if (frame_accessed === true) + this.ExitFrame(); + return error; + } + + /* now, compute the signed value is necessary */ + if (0 != (fval & 1)) + value = (( value << sign_shift ) >>> sign_shift) & 0xFFFFFFFF; + + /* finally, store the value in the object */ + + data = structure.data; + pos = structure.pos + arrayFields[ind].offset; + switch (arrayFields[ind]) + { + case 1: + data[pos] = value & 0xFF; + break; + + case 2: + data[pos] = (value >>> 8)&0xFF; + data[pos+1] = value&0xFF; + break; + + case 4: + data[pos] = (value >>> 24)&0xFF; + data[pos+1] = (value >>> 16)&0xFF; + data[pos+2] = (value >>> 8)&0xFF; + data[pos+3] = value&0xFF; + break; + + default: + data[pos] = (value >>> 24)&0xFF; + data[pos+1] = (value >>> 16)&0xFF; + data[pos+2] = (value >>> 8)&0xFF; + data[pos+3] = value&0xFF; + } + + /* go to next field */ + ind+=3; + } + while ( 1 ); + + return error; + } +} +/******************************************************************************/ +// memory +/******************************************************************************/ +function CPointer() +{ + this.obj = null; + this.data = null; + this.pos = 0; +} +function dublicate_pointer(p) +{ + if (null == p) + return null; + + var d = new CPointer(); + d.data = p.data; + d.pos = p.pos; + return d; +} +function copy_pointer(p, size) +{ + var _p = g_memory.Alloc(size); + for (var i = 0; i < size; i++) + _p.data[i] = p.data[p.pos + i]; + return _p; +} + +function FT_Memory() +{ + this.canvas = document.createElement('canvas'); + this.canvas.width = 1; + this.canvas.height = 1; + this.ctx = this.canvas.getContext('2d'); + + this.Alloc = function(size) + { + var p = new CPointer(); + p.obj = this.ctx.createImageData(1,parseInt((size + 3) / 4)); + p.data = p.obj.data; + p.pos = 0; + return p; + } + this.AllocHeap = function() + { + // TODO: нужно поÑмотреть, как Ñта памÑÑ‚ÑŒ будет иÑпользоватьÑÑ. + // нужно ли здеÑÑŒ делать Ñтек, либо вÑе Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ Ð½ÑƒÐ»Ñ Ð´ÐµÐ»Ð°Ñ‚ÑŒ?? + } + this.CreateStream = function(size) + { + var _size = parseInt((size + 3) / 4); + var obj = this.ctx.createImageData(1,_size); + return new FT_Stream(obj.data,_size); + } +} +var g_memory = new FT_Memory(); + +function FT_PEEK_CHAR(p) +{ + var r = p.data[p.pos]; + if (r > FT_Common.m_c) + return r-FT_Common.a_c; + return r; +} +function FT_NEXT_CHAR(p) +{ + var r = p.data[p.pos++]; + if (r > FT_Common.m_c) + return r - FT_Common.a_c; + return r; +} +function FT_PEEK_BYTE(p) +{ + return p.data[p.pos]; +} +function FT_NEXT_BYTE(p) +{ + var r = p.data[p.pos++]; + return r; +} +function FT_PEEK_SHORT(p) +{ + var r = (p.data[p.pos] << 8 | p.data[p.pos+1]); + if (r > FT_Common.m_s) + return r - FT_Common.a_s; + return r; +} +function FT_PEEK_SHORT_LE(p) +{ + var r = (p.data[p.pos+1] << 8 | p.data[p.pos]); + if (r > FT_Common.m_s) + return r - FT_Common.a_s; + return r; +} +function FT_NEXT_SHORT(p) +{ + var r = (p.data[p.pos++] << 8 | p.data[p.pos++]); + if (r > FT_Common.m_s) + return r - FT_Common.a_s; + return r; +} +function FT_PEEK_USHORT(p) +{ + var r = (p.data[p.pos] << 8 | p.data[p.pos+1]); + return r; +} +function FT_PEEK_USHORT_LE(p) +{ + var r = (p.data[p.pos + 1] << 8 | p.data[p.pos]); + return r; +} +function FT_NEXT_USHORT(p) +{ + var r = (p.data[p.pos++] << 8 | p.data[p.pos++]); + return r; +} +function FT_PEEK_UOFF3(p) +{ + var r = (p.data[p.pos] << 16 | p.data[p.pos+1] << 8 | p.data[p.pos+2]); + return r; +} +function FT_NEXT_UOFF3(p) +{ + var r = (p.data[p.pos++] << 16 | p.data[p.pos++] << 8 | p.data[p.pos++]); + return r; +} +function FT_PEEK_LONG(p) +{ + return (p.data[p.pos] << 24 | p.data[p.pos+1] << 16 | p.data[p.pos+2] << 8 | p.data[p.pos+3]); +} +function FT_NEXT_LONG(p) +{ + var r = (p.data[p.pos++] << 24 | p.data[p.pos++] << 16 | p.data[p.pos++] << 8 | p.data[p.pos++]); + return r; +} +function FT_PEEK_ULONG(p) +{ + var r = (p.data[p.pos] << 24 | p.data[p.pos+1] << 16 | p.data[p.pos+2] << 8 | p.data[p.pos+3]); + if (r<0) + r+=FT_Common.a_i; + return r; +} +function FT_PEEK_ULONG_LE(p) +{ + var r = (p.data[p.pos+3] << 24 | p.data[p.pos+2] << 16 | p.data[p.pos+1] << 8 | p.data[p.pos]); + if (r<0) + r+=FT_Common.a_i; + return r; +} +function FT_NEXT_ULONG(p) +{ + var r = (p.data[p.pos++] << 24 | p.data[p.pos++] << 16 | p.data[p.pos++] << 8 | p.data[p.pos++]); + if (r<0) + r+=FT_Common.a_i; + return r; +} +function FT_PEEK_String1(p,len) +{ + var t = ""; + for (var i = 0; i < len; i++) + { + var r = p.data[p.pos + i]; + if (r == 0) + return t; + t += String.fromCharCode(r); + } + return t; +} +function FT_NEXT_String1(p,len) +{ + var t = ""; + for (var i = 0; i < len; i++) + t += String.fromCharCode(p.data[p.pos + i]); + p.pos+=len; + return t; +} +function ft_memchr(p, v, size) +{ + for (var i=0;i<size;i++) + if (p.data[p.pos+i] == v) + return i; + return -1; +} +function _strncmp(s1,s2,n) +{ + var m1 = s1.length; + var m2 = s2.length; + var l = n; + if (m1 < l) + l = m1; + if (m2 < l) + l = m2; + + for (var i=0;i<l;i++) + { + var c = s1.charCodeAt(i) - s2.charCodeAt(i); + if (c != 0) + return c; + } + return m1 - m2; +} + +function _strcmp_data(s,p) +{ + var m = s.length; + + for (var i=0;i<m;i++) + { + var _c = p.data[p.pos + i]; + if (_c == FT_Common.SYMBOL_CONST_S0) + return 1; + + var c = s.charCodeAt(i) - _c; + if (c != 0) + return c; + } + + if (p.data[p.pos + m] == FT_Common.SYMBOL_CONST_S0) + return 0; + + return -1; +} + +function _strcmp(s1,s2) +{ + return (s1 == s2) ? 0 : 1; +} + +function _strncmp_data(p,s,n) +{ + var m2 = s.length; + var l = n; + if (m2 < l) + l = m2; + + var m1 = 0; + for (var i=0;i<l;i++) + { + m1++; + if (FT_Common.SYMBOL_CONST_S0 == p.data[p.pos + i]) + { + m1 = i; + break; + } + + var c = p.data[p.pos + i] - s.charCodeAt(i); + if (c != 0) + return c; + } + return m1 - m2; +} +function _strncmp2(s1,s2,n,start1,start2) +{ + var m1 = s1.length - start1; + var m2 = s2.length - start2; + var l = n; + if (m1 < l) + l = m1; + if (m2 < l) + l = m2; + + for (var i=0;i<l;i++) + { + var c = s1.charCodeAt(i + start1) - s2.charCodeAt(i + start2); + if (c != 0) + return c; + } + return m1 - m2; +} +function _mem_strcpyn1(dst, src, size) +{ + var i = 0; + var slen = src.length; + while (size > 1 && i < slen) + { + dst.data[dst.pos + i] = src.charCodeAt(i); + i++; + } + + dst.data[dst.pos + i] = 0; /* always zero-terminate */ + return i != slen; +} +/******************************************************************************/ +// calc +/******************************************************************************/ +function FT_LOAD_TARGET_MODE(x) +{ + return ((x >>> 16) & 15); +} +function FT_LOAD_TARGET(x) +{ + return ((x & 15) << 16); +} +function FT_PIX_FLOOR(x) +{ + return x & ~63; +} +function FT_PIX_ROUND(x) +{ + return (x + 32) & ~63; +} +function FT_PIX_CEIL(x) +{ + return (x + 63) & ~63; +} + +function FT_RoundFix(a) +{ + return (a >= 0) ? (a + 0x8000) & ~0xFFFF : -((-a + 0x8000) & ~0xFFFF); +} +function FT_CeilFix(a) +{ + return (a >= 0) ? (a + 0xFFFF) & ~0xFFFF : -((-a + 0xFFFF) & ~0xFFFF); +} +function FT_FloorFix(a) +{ + return (a >= 0) ? a & ~0xFFFF : -((-a) & ~0xFFFF); +} + +// int64 support +function _FT_MulDiv(a,b,c) +{ + var s = 1; + var d = 0; + + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + d = (c > 0 ? parseInt((a * b + (c >>> 1)) / c) : 0x7FFFFFFF); + return (s > 0) ? d : -d; +} +function _FT_MulFix(a,b) +{ + var s = 1; + if (a < 0) + { + a = -a; + s = -1; + } + if (b < 0) + { + b = -b; + s = -s; + } + + var c = ((a * b + 0x8000) >>> 16) & 0xFFFFFFFF; + return ( s > 0 ) ? c : -c; +} +function _FT_DivFix(a,b) +{ + var q; + var s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + + if (b == 0) + q = 0x7FFFFFFF; + else + { + q = parseInt(((a * 65536) + (b >>> 1)) / b); + if (q < 0) + q += FT_Common.a_i; + } + + return (s < 0 ? -q : q); +} + +function Int64() +{ + this.lo = 0; + this.hi = 0; +} +function ft_multo64(x, y, z) +{ + var lo1, hi1, lo2, hi2, lo, hi, i1, i2; + + lo1 = x & 0x0000FFFF; hi1 = x >>> 16; + lo2 = y & 0x0000FFFF; hi2 = y >>> 16; + + lo = lo1 * lo2; + i1 = lo1 * hi2; + i2 = lo2 * hi1; + hi = hi1 * hi2; + + + i1 += i2; + if (i1 < i2) + hi += (1 << 16); + + hi += i1 >>> 16; + i1 = (i1 << 16) & 0xFFFFFFFF; + if (i1 < 0) + i1 += FT_Common.a_i; + + + + lo += i1; + if (lo < i1) + hi++; + + z.lo = lo; + z.hi = hi; +} +function ft_div64by32(hi, lo, y) +{ + var q = 0; + var r = hi; + + if (r >= y) + return 2147483647; + + var i = 32; + do + { + r = (r << 1) & 0xFFFFFFFF; + q = (q << 1) & 0xFFFFFFFF; + if (q < 0) + q += FT_Common.a_i; + + r |= lo >>> 31; + if (r < 0) + r += FT_Common.a_i; + + if (r >= y) + { + r -= y; + q |= 1; + } + lo = (lo << 1) & 0xFFFFFFFF; + if (lo < 0) + lo += FT_Common.a_i; + } while ( --i ); + + return q; +} +function FT_Add64(x, y, z) +{ + var lo = x.lo + y.lo; + var hi = x.hi + y.hi; + if (lo < x.lo) + hi++; + + z.lo = lo; + z.hi = hi; +} +var temp1 = new Int64(); +var temp2 = new Int64(); +function FT_MulDiv(a, b, c) +{ + if (a > FT_Common.m_i || b > FT_Common.m_i || c > FT_Common.m_i) + alert("error"); + + if (a == 0 || b == c) + return a; + + var s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + if (a <= 46340 && b <= 46340 && c <= 176095 && c > 0) + a = ((a * b + (c >> 1)) / c) >> 0; + else if (c > 0) + { + ft_multo64(a >= 0 ? a : a + FT_Common.a_i, b >= 0 ? b : b + FT_Common.a_i, temp1); + + temp2.hi = 0; + temp2.lo = (c >>> 1); + FT_Add64(temp1, temp2, temp1); + a = ft_div64by32(temp1.hi, temp1.lo, c); + } + else + a = 0x7FFFFFFF; + + return (s < 0 ? -a : a); +} +function FT_MulFix(a, b) +{ + if (a > FT_Common.m_i || b > FT_Common.m_i) + { + //alert("error"); + a &= 0xFFFFFFFF; + b &= 0xFFFFFFFF; + } + + if (a == 0 || b == 0x10000) + return a; + + var s = a; a = Math.abs(a); + s ^= b; b = Math.abs(b); + + var ua = a < 0 ? a + FT_Common.a_i : a; + var ub = b < 0 ? b + FT_Common.a_i : b; + + if (ua <= 2048 && ub <= 1048576) + ua = (ua * ub + 0x8000) >>> 16; + else + { + var al = ua & 0xFFFF; + + ua = ((ua >>> 16) * ub) + (al * (ub >>> 16)) + ((al * (ub & 0xFFFF) + 0x8000) >>> 16); + } + var _l = FT_Common.UintToInt(ua); + return (s < 0 ? -_l : _l); +} +function FT_DivFix(a, b) +{ + if (a > FT_Common.m_i || b > FT_Common.m_i) + { + a = (a & 0xFFFFFFFF); + b = (b & 0xFFFFFFFF); + } + + var q = 0; + + var s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + + if (b == 0) + { + q = 0x7FFFFFFF; + } + else if ((a >> 16) == 0) + { + q = parseInt((a * 65536 + parseInt(b / 2)) / b); + //q = parseInt((((a << 16) & 0xFFFFFFFF) + (b >> 1)) / b); + if (q < 0) + q += FT_Common.a_i; + } + else + { + temp1.hi = (a >> 16); + temp1.lo = (a << 16) & 0xFFFFFFFF; + if (temp1.lo < 0) + temp1.lo += FT_Common.a_i; + + temp2.hi = 0; + temp2.lo = (b >> 1); + + if (temp2.lo < 0) + temp2.lo += FT_Common.a_i; + + FT_Add64(temp1, temp2, temp1); + q = ft_div64by32(temp1.hi, temp1.lo, b < 0 ? b + FT_Common.a_i : b); + } + + var _q = (q > FT_Common.m_i) ? q - FT_Common.a_i : q; + return (s < 0) ? -_q : _q; +} + +function FT_Sqrt32(x) +{ + var val, root, newroot, mask; + + root = 0; + mask = 0x40000000; + val = x; + + do + { + newroot = root + mask; + if ( newroot <= val ) + { + val -= newroot; + root = newroot + mask; + } + + root >>>= 1; + mask >>>= 2; + + } while ( mask != 0 ); + + return root; +} + +function FT_Matrix_Multiply(a, b) +{ + var xx, xy, yx, yy; + + if ( !a || !b ) + return; + + xx = FT_MulFix(a.xx, b.xx) + FT_MulFix(a.xy, b.yx); + xy = FT_MulFix(a.xx, b.xy) + FT_MulFix(a.xy, b.yy); + yx = FT_MulFix(a.yx, b.xx) + FT_MulFix(a.yy, b.yx); + yy = FT_MulFix(a.yx, b.xy) + FT_MulFix(a.yy, b.yy); + + b.xx = xx; b.xy = xy; + b.yx = yx; b.yy = yy; +} + +function FT_Matrix_Invert(matrix) +{ + var delta, xx, yy; + + if (!matrix) + return FT_Common.FT_Err_Invalid_Argument; + + delta = FT_MulFix(matrix.xx, matrix.yy) - FT_MulFix(matrix.xy, matrix.yx); + if ( !delta ) + return FT_Common.FT_Err_Invalid_Argument; + + matrix.xy = -FT_DivFix(matrix.xy, delta); + matrix.yx = -FT_DivFix(matrix.yx, delta); + + xx = matrix.xx; + yy = matrix.yy; + + matrix.xx = FT_DivFix(yy, delta); + matrix.yy = FT_DivFix(xx, delta); + + return 0; +} + +function FT_Matrix_Multiply_Scaled(a, b, scaling) +{ + var xx, xy, yx, yy; + var val = 0x10000 * scaling; + if ( !a || !b ) + return; + + xx = FT_MulDiv(a.xx, b.xx, val) + FT_MulDiv(a.xy, b.yx, val); + xy = FT_MulDiv(a.xx, b.xy, val) + FT_MulDiv(a.xy, b.yy, val); + yx = FT_MulDiv(a.yx, b.xx, val) + FT_MulDiv(a.yy, b.yx, val); + yy = FT_MulDiv(a.yx, b.xy, val) + FT_MulDiv(a.yy, b.yy, val); + + b.xx = xx; b.xy = xy; + b.yx = yx; b.yy = yy; +} + +function FT_Vector_Transform_Scaled(vector, matrix, scaling) +{ + var xz, yz; + var val = 0x10000 * scaling; + if (!vector || !matrix) + return; + + xz = FT_MulDiv(vector.x, matrix.xx, val) + FT_MulDiv(vector.y, matrix.xy, val); + yz = FT_MulDiv(vector.x, matrix.yx, val) + FT_MulDiv(vector.y, matrix.yy, val); + + vector.x = xz; + vector.y = yz; +} + +function FT_SqrtFixed(x) +{ + var root, rem_hi, rem_lo, test_div; + var count; + + root = 0; + if (x > 0) + { + rem_hi = 0; + rem_lo = x; + count = 24; + do + { + rem_hi = (rem_hi << 2) | (rem_lo >>> 30); + rem_lo <<= 2; + root <<= 1; + test_div = (root << 1) + 1; + + if (rem_hi >= test_div) + { + rem_hi -= test_div; + root += 1; + } + } while (--count); + } + + return root; +} + +function ft_corner_orientation(in_x, in_y, out_x, out_y) +{ + var result; + if ( in_y == 0 ) + { + if ( in_x >= 0 ) + result = out_y; + else + result = -out_y; + } + else if ( in_x == 0 ) + { + if ( in_y >= 0 ) + result = -out_x; + else + result = out_x; + } + else if ( out_y == 0 ) + { + if ( out_x >= 0 ) + result = in_y; + else + result = -in_y; + } + else if ( out_x == 0 ) + { + if ( out_y >= 0 ) + result = -in_x; + else + result = in_x; + } + else + { + var delta = in_x * out_y - in_y * out_x; + + if ( delta == 0 ) + result = 0; + else + result = 1 - 2 * ( delta < 0 ); + } + + return result; +} + +function ft_corner_is_flat(in_x, in_y, out_x, out_y) +{ + var ax = in_x; + var ay = in_y; + + var d_in, d_out, d_corner; + + if ( ax < 0 ) + ax = -ax; + if ( ay < 0 ) + ay = -ay; + d_in = ax + ay; + + ax = out_x; + if ( ax < 0 ) + ax = -ax; + ay = out_y; + if ( ay < 0 ) + ay = -ay; + d_out = ax + ay; + + ax = out_x + in_x; + if ( ax < 0 ) + ax = -ax; + ay = out_y + in_y; + if ( ay < 0 ) + ay = -ay; + d_corner = ax + ay; + + return (( d_in + d_out - d_corner ) < ( d_corner >>> 4 )) ? 1 : 0; +} +/******************************************************************************/ +// glyph +/******************************************************************************/ +// bitmap +function ft_bitmap_glyph_init(glyph, slot) +{ + var library = glyph.library; + + if (slot.format != FT_Common.FT_GLYPH_FORMAT_BITMAP) + return FT_Common.FT_Err_Invalid_Glyph_Format; + + glyph.left = slot.bitmap_left; + glyph.top = slot.bitmap_top; + + if ((slot.internal.flags & FT_Common.FT_GLYPH_OWN_BITMAP) != 0) + { + var d = glyph.bitmap; + var s = slot.bitmap; + + d.rows = s.rows; + d.width = s.width; + d.pitch = s.pitch; + d.buffer = dublicate_pointer(s.buffer); + d.num_grays = s.num_grays; + d.pixel_mode = s.pixel_mode; + d.palette_mode = s.palette_mode; + d.palette = s.palette; + + slot.internal.flags &= ~FT_Common.FT_GLYPH_OWN_BITMAP; + } + else + { + FT_Bitmap_New(glyph.bitmap); + return FT_Bitmap_Copy(library, slot.bitmap, glyph.bitmap); + } + return 0; +} +function ft_bitmap_glyph_copy(source, target) +{ + target.left = source.left; + target.top = source.top; + return FT_Bitmap_Copy(source.library, source.bitmap, target.bitmap); +} +function ft_bitmap_glyph_done(bitmap_glyph) +{ + FT_Bitmap_Done(bitmap_glyph.library, bitmap_glyph.bitmap); +} +function ft_bitmap_glyph_bbox(glyph, cbox) +{ + cbox.xMin = glyph.left << 6; + cbox.xMax = cbox.xMin + (glyph.bitmap.width << 6); + cbox.yMax = glyph.top << 6; + cbox.yMin = cbox.yMax - (glyph.bitmap.rows << 6); +} + +// outline +function ft_outline_glyph_init(glyph, slot) +{ + var source = slot.outline; + var target = glyph.outline; + + + /* check format in glyph slot */ + if (slot.format != FT_Common.FT_GLYPH_FORMAT_OUTLINE) + return FT_Common.FT_Err_Invalid_Glyph_Format; + + var error = FT_Outline_New(glyph.library, source.n_points, source.n_contours, glyph.outline); + if (error != 0) + return error; + + FT_Outline_Copy(source, target); + return error; +} +function ft_outline_glyph_done(glyph) +{ + FT_Outline_Done(glyph.library, glyph.outline); +} +function ft_outline_glyph_copy(source, target) +{ + var library = source.library; + var error = FT_Outline_New(library, source.outline.n_points, source.outline.n_contours, target.outline); + if (error != 0) + FT_Outline_Copy(source.outline, target.outline); + + return error; +} +function ft_outline_glyph_transform(glyph, matrix, delta) +{ + if (matrix != null) + FT_Outline_Transform(glyph.outline, matrix); + + if (delta != null) + FT_Outline_Translate(glyph.outline, delta.x, delta.y); +} +function ft_outline_glyph_bbox(glyph, bbox) +{ + FT_Outline_Get_CBox(glyph.outline, bbox); +} +function ft_outline_glyph_prepare(glyph, slot) +{ + slot.format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + + var d = slot.outline; + var s = glyph.outline; + + d.n_contours = s.n_contours; + d.n_points = s.n_points; + d.points = s.points; + d.tags = s.tags; + d.contours = s.contours; + d.flags = s.flags; + + slot.outline.flags &= ~FT_Common.FT_OUTLINE_OWNER; + return 0; +} + +function _ft_bitmap_glyph_class() +{ + this.glyph_size = 0; // glyph_type + this.glyph_format = FT_Common.FT_GLYPH_FORMAT_BITMAP; + this.glyph_init = ft_bitmap_glyph_init; + this.glyph_done = ft_bitmap_glyph_done; + this.glyph_copy = ft_bitmap_glyph_copy; + this.glyph_transform = null; + this.glyph_bbox = ft_bitmap_glyph_bbox; + this.glyph_prepare = null; +} +var ft_bitmap_glyph_class = new _ft_bitmap_glyph_class(); +function _ft_outline_glyph_class() +{ + this.glyph_size = 1; // glyph_type + this.glyph_format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + this.glyph_init = ft_outline_glyph_init; + this.glyph_done = ft_outline_glyph_done; + this.glyph_copy = ft_outline_glyph_copy; + this.glyph_transform = ft_outline_glyph_transform; + this.glyph_bbox = ft_outline_glyph_bbox; + this.glyph_prepare = ft_outline_glyph_prepare; +} +var ft_outline_glyph_class = new _ft_outline_glyph_class(); + +function FT_GlyphRec() +{ + this.library = null; + this.clazz = null; + this.format = 0; + this.advance = new FT_Vector(); +} +function FT_BitmapGlyphRec() +{ + this.library = null; + this.clazz = null; + this.format = 0; + this.advance = new FT_Vector(); + + this.left = 0; + this.top = 0; + this.bitmap = new FT_Bitmap(); +} +function FT_OutlineGlyphRec() +{ + this.library = null; + this.clazz = null; + this.format = 0; + this.advance = new FT_Vector(); + + this.outline = new FT_Outline(); +} +function ft_new_glyph(library, clazz) +{ + var glyph = null; + if (clazz.glyph_size == 0) + glyph = new FT_BitmapGlyphRec(); + else + glyph = new FT_OutlineGlyphRec(); + + glyph.library = library; + glyph.clazz = clazz; + glyph.format = clazz.glyph_format; + return glyph; +} +/******************************************************************************/ +// glyphloader +/******************************************************************************/ +function FT_CreateVectorArray(array, start, count) +{ + for (var i = start + count - 1; i >= start; i--) + array[i] = new FT_Vector(); +} +function FT_CreateArray(array, start, count) +{ + for (var i = start + count - 1; i >= start; i--) + array[i] = 0; +} +function FT_CreateArraySubGlyphs(array, start, count) +{ + for (var i = start + count - 1; i >= start; i--) + array[i] = new FT_SubGlyph(); +} +function FT_OutlineCur() +{ + this.n_contours = 0; + this.n_points = 0; + + this.points = 0; + this.tags = 0; + this.contours = 0; + + this.flags = 0; +} +function FT_SubGlyph() +{ + this.index = 0; + this.flags = 0; + this.arg1 = 0; + this.arg2 = 0; + this.transform = new FT_Matrix(); +} +function FT_GlyphLoad() +{ + this.outline = new FT_Outline(); + this.extra_points = null; + this.extra_points2 = 0; + this.num_subglyphs = 0; + this.subglyphs = null; +} +function FT_GlyphLoadCur() +{ + this.outline = new FT_OutlineCur(); + this.extra_points = 0; + this.extra_points2 = 0; + this.num_subglyphs = 0; + this.subglyphs = 0; +} +function FT_GlyphLoader() +{ + this.memory = null; + this.max_points = 0; + this.max_contours = 0; + this.max_subglyphs = 0; + this.use_extra = 0; + + this.base = new FT_GlyphLoad(); + this.current = new FT_GlyphLoadCur(); + + this.other = null; +} + +function FT_GlyphLoader_New(memory) +{ + var loader = new FT_GlyphLoader(); + loader.memory = memory; + return loader; +} +function FT_GlyphLoader_Rewind(loader) +{ + var base = loader.base; + var current = loader.current; + + base.outline.n_points = 0; + base.outline.n_contours = 0; + base.num_subglyphs = 0; + + var _cur = current.outline; + _cur.n_contours = 0; + _cur.n_points = 0; + _cur.points = 0; + _cur.tags = 0; + _cur.contours = 0; + _cur.flags = 0; + + current.extra_points = 0; + current.extra_points2 = 0; + current.num_subglyphs = 0; + current.subglyphs = 0; + + current.extra_points = 0; + current.extra_points2 = base.extra_points2; +} +function FT_GlyphLoader_Reset(loader) +{ + var base = loader.base; + + base.outline.points = null; + base.outline.tags = null; + base.outline.contours = null; + base.extra_points = null; + base.extra_points2 = 0; + base.subglyphs = null; + + loader.max_points = 0; + loader.max_contours = 0; + loader.max_subglyphs = 0; + + FT_GlyphLoader_Rewind(loader); +} +function FT_GlyphLoader_Done(loader) +{ + if (loader) + FT_GlyphLoader_Reset(loader); +} +function FT_GlyphLoader_Adjust_Points(loader) +{ + var base = loader.base.outline; + var current = loader.current.outline; + + current.points = base.n_points; + current.tags = base.n_points; + current.contours = base.n_contours; + + if (loader.use_extra == 1) + { + loader.current.extra_points = base.n_points; + loader.current.extra_points2 = loader.base.extra_points2 + base.n_points; + } +} +function FT_GlyphLoader_CreateExtra(loader) +{ + var c = 2*loader.max_points; + loader.base.extra_points = new Array(c); + FT_CreateVectorArray(loader.base.extra_points, 0, c); + loader.use_extra = 1; + loader.base.extra_points2 = loader.max_points; + FT_GlyphLoader_Adjust_Points(loader); + return 0; +} +function FT_GlyphLoader_Adjust_Subglyphs(loader) +{ + loader.current.subglyphs = loader.base.num_subglyphs; +} +function FT_GlyphLoader_CheckPoints(loader, n_points, n_contours) +{ + var base = loader.base.outline; + var current = loader.current.outline; + var adjust = 0; + + var new_max = base.n_points + current.n_points + n_points; + var old_max = loader.max_points; + + if (new_max > old_max) + { + new_max = (new_max + 7) & ~7; + + if (new_max > 32767) + return FT_Error.FT_Err_Array_Too_Large; + + if (null == base.points) + base.points = new Array(new_max); + if (null == base.tags) + base.tags = new Array(new_max); + + FT_CreateVectorArray(base.points, old_max, new_max - old_max); + FT_CreateArray(base.tags, old_max, new_max - old_max); + + if (1 == loader.use_extra) + { + if (null == loader.base.extra_points) + loader.base.extra_points = new Array(2 * (new_max - old_max)); + FT_CreateVectorArray(loader.base.extra_points, old_max * 2, 2 * (new_max - old_max)); + loader.base.extra_points2 = new_max; + } + + adjust = 1; + loader.max_points = new_max; + } + + /* check contours */ + old_max = loader.max_contours; + new_max = base.n_contours + current.n_contours + n_contours; + if (new_max > old_max) + { + new_max = (new_max + 4) & ~4; + + if (new_max > 32767) + return FT_Common.FT_Err_Array_Too_Large; + + if (base.contours == null) + base.contours = new Array(new_max); + FT_CreateArray(base.contours, old_max, new_max - old_max); + + adjust = 1; + loader.max_contours = new_max; + } + + if (adjust == 1) + FT_GlyphLoader_Adjust_Points(loader); + + return 0; +} +function FT_GlyphLoader_CheckSubGlyphs(loader, n_subs) +{ + var base = loader.base; + var current = loader.current; + + var new_max = base.num_subglyphs + current.num_subglyphs + n_subs; + var old_max = loader.max_subglyphs; + if (new_max > old_max) + { + new_max = (new_max + 2) & ~2; + + if (null == base.subglyphs) + base.subglyphs = new Array(new_max); + FT_CreateArraySubGlyphs(base.subglyphs, old_max, new_max - old_max); + loader.max_subglyphs = new_max; + FT_GlyphLoader_Adjust_Subglyphs(loader); + } + return 0; +} +function FT_GlyphLoader_Prepare(loader) +{ + var current = loader.current; + + current.outline.n_points = 0; + current.outline.n_contours = 0; + current.num_subglyphs = 0; + + FT_GlyphLoader_Adjust_Points(loader); + FT_GlyphLoader_Adjust_Subglyphs(loader); +} +function FT_GlyphLoader_Add(loader) +{ + if ( !loader ) + return; + + var base = loader.base; + var current = loader.current; + + var n_curr_contours = current.outline.n_contours; + var n_base_points = base.outline.n_points; + + base.outline.n_points = base.outline.n_points + current.outline.n_points; + base.outline.n_contours = base.outline.n_contours + current.outline.n_contours; + + base.num_subglyphs += current.num_subglyphs; + + var mass = base.outline.contours; + var start = current.outline.contours; + for (var n = 0; n < n_curr_contours; n++) + mass[start+n] = mass[start+n] + n_base_points; + + FT_GlyphLoader_Prepare(loader); +} +function FT_GlyphLoader_CopyPoints(target, source) +{ + var num_points = source.base.outline.n_points; + var num_contours = source.base.outline.n_contours; + + + var error = FT_GlyphLoader_CheckPoints(target, num_points, num_contours); + if (error != 0) + { + var _out = target.base.outline; + var _in = source.base.outline; + + var i=0; + + var out_p = _out.points; + var in_p = _in.points; + var out_t = _out.tags; + var in_t = _in.tags; + + for (i=0;i<num_points;i++) + { + out_p[i].x = in_p[i].x; + out_p[i].y = in_p[i].y; + + out_t[i] = in_t[i]; + } + + var out_c = _out.contours; + var in_c = _in.contours; + for (i=0;i<num_contours;i++) + out_c[i] = in_c[i]; + + if (1 == target.use_extra && 1 == source.use_extra) + { + var out_e = target.base.extra_points; + var in_e = source.base.extra_points; + var c = 2 * num_points; + for (i=0;i<c;i++) + { + out_e[i].x = in_e[i].x; + out_e[i].y = in_e[i].y; + } + } + + _out.n_points = num_points; + _out.n_contours = num_contours; + + FT_GlyphLoader_Adjust_Points(target); + } + + return error; +} +function FT_GLYPHLOADER_CHECK_POINTS(_loader,_points,_contours) +{ + if (_points == 0 || (_loader.base.outline.n_points + _loader.current.outline.n_points + _points) <= _loader.max_points) + { + if (_contours == 0 || (_loader.base.outline.n_contours + _loader.current.outline.n_contours + _contours) <= _loader.max_contours) + return 0; + } + return FT_GlyphLoader_CheckPoints(_loader,_points,_contours); +} +/******************************************************************************/ +// ftmm +/******************************************************************************/ +function FT_MM_Axis() +{ + this.name = null; + this.minimum = 0; + this.maximum = 0; +} +function FT_Var_Axis() +{ + this.name = null; + + this.minimum = 0; + this.def = 0; + this.maximum = 0; + + this.tag = 0; + this.strid = 0; +} +function FT_Var_Named_Style() +{ + this.coords = null; + this.strid = 0; +} +function FT_MM_Var() +{ + this.num_axis = 0; + this.num_designs = 0; + this.num_namedstyles = 0; + this.axis = null; + this.namedstyle = null; + + this.dublicate = function() + { + var res = new FT_MM_Var(); + res.num_axis = this.num_axis; + res.num_designs = this.num_designs; + res.num_namedstyles = this.num_namedstyles; + + var c = res.num_axis; + if (c != 0) + { + res.axis = new Array(c); + for (var i=0;i<c;i++) + { + res.axis[i] = new FT_Var_Axis(); + var _m = res.axis[i]; + var _s = this.axis[i]; + + _m.name = _s.name; + _m.minimum = _s.minimum; + _m.def = _s.def; + _m.maximum = _s.maximum; + _m.tag = _s.tag; + _m.strid = _s.strid; + } + } + c = res.num_namedstyles; + if (c != 0) + { + res.namedstyle = new Array(c); + for (var i=0;i<c;i++) + { + res.namedstyle[i] = new FT_Var_Named_Style(); + var _m = res.namedstyle[i]; + var _s = this.namedstyle[i]; + + _m.strid = _s.strid; + if (null != _s.coords) + _m.coords = _s.coords.splice(0,0); + } + } + } +} +function FT_Multi_Master() +{ + this.num_axis = 0; + this.num_designs = 0; + this.axis = new Array(FT_Common.T1_MAX_MM_AXIS); + + for (var i = 0; i < FT_Common.T1_MAX_MM_AXIS; i++) + this.axis[i] = new FT_MM_Axis(); +} +/******************************************************************************/ +// ftdriver +/******************************************************************************/ +function FT_Driver_Class() +{ + this.flags = 0; + this.name = ""; + this.version = 0; + this.requires = 0; + + this.module_interface = null; + + this.init = null; + this.done = null; + this.get_interface = null; + + this.face_object_size = 0; + this.size_object_size = 0; + this.slot_object_size = 0; + + this.init_face = null; + this.done_face = null; + + this.init_size = null; + this.done_size = null; + + this.init_slot = null; + this.done_slot = null; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.set_char_sizes = null; + this.set_pixel_sizes = null; + //#endif + + this.load_glyph = null; + + this.get_kerning = null; + this.attach_file = null; + this.get_advances = null; + + this.request_size = null; + this.select_size = null; +} +//#ifdef FT_CONFIG_OPTION_OLD_INTERNALS +function ft_stub_set_char_sizes(size, width, height, horz_res, vert_res) +{ + var driver = size.face.driver; + if (driver.clazz.request_size != null) + { + var req = new FT_Size_RequestRec(); + req.type = 0; + req.width = width; + req.height = height; + + if (horz_res == 0) + horz_res = vert_res; + + if (vert_res == 0) + vert_res = horz_res; + + if (horz_res == 0) + horz_res = vert_res = 72; + + req.horiResolution = horz_res; + req.vertResolution = vert_res; + + return driver.clazz.request_size(size, req); + } + return 0; +} +function ft_stub_set_pixel_sizes(size, width, height) +{ + var driver = size.face.driver; + if (driver.clazz.request_size) + { + var req = new FT_Size_RequestRec(); + req.type = 0; + req.width = width << 6; + req.height = height << 6; + req.horiResolution = 0; + req.vertResolution = 0; + return driver.clazz.request_size(size, req); + } + return 0; +} +//#endif +/******************************************************************************/ +// ftvalid +/******************************************************************************/ +function FT_ValidatorRec() +{ + this.base = new CPointer(); + this.limit = 0; + this.level = 0 + this.error = 0 +} +/******************************************************************************/ +// pshints +/******************************************************************************/ +/******************************************************************************/ +// tttypes +/******************************************************************************/ +function TTC_HeaderRec() +{ + this.tag = 0; + this.version = 0; + this.count = 0; + this.offsets = null; +} +function SFNT_HeaderRec() +{ + this.format_tag = 0; + this.num_tables = 0; + this.search_range = 0; + this.entry_selector = 0; + this.range_shift = 0; + + this.offset = 0; /* not in file */ +} +function TT_Table() +{ + this.Tag = 0; + this.CheckSum = 0; + this.Offset = 0; + this.Length = 0; +} +function TT_LongMetricsRec() +{ + this.advance = 0; + this.bearing = 0; +} +function TT_NameEntryRec() +{ + this.platformID = 0; + this.encodingID = 0; + this.languageID = 0; + this.nameID = 0; + this.stringLength = 0; + this.stringOffset = 0; + this.string = null; +} +function TT_NameTableRec() +{ + this.format = 0; + this.numNameRecords = 0; + this.storageOffset = 0; + this.names = null; + this.stream = null; +} +function TT_GaspRange() +{ + this.maxPPEM = 0; + this.gaspFlag = 0; +} +function TT_Gasp() +{ + this.version = 0; + this.numRanges = 0; + this.gaspRanges = null; +} +//#ifdef FT_CONFIG_OPTION_OLD_INTERNALS +function TT_HdmxEntryRec() +{ + this.ppem = 0; + this.max_width = 0; + this.widths = null; +} +function TT_HdmxRec() +{ + this.version = 0; + this.num_records = 0; + this.records = null; +} +function TT_Kern0_PairRec() +{ + this.left = 0; + this.right = 0; + this.value = 0; +} +//#endif +function TT_SBit_MetricsRec() +{ + this.height = 0; + this.width = 0; + + this.horiBearingX = 0; + this.horiBearingY = 0; + this.horiAdvance = 0; + + this.vertBearingX = 0; + this.vertBearingY = 0; + this.vertAdvance = 0; +} +function TT_SBit_Small_Metrics() +{ + this.height = 0; + this.width = 0; + + this.bearingX = 0; + this.bearingY = 0; + this.advance = 0; +} +function TT_SBit_LineMetricsRec() +{ + this.ascender = 0; + this.descender = 0; + this.max_width = 0; + this.caret_slope_numerator = 0; + this.caret_slope_denominator = 0; + this.caret_offset = 0; + this.min_origin_SB = 0; + this.min_advance_SB = 0; + this.max_before_BL = 0; + this.min_after_BL = 0; + + this.pad1 = 0; + this.pad2 = 0; +} +function TT_SBit_RangeRec() +{ + this.first_glyph = 0; + this.last_glyph = 0; + + this.index_format = 0; + this.image_format = 0; + this.image_offset = 0; + + this.image_size = 0; + this.metrics = new TT_SBit_MetricsRec(); + this.num_glyphs = 0; + + this.glyph_offsets = null; + this.glyph_codes = null; + + this.table_offset = 0; +} +function TT_SBit_StrikeRec() +{ + this.num_ranges = 0; + this.sbit_ranges = null; + this.ranges_offset = 0; + + this.color_ref = 0; + + this.hori = new TT_SBit_LineMetricsRec(); + this.vert = new TT_SBit_LineMetricsRec(); + + this.start_glyph = 0; + this.end_glyph = 0; + + this.x_ppem = 0; + this.y_ppem = 0; + + this.bit_depth = 0; + this.flags = 0; +} +function TT_SBit_ComponentRec() +{ + this.glyph_code = 0; + this.x_offset = 0; + this.y_offset = 0; +} +function TT_SBit_ScaleRec() +{ + this.hori = new TT_SBit_LineMetricsRec(); + this.vert = new TT_SBit_LineMetricsRec(); + + this.x_ppem = 0; + this.y_ppem = 0; + + this.x_ppem_substitute = 0; + this.y_ppem_substitute = 0; +} +function TT_Post_20Rec() +{ + this.num_glyphs = 0; + this.num_names = 0; + this.glyph_indices = null; + this.glyph_names = null; +} +function TT_Post_25Rec() +{ + this.num_glyphs = 0; + this.offsets = null; +} +function TT_Post_NamesRec() +{ + this.loaded = false; + this.format = null; +} +//#ifdef TT_CONFIG_OPTION_BDF +function TT_BDFRec() +{ + this.table = null; + this.table_end = 0; + this.strings = null; + this.strings_size = 0; + this.num_strikes = 0; + this.loaded = 0; +} +//#endif +function TT_GlyphZoneRec() +{ + this.memory = null; + this.max_points = 0; + this.max_contours = 0; + this.n_points = 0; /* number of points in zone */ + this.n_contours = 0; /* number of contours */ + + this.org = null; /* original point coordinates */ + this.cur = null; /* current point coordinates */ + this.orus = null; /* original (unscaled) point coordinates */ + + this.tags = null; /* current touch flags */ + this.contours = null; /* contour end points */ + + this._offset_org = 0; + this._offset_cur = 0; + this._offset_orus = 0; + this._offset_tags = 0; + this._offset_contours = 0; + + this.first_point = 0; /* offset of first (#0) point */ +} +TT_GlyphZoneRec.prototype = +{ + Clear : function() + { + this.memory = null; + this.max_points = 0; + this.max_contours = 0; + this.n_points = 0; + this.n_contours = 0; + + this.org = null; + this.cur = null; + this.orus = null; + + this.tags = null; + this.contours = null; + + this._offset_org = 0; + this._offset_cur = 0; + this._offset_orus = 0; + this._offset_tags = 0; + this._offset_contours = 0; + + this.first_point = 0; + }, + + Copy : function(src) + { + this.memory = src.memory; + this.max_points = src.max_points; + this.max_contours = src.max_contours; + this.n_points = src.n_points; + this.n_contours = src.n_contours; + + this.org = src.org; + this.cur = src.cur; + this.orus = src.orus; + + this.tags = src.tags; + this.contours = src.contours; + + this._offset_org = src._offset_org; + this._offset_cur = src._offset_cur; + this._offset_orus = src._offset_orus; + this._offset_tags = src._offset_tags; + this._offset_contours = src._offset_contours; + + this.first_point = src.first_point; + } +} + +function TT_LoaderRec() +{ + this.face = null; + this.size = null; + this.glyph = null; + this.gloader = null; + + this.load_flags = 0; + this.glyph_index = 0; + + this.stream = null; + this.byte_len = 0; + + this.n_contours = 0; + this.bbox = new FT_BBox(); + this.left_bearing = 0; + this.advance = 0; + this.linear = 0; + this.linear_def = 0; + this.preserve_pps = 0; + this.pp1 = new FT_Vector(); + this.pp2 = new FT_Vector(); + + this.glyf_offset = 0; + + this.base = new TT_GlyphZoneRec(); + this.zone = new TT_GlyphZoneRec(); + + this.exec = null; + this.instructions = null; + this.ins_pos = 0; + + this.other = null; + + this.top_bearing = 0; + this.vadvance = 0; + this.pp3 = new FT_Vector(); + this.pp4 = new FT_Vector(); + + this.cursor = 0; + this.limit = 0; + + this.Clear = function() + { + this.load_flags = 0; + this.glyph_index = 0; + + this.stream = null; + this.byte_len = 0; + + this.n_contours = 0; + this.bbox.xMin = 0; + this.bbox.yMin = 0; + this.bbox.xMax = 0; + this.bbox.yMax = 0; + this.left_bearing = 0; + this.advance = 0; + this.linear = 0; + this.linear_def = 0; + this.preserve_pps = 0; + this.pp1.x = 0; + this.pp1.y = 0; + this.pp2.x = 0; + this.pp2.y = 0; + + this.glyf_offset = 0; + + this.exec = null; + this.instructions = null; + this.ins_pos = 0; + + this.other = null; + + this.top_bearing = 0; + this.vadvance = 0; + this.pp3.x = 0; + this.pp3.y = 0; + this.pp4.x = 0; + this.pp4.y = 0; + + this.cursor = 0; + this.limit = 0; + + this.gloader = null; + } +} +/******************************************************************************/ +// tttables +/******************************************************************************/ +function TT_Header() +{ + this.Table_Version = 0; + this.Font_Revision = 0; + + this.CheckSum_Adjust = 0; + this.Magic_Number = 0; + + this.Flags = 0; + this.Units_Per_EM = 0; + + this.Created1 = 0; + this.Created2 = 0; + this.Modified1 = 0; + this.Modified2 = 0; + + this.xMin = 0; + this.yMin = 0; + this.xMax = 0; + this.yMax = 0; + + this.Mac_Style = 0; + this.Lowest_Rec_PPEM = 0; + + this.Font_Direction = 0; + this.Index_To_Loc_Format = 0; + this.Glyph_Data_Format = 0; +} +function TT_HoriHeader() +{ + this.Version = 0; + this.Ascender = 0; + this.Descender = 0; + this.Line_Gap = 0; + + this.advance_Width_Max = 0; + + this.min_Left_Side_Bearing = 0; + this.min_Right_Side_Bearing = 0; + this.xMax_Extent = 0; + this.caret_Slope_Rise = 0; + this.caret_Slope_Run = 0; + this.caret_Offset = 0; + + this.Reserved1 = 0; + this.Reserved2 = 0; + this.Reserved3 = 0; + this.Reserved4 = 0; + + this.metric_Data_Format = 0; + this.number_Of_HMetrics = 0; + + this.long_metrics = null; + this.short_metrics = null; +} +function TT_VertHeader() +{ + this.Version = 0; + this.Ascender = 0; + this.Descender = 0; + this.Line_Gap = 0; + + this.advance_Height_Max = 0; + + this.min_Top_Side_Bearing = 0; + this.min_Bottom_Side_Bearing = 0; + this.yMax_Extent = 0; + this.caret_Slope_Rise = 0; + this.caret_Slope_Run = 0; + this.caret_Offset = 0; + + this.Reserved1 = 0; + this.Reserved2 = 0; + this.Reserved3 = 0; + this.Reserved4 = 0; + + this.metric_Data_Format = 0; + this.number_Of_VMetrics = 0; + + this.long_metrics = null; + this.short_metrics = null; +} +function TT_OS2() +{ + this.version = 0; + this.xAvgCharWidth = 0; + this.usWeightClass = 0; + this.usWidthClass = 0; + this.fsType = 0; + this.ySubscriptXSize = 0; + this.ySubscriptYSize = 0; + this.ySubscriptXOffset = 0; + this.ySubscriptYOffset = 0; + this.ySuperscriptXSize = 0; + this.ySuperscriptYSize = 0; + this.ySuperscriptXOffset = 0; + this.ySuperscriptYOffset = 0; + this.yStrikeoutSize = 0; + this.yStrikeoutPosition = 0; + this.sFamilyClass = 0; + + this.panose = new Array(10); + + this.ulUnicodeRange1 = 0; /* Bits 0-31 */ + this.ulUnicodeRange2 = 0; /* Bits 32-63 */ + this.ulUnicodeRange3 = 0; /* Bits 64-95 */ + this.ulUnicodeRange4 = 0; /* Bits 96-127 */ + + this.achVendID = new Array(4); + + this.fsSelection = 0; + this.usFirstCharIndex = 0; + this.usLastCharIndex = 0; + this.sTypoAscender = 0; + this.sTypoDescender = 0; + this.sTypoLineGap = 0; + this.usWinAscent = 0; + this.usWinDescent = 0; + + /* only version 1 tables: */ + this.ulCodePageRange1 = 0; /* Bits 0-31 */ + this.ulCodePageRange2 = 0; /* Bits 32-63 */ + + /* only version 2 tables: */ + this.sxHeight = 0; + this.sCapHeight = 0; + this.usDefaultChar = 0; + this.usBreakChar = 0; + this.usMaxContext = 0; +} +function TT_Postscript() +{ + this.FormatType = 0; + this.italicAngle = 0; + this.underlinePosition = 0; + this.underlineThickness = 0; + this.isFixedPitch = 0; + this.minMemType42 = 0; + this.maxMemType42 = 0; + this.minMemType1 = 0; + this.maxMemType1 = 0; +} +function TT_PCLT() +{ + this.Version = 0; + this.FontNumber = 0; + this.Pitch = 0; + this.xHeight = 0; + this.Style = 0; + this.TypeFamily = 0; + this.CapHeight = 0; + this.SymbolSet = 0; + this.TypeFace = ""; + this.CharacterComplement = ""; + this.FileName = ""; + this.StrokeWeight = 0; + this.WidthType = 0; + this.SerifStyle = 0; + this.Reserved = 0; +} +function TT_MaxProfile() +{ + this.version = 0; + this.numGlyphs = 0; + this.maxPoints = 0; + this.maxContours = 0; + this.maxCompositePoints = 0; + this.maxCompositeContours = 0; + this.maxZones = 0; + this.maxTwilightPoints = 0; + this.maxStorage = 0; + this.maxFunctionDefs = 0; + this.maxInstructionDefs = 0; + this.maxStackElements = 0; + this.maxSizeOfInstructions = 0; + this.maxComponentElements = 0; + this.maxComponentDepth = 0; +} +function FT_Get_Sfnt_Table(face, tag) +{ + var table = null; + if (face && ((face.face_flags & FT_Common.FT_FACE_FLAG_SFNT) != 0)) + { + var service = FT_FACE_FIND_SERVICE( face, "sfnt-table"); + if (service != null) + table = service.get_table(face, tag); + } + return table; +} +function FT_Load_Sfnt_Table(face, tag, offset, buffer, length) +{ + if (face == null || ((face.face_flags & FT_Common.FT_FACE_FLAG_SFNT) == 0)) + return FT_Common.FT_Err_Invalid_Face_Handle; + + var service = FT_FACE_FIND_SERVICE(face, FT_SERVICE_ID_SFNT_TABLE); + if (service == null) + return FT_Common.FT_Err_Unimplemented_Feature; + + return service.load_table(face, tag, offset, buffer, length); +} +function FT_Sfnt_Table_Info(face, table_index, tag, length) +{ + if (face == null || ((face.face_flags & FT_Common.FT_FACE_FLAG_SFNT) == 0)) + return FT_Common.FT_Err_Invalid_Face_Handle; + + var service = FT_FACE_FIND_SERVICE(face, FT_SERVICE_ID_SFNT_TABLE); + if (service == null) + return FT_Common.FT_Err_Unimplemented_Feature; + + return service.table_info(face, table_index, tag); +} +function FT_Get_CMap_Language_ID(charmap) +{ + if (charmap == null || charmap.face == null) + return 0; + + var service = FT_FACE_FIND_SERVICE(charmap.face, FT_SERVICE_ID_TT_CMAP); + if (service == null) + return 0; + var cmap_info = new TT_CMapInfo(); + if (0 != service.get_cmap_info( charmap, cmap_info)) + return 0; + return cmap_info.language; +} +/******************************************************************************/ +// ftimage +/******************************************************************************/ +function FT_Vector() +{ + this.x = 0; + this.y = 0; +} +function dublicate_vector(v) +{ + var _v = new FT_Vector(); + _v.x = v.x; + _v.y = v.y; + return _v; +} +function FT_BBox() +{ + this.xMin = 0; + this.yMin = 0; + this.xMax = 0; + this.yMax = 0; +} +function dublicate_bbox(v) +{ + var _v = new FT_BBox(); + _v.xMin = v.xMin; + _v.yMin = v.yMin; + _v.xMax = v.xMax; + _v.yMax = v.yMax; + return _v; +} +function FT_Bitmap() +{ + this.rows = 0; + this.width = 0; + this.pitch = 0; + this.buffer = null; + this.num_grays = 0; + this.pixel_mode = 0; + this.palette_mode = 0; + this.palette = null; +} +function DoNullBitmap(im) +{ + im.rows = 0; + im.width = 0; + im.pitch = 0; + im.buffer = null; + im.num_grays = 0; + im.pixel_mode = 0; + im.palette_mode = 0; + im.palette = null; +} +function FT_Outline() +{ + this.n_contours = 0; + this.n_points = 0; + + this.points = null; + this.tags = null; + this.contours = null; + + this.flags = 0; +} +function EquatingOutline(d, s) +{ + d.n_contours = s.n_contours; + d.n_points = s.n_points; + d.points = s.points; + d.tags = s.tags; + d.contours = s.contours; + d.flags = s.flags; +} +function FT_Span() +{ + this.x = 0; + this.len = 0; + this.coverage = 0; +} +function FT_Raster_Params() +{ + this.target = null; + this.source = null; + this.flags = 0; + this.gray_spans = null; + this.black_spans = null; + this.bit_test = null; + this.bit_set = null; + this.user = null; + this.clip_box = new FT_BBox(); +} +/******************************************************************************/ +// ftbitmap +/******************************************************************************/ +function FT_Bitmap_New(bitmap) +{ + DoNullBitmap(bitmap); +} +function FT_Bitmap_Copy(library, source, target) +{ + var pitch = source.pitch; + if (source == target) + return 0; + + if (source.buffer == null) + { + target.rows = source.rows; + target.width = source.width; + target.pitch = source.pitch; + target.buffer = source.buffer; + target.num_grays = source.num_grays; + target.pixel_mode = source.pixel_mode; + target.palette_mode = source.palette_mode; + target.palette = source.palette; + + return 0; + } + + if (pitch < 0) + pitch = -pitch; + var size = (pitch * source.rows); + + if (target.buffer != null) + { + var target_pitch = target.pitch; + + if (target_pitch < 0 ) + target_pitch = -target_pitch; + var target_size = (target_pitch * target.rows); + + if (target_size != size) + { + target.buffer = null; + target.buffer = g_memory.Alloc(size);//new Array(size); + } + } + else + target.buffer = g_memory.Alloc(size);//new Array(size); + + var s = source.buffer; + var d = target.buffer; + for (var i=0;i<size;i++) + d[i]=s[i]; + + return 0; +} +function FT_Bitmap_Done(library, bitmap) +{ + DoNullBitmap(bitmap); + return 0; +} +/******************************************************************************/ +// ftsnames +/******************************************************************************/ +function FT_SfntName() +{ + this.platform_id = 0; + this.encoding_id = 0; + this.language_id = 0; + this.name_id = 0; + + this.string = ""; + this.string_len = 0; +} +function FT_Get_Sfnt_Name_Count(face) +{ + return (face != null && (face.face_flags & FT_Common.FT_FACE_FLAG_SFNT) != 0) ? face.num_names : 0; +} +function FT_Get_Sfnt_Name(face, idx, aname) +{ + var error = FT_Common.FT_Err_Invalid_Argument; + if (face != null && (face.face_flags & FT_Common.FT_FACE_FLAG_SFNT) != 0) + { + if (idx < face.num_names) + { + var entry = face.name_table.names[idx]; + + if (entry.stringLength > 0 && entry.string == null) + { + var stream = face.stream; + error = stream.Seek(entry.stringOffset); + entry.string = stream.ReadString1(entry.stringLength); + error = FT_Error; + + if (0 != error) + { + entry.string = null; + entry.stringLength = 0; + } + } + + aname.platform_id = entry.platformID; + aname.encoding_id = entry.encodingID; + aname.language_id = entry.languageID; + aname.name_id = entry.nameID; + aname.string = entry.string; + aname.string_len = entry.stringLength; + } + } + return 0; +} +/******************************************************************************/ +// ftincrem +/******************************************************************************/ +function FT_Incremental_MetricsRec() +{ + this.bearing_x = 0; + this.bearing_y = 0; + this.advance = 0; + this.advance_v = 0; +} +function FT_Incremental_FuncsRec() +{ + this.get_glyph_data = null; + this.free_glyph_data = null; + this.get_glyph_metrics = null; +} +function FT_Incremental_Interface() +{ + this.funcs = null; + this.object = null; +} +/******************************************************************************/ +// fttypes +/******************************************************************************/ +function FT_Matrix() +{ + this.xx = 0; + this.xy = 0; + this.yx = 0; + this.yy = 0; +} +function dublicate_matrix(m) +{ + var _m = new FT_Matrix(); + _m.xx = m.xx; + _m.xy = m.xy; + _m.yx = m.yx; + _m.yy = m.yy; + return _m; +} +function FT_Data() +{ + this.pointer = null; + this.length = 0; +} +function FT_Generic() +{ + this.data = null; + this.finalizer = null; +} +function FT_Glyph_Metrics() +{ + this.width = 0; + this.height = 0; + + this.horiBearingX = 0; + this.horiBearingY = 0; + this.horiAdvance = 0; + + this.vertBearingX = 0; + this.vertBearingY = 0; + this.vertAdvance = 0; + +} +function FT_Bitmap_Size() +{ + this.height = 0; + this.width = 0; + + this.size = 0; + + this.x_ppem = 0; + this.y_ppem = 0; +} +function FT_CharMapRec() +{ + this.face = null; + this.encoding = 0; + this.platform_id = 0; + this.encoding_id = 0; +} +function FT_Face() +{ + this.num_faces = 0; + this.face_index = 0; + + this.face_flags = 0; + this.style_flags = 0; + + this.num_glyphs = 0; + + this.family_name = ""; + this.style_name = ""; + + this.num_fixed_sizes = 0; + this.available_sizes = []; + + this.num_charmaps = 0; + this.charmaps = []; + + this.generic = new FT_Generic(); + + /*# The following member variables (down to `underline_thickness') */ + /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ + /*# for bitmap fonts. */ + this.bbox = new FT_BBox(); + + this.units_per_EM = 0; + this.ascender = 0; + this.descender = 0; + this.height = 0; + + this.max_advance_width = 0; + this.max_advance_height = 0; + + this.underline_position = 0; + this.underline_thickness = 0; + + this.glyph = null; + this.size = null; + this.charmap = null; + + /*@private begin */ + this.driver = null; + this.memory = null; + this.stream = null; + + this.sizes_list = []; + + this.autohint = []; + this.extensions = null; + + this.internal = null; + /*@private end */ +} +function FT_Size_Metrics() +{ + this.x_ppem = 0; + this.y_ppem = 0; + + this.x_scale = 0; + this.y_scale = 0; + + this.ascender = 0; + this.descender = 0; + this.height = 0; + this.max_advance = 0; +} +FT_Size_Metrics.prototype = +{ + Copy : function(src) + { + this.x_ppem = src.x_ppem; + this.y_ppem = src.y_ppem; + + this.x_scale = src.x_scale; + this.y_scale = src.y_scale; + + this.ascender = src.ascender; + this.descender = src.descender; + this.height = src.height; + this.max_advance = src.max_advance; + } +}; + +function FT_Size() +{ + this.face = null; + this.generic = null; + this.metrics = new FT_Size_Metrics(); + this.internal = null; +} +function FT_GlyphSlot() +{ + this.library = null; + this.face = null; + this.next = null; + this.reserved = 0; /* retained for binary compatibility */ + this.generic = null; + + this.metrics = new FT_Glyph_Metrics(); + this.linearHoriAdvance = 0; + this.linearVertAdvance = 0; + this.advance = new FT_Vector(); + + this.format = 0; + + this.bitmap = new FT_Bitmap(); + this.bitmap_left = 0; + this.bitmap_top = 0; + + this.outline = new FT_Outline(); + + this.num_subglyphs = 0; + this.subglyphs = []; + + this.control_data = null; + this.control_len = 0; + + this.lsb_delta = 0; + this.rsb_delta = 0; + + this.other = null; + + this.internal = null; + + this.base_root = null; +} +function FT_Open_Args() +{ + this.flags = null; + this.memory_base = null; + this.memory_size = null; + this.pathname = ""; + this.stream = null; + this.driver = null; + this.num_params = 0; + this.params = null; +} +function FT_Size_RequestRec() +{ + this.type = 0; + this.width = 0; + this.height = 0; + this.horiResolution = 0; + this.vertResolution = 0; +} +function FT_CMapRec() +{ + this.charmap = new FT_CharMapRec(); + this.clazz = null; + + this.type = FT_Common.FT_CMAP_0; +} +function __FT_CMapRec(val) +{ + switch (val.type) + { + case FT_Common.FT_CMAP_0: + return val; + case FT_Common.FT_CMAP_1: + return val.cmap; + case FT_Common.FT_CMAP_4: + case FT_Common.FT_CMAP_12: + case FT_Common.FT_CMAP_13: + case FT_Common.FT_CMAP_14: + return val.cmap.cmap; + default: + break; + } + return val; +} +function __FT_TTCMapRec(val) +{ + switch (val.type) + { + case FT_Common.FT_CMAP_0: + return null; + case FT_Common.FT_CMAP_1: + return val; + case FT_Common.FT_CMAP_4: + case FT_Common.FT_CMAP_12: + case FT_Common.FT_CMAP_13: + case FT_Common.FT_CMAP_14: + return val.cmap; + default: + break; + } + return null; +} +function __FT_CharmapRec(val) +{ + switch (val.type) + { + case FT_Common.FT_CMAP_0: + return val.charmap; + case FT_Common.FT_CMAP_1: + return val.cmap.charmap; + case FT_Common.FT_CMAP_4: + case FT_Common.FT_CMAP_12: + case FT_Common.FT_CMAP_13: + case FT_Common.FT_CMAP_14: + return val.cmap.cmap.charmap; + default: + break; + } + return val.charmap; +} +function FT_CMap_ClassRec() +{ + this.size = 0; + this.init = null; + this.done = null; + this.char_index = null; + this.char_next = null; + + this.char_var_index = null; + this.char_var_default = null; + this.variant_list = null; + this.charvariant_list = null; + this.variantchar_list = null; +} +function create_cmap_class_rec(size_,init_,done_,char_index_,char_next_,var_index_,var_default_, + var_list_,char_var_list_, var_char_list_) +{ + var c = new FT_CMap_ClassRec(); + c.size = size_; + c.init = init_; + c.done = done_; + c.char_index = char_index_; + c.char_next = char_next_; + + c.char_var_index = var_index_; + c.char_var_default = var_default_; + c.variant_list = var_list_; + c.charvariant_list = char_var_list_; + c.variantchar_list = var_char_list_; + return c; +} +function FT_Face_Internal() +{ + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.reserved1 = 0; + this.reserved2 = 0; + //#endif + this.transform_matrix = new FT_Matrix(); + this.transform_delta = new FT_Vector(); + this.transform_flags = 0; + + this.services = new FT_ServiceCache(); + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + this.incremental_interface = null; + //#endif + + this.ignore_unpatented_hinter = false; + this.refcount = 0; +} +function FT_Slot_Internal() +{ + this.loader = null; + this.flags = 0; + this.glyph_transformed = false; + this.glyph_matrix = new FT_Matrix(); + this.glyph_delta = new FT_Vector(); + this.glyph_hints = null; +} +function FT_Module() +{ + this.clazz = null; // FT_Module_Class + this.library = null; // FT_Library + this.memory = null; // FT_Memory + this.generic = null; // FT_Generic +} +function FT_Driver() +{ + this.root = new FT_Module(); + this.clazz = new FT_Driver_Class(); + this.faces_list = []; + this.extensions = null; + this.glyph_loader = null; +} +function FT_Module_Class() +{ + this.flags = 0; + this.name = ""; + this.version = 0; + this.requires = 0; + + this.module_interface = null; + + this.init = null; + this.done = null; + this.get_interface = null; +} +/******************************************************************************/ +// outline +/******************************************************************************/ +function FT_Outline_New(library, numPoints, numContours, anoutline) +{ + if (library == null) + return FT_Common.FT_Err_Invalid_Library_Handle; + + return FT_Outline_New_Internal(library.Memory, numPoints, numContours, anoutline); +} +function FT_Outline_New_Internal(memory, numPoints, numContours, anoutline) +{ + if (null == anoutline || null == memory) + return FT_Common.FT_Err_Invalid_Argument; + + var _points = new Array(numPoints); + for (var i = 0; i < numPoints; i++) + _points[i] = new FT_Vector(); + + var _tags = new Array(numPoints); + for (var i = 0; i < numPoints; i++) + _tags[i] = 0; + var _contours = new Array(numContours); + for (var i = 0; i < numContours; i++) + _contours[i] = 0; + + anoutline.points = _points; + anoutline.tags = _tags; + anoutline.contours = _contours; + + anoutline.n_points = numPoints & 0xFFFF; + anoutline.n_contours = numContours & 0xFFFF; + anoutline.flags |= FT_Common.FT_OUTLINE_OWNER; + + return 0; +} +function FT_Outline_Check(outline) +{ + if (outline != null) + { + var n_points = outline.n_points; + var n_contours = outline.n_contours; + var end0, end; + var n; + + if (n_points == 0 && n_contours == 0) + return 0; + + if (n_points <= 0 || n_contours <= 0) + return FT_Common.FT_Err_Invalid_Argument; + + end0 = end = -1; + var _c = outline.contours; + for (n = 0; n < n_contours; n++) + { + end = _c[n]; + if (end <= end0 || end >= n_points) + return FT_Common.FT_Err_Invalid_Argument; + end0 = end; + } + + if ( end != n_points - 1 ) + return FT_Common.FT_Err_Invalid_Argument; + + return 0; + } + return FT_Common.FT_Err_Invalid_Argument; +} +function FT_Outline_Copy(source, target) +{ + if (null == source || null == target || source.n_points != target.n_points || source.n_contours != target.n_contours) + return FT_Common.FT_Err_Invalid_Argument; + + if (source == target) + return 0; + + var n_p = source.n_points; + var s_p = source.points; + var d_p = target.points; + var s_t = source.tags; + var t_t = target.tags; + for (var i = 0; i < n_p; i++) + { + d_p[i].x = s_p[i].x; + d_p[i].y = s_p[i].y; + + t_t[i] = s_t[i]; + } + + var n_c = source.n_contours; + var s_c = source.contours; + var t_c = target.contours; + for (var i = 0; i < source.n_contours; i++) + { + t_c[i] = s_c[i]; + } + + var is_owner = target.flags & FT_Common.FT_OUTLINE_OWNER; + target.flags = source.flags; + + target.flags &= ~FT_Common.FT_OUTLINE_OWNER; + target.flags |= is_owner; + + return 0; +} +function FT_Outline_Done_Internal(memory, outline) +{ + if (memory != null && outline != null) + { + if (outline.flags & FT_Common.FT_OUTLINE_OWNER) + { + outline.points = null; + outline.tags = null; + outline.contours = null; + } + + outline.n_points = 0; + outline.n_contours = 0; + outline.flags = 0; + + return 0; + } + else + return FT_Common.FT_Err_Invalid_Argument; +} +function FT_Outline_Done(library, outline) +{ + if (library == null) + return FT_Common.FT_Err_Invalid_Library_Handle; + + return FT_Outline_Done_Internal(library.memory, outline); +} +/******************************************************************************/ +// obj +/******************************************************************************/ +function find_unicode_charmap(face) +{ + if (null == face || null == face.charmaps) + return FT_Common.FT_Err_Invalid_CharMap_Handle; + + var count = Math.min(face.charmaps.length, face.num_charmaps); + if (0 == count) + return FT_Common.FT_Err_Invalid_CharMap_Handle; + + var cur = count - 1; + for ( ; cur >= 0; cur--) + { + var cmap = __FT_CharmapRec(face.charmaps[cur]); + if (cmap.encoding == FT_Common.FT_ENCODING_UNICODE) + { + if ((cmap.platform_id == FT_Common.TT_PLATFORM_MICROSOFT && cmap.encoding_id == FT_Common.TT_MS_ID_UCS_4) || + (cmap.platform_id == FT_Common.TT_PLATFORM_APPLE_UNICODE && cmap.encoding_id == FT_Common.TT_APPLE_ID_UNICODE_32)) + { + //#ifdef FT_MAX_CHARMAP_CACHEABLE + if (cur > FT_Common.FT_MAX_CHARMAP_CACHEABLE) + { + continue; + } + //#endif + face.charmap = face.charmaps[cur]; + return FT_Common.FT_Err_Ok; + } + } + } + cur = count - 1; + for ( ; cur >= 0; cur--) + { + var cmap = __FT_CharmapRec(face.charmaps[cur]); + if (cmap.encoding == FT_Common.FT_ENCODING_UNICODE) + { + //#ifdef FT_MAX_CHARMAP_CACHEABLE + if (cur > FT_Common.FT_MAX_CHARMAP_CACHEABLE) + { + continue; + } + //#endif + face.charmap = face.charmaps[cur]; + return FT_Common.FT_Err_Ok; + } + } + return FT_Common.FT_Err_Invalid_CharMap_Handle; +} +function ft_glyphslot_init(slot) +{ + var driver = slot.face.driver; + slot.library = driver.library; + slot.internal = new FT_Slot_Internal(); + + var error = 0; + if ((driver.flags & FT_Common.FT_MODULE_DRIVER_NO_OUTLINES) == 0) + slot.internal.loader = FT_GlyphLoader_New(driver.memory); + + if (driver.clazz.init_slot) + error = driver.clazz.init_slot(slot); + return error; +} +function ft_glyphslot_free_bitmap(slot) +{ + if (slot.internal != null && (slot.internal.flags & FT_Common.FT_GLYPH_OWN_BITMAP) != 0) + { + slot.bitmap.buffer = null; + slot.internal.flags &= ~FT_Common.FT_GLYPH_OWN_BITMAP; + } + else + { + slot.bitmap.buffer = null; + } +} +function ft_glyphslot_set_bitmap(slot, buffer) +{ + ft_glyphslot_free_bitmap(slot); + slot.bitmap.buffer = buffer; +} +function ft_glyphslot_alloc_bitmap(slot, size) +{ + if ((slot.internal.flags & FT_Common.FT_GLYPH_OWN_BITMAP) != 0) + slot.bitmap.buffer = null; + else + slot.internal.flags |= FT_Common.FT_GLYPH_OWN_BITMAP; + + slot.bitmap.buffer = g_memory.Alloc(size); + return 0; +} +function ft_glyphslot_clear(slot) +{ + ft_glyphslot_free_bitmap(slot); + + var metrics = slot.metrics; + metrics.width = 0; + metrics.height = 0; + metrics.horiBearingX = 0; + metrics.horiBearingY = 0; + metrics.horiAdvance = 0; + metrics.vertBearingX = 0; + metrics.vertBearingY = 0; + metrics.vertAdvance = 0; + + var outl = slot.outline; + outl.n_contours = 0; + outl.n_points = 0; + outl.contours = null; + outl.points = null; + outl.tags = null; + outl.flags = 0; + + slot.bitmap.width = 0; + slot.bitmap.rows = 0; + slot.bitmap.pitch = 0; + slot.bitmap.pixel_mode = 0; + + slot.bitmap_left = 0; + slot.bitmap_top = 0; + slot.num_subglyphs = 0; + slot.subglyphs = 0; + slot.control_data = 0; + slot.control_len = 0; + slot.other = 0; + slot.format = FT_Common.FT_GLYPH_FORMAT_NONE; + + slot.linearHoriAdvance = 0; + slot.linearVertAdvance = 0; + slot.lsb_delta = 0; + slot.rsb_delta = 0; +} +function ft_glyphslot_done(slot) +{ + var clazz = slot.face.driver.clazz; + if (clazz.done_slot != null) + clazz.done_slot(slot); + + ft_glyphslot_free_bitmap(slot); + slot.internal = null; +} +function ft_glyphslot_grid_fit_metrics(slot, vertical) +{ + var metrics = slot.metrics; + var right, bottom; + + if (1 == vertical) + { + metrics.horiBearingX = FT_PIX_FLOOR(metrics.horiBearingX); + metrics.horiBearingY = FT_PIX_CEIL (metrics.horiBearingY); + + right = FT_PIX_CEIL(metrics.vertBearingX + metrics.width); + bottom = FT_PIX_CEIL(metrics.vertBearingY + metrics.height); + + metrics.vertBearingX = FT_PIX_FLOOR(metrics.vertBearingX); + metrics.vertBearingY = FT_PIX_FLOOR(metrics.vertBearingY); + + metrics.width = right - metrics.vertBearingX; + metrics.height = bottom - metrics.vertBearingY; + } + else + { + metrics.vertBearingX = FT_PIX_FLOOR(metrics.vertBearingX); + metrics.vertBearingY = FT_PIX_FLOOR(metrics.vertBearingY); + + right = FT_PIX_CEIL (metrics.horiBearingX + metrics.width); + bottom = FT_PIX_FLOOR(metrics.horiBearingY - metrics.height); + + metrics.horiBearingX = FT_PIX_FLOOR(metrics.horiBearingX); + metrics.horiBearingY = FT_PIX_CEIL (metrics.horiBearingY); + + metrics.width = right - metrics.horiBearingX; + metrics.height = metrics.horiBearingY - bottom; + } + + metrics.horiAdvance = FT_PIX_ROUND(metrics.horiAdvance); + metrics.vertAdvance = FT_PIX_ROUND(metrics.vertAdvance); +} +function ft_synthesize_vertical_metrics(metrics, advance) +{ + var height = metrics.height; + + /* compensate for glyph with bbox above/below the baseline */ + if (metrics.horiBearingY < 0) + { + if (height < metrics.horiBearingY) + height = metrics.horiBearingY; + } + else if (metrics.horiBearingY > 0) + height -= metrics.horiBearingY; + + /* the factor 1.2 is a heuristical value */ + if (advance == 0) + advance = parseInt(height * 12 / 10); + + metrics.vertBearingX = parseInt(metrics.horiBearingX - metrics.horiAdvance / 2); + metrics.vertBearingY = parseInt((advance - height) / 2); + metrics.vertAdvance = advance; +} \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/config.js b/Common/FontsFreeType/Private/FreeType/config.js new file mode 100644 index 0000000000000000000000000000000000000000..e130ff0eeea752aaad3044ec43f62d104f6a6e1b --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/config.js @@ -0,0 +1,1078 @@ +function FT_MAKE_TAG(a,b,c,d) +{ + var r = a.charCodeAt(0) << 24 | b.charCodeAt(0) << 16 | c.charCodeAt(0) << 8 | d.charCodeAt(0); + if (r < 0) + r+=FT_Common.a_i; + return r; +} +function _FT_Common() +{ +// GENERATOR_START_CONSTANTS + this.FT_ENCODING_NONE = 0; + + this.FT_ENCODING_MS_SYMBOL = FT_MAKE_TAG("s","y","m","b"); + this.FT_ENCODING_UNICODE = FT_MAKE_TAG("u","n","i","c"); + + this.FT_ENCODING_SJIS = FT_MAKE_TAG("s","j","i","s"); + this.FT_ENCODING_GB2312 = FT_MAKE_TAG("g","b"," "," "); + this.FT_ENCODING_BIG5 = FT_MAKE_TAG("b","i","g","5"); + this.FT_ENCODING_WANSUNG = FT_MAKE_TAG("w","a","n","s"); + this.FT_ENCODING_JOHAB = FT_MAKE_TAG("j","o","h","a"); + + /* for backwards compatibility */ + this.FT_ENCODING_MS_SJIS = this.FT_ENCODING_SJIS; + this.FT_ENCODING_MS_GB2312 = this.FT_ENCODING_GB2312; + this.FT_ENCODING_MS_BIG5 = this.FT_ENCODING_BIG5; + this.FT_ENCODING_MS_WANSUNG = this.FT_ENCODING_WANSUNG; + this.FT_ENCODING_MS_JOHAB = this.FT_ENCODING_JOHAB; + + this.FT_ENCODING_ADOBE_STANDARD = FT_MAKE_TAG("A","D","O","B"); + this.FT_ENCODING_ADOBE_EXPERT = FT_MAKE_TAG("A","D","B","E"); + this.FT_ENCODING_ADOBE_CUSTOM = FT_MAKE_TAG("A","D","B","C"); + this.FT_ENCODING_ADOBE_LATIN_1 = FT_MAKE_TAG("l","a","t","1"); + + this.FT_ENCODING_OLD_LATIN_2 = FT_MAKE_TAG("l","a","t","2"); + + this.FT_ENCODING_APPLE_ROMAN = FT_MAKE_TAG("a","r","m","n"); + + // modules types + this.FT_MODULE_FONT_DRIVER = 1; + this.FT_MODULE_RENDERER = 2; + this.FT_MODULE_HINTER = 4; + this.FT_MODULE_STYLER = 8; + + this.FT_MODULE_DRIVER_SCALABLE = 0x100; + this.FT_MODULE_DRIVER_NO_OUTLINES = 0x200; + this.FT_MODULE_DRIVER_HAS_HINTER = 0x400; + + // errors codes + this.FT_Err_Ok = 0x00; + this.FT_Err_Cannot_Open_Resource = 0x01; + this.FT_Err_Unknown_File_Format = 0x02; + this.FT_Err_Invalid_File_Format = 0x03; + this.FT_Err_Invalid_Version = 0x04; + this.FT_Err_Lower_Module_Version = 0x05; + this.FT_Err_Invalid_Argument = 0x06; + this.FT_Err_Unimplemented_Feature = 0x07; + this.FT_Err_Invalid_Table = 0x08; + this.FT_Err_Invalid_Offset = 0x09; + this.FT_Err_Array_Too_Large = 0x0A; + + /* glyph/character errors */ + this.FT_Err_Invalid_Glyph_Index = 0x10; + this.FT_Err_Invalid_Character_Code = 0x11; + this.FT_Err_Invalid_Glyph_Format = 0x12; + this.FT_Err_Cannot_Render_Glyph = 0x13; + this.FT_Err_Invalid_Outline = 0x14; + this.FT_Err_Invalid_Composite = 0x15; + this.FT_Err_Too_Many_Hints = 0x16; + this.FT_Err_Invalid_Pixel_Size = 0x17; + + /* handle errors */ + this.FT_Err_Invalid_Handle = 0x20; + this.FT_Err_Invalid_Library_Handle = 0x21; + this.FT_Err_Invalid_Driver_Handle = 0x22; + this.FT_Err_Invalid_Face_Handle = 0x23; + this.FT_Err_Invalid_Size_Handle = 0x24; + this.FT_Err_Invalid_Slot_Handle = 0x25; + this.FT_Err_Invalid_CharMap_Handle = 0x26; + this.FT_Err_Invalid_Cache_Handle = 0x27; + this.FT_Err_Invalid_Stream_Handle = 0x28; + + /* driver errors */ + this.FT_Err_Too_Many_Drivers = 0x30; + this.FT_Err_Too_Many_Extensions = 0x31; + /* memory errors */ + + this.FT_Err_Out_Of_Memory = 0x40; + this.FT_Err_Unlisted_Object = 0x41; + + /* stream errors */ + this.FT_Err_Cannot_Open_Stream = 0x51; + this.FT_Err_Invalid_Stream_Seek = 0x52; + this.FT_Err_Invalid_Stream_Skip = 0x53; + this.FT_Err_Invalid_Stream_Read = 0x54; + this.FT_Err_Invalid_Stream_Operation = 0x55; + this.FT_Err_Invalid_Frame_Operation = 0x56; + this.FT_Err_Nested_Frame_Access = 0x57; + this.FT_Err_Invalid_Frame_Read = 0x58; + + /* raster errors */ + this.FT_Err_Raster_Uninitialized = 0x60; + this.FT_Err_Raster_Corrupted = 0x61; + this.FT_Err_Raster_Overflow = 0x62; + this.FT_Err_Raster_Negative_Height = 0x63; + + /* cache errors */ + this.FT_Err_Too_Many_Caches = 0x70; + + /* TrueType and SFNT errors */ + this.FT_Err_Invalid_Opcode = 0x80; + this.FT_Err_Too_Few_Arguments = 0x81; + this.FT_Err_Stack_Overflow = 0x82; + this.FT_Err_Code_Overflow = 0x83; + this.FT_Err_Bad_Argument = 0x84; + this.FT_Err_Divide_By_Zero = 0x85; + this.FT_Err_Invalid_Reference = 0x86; + this.FT_Err_Debug_OpCode = 0x87; + this.FT_Err_ENDF_In_Exec_Stream = 0x88; + this.FT_Err_Nested_DEFS = 0x89; + this.FT_Err_Invalid_CodeRange = 0x8A; + this.FT_Err_Execution_Too_Long = 0x8B; + this.FT_Err_Too_Many_Function_Defs = 0x8C; + this.FT_Err_Too_Many_Instruction_Defs = 0x8D; + this.FT_Err_Table_Missing = 0x8E; + this.FT_Err_Horiz_Header_Missing = 0x8F; + this.FT_Err_Locations_Missing = 0x90; + this.FT_Err_Name_Table_Missing = 0x91; + this.FT_Err_CMap_Table_Missing = 0x92; + this.FT_Err_Hmtx_Table_Missing = 0x93; + this.FT_Err_Post_Table_Missing = 0x94; + this.FT_Err_Invalid_Horiz_Metrics = 0x95; + this.FT_Err_Invalid_CharMap_Format = 0x96; + this.FT_Err_Invalid_PPem = 0x97; + this.FT_Err_Invalid_Vert_Metrics = 0x98; + this.FT_Err_Could_Not_Find_Context = 0x99; + this.FT_Err_Invalid_Post_Table_Format = 0x9A; + this.FT_Err_Invalid_Post_Table = 0x9B; + + /* CFF, CID, and Type 1 errors */ + this.FT_Err_Syntax_Error = 0xA0; + this.FT_Err_Stack_Underflow = 0xA1; + this.FT_Err_Ignore = 0xA2; + this.FT_Err_No_Unicode_Glyph_Name = 0xA3; + + /* BDF errors */ + this.FT_Err_Missing_Startfont_Field = 0xB0; + this.FT_Err_Missing_Font_Field = 0xB1; + this.FT_Err_Missing_Size_Field = 0xB2; + this.FT_Err_Missing_Fontboundingbox_Field = 0xB3; + this.FT_Err_Missing_Chars_Field = 0xB4; + this.FT_Err_Missing_Startchar_Field = 0xB5; + this.FT_Err_Missing_Encoding_Field = 0xB6; + this.FT_Err_Missing_Bbx_Field = 0xB7; + this.FT_Err_Bbx_Too_Big = 0xB8; + this.FT_Err_Corrupted_Font_Header = 0xB9; + this.FT_Err_Corrupted_Font_Glyphs = 0xBA; + + this.FT_Mod_Err = 0x100; + + // + this.BDF_PROPERTY_TYPE_NONE = 0; + this.BDF_PROPERTY_TYPE_ATOM = 1; + this.BDF_PROPERTY_TYPE_INTEGER = 2; + this.BDF_PROPERTY_TYPE_CARDINAL = 3; + + // + this.TT_CMAP_FLAG_UNSORTED = 1; + this.TT_CMAP_FLAG_OVERLAPPING = 2; + + this.m_c = 0x7F; + this.m_s = 0x7FFF; + this.m_i = 0x7FFFFFFF; + this.a_c = 0xFF + 1; + this.a_s = 0xFFFF + 1; + this.a_i = 0xFFFFFFFF + 1; + + // base + this.FT_MAX_CHARMAP_CACHEABLE = 15; + + this.TT_PLATFORM_APPLE_UNICODE = 0; + this.TT_PLATFORM_MACINTOSH = 1; + this.TT_PLATFORM_ISO = 2; + this.TT_PLATFORM_MICROSOFT = 3; + this.TT_PLATFORM_CUSTOM = 4; + this.TT_PLATFORM_ADOBE = 7; + + // + this.TT_MAC_ID_ROMAN = 0; + // + this.TT_MS_ID_SYMBOL_CS = 0; + this.TT_MS_ID_UNICODE_CS = 1; + this.TT_MS_ID_SJIS = 2; + this.TT_MS_ID_GB2312 = 3; + this.TT_MS_ID_BIG_5 = 4; + this.TT_MS_ID_WANSUNG = 5; + this.TT_MS_ID_JOHAB = 6; + this.TT_MS_ID_UCS_4 = 10; + + this.TT_APPLE_ID_DEFAULT = 0; + this.TT_APPLE_ID_UNICODE_1_1 = 1; + this.TT_APPLE_ID_ISO_10646 = 2; + this.TT_APPLE_ID_UNICODE_2_0 = 3; + this.TT_APPLE_ID_UNICODE_32 = 4; + this.TT_APPLE_ID_VARIANT_SELECTOR = 5; + + // true type tags + this.TTAG_avar = FT_MAKE_TAG("a","v","a","r"); + this.TTAG_BASE = FT_MAKE_TAG("B","A","S","E"); + this.TTAG_bdat = FT_MAKE_TAG("b","d","a","t"); + this.TTAG_BDF = FT_MAKE_TAG("B","D","F"," "); + this.TTAG_bhed = FT_MAKE_TAG("b","h","e","d"); + this.TTAG_bloc = FT_MAKE_TAG("b","l","o","c"); + this.TTAG_bsln = FT_MAKE_TAG("b","s","l","n"); + this.TTAG_CFF = FT_MAKE_TAG("C","F","F"," "); + this.TTAG_CID = FT_MAKE_TAG("C","I","D"," "); + this.TTAG_cmap = FT_MAKE_TAG("c","m","a","p"); + this.TTAG_cvar = FT_MAKE_TAG("c","v","a","r"); + this.TTAG_cvt = FT_MAKE_TAG("c","v","t"," "); + this.TTAG_DSIG = FT_MAKE_TAG("D","S","I","G"); + this.TTAG_EBDT = FT_MAKE_TAG("E","B","D","T"); + this.TTAG_EBLC = FT_MAKE_TAG("E","B","L","C"); + this.TTAG_EBSC = FT_MAKE_TAG("E","B","S","C"); + this.TTAG_feat = FT_MAKE_TAG("f","e","a","t"); + this.TTAG_FOND = FT_MAKE_TAG("F","O","N","D"); + this.TTAG_fpgm = FT_MAKE_TAG("f","p","g","m"); + this.TTAG_fvar = FT_MAKE_TAG("f","v","a","r"); + this.TTAG_gasp = FT_MAKE_TAG("g","a","s","p"); + this.TTAG_GDEF = FT_MAKE_TAG("G","D","E","F"); + this.TTAG_glyf = FT_MAKE_TAG("g","l","y","f"); + this.TTAG_GPOS = FT_MAKE_TAG("G","P","O","S"); + this.TTAG_GSUB = FT_MAKE_TAG("G","S","U","B"); + this.TTAG_gvar = FT_MAKE_TAG("g","v","a","r"); + this.TTAG_hdmx = FT_MAKE_TAG("h","d","m","x"); + this.TTAG_head = FT_MAKE_TAG("h","e","a","d"); + this.TTAG_hhea = FT_MAKE_TAG("h","h","e","a"); + this.TTAG_hmtx = FT_MAKE_TAG("h","m","t","x"); + this.TTAG_JSTF = FT_MAKE_TAG("J","S","T","F"); + this.TTAG_just = FT_MAKE_TAG("j","u","s","t"); + this.TTAG_kern = FT_MAKE_TAG("k","e","r","n"); + this.TTAG_lcar = FT_MAKE_TAG("l","c","a","r"); + this.TTAG_loca = FT_MAKE_TAG("l","o","c","a"); + this.TTAG_LTSH = FT_MAKE_TAG("L","T","S","H"); + this.TTAG_LWFN = FT_MAKE_TAG("L","W","F","N"); + this.TTAG_MATH = FT_MAKE_TAG("M","A","T","H"); + this.TTAG_maxp = FT_MAKE_TAG("m","a","x","p"); + this.TTAG_META = FT_MAKE_TAG("M","E","T","A"); + this.TTAG_MMFX = FT_MAKE_TAG("M","M","F","X"); + this.TTAG_MMSD = FT_MAKE_TAG("M","M","S","D"); + this.TTAG_mort = FT_MAKE_TAG("m","o","r","t"); + this.TTAG_morx = FT_MAKE_TAG("m","o","r","x"); + this.TTAG_name = FT_MAKE_TAG("n","a","m","e"); + this.TTAG_opbd = FT_MAKE_TAG("o","p","b","d"); + this.TTAG_OS2 = FT_MAKE_TAG("O","S","/","2"); + this.TTAG_OTTO = FT_MAKE_TAG("O","T","T","O"); + this.TTAG_PCLT = FT_MAKE_TAG("P","C","L","T"); + this.TTAG_POST = FT_MAKE_TAG("P","O","S","T"); + this.TTAG_post = FT_MAKE_TAG("p","o","s","t"); + this.TTAG_prep = FT_MAKE_TAG("p","r","e","p"); + this.TTAG_prop = FT_MAKE_TAG("p","r","o","p"); + this.TTAG_sfnt = FT_MAKE_TAG("s","f","n","t"); + this.TTAG_SING = FT_MAKE_TAG("S","I","N","G"); + this.TTAG_trak = FT_MAKE_TAG("t","r","a","k"); + this.TTAG_true = FT_MAKE_TAG("t","r","u","e"); + this.TTAG_ttc = FT_MAKE_TAG("t","t","c"," "); + this.TTAG_ttcf = FT_MAKE_TAG("t","t","c","f"); + this.TTAG_TYP1 = FT_MAKE_TAG("T","Y","P","1"); + this.TTAG_typ1 = FT_MAKE_TAG("t","y","p","1"); + this.TTAG_VDMX = FT_MAKE_TAG("V","D","M","X"); + this.TTAG_vhea = FT_MAKE_TAG("v","h","e","a"); + this.TTAG_vmtx = FT_MAKE_TAG("v","m","t","x"); + + // + this.FT_FACE_FLAG_SCALABLE = (1 << 0); + this.FT_FACE_FLAG_FIXED_SIZES = (1 << 1); + this.FT_FACE_FLAG_FIXED_WIDTH = (1 << 2); + this.FT_FACE_FLAG_SFNT = (1 << 3); + this.FT_FACE_FLAG_HORIZONTAL = (1 << 4); + this.FT_FACE_FLAG_VERTICAL = (1 << 5); + this.FT_FACE_FLAG_KERNING = (1 << 6); + this.FT_FACE_FLAG_FAST_GLYPHS = (1 << 7); + this.FT_FACE_FLAG_MULTIPLE_MASTERS = (1 << 8); + this.FT_FACE_FLAG_GLYPH_NAMES = (1 << 9); + this.FT_FACE_FLAG_EXTERNAL_STREAM = (1 << 10); + this.FT_FACE_FLAG_HINTER = (1 << 11); + this.FT_FACE_FLAG_CID_KEYED = (1 << 12); + this.FT_FACE_FLAG_TRICKY = (1 << 13); + + this.FT_SIZE_REQUEST_TYPE_NOMINAL = 0; + this.FT_SIZE_REQUEST_TYPE_REAL_DIM = 1; + this.FT_SIZE_REQUEST_TYPE_BBOX = 2; + this.FT_SIZE_REQUEST_TYPE_CELL = 3; + this.FT_SIZE_REQUEST_TYPE_SCALES = 4; + this.FT_SIZE_REQUEST_TYPE_MAX = 5; + + this.FT_LOAD_DEFAULT = 0x0; + this.FT_LOAD_NO_SCALE = 0x1; + this.FT_LOAD_NO_HINTING = 0x2; + this.FT_LOAD_RENDER = 0x4; + this.FT_LOAD_NO_BITMAP = 0x8; + this.FT_LOAD_VERTICAL_LAYOUT = 0x10; + this.FT_LOAD_FORCE_AUTOHINT = 0x20; + this.FT_LOAD_CROP_BITMAP = 0x40; + this.FT_LOAD_PEDANTIC = 0x80; + this.FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH = 0x200; + this.FT_LOAD_NO_RECURSE = 0x400; + this.FT_LOAD_IGNORE_TRANSFORM = 0x800; + this.FT_LOAD_MONOCHROME = 0x1000; + this.FT_LOAD_LINEAR_DESIGN = 0x2000; + this.FT_LOAD_NO_AUTOHINT = 0x8000; + + this.FT_GLYPH_FORMAT_NONE = 0; + this.FT_GLYPH_FORMAT_COMPOSITE = FT_MAKE_TAG("c","o","m","p"); + this.FT_GLYPH_FORMAT_BITMAP = FT_MAKE_TAG("b","i","t","s"); + this.FT_GLYPH_FORMAT_OUTLINE = FT_MAKE_TAG("o","u","t","l"); + this.FT_GLYPH_FORMAT_PLOTTER = FT_MAKE_TAG("p","l","o","t"); + + this.FT_RENDER_MODE_NORMAL = 0; + this.FT_RENDER_MODE_LIGHT = 1; + this.FT_RENDER_MODE_MONO = 2; + this.FT_RENDER_MODE_LCD = 3; + this.FT_RENDER_MODE_LCD_V = 4; + this.FT_RENDER_MODE_MAX = 5; + + this.FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS = 1; + this.FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES = 2; + this.FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID = 4; + this.FT_SUBGLYPH_FLAG_SCALE = 8; + this.FT_SUBGLYPH_FLAG_XY_SCALE = 0x40; + this.FT_SUBGLYPH_FLAG_2X2 = 0x80; + this.FT_SUBGLYPH_FLAG_USE_MY_METRICS = 0x200; + + this.FT_LOAD_ADVANCE_ONLY = 0x100; + this.FT_LOAD_SBITS_ONLY = 0x4000; + + this.FT_KERNING_DEFAULT = 0; + this.FT_KERNING_UNFITTED = 1; + this.FT_KERNING_UNSCALED = 2; + + // + this.TT_NAME_ID_COPYRIGHT = 0; + this.TT_NAME_ID_FONT_FAMILY = 1; + this.TT_NAME_ID_FONT_SUBFAMILY = 2; + this.TT_NAME_ID_UNIQUE_ID = 3; + this.TT_NAME_ID_FULL_NAME = 4; + this.TT_NAME_ID_VERSION_STRING = 5; + this.TT_NAME_ID_PS_NAME = 6; + this.TT_NAME_ID_TRADEMARK = 7; + + this.TT_NAME_ID_MANUFACTURER = 8; + this.TT_NAME_ID_DESIGNER = 9; + this.TT_NAME_ID_DESCRIPTION = 10; + this.TT_NAME_ID_VENDOR_URL = 11; + this.TT_NAME_ID_DESIGNER_URL = 12; + this.TT_NAME_ID_LICENSE = 13; + this.TT_NAME_ID_LICENSE_URL = 14; + + this.TT_NAME_ID_PREFERRED_FAMILY = 16; + this.TT_NAME_ID_PREFERRED_SUBFAMILY = 17; + this.TT_NAME_ID_MAC_FULL_NAME = 18; + + this.TT_NAME_ID_SAMPLE_TEXT = 19; + + this.TT_NAME_ID_CID_FINDFONT_NAME = 20; + + this.TT_NAME_ID_WWS_FAMILY = 21; + this.TT_NAME_ID_WWS_SUBFAMILY = 22; + + // + this.FT_STYLE_FLAG_ITALIC = 1; + this.FT_STYLE_FLAG_BOLD = 2; + + // + this.FT_RASTER_FLAG_DEFAULT = 0; + this.FT_RASTER_FLAG_AA = 1; + this.FT_RASTER_FLAG_DIRECT = 2; + this.FT_RASTER_FLAG_CLIP = 4; + + // + this.FT_CURVE_TAG_ON = 1; + this.FT_CURVE_TAG_CONIC = 0; + this.FT_CURVE_TAG_CUBIC = 2; + + // + this.FT_OUTLINE_NONE = 0x0; + this.FT_OUTLINE_OWNER = 0x1; + this.FT_OUTLINE_EVEN_ODD_FILL = 0x2; + this.FT_OUTLINE_REVERSE_FILL = 0x4; + this.FT_OUTLINE_IGNORE_DROPOUTS = 0x8; + this.FT_OUTLINE_SMART_DROPOUTS = 0x10; + this.FT_OUTLINE_INCLUDE_STUBS = 0x20; + + this.FT_OUTLINE_HIGH_PRECISION = 0x100; + this.FT_OUTLINE_SINGLE_PASS = 0x200; + + // + this.FT_GLYPH_OWN_BITMAP = 0x1; + + // + this.FT_PIXEL_MODE_NONE = 0; + this.FT_PIXEL_MODE_MONO = 1; + this.FT_PIXEL_MODE_GRAY = 2; + this.FT_PIXEL_MODE_GRAY2 = 3; + this.FT_PIXEL_MODE_GRAY4 = 4; + this.FT_PIXEL_MODE_LCD = 5; + this.FT_PIXEL_MODE_LCD_V = 6; + this.FT_PIXEL_MODE_MAX = 7; + + this.ErrorLongJump = -100; + + // + this.FT_GLYPH_BBOX_UNSCALED = 0; + this.FT_GLYPH_BBOX_SUBPIXELS = 0; + this.FT_GLYPH_BBOX_GRIDFIT = 1; + this.FT_GLYPH_BBOX_TRUNCATE = 2; + this.FT_GLYPH_BBOX_PIXELS = 3; + + // GX_TupleCountFlags + this.GX_TC_TUPLES_SHARE_POINT_NUMBERS = 0x8000; + this.GX_TC_RESERVED_TUPLE_FLAGS = 0x7000; + this.GX_TC_TUPLE_COUNT_MASK = 0x0FFF; + + // GX_TupleIndexFlags + this.GX_TI_EMBEDDED_TUPLE_COORD = 0x8000; + this.GX_TI_INTERMEDIATE_TUPLE = 0x4000; + this.GX_TI_PRIVATE_POINT_NUMBERS = 0x2000; + this.GX_TI_RESERVED_TUPLE_FLAG = 0x1000; + this.GX_TI_TUPLE_INDEX_MASK = 0x0FFF; + + // + this.TTAG_wght = FT_MAKE_TAG("w","g","h","t"); + this.TTAG_wdth = FT_MAKE_TAG("w","d","t","h"); + this.TTAG_opsz = FT_MAKE_TAG("o","p","s","z"); + this.TTAG_slnt = FT_MAKE_TAG("s","l","n","t"); + + // + this.FT_PARAM_TAG_UNPATENTED_HINTING = FT_MAKE_TAG("u","n","p","a"); + + // Ñто Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð° ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° cmap + this.FT_CMAP_0 = 0; + this.FT_CMAP_1 = 1; + this.FT_CMAP_4 = 2; + this.FT_CMAP_12 = 3; + this.FT_CMAP_13 = 4; + this.FT_CMAP_14 = 5; + + // t1types + this.T1_BLEND_UNDERLINE_POSITION = 0; + this.T1_BLEND_UNDERLINE_THICKNESS = 1; + this.T1_BLEND_ITALIC_ANGLE = 2; + + this.T1_BLEND_BLUE_VALUES = 3; + this.T1_BLEND_OTHER_BLUES = 4; + this.T1_BLEND_STANDARD_WIDTH = 5; + this.T1_BLEND_STANDARD_HEIGHT = 6; + this.T1_BLEND_STEM_SNAP_WIDTHS = 7; + this.T1_BLEND_STEM_SNAP_HEIGHTS = 8; + this.T1_BLEND_BLUE_SCALE = 9; + this.T1_BLEND_BLUE_SHIFT = 10; + this.T1_BLEND_FAMILY_BLUES = 11; + this.T1_BLEND_FAMILY_OTHER_BLUES = 12; + this.T1_BLEND_FORCE_BOLD = 13; + this.T1_BLEND_MAX = 14; + + this.T1_MAX_MM_DESIGNS = 16; + this.T1_MAX_MM_AXIS = 4; + this.T1_MAX_MM_MAP_POINTS = 20; + + this.T1_ENCODING_TYPE_NONE = 0; + this.T1_ENCODING_TYPE_ARRAY = 1; + this.T1_ENCODING_TYPE_STANDARD = 2; + this.T1_ENCODING_TYPE_ISOLATIN1 = 3; + this.T1_ENCODING_TYPE_EXPERT = 4; + + // keys + this.PS_DICT_FONT_TYPE = 0; + this.PS_DICT_FONT_MATRIX = 1; + this.PS_DICT_FONT_BBOX = 2; + this.PS_DICT_PAINT_TYPE = 3; + this.PS_DICT_FONT_NAME = 4; + this.PS_DICT_UNIQUE_ID = 5; + this.PS_DICT_NUM_CHAR_STRINGS = 6; + this.PS_DICT_CHAR_STRING_KEY = 7; + this.PS_DICT_CHAR_STRING = 8; + this.PS_DICT_ENCODING_TYPE = 9; + this.PS_DICT_ENCODING_ENTRY = 10; + + /* conventionally in the font Private dictionary */ + this.PS_DICT_NUM_SUBRS = 11; + this.PS_DICT_SUBR = 12; + this.PS_DICT_STD_HW = 13; + this.PS_DICT_STD_VW = 14; + this.PS_DICT_NUM_BLUE_VALUES = 15; + this.PS_DICT_BLUE_VALUE = 16; + this.PS_DICT_BLUE_FUZZ = 17; + this.PS_DICT_NUM_OTHER_BLUES = 18; + this.PS_DICT_OTHER_BLUE = 19; + this.PS_DICT_NUM_FAMILY_BLUES = 20; + this.PS_DICT_FAMILY_BLUE = 21; + this.PS_DICT_NUM_FAMILY_OTHER_BLUES = 22; + this.PS_DICT_FAMILY_OTHER_BLUE = 23; + this.PS_DICT_BLUE_SCALE = 24; + this.PS_DICT_BLUE_SHIFT = 25; + this.PS_DICT_NUM_STEM_SNAP_H = 26; + this.PS_DICT_STEM_SNAP_H = 27; + this.PS_DICT_NUM_STEM_SNAP_V = 28; + this.PS_DICT_STEM_SNAP_V = 29; + this.PS_DICT_FORCE_BOLD = 30; + this.PS_DICT_RND_STEM_UP = 31; + this.PS_DICT_MIN_FEATURE = 32; + this.PS_DICT_LEN_IV = 33; + this.PS_DICT_PASSWORD = 34; + this.PS_DICT_LANGUAGE_GROUP = 35; + + /* conventionally in the font FontInfo dictionary */ + this.PS_DICT_VERSION = 36; + this.PS_DICT_NOTICE = 37; + this.PS_DICT_FULL_NAME = 38; + this.PS_DICT_FAMILY_NAME = 39; + this.PS_DICT_WEIGHT = 40; + this.PS_DICT_IS_FIXED_PITCH = 41; + this.PS_DICT_UNDERLINE_POSITION = 42; + this.PS_DICT_UNDERLINE_THICKNESS = 43; + this.PS_DICT_FS_TYPE = 44; + this.PS_DICT_ITALIC_ANGLE = 45; + + this.PS_DICT_MAX = this.PS_DICT_ITALIC_ANGLE; + + this.TT_ADOBE_ID_STANDARD = 0; + this.TT_ADOBE_ID_EXPERT = 1; + this.TT_ADOBE_ID_CUSTOM = 2; + this.TT_ADOBE_ID_LATIN_1 = 3; + + // PSAUX + this.T1_TOKEN_TYPE_NONE = 0; + this.T1_TOKEN_TYPE_ANY = 1; + this.T1_TOKEN_TYPE_STRING = 2; + this.T1_TOKEN_TYPE_ARRAY = 3; + this.T1_TOKEN_TYPE_KEY = 4; + this.T1_TOKEN_TYPE_MAX = 5; + + this.T1_FIELD_TYPE_NONE = 0; + this.T1_FIELD_TYPE_BOOL = 1; + this.T1_FIELD_TYPE_INTEGER = 2; + this.T1_FIELD_TYPE_FIXED = 3; + this.T1_FIELD_TYPE_FIXED_1000 = 4; + this.T1_FIELD_TYPE_STRING = 5; + this.T1_FIELD_TYPE_KEY = 6; + this.T1_FIELD_TYPE_BBOX = 7; + this.T1_FIELD_TYPE_INTEGER_ARRAY = 8; + this.T1_FIELD_TYPE_FIXED_ARRAY = 9; + this.T1_FIELD_TYPE_CALLBACK = 10; + this.T1_FIELD_TYPE_MAX = 11; + + this.T1_FIELD_LOCATION_CID_INFO = 0; + this.T1_FIELD_LOCATION_FONT_DICT = 1; + this.T1_FIELD_LOCATION_FONT_EXTRA = 2; + this.T1_FIELD_LOCATION_FONT_INFO = 3; + this.T1_FIELD_LOCATION_PRIVATE = 4; + this.T1_FIELD_LOCATION_BBOX = 5; + this.T1_FIELD_LOCATION_LOADER = 6; + this.T1_FIELD_LOCATION_FACE = 7; + this.T1_FIELD_LOCATION_BLEND = 8; + this.T1_FIELD_LOCATION_MAX = 9; + + this.T1_FIELD_DICT_FONTDICT = 1; + this.T1_FIELD_DICT_PRIVATE = 2; + + this.T1_Parse_Start = 0; + this.T1_Parse_Have_Width = 1; + this.T1_Parse_Have_Moveto = 2; + this.T1_Parse_Have_Path = 3; + + this.T1_MAX_CHARSTRINGS_OPERANDS = 256; + + this.AFM_VALUE_TYPE_STRING = 0; + this.AFM_VALUE_TYPE_NAME = 1; + this.AFM_VALUE_TYPE_FIXED = 2; + this.AFM_VALUE_TYPE_INTEGER = 3; + this.AFM_VALUE_TYPE_BOOL = 4; + this.AFM_VALUE_TYPE_INDEX = 5; + + this.AFM_STREAM_STATUS_NORMAL = 0; + this.AFM_STREAM_STATUS_EOC = 1; + this.AFM_STREAM_STATUS_EOL = 2; + this.AFM_STREAM_STATUS_EOF = 3; + + this.AFM_MAX_ARGUMENTS = 5; + + this.AFM_TOKEN_ASCENDER = 0; + this.AFM_TOKEN_AXISLABEL = 1; + this.AFM_TOKEN_AXISTYPE = 2; + this.AFM_TOKEN_B = 3; + this.AFM_TOKEN_BLENDAXISTYPES = 4; + this.AFM_TOKEN_BLENDDESIGNMAP = 5; + this.AFM_TOKEN_BLENDDESIGNPOSITIONS = 6; + this.AFM_TOKEN_C = 7; + this.AFM_TOKEN_CC = 8; + this.AFM_TOKEN_CH = 9; + this.AFM_TOKEN_CAPHEIGHT = 10; + this.AFM_TOKEN_CHARWIDTH = 11; + this.AFM_TOKEN_CHARACTERSET = 12; + this.AFM_TOKEN_CHARACTERS = 13; + this.AFM_TOKEN_DESCENDER = 14; + this.AFM_TOKEN_ENCODINGSCHEME = 15; + this.AFM_TOKEN_ENDAXIS = 16; + this.AFM_TOKEN_ENDCHARMETRICS = 17; + this.AFM_TOKEN_ENDCOMPOSITES = 18; + this.AFM_TOKEN_ENDDIRECTION = 19; + this.AFM_TOKEN_ENDFONTMETRICS = 20; + this.AFM_TOKEN_ENDKERNDATA = 21; + this.AFM_TOKEN_ENDKERNPAIRS = 22; + this.AFM_TOKEN_ENDTRACKKERN = 23; + this.AFM_TOKEN_ESCCHAR = 24; + this.AFM_TOKEN_FAMILYNAME = 25; + this.AFM_TOKEN_FONTBBOX = 26; + this.AFM_TOKEN_FONTNAME = 27; + this.AFM_TOKEN_FULLNAME = 28; + this.AFM_TOKEN_ISBASEFONT = 29; + this.AFM_TOKEN_ISCIDFONT = 30; + this.AFM_TOKEN_ISFIXEDPITCH = 31; + this.AFM_TOKEN_ISFIXEDV = 32; + this.AFM_TOKEN_ITALICANGLE = 33; + this.AFM_TOKEN_KP = 34; + this.AFM_TOKEN_KPH = 35; + this.AFM_TOKEN_KPX = 36; + this.AFM_TOKEN_KPY = 37; + this.AFM_TOKEN_L = 38; + this.AFM_TOKEN_MAPPINGSCHEME = 39; + this.AFM_TOKEN_METRICSSETS = 40; + this.AFM_TOKEN_N = 41; + this.AFM_TOKEN_NOTICE = 42; + this.AFM_TOKEN_PCC = 43; + this.AFM_TOKEN_STARTAXIS = 44; + this.AFM_TOKEN_STARTCHARMETRICS = 45; + this.AFM_TOKEN_STARTCOMPOSITES = 46; + this.AFM_TOKEN_STARTDIRECTION = 47; + this.AFM_TOKEN_STARTFONTMETRICS = 48; + this.AFM_TOKEN_STARTKERNDATA = 49; + this.AFM_TOKEN_STARTKERNPAIRS = 50; + this.AFM_TOKEN_STARTKERNPAIRS0 = 51; + this.AFM_TOKEN_STARTKERNPAIRS1 = 52; + this.AFM_TOKEN_STARTTRACKKERN = 53; + this.AFM_TOKEN_STDHW = 54; + this.AFM_TOKEN_STDVW = 55; + this.AFM_TOKEN_TRACKKERN = 56; + this.AFM_TOKEN_UNDERLINEPOSITION = 57; + this.AFM_TOKEN_UNDERLINETHICKNESS = 58; + this.AFM_TOKEN_VV = 59; + this.AFM_TOKEN_VVECTOR = 60; + this.AFM_TOKEN_VERSION = 61; + this.AFM_TOKEN_W = 62; + this.AFM_TOKEN_W0 = 63; + this.AFM_TOKEN_W0X = 64; + this.AFM_TOKEN_W0Y = 65; + this.AFM_TOKEN_W1 = 66; + this.AFM_TOKEN_W1X = 67; + this.AFM_TOKEN_W1Y = 68; + this.AFM_TOKEN_WX = 69; + this.AFM_TOKEN_WY = 70; + this.AFM_TOKEN_WEIGHT = 71; + this.AFM_TOKEN_WEIGHTVECTOR = 72; + this.AFM_TOKEN_XHEIGHT = 73; + this.N_AFM_TOKENS = 74; + this.AFM_TOKEN_UNKNOWN = 75; + + this.T1_MAX_TABLE_ELEMENTS = 32; + this.T1_MAX_SUBRS_CALLS = 16; + + this.TABLE_EXTEND = 5; + + // конÑтанты Ñтроковые + this.SYMBOL_CONST_SR = "\r".charCodeAt(0); + this.SYMBOL_CONST_SN = "\n".charCodeAt(0); + this.SYMBOL_CONST_ST = "\t".charCodeAt(0); + this.SYMBOL_CONST_SF = "\f".charCodeAt(0); + this.SYMBOL_CONST_S0 = "\0".charCodeAt(0); + + this.SYMBOL_CONST_SPACE = " ".charCodeAt(0); + this.SYMBOL_CONST_LS1 = "(".charCodeAt(0); + this.SYMBOL_CONST_LS2 = "[".charCodeAt(0); + this.SYMBOL_CONST_LS3 = "{".charCodeAt(0); + this.SYMBOL_CONST_RS1 = ")".charCodeAt(0); + this.SYMBOL_CONST_RS2 = "]".charCodeAt(0); + this.SYMBOL_CONST_RS3 = "}".charCodeAt(0); + this.SYMBOL_CONST_BS = "/".charCodeAt(0); + this.SYMBOL_CONST_SS = "\\".charCodeAt(0); + + this.SYMBOL_CONST_MATH_1 = "<".charCodeAt(0); + this.SYMBOL_CONST_MATH_2 = ">".charCodeAt(0); + this.SYMBOL_CONST_MATH_3 = "%".charCodeAt(0); + this.SYMBOL_CONST_MATH_MINUS = "-".charCodeAt(0); + this.SYMBOL_CONST_MATH_PLUS = "+".charCodeAt(0); + + this.SYMBOL_CONST_0 = "0".charCodeAt(0); + this.SYMBOL_CONST_7 = "7".charCodeAt(0); + this.SYMBOL_CONST_9 = "9".charCodeAt(0); + + this.SYMBOL_CONST_a = "a".charCodeAt(0); + this.SYMBOL_CONST_b = "b".charCodeAt(0); + this.SYMBOL_CONST_c = "c".charCodeAt(0); + this.SYMBOL_CONST_d = "d".charCodeAt(0); + this.SYMBOL_CONST_e = "e".charCodeAt(0); + this.SYMBOL_CONST_f = "f".charCodeAt(0); + this.SYMBOL_CONST_g = "g".charCodeAt(0); + this.SYMBOL_CONST_h = "h".charCodeAt(0); + this.SYMBOL_CONST_i = "i".charCodeAt(0); + this.SYMBOL_CONST_j = "j".charCodeAt(0); + this.SYMBOL_CONST_k = "k".charCodeAt(0); + this.SYMBOL_CONST_l = "l".charCodeAt(0); + this.SYMBOL_CONST_m = "m".charCodeAt(0); + this.SYMBOL_CONST_n = "n".charCodeAt(0); + this.SYMBOL_CONST_o = "o".charCodeAt(0); + this.SYMBOL_CONST_p = "p".charCodeAt(0); + this.SYMBOL_CONST_q = "q".charCodeAt(0); + this.SYMBOL_CONST_r = "r".charCodeAt(0); + this.SYMBOL_CONST_s = "s".charCodeAt(0); + this.SYMBOL_CONST_t = "t".charCodeAt(0); + this.SYMBOL_CONST_u = "u".charCodeAt(0); + this.SYMBOL_CONST_v = "v".charCodeAt(0); + this.SYMBOL_CONST_w = "w".charCodeAt(0); + this.SYMBOL_CONST_x = "x".charCodeAt(0); + this.SYMBOL_CONST_y = "y".charCodeAt(0); + this.SYMBOL_CONST_z = "z".charCodeAt(0); + + this.SYMBOL_CONST_A = "A".charCodeAt(0); + this.SYMBOL_CONST_B = "B".charCodeAt(0); + this.SYMBOL_CONST_C = "C".charCodeAt(0); + this.SYMBOL_CONST_D = "D".charCodeAt(0); + this.SYMBOL_CONST_E = "E".charCodeAt(0); + this.SYMBOL_CONST_F = "F".charCodeAt(0); + this.SYMBOL_CONST_G = "G".charCodeAt(0); + this.SYMBOL_CONST_H = "H".charCodeAt(0); + this.SYMBOL_CONST_I = "I".charCodeAt(0); + this.SYMBOL_CONST_J = "J".charCodeAt(0); + this.SYMBOL_CONST_K = "K".charCodeAt(0); + this.SYMBOL_CONST_L = "L".charCodeAt(0); + this.SYMBOL_CONST_M = "M".charCodeAt(0); + this.SYMBOL_CONST_N = "N".charCodeAt(0); + this.SYMBOL_CONST_O = "O".charCodeAt(0); + this.SYMBOL_CONST_P = "P".charCodeAt(0); + this.SYMBOL_CONST_Q = "Q".charCodeAt(0); + this.SYMBOL_CONST_R = "R".charCodeAt(0); + this.SYMBOL_CONST_S = "S".charCodeAt(0); + this.SYMBOL_CONST_T = "T".charCodeAt(0); + this.SYMBOL_CONST_U = "U".charCodeAt(0); + this.SYMBOL_CONST_V = "V".charCodeAt(0); + this.SYMBOL_CONST_W = "W".charCodeAt(0); + this.SYMBOL_CONST_X = "X".charCodeAt(0); + this.SYMBOL_CONST_Y = "Y".charCodeAt(0); + this.SYMBOL_CONST_Z = "Z".charCodeAt(0); + + this.SYMBOL_CONST_VOSCL = "!".charCodeAt(0); + this.SYMBOL_CONST_VOPROS = "?".charCodeAt(0); + this.SYMBOL_CONST_LOGOR = "|".charCodeAt(0); + + this.SYMBOL_CONST_POINT = ".".charCodeAt(0); + this.SYMBOL_CONST_SHARP = "#".charCodeAt(0); + this.SYMBOL_CONST_SERP = ";".charCodeAt(0); + this.SYMBOL_CONST__ = "_".charCodeAt(0); + + this.op_none = 0; + this.op_endchar = 1; + this.op_hsbw = 2; + this.op_seac = 3; + this.op_sbw = 4; + this.op_closepath = 5; + this.op_hlineto = 6; + this.op_hmoveto = 7; + this.op_hvcurveto = 8; + this.op_rlineto = 9; + this.op_rmoveto = 10; + this.op_rrcurveto = 11; + this.op_vhcurveto = 12; + this.op_vlineto = 13; + this.op_vmoveto = 14; + this.op_dotsection = 15; + this.op_hstem = 16; + this.op_hstem3 = 17; + this.op_vstem = 18; + this.op_vstem3 = 19; + this.op_div = 20; + this.op_callothersubr = 21; + this.op_callsubr = 22; + this.op_pop = 23; + this.op_return = 24; + this.op_setcurrentpoint = 25; + this.op_unknown15 = 26; + this.op_max = 27; + + // cff + this.CFF_MAX_CID_FONTS = 256; + + this.CFF_MAX_STACK_DEPTH = 96; + + this.CFF_CODE_TOPDICT = 0x1000; + this.CFF_CODE_PRIVATE = 0x2000; + + this.CFFCODE_TOPDICT = 0x1000; + this.CFFCODE_PRIVATE = 0x2000; + + this.cff_kind_none = 0; + this.cff_kind_num = 1; + this.cff_kind_fixed = 2; + this.cff_kind_fixed_thousand = 3; + this.cff_kind_string = 4; + this.cff_kind_bool = 5; + this.cff_kind_delta = 6; + this.cff_kind_callback = 7; + this.cff_kind_max = 8; + + this.CFF_MAX_OPERANDS = 48; + this.CFF_MAX_SUBRS_CALLS = 32; + this.CFF_MAX_TRANS_ELEMENTS = 32; + + this.CFF_COUNT_CHECK_WIDTH = 0x80; + this.CFF_COUNT_EXACT = 0x40; + this.CFF_COUNT_CLEAR_STACK = 0x20; + + this.cff_op_unknown = 0; + + this.cff_op_rmoveto = 1; + this.cff_op_hmoveto = 2; + this.cff_op_vmoveto = 3; + + this.cff_op_rlineto = 4; + this.cff_op_hlineto = 5; + this.cff_op_vlineto = 6; + + this.cff_op_rrcurveto = 7; + this.cff_op_hhcurveto = 8; + this.cff_op_hvcurveto = 9; + this.cff_op_rcurveline = 10; + this.cff_op_rlinecurve = 11; + this.cff_op_vhcurveto = 12; + this.cff_op_vvcurveto = 13; + + this.cff_op_flex = 14; + this.cff_op_hflex = 15; + this.cff_op_hflex1 = 16; + this.cff_op_flex1 = 17; + + this.cff_op_endchar = 18; + + this.cff_op_hstem = 19; + this.cff_op_vstem = 20; + this.cff_op_hstemhm = 21; + this.cff_op_vstemhm = 22; + + this.cff_op_hintmask = 23; + this.cff_op_cntrmask = 24; + this.cff_op_dotsection = 25; + + this.cff_op_abs = 26; + this.cff_op_add = 27; + this.cff_op_sub = 28; + this.cff_op_div = 29; + this.cff_op_neg = 30; + this.cff_op_random = 31; + this.cff_op_mul = 32; + this.cff_op_sqrt = 33; + + this.cff_op_blend = 34; + + this.cff_op_drop = 35; + this.cff_op_exch = 36; + this.cff_op_index = 37; + this.cff_op_roll = 38; + this.cff_op_dup = 39; + + this.cff_op_put = 40; + this.cff_op_get = 41; + this.cff_op_store = 42; + this.cff_op_load = 43; + + this.cff_op_and = 44; + this.cff_op_or = 45; + this.cff_op_not = 46; + this.cff_op_eq = 47; + this.cff_op_ifelse = 48; + + this.cff_op_callsubr = 49; + this.cff_op_callgsubr = 50; + this.cff_op_return = 51; + + /* Type 1 opcodes: invalid but seen in real life */ + this.cff_op_hsbw = 52; + this.cff_op_closepath = 53; + this.cff_op_callothersubr = 54; + this.cff_op_pop = 55; + this.cff_op_seac = 56; + this.cff_op_sbw = 57; + this.cff_op_setcurrentpoint = 58; + + this.cff_op_max = 59; + + // t1 + this.T1_PRIVATE = 1; + this.T1_FONTDIR_AFTER_PRIVATE = 2; + + // ttinterp + this.TT_MAX_CODE_RANGES = 3; + + this.tt_coderange_none = 0; + this.tt_coderange_font = 1; + this.tt_coderange_cvt = 2; + this.tt_coderange_glyph = 3; + + this.SPH_OPTION_BITMAP_WIDTHS = false; + this.SPH_OPTION_SET_SUBPIXEL = true; + this.SPH_OPTION_SET_GRAYSCALE = false; + this.SPH_OPTION_SET_COMPATIBLE_WIDTHS = false; + this.SPH_OPTION_SET_RASTERIZER_VERSION = 38; + + this.SPH_TWEAK_ALLOW_X_DMOVE = 0x0000001; + this.SPH_TWEAK_ALLOW_X_DMOVEX = 0x0000002; + this.SPH_TWEAK_ALLOW_X_MOVE_ZP2 = 0x0000004; + this.SPH_TWEAK_ALWAYS_DO_DELTAP = 0x0000008; + this.SPH_TWEAK_ALWAYS_SKIP_DELTAP = 0x0000010; + this.SPH_TWEAK_COURIER_NEW_2_HACK = 0x0000020; + this.SPH_TWEAK_DEEMBOLDEN = 0x0000040; + this.SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES = 0x0000080; + this.SPH_TWEAK_DO_SHPIX = 0x0000100; + this.SPH_TWEAK_EMBOLDEN = 0x0000200; + this.SPH_TWEAK_MIAP_HACK = 0x0000400; + this.SPH_TWEAK_NORMAL_ROUND = 0x0000800; + this.SPH_TWEAK_NO_ALIGNRP_AFTER_IUP = 0x0001000; + this.SPH_TWEAK_NO_CALL_AFTER_IUP = 0x0002000; + this.SPH_TWEAK_NO_DELTAP_AFTER_IUP = 0x0004000; + this.SPH_TWEAK_PIXEL_HINTING = 0x0008000; + this.SPH_TWEAK_RASTERIZER_35 = 0x0010000; + this.SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES = 0x0020000; + this.SPH_TWEAK_SKIP_INLINE_DELTAS = 0x0040000; + this.SPH_TWEAK_SKIP_IUP = 0x0080000; + this.SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES = 0x0100000; + this.SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES = 0x0200000; + this.SPH_TWEAK_TIMES_NEW_ROMAN_HACK = 0x0400000; + this.SPH_TWEAK_MIRP_CVT_ZERO = 0x0800000; + + this.FT_CURVE_TAG_HAS_SCANMODE = 4; + this.FT_CURVE_TAG_TOUCH_X = 8; /* reserved for the TrueType hinter */ + this.FT_CURVE_TAG_TOUCH_Y = 16; /* reserved for the TrueType hinter */ + this.FT_CURVE_TAG_TOUCH_BOTH = (this.FT_CURVE_TAG_TOUCH_X | this.FT_CURVE_TAG_TOUCH_Y); + + this.FT_ORIENTATION_TRUETYPE = 0; + this.FT_ORIENTATION_POSTSCRIPT = 1; + this.FT_ORIENTATION_FILL_RIGHT = this.FT_ORIENTATION_TRUETYPE; + this.FT_ORIENTATION_FILL_LEFT = this.FT_ORIENTATION_POSTSCRIPT; + this.FT_ORIENTATION_NONE = 2; + + this.FT_ANGLE_PI = (180 << 16); + this.FT_ANGLE_PI2 = (this.FT_ANGLE_PI / 2); + this.FT_TRIG_MAX_ITERS = 23; + + this.FT_TRIG_SCALE = 0x9B74EDA8; + if (this.FT_TRIG_SCALE < 0) + this.FT_TRIG_SCALE = this.IntToUInt(this.FT_TRIG_SCALE); + + this.tt_coderange_none = 0; + this.tt_coderange_font = 1; + this.tt_coderange_cvt = 2; + this.tt_coderange_glyph = 3; + + this.MAX_RUNNABLE_OPCODES = 1000000; + + this.ARGS_ARE_WORDS = 0x0001; + this.ARGS_ARE_XY_VALUES = 0x0002; + this.ROUND_XY_TO_GRID = 0x0004; + this.WE_HAVE_A_SCALE = 0x0008; + this.MORE_COMPONENTS = 0x0020; + this.WE_HAVE_AN_XY_SCALE = 0x0040; + this.WE_HAVE_A_2X2 = 0x0080; + this.WE_HAVE_INSTR = 0x0100; + this.USE_MY_METRICS = 0x0200; + this.OVERLAP_COMPOUND = 0x0400; + this.SCALED_COMPONENT_OFFSET = 0x0800; + this.UNSCALED_COMPONENT_OFFSET = 0x1000; + +// GENERATOR_END_CONSTANTS + + this.UintToInt = function(v){ + return (v>FT_Common.m_i)?v-FT_Common.a_i:v; + } + this.UShort_To_Short = function(v){ + return (v>FT_Common.m_s)?v-FT_Common.a_s:v; + } + this.IntToUInt = function(v){ + return (v<0)?v+FT_Common.a_i:v; + } + this.Short_To_UShort = function(v){ + return (v<0)?v+FT_Common.a_s:v; + } + this.memset = function(d,v,s) + { + for (var i=0;i<s;i++) + d[i]=v; + } + this.memcpy = function(d,s,l) + { + for (var i=0;i<l;i++) + d[i]=s[i]; + } + this.memset_p = function(d,v,s) + { + var _d = d.data; + var _e = d.pos+s; + for (var i=d.pos;i<_e;i++) + _d[i]=v; + } + this.memcpy_p = function(d,s,l) + { + var _d1=d.data; + var _p1=d.pos; + var _d2=s.data; + var _p2=s.pos; + for (var i=0;i<l;i++) + _d1[_p1++]=_d2[_p2++]; + } + this.memcpy_p2 = function(d,s,p,l) + { + var _d1=d.data; + var _p1=d.pos; + var _p2=p; + for (var i=0;i<l;i++) + _d1[_p1++]=s[_p2++]; + } + this.realloc = function(memory, pointer, cur_count, new_count) + { + var ret = { block: null, err : 0, size : new_count}; + if (cur_count < 0 || new_count < 0) + { + /* may help catch/prevent nasty security issues */ + ret.err = FT_Common.FT_Err_Invalid_Argument; + } + else if (new_count == 0) + { + ret.block = null; + } + else if (cur_count == 0) + { + ret.block = memory.Alloc(new_count); + } + else + { + var block2 = memory.Alloc(new_count); + FT_Common.memcpy_p(block2, pointer, cur_count); + ret.block = block2; + } + return ret; + } + + this.realloc_long = function(memory, pointer, cur_count, new_count) + { + var ret = { block: null, err : 0, size : new_count}; + if (cur_count < 0 || new_count < 0) + { + /* may help catch/prevent nasty security issues */ + ret.err = FT_Common.FT_Err_Invalid_Argument; + } + else if (new_count == 0) + { + ret.block = null; + } + else if (cur_count == 0) + { + ret.block = CreateIntArray(new_count); + } + else + { + var block2 = CreateIntArray(new_count); + for (var i = 0; i < cur_count; i++) + block2[i] = pointer[i]; + + ret.block = block2; + } + return ret; + } +} +var FT_Common = new _FT_Common(); \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/drivers/cff.js b/Common/FontsFreeType/Private/FreeType/drivers/cff.js new file mode 100644 index 0000000000000000000000000000000000000000..9ab92612aa16935eb1790bdb770d9338ebae93a5 --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/drivers/cff.js @@ -0,0 +1,5967 @@ +/******************************************************************************/ +// cfftypes +/******************************************************************************/ +function CFF_IndexRec() +{ + this.stream = null; + this.start = 0; + this.count = 0; + this.off_size = 0; + this.data_offset = 0; + this.data_size = 0; + + this.offsets = null; + this.bytes = null; + + this.clear = function() + { + this.stream = null; + this.start = 0; + this.count = 0; + this.off_size = 0; + this.data_offset = 0; + this.data_size = 0; + + this.offsets = null; + this.bytes = null; + } +} + +function CFF_EncodingRec() +{ + this.format = 0; + this.offset = 0; + + this.count = 0; + this.sids = CreateIntArray(256); + this.codes = CreateIntArray(256); +} + +function CFF_CharsetRec() +{ + this.format = 0; + this.offset = 0; + + this.sids = null; + this.cids = null; + + this.max_cid = 0; + this.num_glyphs = 0; +} + +function CFF_FontRecDictRec() +{ + this.version = 0; + this.notice = 0; + this.copyright = 0; + this.full_name = 0; + this.family_name = 0; + this.weight = 0; + this.is_fixed_pitch = 0; + this.italic_angle = 0; + this.underline_position = 0; + this.underline_thickness = 0; + this.paint_type = 0; + this.charstring_type = 0; + this.font_matrix = new FT_Matrix(); + this.has_font_matrix = 0; + this.units_per_em = 0; + this.font_offset = new FT_Vector(); + this.unique_id = 0; + this.font_bbox = new FT_BBox(); + this.stroke_width = 0; + this.charset_offset = 0; + this.encoding_offset = 0; + this.charstrings_offset = 0; + this.private_offset = 0; + this.private_size = 0; + this.synthetic_base = 0; + this.embedded_postscript = 0; + + this.cid_registry = 0; + this.cid_ordering = 0; + this.cid_supplement = 0; + + this.cid_font_version = 0; + this.cid_font_revision = 0; + this.cid_font_type = 0; + this.cid_count = 0; + this.cid_uid_base = 0; + this.cid_fd_array_offset = 0; + this.cid_fd_select_offset = 0; + this.cid_font_name = 0; + + this.clear = function() + { + this.version = 0; + this.notice = 0; + this.copyright = 0; + this.full_name = 0; + this.family_name = 0; + this.weight = 0; + this.is_fixed_pitch = 0; + this.italic_angle = 0; + this.underline_position = 0; + this.underline_thickness = 0; + this.paint_type = 0; + this.charstring_type = 0; + + this.font_matrix.xx = 0; + this.font_matrix.xy = 0; + this.font_matrix.yx = 0; + this.font_matrix.yy = 0; + + this.has_font_matrix = 0; + this.units_per_em = 0; + + this.font_offset.x = 0; + this.font_offset.y = 0; + + this.unique_id = 0; + + this.font_bbox.xMin = 0; + this.font_bbox.yMin = 0; + this.font_bbox.xMax = 0; + this.font_bbox.yMax = 0; + + this.stroke_width = 0; + this.charset_offset = 0; + this.encoding_offset = 0; + this.charstrings_offset = 0; + this.private_offset = 0; + this.private_size = 0; + this.synthetic_base = 0; + this.embedded_postscript = 0; + + this.cid_registry = 0; + this.cid_ordering = 0; + this.cid_supplement = 0; + + this.cid_font_version = 0; + this.cid_font_revision = 0; + this.cid_font_type = 0; + this.cid_count = 0; + this.cid_uid_base = 0; + this.cid_fd_array_offset = 0; + this.cid_fd_select_offset = 0; + this.cid_font_name = 0; + } +} + +function CFF_PrivateRec() +{ + this.num_blue_values = 0; + this.num_other_blues = 0; + this.num_family_blues = 0; + this.num_family_other_blues = 0; + + this.blue_values = CreateIntArray(14); + this.other_blues = CreateIntArray(10); + this.family_blues = CreateIntArray(14); + this.family_other_blues = CreateIntArray(10); + + this.blue_scale = 0; + this.blue_shift = 0; + this.blue_fuzz = 0; + this.standard_width = 0; + this.standard_height = 0; + + this.num_snap_widths = 0; + this.num_snap_heights = 0; + this.snap_widths = CreateIntArray(13); + this.snap_heights = CreateIntArray(13); + this.force_bold = 0; + this.force_bold_threshold = 0; + this.lenIV = 0; + this.language_group = 0; + this.expansion_factor = 0; + this.initial_random_seed = 0; + this.local_subrs_offset = 0; + this.default_width = 0; + this.nominal_width = 0; + + this.clear = function() + { + this.num_blue_values = 0; + this.num_other_blues = 0; + this.num_family_blues = 0; + this.num_family_other_blues = 0; + + for (var i = 0; i < 14; i++) + this.blue_values[i] = 0; + for (var i = 0; i < 10; i++) + this.other_blues[i] = 0; + for (var i = 0; i < 14; i++) + this.family_blues[i] = 0; + for (var i = 0; i < 10; i++) + this.family_other_blues[i] = 0; + + this.blue_scale = 0; + this.blue_shift = 0; + this.blue_fuzz = 0; + this.standard_width = 0; + this.standard_height = 0; + + this.num_snap_widths = 0; + this.num_snap_heights = 0; + + for (var i = 0; i < 13; i++) + this.snap_widths[i] = 0; + for (var i = 0; i < 13; i++) + this.snap_heights[i] = 0; + + this.force_bold = 0; + this.force_bold_threshold = 0; + this.lenIV = 0; + this.language_group = 0; + this.expansion_factor = 0; + this.initial_random_seed = 0; + this.local_subrs_offset = 0; + this.default_width = 0; + this.nominal_width = 0; + } +} + +function CFF_FDSelectRec() +{ + this.format = 0; + this.range_count = 0; + + /* that's the table, taken from the file `as is' */ + this.data = null; + this.data_size = 0; + + /* small cache for format 3 only */ + this.cache_first = 0; + this.cache_count = 0; + this.cache_fd = 0; +} + +/* A SubFont packs a font dict and a private dict together. They are */ +/* needed to support CID-keyed CFF fonts. */ +function CFF_SubFontRec() +{ + this.font_dict = new CFF_FontRecDictRec(); + this.private_dict = new CFF_PrivateRec(); + + this.local_subrs_index = new CFF_IndexRec(); + this.local_subrs = []; /* array of pointers into Local Subrs INDEX data */ +} + +function CFF_FontRec() +{ + this.stream = null; + this.memory = null; + this.num_faces = 0; + this.num_glyphs = 0; + + this.version_major = 0; + this.version_minor = 0; + this.header_size = 0; + this.absolute_offsize = 0; + + + this.name_index = new CFF_IndexRec(); + this.top_dict_index = new CFF_IndexRec(); + this.global_subrs_index = new CFF_IndexRec(); + + this.encoding = new CFF_EncodingRec(); + this.charset = new CFF_CharsetRec(); + + this.charstrings_index = new CFF_IndexRec(); + this.font_dict_index = new CFF_IndexRec(); + this.private_index = new CFF_IndexRec(); + this.local_subrs_index = new CFF_IndexRec(); + + this.font_name = ""; + + /* array of pointers into Global Subrs INDEX data */ + this.global_subrs = []; + + /* array of pointers into String INDEX data stored at string_pool */ + this.num_strings = 0; + this.strings = null; + this.string_pool = null; + + this.top_font = new CFF_SubFontRec(); + this.num_subfonts = 0; + this.subfonts = new Array(FT_Common.CFF_MAX_CID_FONTS); + for (var i = 0; i < FT_Common.CFF_MAX_CID_FONTS; i++) + this.subfonts[i] = null; + + this.fd_select = new CFF_FDSelectRec(); + + /* interface to PostScript hinter */ + this.pshinter = null; + + /* interface to Postscript Names service */ + this.psnames = null; + + /* since version 2.3.0 */ + this.font_info = null; /* font info dictionary */ + + /* since version 2.3.6 */ + this.registry = ""; + this.ordering = ""; +} + +function CFF_ParserRec() +{ + this.library = null; + this.start = null; + this.limit = 0; + this.cursor = null; + + this.stack = new Array(FT_Common.CFF_MAX_STACK_DEPTH + 1); + this.top = 0; + + this.object_code = 0; + this.object = 0; + + this.clear = function() + { + this.library = null; + this.start = null; + this.limit = 0; + this.cursor = null; + + for (var i = 0; i < (FT_Common.CFF_MAX_STACK_DEPTH + 1); i++) + this.stack[i] = 0; + this.top = 0; + + this.object_code = 0; + this.object = 0; + } +} + +function CFF_Field_Handler() +{ + this.kind = 0; + this.code = 0; + this.offset = 0; + this.size = 0; + this.reader = null; + this.array_max = 0; + this.count_offset = 0; + + this.set_field = null; + this.set_field_count = null; +} + +function create_cff_field(_kind, _code, _reader, _array_max, _set_field, _set_field_count) +{ + var ret = new CFF_Field_Handler(); + ret.kind = _kind; + ret.code = _code; + ret.offset = 0; + ret.size = 0; + ret.reader = _reader; + ret.array_max = _array_max; + ret.count_offset = 0; + + ret.set_field = _set_field; + ret.set_field_count = _set_field_count; + + return ret; +} +/******************************************************************************/ +// cffparse +/******************************************************************************/ +function cff_parser_init(parser, code, object, library) +{ + parser.clear(); + + parser.top = 0; + parser.object_code = code; + parser.object = object; + parser.library = library; +} + +function cff_parse_integer(start, limit) +{ + var p = dublicate_pointer(start); + var v = p.data[p.pos]; + p.pos++; + var val = 0; + + if (v == 28) + { + if (p.pos + 2 > limit) + return 0; + + val = FT_Common.UShort_To_Short((p.data[p.pos] << 8) | p.data[p.pos + 1]); + p.pos += 2; + } + else if ( v == 29 ) + { + if (p.pos + 4 > limit) + return 0; + + val = (p.data[p.pos] << 24) | (p.data[p.pos + 1] << 16) | (p.data[p.pos + 2] << 8) | p.data[p.pos + 3]; + p.pos += 4; + } + else if (v < 247) + { + val = v - 139; + } + else if (v < 251) + { + if (p.pos + 1 > limit) + return 0; + + val = (v - 247) * 256 + p.data[p.pos] + 108; + p.pos++; + } + else + { + if (p + 1 > limit) + return 0; + + val = -(v - 251) * 256 - p.data[p.pos] - 108; + p.pos++; + } + return val; +} + +var power_tens = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; + +function cff_parse_real(start, limit, power_ten, is_scaling) +{ + var scaling = 0; + var result = 0; + + var p = dublicate_pointer(start); + var nib = 0; + var phase = 0; + + var sign = 0, exponent_sign = 0; + + var number = 0; + var exponent = 0; + + var exponent_add = 0; + var integer_length = 0; + var fraction_length = 0; + + /* First of all, read the integer part. */ + phase = 4; + + for (;;) + { + /* If we entered this iteration with phase == 4, we need to */ + /* read a new byte. This also skips past the initial 0x1E. */ + if (phase) + { + p.pos++; + + /* Make sure we don't read past the end. */ + if (p.pos >= limit) + return { res : result, scaling: scaling }; + } + + /* Get the nibble. */ + nib = (p.data[p.pos] >> phase) & 0xF; + phase = 4 - phase; + + if (nib == 0xE) + sign = 1; + else if (nib > 9) + break; + else + { + /* Increase exponent if we can't add the digit. */ + if (number >= 0xCCCCCCC) + exponent_add++; + /* Skip leading zeros. */ + else if ( nib || number ) + { + integer_length++; + number = number * 10 + nib; + } + } + } + + /* Read fraction part, if any. */ + if (nib == 0xa) + { + for (;;) + { + /* If we entered this iteration with phase == 4, we need */ + /* to read a new byte. */ + if (phase) + { + p.pos++; + + /* Make sure we don't read past the end. */ + if (p.pos >= limit) + return { res : result, scaling: scaling }; + } + + /* Get the nibble. */ + nib = (p.data[p.pos] >> phase) & 0xF; + phase = 4 - phase; + if (nib >= 10) + break; + + /* Skip leading zeros if possible. */ + if (!nib && !number) + exponent_add--; + /* Only add digit if we don't overflow. */ + else if (number < 0xCCCCCCC && fraction_length < 9) + { + fraction_length++; + number = number * 10 + nib; + } + } + } + + /* Read exponent, if any. */ + if (nib == 12) + { + exponent_sign = 1; + nib = 11; + } + + if (nib == 11) + { + for (;;) + { + /* If we entered this iteration with phase == 4, */ + /* we need to read a new byte. */ + if (phase) + { + p.pos++; + + /* Make sure we don't read past the end. */ + if (p.pos >= limit) + return { res : result, scaling: scaling }; + } + + /* Get the nibble. */ + nib = (p.data[p.pos] >> phase) & 0xF; + phase = 4 - phase; + if (nib >= 10) + break; + + exponent = exponent * 10 + nib; + + /* Arbitrarily limit exponent. */ + if (exponent > 1000) + return { res : result, scaling: scaling }; + } + + if (exponent_sign) + exponent = -exponent; + } + + /* We don't check `power_ten' and `exponent_add'. */ + exponent += power_ten + exponent_add; + + if (is_scaling != 0) + { + /* Only use `fraction_length'. */ + fraction_length += integer_length; + exponent += integer_length; + + if (fraction_length <= 5) + { + if (number > 0x7FFF) + { + result = FT_DivFix(number, 10); + scaling = exponent - fraction_length + 1; + } + else + { + if (exponent > 0) + { + /* Make `scaling' as small as possible. */ + var new_fraction_length = Math.min(exponent, 5); + exponent -= new_fraction_length; + var shift = new_fraction_length - fraction_length; + + number *= power_tens[shift]; + if (number > 0x7FFF) + { + number /= 10; + exponent += 1; + } + } + else + exponent -= fraction_length; + + result = number << 16; + scaling = exponent; + } + } + else + { + if ((number / power_tens[fraction_length - 5]) > 0x7FFF) + { + result = FT_DivFix(number, power_tens[fraction_length - 4]); + scaling = exponent - 4; + } + else + { + result = FT_DivFix(number, power_tens[fraction_length - 5]); + scaling = exponent - 5; + } + } + } + else + { + integer_length += exponent; + fraction_length -= exponent; + + /* Check for overflow and underflow. */ + if (Math.abs(integer_length) > 5) + return { res : result, scaling: scaling }; + + /* Remove non-significant digits. */ + if (integer_length < 0) + { + number /= power_tens[-integer_length]; + fraction_length += integer_length; + } + + /* this can only happen if exponent was non-zero */ + if (fraction_length == 10) + { + number /= 10; + fraction_length -= 1; + } + + /* Convert into 16.16 format. */ + if (fraction_length > 0) + { + if ((number / power_tens[fraction_length]) > 0x7FFF) + return { res : result, scaling: scaling }; + + result = FT_DivFix(number, power_tens[fraction_length]); + } + else + { + number *= power_tens[-fraction_length]; + + if (number > 0x7FFF) + return { res : result, scaling: scaling }; + + result = number << 16; + } + } + + if (sign) + result = -result; + + return { res : result, scaling: scaling }; +} + +function cff_parse_num(d, start) +{ + var _d0 = d[start]; + var _d1 = d[start + 1]; + if (_d0.data[_d0.pos] == 30) + return cff_parse_real(_d0, _d1.pos, 0, false).res >> 16; + return cff_parse_integer(_d0, _d1.pos); +} + +function cff_parse_fixed(d, start) +{ + var _d0 = d[start]; + var _d1 = d[start + 1]; + if (_d0.data[_d0.pos] == 30) + return cff_parse_real(_d0, _d1.pos, 0, false).res; + return cff_parse_integer(_d0, _d1.pos) << 16; +} + +function cff_parse_fixed_scaled(d, start, scaling) +{ + var _d0 = d[start]; + var _d1 = d[start + 1]; + if (_d0.data[_d0.pos] == 30) + return cff_parse_real(_d0, _d1.pos, scaling, false).res; + + return (cff_parse_integer(_d0, _d1.pos) * power_tens[scaling]) << 16; +} + +function cff_parse_fixed_dynamic(d, start) +{ + var _d0 = d[start]; + var _d1 = d[start + 1]; + if (_d0.data[_d0.pos] == 30) + return cff_parse_real(_d0, _d1.pos, 0, true); + + var integer_length = 0; + var number = cff_parse_integer(_d0, _d1.pos); + + var scaling = 0; + if (number > 0x7FFF) + { + for (integer_length = 5; integer_length < 10; integer_length++) + if (number < power_tens[integer_length]) + break; + + if ((number / power_tens[integer_length - 5]) > 0x7FFF) + { + scaling = integer_length - 4; + var result = FT_DivFix(number, power_tens[integer_length - 4]); + return { res : result, scaling: scaling }; + } + else + { + scaling = integer_length - 5; + var result = FT_DivFix(number, power_tens[integer_length - 5]); + return { res : result, scaling: scaling }; + } + } + else + { + return { res : number << 16, scaling: 0 }; + } +} + +function cff_parse_font_matrix(parser) +{ + var dict = parser.object; + var matrix = dict.font_matrix; + var offset = dict.font_offset; + //FT_ULong* upm = &dict.units_per_em; + var data = parser.stack; + var start = 0; + var error = FT_Common.FT_Err_Stack_Underflow; + + if (parser.top >= 6) + { + var scaling = 0; + error = FT_Common.FT_Err_Ok; + + dict.has_font_matrix = 1; + /* We expect a well-formed font matrix, this is, the matrix elements */ + /* `xx' and `yy' are of approximately the same magnitude. To avoid */ + /* loss of precision, we use the magnitude of element `xx' to scale */ + /* all other elements. The scaling factor is then contained in the */ + /* `units_per_em' value. */ + + var ret = cff_parse_fixed_dynamic(data, start++); + scaling = ret.scaling; + matrix.xx = ret.res; + + scaling = -scaling; + if (scaling < 0 || scaling > 9) + { + /* Return default matrix in case of unlikely values. */ + matrix.xx = 0x10000; + matrix.yx = 0; + matrix.xy = 0; + matrix.yy = 0x10000; + offset.x = 0; + offset.y = 0; + dict.units_per_em = 1; + + return error; + } + + matrix.yx = cff_parse_fixed_scaled(data, start++, scaling); + matrix.xy = cff_parse_fixed_scaled(data, start++, scaling); + matrix.yy = cff_parse_fixed_scaled(data, start++, scaling); + offset.x = cff_parse_fixed_scaled(data, start++, scaling); + offset.y = cff_parse_fixed_scaled(data, start, scaling); + + dict.units_per_em = power_tens[scaling]; + } + + return error; +} + +function cff_parse_font_bbox(parser) +{ + var dict = parser.object; + var bbox = dict.font_bbox; + var data = parser.stack; + + if (parser.top >= 4) + { + var start = 0; + + bbox.xMin = FT_RoundFix(cff_parse_fixed(data, start++)); + bbox.yMin = FT_RoundFix(cff_parse_fixed(data, start++)); + bbox.xMax = FT_RoundFix(cff_parse_fixed(data, start++)); + bbox.yMax = FT_RoundFix(cff_parse_fixed(data, start)); + + return 0; + } + return FT_Common.FT_Err_Stack_Underflow; +} + +function cff_parse_private_dict(parser) +{ + var dict = parser.object; + var data = parser.stack; + + if (parser.top >= 2) + { + dict.private_size = cff_parse_num(data, 0); + dict.private_offset = cff_parse_num(data, 1); + + return 0; + } + return FT_Common.FT_Err_Stack_Underflow; +} + +function cff_parse_cid_ros(parser) +{ + var dict = parser.object; + var data = parser.stack; + + if (parser.top >= 3) + { + dict.cid_registry = FT_Common.IntToUInt(cff_parse_num(data, 0)); + dict.cid_ordering = FT_Common.IntToUInt(cff_parse_num(data, 1)); + + dict.cid_supplement = cff_parse_num(data, 2); + return 0; + } + return FT_Common.FT_Err_Stack_Underflow; +} + +function cff_parser_run(parser, start, limit) +{ + var p = dublicate_pointer(start); + var error = 0; + + parser.top = 0; + parser.start = start; + parser.limit = limit; + parser.cursor = dublicate_pointer(start); + + var tops = parser.stack; + while (p.pos < limit) + { + var v = p.data[p.pos]; + + if (v >= 27 && v != 31) + { + /* it's a number; we will push its position on the stack */ + if (parser.top >= FT_Common.CFF_MAX_STACK_DEPTH) + return FT_Common.FT_Err_Invalid_Argument; + + tops[parser.top++] = dublicate_pointer(p); + + /* now, skip it */ + if (v == 30) + { + /* skip real number */ + p.pos++; + for (;;) + { + /* An unterminated floating point number at the */ + /* end of a dictionary is invalid but harmless. */ + if (p.pos >= limit) + return error; + v = p.data[p.pos] >> 4; + if (v == 15) + break; + v = p.data[p.pos] & 0xF; + if (v == 15) + break; + p.pos++; + } + } + else if (v == 28) + p.pos += 2; + else if (v == 29) + p.pos += 4; + else if (v > 246) + p.pos += 1; + } + else + { + /* This is not a number, hence it's an operator. Compute its code */ + /* and look for it in our current list. */ + + var num_args = parser.top; + var code = v; + + tops[parser.top++] = dublicate_pointer(p); + if (v == 12) + { + /* two byte operator */ + p.pos++; + if (p.pos >= limit) + return FT_Common.FT_Err_Invalid_Argument; + + code = 0x100 | p.data[p.pos]; + } + code = code | parser.object_code; + + var fields = cff_field_handlers; + for (var field_ = 0; field_ < fields.length; field_++) + { + var field = fields[field_]; + if (field.code == FT_Common.UintToInt(code)) + { + /* we found our field's handler; read it */ + var val; + + /* check that we have enough arguments -- except for */ + /* delta encoded arrays, which can be empty */ + if (field.kind != FT_Common.cff_kind_delta && num_args < 1) + return FT_Common.FT_Err_Invalid_Argument; + + switch (field.kind) + { + case FT_Common.cff_kind_bool: + case FT_Common.cff_kind_string: + case FT_Common.cff_kind_num: + val = cff_parse_num(parser.stack, 0); + fire_t1_field(parser.object, val, field); + break; + + case FT_Common.cff_kind_fixed: + val = cff_parse_fixed(parser.stack, 0); + fire_t1_field(parser.object, val, field); + break; + + case FT_Common.cff_kind_fixed_thousand: + val = cff_parse_fixed_scaled(parser.stack, 0, 3); + fire_t1_field(parser.object, val, field); + break; + + case FT_Common.cff_kind_delta: + var data = parser.stack; + var _data_pos = 0; + + if (num_args > field.array_max) + num_args = field.array_max; + + fire_t1_field_count(parser.object, num_args, field); + val = 0; + field.offset = 0; + while (num_args > 0) + { + val += cff_parse_num(data, _data_pos++); + fire_t1_field(parser.object, val, field); + field.offset++; + num_args--; + } + + break; + + default: /* callback */ + error = field.reader(parser); + if ( error ) + return error; + } + + break; + } + } + + /* this is an unknown operator, or it is unsupported; */ + /* we will ignore it for now. */ + /* clear stack */ + parser.top = 0; + } + p.pos++; + } + + return error; +} + +/******************************************************************************/ +// cfftoken +/******************************************************************************/ +var cff_field_handlers = new Array(51); + +// CFF_FontRecDictRec +cff_field_handlers[0] = create_cff_field(FT_Common.cff_kind_string, 0 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.version = val }, undefined); +cff_field_handlers[1] = create_cff_field(FT_Common.cff_kind_string, 1 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.notice = val }, undefined); +cff_field_handlers[2] = create_cff_field(FT_Common.cff_kind_string, 0x100 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.copyright = val }, undefined); +cff_field_handlers[3] = create_cff_field(FT_Common.cff_kind_string, 2 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.full_name = val }, undefined); +cff_field_handlers[4] = create_cff_field(FT_Common.cff_kind_string, 3 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.family_name = val }, undefined); +cff_field_handlers[5] = create_cff_field(FT_Common.cff_kind_string, 4 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.weight = val }, undefined); + +cff_field_handlers[6] = create_cff_field(FT_Common.cff_kind_bool, 0x101 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.is_fixed_pitch = val }, undefined); + +cff_field_handlers[7] = create_cff_field(FT_Common.cff_kind_fixed, 0x102 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.italic_angle = val }, undefined); +cff_field_handlers[8] = create_cff_field(FT_Common.cff_kind_fixed, 0x103 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.underline_position = val }, undefined); +cff_field_handlers[9] = create_cff_field(FT_Common.cff_kind_fixed, 0x104 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.underline_thickness = val }, undefined); + +cff_field_handlers[10] = create_cff_field(FT_Common.cff_kind_num, 0x105 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.paint_type = val }, undefined); +cff_field_handlers[11] = create_cff_field(FT_Common.cff_kind_num, 0x106 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.charstring_type = val }, undefined); + +cff_field_handlers[12] = create_cff_field(FT_Common.cff_kind_callback, 0x107 | FT_Common.CFFCODE_TOPDICT, cff_parse_font_matrix, 0, undefined, undefined); + +cff_field_handlers[13] = create_cff_field(FT_Common.cff_kind_num, 13 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.unique_id = val }, undefined); + +cff_field_handlers[14] = create_cff_field(FT_Common.cff_kind_callback, 5 | FT_Common.CFFCODE_TOPDICT, cff_parse_font_bbox, 0, undefined, undefined); + +cff_field_handlers[15] = create_cff_field(FT_Common.cff_kind_num, 0x108 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.stroke_width = val }, undefined); +cff_field_handlers[16] = create_cff_field(FT_Common.cff_kind_num, 15 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.charset_offset = val }, undefined); +cff_field_handlers[17] = create_cff_field(FT_Common.cff_kind_num, 16 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.encoding_offset = val }, undefined); +cff_field_handlers[18] = create_cff_field(FT_Common.cff_kind_num, 17 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.charstrings_offset = val }, undefined); + +cff_field_handlers[19] = create_cff_field(FT_Common.cff_kind_callback, 18 | FT_Common.CFFCODE_TOPDICT, cff_parse_private_dict, 0, undefined, undefined); + +cff_field_handlers[20] = create_cff_field(FT_Common.cff_kind_num, 0x114 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.synthetic_base = val }, undefined); + +cff_field_handlers[21] = create_cff_field(FT_Common.cff_kind_string, 0x115 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.embedded_postscript = val }, undefined); + +cff_field_handlers[22] = create_cff_field(FT_Common.cff_kind_callback, 0x11E | FT_Common.CFFCODE_TOPDICT, cff_parse_cid_ros, 0, undefined, undefined); + +cff_field_handlers[23] = create_cff_field(FT_Common.cff_kind_num, 0x11F | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.cid_font_version = val }, undefined); +cff_field_handlers[24] = create_cff_field(FT_Common.cff_kind_num, 0x120 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.cid_font_revision = val }, undefined); +cff_field_handlers[25] = create_cff_field(FT_Common.cff_kind_num, 0x121 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.cid_font_type = val }, undefined); +cff_field_handlers[26] = create_cff_field(FT_Common.cff_kind_num, 0x122 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.cid_count = val }, undefined); +cff_field_handlers[27] = create_cff_field(FT_Common.cff_kind_num, 0x123 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.cid_uid_base = val }, undefined); +cff_field_handlers[28] = create_cff_field(FT_Common.cff_kind_num, 0x124 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.cid_fd_array_offset = val }, undefined); +cff_field_handlers[29] = create_cff_field(FT_Common.cff_kind_num, 0x125 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.cid_fd_select_offset = val }, undefined); + +cff_field_handlers[30] = create_cff_field(FT_Common.cff_kind_string, 0x126 | FT_Common.CFFCODE_TOPDICT, null, 0, function(obj, val, f) { obj.cid_font_name = val }, undefined); + +// CFF_PrivateRec +cff_field_handlers[31] = create_cff_field(FT_Common.cff_kind_delta, 6 | FT_Common.CFFCODE_PRIVATE, null, 14, function(obj, val, f) { obj.blue_values[f.offset] = val }, function(obj, val, f) { obj.num_blue_values = val }); +cff_field_handlers[32] = create_cff_field(FT_Common.cff_kind_delta, 7 | FT_Common.CFFCODE_PRIVATE, null, 10, function(obj, val, f) { obj.other_blues[f.offset] = val }, function(obj, val, f) { obj.num_other_blues = val }); +cff_field_handlers[33] = create_cff_field(FT_Common.cff_kind_delta, 8 | FT_Common.CFFCODE_PRIVATE, null, 14, function(obj, val, f) { obj.family_blues[f.offset] = val }, function(obj, val, f) { obj.num_family_blues = val }); +cff_field_handlers[34] = create_cff_field(FT_Common.cff_kind_delta, 9 | FT_Common.CFFCODE_PRIVATE, null, 10, function(obj, val, f) { obj.family_other_blues[f.offset] = val }, function(obj, val, f) { obj.num_family_other_blues = val }); + +cff_field_handlers[35] = create_cff_field(FT_Common.cff_kind_fixed_thousand, 0x109 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.blue_scale = val }, undefined); + +cff_field_handlers[36] = create_cff_field(FT_Common.cff_kind_num, 0x10A | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.blue_shift = val }, undefined); +cff_field_handlers[37] = create_cff_field(FT_Common.cff_kind_num, 0x10B | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.blue_fuzz = val }, undefined); +cff_field_handlers[38] = create_cff_field(FT_Common.cff_kind_num, 10 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.standard_width = val }, undefined); +cff_field_handlers[39] = create_cff_field(FT_Common.cff_kind_num, 11 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.standard_height = val }, undefined); + +cff_field_handlers[40] = create_cff_field(FT_Common.cff_kind_delta, 0x10C | FT_Common.CFFCODE_PRIVATE, null, 13, function(obj, val, f) { obj.snap_widths[f.offset] = val }, function(obj, val, f) { obj.num_snap_widths = val }); +cff_field_handlers[41] = create_cff_field(FT_Common.cff_kind_delta, 0x10D | FT_Common.CFFCODE_PRIVATE, null, 13, function(obj, val, f) { obj.snap_heights[f.offset] = val }, function(obj, val, f) { obj.num_snap_heights = val }); + +cff_field_handlers[42] = create_cff_field(FT_Common.cff_kind_bool, 0x10E | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.force_bold = val }, undefined); +cff_field_handlers[43] = create_cff_field(FT_Common.cff_kind_fixed, 0x10F | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.force_bold_threshold = val }, undefined); + +cff_field_handlers[44] = create_cff_field(FT_Common.cff_kind_num, 0x110 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.lenIV = val }, undefined); +cff_field_handlers[45] = create_cff_field(FT_Common.cff_kind_num, 0x111 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.language_group = val }, undefined); + +cff_field_handlers[46] = create_cff_field(FT_Common.cff_kind_fixed, 0x112 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.expansion_factor = val }, undefined); + +cff_field_handlers[47] = create_cff_field(FT_Common.cff_kind_num, 0x113 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.initial_random_seed = val }, undefined); +cff_field_handlers[48] = create_cff_field(FT_Common.cff_kind_num, 19 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.local_subrs_offset = val }, undefined); +cff_field_handlers[49] = create_cff_field(FT_Common.cff_kind_num, 20 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.default_width = val }, undefined); +cff_field_handlers[50] = create_cff_field(FT_Common.cff_kind_num, 21 | FT_Common.CFFCODE_PRIVATE, null, 0, function(obj, val, f) { obj.nominal_width = val }, undefined); + +/******************************************************************************/ +// cffload +/******************************************************************************/ +var cff_isoadobe_charset = +[ + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228 +]; + +var cff_expert_charset = +[ + 0, 1, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 13, 14, 15, 99, + 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 27, 28, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 109, 110, + 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 158, 155, 163, 319, + 320, 321, 322, 323, 324, 325, 326, 150, + 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378 +]; + +var cff_expertsubset_charset = +[ + 0, 1, 231, 232, 235, 236, 237, 238, + 13, 14, 15, 99, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 27, 28, + 249, 250, 251, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, + 266, 109, 110, 267, 268, 269, 270, 272, + 300, 301, 302, 305, 314, 315, 158, 155, + 163, 320, 321, 322, 323, 324, 325, 326, + 150, 164, 169, 327, 328, 329, 330, 331, + 332, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346 +]; + +var cff_standard_encoding = +[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, + 0, 111, 112, 113, 114, 0, 115, 116, + 117, 118, 119, 120, 121, 122, 0, 123, + 0, 124, 125, 126, 127, 128, 129, 130, + 131, 0, 132, 133, 0, 134, 135, 136, + 137, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 138, 0, 139, 0, 0, 0, 0, + 140, 141, 142, 143, 0, 0, 0, 0, + 0, 144, 0, 0, 0, 145, 0, 0, + 146, 147, 148, 149, 0, 0, 0, 0 +]; + +var cff_expert_encoding = +[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 229, 230, 0, 231, 232, 233, 234, + 235, 236, 237, 238, 13, 14, 15, 99, + 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 27, 28, 249, 250, 251, 252, + 0, 253, 254, 255, 256, 257, 0, 0, + 0, 258, 0, 0, 259, 260, 261, 262, + 0, 0, 263, 264, 265, 0, 266, 109, + 110, 267, 268, 269, 0, 270, 271, 272, + 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 304, 305, 306, 0, 0, 307, 308, + 309, 310, 311, 0, 312, 0, 0, 312, + 0, 0, 314, 315, 0, 0, 316, 317, + 318, 0, 0, 0, 158, 155, 163, 319, + 320, 321, 322, 323, 324, 325, 0, 0, + 326, 150, 164, 169, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 336, 337, 338, + 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378 +]; + +function cff_get_standard_encoding(charcode) +{ + return (charcode < 256 ? cff_standard_encoding[charcode] : 0); +} + +function cff_index_read_offset(idx) +{ + var result = 0; + var tmp = g_memory.Alloc(4); + var error = idx.stream.Read(tmp, idx.off_size); + + if (error == 0) + { + for (var nn = 0; nn < idx.off_size; nn++) + result = (result << 8) | tmp.data[nn]; + + result = FT_Common.IntToUInt(result); + } + + return { err : error, result: result }; +} + +function cff_index_init(idx, stream, load) +{ + idx.clear(); + idx.stream = stream; + idx.start = stream.pos; + + var count = stream.ReadUShort(); + var error = FT_Error; + if (error != 0) + return error; + + if (0 == count) + return error; + + var offsize = stream.ReadUChar(); + if (error != 0) + return error; + + if (offsize < 1 || offsize > 4) + return FT_Common.FT_Err_Invalid_Table; + + idx.count = count; + idx.off_size = offsize; + var size = (count + 1) * offsize; + + idx.data_offset = idx.start + 3 + size; + + error = stream.Skip(size - offsize); + if (error != 0) + return error; + + var _err = cff_index_read_offset(idx); + error = _err.err; + size = _err.result; + if (error != 0) + return error; + + if (size == 0) + return FT_Common.FT_Err_Invalid_Table; + + idx.data_size = --size; + + if (load) + { + /* load the data */ + idx.bytes = new CPointer(); + error = stream.ExtractFrame(size, idx.bytes); + } + else + { + /* skip the data */ + error = stream.Skip(size); + } + + return error; +} + +function cff_index_done(idx) +{ + if (idx.stream != null) + { + idx.clear(); + } +} + +function cff_index_load_offsets(idx) +{ + var error = 0; + var stream = idx.stream; + + if (idx.count > 0 && idx.offsets == null) + { + var offsize = idx.off_size; + var data_size = (idx.count + 1) * offsize; + + error = stream.Seek(idx.start + 3); + if (error == 0) + error = stream.EnterFrame(data_size); + + if (error != 0) + return error; + + idx.offsets = CreateUIntArray(idx.count + 1); + + var poff = 0; + var p = stream.cur; + var p_end = p + data_size; + + var _s = stream.data; + var _d = idx.offsets; + + switch (offsize) + { + case 1: + for (; p < p_end; p++, poff++) + _d[poff] = _s[p]; + break; + + case 2: + for (; p < p_end; p += 2, poff++) + _d[poff] = (_s[p] << 8 | _s[p+1]); + break; + + case 3: + for (; p < p_end; p += 3, poff++) + _d[poff] = (_s[p] << 16 | _s[p+1] << 8 | _s[p+2]); + break; + + default: + for (; p < p_end; p += 4, poff++) + { + var r = (_s[p] << 24 | _s[p+1] << 16 | _s[p+2] << 8 | _s[p+3]); + if (r<0) + r+=FT_Common.a_i; + _d[poff] = r; + } + } + + stream.ExitFrame(); + } + + return error; +} + +function cff_index_get_pointers(idx, table, pool, is_pool) +{ + var error = 0; + + if (idx.offsets == null) + { + error = cff_index_load_offsets(idx); + if (error != 0) + return { err: error, table: table, pool: pool }; + } + + if (idx.count > 0) + { + var t = new Array(idx.count + 1); + var new_bytes = g_memory.Alloc(idx.data_size + idx.count); + + var extra = 0; + var org_bytes = idx.bytes; + + /* at this point, `idx->offsets' can't be NULL */ + var cur_offset = idx.offsets[0] - 1; + + /* sanity check */ + if (cur_offset >= idx.data_size) + { + cur_offset = 0; + } + + if (is_pool == 0) + { + t[0] = dublicate_pointer(org_bytes); + t[0].pos += cur_offset; + } + else + { + t[0] = dublicate_pointer(new_bytes); + t[0].pos += cur_offset; + } + + for (var n = 1; n <= idx.count; n++) + { + var next_offset = idx.offsets[n] - 1; + + /* empty slot + two sanity checks for invalid offset tables */ + if (next_offset == 0 || next_offset < cur_offset || (next_offset >= idx.data_size && n < idx.count)) + next_offset = cur_offset; + + if (is_pool == 0) + { + t[n] = dublicate_pointer(org_bytes); + t[n].pos += next_offset; + } + else + { + t[n] = dublicate_pointer(new_bytes); + t[n].pos += next_offset + extra; + + if (next_offset != cur_offset) + { + var _d = t[n - 1]; + var _s = dublicate_pointer(org_bytes); + _s.pos += cur_offset; + var _l = t[n].pos - t[n-1].pos; + + for (var i = 0; i < _l; i++) + _d.data[_d.pos + i] = _s.data[_s.pos + i]; + + t[n].data[t[n].pos] = FT_Common.SYMBOL_CONST_S0; + t[n].pos += 1; + extra++; + } + } + + cur_offset = next_offset; + } + + return { err: error, table: t, pool: new_bytes }; + } + + return { err: error, table: table, pool: pool }; +} + +function cff_index_access_element(idx, element) +{ + var error = 0; + var pbytes = null; + var pbyte_len = 0; + + if (idx && idx.count > element) + { + /* compute start and end offsets */ + var stream = idx.stream; + var off1, off2 = 0; + + + /* load offsets from file or the offset table */ + if (idx.offsets == null) + { + var pos = element * idx.off_size; + + error = stream.Seek(idx.start + 3 + pos); + if (error != 0) + return { err: error, bytes: pbytes, len: pbyte_len }; + + var ret = cff_index_read_offset(idx); + error = ret.err; + off1 = ret.result; + if (error != 0) + return { err: error, bytes: pbytes, len: pbyte_len }; + + if (off1 != 0) + { + do + { + element++; + ret = cff_index_read_offset(idx); + error = ret.err; + off2 = ret.result; + } + while (off2 == 0 && element < idx.count); + } + } + else /* use offsets table */ + { + off1 = idx.offsets[element]; + if (off1) + { + do + { + element++; + off2 = idx.offsets[element]; + + } while (off2 == 0 && element < idx.count); + } + } + + /* XXX: should check off2 does not exceed the end of this entry; */ + /* at present, only truncate off2 at the end of this stream */ + if (off2 > stream.size + 1 || idx.data_offset > stream.size - off2 + 1) + { + off2 = stream.size - idx.data_offset + 1; + } + + /* access element */ + if (off1 && off2 > off1) + { + pbyte_len = off2 - off1; + + if (idx.bytes != null) + { + /* this index was completely loaded in memory, that's easy */ + pbytes = dublicate_pointer(idx.bytes); + pbytes.pos += (off1 - 1); + } + else + { + /* this index is still on disk/file, access it through a frame */ + error = stream.Seek(idx.data_offset + off1 - 1); + if (error == 0) + { + pbytes = new CPointer(); + error = stream.ExtractFrame(off2 - off1, pbytes); + } + } + } + else + { + /* empty index element */ + pbytes = null; + pbyte_len = 0; + } + } + else + error = FT_Common.FT_Err_Invalid_Argument; + + return { err: error, bytes: pbytes, len: pbyte_len }; +} + +function cff_index_forget_element(idx, pbytes) +{ + if (idx.bytes == null) + { + idx.stream.ReleaseFrame(); + pbytes = null; + } +} + +function cff_index_get_name(font, element) +{ + var idx = font.name_index; + var ret = cff_index_access_element(idx, element); + if (0 != ret.err) + return null; + + var name = ""; + var _len = ret.len; + var _d = ret.bytes; + for (var i = 0; i < _len; i++) + name += String.fromCharCode(_d.data[_d.pos + i]); + + cff_index_forget_element(idx, ret.bytes); + return name; +} + +function cff_index_get_string(font, element) +{ + return (element < font.num_strings) ? FT_PEEK_String1(font.strings[element], 1000) : null; +} + +function cff_index_get_sid_string(font, sid) +{ + /* value 0xFFFFU indicates a missing dictionary entry */ + if (sid == 0xFFFF) + return null; + + /* if it is not a standard string, return it */ + if (sid > 390) + return cff_index_get_string(font, sid - 391); + + /* CID-keyed CFF fonts don't have glyph names */ + if (font.psnames == null) + return null; + + /* this is a standard string */ + return font.psnames.adobe_std_strings(sid); +} + +function CFF_Done_FD_Select(fdselect, stream) +{ + if (fdselect.data) + { + stream.ReleaseFrame(); + fdselect.data = null; + } + + fdselect.data_size = 0; + fdselect.format = 0; + fdselect.range_count = 0; +} + +function CFF_Load_FD_Select(fdselect, num_glyphs, stream, offset) +{ + var error = stream.Seek(offset); + if (error != 0) + return error; + + var format = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + return error; + + fdselect.format = format; + fdselect.cache_count = 0; /* clear cache */ + + switch (format) + { + case 0: /* format 0, that's simple */ + fdselect.data_size = num_glyphs; + fdselect.data = new CPointer(); + error = stream.ExtractFrame(fdselect.data_size, fdselect.data); + break; + case 3: /* format 3, a tad more complex */ + var num_ranges = stream.ReadUShort(); + error = FT_Error; + if (error != 0) + return error; + + fdselect.data_size = num_ranges * 3 + 2; + fdselect.data = new CPointer(); + error = stream.ExtractFrame(fdselect.data_size, fdselect.data); + break; + + default: /* hmm... that's wrong */ + error = FT_Common.FT_Err_Invalid_File_Format; + } + + return error; +} + +function cff_fd_select_get(fdselect, glyph_index) +{ + var fd = 0; + switch (fdselect.format) + { + case 0: + fd = fdselect.data.data[fdselect.data.pos + glyph_index]; + break; + + case 3: + /* first, compare to cache */ + if ((glyph_index - fdselect.cache_first) < fdselect.cache_count) + { + fd = fdselect.cache_fd; + break; + } + + /* then, lookup the ranges array */ + var p = dublicate_pointer(fdselect.data); + var p_limit = p.pos + fdselect.data_size; + + var first = FT_NEXT_USHORT(p); + do + { + if (glyph_index < first) + break; + + var fd2 = p.data[p.pos]; + p.pos++; + var limit = FT_NEXT_USHORT(p); + + if (glyph_index < limit) + { + fd = fd2; + + /* update cache */ + fdselect.cache_first = first; + fdselect.cache_count = limit-first; + fdselect.cache_fd = fd2; + break; + } + first = limit; + + } while ( p < p_limit ); + break; + + default: + break; + } + + return fd; +} + +function cff_charset_compute_cids(charset, num_glyphs, memory) +{ + var error = 0; + var max_cid = 0; + + if (charset.max_cid > 0) + return error; + + for (var i = 0; i < num_glyphs; i++) + { + if (charset.sids[i] > max_cid) + max_cid = charset.sids[i]; + } + + charset.cids = CreateUIntArray(max_cid + 1); + + /* When multiple GIDs map to the same CID, we choose the lowest */ + /* GID. This is not described in any spec, but it matches the */ + /* behaviour of recent Acroread versions. */ + for (var j = num_glyphs - 1; j >= 0 ; j--) + charset.cids[charset.sids[j]] = j; + + charset.max_cid = max_cid; + charset.num_glyphs = num_glyphs; + + return error; +} + +function cff_charset_cid_to_gindex(charset, cid) +{ + if (cid <= charset.max_cid) + return charset.cids[cid]; + return 0; +} + +function cff_charset_free_cids(charset, memory) +{ + charset.cids = null; + charset.max_cid = 0; +} + +function cff_charset_done(charset, stream) +{ + cff_charset_free_cids(charset, stream.memory); + + charset.sids = null; + charset.format = 0; + charset.offset = 0; +} + +function cff_charset_load(charset, num_glyphs, stream, base_offset, offset, invert) +{ + var error = 0; + var glyph_sid = 0; + + /* If the the offset is greater than 2, we have to parse the */ + /* charset table. */ + if (offset > 2) + { + charset.offset = base_offset + offset; + + error = stream.Seek(charset.offset); + if (error != 0) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return error; + } + + charset.format = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return error; + } + + charset.sids = CreateUIntArray(num_glyphs); + + /* assign the .notdef glyph */ + charset.sids[0] = 0; + + switch (charset.format) + { + case 0: + if (num_glyphs > 0) + { + error = stream.EnterFrame((num_glyphs - 1) * 2); + if (error != 0) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return error; + } + + for (j = 1; j < num_glyphs; j++) + charset.sids[j] = stream.GetUShort(); + + stream.ExitFrame(); + } + break; + + case 1: + case 2: + var nleft = 0; + var j = 1; + while (j < num_glyphs) + { + glyph_sid = stream.ReadUShort(); + error = FT_Error; + if (error != 0) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return error; + } + + if (charset.format == 2) + { + nleft = stream.ReadUShort(); + error = FT_Error; + if (error != 0) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return error; + } + } + else + { + nleft = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return error; + } + } + + /* try to rescue some of the SIDs if `nleft' is too large */ + if (glyph_sid > (0xFFFF - nleft)) + { + nleft = (0xFFFF - glyph_sid); + } + + /* Fill in the range of sids -- `nleft + 1' glyphs. */ + for (i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++) + charset.sids[j] = glyph_sid; + } + break; + + default: + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return FT_Common.FT_Err_Invalid_File_Format; + } + } + else + { + /* Parse default tables corresponding to offset == 0, 1, or 2. */ + /* CFF specification intimates the following: */ + /* */ + /* In order to use a predefined charset, the following must be */ + /* true: The charset constructed for the glyphs in the font's */ + /* charstrings dictionary must match the predefined charset in */ + /* the first num_glyphs. */ + charset.offset = offset; /* record charset type */ + + switch (offset) + { + case 0: + if (num_glyphs > 229) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return FT_Common.FT_Err_Invalid_File_Format; + } + + charset.sids = CreateUIntArray(num_glyphs); + for (var k = 0; k < num_glyphs; k++) + charset.sids[k] = cff_isoadobe_charset[k]; + + break; + + case 1: + if (num_glyphs > 166) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return FT_Common.FT_Err_Invalid_File_Format; + } + + charset.sids = CreateUIntArray(num_glyphs); + for (var k = 0; k < num_glyphs; k++) + charset.sids[k] = cff_expert_charset[k]; + + break; + + case 2: + if (num_glyphs > 87) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return FT_Common.FT_Err_Invalid_File_Format; + } + + charset.sids = CreateUIntArray(num_glyphs); + for (var k = 0; k < num_glyphs; k++) + charset.sids[k] = cff_expertsubset_charset[k]; + + break; + + default: + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + return FT_Common.FT_Err_Invalid_File_Format; + } + } + + /* we have to invert the `sids' array for subsetted CID-keyed fonts */ + if (invert) + error = cff_charset_compute_cids(charset, num_glyphs, stream.memory); + + if (error != 0) + { + charset.sids = null; + charset.cids = null; + charset.format = 0; + charset.offset = 0; + } + return error; +} + +function cff_encoding_done(encoding) +{ + encoding.format = 0; + encoding.offset = 0; + encoding.count = 0; +} + +function cff_encoding_load(encoding, charset, num_glyphs, stream, base_offset, offset) +{ + var error = 0; + var count = 0; + var j = 0; + var glyph_sid = 0; + var glyph_code = 0; + + + /* Check for charset->sids. If we do not have this, we fail. */ + if (charset.sids == null) + return FT_Common.FT_Err_Invalid_File_Format; + + /* Zero out the code to gid/sid mappings. */ + for (j = 0; j < 256; j++) + { + encoding.sids[j] = 0; + encoding.codes[j] = 0; + } + + /* Note: The encoding table in a CFF font is indexed by glyph index; */ + /* the first encoded glyph index is 1. Hence, we read the character */ + /* code (`glyph_code') at index j and make the assignment: */ + /* */ + /* encoding->codes[glyph_code] = j + 1 */ + /* */ + /* We also make the assignment: */ + /* */ + /* encoding->sids[glyph_code] = charset->sids[j + 1] */ + /* */ + /* This gives us both a code to GID and a code to SID mapping. */ + if (offset > 1) + { + encoding.offset = base_offset + offset; + + error = stream.Seek(encoding.offset); + if (error != 0) + return error; + encoding.format = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + return error; + count = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + return error; + + switch (encoding.format & 0x7F) + { + case 0: + encoding.count = count + 1; + error = stream.EnterFrame(count); + if (error != 0) + return error; + + var p = stream.cur; + for (j = 1; j <= count; j++) + { + glyph_code = stream.data[p]; + p++; + /* Make sure j is not too big. */ + if (j < num_glyphs) + { + /* Assign code to GID mapping. */ + encoding.codes[glyph_code] = j; + /* Assign code to SID mapping. */ + encoding.sids[glyph_code] = charset.sids[j]; + } + } + stream.ExitFrame(); + break; + + case 1: + var nleft = 0; + var i = 1; + encoding.count = 0; + + /* Parse the Format1 ranges. */ + for (j = 0; j < count; j++, i += nleft) + { + /* Read the first glyph code of the range. */ + glyph_code = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + return error; + + nleft = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + return error; + /* Read the number of codes in the range. */ + /* Increment nleft, so we read `nleft + 1' codes/sids. */ + nleft++; + + /* compute max number of character codes */ + if (nleft > encoding.count) + encoding.count = nleft; + + /* Fill in the range of codes/sids. */ + for (var k = i; k < nleft + i; k++, glyph_code++) + { + /* Make sure k is not too big. */ + if (k < num_glyphs && glyph_code < 256) + { + /* Assign code to GID mapping. */ + encoding.codes[glyph_code] = k; + /* Assign code to SID mapping. */ + encoding.sids[glyph_code] = charset.sids[k]; + } + } + } + + /* simple check; one never knows what can be found in a font */ + if (encoding.count > 256) + encoding.count = 256; + + break; + + default: + return FT_Common.FT_Err_Invalid_File_Format; + } + + /* Parse supplemental encodings, if any. */ + if (encoding.format & 0x80) + { + count = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + return error; + + for (j = 0; j < count; j++) + { + /* Read supplemental glyph code. */ + glyph_code = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + return error; + + glyph_sid = stream.ReadUShort(); + error = FT_Error; + if (error != 0) + return error; + + /* Assign code to SID mapping. */ + encoding.sids[glyph_code] = glyph_sid; + + /* First, look up GID which has been assigned to */ + /* SID glyph_sid. */ + for (var gindex = 0; gindex < num_glyphs; gindex++) + { + if (charset.sids[gindex] == glyph_sid) + { + encoding.codes[glyph_code] = gindex; + break; + } + } + } + } + } + else + { + /* We take into account the fact a CFF font can use a predefined */ + /* encoding without containing all of the glyphs encoded by this */ + /* encoding (see the note at the end of section 12 in the CFF */ + /* specification). */ + + switch (offset) + { + case 0: + case 1: + var src = (offset == 0) ? cff_standard_encoding : cff_expert_encoding; + for (var k = 0; k < 256; k++) + encoding.sids[k] = src[k]; + + encoding.count = 0; + error = cff_charset_compute_cids(charset, num_glyphs, stream.memory); + if (error != 0) + return error; + + for (j = 0; j < 256; j++) + { + var sid = encoding.sids[j]; + var gid = 0; + + + if (sid) + gid = cff_charset_cid_to_gindex(charset, sid); + + if ( gid != 0 ) + { + encoding.codes[j] = gid; + encoding.count = j + 1; + } + else + { + encoding.codes[j] = 0; + encoding.sids [j] = 0; + } + } + break; + + default: + return FT_Common.FT_Err_Invalid_File_Format; + } + } + + return error; +} + +function cff_subfont_load(font, idx, font_index, stream, base_offset, library) +{ + var error = 0; + var parser = new CFF_ParserRec(); + var top = font.font_dict; + var priv = font.private_dict; + + cff_parser_init(parser, FT_Common.CFF_CODE_TOPDICT, font.font_dict, library); + + /* set defaults */ + top.clear(); + + top.underline_position = -100 << 16; + top.underline_thickness = 50 << 16; + top.charstring_type = 2; + top.font_matrix.xx = 0x10000; + top.font_matrix.yy = 0x10000; + top.cid_count = 8720; + + /* we use the implementation specific SID value 0xFFFF to indicate */ + /* missing entries */ + top.version = 0xFFFF; + top.notice = 0xFFFF; + top.copyright = 0xFFFF; + top.full_name = 0xFFFF; + top.family_name = 0xFFFF; + top.weight = 0xFFFF; + top.embedded_postscript = 0xFFFF; + + top.cid_registry = 0xFFFF; + top.cid_ordering = 0xFFFF; + top.cid_font_name = 0xFFFF; + + var ret = cff_index_access_element(idx, font_index); + error = ret.err; + var dict = ret.bytes; + var dict_len = ret.len; + + if (error == 0) + { + error = cff_parser_run(parser, dict, dict.pos + dict_len); + } + + cff_index_forget_element(idx, dict); + + if (error != 0) + return error; + + /* if it is a CID font, we stop there */ + if (top.cid_registry != 0xFFFF) + return error; + + /* parse the private dictionary, if any */ + if (top.private_offset != 0 && top.private_size != 0) + { + priv.clear(); + + priv.blue_shift = 7; + priv.blue_fuzz = 1; + priv.lenIV = -1; + priv.expansion_factor = parseInt(0.06 * 0x10000); + priv.blue_scale = parseInt(0.039625 * 0x10000 * 1000); + + cff_parser_init(parser, FT_Common.CFF_CODE_PRIVATE, priv, library); + + error = stream.Seek(base_offset + font.font_dict.private_offset); + if (error != 0) + return error; + + error = stream.EnterFrame(font.font_dict.private_size); + if (error != 0) + return error; + + var curs = new CPointer(); + curs.data = stream.data; + curs.pos = stream.cur; + error = cff_parser_run(parser, curs, curs.pos + font.font_dict.private_size); + + stream.ExitFrame(); + if (error != 0) + return error; + + /* ensure that `num_blue_values' is even */ + priv.num_blue_values &= ~1; + } + + /* read the local subrs, if any */ + if (priv.local_subrs_offset != 0) + { + error = stream.Seek(base_offset + top.private_offset + priv.local_subrs_offset); + if (error != 0) + return error; + + error = cff_index_init(font.local_subrs_index, stream, 1); + if (error != 0) + return error; + + ret = cff_index_get_pointers(font.local_subrs_index, font.local_subrs, null, 0); + error = ret.err; + font.local_subrs = ret.table; + if (error != 0) + return error; + } + + return error; +} + +function cff_subfont_done(memory, subfont) +{ + if (subfont != null) + { + cff_index_done(subfont.local_subrs_index); + subfont.local_subrs = null; + } +} + +function cff_font_load(library, stream, face_index, font, pure_cff) +{ + var error = 0; + var memory = stream.memory; + var base_offset = stream.pos; + var dict = font.top_font.font_dict; + var string_index = new CFF_IndexRec(); + + // TODO: font.clear(); + error = stream.EnterFrame(4); + if (error != 0) + return error; + + /* read CFF font header */ + font.version_major = stream.GetUChar(); + font.version_minor = stream.GetUChar(); + font.header_size = stream.GetUChar(); + font.absolute_offsize = stream.GetUChar(); + + stream.ExitFrame(); + + /* check format */ + if (font.version_major != 1 || font.header_size < 4 || font.absolute_offsize > 4) + return FT_Common.FT_Err_Unknown_File_Format; + + /* skip the rest of the header */ + error = stream.Skip(font.header_size - 4); + if (error != 0) + return error; + + /* read the name, top dict, string and global subrs index */ + error = cff_index_init(font.name_index, stream, 0); + if (error == 0) + error = cff_index_init(font.font_dict_index, stream, 0); + if (error == 0) + error = cff_index_init(string_index, stream, 1); + if (error == 0) + error = cff_index_init(font.global_subrs_index, stream, 1); + + if (error != 0) + return error; + + var ret = cff_index_get_pointers(string_index, font.strings, font.string_pool, 1); + error = ret.err; + font.strings = ret.table; + font.string_pool = ret.pool; + + font.num_strings = string_index.count; + + /* well, we don't really forget the `disabled' fonts... */ + font.num_faces = font.name_index.count; + if (face_index >= font.num_faces) + { + error = FT_Common.FT_Err_Invalid_Argument; + } + + /* in case of a font format check, simply exit now */ + if (face_index < 0) + return error; + + /* now, parse the top-level font dictionary */ + error = cff_subfont_load(font.top_font, font.font_dict_index, face_index, stream, base_offset, library); + if (error != 0) + return error; + + error = stream.Seek(base_offset + dict.charstrings_offset); + if (error != 0) + return error; + + error = cff_index_init(font.charstrings_index, stream, 0); + if (error != 0) + return error; + + /* now, check for a CID font */ + if (dict.cid_registry != 0xFFFF) + { + var fd_index = new CFF_IndexRec(); + var sub = null; + + /* this is a CID-keyed font, we must now allocate a table of */ + /* sub-fonts, then load each of them separately */ + error = stream.Seek(base_offset + dict.cid_fd_array_offset); + if (error != 0) + return error; + + error = cff_index_init(fd_index, stream, 0); + if (error != 0) + return error; + + if (fd_index.count > FT_Common.CFF_MAX_CID_FONTS) + { + cff_index_done(fd_index); + } + else + { + var _is_break = 0; + /* allocate & read each font dict independently */ + font.num_subfonts = fd_index.count; + sub = new Array(fd_index.count); + + for (var idx = 0; idx < fd_index.count; idx++) + sub[idx] = new CFF_SubFontRec(); + + /* set up pointer table */ + for (var idx = 0; idx < fd_index.count; idx++) + font.subfonts[idx] = sub[idx]; + + /* now load each subfont independently */ + for (var idx = 0; idx < fd_index.count; idx++) + { + error = cff_subfont_load(font.subfonts[idx], fd_index, idx, stream, base_offset, library); + if (error != 0) + { + cff_index_done(fd_index); + _is_break = 1; + } + } + + /* now load the FD Select array */ + if (_is_break == 0) + { + error = CFF_Load_FD_Select(font.fd_select, font.charstrings_index.count, stream, base_offset + dict.cid_fd_select_offset); + } + + cff_index_done(fd_index); + + if (error != 0) + return error; + } + } + else + font.num_subfonts = 0; + + /* read the charstrings index now */ + if (dict.charstrings_offset == 0) + return FT_Common.FT_Err_Invalid_File_Format; + + + font.num_glyphs = font.charstrings_index.count; + + ret = cff_index_get_pointers(font.global_subrs_index, font.global_subrs, null, 0); + error = ret.err; + font.global_subrs = ret.table; + + if (error != 0) + return error; + + /* read the Charset and Encoding tables if available */ + if (font.num_glyphs > 0) + { + var invert = (dict.cid_registry != 0xFFFF && pure_cff) ? 1 : 0; + + error = cff_charset_load(font.charset, font.num_glyphs, stream, base_offset, dict.charset_offset, invert); + if (error != 0) + return error; + + /* CID-keyed CFFs don't have an encoding */ + if (dict.cid_registry == 0xFFFF) + { + error = cff_encoding_load(font.encoding, font.charset, font.num_glyphs, stream, base_offset, dict.encoding_offset); + if (error != 0) + return error; + } + } + + /* get the font name (/CIDFontName for CID-keyed fonts, */ + /* /FontName otherwise) */ + font.font_name = cff_index_get_name(font, face_index); + + cff_index_done(string_index); + return error; +} + +function cff_font_done(font) +{ + var memory = font.memory; + + cff_index_done(font.global_subrs_index); + cff_index_done(font.font_dict_index ); + cff_index_done(font.name_index); + cff_index_done(font.charstrings_index); + + /* release font dictionaries, but only if working with */ + /* a CID keyed CFF font */ + if (font.num_subfonts > 0) + { + for (var idx = 0; idx < font.num_subfonts; idx++) + cff_subfont_done(memory, font.subfonts[idx]); + + /* the subfonts array has been allocated as a single block */ + font.subfonts[0] = null; + } + + cff_encoding_done(font.encoding); + cff_charset_done(font.charset, font.stream); + + cff_subfont_done(memory, font.top_font); + + CFF_Done_FD_Select(font.fd_select, font.stream); + + font.font_info = null; + + font.strings = null; + font.string_pool = null; +} + +/******************************************************************************/ +// cffcmaps +/******************************************************************************/ +function CFF_CMapStdRec() +{ + this.cmap = new FT_CMapRec(); + this.gids = null; + + this.type = FT_Common.FT_CMAP_1; +} + +function cff_cmap_encoding_init(cmap) +{ + cmap.gids = __FT_CMapRec(cmap).charmap.face.extra.data.encoding.codes; + return 0; +} + +function cff_cmap_encoding_done(cmap) +{ + cmap.gids = null; +} + +function cff_cmap_encoding_char_index(cmap, char_code) +{ + if (char_code < 256) + return cmap.gids[char_code]; + + return 0; +} + +function cff_cmap_encoding_char_next(cmap, pchar_code) +{ + var char_code = pchar_code; + var ret = {gindex: 0, char_code: 0}; + + if (char_code < 255) + { + var code = char_code + 1; + + for (;;) + { + if (code >= 256) + break; + + ret.gindex = cmap.gids[code]; + if (ret.gindex != 0) + { + ret.char_code = code; + break; + } + code++; + } + } + return ret; +} + +var cff_cmap_encoding_class_rec = create_cmap_class_rec(101,cff_cmap_encoding_init,cff_cmap_encoding_done,cff_cmap_encoding_char_index,cff_cmap_encoding_char_next,null,null,null,null,null); + +function cff_sid_to_glyph_name(face, idx) +{ + var cff = face.extra.data; + var sid = cff.charset.sids[idx]; + + return cff_index_get_sid_string(cff, sid); +} + +function cff_cmap_unicode_init(unicodes) +{ + var face = __FT_CharmapRec(unicodes).face; + var cff = face.extra.data; + var charset = cff.charset; + var psnames = cff.psnames; + + /* can't build Unicode map for CID-keyed font */ + /* because we don't know glyph names. */ + if (charset.sids == null) + return FT_Common.FT_Err_No_Unicode_Glyph_Name; + + return psnames.unicodes_init(face.memory, unicodes, cff.num_glyphs, cff_sid_to_glyph_name, null, face); +} + +function cff_cmap_unicode_done(unicodes) +{ + unicodes.maps = null; + unicodes.num_maps = 0; +} + +function cff_cmap_unicode_char_index(unicodes, char_code) +{ + var face = __FT_CharmapRec(unicodes).face; + var psnames = face.extra.data.psnames; + + return psnames.unicodes_char_index(unicodes, char_code); +} + +function cff_cmap_unicode_char_next(unicodes, pchar_code) +{ + var face = __FT_CharmapRec(unicodes).face; + var psnames = face.extra.data.psnames; + + return psnames.unicodes_char_next(unicodes, pchar_code); +} + +var cff_cmap_unicode_class_rec = create_cmap_class_rec(102,cff_cmap_unicode_init,cff_cmap_unicode_done,cff_cmap_unicode_char_index,cff_cmap_unicode_char_next,null,null,null,null,null); + +/******************************************************************************/ +// cffobjs +/******************************************************************************/ + +function CFF_SizeRec() +{ + this.face = null; + this.generic = null; + this.metrics = new FT_Size_Metrics(); + this.internal = null; + + this.strike_index = 0; /* 0xFFFFFFFF to indicate invalid */ +} + +function CFF_GlyphSlotRec() +{ + this.root = new FT_GlyphSlot(); + + this.hint = 0; + this.scaled = 0; + + this.x_scale = 0; + this.y_scale = 0; +} + +function CFF_InternalRec() +{ + this.topfont = null; + this.subfonts = new Array(FT_Common.CFF_MAX_CID_FONTS); +} + +function CFF_Transform() +{ + this.xx = 0; + this.xy = 0; + this.yx = 0; + this.yy = 0; + + this.ox = 0; + this.oy = 0; +} + +function cff_size_get_globals_funcs(size) +{ + var face = size.face; + var font = face.extra.data; + var pshinter = font.pshinter; + + var module = face.driver.library.FT_Get_Module("pshinter"); + return (module != null && pshinter != null && pshinter.get_globals_funcs != null) ? pshinter.get_globals_funcs(module) : null; +} + +function cff_size_done(cffsize) +{ + var internal = cffsize.internal; + if (internal != null) + { + var funcs = cff_size_get_globals_funcs(size); + if (funcs != null) + { + funcs.destroy(internal.topfont); + + for (var i = font.num_subfonts; i > 0; i--) + funcs.destroy(internal.subfonts[i - 1]); + } + /* `internal' is freed by destroy_size (in ftobjs.c) */ + } +} + +function cff_make_private_dict(subfont, priv) +{ + var cpriv = subfont.private_dict; + var n = 0; + priv.clear(); + + var count = priv.num_blue_values = cpriv.num_blue_values; + for (n = 0; n < count; n++) + priv.blue_values[n] = cpriv.blue_values[n]; + + count = priv.num_other_blues = cpriv.num_other_blues; + for (n = 0; n < count; n++) + priv.other_blues[n] = cpriv.other_blues[n]; + + count = priv.num_family_blues = cpriv.num_family_blues; + for (n = 0; n < count; n++) + priv.family_blues[n] = cpriv.family_blues[n]; + + count = priv.num_family_other_blues = cpriv.num_family_other_blues; + for (n = 0; n < count; n++) + priv.family_other_blues[n] = cpriv.family_other_blues[n]; + + priv.blue_scale = cpriv.blue_scale; + priv.blue_shift = cpriv.blue_shift; + priv.blue_fuzz = cpriv.blue_fuzz; + + priv.standard_width[0] = cpriv.standard_width; + priv.standard_height[0] = cpriv.standard_height; + + count = priv.num_snap_widths = cpriv.num_snap_widths; + for (n = 0; n < count; n++) + priv.snap_widths[n] = cpriv.snap_widths[n]; + + count = priv.num_snap_heights = cpriv.num_snap_heights; + for (n = 0; n < count; n++) + priv.snap_heights[n] = cpriv.snap_heights[n]; + + priv.force_bold = cpriv.force_bold; + priv.language_group = cpriv.language_group; + priv.lenIV = cpriv.lenIV; +} + +function cff_size_init() +{ + var size = new CFF_SizeRec(); + var funcs = null;//cff_size_get_globals_funcs(size); + + if (funcs != null) + { + // TODO: global funcs... + } + + FT_Error = 0; + size.strike_index = 0xFFFFFFFF; + return size; +} + +function cff_size_select(size, strike_index) +{ + size.strike_index = strike_index; + FT_Select_Metrics(size.face, strike_index); + + var funcs = cff_size_get_globals_funcs(size); + + if (funcs != null) + { + // TODO: global funcs... + } + + return 0; +} + +function cff_size_request(size, req) +{ + var face = size.face; + if (0 != (face.face_flags & FT_Common.FT_FACE_FLAG_FIXED_SIZES)) + { + var sfnt = face.sfnt; + + var strike_index = sfnt.set_sbit_strike(face, req); + if (FT_Error != 0) + size.strike_index = 0xFFFFFFFF; + else + return cff_size_select(size, strike_index); + } + + FT_Request_Metrics(size.face, req); + + var funcs = cff_size_get_globals_funcs(size); + if (funcs != null) + { + // TODO: global funcs... + } + return 0; +} + +function cff_slot_done(slot) +{ + slot.internal.glyph_hints = null; +} + +function cff_slot_init(slot) +{ + var face = slot.face; + var font = face.extra.data; + var pshinter = font.pshinter; + + if (pshinter != null) + { + var module = face.driver.library.FT_Get_Module("pshinter"); + if (module != null) + { + slot.internal.glyph_hints = pshinter.get_t2_funcs(module); + } + } + return 0; +} + +function cff_strcpy(memory, source) +{ + var result = source; + return result; +} + +function remove_subset_prefix(name) +{ + var idx = 0; + var length = name.length + 1; + var continue_search = 1; + + while (continue_search) + { + if (length >= 7 && name.charCodeAt(6) == FT_Common.SYMBOL_CONST_MATH_PLUS) + { + for (idx = 0; idx < 6; idx++) + { + /* ASCII uppercase letters */ + var c = name.charCodeAt(idx); + if (!(FT_Common.SYMBOL_CONST_A <= c && c <= FT_Common.SYMBOL_CONST_Z)) + continue_search = 0; + } + + if (continue_search) + { + name = name.substring(7); + length -= 7; + } + } + else + continue_search = 0; + } + + return name; +} + +function remove_style(family_name, style_name) +{ + var family_name_length = family_name.length; + var style_name_length = style_name.length; + + if (family_name_length > style_name_length) + { + var idx = 0; + for (idx = 1; idx <= style_name_length; idx++) + { + if (family_name.charCodeAt(family_name_length - idx) != style_name.charCodeAt(style_name_length - idx)) + break; + } + + if (idx > style_name_length) + { + /* family_name ends with style_name; remove it */ + idx = family_name_length - style_name_length - 1; + + /* also remove special characters */ + /* between real family name and style */ + while (idx > 0) + { + var c = family_name.charCodeAt(idx); + if (c == FT_Common.SYMBOL_CONST_MATH_MINUS || c == FT_Common.SYMBOL_CONST_SPACE || c == FT_Common.SYMBOL_CONST__ || c == FT_Common.SYMBOL_CONST_MATH_PLUS) + break; + + --idx; + } + + if (idx > 0) + family_name = family_name.substring(0, idx); + } + } + + return family_name; +} + +function cff_face_init(stream, face, face_index, num_params, params) +{ + var pure_cff = 1; + var sfnt_format = 0; + var flags = 0; + var library = face.driver.library; + + var sfnt = library.FT_Get_Module_Interface("sfnt"); + if (sfnt == null) + return FT_Common.FT_Err_Unknown_File_Format; + + var psnames = FT_FACE_FIND_GLOBAL_SERVICE(face, FT_SERVICE_ID_POSTSCRIPT_CMAPS); + var pshinter = library.FT_Get_Module_Interface("pshinter"); + + /* create input stream from resource */ + var error = stream.Seek(0); + if (error != 0) + return error; + + /* check whether we have a valid OpenType file */ + error = sfnt.init_face(stream, face, face_index, num_params, params); + if (error == 0) + { + if (face.format_tag != FT_Common.TTAG_OTTO) + return FT_Common.FT_Err_Unknown_File_Format; + + /* if we are performing a simple font format check, exit immediately */ + if (face_index < 0) + return 0; + + /* UNDOCUMENTED! A CFF in an SFNT can have only a single font. */ + if (face_index > 0) + return FT_Common.FT_Err_Invalid_Argument; + + sfnt_format = 1; + + /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ + /* font; in the latter case it doesn't have a `head' table */ + face.goto_table(face, FT_Common.TTAG_head, stream); + error = FT_Error; + if (error == 0) + { + pure_cff = 0; + + /* load font directory */ + error = sfnt.load_face(stream, face, 0); + if (error != 0) + return error; + } + else + { + /* load the `cmap' table explicitly */ + error = sfnt.load_cmap(face, stream); + if (error != 0) + return error; + + /* XXX: we don't load the GPOS table, as OpenType Layout */ + /* support will be added later to a layout library on top of */ + /* FreeType 2 */ + } + + /* now load the CFF part of the file */ + face.goto_table(face, FT_Common.TTAG_CFF, stream); + error = FT_Error; + if (error != 0) + return error; + } + else + { + /* rewind to start of file; we are going to load a pure-CFF font */ + error = stream.Seek(0); + if (error != 0) + return error; + } + + /* now load and parse the CFF table in the file */ + var cff = new CFF_FontRec(); + face.extra.data = cff; + + error = cff_font_load(library, stream, face_index, cff, pure_cff); + if (error != 0) + return error; + + cff.pshinter = pshinter; + cff.psnames = psnames; + + face.face_index = face_index; + + /* Complement the root flags with some interesting information. */ + /* Note that this is only necessary for pure CFF and CEF fonts; */ + /* SFNT based fonts use the `name' table instead. */ + face.num_glyphs = cff.num_glyphs; + var dict = cff.top_font.font_dict; + + /* we need the `PSNames' module for CFF and CEF formats */ + /* which aren't CID-keyed */ + if (dict.cid_registry == 0xFFFF && psnames == null) + return FT_Common.FT_Err_Unknown_File_Format; + + if (dict.has_font_matrix == 0) + dict.units_per_em = pure_cff ? 1000 : face.units_per_EM; + + /* Normalize the font matrix so that `matrix->xx' is 1; the */ + /* scaling is done with `units_per_em' then (at this point, */ + /* it already contains the scaling factor, but without */ + /* normalization of the matrix). */ + /* */ + /* Note that the offsets must be expressed in integer font */ + /* units. */ + var matrix = dict.font_matrix; + var offset = dict.font_offset; + var temp = Math.abs(matrix.yy); + + if (temp != 0x10000) + { + dict.units_per_em = FT_DivFix(dict.units_per_em, temp); + + matrix.xx = FT_DivFix(matrix.xx, temp); + matrix.yx = FT_DivFix(matrix.yx, temp); + matrix.xy = FT_DivFix(matrix.xy, temp); + matrix.yy = FT_DivFix(matrix.yy, temp); + offset.x = FT_DivFix(offset.x, temp); + offset.y = FT_DivFix(offset.y, temp); + } + + offset.x >>= 16; + offset.y >>= 16; + + for (var i = cff.num_subfonts; i > 0; i--) + { + var sub = cff.subfonts[i - 1].font_dict; + var top = cff.top_font.font_dict; + + if (sub.has_font_matrix == 1) + { + var scaling = 0; + /* if we have a top-level matrix, */ + /* concatenate the subfont matrix */ + + if (top.has_font_matrix == 1) + { + if (top.units_per_em > 1 && sub.units_per_em > 1) + scaling = Math.min(top.units_per_em, sub.units_per_em); + else + scaling = 1; + + FT_Matrix_Multiply_Scaled(top.font_matrix, sub.font_matrix, scaling); + FT_Vector_Transform_Scaled(sub.font_offset, top.font_matrix, scaling); + + sub.units_per_em = FT_MulDiv(sub.units_per_em, top.units_per_em, scaling); + } + } + else + { + sub.font_matrix = top.font_matrix; + sub.font_offset = top.font_offset; + + sub.units_per_em = top.units_per_em; + } + + matrix = sub.font_matrix; + offset = sub.font_offset; + temp = Math.abs(matrix.yy); + + if (temp != 0x10000) + { + sub.units_per_em = FT_DivFix(sub.units_per_em, temp); + + matrix.xx = FT_DivFix(matrix.xx, temp); + matrix.yx = FT_DivFix(matrix.yx, temp); + matrix.xy = FT_DivFix(matrix.xy, temp); + matrix.yy = FT_DivFix(matrix.yy, temp); + offset.x = FT_DivFix(offset.x, temp); + offset.y = FT_DivFix(offset.y, temp); + } + + offset.x >>= 16; + offset.y >>= 16; + } + + if (pure_cff == 1) + { + var style_name = null; + + /* set up num_faces */ + face.num_faces = cff.num_faces; + + /* compute number of glyphs */ + if (dict.cid_registry != 0xFFFF) + face.num_glyphs = cff.charset.max_cid + 1; + else + face.num_glyphs = cff.charstrings_index.count; + + /* set global bbox, as well as EM size */ + face.bbox.xMin = dict.font_bbox.xMin >> 16; + face.bbox.yMin = dict.font_bbox.yMin >> 16; + /* no `U' suffix here to 0xFFFF! */ + face.bbox.xMax = (dict.font_bbox.xMax + 0xFFFF) >> 16; + face.bbox.yMax = (dict.font_bbox.yMax + 0xFFFF) >> 16; + + face.units_per_EM = dict.units_per_em & 0xFFFF; + + face.ascender = face.bbox.yMax; + face.descender = face.bbox.yMin; + + face.height = ((face.units_per_EM * 12) / 10); + if (face.height < (face.ascender - face.descender)) + face.height = (face.ascender - face.descender); + + face.underline_position = (dict.underline_position >> 16); + face.underline_thickness = (dict.underline_thickness >> 16); + + /* retrieve font family & style name */ + face.family_name = cff_index_get_name(cff, face_index); + if (face.family_name != null) + { + var full = cff_index_get_sid_string(cff, dict.full_name); + var fullp = 0; + var family = face.family_name; + var family_name = null; + + face.family_name = remove_subset_prefix(face.family_name); + + if (dict.family_name != 0) + { + family_name = cff_index_get_sid_string(cff, dict.family_name); + if (family_name != null) + family = family_name; + } + + var familyp = 0; + var full_len = (full == null) ? 0 : full.length; + var family_len = family.length; + + /* We try to extract the style name from the full name. */ + /* We need to ignore spaces and dashes during the search. */ + if (full != null && family != null) + { + while (fullp < full_len) + { + var _c1 = full.charCodeAt(fullp); + var _c2 = 0; + if (familyp < family_len) + _c2 = family.charCodeAt(familyp); + + /* skip common characters at the start of both strings */ + if (_c1 == _c2) + { + familyp++; + fullp++; + continue; + } + + if (_c1 == FT_Common.SYMBOL_CONST_SPACE || _c1 == FT_Common.SYMBOL_CONST_MATH_MINUS) + { + fullp++; + continue; + } + + if (_c2 == FT_Common.SYMBOL_CONST_SPACE || _c2 == FT_Common.SYMBOL_CONST_MATH_MINUS) + { + familyp++; + continue; + } + + if (familyp >= family_len && fullp < full_len) + { + /* The full name begins with the same characters as the */ + /* family name, with spaces and dashes removed. In this */ + /* case, the remaining string in `fullp' will be used as */ + /* the style name. */ + style_name = full.substring(fullp); + + /* remove the style part from the family name (if present) */ + face.family_name = remove_style(face.family_name, style_name); + } + break; + } + } + } + else + { + var cid_font_name = cff_index_get_sid_string(cff, dict.cid_font_name); + /* do we have a `/FontName' for a CID-keyed font? */ + if (cid_font_name != null) + face.family_name = cff_strcpy(memory, cid_font_name); + } + + if (style_name != null) + face.style_name = style_name; + else /* assume "Regular" style if we don't know better */ + face.style_name = "Regular"; + + /*******************************************************************/ + /* */ + /* Compute face flags. */ + /* */ + flags = (FT_Common.FT_FACE_FLAG_SCALABLE | FT_Common.FT_FACE_FLAG_HORIZONTAL | FT_Common.FT_FACE_FLAG_HINTER); + + if (sfnt_format != 0) + flags |= FT_Common.FT_FACE_FLAG_SFNT; + + /* fixed width font? */ + if (dict.is_fixed_pitch != 0) + flags |= FT_Common.FT_FACE_FLAG_FIXED_WIDTH; + + /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ + + face.face_flags = flags; + /*******************************************************************/ + /* */ + /* Compute style flags. */ + /* */ + flags = 0; + + if (dict.italic_angle != 0) + flags |= FT_Common.FT_STYLE_FLAG_ITALIC; + + var weight = cff_index_get_sid_string(cff, dict.weight); + if (weight != null) + if (weight == "Bold" || weight == "Black") + flags |= FT_Common.FT_STYLE_FLAG_BOLD; + + /* double check */ + if (0 == (flags & FT_Common.FT_STYLE_FLAG_BOLD) && face.style_name != null) + if (!_strncmp(face.style_name, "Bold", 4) || !_strncmp(face.style_name, "Black", 5)) + flags |= FT_Common.FT_STYLE_FLAG_BOLD; + + face.style_flags = flags; + } + + + //#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES + /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ + /* has unset this flag because of the 3.0 `post' table. */ + if (dict.cid_registry == 0xFFFF) + face.face_flags |= FT_Common.FT_FACE_FLAG_GLYPH_NAMES; + //#endif + + if (dict.cid_registry != 0xFFFF && pure_cff == 1) + face.face_flags |= FT_Common.FT_FACE_FLAG_CID_KEYED; + + + /*******************************************************************/ + /* */ + /* Compute char maps. */ + /* */ + + /* Try to synthesize a Unicode charmap if there is none available */ + /* already. If an OpenType font contains a Unicode "cmap", we */ + /* will use it, whatever be in the CFF part of the file. */ + var cmaprec = new FT_CharMapRec(); + var cmap = null; + var nn = 0; + var encoding = cff.encoding; + + var is_skip_unicode = 0; + for (nn = 0; nn < face.num_charmaps; nn++) + { + cmap = face.charmaps[nn]; + + /* Windows Unicode? */ + if (cmap.platform_id == FT_Common.TT_PLATFORM_MICROSOFT && cmap.encoding_id == FT_Common.TT_MS_ID_UNICODE_CS) + is_skip_unicode = 1; + + /* Apple Unicode platform id? */ + if (cmap.platform_id == FT_Common.TT_PLATFORM_APPLE_UNICODE) + is_skip_unicode = 1; /* Apple Unicode */ + } + + if (0 == is_skip_unicode) + { + /* since CID-keyed fonts don't contain glyph names, we can't */ + /* construct a cmap */ + if (pure_cff == 1 && cff.top_font.font_dict.cid_registry != 0xFFFF) + return error; + + //#ifdef FT_MAX_CHARMAP_CACHEABLE + if (nn + 1 > FT_Common.FT_MAX_CHARMAP_CACHEABLE) + return error; + //#endif + + /* we didn't find a Unicode charmap -- synthesize one */ + cmaprec.face = face; + cmaprec.platform_id = FT_Common.TT_PLATFORM_MICROSOFT; + cmaprec.encoding_id = FT_Common.TT_MS_ID_UNICODE_CS; + cmaprec.encoding = FT_Common.FT_ENCODING_UNICODE; + + nn = face.num_charmaps; + + FT_CMap_New(FT_CFF_CMAP_UNICODE_CLASS_REC_GET, null, cmaprec); + error = FT_Error; + if (error && FT_Common.FT_Err_No_Unicode_Glyph_Name != error) + return error; + error = 0; + + /* if no Unicode charmap was previously selected, select this one */ + if (face.charmap == null && nn != face.num_charmaps) + face.charmap = face.charmaps[nn]; + } + + //#ifdef FT_MAX_CHARMAP_CACHEABLE + if (nn > FT_Common.FT_MAX_CHARMAP_CACHEABLE) + return error; + //#endif + + if (encoding.count > 0) + { + var clazz = null; + + cmaprec.face = face; + cmaprec.platform_id = FT_Common.TT_PLATFORM_ADOBE; /* Adobe platform id */ + + if (encoding.offset == 0) + { + cmaprec.encoding_id = FT_Common.TT_ADOBE_ID_STANDARD; + cmaprec.encoding = FT_Common.FT_ENCODING_ADOBE_STANDARD; + clazz = FT_CFF_CMAP_ENCODING_CLASS_REC_GET; + } + else if (encoding.offset == 1) + { + cmaprec.encoding_id = FT_Common.TT_ADOBE_ID_EXPERT; + cmaprec.encoding = FT_Common.FT_ENCODING_ADOBE_EXPERT; + clazz = FT_CFF_CMAP_ENCODING_CLASS_REC_GET; + } + else + { + cmaprec.encoding_id = FT_Common.TT_ADOBE_ID_CUSTOM; + cmaprec.encoding = FT_Common.FT_ENCODING_ADOBE_CUSTOM; + clazz = FT_CFF_CMAP_ENCODING_CLASS_REC_GET; + } + + FT_CMap_New(clazz, null, cmaprec); + error = FT_Error; + } + + return error; +} + +function cff_face_done(face) +{ + if (face == null) + return; + + var sfnt = face.sfnt; + + if (sfnt != null) + sfnt.done_face(face); + + var cff = face.extra.data; + if (cff != null) + { + cff_font_done(cff); + face.extra.data = null; + } +} + +function cff_driver_init(module) +{ + return 0; +} + +function cff_driver_done(module) +{ +} + +/******************************************************************************/ +// cffgload +/******************************************************************************/ + +var cff_argument_counts = +[ + 0, /* unknown */ + + 2 | FT_Common.CFF_COUNT_CHECK_WIDTH | FT_Common.CFF_COUNT_EXACT, /* rmoveto */ + 1 | FT_Common.CFF_COUNT_CHECK_WIDTH | FT_Common.CFF_COUNT_EXACT, + 1 | FT_Common.CFF_COUNT_CHECK_WIDTH | FT_Common.CFF_COUNT_EXACT, + + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, /* rlineto */ + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, + + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, /* rrcurveto */ + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, + 0 | FT_Common.CFF_COUNT_CLEAR_STACK, + + 13, /* flex */ + 7, + 9, + 11, + + 0 | FT_Common.CFF_COUNT_CHECK_WIDTH, /* endchar */ + + 2 | FT_Common.CFF_COUNT_CHECK_WIDTH, /* hstem */ + 2 | FT_Common.CFF_COUNT_CHECK_WIDTH, + 2 | FT_Common.CFF_COUNT_CHECK_WIDTH, + 2 | FT_Common.CFF_COUNT_CHECK_WIDTH, + + 0 | FT_Common.CFF_COUNT_CHECK_WIDTH, /* hintmask */ + 0 | FT_Common.CFF_COUNT_CHECK_WIDTH, /* cntrmask */ + 0, /* dotsection */ + + 1, /* abs */ + 2, + 2, + 2, + 1, + 0, + 2, + 1, + + 1, /* blend */ + + 1, /* drop */ + 2, + 1, + 2, + 1, + + 2, /* put */ + 1, + 4, + 3, + + 2, /* and */ + 2, + 1, + 2, + 4, + + 1, /* callsubr */ + 1, + 0, + + 2, /* hsbw */ + 0, + 0, + 0, + 5, /* seac */ + 4, /* sbw */ + 2 /* setcurrentpoint */ +]; + +function CFF_Builder() +{ + this.memory = null; + this.face = null; + this.glyph = null; + this.loader = null; + this.base = null; + this.current = null; + + this.pos_x = 0; + this.pos_y = 0; + + this.left_bearing = new FT_Vector(); + this.advance = new FT_Vector(); + + this.bbox = new FT_BBox(); + this.path_begun = 0; + this.load_points = 0; + this.no_recurse = 0; + + this.metrics_only = 0; + + this.hints_funcs = null; + this.hints_globals = null; + + this.clear = function() + { + this.memory = null; + this.face = null; + this.glyph = null; + this.loader = null; + this.base = null; + this.current = null; + + this.pos_x = 0; + this.pos_y = 0; + + this.left_bearing.x = 0; + this.left_bearing.y = 0; + + this.advance.x = 0; + this.advance.y = 0; + + this.bbox.xMin = 0; + this.bbox.yMin = 0; + this.bbox.xMax = 0; + this.bbox.yMax = 0; + + this.path_begun = 0; + this.load_points = 0; + this.no_recurse = 0; + + this.metrics_only = 0; + + this.hints_funcs = null; + this.hints_globals = null; + } +} + +function CFF_Decoder_Zone() +{ + this.base = null; + this.limit = 0; + this.cursor = 0; +} + +function CFF_Decoder() +{ + this.builder = new CFF_Builder(); + this.cff = null; + + this.stack = CreateIntArray(FT_Common.CFF_MAX_OPERANDS + 1); + this.top = 0; + + this.zones = new Array(FT_Common.CFF_MAX_SUBRS_CALLS + 1); + for (var i = 0; i < (FT_Common.CFF_MAX_SUBRS_CALLS + 1); i++) + this.zones[i] = new CFF_Decoder_Zone(); + + this.zone = 0; + + this.flex_state = 0; + this.num_flex_vectors = 0; + + this.flex_vectors = new Array(7); + for (var i = 0; i < 7; i++) + this.flex_vectors[i] = new FT_Vector(); + + this.glyph_width = 0; + this.nominal_width = 0; + + this.read_width = 0; + this.width_only = 0; + this.num_hints = 0; + this.buildchar = CreateIntArray(FT_Common.CFF_MAX_TRANS_ELEMENTS); + + this.num_locals = 0; + this.num_globals = 0; + + this.locals_bias = 0; + this.globals_bias = 0; + + this.locals = null; + this.globals = null; + + this.glyph_names = null; /* for pure CFF fonts only */ + this.num_glyphs = 0; /* number of glyphs in font */ + + this.hint_mode = 0; + + this.seac = 0; + + this.clear = function() + { + this.builder.clear(); + this.cff = null; + + this.stack = CreateIntArray(FT_Common.CFF_MAX_OPERANDS + 1); + for (var i = 0; i < (FT_Common.CFF_MAX_OPERANDS + 1); i++) + this.stack[i] = 0; + this.top = 0; + + for (var i = 0; i < (FT_Common.CFF_MAX_SUBRS_CALLS + 1); i++) + { + var p = this.zones[i]; + p.base = null; + p.cursor = 0; + p.limit = 0; + } + + this.zone = 0; + + this.flex_state = 0; + this.num_flex_vectors = 0; + + for (var i = 0; i < 7; i++) + { + this.flex_vectors[i].x = 0; + this.flex_vectors[i].y = 0; + } + + this.glyph_width = 0; + this.nominal_width = 0; + + this.read_width = 0; + this.width_only = 0; + this.num_hints = 0; + + for (var i = 0; i < FT_Common.CFF_MAX_TRANS_ELEMENTS; i++) + this.buildchar[i] = 0; + + this.num_locals = 0; + this.num_globals = 0; + + this.locals_bias = 0; + this.globals_bias = 0; + + this.locals = null; + this.globals = null; + + this.glyph_names = null; /* for pure CFF fonts only */ + this.num_glyphs = 0; /* number of glyphs in font */ + + this.hint_mode = 0; + + this.seac = 0; + } +} + +function cff_builder_init(builder, face, size, glyph, hinting) +{ + builder.path_begun = 0; + builder.path_begun = 0; + builder.load_points = 1; + + builder.face = face; + builder.glyph = glyph; + builder.memory = face.memory; + + if (glyph != null) + { + var loader = glyph.internal.loader; + + builder.loader = loader; + builder.base = loader.base.outline; + builder.current = loader.current.outline; + FT_GlyphLoader_Rewind(loader); + + builder.hints_globals = null; + builder.hints_funcs = null; + + if (hinting && size != null) + { + var internal = size.internal; + + builder.hints_globals = internal.topfont; + builder.hints_funcs = glyph.internal.glyph_hints; + } + } + + builder.pos_x = 0; + builder.pos_y = 0; + + builder.left_bearing.x = 0; + builder.left_bearing.y = 0; + builder.advance.x = 0; + builder.advance.y = 0; +} + +function cff_builder_done(builder) +{ + var glyph = builder.glyph; + if (glyph != null) + EquatingOutline(glyph.outline, builder.base); +} + +function cff_compute_bias(in_charstring_type, num_subrs) +{ + if (in_charstring_type == 1) + return 0; + else if (num_subrs < 1240) + return 107; + else if (num_subrs < 33900) + return 1131; + + return 32768; +} + +function cff_decoder_init(decoder, face, size, slot, hinting, hint_mode) +{ + var cff = face.extra.data; + /* clear everything */ + decoder.clear(); + + /* initialize builder */ + cff_builder_init(decoder.builder, face, size, slot, hinting); + + /* initialize Type2 decoder */ + decoder.cff = cff; + decoder.num_globals = cff.global_subrs_index.count; + decoder.globals = cff.global_subrs; + decoder.globals_bias = cff_compute_bias(cff.top_font.font_dict.charstring_type, decoder.num_globals); + + decoder.hint_mode = hint_mode; +} + +function cff_decoder_prepare(decoder, size, glyph_index) +{ + var builder = decoder.builder; + var cff = builder.face.extra.data; + var sub = cff.top_font; + + /* manage CID fonts */ + if (cff.num_subfonts != 0) + { + var fd_index = cff_fd_select_get(cff.fd_select, glyph_index); + + if (fd_index >= cff.num_subfonts) + return FT_Common.FT_Err_Invalid_File_Format; + + sub = cff.subfonts[fd_index]; + + if (builder.hints_funcs != null && size != null) + { + var internal = size.internal; + + /* for CFFs without subfonts, this value has already been set */ + builder.hints_globals = internal.subfonts[fd_index]; + } + } + + decoder.num_locals = sub.local_subrs_index.count; + decoder.locals = sub.local_subrs; + decoder.locals_bias = cff_compute_bias(decoder.cff.top_font.font_dict.charstring_type, decoder.num_locals); + + decoder.glyph_width = sub.private_dict.default_width; + decoder.nominal_width = sub.private_dict.nominal_width; + + return 0; +} + +function _cff_check_points(builder, count) +{ + return FT_GLYPHLOADER_CHECK_POINTS(builder.loader, count, 0); +} + +function cff_builder_add_point(builder, x, y, flag) +{ + var base = builder.base; + var outline = builder.current; + + if (builder.load_points = 1) + { + var point = base.points[outline.points + outline.n_points]; + var control = base.tags[outline.tags + outline.n_points]; + + point.x = x >> 16; + point.y = y >> 16; + base.tags[outline.tags + outline.n_points] = ((flag != 0) ? FT_Common.FT_CURVE_TAG_ON : FT_Common.FT_CURVE_TAG_CUBIC); + } + + outline.n_points++; +} + +function cff_builder_add_point1(builder, x, y) +{ + var error = _cff_check_points(builder, 1); + if (error == 0) + cff_builder_add_point(builder, x, y, 1); + + return error; +} + +function cff_builder_add_contour(builder) +{ + if (builder.load_points == 0) + { + builder.current.n_contours++; + return 0; + } + + var base = builder.base; + var outline = builder.current; + var error = FT_GLYPHLOADER_CHECK_POINTS(builder.loader, 0, 1); + if (error == 0) + { + if (outline.n_contours > 0) + base.contours[outline.contours + outline.n_contours - 1] = (outline.n_points - 1); + + outline.n_contours++; + } + + return error; +} + +function cff_builder_start_point(builder, x, y) +{ + var error = 0; + if (builder.path_begun == 0) + { + builder.path_begun = 1; + error = cff_builder_add_contour(builder); + if (error == 0) + error = cff_builder_add_point1(builder, x, y); + } + return error; +} + +function cff_builder_close_contour(builder) +{ + var base = builder.base; + var outline = builder.current; + + if (outline == null) + return; + + var first = (outline.n_contours <= 1) ? 0 : base.contours[outline.contours + outline.n_contours - 2] + 1; + + /* We must not include the last point in the path if it */ + /* is located on the first point. */ + if (outline.n_points > 1) + { + var p1 = base.points[outline.points + first]; + var p2 = base.points[outline.points + outline.n_points - 1]; + var control = base.tags[outline.tags + outline.n_points - 1]; + + /* `delete' last point only if it coincides with the first */ + /* point and if it is not a control point (which can happen). */ + if (p1.x == p2.x && p1.y == p2.y) + if (control == FT_Common.FT_CURVE_TAG_ON) + outline.n_points--; + } + + if (outline.n_contours > 0) + { + /* Don't add contours only consisting of one point, i.e., */ + /* check whether begin point and last point are the same. */ + if (first == outline.n_points - 1) + { + outline.n_contours--; + outline.n_points--; + } + else + base.contours[outline.contours + outline.n_contours - 1] = (outline.n_points - 1); + } +} + +function cff_lookup_glyph_by_stdcharcode(cff, charcode) +{ + /* CID-keyed fonts don't have glyph names */ + if (null == cff.charset.sids) + return -1; + + /* check range of standard char code */ + if (charcode < 0 || charcode > 255) + return -1; + + /* Get code to SID mapping from `cff_standard_encoding'. */ + var glyph_sid = cff_get_standard_encoding(charcode); + + for (var n = 0; n < cff.num_glyphs; n++) + { + if (cff.charset.sids[n] == glyph_sid) + return n; + } + + return -1; +} + +function cff_get_glyph_data(face, glyph_index) +{ + var cff = face.extra.data; + return cff_index_access_element(cff.charstrings_index, glyph_index); +} + +function cff_free_glyph_data(face, pointer, length) +{ + var cff = face.extra.data; + cff_index_forget_element(cff.charstrings_index, pointer); +} + +function cff_operator_seac(decoder, asb, adx, ady, bchar, achar) +{ + var builder = decoder.builder; + var bchar_index, achar_index; + var face = builder.face; + + if (decoder.seac != 0) + return FT_Common.FT_Err_Syntax_Error; + + adx += decoder.builder.left_bearing.x; + ady += decoder.builder.left_bearing.y; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* Incremental fonts don't necessarily have valid charsets. */ + /* They use the character code, not the glyph index, in this case. */ + if (face.internal.incremental_interface != null) + { + bchar_index = bchar; + achar_index = achar; + } + else //#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + { + var cff = face.extra.data; + bchar_index = cff_lookup_glyph_by_stdcharcode(cff, bchar); + achar_index = cff_lookup_glyph_by_stdcharcode(cff, achar); + } + + if (bchar_index < 0 || achar_index < 0) + return FT_Common.FT_Err_Syntax_Error; + + /* If we are trying to load a composite glyph, do not load the */ + /* accent character and return the array of subglyphs. */ + if (builder.no_recurse != 0) + { + var glyph = builder.glyph; + var loader = glyph.internal.loader; + + /* reallocate subglyph array if necessary */ + error = FT_GlyphLoader_CheckSubGlyphs(loader, 2); + if (error != 0) + return error; + + var subg = loader.base.subglyphs[loader.current.subglyphs]; + + /* subglyph 0 = base character */ + subg.index = bchar_index; + subg.flags = FT_Common.FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | FT_Common.FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg.arg1 = 0; + subg.arg2 = 0; + + subg = loader.base.subglyphs[loader.current.subglyphs + 1]; + + /* subglyph 1 = accent character */ + subg.index = achar_index; + subg.flags = FT_Common.FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg.arg1 = (adx >> 16); + subg.arg2 = (ady >> 16); + + /* set up remaining glyph fields */ + glyph.num_subglyphs = 2; + glyph.subglyphs = loader.base.subglyphs; + glyph.format = FT_Common.FT_GLYPH_FORMAT_COMPOSITE; + + loader.current.num_subglyphs = 2; + } + + FT_GlyphLoader_Prepare(builder.loader); + + /* First load `bchar' in builder */ + var ret = cff_get_glyph_data(face, bchar_index); + var error = ret.err; + var charstring = ret.bytes; + var charstring_len = ret.len; + if (error == 0) + { + /* the seac operator must not be nested */ + decoder.seac = 1; + error = cff_decoder_parse_charstrings(decoder, charstring, charstring_len); + decoder.seac = 0; + + cff_free_glyph_data(face, charstring, charstring_len); + + if (error != 0) + return error; + } + + /* Save the left bearing, advance and glyph width of the base */ + /* character as they will be erased by the next load. */ + + var left_bearing = dublicate_vector(builder.left_bearing); + var advance = dublicate_vector(builder.advance); + var glyph_width = decoder.glyph_width; + + builder.left_bearing.x = 0; + builder.left_bearing.y = 0; + + builder.pos_x = adx - asb; + builder.pos_y = ady; + + /* Now load `achar' on top of the base outline. */ + ret = cff_get_glyph_data(face, achar_index); + error = ret.err; + charstring = ret.bytes; + charstring_len = ret.len; + if (error == 0) + { + /* the seac operator must not be nested */ + decoder.seac = 1; + error = cff_decoder_parse_charstrings(decoder, charstring, charstring_len); + decoder.seac = 0; + + cff_free_glyph_data(face, charstring, charstring_len); + + if (error != 0) + return error; + } + + /* Restore the left side bearing, advance and glyph width */ + /* of the base character. */ + builder.left_bearing.x = left_bearing.x; + builder.left_bearing.y = left_bearing.y; + builder.advance.x = advance.x; + builder.advance.y = advance.y; + + decoder.glyph_width = glyph_width; + + builder.pos_x = 0; + builder.pos_y = 0; + + return error; +} + +function cff_decoder_parse_charstrings(decoder, charstring_base, charstring_len) +{ + var builder = decoder.builder; + var charstring_type = decoder.cff.top_font.font_dict.charstring_type; + + /* set default width */ + decoder.num_hints = 0; + decoder.read_width = 1; + + /* compute random seed from stack address of parameter */ + var seed = parseInt(Math.random() * 0xFFFF); + if (seed == 0) + seed = 0x7384; + + /* initialize the decoder */ + decoder.top = 0; + decoder.zone = 0; + + var zones = decoder.zones; + var zone = 0; + + var tops = decoder.stack; + var stack = decoder.top; + + var hinter = builder.hints_funcs; + + builder.path_begun = 0; + + zones[zone].base = dublicate_pointer(charstring_base); + var limit = zones[zone].limit = charstring_base.pos + charstring_len; + zones[zone].cursor = 0; + var ip = dublicate_pointer(charstring_base); + + var error = 0; + + var x = builder.pos_x; + var y = builder.pos_y; + + /* begin hints recording session, if any */ + if (hinter != null) + hinter.open(hinter.hints); + + /* now execute loop */ + while (ip.pos < limit) + { + var op = 0; + /********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + var v = ip.data[ip.pos]; + ip.pos++; + if (v >= 32 || v == 28) + { + var shift = 16; + var val = 0; + + /* this is an operand, push it on the stack */ + if (v == 28) + { + if (ip.pos + 1 >= limit) + return FT_Common.FT_Err_Invalid_File_Format; + val = ((ip.data[ip.pos] << 8) | ip.data[ip.pos + 1]); + if (val > FT_Common.m_s) + val = val - FT_Common.a_s; + ip.pos += 2; + } + else if (v < 247) + val = v - 139; + else if (v < 251) + { + if (ip.pos >= limit) + return FT_Common.FT_Err_Invalid_File_Format; + val = (v - 247) * 256 + ip.data[ip.pos] + 108; + ip.pos++; + } + else if (v < 255) + { + if (ip.pos >= limit) + return FT_Common.FT_Err_Invalid_File_Format; + val = -(v - 251) * 256 - ip.data[ip.pos] - 108; + ip.pos++; + } + else + { + if (ip.pos + 3 >= limit) + return FT_Common.FT_Err_Invalid_File_Format; + val = (ip.data[ip.pos] << 24 )| (ip.data[ip.pos + 1] << 16) | (ip.data[ip.po + 2] << 8) | ip.data[ip.pos + 3]; + ip.pos += 4; + if (charstring_type == 2) + shift = 0; + } + if (decoder.top >= FT_Common.CFF_MAX_OPERANDS) + return FT_Common.FT_Err_Stack_Overflow; + + val <<= shift; + tops[decoder.top] = val; + decoder.top++; + } + else + { + /* The specification says that normally arguments are to be taken */ + /* from the bottom of the stack. However, this seems not to be */ + /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */ + /* arguments similar to a PS interpreter. */ + var args = decoder.top; + var num_args = args; + + /* find operator */ + op = FT_Common.cff_op_unknown; + + switch (v) + { + case 1: + op = FT_Common.cff_op_hstem; + break; + case 3: + op = FT_Common.cff_op_vstem; + break; + case 4: + op = FT_Common.cff_op_vmoveto; + break; + case 5: + op = FT_Common.cff_op_rlineto; + break; + case 6: + op = FT_Common.cff_op_hlineto; + break; + case 7: + op = FT_Common.cff_op_vlineto; + break; + case 8: + op = FT_Common.cff_op_rrcurveto; + break; + case 9: + op = FT_Common.cff_op_closepath; + break; + case 10: + op = FT_Common.cff_op_callsubr; + break; + case 11: + op = FT_Common.cff_op_return; + break; + case 12: + { + if (ip.pos >= limit) + return FT_Common.FT_Err_Invalid_File_Format; + v = ip.data[ip.pos]; + ip.pos++; + switch (v) + { + case 0: + op = FT_Common.cff_op_dotsection; + break; + case 1: /* this is actually the Type1 vstem3 operator */ + op = FT_Common.cff_op_vstem; + break; + case 2: /* this is actually the Type1 hstem3 operator */ + op = FT_Common.cff_op_hstem; + break; + case 3: + op = FT_Common.cff_op_and; + break; + case 4: + op = FT_Common.cff_op_or; + break; + case 5: + op = FT_Common.cff_op_not; + break; + case 6: + op = FT_Common.cff_op_seac; + break; + case 7: + op = FT_Common.cff_op_sbw; + break; + case 8: + op = FT_Common.cff_op_store; + break; + case 9: + op = FT_Common.cff_op_abs; + break; + case 10: + op = FT_Common.cff_op_add; + break; + case 11: + op = FT_Common.cff_op_sub; + break; + case 12: + op = FT_Common.cff_op_div; + break; + case 13: + op = FT_Common.cff_op_load; + break; + case 14: + op = FT_Common.cff_op_neg; + break; + case 15: + op = FT_Common.cff_op_eq; + break; + case 16: + op = FT_Common.cff_op_callothersubr; + break; + case 17: + op = FT_Common.cff_op_pop; + break; + case 18: + op = FT_Common.cff_op_drop; + break; + case 20: + op = FT_Common.cff_op_put; + break; + case 21: + op = FT_Common.cff_op_get; + break; + case 22: + op = FT_Common.cff_op_ifelse; + break; + case 23: + op = FT_Common.cff_op_random; + break; + case 24: + op = FT_Common.cff_op_mul; + break; + case 26: + op = FT_Common.cff_op_sqrt; + break; + case 27: + op = FT_Common.cff_op_dup; + break; + case 28: + op = FT_Common.cff_op_exch; + break; + case 29: + op = FT_Common.cff_op_index; + break; + case 30: + op = FT_Common.cff_op_roll; + break; + case 33: + op = FT_Common.cff_op_setcurrentpoint; + break; + case 34: + op = FT_Common.cff_op_hflex; + break; + case 35: + op = FT_Common.cff_op_flex; + break; + case 36: + op = FT_Common.cff_op_hflex1; + break; + case 37: + op = FT_Common.cff_op_flex1; + break; + default: + break; + } + break; + } + case 13: + op = FT_Common.cff_op_hsbw; + break; + case 14: + op = FT_Common.cff_op_endchar; + break; + case 16: + op = FT_Common.cff_op_blend; + break; + case 18: + op = FT_Common.cff_op_hstemhm; + break; + case 19: + op = FT_Common.cff_op_hintmask; + break; + case 20: + op = FT_Common.cff_op_cntrmask; + break; + case 21: + op = FT_Common.cff_op_rmoveto; + break; + case 22: + op = FT_Common.cff_op_hmoveto; + break; + case 23: + op = FT_Common.cff_op_vstemhm; + break; + case 24: + op = FT_Common.cff_op_rcurveline; + break; + case 25: + op = FT_Common.cff_op_rlinecurve; + break; + case 26: + op = FT_Common.cff_op_vvcurveto; + break; + case 27: + op = FT_Common.cff_op_hhcurveto; + break; + case 29: + op = FT_Common.cff_op_callgsubr; + break; + case 30: + op = FT_Common.cff_op_vhcurveto; + break; + case 31: + op = FT_Common.cff_op_hvcurveto; + break; + default: + break; + } + + if (op == FT_Common.cff_op_unknown) + continue; + + /* check arguments */ + var req_args = cff_argument_counts[op]; + if ((req_args & FT_Common.CFF_COUNT_CHECK_WIDTH) != 0) + { + if (num_args > 0 && decoder.read_width != 0) + { + /* If `nominal_width' is non-zero, the number is really a */ + /* difference against `nominal_width'. Else, the number here */ + /* is truly a width, not a difference against `nominal_width'. */ + /* If the font does not set `nominal_width', then */ + /* `nominal_width' defaults to zero, and so we can set */ + /* `glyph_width' to `nominal_width' plus number on the stack */ + /* -- for either case. */ + var set_width_ok = 0; + switch (op) + { + case FT_Common.cff_op_hmoveto: + case FT_Common.cff_op_vmoveto: + set_width_ok = num_args & 2; + break; + + case FT_Common.cff_op_hstem: + case FT_Common.cff_op_vstem: + case FT_Common.cff_op_hstemhm: + case FT_Common.cff_op_vstemhm: + case FT_Common.cff_op_rmoveto: + case FT_Common.cff_op_hintmask: + case FT_Common.cff_op_cntrmask: + set_width_ok = num_args & 1; + break; + + case FT_Common.cff_op_endchar: + /* If there is a width specified for endchar, we either have */ + /* 1 argument or 5 arguments. We like to argue. */ + set_width_ok = ((num_args == 5) || (num_args == 1)) ? 1 : 0; + break; + + default: + FT_Common.set_width_ok = 0; + break; + } + + if (set_width_ok != 0) + { + decoder.glyph_width = decoder.nominal_width + (tops[stack] >> 16); + + if (decoder.width_only != 0) + { + /* we only want the advance width; stop here */ + break; + } + + /* Consumed an argument. */ + num_args--; + } + } + + decoder.read_width = 0; + req_args = 0; + } + + req_args &= 0x000F; + if (num_args < req_args) + return FT_Common.FT_Err_Too_Few_Arguments; + args -= req_args; + num_args -= req_args; + + /* At this point, `args' points to the first argument of the */ + /* operand in case `req_args' isn't zero. Otherwise, we have */ + /* to adjust `args' manually. */ + + /* Note that we only pop arguments from the stack which we */ + /* really need and can digest so that we can continue in case */ + /* of superfluous stack elements. */ + + switch (op) + { + case FT_Common.cff_op_hstem: + case FT_Common.cff_op_vstem: + case FT_Common.cff_op_hstemhm: + case FT_Common.cff_op_vstemhm: + /* the number of arguments is always even here */ + if (hinter != null) + hinter.stems(hinter.hints, (op == FT_Common.cff_op_hstem || op == FT_Common.cff_op_hstemhm) ? 1 : 0, num_args / 2, tops[args - (num_args & ~1)]); + + decoder.num_hints += num_args / 2; + args = stack; + break; + + case FT_Common.cff_op_hintmask: + case FT_Common.cff_op_cntrmask: + /* implement vstem when needed -- */ + /* the specification doesn't say it, but this also works */ + /* with the 'cntrmask' operator */ + /* */ + if (num_args > 0) + { + if (hinter != null) + hinter.stems(hinter.hints, 0, num_args / 2, tops[args - (num_args & ~1)]); + + decoder.num_hints += num_args / 2; + } + + /* In a valid charstring there must be at least one byte */ + /* after `hintmask' or `cntrmask' (e.g., for a `return' */ + /* instruction). Additionally, there must be space for */ + /* `num_hints' bits. */ + if ((ip.pos + ((decoder.num_hints + 7) >> 3)) >= limit) + return FT_Common.FT_Err_Invalid_File_Format; + + if (hinter != null) + { + if (op == FT_Common.cff_op_hintmask) + hinter.hintmask(hinter.hints, builder.current.n_points, decoder.num_hints, ip); + else + hinter.counter(hinter.hints, decoder.num_hints, ip); + } + + ip.pos += (decoder.num_hints + 7 ) >> 3; + args = stack; + break; + + case FT_Common.cff_op_rmoveto: + cff_builder_close_contour(builder); + builder.path_begun = 0; + x += tops[args - 2]; + y += tops[args - 1]; + args = stack; + break; + + case FT_Common.cff_op_vmoveto: + cff_builder_close_contour(builder); + builder.path_begun = 0; + y += tops[args - 1]; + args = stack; + break; + + case FT_Common.cff_op_hmoveto: + cff_builder_close_contour(builder); + builder.path_begun = 0; + x += tops[args - 1]; + args = stack; + break; + + case FT_Common.cff_op_rlineto: + if (cff_builder_start_point(builder, x, y) != 0 || _cff_check_points(builder, parseInt(num_args / 2)) != 0) + return error; + + if (num_args < 2) + return FT_Common.FT_Err_Too_Few_Arguments; + + args -= num_args & ~1; + while (args < decoder.top) + { + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, 1); + args += 2; + } + args = stack; + break; + + case FT_Common.cff_op_hlineto: + case FT_Common.cff_op_vlineto: + { + var phase = (op == FT_Common.cff_op_hlineto) ? 1 : 0; + + if (num_args < 0) + return FT_Common.FT_Err_Too_Few_Arguments; + + /* there exist subsetted fonts (found in PDFs) */ + /* which call `hlineto' without arguments */ + if (num_args == 0) + break; + + if (cff_builder_start_point(builder, x, y) != 0 || _cff_check_points(builder, num_args)) + return error; + + args = stack; + while (args < decoder.top) + { + if (phase == 1) + x += tops[args]; + else + y += tops[args]; + + if (cff_builder_add_point1(builder, x, y) != 0) + return error; + + args++; + phase ^= 1; + } + args = stack; + break; + } + + case FT_Common.cff_op_rrcurveto: + { + if (num_args < 6) + return FT_Error.FT_Err_Too_Few_Arguments; + + var nargs = num_args - num_args % 6; + + if (cff_builder_start_point(builder, x, y) != 0 || _cff_check_points(builder, parseInt(nargs / 2))) + return error; + + args -= nargs; + while (args < decoder.top) + { + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 2]; + y += tops[args + 3]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 4]; + y += tops[args + 5]; + cff_builder_add_point(builder, x, y, 1); + args += 6; + } + args = stack; + break; + } + + case FT_Common.cff_op_vvcurveto: + { + if (num_args < 4) + return FT_Common.FT_Err_Too_Few_Arguments; + + /* if num_args isn't of the form 4n or 4n+1, */ + /* we reduce it to 4n+1 */ + var nargs = num_args - num_args % 4; + if ((num_args - nargs) > 0) + nargs += 1; + + if (cff_builder_start_point(builder, x, y) != 0) + return error; + + args -= nargs; + if ((nargs & 1) != 0) + { + x += tops[args]; + args++; + nargs--; + } + + if (_cff_check_points(builder, 3 * parseInt(nargs / 4))) + return error; + + while (args < decoder.top) + { + y += tops[args]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 1]; + y += tops[args + 2]; + cff_builder_add_point(builder, x, y, 0); + y += tops[args + 3]; + cff_builder_add_point(builder, x, y, 1); + args += 4; + } + args = stack; + break; + } + + case FT_Common.cff_op_hhcurveto: + { + if (num_args < 4) + return FT_Common.FT_Err_Too_Few_Arguments; + + /* if num_args isn't of the form 4n or 4n+1, */ + /* we reduce it to 4n+1 */ + var nargs = num_args - num_args % 4; + if ((num_args - nargs) > 0) + nargs += 1; + + if (cff_builder_start_point(builder, x, y) != 0) + return error; + + args -= nargs; + if ((nargs & 1) != 0) + { + y += tops[args]; + args++; + nargs--; + } + + if (_cff_check_points(builder, 3 * parseInt(nargs / 4))) + return error; + + while (args < decoder.top) + { + x += tops[args]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 1]; + y += tops[args + 2]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 3]; + cff_builder_add_point(builder, x, y, 1); + args += 4; + } + args = stack; + break; + } + + case FT_Common.cff_op_vhcurveto: + case FT_Common.cff_op_hvcurveto: + { + if (cff_builder_start_point(builder, x, y) != 0) + return error; + + if (num_args < 4) + return FT_Common.FT_Err_Too_Few_Arguments; + + /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ + /* we reduce it to the largest one which fits */ + var nargs = num_args - num_args % 4; + if ((num_args - nargs) > 0) + nargs += 1; + + args -= nargs; + if (_cff_check_points(builder, parseInt(nargs / 4) * 3)) + return FT_Common.FT_Err_Too_Few_Arguments; + + var phase = (op == FT_Common.cff_op_hvcurveto) ? 1 : 0; + + while (nargs >= 4) + { + nargs -= 4; + if (phase == 1) + { + x += tops[args]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 1]; + y += tops[args + 2]; + cff_builder_add_point(builder, x, y, 0); + y += tops[args + 3]; + if (nargs == 1) + x += tops[args + 4]; + cff_builder_add_point(builder, x, y, 1); + } + else + { + y += tops[args]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 1]; + y += tops[args + 2]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 3]; + if (nargs == 1) + y += tops[args + 4]; + cff_builder_add_point(builder, x, y, 1); + } + args += 4; + phase ^= 1; + } + args = stack; + break; + } + + case FT_Common.cff_op_rlinecurve: + { + if (num_args < 8) + return FT_Common.FT_Err_Too_Few_Arguments; + + var nargs = num_args & ~1; + var num_lines = parseInt((nargs - 6) / 2); + + if (cff_builder_start_point(builder, x, y) || _cff_check_points(builder, num_lines + 3)) + return error; + + args -= nargs; + + /* first, add the line segments */ + while (num_lines > 0) + { + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, 1); + args += 2; + num_lines--; + } + + /* then the curve */ + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 2]; + y += tops[args + 3]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 4]; + y += tops[args + 5]; + cff_builder_add_point(builder, x, y, 1); + args = stack; + break; + } + + case FT_Common.cff_op_rcurveline: + { + if ( num_args < 8 ) + return FT_Common.FT_Err_Too_Few_Arguments; + + var nargs = num_args - 2; + nargs = nargs - nargs % 6 + 2; + var num_curves = parseInt((nargs - 2) / 6); + + if (cff_builder_start_point(builder, x, y) != 0 || _cff_check_points(builder, num_curves * 3 + 2)) + return error; + + args -= nargs; + + /* first, add the curves */ + while (num_curves > 0) + { + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 2]; + y += tops[args + 3]; + cff_builder_add_point(builder, x, y, 0); + x += tops[args + 4]; + y += tops[args + 5]; + cff_builder_add_point(builder, x, y, 1); + args += 6; + num_curves--; + } + + /* then the final line */ + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, 1); + args = stack; + + break; + } + + case FT_Common.cff_op_hflex1: + { + /* adding five more points: 4 control points, 1 on-curve point */ + /* -- make sure we have enough space for the start point if it */ + /* needs to be added */ + if (cff_builder_start_point(builder, x, y) != 0 || _cff_check_points(builder, 6)) + return error; + + /* record the starting point's y position for later use */ + var start_y = y; + + /* first control point */ + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, 0); + + /* second control point */ + x += tops[args + 2]; + y += tops[args + 3]; + cff_builder_add_point(builder, x, y, 0); + + /* join point; on curve, with y-value the same as the last */ + /* control point's y-value */ + x += tops[args + 4]; + cff_builder_add_point(builder, x, y, 1); + + /* third control point, with y-value the same as the join */ + /* point's y-value */ + x += tops[args + 5]; + cff_builder_add_point(builder, x, y, 0); + + /* fourth control point */ + x += tops[args + 6]; + y += tops[args + 7]; + cff_builder_add_point(builder, x, y, 0); + + /* ending point, with y-value the same as the start */ + x += tops[args + 8]; + y = start_y; + cff_builder_add_point(builder, x, y, 1); + + args = stack; + break; + } + + case FT_Common.cff_op_hflex: + { + /* adding six more points; 4 control points, 2 on-curve points */ + if (cff_builder_start_point(builder, x, y) != 0 || _cff_check_points(builder, 6)) + return error; + + /* record the starting point's y-position for later use */ + var start_y = y; + + /* first control point */ + x += tops[args]; + cff_builder_add_point(builder, x, y, 0); + + /* second control point */ + x += tops[args + 1]; + y += tops[args + 2]; + cff_builder_add_point(builder, x, y, 0); + + /* join point; on curve, with y-value the same as the last */ + /* control point's y-value */ + x += tops[args + 3]; + cff_builder_add_point(builder, x, y, 1); + + /* third control point, with y-value the same as the join */ + /* point's y-value */ + x += tops[args + 4]; + cff_builder_add_point(builder, x, y, 0); + + /* fourth control point */ + x += tops[args + 5]; + y = start_y; + cff_builder_add_point(builder, x, y, 0); + + /* ending point, with y-value the same as the start point's */ + /* y-value -- we don't add this point, though */ + x += tops[args + 6]; + cff_builder_add_point(builder, x, y, 1); + + args = stack; + break; + } + + case FT_Common.cff_op_flex1: + { + /* alter use */ + var dx = 0, dy = 0; /* used in horizontal/vertical */ + + /* adding six more points; 4 control points, 2 on-curve points */ + if (cff_builder_start_point(builder, x, y) != 0 || _cff_check_points(builder, 6) != 0) + return error; + + /* record the starting point's x, y position for later use */ + var start_x = x; + var start_y = y; + + /* XXX: figure out whether this is supposed to be a horizontal */ + /* or vertical flex; the Type 2 specification is vague... */ + + var temp = args; + var count = 0; + + /* grab up to the last argument */ + for (count = 5; count > 0; count--) + { + dx += tops[temp]; + dy += tops[temp + 1]; + temp += 2; + } + + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + + /* strange test, but here it is... */ + var horizontal = (dx > dy) ? 1 : 0; + + for (count = 5; count > 0; count--) + { + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, (count == 3) ? 1 : 0); + args += 2; + } + + /* is last operand an x- or y-delta? */ + if (horizontal == 1) + { + x += tops[args]; + y = start_y; + } + else + { + x = start_x; + y += tops[args]; + } + + cff_builder_add_point(builder, x, y, 1); + + args = stack; + break; + } + + case FT_Common.cff_op_flex: + { + if (cff_builder_start_point(builder, x, y) != 0 || _cff_check_points(builder, 6)) + return error; + + for (var count = 6; count > 0; count--) + { + x += tops[args]; + y += tops[args + 1]; + cff_builder_add_point(builder, x, y, (count == 4 || count == 1) ? 1 : 0); + args += 2; + } + + args = stack; + break; + } + + case FT_Common.cff_op_seac: + error = cff_operator_seac(decoder, tops[args], tops[args + 1], tops[args + 2], (tops[args + 3] >> 16), (tops[args + 4] >> 16)); + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add(builder.loader); + return error; + + case FT_Common.cff_op_endchar: + /* We are going to emulate the seac operator. */ + if (num_args >= 4) + { + /* Save glyph width so that the subglyphs don't overwrite it. */ + var glyph_width = decoder.glyph_width; + + error = cff_operator_seac(decoder, 0, tops[args - 4], tops[args - 3], (tops[args - 2] >> 16), (tops[args - 1] >> 16)); + decoder.glyph_width = glyph_width; + } + else + { + cff_builder_close_contour(builder); + + /* close hints recording session */ + if (hinter != null) + { + if (hinter.close(hinter.hints, builder.current.n_points)) + return FT_Common.FT_Err_Invalid_File_Format; + + /* apply hints to the loaded glyph outline now */ + hinter.apply(hinter.hints, builder.current, builder.hints_globals, decoder.hint_mode); + } + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add(builder.loader); + } + + /* return now! */ + return error; + + case FT_Common.cff_op_abs: + if (tops[args] < 0) + tops[args] = -tops[args]; + args++; + break; + + case FT_Common.cff_op_add: + tops[args] += tops[args + 1]; + args++; + break; + + case FT_Common.cff_op_sub: + tops[args] -= tops[args + 1]; + args++; + break; + + case FT_Common.cff_op_div: + tops[args] = FT_DivFix(tops[args], tops[args + 1]); + args++; + break; + + case FT_Common.cff_op_neg: + tops[args] = -tops[args]; + args++; + break; + + case FT_Common.cff_op_random: + { + var Rand = seed; + if (Rand >= 0x8000) + Rand++; + + tops[args] = Rand; + seed = FT_MulFix(seed, 0x10000 - seed); + if (seed == 0) + seed += 0x2873; + args++; + + break; + } + + case FT_Common.cff_op_mul: + topsargs[0] = FT_MulFix( args[0], args[1] ); + args++; + break; + + case FT_Common.cff_op_sqrt: + if (tops[args] > 0) + { + var count = 9; + var root = tops[args]; + var new_root = 0; + for (;;) + { + new_root = (root + FT_DivFix(tops[args], root) + 1) >> 1; + if (new_root == root || count <= 0) + break; + root = new_root; + } + tops[args] = new_root; + } + else + tops[args] = 0; + args++; + break; + + case FT_Common.cff_op_drop: + /* nothing */ + break; + + case FT_Common.cff_op_exch: + { + var tmp = tops[args]; + tops[args] = tops[args + 1]; + tops[args + 1] = tmp; + args += 2; + + break; + } + + case FT_Common.cff_op_index: + { + var idx = (tops[args] >> 16); + + if (idx < 0) + idx = 0; + else if (idx > num_args - 2) + idx = num_args - 2; + tops[args] = tops[args-(idx + 1)]; + args++; + + break; + } + + case FT_Common.cff_op_roll: + { + var count = (tops[args] >> 16); + var idx = (tops[args + 1] >> 16); + + if (count <= 0) + count = 1; + + args -= count; + if (args < stack) + return FT_Common.FT_Err_Too_Few_Arguments; + + if (idx >= 0) + { + while (idx > 0) + { + var tmp = tops[args + count - 1]; + for (var i = count - 2; i >= 0; i--) + tops[args + i + 1] = tops[args + i]; + tops[args] = tmp; + idx--; + } + } + else + { + while (idx < 0) + { + var tmp = tops[args]; + for (var i = 0; i < count - 1; i++) + tops[args + i] = tops[args + i + 1]; + tops[args + count - 1] = tmp; + idx++; + } + } + args += count; + + break; + } + + case FT_Common.cff_op_dup: + tops[args + 1] = tops[args]; + args += 2; + break; + + case FT_Common.cff_op_put: + { + var val = tops[args]; + var idx = (tops[args + 1] >> 16); + + if (idx >= 0 && idx < FT_Common.CFF_MAX_TRANS_ELEMENTS) + decoder.buildchar[idx] = val; + + break; + } + + case FT_Common.cff_op_get: + { + var idx = (tops[args] >> 16); + var val = 0; + + if (idx >= 0 && idx < FT_Common.CFF_MAX_TRANS_ELEMENTS) + val = decoder.buildchar[idx]; + + tops[args] = val; + args++; + + break; + } + + case FT_Common.cff_op_store: + return FT_Common.FT_Err_Unimplemented_Feature; + + case FT_Common.cff_op_load: + return FT_Common.FT_Err_Unimplemented_Feature; + + case FT_Common.cff_op_dotsection: + /* this operator is deprecated and ignored by the parser */ + break; + + case FT_Common.cff_op_closepath: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + args = stack; + break; + + case FT_Common.cff_op_hsbw: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + decoder.glyph_width = decoder.nominal_width + (tops[args + 1] >> 16); + + decoder.builder.left_bearing.x = tops[args]; + decoder.builder.left_bearing.y = 0; + + x = decoder.builder.pos_x + tops[args]; + y = decoder.builder.pos_y; + args = stack; + break; + + case FT_Common.cff_op_sbw: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + decoder.glyph_width = decoder.nominal_width + (tops[args + 2] >> 16); + + decoder.builder.left_bearing.x = tops[args]; + decoder.builder.left_bearing.y = tops[args + 1]; + + x = decoder.builder.pos_x + tops[args]; + y = decoder.builder.pos_y + tops[args + 1]; + args = stack; + break; + + case FT_Common.cff_op_setcurrentpoint: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + x = decoder.builder.pos_x + tops[args]; + y = decoder.builder.pos_y + tops[args + 1]; + args = stack; + break; + + case FT_Common.cff_op_callothersubr: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + /* subsequent `pop' operands should add the arguments, */ + /* this is the implementation described for `unknown' other */ + /* subroutines in the Type1 spec. */ + /* */ + /* XXX Fix return arguments (see discussion below). */ + args -= 2 + (tops[args - 2] >> 16); + if (args < stack) + return FT_Common.FT_Err_Too_Few_Arguments; + break; + + case FT_Common.cff_op_pop: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + /* XXX Increasing `args' is wrong: After a certain number of */ + /* `pop's we get a stack overflow. Reason for doing it is */ + /* code like this (actually found in a CFF font): */ + /* */ + /* 17 1 3 callothersubr */ + /* pop */ + /* callsubr */ + /* */ + /* Since we handle `callothersubr' as a no-op, and */ + /* `callsubr' needs at least one argument, `pop' can't be a */ + /* no-op too as it basically should be. */ + /* */ + /* The right solution would be to provide real support for */ + /* `callothersubr' as done in `t1decode.c', however, given */ + /* the fact that CFF fonts with `pop' are invalid, it is */ + /* questionable whether it is worth the time. */ + args++; + break; + + case FT_Common.cff_op_and: + { + var cond = (tops[args] != 0 && tops[args + 1] != 0) ? 1 : 0; + + tops[args] = (cond == 1) ? 0x10000 : 0; + args++; + + break; + } + case FT_Common.cff_op_or: + { + var cond = (tops[args] != 0 || tops[args + 1]) ? 1 : 0; + + tops[args] = (cond == 1) ? 0x10000 : 0; + args++; + + break; + } + + case FT_Common.cff_op_eq: + { + tops[args] = (tops[args] == 0) ? 0x10000 : 0; + args++; + + break; + } + + case FT_Common.cff_op_ifelse: + { + if (tops[args + 2] > tops[args + 3]) + tops[args] = tops[args + 1]; + args++; + + break; + } + + case FT_Common.cff_op_callsubr: + { + var idx = ((tops[args] >> 16) + decoder.locals_bias); + + if (idx >= decoder.num_locals) + return FT_Common.FT_Err_Invalid_File_Format; + + if (zone >= FT_Common.CFF_MAX_SUBRS_CALLS) + return FT_Common.FT_Err_Invalid_File_Format; + + zones[zone].cursor = ip.pos - zones[zone].base.pos; /* save current instruction pointer */ + + zone++; + zones[zone].base = dublicate_pointer(decoder.locals[idx]); + zones[zone].limit = (decoder.locals[idx + 1] != null) ? decoder.locals[idx + 1].pos : zones[zone].base.pos; + zones[zone].cursor = 0; + + if (zones[zone].base == null || zones[zone].limit == zones[zone].base.pos) + return FT_Common.FT_Err_Invalid_File_Format; + + decoder.zone = zone; + ip = dublicate_pointer(zones[zone].base); + limit = zones[zone].limit; + + break; + } + + case FT_Common.cff_op_callgsubr: + { + var idx = ((tops[args] >> 16) + decoder.globals_bias); + + if (idx >= decoder.num_globals) + return FT_Common.FT_Err_Invalid_File_Format; + + if (zone >= FT_Common.CFF_MAX_SUBRS_CALLS) + return FT_Common.FT_Err_Invalid_File_Format; + + zones[zone].cursor = ip.pos - zones[zone].base.pos; /* save current instruction pointer */ + + zone++; + zones[zone].base = dublicate_pointer(decoder.globals[idx]); + zones[zone].limit = (decoder.globals[idx + 1] != null) ? decoder.globals[idx + 1].pos : zones[zone].base.pos; + zones[zone].cursor = 0; + + if (zones[zone].base == null || zones[zone].limit == zones[zone].base.pos) + return FT_Common.FT_Err_Invalid_File_Format; + + decoder.zone = zone; + ip = dublicate_pointer(zones[zone].base); + limit = zones[zone].limit; + + break; + } + + case FT_Common.cff_op_return: + if (decoder.zone <= 0) + return FT_Common.FT_Err_Invalid_File_Format; + + decoder.zone--; + zone = decoder.zone; + ip = dublicate_pointer(zones[zone].base); + ip.pos += zones[zone].cursor; + limit = zones[zone].limit; + break; + + default: + return FT_Common.FT_Err_Unimplemented_Feature; + } + + decoder.top = args; + + if (decoder.top >= FT_Common.CFF_MAX_OPERANDS) + return FT_Common.FT_Err_Stack_Overflow; + + } /* general operator processing */ + + } /* while ip < limit */ + + return error; +} + +function cff_slot_load(glyph, size, glyph_index, load_flags) +{ + var face = glyph.face; + var cff = face.extra.data; + + var font_matrix = null; + var font_offset = null; + + var hinting = 0; + var force_scaling = 0; + + /* in a CID-keyed font, consider `glyph_index' as a CID and map */ + /* it immediately to the real glyph_index -- if it isn't a */ + /* subsetted font, glyph_indices and CIDs are identical, though */ + if (cff.top_font.font_dict.cid_registry != 0xFFFF && cff.charset.cids != null) + { + /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */ + if (glyph_index != 0) + { + glyph_index = cff_charset_cid_to_gindex(cff.charset, glyph_index); + if (glyph_index == 0) + return FT_Common.FT_Err_Invalid_Argument; + } + } + else if (glyph_index >= cff.num_glyphs) + return FT_Common.FT_Err_Invalid_Argument; + + if ((load_flags & FT_Common.FT_LOAD_NO_RECURSE) != 0) + load_flags |= (FT_Common.FT_LOAD_NO_SCALE | FT_Common.FT_LOAD_NO_HINTING); + + glyph.x_scale = 0x10000; + glyph.y_scale = 0x10000; + if (size != 0) + { + glyph.x_scale = size.metrics.x_scale; + glyph.y_scale = size.metrics.y_scale; + } + + var error = 0; + + //#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* try to load embedded bitmap if any */ + /* */ + /* XXX: The convention should be emphasized in */ + /* the documents because it can be confusing. */ + if (size != null) + { + var cff_face = size.face; + var sfnt = cff_face.sfnt; + var stream = cff_face.stream; + + if (size.strike_index != 0xFFFFFFFF && sfnt.load_eblc != null && (load_flags & FT_Common.FT_LOAD_NO_BITMAP) == 0) + { + var metrics = new TT_SBit_MetricsRec(); + + error = sfnt.load_sbit_image(face, size.strike_index, glyph_index, load_flags, stream, glyph.bitmap, metrics); + + if (error == 0) + { + glyph.outline.n_points = 0; + glyph.outline.n_contours = 0; + + glyph.metrics.width = metrics.width << 6; + glyph.metrics.height = metrics.height << 6; + + glyph.metrics.horiBearingX = metrics.horiBearingX << 6; + glyph.metrics.horiBearingY = metrics.horiBearingY << 6; + glyph.metrics.horiAdvance = metrics.horiAdvance << 6; + + glyph.metrics.vertBearingX = metrics.vertBearingX << 6; + glyph.metrics.vertBearingY = metrics.vertBearingY << 6; + glyph.metrics.vertAdvance = metrics.vertAdvance << 6; + + glyph.format = FT_Common.FT_GLYPH_FORMAT_BITMAP; + + if (load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) + { + glyph.bitmap_left = metrics.vertBearingX; + glyph.bitmap_top = metrics.vertBearingY; + } + else + { + glyph.bitmap_left = metrics.horiBearingX; + glyph.bitmap_top = metrics.horiBearingY; + } + return error; + } + } + } + + //#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* return immediately if we only want the embedded bitmaps */ + if ((load_flags & FT_Common.FT_LOAD_SBITS_ONLY) != 0) + return FT_Common.FT_Err_Invalid_Argument; + + /* if we have a CID subfont, use its matrix (which has already */ + /* been multiplied with the root matrix) */ + + /* this scaling is only relevant if the PS hinter isn't active */ + if (cff.num_subfonts > 0) + { + var fd_index = cff_fd_select_get(cff.fd_select, glyph_index); + + if (fd_index >= cff.num_subfonts) + fd_index = (cff.num_subfonts - 1); + + var top_upm = cff.top_font.font_dict.units_per_em; + var sub_upm = cff.subfonts[fd_index].font_dict.units_per_em; + + font_matrix = dublicate_matrix(cff.subfonts[fd_index].font_dict.font_matrix); + font_offset = dublicate_vector(cff.subfonts[fd_index].font_dict.font_offset); + + if (top_upm != sub_upm) + { + glyph.x_scale = FT_MulDiv(glyph.x_scale, top_upm, sub_upm); + glyph.y_scale = FT_MulDiv(glyph.y_scale, top_upm, sub_upm); + + force_scaling = 1; + } + } + else + { + font_matrix = dublicate_matrix(cff.top_font.font_dict.font_matrix); + font_offset = dublicate_vector(cff.top_font.font_dict.font_offset); + } + + glyph.outline.n_points = 0; + glyph.outline.n_contours = 0; + + hinting = ((load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0 && (load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) ? 1 : 0; + + glyph.format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; /* by default */ + + var decoder = new CFF_Decoder(); + cff_decoder_init(decoder, face, size, glyph, hinting, FT_LOAD_TARGET_MODE(load_flags)); + + if ((load_flags & FT_Common.FT_LOAD_ADVANCE_ONLY) != 0) + decoder.width_only = 1; + + decoder.builder.no_recurse = ((load_flags & FT_Common.FT_LOAD_NO_RECURSE) != 0) ? 1 : 0; + + /* now load the unscaled outline */ + var ret = cff_get_glyph_data(face, glyph_index); + error = ret.err; + var charstring = ret.bytes; + var charstring_len = ret.len; + + if (error == 0) + { + error = cff_decoder_prepare(decoder, size, glyph_index); + if (error == 0) + { + error = cff_decoder_parse_charstrings(decoder, charstring, charstring_len); + cff_free_glyph_data(face, charstring, charstring_len); + charstring = null; + + if (error == 0) + { + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* Control data and length may not be available for incremental */ + /* fonts. */ + if (face.internal.incremental_interface != null) + { + glyph.control_data = null; + glyph.control_len = 0; + } + else //#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + { + var csindex = cff.charstrings_index; + + if (csindex.offsets != null) + { + glyph.control_data = dublicate_pointer(csindex.bytes); + glyph.control_data.pos += csindex.offsets[glyph_index] - 1; + glyph.control_len = charstring_len; + } + + } + cff_builder_done(decoder.builder); + } + } + } + /* XXX: anything to do for broken glyph entry? */ + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* Incremental fonts can optionally override the metrics. */ + if (error == 0 && face.internal.incremental_interface != null && face.internal.incremental_interface.funcs.get_glyph_metrics != null) + { + var metrics = new FT_Incremental_MetricsRec(); + + metrics.bearing_x = decoder.builder.left_bearing.x; + metrics.bearing_y = 0; + metrics.advance = decoder.builder.advance.x; + metrics.advance_v = decoder.builder.advance.y; + + error = face.internal.incremental_interface.funcs.get_glyph_metrics(face.internal.incremental_interface.object, glyph_index, 0, metrics); + + decoder.builder.left_bearing.x = metrics.bearing_x; + decoder.builder.advance.x = metrics.advance; + decoder.builder.advance.y = metrics.advance_v; + } + + //#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + if (error == 0) + { + /* Now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax. */ + + /* For composite glyphs, return only left side bearing and */ + /* advance width. */ + if ((load_flags & FT_Common.FT_LOAD_NO_RECURSE) != 0) + { + var internal = glyph.internal; + + glyph.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph.metrics.horiAdvance = decoder.glyph_width; + internal.glyph_matrix = dublicate_matrix(font_matrix); + internal.glyph_delta = dublicate_matrix(font_offset); + internal.glyph_transformed = 1; + } + else + { + var cbox = new FT_BBox(); + var metrics = glyph.metrics; + var advance = new FT_Vector(); + var has_vertical_info = 0; + + /* copy the _unscaled_ advance width */ + metrics.horiAdvance = decoder.glyph_width; + glyph.linearHoriAdvance = decoder.glyph_width; + glyph.internal.glyph_transformed = 0; + + has_vertical_info = (face.vertical_info && face.vertical.number_Of_VMetrics > 0 && face.vertical.long_metrics) ? 1 : 0; + + /* get the vertical metrics from the vtmx table if we have one */ + if (has_vertical_info == 1) + { + var _ret = face.sfnt.get_metrics(face, 1, glyph_index); + metrics.vertBearingY = _ret.bearing; + metrics.vertAdvance = _ret.advance; + } + else + { + /* make up vertical ones */ + if (face.os2.version != 0xFFFF) + metrics.vertAdvance = (face.os2.sTypoAscender - face.os2.sTypoDescender); + else + metrics.vertAdvance = (face.horizontal.Ascender - face.horizontal.Descender); + } + + glyph.linearVertAdvance = metrics.vertAdvance; + + glyph.format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + + glyph.outline.flags = 0; + if (size != null && size.metrics.y_ppem < 24) + glyph.outline.flags |= FT_Common.FT_OUTLINE_HIGH_PRECISION; + + glyph.outline.flags |= FT_Common.FT_OUTLINE_REVERSE_FILL; + + if (!(font_matrix.xx == 0x10000 && font_matrix.yy == 0x10000 && font_matrix.xy == 0 && font_matrix.yx == 0)) + FT_Outline_Transform(glyph.outline, font_matrix); + + if (!(font_offset.x == 0 && font_offset.y == 0)) + FT_Outline_Translate(glyph.outline, font_offset.x, font_offset.y); + + advance.x = metrics.horiAdvance; + advance.y = 0; + FT_Vector_Transform(advance, font_matrix); + metrics.horiAdvance = advance.x + font_offset.x; + + advance.x = 0; + advance.y = metrics.vertAdvance; + FT_Vector_Transform(advance, font_matrix); + metrics.vertAdvance = advance.y + font_offset.y; + + if ((load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0 || force_scaling == 1) + { + /* scale the outline and the metrics */ + var cur = glyph.outline; + var vecs = cur.points; + var _vec = 0; + var x_scale = glyph.x_scale; + var y_scale = glyph.y_scale; + + /* First of all, scale the points */ + if (hinting == 0 || decoder.builder.hints_funcs == null) + for (var n = cur.n_points; n > 0; n--, _vec++) + { + vecs[_vec].x = FT_MulFix(vecs[_vec].x, x_scale); + vecs[_vec].y = FT_MulFix(vecs[_vec].y, y_scale); + } + + /* Then scale the metrics */ + metrics.horiAdvance = FT_MulFix(metrics.horiAdvance, x_scale); + metrics.vertAdvance = FT_MulFix(metrics.vertAdvance, y_scale); + } + + /* compute the other metrics */ + FT_Outline_Get_CBox(glyph.outline, cbox); + + metrics.width = cbox.xMax - cbox.xMin; + metrics.height = cbox.yMax - cbox.yMin; + + metrics.horiBearingX = cbox.xMin; + metrics.horiBearingY = cbox.yMax; + + if (has_vertical_info == 1) + metrics.vertBearingX = metrics.horiBearingX - parseInt(metrics.horiAdvance / 2); + else + { + if ((load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) != 0) + ft_synthesize_vertical_metrics(metrics, metrics.vertAdvance); + } + } + } + + return error; +} + +/******************************************************************************/ +// driver +/******************************************************************************/ +function cff_get_kerning(face, left_glyph, right_glyph, kerning) +{ + var sfnt = face.sfnt; + + kerning.x = 0; + kerning.y = 0; + + if (sfnt != null) + kerning.x = sfnt.get_kerning(face, left_glyph, right_glyph); + + return 0; +} + +function cff_Load_Glyph(slot, cffsize, glyph_index, load_flags) +{ + var size = cffsize; + if (slot == null) + return FT_Common.FT_Err_Invalid_Slot_Handle; + + /* check whether we want a scaled outline or bitmap */ + if (size == null) + load_flags |= FT_Common.FT_LOAD_NO_SCALE | FT_Common.FT_LOAD_NO_HINTING; + + /* reset the size object if necessary */ + if (load_flags & FT_Common.FT_LOAD_NO_SCALE) + size = null; + + if (size != null) + { + /* these two objects must have the same parent */ + if (cffsize.face != slot.face) + return FT_Common.FT_Err_Invalid_Face_Handle; + } + + /* now load the glyph outline if necessary */ + var error = cff_slot_load(slot, size, glyph_index, load_flags); + + /* force drop-out mode to 2 - irrelevant now */ + /* slot->outline.dropout_mode = 2; */ + return error; +} + +function cff_get_advances(face, start, count, flags, advances) +{ + var slot = face.glyph; + var error = 0; + flags |= FT_Common.FT_LOAD_ADVANCE_ONLY; + + for (var nn = 0; nn < count; nn++) + { + error = cff_Load_Glyph(slot, face.size, start + nn, flags); + if (error ) + break; + + advances[nn] = (flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) ? slot.linearVertAdvance : slot.linearHoriAdvance; + } + + return error; +} + +function cff_get_glyph_name(face, glyph_index, buffer, buffer_max) +{ + var font = face.extra.data; + + if (font.psnames == null) + return FT_Common.FT_Err_Unknown_File_Format; + + /* first, locate the sid in the charset table */ + var sid = font.charset.sids[glyph_index]; + + /* now, lookup the name itself */ + var gname = cff_index_get_sid_string(font, sid); + + if (gname != null) + _mem_strcpyn1(buffer, gname, buffer_max); + + return 0; +} + +function cff_get_name_index(face, glyph_name) +{ + var cff = face.extra.data; + var charset = cf.charset; + + var psnames = FT_FACE_FIND_GLOBAL_SERVICE(face, FT_SERVICE_ID_POSTSCRIPT_CMAPS); + if (psnames == null) + return 0; + + var sid = 0; + var name = ""; + for (var i = 0; i < cff.num_glyphs; i++) + { + sid = charset.sids[i]; + + if (sid > 390) + name = cff_index_get_string(cff, sid - 391); + else + name = psnames.adobe_std_strings(sid); + + if (name == null || name == "") + continue; + + if (glyph_name == name) + return i; + } + return 0; +} + +var cff_service_glyph_dict = new FT_Service_GlyphDictRec(cff_get_glyph_name, cff_get_name_index); + +function cff_ps_has_glyph_names(face) +{ + return ((face.face_flags & FT_Common.FT_FACE_FLAG_GLYPH_NAMES) > 0) ? 1 : 0; +} + +function cff_ps_get_font_info(face) +{ + var cff = face.extra.data; + var font_info = null; + if (cff != null && cff.font_info == null) + { + var dict = cff.top_font.font_dict; + font_info = new PS_FontInfoRec(); + + font_info.version = cff_index_get_sid_string(cff, dict.version); + font_info.notice = cff_index_get_sid_string(cff, dict.notice); + font_info.full_name = cff_index_get_sid_string(cff, dict.full_name); + font_info.family_name = cff_index_get_sid_string(cff, dict.family_name); + font_info.weight = cff_index_get_sid_string(cff, dict.weight); + + font_info.italic_angle = dict.italic_angle; + font_info.is_fixed_pitch = dict.is_fixed_pitch; + font_info.underline_position = dict.underline_position; + font_info.underline_thickness = dict.underline_thickness; + + cff.font_info = font_info; + } + return { err : 0, font_info : font_info }; +} + +var cff_service_ps_info = new FT_Service_PsInfoRec(cff_ps_get_font_info, null, cff_ps_has_glyph_names, null, null); + +function cff_get_ps_name(face) +{ + return face.extra.data.font_name; +} + +var cff_service_ps_name = new FT_Service_PsFontNameRec(cff_get_ps_name); + +function cff_get_cmap_info(charmap, cmap_info) +{ + var cmap = charmap.cmap; + var library = __FT_CMapRec(cmap).charmap.face.driver.library; + + cmap_info.language = 0; + cmap_info.format = 0; + + var error = 0; + if (cmap.clazz != FT_CFF_CMAP_ENCODING_CLASS_REC_GET && cmap.clazz != FT_CFF_CMAP_UNICODE_CLASS_REC_GET) + { + var sfnt = library.FT_Get_Module("sfnt"); + var service = ft_module_get_service(sfnt, FT_SERVICE_ID_TT_CMAP); + + if (service != null && service.get_cmap_info != null) + error = service.get_cmap_info(charmap, cmap_info); + } + return error; +} + +var cff_service_get_cmap_info = new FT_Service_TTCMapsRec(cff_get_cmap_info); + +function cff_get_ros(face, registry, ordering, supplement) +{ + var ret = {err : 0, registry : "", ordering : "", supplement : 0}; + var cff = face.extra.data; + + if (cff != null) + { + var dict = cff.top_font.font_dict; + + if (dict.cid_registry == 0xFFFF) + { + ret.err = FT_Common.FT_Err_Invalid_Argument; + return ret; + } + + if (cff.registry == null) + cff.registry = cff_index_get_sid_string(cff, dict.cid_registry); + ret.registry = cff.registry; + + if (cff.ordering == null) + cff.ordering = cff_index_get_sid_string(cff, dict.cid_ordering); + ret.ordering = cff.ordering; + + /* + * XXX: According to Adobe TechNote #5176, the supplement in CFF + * can be a real number. We truncate it to fit public API + * since freetype-2.3.6. + */ + ret.supplement = dict.cid_supplement; + } + + return error; +} + +function cff_get_is_cid(face) +{ + var ret = {err : 0, is_cid : 0}; + var cff = face.extra.data; + + if (cff != null) + { + var dict = cff.top_font.font_dict; + + if (dict.cid_registry != 0xFFFF) + ret.is_cid = 1; + } + + return ret; +} + +function cff_get_cid_from_glyph_index(face, glyph_index) +{ + var ret = { err : 0, cid : 0}; + var cff = face.extra.data; + + if (cff != null) + { + var dict = cff.top_font.font_dict; + + if (dict.cid_registry == 0xFFFF || glyph_index > cff.num_glyphs) + { + ret.err = FT_Common.FT_Err_Invalid_Argument; + return ret; + } + + ret.cid = cff.charset.sids[glyph_index]; + } + return ret; +} + +var cff_service_cid_info = new FT_Service_CIDRec(cff_get_ros, cff_get_is_cid, cff_get_cid_from_glyph_index); + +var FT_CFF_SERVICE_PS_INFO_GET = cff_service_ps_info; +var FT_CFF_SERVICE_GLYPH_DICT_GET = cff_service_glyph_dict; +var FT_CFF_SERVICE_PS_NAME_GET = cff_service_ps_name; +var FT_CFF_SERVICE_GET_CMAP_INFO_GET = cff_service_get_cmap_info; +var FT_CFF_SERVICE_CID_INFO_GET = cff_service_cid_info; +var FT_CFF_CMAP_ENCODING_CLASS_REC_GET = cff_cmap_encoding_class_rec; +var FT_CFF_CMAP_UNICODE_CLASS_REC_GET = cff_cmap_unicode_class_rec; +var FT_CFF_FIELD_HANDLERS_GET = cff_field_handlers; + +var cff_services = new Array(6); +cff_services[0] = new FT_ServiceDescRec(FT_SERVICE_ID_XF86_NAME,FT_XF86_FORMAT_CFF); +cff_services[1] = new FT_ServiceDescRec(FT_SERVICE_ID_POSTSCRIPT_INFO,FT_CFF_SERVICE_PS_INFO_GET); +cff_services[2] = new FT_ServiceDescRec(FT_SERVICE_ID_POSTSCRIPT_FONT_NAME,FT_CFF_SERVICE_PS_NAME_GET); +cff_services[3] = new FT_ServiceDescRec(FT_SERVICE_ID_GLYPH_DICT,FT_CFF_SERVICE_GLYPH_DICT_GET); +cff_services[4] = new FT_ServiceDescRec(FT_SERVICE_ID_TT_CMAP,FT_CFF_SERVICE_GET_CMAP_INFO_GET); +cff_services[5] = new FT_ServiceDescRec(FT_SERVICE_ID_CID,FT_CFF_SERVICE_CID_INFO_GET); + +var FT_CFF_SERVICES_GET = cff_services; + +function cff_get_interface(driver, module_interface) +{ + var result = ft_service_list_lookup(FT_CFF_SERVICES_GET, module_interface); + if (result != null) + return result; + + if (driver == null) + return null; + + /* we pass our request to the `sfnt' module */ + var sfnt = driver.library.FT_Get_Module("sfnt"); + if (sfnt == null) + return null; + + return sfnt.clazz.get_interface(sfnt, module_interface); +} + +function CFF_Driver_Class() +{ + this.flags = 0x501; + this.name = "cff"; + this.version = 0x10000; + this.requires = 0x20000; + + this.module_interface = null; + + this.init = cff_driver_init; + this.done = cff_driver_done; + this.get_interface = cff_get_interface; + + this.face_object_size = 0; + this.size_object_size = 0; + this.slot_object_size = 0; + + this.init_face = cff_face_init; + this.done_face = cff_face_done; + + this.init_size = cff_size_init; + this.done_size = cff_size_done; + + this.init_slot = cff_slot_init; + this.done_slot = cff_slot_done; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.set_char_sizes = ft_stub_set_char_sizes; + this.set_pixel_sizes = ft_stub_set_pixel_sizes; + //#endif + + this.load_glyph = cff_Load_Glyph; + + this.get_kerning = cff_get_kerning; + this.attach_file = null; + this.get_advances = cff_get_advances; + + this.request_size = cff_size_request; + this.select_size = cff_size_select; +} + +function CFF_Driver() +{ + this.clazz = null; // FT_Module_Class + this.library = null; // FT_Library + this.memory = null; // FT_Memory + this.generic = null; // FT_Generic + + this.clazz = new CFF_Driver_Class(); + this.faces_list = []; + this.extensions = null; + this.glyph_loader = null; + + this.extension_component = null; + + this.open_face = function(stream, face_index) + { + FT_Error = 0; + var face = new TT_Face(); + var internal = new FT_Face_Internal(); + + face.driver = this; + face.memory = this.memory; + face.stream = stream; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + face.internal = internal; + face.internal.incremental_interface = null; + //#endif + + var err1 = this.clazz.init_face(stream, face, face_index); + + if (err1 != 0) + { + face = null; + FT_Error = err1; + return null; + } + + var err2 = find_unicode_charmap(face); + if (err2 != 0 && err2 != FT_Common.FT_Err_Invalid_CharMap_Handle) + { + face = null; + FT_Error = err2; + return null; + } + + FT_Error = 0; + return face; + } +} + +function create_cff_driver(library) +{ + var driver = new CFF_Driver(); + driver.library = library; + driver.memory = library.Memory; + + return driver; +} \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/drivers/cid.js b/Common/FontsFreeType/Private/FreeType/drivers/cid.js new file mode 100644 index 0000000000000000000000000000000000000000..65d1f80bcdcf1f6eb62780ef1fd01e3f5dd3457a --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/drivers/cid.js @@ -0,0 +1,1515 @@ +/******************************************************************************/ +// cidgload +/******************************************************************************/ +function cid_load_glyph(decoder, glyph_index) +{ + var face = decoder.builder.face; + var cid = face.cid; + var memory = face.memory; + var fd_select; + var stream = face.cid_stream; + var error = 0; + var charstring = null; + var glyph_length = 0; + var psaux = face.psaux; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + var inc = face.internal.incremental_interface; + //#endif + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (inc != null) + { + var glyph_data = new FT_Data(); + + error = inc.funcs.get_glyph_data(inc.object, glyph_index, glyph_data); + if (error != 0) + return error; + + var p = glyph_data.pointer; + fd_select = cid_get_offset(p, cid.fd_bytes); + + if (glyph_data.length != 0) + { + glyph_length = glyph_data.length - cid.fd_bytes; + charstring = memory.Alloc(glyph_length); + + var _data = glyph_data.pointer.data; + var _start = glyph_data.pointer.pos + cid.fd_bytes; + for (var i = 0; i < glyph_length; i++) + charstring[i] = _data[_start + i]; + } + + inc.funcs.free_glyph_data(inc.object, glyph_data); + glyph_data = null; + } + else + { + //#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + var entry_len = cid.fd_bytes + cid.gd_bytes; + + error = stream.Seek(cid.data_offset + cid.cidmap_offset + glyph_index * entry_len); + if (error != 0) + return error; + + error = stream.EnterFrame(2 * entry_len); + if (error != 0) + return error; + + var p = new CPointer(); + p.data = stream.data; + p.pos = stream.cur; + fd_select = cid_get_offset(p, cid.fd_bytes); + var off1 = cid_get_offset(p, cid.gd_bytes); + p.pos += cid.fd_bytes; + glyph_length = cid_get_offset(p, cid.gd_bytes) - off1; + + stream.ExitFrame(); + + if (fd_select >= cid.num_dicts) + return FT_Common.FT_Err_Invalid_Offset; + if (glyph_length == 0) + return error; + + charstring = memory.Alloc(glyph_length); + error = stream.ReadAt(cid.data_offset + off1, charstring, glyph_length); + if (error != 0) + return error; + } + + var cid_subrs = face.subrs[fd_select]; + + + /* Set up subrs */ + decoder.num_subrs = cid_subrs.num_subrs; + decoder.subrs = cid_subrs.code; + decoder.subrs_len = 0; + + /* Set up font matrix */ + var dict = cid.font_dicts[fd_select]; + + decoder.font_matrix = dublicate_matrix(dict.font_matrix); + decoder.font_offset = dublicate_vector(dict.font_offset); + decoder.lenIV = dict.private_dict.lenIV; + + /* Decode the charstring. */ + + /* Adjustment for seed bytes. */ + var cs_offset = (decoder.lenIV >= 0 ? decoder.lenIV : 0); + + /* Decrypt only if lenIV >= 0. */ + if (decoder.lenIV >= 0) + psaux.t1_decrypt(charstring, glyph_length, 4330); + + error = decoder.funcs.parse_charstrings(decoder, charstring + cs_offset, glyph_length - cs_offset); + charstring = null; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (!error && inc && inc.funcs.get_glyph_metrics) + { + var metrics = new FT_Incremental_MetricsRec(); + + metrics.bearing_x = (FT_RoundFix(decoder.builder.left_bearing.x) >> 16); + metrics.bearing_y = 0; + metrics.advance = (FT_RoundFix(decoder.builder.advance.x) >> 16); + metrics.advance_v = (FT_RoundFix(decoder.builder.advance.y) >> 16); + + error = inc.funcs.get_glyph_metrics(inc.object, glyph_index, false, metrics); + + decoder.builder.left_bearing.x = (metrics.bearing_x << 16); + decoder.builder.advance.x = (metrics.advance << 16); + decoder.builder.advance.y = (metrics.advance_v << 16); + } + //#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + return error; +} + +function cid_slot_load_glyph(glyph, cidsize, glyph_index, load_flags) +{ + var error = null; + var decoder = new T1_DecoderRec(); + var face = glyph.face; + + var psaux = face.psaux; + + if (glyph_index >= face.num_glyphs) + return FT_Common.FT_Err_Invalid_Argument; + + if (load_flags & FT_Common.FT_LOAD_NO_RECURSE) + load_flags |= (FT_Common.FT_LOAD_NO_SCALE | FT_Common.FT_LOAD_NO_HINTING); + + glyph.x_scale = cidsize.metrics.x_scale; + glyph.y_scale = cidsize.metrics.y_scale; + + glyph.outline.n_points = 0; + glyph.outline.n_contours = 0; + + var hinting = ((load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0 && (load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) ? 1 : 0; + glyph.format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + + error = psaux.t1_decoder_funcs.init(decoder, glyph.face, cidsize, glyph, null, null, hinting, FT_LOAD_TARGET_MODE(load_flags), cid_load_glyph); + if (error != 0) + return error; + + /* TODO: initialize decoder.len_buildchar and decoder.buildchar */ + /* if we ever support CID-keyed multiple master fonts */ + + /* set up the decoder */ + decoder.builder.no_recurse = ((load_flags & FT_Common.FT_LOAD_NO_RECURSE) != 0); + + error = cid_load_glyph(decoder, glyph_index); + if (error != 0) + return error; + + var font_matrix = dublicate_matrix(decoder.font_matrix); + var font_offset = dublicate_vector(decoder.font_offset); + + /* save new glyph tables */ + psaux.t1_decoder_funcs.done(decoder); + decoder = null; + + /* now set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax */ + glyph.outline.flags &= FT_Common.FT_OUTLINE_OWNER; + glyph.outline.flags |= FT_Common.FT_OUTLINE_REVERSE_FILL; + + /* for composite glyphs, return only left side bearing and */ + /* advance width */ + if (load_flags & FT_Common.FT_LOAD_NO_RECURSE) + { + var internal = glyph.internal; + + glyph.metrics.horiBearingX = (FT_RoundFix(decoder.builder.left_bearing.x) >> 16); + glyph.metrics.horiAdvance = (FT_RoundFix(decoder.builder.advance.x) >> 16); + + internal.glyph_matrix = dublicate_matrix(font_matrix); + internal.glyph_delta = dublicate_vector(font_offset); + internal.glyph_transformed = 1; + } + else + { + var metrics = glyph.metrics; + + /* copy the _unscaled_ advance width */ + metrics.horiAdvance = (FT_RoundFix(decoder.builder.advance.x) >> 16); + glyph.linearHoriAdvance = (FT_RoundFix(decoder.builder.advance.x) >> 16); + glyph.internal.glyph_transformed = 0; + + /* make up vertical ones */ + metrics.vertAdvance = (face.cid.font_bbox.yMax - face.cid.font_bbox.yMin) >> 16; + glyph.linearVertAdvance = metrics.vertAdvance; + glyph.format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + + if (cidsize.metrics.y_ppem < 24) + cidglyph.outline.flags |= FT_Common.FT_OUTLINE_HIGH_PRECISION; + + /* apply the font matrix */ + FT_Outline_Transform(glyph.outline, font_matrix); + FT_Outline_Translate(glyph.outline, font_offset.x, font_offset.y); + + var advance = new FT_Vector(); + advance.x = metrics.horiAdvance; + advance.y = 0; + FT_Vector_Transform(advance, font_matrix); + metrics.horiAdvance = advance.x + font_offset.x; + + advance.x = 0; + advance.y = metrics.vertAdvance; + FT_Vector_Transform(advance, font_matrix); + metrics.vertAdvance = advance.y + font_offset.y; + + if ((load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0) + { + /* scale the outline and the metrics */ + var cur = decoder.builder.base; + var vec = cur.points; + var x_scale = glyph.x_scale; + var y_scale = glyph.y_scale; + + /* First of all, scale the points */ + if (!hinting || decoder.builder.hints_funcs == null) + { + for (var n = cur.n_points; n > 0; n--, vec++) + { + cur.points[vec].x = FT_MulFix(cur.points[vec].x, x_scale); + cur.points[vec].y = FT_MulFix(cur.points[vec].y, y_scale); + } + } + + /* Then scale the metrics */ + metrics.horiAdvance = FT_MulFix(metrics.horiAdvance, x_scale); + metrics.vertAdvance = FT_MulFix(metrics.vertAdvance, y_scale); + } + + /* compute the other metrics */ + var cbox = new FT_BBox(); + FT_Outline_Get_CBox(glyph.outline, cbox); + + metrics.width = cbox.xMax - cbox.xMin; + metrics.height = cbox.yMax - cbox.yMin; + + metrics.horiBearingX = cbox.xMin; + metrics.horiBearingY = cbox.yMax; + + if (load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) + { + /* make up vertical ones */ + ft_synthesize_vertical_metrics(metrics, metrics.vertAdvance); + } + } + + return error; +} + +/******************************************************************************/ +// cidparse +/******************************************************************************/ +function CID_Parser() +{ + this.root = new PS_ParserRec(); + this.stream = null; + + this.postscript = null; + this.postscript_len = 0; + + this.data_offset = 0; + this.binary_length = 0; + + this.cid = null; + this.num_dict = 0; + + this.clear = function() + { + this.root.cursor = 0; + this.root.base = null; + this.root.limit = 0; + this.root.error = 0; + this.root.memory = null; + + this.funcs = null; + + this.stream = null; + + this.postscript = null; + this.postscript_len = 0; + + this.data_offset = 0; + this.binary_length = 0; + + this.cid = null; + this.num_dict = 0; + } +} + +function cid_parser_new(parser, stream, memory, psaux) +{ + parser.clear(); + psaux.ps_parser_funcs.init(parser.root, null, 0, memory); + + parser.stream = stream; + + var base_offset = stream.pos; + var offset = 0; + + /* first of all, check the font format in the header */ + var error = stream.EnterFrame(31); + if (error != 0) + return error; + + var cur_str = stream.GetString1(31); + if (cur_str != "%!PS-Adobe-3.0 Resource-CIDFont") + return FT_Common.FT_Err_Unknown_File_Format; + + stream.ExitFrame(); + + /* now, read the rest of the file until we find */ + /* `StartData' or `/sfnts' */ + var limit = 0; + while (true) + { + var buffer = memory.Alloc(256 + 10); + var read_len = 256 + 10; /* same as signed FT_Stream->size */ + var p = dublicate_pointer(buffer); + + for (offset = stream.pos; ; offset += 256) + { + var stream_len = stream.size - stream.pos;/* same as signed FT_Stream->size */ + if (stream_len == 0) + return FT_Common.FT_Err_Unknown_File_Format; + + read_len = Math.min(read_len, stream_len); + + error = stream.Read(p, read_len); + if (error != 0) + return error; + + if (read_len < 256) + p[read_len] = FT_Common.SYMBOL_CONST_S0; + + limit = p.pos + read_len - 10; + + p.pos = buffer.pos; + + var bIsGoToFound = 0; + for (; p.pos < limit; p.pos++) + { + if ((p.data[p.pos] == FT_Common.SYMBOL_CONST_S) && (_strncmp_data(p, "StartData", 9) == 0)) + { + /* save offset of binary data after `StartData' */ + offset += (p.pos - buffer.pos + 10); + bIsGoToFound = 1; + break; + } + else if ((p.data[p.pos + 1] == FT_Common.SYMBOL_CONST_s) && (_strncmp_data(p, "/sfnts", 6) == 0)) + { + offset += (p.pos - buffer.pos + 7); + bIsGoToFound = 1; + break; + } + } + + if (bIsGoToFound == 1) + break; + + var _dd = p.data; + var __s1 = buffer.pos; + var __s2 = p.pos; + + var arr_move = memory.Alloc(10); + for (var i = 0; i < 10; i++) + arr_move[i] = _dd[__s2 + i]; + + for (var i = 0; i < 10; i++) + _dd[__s1 + i] = arr_move[i]; + + arr_move = null; + + read_len = 256; + p.pos = buffer.pos + 10; + } + + /* We have found the start of the binary data or the `/sfnts' token. */ + /* Now rewind and extract the frame corresponding to this PostScript */ + /* section. */ + var ps_len = offset - base_offset; + + error = stream.Seek(base_offset); + if (error != 0) + return error; + + parser.postscript = new CPointer(); + error = stream.ExtractFrame(ps_len, parser.postscript); + + if (error != 0) + return error; + + parser.data_offset = offset; + parser.postscript_len = ps_len; + parser.root.base = dublicate_pointer(parser.postscript); + parser.root.cursor = 0; + parser.root.limit = parser.postscript.pos + ps_len; + parser.num_dict = -1; + + /* Finally, we check whether `StartData' or `/sfnts' was real -- */ + /* it could be in a comment or string. We also get the arguments */ + /* of `StartData' to find out whether the data is represented in */ + /* binary or hex format. */ + + var arg1 = dublicate_pointer(parser.root.base); + arg1.pos += parser.root.cursor; + parser.root.funcs.skip_PS_token(p.root); + parser.root.funcs.skip_spaces(p.root); + + var arg2 = dublicate_pointer(parser.root.base); + arg2.pos += parser.root.cursor; + parser.root.funcs.skip_PS_token(p.root); + parser.root.funcs.skip_spaces(p.root); + + limit = parser.root.limit; + var cur = dublicate_pointer(parser.root.base); + cur.pos += parser.root.cursor; + + while (cur.pos < limit) + { + if (parser.root.error != 0) + return parser.root.error; + + if ((cur.data[cur.pos] == FT_Common.SYMBOL_CONST_S) && (_strncmp_data(cur, "StartData", 9) == 0)) + { + if (_strncmp_data(arg1, "(Hex)", 5) == 0) + { + var _num_s = ""; + var ii = 0; + while (true) + { + if (arg2.data[arg2.pos + ii] == FT_Common.SYMBOL_CONST_S0) + break; + _num_s += String.fromCharCode(arg2.data[arg2.pos + ii]); + } + parser.binary_length = parseInt(_num_s); + } + + limit = parser.root.limit; + cur.pos = parser.root.base.pos + parser.root.cursor; + return error; + } + else if ((cur.data[cur.pos + 1] == FT_Common.SYMBOL_CONST_s) && (_strncmp_data(cur, "/sfnts", 6) == 0)) + { + return FT_Common.FT_Err_Unknown_File_Format; + } + + parser.root.funcs.skip_PS_token(p.root); + parser.root.funcs.skip_spaces(p.root); + + arg1.pos = arg2.pos; + arg2.pos = cur.pos; + cur.pos = parser.root.base.pos + parser.root.cursor; + } + + /* we haven't found the correct `StartData'; go back and continue */ + /* searching */ + stream.ReleaseFrame(); + parser.postscript = null; + + error = stream.Seek(offset); + if (error != 0) + break; + } + + return error; +} + +function cid_parser_done(parser) +{ + /* always free the private dictionary */ + if (parser.postscript != null) + { + parser.stream.ReleaseFrame(); + parser.postscript = null; + } + parser.root.funcs.done(parser.root); +} + + +/******************************************************************************/ +// cidload +/******************************************************************************/ +function CID_Loader() +{ + this.parser = new CID_Parser(); + this.num_chars = 0; + + this.clear = function() + { + this.parser.clear(); + this.num_chars = 0; + } +} + +function cid_get_offset(start, offsize) +{ + var result = 0; + for (; offsize > 0; offsize--) + { + result <<= 8; + result |= start.data[start.pos++]; + } + return result; +} +function cid_load_keyword(face, loader, keyword) +{ + var error = 0; + var parser = loader.parser; + var object = null; + var cid = face.cid; + + if (keyword.type == FT_Common.T1_FIELD_TYPE_CALLBACK) + { + keyword.reader(face, parser); + error = parser.error; + return error; + } + + switch (keyword.location) + { + case FT_Common.T1_FIELD_LOCATION_CID_INFO: + object = cid; + break; + case FT_Common.T1_FIELD_LOCATION_FONT_INFO: + object = cid.font_info; + break; + case FT_Common.T1_FIELD_LOCATION_FONT_EXTRA: + object = face.font_extra; + break; + case FT_Common.T1_FIELD_LOCATION_BBOX: + object = cid.font_bbox; + break; + default: + { + if (parser.num_dict < 0 || parser.num_dict >= cid.num_dicts) + return FT_Error.FT_Err_Syntax_Error; + + var dict = cid.font_dicts[parser.num_dict]; + switch (keyword.location) + { + case FT_Common.T1_FIELD_LOCATION_PRIVATE: + object = dict.private_dict; + break; + default: + object = dict; + } + } + } + + var dummy_object = new Array(1); + dummy_object[0] = object; + + if (keyword.type == FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY || keyword.type == FT_Common.T1_FIELD_TYPE_FIXED_ARRAY) + error = loader.parser.root.funcs.load_field_table(loader.parser.root, keyword, dummy_object, 0, 0); + else + error = loader.parser.root.funcs.load_field(loader.parser.root, keyword, dummy_object, 0, 0); + + return error; +} + +function parse_font_matrix(face, parser) +{ + var temp = new Array(6); + if (parser.num_dict >= 0 && parser.num_dict < face.cid.num_dicts) + { + var dict = face.cid.font_dicts[parser.num_dict]; + var matrix = dict.font_matrix; + var offset = dict.font_offset; + + parser.root.funcs.to_fixed_array(parser.root, 6, temp, 3); + + var temp_scale = Math.abs(temp[3]); + + /* Set units per EM based on FontMatrix values. We set the value to */ + /* `1000/temp_scale', because temp_scale was already multiplied by */ + /* 1000 (in `t1_tofixed', from psobjs.c). */ + face.units_per_EM = (FT_DivFix(0x10000, FT_DivFix(temp_scale, 1000))); + if (face.units_per_EM > 0xFFFF) + face.units_per_EM = 0xFFFF; + + /* we need to scale the values by 1.0/temp[3] */ + if (temp_scale != 0x10000) + { + temp[0] = FT_DivFix(temp[0], temp_scale); + temp[1] = FT_DivFix(temp[1], temp_scale); + temp[2] = FT_DivFix(temp[2], temp_scale); + temp[4] = FT_DivFix(temp[4], temp_scale); + temp[5] = FT_DivFix(temp[5], temp_scale); + temp[3] = 0x10000; + } + + matrix.xx = temp[0]; + matrix.yx = temp[1]; + matrix.xy = temp[2]; + matrix.yy = temp[3]; + + /* note that the font offsets are expressed in integer font units */ + offset.x = temp[4] >> 16; + offset.y = temp[5] >> 16; + } + + return 0; +} + +function parse_fd_array(face, parser) +{ + var cid = face.cid; + var error = 0; + + var num_dicts = parser.root.funcs.to_int(parser.root); + + if (cid.font_dicts == null) + { + cid.font_dicts = new Array(num_dicts); + for (var i = 0; i < num_dicts; i++) + { + cid.font_dicts[i] = new CID_FaceDictRec(); + cid.font_dicts[i].private_dict.lenIV = 4; + } + cid.num_dicts = num_dicts; + } + return error; +} + +function parse_expansion_factor(face, parser) +{ + if (parser.num_dict >= 0 && parser.num_dict < face.cid.num_dicts) + { + var dict = face.cid.font_dicts[parser.num_dict]; + + dict.expansion_factor = parser.root.funcs.to_fixed(parser.root, 0); + dict.private_dict.expansion_factor = dict.expansion_factor; + } + return 0; +} + +function cid_parse_dict(face, loader, base, size) +{ + var parser = loader.parser; + + parser.root.cursor = dublicate_pointer(base); + parser.root.limit = base.pos + size; + parser.root.error = 0; + + var cur = dublicate_pointer(base); + var limit = cur.pos + size; + + var newlimit = 0; + + while (true) + { + parser.root.cursor = cur.pos; + parser.root.funcs.skip_spaces(parser.root); + + if (parser.root.cursor.pos >= limit) + newlimit = limit - 1 - 17; + else + newlimit = parser.root.cursor.pos - 17; + + /* look for `%ADOBeginFontDict' */ + for (; cur.pos < newlimit; cur.pos++) + { + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_MATH_3 && _strncmp_data(cur, "%ADOBeginFontDict", 17) == 0) + { + /* if /FDArray was found, then cid->num_dicts is > 0, and */ + /* we can start increasing parser->num_dict */ + if (face.cid.num_dicts > 0) + parser.num_dict++; + } + } + + cur.pos = parser.root.cursor.pos; + /* no error can occur in cid_parser_skip_spaces */ + if (cur.pos >= limit) + break; + + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.cursor.pos >= limit || parser.root.error != 0) + break; + + /* look for immediates */ + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_BS && cur.pos + 2 < limit) + { + cur.pos++; + var len = parser.root.cursor.pos - cur.pos; + + if (len > 0 && len < 22) + { + /* now compare the immediate name to the keyword table */ + var keyword = 0; + var keywords_count = cid_field_records.length; + + while (true) + { + if (keyword >= keywords_count) + break; + + var _key = cid_field_records[keyword]; + + if (cur.data[cur.pos] == _key.ident.charCodeAt(0) && len == _key.ident.length) + { + var n; + for (n = 1; n < len; n++) + if (cur.data[cur.pos + n] != _key.ident.charCodeAt(n)) + break; + + if (n >= len) + { + /* we found it - run the parsing callback */ + parser.root.error = cid_load_keyword(face, loader, keyword); + if (parser.root.error) + return parser.root.error; + break; + } + } + keyword++; + } + } + } + + cur.pos = parser.root.cursor.pos; + } + return parser.root.error; +} + +function cid_read_subrs(face) +{ + var cid = face.cid; + var memory = face.memory; + var stream = face.cid_stream; + var error = 0; + var n = 0; + + var _num_dicts = cid.num_dicts; + face.subrs = new Array(_num_dicts); + var subrs = face.subrs; + + for (n = 0; n < _num_dicts; n++) + subrs[n] = new CID_SubrsRec(); + + var subr = 0; + var max_offsets = 0; + var offsets = []; + var psaux = face.psaux; + + for (n = 0; n < _num_dicts; n++, subr++) + { + var dict = cid.font_dicts[n]; + var lenIV = dict.private_dict.lenIV; + var count, num_subrs = dict.num_subrs; + + /* Check for possible overflow. */ + if (num_subrs == 0xFFFFFFFF) + { + face.subrs = null; + offsets = null; + return FT_Common.FT_Err_Syntax_Error; + } + + /* reallocate offsets array if needed */ + if (num_subrs + 1 > max_offsets) + { + var new_max = (num_subrs + 4) & (~3); + + if ( new_max <= max_offsets ) + { + face.subrs = null; + offsets = null; + return FT_Common.FT_Err_Syntax_Error; + } + + for (var i = max_offsets; i < new_max; i++) + offsets[i] = 0; + + max_offsets = new_max; + } + + /* read the subrmap's offsets */ + error = stream.Seek(cid.data_offset + dict.subrmap_offset); + if (error == 0) + error = stream.EnterFrame((num_subrs + 1) * dict.sd_bytes); + + if (error != 0) + { + face.subrs = null; + offsets = null; + return error; + } + + var p = new CPointer; + p.data = stream.data; + p.pos = stream.cur; + for (count = 0; count <= num_subrs; count++) + offsets[count] = cid_get_offset(p, dict.sd_bytes); + + stream.ExitFrame(); + + /* offsets must be ordered */ + for (count = 1; count <= num_subrs; count++) + { + if (offsets[count - 1] > offsets[count]) + { + face.subrs = null; + offsets = null; + return error; + } + } + + /* now, compute the size of subrs charstrings, */ + /* allocate, and read them */ + var data_len = offsets[num_subrs] - offsets[0]; + + subrs[subr].code = new Array(num_subrs + 1); + subrs[subr].code[0] = memory.Alloc(data_len); + + error = stream.Seek(cid.data_offset + offsets[0]); + if (error == 0) + error = stream.Read(subrs[subr].code[0], data_len); + + if (error != 0) + { + face.subrs = null; + offsets = null; + return error; + } + + /* set up pointers */ + for (count = 1; count <= num_subrs; count++) + { + var len = offsets[count] - offsets[count - 1]; + subrs[subr].code[count] = subrs[subr].code[count - 1] + len; + } + + /* decrypt subroutines, but only if lenIV >= 0 */ + if (lenIV >= 0) + { + for (count = 0; count < num_subrs; count++) + { + var len = offsets[count + 1] - offsets[count]; + psaux.t1_decrypt(subrs[subr].code[count], len, 4330); + } + } + + subrs[subr].num_subrs = num_subrs; + } + + offsets = null; + return error; +} + +function t1_init_loader(loader, face) +{ + loader.clear(); +} +function t1_done_loader(loader) +{ + cid_parser_done(loader.parser); +} + +function cid_hex_to_binary(data, data_len, offset, face) +{ + var stream = face.stream; + + var error = stream.Seek(offset); + if (error != 0) + return error; + + var buffer = face.memoty.Alloc(256); + var val = null; + + var d = dublicate_pointer(data); + var dlimit = d.pos + data_len; + var p = dublicate_pointer(buffer); + var plimit = p.pos; + + var upper_nibble = 1; + var done = 0; + + while (d.pos < dlimit) + { + if (p.pos >= plimit) + { + var oldpos = stream.pos; + var size = stream.size - oldpos; + + if (size == 0) + return FT_Common.FT_Err_Syntax_Error; + + error = stream.Read(buffer, (256 > size) ? size : 256); + if (error != 0) + return error; + + p.pos = buffer.pos; + plimit = p.pos + stream.pos - oldpos; + } + + var _p = p.data[p.pos]; + if (_p >= FT_Common.SYMBOL_CONST_0 && _p <= FT_Common.SYMBOL_CONST_9) + val = _p - FT_Common.SYMBOL_CONST_0; + else if (_p >= FT_Common.SYMBOL_CONST_a && _p <= FT_Common.SYMBOL_CONST_f) + val = _p - FT_Common.SYMBOL_CONST_a; + else if (_p >= FT_Common.SYMBOL_CONST_A && _p <= FT_Common.SYMBOL_CONST_F) + val = _p - FT_Common.SYMBOL_CONST_A + 10; + else if (_p == FT_Common.SYMBOL_CONST_SPACE || _p == FT_Common.SYMBOL_CONST_ST || + _p == FT_Common.SYMBOL_CONST_SR || _p == FT_Common.SYMBOL_CONST_SN || + _p == FT_Common.SYMBOL_CONST_SF || _p == FT_Common.SYMBOL_CONST_S0) + { + p.pos++; + continue; + } + else if (_p == FT_Common.SYMBOL_CONST_MATH_2) + { + val = 0; + done = 1; + } + else + { + return FT_Common.FT_Err_Syntax_Error; + } + + if (upper_nibble == 1) + d.data[d.pos] = (val << 4) & 0xFF; + else + { + d.data[d.pos] = (d.data[d.pos] + val) & 0xFF; + d.pos++; + } + + upper_nibble = (1 - upper_nibble); + + if (done == 1) + break; + + p.pos++; + } + + return 0; +} + +function cid_face_open(face, face_index) +{ + var loader = new CID_Loader(); + var memory = face.memory; + + t1_init_loader(loader, face); + + var parser = loader.parser; + var error = cid_parser_new(parser, face.stream, memory, face.psaux); + if (error != 0) + { + t1_done_loader(loader); + return error; + } + + error = cid_parse_dict(face, loader, parser.postscript, parser.postscript_len); + if (error != 0) + { + return error; + } + + if (face_index < 0) + { + t1_done_loader(loader); + return error; + } + + if (parser.binary_length != 0) + { + face.binary_data = memory.Alloc(parser.binary_length); + /* we must convert the data section from hexadecimal to binary */ + error = cid_hex_to_binary(face.binary_data, parser.binary_length, parser.data_offset, face); + if (error != 0) + { + t1_done_loader(loader); + return error; + } + + face.cid_stream = new FT_Stream(face.binary_data.data, parser.binary_length); + face.cid.data_offset = 0; + } + else + { + face.cid_stream = new FT_Stream(face.stream.data, face.stream.size); + face.cid.data_offset = loader.parser.data_offset; + } + + error = cid_read_subrs(face); + + t1_done_loader(loader); + return error; +} + +/******************************************************************************/ +// objs +/******************************************************************************/ +function CID_SizeRec() +{ + this.root = new FT_Size(); + this.valid = 0; +} + +function CID_GlyphSlotRec() +{ + this.root = new FT_GlyphSlot(); + + this.hint = 0; + this.scaled = 0; + + this.x_scale = 0; + this.y_scale = 0; +} + +function cid_slot_done(_slot) +{ + var slot = (slot.hint == undefined) ? _slot : _slot.root; + slot.internal.glyph_hints = null; +} + +function cid_slot_init(_slot) +{ + var slot = (slot.hint == undefined) ? _slot : _slot.root; + + var face = slot.face; + var pshinter = face.pshinter; + + if (pshinter != null) + { + var module = slot.face.driver.library.FT_Get_Module("pshinter"); + if (module != null) + { + // пока нет хинтов - нету и Ñтого if'а + slot.internal.glyph_hints = pshinter.get_t1_funcs(module); + } + } + + return 0; +} + +function cid_size_get_globals_funcs(size) +{ + var face = size.root.face; + var pshinter = face.pshinter; + + var module = size.face.driver.library.FT_Get_Module("pshinter"); + return (module && pshinter && pshinter.get_globals_funcs) ? pshinter.get_globals_funcs(module) : null; +} + +function cid_size_done(size) +{ + if (size.root.internal != null) + { + var funcs = cid_size_get_globals_funcs(size); + if (funcs != null) + funcs.destroy(size.root.internal); + + size.root.internal = 0; + } +} + +function cid_size_init(size) /* CID_Size */ +{ + var error = 0; + var funcs = cid_size_get_globals_funcs(size); + + if (funcs != null) + { + var face = size.root.face; + var dict = face.cid.font_dicts[face.face_index]; + var priv = dict.private_dict; + + var ret = funcs.create(size.root.face.memory, priv); + error = ret.err; + if (error == 0) + size.internal = ret.globals; + } + + return error; +} + +function cid_size_request(size, req) +{ + FT_Request_Metrics(size.face, req); + + var funcs = cid_size_get_globals_funcs(size); + + if (funcs) + funcs.set_scale(size.internal, size.metrics.x_scale, size.metrics.y_scale, 0, 0); + + return 0; +} + +function cid_face_done(face) /* CID_Face */ +{ + if (face == null) + return; + + var cid = face.cid; + var info = cid.font_info; + + /* release subrs */ + face.subrs = null; + + /* release FontInfo strings */ + info.version = ""; + info.notice = ""; + info.full_name = ""; + info.family_name = ""; + info.weight = ""; + + /* release font dictionaries */ + cid.font_dicts = null; + cid.num_dicts = 0; + + /* release other strings */ + cid.cid_font_name = ""; + cid.registry = ""; + cid.ordering = ""; + + face.family_name = ""; + face.style_name = ""; + + face.binary_data = null; + face.cid_stream = null; +} + +function cid_face_init(stream, face, face_index, num_params, params) +{ + face.num_faces = 1; + + var psaux = face.psaux; + if (psaux == null) + { + psaux = face.driver.library.FT_Get_Module_Interface("psaux"); + face.psaux = psaux; + } + + var pshinter = face.pshinter; + if (pshinter == null) + { + pshinter = face.driver.library.FT_Get_Module_Interface("pshinter"); + face.pshinter = pshinter; + } + + /* open the tokenizer; this will also check the font format */ + var error = stream.Seek(0); + if (error != 0) + return error; + + error = cid_face_open(face, face_index); + if (error != 0) + return error; + + /* if we just wanted to check the format, leave successfully now */ + if (face_index < 0) + return error; + + /* check the face index */ + /* XXX: handle CID fonts with more than a single face */ + if (face_index != 0) + return FT_Common.FT_Err_Invalid_Argument; + + /* now load the font program into the face object */ + /* initialize the face object fields */ + /* set up root face fields */ + var cid = face.cid; + var info = cid.font_info; + + face.num_glyphs = cid.cid_count; + face.num_charmaps = 0; + + face.face_index = face_index; + face.face_flags = FT_Common.FT_FACE_FLAG_SCALABLE | FT_Common.FT_FACE_FLAG_HORIZONTAL | FT_Common.FT_FACE_FLAG_HINTER; + + if (info.is_fixed_pitch) + face.face_flags |= FT_Common.FT_FACE_FLAG_FIXED_WIDTH; + + /* XXX: TODO: add kerning with .afm support */ + + /* get style name -- be careful, some broken fonts only */ + /* have a /FontName dictionary entry! */ + face.family_name = info.family_name; + /* assume "Regular" style if we don't know better */ + face.style_name = "Regular"; + if (face.family_name != null) + { + var full = info.full_name; + var family = face.family_name; + + var full_ind = 0; + var family_ind = 0; + + var full_count = 0; + var family_count = 0; + + if (full != null) + { + while (full_ind < full_count) + { + if (full.charCodeAt(full_ind) == family.charCodeAt(family_ind)) + { + family_ind++; + full_ind++; + } + else + { + if (full.charCodeAt(full_ind) == FT_Common.SYMBOL_CONST_SPACE || full.charCodeAt(full_ind) == FT_Common.SYMBOL_CONST_MATH_MINUS) + full_ind++; + else if (family.charCodeAt(family_ind) == FT_Common.SYMBOL_CONST_SPACE || family.charCodeAt(family_ind) == FT_Common.SYMBOL_CONST_MATH_MINUS) + family_ind++; + else + { + if (family_ind == family_count) + face.style_name = full; + break; + } + } + } + } + } + else + { + /* do we have a `/FontName'? */ + if (cid.cid_font_name) + face.family_name = cid.cid_font_name; + } + + /* compute style flags */ + face.style_flags = 0; + if (info.italic_angle) + face.style_flags |= FT_Common.FT_STYLE_FLAG_ITALIC; + if (info.weight != null) + { + if (info.weight == "Bold" || info.weight == "Black") + face.style_flags |= FT_Common.FT_STYLE_FLAG_BOLD; + } + + /* no embedded bitmap support */ + face.num_fixed_sizes = 0; + face.available_sizes = 0; + + face.bbox.xMin = cid.font_bbox.xMin >> 16; + face.bbox.yMin = cid.font_bbox.yMin >> 16; + /* no `U' suffix here to 0xFFFF! */ + face.bbox.xMax = (cid.font_bbox.xMax + 0xFFFF) >> 16; + face.bbox.yMax = (cid.font_bbox.yMax + 0xFFFF) >> 16; + + if (face.units_per_EM) + face.units_per_EM = 1000; + + face.ascender = face.bbox.yMax; + face.descender = face.bbox.yMin; + + face.height = parseInt((face.units_per_EM * 12) / 10); + if (face.height < face.ascender - face.descender) + face.height = (face.ascender - face.descender); + + face.underline_position = info.underline_position; + face.underline_thickness = info.underline_thickness; + + return error; +} + +function cid_driver_init(driver) +{ + return 0; +} + +function cid_driver_done(driver) +{ +} + + +/******************************************************************************/ +// token +/******************************************************************************/ +var cid_field_records = new Array(50); +// CID_FaceInfoRec +cid_field_records[0] = create_t1_field2("CIDFontName", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_KEY, function(obj, val, f) { obj.cid_font_name = val}, undefined); +cid_field_records[1] = create_t1_field2("CIDFontVersion", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_FIXED, function(obj, val, f) { obj.cid_version = val}, undefined); +cid_field_records[2] = create_t1_field2("CIDFontType", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.cid_font_type = val}, undefined); +cid_field_records[3] = create_t1_field2("Registry", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_STRING, function(obj, val, f) { obj.registry = val}, undefined); +cid_field_records[4] = create_t1_field2("Ordering", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_STRING, function(obj, val, f) { obj.ordering = val}, undefined); +cid_field_records[5] = create_t1_field2("Supplement", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.supplement = val}, undefined); +cid_field_records[6] = create_t1_field2("UIDBase", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.uid_base = val}, undefined); +cid_field_records[7] = create_t1_field2("CIDMapOffset", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.cidmap_offset = val}, undefined); +cid_field_records[8] = create_t1_field2("FDBytes", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.fd_bytes = val}, undefined); +cid_field_records[9] = create_t1_field2("GDBytes", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.gd_bytes = val}, undefined); +cid_field_records[10] = create_t1_field2("CIDCount", FT_Common.T1_FIELD_LOCATION_CID_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.cid_count = val}, undefined); + +// PS_FontInfoRec +cid_field_records[11] = create_t1_field2("version", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, function(obj, val, f) { obj.version = val}, undefined); +cid_field_records[12] = create_t1_field2("Notice", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, function(obj, val, f) { obj.notice = val}, undefined); +cid_field_records[13] = create_t1_field2("FullName", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, function(obj, val, f) { obj.full_name = val}, undefined); +cid_field_records[14] = create_t1_field2("FamilyName", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, function(obj, val, f) { obj.family_name = val}, undefined); +cid_field_records[15] = create_t1_field2("Weight", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, function(obj, val, f) { obj.weight = val}, undefined); +cid_field_records[16] = create_t1_field2("ItalicAngle", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.italic_angle = val}, undefined); +cid_field_records[17] = create_t1_field2("isFixedPitch", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_BOOL, function(obj, val, f) { obj.is_fixed_pitch = val}, undefined); +cid_field_records[18] = create_t1_field2("UnderlinePosition", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.underline_position = val}, undefined); +cid_field_records[19] = create_t1_field2("UnderlineThickness", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.underline_thickness = val}, undefined); + +// PS_FontExtraRec +cid_field_records[20] = create_t1_field2("FSType", FT_Common.T1_FIELD_LOCATION_FONT_EXTRA, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.fs_type = val}, undefined); + +// CID_FaceDictRec +cid_field_records[21] = create_t1_field2("PaintType", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.paint_type = val & 0xFF }, undefined); +cid_field_records[22] = create_t1_field2("FontType", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.font_type = val & 0xFF}, undefined); +cid_field_records[23] = create_t1_field2("SubrMapOffset", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.subrmap_offset = val}, undefined); +cid_field_records[24] = create_t1_field2("SDBytes", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.sd_bytes = val}, undefined); +cid_field_records[25] = create_t1_field2("SubrCount", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.num_subrs = val}, undefined); +cid_field_records[26] = create_t1_field2("lenBuildCharArray", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.len_buildchar = val}, undefined); +cid_field_records[27] = create_t1_field2("ForceBoldThreshold", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_FIXED, function(obj, val, f) { obj.forcebold_threshold = val}, undefined); +cid_field_records[28] = create_t1_field2("StrokeWidth", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_FIXED, function(obj, val, f) { obj.stroke_width = val}, undefined); + +// PS_PrivateRec +cid_field_records[29] = create_t1_field2("UniqueID", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.unique_id = val}, undefined); +cid_field_records[30] = create_t1_field2("lenIV", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.lenIV = val}, undefined); +cid_field_records[31] = create_t1_field2("LanguageGroup", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.language_group = val}, undefined); +cid_field_records[32] = create_t1_field2("password", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.password = val}, undefined); + +cid_field_records[33] = create_t1_field2("BlueScale", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_FIXED_1000, function(obj, val, f) { obj.blue_scale = val}, undefined); +cid_field_records[34] = create_t1_field2("BlueShift", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.blue_shift = val}, undefined); +cid_field_records[35] = create_t1_field2("BlueFuzz", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, function(obj, val, f) { obj.blue_fuzz = val}, undefined); + +cid_field_records[36] = create_t1_field3("BlueValues", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 14, function(obj, val, f) { obj.blue_values[f.offset] = val}, function(obj, val, f) { obj.num_blue_values = val}); +cid_field_records[37] = create_t1_field3("OtherBlues", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 10, function(obj, val, f) { obj.other_blues[f.offset] = val}, function(obj, val, f) { obj.num_other_blues = val}); +cid_field_records[38] = create_t1_field3("FamilyBlues", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 14, function(obj, val, f) { obj.family_blues[f.offset] = val}, function(obj, val, f) { obj.num_family_blues = val}); +cid_field_records[39] = create_t1_field3("FamilyOtherBlues", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 10, function(obj, val, f) { obj.family_other_blues[f.offset] = val}, function(obj, val, f) { obj.num_family_other_blues = val}); + +cid_field_records[40] = create_t1_field3("StdHW", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 1, function(obj, val, f) { obj.standard_width[0] = val}, undefined); +cid_field_records[41] = create_t1_field3("StdVW", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 1, function(obj, val, f) { obj.standard_height[0] = val}, undefined); +cid_field_records[42] = create_t1_field3("MinFeature", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 2, function(obj, val, f) { obj.min_feature[f.offset] = val}, undefined); + +cid_field_records[43] = create_t1_field3("StemSnapH", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 12, function(obj, val, f) { obj.snap_widths[f.offset] = val}, function(obj, val, f) { obj.num_snap_widths = val}); +cid_field_records[44] = create_t1_field3("StemSnapV", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 12, function(obj, val, f) { obj.snap_heights[f.offset] = val}, function(obj, val, f) { obj.num_snap_heights = val}); + +cid_field_records[45] = create_t1_field2("ForceBold", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_BOOL, function(obj, val, f) { obj.force_bold = val}, undefined); + +// FT_BBox +cid_field_records[46] = create_t1_field2("FontBBox", FT_Common.T1_FIELD_LOCATION_BBOX, FT_Common.T1_FIELD_TYPE_BOOL, undefined, undefined); + +// callbacks +cid_field_records[47] = create_t1_field("FDArray", FT_Common.T1_FIELD_LOCATION_BBOX, FT_Common.T1_FIELD_TYPE_CALLBACK, parse_fd_array, 0, -1, 0, 0, 0, undefined, undefined); +cid_field_records[48] = create_t1_field("FontMatrix", FT_Common.T1_FIELD_LOCATION_BBOX, FT_Common.T1_FIELD_TYPE_CALLBACK, parse_font_matrix, 0, -1, 0, 0, 0, undefined, undefined); +cid_field_records[49] = create_t1_field("ExpansionFactor", FT_Common.T1_FIELD_LOCATION_BBOX, FT_Common.T1_FIELD_TYPE_CALLBACK, parse_expansion_factor, 0, -1, 0, 0, 0, undefined, undefined); + + +/******************************************************************************/ +// driver +/******************************************************************************/ +function cid_get_postscript_name(face) +{ + var result = face.cid.cid_font_name; + + if (result && result[0] == '/') + result = result.substring(1); + + return result; +} +var cid_service_ps_name = new FT_Service_PsFontNameRec(cid_get_postscript_name); + +function cid_ps_get_font_info(face) +{ + FT_Error = FT_Common.FT_Err_Ok; + return face.cid.font_info.CreateDublicate(); +} +function cid_ps_get_font_extra(face) +{ + FT_Error = FT_Common.FT_Err_Ok; + return face.cid.font_extra.CreateDublicate(); +} +var cid_service_ps_info = new FT_Service_PsInfoRec(cid_ps_get_font_info,cid_ps_get_font_extra,null,null,null); + +function cid_get_ros(face, registry, ordering, supplement) +{ + FT_Error = FT_Common.FT_Err_Ok; + var cid = face.cid; + return { registry : cid.registry, ordering : cid.ordering, supplement : cid.supplement } +} +function cid_get_is_cid(face) +{ + FT_Error = FT_Common.FT_Err_Ok; + return 1; +} +function cid_get_cid_from_glyph_index(face, glyph_index) +{ + FT_Error = FT_Common.FT_Err_Ok; + return glyph_index; +} +var cid_service_cid_info = new FT_Service_CIDRec(cid_get_ros, cid_get_is_cid, cid_get_cid_from_glyph_index); + +var cid_services = new Array(4); +cid_services[0] = new FT_ServiceDescRec(FT_SERVICE_ID_XF86_NAME,FT_XF86_FORMAT_CID); +cid_services[1] = new FT_ServiceDescRec(FT_SERVICE_ID_POSTSCRIPT_FONT_NAME,cid_service_ps_name); +cid_services[2] = new FT_ServiceDescRec(FT_SERVICE_ID_POSTSCRIPT_INFO,cid_service_ps_info); +cid_services[3] = new FT_ServiceDescRec(FT_SERVICE_ID_CID,cid_service_cid_info); + +function cid_get_interface(module, cid_interface) +{ + return ft_service_list_lookup(cid_services, cid_interface); +} + +function CID_Driver_Class() +{ + this.flags = 0x501; + this.name = "t1cid"; + this.version = 0x10000; + this.requires = 0x20000; + + this.module_interface = null; + + this.init = cid_driver_init; + this.done = cid_driver_done; + this.get_interface = cid_get_interface; + + this.face_object_size = 0; + this.size_object_size = 0; + this.slot_object_size = 0; + + this.init_face = cid_face_init; + this.done_face = cid_face_done; + + this.init_size = cid_size_init; + this.done_size = cid_size_done; + + this.init_slot = cid_slot_init; + this.done_slot = cid_slot_done; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.set_char_sizes = ft_stub_set_char_sizes; + this.set_pixel_sizes = ft_stub_set_pixel_sizes; + //#endif + + this.load_glyph = cid_slot_load_glyph; + + this.get_kerning = null; + this.attach_file = null; + this.get_advances = null; + + this.request_size = cid_size_request; + this.select_size = null; +} + +function CID_Driver() +{ + this.clazz = null; // FT_Module_Class + this.library = null; // FT_Library + this.memory = null; // FT_Memory + this.generic = null; // FT_Generic + + this.clazz = new CID_Driver_Class(); + this.faces_list = []; + this.extensions = null; + this.glyph_loader = null; + + this.open_face = function(stream, face_index) + { + FT_Error = 0; + var face = new CID_Face(); + var internal = new FT_Face_Internal(); + + face.driver = this; + face.memory = this.memory; + face.stream = stream; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + face.internal = internal; + face.internal.incremental_interface = null; + //#endif + + var err1 = this.clazz.init_face(stream, face, face_index); + + if (err1 != 0) + { + face = null; + FT_Error = err1; + return null; + } + + var err2 = find_unicode_charmap(face); + if (err2 != 0 && err2 != FT_Common.FT_Err_Invalid_CharMap_Handle) + { + face = null; + FT_Error = err2; + return null; + } + + return face; + } +} + +function create_cid_driver(library) +{ + var driver = new CID_Driver(); + driver.library = library; + driver.memory = library.Memory; + + driver.clazz = new CID_Driver_Class(); + return driver; +} \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/drivers/t1.js b/Common/FontsFreeType/Private/FreeType/drivers/t1.js new file mode 100644 index 0000000000000000000000000000000000000000..bbabefc3613beae72c71c157936f1de4401cc31f --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/drivers/t1.js @@ -0,0 +1,3638 @@ +/******************************************************************************/ +// afm +/******************************************************************************/ +function T1_Done_Metrics(memory, fi) +{ + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.TrackKerns = null; + fi.NumTrackKern = 0; +} + +function t1_get_index(name, len, user_data) +{ + var type1 = user_data; + + /* PS string/name length must be < 16-bit */ + if (len > 0xFFFF) + return 0; + + for (var n = 0; n < type1.num_glyphs; n++) + { + var gname = type1.glyph_names[n]; + + if (gname == name) + return n; + } + + return 0; +} + +function compare_kern_pairs(a, b) +{ + var index1 = (a.index1 << 16) | a.index2; + var index2 = (b.index2 << 16) | b.index2; + + if (index1 > index2) + return 1; + else if (index1 < index2) + return -1; + else + return 0; +} + +function T1_Read_PFM(t1_face, stream, fi) +{ + var error = 0; + var start = new CPointer(); + start.data = stream.data; + start.pos = stream.cur; + + var limit = stream.limit; + var p = dublicate_pointer(start); + + /* Figure out how long the width table is. */ + /* This info is a little-endian short at offset 99. */ + p.pos = start.pos + 99; + if (p.pos + 2 > limit) + return FT_Common.FT_Err_Invalid_File_Format; + + var width_table_length = FT_PEEK_USHORT_LE(p); + + p.pos += 18 + width_table_length; + if (p.pos + 0x12 > limit || FT_PEEK_USHORT_LE(p) < 0x12) + return error; + + /* Kerning offset is 14 bytes from start of extensions table. */ + p.pos += 14; + p.pos = start.pos + FT_PEEK_ULONG_LE(p); + + if (p.pos == start.pos) + return error; + + if (p.pos + 2 > limit) + return FT_Common.FT_Err_Unknown_File_Format; + + fi.NumKernPair = FT_PEEK_USHORT_LE(p); + p.pos += 2; + if (p.pos + 4 * fi.NumKernPair > limit) + return FT_Common.FT_Err_Invalid_File_Format; + + /* Actually, kerning pairs are simply optional! */ + if (fi.NumKernPair == 0) + return error; + + fi.KernPairs = new Array(fi.NumKernPair); + for (var i = 0; i < fi.KernPairs; i++) + { + fi.KernPairs[i] = new AFM_KernPairRec(); + } + + /* now, read each kern pair */ + var kp = 0; + limit = p.pos + 4 * fi.NumKernPair; + + /* PFM kerning data are stored by encoding rather than glyph index, */ + /* so find the PostScript charmap of this font and install it */ + /* temporarily. If we find no PostScript charmap, then just use */ + /* the default and hope it is the right one. */ + var oldcharmap = t1_face.charmap; + var charmap = null; + + for (var n = 0; n < t1_face.num_charmaps; n++) + { + charmap = t1_face.charmaps[n]; + /* check against PostScript pseudo platform */ + if (__FT_CharmapRec(charmap).platform_id == 7) + { + error = FT_Set_Charmap(t1_face, charmap); + if (error) + { + fi.KernPairs = null; + return error; + } + break; + } + } + + /* Kerning info is stored as: */ + /* */ + /* encoding of first glyph (1 byte) */ + /* encoding of second glyph (1 byte) */ + /* offset (little-endian short) */ + for (; p.pos < limit; p.pos += 4) + { + var _t = fi.KernPairs[kp]; + + _t.index1 = FT_Get_Char_Index(t1_face, p.data[p.pos]); + _t.index2 = FT_Get_Char_Index(t1_face, p.data[p.data + 1]); + + p.pos += 2; + _t.x = FT_PEEK_SHORT_LE(p); + p.pos -= 2; + _t.y = 0; + + kp++; + } + + if (oldcharmap != null) + error = FT_Set_Charmap(t1_face, oldcharmap); + + if (error != 0) + { + fi.KernPairs = null; + return error; + } + + /* now, sort the kern pairs according to their glyph indices */ + ft_qsort(fi.KernPairs, fi.NumKernPair, compare_kern_pairs); + + return error; +} + +function T1_Read_Metrics(t1_face, stream) +{ + var parser = new AFM_ParserRec(); + + var fi = new AFM_FontInfoRec(); + var t1_font = t1_face.type1; + + var error = stream.EnterFrame(stream.size); + + fi.FontBBox = dublicate_bbox(t1_font.font_bbox); + fi.Ascender = t1_font.font_bbox.yMax; + fi.Descender = t1_font.font_bbox.yMin; + + var psaux = t1_face.psaux; + if (psaux != null && psaux.afm_parser_funcs != null) + { + var cur = new CPointer(); + cur.pos = stream.cur; + cur.data = stream.data; + error = psaux.afm_parser_funcs.init(parser, g_memory, cur, stream.size); + + if (error == 0) + { + parser.FontInfo = fi; + parser.get_index = t1_get_index; + parser.user_data = t1_face.type1; + + error = psaux.afm_parser_funcs.parse(parser); + psaux.afm_parser_funcs.done(parser); + } + } + + if (error == FT_Common.FT_Err_Unknown_File_Format) + { + var start = new CPointer(); + start.pos = stream.cur; + start.data = stream.data; + + /* MS Windows allows versions up to 0x3FF without complaining */ + if (stream.size > 6 && start.data[start.pos + 1] < 4) + { + start.pos += 2; + if (FT_PEEK_ULONG_LE(start) == stream.size) + { + error = T1_Read_PFM(t1_face, stream, fi); + } + } + } + + if (error == 0) + { + t1_font.font_bbox = dublicate_bbox(fi.FontBBox); + + t1_face.bbox.xMin = fi.FontBBox.xMin >> 16; + t1_face.bbox.yMin = fi.FontBBox.yMin >> 16; + /* no `U' suffix here to 0xFFFF! */ + t1_face.bbox.xMax = (fi.FontBBox.xMax + 0xFFFF) >> 16; + t1_face.bbox.yMax = (fi.FontBBox.yMax + 0xFFFF) >> 16; + + /* no `U' suffix here to 0x8000! */ + t1_face.ascender = ((fi.Ascender + 0x8000) >> 16); + t1_face.descender = ((fi.Descender + 0x8000) >> 16); + + if (fi.NumKernPair == 0) + { + t1_face.face_flags |= FT_Common.FT_FACE_FLAG_KERNING; + t1_face.afm_data = fi; + fi = null; + } + } + + stream.ExitFrame(); + + if (fi != null) + { + T1_Done_Metrics(g_memory, fi); + fi = null; + } + return error; +} + +function T1_Get_Kerning(fi, glyph1, glyph2) +{ + var kerning = new FT_Vector(); + var min = 0; + var mid = 0; + var max = fi.NumKernPair - 1; + var idx = (glyph1 << 16) | glyph2; + + /* simple binary search */ + var pairs = fi.KernPairs; + + while (min <= max) + { + mid = min + (max - min) / 2; + var midi = (pairs[mid].index1) << 16 | pairs[mid].index2; + + if (midi == idx) + { + kerning.x = mid.x; + kerning.y = mid.y; + + return kerning; + } + + if (midi < idx) + min = mid + 1; + else + max = mid - 1; + } + + kerning.x = 0; + kerning.y = 0; + + return kerning; +} + +function T1_Get_Track_Kerning(face, ptsize, degree, kerning) +{ + var fi = face.afm_data; + var ret = { err: FT_Common.FT_Err_Invalid_Argument, kerning: kerning }; + + if (fi == null) + { + ret.err = FT_Common.FT_Err_Invalid_Argument; + return ret; + } + + var count = fi.NumTrackKern; + for (var i = 0; i < count; i++) + { + var tk = fi.TrackKerns[i]; + + if (tk.degree != degree) + continue; + + if (ptsize < tk.min_ptsize) + { + ret.kerning = tk.min_kern; + } + else if (ptsize > tk.max_ptsize) + { + ret.kerning = tk.max_kern; + } + else + { + ret.kerning = FT_MulDiv(ptsize - tk.min_ptsize, tk.max_kern - tk.min_kern, tk.max_ptsize - tk.min_ptsize) + tk.min_kern; + } + } + + return ret; +} + +/******************************************************************************/ +// gload +/******************************************************************************/ +function T1_Parse_Glyph_And_Get_Char_String(decoder, glyph_index, char_string) +{ + var face = decoder.builder.face; + var type1 = face.type1; + var error = 0; + + decoder.font_matrix = dublicate_matrix(type1.font_matrix); + decoder.font_offset = dublicate_vector(type1.font_offset); + + char_string.pointer = dublicate_pointer(type1.charstrings[glyph_index]); + char_string.length = type1.charstrings_len[glyph_index]; + + if (error == 0) + error = decoder.funcs.parse_charstrings(decoder, char_string.pointer, char_string.length); + + return error; +} + +function T1_Parse_Glyph(decoder, glyph_index) +{ + var glyph_data = new FT_Data(); + var error = T1_Parse_Glyph_And_Get_Char_String(decoder, glyph_index, glyph_data); + return error; +} + +function T1_Compute_Max_Advance(face) +{ + var ret = { err : 0, max_advance : 0 }; + + var type1 = face.type1; + var psaux = face.psaux; + + /* initialize load decoder */ + var decoder = new T1_DecoderRec(); + + ret.err = psaux.t1_decoder_funcs.init(decoder, face, null, null, type1.glyph_names, face.blend, 0, FT_Common.FT_RENDER_MODE_NORMAL, T1_Parse_Glyph); + if (ret.err != 0) + return ret; + + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + decoder.num_subrs = type1.num_subrs; + decoder.subrs = type1.subrs; + decoder.subrs_len = type1.subrs_len; + + decoder.buildchar = face.buildchar; + decoder.len_buildchar = face.len_buildchar; + + /* for each glyph, parse the glyph charstring and extract */ + /* the advance width */ + var _count = type1.num_glyphs; + for (var glyph_index = 0; glyph_index < _count; glyph_index++) + { + if (glyph_index == 342) + { + var tt = 0; + tt += 5; + tt -= 89; + tt += 8; + } + + /* now get load the unscaled outline */ + ret.err = T1_Parse_Glyph(decoder, glyph_index); + if (glyph_index == 0 || decoder.builder.advance.x > ret.max_advance) + ret.max_advance = decoder.builder.advance.x; + } + + psaux.t1_decoder_funcs.done(decoder); + ret.err = 0; + return ret; +} + +function T1_Get_Advances(face, first, count, load_flags, advances) +{ + if (load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) + { + for ( nn = 0; nn < count; nn++ ) + advances[nn] = 0; + + return 0; + } + + var decoder = new T1_DecoderRec(); + var psaux = face.psaux; + var type1 = face.type1; + + var error = psaux.t1_decoder_funcs.init(decoder, face, null, null, type1.glyph_names, face.blend, 0, FT_Common.FT_RENDER_MODE_NORMAL, T1_Parse_Glyph); + if (error != 0) + return error; + + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + decoder.num_subrs = type1.num_subrs; + decoder.subrs = type1.subrs; + decoder.subrs_len = type1.subrs_len; + + decoder.buildchar = face.buildchar; + decoder.len_buildchar = face.len_buildchar; + + for (var nn = 0; nn < count; nn++) + { + error = T1_Parse_Glyph(decoder, first + nn); + if (error == 0) + advances[nn] = FT_RoundFix(decoder.builder.advance.x) >> 16; + else + advances[nn] = 0; + } + + return 0; +} + +function T1_Load_Glyph(_glyph, size, glyph_index, load_flags) +{ + var glyph = _glyph.base_root; + + var decoder = new T1_DecoderRec(); + var face = _glyph.face; + var type1 = face.type1; + var psaux = face.psaux; + var decoder_funcs = psaux.t1_decoder_funcs; + + var glyph_data = new FT_Data(); + var must_finish_decoder = 0; + + if (glyph_index >= face.num_glyphs) + return FT_Common.FT_Err_Invalid_Argument; + + if (load_flags & FT_Common.FT_LOAD_NO_RECURSE) + load_flags |= (FT_Common.FT_LOAD_NO_SCALE | FT_Common.FT_LOAD_NO_HINTING); + + if (size != null) + { + glyph.x_scale = size.metrics.x_scale; + glyph.y_scale = size.metrics.y_scale; + } + else + { + glyph.x_scale = 0x10000; + glyph.y_scale = 0x10000; + } + + _glyph.outline.n_points = 0; + _glyph.outline.n_contours = 0; + + var hinting = ((load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0 && (load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0); + _glyph.format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + + var error = decoder_funcs.init(decoder, face, size, glyph, type1.glyph_names, face.blend, hinting, FT_LOAD_TARGET_MODE(load_flags), T1_Parse_Glyph); + if (error != 0) + return error; + + must_finish_decoder = 1; + + decoder.builder.no_recurse = ((load_flags & FT_Common.FT_LOAD_NO_RECURSE) != 0) ? 1 : 0; + + decoder.num_subrs = type1.num_subrs; + decoder.subrs = type1.subrs; + decoder.subrs_len = type1.subrs_len; + + decoder.buildchar = face.buildchar; + decoder.len_buildchar = face.len_buildchar; + + /* now load the unscaled outline */ + error = T1_Parse_Glyph_And_Get_Char_String(decoder, glyph_index, glyph_data); + if (error != 0) + { + decoder_funcs.done(decoder); + return error; + } + + var font_matrix = dublicate_matrix(decoder.font_matrix); + var font_offset = dublicate_vector(decoder.font_offset); + + /* save new glyph tables */ + decoder_funcs.done(decoder); + + must_finish_decoder = 0; + + /* now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax */ + if (error == 0) + { + glyph.root.outline.flags &= FT_Common.FT_OUTLINE_OWNER; + glyph.root.outline.flags |= FT_Common.FT_OUTLINE_REVERSE_FILL; + + /* for composite glyphs, return only left side bearing and */ + /* advance width */ + if ((load_flags & FT_Common.FT_LOAD_NO_RECURSE) != 0) + { + var internal = glyph.root.internal; + + glyph.root.metrics.horiBearingX = FT_RoundFix(decoder.builder.left_bearing.x) >> 16; + glyph.root.metrics.horiAdvance = FT_RoundFix(decoder.builder.advance.x); + + internal.glyph_matrix = dublicate_matrix(font_matrix); + internal.glyph_delta = dublicate_vector(font_offset); + internal.glyph_transformed = 1; + } + else + { + var cbox = new FT_BBox(); + var metrics = glyph.root.metrics; + var advance = new FT_Vector(); + + /* copy the _unscaled_ advance width */ + metrics.horiAdvance = FT_RoundFix(decoder.builder.advance.x) >> 16; + glyph.root.linearHoriAdvance = FT_RoundFix(decoder.builder.advance.x) >> 16; + glyph.root.internal.glyph_transformed = 0; + + if ((load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) != 0) + { + /* make up vertical ones */ + metrics.vertAdvance = (face.type1.font_bbox.yMax - face.type1.font_bbox.yMin) >> 16; + glyph.root.linearVertAdvance = metrics.vertAdvance; + } + else + { + metrics.vertAdvance = FT_RoundFix(decoder.builder.advance.y) >> 16; + glyph.root.linearVertAdvance = FT_RoundFix(decoder.builder.advance.y) >> 16; + } + + glyph.root.format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + + if (size != null && size.metrics.y_ppem < 24) + glyph.root.outline.flags |= FT_Common.FT_OUTLINE_HIGH_PRECISION; + + /* apply the font matrix, if any */ + if (font_matrix.xx != 0x10000 || font_matrix.yy != font_matrix.xx || font_matrix.xy != 0 || font_matrix.yx != 0) + FT_Outline_Transform(glyph.root.outline, font_matrix); + + if (font_offset.x || font_offset.y) + FT_Outline_Translate(glyph.root.outline, font_offset.x, font_offset.y); + + advance.x = metrics.horiAdvance; + advance.y = 0; + FT_Vector_Transform(advance, font_matrix); + metrics.horiAdvance = advance.x + font_offset.x; + advance.x = 0; + advance.y = metrics.vertAdvance; + FT_Vector_Transform(advance, font_matrix); + metrics.vertAdvance = advance.y + font_offset.y; + + if ((load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0) + { + /* scale the outline and the metrics */ + var cur_p_c = decoder.builder.base.n_points; + var points = decoder.builder.base.points; + var vec = 0; + var x_scale = glyph.x_scale; + var y_scale = glyph.y_scale; + + + /* First of all, scale the points, if we are not hinting */ + if (hinting == 0 || decoder.builder.hints_funcs == null) + { + for (var n = cur_p_c; n > 0; n--, vec++) + { + points[vec].x = FT_MulFix(points[vec].x, x_scale); + points[vec].y = FT_MulFix(points[vec].y, y_scale); + } + } + + /* Then scale the metrics */ + metrics.horiAdvance = FT_MulFix(metrics.horiAdvance, x_scale); + metrics.vertAdvance = FT_MulFix(metrics.vertAdvance, y_scale); + } + + /* compute the other metrics */ + FT_Outline_Get_CBox(glyph.root.outline, cbox); + + metrics.width = cbox.xMax - cbox.xMin; + metrics.height = cbox.yMax - cbox.yMin; + + metrics.horiBearingX = cbox.xMin; + metrics.horiBearingY = cbox.yMax; + + if ((load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) != 0) + { + /* make up vertical ones */ + ft_synthesize_vertical_metrics(metrics, metrics.vertAdvance); + } + } + + /* Set control data to the glyph charstrings. Note that this is */ + /* _not_ zero-terminated. */ + glyph.root.control_data = dublicate_pointer(glyph_data.pointer); + glyph.root.control_len = glyph_data.length; + } + + return error; +} + +/******************************************************************************/ +// parse +/******************************************************************************/ +function T1_ParserRec() +{ + this.root = new PS_ParserRec(); + this.stream = null; + + this.base_dict = null; + this.base_len = 0; + + this.private_dict = null; + this.private_len = 0; + + this.in_pfb = 0; + this.in_memory = 0; + this.single_block = 0; + + this.clear = function() + { + this.root.clear(); + this.stream = null; + + this.base_dict = null; + this.base_len = 0; + + this.private_dict = null; + this.private_len = 0; + + this.in_pfb = 0; + this.in_memory = 0; + this.single_block = 0; + } +} + +function read_pfb_tag(stream) +{ + var ret = { tag: 0, size: 0, err: 0 }; + + var tag = stream.ReadUShort(); + ret.err = FT_Error; + if (ret.err == 0) + { + if (tag == 0x8001 || tag == 0x8002) + { + var size = stream.ReadULongLE(); + ret.err = FT_Error; + if (ret.err == 0) + ret.size = size; + } + ret.tag = tag; + } + return ret; +} + +function check_type1_format(stream, header_string, header_length) +{ + var error = stream.Seek(0); + if (error != 0) + return error; + + + var ret = read_pfb_tag(stream); + if (ret.err != 0) + return ret.err; + + /* We assume that the first segment in a PFB is always encoded as */ + /* text. This might be wrong (and the specification doesn't insist */ + /* on that), but we have never seen a counterexample. */ + if (ret.tag != 0x8001 && 0 != stream.Seek(0)) + return error; + + error = stream.EnterFrame(header_length); + if (error == 0) + { + for (var i = 0; i < header_length; i++) + { + if (header_string.charCodeAt(i) != stream.data[stream.cur + i]) + return FT_Common.FT_Err_Unknown_File_Format; + } + + stream.ExitFrame(); + } + return error; +} + +function T1_New_Parser(parser, stream, memory, psaux) +{ + psaux.ps_parser_funcs.init(parser.root, null, 0, memory); + + parser.stream = stream; + parser.base_len = 0; + parser.base_dict = null; + parser.private_len = 0; + parser.private_dict = null; + parser.in_pfb = 0; + parser.in_memory = 0; + parser.single_block = 0; + + /* check the header format */ + var error = check_type1_format(stream, "%!PS-AdobeFont", 14); + if (error != 0) + { + if (error != FT_Common.FT_Err_Unknown_File_Format) + return error; + + error = check_type1_format(stream, "%!FontType", 10); + if (error != 0) + return error; + } + + error = stream.Seek(0); + if (error != 0) + return error; + + var ret = read_pfb_tag(stream); + if (ret.err != 0) + return ret.err; + + var size = ret.size; + + if (ret.tag != 0x8001) + { + /* assume that this is a PFA file for now; an error will */ + /* be produced later when more things are checked */ + error = stream.Seek(0); + if (error != 0) + return error; + size = stream.size; + } + else + parser.in_pfb = 1; + + /* now, try to load `size' bytes of the `base' dictionary we */ + /* found previously */ + /* if it is a memory-based resource, set up pointers */ + parser.base_dict = new CPointer(); + parser.base_dict.data = stream.data; + parser.base_dict.pos = stream.pos; + parser.base_len = size; + parser.in_memory = 1; + + error = stream.Skip(size); + if (error != 0) + return error; + + parser.root.base = dublicate_pointer(parser.base_dict); + parser.root.cursor = dublicate_pointer(parser.root.base); + parser.root.limit = parser.root.base.pos + parser.base_len; + + return error; +} + +function T1_Finalize_Parser(parser) +{ + parser.private_dict = null; + parser.base_dict = null; + + parser.root.funcs.done(parser.root); +} + +function T1_Get_Private_Dict(parser, psaux) +{ + var stream = parser.stream; + var memory = parser.root.memory; + + var error = 0; + var size = 0; + + if (parser.in_pfb == 1) + { + /* in the case of the PFB format, the private dictionary can be */ + /* made of several segments. We thus first read the number of */ + /* segments to compute the total size of the private dictionary */ + /* then re-read them into memory. */ + var start_pos = stream.pos; + parser.private_len = 0; + for (;;) + { + var ret = read_pfb_tag(stream); + if (ret.err != 0) + return ret.err; + + if (ret.tag != 0x8002) + break; + + parser.private_len += ret.size; + + error = stream.Skip(ret.size); + } + + /* Check that we have a private dictionary there */ + /* and allocate private dictionary buffer */ + if (parser.private_len == 0) + return FT_Common.FT_Err_Invalid_File_Format; + + error = stream.Seek(start_pos); + if (error != 0) + return error; + + parser.private_dict = memory.Alloc(parser.private_len); + parser.private_len = 0; + var p = dublicate_pointer(parser.private_dict); + for (;;) + { + var ret = read_pfb_tag(stream); + if (ret.err != 0 || ret.tag != 0x8002) + { + error = 0; + break; + } + + p.pos = parser.private_len; + error = stream.Read(p, ret.size); + + if (error != 0) + return error; + + parser.private_len += ret.size; + } + } + else + { + /* We have already `loaded' the whole PFA font file into memory; */ + /* if this is a memory resource, allocate a new block to hold */ + /* the private dict. Otherwise, simply overwrite into the base */ + /* dictionary block in the heap. */ + + /* first of all, look at the `eexec' keyword */ + var cur = dublicate_pointer(parser.base_dict); + var limit = cur.pos + parser.base_len; + var c = 0; + + var _go_to_found = 0; + + while (true) + { + for (;;) + { + c = cur.data[cur.pos]; + if (c == FT_Common.SYMBOL_CONST_e && cur.pos + 9 < limit) /* 9 = 5 letters for `eexec' + */ + { + if (cur.data[cur.pos + 1] == FT_Common.SYMBOL_CONST_e && cur.data[cur.pos + 2] == FT_Common.SYMBOL_CONST_x && + cur.data[cur.pos + 3] == FT_Common.SYMBOL_CONST_e && cur.data[cur.pos + 4] == FT_Common.SYMBOL_CONST_c) + break; + } + cur.pos++; + if (cur.pos >= limit) + return FT_Common.FT_Err_Invalid_File_Format; + } + + /* check whether `eexec' was real -- it could be in a comment */ + /* or string (as e.g. in u003043t.gsf from ghostscript) */ + parser.root.cursor = dublicate_pointer(parser.base_dict); + parser.root.limit = cur.pos + 9; + + cur = dublicate_pointer(parser.root.cursor); + + limit = parser.root.limit; + + while (cur.pos < limit) + { + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_e && _strncmp_data(cur, "eexec", 5) == 0) + { + _go_to_found = 1; + break; + } + + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.error != 0) + break; + parser.root.funcs.skip_spaces(parser.root); + cur.pos = parser.root.cursor.pos; + } + + if (_go_to_found == 1) + break; + + /* we haven't found the correct `eexec'; go back and continue */ + /* searching */ + cur.pos = limit; + limit = parser.base_dict.pos + parser.base_len; + } + + /* now determine where to write the _encrypted_ binary private */ + /* dictionary. We overwrite the base dictionary for disk-based */ + /* resources and allocate a new block otherwise */ + parser.root.limit = parser.base_dict.pos + parser.base_len; + + parser.root.funcs.skip_PS_token(parser.root); + cur.pos = parser.root.cursor.pos; + + /* according to the Type1 spec, the first cipher byte must not be */ + /* an ASCII whitespace character code (blank, tab, carriage return */ + /* or line feed). We have seen Type 1 fonts with two line feed */ + /* characters... So skip now all whitespace character codes. */ + while (cur.pos < limit && (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_SPACE || cur.data[cur.pos] == FT_Common.SYMBOL_CONST_ST || cur.data[cur.pos] == FT_Common.SYMBOL_CONST_SR || cur.data[cur.pos] == FT_Common.SYMBOL_CONST_SN)) + cur.pos++; + if (cur.pos >= limit) + return FT_Common.FT_Err_Invalid_File_Format; + + size = parser.base_len - (cur.pos - parser.base_dict.pos); + + if (parser.in_memory == 1) + { + /* note that we allocate one more byte to put a terminating `0' */ + parser.private_dict = memory.Alloc(size + 1); + parser.private_len = size; + } + else + { + parser.single_block = 1; + parser.private_dict = dublicate_pointer(parser.base_dict); + parser.private_len = size; + parser.base_dict = null; + parser.base_len = 0; + } + + /* now determine whether the private dictionary is encoded in binary */ + /* or hexadecimal ASCII format -- decode it accordingly */ + + /* we need to access the next 4 bytes (after the final \r following */ + /* the `eexec' keyword); if they all are hexadecimal digits, then */ + /* we have a case of ASCII storage */ + + if (_isxdigit(cur[0]) && _isxdigit(cur[1]) && _isxdigit(cur[2]) && _isxdigit(cur[3])) + { + /* ASCII hexadecimal encoding */ + parser.root.cursor = cur.pos; + var ret = psaux.ps_parser_funcs.to_bytes(parser.root, parser.private_dict, parser.private_len, 0); + parser.private_len = ret.num_bytes; + + /* put a safeguard */ + parser.private_dict[len] = FT_Common.SYMBOL_CONST_S0; + } + else + { + var mem = memory.Alloc(size); + for (var i = 0; i < size; i++) + mem.data[i] = cur.data[cur.pos + i]; + + var _p = parser.private_dict.data; + var _n = parser.private_dict.pos; + for (var i = 0; i < size; i++) + _p[_n + i] = mem.data[i]; + + mem = null; + } + + } + + /* we now decrypt the encoded binary private dictionary */ + var _mem = dublicate_pointer(parser.private_dict); + psaux.t1_decrypt(_mem, parser.private_len, 55665); + + /* replace the four random bytes at the beginning with whitespace */ + var _d = parser.private_dict.data; + _d[0] = FT_Common.SYMBOL_CONST_SPACE; + _d[1] = FT_Common.SYMBOL_CONST_SPACE; + _d[2] = FT_Common.SYMBOL_CONST_SPACE; + _d[3] = FT_Common.SYMBOL_CONST_SPACE; + + parser.root.base = dublicate_pointer(parser.private_dict); + parser.root.cursor = dublicate_pointer(parser.private_dict); + parser.root.limit = parser.private_dict.pos + parser.private_len; + + return error; +} + +/******************************************************************************/ +// objs +/******************************************************************************/ +var T1_SizeRec = FT_Size; + +function T1_GlyphSlotRec() +{ + this.root = new FT_GlyphSlot(); + this.root.base_root = this; + + this.hint = 0; + this.scaled = 0; + + this.max_points = 0; + this.max_contours = 0; + + this.x_scale = 0; + this.y_scale = 0; +} + +function T1_Size_Get_Globals_Funcs(size) +{ + return null; + + var pshinter = size.face.pshinter; + var module = size.face.driver.library.FT_Get_Module("pshinter"); + if (module != null && pshinter != null && pshinter.get_globals_funcs != null) + return pshinter.get_globals_funcs(module); + return null; +} + +function T1_Size_Done(size) +{ + if (size.internal != null) + { + var funcs = T1_Size_Get_Globals_Funcs(size); + if (funcs != null) + funcs.destroy(size.internal); + + size.internal = null; + } +} + +function T1_Size_Init() +{ + var size = new FT_Size(); + var funcs = T1_Size_Get_Globals_Funcs(size); + + if (funcs != null) + { + // TODO: (hints) + } + + return size; +} + +function T1_Size_Request(size, req) +{ + var funcs = T1_Size_Get_Globals_Funcs(size); + FT_Request_Metrics(size.face, req); + + if (funcs != null) + funcs.set_scale(size.internal, size.metrics.x_scale, size.metrics.y_scale, 0, 0); + + return 0; +} + +function T1_GlyphSlot_Done(slot) +{ + slot.internal.glyph_hints = null; +} + +function T1_GlyphSlot_Init(slot) +{ + var face = slot.face; + var pshinter = face.pshinter; + + if (pshinter != null) + { + var module = face.driver.library.FT_Get_Module("pshinter"); + if (module != null) + { + var funcs = pshinter.get_t1_funcs(module); + slot.internal.glyph_hints = funcs; + } + } + return 0; +} + +function T1_Face_Done(face) +{ + if (face == null) + return; + + var memory = face.memory; + var type1 = face.type1; + + //#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + /* release multiple masters information */ + if (face.buildchar != null) + { + face.buildchar = null; + face.len_buildchar = 0; + } + + T1_Done_Blend(face); + face.blend = 0; + //#endif + + /* release font info strings */ + var info = type1.font_info; + + info.version = null; + info.notice = null; + info.full_name = null; + info.family_name = null; + info.weight = null; + + /* release top dictionary */ + type1.charstrings_len = null; + type1.charstrings = null; + type1.glyph_names = null; + + type1.subrs = null; + type1.subrs_len = null; + + type1.subrs_block = null; + type1.charstrings_block = null; + type1.glyph_names_block = null; + + type1.encoding.char_index = null; + type1.encoding.char_name = null; + type1.font_name = null; + + //#ifndef T1_CONFIG_OPTION_NO_AFM + /* release afm data if present */ + if (face.afm_data != null) + { + T1_Done_Metrics(memory, face.afm_data); + face.afm_data = null; + } + //#endif + + face.family_name = ""; + face.style_name = ""; +} + +function T1_Face_Init(stream, face, face_index, num_params, params) +{ + var type1 = face.type1; + var info = type1.font_info; + + face.num_faces = 1; + + var psnames = FT_FACE_FIND_GLOBAL_SERVICE(face, FT_SERVICE_ID_POSTSCRIPT_CMAPS); + face.psnames = psnames; + + var psaux = face.driver.library.FT_Get_Module_Interface("psaux"); + face.psaux = psaux; + + face.pshinter = face.driver.library.FT_Get_Module_Interface("pshinter"); + + /* open the tokenizer; this will also check the font format */ + var error = T1_Open_Face(face); + if (error != 0) + return error; + + /* if we just wanted to check the format, leave successfully now */ + if (face_index < 0) + return error; + + /* check the face index */ + if (face_index > 0) + return FT_Common.FT_Err_Invalid_Argument; + + /* now load the font program into the face object */ + /* initialize the face object fields */ + /* set up root face fields */ + face.num_glyphs = type1.num_glyphs; + face.face_index = 0; + + face.face_flags = FT_Common.FT_FACE_FLAG_SCALABLE | FT_Common.FT_FACE_FLAG_HORIZONTAL | FT_Common.FT_FACE_FLAG_GLYPH_NAMES | FT_Common.FT_FACE_FLAG_HINTER; + + if (info.is_fixed_pitch == 1) + face.face_flags |= FT_Common.FT_FACE_FLAG_FIXED_WIDTH; + + if (face.blend != null) + face.face_flags |= FT_Common.FT_FACE_FLAG_MULTIPLE_MASTERS; + + /* XXX: TODO -- add kerning with .afm support */ + /* The following code to extract the family and the style is very */ + /* simplistic and might get some things wrong. For a full-featured */ + /* algorithm you might have a look at the whitepaper given at */ + /* */ + /* http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */ + + /* get style name -- be careful, some broken fonts only */ + /* have a `/FontName' dictionary entry! */ + face.family_name = info.family_name; + face.style_name = null; + + if (face.family_name != null) + { + var full = 0; + var family = 0; + + var full_len = info.full_name.length; + var family_len = face.family_name.length; + + if (full < full_len) + { + var the_same = 1; + while (full < full_len) + { + var _1 = info.full_name.charCodeAt(full); + var _2 = (family < family_len) ? face.family_name.charCodeAt(family) : 0; + + if (_1 == _2) + { + family++; + full++; + } + else + { + if (_1 == FT_Common.SYMBOL_CONST_SPACE || _1 == FT_Common.SYMBOL_CONST_MATH_MINUS) + full++; + else if (_2 == FT_Common.SYMBOL_CONST_SPACE || _2 == FT_Common.SYMBOL_CONST_MATH_MINUS) + family++; + else + { + the_same = 0; + + if (family == family_len) + face.style_name = full; + break; + } + } + } + + if (the_same == 1) + face.style_name = "Regular"; + } + } + else + { + /* do we have a `/FontName'? */ + if (type1.font_name != null) + face.family_name = type1.font_name; + } + + if (face.style_name != null) + { + if (info.weight != null) + face.style_name = info.weight; + else + face.style_name = "Regular"; + } + + /* compute style flags */ + face.style_flags = 0; + if (info.italic_angle != 0) + face.style_flags |= FT_Common.FT_STYLE_FLAG_ITALIC; + if (info.weight != null) + { + if (info.weight == "Bold" || info.weight == "Black") + face.style_flags |= FT_Common.FT_STYLE_FLAG_BOLD; + } + + /* no embedded bitmap support */ + face.num_fixed_sizes = 0; + face.available_sizes = 0; + + face.bbox.xMin = type1.font_bbox.xMin >> 16; + face.bbox.yMin = type1.font_bbox.yMin >> 16; + /* no `U' suffix here to 0xFFFF! */ + face.bbox.xMax = (type1.font_bbox.xMax + 0xFFFF) >> 16; + face.bbox.yMax = (type1.font_bbox.yMax + 0xFFFF) >> 16; + + /* Set units_per_EM if we didn't set it in parse_font_matrix. */ + if (face.units_per_EM == 0) + face.units_per_EM = 1000; + + face.ascender = face.bbox.yMax; + face.descender = face.bbox.yMin; + + face.height = parseInt((face.units_per_EM * 12) / 10); + if (face.height < (face.ascender - face.descender)) + face.height = (face.ascender - face.descender); + + /* now compute the maximum advance width */ + face.max_advance_width = (face.bbox.xMax); + + var ret = T1_Compute_Max_Advance(face); + + /* in case of error, keep the standard width */ + if (ret.err == 0) + face.max_advance_width = FT_RoundFix(ret.max_advance) >> 16; + else + error = 0; /* clear error */ + + face.max_advance_height = face.height; + + face.underline_position = info.underline_position; + face.underline_thickness = info.underline_thickness; + + if (psnames != null && psaux != null) + { + var cmap_classes = psaux.t1_cmap_classes; + var charmap = new FT_CharMapRec(); + + charmap.face = face; + + /* first of all, try to synthesize a Unicode charmap */ + charmap.platform_id = FT_Common.TT_PLATFORM_MICROSOFT; + charmap.encoding_id = FT_Common.TT_MS_ID_UNICODE_CS; + charmap.encoding = FT_Common.FT_ENCODING_UNICODE; + + var __cmap = FT_CMap_New(cmap_classes.unicode, null, charmap); + __cmap = null; + error = FT_Error; + FT_Error = 0; + if (error != 0 && FT_Common.FT_Err_No_Unicode_Glyph_Name != error) + return error; + error = 0; + + /* now, generate an Adobe Standard encoding when appropriate */ + charmap.platform_id = FT_Common.TT_PLATFORM_ADOBE; + var clazz = null; + + switch (type1.encoding_type) + { + case FT_Common.T1_ENCODING_TYPE_STANDARD: + charmap.encoding = FT_Common.FT_ENCODING_ADOBE_STANDARD; + charmap.encoding_id = FT_Common.TT_ADOBE_ID_STANDARD; + clazz = cmap_classes.standard; + break; + + case FT_Common.T1_ENCODING_TYPE_EXPERT: + charmap.encoding = FT_Common.FT_ENCODING_ADOBE_EXPERT; + charmap.encoding_id = FT_Common.TT_ADOBE_ID_EXPERT; + clazz = cmap_classes.expert; + break; + + case FT_Common.T1_ENCODING_TYPE_ARRAY: + charmap.encoding = FT_Common.FT_ENCODING_ADOBE_CUSTOM; + charmap.encoding_id = FT_Common.TT_ADOBE_ID_CUSTOM; + clazz = cmap_classes.custom; + break; + + case FT_Common.T1_ENCODING_TYPE_ISOLATIN1: + charmap.encoding = FT_Common.FT_ENCODING_ADOBE_LATIN_1; + charmap.encoding_id = FT_Common.TT_ADOBE_ID_LATIN_1; + clazz = cmap_classes.unicode; + break; + + default: + break; + } + + if (clazz != null) + { + __cmap = FT_CMap_New(clazz, null, charmap); + error = FT_Error; + __cmap = null; + } + } + + return error; +} + +function T1_Driver_Init(driver) +{ + return 0; +} + +function T1_Driver_Done(driver) +{ +} + +/******************************************************************************/ +// load +/******************************************************************************/ + +function T1_Loader() +{ + this.parser = new T1_ParserRec(); + + this.num_chars = 0; + this.encoding_table = new PS_TableRec(); + /* encoding character names */ + + this.num_glyphs = 0; + this.glyph_names = new PS_TableRec(); + this.charstrings = new PS_TableRec(); + this.swap_table = new PS_TableRec(); + + this.num_subrs = 0; + this.subrs = new PS_TableRec(); + this.fontdata = 0; + + this.keywords_encountered = 0; + + this.clear = function() + { + this.parser.clear(); + + this.num_chars = 0; + this.encoding_table.clear(); + /* encoding character names */ + + this.num_glyphs = 0; + this.glyph_names.clear(); + this.charstrings.clear(); + this.swap_table.clear(); + + this.num_subrs = 0; + this.subrs.clear(); + this.fontdata = 0; + + this.keywords_encountered = 0; + } +} + +function t1_allocate_blend(face, num_designs, num_axis) +{ + var blend = face.blend; + if (blend == null) + { + blend = new PS_BlendRec(); + blend.num_default_design_vector = 0; + face.blend = blend; + } + + /* allocate design data if needed */ + if (num_designs > 0) + { + if (blend.num_designs == 0) + { + blend.font_infos[0] = face.type1.font_info; + blend.privates[0] = face.type1.private_dict; + blend.bboxes[0] = face.type1.font_bbox; + + for (var i = 1; i <= num_designs; i++) + { + blend.font_infos[i] = new PS_FontInfoRec(); + blend.privates[i] = new PS_PrivateRec(); + blend.bboxes[i] = new FT_BBox(); + } + + blend.weight_vector = CreateIntArray(num_designs * 2); + blend.default_weight_vector = num_designs; + + blend.num_designs = num_designs; + } + else if (blend.num_designs != num_designs) + return FT_Common.FT_Err_Invalid_File_Format; + } + + /* allocate axis data if needed */ + if (num_axis > 0) + { + if (blend.num_axis != 0 && blend.num_axis != num_axis) + return FT_Common.FT_Err_Invalid_File_Format; + + blend.num_axis = num_axis; + } + + /* allocate the blend design pos table if needed */ + num_designs = blend.num_designs; + num_axis = blend.num_axis; + if (num_designs && num_axis && blend.design_pos[0] == null) + { + for (var i = 0; i < num_designs; i++) + blend.design_pos[i] = CreateIntArray(num_axis); + } + return 0; +} + +function T1_Get_Multi_Master(face, master) +{ + var blend = face.blend; + if (null == blend) + return FT_Common.FT_Err_Invalid_Argument; + + master.num_axis = blend.num_axis; + master.num_designs = blend.num_designs; + + for (var n = 0; n < blend.num_axis; n++) + { + var axis = master.axis[n]; + var map = blend.design_map[n]; + + axis.name = blend.axis_names[n]; + axis.minimum = map.design_points[0]; + axis.maximum = map.design_points[map.num_points - 1]; + } + return 0; +} + +function mm_axis_unmap(axismap, ncv) +{ + if (ncv <= axismap.blend_points[0]) + return (axismap.design_points[0] << 16); + + for (var j = 1; j < axismap.num_points; j++) + { + if (ncv <= axismap.blend_points[j]) + { + var t = FT_MulDiv(ncv - axismap.blend_points[j - 1], 0x10000, axismap.blend_points[j] - axismap.blend_points[j - 1]); + return (axismap.design_points[j - 1] << 16) + FT_MulDiv(t, axismap.design_points[j] - axismap.design_points[j - 1], 1); + } + } + + return (axismap.design_points[axismap.num_points - 1] << 16); +} + +function mm_weights_unmap(weights, w_s, axiscoords, a_s, axis_count) +{ + if (axis_count == 1) + axiscoords[a_s] = weights[w_s + 1]; + else if (axis_count == 2) + { + axiscoords[a_s] = weights[w_s + 3] + weights[w_s + 1]; + axiscoords[a_s + 1] = weights[w_s + 3] + weights[w_s + 2]; + } + else if (axis_count == 3) + { + axiscoords[a_s] = weights[w_s + 7] + weights[w_s + 5] + weights[w_s + 3] + weights[w_s + 1]; + axiscoords[a_s + 1] = weights[w_s + 7] + weights[w_s + 6] + weights[w_s + 3] + weights[w_s + 2]; + axiscoords[a_s + 2] = weights[w_s + 7] + weights[w_s + 6] + weights[w_s + 5] + weights[w_s + 4]; + } + else + { + axiscoords[a_s] = weights[w_s + 15] + weights[w_s + 13] + weights[w_s + 11] + weights[w_s + 9] + weights[w_s + 7] + weights[w_s + 5] + weights[w_s + 3] + weights[w_s + 1]; + axiscoords[a_s + 1] = weights[w_s + 15] + weights[w_s + 14] + weights[w_s + 11] + weights[w_s + 10] + weights[w_s + 7] + weights[w_s + 6] + weights[w_s + 3] + weights[w_s + 2]; + axiscoords[a_s + 2] = weights[w_s + 15] + weights[w_s + 14] + weights[w_s + 13] + weights[w_s + 12] + weights[w_s + 7] + weights[w_s + 6] + weights[w_s + 5] + weights[w_s + 4]; + axiscoords[a_s + 3] = weights[w_s + 15] + weights[w_s + 14] + weights[w_s + 13] + weights[w_s + 12] + weights[w_s + 11] + weights[w_s + 10] + weights[w_s + 9] + weights[w_s + 8]; + } +} + +function T1_Get_MM_Var(face) +{ + var mmvar = new FT_MM_Var(); + var mmaster = new FT_Multi_Master(); + var axiscoords = CreateIntArray(FT_Common.T1_MAX_MM_AXIS); + var blend = face.blend; + + var error = T1_Get_Multi_Master(face, mmaster); + if (error != 0) + return { err: error, mm : null }; + + var _num_axis = master.num_axis; + mmvar.axis = new Array(_num_axis); + for (var i = 0; i < _num_axis; i++) + mmvar.axis[i] = new FT_Var_Axis(); + + mmvar.num_axis = mmaster.num_axis; + mmvar.num_designs = mmaster.num_designs; + mmvar.num_namedstyles = 0xFFFFFFFF; /* Does not apply */ + /* Point to axes after MM_Var struct */ + mmvar.namedstyle = null; + + for (var i = 0 ; i < _num_axis; i++) + { + var _axis = mmvar.axis[i]; + + _axis.name = mmaster.axis[i].name; + _axis.minimum = (mmaster.axis[i].minimum << 16); + _axis.maximum = (mmaster.axis[i].maximum << 16); + _axis.def = parseInt((_axis.minimum + _axis.maximum) / 2); + /* Does not apply. But this value is in range */ + _axis.strid = 0xFFFFFFFF; + _axis.tag = 0xFFFFFFFF; + + if (_axis.name == "Weight") + _axis.tag = 2003265652;//FT_MAKE_TAG("w", "g", "h", "t"); + else if (_axis.name == "Width") + _axis.tag = 2003072104;//FT_MAKE_TAG("w", "d", "t", "h"); + else if (_axis.name == "OpticalSize") + _axis.tag = 1869640570;//FT_MAKE_TAG("o", "p", "s", "z"); + } + + if (blend.num_designs == (1 << blend.num_axis)) + { + mm_weights_unmap(blend.default_weight_vector, 0, axiscoords, 0, blend.num_axis); + + for (var i = 0; i < _num_axis; i++) + mmvar.axis[i].def = mm_axis_unmap(blend.design_map[i], axiscoords[i]); + } + + return { err : 0, mm : mmvar }; +} + +function T1_Set_MM_Blend(face, num_coords, coords) +{ + var blend = face.blend; + if (blend != null) + return FT_Common.FT_Err_Invalid_Argument; + + if (blend != null && blend.num_axis == num_coords) + { + for (var n = 0; n < blend.num_designs; n++) + { + var result = 0x10000; /* 1.0 fixed */ + + for (var m = 0; m < blend.num_axis; m++) + { + var factor = coords[m]; + if (factor < 0) + factor = 0; + if (factor > 0x10000) + factor = 0x10000; + if (( n & (1 << m)) == 0) + factor = 0x10000 - factor; + + result = FT_MulFix(result, factor); + } + blend.weight_vector[n] = result; + } + } + + return 0; +} + +function T1_Set_MM_Design(face, num_coords, coords) +{ + var blend = face.blend; + if (null == blend || blend.num_axis != num_coords) + return FT_Common.FT_Err_Invalid_Argument; + + /* compute the blend coordinates through the blend design map */ + var final_blends = CreateIntArray(FT_Common.T1_MAX_MM_DESIGNS); + + for (var n = 0; n < blend.num_axis; n++) + { + var design = coords[n]; + var the_blend = 0; + var map = blend.design_map[n]; + var designs = map.design_points; + var blends = map.blend_points; + var before = -1, after = -1; + + var is_go_to_found = 0; + for (var p = 0; p < map.num_points; p++) + { + var p_design = designs[p]; + + /* exact match? */ + if (design == p_design) + { + the_blend = blends[p]; + is_go_to_found = 1; + break; + } + + if (design < p_design) + { + after = p; + break; + } + + before = p; + } + + if (0 == is_go_to_found) + { + /* now interpolate if necessary */ + if (before < 0) + the_blend = blends[0]; + else if ( after < 0 ) + the_blend = blends[map.num_points - 1]; + else + the_blend = FT_MulDiv(design - designs[before], blends[after] - blends[before], designs[after] - designs[before]); + } + + final_blends[n] = the_blend; + } + + var error = T1_Set_MM_Blend(face, num_coords, final_blends); + return error; +} + +function T1_Set_Var_Design(face, num_coords, coords) +{ + var lcoords = CreateIntArray(4); /* maximum axis count is 4 */ + + if (num_coords <= 4 && num_coords > 0) + { + for (var i = 0; i < num_coords; i++) + lcoords[i] = FT_RoundFix(coords[i]) >> 16; + var error = T1_Set_MM_Design(face, num_coords, lcoords); + return error; + } + return FT_Common.FT_Err_Invalid_Argument; +} + +function T1_Done_Blend(face) +{ + face.blend = null; +} + +function t1_parse_blend_axis_types(face, loader) +{ + var axis_tokens = new Array(FT_Common.T1_MAX_MM_AXIS); + for (var i = 0; i < FT_Common.T1_MAX_MM_AXIS; i++) + axis_tokens[i] = new T1_TokenRec(); + + /* take an array of objects */ + var num_axis = loader.parser.root.funcs.to_token_array(loader.parser.root, axis_tokens, FT_Common.T1_MAX_MM_AXIS); + if (num_axis < 0) + { + loader.parser.root.error = FT_Common.FT_Err_Ignore; + return; + } + if (num_axis == 0 || num_axis > FT_Common.T1_MAX_MM_AXIS) + { + loader.parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + /* allocate blend if necessary */ + var error = t1_allocate_blend(face, 0, num_axis); + if (error != 0) + { + loader.parser.root.error = error; + return; + } + + var blend = face.blend; + + /* each token is an immediate containing the name of the axis */ + for (var n = 0; n < num_axis; n++) + { + var token = axis_tokens[n]; + + /* skip first slash, if any */ + if (token.start.data[token.start.pos] == FT_Common.SYMBOL_CONST_BS) + token.start.pos++; + + var len = token.limit - token.start.pos; + if (len == 0) + { + loader.parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + blend.axis_names[n] = ""; + for (var i = 0; i < len; i++) + { + blend.axis_names[n] += String.fromCharCode(token.start.data[token.start.pos + n]); + } + } + + loader.parser.root.error = error; +} + +function t1_parse_blend_design_positions(face, loader) +{ + var design_tokens = new Array(FT_Common.T1_MAX_MM_DESIGNS); + for (var i = 0; i < FT_Common.T1_MAX_MM_DESIGNS; i++) + design_tokens[i] = new T1_TokenRec(); + + var parser = loader.parser; + + /* get the array of design tokens -- compute number of designs */ + var num_designs = parser.root.funcs.to_token_array(parser.root, design_tokens, FT_Common.T1_MAX_MM_DESIGNS); + if (num_designs < 0) + { + parser.root.error = FT_Common.FT_Err_Ignore; + return; + } + if (num_designs == 0 || num_designs > FT_Common.T1_MAX_MM_DESIGNS) + { + loader.parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + var old_cursor = parser.root.cursor; + var old_limit = parser.root.limit; + + var blend = face.blend; + var num_axis = 0; /* make compiler happy */ + + var error = 0; + for (var n = 0; n < num_designs; n++) + { + /* read axis/coordinates tokens */ + var token = design_tokens[n]; + parser.root.cursor = token.start.pos; + parser.root.limit = token.limit; + + var axis_tokens = new Array(FT_Common.T1_MAX_MM_AXIS); + for (var i = 0; i < FT_Common.T1_MAX_MM_AXIS; i++) + axis_tokens[i] = new T1_TokenRec(); + + var n_axis = parser.root.funcs.to_token_array(parser.root, axis_tokens, FT_Common.T1_MAX_MM_AXIS); + + if (n == 0) + { + if (n_axis <= 0 || n_axis > FT_Common.T1_MAX_MM_AXIS) + { + loader.parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + num_axis = n_axis; + error = t1_allocate_blend( face, num_designs, num_axis ); + if (error != 0) + { + loader.parser.root.error = error; + return; + } + blend = face.blend; + } + else if (n_axis != num_axis) + { + loader.parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + /* now read each axis token into the design position */ + for (var axis = 0; axis < n_axis; axis++) + { + var token2 = axis_tokens[axis]; + + parser.root.cursor = token2.start.pos; + parser.root.limit = token2.limit; + blend.design_pos[n][axis] = parser.root.funcs.to_fixed(parser, 0); + } + } + + parser.root.cursor = old_cursor; + parser.root.limit = old_limit; + + parser.root.error = error; +} + +function t1_parse_blend_design_map(face, loader) +{ + var parser = loader.parser; + + var axis_tokens = new Array(FT_Common.T1_MAX_MM_AXIS); + for (var i = 0; i < FT_Common.T1_MAX_MM_AXIS; i++) + axis_tokens[i] = new T1_TokenRec(); + + var num_axis = parser.root.funcs.to_token_array(parser.root, axis_tokens, FT_Common.T1_MAX_MM_AXIS); + + if (num_axis < 0) + { + parser.root.error = FT_Common.FT_Err_Ignore; + return; + } + if (num_axis == 0 || num_axis > FT_Common.T1_MAX_MM_AXIS) + { + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + var old_cursor = parser.root.cursor; + var old_limit = parser.root.limit; + + var error = t1_allocate_blend(face, 0, num_axis); + if (error != 0) + { + parser.root.error = error; + return; + } + var blend = face.blend; + + /* now read each axis design map */ + for (var n = 0; n < num_axis; n++) + { + var map = blend.design_map[n]; + + var point_tokens = new Array(FT_Common.T1_MAX_MM_MAP_POINTS); + for (var i = 0; i < FT_Common.T1_MAX_MM_MAP_POINTS; i++) + point_tokens[i] = new T1_TokenRec(); + + var axis_token = axis_tokens[n]; + + parser.root.cursor = axis_token.start.pos; + parser.root.limit = axis_token.limit; + + var num_points = parser.root.funcs.to_token_array(parser.root, point_tokens, FT_Common.T1_MAX_MM_MAP_POINTS); + + if (num_points <= 0 || num_points > FT_Common.T1_MAX_MM_MAP_POINTS) + { + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + /* allocate design map data */ + map.design_points = CreateIntArray(num_points); + map.blend_points = CreateIntArray(num_points); + map.num_points = num_points; + + for (var p = 0; p < num_points; p++) + { + var point_token = point_tokens[p]; + + /* don't include delimiting brackets */ + parser.root.cursor = point_token.start.pos + 1; + parser.root.limit = point_token.limit - 1; + + map.design_points[p] = parser.root.funcs.to_int(parser.root); + map.blend_points [p] = parser.root.funcs.to_fixed(parser.root, 0); + } + } + + parser.root.cursor = old_cursor; + parser.root.limit = old_limit; + + parser.root.error = error; +} + +function t1_parse_weight_vector(face, loader) +{ + var design_tokens = new Array(FT_Common.T1_MAX_MM_DESIGNS); + for (var i = 0; i < FT_Common.T1_MAX_MM_DESIGNS; i++) + design_tokens[i] = new T1_TokenRec(); + + var parser = loader.parser; + var blend = face.blend; + var num_designs = parser.root.funcs.to_token_array(parser.root, design_tokens, FT_Common.T1_MAX_MM_DESIGNS); + if (num_designs < 0) + { + parser.root.error = FT_Common.FT_Err_Ignore; + return; + } + if (num_designs == 0 || num_designs > FT_Common.T1_MAX_MM_DESIGNS) + { + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + var error = 0; + if (blend == null || blend.num_designs == 0) + { + error = t1_allocate_blend(face, num_designs, 0 ); + if (error != 0) + { + parser.root.error = error; + return; + } + blend = face.blend; + } + else if (blend.num_designs != num_designs) + { + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + var old_cursor = parser.root.cursor; + var old_limit = parser.root.limit; + + for (var n = 0; n < num_designs; n++) + { + var token = design_tokens[n]; + parser.root.cursor = token.start.pos; + parser.root.limit = token.limit; + + var _temp = parser.root.funcs.to_fixed(parser.root, 0); + blend.weight_vector[n] = _temp; + blend.weight_vector[blend.default_weight_vector + n] = _temp; + } + + parser.root.cursor = old_cursor; + parser.root.limit = old_limit; + + parser.root.error = error; +} + +function t1_parse_buildchar(face, loader) +{ + face.len_buildchar = loader.parser.funcs.to_fixed_array(loader.parser.root, 0, null, 0); +} + +function t1_load_keyword(face, loader, field) +{ + var blend = face.blend; + if (blend != null && blend.num_designs == 0) + blend = null; + + /* if the keyword has a dedicated callback, call it */ + if (field.type == FT_Common.T1_FIELD_TYPE_CALLBACK) + { + field.reader(face, loader); + return loader.parser.root.error; + } + + var max_objects = 0; + var arr = null; + + /* now, the keyword is either a simple field, or a table of fields; */ + /* we are now going to take care of it */ + switch (field.location) + { + case FT_Common.T1_FIELD_LOCATION_FONT_INFO: + if (blend != null) + { + arr = blend.font_infos; + max_objects = blend.num_designs; + } + else + { + arr = new Array(1); + arr[0] = face.type1.font_info; + max_objects = 0; + } + break; + + case FT_Common.T1_FIELD_LOCATION_FONT_EXTRA: + arr = new Array(1); + arr[0] = face.type1.font_extra; + max_objects = 0; + break; + + case FT_Common.T1_FIELD_LOCATION_PRIVATE: + if (blend != null) + { + arr = blend.privates; + max_objects = blend.num_designs; + } + else + { + arr = new Array(1); + arr[0] = face.type1.private_dict; + max_objects = 0; + } + break; + + case FT_Common.T1_FIELD_LOCATION_BBOX: + if (blend != null) + { + arr = blend.bboxes; + max_objects = blend.num_designs; + } + else + { + arr = new Array(1); + arr[0] = face.type1.font_bbox; + max_objects = 0; + } + break; + + case FT_Common.T1_FIELD_LOCATION_LOADER: + arr = new Array(1); + arr[0] = loader; + max_objects = 0; + break; + + case FT_Common.T1_FIELD_LOCATION_FACE: + arr = new Array(1); + arr[0] = face; + max_objects = 0; + break; + + case FT_Common.T1_FIELD_LOCATION_BLEND: + arr = new Array(1); + arr[0] = loader; + max_objects = 0; + break; + + default: + arr = new Array(1); + arr[0] = face.type1; + max_objects = 0; + } + + if (field.type == FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY || field.type == FT_Common.T1_FIELD_TYPE_FIXED_ARRAY) + return loader.parser.root.funcs.load_field_table(loader.parser.root, field, arr, max_objects, 0); + + return loader.parser.root.funcs.load_field(loader.parser.root, field, arr, max_objects, 0); +} + +function t1_parse_private(face, loader) +{ + loader.keywords_encountered |= FT_Common.T1_PRIVATE; +} + +function _t1_read_binary_data(parser) +{ + var ret = { size: 0, base: null, err: 0 }; + + var limit = parser.root.limit; + + /* the binary data has one of the following formats */ + /* */ + /* `size' [white*] RD white ....... ND */ + /* `size' [white*] -| white ....... |- */ + /* */ + + parser.root.funcs.skip_spaces(parser.root); + var cur = dublicate_pointer(parser.root.cursor); + + if (cur.pos < limit && (cur.data[cur.pos] >= FT_Common.SYMBOL_CONST_0) && (cur.data[cur.pos] <= FT_Common.SYMBOL_CONST_9)) + { + var s = parser.root.funcs.to_int(parser.root); + parser.root.funcs.skip_PS_token(parser.root); + + /* there is only one whitespace char after the */ + /* `RD' or `-|' token */ + ret.base = dublicate_pointer(parser.root.cursor); + ret.base.pos += 1; + + if (s >= 0 && s < (limit - ret.base.pos)) + { + parser.root.cursor.pos += (s + 1); + ret.size = s; + ret.err = (parser.root.error == 0) ? 1 : 0; + return ret; + } + } + + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return ret; +} + +function t1_parse_font_matrix(face, loader) +{ + var parser = loader.parser; + var matrix = face.type1.font_matrix; + var offset = face.type1.font_offset; + + var temp = CreateIntArray(6); + + var result = parser.root.funcs.to_fixed_array(parser.root, 6, temp, 3); + + if (result < 0) + { + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + var temp_scale = Math.abs(temp[3]); + + if (temp_scale == 0) + { + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + /* Set Units per EM based on FontMatrix values. We set the value to */ + /* 1000 / temp_scale, because temp_scale was already multiplied by */ + /* 1000 (in t1_tofixed, from psobjs.c). */ + face.units_per_EM = (FT_DivFix(1000 * 0x10000, temp_scale) >> 16); + + /* we need to scale the values by 1.0/temp_scale */ + if (temp_scale != 0x10000) + { + temp[0] = FT_DivFix(temp[0], temp_scale); + temp[1] = FT_DivFix(temp[1], temp_scale); + temp[2] = FT_DivFix(temp[2], temp_scale); + temp[4] = FT_DivFix(temp[4], temp_scale); + temp[5] = FT_DivFix(temp[5], temp_scale); + temp[3] = temp[3] < 0 ? -0x10000 : 0x10000; + } + + matrix.xx = temp[0]; + matrix.yx = temp[1]; + matrix.xy = temp[2]; + matrix.yy = temp[3]; + + /* note that the offsets must be expressed in integer font units */ + offset.x = temp[4] >> 16; + offset.y = temp[5] >> 16; +} + +function t1_parse_encoding(face, loader) +{ + var parser = loader.parser; + var limit = parser.root.limit; + + var memory = parser.root.memory; + + var psaux = face.psaux; + + parser.root.funcs.skip_spaces(parser.root); + var cur = dublicate_pointer(parser.root.cursor); + if (cur.pos >= limit) + { + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + /* if we have a number or `[', the encoding is an array, */ + /* and we must load it now */ + var _cur_v = cur.data[cur.pos]; + if ((_cur_v >= FT_Common.SYMBOL_CONST_0 && _cur_v <= FT_Common.SYMBOL_CONST_9) || _cur_v == FT_Common.SYMBOL_CONST_LS2) + { + var encode = face.type1.encoding; + var count, n; + var char_table = loader.encoding_table; + var only_immediates = 0; + + /* read the number of entries in the encoding; should be 256 */ + if (_cur_v == FT_Common.SYMBOL_CONST_LS2) + { + count = 256; + only_immediates = 1; + parser.root.cursor.pos++; + } + else + count = parser.root.funcs.to_int(parser.root); + + parser.root.funcs.skip_spaces(parser.root); + if (parser.root.cursor.pos >= limit) + return; + + /* we use a T1_Table to store our charnames */ + loader.num_chars = encode.num_chars = count; + + encode.char_index = CreateUIntArray(count); + encode.char_name = CreateNullArray(count); + var error = psaux.ps_table_funcs.init(char_table, count, memory); + if (error != 0) + { + parser.root.error = error; + return; + } + + /* We need to `zero' out encoding_table.elements */ + for (n = 0; n < count; n++) + { + var notdef_name = memory.Alloc(8); + notdef_name.data[0] = FT_Common.SYMBOL_CONST_POINT; + notdef_name.data[1] = FT_Common.SYMBOL_CONST_n; + notdef_name.data[2] = FT_Common.SYMBOL_CONST_o; + notdef_name.data[3] = FT_Common.SYMBOL_CONST_t; + notdef_name.data[4] = FT_Common.SYMBOL_CONST_d; + notdef_name.data[5] = FT_Common.SYMBOL_CONST_e; + notdef_name.data[6] = FT_Common.SYMBOL_CONST_f; + notdef_name.data[7] = FT_Common.SYMBOL_CONST_S0; + + char_table.funcs.add(char_table, n, notdef_name, 8) + } + + /* Now we need to read records of the form */ + /* */ + /* ... charcode /charname ... */ + /* */ + /* for each entry in our table. */ + /* */ + /* We simply look for a number followed by an immediate */ + /* name. Note that this ignores correctly the sequence */ + /* that is often seen in type1 fonts: */ + /* */ + /* 0 1 255 { 1 index exch /.notdef put } for dup */ + /* */ + /* used to clean the encoding array before anything else. */ + /* */ + /* Alternatively, if the array is directly given as */ + /* */ + /* /Encoding [ ... ] */ + /* */ + /* we only read immediates. */ + + n = 0; + parser.root.funcs.skip_spaces(parser.root); + + while (parser.root.cursor.pos < limit) + { + cur.pos = parser.root.cursor.pos; + + /* we stop when we encounter a `def' or `]' */ + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_d && cur.pos + 3 < limit) + { + if (cur.data[cur.pos + 1] == FT_Common.SYMBOL_CONST_e && cur.data[cur.pos + 2] == FT_Common.SYMBOL_CONST_f && IS_PS_DELIM(cur.data[cur.pos + 3])) + { + cur.pos += 3; + break; + } + } + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_RS2) + { + cur.pos++; + break; + } + + /* check whether we've found an entry */ + if (((cur.data[cur.pos] >= FT_Common.SYMBOL_CONST_0) && (cur.data[cur.pos] <= FT_Common.SYMBOL_CONST_9)) || (only_immediates == 1)) + { + var charcode = 0; + + if (only_immediates == 1) + charcode = n; + else + { + charcode = parser.root.funcs.to_int(parser.root); + parser.root.funcs.skip_spaces(parser.root); + } + + cur.pos = parser.root.cursor.pos; + + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_BS && (cur.pos + 2) < limit && (n < count)) + { + cur.pos++; + parser.root.cursor.pos = cur.pos; + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.error != 0) + return; + + var len = parser.root.cursor.pos - cur.pos; + + parser.root.error = char_table.funcs.add(char_table, charcode, cur, len + 1); + if (parser.root.error != 0) + return; + char_table.elements[charcode][len] = FT_Common.SYMBOL_CONST_S0; + + n++; + } + else if (only_immediates == 1) + { + /* Since the current position is not updated for */ + /* immediates-only mode we would get an infinite loop if */ + /* we don't do anything here. */ + /* */ + /* This encoding array is not valid according to the type1 */ + /* specification (it might be an encoding for a CID type1 */ + /* font, however), so we conclude that this font is NOT a */ + /* type1 font. */ + parser.root.error = FT_Common.FT_Err_Unknown_File_Format; + return; + } + } + else + { + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.error != 0) + return; + } + + parser.root.funcs.skip_spaces(parser.root); + } + + face.type1.encoding_type = FT_Common.T1_ENCODING_TYPE_ARRAY; + parser.root.cursor.pos = cur.pos; + } + else + { + if (cur.pos + 17 < limit && _strncmp_data(cur, "StandardEncoding", 16) == 0) + face.type1.encoding_type = FT_Common.T1_ENCODING_TYPE_STANDARD; + else if (cur + 15 < limit && _strncmp_data(cur, "ExpertEncoding", 14) == 0) + face.type1.encoding_type = FT_Common.T1_ENCODING_TYPE_EXPERT; + else if (cur + 18 < limit && _strncmp_data(cur, "ISOLatin1Encoding", 17) == 0) + face.type1.encoding_type = FT_Common.T1_ENCODING_TYPE_ISOLATIN1; + else + parser.root.error = FT_Common.FT_Err_Ignore; + } +} + +function t1_parse_subrs(face, loader) +{ + var parser = loader.parser; + var table = loader.subrs; + var memory = parser.root.memory; + + var psaux = face.psaux; + parser.root.funcs.skip_spaces(parser.root); + + /* test for empty array */ + if (parser.root.cursor.pos < parser.root.limit && parser.root.cursor.data[parser.root.cursor.pos] == FT_Common.SYMBOL_CONST_LS2) + { + parser.root.funcs.skip_PS_token(parser.root); + parser.root.funcs.skip_spaces(parser.root); + + if (parser.root.cursor.pos >= parser.root.limit || parser.root.cursor.data[parser.root.cursor.pos] != FT_Common.SYMBOL_CONST_RS2) + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + var num_subrs = parser.root.funcs.to_int(parser.root); + + /* position the parser right before the `dup' of the first subr */ + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.error != 0) + return; + + parser.root.funcs.skip_spaces(parser.root); + + var error = 0; + /* initialize subrs array -- with synthetic fonts it is possible */ + /* we get here twice */ + if (loader.num_subrs == 0) + { + error = psaux.ps_table_funcs.init(table, num_subrs, memory); + if (error != 0) + { + parser.root.error = 0; + return; + } + } + + /* the format is simple: */ + /* */ + /* `index' + binary data */ + /* */ + for (;;) + { + /* If the next token isn't `dup' we are done. */ + if (_strncmp_data(parser.root.cursor, "dup", 3) != 0) + break; + + parser.root.funcs.skip_PS_token(parser.root); + + var idx = parser.root.funcs.to_int(parser.root); + + var ret = _t1_read_binary_data(parser); + + var size = ret.size; + var base = ret.base; + if (0 == ret.err) + return; + + /* The binary string is followed by one token, e.g. `NP' */ + /* (bound to `noaccess put') or by two separate tokens: */ + /* `noaccess' & `put'. We position the parser right */ + /* before the next `dup', if any. */ + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.error != 0) + return; + + parser.root.funcs.skip_spaces(parser.root); + + if (_strncmp_data(parser.root.cursor, "put", 3) == 0) + { + parser.root.funcs.skip_PS_token(parser.root); + parser.root.funcs.skip_spaces(parser); + } + + /* with synthetic fonts it is possible we get here twice */ + if (loader.num_subrs != 0) + continue; + + /* some fonts use a value of -1 for lenIV to indicate that */ + /* the charstrings are unencoded */ + /* */ + /* thanks to Tom Kacvinsky for pointing this out */ + /* */ + if (face.type1.private_dict.lenIV >= 0) + { + /* some fonts define empty subr records -- this is not totally */ + /* compliant to the specification (which says they should at */ + /* least contain a `return'), but we support them anyway */ + if (size < face.type1.private_dict.lenIV) + { + parser.root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + /* t1_decrypt() shouldn't write to base -- make temporary copy */ + var temp = memory.Alloc(size); + for (var i = 0; i < size; i++) + { + temp.data[i] = base.data[base.pos + i]; + } + + psaux.t1_decrypt(temp, size, 4330); + size -= face.type1.private_dict.lenIV; + + temp.pos += face.type1.private_dict.lenIV; + error = table.funcs.add(table, idx, temp, size); + + temp = null; + } + else + error = table.funcs.add(table, idx, base, size); + + if (error != 0) + { + parser.root.error = error; + } + } + + if (loader.num_subrs == 0) + loader.num_subrs = num_subrs; +} + +function t1_parse_charstrings(face, loader) +{ + var parser = loader.parser; + var code_table = loader.charstrings; + var name_table = loader.glyph_names; + var swap_table = loader.swap_table; + var memory = parser.root.memory; + + var psaux = face.psaux; + + var limit = parser.root.limit; + var n = 0; + var notdef_index = 0; + var notdef_found = 0; + + var num_glyphs = parser.root.funcs.to_int(parser.root); + /* some fonts like Optima-Oblique not only define the /CharStrings */ + /* array but access it also */ + if (num_glyphs == 0 || parser.root.error != 0) + return; + + /* initialize tables, leaving space for addition of .notdef, */ + /* if necessary, and a few other glyphs to handle buggy */ + /* fonts which have more glyphs than specified. */ + + /* for some non-standard fonts like `Optima' which provides */ + /* different outlines depending on the resolution it is */ + /* possible to get here twice */ + + var root = parser.root; + + var error = 0; + if (loader.num_glyphs == 0) + { + error = psaux.ps_table_funcs.init(code_table, num_glyphs + 1 + FT_Common.TABLE_EXTEND, memory); + if (error != 0) + { + root.error = error; + return; + } + + error = psaux.ps_table_funcs.init(name_table, num_glyphs + 1 + FT_Common.TABLE_EXTEND, memory); + if (error != 0) + { + root.error = error; + return; + } + + /* Initialize table for swapping index notdef_index and */ + /* index 0 names and codes (if necessary). */ + error = psaux.ps_table_funcs.init(swap_table, 4, memory); + if (error != 0) + { + root.error = error; + return error; + } + } + + n = 0; + + for (;;) + { + /* the format is simple: */ + /* `/glyphname' + binary data */ + + root.funcs.skip_spaces(root); + + var cur = dublicate_pointer(root.cursor); + if (cur.pos >= limit) + break; + + /* we stop when we find a `def' or `end' keyword */ + if (cur.pos + 3 < limit && IS_PS_DELIM(cur.data[cur.pos + 3])) + { + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_d && cur.data[cur.pos + 1] == FT_Common.SYMBOL_CONST_e && cur.data[cur.pos + 2] == FT_Common.SYMBOL_CONST_f) + { + /* There are fonts which have this: */ + /* */ + /* /CharStrings 118 dict def */ + /* Private begin */ + /* CharStrings begin */ + /* ... */ + /* */ + /* To catch this we ignore `def' if */ + /* no charstring has actually been */ + /* seen. */ + if (n != 0) + break; + } + + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_e && cur.data[cur.pos + 1] == FT_Common.SYMBOL_CONST_n && cur.data[cur.pos + 2] == FT_Common.SYMBOL_CONST_d) + break; + } + + root.funcs.skip_PS_token(root); + if (root.error != 0) + return; + + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_BS) + { + if (cur.pos + 1 >= limit) + { + root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + cur.pos++; /* skip `/' */ + var len = root.cursor.pos - cur.pos; + + var ret = _t1_read_binary_data(parser); + + if (ret.err == 0) + return; + + var size = ret.size; + var base = ret.base; + + /* for some non-standard fonts like `Optima' which provides */ + /* different outlines depending on the resolution it is */ + /* possible to get here twice */ + if (loader.num_glyphs != 0) + continue; + + error = name_table.funcs.add(name_table, n, cur, len + 1); + if (error != 0) + { + root.error = error; + return; + } + + /* add a trailing zero to the name table */ + name_table.elements[n].data[name_table.elements[n].pos + len] = FT_Common.SYMBOL_CONST_S0; + + /* record index of /.notdef */ + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_POINT && _strcmp_data(".notdef", name_table.elements[n]) == 0) + { + notdef_index = n; + notdef_found = 1; + } + + if (face.type1.private_dict.lenIV >= 0 && (n < (num_glyphs + FT_Common.TABLE_EXTEND))) + { + if (size <= face.type1.private_dict.lenIV) + { + root.error = FT_Common.FT_Err_Invalid_File_Format; + return; + } + + /* t1_decrypt() shouldn't write to base -- make temporary copy */ + var temp = memory.Alloc(size); + + for (var i = 0; i < size; i++) + temp.data[i] = base.data[base.pos + i]; + + + psaux.t1_decrypt(temp, size, 4330); + size -= face.type1.private_dict.lenIV; + + temp.pos += face.type1.private_dict.lenIV; + error = code_table.funcs.add(code_table, n, temp, size); + + temp = null; + } + else + error = code_table.funcs.add(code_table, n, base, size); + + if (error != 0) + { + root.error = error; + return; + } + + n++; + } + } + + loader.num_glyphs = n; + + /* if /.notdef is found but does not occupy index 0, do our magic. */ + if (notdef_found != 0 && _strcmp_data(".notdef", name_table.elements[0])) + { + /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */ + /* name and code entries to swap_table. Then place notdef_index */ + /* name and code entries into swap_table. Then swap name and code */ + /* entries at indices notdef_index and 0 using values stored in */ + /* swap_table. */ + + /* Index 0 name */ + error = swap_table.funcs.add(swap_table, 0, name_table.elements[0], name_table.lengths[0]); + if (error != 0) + { + root.error = error; + return; + } + + /* Index 0 code */ + error = swap_table.funcs.add(swap_table, 1, code_table.elements[0], code_table.lengths[0]); + if (error != 0) + { + root.error = error; + return; + } + + /* Index notdef_index name */ + error = swap_table.funcs.add(swap_table, 2, name_table.elements[notdef_index], name_table.lengths[notdef_index]); + if (error != 0) + { + root.error = error; + return; + } + + /* Index notdef_index code */ + error = swap_table.funcs.add(swap_table, 3, code_table.elements[notdef_index], code_table.lengths[notdef_index]); + if (error != 0) + { + root.error = error; + return; + } + + error = name_table.funcs.add(name_table, notdef_index, swap_table.elements[0], swap_table.lengths[0]); + if (error != 0) + { + root.error = error; + return; + } + + error = code_table.funcs.add(code_table, notdef_index, swap_table.elements[1], swap_table.lengths[1]); + if (error != 0) + { + root.error = error; + return; + } + + error = name_table.funcs.add(name_table, 0, swap_table.elements[2], swap_table.lengths[2]); + if (error != 0) + { + root.error = error; + return; + } + + error = code_table.funcs.add(code_table, 0, swap_table.elements[3], swap_table.lengths[3]); + if (error != 0) + { + root.error = error; + return; + } + } + else if (notdef_found == 0) + { + /* notdef_index is already 0, or /.notdef is undefined in */ + /* charstrings dictionary. Worry about /.notdef undefined. */ + /* We take index 0 and add it to the end of the table(s) */ + /* and add our own /.notdef glyph to index 0. */ + + /* 0 333 hsbw endchar */ + var notdef_glyph = memory.Alloc(5); + notdef_glyph.data[0] = 0x8B; + notdef_glyph.data[1] = 0xF7; + notdef_glyph.data[2] = 0xE1; + notdef_glyph.data[3] = 0x0D; + notdef_glyph.data[4] = 0x0E; + + var notdef_name = memory.Alloc(8); + notdef_name.data[0] = FT_Common.SYMBOL_CONST_POINT; + notdef_name.data[1] = FT_Common.SYMBOL_CONST_n; + notdef_name.data[2] = FT_Common.SYMBOL_CONST_o; + notdef_name.data[3] = FT_Common.SYMBOL_CONST_t; + notdef_name.data[4] = FT_Common.SYMBOL_CONST_d; + notdef_name.data[5] = FT_Common.SYMBOL_CONST_e; + notdef_name.data[6] = FT_Common.SYMBOL_CONST_f; + notdef_name.data[7] = FT_Common.SYMBOL_CONST_S0; + + error = swap_table.funcs.add(swap_table, 0, name_table.elements[0], name_table.lengths[0]); + if (error != 0) + { + root.error = error; + return; + } + + error = swap_table.funcs.add(swap_table, 1, code_table.elements[0], code_table.lengths[0]); + if (error != 0) + { + root.error = error; + return; + } + + error = name_table.funcs.add(name_table, 0, notdef_name, 8); + if (error != 0) + { + root.error = error; + return; + } + + error = code_table.funcs.add(code_table, 0, notdef_glyph, 5); + if (error != 0) + { + root.error = error; + return; + } + + error = name_table.funcs.add(name_table, n, swap_table.elements[0], swap_table.lengths[0]); + if (error != 0) + { + root.error = error; + return; + } + + error = code_table.funcs.add(code_table, n, swap_table.elements[1], swap_table.lengths[1]); + if (error != 0) + { + root.error = error; + return; + } + + /* we added a glyph. */ + loader.num_glyphs += 1; + } +} + +function _t1_parse_dict(face, loader, base, size) +{ + var parser = loader.parser; + var have_integer = 0; + + parser.root.cursor = dublicate_pointer(base); + parser.root.limit = base.pos + size; + parser.root.error = 0; + + var limit = parser.root.limit; + + parser.root.funcs.skip_spaces(parser.root); + + var start_binary = dublicate_pointer(parser.root.cursor); + + while (parser.root.cursor.pos < limit) + { + var cur = dublicate_pointer(parser.root.cursor); + + /* look for `eexec' */ + if (IS_PS_TOKEN(cur, limit, "eexec", 6) == 1) + break; + + /* look for `closefile' which ends the eexec section */ + else if (IS_PS_TOKEN(cur, limit, "closefile", 10) == 1) + break; + + /* in a synthetic font the base font starts after a */ + /* `FontDictionary' token that is placed after a Private dict */ + else if (IS_PS_TOKEN(cur, limit, "FontDirectory", 14) == 1) + { + if (loader.keywords_encountered & FT_Common.T1_PRIVATE) + loader.keywords_encountered |= FT_Common.T1_FONTDIR_AFTER_PRIVATE; + parser.root.cursor.pos += 13; + } + /* check whether we have an integer */ + else if (cur.data[cur.pos] >= FT_Common.SYMBOL_CONST_0 && cur.data[cur.pos] <= FT_Common.SYMBOL_CONST_9) + { + start_binary.pos = cur.pos; + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.error != 0) + return parser.root.error; + have_integer = 1; + } + + /* in valid Type 1 fonts we don't see `RD' or `-|' directly */ + /* since those tokens are handled by parse_subrs and */ + /* parse_charstrings */ + else if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_R && ((cur.pos + 6) < limit) && cur.data[cur.pos + 1] == FT_Common.SYMBOL_CONST_D && have_integer == 1) + { + parser.root.cursor.pos = start_binary.pos; + + var ret = _t1_read_binary_data(parser); + if (0 == ret.err) + return FT_Common.FT_Err_Invalid_File_Format; + have_integer = 0; + } + else if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_MATH_MINUS && ((cur.pos + 6) < limit) && cur.data[cur.pos + 1] == FT_Common.SYMBOL_CONST_LOGOR && have_integer == 1) + { + var ret = _t1_read_binary_data(parser); + if (0 == ret.err) + return FT_Common.FT_Err_Invalid_File_Format; + have_integer = 0; + } + + /* look for immediates */ + else if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_BS && ((cur.pos + 2) < limit)) + { + cur.pos++; + + parser.root.cursor.pos = cur.pos; + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.error != 0) + return parser.root.error; + + var len = parser.root.cursor.pos - cur.pos; + + if (len > 0 && len < 22 && parser.root.cursor.pos < limit) + { + /* now compare the immediate name to the keyword table */ + for (var _i = 0; _i < t1_keywords.length; _i++) + { + var keyword = t1_keywords[_i]; + var name = keyword.ident; + if (name == null) + break; + + if (cur.data[cur.pos] == name.charCodeAt(0) && len == name.length && _strncmp_data(cur, name, len) == 0) + { + var dict = ((loader.keywords_encountered & FT_Common.T1_PRIVATE) != 0) ? FT_Common.T1_FIELD_DICT_PRIVATE : FT_Common.T1_FIELD_DICT_FONTDICT; + + if ((dict & keyword.dict) == 0) + { + break; + } + + if (((loader.keywords_encountered & FT_Common.T1_FONTDIR_AFTER_PRIVATE) == 0) || (name == "CharStrings")) + { + parser.root.error = t1_load_keyword(face, loader, keyword); + if (parser.root.error != 0) + { + if (parser.root.error == FT_Common.FT_Err_Ignore) + parser.root.error = 0; + else + return parser.root.error; + } + } + break; + } + } + } + + have_integer = 0; + } + else + { + parser.root.funcs.skip_PS_token(parser.root); + if (parser.root.error != 0) + return parser.root.error; + have_integer = 0; + } + + parser.root.funcs.skip_spaces(parser.root); + } + + return parser.root.error; +} + +function t1_init_loader(loader, face) +{ + loader.clear(); + + loader.num_glyphs = 0; + loader.num_chars = 0; + + /* initialize the tables -- simply set their `init' field to 0 */ + loader.encoding_table.init = 0; + loader.charstrings.init = 0; + loader.glyph_names.init = 0; + loader.subrs.init = 0; + loader.swap_table.init = 0; + loader.fontdata = 0; + loader.keywords_encountered = 0; +} + +function t1_done_loader(loader) +{ + var parser = loader.parser; + + /* finalize tables */ + if (loader.encoding_table.funcs.release != null) + loader.encoding_table.funcs.release(loader.encoding_table); + + if (loader.charstrings.funcs.release != null) + loader.charstrings.funcs.release(loader.charstrings); + + if (loader.glyph_names.funcs.release != null) + loader.glyph_names.funcs.release(loader.glyph_names); + + if (loader.swap_table.funcs.release != null) + loader.swap_table.funcs.release(loader.swap_table); + + if (loader.subrs.funcs.release != null) + loader.subrs.funcs.release(loader.subrs); + + /* finalize parser */ + T1_Finalize_Parser(parser); +} + +function T1_Open_Face(face) +{ + var loader = new T1_Loader(); + var type1 = face.type1; + var priv = type1.private_dict; + + var psaux = face.psaux; + + t1_init_loader(loader, face); + + /* default values */ + face.ndv_idx = -1; + face.cdv_idx = -1; + face.len_buildchar = 0; + + priv.blue_shift = 7; + priv.blue_fuzz = 1; + priv.lenIV = 4; + priv.expansion_factor = parseInt(0.06 * 0x10000); + priv.blue_scale = parseInt(0.039625 * 0x10000 * 1000); + + var parser = loader.parser; + var error = T1_New_Parser(parser, face.stream, face.memory, psaux); + if (error != 0) + { + t1_done_loader(loader); + return error; + } + + error = _t1_parse_dict(face, loader, parser.base_dict, parser.base_len); + if (error != 0) + { + t1_done_loader(loader); + return error; + } + + error = T1_Get_Private_Dict(parser, psaux); + if (error != 0) + { + t1_done_loader(loader); + return error; + } + + error = _t1_parse_dict(face, loader, parser.private_dict, parser.private_len); + if (error != 0) + { + t1_done_loader(loader); + return error; + } + + /* ensure even-ness of `num_blue_values' */ + priv.num_blue_values &= 0xFFFFFFFE; + + //#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + + if (face.blend != null && face.blend.num_default_design_vector != 0 && face.blend.num_default_design_vector != face.blend.num_axis) + { + face.blend.num_default_design_vector = 0; + } + + /* the following can happen for MM instances; we then treat the */ + /* font as a normal PS font */ + if (face.blend != null && (face.blend.num_designs == 0 || face.blend.num_axis == 0)) + T1_Done_Blend(face); + + /* another safety check */ + if (face.blend != null) + { + for (var i = 0; i < face.blend.num_axis; i++) + { + if (face.blend.design_map[i].num_points == 0) + { + T1_Done_Blend(face); + break; + } + } + } + + if (face.blend != null) + { + if (face.len_buildchar > 0) + { + face.buildchar = CreateIntArray(face.len_buildchar); + } + } + else + { + face.len_buildchar = 0; + } + + //#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ + + /* now, propagate the subrs, charstrings, and glyphnames tables */ + /* to the Type1 data */ + type1.num_glyphs = loader.num_glyphs; + + if (loader.subrs.init != null) + { + loader.subrs.init = null; + type1.num_subrs = loader.num_subrs; + type1.subrs_block = loader.subrs.block; + type1.subrs = loader.subrs.elements; + type1.subrs_len = loader.subrs.lengths; + } + + if (loader.charstrings.init == 0) + { + error = FT_Common.FT_Err_Invalid_File_Format; + } + + loader.charstrings.init = 0; + type1.charstrings_block = loader.charstrings.block; + type1.charstrings = loader.charstrings.elements; + type1.charstrings_len = loader.charstrings.lengths; + + /* we copy the glyph names `block' and `elements' fields; */ + /* the `lengths' field must be released later */ + type1.glyph_names_block = loader.glyph_names.block; + type1.glyph_names = loader.glyph_names.elements; + + for (var ii = 0; ii < type1.num_glyphs; ii++) + { + var s = ""; + var p = type1.glyph_names[ii]; + var indC = 0; + while (true) + { + var _c = p.data[p.pos + indC]; + indC++; + + if (_c == FT_Common.SYMBOL_CONST_S0) + break; + + s += String.fromCharCode(_c); + } + type1.glyph_names[ii] = s; + } + + loader.glyph_names.block = 0; + loader.glyph_names.elements = 0; + + /* we must now build type1.encoding when we have a custom array */ + if (type1.encoding_type == FT_Common.T1_ENCODING_TYPE_ARRAY) + { + /* OK, we do the following: for each element in the encoding */ + /* table, look up the index of the glyph having the same name */ + /* the index is then stored in type1.encoding.char_index, and */ + /* the name to type1.encoding.char_name */ + + var min_char = 0; + var max_char = 0; + + var charcode = 0; + for ( ; charcode < loader.encoding_table.max_elems; charcode++) + { + type1.encoding.char_index[charcode] = 0; + type1.encoding.char_name[charcode] = ".notdef"; + + var char_name = loader.encoding_table.elements[charcode]; + if (char_name != null) + { + for (var idx = 0; idx < type1.num_glyphs; idx++) + { + var glyph_name = type1.glyph_names[idx]; + if (_strncmp_data(char_name, glyph_name, glyph_name.length) == 0) + { + type1.encoding.char_index[charcode] = idx; + type1.encoding.char_name[charcode] = glyph_name; + + /* Change min/max encoded char only if glyph name is */ + /* not /.notdef */ + if (".notdef" != glyph_name) + { + if (charcode < min_char) + min_char = charcode; + if (charcode >= max_char) + max_char = charcode + 1; + } + break; + } + } + } + } + + type1.encoding.code_first = min_char; + type1.encoding.code_last = max_char; + type1.encoding.num_chars = loader.num_chars; + } + + t1_done_loader(loader); + return error; +} + +/******************************************************************************/ +// tokens +/******************************************************************************/ +var t1_keywords = new Array(45); +// PS_FontInfoRec +t1_keywords[0] = create_t1_field4("version", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.version = val}, undefined); +t1_keywords[1] = create_t1_field4("Notice", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.notice = val}, undefined); +t1_keywords[2] = create_t1_field4("FullName", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.full_name = val}, undefined); +t1_keywords[3] = create_t1_field4("FamilyName", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.family_name = val}, undefined); +t1_keywords[4] = create_t1_field4("Weight", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_STRING, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.weight = val}, undefined); +t1_keywords[5] = create_t1_field4("ItalicAngle", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.italic_angle = val}, undefined); +t1_keywords[6] = create_t1_field4("isFixedPitch", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_BOOL, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.is_fixed_pitch = val}, undefined); +t1_keywords[7] = create_t1_field4("UnderlinePosition", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.underline_position = val}, undefined); +t1_keywords[8] = create_t1_field4("UnderlineThickness", FT_Common.T1_FIELD_LOCATION_FONT_INFO, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.underline_thickness = val}, undefined); + +// PS_FontExtraRec +t1_keywords[9] = create_t1_field4("FSType", FT_Common.T1_FIELD_LOCATION_FONT_EXTRA, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.fs_type = val}, undefined); + +// PS_PrivateRec +t1_keywords[10] = create_t1_field4("UniqueID", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_FONTDICT | FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.unique_id = val}, undefined); +t1_keywords[11] = create_t1_field4("lenIV", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.lenIV = val}, undefined); +t1_keywords[12] = create_t1_field4("LanguageGroup", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.language_group = val}, undefined); +t1_keywords[13] = create_t1_field4("password", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.password = val}, undefined); + +t1_keywords[14] = create_t1_field4("BlueScale", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_FIXED_1000, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.blue_scale = val}, undefined); +t1_keywords[15] = create_t1_field4("BlueShift", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.blue_shift = val}, undefined); +t1_keywords[16] = create_t1_field4("BlueFuzz", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.blue_fuzz = val}, undefined); + +t1_keywords[17] = create_t1_field5("BlueValues", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 14, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.blue_values[f.offset] = val}, function(obj, val, f) { obj.num_blue_values = val}); +t1_keywords[18] = create_t1_field5("OtherBlues", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 10, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.other_blues[f.offset] = val}, function(obj, val, f) { obj.num_other_blues = val}); +t1_keywords[19] = create_t1_field5("FamilyBlues", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 14, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.family_blues[f.offset] = val}, function(obj, val, f) { obj.num_family_blues = val}); +t1_keywords[20] = create_t1_field5("FamilyOtherBlues", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 10, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.family_other_blues[f.offset] = val}, function(obj, val, f) { obj.num_family_other_blues = val}); + +t1_keywords[21] = create_t1_field5("StdHW", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 1, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.standard_width[0] = val}, undefined); +t1_keywords[22] = create_t1_field5("StdVW", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 1, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.standard_height[0] = val}, undefined); +t1_keywords[23] = create_t1_field5("MinFeature", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 2, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.min_feature[f.offset] = val}, undefined); + +t1_keywords[24] = create_t1_field5("StemSnapH", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 12, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.snap_widths[f.offset] = val}, function(obj, val, f) { obj.num_snap_widths = val}); +t1_keywords[25] = create_t1_field5("StemSnapV", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY, 12, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.snap_heights[f.offset] = val}, function(obj, val, f) { obj.num_snap_heights = val}); + +t1_keywords[26] = create_t1_field4("ForceBold", FT_Common.T1_FIELD_LOCATION_PRIVATE, FT_Common.T1_FIELD_TYPE_BOOL, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.force_bold = val}, undefined); + +// T1_FontRec +t1_keywords[27] = create_t1_field4("FontName", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_KEY, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.font_name = val}, undefined); +t1_keywords[28] = create_t1_field4("PaintType", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.paint_type = val}, undefined); +t1_keywords[29] = create_t1_field4("FontType", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.font_type = val}, undefined); +t1_keywords[30] = create_t1_field4("StrokeWidth", FT_Common.T1_FIELD_LOCATION_FONT_DICT, FT_Common.T1_FIELD_TYPE_FIXED, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.stroke_width = val}, undefined); + +// FT_BBox +t1_keywords[31] = create_t1_field4("FontBBox", FT_Common.T1_FIELD_LOCATION_BBOX, FT_Common.T1_FIELD_TYPE_BBOX, FT_Common.T1_FIELD_DICT_FONTDICT, undefined, undefined); + +// T1_FaceRec +t1_keywords[32] = create_t1_field4("NDV", FT_Common.T1_FIELD_LOCATION_FACE, FT_Common.T1_FIELD_TYPE_INTEGER, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.ndv_idx = val}, undefined); +t1_keywords[33] = create_t1_field4("CDV", FT_Common.T1_FIELD_LOCATION_FACE, FT_Common.T1_FIELD_TYPE_FIXED, FT_Common.T1_FIELD_DICT_PRIVATE, function(obj, val, f) { obj.cdv_idx = val}, undefined); + +// PS_BlendRec +t1_keywords[34] = create_t1_field5("CDV", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_FIXED, FT_Common.T1_MAX_MM_DESIGNS, FT_Common.T1_FIELD_DICT_FONTDICT, function(obj, val, f) { obj.default_design_vector[f.offset] = val}, function(obj, val, f) { obj.num_default_design_vector = val}); + +// callbacks +t1_keywords[35] = create_t1_field("FontMatrix", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_font_matrix, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_FONTDICT, undefined, undefined); +t1_keywords[36] = create_t1_field("Encoding", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_encoding, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_FONTDICT, undefined, undefined); +t1_keywords[37] = create_t1_field("Subrs", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_subrs, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_PRIVATE, undefined, undefined); +t1_keywords[38] = create_t1_field("CharStrings", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_charstrings, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_PRIVATE, undefined, undefined); +t1_keywords[39] = create_t1_field("Private", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_private, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_FONTDICT, undefined, undefined); + +t1_keywords[40] = create_t1_field("BlendDesignPositions", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_blend_design_positions, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_FONTDICT, undefined, undefined); +t1_keywords[41] = create_t1_field("BlendDesignMap", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_blend_design_map, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_FONTDICT, undefined, undefined); +t1_keywords[42] = create_t1_field("BlendAxisTypes", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_blend_axis_types, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_FONTDICT, undefined, undefined); +t1_keywords[43] = create_t1_field("WeightVector", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_weight_vector, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_FONTDICT, undefined, undefined); +t1_keywords[44] = create_t1_field("BuildCharArray", FT_Common.T1_FIELD_LOCATION_BLEND, FT_Common.T1_FIELD_TYPE_CALLBACK, t1_parse_buildchar, 0, -1, 0, 0, FT_Common.T1_FIELD_DICT_PRIVATE, undefined, undefined); + +/******************************************************************************/ +// driver +/******************************************************************************/ + +function t1_get_glyph_name(face, glyph_index, buffer, buffer_max) +{ + return face.type1.glyph_names[glyph_index]; + //_mem_strcpyn1(buffer, face.type1.glyph_names[glyph_index], buffer_max); + //return 0; +} + +function t1_get_name_index(face, glyph_name) +{ + var _count = face.type1.num_glyphs; + for (var i = 0; i < _count; i++) + { + if (face.type1.glyph_names[i] == glyph_name) + return i; + } + return 0; +} + +var t1_service_glyph_dict = new FT_Service_GlyphDictRec(t1_get_glyph_name, t1_get_name_index); + +function t1_get_ps_name(face) +{ + return face.type1.font_name; +} +var t1_service_ps_name = new FT_Service_PsFontNameRec(t1_get_ps_name); + +var t1_service_multi_masters = new FT_Service_MultiMastersRec(T1_Get_Multi_Master, T1_Set_MM_Design, T1_Set_MM_Blend, T1_Get_MM_Var, T1_Set_Var_Design); + +function t1_ps_get_font_info(face) +{ + FT_Error = 0; + return face.type1.font_info.CreateDublicate(); +} +function t1_ps_get_font_extra(face) +{ + FT_Error = 0; + return face.type1.font_extra.CreateDublicate(); +} +function t1_ps_has_glyph_names(face) +{ + return 1; +} +function t1_ps_get_font_private(face) +{ + FT_Error = 0; + return face.type1.private_dict; +} + +function t1_ps_get_font_value(face, key, idx) +{ + var retval = -1; + var value = null; + var type1 = face.type1; + + switch (key) + { + case FT_Common.PS_DICT_FONT_TYPE: + value = type1.font_type; + break; + + case FT_Common.PS_DICT_FONT_MATRIX: + switch (idx) + { + case 0: + value = type1.font_matrix.xx; + break; + case 1: + value = type1.font_matrix.xy; + break; + case 2: + value = type1.font_matrix.yx; + break; + case 3: + value = type1.font_matrix.yy; + break; + } + break; + + case FT_Common.PS_DICT_FONT_BBOX: + switch (idx) + { + case 0: + value = type1.font_bbox.xMin; + break; + case 1: + value = type1.font_bbox.yMin; + break; + case 2: + value = type1.font_bbox.xMax; + break; + case 3: + value = type1.font_bbox.yMax; + break; + } + break; + + case FT_Common.PS_DICT_PAINT_TYPE: + value = type1.paint_type; + break; + + case FT_Common.PS_DICT_FONT_NAME: + value = type1.font_name; + break; + + case FT_Common.PS_DICT_UNIQUE_ID: + value = type1.private_dict.unique_id; + break; + + case FT_Common.PS_DICT_NUM_CHAR_STRINGS: + value = type1.num_glyphs; + break; + + case FT_Common.PS_DICT_CHAR_STRING_KEY: + if (idx < type1.num_glyphs) + { + value = type1.glyph_names[idx]; + } + break; + + case FT_Common.PS_DICT_CHAR_STRING: + if (idx < type1.num_glyphs) + { + value = type1.charstrings[idx]; + } + break; + + case FT_Common.PS_DICT_ENCODING_TYPE: + value = type1.encoding_type; + break; + + case FT_Common.PS_DICT_ENCODING_ENTRY: + if (type1.encoding_type == FT_Common.T1_ENCODING_TYPE_ARRAY && idx < type1.encoding.num_chars) + { + value = type1.encoding.char_name[idx]; + } + break; + + case FT_Common.PS_DICT_NUM_SUBRS: + value = type1.num_subrs; + break; + + case FT_Common.PS_DICT_SUBR: + if (idx < type1.num_subrs) + { + value = type1.subrs[idx]; + } + break; + + case FT_Common.PS_DICT_STD_HW: + value = type1.private_dict.standard_width[0]; + break; + + case FT_Common.PS_DICT_STD_VW: + value = type1.private_dict.standard_height[0]; + break; + + case FT_Common.PS_DICT_NUM_BLUE_VALUES: + value = type1.private_dict.num_blue_values; + break; + + case FT_Common.PS_DICT_BLUE_VALUE: + if (idx < type1.private_dict.num_blue_values) + { + value = type1.private_dict.blue_values[idx]; + } + break; + + case FT_Common.PS_DICT_BLUE_SCALE: + value = type1.private_dict.blue_scale; + break; + + case FT_Common.PS_DICT_BLUE_FUZZ: + value = type1.private_dict.blue_fuzz; + break; + + case FT_Common.PS_DICT_BLUE_SHIFT: + value = type1.private_dict.blue_shift; + break; + + case FT_Common.PS_DICT_NUM_OTHER_BLUES: + value = type1.private_dict.num_other_blues; + break; + + case FT_Common.PS_DICT_OTHER_BLUE: + if (idx < type1.private_dict.num_other_blues) + { + value = type1.private_dict.other_blues[idx]; + } + break; + + case FT_Common.PS_DICT_NUM_FAMILY_BLUES: + value = type1.private_dict.num_family_blues; + break; + + case FT_Common.PS_DICT_FAMILY_BLUE: + if (idx < type1.private_dict.num_family_blues) + { + value = type1.private_dict.family_blues[idx]; + } + break; + + case FT_Common.PS_DICT_NUM_FAMILY_OTHER_BLUES: + value = type1.private_dict.num_family_other_blues; + break; + + case FT_Common.PS_DICT_FAMILY_OTHER_BLUE: + if (idx < type1.private_dict.num_family_other_blues) + { + value = type1.private_dict.family_other_blues[idx]; + } + break; + + case FT_Common.PS_DICT_NUM_STEM_SNAP_H: + value = type1.private_dict.num_snap_widths; + break; + + case FT_Common.PS_DICT_STEM_SNAP_H: + if (idx < type1.private_dict.num_snap_widths) + { + value = type1.private_dict.snap_widths[idx]; + } + break; + + case FT_Common.PS_DICT_NUM_STEM_SNAP_V: + value = type1.private_dict.num_snap_heights; + break; + + case FT_Common.PS_DICT_STEM_SNAP_V: + if (idx < type1.private_dict.num_snap_heights) + { + value = type1.private_dict.snap_heights[idx]; + } + break; + + case FT_Common.PS_DICT_RND_STEM_UP: + value = type1.private_dict.round_stem_up; + break; + + case FT_Common.PS_DICT_FORCE_BOLD: + value = type1.private_dict.force_bold; + break; + + case FT_Common.PS_DICT_MIN_FEATURE: + value = type1.private_dict.min_feature[idx]; + break; + + case FT_Common.PS_DICT_LEN_IV: + value = type1.private_dict.lenIV; + break; + + case FT_Common.PS_DICT_PASSWORD: + value = type1.private_dict.password; + break; + + case FT_Common.PS_DICT_LANGUAGE_GROUP: + value= type1.private_dict.language_group; + break; + + case FT_Common.PS_DICT_IS_FIXED_PITCH: + value = type1.font_info.is_fixed_pitch; + break; + + case FT_Common.PS_DICT_UNDERLINE_POSITION: + value = type1.font_info.underline_position; + break; + + case FT_Common.PS_DICT_UNDERLINE_THICKNESS: + value = type1.font_info.underline_thickness; + break; + + case FT_Common.PS_DICT_FS_TYPE: + value = type1.font_extra.fs_type; + break; + + case FT_Common.PS_DICT_VERSION: + value = type1.font_info.version; + break; + + case FT_Common.PS_DICT_NOTICE: + value = type1.font_info.notice; + break; + + case FT_Common.PS_DICT_FULL_NAME: + value = type1.font_info.full_name; + break; + + case FT_Common.PS_DICT_FAMILY_NAME: + value = type1.font_info.family_name; + break; + + case FT_Common.PS_DICT_WEIGHT: + value = type1.font_info.weight; + break; + + case FT_Common.PS_DICT_ITALIC_ANGLE: + value = type1.font_info.italic_angle; + break; + + default: + break; + } + + return retval; +} + +var t1_service_ps_info = new FT_Service_PsInfoRec(t1_ps_get_font_info, t1_ps_get_font_extra, t1_ps_has_glyph_names, t1_ps_get_font_private, t1_ps_get_font_value); +var t1_service_kerning = new FT_Service_KerningRec(T1_Get_Track_Kerning); + +var t1_services = new Array(6); +t1_services[0] = new FT_ServiceDescRec(FT_SERVICE_ID_POSTSCRIPT_FONT_NAME,t1_service_ps_name); +t1_services[1] = new FT_ServiceDescRec(FT_SERVICE_ID_GLYPH_DICT,t1_service_glyph_dict); +t1_services[2] = new FT_ServiceDescRec(FT_SERVICE_ID_XF86_NAME,FT_XF86_FORMAT_TYPE_1); +t1_services[3] = new FT_ServiceDescRec(FT_SERVICE_ID_POSTSCRIPT_INFO,t1_service_ps_info); +t1_services[4] = new FT_ServiceDescRec(FT_SERVICE_ID_KERNING,t1_service_kerning); +t1_services[5] = new FT_ServiceDescRec(FT_SERVICE_ID_MULTI_MASTERS,t1_service_multi_masters); + +function Get_Interface(driver, t1_interface) +{ + return ft_service_list_lookup(t1_services, t1_interface); +} + +function Get_Kerning(face, left_glyph, right_glyph, kerning) +{ + kerning.x = 0; + kerning.y = 0; + + if (face.afm_data != null) + T1_Get_Kerning(face.afm_data, left_glyph, right_glyph, kerning); + + return 0; +} + +function T1_Driver_Class() +{ + this.flags = 0x501; + this.name = "type1"; + this.version = 0x10000; + this.requires = 0x20000; + + this.module_interface = null; + + this.init = T1_Driver_Init; + this.done = T1_Driver_Done; + this.get_interface = Get_Interface; + + this.face_object_size = 0; + this.size_object_size = 0; + this.slot_object_size = 0; + + this.init_face = T1_Face_Init; + this.done_face = T1_Face_Done; + + this.init_size = T1_Size_Init; + this.done_size = T1_Size_Done; + + this.init_slot = T1_GlyphSlot_Init; + this.done_slot = T1_GlyphSlot_Done; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.set_char_sizes = ft_stub_set_char_sizes; + this.set_pixel_sizes = ft_stub_set_pixel_sizes; + //#endif + + this.load_glyph = T1_Load_Glyph; + + this.get_kerning = Get_Kerning; + this.attach_file = T1_Read_Metrics; + this.get_advances = T1_Get_Advances; + + this.request_size = T1_Size_Request; + this.select_size = null; +} + +function T1_Driver() +{ + this.clazz = null; // FT_Module_Class + this.library = null; // FT_Library + this.memory = null; // FT_Memory + this.generic = null; // FT_Generic + + this.clazz = new T1_Driver_Class(); + this.faces_list = []; + this.extensions = null; + this.glyph_loader = null; + + this.open_face = function(stream, face_index) + { + FT_Error = 0; + var face = new T1_Face(); + var internal = new FT_Face_Internal(); + + face.driver = this; + face.memory = this.memory; + face.stream = stream; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + face.internal = internal; + face.internal.incremental_interface = null; + //#endif + + var err1 = this.clazz.init_face(stream, face, face_index); + + if (err1 != 0) + { + face = null; + FT_Error = err1; + return null; + } + + var err2 = find_unicode_charmap(face); + if (err2 != 0 && err2 != FT_Common.FT_Err_Invalid_CharMap_Handle) + { + face = null; + FT_Error = err2; + return null; + } + + FT_Error = 0; + return face; + } +} + +function create_t1_driver(library) +{ + var driver = new T1_Driver(); + driver.library = library; + driver.memory = library.Memory; + + driver.clazz = new T1_Driver_Class(); + return driver; +} \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/drivers/truetype.js b/Common/FontsFreeType/Private/FreeType/drivers/truetype.js new file mode 100644 index 0000000000000000000000000000000000000000..e22d074a16d862a8b2c060f1ca486442d661432f --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/drivers/truetype.js @@ -0,0 +1,3787 @@ +/******************************************************************************/ +// classes +/******************************************************************************/ +function TT_Size_Metrics() +{ + this.x_ratio = 0; + this.y_ratio = 0; + + this.ppem = 0; + this.ratio = 0; + this.scale = 0; + + this.compensations = new Array(4); + + this.valid = 0; + + this.rotated = 0; + this.stretched = 0; +} +TT_Size_Metrics.prototype = +{ + Copy : function(src) + { + this.x_ratio = src.x_ratio; + this.y_ratio = src.y_ratio; + + this.ppem = src.ppem; + this.ratio = src.ratio; + this.scale = src.scale; + + this.compensations[0] = src.compensations[0]; + this.compensations[1] = src.compensations[1]; + this.compensations[2] = src.compensations[2]; + this.compensations[3] = src.compensations[3]; + + this.valid = src.valid; + + this.rotated = src.rotated; + this.stretched = src.stretched; + } +}; + +function TT_DefRecord() +{ + this.range = 0; /* in which code range is it located? */ + this.start = 0; /* where does it start? */ + this.end = 0; /* where does it end? */ + this.opc = 0; /* function #, or instruction code */ + this.active = false; /* is it active? */ + this.inline_delta = false; /* is function that defines inline delta? */ +} + +function TT_CodeRange() +{ + this.base = null; + this.size = 0; +} + +function TT_SizeRec() +{ + this.face = null; + this.generic = null; + this.metrics = new FT_Size_Metrics(); + this.internal = null; + + /* we have our own copy of metrics so that we can modify */ + /* it without affecting auto-hinting (when used) */ + this._metrics = new FT_Size_Metrics(); + + this.ttmetrics = new TT_Size_Metrics(); + + this.strike_index = 0; + //#ifdef TT_USE_BYTECODE_INTERPRETER + this.num_function_defs = 0; /* number of function definitions */ + this.max_function_defs = 0; + this.function_defs = null; /* table of function definitions */ + + this.num_instruction_defs = 0; /* number of ins. definitions */ + this.max_instruction_defs = 0; + this.instruction_defs = null; /* table of ins. definitions */ + + this.max_func = 0; + this.max_ins = 0; + + this.codeRangeTable = new Array(3); + this.codeRangeTable[0] = new TT_CodeRange(); + this.codeRangeTable[1] = new TT_CodeRange(); + this.codeRangeTable[2] = new TT_CodeRange(); + + this.GS = new TT_GraphicsState(); + + this.cvt_size = 0; /* the scaled control value table */ + this.cvt = null; + + this.storage_size = 0; /* The storage area is now part of */ + this.storage = null; /* the instance */ + + this.twilight = new TT_GlyphZoneRec(); /* The instance's twilight zone */ + + /* debugging variables */ + + /* When using the debugger, we must keep the */ + /* execution context tied to the instance */ + /* object rather than asking it on demand. */ + this.debug = false; + this.context = null; + + this.bytecode_ready = false; + this.cvt_ready = false; + this.ttfautohinted = false; + //#endif +} +function TT_Face() +{ + this.num_faces = 0; + this.face_index = 0; + + this.face_flags = 0; + this.style_flags = 0; + + this.num_glyphs = 0; + + this.family_name = ""; + this.style_name = ""; + + this.num_fixed_sizes = 0; + this.available_sizes = null; + + this.num_charmaps = 0; + this.charmaps = null; + + this.generic = new FT_Generic(); + + /*# The following member variables (down to `underline_thickness') */ + /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ + /*# for bitmap fonts. */ + this.bbox = new FT_BBox(); + + this.units_per_EM = 0; + this.ascender = 0; + this.descender = 0; + this.height = null; + + this.max_advance_width = 0; + this.max_advance_height = 0; + + this.underline_position = 0; + this.underline_thickness = 0; + + this.glyph = null; + this.size = null; + this.charmap = null; + + /*@private begin */ + this.driver = null; + this.memory = null; + this.stream = null; + + this.sizes_list = []; + + this.autohint = []; + this.extensions = null; + + this.internal = null; + /*@private end */ + + this.ttc_header = new TTC_HeaderRec(); + + this.format_tag = 0; + this.num_tables = 0; + this.dir_tables = null; + + this.header = new TT_Header(); + this.horizontal = new TT_HoriHeader(); + + this.max_profile = new TT_MaxProfile(); + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.max_components = 0; + //#endif + + this.vertical_info = false; + this.vertical = new TT_VertHeader(); + + this.num_names = 0; + this.name_table = new TT_NameTableRec(); + + this.os2 = new TT_OS2(); + this.postscript = new TT_Postscript(); + + this.cmap_table = null; + this.cmap_size = 0; + + this.sfnt = null; + this.psnames = null; + + // horizontal device metrics + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.hdmx = new TT_HdmxRec(); + //#endif + + // grid-fitting and scaling table + this.gasp = new TT_Gasp(); // the `gasp' table + + // PCL 5 tabl + this.pclt = new TT_PCLT(); + + // embedded bitmaps support + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.num_sbit_strikes = 0; + this.sbit_strikes = null; + //#endif + + this.num_sbit_scales = 0; + this.sbit_scales = null; + + // postscript names table + this.postscript_names = new TT_Post_NamesRec(); + + // TrueType-specific fields (ignored by the OTF-Type2 driver) + // the glyph locations + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.num_locations_stub = 0; + this.glyph_locations_stub = null; + //#endif + + // the font program, if any + this.font_program_size = 0; + this.font_program = null; + + // the cvt program, if any + this.cvt_program_size = 0; + this.cvt_program = null; + + // the original, unscaled, control value table + this.cvt_size = 0; + this.cvt = null; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + // the format 0 kerning table, if any + this.num_kern_pairs = 0; + this.kern_table_index = 0; + this.kern_pairs = []; + //#endif + + // A pointer to the bytecode interpreter to use. This is also + // used to hook the debugger for the `ttdebug' utility. + this.interpreter = null; + + //#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + // Use unpatented hinting only. + this.unpatented_hinting = false; + //#endif + + // Other tables or fields. This is used by derivative formats like OpenType. + this.extra = new FT_Generic(); + + this.postscript_name = ""; + + // since version 2.1.8, but was originally placed after + // `glyph_locations_stub' + this.glyf_len = 0; + + // since version 2.1.8, but was originally placed before `extra' + //#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + this.doblend = 0; + this.blend = null; + //#endif + + // since version 2.2 + + this.horz_metrics = null; + this.horz_metrics_size = 0; + + this.vert_metrics = null; + this.vert_metrics_size = 0; + + this.num_locations = 0; // in broken TTF, gid > 0xFFFF + this.glyph_locations = null; + + this.hdmx_table = null; + this.hdmx_table_size = 0; + this.hdmx_record_count = 0; + this.hdmx_record_size = 0; + this.hdmx_record_sizes = null; + + this.sbit_table = null; + this.sbit_table_size = 0; + this.sbit_num_strikes = 0; + + this.kern_table = null; + this.kern_table_size = 0; + this.num_kern_tables = 0; + this.kern_avail_bits = 0; + this.kern_order_bits = 0; + + //#ifdef TT_CONFIG_OPTION_BDF + this.bdf = new TT_BDFRec(); + //#endif + + // since 2.3.0 + this.horz_metrics_offset = 0; + this.vert_metrics_offset = 0; + + this.goto_table = null; + this.access_glyph_frame = null; + this.forget_glyph_frame = null; + this.read_glyph_header = null; + this.read_simple_glyph = null; + this.read_composite_glyph = null; +} +/******************************************************************************/ +// gxvar +/******************************************************************************/ +function GX_AVarCorrespondenceRec() +{ + this.fromCoord = 0; + this.toCoord = 0; +} +function GX_AVarSegmentRec() +{ + this.pairCount = 0; + this.correspondence = null; +} +function GX_BlendRec() +{ + this.num_axis = 0; + this.normalizedcoords = null; + + this.mmvar = null; + this.mmvar_len = 0; + + this.avar_checked = 0; + this.avar_segment = null; + + this.tuplecount = 0; + this.tuplecoords = null; + + this.gv_glyphcnt = 0; + this.glyphoffsets = null; +} +function GX_GVar_Head() +{ + this.version = 0; + this.axisCount = 0; + this.globalCoordCount = 0; + this.offsetToCoord = 0; + this.glyphCount = 0; + this.flags = 0; + this.offsetToData = 0; +} +function GX_FVar_Head() +{ + this.version = 0; + this.offsetToData = 0; + this.countSizePairs = 0; + this.axisCount = 0; + this.axisSize = 0; + this.instanceCount = 0; + this.instanceSize = 0; +} +function GX_FVar_Axis() +{ + this.axisTag = 0; + this.minValue = 0; + this.defaultValue = 0; + this.maxValue = 0; + this.flags = 0; + this.nameID = 0; +} +function ft_var_readpackedpoints(stream) +{ + var points = null; + var point_cnt = 0; + + var n; + var runcnt; + var j; + var first; + point_cnt = n = stream.GetUChar(); + + if (n == 0) + return {points:points, point_cnt:point_cnt}; + + if (n & 0x80) + n = stream.GetUChar() | ((n & 0x7F) << 8); + + points = new Array(n); + var i = 0; + while (i < n) + { + runcnt = stream.GetUChar(); + if (runcnt & 0x80) + { + runcnt = runcnt & 0x7F; + first = points[i++] = stream.GetUShort(); + + if (runcnt < 1 || i + runcnt >= n) + return {points:points, point_cnt:point_cnt}; + + /* first point not included in runcount */ + for (j = 0; j < runcnt; ++j) + { + first += stream.GetUShort(); + points[i++] = first & 0xFFFF; + } + } + else + { + first = points[i++] = stream.GetUChar(); + + if (runcnt < 1 || i + runcnt >= n) + return {points:points, point_cnt:point_cnt}; + + for (j = 0; j < runcnt; ++j) + { + first += stream.GetUChar(); + points[i++] = first & 0xFFFF; + } + } + } + + return {points:points, point_cnt:point_cnt}; +} +function ft_var_readpackeddeltas(stream, delta_cnt) +{ + var runcnt; + var j; + + var deltas = new Array(delta_cnt); + var i = 0; + while (i < delta_cnt) + { + runcnt = stream.GetUChar(); + if ((runcnt & 128)!=0) + { + for (j = 0;j <= (runcnt & 63) && i < delta_cnt;j++) + deltas[i++] = 0; + } + else if ((runcnt & 64)!=0) + { + for (j = 0;j <= (runcnt & 63) && i < delta_cnt;j++) + deltas[i++] = stream.GetShort(); + } + else + { + for (j = 0;j <= (runcnt & 63) && i < delta_cnt;j++) + deltas[i++] = stream.GetChar(); + } + + if (j <= (runcnt & 63)) + { + deltas = null; + return null; + } + } + return deltas; +} +function ft_var_load_avar(face) +{ + var stream = face.stream; + var blend = face.blend; + var segment = null; + var i, j; + + blend.avar_checked = 1; + var table_len = face.goto_table(face, FT_Common.TTAG_avar, stream); + var error = FT_Error; + if (error != 0) + return; + + error = stream.EnterFrame(table_len); + if (error != 0) + return; + + var version = stream.GetLong(); + var axisCount = stream.GetLong(); + + if (version != 0x00010000 || axisCount != blend.mmvar.num_axis) + { + stream.ExitFrame(); + return; + } + + blend.avar_segment = new Array(axisCount); + for (i=0;i<axisCount;i++) + blend.avar_segment[i] = new GX_AVarSegmentRec(); + + for (i = 0; i < axisCount; ++i) + { + segment = blend.avar_segment[i]; + segment.pairCount = stream.GetUShort(); + segment.correspondence = new Array(segment.pairCount); + + for (j = 0; j < segment.pairCount; ++j) + { + segment.correspondence[j].fromCoord = stream.GetShort() << 2; + segment.correspondence[j].toCoord = stream.GetShort() << 2; + } + } + stream.ExitFrame(); +} +function ft_var_load_gvar(face) +{ + var stream = face.stream; + var blend = face.blend; + var error = 0; + var i, j; + var gvar_head = new GX_GVar_Head(); + + var table_len = face.goto_table(face, FT_Common.TTAG_gvar, stream); + error = FT_Error; + if (error != 0) + return error; + + var gvar_start = stream.pos; + + error = stream.EnterFrame(20); + if (error != 0) + return error; + + gvar_head.version = stream.GetLong(); + gvar_head.axisCount = stream.GetUShort(); + gvar_head.globalCoordCount = stream.GetUShort(); + gvar_head.offsetToCoord = stream.GetULong(); + gvar_head.glyphCount = stream.GetUShort(); + gvar_head.flags = stream.GetUShort(); + gvar_head.offsetToData = stream.GetULong(); + + stream.ExitFrame(); + + blend.tuplecount = gvar_head.globalCoordCount; + blend.gv_glyphcnt = gvar_head.glyphCount; + var offsetToData = gvar_start + gvar_head.offsetToData; + + if (gvar_head.version != 0x00010000 || gvar_head.axisCount != blend.mmvar.num_axis) + return FT_Common.FT_Err_Invalid_Table; + + blend.glyphoffsets = new Array(blend.gv_glyphcnt + 1); + if ((gvar_head.flags & 1) != 0) + { + error = stream.EnterFrame((blend.gv_glyphcnt + 1)*4); + if (error != 0) + return error; + + for (i = 0; i <= blend.gv_glyphcnt; ++i) + blend.glyphoffsets[i] = offsetToData + stream.GetLong(); + + stream.ExitFrame(); + } + else + { + error = stream.EnterFrame((blend.gv_glyphcnt + 1)*2); + if (error != 0) + return error; + + for (i = 0; i <= blend.gv_glyphcnt; ++i) + blend.glyphoffsets[i] = offsetToData + stream.GetUShort() * 2; + + stream.ExitFrame(); + } + + if (blend.tuplecount != 0) + { + blend.tuplecoords = new Array(gvar_head.axisCount * blend.tuplecount); + error = stream.Seek(gvar_start + gvar_head.offsetToCoord); + if (error != 0) + return error; + + error = stream.EnterFrame(blend.tuplecount * gvar_head.axisCount * 2); + + for (i = 0; i < blend.tuplecount; i++) + { + for (j=0;j<gvar_head.axisCount;j++) + { + blend.tuplecoords[i * gvar_head.axisCount + j] = stream.GetShort() << 2; + } + } + + stream.ExitFrame(); + } + return error; +} +function ft_var_apply_tuple(blend, tupleIndex, tuple_coords, im_start_coords, im_end_coords) +{ + var apply = 0x10000; + var temp = 0; + var i = 0; + var c = blend.num_axis; + var nn = blend.normalizedcoords; + for (; i < c;i++) + { + if (tuple_coords[i] == 0) + continue; + else if (nn[i] == 0 || (nn[i] < 0 && tuple_coords[i] > 0) || (nn[i] > 0 && tuple_coords[i] < 0)) + { + apply = 0; + break; + } + else if (0 == (tupleIndex & FT_Common.GX_TI_INTERMEDIATE_TUPLE)) + apply = FT_MulDiv(apply, nn[i] > 0 ? nn[i] : -nn[i], 0x10000); + + else if (nn[i] <= im_start_coords[i] || nn[i] >= im_end_coords[i]) + { + apply = 0; + break; + } + else if (nn[i] < tuple_coords[i]) + { + temp = FT_MulDiv(nn[i] - im_start_coords[i], 0x10000, tuple_coords[i] - im_start_coords[i]); + apply = FT_MulDiv(apply, temp, 0x10000); + } + else + { + temp = FT_MulDiv(im_end_coords[i] - nn[i], 0x10000, im_end_coords[i] - tuple_coords[i]); + apply = FT_MulDiv(apply, temp, 0x10000); + } + } + return apply; +} +function TT_Get_MM_Var(face, bIsRet) +{ + var stream = face.stream; + var table_len; + FT_Error = 0; + var fvar_start; + var i, j; + var mmvar = null; + var fvar_head = new GX_FVar_Head(); + + if (face.blend == null) + { + table_len = face.goto_table(face, FT_Common.TTAG_gvar, stream); + if (FT_Error != 0) + return null; + + table_len = face.goto_table(face, FT_Common.TTAG_fvar, stream); + if (FT_Error != 0) + return null; + + fvar_start = stream.pos; + + FT_Error = stream.EnterFrame(16); + if (FT_Error != 0) + return null; + fvar_head.version = stream.GetULong(); + fvar_head.offsetToData = stream.GetUShort(); + fvar_head.countSizePairs = stream.GetUShort(); + fvar_head.axisCount = stream.GetUShort(); + fvar_head.axisSize = stream.GetUShort(); + fvar_head.instanceCount = stream.GetUShort(); + fvar_head.instanceSize = stream.GetUShort(); + stream.ExitFrame(); + + + if (fvar_head.version != 0x00010000 || fvar_head.countSizePairs != 2 || fvar_head.axisSize != 20 || + fvar_head.axisCount > 0x3FFE || fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount || fvar_head.instanceCount > 0x7EFF || + fvar_head.offsetToData + fvar_head.axisCount * 20 + fvar_head.instanceCount * fvar_head.instanceSize > table_len) + { + FT_Error = FT_Common.FT_Err_Invalid_Table; + return null; + } + + face.blend = new GX_BlendRec(); + face.blend.mmvar_len = 0; + mmvar = new FT_MM_Var(); + + face.blend.mmvar = mmvar; + + mmvar.num_axis = fvar_head.axisCount; + mmvar.num_designs = 0xFFFFFFFF; + mmvar.num_namedstyles = fvar_head.instanceCount; + mmvar.axis = new Array(mmvar.num_axis); + mmvar.namedstyle = new Array(mmvar.num_namedstyles); + + FT_Error = stream.EnterFrame(fvar_start + fvar_head.offsetToData); + if (FT_Error != 0) + return null; + + var mass_a = mmvar.axis; + var count_a = mmvar.num_axis; + for (i = 0; i < count_a; i++) + { + mass_a[i] = new FT_Var_Axis(); + var a = mass_a[i]; + + FT_Error = stream.EnterFrame(20); + if (FT_Error != 0) + return null; + + a.tag = stream.GetULong(); + a.minimum = stream.GetULong(); + a.def = stream.GetULong(); + a.maximum = stream.GetULong(); + stream.Skip(2); + a.strid = stream.GetUShort(); + + var tag = a.tag; + a.name = ""; + a.name += String.fromCharCode((tag >>> 24) & 0xFF); + a.name += String.fromCharCode((tag >>> 16) & 0xFF); + a.name += String.fromCharCode((tag >>> 8) & 0xFF); + a.name += String.fromCharCode(tag & 0xFF); + + stream.ExitFrame(); + } + + if (0 == bIsRet) + return null; + + var mass_s = mmvar.namedstyle; + var count_s = mmvar.num_namedstyles; + for (i = 0;i < count_s;i++) + { + FT_Error = stream.EnterFrame(4 + 4 * count_a); + if (FT_Error != 0) + return null; + + mass_s[i] = new FT_Var_Named_Style(); + var s = mass_s[i]; + + s.strid = stream.GetUShort(); + stream.Skip(2); + + s.coords = new Array(count_a); + for (j = 0; j < count_a; j++) + s.coords[j] = stream.GetULong(); + + stream.ExitFrame(); + } + } + + mmvar = null; + mmvar = face.blend.mmvar.dublicate(); + + mass_a = mmvar.axis; + count_a = mmvar.num_axis; + for (i = 0; i < count_a; i++) + { + var a = mass_a[i]; + + if (a.tag == FT_Common.TTAG_wght) + a.name = "Weight"; + else if (a.tag == FT_Common.TTAG_wdth) + a.name = "Width"; + else if (a.tag == FT_Common.TTAG_opsz) + a.name = "OpticalSize"; + else if (a.tag == FT_Common.TTAG_slnt) + a.name = "Slant"; + } + + return mmvar; +} +function TT_Set_MM_Blend(face, num_coords, coords) +{ + var error = 0; + face.doblend = 0; + + if (face.blend == null) + { + TT_Get_MM_Var(face, 0); + if (FT_Error != 0) + return FT_Error; + } + var manageCvt = 0; + + var blend = face.blend; + var mmvar = blend.mmvar; + + if (num_coords != mmvar.num_axis) + return FT_Common.FT_Err_Invalid_Argument; + + for (var i = 0; i < num_coords; i++) + { + if (coords[i] < -0x00010000 || coords[i] > 0x00010000) + return FT_Common.FT_Err_Invalid_Argument; + } + + if (blend.glyphoffsets == null) + { + error = ft_var_load_gvar(face); + if (error != 0) + return error; + } + + if (blend.normalizedcoords == null) + { + blend.normalizedcoords = new Array(num_coords); + manageCvt = 1; + } + else + { + manageCvt = 0; + for (var i = 0; i < num_coords; ++i) + { + if (blend.normalizedcoords[i] != coords[i]) + { + manageCvt = 2; + break; + } + } + } + + blend.num_axis = num_coords; + for (var i = 0;i < num_coords; i++) + blend.normalizedcoords[i] = coords[i]; + face.doblend = 1; + if (face.cvt != null) + { + switch (manageCvt) + { + case 2: + tt_face_load_cvt(face, face.stream); + break; + + case 1: + tt_face_vary_cvt(face, face.stream); + break; + + case 0: + break; + } + } + return error; +} +function TT_Set_Var_Design(face, num_coords, coords) +{ + var error = 0; + var i, j; + var a = null; + var av = null; + if (face.blend == null) + { + TT_Get_MM_Var(face, 0); + if (FT_Error != 0) + return FT_Error; + } + + var blend = face.blend; + var mmvar = blend.mmvar; + + if (num_coords != mmvar.num_axis) + return FT_Common.FT_Err_Invalid_Argument; + + var _c = mmvar.num_axis; + var normalized = new Array(_c); + + for (i = 0; i < _c; i++) + { + a = mmvar.axis[i]; + if (coords[i] > a.maximum || coords[i] < a.minimum) + return FT_Common.FT_Err_Invalid_Argument; + + if (coords[i] < a.def) + { + normalized[i] = -FT_MulDiv(coords[i] - a.def, 0x10000, a.minimum - a.def); + } + else if (a.maximum == a.def) + normalized[i] = 0; + else + { + normalized[i] = FT_MulDiv(coords[i] - a.def, 0x10000, a.maximum - a.def); + } + } + + if (0 == blend.avar_checked) + ft_var_load_avar(face); + + if (blend.avar_segment != null) + { + for (i = 0; i < _c; i++) + { + av = blend.avar_segment[i]; + var _coords = av.correspondence; + for (j = 1; j < av.pairCount; j++) + if (normalized[i] < _coords[j].fromCoord) + { + var mem = FT_MulDiv(normalized[i] - _coords[j - 1].fromCoord, 0x10000, _coords[j].fromCoord - _coords[j - 1].fromCoord); + normalized[i] = FT_MulDiv(mem, _coords[j].toCoord - _coords[j - 1].toCoord, 0x10000) + _coords[j - 1].toCoord; + break; + } + } + } + + error = TT_Set_MM_Blend(face, num_coords, normalized); + normalized = null; + return error; +} +function tt_face_vary_cvt(face, stream) +{ + var error = 0; + var here; + var i, j; + var blend = face.blend; + var point_count; + var localpoints; + var deltas; + + if (blend == null) + return 0; + + if (face.cvt == null) + return 0; + + var table_len = face.goto_table(face, FT_Common.TTAG_cvar, stream); + error = FT_Error; + if (error != 0) + return 0; + + error = stream.EnterFrame(table_len); + if (error != 0) + return 0; + + var table_start = stream.cur; + if (0x00010000 != stream.GetLong()) + { + stream.ExitFrame(); + return 0; + } + + var num_axis = blend.num_axis; + var tuple_coords = new Array(num_axis); + var im_start_coords = new Array(num_axis); + var im_end_coords = new Array(num_axis); + + var tupleCount = stream.GetUShort(); + var offsetToData = table_start + stream.GetUShort(); + + for (i = 0; i < (tupleCount & 0xFFF); ++i) + { + var tupleDataSize = stream.GetUShort(); + var tupleIndex = stream.GetUShort(); + + if ((tupleIndex & FT_Common.GX_TI_EMBEDDED_TUPLE_COORD) != 0) + { + for (j = 0; j < num_axis; j++) + tuple_coords[j] = stream.GetShort() << 2; + } + else + { + if ((tupleIndex & FT_Common.GX_TI_INTERMEDIATE_TUPLE) != 0) + { + stream.Skip(4 * num_axis); + } + offsetToData += tupleDataSize; + continue; + } + if ((tupleIndex & FT_Common.GX_TI_INTERMEDIATE_TUPLE) != 0) + { + for (j = 0; j < num_axis; j++) + im_start_coords[j] = stream.GetShort() << 2; + for (j = 0; j < num_axis; j++) + im_end_coords[j] = stream.GetShort() << 2; + } + + var apply = ft_var_apply_tuple(blend, tupleIndex, tuple_coords, im_start_coords, im_end_coords); + if (apply == 0 || 0 == (tupleIndex & FT_Common.GX_TI_PRIVATE_POINT_NUMBERS)) + { + offsetToData += tupleDataSize; + continue; + } + + here = stream.cur; + stream.cur = offsetToData; + + var __mem1 = ft_var_readpackedpoints(stream); + localpoints = __mem1.points; + point_count = __mem1.point_cnt; + var cvt_size = face.cvt_size; + deltas = ft_var_readpackeddeltas(stream, point_count == 0 ? cvt_size : point_count); + if (deltas == null) + { + } + else if (localpoints == null) + { + for (j = 0; j < cvt_size; j++) + face.cvt[j] = (face.cvt[j] + FT_MulFix(deltas[j], apply)) & 0xFFFF; + } + else + { + for (j = 0; j < point_count; ++j) + { + var pindex = localpoints[j]; + face.cvt[pindex] = (face.cvt[pindex] + FT_MulFix(deltas[j], apply)) & 0xFFFF; + } + } + + localpoints = null; + deltas = null; + offsetToData += tupleDataSize; + stream.cur = here; + } + + stream.ExitFrame(); + + tuple_coords = null; + im_start_coords = null; + im_end_coords = null; + + return error; +} +function TT_Vary_Get_Glyph_Deltas(face, glyph_index, n_points) +{ + var stream = face.stream; + var blend = face.blend; + var error; + var here; + var i, j; + var point_count, spoint_count = 0; + var sharedpoints = null; + var localpoints = null; + var points = null; + var deltas_x = null, deltas_y = null; + + + if (face.doblend == 0 || blend == null) + { + FT_Error = FT_Common.FT_Err_Invalid_Argument; + return null; + } + + var delta_xy = new Array(n_points); + for (i=0;i<n_points;i++) + delta_xy[i] = new FT_Vector(); + + if (glyph_index >= blend.gv_glyphcnt || blend.glyphoffsets[glyph_index] == blend.glyphoffsets[glyph_index + 1]) + return 0; + + error = stream.Seek(blend.glyphoffsets[glyph_index]); + if (error == 0) + error = stream.EnterFrame(blend.glyphoffsets[glyph_index + 1] - blend.glyphoffsets[glyph_index]); + + if (error != 0) + { + delta_xy = null; + FT_Error = error; + return null; + } + + var glyph_start = stream.cur; + + var num_axis = blend.num_axis; + var tuple_coords = new Array(num_axis); + var im_start_coords = new Array(num_axis); + var im_end_coords = new Array(num_axis); + + var tupleCount = stream.GetUShort(); + var offsetToData = glyph_start + stream.GetUShort(); + + if ((tupleCount & FT_Common.GX_TC_TUPLES_SHARE_POINT_NUMBERS) != 0) + { + here = stream.cur; + stream.cur = offsetToData; + + var __mem = ft_var_readpackedpoints(stream); + sharedpoints = __mem.points; + spoint_count = __mem.point_cnt; + offsetToData = stream.cur; + stream.cur = here; + } + + for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i ) + { + var tupleDataSize = stream.GetUShort(); + var tupleIndex = stream.GetUShort(); + + if (0 != (tupleIndex & FT_Common.GX_TI_EMBEDDED_TUPLE_COORD)) + { + for (j = 0; j < num_axis; j++) + tuple_coords[j] = stream.GetShort() << 2; + } + else if (((tupleIndex & FT_Common.GX_TI_TUPLE_INDEX_MASK) != 0) >= blend.tuplecount) + { + FT_Error = FT_Common.FT_Err_Invalid_Table; + tuple_coords = null; + im_start_coords = null; + im_end_coords = null; + delta_xy = null; + stream.ExitFrame(); + return null; + } + else + { + var _src = blend.tuplecoords; + var _s_start = (tupleIndex & 0xFFF) * num_axis; + for (j=0;j<num_axis;j++) + tuple_coords[j] = _src[_s_start+j]; + } + + if (0 != (tupleIndex & FT_Common.GX_TI_INTERMEDIATE_TUPLE)) + { + for (j = 0; j < num_axis; j++) + im_start_coords[j] = stream.GetShort() << 2; + for (j = 0; j < num_axis; j++) + im_end_coords[j] = stream.GetShort() << 2; + } + + var apply = ft_var_apply_tuple(blend, tupleIndex, tuple_coords, im_start_coords, im_end_coords); + if (apply == 0) + { + offsetToData += tupleDataSize; + continue; + } + + here = stream.cur; + if (0 != (tupleIndex & FT_Common.GX_TI_PRIVATE_POINT_NUMBERS)) + { + stream.cur = offsetToData; + var __mem = ft_var_readpackedpoints(stream); + localpoints = __mem.points; + point_count = __mem.point_cnt; + points = localpoints; + } + else + { + points = sharedpoints; + point_count = spoint_count; + } + + deltas_x = ft_var_readpackeddeltas(stream, point_count == 0 ? n_points : point_count); + deltas_y = ft_var_readpackeddeltas(stream, point_count == 0 ? n_points : point_count); + + if (points == null || deltas_y == null || deltas_x == null) + { + } + else if (points == null) + { + for (j = 0; j < n_points; j++) + { + delta_xy[j].x += FT_MulFix(deltas_x[j], apply); + delta_xy[j].y += FT_MulFix(deltas_y[j], apply); + } + } + else + { + for (j = 0; j < point_count; j++) + { + if (localpoints[j] >= n_points) + continue; + + delta_xy[localpoints[j]].x += FT_MulFix(deltas_x[j], apply); + delta_xy[localpoints[j]].y += FT_MulFix(deltas_y[j], apply); + } + } + + localpoints = null; + deltas_x = null; + deltas_y = null; + + offsetToData += tupleDataSize; + stream.cur = here; + } + + tuple_coords = null; + im_start_coords = null; + im_end_coords = null; + delta_xy = null; + stream.ExitFrame(); + if (error != 0) + delta_xy = null; + + FT_Error = error; + return delta_xy; +} +function tt_done_blend(memory, blend) +{ +} +/******************************************************************************/ +// glyphloader +/******************************************************************************/ +function load_sbit_image(size, glyph, glyph_index, load_flags) +{ + var metrics = new TT_SBit_MetricsRec(); + + var face = glyph.face; + var stream = face.stream; + var error = face.sfnt.load_sbit_image(face, size.strike_index, glyph_index, load_flags, stream, glyph.bitmap, metrics); + if (error == 0) + { + glyph.outline.n_points = 0; + glyph.outline.n_contours = 0; + + glyph.metrics.width = metrics.width << 6; + glyph.metrics.height = metrics.height << 6; + + glyph.metrics.horiBearingX = metrics.horiBearingX << 6; + glyph.metrics.horiBearingY = metrics.horiBearingY << 6; + glyph.metrics.horiAdvance = metrics.horiAdvance << 6; + + glyph.metrics.vertBearingX = metrics.vertBearingX << 6; + glyph.metrics.vertBearingY = metrics.vertBearingY << 6; + glyph.metrics.vertAdvance = metrics.vertAdvance << 6; + + glyph.format = FT_Common.FT_GLYPH_FORMAT_BITMAP; + + if ((load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) != 0) + { + glyph.bitmap_left = metrics.vertBearingX; + glyph.bitmap_top = metrics.vertBearingY; + } + else + { + glyph.bitmap_left = metrics.horiBearingX; + glyph.bitmap_top = metrics.horiBearingY; + } + } + + return error; +} +function TT_Get_HMetrics(face, idx) +{ + return face.sfnt.get_metrics(face, 0, idx); +} +function TT_Get_VMetrics(face, idx) +{ + if (face.vertical_info === true) + return face.sfnt.get_metrics(face, 1, idx); + + return {bearing : 0, advance : face.units_per_EM}; +} + +function tt_get_metrics(loader, glyph_index) +{ + var face = loader.face; + + var h = TT_Get_HMetrics(face, glyph_index); + var v = TT_Get_VMetrics(face, glyph_index); + + loader.left_bearing = h.bearing; + loader.advance = h.advance; + loader.top_bearing = v.bearing; + loader.vadvance = v.advance; + + if (face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) //#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (loader.exec != null) + loader.exec.sph_tweak_flags = 0; + + /* this may not be the right place for this, but it works */ + if (loader.exec != null && loader.exec.ignore_x_mode) + global_SubpixHintingHacks.sph_set_tweaks(loader, glyph_index); + }//#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + if (loader.linear_def == 0) + { + loader.linear_def = 1; + loader.linear = h.advance; + } +} +function tt_get_metrics_incr_overrides(loader, glyph_index) +{ + var face = loader.face; + + var h = TT_Get_HMetrics(face, glyph_index); + var v = TT_Get_VMetrics(face, glyph_index); + + if (face.internal.incremental_interface && face.internal.incremental_interface.funcs.get_glyph_metrics) + { + var metrics = new FT_Incremental_MetricsRec(); + + metrics.bearing_x = loader.left_bearing; + metrics.bearing_y = 0; + metrics.advance = loader.advance; + metrics.advance_v = 0; + + var error = face.internal.incremental_interface.funcs.get_glyph_metrics(face.internal.incremental_interface.object, + glyph_index, false, metrics); + if (error != 0) + return 0; + + loader.left_bearing = metrics.bearing_x; + loader.advance = metrics.advance; + loader.top_bearing = v.tsb; + loader.vadvance = v.ah; + + if (0 == loader.linear_def) + { + loader.linear_def = 1; + loader.linear = h.aw; + } + } + return 0; +} +function translate_array(n, coords, delta_x, delta_y) +{ + if (delta_x != 0) + for (var k = 0; k < n; k++) + coords[k].x += delta_x; + + if (delta_y != 0) + for (var k = 0; k < n; k++) + coords[k].y += delta_y; +} +function translate_array_ex(n, coords, start_p, delta_x, delta_y) +{ + if (delta_x != 0) + for (var k = 0; k < n; k++) + coords[start_p + k].x += delta_x; + + if (delta_y != 0) + for (var k = 0; k < n; k++) + coords[start_p + k].y += delta_y; +} + +function TT_Access_Glyph_Frame(loader, glyph_index, offset, byte_count) +{ + var error = 0; + var stream = loader.stream; + + error = stream.Seek(offset); + if (error == 0) + error = stream.EnterFrame(byte_count); + + if (error != 0) + return error; + + loader.cursor = stream.cur; + loader.limit = stream.size; + + return 0; +} + +function TT_Forget_Glyph_Frame(loader) +{ + loader.stream.ExitFrame(); +} + +function TT_Load_Glyph_Header(loader) +{ + var stream = loader.stream; + + if (stream.cur + 10 > stream.size) + return FT_Common.FT_Err_Invalid_Outline; + + loader.n_contours = stream.GetShort(); + loader.bbox.xMin = stream.GetShort(); + loader.bbox.yMin = stream.GetShort(); + loader.bbox.xMax = stream.GetShort(); + loader.bbox.yMax = stream.GetShort(); + + loader.cursor += 10; + + return 0; +} + +function TT_Load_Simple_Glyph(load) +{ + var error = 0; + var p = new FT_Stream(load.stream.data, load.stream.size); + p.cur = load.cursor; + + var gloader = load.gloader; + var n_contours = load.n_contours; + var face = load.face; + var n_ins; + var n_points; + + var c, count; + var x; + var prev_cont; + var xy_size = 0; + + error = FT_GLYPHLOADER_CHECK_POINTS(gloader, 0, n_contours); + if (error != 0) + return error; + + if (null == gloader.base.outline.contours) + { + error = FT_GLYPHLOADER_CHECK_POINTS(gloader, 0, n_contours); + } + + var conts = gloader.base.outline.contours; + var cont = gloader.current.outline.contours; + var cont_limit = cont + n_contours; + + if (n_contours >= 0xFFF || p.cur + (n_contours + 1) * 2 > load.limit) + return FT_Common.FT_Err_Invalid_Outline; + + prev_cont = p.GetUShort(); + + if (n_contours > 0) + conts[cont] = prev_cont; + + for (cont++; cont < cont_limit; cont++) + { + conts[cont] = p.GetUShort(); + if (conts[cont] <= prev_cont) + return FT_Common.FT_Err_Invalid_Table; + prev_cont = conts[cont]; + } + + n_points = 0; + if (n_contours > 0) + { + n_points = conts[cont-1] + 1; + if (n_points < 0) + return FT_Common.FT_Err_Invalid_Outline; + } + + /* note that we will add four phantom points later */ + error = FT_GLYPHLOADER_CHECK_POINTS(gloader, n_points + 4, 0); + if (error != 0) + return error; + + var outline = gloader.current.outline; + for (cont = outline.contours + 1; cont < cont_limit; cont++) + if (conts[cont-1] >= conts[cont]) + return FT_Common.FT_Err_Invalid_Outline; + + load.glyph.control_len = 0; + load.glyph.control_data = 0; + + if (p.cur + 2 > load.limit) + return FT_Common.FT_Err_Invalid_Outline; + + n_ins = p.GetUShort(); + if (n_ins > face.max_profile.maxSizeOfInstructions) + return FT_Common.FT_Err_Too_Many_Hints; + + if ((load.limit - p.cur) < n_ins) + return FT_Common.FT_Err_Too_Many_Hints; + + //#ifdef TT_USE_BYTECODE_INTERPRETER + if (face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER) + { + if ((load.load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) + { + load.glyph.control_len = n_ins; + load.glyph.control_data = dublicate_pointer(load.exec.glyphIns); + + if (load.glyph.control_data != null) + { + var _dd = load.glyph.control_data.data; + var _dc = load.glyph.control_data.pos; + + for (var j = 0; j < n_ins; j++) + _dd[_dc + j] = p.data[p.cur + j]; + } + } + } + + p.cur += n_ins; + + var flags = gloader.base.outline.tags; + var flag = outline.tags; + var flag_limit = flag + n_points; + + var limit = load.limit; + while (flag < flag_limit) + { + if (p.cur + 1 > limit) + return FT_Common.FT_Err_Invalid_Outline; + + flags[flag++] = c = p.GetUChar(); + if ((c & 8)!=0) + { + if (p.cur + 1 > limit) + return FT_Common.FT_Err_Invalid_Outline; + + count = p.GetUChar(); + if (flag + count > flag_limit) + return FT_Common.FT_Err_Invalid_Outline; + + for (; count > 0; count--) + flags[flag++] = c; + } + } + + var vecs = gloader.base.outline.points; + var vec = outline.points; + var vec_limit = vec + n_points; + flag = outline.tags; + x = 0; + + if (p.cur + xy_size > limit) + return FT_Common.FT_Err_Invalid_Outline; + + for ( ; vec < vec_limit; vec++, flag++ ) + { + var y = 0; + var f = flags[flag]; + + if ((f & 2)!=0) + { + if (p.cur + 1 > limit) + return FT_Common.FT_Err_Invalid_Outline; + + y = p.GetUChar(); + if (( f & 16 ) == 0) + y = -y; + } + else if (( f & 16 ) == 0) + { + if (p.cur + 2 > limit) + return FT_Common.FT_Err_Invalid_Outline; + + y = p.GetShort(); + } + + x += y; + vecs[vec].x = x; + flags[flag] = (f & ~( 2 | 16 )) & 0xFF; + } + + vec = outline.points; + flag = outline.tags; + x = 0; + + for ( ; vec < vec_limit; vec++, flag++) + { + var y = 0; + var f = flags[flag]; + + if ((f & 4)!=0) + { + if (p.cur + 1 > limit) + return FT_Common.FT_Err_Invalid_Outline; + + y = p.GetUChar(); + if ((f & 32) == 0) + y = -y; + } + else if ((f & 32) == 0) + { + if (p.cur + 2 > limit) + return FT_Common.FT_Err_Invalid_Outline; + + y = p.GetShort(); + } + + x += y; + vecs[vec].y = x; + flags[flag] = (f & FT_Common.FT_CURVE_TAG_ON) & 0xFF; + } + + outline.n_points = n_points & 0xFFFF; + outline.n_contours = n_contours & 0xFFFF; + + load.cursor = p.cur; + return error; +} + +function TT_Load_Composite_Glyph(loader) +{ + var error = 0; + var s = new FT_Stream(loader.stream.data, loader.stream.size); + s.cur = loader.cursor; + var size_read = loader.limit - loader.cursor; + var count_read = 0; + + var gloader = loader.gloader; + var subglyph = null; + var num_subglyphs = 0; + + do + { + var xx, xy, yy, yx; + var count; + + error = FT_GlyphLoader_CheckSubGlyphs(gloader, num_subglyphs + 1); + if (error != 0) + return error; + + if (count_read + 4 > size_read) + return FT_Common.FT_Err_Invalid_Composite; + + subglyph = gloader.base.subglyphs[gloader.current.subglyphs + num_subglyphs]; + + subglyph.arg1 = subglyph.arg2 = 0; + + subglyph.flags = s.GetUShort(); + subglyph.index = s.GetUShort(); + + count_read += 4; + + count = 2; + if (subglyph.flags & FT_Common.ARGS_ARE_WORDS) + count += 2; + if (subglyph.flags & FT_Common.WE_HAVE_A_SCALE) + count += 2; + else if (subglyph.flags & FT_Common.WE_HAVE_AN_XY_SCALE) + count += 4; + else if (subglyph.flags & FT_Common.WE_HAVE_A_2X2) + count += 8; + + if (count_read + count > size_read) + return FT_Common.FT_Err_Invalid_Composite; + + if (subglyph.flags & FT_Common.ARGS_ARE_WORDS) + { + subglyph.arg1 = s.GetShort(); + subglyph.arg2 = s.GetShort(); + } + else + { + subglyph.arg1 = s.GetChar(); + subglyph.arg2 = s.GetChar(); + } + + xx = yy = 0x10000; + xy = yx = 0; + + if (subglyph.flags & FT_Common.WE_HAVE_A_SCALE) + { + xx = s.GetShort() << 2; + yy = xx; + } + else if (subglyph.flags & FT_Common.WE_HAVE_AN_XY_SCALE) + { + xx = s.GetShort() << 2; + yy = s.GetShort() << 2; + } + else if (subglyph.flags & FT_Common.WE_HAVE_A_2X2) + { + xx = s.GetShort() << 2; + yx = s.GetShort() << 2; + xy = s.GetShort() << 2; + yy = s.GetShort() << 2; + } + + subglyph.transform.xx = xx; + subglyph.transform.xy = xy; + subglyph.transform.yx = yx; + subglyph.transform.yy = yy; + + num_subglyphs++; + + count_read += count; + + } while (subglyph.flags & FT_Common.MORE_COMPONENTS); + + gloader.current.num_subglyphs = num_subglyphs; + + if (loader.face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER) + { + loader.ins_pos = loader.stream.pos + s.cur - loader.limit; + } + + loader.cursor = s.cur; + return error +} + +function TT_Process_Simple_Glyph(loader) +{ + var gloader = loader.gloader; + var error = 0; + + var outline = gloader.current.outline; + var base = gloader.base.outline; + var n_points = outline.n_points; + + var points = base.points; + var p_s = outline.points; + var s = p_s + n_points; + var tags = base.tags; + var t_s = outline.tags; + var t = t_s + n_points; + + points[s ].x = loader.pp1.x; + points[s + 1].x = loader.pp2.x; + points[s + 2].x = loader.pp3.x; + points[s + 3].x = loader.pp4.x; + points[s ].y = loader.pp1.y; + points[s + 1].y = loader.pp2.y; + points[s + 2].y = loader.pp3.y; + points[s + 3].y = loader.pp4.y; + + tags[t ] = 0; + tags[t + 1] = 0; + tags[t + 2] = 0; + tags[t + 3] = 0; + + n_points += 4; + s += 4; + + //#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if (loader.face.doblend != 0) + { + var deltas = TT_Vary_Get_Glyph_Deltas(loader.face, loader.glyph_index, n_points); + error = FT_Error; + if (error != 0) + return error; + + for (var i = 0; i < n_points; i++) + { + points[i + p_s].x += deltas[i].x; + points[i + p_s].y += deltas[i].y; + } + + deltas = null; + } + //#endif + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) + { + tt_prepare_zone_cur(loader.zone, gloader, 0, 0); + + var _p_len = loader.zone.n_points + 4; + + var _orus = loader.zone.orus; + var _cur = loader.zone.cur; + for (var i = 0; i < _p_len; i++) + { + _orus[loader.zone._offset_orus + i].x = _cur[loader.zone._offset_cur + i].x; + _orus[loader.zone._offset_orus + i].y = _cur[loader.zone._offset_cur + i].y; + } + } + + var _face = loader.face; + if (_face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) + { + var x_scale_factor = 1000; + var ppem = loader.size.metrics.x_ppem; + if ((loader.load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) + { + x_scale_factor = global_SubpixHintingHacks.scale_test_tweak(_face, _face.family_name, ppem, _face.style_name, loader.glyph_index, + global_SubpixHintingHacks.X_SCALING_Rules, global_SubpixHintingHacks.X_SCALING_RULES_SIZE); + } + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0 || x_scale_factor != 1000) + { + var x_scale = FT_MulDiv(loader.size.metrics.x_scale, x_scale_factor, 1000); + var y_scale = loader.size.metrics.y_scale; + + /* compensate for any scaling by de/emboldening; */ + /* the amount was determined via experimentation */ + if (x_scale_factor != 1000 && ppem > 11) + FT_Outline_EmboldenXY(outline, FT_MulFix(1280 * ppem, 1000 - x_scale_factor), 0); + + for (var vec = 0 ; vec < n_points; vec++) + { + points[vec + p_s].x = FT_MulFix(points[vec + p_s].x, x_scale); + points[vec + p_s].y = FT_MulFix(points[vec + p_s].y, y_scale); + } + + loader.pp1.x = points[s - 4].x; + loader.pp2.x = points[s - 3].x; + loader.pp3.x = points[s - 2].x; + loader.pp4.x = points[s - 1].x; + loader.pp1.y = points[s - 4].y; + loader.pp2.y = points[s - 3].y; + loader.pp3.y = points[s - 2].y; + loader.pp4.y = points[s - 1].y; + } + } + else + { + if ((loader.load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0) + { + var x_scale = loader.size.metrics.x_scale; + var y_scale = loader.size.metrics.y_scale; + + for (var vec = 0 ; vec < n_points; vec++) + { + points[vec + p_s].x = FT_MulFix(points[vec + p_s].x, x_scale); + points[vec + p_s].y = FT_MulFix(points[vec + p_s].y, y_scale); + } + + loader.pp1.x = points[s - 4].x; + loader.pp2.x = points[s - 3].x; + loader.pp3.x = points[s - 2].x; + loader.pp4.x = points[s - 1].x; + loader.pp1.y = points[s - 4].y; + loader.pp2.y = points[s - 3].y; + loader.pp3.y = points[s - 2].y; + loader.pp4.y = points[s - 1].y; + } + } + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) + { + loader.zone.n_points += 4; + error = TT_Hint_Glyph(loader, false); + } + + return error; +} + +function TT_Process_Composite_Component(loader, subglyph, start_point, num_base_points) +{ + var gloader = loader.gloader; + var base_vecs = gloader.base.outline.points; + var base_vec = 0; + var num_points = gloader.base.outline.n_points; + var x, y; + + var have_scale = (0 == (subglyph.flags & (FT_Common.WE_HAVE_A_SCALE | FT_Common.WE_HAVE_AN_XY_SCALE | FT_Common.WE_HAVE_A_2X2))) ? 0 : 1; + + if (have_scale != 0) + { + for (var i = num_base_points; i < num_points; i++) + FT_Vector_Transform(base_vecs[i], subglyph.transform); + } + + if (0 == (subglyph.flags & FT_Common.ARGS_ARE_XY_VALUES)) + { + var k = subglyph.arg1; + var l = subglyph.arg2; + k += start_point; + l += num_base_points; + if (k >= num_base_points || l >= num_points) + return FT_Common.FT_Err_Invalid_Composite; + + var p1 = gloader.base.outline.points[k]; + var p2 = gloader.base.outline.points[l]; + + x = p1.x - p2.x; + y = p1.y - p2.y; + } + else + { + x = subglyph.arg1; + y = subglyph.arg2; + + if (x == 0 && y == 0) + return 0; + + if (have_scale != 0 && 0 != (subglyph.flags & FT_Common.SCALED_COMPONENT_OFFSET)) + { + var mac_xscale = FT_SqrtFixed(FT_MulFix(subglyph.transform.xx, subglyph.transform.xx) + + FT_MulFix(subglyph.transform.xy, subglyph.transform.xy)); + var mac_yscale = FT_SqrtFixed(FT_MulFix(subglyph.transform.yy, subglyph.transform.yy) + + FT_MulFix(subglyph.transform.yx, subglyph.transform.yx)); + + + x = FT_MulFix(x, mac_xscale); + y = FT_MulFix(y, mac_yscale); + } + + if (0 == (loader.load_flags & FT_Common.FT_LOAD_NO_SCALE)) + { + var x_scale = loader.size.metrics.x_scale; + var y_scale = loader.size.metrics.y_scale; + + x = FT_MulFix(x, x_scale); + y = FT_MulFix(y, y_scale); + + if (subglyph.flags & FT_Common.ROUND_XY_TO_GRID) + { + x = FT_PIX_ROUND(x); + y = FT_PIX_ROUND(y); + } + } + } + + if (x != 0) + { + for (var j=num_base_points;j<num_points;j++) + base_vecs[j].x += x; + } + if (y != 0) + { + for (var j=num_base_points;j<num_points;j++) + base_vecs[j].y += y; + } + + return 0; +} + +function TT_Process_Composite_Glyph(loader, start_point, start_contour) +{ + var outline = loader.gloader.base.outline; + + /* make room for phantom points */ + var error = FT_GLYPHLOADER_CHECK_POINTS(loader.gloader, outline.n_points + 4, 0); + if (error != 0) + return error; + + var _points = outline.points; + var _n_points = outline.n_points; + var _tags = outline.tags; + + _points[_n_points].x = loader.pp1.x; + _points[_n_points].y = loader.pp1.y; + + _points[_n_points + 1].x = loader.pp2.x; + _points[_n_points + 1].y = loader.pp2.y; + + _points[_n_points + 2].x = loader.pp3.x; + _points[_n_points + 2].y = loader.pp3.y; + + _points[_n_points + 3].x = loader.pp4.x; + _points[_n_points + 3].y = loader.pp4.y; + + _tags[_n_points] = 0; + _tags[_n_points + 1] = 0; + _tags[_n_points + 2] = 0; + _tags[_n_points + 3] = 0; + + if (loader.face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER) //#ifdef TT_USE_BYTECODE_INTERPRETER + { + /* TT_Load_Composite_Glyph only gives us the offset of instructions */ + /* so we read them here */ + var stream = loader.stream; + error = stream.Seek(loader.ins_pos); + if (error != 0) + return error; + + var n_ins = stream.ReadUShort(); + error = FT_Error; + FT_Error = 0; + if (error != 0) + return error; + + /* check it */ + var max_ins = loader.face.max_profile.maxSizeOfInstructions; + if (n_ins > max_ins) + { + /* acroread ignores this field, so we only do a rough safety check */ + if (n_ins > loader.byte_len) + return FT_Common.FT_Err_Too_Many_Hints; + + var ret = Update_MaxBYTE(loader.exec.memory, loader.exec.glyphSize, loader.exec.glyphIns, n_ins); + if (ret != null) + { + loader.exec.glyphSize = ret.size; + loader.exec.glyphIns = ret.block; + } + + if ( error ) + return error; + } + else if (n_ins == 0) + return 0; + + error = stream.Read(loader.exec.glyphIns, n_ins); + if (error != 0) + return error; + + loader.glyph.control_data = dublicate_pointer(loader.exec.glyphIns); + loader.glyph.control_len = n_ins; + } + //#endif + + tt_prepare_zone(loader.zone, loader.gloader.base, start_point, start_contour); + + /* Some points are likely touched during execution of */ + /* instructions on components. So let's untouch them. */ + for (var i = start_point; i < loader.zone.n_points; i++) + loader.zone.tags[i] &= ~FT_Common.FT_CURVE_TAG_TOUCH_BOTH; + + loader.zone.n_points += 4; + + return TT_Hint_Glyph(loader, true); +} + +function TT_Hint_Glyph(loader, is_composite) +{ + var zone = loader.zone; + var n_ins = 0; + + var _tt_hints = loader.face.driver.library.tt_hint_props; + if (_tt_hints.TT_USE_BYTECODE_INTERPRETER) //#ifdef TT_USE_BYTECODE_INTERPRETER + { + n_ins = loader.glyph.control_len; + } + //#endif + + var origin = zone.cur[zone._offset_cur + zone.n_points - 4].x; + origin = FT_PIX_ROUND(origin) - origin; + if (origin != 0) + translate_array_ex(zone.n_points, zone.cur, zone._offset_cur, origin, 0); + + if (_tt_hints.TT_USE_BYTECODE_INTERPRETER) //#ifdef TT_USE_BYTECODE_INTERPRETER + { + /* save original point position in org */ + if (n_ins > 0) + { + var _arr_d = zone.org; + var _arr_s = zone.cur; + var _count = zone.n_points; + var _d_s = zone._offset_org; + var _s_s = zone._offset_cur; + + for (var i = 0; i < _count; i++) + { + _arr_d[i + _d_s].x = _arr_s[i + _s_s].x; + _arr_d[i + _d_s].y = _arr_s[i + _s_s].y; + } + } + + /* Reset graphics state. */ + loader.size.GS.Copy(loader.exec.GS); + + /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ + /* completely refer to the (already) hinted subglyphs. */ + if (is_composite) + { + loader.exec.metrics.x_scale = 1 << 16; + loader.exec.metrics.y_scale = 1 << 16; + + var _arr_d = zone.orus; + var _arr_s = zone.cur; + var _count = zone.n_points; + var _d_s = zone._offset_orus; + var _s_s = zone._offset_cur; + + for (var i = 0; i < _count; i++) + { + _arr_d[i + _d_s].x = _arr_s[i + _s_s].x; + _arr_d[i + _d_s].y = _arr_s[i + _s_s].y; + } + } + else + { + loader.exec.metrics.x_scale = loader.size.metrics.x_scale; + loader.exec.metrics.y_scale = loader.size.metrics.y_scale; + } + }//#endif + + /* round pp2 and pp4 */ + zone.cur[zone._offset_cur + zone.n_points - 3].x = FT_PIX_ROUND(zone.cur[zone._offset_cur + zone.n_points - 3].x); + zone.cur[zone._offset_cur + zone.n_points - 1].y = FT_PIX_ROUND(zone.cur[zone._offset_cur + zone.n_points - 1].y); + + //#ifdef TT_USE_BYTECODE_INTERPRETER + if ( n_ins > 0 ) + { + var base_outline = loader.gloader.base.outline; + var current_outline = loader.gloader.current.outline; + + var error = TT_Set_CodeRange(loader.exec, FT_Common.tt_coderange_glyph, loader.exec.glyphIns, n_ins); + if (error) + return error; + + loader.exec.is_composite = is_composite; + loader.exec.pts.Copy(zone); + + var debug = (!(loader.load_flags & FT_Common.FT_LOAD_NO_SCALE) && loader.size.debug) ? true : false; + + error = TT_Run_Context(loader.exec, debug); + if (error && loader.exec.pedantic_hinting) + return error; + + /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ + base_outline.tags[current_outline.tags] |= (loader.exec.GS.scan_type << 5) | FT_Common.FT_CURVE_TAG_HAS_SCANMODE; + } + //#endif + + /* save glyph phantom points */ + if (!loader.preserve_pps) + { + var _off = zone.n_points + zone._offset_cur; + + loader.pp1.x = zone.cur[_off - 4].x; + loader.pp1.y = zone.cur[_off - 4].y; + + loader.pp2.x = zone.cur[_off - 3].x; + loader.pp2.y = zone.cur[_off - 3].y; + + loader.pp3.x = zone.cur[_off - 2].x; + loader.pp3.y = zone.cur[_off - 2].y; + + loader.pp4.x = zone.cur[_off - 1].x; + loader.pp4.y = zone.cur[_off - 1].y; + } + + if (_tt_hints.TT_CONFIG_OPTION_SUBPIXEL_HINTING) //#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (loader.exec.sph_tweak_flags & FT_Common.SPH_TWEAK_DEEMBOLDEN) + FT_Outline_EmboldenXY(loader.gloader.current.outline, -24, 0); + else if (loader.exec.sph_tweak_flags & FT_Common.SPH_TWEAK_EMBOLDEN) + FT_Outline_EmboldenXY(loader.gloader.current.outline, 24, 0); + }//#endif + return 0; +} + +function tt_prepare_zone(zone, load, start_point, start_contour) +{ + zone.n_points = (load.outline.n_points - start_point) & 0xFFFF; + zone.n_contours = FT_Common.UShort_To_Short((load.outline.n_contours - start_contour) & 0xFFFF); + + zone.org = load.extra_points; + zone._offset_org = start_point; + + zone.cur = load.outline.points; + zone._offset_cur = start_point; + + zone.orus = load.extra_points; + zone._offset_orus = load.extra_points2 + start_point; + + zone.tags = load.outline.tags; + zone._offset_tags = start_point; + + zone.contours = load.outline.contours; + zone._offset_contours = start_contour; + + zone.first_point = start_point; +} + +function tt_prepare_zone_cur(zone, load, start_point, start_contour) +{ + var _base = load.base; + var _cur = load.current; + + zone.n_points = (_cur.outline.n_points - start_point) & 0xFFFF; + zone.n_contours = FT_Common.UShort_To_Short((_cur.outline.n_contours - start_contour) & 0xFFFF); + + zone.org = _base.extra_points; + zone._offset_org = _cur.extra_points + start_point; + + zone.cur = _base.outline.points; + zone._offset_cur = _cur.outline.points + start_point; + + zone.orus = _base.extra_points; + zone._offset_orus = _cur.extra_points2 + start_point; + + zone.tags = _base.outline.tags; + zone._offset_tags = _cur.outline.tags + start_point; + + zone.contours = _base.outline.contours; + zone._offset_contours = _cur.outline.contours + start_contour; + + zone.first_point = start_point; +} + +function tt_size_run_prep(size, pedantic) +{ + var face = size.face; + var exec; + var error = 0; + + /* debugging instances have their own context */ + if (size.debug) + exec = size.context; + else + exec = face.driver.context; + + if (exec == null) + return FT_Common.FT_Err_Could_Not_Find_Context; + + TT_Load_Context(exec, face, size); + + exec.callTop = 0; + exec.top = 0; + + exec.instruction_trap = false; + exec.pedantic_hinting = pedantic; + + TT_Set_CodeRange(exec, FT_Common.tt_coderange_cvt, face.cvt_program, face.cvt_program_size); + TT_Clear_CodeRange(exec, FT_Common.tt_coderange_glyph); + + if (face.cvt_program_size > 0) + { + error = TT_Goto_CodeRange(exec, FT_Common.tt_coderange_cvt, 0); + + if (!error && !size.debug) + { + error = face.interpreter(exec); + } + } + else + error = 0; + + /* save as default graphics state */ + exec.GS.Copy(size.GS); + + // _DEBUG! + /* + var __arr = exec.stack; + var __len = exec.stackSize; + for (var __i = 0; __i < __len; ++__i) + console.log("" + __i + ": " + __arr[__i]); + */ + // + + TT_Save_Context(exec, size); + return error; +} + +function tt_loader_init(loader, size, glyph, load_flags, glyf_table_only) +{ + var face = glyph.face; + var stream = face.stream; + var pedantic = (0 == (load_flags & FT_Common.FT_LOAD_PEDANTIC)) ? 0 : 1; + + loader.Clear(); + + var bIsHint = face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER; + var bIsSubpixHint = face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + + if (bIsHint)//#ifdef TT_USE_BYTECODE_INTERPRETER + {/* load execution context */ + if ((load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0 && !glyf_table_only) + { + var grayscale = false; + + //#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + var subpixel_hinting = false; + var grayscale_hinting = false; + //#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + if (!size.cvt_ready) + { + var error = tt_size_ready_bytecode(size, pedantic); + if (error != 0) + return error; + } + + /* query new execution context */ + var exec = size.debug ? size.context : face.driver.context; + if (exec == null) + return FT_Common.FT_Err_Could_Not_Find_Context; + + if (bIsSubpixHint) // #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + subpixel_hinting = ((FT_LOAD_TARGET_MODE(load_flags) != FT_Common.FT_RENDER_MODE_MONO) && FT_Common.SPH_OPTION_SET_SUBPIXEL); + + if (subpixel_hinting) + grayscale = grayscale_hinting = false; + else if (FT_Common.SPH_OPTION_SET_GRAYSCALE) + { + grayscale = grayscale_hinting = true; + subpixel_hinting = false; + } + + if ((face.face_flags & FT_Common.FT_FACE_FLAG_TRICKY) != 0) + subpixel_hinting = grayscale_hinting = false; + + exec.ignore_x_mode = subpixel_hinting || grayscale_hinting; + exec.rasterizer_version = FT_Common.SPH_OPTION_SET_RASTERIZER_VERSION; + if (exec.sph_tweak_flags & FT_Common.SPH_TWEAK_RASTERIZER_35) + exec.rasterizer_version = 35; + + if (true) + { + exec.compatible_widths = FT_Common.SPH_OPTION_SET_COMPATIBLE_WIDTHS; + exec.symmetrical_smoothing = false; + exec.bgr = false; + exec.subpixel_positioned = true; + } + else + { + /* + exec.compatible_widths = (FT_LOAD_TARGET_MODE(load_flags) != FT_Common.TT_LOAD_COMPATIBLE_WIDTHS); + exec.symmetrical_smoothing = (FT_LOAD_TARGET_MODE(load_flags) != FT_Common.TT_LOAD_SYMMETRICAL_SMOOTHING); + exec.bgr = (FT_LOAD_TARGET_MODE(load_flags) != FT_Common.TT_LOAD_BGR); + exec.subpixel_positioned = (FT_LOAD_TARGET_MODE(load_flags) != FT_Common.TT_LOAD_SUBPIXEL_POSITIONED); + */ + } + }/* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + else + { + grayscale = (FT_LOAD_TARGET_MODE(load_flags) != FT_Common.FT_RENDER_MODE_MONO); + }/* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + TT_Load_Context(exec, face, size); + + if (bIsSubpixHint)//#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + /* a change from mono to subpixel rendering (and vice versa) */ + /* requires a re-execution of the CVT program */ + if (subpixel_hinting != exec.subpixel_hinting) + { + exec.subpixel_hinting = subpixel_hinting; + + for (var i = 0; i < size.cvt_size; i++) + size.cvt[i] = FT_MulFix(face.cvt[i], size.ttmetrics.scale); + + tt_size_run_prep(size, pedantic); + } + + /* a change from mono to grayscale rendering (and vice versa) */ + /* requires a re-execution of the CVT program */ + if (grayscale != exec.grayscale_hinting) + { + exec.grayscale_hinting = grayscale_hinting; + + for (var i = 0; i < size.cvt_size; i++) + size.cvt[i] = FT_MulFix(face.cvt[i], size.ttmetrics.scale); + tt_size_run_prep( size, pedantic ); + } + }/* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + else + { + /* a change from mono to grayscale rendering (and vice versa) */ + /* requires a re-execution of the CVT program */ + if (grayscale != exec.grayscale) + { + exec.grayscale = grayscale; + + for (i = 0; i < size.cvt_size; i++) + size.cvt[i] = FT_MulFix(face.cvt[i], size.ttmetrics.scale); + + tt_size_run_prep(size, pedantic); + } + }//#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + /* see whether the cvt program has disabled hinting */ + if (exec.GS.instruct_control & 1) + load_flags |= FT_Common.FT_LOAD_NO_HINTING; + + /* load default graphics state -- if needed */ + if (exec.GS.instruct_control & 2) + exec.GS.default_tt(); + + exec.pedantic_hinting = ((load_flags & FT_Common.FT_LOAD_PEDANTIC) != 0) ? true : false; + loader.exec = exec; + loader.instructions = dublicate_pointer(exec.glyphIns); + } + }//#endif /* TT_USE_BYTECODE_INTERPRETER */ + + if (face.internal.incremental_interface) + loader.glyf_offset = 0; + else + { + face.goto_table(face, FT_Common.TTAG_glyf, stream); + var error = FT_Error; + FT_Error = 0; + if (error == FT_Common.FT_Err_Table_Missing) + loader.glyf_offset = 0; + else if ( error ) + return error; + else + loader.glyf_offset = stream.pos; + } + + if (0 == glyf_table_only) + { + var gloader = glyph.internal.loader; + FT_GlyphLoader_Rewind(gloader); + loader.gloader = gloader; + } + + loader.load_flags = load_flags; + + loader.face = face; + loader.size = size; + loader.glyph = glyph; + loader.stream = stream; + + return 0; +} +function compute_glyph_metrics(loader, glyph_index) +{ + var bbox = new FT_BBox(); + var face = loader.face; + var y_scale = 0x10000; + var glyph = loader.glyph; + var size = loader.size; + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0) + y_scale = size.metrics.y_scale; + + if (glyph.format != FT_Common.FT_GLYPH_FORMAT_COMPOSITE) + FT_Outline_Get_CBox(glyph.outline, bbox); + else + { + bbox.xMin = loader.bbox.xMin; + bbox.yMin = loader.bbox.yMin; + bbox.xMax = loader.bbox.xMax; + bbox.yMax = loader.bbox.yMax; + } + + glyph.linearHoriAdvance = loader.linear; + + glyph.metrics.horiBearingX = bbox.xMin; + glyph.metrics.horiBearingY = bbox.yMax; + glyph.metrics.horiAdvance = loader.pp2.x - loader.pp1.x; + + if (face.postscript.isFixedPitch == 0 && (loader.load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) + { + // TODO: + } + + glyph.metrics.width = bbox.xMax - bbox.xMin; + glyph.metrics.height = bbox.yMax - bbox.yMin; + + var top; + var advance; + + if (face.vertical_info === true && face.vertical.number_Of_VMetrics > 0) + { + top = FT_DivFix(loader.pp3.y - bbox.yMax, y_scale); + + if (loader.pp3.y <= loader.pp4.y) + advance = 0; + else + advance = FT_DivFix(loader.pp3.y - loader.pp4.y, y_scale); + } + else + { + var height = FT_DivFix(bbox.yMax - bbox.yMin, y_scale); + if (face.os2.version != 0xFFFF) + advance = face.os2.sTypoAscender - face.os2.sTypoDescender; + else + advance = face.horizontal.Ascender - face.horizontal.Descender; + + top = parseInt((advance - height)/2); + } + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + var metrics = new FT_Incremental_MetricsRec(); + + var incr = face.internal.incremental_interface; + if (incr && incr.funcs.get_glyph_metrics) + { + metrics.bearing_x = 0; + metrics.bearing_y = top; + metrics.advance = advance; + + var error = incr.funcs.get_glyph_metrics(incr.object, glyph_index, true, metrics); + if (error != 0) + return error; + + top = metrics.bearing_y; + advance = metrics.advance; + } + //#endif + + glyph.linearVertAdvance = advance; + + /* scale the metrics */ + if (0 == (loader.load_flags & FT_Common.FT_LOAD_NO_SCALE)) + { + top = FT_MulFix(top, y_scale); + advance = FT_MulFix(advance, y_scale); + } + + glyph.metrics.vertBearingX = glyph.metrics.horiBearingX - parseInt(glyph.metrics.horiAdvance / 2); + glyph.metrics.vertBearingY = top; + glyph.metrics.vertAdvance = advance; + + return 0; +} +function TT_Load_Glyph(size, glyph, glyph_index, load_flags) +{ + var loader = new TT_LoaderRec(); + var face = glyph.face; + var error = 0; + + //#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + if (size.strike_index != 0xFFFFFFFF && ((load_flags & FT_Common.FT_LOAD_NO_BITMAP) == 0)) + { + error = load_sbit_image(size, glyph, glyph_index, load_flags); + if (error == 0) + { + if ((face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) != 0) + { + tt_loader_init(loader, size, glyph, load_flags, true); + load_truetype_glyph(loader, glyph_index, 0, true); + glyph.linearHoriAdvance = loader.linear; + glyph.linearVertAdvance = loader.top_bearing + loader.bbox.yMax - loader.vadvance; + } + + return 0; + } + } + //#endif + + if ((0 == (load_flags & FT_Common.FT_LOAD_NO_SCALE)) && (size.ttmetrics.valid == 0)) + return FT_Common.FT_Err_Invalid_Size_Handle; + + if ((load_flags & FT_Common.FT_LOAD_SBITS_ONLY) != 0) + return FT_Common.FT_Err_Invalid_Argument; + + error = tt_loader_init(loader, size, glyph, load_flags, false); + if (error != 0) + return error; + + glyph.format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + glyph.num_subglyphs = 0; + glyph.outline.flags = 0; + + /* main loading loop */ + error = load_truetype_glyph(loader, glyph_index, 0, false); + if (error == 0) + { + if (glyph.format == FT_Common.FT_GLYPH_FORMAT_COMPOSITE) + { + glyph.num_subglyphs = loader.gloader.base.num_subglyphs; + glyph.subglyphs = loader.gloader.base.subglyphs; + } + else + { + EquatingOutline(glyph.outline, loader.gloader.base.outline); + glyph.outline.flags &= ~FT_Common.FT_OUTLINE_SINGLE_PASS; + + if (loader.pp1.x != 0) + FT_Outline_Translate(glyph.outline, -loader.pp1.x, 0); + } + + if (face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER && ((load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0)) + { + if (loader.exec.GS.scan_control) + { + /* convert scan conversion mode to FT_OUTLINE_XXX flags */ + switch (loader.exec.GS.scan_type) + { + case 0: /* simple drop-outs including stubs */ + glyph.outline.flags |= FT_Common.FT_OUTLINE_INCLUDE_STUBS; + break; + case 1: /* simple drop-outs excluding stubs */ + /* nothing; it's the default rendering mode */ + break; + case 4: /* smart drop-outs including stubs */ + glyph.outline.flags |= (FT_Common.FT_OUTLINE_SMART_DROPOUTS | FT_Common.FT_OUTLINE_INCLUDE_STUBS); + break; + case 5: /* smart drop-outs excluding stubs */ + glyph.outline.flags |= FT_Common.FT_OUTLINE_SMART_DROPOUTS; + break; + + default: /* no drop-out control */ + glyph.outline.flags |= FT_Common.FT_OUTLINE_IGNORE_DROPOUTS; + break; + } + } + else + glyph.outline.flags |= FT_Common.FT_OUTLINE_IGNORE_DROPOUTS; + } + compute_glyph_metrics(loader, glyph_index); + } + + if ((0 == (load_flags & FT_Common.FT_LOAD_NO_SCALE)) && size.metrics.y_ppem < 24) + glyph.outline.flags |= FT_Common.FT_OUTLINE_HIGH_PRECISION; + + return error; +} + +function load_truetype_glyph(loader, glyph_index, recurse_count, header_only) +{ + var error = 0; + var x_scale, y_scale; + var offset; + var face = loader.face; + var gloader = loader.gloader; + var opened_frame = 0; + + var glyph_data; + var glyph_data_loaded = 0; + + if (recurse_count > 1 && recurse_count > face.max_profile.maxComponentDepth ) + return FT_Common.FT_Err_Invalid_Composite; + + if (glyph_index >= face.num_glyphs) + error = FT_Common.FT_Err_Invalid_Glyph_Index; + + loader.glyph_index = glyph_index; + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0) + { + x_scale = loader.size.metrics.x_scale; + y_scale = loader.size.metrics.y_scale; + } + else + { + x_scale = 0x10000; + y_scale = 0x10000; + } + + tt_get_metrics(loader, glyph_index); + + if (face.internal.incremental_interface != null) + { + glyph_data = face.internal.incremental_interface.funcs.get_glyph_data(face.internal.incremental_interface.object, glyph_index); + error = FT_Error; + if (error != 0) + return error; + + glyph_data_loaded = 1; + offset = 0; + loader.byte_len = glyph_data.length; + + loader.stream = new FT_Stream(glyph_data.pointer, glyph_data.length); + } + else + { + var __mem = tt_face_get_location(face, glyph_index); + offset = __mem.loc; + loader.byte_len = __mem.size; + } + + if (loader.byte_len > 0) + { + if (0 == loader.glyf_offset && null == face.internal.incremental_interface) + return FT_Common.FT_Err_Invalid_Table; + + error = face.access_glyph_frame(loader, glyph_index, loader.glyf_offset + offset, loader.byte_len); + if (error != 0) + return error; + + opened_frame = 1; + + error = face.read_glyph_header(loader); + if (error != 0 || header_only) + return error; + } + + if (loader.byte_len == 0 || loader.n_contours == 0) + { + loader.bbox.xMin = 0; + loader.bbox.xMax = 0; + loader.bbox.yMin = 0; + loader.bbox.yMax = 0; + + if (header_only == 1) + return error; + + loader.pp1.x = loader.bbox.xMin - loader.left_bearing; + loader.pp1.y = 0; + loader.pp2.x = loader.pp1.x + loader.advance; + loader.pp2.y = 0; + loader.pp3.x = 0; + loader.pp3.y = loader.top_bearing + loader.bbox.yMax; + loader.pp4.x = 0; + loader.pp4.y = loader.pp3.y - loader.vadvance; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + tt_get_metrics_incr_overrides(loader, glyph_index); + //#endif + + //#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if (loader.face.doblend != 0) + { + var deltas = TT_Vary_Get_Glyph_Deltas(loader.face, glyph_index, 4); + error = FT_Error; + if (error != 0) + return error; + + loader.pp1.x += deltas[0].x; loader.pp1.y += deltas[0].y; + loader.pp2.x += deltas[1].x; loader.pp2.y += deltas[1].y; + loader.pp3.x += deltas[2].x; loader.pp3.y += deltas[2].y; + loader.pp4.x += deltas[3].x; loader.pp4.y += deltas[3].y; + + deltas = null; + } + //#endif + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0) + { + loader.pp1.x = FT_MulFix(loader.pp1.x, x_scale); + loader.pp2.x = FT_MulFix(loader.pp2.x, x_scale); + loader.pp3.y = FT_MulFix(loader.pp3.y, y_scale); + loader.pp4.y = FT_MulFix(loader.pp4.y, y_scale); + } + + error = 0; + return error; + } + + loader.pp1.x = loader.bbox.xMin - loader.left_bearing; + loader.pp1.y = 0; + loader.pp2.x = loader.pp1.x + loader.advance; + loader.pp2.y = 0; + loader.pp3.x = 0; + loader.pp3.y = loader.top_bearing + loader.bbox.yMax; + loader.pp4.x = 0; + loader.pp4.y = loader.pp3.y - loader.vadvance; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + tt_get_metrics_incr_overrides(loader, glyph_index); + //#endif + + if (loader.n_contours > 0) + { + error = face.read_simple_glyph( loader ); + if (error != 0) + return error; + + face.forget_glyph_frame(loader); + opened_frame = 0; + + error = TT_Process_Simple_Glyph(loader); + if (error != 0) + return error; + + FT_GlyphLoader_Add(gloader); + } + else if (loader.n_contours == -1) + { + var start_point = gloader.base.outline.n_points; + var start_contour = gloader.base.outline.n_contours; + + error = face.read_composite_glyph(loader); + if (error != 0) + return error; + + var ins_pos = loader.ins_pos; + + face.forget_glyph_frame( loader ); + opened_frame = 0; + + //#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + if (face.doblend != 0) + { + var deltas = TT_Vary_Get_Glyph_Deltas(face, glyph_index, gloader.current.num_subglyphs + 4); + error = FT_Error; + if (error != 0) + return error; + + var subglyph = gloader.current.subglyphs[gloader.base.num_subglyphs]; + var limit = gloader.current.num_subglyphs; + + var i = 0; + for (; i < limit; ++i, ++subglyph ) + { + if (subglyph.flags & FT_Common.ARGS_ARE_XY_VALUES) + { + subglyph.arg1 += (deltas[i].x & 0xFFFF); + subglyph.arg2 += (deltas[i].y & 0xFFFF); + } + } + + loader.pp1.x += deltas[i + 0].x; loader.pp1.y += deltas[i + 0].y; + loader.pp2.x += deltas[i + 1].x; loader.pp2.y += deltas[i + 1].y; + loader.pp3.x += deltas[i + 2].x; loader.pp3.y += deltas[i + 2].y; + loader.pp4.x += deltas[i + 3].x; loader.pp4.y += deltas[i + 3].y; + + deltas = null; + } + //#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_SCALE) == 0) + { + loader.pp1.x = FT_MulFix(loader.pp1.x, x_scale); + loader.pp2.x = FT_MulFix(loader.pp2.x, x_scale); + loader.pp3.y = FT_MulFix(loader.pp3.y, y_scale); + loader.pp4.y = FT_MulFix(loader.pp4.y, y_scale); + } + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_RECURSE) != 0) + { + FT_GlyphLoader_Add( gloader ); + loader.glyph.format = FT_Common.FT_GLYPH_FORMAT_COMPOSITE; + + return error; + } + + var n, num_base_points; + var subglyph = 0; + + var num_points = start_point; + var num_subglyphs = gloader.current.num_subglyphs; + var num_base_subgs = gloader.base.num_subglyphs; + + var old_stream = loader.stream; + var old_byte_len = loader.byte_len; + + FT_GlyphLoader_Add(gloader); + + for ( n = 0; n < num_subglyphs; n++ ) + { + var pp = new Array(4); + subglyph = gloader.base.subglyphs[num_base_subgs + n]; + + pp[0] = loader.pp1; + pp[1] = loader.pp2; + pp[2] = loader.pp3; + pp[3] = loader.pp4; + + num_base_points = gloader.base.outline.n_points; + + error = load_truetype_glyph(loader, subglyph.index, recurse_count + 1, 0); + if (error != 0) + return error; + + subglyph = gloader.base.subglyphs[num_base_subgs + n]; + + if (0 == (subglyph.flags & 0x0200)) + { + loader.pp1 = pp[0]; + loader.pp2 = pp[1]; + loader.pp3 = pp[2]; + loader.pp4 = pp[3]; + } + + if (gloader.base.outline.n_points == num_base_points) + continue; + + TT_Process_Composite_Component(loader, subglyph, start_point, num_base_points); + } + + loader.stream = old_stream; + loader.byte_len = old_byte_len; + + loader.ins_pos = ins_pos; + + var bIsSubFlags = true; + if (bIsSubFlags && face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER) + bIsSubFlags = ((subglyph.flags & FT_Common.WE_HAVE_INSTR) != 0); + + if (((loader.load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) && bIsSubFlags && num_points > start_point) + TT_Process_Composite_Glyph(loader, start_point, start_contour); + } + else + return FT_Common.FT_Err_Invalid_Outline; + + if (opened_frame == 1) + face.forget_glyph_frame(loader); + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (glyph_data_loaded != 0) + { + face.internal.incremental_interface.funcs.free_glyph_data(face.internal.incremental_interface.object, glyph_data); + glyph_data = null; + } + //#endif + return error; +} +function TT_Init_Glyph_Loading(face) +{ + face.access_glyph_frame = TT_Access_Glyph_Frame; + face.read_glyph_header = TT_Load_Glyph_Header; + face.read_simple_glyph = TT_Load_Simple_Glyph; + face.read_composite_glyph = TT_Load_Composite_Glyph; + face.forget_glyph_frame = TT_Forget_Glyph_Frame; +} +/******************************************************************************/ +// driver +/******************************************************************************/ +var tt_service_truetype_engine = new FT_Service_TrueTypeEngineRec(0); +var tt_service_truetype_glyf = new FT_Service_TTGlyfRec(tt_face_get_location); +var tt_service_gx_multi_masters = new FT_Service_MultiMastersRec(null,null,TT_Set_MM_Blend,TT_Get_MM_Var,TT_Set_Var_Design); +var tt_services = new Array(4); +tt_services[0] = new FT_ServiceDescRec(FT_SERVICE_ID_XF86_NAME,FT_XF86_FORMAT_TRUETYPE); +tt_services[1] = new FT_ServiceDescRec(FT_SERVICE_ID_MULTI_MASTERS,tt_service_gx_multi_masters); +tt_services[2] = new FT_ServiceDescRec(FT_SERVICE_ID_TRUETYPE_ENGINE,tt_service_truetype_engine); +tt_services[3] = new FT_ServiceDescRec(FT_SERVICE_ID_TT_GLYF,tt_service_truetype_glyf); + +var FT_TT_SERVICES_GET = tt_services; +var FT_TT_SERVICE_GX_MULTI_MASTERS_GET = tt_service_gx_multi_masters; +var FT_TT_SERVICE_TRUETYPE_GLYF_GET = tt_service_truetype_glyf; + +function tt_check_trickyness_sfnt_ids(face) +{ + var checksum = 0; + var i = 0; + var j = 0; + var k = 0; + var num_matched_ids = new Array(13); + for (var l = 0; l < 13; l++) + num_matched_ids[l] = 0; + + var TRICK_SFNT_ID_cvt = 0; + var TRICK_SFNT_ID_fpgm = 1; + var TRICK_SFNT_ID_prep = 2; + + var has_cvt = false; + var has_fpgm = false; + var has_prep = false; + + var sfnt_id = face.driver.sfnt_id; + + for (i = 0; i < face.num_tables; i++) + { + checksum = 0; + switch(face.dir_tables[i].Tag) + { + case FT_Common.TTAG_cvt: + k = TRICK_SFNT_ID_cvt; + has_cvt = true; + break; + + case FT_Common.TTAG_fpgm: + k = TRICK_SFNT_ID_fpgm; + has_fpgm = true; + break; + + case FT_Common.TTAG_prep: + k = TRICK_SFNT_ID_prep; + has_prep = true; + break; + + default: + continue; + } + + for ( j = 0; j < 13; j++ ) + if ( face.dir_tables[i].Length == sfnt_id[j][k].Length ) + { + if (checksum != 0) + checksum = tt_get_sfnt_checksum(face, i); + + if (sfnt_id[j][k].CheckSum == checksum) + num_matched_ids[j]++; + + if (num_matched_ids[j] == 3) + return true; + } + } + for (j = 0; j < 13; j++) + { + if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length ) + num_matched_ids[j] ++; + if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length ) + num_matched_ids[j] ++; + if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length ) + num_matched_ids[j] ++; + if (num_matched_ids[j] == 3) + return true; + } + return false; +} +function tt_get_sfnt_checksum(face, i) +{ + if (!face.goto_table) + return 0; + + var len = face.goto_table(face, face.dir_tables[i].Tag, face.stream); + return 0; + + if (FT_Error != FT_Common.FT_Err_Ok) + return 0; + + return tt_synth_sfnt_checksum(face.stream, face.dir_tables[i].Length); +} +function tt_synth_sfnt_checksum(stream, length) +{ + var error = 0; + var checksum = 0; + var i = 0; + + var len = length; + if (FT_Common.FT_Err_Ok != stream.EnterFrame(len)) + return 0; + + for ( ; len > 3; len -= 4 ) + checksum += stream.GetULong(); + + for ( i = 3; len > 0; len --,i--) + checksum += (stream.GetUChar() << (i * 8)); + + stream.ExitFrame(); + return checksum; +} +function tt_check_trickyness(face) +{ + if (!face) + return false; + + if ((face.family_name != "") && (tt_check_trickyness_family(face.family_name) === true)) + return true; + + return tt_check_trickyness_sfnt_ids(face); +} +function tt_check_trickyness_family(name) +{ + if (name == "DFKaiSho-SB") + return true; + if (name == "DFKaiShu") + return true; + if (name == "DFKai-SB") + return true; + if (name == "HuaTianKaiTi?") + return true; + if (name == "HuaTianSongTi?") + return true; + if (name == "MingLiU") + return true; + if (name == "PMingLiU") + return true; + if (name == "MingLi43") + return true; + return false; +} +function tt_face_load_hdmx(face, stream) +{ + var error = FT_Common.FT_Err_Ok; + var version = 0; + var nn = 0; + var num_records = 0; + var table_size = 0; + var record_size = 0; + + table_size = face.goto_table(face, FT_Common.TTAG_hdmx, stream); + if ( (FT_Error != FT_Common.FT_Err_Ok) || table_size < 8 ) + { + FT_Error = 0; + return FT_Common.FT_Err_Ok; + } + + face.hdmx_table = new CPointer(); + error = stream.ExtractFrame(table_size, face.hdmx_table); + if (error != FT_Common.FT_Err_Ok) + return error; + + var p = dublicate_pointer(face.hdmx_table); + var end = p.pos + table_size; + + version = FT_NEXT_USHORT(p); + num_records = FT_NEXT_USHORT(p); + record_size = FT_NEXT_ULONG(p); + + if (record_size >= 0xFFFF0000) + record_size &= 0xFFFF; + + if (version != 0 || num_records > 255 || record_size > 0x10001) + { + error = FT_Common.FT_Err_Invalid_File_Format; + face.hdmx_table = null; + face.hdmx_table_size = 0; + stream.ReleaseFrame(); + return error; + } + + if (0 != num_records) + face.hdmx_record_sizes = new Array(num_records); + + for ( nn = 0; nn < num_records; nn++ ) + { + if ( (p.pos + record_size) > end ) + break; + + face.hdmx_record_sizes[nn] = p.data[p.pos]; + p.pos += record_size; + } + + face.hdmx_record_count = nn; + face.hdmx_table_size = table_size; + face.hdmx_record_size = record_size; + + return error; +} + +function tt_face_load_loca(face, stream) +{ + var error = FT_Common.FT_Err_Ok; + var table_len = 0; + var shift = 0; + + face.glyf_len = face.goto_table(face, FT_Common.TTAG_glyf, stream); + error = FT_Error; + + if ( error == FT_Common.FT_Err_Table_Missing) + face.glyf_len = 0; + else if (error != FT_Common.FT_Err_Ok) + return error; + + table_len = face.goto_table(face, FT_Common.TTAG_loca, stream); + error = FT_Error; + if (error != FT_Common.FT_Err_Ok) + { + error = FT_Common.FT_Err_Locations_Missing; + return error; + } + + if (face.header.Index_To_Loc_Format != 0) + { + shift = 2; + if (table_len >= 0x40000) + { + error = FT_Common.FT_Err_Invalid_Table; + return error; + } + face.num_locations = table_len >>> shift; + } + else + { + shift = 1; + + if (table_len >= 0x20000) + { + error = FT_Common.FT_Err_Invalid_Table; + return error; + } + face.num_locations = table_len >>> shift; + } + + if (face.num_locations != (face.num_glyphs + 1)) + { + if (face.num_locations <= face.num_glyphs) + { + var new_loca_len = (face.num_glyphs + 1) << shift; + + var pos = stream.pos; + var dist = 0x7FFFFFFF; + + var entry = 0; + for (; entry < face.num_tables; entry++) + { + var diff = face.dir_tables[entry].Offset - pos; + if (diff > 0 && diff < dist) + dist = diff; + } + + if (entry == face.num_tables) + { + dist = stream.size - pos; + } + + if (new_loca_len <= dist) + { + face.num_locations = face.num_glyphs + 1; + table_len = new_loca_len; + } + } + } + + face.glyph_locations = new CPointer(); + error = stream.ExtractFrame(table_len, face.glyph_locations); + return error; +} +function tt_face_get_location(face, gindex) +{ + var pos1 = 0; + var pos2 = 0; + var asize = 0; + + pos1 = pos2 = 0; + var p = new CPointer(); + p.data = face.glyph_locations.data; + var pos_s = face.glyph_locations.pos; + var p_limit = 0; + if (gindex < face.num_locations) + { + if (face.header.Index_To_Loc_Format != 0) + { + p.pos = pos_s + gindex * 4; + p_limit = pos_s + face.num_locations * 4; + + pos1 = FT_NEXT_ULONG(p); + pos2 = pos1; + + if (p.pos + 4 <= p_limit) + pos2 = FT_NEXT_ULONG(p); + } + else + { + p.pos = pos_s + gindex * 2; + p_limit = pos_s + face.num_locations * 2; + + pos1 = FT_NEXT_USHORT(p); + pos2 = pos1; + + if (p.pos + 2 <= p_limit) + pos2 = FT_NEXT_USHORT(p); + + pos1 <<= 1; + pos2 <<= 1; + } + } + + if (pos1 >= face.glyf_len) + return {loc:0,size:0}; + + if (pos2 >= face.glyf_len) + pos2 = face.glyf_len; + + if (pos2 >= pos1) + asize = pos2 - pos1; + else + asize = face.glyf_len - pos1; + + return {loc:pos1,size:asize}; +} +function tt_face_load_cvt(face, stream) +{ + //#ifdef TT_USE_BYTECODE_INTERPRETER + if (face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER || true) + { + var table_len = face.goto_table(face, FT_Common.TTAG_cvt, stream); + var error = FT_Error; + FT_Error = 0; + + if (error != 0) + { + face.cvt_size = 0; + face.cvt = null; + return 0; + } + + face.cvt_size = table_len / 2; + face.cvt = CreateIntArray(face.cvt_size); + + error = stream.EnterFrame(table_len); + if (error != 0) + return error; + + for (var i = 0; i < face.cvt_size; i++) + face.cvt[i] = stream.GetShort(); + + //#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if (face.doblend) + error = tt_face_vary_cvt(face, stream); + //#endif + + return error; + } + //#endif + return 0; +} +function tt_face_load_fpgm(face, stream) +{ + //#ifdef TT_USE_BYTECODE_INTERPRETER + if (face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER || true) + { + /* The font program is optional */ + var table_len = face.goto_table(face, FT_Common.TTAG_fpgm, stream); + var error = FT_Error; + FT_Error = 0; + + if (error != 0) + { + face.font_program = null; + face.font_program_size = 0; + error = 0; + return error; + } + else + { + face.font_program_size = table_len; + face.font_program = new CPointer(); + return stream.ExtractFrame(table_len, face.font_program); + } + } + //#endif + return 0; +} +function tt_face_load_prep(face, stream) +{ + //#ifdef TT_USE_BYTECODE_INTERPRETER + if (face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER || true) + { + var table_len = face.goto_table(face, FT_Common.TTAG_prep, stream); + var error = FT_Error; + FT_Error = 0; + + if (error != 0) + { + face.cvt_program = null; + face.cvt_program_size = 0; + return 0; + } + else + { + face.cvt_program_size = table_len; + face.cvt_program = new CPointer(); + return stream.ExtractFrame(table_len, face.cvt_program); + } + } + //#endif + return 0; +} +function tt_check_single_notdef(face) +{ + var result = false; + + var asize = 0; + var i = 0; + var glyph_index = 0; + var count = 0; + + for( i = 0; i < face.num_locations; i++ ) + { + asize = tt_face_get_location(face, i).size; + if ( asize > 0 ) + { + count += 1; + if ( count > 1 ) + break; + glyph_index = i; + } + } + + /* Only have a single outline. */ + if (count == 1) + { + if (glyph_index == 0) + result = true; + else + { + /* FIXME: Need to test glyphname == .notdef ? */ + FT_Error = FT_Common.FT_Err_Ok; + var buffer = g_memory.Alloc(10); + buffer.pos = 0; + + FT_Get_Glyph_Name(face, glyph_index, buffer, 8); + var buf = ""; + for (var i = 0; i < 10; i++) + { + buf += String.fromCharCode(buffer.data[i]); + } + + if (FT_Error != FT_Common.FT_Err_Ok && buf[0] == '.' && (0 == _strncmp(buf,".notdef",8))) + result = true; + } + } + + FT_Error = FT_Common.FT_Err_Ok; + return result; +} + +function tt_driver_init(ttdriver) +{ + var _tt_hint_props = ttdriver.library.tt_hint_props; + if (_tt_hint_props.TT_USE_BYTECODE_INTERPRETER || true) + { + if (!TT_New_Context(ttdriver)) + FT_Common.FT_Err_Could_Not_Find_Context; + } + return 0; +} +function tt_driver_done(ttdriver) +{ + var _tt_hint_props = ttdriver.library.tt_hint_props; + if (_tt_hint_props.TT_USE_BYTECODE_INTERPRETER || true) + { + if (ttdriver.context != null) + { + TT_Done_Context(ttdriver.context); + ttdriver.context = null; + } + } +} +function tt_get_interface(driver, tt_interface) +{ + var result = ft_service_list_lookup(FT_TT_SERVICES_GET, tt_interface); + if (result != null) + return result; + + if (driver == null) + return null; + + var sfntd = driver.library.FT_Get_Module("sfnt"); + if (null != sfntd) + { + var sfnt = sfntd.clazz.module_interface; + if (null != sfnt) + return sfnt.get_interface(driver, tt_interface); + } + return null; +} +function tt_face_init(stream, face, face_index) +{ + var error = FT_Common.FT_Err_Ok; + var library = face.driver.library; + var sfnt = library.FT_Get_Module_Interface("sfnt"); + + error = stream.Seek(0); + if (error != FT_Common.FT_Err_Ok) + return error; + + error = sfnt.init_face(stream, face, face_index); + if (error != FT_Common.FT_Err_Ok) + return error; + + if (face.format_tag != 0x00010000 && face.format_tag != 0x00020000 && face.format_tag != FT_Common.TTAG_true) + { + error = FT_Common.FT_Err_Unknown_File_Format; + return error; + } + + if (library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER || true) + face.face_flags |= FT_Common.FT_FACE_FLAG_HINTER; + + if ( face_index < 0 ) + return FT_Common.FT_Err_Ok; + + error = sfnt.load_face(stream, face, face_index); + if (error != FT_Common.FT_Err_Ok) + return error; + + if (tt_check_trickyness(face) === true) + face.face_flags |= FT_Common.FT_FACE_FLAG_TRICKY; + + error = tt_face_load_hdmx(face, stream); + if (error != FT_Common.FT_Err_Ok) + return error; + + if ((face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) != 0) + { + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (null == face.internal.incremental_interface) + error = tt_face_load_loca(face, stream); + if (error == FT_Common.FT_Err_Ok) + error = tt_face_load_cvt(face, stream); + if (error == FT_Common.FT_Err_Ok) + error = tt_face_load_fpgm(face, stream); + if (error == FT_Common.FT_Err_Ok) + error = tt_face_load_prep(face, stream); + + /* Check the scalable flag based on `loca'. */ + if ((null == face.internal.incremental_interface) && (0 != face.num_fixed_sizes) && (face.glyph_locations != null) && + tt_check_single_notdef(face)) + { + face.face_flags &= ~FT_Common.FT_FACE_FLAG_SCALABLE; + } + //#endif + } + + //#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) + // TODO: + //#endif + + TT_Init_Glyph_Loading(face); + return error; +} +function tt_face_done(face) +{ +} +function tt_size_init() +{ + var size = new TT_SizeRec(); + + //#ifdef TT_USE_BYTECODE_INTERPRETER + size.bytecode_ready = 0; + size.cvt_ready = 0; + //#endif + + size.ttmetrics.valid = 0; + size.strike_index = 0xFFFFFFFF; + + return size; +} +function tt_size_done(size) +{ + //#ifdef TT_USE_BYTECODE_INTERPRETER + if (size.bytecode_ready) + tt_size_done_bytecode(size); + //#endif + size.ttmetrics.valid = 0; +} +function tt_slot_init(slot) +{ + return FT_GlyphLoader_CreateExtra(slot.internal.loader); +} +function Load_Glyph(slot, size, glyph_index, load_flags) +{ + var face = slot.face; + var error = 0; + + if (!slot) + return FT_Common.FT_Err_Invalid_Slot_Handle; + + if (!size) + return FT_Common.FT_Err_Invalid_Size_Handle; + + if (!face) + return FT_Common.FT_Err_Invalid_Argument; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (glyph_index >= face.num_glyphs && (null == face.internal.incremental_interface)) + return FT_Common.FT_Err_Invalid_Argument; + + if ((load_flags & FT_Common.FT_LOAD_NO_HINTING) != 0) + { + if ((face.face_flags & FT_Common.FT_FACE_FLAG_TRICKY) != 0) + load_flags &= ~FT_Common.FT_LOAD_NO_HINTING; + + if ((load_flags & FT_Common.FT_LOAD_NO_AUTOHINT) != 0) + load_flags |= FT_Common.FT_LOAD_NO_HINTING; + } + + if ((load_flags & (FT_Common.FT_LOAD_NO_RECURSE | FT_Common.FT_LOAD_NO_SCALE)) != 0) + { + load_flags |= (FT_Common.FT_LOAD_NO_BITMAP | FT_Common.FT_LOAD_NO_SCALE); + + if ((face.face_flags & FT_Common.FT_FACE_FLAG_TRICKY) == 0) + load_flags |= FT_Common.FT_LOAD_NO_HINTING; + } + + error = TT_Load_Glyph(size, slot, glyph_index, load_flags); + return error; +} +function tt_get_kerning(face, left_glyph, right_glyph, kerning) +{ + kerning.x = 0; + kerning.y = 0; + + if (face.sfnt) + kerning.x = face.sfnt.get_kerning(face, left_glyph, right_glyph); + + return 0; +} +function tt_get_advances(face, start, count, flags, advances) +{ + /* XXX: TODO: check for sbits */ + if ((face.face_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) != 0) + { + for (var nn = 0; nn < count; nn++) + { + var res = TT_Get_VMetrics(face, start + nn); + advances[nn] = res.ah; + } + } + else + { + for (var nn = 0; nn < count; nn++) + { + var res = TT_Get_HMetrics(face, start); + advances[nn] = res.aw; + } + } + + return 0; +} +function tt_size_request(size, req) +{ + var error = 0; + + //#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + if ((size.face.face_flags & FT_Common.FT_FACE_FLAG_FIXED_SIZES) != 0) + { + var sfnt = size.face.sfnt; + var strike_index = sfnt.set_sbit_strike(size.face, req); + + error = FT_Error; + FT_Error = 0; + + if (error != 0) + size.strike_index = 0xFFFFFFFF; + else + return this.select_size(size, strike_index); + } + //#endif + + FT_Request_Metrics(size.face, req); + + if ((size.face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) != 0) + { + error = tt_size_reset(size); + + var s = size._metrics; + var d = size.metrics; + + d.x_ppem = s.x_ppem; + d.y_ppem = s.y_ppem; + + d.x_scale = s.x_scale; + d.y_scale = s.y_scale; + + d.ascender = s.ascender; + d.descender = s.descender; + d.height = s.height; + d.max_advance = s.max_advance; + } + + return error; +} +function tt_size_select(size, strike_index) +{ + var ttface = size.face; + var error = 0; + size.strike_index = strike_index; + + if ((ttface.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) != 0) + { + FT_Select_Metrics(ttface, strike_index); + tt_size_reset(size); + } + else + { + var sfnt = ttface.sfnt; + var metrics = size.metrics; + + error = sfnt.load_strike_metrics(ttface, strike_index, metrics); + if (error != 0) + size.strike_index = 0xFFFFFFFF; + } + return error; +} + +function tt_size_reset(size) +{ + size.ttmetrics.valid = 0; + var face = size.face; + + var d = size._metrics; + var s = size.metrics; + + d.x_ppem = s.x_ppem; + d.y_ppem = s.y_ppem; + + d.x_scale = s.x_scale; + d.y_scale = s.y_scale; + + d.ascender = s.ascender; + d.descender = s.descender; + d.height = s.height; + d.max_advance = s.max_advance; + + if (d.x_ppem < 1 || d.y_ppem < 1) + return FT_Common.FT_Err_Invalid_PPem; + + if (face.header.Flags & 8) + { + d.x_scale = FT_DivFix(d.x_ppem << 6, face.units_per_EM); + d.y_scale = FT_DivFix(d.y_ppem << 6, face.units_per_EM); + + d.ascender = FT_PIX_ROUND(FT_MulFix(face.ascender, d.y_scale)); + d.descender = FT_PIX_ROUND(FT_MulFix(face.descender, d.y_scale)); + d.height = FT_PIX_ROUND(FT_MulFix(face.height, d.y_scale)); + d.max_advance = FT_PIX_ROUND(FT_MulFix(face.max_advance_width, d.x_scale)); + } + + var tt = size.ttmetrics; + /* compute new transformation */ + if (d.x_ppem >= d.y_ppem) + { + tt.scale = d.x_scale; + tt.ppem = d.x_ppem; + tt.x_ratio = 0x10000; + tt.y_ratio = FT_MulDiv(d.y_ppem, 0x10000, d.x_ppem); + } + else + { + tt.scale = d.y_scale; + tt.ppem = d.y_ppem; + tt.x_ratio = FT_MulDiv(d.x_ppem, 0x10000, d.y_ppem); + tt.y_ratio = 0x10000; + } + + //#ifdef TT_USE_BYTECODE_INTERPRETER + // TODO: + //#endif + + size.ttmetrics.valid = 1; + return 0; +} + +function TT_Driver_Class() +{ + this.flags = 0x101; + this.name = "truetype"; + this.version = 0x10000; + this.requires = 0x20000; + + this.module_interface = null; + + this.init = tt_driver_init; + this.done = tt_driver_done; + this.get_interface = tt_get_interface; + + this.face_object_size = 0; + this.size_object_size = 0; + this.slot_object_size = 0; + + this.init_face = tt_face_init; + this.done_face = tt_face_done; + + this.init_size = tt_size_init; + this.done_size = tt_size_done; + + this.init_slot = tt_slot_init; + this.done_slot = null; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.set_char_sizes = ft_stub_set_char_sizes; + this.set_pixel_sizes = ft_stub_set_pixel_sizes; + //#endif + + this.load_glyph = Load_Glyph; + + this.get_kerning = tt_get_kerning; + this.attach_file = null; + this.get_advances = tt_get_advances; + + this.request_size = tt_size_request; + this.select_size = tt_size_select; +} + +function tt_sfnt_id_rec(c,l) +{ + this.CheckSum = c; + this.Length = l; +} + +function TT_Driver() +{ + this.clazz = null; // FT_Module_Class + this.library = null; // FT_Library + this.memory = null; // FT_Memory + this.generic = null; // FT_Generic + + this.clazz = new TT_Driver_Class(); + this.faces_list = []; + this.extensions = null; + this.glyph_loader = null; + + this.context = null; + this.zone = new TT_GlyphZoneRec(); + this.extension_component = null; + + this.open_face = function(stream, face_index) + { + if (null == this.sfnt_id) + { + this.sfnt_id = new Array(13); + this.sfnt_id[0] = new Array(3); + this.sfnt_id[0][0] = new tt_sfnt_id_rec(0x05bcf058, 0x000002e4); + this.sfnt_id[0][1] = new tt_sfnt_id_rec(0x28233bf1, 0x000087c4); + this.sfnt_id[0][2] = new tt_sfnt_id_rec(0xa344a1ea, 0x000001e1); + + this.sfnt_id[1] = new Array(3); + this.sfnt_id[1][0] = new tt_sfnt_id_rec(0x05bcf058, 0x000002e4); + this.sfnt_id[1][1] = new tt_sfnt_id_rec(0x28233bf1, 0x000087c4); + this.sfnt_id[1][2] = new tt_sfnt_id_rec(0xa344a1eb, 0x000001e1); + + this.sfnt_id[2] = new Array(3); + this.sfnt_id[2][0] = new tt_sfnt_id_rec(0x11e5ead4, 0x00000350); + this.sfnt_id[2][1] = new tt_sfnt_id_rec(0x5a30ca3b, 0x00009063); + this.sfnt_id[2][2] = new tt_sfnt_id_rec(0x13a42602, 0x0000007e); + + this.sfnt_id[3] = new Array(3); + this.sfnt_id[3][0] = new tt_sfnt_id_rec(0xfffbfffc, 0x00000008); + this.sfnt_id[3][1] = new tt_sfnt_id_rec(0x9c9e48b8, 0x0000bea2); + this.sfnt_id[3][2] = new tt_sfnt_id_rec(0x70020112, 0x00000008); + + this.sfnt_id[4] = new Array(3); + this.sfnt_id[4][0] = new tt_sfnt_id_rec(0xfffbfffc, 0x00000008); + this.sfnt_id[4][1] = new tt_sfnt_id_rec(0x0a5a0483, 0x00017c39); + this.sfnt_id[4][2] = new tt_sfnt_id_rec(0x70020112, 0x00000008); + + this.sfnt_id[5] = new Array(3); + this.sfnt_id[5][0] = new tt_sfnt_id_rec(0x00000000, 0x00000000); + this.sfnt_id[5][1] = new tt_sfnt_id_rec(0x40c92555, 0x000000e5); + this.sfnt_id[5][2] = new tt_sfnt_id_rec(0xa39b58e3, 0x0000117c); + + this.sfnt_id[6] = new Array(3); + this.sfnt_id[6][0] = new tt_sfnt_id_rec(0x00000000, 0x00000000); + this.sfnt_id[6][1] = new tt_sfnt_id_rec(0x33c41652, 0x000000e5); + this.sfnt_id[6][2] = new tt_sfnt_id_rec(0x26d6c52a, 0x00000f6a); + + this.sfnt_id[7] = new Array(3); + this.sfnt_id[7][0] = new tt_sfnt_id_rec(0x00000000, 0x00000000); + this.sfnt_id[7][1] = new tt_sfnt_id_rec(0x6db1651d, 0x0000019d); + this.sfnt_id[7][2] = new tt_sfnt_id_rec(0x6c6e4b03, 0x00002492); + + this.sfnt_id[8] = new Array(3); + this.sfnt_id[8][0] = new tt_sfnt_id_rec(0x00000000, 0x00000000); + this.sfnt_id[8][1] = new tt_sfnt_id_rec(0x40c92555, 0x000000e5); + this.sfnt_id[8][2] = new tt_sfnt_id_rec(0xde51fad0, 0x0000117c); + + this.sfnt_id[9] = new Array(3); + this.sfnt_id[9][0] = new tt_sfnt_id_rec(0x00000000, 0x00000000); + this.sfnt_id[9][1] = new tt_sfnt_id_rec(0x85e47664, 0x000000e5); + this.sfnt_id[9][2] = new tt_sfnt_id_rec(0xa6c62831, 0x00001caa); + + this.sfnt_id[10] = new Array(3); + this.sfnt_id[10][0] = new tt_sfnt_id_rec(0x00000000, 0x00000000); + this.sfnt_id[10][1] = new tt_sfnt_id_rec(0x2d891cfd, 0x0000019d); + this.sfnt_id[10][2] = new tt_sfnt_id_rec(0xa0604633, 0x00001de8); + + this.sfnt_id[11] = new Array(3); + this.sfnt_id[11][0] = new tt_sfnt_id_rec(0x00000000, 0x00000000); + this.sfnt_id[11][1] = new tt_sfnt_id_rec(0x40aa774c, 0x000001cb); + this.sfnt_id[11][2] = new tt_sfnt_id_rec(0x9b5caa96, 0x00001f9a); + + this.sfnt_id[12] = new Array(3); + this.sfnt_id[12][0] = new tt_sfnt_id_rec(0x00000000, 0x00000000); + this.sfnt_id[12][1] = new tt_sfnt_id_rec(0x0d3de9cb, 0x00000141); + this.sfnt_id[12][2] = new tt_sfnt_id_rec(0xd4127766, 0x00002280); + } + + FT_Error = 0; + var face = new TT_Face(); + var internal = new FT_Face_Internal(); + + face.driver = this; + face.memory = this.memory; + face.stream = stream; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + face.internal = internal; + face.internal.incremental_interface = null; + //#endif + + var err1 = this.clazz.init_face(stream, face, face_index); + + if (err1 != 0) + { + face = null; + FT_Error = err1; + return null; + } + + var err2 = find_unicode_charmap(face); + if (err2 != 0 && err2 != FT_Common.FT_Err_Invalid_CharMap_Handle) + { + face = null; + FT_Error = err2; + return null; + } + + FT_Error = 0; + return face; + } +} + +function create_tt_driver(library) +{ + var driver = new TT_Driver(); + driver.library = library; + driver.memory = library.Memory; + + driver.clazz = new TT_Driver_Class(); + return driver; +} \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/drivers/ttinterp.js b/Common/FontsFreeType/Private/FreeType/drivers/ttinterp.js new file mode 100644 index 0000000000000000000000000000000000000000..db16c8e6cff88e1f292f5f270c17c339584e77fc --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/drivers/ttinterp.js @@ -0,0 +1,6444 @@ +var TT_Round_Off = 5; +var TT_Round_To_Half_Grid = 0; +var TT_Round_To_Grid = 1; +var TT_Round_To_Double_Grid = 2; +var TT_Round_Up_To_Grid = 4; +var TT_Round_Down_To_Grid = 3; +var TT_Round_Super = 6; +var TT_Round_Super_45 = 7; + +function LibraryHintingParams() +{ + this.TT_USE_BYTECODE_INTERPRETER = false; + this.TT_CONFIG_OPTION_SUBPIXEL_HINTING = false; + this.TT_CONFIG_OPTION_UNPATENTED_HINTING = false; + + this.TT_HINTER_FLAG = (this.TT_USE_BYTECODE_INTERPRETER) ? FT_Common.FT_MODULE_DRIVER_HAS_HINTER : 0; + this.TT_CONFIG_OPTION_INTERPRETER_SWITCH = false; +} + +function TT_CallRec() +{ + this.Caller_Range = 0; + this.Caller_IP = 0; + this.Cur_Count = 0; + this.Cur_Restart = 0; + this.Cur_End = 0; +} + +function SPH_TweakRule() +{ + this.family = ""; + this.ppem = 0; + this.style = ""; + this.glyph = 0; +} + +function SPH_ScaleRule() +{ + this.family = ""; + this.ppem = 0; + this.style = ""; + this.glyph = 0; + this.scale = 0; +} + +var MAX_NAME_SIZE = 32; +var MAX_CLASS_MEMBERS = 100; + +function Font_Class() +{ + this.name = ""; + this.member = null; +} +function create_font_class(name, arr) +{ + var fc = new Font_Class(); + fc.name = name; + fc.member = arr; + return fc; +} + +function FT_UnitVector() +{ + this.x = 0; + this.y = 0; +} + +function TT_GraphicsState() +{ + this.rp0 = 0; + this.rp1 = 0; + this.rp2 = 0; + + this.dualVector = new FT_UnitVector(); + this.projVector = new FT_UnitVector(); + this.freeVector = new FT_UnitVector(); + + // #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + this.both_x_axis = false; + // #endif + + this.loop = 0; + this.minimum_distance = 0; + this.round_state = 0; + + this.auto_flip = false; + this.control_value_cutin = 0; + this.single_width_cutin = 0; + this.single_width_value = 0; + this.delta_base = 0; + this.delta_shift = 0; + + this.instruct_control = 0; + /* According to Greg Hitchcock from Microsoft, the `scan_control' */ + /* variable as documented in the TrueType specification is a 32-bit */ + /* integer; the high-word part holds the SCANTYPE value, the low-word */ + /* part the SCANCTRL value. We separate it into two fields. */ + this.scan_control = false; + this.scan_type = 0; + + this.gep0 = 0; + this.gep1 = 0; + this.gep2 = 0; +} +TT_GraphicsState.prototype = +{ + default_tt : function() + { + this.rp0 = 0; + this.rp1 = 0; + this.rp2 = 0; + + this.dualVector.x = 0x4000; this.dualVector.y = 0; + this.projVector.x = 0x4000; this.projVector.y = 0; + this.freeVector.x = 0x4000; this.freeVector.y = 0; + + this.both_x_axis = true; + + this.loop = 1; + this.minimum_distance = 64; + this.round_state = 1; + + this.auto_flip = true; + this.control_value_cutin = 68; + this.single_width_cutin = 0; + this.single_width_value = 0; + this.delta_base = 9; + this.delta_shift = 3; + + this.instruct_control = 0; + /* According to Greg Hitchcock from Microsoft, the `scan_control' */ + /* variable as documented in the TrueType specification is a 32-bit */ + /* integer; the high-word part holds the SCANTYPE value, the low-word */ + /* part the SCANCTRL value. We separate it into two fields. */ + this.scan_control = false; + this.scan_type = 0; + + this.gep0 = 1; + this.gep1 = 1; + this.gep2 = 1; + }, + + Copy : function(dst) + { + dst.rp0 = this.rp0; + dst.rp1 = this.rp1; + dst.rp2 = this.rp2; + + dst.dualVector.x = this.dualVector.x; dst.dualVector.y = this.dualVector.y; + dst.projVector.x = this.projVector.x; dst.projVector.y = this.projVector.y; + dst.freeVector.x = this.freeVector.x; dst.freeVector.y = this.freeVector.y; + + dst.both_x_axis = this.both_x_axis; + + dst.loop = this.loop; + dst.minimum_distance = this.minimum_distance; + dst.round_state = this.round_state; + + dst.auto_flip = this.auto_flip; + dst.control_value_cutin = this.control_value_cutin; + dst.single_width_cutin = this.single_width_cutin; + dst.single_width_value = this.single_width_value; + dst.delta_base = this.delta_base; + dst.delta_shift = this.delta_shift; + + dst.instruct_control = this.instruct_control; + /* According to Greg Hitchcock from Microsoft, the `scan_control' */ + /* variable as documented in the TrueType specification is a 32-bit */ + /* integer; the high-word part holds the SCANTYPE value, the low-word */ + /* part the SCANCTRL value. We separate it into two fields. */ + dst.scan_control = this.scan_control; + dst.scan_type = this.scan_type; + + dst.gep0 = this.gep0; + dst.gep1 = this.gep1; + dst.gep2 = this.gep2; + } +} + +function TT_DefRecord() +{ + this.range = 0; /* in which code range is it located? */ + this.start = 0; /* where does it start? */ + this.end = 0; /* where does it end? */ + this.opc = 0; /* function #, or instruction code */ + this.active = false; /* is it active? */ + this.inline_delta = false; /* is function that defines inline delta? */ +} + +function TT_CodeRange() +{ + this.base = null; + this.size = 0; +} +function coderange_copy(d, s) +{ + d.base = dublicate_pointer(s.base); + d.size = s.size; +} + +function TT_ExecContextRec() +{ + this.face = null; + this.size = null; + this.memory = null; + + /* instructions state */ + this.error = 0; /* last execution error */ + this.top = 0; /* top of exec. stack */ + + this.stackSize = 0; /* size of exec. stack */ + this.stack = null; /* current exec. stack */ + + this.args = 0; + this.new_top = 0; /* new top after exec. */ + + this.zp0 = new TT_GlyphZoneRec(); + this.zp1 = new TT_GlyphZoneRec(); + this.zp2 = new TT_GlyphZoneRec(); + this.pts = new TT_GlyphZoneRec(); + this.twilight = new TT_GlyphZoneRec(); + + this.metrics = new FT_Size_Metrics(); + this.tt_metrics = new TT_Size_Metrics(); /* size metrics */ + + this.GS = new TT_GraphicsState(); /* current graphics state */ + + this.curRange = 0; /* current code range number */ + this.code = null; /* current code range */ + this.IP = 0; /* current instruction pointer */ + this.codeSize = 0; /* size of current range */ + + this.opcode = 0; /* current opcode */ + this.length = 0; /* length of current opcode */ + + this.step_ins = false; /* true if the interpreter must */ + /* increment IP after ins. exec */ + this.cvtSize = 0; + this.cvt = null; + + this.glyphSize = 0; /* glyph instructions buffer size */ + this.glyphIns = null; /* glyph instructions buffer */ + + this.numFDefs = 0; /* number of function defs */ + this.maxFDefs = 0; /* maximum number of function defs */ + this.FDefs = null; /* table of FDefs entries */ + + this.numIDefs = 0; /* number of instruction defs */ + this.maxIDefs = 0; /* maximum number of ins defs */ + this.IDefs = null; /* table of IDefs entries */ + + this.maxFunc = 0; /* maximum function index */ + this.maxIns = 0; /* maximum instruction index */ + + this.callTop = 0; /* top of call stack during execution */ + this.callSize = 0; /* size of call stack */ + this.callStack = null; /* call stack */ + + this.maxPoints = 0; /* capacity of this context's `pts' */ + this.maxContours = 0; /* record, expressed in points and */ + /* contours. */ + + /* table of valid code ranges */ + /* useful for the debugger */ + this.codeRangeTable = new Array(FT_Common.TT_MAX_CODE_RANGES); + for (var i = 0; i < FT_Common.TT_MAX_CODE_RANGES; i++) + this.codeRangeTable[i] = new TT_CodeRange(); + + this.storeSize = 0; /* size of current storage */ + this.storage = null; /* storage area */ + + this.period = 0; /* values used for the */ + this.phase = 0; /* `SuperRounding' */ + this.threshold = 0; + + //#if 0 + /* this seems to be unused */ + //FT_Int cur_ppem; /* ppem along the current proj vector */ + //#endif + + this.instruction_trap = false; /* If `True', the interpreter will */ + /* exit after each instruction */ + + this.default_GS = new TT_GraphicsState(); /* graphics state resulting from */ + /* the prep program */ + this.is_composite = false; /* true if the glyph is composite */ + this.pedantic_hinting = false; /* true if pedantic interpretation */ + + /* latest interpreter additions */ + this.F_dot_P = 0; /* dot product of freedom and projection */ + /* vectors */ + this.func_round = null; /* current rounding function */ + + this.func_project = null; /* current projection function */ + this.func_dualproj = null; /* current dual proj. function */ + this.func_freeProj = null; /* current freedom proj. func */ + + this.func_move = null; /* current point move function */ + this.func_move_orig = null; /* move original position function */ + + this.func_read_cvt = null; /* read a cvt entry */ + this.func_write_cvt = null; /* write a cvt entry (in pixels) */ + this.func_move_cvt = null; /* incr a cvt entry (in pixels) */ + + this.grayscale = false; /* are we hinting for grayscale? */ + + // #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + this.func_round_sphn = null; /* subpixel rounding function */ + + this.grayscale_hinting = false; /* Using grayscale hinting? */ + this.subpixel_hinting = false; /* Using subpixel hinting? */ + this.native_hinting = false; /* Using native hinting? */ + this.ignore_x_mode = false; /* Standard rendering mode for */ + /* subpixel hinting. On if gray */ + /* or subpixel hinting is on ) */ + this.compatibility_mode = false; /* Additional exceptions to */ + /* native TT rules for legacy */ + /* fonts. Implies */ + /* ignore_x_mode. */ + + /* The following 4 aren't fully implemented but here for MS rasterizer */ + /* compatibility. */ + this.compatible_widths = false; /* compatible widths? */ + this.symmetrical_smoothing = false; /* symmetrical_smoothing? */ + this.bgr = false; /* bgr instead of rgb? */ + this.subpixel_positioned = false; /* subpixel positioned */ + /* (DirectWrite ClearType)? */ + + this.rasterizer_version = 0; /* MS rasterizer version */ + + this.iup_called = false; /* IUP called for glyph? */ + + this.sph_tweak_flags = 0; /* flags to control */ + /* hint tweaks */ + // #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ +} + +function Init_Context(exec, memory) +{ + exec.memory = memory; + exec.callSize = 32; + + exec.callStack = new Array(exec.callSize); + for (var i = 0; i < exec.callSize; i++) + exec.callStack[i] = new TT_CallRec(); + + /* all values in the context are set to 0 already, but this is */ + /* here as a remainder */ + exec.maxPoints = 0; + exec.maxContours = 0; + + exec.stackSize = 0; + exec.glyphSize = 0; + + exec.stack = null; + exec.glyphIns = null; + + exec.face = null; + exec.size = null; + + return 0; +} + +function TT_New_Context(driver) +{ + if (driver.context == null) + { + driver.context = new TT_ExecContextRec(); + + /* initialize it; in case of error this deallocates `exec' too */ + var error = Init_Context(driver.context, driver.memory); + if (error != 0) + driver.context = null; + } + return driver.context; +} + +function TT_Done_Context(exec) +{ + /* points zone */ + exec.maxPoints = 0; + exec.maxContours = 0; + + /* free stack */ + exec.stack = null; + exec.stackSize = 0; + + /* free call stack */ + exec.callStack = null; + exec.callSize = 0; + exec.callTop = 0; + + /* free glyph code range */ + exec.glyphIns = null; + exec.glyphSize = 0; + + exec.size = null; + exec.face = null; + + return 0; +} + +function TT_Load_Context(exec, face, size) +{ + exec.face = face; + var maxp = face.max_profile; + exec.size = size; + + if (size != null) + { + exec.numFDefs = size.num_function_defs; + exec.maxFDefs = size.max_function_defs; + exec.numIDefs = size.num_instruction_defs; + exec.maxIDefs = size.max_instruction_defs; + exec.FDefs = size.function_defs; + exec.IDefs = size.instruction_defs; + exec.tt_metrics.Copy(size.ttmetrics); + exec.metrics.Copy(size.metrics); + + exec.maxFunc = size.max_func; + exec.maxIns = size.max_ins; + + for (var i = 0; i < FT_Common.TT_MAX_CODE_RANGES; i++) + coderange_copy(exec.codeRangeTable[i], size.codeRangeTable[i]); + + /* set graphics state */ + size.GS.Copy(exec.GS); + + exec.cvtSize = size.cvt_size; + exec.cvt = size.cvt; + + exec.storeSize = size.storage_size; + exec.storage = size.storage; + + exec.twilight.Copy(size.twilight); + + /* In case of multi-threading it can happen that the old size object */ + /* no longer exists, thus we must clear all glyph zone references. */ + exec.zp0.Clear(); + exec.zp1.Clear(); + exec.zp2.Clear(); + } + + /* XXX: We reserve a little more elements on the stack to deal safely */ + /* with broken fonts like arialbs, courbs, timesbs, etc. */ + var ret = Update_MaxLONG(exec.memory, exec.stackSize, exec.stack, maxp.maxStackElements + 32); + if (null != ret) + { + exec.stackSize = ret.size; + exec.stack = ret.block; + + if (ret.err != 0) + return ret.err; + } + + ret = Update_MaxBYTE(exec.memory, exec.glyphSize, exec.glyphIns, maxp.maxSizeOfInstructions); + if (ret != null) + { + exec.glyphSize = ret.size; + exec.glyphIns = ret.block; + + if (ret.err != 0) + return ret.err; + } + + exec.pts.n_points = 0; + exec.pts.n_contours = 0; + + exec.zp1.Copy(exec.pts); + exec.zp2.Copy(exec.pts); + exec.zp0.Copy(exec.pts); + + exec.instruction_trap = false; + + return 0; +} + +function Update_MaxBYTE(memory, size, buff, new_max) +{ + if (size >= new_max) + return null; + + return FT_Common.realloc(memory, buff, size, new_max); +} +function Update_MaxLONG(memory, size, buff, new_max) +{ + if (size >= new_max) + return null; + + return FT_Common.realloc_long(memory, buff, size, new_max); +} + +function tt_size_ready_bytecode(size, pedantic) +{ + var error = 0; + if (!size.bytecode_ready) + { + error = tt_size_init_bytecode(size, pedantic); + if (error != 0) + return error; + } + + /* rescale CVT when needed */ + if (!size.cvt_ready) + { + var face = size.face; + + /* Scale the cvt values to the new ppem. */ + /* We use by default the y ppem to scale the CVT. */ + for (var i = 0; i < size.cvt_size; i++) + size.cvt[i] = FT_MulFix(face.cvt[i], size.ttmetrics.scale); + + /* all twilight points are originally zero */ + for (var i = 0; i < size.twilight.n_points; i++ ) + { + size.twilight.org[size.twilight._offset_org + i].x = 0; + size.twilight.org[size.twilight._offset_org + i].y = 0; + size.twilight.cur[size.twilight._offset_cur + i].x = 0; + size.twilight.cur[size.twilight._offset_cur + i].y = 0; + } + + /* clear storage area */ + for (var i = 0; i < size.storage_size; i++) + size.storage[i] = 0; + + size.GS.default_tt(); + + error = tt_size_run_prep(size, pedantic); + if (error != 0) + size.cvt_ready = 1; + } + return error; +} + +function tt_size_init_bytecode(size, pedantic) +{ + var maxp = size.face.max_profile; + + size.bytecode_ready = 1; + size.cvt_ready = 0; + + size.max_function_defs = maxp.maxFunctionDefs; + size.max_instruction_defs = maxp.maxInstructionDefs; + + size.num_function_defs = 0; + size.num_instruction_defs = 0; + + size.max_func = 0; + size.max_ins = 0; + + size.cvt_size = size.face.cvt_size; + size.storage_size = maxp.maxStorage; + + /* Set default metrics */ + var metrics = size.ttmetrics; + metrics.rotated = false; + metrics.stretched = false; + + /* set default compensation (all 0) */ + for (var i = 0; i < 4; i++) + metrics.compensations[i] = 0; + + /* allocate function defs, instruction defs, cvt, and storage area */ + size.function_defs = new Array(size.max_function_defs); + for (var i = 0; i < size.max_function_defs; i++) + size.function_defs[i] = new TT_DefRecord(); + + size.instruction_defs = new Array(size.max_instruction_defs); + for (var i = 0; i < size.max_instruction_defs; i++) + size.instruction_defs[i] = new TT_DefRecord(); + + size.cvt = new CreateIntArray(size.cvt_size); + size.storage = new CreateIntArray(size.storage_size); + + /* reserve twilight zone */ + var n_twilight = maxp.maxTwilightPoints; + + /* there are 4 phantom points (do we need this?) */ + n_twilight += 4; + + var error = tt_glyphzone_new(size.face.memory, n_twilight, 0, size.twilight); + if (error != 0) + { + tt_size_done_bytecode(size); + return error; + } + + size.twilight.n_points = n_twilight; + + size.GS.default_tt(); + size.face.interpreter = TT_RunIns; + + /* Fine, now run the font program! */ + error = tt_size_run_fpgm(size, pedantic); + if (error != 0) + tt_size_done_bytecode(size); + + return error; +} + +function tt_size_run_fpgm(size, pedantic) +{ + var face = size.face; + var exec = null; + + /* debugging instances have their own context */ + if (size.debug) + exec = size.context; + else + exec = face.driver.context; + + if (exec == null) + return FT_Common.FT_Err_Could_Not_Find_Context; + + TT_Load_Context(exec, face, size); + + exec.callTop = 0; + exec.top = 0; + + exec.period = 64; + exec.phase = 0; + exec.threshold = 0; + + exec.instruction_trap = false; + exec.F_dot_P = 0x4000; + + exec.pedantic_hinting = pedantic; + + var metrics = exec.metrics; + var tt_metrics = exec.tt_metrics; + + metrics.x_ppem = 0; + metrics.y_ppem = 0; + metrics.x_scale = 0; + metrics.y_scale = 0; + + tt_metrics.ppem = 0; + tt_metrics.scale = 0; + tt_metrics.ratio = 0x10000; + + /* allow font program execution */ + TT_Set_CodeRange(exec, FT_Common.tt_coderange_font, face.font_program, face.font_program_size); + + /* disable CVT and glyph programs coderange */ + TT_Clear_CodeRange(exec, FT_Common.tt_coderange_cvt); + TT_Clear_CodeRange(exec, FT_Common.tt_coderange_glyph); + + var error = 0; + if (face.font_program_size > 0) + { + error = TT_Goto_CodeRange(exec, FT_Common.tt_coderange_font, 0); + if (error == 0) + error = face.interpreter(exec); + } + else + error = 0; + + if (error == 0) + TT_Save_Context(exec, size); + + return error; +} + +function TT_Clear_CodeRange(exec, range) +{ + exec.codeRangeTable[range - 1].base = null; + exec.codeRangeTable[range - 1].size = 0; + + return 0; +} + +function TT_Save_Context(exec, size) +{ + /* XXX: Will probably disappear soon with all the code range */ + /* management, which is now rather obsolete. */ + /* */ + size.num_function_defs = exec.numFDefs; + size.num_instruction_defs = exec.numIDefs; + + size.max_func = exec.maxFunc; + size.max_ins = exec.maxIns; + + for (var i = 0; i < FT_Common.TT_MAX_CODE_RANGES; i++) + { + size.codeRangeTable[i].base = dublicate_pointer(exec.codeRangeTable[i].base); + size.codeRangeTable[i].size = exec.codeRangeTable[i].size; + } + + return 0; +} + +function tt_size_done_bytecode(size) +{ + if (size.debug) + { + /* the debug context must be deleted by the debugger itself */ + size.context = null; + size.debug = false; + } + + size.cvt = null; + size.cvt_size = 0; + + /* free storage area */ + size.storage = null; + size.storage_size = 0; + + /* twilight zone */ + tt_glyphzone_done(size.twilight); + + size.function_defs = null; + size.instruction_defs = null; + + size.num_function_defs = 0; + size.max_function_defs = 0; + size.num_instruction_defs = 0; + size.max_instruction_defs = 0; + + size.max_func = 0; + size.max_ins = 0; + + size.bytecode_ready = false; + size.cvt_ready = false; +} + +function tt_glyphzone_done(zone) +{ + if (zone.memory != null) + { + zone.contours = null; + zone.tags = null; + zone.cur = null; + zone.org = null; + zone.orus = null; + + zone.max_points = zone.n_points = 0; + zone.max_contours = zone.n_contours = 0; + zone.memory = null; + } +} + +function tt_glyphzone_new(memory, maxPoints, maxContours, zone) +{ + zone.Clear(); + zone.memory = memory; + + zone.org = new Array(maxPoints); + FT_CreateVectorArray(zone.org, 0, maxPoints); + + zone.cur = new Array(maxPoints); + FT_CreateVectorArray(zone.cur, 0, maxPoints); + + zone.orus = new Array(maxPoints); + FT_CreateVectorArray(zone.orus, 0, maxPoints); + + zone.tags = CreateIntArray(maxPoints); + zone.contours = CreateIntArray(maxContours); + + zone.max_points = maxPoints; + zone.max_contours = maxContours; + return 0; +} + +function TT_Set_CodeRange(exec, range, base, length) +{ + exec.codeRangeTable[range - 1].base = dublicate_pointer(base); + exec.codeRangeTable[range - 1].size = length; + + return 0; +} + +function TT_Goto_CodeRange(exec, range, IP) +{ + var coderange = exec.codeRangeTable[range - 1]; + + /* NOTE: Because the last instruction of a program may be a CALL */ + /* which will return to the first byte *after* the code */ + /* range, we test for IP <= Size instead of IP < Size. */ + /* */ + exec.code = dublicate_pointer(coderange.base); + exec.codeSize = coderange.size; + exec.IP = IP; + exec.curRange = range; + + return 0; +} + +function TT_Run_Context(exec, debug) +{ + var error = TT_Goto_CodeRange(exec, FT_Common.tt_coderange_glyph, 0); + if (error != 0) + return error; + + exec.zp0.Copy(exec.pts); + exec.zp1.Copy(exec.pts); + exec.zp2.Copy(exec.pts); + + exec.GS.gep0 = 1; + exec.GS.gep1 = 1; + exec.GS.gep2 = 1; + + exec.GS.projVector.x = 0x4000; + exec.GS.projVector.y = 0x0000; + + exec.GS.freeVector.x = exec.GS.projVector.x; + exec.GS.freeVector.y = exec.GS.projVector.y; + exec.GS.dualVector.x = exec.GS.projVector.x; + exec.GS.dualVector.y = exec.GS.projVector.y; + + if (exec.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING)//#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + { + exec.GS.both_x_axis = true; + }//#endif + + exec.GS.round_state = 1; + exec.GS.loop = 1; + + /* some glyphs leave something on the stack. so we clean it */ + /* before a new execution. */ + exec.top = 0; + exec.callTop = 0; + + return exec.face.interpreter(exec); +} + +//--------------------------------------------------------------// + +var opcode_length = +[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +-1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17, + +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + +function Pop_Push_PACK(x, y) +{ + return ((x << 4) | y); +} +var Pop_Push_Count = +[ + /* opcodes are gathered in groups of 16 */ + /* please keep the spaces as they are */ + + /* SVTCA y */ Pop_Push_PACK( 0, 0 ), + /* SVTCA x */ Pop_Push_PACK( 0, 0 ), + /* SPvTCA y */ Pop_Push_PACK( 0, 0 ), + /* SPvTCA x */ Pop_Push_PACK( 0, 0 ), + /* SFvTCA y */ Pop_Push_PACK( 0, 0 ), + /* SFvTCA x */ Pop_Push_PACK( 0, 0 ), + /* SPvTL // */ Pop_Push_PACK( 2, 0 ), + /* SPvTL + */ Pop_Push_PACK( 2, 0 ), + /* SFvTL // */ Pop_Push_PACK( 2, 0 ), + /* SFvTL + */ Pop_Push_PACK( 2, 0 ), + /* SPvFS */ Pop_Push_PACK( 2, 0 ), + /* SFvFS */ Pop_Push_PACK( 2, 0 ), + /* GPV */ Pop_Push_PACK( 0, 2 ), + /* GFV */ Pop_Push_PACK( 0, 2 ), + /* SFvTPv */ Pop_Push_PACK( 0, 0 ), + /* ISECT */ Pop_Push_PACK( 5, 0 ), + + /* SRP0 */ Pop_Push_PACK( 1, 0 ), + /* SRP1 */ Pop_Push_PACK( 1, 0 ), + /* SRP2 */ Pop_Push_PACK( 1, 0 ), + /* SZP0 */ Pop_Push_PACK( 1, 0 ), + /* SZP1 */ Pop_Push_PACK( 1, 0 ), + /* SZP2 */ Pop_Push_PACK( 1, 0 ), + /* SZPS */ Pop_Push_PACK( 1, 0 ), + /* SLOOP */ Pop_Push_PACK( 1, 0 ), + /* RTG */ Pop_Push_PACK( 0, 0 ), + /* RTHG */ Pop_Push_PACK( 0, 0 ), + /* SMD */ Pop_Push_PACK( 1, 0 ), + /* ELSE */ Pop_Push_PACK( 0, 0 ), + /* JMPR */ Pop_Push_PACK( 1, 0 ), + /* SCvTCi */ Pop_Push_PACK( 1, 0 ), + /* SSwCi */ Pop_Push_PACK( 1, 0 ), + /* SSW */ Pop_Push_PACK( 1, 0 ), + + /* DUP */ Pop_Push_PACK( 1, 2 ), + /* POP */ Pop_Push_PACK( 1, 0 ), + /* CLEAR */ Pop_Push_PACK( 0, 0 ), + /* SWAP */ Pop_Push_PACK( 2, 2 ), + /* DEPTH */ Pop_Push_PACK( 0, 1 ), + /* CINDEX */ Pop_Push_PACK( 1, 1 ), + /* MINDEX */ Pop_Push_PACK( 1, 0 ), + /* AlignPTS */ Pop_Push_PACK( 2, 0 ), + /* INS_$28 */ Pop_Push_PACK( 0, 0 ), + /* UTP */ Pop_Push_PACK( 1, 0 ), + /* LOOPCALL */ Pop_Push_PACK( 2, 0 ), + /* CALL */ Pop_Push_PACK( 1, 0 ), + /* FDEF */ Pop_Push_PACK( 1, 0 ), + /* ENDF */ Pop_Push_PACK( 0, 0 ), + /* MDAP[0] */ Pop_Push_PACK( 1, 0 ), + /* MDAP[1] */ Pop_Push_PACK( 1, 0 ), + + /* IUP[0] */ Pop_Push_PACK( 0, 0 ), + /* IUP[1] */ Pop_Push_PACK( 0, 0 ), + /* SHP[0] */ Pop_Push_PACK( 0, 0 ), + /* SHP[1] */ Pop_Push_PACK( 0, 0 ), + /* SHC[0] */ Pop_Push_PACK( 1, 0 ), + /* SHC[1] */ Pop_Push_PACK( 1, 0 ), + /* SHZ[0] */ Pop_Push_PACK( 1, 0 ), + /* SHZ[1] */ Pop_Push_PACK( 1, 0 ), + /* SHPIX */ Pop_Push_PACK( 1, 0 ), + /* IP */ Pop_Push_PACK( 0, 0 ), + /* MSIRP[0] */ Pop_Push_PACK( 2, 0 ), + /* MSIRP[1] */ Pop_Push_PACK( 2, 0 ), + /* AlignRP */ Pop_Push_PACK( 0, 0 ), + /* RTDG */ Pop_Push_PACK( 0, 0 ), + /* MIAP[0] */ Pop_Push_PACK( 2, 0 ), + /* MIAP[1] */ Pop_Push_PACK( 2, 0 ), + + /* NPushB */ Pop_Push_PACK( 0, 0 ), + /* NPushW */ Pop_Push_PACK( 0, 0 ), + /* WS */ Pop_Push_PACK( 2, 0 ), + /* RS */ Pop_Push_PACK( 1, 1 ), + /* WCvtP */ Pop_Push_PACK( 2, 0 ), + /* RCvt */ Pop_Push_PACK( 1, 1 ), + /* GC[0] */ Pop_Push_PACK( 1, 1 ), + /* GC[1] */ Pop_Push_PACK( 1, 1 ), + /* SCFS */ Pop_Push_PACK( 2, 0 ), + /* MD[0] */ Pop_Push_PACK( 2, 1 ), + /* MD[1] */ Pop_Push_PACK( 2, 1 ), + /* MPPEM */ Pop_Push_PACK( 0, 1 ), + /* MPS */ Pop_Push_PACK( 0, 1 ), + /* FlipON */ Pop_Push_PACK( 0, 0 ), + /* FlipOFF */ Pop_Push_PACK( 0, 0 ), + /* DEBUG */ Pop_Push_PACK( 1, 0 ), + + /* LT */ Pop_Push_PACK( 2, 1 ), + /* LTEQ */ Pop_Push_PACK( 2, 1 ), + /* GT */ Pop_Push_PACK( 2, 1 ), + /* GTEQ */ Pop_Push_PACK( 2, 1 ), + /* EQ */ Pop_Push_PACK( 2, 1 ), + /* NEQ */ Pop_Push_PACK( 2, 1 ), + /* ODD */ Pop_Push_PACK( 1, 1 ), + /* EVEN */ Pop_Push_PACK( 1, 1 ), + /* IF */ Pop_Push_PACK( 1, 0 ), + /* EIF */ Pop_Push_PACK( 0, 0 ), + /* AND */ Pop_Push_PACK( 2, 1 ), + /* OR */ Pop_Push_PACK( 2, 1 ), + /* NOT */ Pop_Push_PACK( 1, 1 ), + /* DeltaP1 */ Pop_Push_PACK( 1, 0 ), + /* SDB */ Pop_Push_PACK( 1, 0 ), + /* SDS */ Pop_Push_PACK( 1, 0 ), + + /* ADD */ Pop_Push_PACK( 2, 1 ), + /* SUB */ Pop_Push_PACK( 2, 1 ), + /* DIV */ Pop_Push_PACK( 2, 1 ), + /* MUL */ Pop_Push_PACK( 2, 1 ), + /* ABS */ Pop_Push_PACK( 1, 1 ), + /* NEG */ Pop_Push_PACK( 1, 1 ), + /* FLOOR */ Pop_Push_PACK( 1, 1 ), + /* CEILING */ Pop_Push_PACK( 1, 1 ), + /* ROUND[0] */ Pop_Push_PACK( 1, 1 ), + /* ROUND[1] */ Pop_Push_PACK( 1, 1 ), + /* ROUND[2] */ Pop_Push_PACK( 1, 1 ), + /* ROUND[3] */ Pop_Push_PACK( 1, 1 ), + /* NROUND[0] */ Pop_Push_PACK( 1, 1 ), + /* NROUND[1] */ Pop_Push_PACK( 1, 1 ), + /* NROUND[2] */ Pop_Push_PACK( 1, 1 ), + /* NROUND[3] */ Pop_Push_PACK( 1, 1 ), + + /* WCvtF */ Pop_Push_PACK( 2, 0 ), + /* DeltaP2 */ Pop_Push_PACK( 1, 0 ), + /* DeltaP3 */ Pop_Push_PACK( 1, 0 ), + /* DeltaCn[0] */ Pop_Push_PACK( 1, 0 ), + /* DeltaCn[1] */ Pop_Push_PACK( 1, 0 ), + /* DeltaCn[2] */ Pop_Push_PACK( 1, 0 ), + /* SROUND */ Pop_Push_PACK( 1, 0 ), + /* S45Round */ Pop_Push_PACK( 1, 0 ), + /* JROT */ Pop_Push_PACK( 2, 0 ), + /* JROF */ Pop_Push_PACK( 2, 0 ), + /* ROFF */ Pop_Push_PACK( 0, 0 ), + /* INS_$7B */ Pop_Push_PACK( 0, 0 ), + /* RUTG */ Pop_Push_PACK( 0, 0 ), + /* RDTG */ Pop_Push_PACK( 0, 0 ), + /* SANGW */ Pop_Push_PACK( 1, 0 ), + /* AA */ Pop_Push_PACK( 1, 0 ), + + /* FlipPT */ Pop_Push_PACK( 0, 0 ), + /* FlipRgON */ Pop_Push_PACK( 2, 0 ), + /* FlipRgOFF */ Pop_Push_PACK( 2, 0 ), + /* INS_$83 */ Pop_Push_PACK( 0, 0 ), + /* INS_$84 */ Pop_Push_PACK( 0, 0 ), + /* ScanCTRL */ Pop_Push_PACK( 1, 0 ), + /* SDPVTL[0] */ Pop_Push_PACK( 2, 0 ), + /* SDPVTL[1] */ Pop_Push_PACK( 2, 0 ), + /* GetINFO */ Pop_Push_PACK( 1, 1 ), + /* IDEF */ Pop_Push_PACK( 1, 0 ), + /* ROLL */ Pop_Push_PACK( 3, 3 ), + /* MAX */ Pop_Push_PACK( 2, 1 ), + /* MIN */ Pop_Push_PACK( 2, 1 ), + /* ScanTYPE */ Pop_Push_PACK( 1, 0 ), + /* InstCTRL */ Pop_Push_PACK( 2, 0 ), + /* INS_$8F */ Pop_Push_PACK( 0, 0 ), + + /* INS_$90 */ Pop_Push_PACK( 0, 0 ), + /* INS_$91 */ Pop_Push_PACK( 0, 0 ), + /* INS_$92 */ Pop_Push_PACK( 0, 0 ), + /* INS_$93 */ Pop_Push_PACK( 0, 0 ), + /* INS_$94 */ Pop_Push_PACK( 0, 0 ), + /* INS_$95 */ Pop_Push_PACK( 0, 0 ), + /* INS_$96 */ Pop_Push_PACK( 0, 0 ), + /* INS_$97 */ Pop_Push_PACK( 0, 0 ), + /* INS_$98 */ Pop_Push_PACK( 0, 0 ), + /* INS_$99 */ Pop_Push_PACK( 0, 0 ), + /* INS_$9A */ Pop_Push_PACK( 0, 0 ), + /* INS_$9B */ Pop_Push_PACK( 0, 0 ), + /* INS_$9C */ Pop_Push_PACK( 0, 0 ), + /* INS_$9D */ Pop_Push_PACK( 0, 0 ), + /* INS_$9E */ Pop_Push_PACK( 0, 0 ), + /* INS_$9F */ Pop_Push_PACK( 0, 0 ), + + /* INS_$A0 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A1 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A2 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A3 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A4 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A5 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A6 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A7 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A8 */ Pop_Push_PACK( 0, 0 ), + /* INS_$A9 */ Pop_Push_PACK( 0, 0 ), + /* INS_$AA */ Pop_Push_PACK( 0, 0 ), + /* INS_$AB */ Pop_Push_PACK( 0, 0 ), + /* INS_$AC */ Pop_Push_PACK( 0, 0 ), + /* INS_$AD */ Pop_Push_PACK( 0, 0 ), + /* INS_$AE */ Pop_Push_PACK( 0, 0 ), + /* INS_$AF */ Pop_Push_PACK( 0, 0 ), + + /* PushB[0] */ Pop_Push_PACK( 0, 1 ), + /* PushB[1] */ Pop_Push_PACK( 0, 2 ), + /* PushB[2] */ Pop_Push_PACK( 0, 3 ), + /* PushB[3] */ Pop_Push_PACK( 0, 4 ), + /* PushB[4] */ Pop_Push_PACK( 0, 5 ), + /* PushB[5] */ Pop_Push_PACK( 0, 6 ), + /* PushB[6] */ Pop_Push_PACK( 0, 7 ), + /* PushB[7] */ Pop_Push_PACK( 0, 8 ), + /* PushW[0] */ Pop_Push_PACK( 0, 1 ), + /* PushW[1] */ Pop_Push_PACK( 0, 2 ), + /* PushW[2] */ Pop_Push_PACK( 0, 3 ), + /* PushW[3] */ Pop_Push_PACK( 0, 4 ), + /* PushW[4] */ Pop_Push_PACK( 0, 5 ), + /* PushW[5] */ Pop_Push_PACK( 0, 6 ), + /* PushW[6] */ Pop_Push_PACK( 0, 7 ), + /* PushW[7] */ Pop_Push_PACK( 0, 8 ), + + /* MDRP[00] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[01] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[02] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[03] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[04] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[05] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[06] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[07] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[08] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[09] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[10] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[11] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[12] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[13] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[14] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[15] */ Pop_Push_PACK( 1, 0 ), + + /* MDRP[16] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[17] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[18] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[19] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[20] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[21] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[22] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[23] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[24] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[25] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[26] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[27] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[28] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[29] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[30] */ Pop_Push_PACK( 1, 0 ), + /* MDRP[31] */ Pop_Push_PACK( 1, 0 ), + + /* MIRP[00] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[01] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[02] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[03] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[04] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[05] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[06] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[07] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[08] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[09] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[10] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[11] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[12] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[13] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[14] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[15] */ Pop_Push_PACK( 2, 0 ), + + /* MIRP[16] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[17] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[18] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[19] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[20] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[21] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[22] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[23] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[24] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[25] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[26] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[27] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[28] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[29] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[30] */ Pop_Push_PACK( 2, 0 ), + /* MIRP[31] */ Pop_Push_PACK( 2, 0 ) +]; + +function GUESS_VECTOR(exc, v) +{ + // TODO: unpatented +} + +function Ins_SxVTL(exc, aIdx1, aIdx2, aOpc, Vec) +{ + if ((aIdx1 >= exc.zp2.n_points) || (aIdx2 >= exc.zp1.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Err_Invalid_Reference; + return 1; + } + + var p1 = exc.zp1.cur[exc.zp1._offset_cur + aIdx2]; + var p2 = exc.zp2.cur[exc.zp2._offset_cur + aIdx1]; + + var A = p1.x - p2.x; + var B = p1.y - p2.y; + + /* If p1 == p2, SPVTL and SFVTL behave the same as */ + /* SPVTCA[X] and SFVTCA[X], respectively. */ + /* */ + /* Confirmed by Greg Hitchcock. */ + + if (A == 0 && B == 0) + { + A = 0x4000; + aOpc = 0; + } + + if ((aOpc & 1) != 0) + { + var C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + Normalize(exc, A, B, Vec); + + return 0; +} + +function TT_VecLen(X, Y) +{ + if (X > FT_Common.m_i || Y > FT_Common.m_i) + alert("error"); + + var v = new FT_Vector(); + v.x = X; + v.y = Y; + return FT_Vector_Length(v); +} + +function Normalize(exc, Vx, Vy, R) +{ + if (Vx > FT_Common.m_i || Vy > FT_Common.m_i) + alert("error"); + + var W = 0; + var S1, S2; + + if (Math.abs(Vx) < 0x10000 && Math.abs(Vy) < 0x10000) + { + Vx *= 0x100; + Vy *= 0x100; + + Vx = (Vx & 0xFFFFFFFF); + Vy = (Vy & 0xFFFFFFFF); + + W = TT_VecLen(Vx, Vy); + + if (W == 0) + { + /* XXX: UNDOCUMENTED! It seems that it is possible to try */ + /* to normalize the vector (0,0). Return immediately. */ + return 0; + } + + R.x = FT_Common.UShort_To_Short(FT_DivFix(Vx, W << 2) & 0xFFFF); + R.y = FT_Common.UShort_To_Short(FT_DivFix(Vy, W << 2) & 0xFFFF); + + return 0; + } + + W = TT_VecLen(Vx, Vy); + + Vx = FT_DivFix(Vx, W << 2); + Vy = FT_DivFix(Vy, W << 2); + + W = Vx * Vx + Vy * Vy; + W = (W & 0xFFFFFFFF); + + /* Now, we want that Sqrt( W ) = 0x4000 */ + /* Or 0x10000000 <= W < 0x10004000 */ + + if (Vx < 0) + { + Vx = -Vx; + S1 = 1; + } + else + S1 = 0; + + if (Vy < 0) + { + Vy = -Vy; + S2 = 1; + } + else + S2 = 0; + + while (W < 0x10000000) + { + /* We need to increase W by a minimal amount */ + if (Vx < Vy) + Vx++; + else + Vy++; + + W = Vx * Vx + Vy * Vy; + } + + while (W >= 0x10004000) + { + /* We need to decrease W by a minimal amount */ + if (Vx < Vy) + Vx--; + else + Vy--; + + W = Vx * Vx + Vy * Vy; + } + + /* Note that in various cases, we can only */ + /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */ + if (S1 == 1) + Vx = -Vx; + + if (S2 == 1) + Vy = -Vy; + + R.x = FT_Common.UShort_To_Short(Vx & 0xFFFF); /* Type conversion */ + R.y = FT_Common.UShort_To_Short(Vy & 0xFFFF); /* Type conversion */ + + return 0; +} + +// ------ +function Compute_Funcs(exc) +{ + // TODO: unpatented + if (exc.GS.freeVector.x == 0x4000) + exc.F_dot_P = exc.GS.projVector.x; + else if (exc.GS.freeVector.y == 0x4000) + exc.F_dot_P = exc.GS.projVector.y; + else + exc.F_dot_P = (exc.GS.projVector.x * exc.GS.freeVector.x + exc.GS.projVector.y * exc.GS.freeVector.y) >> 14; + + if (exc.GS.projVector.x == 0x4000) + exc.func_project = Project_x; + else if (exc.GS.projVector.y == 0x4000) + exc.func_project = Project_y; + else + exc.func_project = Project; + + if (exc.GS.dualVector.x == 0x4000) + exc.func_dualproj = Project_x; + else if (exc.GS.dualVector.y == 0x4000) + exc.func_dualproj = Project_y; + else + exc.func_dualproj = Dual_Project; + + exc.func_move = Direct_Move; + exc.func_move_orig = Direct_Move_Orig; + + if (exc.F_dot_P == 0x4000) + { + if ( exc.GS.freeVector.x == 0x4000 ) + { + exc.func_move = Direct_Move_X; + exc.func_move_orig = Direct_Move_Orig_X; + } + else if ( exc.GS.freeVector.y == 0x4000 ) + { + exc.func_move = Direct_Move_Y; + exc.func_move_orig = Direct_Move_Orig_Y; + } + } + + /* at small sizes, F_dot_P can become too small, resulting */ + /* in overflows and `spikes' in a number of glyphs like `w'. */ + if (Math.abs(exc.F_dot_P) < 0x400) + exc.F_dot_P = 0x4000; + + /* Disable cached aspect ratio */ + exc.tt_metrics.ratio = 0; +} + +function Project(exc, dx, dy) +{ + if (dx > FT_Common.m_i || dy > FT_Common.m_i) + alert("error"); + + return TT_DotFix14(dx, dy, exc.GS.projVector.x, exc.GS.projVector.y); +} +function Project_x(exc, dx, dy) +{ + if (dx > FT_Common.m_i || dy > FT_Common.m_i) + alert("error"); + + return dx; +} +function Project_y(exc, dx, dy) +{ + if (dx > FT_Common.m_i || dy > FT_Common.m_i) + alert("error"); + + return dy; +} +function Dual_Project(exc, dx, dy) +{ + if (dx > FT_Common.m_i || dy > FT_Common.m_i) + alert("error"); + + return TT_DotFix14(dx, dy, exc.GS.dualVector.x, exc.GS.dualVector.y); +} + +function Direct_Move(exc, zone, point, distance) +{ + if (point < 0 || point > 0xFFFF || distance > FT_Common.m_i) + alert("error"); + + var v = exc.GS.freeVector.x; + if (v != 0) + { + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) + { + if (!exc.ignore_x_mode || (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ALLOW_X_DMOVE)) + { + zone.cur[zone._offset_cur + point].x += FT_MulDiv(distance, v, exc.F_dot_P); + } + zone.tags[zone._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_X; + } + else + { + zone.cur[zone._offset_cur + point].x += FT_MulDiv(distance, v, exc.F_dot_P); + + // DEBUG + zone.cur[zone._offset_cur + point].x &= 0xFFFFFFFF; + + zone.tags[zone._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_X; + } + } + + v = exc.GS.freeVector.y; + + if (v != 0) + { + zone.cur[zone._offset_cur + point].y += FT_MulDiv(distance, v, exc.F_dot_P); + + // DEBUG + zone.cur[zone._offset_cur + point].y &= 0xFFFFFFFF; + + zone.tags[zone._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_Y; + } +} + +function Direct_Move_Orig(exc, zone, point, distance) +{ + if (point < 0 || point > 0xFFFF || distance > FT_Common.m_i) + alert("error"); + + var v = exc.GS.freeVector.x; + + if (v != 0) + { + zone.org[zone._offset_org + point].x += FT_MulDiv(distance, v, exc.F_dot_P); + + // DEBUG + zone.org[zone._offset_org + point].x &= 0xFFFFFFFF; + } + + v = exc.GS.freeVector.y; + + if (v != 0) + { + zone.org[zone._offset_org + point].y += FT_MulDiv(distance, v, exc.F_dot_P); + + // DEBUG + zone.org[zone._offset_cur + point].y &= 0xFFFFFFFF; + } +} + +function Direct_Move_X(exc, zone, point, distance) +{ + if (point < 0 || point > 0xFFFF || distance > FT_Common.m_i) + alert("error"); + + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) + { + if (!exc.ignore_x_mode || (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ALLOW_X_DMOVEX) != 0) + { + zone.cur[zone._offset_cur + point].x += distance; + + // DEBUG + zone.cur[zone._offset_cur + point].x &= 0xFFFFFFFF; + } + zone.tags[zone._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_X; + } + else + { + zone.cur[zone._offset_cur + point].x += distance; + + // DEBUG + zone.cur[zone._offset_cur + point].x &= 0xFFFFFFFF; + + zone.tags[zone._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_X; + } +} + +function Direct_Move_Y(exc, zone, point, distance) +{ + if (point < 0 || point > 0xFFFF || distance > FT_Common.m_i) + alert("error"); + + zone.cur[zone._offset_cur + point].y += distance; + + // DEBUG + zone.cur[zone._offset_cur + point].y &= 0xFFFFFFFF; + + zone.tags[zone._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_Y; +} + +function Direct_Move_Orig_X(exc, zone, point, distance) +{ + if (point < 0 || point > 0xFFFF || distance > FT_Common.m_i) + alert("error"); + + zone.org[zone._offset_org + point].x += distance; + + // DEBUG + zone.org[zone._offset_org + point].x &= 0xFFFFFFFF; +} + +function Direct_Move_Orig_Y(exc, zone, point, distance) +{ + if (point < 0 || point > 0xFFFF || distance > FT_Common.m_i) + alert("error"); + + zone.org[zone._offset_org + point].y += distance; + + // DEBUG + zone.org[zone._offset_org + point].y &= 0xFFFFFFFF; +} + +// ------ + +// ------ +function Compute_Round(exc, round_mode) +{ + switch (round_mode) + { + case TT_Round_Off: + exc.func_round = Round_None; + break; + + case TT_Round_To_Grid: + exc.func_round = Round_To_Grid; + break; + + case TT_Round_Up_To_Grid: + exc.func_round = Round_Up_To_Grid; + break; + + case TT_Round_Down_To_Grid: + exc.func_round = Round_Down_To_Grid; + break; + + case TT_Round_To_Half_Grid: + exc.func_round = Round_To_Half_Grid; + break; + + case TT_Round_To_Double_Grid: + exc.func_round = Round_To_Double_Grid; + break; + + case TT_Round_Super: + exc.func_round = Round_Super; + break; + + case TT_Round_Super_45: + exc.func_round = Round_Super_45; + break; + } +} + +function Round_None(exc, distance, compensation) +{ + if (distance > FT_Common.m_i || compensation > FT_Common.m_i) + alert("error"); + + var val; + if (distance >= 0) + { + val = distance + compensation; + if (distance && val < 0) + val = 0; + } + else + { + val = distance - compensation; + if (val > 0) + val = 0; + } + return val; +} + +function Round_To_Grid(exc, distance, compensation) +{ + if (distance > FT_Common.m_i || compensation > FT_Common.m_i) + alert("error"); + + var val; + if (distance >= 0) + { + val = distance + compensation + 32; + if (distance && val > 0) + val &= ~63; + else + val = 0; + } + else + { + val = -FT_PIX_ROUND(compensation - distance); + if (val > 0) + val = 0; + } + + return val; +} + +function Round_Up_To_Grid(exc, distance, compensation) +{ + if (distance > FT_Common.m_i || compensation > FT_Common.m_i) + alert("error"); + + var val; + if (distance >= 0) + { + val = distance + compensation + 63; + if (distance && val > 0) + val &= ~63; + else + val = 0; + } + else + { + val = -FT_PIX_CEIL(compensation - distance); + if (val > 0) + val = 0; + } + return val; +} + +function Round_Down_To_Grid(exc, distance, compensation) +{ + if (distance > FT_Common.m_i || compensation > FT_Common.m_i) + alert("error"); + + var val; + if (distance >= 0) + { + val = distance + compensation; + if (distance && val > 0) + val &= ~63; + else + val = 0; + } + else + { + val = -((compensation - distance) & -64); + if (val > 0) + val = 0; + } + return val; +} + +function Round_To_Half_Grid(exc, distance, compensation) +{ + if (distance > FT_Common.m_i || compensation > FT_Common.m_i) + alert("error"); + + var val; + if (distance >= 0) + { + val = FT_PIX_FLOOR(distance + compensation) + 32; + if (distance && val < 0) + val = 0; + } + else + { + val = -(FT_PIX_FLOOR(compensation - distance) + 32); + if (val > 0) + val = 0; + } + return val; +} + +function Round_To_Double_Grid(exc, distance, compensation) +{ + if (distance > FT_Common.m_i || compensation > FT_Common.m_i) + alert("error"); + + var val; + if (distance >= 0) + { + val = distance + compensation + 16; + if (distance && val > 0) + val &= ~31; + else + val = 0; + } + else + { + val = -((compensation - distance + 16) & ~31); + if (val > 0) + val = 0; + } + + return val; +} + +function Round_Super(exc, distance, compensation) +{ + if (distance > FT_Common.m_i || compensation > FT_Common.m_i) + alert("error"); + + var val; + if (distance >= 0) + { + val = (distance - exc.phase + exc.threshold + compensation) & -exc.period; + if (distance && val < 0) + val = 0; + val += exc.phase; + } + else + { + val = -((exc.threshold - exc.phase - distance + compensation) & -exc.period); + if (val > 0) + val = 0; + val -= exc.phase; + } + return val; +} + +function Round_Super_45(exc, distance, compensation) +{ + if (distance > FT_Common.m_i || compensation > FT_Common.m_i) + alert("error"); + + var val; + if (distance >= 0) + { + val = (((distance - exc.phase + exc.threshold + compensation) / exc.period) >> 0) * exc.period; + if (distance && val < 0) + val = 0; + val += exc.phase; + } + else + { + val = -((((exc.threshold - exc.phase - distance + compensation) / exc.period) >> 0) * exc.period); + if (val > 0) + val = 0; + val -= exc.phase; + } + return val; +} + +function SetSuperRound(exc, GridPeriod, selector) +{ + switch ((selector & 0xC0)) + { + case 0: + exc.period = (GridPeriod / 2) >> 0; + break; + case 0x40: + exc.period = GridPeriod; + break; + case 0x80: + exc.period = GridPeriod * 2; + break; + /* This opcode is reserved, but... */ + case 0xC0: + exc.period = GridPeriod; + break; + } + + switch ((selector & 0x30)) + { + case 0: + exc.phase = 0; + break; + case 0x10: + exc.phase = exc.period >> 2; + break; + case 0x20: + exc.phase = exc.period >> 1; + break; + case 0x30: + exc.phase = (exc.period * 3) >> 2; + break; + } + + if ((selector & 0x0F) == 0) + exc.threshold = exc.period - 1; + else + exc.threshold = (((selector & 0x0F) - 4) * exc.period) >> 3; + + exc.period >>= 8; + exc.phase >>= 8; + exc.threshold >>= 8; +} + +// ------ + +function SkipCode(exc) +{ + exc.IP += exc.length; + + if (exc.IP < exc.codeSize) + { + exc.opcode = exc.code.data[exc.code.pos + exc.IP]; + + exc.length = opcode_length[exc.opcode]; + if ( exc.length < 0 ) + { + if ( exc.IP + 1 >= exc.codeSize ) + { + exc.error = FT_Common.FT_Err_Code_Overflow; + return 1; + } + exc.length = 2 - exc.length * exc.code.data[exc.code.pos + exc.IP + 1]; + } + + if (exc.IP + exc.length <= exc.codeSize) + return 0; + } + + exc.error = FT_Common.FT_Err_Code_Overflow; + return 1; +} + +function Ins_Goto_CodeRange(exc, aRange, aIP) +{ + if (aRange < 1 || aRange > 3) + { + exc.error = FT_Common.FT_Err_Bad_Argument; + return 1; + } + + var range = exc.codeRangeTable[aRange - 1]; + + if (range.base == null) /* invalid coderange */ + { + exc.error = FT_Common.FT_Err_Invalid_CodeRange; + return 1; + } + + /* NOTE: Because the last instruction of a program may be a CALL */ + /* which will return to the first byte *after* the code */ + /* range, we test for aIP <= Size, instead of aIP < Size. */ + + if (aIP > range.size) + { + exc.error = FT_Common.FT_Err_Code_Overflow; + return 1; + } + + exc.code = dublicate_pointer(range.base); + exc.codeSize = range.size; + exc.IP = aIP; + exc.curRange = aRange; + + return 0; +} + +function Compute_Point_Displacement(exc, x, y, zone, refp) +{ + var ret = {x: x, y: y, refp: refp, err: 0}; + var zp = null; + var p; + + if (exc.opcode & 1) + { + zp = exc.zp0; + p = exc.GS.rp1; + } + else + { + zp = exc.zp1; + p = exc.GS.rp2; + } + + if (p >= zp.n_points) + { + if (exc.pedantic_hinting ) + exc.error = FT_Common.FT_Err_Invalid_Reference; + ret.refp = 0; + ret.err = 1; + return ret; + } + + zone.Copy(zp); + ret.refp = p; + + var v1 = zp.cur[zp._offset_cur + p]; + var v2 = zp.org[zp._offset_org + p]; + var d = exc.func_project(exc, v1.x - v2.x, v1.y - v2.y); + + // TODO : unpatended + ret.x = FT_MulDiv(d, exc.GS.freeVector.x, exc.F_dot_P); + ret.y = FT_MulDiv(d, exc.GS.freeVector.y, exc.F_dot_P); + + return ret; +} + +function TT_MulFix14(a, b) +{ + a = FT_Common.UintToInt(a); + b = FT_Common.UintToInt(b); + + var sign = a ^ b; + + if (a < 0) + a = -a; + if (b < 0) + b = -b; + + var ah = ((a >> 16) & 0xFFFF); + var al = (a & 0xFFFF); + + var lo = FT_Common.IntToUInt((al * b) & 0xFFFFFFFF); + var mid = FT_Common.IntToUInt((ah * b) & 0xFFFFFFFF); + var hi = FT_Common.IntToUInt(mid >> 16); + mid = FT_Common.IntToUInt(((mid << 16) + (1 << 13)) & 0xFFFFFFFF); /* rounding */ + lo += mid; + + lo = FT_Common.IntToUInt(lo & 0xFFFFFFFF); + + if (lo < mid) + hi += 1; + + mid = FT_Common.IntToUInt(((lo >> 14) | (hi << 18)) & 0xFFFFFFFF); + return sign >= 0 ? mid : -mid; +} + +function TT_DotFix14(ax, ay, bx, by) +{ + ax = FT_Common.UintToInt(ax); + ay = FT_Common.UintToInt(ay); + bx = FT_Common.UintToInt(bx); + by = FT_Common.UintToInt(by); + + /* compute ax*bx as 64-bit value */ + var _l = ((ax & 0xFFFF) * bx) & 0xFFFFFFFF; + var l = FT_Common.IntToUInt(_l); + var m = ((ax >> 16) * bx) & 0xFFFFFFFF; + + var lo1 = l + FT_Common.IntToUInt((m << 16) & 0xFFFFFFFF); + lo1 = FT_Common.IntToUInt(lo1 & 0xFFFFFFFF); + + var hi1 = (m >> 16) + (_l >> 31) + ((lo1 < l) ? 1 : 0); + + /* compute ay*by as 64-bit value */ + _l = ((ay & 0xFFFF) * by) & 0xFFFFFFFF; + l = FT_Common.IntToUInt(_l); + m = ((ay >> 16) * by) & 0xFFFFFFFF; + + var lo2 = l + FT_Common.IntToUInt(m << 16); + lo2 = FT_Common.IntToUInt(lo2 & 0xFFFFFFFF); + + var hi2 = (m >> 16) + (_l >> 31) + ((lo2 < l) ? 1 : 0); + + /* add them */ + var lo = lo1 + lo2; + lo = FT_Common.IntToUInt(lo & 0xFFFFFFFF); + + var hi = hi1 + hi2 + ((lo < lo1) ? 1 : 0); + + /* divide the result by 2^14 with rounding */ + var s = hi >> 31; + l = lo + FT_Common.IntToUInt(s); + l = FT_Common.IntToUInt(l & 0xFFFFFFFF); + + hi += s + ((l < lo) ? 1 : 0); + lo = l; + + l = lo + 0x2000; + l = FT_Common.IntToUInt(l & 0xFFFFFFFF); + + hi += ((l < lo) ? 1 : 0); + + return ((hi << 18) | (l >> 14)) & 0xFFFFFFFF; +} + +function Move_Zp2_Point(exc, point, dx, dy, touch) +{ + // TODO: unpatented + if (exc.GS.freeVector.x != 0) + { + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) //#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (!exc.ignore_x_mode || (exc.ignore_x_mode && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ALLOW_X_MOVE_ZP2))) + { + exc.zp2.cur[exc.zp2._offset_cur + point].x += dx; + } + } + else + { + exc.zp2.cur[exc.zp2._offset_cur + point].x += dx; + } + if (touch) + exc.zp2.tags[exc.zp2._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_X; + } + + if (exc.GS.freeVector.y != 0) + { + exc.zp2.cur[exc.zp2._offset_cur + point].y += dy; + if (touch) + exc.zp2.tags[exc.zp2._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_Y; + } +} +//////////////////////////////////////////////////////// +function Ins_SVTCA(exc, args, args_pos) +{ + var A = 0; + var B = 0x4000; + if ((exc.opcode & 1) == 1) + { + A = 0x4000; + B = 0; + } + + exc.GS.freeVector.x = A; + exc.GS.projVector.x = A; + exc.GS.dualVector.x = A; + + exc.GS.freeVector.y = B; + exc.GS.projVector.y = B; + exc.GS.dualVector.y = B; + + Compute_Funcs(exc); +} + +function Ins_SPVTCA(exc, args, args_pos) +{ + var A = 0; + var B = 0x4000; + if ((exc.opcode & 1) == 1) + { + A = 0x4000; + B = 0; + } + + exc.GS.projVector.x = A; + exc.GS.dualVector.x = A; + + exc.GS.projVector.y = B; + exc.GS.dualVector.y = B; + + GUESS_VECTOR(exc, exc.GS.freeVector); + + Compute_Funcs(exc); +} + +function Ins_SFVTCA(exc, args, args_pos) +{ + var A = 0; + var B = 0x4000; + if ((exc.opcode & 1) == 1) + { + A = 0x4000; + B = 0; + } + + exc.GS.freeVector.x = A; + exc.GS.freeVector.y = B; + + GUESS_VECTOR(exc, exc.projVector); + + Compute_Funcs(exc); +} + +function Ins_SPVTL(exc, args, args_pos) +{ + if (Ins_SxVTL(exc, 0xFFFF & args[args_pos + 1], 0xFFFF & args[args_pos], exc.opcode, exc.GS.projVector) == 0) + { + exc.GS.dualVector.x = exc.GS.projVector.x; + exc.GS.dualVector.y = exc.GS.projVector.y; + GUESS_VECTOR(exc, exc.GS.freeVector); + Compute_Funcs(exc); + } +} + +function Ins_SFVTL(exc, args, args_pos) +{ + if (Ins_SxVTL(exc, 0xFFFF & args[args_pos + 1], 0xFFFF & args[args_pos], exc.opcode, exc.GS.freeVector) == 0) + { + GUESS_VECTOR(exc, exc.GS.projVector ); + Compute_Funcs(exc); + } +} + +function Ins_SPVFS(exc, args, args_pos) +{ + /* Only use low 16bits, then sign extend */ + var Y = FT_Common.UShort_To_Short(0xFFFF & args[args_pos + 1]); + var X = FT_Common.UShort_To_Short(0xFFFF & args[args_pos]); + + Normalize(exc, X, Y, exc.GS.projVector); + + exc.GS.dualVector.x = exc.GS.projVector.x; + exc.GS.dualVector.y = exc.GS.projVector.y; + GUESS_VECTOR(exc, exc.GS.freeVector ); + Compute_Funcs(exc); +} + +function Ins_SFVFS(exc, args, args_pos) +{ + /* Only use low 16bits, then sign extend */ + var Y = FT_Common.UShort_To_Short(0xFFFF & args[args_pos + 1]); + var X = FT_Common.UShort_To_Short(0xFFFF & args[args_pos]); + + Normalize(exc, X, Y, exc.GS.freeVector); + GUESS_VECTOR(exc, exc.GS.projVector ); + Compute_Funcs(exc); +} + +function Ins_GPV(exc, args, args_pos) +{ + // TODO: unpatented + args[args_pos] = exc.GS.projVector.x; + args[args_pos + 1] = exc.GS.projVector.y; +} + +function Ins_GFV(exc, args, args_pos) +{ + // TODO: unpatented + args[args_pos] = exc.GS.freeVector.x; + args[args_pos + 1] = exc.GS.freeVector.y; +} + +function Ins_SFVTPV(exc, args, args_pos) +{ + GUESS_VECTOR(exc, exc.GS.projVector); + exc.GS.freeVector.x = exc.GS.projVector.x; + exc.GS.freeVector.y = exc.GS.projVector.y; + Compute_Funcs(exc); +} + +function Ins_ISECT(exc, args, args_pos) +{ + var point = 0xFFFF & args[args_pos]; + + var a0 = 0xFFFF & args[args_pos + 1]; + var a1 = 0xFFFF & args[args_pos + 2]; + var b0 = 0xFFFF & args[args_pos + 3]; + var b1 = 0xFFFF & args[args_pos + 4]; + + if ((b0 >= exc.zp0.n_points) || + (b1 >= exc.zp0.n_points) || + (a0 >= exc.zp1.n_points) || + (a1 >= exc.zp1.n_points) || + (point >= exc.zp2.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + /* Cramer's rule */ + + var off0 = exc.zp0._offset_cur; + var off1 = exc.zp1._offset_cur; + var off2 = exc.zp2._offset_cur; + + var dbx = exc.zp0.cur[off0+b1].x - exc.zp0.cur[off0+b0].x; + var dby = exc.zp0.cur[off0+b1].y - exc.zp0.cur[off0+b0].y; + + var dax = exc.zp1.cur[off1+a1].x - exc.zp1.cur[off1+a0].x; + var day = exc.zp1.cur[off1+a1].y - exc.zp1.cur[off1+a0].y; + + var dx = exc.zp0.cur[off0+b0].x - exc.zp1.cur[off1+a0].x; + var dy = exc.zp0.cur[off0+b0].y - exc.zp1.cur[off1+a0].y; + + exc.zp2.tags[exc.zp2._offset_tags + point] |= FT_Common.FT_CURVE_TAG_TOUCH_BOTH; + + var discriminant = FT_MulDiv(dax, -dby, 0x40) + FT_MulDiv(day, dbx, 0x40); + var dotproduct = FT_MulDiv(dax, dbx, 0x40) + FT_MulDiv(day, dby, 0x40); + + /* The discriminant above is actually a cross product of vectors */ + /* da and db. Together with the dot product, they can be used as */ + /* surrogates for sine and cosine of the angle between the vectors. */ + /* Indeed, */ + /* dotproduct = |da||db|cos(angle) */ + /* discriminant = |da||db|sin(angle) . */ + /* We use these equations to reject grazing intersections by */ + /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */ + if (19 * Math.abs(discriminant) > Math.abs(dotproduct)) + { + var val = FT_MulDiv(dx, -dby, 0x40) + FT_MulDiv(dy, dbx, 0x40); + + var __x = FT_MulDiv(val, dax, discriminant); + var __y = FT_MulDiv(val, day, discriminant); + + exc.zp2.cur[off2 + point].x = exc.zp1.cur[off1 + a0].x + __x; + exc.zp2.cur[off2 + point].y = exc.zp1.cur[off1 + a0].y + __y; + } + else + { + /* else, take the middle of the middles of A and B */ + exc.zp2.cur[off2 + point].x = (exc.zp1.cur[off1 + a0].x + + exc.zp1.cur[off1 + a1].x + + exc.zp0.cur[off0 + b0].x + + exc.zp0.cur[off0 + b1].x ) >> 2; + exc.zp2.cur[off2 + point].y = (exc.zp1.cur[off1 + a0].y + + exc.zp1.cur[off1 + a1].y + + exc.zp0.cur[off0 + b0].y + + exc.zp0.cur[off0 + b1].y ) >> 2; + } +} + +function Ins_SRP0(exc, args, args_pos) +{ + exc.GS.rp0 = 0xFFFF & args[args_pos]; +} + +function Ins_SRP1(exc, args, args_pos) +{ + exc.GS.rp1 = 0xFFFF & args[args_pos]; +} + +function Ins_SRP2(exc, args, args_pos) +{ + exc.GS.rp2 = 0xFFFF & args[args_pos]; +} + +function Ins_SZP0(exc, args, args_pos) +{ + switch (args[args_pos]) + { + case 0: + exc.zp0.Copy(exc.twilight); + break; + + case 1: + exc.zp0.Copy(exc.pts); + break; + + default: + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + exc.GS.gep0 = 0xFFFF & args[args_pos]; +} + +function Ins_SZP1(exc, args, args_pos) +{ + switch (args[args_pos]) + { + case 0: + exc.zp1.Copy(exc.twilight); + break; + + case 1: + exc.zp1.Copy(exc.pts); + break; + + default: + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + exc.GS.gep1 = 0xFFFF & args[args_pos]; +} + +function Ins_SZP2(exc, args, args_pos) +{ + switch (args[args_pos]) + { + case 0: + exc.zp2.Copy(exc.twilight); + break; + + case 1: + exc.zp2.Copy(exc.pts); + break; + + default: + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + exc.GS.gep2 = 0xFFFF & args[args_pos]; +} + +function Ins_SZPS(exc, args, args_pos) +{ + switch (args[args_pos]) + { + case 0: + exc.zp0.Copy(exc.twilight); + break; + + case 1: + exc.zp0.Copy(exc.pts); + break; + + default: + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + exc.zp1.Copy(exc.zp0); + exc.zp2.Copy(exc.zp0); + + exc.GS.gep0 = 0xFFFF & args[args_pos]; + exc.GS.gep1 = 0xFFFF & args[args_pos]; + exc.GS.gep2 = 0xFFFF & args[args_pos]; +} + +function Ins_SLOOP(exc, args, args_pos) +{ + if (args[args_pos] < 0) + exc.error = FT_Common.FT_Err_Bad_Argument; + else + exc.GS.loop = args[args_pos]; +} + +function Ins_RTG(exc, args, args_pos) +{ + exc.GS.round_state = TT_Round_To_Grid; + exc.func_round = Round_To_Grid; +} + +function Ins_RTHG(exc, args, args_pos) +{ + exc.GS.round_state = TT_Round_To_Half_Grid; + exc.func_round = Round_To_Half_Grid; +} + +function Ins_SMD(exc, args, args_pos) +{ + exc.GS.minimum_distance = args[args_pos]; +} + +function Ins_ELSE(exc, args, args_pos) +{ + var nIfs = 1; + + do + { + if (SkipCode(exc) == 1) + return; + + switch (exc.opcode) + { + case 0x58: /* IF */ + nIfs++; + break; + + case 0x59: /* EIF */ + nIfs--; + break; + } + } while ( nIfs != 0 ); +} + +function Ins_JMPR(exc, args, args_pos) +{ + if (args[args_pos] == 0 && exc.args == 0) + exc.error = FT_Common.FT_Err_Bad_Argument; + exc.IP += args[args_pos]; + if (exc.IP < 0 || (exc.callTop > 0 && exc.IP > exc.callStack[exc.callTop - 1].Cur_End)) + exc.error = FT_Common.FT_Err_Bad_Argument; + exc.step_ins = 0; +} + +function Ins_SCVTCI(exc, args, args_pos) +{ + exc.GS.control_value_cutin = args[args_pos]; +} + +function Ins_SSWCI(exc, args, args_pos) +{ + exc.GS.single_width_cutin = args[args_pos]; +} + +function Ins_SSW(exc, args, args_pos) +{ + exc.GS.single_width_value = FT_MulFix(args[args_pos], exc.tt_metrics.scale); +} + +function Ins_DUP(exc, args, args_pos) +{ + args[args_pos + 1] = args[args_pos]; +} + +function Ins_POP(exc, args, args_pos) +{ +} + +function Ins_CLEAR(exc, args, args_pos) +{ + exc.new_top = 0; +} + +function Ins_SWAP(exc, args, args_pos) +{ + var L = args[args_pos]; + args[args_pos] = args[args_pos + 1]; + args[args_pos + 1] = L; +} + +function Ins_DEPTH(exc, args, args_pos) +{ + args[args_pos] = exc.top; +} + +function Ins_CINDEX(exc, args, args_pos) +{ + var L = args[args_pos]; + + if (L <= 0 || L > exc.args) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + args[args_pos] = 0; + } + else + args[args_pos] = exc.stack[exc.args - L]; +} + +function Ins_MINDEX(exc, args, args_pos) +{ + var L = args[args_pos]; + + if (L <= 0 || L > exc.args) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + } + else + { + var K = exc.stack[exc.args - L]; + + var _i1 = exc.args - L; + var _i2 = exc.args - 1; + for (var i = _i1; i < _i2; i++) + exc.stack[i] = exc.stack[i + 1]; + + exc.stack[exc.args - 1] = K; + } +} + +function Ins_ALIGNPTS(exc, args, args_pos) +{ + var p1 = 0xFFFF & args[args_pos]; + var p2 = 0xFFFF & args[args_pos + 1]; + + if ((p1 >= exc.zp1.n_points) || (p2 >= exc.zp0.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + var v1 = exc.zp0.cur[exc.zp0._offset_cur + p2]; + var v2 = exc.zp1.cur[exc.zp1._offset_cur + p1]; + + var distance = (exc.func_project(exc, v1.x - v2.x, v1.y - v2.y) / 2) >> 0; + + exc.func_move(exc, exc.zp1, p1, distance); + exc.func_move(exc, exc.zp0, p2, -distance); +} + +function Ins_UNKNOWN(exc, args, args_pos) +{ + var defs = exc.IDefs; + var limit = exc.numIDefs; + + for (var def = 0; def < limit; def++) + { + if (defs[def].opc == exc.opcode && defs[def].active) + { + if (exc.callTop >= exc.callSize) + { + exc.error = FT_Common.FT_Err_Stack_Overflow; + return; + } + + var call = exc.callStack[exc.callTop++]; + + call.Caller_Range = exc.curRange; + call.Caller_IP = exc.IP + 1; + call.Cur_Count = 1; + call.Cur_Restart = defs[def].start; + call.Cur_End = defs[def].end; + + Ins_Goto_CodeRange(defs[def].range, defs[def].start); + + exc.step_ins = false; + return; + } + } + + exc.error = FT_Common.FT_Err_Invalid_Opcode; +} +function Ins_UTP(exc, args, args_pos) +{ + var point = 0xFFFF & args[args_pos]; + + if (point >= exc.zp0.n_points) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + var mask = 0xFF; + + if (exc.GS.freeVector.x != 0) + mask &= ~FT_Common.FT_CURVE_TAG_TOUCH_X; + + if (exc.GS.freeVector.y != 0) + mask &= ~FT_Common.FT_CURVE_TAG_TOUCH_Y; + + exc.zp0.tags[exc.zp0._offset_tags + point] &= mask; +} + +function Ins_LOOPCALL(exc, args, args_pos) +{ + /* first of all, check the index */ + var F = args[args_pos + 1]; + if (F >= (exc.maxFunc + 1)) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + /* Except for some old Apple fonts, all functions in a TrueType */ + /* font are defined in increasing order, starting from 0. This */ + /* means that we normally have */ + /* */ + /* CUR.maxFunc+1 == CUR.numFDefs */ + /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */ + /* */ + /* If this isn't true, we need to look up the function table. */ + var defs = exc.FDefs; + var def = F; + if (exc.maxFunc + 1 != exc.numFDefs || exc.FDefs[def].opc != F) + { + /* look up the FDefs table */ + def = 0; + var limit = exc.numFDefs; + + while (def < limit && defs[def].opc != F) + def++; + + if (def == limit) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + + /* check that the function is active */ + if (!defs[def].active) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + /* check stack */ + if (exc.callTop >= exc.callSize) + { + exc.error = FT_Common.FT_Err_Stack_Overflow; + return; + } + + if (args[args_pos] > 0) + { + var pCrec = exc.callStack[exc.callTop]; + + pCrec.Caller_Range = exc.curRange; + pCrec.Caller_IP = exc.IP + 1; + pCrec.Cur_Count = args[args_pos]; + pCrec.Cur_Restart = defs[def].start; + pCrec.Cur_End = defs[def].end; + + exc.callTop++; + + Ins_Goto_CodeRange(exc, defs[def].range, defs[def].start); + exc.step_ins = false; + } +} + +function Ins_CALL(exc, args, args_pos) +{ + /* first of all, check the index */ + var F = FT_Common.IntToUInt(args[args_pos]); + if (F >= (exc.maxFunc + 1)) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + /* Except for some old Apple fonts, all functions in a TrueType */ + /* font are defined in increasing order, starting from 0. This */ + /* means that we normally have */ + /* */ + /* CUR.maxFunc+1 == CUR.numFDefs */ + /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */ + /* */ + /* If this isn't true, we need to look up the function table. */ + + var defs = exc.FDefs; + var def = F; + if ((exc.maxFunc + 1) != exc.numFDefs || defs[def].opc != F) + { + /* look up the FDefs table */ + def = 0; + var limit = exc.numFDefs; + + while (def < limit && defs[def].opc != F) + def++; + + if (def == limit) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + + /* check that the function is active */ + if (!defs[def].active) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + /* check the call stack */ + if (exc.callTop >= exc.callSize) + { + exc.error = FT_Common.FT_Err_Stack_Overflow; + return; + } + + var pCrec = exc.callStack[exc.callTop]; + + pCrec.Caller_Range = exc.curRange; + pCrec.Caller_IP = exc.IP + 1; + pCrec.Cur_Count = 1; + pCrec.Cur_Restart = defs[def].start; + pCrec.Cur_End = defs[def].end; + + exc.callTop++; + + Ins_Goto_CodeRange(exc, defs[def].range, defs[def].start); + + exc.step_ins = false; +} + +function Ins_FDEF(exc, args, args_pos) +{ + var bIsSubpix = exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + + /* some font programs are broken enough to redefine functions! */ + /* We will then parse the current table. */ + var defs = exc.FDefs; + var rec = 0; + var limit = exc.numFDefs; + var n = args[args_pos]; + + for ( ; rec < limit; rec++) + { + if (defs[rec].opc == n) + break; + } + + if (rec == limit) + { + /* check that there is enough room for new functions */ + if (exc.numFDefs >= exc.maxFDefs) + { + exc.error = FT_Common.FT_Err_Too_Many_Function_Defs; + return; + } + exc.numFDefs++; + } + + /* Although FDEF takes unsigned 32-bit integer, */ + /* func # must be within unsigned 16-bit integer */ + if (n > 0xFFFF) + { + exc.error = FT_Common.FT_Err_Too_Many_Function_Defs; + return; + } + + defs[rec].range = exc.curRange; + defs[rec].opc = 0xFFFF & n; + defs[rec].start = exc.IP + 1; + defs[rec].active = true; + defs[rec].inline_delta = false; + + if (n > exc.maxFunc) + exc.maxFunc = 0xFFFF & n; + + /* Now skip the whole function definition. */ + /* We don't allow nested IDEFS & FDEFs. */ + + while (SkipCode(exc) == 0) + { + if (bIsSubpix)//#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + /* arguments to opcodes are skipped by `SKIP_Code' */ + var opcode_pattern = []; + opcode_pattern[0] = [/* #0 TTFautohint bytecode (old) */ + 0x20, /* DUP */ + 0x64, /* ABS */ + 0xB0, /* PUSHB_1 */ + /* 32 */ + 0x60, /* ADD */ + 0x66, /* FLOOR */ + 0x23, /* SWAP */ + 0xB0, /* PUSHB_1 */ + 0,0,0,0,0 + ]; + var opcode_patterns = 1; + var opcode_pointer = [0]; + var opcode_size = [7]; + + for (var i = 0; i < opcode_patterns; i++) + { + if (opcode_pointer[i] < opcode_size[i] && exc.opcode == opcode_pattern[i][opcode_pointer[i]]) + { + opcode_pointer[i] += 1; + + if (opcode_pointer[i] == opcode_size[i]) + { + switch ( i ) + { + case 0: + exc.size.ttfautohinted = true; + break; + } + opcode_pointer[i] = 0; + } + } + else + opcode_pointer[i] = 0; + } + } //#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + switch (exc.opcode) + { + case 0x89: /* IDEF */ + case 0x2C: /* FDEF */ + exc.error = FT_Common.FT_Err_Nested_DEFS; + return; + case 0x2D: /* ENDF */ + defs[rec].end = exc.IP; + return; + default: + break; + } + } +} + +function Ins_ENDF(exc, args, args_pos) +{ + if (exc.callTop <= 0) /* We encountered an ENDF without a call */ + { + exc.error = FT_Common.FT_Err_ENDF_In_Exec_Stream; + return; + } + + exc.callTop--; + var pRec = exc.callStack[exc.callTop]; + + pRec.Cur_Count--; + exc.step_ins = false; + + var bIsSubpix = exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + + if (bIsSubpix) //#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + /* + * CUR.ignore_x_mode may be turned off prior to function calls. This + * ensures it is turned back on. + */ + exc.ignore_x_mode = (exc.subpixel_hinting || exc.grayscale_hinting) && !(exc.sph_tweak_flags & FT_Common.SPH_TWEAK_PIXEL_HINTING); + }//#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + if (pRec.Cur_Count > 0) + { + exc.callTop++; + exc.IP = pRec.Cur_Restart; + } + else + { + /* Loop through the current function */ + Ins_Goto_CodeRange(exc, pRec.Caller_Range, pRec.Caller_IP); + } + + /* Exit the current call frame. */ + + /* NOTE: If the last instruction of a program is a */ + /* CALL or LOOPCALL, the return address is */ + /* always out of the code range. This is a */ + /* valid address, and it is why we do not test */ + /* the result of Ins_Goto_CodeRange() here! */ +} + +function Ins_MDAP(exc, args, args_pos) +{ + var point = 0xFFFF & args[args_pos]; + + if (point >= exc.zp0.n_points) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + var distance = 0; + if ((exc.opcode & 1) != 0) + { + var cur_dist = exc.func_project(exc, exc.zp0.cur[exc.zp0._offset_cur + point].x, exc.zp0.cur[exc.zp0._offset_cur + point].y); + var bIsSubpix = exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + + if (bIsSubpix) + { + if (exc.ignore_x_mode && exc.GS.freeVector.x != 0) + { + distance = Round_None(exc, cur_dist, exc.tt_metrics.compensations[0]) - cur_dist; + } + else + { + distance = exc.func_round(exc, cur_dist, exc.tt_metrics.compensations[0]) - cur_dist; + } + } + else + { + distance = exc.func_round(exc, cur_dist, exc.tt_metrics.compensations[0]) - cur_dist; + } + } + + exc.func_move(exc, exc.zp0, point, distance); + + exc.GS.rp0 = point; + exc.GS.rp1 = point; +} + +// -- +function IUP_WorkerRec() +{ + this.orgs = null; /* original and current coordinate */ + this.curs = null; /* arrays */ + this.orus = null; + + this.off_orgs = 0; + this.off_curs = 0; + this.off_orus = 0; + + this.max_points = 0; + this.is_offset_one = false; +} + +function _iup_worker_shift(worker, p1, p2, p) +{ + if (!worker.is_offset_one) + { + var dx = worker.curs[worker.off_curs + p].x - worker.orgs[worker.off_orgs + p].x; + if (dx != 0) + { + for (var i = p1; i < p; i++) + worker.curs[worker.off_curs + i].x += dx; + + for (var i = p + 1; i <= p2; i++) + worker.curs[worker.off_curs + i].x += dx; + } + } + else + { + var dy = worker.curs[worker.off_curs + p].y - worker.orgs[worker.off_orgs + p].y; + if (dy != 0) + { + for (var i = p1; i < p; i++) + worker.curs[worker.off_curs + i].y += dy; + + for (var i = p + 1; i <= p2; i++) + worker.curs[worker.off_curs + i].y += dy; + } + } +} + +function _iup_worker_interpolate(worker, p1, p2, ref1, ref2) +{ + if (!worker.is_offset_one) + { + if (p1 > p2) + return; + + if ((ref1 >= worker.max_points) || (ref2 >= worker.max_points)) + return; + + var orus1 = worker.orus[worker.off_orus + ref1].x; + var orus2 = worker.orus[worker.off_orus + ref2].x; + + if (orus1 > orus2) + { + var tmp_o = orus1; + orus1 = orus2; + orus2 = tmp_o; + + var tmp_r = ref1; + ref1 = ref2; + ref2 = tmp_r; + } + + var org1 = worker.orgs[worker.off_orgs + ref1].x; + var org2 = worker.orgs[worker.off_orgs + ref2].x; + var delta1 = worker.curs[worker.off_curs + ref1].x - org1; + var delta2 = worker.curs[worker.off_curs + ref2].x - org2; + + if (orus1 == orus2) + { + /* simple shift of untouched points */ + for (var i = p1; i <= p2; i++) + { + var x = worker.orgs[worker.off_orgs + i].x; + if ( x <= org1 ) + x += delta1; + else + x += delta2; + + worker.curs[worker.off_curs + i].x = x; + } + } + else + { + var scale = 0; + var scale_valid = 0; + + /* interpolation */ + for (var i = p1; i <= p2; i++) + { + var x = worker.orgs[worker.off_orgs + i].x; + + if ( x <= org1 ) + x += delta1; + else if ( x >= org2 ) + x += delta2; + else + { + if ( !scale_valid ) + { + scale_valid = 1; + scale = FT_DivFix(org2 + delta2 - (org1 + delta1), orus2 - orus1); + } + + x = (org1 + delta1) + FT_MulFix(worker.orus[worker.off_orus + i].x - orus1, scale); + } + worker.curs[worker.off_curs + i].x = x; + } + } + } + else + { + if (p1 > p2) + return; + + if ((ref1 >= worker.max_points) || (ref2 >= worker.max_points)) + return; + + var orus1 = worker.orus[worker.off_orus + ref1].y; + var orus2 = worker.orus[worker.off_orus + ref2].y; + + if (orus1 > orus2) + { + var tmp_o = orus1; + orus1 = orus2; + orus2 = tmp_o; + + var tmp_r = ref1; + ref1 = ref2; + ref2 = tmp_r; + } + + var org1 = worker.orgs[worker.off_orgs + ref1].y; + var org2 = worker.orgs[worker.off_orgs + ref2].y; + var delta1 = worker.curs[worker.off_curs + ref1].y - org1; + var delta2 = worker.curs[worker.off_curs + ref2].y - org2; + + if (orus1 == orus2) + { + /* simple shift of untouched points */ + for (var i = p1; i <= p2; i++) + { + var y = worker.orgs[worker.off_orgs + i].y; + if (y <= org1) + y += delta1; + else + y += delta2; + + worker.curs[worker.off_curs + i].y = y; + } + } + else + { + var scale = 0; + var scale_valid = 0; + + /* interpolation */ + for (var i = p1; i <= p2; i++) + { + var y = worker.orgs[worker.off_orgs + i].y; + + if (y <= org1) + y += delta1; + else if (y >= org2) + y += delta2; + else + { + if ( !scale_valid ) + { + scale_valid = 1; + scale = FT_DivFix(org2 + delta2 - (org1 + delta1), orus2 - orus1); + } + + y = (org1 + delta1) + FT_MulFix(worker.orus[worker.off_orus + i].y - orus1, scale); + } + worker.curs[worker.off_curs + i].y = y; + } + } + } +} +// -- + +function Ins_IUP(exc, args, args_pos) +{ + var mask; + + /* ignore empty outlines */ + if (exc.pts.n_contours == 0) + return; + + var V = new IUP_WorkerRec(); + if (exc.opcode & 1) + { + mask = FT_Common.FT_CURVE_TAG_TOUCH_X; + V.orgs = exc.pts.org; + V.curs = exc.pts.cur; + V.orus = exc.pts.orus; + + V.off_orgs = exc.pts._offset_org; + V.off_curs = exc.pts._offset_cur; + V.off_orus = exc.pts._offset_orus; + } + else + { + mask = FT_Common.FT_CURVE_TAG_TOUCH_Y; + + V.orgs = exc.pts.org; + V.curs = exc.pts.cur; + V.orus = exc.pts.orus; + + V.off_orgs = exc.pts._offset_org; + V.off_curs = exc.pts._offset_cur; + V.off_orus = exc.pts._offset_orus; + V.is_offset_one = true; + } + V.max_points = exc.pts.n_points; + + var contour = 0; + var point = 0; + + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) // #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (exc.ignore_x_mode) + { + exc.iup_called = 1; + if (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_SKIP_IUP) + return; + } + } //#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + do + { + var end_point = exc.pts.contours[exc.pts._offset_contours + contour] - exc.pts.first_point; + var first_point = point; + + if (end_point >= exc.pts.n_points) + end_point = exc.pts.n_points - 1; + + while (point <= end_point && (exc.pts.tags[exc.pts._offset_tags + point] & mask) == 0) + point++; + + if ( point <= end_point ) + { + var first_touched = point; + var cur_touched = point; + + point++; + + while ( point <= end_point ) + { + if ((exc.pts.tags[exc.pts._offset_tags + point] & mask) != 0) + { + _iup_worker_interpolate(V, cur_touched + 1, point - 1, cur_touched, point); + cur_touched = point; + } + + point++; + } + + if (cur_touched == first_touched) + _iup_worker_shift(V, first_point, end_point, cur_touched); + else + { + _iup_worker_interpolate(V, 0xFFFF & (cur_touched + 1), end_point, cur_touched, first_touched); + + if (first_touched > 0) + _iup_worker_interpolate(V, first_point, first_touched - 1, cur_touched, first_touched); + } + } + contour++; + } while (contour < exc.pts.n_contours); +} + +function Ins_SHP(exc, args, args_pos) +{ + if (exc.top < exc.GS.loop) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + + exc.GS.loop = 1; + exc.new_top = exc.args; + } + + var zp = new TT_GlyphZoneRec(); + + var dx, dy, refp; + var ret = Compute_Point_Displacement(exc, dx, dy, zp, refp); + if (ret.err == 1) + return; + + dx = ret.x; + dy = ret.y; + refp = ret.refp; + while (exc.GS.loop > 0) + { + exc.args--; + var point = 0xFFFF & exc.stack[exc.args]; + + if (point >= exc.zp2.n_points) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + else + Move_Zp2_Point(exc, point, dx, dy, true); + + exc.GS.loop--; + } + + exc.GS.loop = 1; + exc.new_top = exc.args; +} + +function Ins_SHC(exc, args, args_pos) +{ + var contour = 0xFFFF & args[args_pos]; + var bounds = (exc.GS.gep2 == 0) ? 1 : exc.zp2.n_contours; + + if (contour >= bounds) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + var zp = new TT_GlyphZoneRec(); + + var dx, dy, refp; + var ret = Compute_Point_Displacement(exc, dx, dy, zp, refp); + if (ret.err == 1) + return; + + dx = ret.x; + dy = ret.y; + refp = ret.refp; + + var start, limit; + if (contour == 0) + start = 0; + else + start = 0xFFFF & (exc.zp2.contours[exc.zp2._offset_contours + contour - 1] + 1 - exc.zp2.first_point); + + /* we use the number of points if in the twilight zone */ + if (exc.GS.gep2 == 0) + limit = exc.zp2.n_points; + else + limit = 0xFFFF & (exc.zp2.contours[exc.zp2._offset_contours + contour] - exc.zp2.first_point + 1); + + for (var i = start; i < limit; i++) + { + if ((zp.cur != exc.zp2.cur || zp._offset_cur != exc.zp2._offset_cur) || refp != i) + Move_Zp2_Point(exc, i, dx, dy, true); + } +} + +function Ins_SHZ(exc, args, args_pos) +{ + if (args[args_pos] >= 2) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + var zp = new TT_GlyphZoneRec(); + + var dx, dy, refp; + var ret = Compute_Point_Displacement(exc, dx, dy, zp, refp); + if (ret.err == 1) + return; + + dx = ret.x; + dy = ret.y; + refp = ret.refp; + + /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */ + /* Twilight zone has no real contours, so use `n_points'. */ + /* Normal zone's `n_points' includes phantoms, so must */ + /* use end of last contour. */ + var limit = 0; + if (exc.GS.gep2 == 0) + limit = 0xFFFF & exc.zp2.n_points; + else if (exc.GS.gep2 == 1 && exc.zp2.n_contours > 0) + limit = 0xFFFF & (exc.zp2.contours[exc.zp2._offset_contours + exc.zp2.n_contours - 1] + 1); + + /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */ + for (var i = 0; i < limit; i++) + { + if ((zp.cur != exc.zp2.cur || zp._offset_cur != exc.zp2._offset_cur) || refp != i) + Move_Zp2_Point(exc, i, dx, dy, false); + } +} + +function Ins_SHPIX(exc, args, args_pos) +{ + if (exc.top < (exc.GS.loop + 1)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + + exc.GS.loop = 1; + exc.new_top = exc.args; + return; + } + + // TODO: unpatented + var dx = TT_MulFix14(args[args_pos], exc.GS.freeVector.x); + var dy = TT_MulFix14(args[args_pos], exc.GS.freeVector.y); + + while (exc.GS.loop > 0) + { + exc.args--; + var point = 0xFFFF & exc.stack[exc.args]; + + if (point >= exc.zp2.n_points) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + else + { + if (!exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) + { + Move_Zp2_Point(exc, point, dx, dy, true); + exc.GS.loop -= 1; + continue; + } + + var B1, B2; + if (exc.ignore_x_mode) + { + /* save point for later comparison */ + if (exc.GS.freeVector.y != 0) + B1 = exc.zp2.cur[exc.zp2._offset_cur + point].y; + else + B1 = exc.zp2.cur[exc.zp2._offset_cur + point].x; + + if (exc.GS.freeVector.y != 0 && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_SKIP_INLINE_DELTAS)) + { + exc.GS.loop--; + continue; + } + + if (exc.ignore_x_mode && !exc.compatibility_mode && exc.GS.freeVector.y != 0) + Move_Zp2_Point(exc, point, dx, dy, true); + else if (exc.ignore_x_mode && exc.compatibility_mode) + { + if (exc.ignore_x_mode && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES)) + { + dx = FT_PIX_ROUND( B1 + dx ) - B1; + dy = FT_PIX_ROUND( B1 + dy ) - B1; + } + + if (!(exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ALWAYS_SKIP_DELTAP) && + ((exc.is_composite && exc.GS.freeVector.y != 0) || + (exc.zp2.tags[exc.zp2._offset_tags + point] & FT_Common.FT_CURVE_TAG_TOUCH_Y) || + (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_DO_SHPIX))) + Move_Zp2_Point(exc, point, dx, dy, true); + } + + /* save new point */ + if (exc.GS.freeVector.y != 0) + B2 = exc.zp2.cur[exc.zp2._offset_cur + point].y; + else + B2 = exc.zp2.cur[exc.zp2._offset_cur + point].x; + + /* reverse any disallowed moves */ + if (((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES) && + exc.GS.freeVector.y != 0 && + B1 % 64 != 0 && + B2 % 64 != 0 && + B1 != B2 ) || + ((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES) && + exc.GS.freeVector.y != 0 && + B1 % 64 == 0 && + B2 % 64 != 0 && + B1 != B2 && + !exc.size.ttfautohinted)) + { + Move_Zp2_Point(exc, point, -dx, -dy, true); + } + } + else + Move_Zp2_Point(exc, point, dx, dy, true); + + exc.GS.loop--; + } + } + + exc.GS.loop = 1; + exc.new_top = exc.args; +} + +function Ins_IP(exc, args, args_pos) +{ + if (exc.top < exc.GS.loop) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + + exc.GS.loop = 1; + exc.new_top = exc.args; + return; + } + + /* + * We need to deal in a special way with the twilight zone. + * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0), + * for every n. + */ + var twilight = (exc.GS.gep0 == 0 || exc.GS.gep1 == 0 || exc.GS.gep2 == 0) ? 1 : 0; + + if (exc.GS.rp1 >= exc.zp0.n_points) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + + exc.GS.loop = 1; + exc.new_top = exc.args; + return; + } + + var orus_base = null; + var orus_base_off = 0; + if (twilight) + { + orus_base = exc.zp0.org; + orus_base_off = exc.zp0._offset_org + exc.GS.rp1; + } + else + { + orus_base = exc.zp0.orus; + orus_base_off = exc.zp0._offset_orus + exc.GS.rp1; + } + + var cur_base = exc.zp0.cur; + var cur_base_off = exc.zp0._offset_cur + exc.GS.rp1; + + var old_range = 0; + var cur_range = 0; + + /* XXX: There are some glyphs in some braindead but popular */ + /* fonts out there (e.g. [aeu]grave in monotype.ttf) */ + /* calling IP[] with bad values of rp[12]. */ + /* Do something sane when this odd thing happens. */ + if ((exc.GS.rp1 >= exc.zp0.n_points) || (exc.GS.rp2 >= exc.zp1.n_points)) + { + old_range = 0; + cur_range = 0; + } + else + { + var v1, v2; + if (twilight != 0) + { + v1 = exc.zp1.org[exc.zp1._offset_org + exc.GS.rp2]; + v2 = orus_base[orus_base_off]; + old_range = exc.func_dualproj(exc, v1.x - v2.x, v1.y - v2.y); + } + else if (exc.metrics.x_scale == exc.metrics.y_scale) + { + v1 = exc.zp1.orus[exc.zp1._offset_orus + exc.GS.rp2]; + v2 = orus_base[orus_base_off]; + old_range = exc.func_dualproj(exc, v1.x - v2.x, v1.y - v2.y); + } + else + { + v1 = exc.zp1.orus[exc.zp1._offset_orus + exc.GS.rp2]; + v2 = orus_base[orus_base_off]; + + var _x = FT_MulFix(v1.x - v2.x, exc.metrics.x_scale); + var _y = FT_MulFix(v1.y - v2.y, exc.metrics.y_scale); + + old_range = exc.func_dualproj(exc, _x, _y); + } + + v1 = exc.zp1.cur[exc.zp1._offset_cur + exc.GS.rp2]; + v2 = cur_base[cur_base_off]; + + cur_range = exc.func_project(exc, v1.x - v2.x, v1.y - v2.y); + } + + for ( ; exc.GS.loop > 0; --exc.GS.loop ) + { + var point = exc.stack[--exc.args]; + var org_dist, cur_dist, new_dist; + + /* check point bounds */ + if (point >= exc.zp2.n_points) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + continue; + } + + var v1, v2; + if (twilight) + { + v1 = exc.zp2.org[exc.zp2._offset_org + point]; + v2 = orus_base[orus_base_off]; + org_dist = exc.func_dualproj(exc, v1.x - v2.x, v1.y - v2.y); + } + else if ( exc.metrics.x_scale == exc.metrics.y_scale ) + { + v1 = exc.zp2.orus[exc.zp2._offset_orus + point]; + v2 = orus_base[orus_base_off]; + org_dist = exc.func_dualproj(exc, v1.x - v2.x, v1.y - v2.y); + } + else + { + v1 = exc.zp2.orus[exc.zp2._offset_orus + point]; + v2 = orus_base[orus_base_off]; + + var _x = FT_MulFix(v1.x - v2.x, exc.metrics.x_scale); + var _y = FT_MulFix(v1.y - v2.y, exc.metrics.y_scale); + + org_dist = exc.func_dualproj(exc, _x, _y); + } + + v1 = exc.zp2.cur[exc.zp2._offset_cur + point]; + v2 = cur_base[cur_base_off]; + cur_dist = exc.func_project(exc, v1.x - v2.x, v1.y - v2.y); + + if (org_dist != 0) + new_dist = (old_range != 0) ? FT_MulDiv(org_dist, cur_range, old_range) : cur_dist; + else + new_dist = 0; + + exc.func_move(exc, exc.zp2, 0xFFFF & point, new_dist - cur_dist); + } + + exc.GS.loop = 1; + exc.new_top = exc.args; +} + +function Ins_MSIRP(exc, args, args_pos) +{ + var control_value_cutin = 0; + + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) + { + control_value_cutin = exc.GS.control_value_cutin; + if (exc.ignore_x_mode && exc.GS.freeVector.x != 0 && ((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_NORMAL_ROUND) == 0)) + control_value_cutin = 0; + } + + var point = 0xFFFF & args[args_pos]; + + if ((point >= exc.zp1.n_points) || (exc.GS.rp0 >= exc.zp0.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + /* UNDOCUMENTED! The MS rasterizer does that with */ + /* twilight points (confirmed by Greg Hitchcock) */ + if (exc.GS.gep1 == 0) + { + exc.zp1.org[exc.zp1._offset_org + point] = exc.zp0.org[exc.zp0._offset_org + exc.GS.rp0]; + exc.func_move_orig(exc, exc.zp1, point, args[args_pos + 1]); + exc.zp1.cur[exc.zp1._offset_cur + point] = exc.zp1.org[exc.zp1._offset_org + point]; + } + + var v1 = exc.zp1.cur[exc.zp1._offset_cur + point]; + var v2 = exc.zp0.cur[exc.zp0._offset_cur + exc.GS.rp0]; + var distance = exc.func_project(exc, v1.x - v2.x, v1.y - v2.y); + + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) // #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + control_value_cutin = exc.GS.control_value_cutin; + if (exc.ignore_x_mode && exc.GS.freeVector.x != 0 && (Math.abs(distance - args[args_pos + 1]) >= control_value_cutin)) + distance = args[args_pos + 1]; + } // #endif + + exc.func_move(exc, exc.zp1, point, args[args_pos + 1] - distance); + + exc.GS.rp1 = exc.GS.rp0; + exc.GS.rp2 = point; + + if ((exc.opcode & 1 ) != 0) + exc.GS.rp0 = point; +} + +function Ins_ALIGNRP(exc, args, args_pos) +{ + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING)//#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (exc.ignore_x_mode && exc.iup_called && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_NO_ALIGNRP_AFTER_IUP) != 0) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + exc.GS.loop = 1; + exc.new_top = exc.args; + return; + } + } // #endif + + if (exc.top < exc.GS.loop || (exc.GS.rp0 >= exc.zp0.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + + exc.GS.loop = 1; + exc.new_top = exc.args; + return; + } + + while (exc.GS.loop > 0) + { + exc.args--; + var point = 0xFFFF & exc.stack[exc.args]; + + if (point >= exc.zp1.n_points) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + else + { + var v1 = exc.zp1.cur[exc.zp1._offset_cur + point]; + var v2 = exc.zp0.cur[exc.zp0._offset_cur + exc.GS.rp0]; + var distance = exc.func_project(exc, v1.x - v2.x, v1.y - v2.y); + + exc.func_move(exc, exc.zp1, point, -distance); + } + exc.GS.loop--; + } + + exc.GS.loop = 1; + exc.new_top = exc.args; +} + +function Ins_RTDG(exc, args, args_pos) +{ + exc.GS.round_state = TT_Round_To_Double_Grid; + exc.func_round = Round_To_Double_Grid; +} + +function Ins_MIAP(exc, args, args_pos) +{ + var control_value_cutin = exc.GS.control_value_cutin; + var cvtEntry = FT_Common.IntToUInt(args[args_pos + 1]); + var point = 0xFFFF & args[args_pos]; + + var bIsSubpix = exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + if (bIsSubpix) // #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (exc.ignore_x_mode && exc.GS.freeVector.x != 0 && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_NORMAL_ROUND) == 0) + control_value_cutin = 0; + } // #endif + + if ((point >= exc.zp0.n_points) || (cvtEntry >= exc.cvtSize)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + + exc.GS.rp0 = point; + exc.GS.rp1 = point; + return; + } + + /* UNDOCUMENTED! */ + /* */ + /* The behaviour of an MIAP instruction is quite different when used */ + /* in the twilight zone. */ + /* */ + /* First, no control value cut-in test is performed as it would fail */ + /* anyway. Second, the original point, i.e. (org_x,org_y) of */ + /* zp0.point, is set to the absolute, unrounded distance found in the */ + /* CVT. */ + /* */ + /* This is used in the CVT programs of the Microsoft fonts Arial, */ + /* Times, etc., in order to re-adjust some key font heights. It */ + /* allows the use of the IP instruction in the twilight zone, which */ + /* otherwise would be invalid according to the specification. */ + /* */ + /* We implement it with a special sequence for the twilight zone. */ + /* This is a bad hack, but it seems to work. */ + /* */ + /* Confirmed by Greg Hitchcock. */ + + var distance = exc.func_read_cvt(exc, cvtEntry); + + if (exc.GS.gep0 == 0) /* If in twilight zone */ + { + if (bIsSubpix) + { + if (exc.compatibility_mode) + exc.zp0.org[exc.zp0._offset_org + point].x = TT_MulFix14(distance, exc.GS.freeVector.x); + } + else + { + exc.zp0.org[exc.zp0._offset_org + point].x = TT_MulFix14(distance, exc.GS.freeVector.x); + } + + exc.zp0.org[exc.zp0._offset_org + point].y = TT_MulFix14(distance, exc.GS.freeVector.y), + exc.zp0.cur[exc.zp0._offset_cur + point].x = exc.zp0.org[exc.zp0._offset_org + point].x; + exc.zp0.cur[exc.zp0._offset_cur + point].y = exc.zp0.org[exc.zp0._offset_org + point].y; + } + + if (bIsSubpix) + { + if ((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_MIAP_HACK) != 0 && distance > 0 && exc.GS.freeVector.y != 0) + distance = 0; + } + + var v = exc.zp0.cur[exc.zp0._offset_cur + point]; + var org_dist = exc.func_project(exc, v.x, v.y); + + if ((exc.opcode & 1) != 0) /* rounding and control cut-in flag */ + { + if (Math.abs( distance - org_dist) > control_value_cutin) + distance = org_dist; + + if (bIsSubpix) + { + if (exc.ignore_x_mode && exc.GS.freeVector.x != 0) + distance = Round_None(exc, distance, exc.tt_metrics.compensations[0]); + else + distance = exc.func_round(exc, distance, exc.tt_metrics.compensations[0]); + } + else + { + distance = exc.func_round(exc, distance, exc.tt_metrics.compensations[0]); + } + } + + exc.func_move(exc, exc.zp0, point, distance - org_dist); + + exc.GS.rp0 = point; + exc.GS.rp1 = point; +} + +function Ins_NPUSHB(exc, args, args_pos) +{ + var L = exc.code.data[exc.code.pos + exc.IP + 1]; + + if (L >= (exc.stackSize + 1 - exc.top)) + { + exc.error = FT_Common.FT_Err_Stack_Overflow; + return; + } + + for (var K = 1; K <= L; K++) + args[args_pos + K - 1] = exc.code.data[exc.code.pos + exc.IP + K + 1]; + + exc.new_top += L; +} + +// -- +function GetShortIns(exc) +{ + /* Reading a byte stream so there is no endianess (DaveP) */ + exc.IP += 2; + return FT_Common.UShort_To_Short((exc.code.data[exc.code.pos + exc.IP - 2] << 8) + exc.code.data[exc.code.pos + exc.IP - 1]); +} +// -- + +function Ins_NPUSHW(exc, args, args_pos) +{ + var L = exc.code.data[exc.code.pos + exc.IP + 1]; + + if (L >= (exc.stackSize + 1 - exc.top)) + { + exc.error = FT_Common.FT_Err_Stack_Overflow; + return; + } + + exc.IP += 2; + + for (var K = 0; K < L; K++) + args[args_pos + K] = GetShortIns(exc); + + exc.step_ins = false; + exc.new_top += L; +} + +function Ins_WS(exc, args, args_pos) +{ + var I = args[args_pos]; + if (I >= exc.storeSize) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + else + exc.storage[I] = args[args_pos + 1]; +} + +function Ins_RS(exc, args, args_pos) +{ + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING) + { + var I = FT_Common.IntToUInt(args[args_pos]); + if (I >= exc.storeSize) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + else + args[args_pos] = 0; + } + else + { + /* subpixel hinting - avoid Typeman Dstroke and */ + /* IStroke and Vacuform rounds */ + + if (exc.compatibility_mode && (I == 24 || I == 22 || I == 8)) + args[args_pos] = 0; + else + args[args_pos] = exc.storage[I]; + } + } + else + { + var I = FT_Common.IntToUInt(args[args_pos]); + + if (I >= exc.storeSize) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + else + args[args_pos] = 0; + } + else + args[args_pos] = exc.storage[I]; + } +} + +function Ins_WCVTP(exc, args, args_pos) +{ + var I = args[args_pos]; + if (I >= exc.cvtSize) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + else + exc.func_write_cvt(exc, I, args[args_pos + 1]); +} + +function Ins_RCVT(exc, args, args_pos) +{ + var I = args[args_pos]; + if (I >= exc.cvtSize) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + else + args[args_pos] = 0; + } + else + args[args_pos] = exc.func_read_cvt(exc, I); +} + +function Ins_GC(exc, args, args_pos) +{ + var L = args[args_pos]; + var R = 0; + if (L >= exc.zp2.n_points) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + } + else + { + if (exc.opcode & 1) + R = exc.func_dualproj(exc, exc.zp2.org[exc.zp2._offset_org + L].x, exc.zp2.org[exc.zp2._offset_org + L].y); + else + R = exc.func_project(exc, exc.zp2.cur[exc.zp2._offset_cur + L].x, exc.zp2.cur[exc.zp2._offset_cur + L].y); + } + + args[args_pos] = R; +} + +function Ins_SCFS(exc, args, args_pos) +{ + var L = 0xFFFF & args[args_pos]; + + if (L >= exc.zp2.n_points) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + var K = exc.func_project(exc, exc.zp2.cur[exc.zp2._offset_cur + L].x, exc.zp2.cur[exc.zp2._offset_cur + L].y); + + exc.func_move(exc, exc.zp2, L, args[args_pos + 1] - K); + + /* UNDOCUMENTED! The MS rasterizer does that with */ + /* twilight points (confirmed by Greg Hitchcock) */ + if (exc.GS.gep2 == 0) + { + exc.zp2.org[exc.zp2._offset_org + L].x = exc.zp2.cur[exc.zp2._offset_cur + L].x; + exc.zp2.org[exc.zp2._offset_org + L].y = exc.zp2.cur[exc.zp2._offset_cur + L].y; + } +} + +function Ins_MD(exc, args, args_pos) +{ + var D = 0; + var K = 0xFFFF & args[args_pos + 1]; + var L = 0xFFFF & args[args_pos]; + + if ((L >= exc.zp0.n_points) || (K >= exc.zp1.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + D = 0; + } + else + { + if (exc.opcode & 1) + { + var vec1 = exc.zp0.cur[exc.zp0._offset_cur + L]; + var vec2 = exc.zp1.cur[exc.zp1._offset_cur + K]; + + D = exc.func_project(exc, vec1.x - vec2.x, vec1.y - vec2.y); + } + else + { + /* XXX: UNDOCUMENTED: twilight zone special case */ + if (exc.GS.gep0 == 0 || exc.GS.gep1 == 0) + { + var vec1 = exc.zp0.org[exc.zp0._offset_org + L]; + var vec2 = exc.zp1.org[exc.zp1._offset_org + K]; + + D = exc.func_dualproj(exc, vec1.x - vec2.x, vec1.y - vec2.y); + } + else + { + var vec1 = exc.zp0.orus[exc.zp0._offset_orus + L]; + var vec2 = exc.zp1.orus[exc.zp1._offset_orus + K]; + + if ( exc.metrics.x_scale == exc.metrics.y_scale ) + { + /* this should be faster */ + D = exc.func_dualproj(exc, vec1.x - vec2.x, vec1.y - vec2.y); + D = FT_MulFix(D, exc.metrics.x_scale); + } + else + { + var vec = new FT_Vector(); + vec.x = FT_MulFix(vec1.x - vec2.x, exc.metrics.x_scale); + vec.y = FT_MulFix(vec1.y - vec2.y, exc.metrics.y_scale); + + D = exc.func_dualproj(exc, vec.x, vec.y); + } + } + } + } + + if (exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING)//#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */ + if (exc.ignore_x_mode && Math.abs(D) == 64) + D += 1; + } //#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + args[args_pos] = D; +} + +// -- +function Current_Ppem(exc) +{ + return FT_MulFix(exc.tt_metrics.ppem, Current_Ratio(exc)); +} + +function Current_Ratio(exc) +{ + if (!exc.tt_metrics.ratio) + { + // TODO: unpatented + if (exc.GS.projVector.y == 0) + exc.tt_metrics.ratio = exc.tt_metrics.x_ratio; + else if (exc.GS.projVector.x == 0) + exc.tt_metrics.ratio = exc.tt_metrics.y_ratio; + else + { + var x = TT_MulFix14(exc.tt_metrics.x_ratio, exc.GS.projVector.x); + var y = TT_MulFix14(exc.tt_metrics.y_ratio, exc.GS.projVector.y); + exc.tt_metrics.ratio = TT_VecLen(x, y); + } + } + return exc.tt_metrics.ratio; +} + +function FT_MulDiv_No_Round(a, b, c) +{ + var s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + var d = (c > 0 ? a * b / c : 0x7FFFFFFF); + d = d >> 0; + + return ( s > 0 ) ? d : -d; +} +// -- + +function Ins_MPPEM(exc, args, args_pos) +{ + args[args_pos] = Current_Ppem(exc); +} + +function Ins_MPS(exc, args, args_pos) +{ + args[args_pos] = Current_Ppem(exc); +} + +function Ins_FLIPON(exc, args, args_pos) +{ + exc.GS.auto_flip = true; +} + +function Ins_FLIPOFF(exc, args, args_pos) +{ + exc.GS.auto_flip = false; +} + +function Ins_DEBUG(exc, args, args_pos) +{ + exc.error = FT_Common.FT_Err_Debug_OpCode; +} + +function Ins_LT(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] < args[args_pos + 1]) ? 1 : 0; +} +function Ins_LTEQ(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] <= args[args_pos + 1]) ? 1 : 0; +} +function Ins_GT(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] > args[args_pos + 1]) ? 1 : 0; +} +function Ins_GTEQ(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] >= args[args_pos + 1]) ? 1 : 0; +} +function Ins_EQ(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] == args[args_pos + 1]) ? 1 : 0; +} +function Ins_NEQ(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] != args[args_pos + 1]) ? 1 : 0; +} +function Ins_ODD(exc, args, args_pos) +{ + args[args_pos] = ((exc.func_round(exc, args[args_pos], 0) & 127) == 64) ? 1 : 0; +} +function Ins_EVEN(exc, args, args_pos) +{ + args[args_pos] = ((exc.func_round(exc, args[args_pos], 0) & 127) == 64) ? 1 : 0; +} +function Ins_IF(exc, args, args_pos) +{ + if (args[args_pos] != 0) + return; + + var nIfs = 1; + var Out = 0; + + do + { + if (SkipCode(exc) == 1) + return; + + switch ( exc.opcode ) + { + case 0x58: /* IF */ + nIfs++; + break; + case 0x1B: /* ELSE */ + Out = (nIfs == 1) ? 1 : 0; + break; + case 0x59: /* EIF */ + nIfs--; + Out = (nIfs == 0) ? 1 : 0; + break; + } + } while ( Out == 0 ); +} +function Ins_EIF(exc, args, args_pos) +{ + // nothing +} +function Ins_AND(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] && args[args_pos + 1]) ? 1 : 0; +} +function Ins_OR(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] || args[args_pos + 1]) ? 1 : 0; +} +function Ins_NOT(exc, args, args_pos) +{ + args[args_pos] = (args[args_pos] != 0) ? 0 : 1; +} +function Ins_SDB(exc, args, args_pos) +{ + exc.GS.delta_base = FT_Common.UShort_To_Short(0xFFFF & args[args_pos]); +} +function Ins_SDS(exc, args, args_pos) +{ + exc.GS.delta_shift = FT_Common.UShort_To_Short(0xFFFF & args[args_pos]); +} + +function Ins_ADD(exc, args, args_pos) +{ + args[args_pos] += args[args_pos + 1]; +} +function Ins_SUB(exc, args, args_pos) +{ + args[args_pos] -= args[args_pos + 1]; +} +function Ins_DIV(exc, args, args_pos) +{ + if (args[args_pos + 1] == 0) + exc.error = FT_Common.FT_Err_Divide_By_Zero; + else + args[args_pos] = FT_MulDiv_No_Round(args[args_pos], 64, args[args_pos + 1]); +} +function Ins_MUL(exc, args, args_pos) +{ + args[args_pos] = FT_MulDiv(args[args_pos], args[args_pos + 1], 64); +} +function Ins_ABS(exc, args, args_pos) +{ + args[args_pos] = Math.abs(args[args_pos]); +} +function Ins_NEG(exc, args, args_pos) +{ + args[args_pos] = -args[args_pos]; +} +function Ins_FLOOR(exc, args, args_pos) +{ + args[args_pos] = FT_PIX_FLOOR(args[args_pos]); +} +function Ins_CEILING(exc, args, args_pos) +{ + args[args_pos] = FT_PIX_CEIL(args[args_pos]); +} +function Ins_ROUND(exc, args, args_pos) +{ + args[args_pos] = exc.func_round(exc, args[args_pos], exc.tt_metrics.compensations[exc.opcode - 0x68]); +} +function Ins_NROUND(exc, args, args_pos) +{ + args[args_pos] = Round_None(exc, args[args_pos], exc.tt_metrics.compensations[exc.opcode - 0x6C]); +} + +function Ins_WCVTF(exc, args, args_pos) +{ + var I = args[args_pos]; + if (I >= exc.cvtSize) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + else + { + exc.cvt[I] = FT_MulFix(args[args_pos + 1], exc.tt_metrics.scale); + } +} + +function Ins_DELTAP(exc, args, args_pos) +{ + var A = 0; + var C = 0; + var B = 0; + var B1 = 0; + var B2 = 0; + + var bIsSubpix = exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + // TODO: unpatented + + var nump = args[args_pos]; /* some points theoretically may occur more + than once, thus UShort isn't enough */ + if (nump < 0) + nump += FT_Common.a_i; + + for (var k = 1; k <= nump; k++) + { + if (exc.args < 2) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Too_Few_Arguments; + exc.args = 0; + exc.new_top = exc.args; + return; + } + + exc.args -= 2; + + A = 0xFFFF & exc.stack[exc.args + 1]; + B = exc.stack[exc.args]; + + /* XXX: Because some popular fonts contain some invalid DeltaP */ + /* instructions, we simply ignore them when the stacked */ + /* point reference is off limit, rather than returning an */ + /* error. As a delta instruction doesn't change a glyph */ + /* in great ways, this shouldn't be a problem. */ + if (A < exc.zp0.n_points) + { + C = (B & 0xF0) >> 4; + + switch (exc.opcode) + { + case 0x5D: + break; + case 0x71: + C += 16; + break; + case 0x72: + C += 32; + break; + } + + C += exc.GS.delta_base; + if (C < 0) + C += FT_Common.a_i; + + if (Current_Ppem(exc) == C) + { + B = (B & 0xF) - 8; + if (B >= 0) + B++; + B = B * 64 / (1 << exc.GS.delta_shift); + B = B >> 0; + + if (!bIsSubpix) + { + exc.func_move(exc, exc.zp0, A, B); + } + else + { + /* + * Allow delta move if + * + * - not using ignore_x_mode rendering + * - glyph is specifically set to allow it + * - glyph is composite and freedom vector is not subpixel vector + */ + if (!exc.ignore_x_mode || (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ALWAYS_DO_DELTAP) != 0 || + (exc.is_composite && exc.GS.freeVector.y != 0)) + exc.func_move(exc, exc.zp0, A, B); + else if (exc.ignore_x_mode) /* Otherwise apply subpixel hinting and compatibility mode rules */ + { + if (exc.GS.freeVector.y != 0) + B1 = exc.zp0.cur[exc.zp0._offset_cur + A].y; + else + B1 = exc.zp0.cur[exc.zp0._offset_cur + A].x; + + /* Standard Subpixel Hinting: Allow y move */ + if (!exc.compatibility_mode && exc.GS.freeVector.y != 0) + exc.func_move(exc, exc.zp0, A, B); + /* Compatibility Mode: Allow x or y move if point touched in Y direction */ + else if (exc.compatibility_mode && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ALWAYS_SKIP_DELTAP) == 0) + { + /* save the y value of the point now; compare after move */ + B1 = exc.zp0.cur[exc.zp0._offset_cur + A].y; + + if ((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES) != 0) + B = FT_PIX_ROUND(B1 + B) - B1; + + /* + * Allow delta move if using compatibility_mode, IUP has not + * been called, and point is touched on Y. + */ + if (!exc.iup_called && (exc.zp0.tags[exc.zp0._offset_tags + A] & FT_Common.FT_CURVE_TAG_TOUCH_Y) != 0) + exc.func_move(exc, exc.zp0, A, B); + } + + B2 = exc.zp0.cur[exc.zp0._offset_cur + A].y; + + /* Reverse this move if it results in a disallowed move */ + if (exc.GS.freeVector.y != 0 && (((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES) && + (B1 % 64) == 0 && (B2 % 64) != 0 && !exc.size.ttfautohinted) || + ((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES) && (B1 % 64) != 0 && (B2 % 64) != 0))) + exc.func_move(exc, exc.zp0, A, -B); + } + } + + } + } + else + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + } + } + + exc.new_top = exc.args; +} + +function Ins_DELTAC(exc, args, args_pos) +{ + // TODO: unpatented + var nump = args[args_pos]; + + for (var k = 1; k <= nump; k++) + { + if (exc.args < 2) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Too_Few_Arguments; + exc.args = 0; + exc.new_top = exc.args; + return; + } + + exc.args -= 2; + + var A = FT_Common.IntToUInt(exc.stack[exc.args + 1]); + var B = exc.stack[exc.args]; + var C = 0; + + if (A >= exc.cvtSize) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + else + { + C = (B & 0xF0) >> 4; + + switch (exc.opcode) + { + case 0x73: + break; + case 0x74: + C += 16; + break; + case 0x75: + C += 32; + break; + } + + C += exc.GS.delta_base; + + if (Current_Ppem(exc) == C) + { + B = (B & 0xF) - 8; + if (B >= 0) + B++; + B = B * 64 / (1 << exc.GS.delta_shift); + B = B >> 0; + + exc.func_move_cvt(exc, A, B); + } + } + } + exc.new_top = exc.args; +} + +function Ins_SROUND(exc, args, args_pos) +{ + SetSuperRound(exc, 0x4000, args[args_pos]); + exc.GS.round_state = TT_Round_Super; + exc.func_round = Round_Super; +} + +function Ins_S45ROUND(exc, args, args_pos) +{ + SetSuperRound(exc, 0x2D41, args[args_pos]); + exc.GS.round_state = TT_Round_Super_45; + exc.func_round = Round_Super_45; +} + +function Ins_JROT(exc, args, args_pos) +{ + if (args[args_pos + 1] != 0) + { + if (args[args_pos] == 0 && exc.args == 0) + exc.error = FT_Common.FT_Err_Bad_Argument; + exc.IP += args[args_pos]; + if (exc.IP < 0 || (exc.callTop > 0 && exc.IP > exc.callStack[exc.callTop - 1].Cur_End)) + exc.error = FT_Common.FT_Err_Bad_Argument; + exc.step_ins = false; + } +} + +function Ins_JROF(exc, args, args_pos) +{ + if (args[args_pos + 1] == 0) + { + if (args[args_pos] == 0 && exc.args == 0) + exc.error = FT_Common.FT_Err_Bad_Argument; + exc.IP += args[args_pos]; + if (exc.IP < 0 || (exc.callTop > 0 && exc.IP > exc.callStack[exc.callTop - 1].Cur_End)) + exc.error = FT_Common.FT_Err_Bad_Argument; + exc.step_ins = false; + } +} + +function Ins_ROFF(exc, args, args_pos) +{ + exc.GS.round_state = TT_Round_Off; + exc.func_round = Round_None; +} + +function Ins_RUTG(exc, args, args_pos) +{ + exc.GS.round_state = TT_Round_Up_To_Grid; + exc.func_round = Round_Up_To_Grid; +} + +function Ins_RDTG(exc, args, args_pos) +{ + exc.GS.round_state = TT_Round_Down_To_Grid; + exc.func_round = Round_Down_To_Grid; +} + +function Ins_SANGW(exc, args, args_pos) +{ + /* instruction not supported anymore */ +} + +function Ins_AA(exc, args, args_pos) +{ + /* intentionally no longer supported */ +} + +function Ins_FLIPPT(exc, args, args_pos) +{ + if (exc.top < exc.GS.loop) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Too_Few_Arguments; + + exc.GS.loop = 1; + exc.new_top = exc.args; + return; + } + + while (exc.GS.loop > 0) + { + exc.args--; + var point = 0xFFFF & exc.stack[exc.args]; + + if (point >= exc.pts.n_points) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + } + else + exc.pts.tags[exc.pts._offset_tags + point] ^= FT_Common.FT_CURVE_TAG_ON; + + exc.GS.loop--; + } + + exc.GS.loop = 1; + exc.new_top = exc.args; +} + +function Ins_FLIPRGON(exc, args, args_pos) +{ + var K = 0xFFFF & args[args_pos + 1]; + var L = 0xFFFF & args[args_pos]; + + if ((K >= exc.pts.n_points) || (L >= exc.pts.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + for (var I = L; I <= K; I++) + exc.pts.tags[exc.pts._offset_tags + I] |= FT_Common.FT_CURVE_TAG_ON; +} + +function Ins_FLIPRGOFF(exc, args, args_pos) +{ + var K = 0xFFFF & args[args_pos + 1]; + var L = 0xFFFF & args[args_pos]; + + if ((K >= exc.pts.n_points) || (L >= exc.pts.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + for (var I = L; I <= K; I++) + exc.pts.tags[exc.pts._offset_tags + I] &= ~FT_Common.FT_CURVE_TAG_ON; +} + +function Ins_SCANCTRL(exc, args, args_pos) +{ + /* Get Threshold */ + var A = (args[args_pos] & 0xFF); + + if (A == 0xFF) + { + exc.GS.scan_control = true; + return; + } + else if (A == 0) + { + exc.GS.scan_control = false; + return; + } + + if ((args[args_pos] & 0x100 ) != 0 && exc.tt_metrics.ppem <= A) + exc.GS.scan_control = true; + + if ((args[args_pos] & 0x200 ) != 0 && exc.tt_metrics.rotated) + exc.GS.scan_control = true; + + if ((args[args_pos] & 0x400 ) != 0 && exc.tt_metrics.stretched) + exc.GS.scan_control = true; + + if ((args[args_pos] & 0x800 ) != 0 && exc.tt_metrics.ppem > A) + exc.GS.scan_control = false; + + if ((args[args_pos] & 0x1000 ) != 0 && exc.tt_metrics.rotated) + exc.GS.scan_control = false; + + if ((args[args_pos] & 0x2000 ) != 0 && exc.tt_metrics.stretched) + exc.GS.scan_control = false; +} + +function Ins_SDPVTL(exc, args, args_pos) +{ + var aOpc = exc.opcode; + + var p1 = 0xFFFF & args[args_pos + 1]; + var p2 = 0xFFFF & args[args_pos]; + + if ((p2 >= exc.zp1.n_points) || (p1 >= exc.zp2.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + var v1 = exc.zp1.org[exc.zp1._offset_org + p2]; + var v2 = exc.zp2.org[exc.zp2._offset_org + p1]; + + var A = v1.x - v2.x; + var B = v1.y - v2.y; + + /* If v1 == v2, SDPVTL behaves the same as */ + /* SVTCA[X], respectively. */ + /* */ + /* Confirmed by Greg Hitchcock. */ + if ( A == 0 && B == 0 ) + { + A = 0x4000; + aOpc = 0; + } + + if ((aOpc & 1) != 0) + { + var C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + Normalize(exc, A, B, exc.GS.dualVector); + + v1 = exc.zp1.cur[exc.zp1._offset_cur + p2]; + v2 = exc.zp2.cur[exc.zp2._offset_cur + p1]; + + A = v1.x - v2.x; + B = v1.y - v2.y; + + if ((aOpc & 1) != 0) + { + var C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + Normalize(exc, A, B, exc.GS.projVector); + + GUESS_VECTOR(exc, exc.GS.freeVector); + + Compute_Funcs(exc); +} + +function Ins_GETINFO(exc, args, args_pos) +{ + var K = 0; + var bIsSubpix = exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + + if (bIsSubpix) + { + /********************************/ + /* RASTERIZER VERSION */ + /* Selector Bit: 0 */ + /* Return Bit(s): 0-7 */ + /* */ + if ((args[args_pos] & 1) != 0 && exc.ignore_x_mode) + { + K = exc.rasterizer_version; + } + else + { + if ((args[args_pos] & 1) != 0) + K = 35; + } + } + else + { + if ((args[args_pos] & 1) != 0) + K = 35; + } + + /********************************/ + /* GLYPH ROTATED */ + /* Selector Bit: 1 */ + /* Return Bit(s): 8 */ + /* */ + if (( args[args_pos] & 2) != 0 && exc.tt_metrics.rotated) + K |= 0x80; + + /********************************/ + /* GLYPH STRETCHED */ + /* Selector Bit: 2 */ + /* Return Bit(s): 9 */ + /* */ + if ((args[args_pos] & 4) != 0 && exc.tt_metrics.stretched) + K |= 1 << 8; + + /********************************/ + /* HINTING FOR GRAYSCALE */ + /* Selector Bit: 5 */ + /* Return Bit(s): 12 */ + /* */ + if ((args[args_pos] & 32) != 0 && exc.grayscale) + K |= 1 << 12; + + if (bIsSubpix) //#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (exc.ignore_x_mode && exc.rasterizer_version >= 35) + { + /********************************/ + /* HINTING FOR GRAYSCALE */ + /* Selector Bit: 5 */ + /* Return Bit(s): 12 */ + /* */ + if ((args[args_pos] & 32) != 0 && exc.grayscale_hinting) + K |= 1 << 12; + + /********************************/ + /* HINTING FOR SUBPIXEL */ + /* Selector Bit: 6 */ + /* Return Bit(s): 13 */ + /* */ + if ((args[args_pos] & 64) != 0 && exc.subpixel_hinting && exc.rasterizer_version >= 37) + { + K |= 1 << 13; + + /* the stuff below is irrelevant if subpixel_hinting is not set */ + + /********************************/ + /* COMPATIBLE WIDTHS ENABLED */ + /* Selector Bit: 7 */ + /* Return Bit(s): 14 */ + /* */ + /* Functionality still needs to be added */ + if ((args[args_pos] & 128) != 0 && exc.compatible_widths) + K |= 1 << 14; + + /********************************/ + /* SYMMETRICAL SMOOTHING */ + /* Selector Bit: 8 */ + /* Return Bit(s): 15 */ + /* */ + /* Functionality still needs to be added */ + if ((args[args_pos] & 256) != 0 && exc.symmetrical_smoothing) + K |= 1 << 15; + + /********************************/ + /* HINTING FOR BGR? */ + /* Selector Bit: 9 */ + /* Return Bit(s): 16 */ + /* */ + /* Functionality still needs to be added */ + if ((args[args_pos] & 512) != 0 && exc.bgr) + K |= 1 << 16; + + if (exc.rasterizer_version >= 38) + { + /********************************/ + /* SUBPIXEL POSITIONED? */ + /* Selector Bit: 10 */ + /* Return Bit(s): 17 */ + /* */ + /* Functionality still needs to be added */ + if ((args[args_pos] & 1024) != 0 && exc.subpixel_positioned) + K |= 1 << 17; + } + } + } + }//#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + args[args_pos] = K; +} + +function Ins_IDEF(exc, args, args_pos) +{ + /* First of all, look for the same function in our table */ + var defs = exc.IDefs; + var _ind_def = 0; + var limit = exc.numIDefs; + var def = defs[_ind_def]; + + for ( ; _ind_def < limit; _ind_def++) + { + def = defs[_ind_def]; + if (def.opc == args[args_pos]) + break; + } + + if (_ind_def == limit) + { + /* check that there is enough room for a new instruction */ + if (exc.numIDefs >= exc.maxIDefs) + { + exc.error = FT_Common.FT_Err_Too_Many_Instruction_Defs; + return; + } + exc.numIDefs++; + } + + /* opcode must be unsigned 8-bit integer */ + if (0 > args[args_pos] || args[args_pos] > 0x00FF) + { + exc.error = FT_Common.FT_Err_Too_Many_Instruction_Defs; + return; + } + + def.opc = 0xFF & args[args_pos]; + def.start = exc.IP + 1; + def.range = exc.curRange; + def.active = true; + + if (args[args_pos] > exc.maxIns) + exc.maxIns = 0xFF & args[args_pos]; + + /* Now skip the whole function definition. */ + /* We don't allow nested IDEFs & FDEFs. */ + + while (SkipCode(exc) == 0) + { + switch (exc.opcode) + { + case 0x89: /* IDEF */ + case 0x2C: /* FDEF */ + exc.error = FT_Common.FT_Err_Nested_DEFS; + return; + case 0x2D: /* ENDF */ + return; + } + } +} + +function Ins_ROLL(exc, args, args_pos) +{ + var A = args[args_pos + 2]; + var B = args[args_pos + 1]; + var C = args[args_pos]; + + args[args_pos + 2] = C; + args[args_pos + 1] = A; + args[args_pos] = B; +} + +function Ins_MAX(exc, args, args_pos) +{ + if (args[args_pos + 1] > args[args_pos]) + args[args_pos] = args[args_pos + 1]; +} + +function Ins_MIN(exc, args, args_pos) +{ + if (args[args_pos + 1] < args[args_pos]) + args[args_pos] = args[args_pos + 1]; +} + +function Ins_SCANTYPE(exc, args, args_pos) +{ + if (args[args_pos] >= 0) + exc.GS.scan_type = args[args_pos]; +} + +function Ins_INSTCTRL(exc, args, args_pos) +{ + var K = args[args_pos + 1]; + var L = args[args_pos]; + + if (K < 1 || K > 2) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + return; + } + + if (L != 0) + L = K; + + exc.GS.instruct_control = ((((0xFF & exc.GS.instruct_control) & ~(K & 0xFF)) | (L & 0xFF)) != 0) ? 1 : 0; +} + +function Ins_PUSHB(exc, args, args_pos) +{ + var L = 0xFFFF & (exc.opcode - 0xB0 + 1); + + if (L >= (exc.stackSize + 1 - exc.top)) + { + exc.error = FT_Common.FT_Err_Stack_Overflow; + return; + } + + for (var K = 1; K <= L; K++) + args[args_pos + K - 1] = exc.code.data[exc.code.pos + exc.IP + K]; +} + +function Ins_PUSHW(exc, args, args_pos) +{ + var L = 0xFFFF & (exc.opcode - 0xB8 + 1); + + if (L >= (exc.stackSize + 1 - exc.top)) + { + exc.error = FT_Common.FT_Err_Stack_Overflow; + return; + } + + exc.IP++; + + for (var K = 0; K < L; K++) + args[args_pos + K] = GetShortIns(exc); + + exc.step_ins = false; +} + +function Ins_MDRP(exc, args, args_pos) +{ + var org_dist, distance; + var minimum_distance = exc.GS.minimum_distance; + + var bIsSubpix = exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + + if (bIsSubpix) + { + if (exc.ignore_x_mode && exc.GS.freeVector.x != 0 && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_NORMAL_ROUND) == 0) + minimum_distance = 0; + } + + var point = 0xFFFF & args[args_pos]; + + if ((point >= exc.zp1.n_points) || (exc.GS.rp0 >= exc.zp0.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + + exc.GS.rp1 = exc.GS.rp0; + exc.GS.rp2 = point; + if ((exc.opcode & 16) != 0) + exc.GS.rp0 = point; + } + + /* XXX: Is there some undocumented feature while in the */ + /* twilight zone? */ + + var v1, v2; + /* XXX: UNDOCUMENTED: twilight zone special case */ + if (exc.GS.gep0 == 0 || exc.GS.gep1 == 0) + { + v1 = exc.zp1.org[exc.zp1._offset_org + point]; + v2 = exc.zp0.org[exc.zp0._offset_org + exc.GS.rp0]; + org_dist = exc.func_dualproj(exc, v1.x - v2.x, v1.y - v2.y); + } + else + { + v1 = exc.zp1.orus[exc.zp1._offset_orus + point]; + v2 = exc.zp0.orus[exc.zp0._offset_orus + exc.GS.rp0]; + + if (exc.metrics.x_scale == exc.metrics.y_scale) + { + /* this should be faster */ + org_dist = exc.func_dualproj(exc, v1.x - v2.x, v1.y - v2.y); + org_dist = FT_MulFix(org_dist, exc.metrics.x_scale); + } + else + { + var _x = FT_MulFix(v1.x - v2.x, exc.metrics.x_scale); + var _y = FT_MulFix(v1.y - v2.y, exc.metrics.y_scale); + org_dist = exc.func_dualproj(exc, _x, _y); + } + } + + /* single width cut-in test */ + if (Math.abs(org_dist - exc.GS.single_width_value) < exc.GS.single_width_cutin) + { + if (org_dist >= 0) + org_dist = exc.GS.single_width_value; + else + org_dist = -exc.GS.single_width_value; + } + + /* round flag */ + if ((exc.opcode & 4) != 0) + { + if (bIsSubpix) + { + if (exc.ignore_x_mode && exc.GS.freeVector.x != 0) + distance = Round_None(org_dist, exc.tt_metrics.compensations[exc.opcode & 3]); + else + distance = exc.func_round(exc, org_dist, exc.tt_metrics.compensations[exc.opcode & 3]); + } + else + { + distance = exc.func_round(exc, org_dist, exc.tt_metrics.compensations[exc.opcode & 3]); + } + } + else + distance = Round_None(exc, org_dist, exc.tt_metrics.compensations[exc.opcode & 3]); + + /* minimum distance flag */ + if ((exc.opcode & 8) != 0) + { + if (org_dist >= 0) + { + if (distance < minimum_distance) + distance = minimum_distance; + } + else + { + if (distance > -minimum_distance) + distance = -minimum_distance; + } + } + + /* now move the point */ + v1 = exc.zp1.cur[exc.zp1._offset_cur + point]; + v2 = exc.zp0.cur[exc.zp0._offset_cur + exc.GS.rp0]; + org_dist = exc.func_project(exc, v1.x - v2.x, v1.y - v2.y); + + exc.func_move(exc, exc.zp1, point, distance - org_dist); + + exc.GS.rp1 = exc.GS.rp0; + exc.GS.rp2 = point; + if ((exc.opcode & 16) != 0) + exc.GS.rp0 = point; +} + +function Ins_MIRP(exc, args, args_pos) +{ + var bIsSubpix = exc.face.driver.library.tt_hint_props.TT_CONFIG_OPTION_SUBPIXEL_HINTING; + + var minimum_distance = exc.GS.minimum_distance; + var control_value_cutin = exc.GS.control_value_cutin; + var point = 0xFFFF & args[args_pos]; + var cvtEntry = FT_Common.IntToUInt(args[args_pos + 1] + 1); + var distance = 0; + + if (bIsSubpix) + { + if (exc.ignore_x_mode && exc.GS.freeVector.x != 0 && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_NORMAL_ROUND) == 0) + control_value_cutin = minimum_distance = 0; + } + + /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ + if ((point >= exc.zp1.n_points) || (cvtEntry >= (exc.cvtSize + 1)) || (exc.GS.rp0 >= exc.zp0.n_points)) + { + if (exc.pedantic_hinting) + exc.error = FT_Common.FT_Err_Invalid_Reference; + + exc.GS.rp1 = exc.GS.rp0; + if ((exc.opcode & 16) != 0) + exc.GS.rp0 = point; + exc.GS.rp2 = point; + } + + var cvt_dist = 0; + if (cvtEntry == 0) + cvt_dist = 0; + else + cvt_dist = exc.func_read_cvt(exc, cvtEntry - 1); + + if (bIsSubpix) + { + if (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_MIRP_CVT_ZERO) + cvt_dist = 0; + } + + /* single width test */ + if (Math.abs(cvt_dist - exc.GS.single_width_value) < exc.GS.single_width_cutin) + { + if (cvt_dist >= 0) + cvt_dist = exc.GS.single_width_value; + else + cvt_dist = -exc.GS.single_width_value; + } + + /* UNDOCUMENTED! The MS rasterizer does that with */ + /* twilight points (confirmed by Greg Hitchcock) */ + if (exc.GS.gep1 == 0) + { + var _v = exc.zp0.org[exc.zp0._offset_org + exc.GS.rp0]; + exc.zp1.org[exc.zp1._offset_org + point].x = _v.x + TT_MulFix14(cvt_dist, exc.GS.freeVector.x); + exc.zp1.org[exc.zp1._offset_org + point].y = _v.y + TT_MulFix14(cvt_dist, exc.GS.freeVector.y); + + exc.zp1.cur[exc.zp1._offset_cur + point].x = exc.zp1.org[exc.zp1._offset_org + point].x; + exc.zp1.cur[exc.zp1._offset_cur + point].y = exc.zp1.org[exc.zp1._offset_org + point].y; + } + + var v1 = exc.zp1.org[exc.zp1._offset_org + point]; + var v2 = exc.zp0.org[exc.zp0._offset_org + exc.GS.rp0]; + + var org_dist = exc.func_dualproj(exc, v1.x - v2.x, v1.y - v2.y); + + v1 = exc.zp1.cur[exc.zp1._offset_cur + point]; + v2 = exc.zp0.cur[exc.zp0._offset_cur + exc.GS.rp0]; + + var cur_dist = exc.func_project(exc, v1.x - v2.x, v1.y - v2.y); + + /* auto-flip test */ + if (exc.GS.auto_flip) + { + if ((org_dist ^ cvt_dist) < 0) + cvt_dist = -cvt_dist; + } + + if (bIsSubpix) //#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (exc.GS.freeVector.y != 0 && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_TIMES_NEW_ROMAN_HACK) != 0) + { + if (cur_dist < -64) + cvt_dist -= 16; + else if (cur_dist > 64 && cur_dist < 84) + cvt_dist += 32; + } + } //#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + /* control value cut-in and round */ + if ((exc.opcode & 4) != 0) + { + /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */ + /* refer to the same zone. */ + if (exc.GS.gep0 == exc.GS.gep1) + { + /* XXX: According to Greg Hitchcock, the following wording is */ + /* the right one: */ + /* */ + /* When the absolute difference between the value in */ + /* the table [CVT] and the measurement directly from */ + /* the outline is _greater_ than the cut_in value, the */ + /* outline measurement is used. */ + /* */ + /* This is from `instgly.doc'. The description in */ + /* `ttinst2.doc', version 1.66, is thus incorrect since */ + /* it implies `>=' instead of `>'. */ + + if (Math.abs(cvt_dist - org_dist) > control_value_cutin) + cvt_dist = org_dist; + } + + distance = exc.func_round(exc, cvt_dist, exc.tt_metrics.compensations[exc.opcode & 3]); + } + else + distance = Round_None(exc, cvt_dist, exc.tt_metrics.compensations[exc.opcode & 3]); + + /* minimum distance test */ + if ((exc.opcode & 8) != 0) + { + if (org_dist >= 0) + { + if (distance < minimum_distance) + distance = minimum_distance; + } + else + { + if (distance > -minimum_distance) + distance = -minimum_distance; + } + } + + if (!bIsSubpix) + { + exc.func_move(exc, exc.zp1, point, distance - cur_dist); + } + else + { + var B1 = exc.zp1.cur[exc.zp1._offset_cur + point].y; + + /* Round moves if necessary */ + if (exc.ignore_x_mode && exc.GS.freeVector.y != 0 && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES) != 0) + distance = FT_PIX_ROUND(B1 + distance - cur_dist) - B1 + cur_dist; + + if (exc.GS.freeVector.y != 0 && (exc.opcode & 16) == 0 && (exc.opcode & 8) == 0 && (exc.sph_tweak_flags & FT_Common.SPH_TWEAK_COURIER_NEW_2_HACK) != 0) + distance += 64; + + exc.func_move(exc, exc.zp1, point, distance - cur_dist); + + var B2 = exc.zp1.cur[exc.zp1._offset_cur + point].y; + + var reverse_move = false; + /* Reverse move if necessary */ + if (exc.ignore_x_mode) + { + if ((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES) != 0 && exc.GS.freeVector.y != 0 && (B1 % 64) == 0 && + (B2 % 64) != 0 && !exc.size.ttfautohinted) + reverse_move = true; + + if ((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES) != 0 && exc.GS.freeVector.y != 0 && + (B2 % 64) != 0 && (B1 % 64) != 0) + reverse_move = true; + + if ((exc.sph_tweak_flags & FT_Common.SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES) != 0 && !reverse_move && Math.abs(B1 - B2) >= 64) + reverse_move = true; + } + + if (reverse_move) + exc.func_move(exc, exc.zp1, point, -(distance - cur_dist)); + } + + exc.GS.rp1 = exc.GS.rp0; + if ((exc.opcode & 16) != 0) + exc.GS.rp0 = point; + exc.GS.rp2 = point; +} + +var Instruct_Dispatch = +[ + /* Opcodes are gathered in groups of 16. */ + /* Please keep the spaces as they are. */ + + /* SVTCA y */ Ins_SVTCA, + /* SVTCA x */ Ins_SVTCA, + /* SPvTCA y */ Ins_SPVTCA, + /* SPvTCA x */ Ins_SPVTCA, + /* SFvTCA y */ Ins_SFVTCA, + /* SFvTCA x */ Ins_SFVTCA, + /* SPvTL // */ Ins_SPVTL, + /* SPvTL + */ Ins_SPVTL, + /* SFvTL // */ Ins_SFVTL, + /* SFvTL + */ Ins_SFVTL, + /* SPvFS */ Ins_SPVFS, + /* SFvFS */ Ins_SFVFS, + /* GPV */ Ins_GPV, + /* GFV */ Ins_GFV, + /* SFvTPv */ Ins_SFVTPV, + /* ISECT */ Ins_ISECT, + + /* SRP0 */ Ins_SRP0, + /* SRP1 */ Ins_SRP1, + /* SRP2 */ Ins_SRP2, + /* SZP0 */ Ins_SZP0, + /* SZP1 */ Ins_SZP1, + /* SZP2 */ Ins_SZP2, + /* SZPS */ Ins_SZPS, + /* SLOOP */ Ins_SLOOP, + /* RTG */ Ins_RTG, + /* RTHG */ Ins_RTHG, + /* SMD */ Ins_SMD, + /* ELSE */ Ins_ELSE, + /* JMPR */ Ins_JMPR, + /* SCvTCi */ Ins_SCVTCI, + /* SSwCi */ Ins_SSWCI, + /* SSW */ Ins_SSW, + + /* DUP */ Ins_DUP, + /* POP */ Ins_POP, + /* CLEAR */ Ins_CLEAR, + /* SWAP */ Ins_SWAP, + /* DEPTH */ Ins_DEPTH, + /* CINDEX */ Ins_CINDEX, + /* MINDEX */ Ins_MINDEX, + /* AlignPTS */ Ins_ALIGNPTS, + /* INS_0x28 */ Ins_UNKNOWN, + /* UTP */ Ins_UTP, + /* LOOPCALL */ Ins_LOOPCALL, + /* CALL */ Ins_CALL, + /* FDEF */ Ins_FDEF, + /* ENDF */ Ins_ENDF, + /* MDAP[0] */ Ins_MDAP, + /* MDAP[1] */ Ins_MDAP, + + /* IUP[0] */ Ins_IUP, + /* IUP[1] */ Ins_IUP, + /* SHP[0] */ Ins_SHP, + /* SHP[1] */ Ins_SHP, + /* SHC[0] */ Ins_SHC, + /* SHC[1] */ Ins_SHC, + /* SHZ[0] */ Ins_SHZ, + /* SHZ[1] */ Ins_SHZ, + /* SHPIX */ Ins_SHPIX, + /* IP */ Ins_IP, + /* MSIRP[0] */ Ins_MSIRP, + /* MSIRP[1] */ Ins_MSIRP, + /* AlignRP */ Ins_ALIGNRP, + /* RTDG */ Ins_RTDG, + /* MIAP[0] */ Ins_MIAP, + /* MIAP[1] */ Ins_MIAP, + + /* NPushB */ Ins_NPUSHB, + /* NPushW */ Ins_NPUSHW, + /* WS */ Ins_WS, + /* RS */ Ins_RS, + /* WCvtP */ Ins_WCVTP, + /* RCvt */ Ins_RCVT, + /* GC[0] */ Ins_GC, + /* GC[1] */ Ins_GC, + /* SCFS */ Ins_SCFS, + /* MD[0] */ Ins_MD, + /* MD[1] */ Ins_MD, + /* MPPEM */ Ins_MPPEM, + /* MPS */ Ins_MPS, + /* FlipON */ Ins_FLIPON, + /* FlipOFF */ Ins_FLIPOFF, + /* DEBUG */ Ins_DEBUG, + + /* LT */ Ins_LT, + /* LTEQ */ Ins_LTEQ, + /* GT */ Ins_GT, + /* GTEQ */ Ins_GTEQ, + /* EQ */ Ins_EQ, + /* NEQ */ Ins_NEQ, + /* ODD */ Ins_ODD, + /* EVEN */ Ins_EVEN, + /* IF */ Ins_IF, + /* EIF */ Ins_EIF, + /* AND */ Ins_AND, + /* OR */ Ins_OR, + /* NOT */ Ins_NOT, + /* DeltaP1 */ Ins_DELTAP, + /* SDB */ Ins_SDB, + /* SDS */ Ins_SDS, + + /* ADD */ Ins_ADD, + /* SUB */ Ins_SUB, + /* DIV */ Ins_DIV, + /* MUL */ Ins_MUL, + /* ABS */ Ins_ABS, + /* NEG */ Ins_NEG, + /* FLOOR */ Ins_FLOOR, + /* CEILING */ Ins_CEILING, + /* ROUND[0] */ Ins_ROUND, + /* ROUND[1] */ Ins_ROUND, + /* ROUND[2] */ Ins_ROUND, + /* ROUND[3] */ Ins_ROUND, + /* NROUND[0] */ Ins_NROUND, + /* NROUND[1] */ Ins_NROUND, + /* NROUND[2] */ Ins_NROUND, + /* NROUND[3] */ Ins_NROUND, + + /* WCvtF */ Ins_WCVTF, + /* DeltaP2 */ Ins_DELTAP, + /* DeltaP3 */ Ins_DELTAP, + /* DeltaCn[0] */ Ins_DELTAC, + /* DeltaCn[1] */ Ins_DELTAC, + /* DeltaCn[2] */ Ins_DELTAC, + /* SROUND */ Ins_SROUND, + /* S45Round */ Ins_S45ROUND, + /* JROT */ Ins_JROT, + /* JROF */ Ins_JROF, + /* ROFF */ Ins_ROFF, + /* INS_0x7B */ Ins_UNKNOWN, + /* RUTG */ Ins_RUTG, + /* RDTG */ Ins_RDTG, + /* SANGW */ Ins_SANGW, + /* AA */ Ins_AA, + + /* FlipPT */ Ins_FLIPPT, + /* FlipRgON */ Ins_FLIPRGON, + /* FlipRgOFF */ Ins_FLIPRGOFF, + /* INS_0x83 */ Ins_UNKNOWN, + /* INS_0x84 */ Ins_UNKNOWN, + /* ScanCTRL */ Ins_SCANCTRL, + /* SDPVTL[0] */ Ins_SDPVTL, + /* SDPVTL[1] */ Ins_SDPVTL, + /* GetINFO */ Ins_GETINFO, + /* IDEF */ Ins_IDEF, + /* ROLL */ Ins_ROLL, + /* MAX */ Ins_MAX, + /* MIN */ Ins_MIN, + /* ScanTYPE */ Ins_SCANTYPE, + /* InstCTRL */ Ins_INSTCTRL, + /* INS_0x8F */ Ins_UNKNOWN, + + /* INS_0x90 */ Ins_UNKNOWN, + /* INS_0x91 */ Ins_UNKNOWN, + /* INS_0x92 */ Ins_UNKNOWN, + /* INS_0x93 */ Ins_UNKNOWN, + /* INS_0x94 */ Ins_UNKNOWN, + /* INS_0x95 */ Ins_UNKNOWN, + /* INS_0x96 */ Ins_UNKNOWN, + /* INS_0x97 */ Ins_UNKNOWN, + /* INS_0x98 */ Ins_UNKNOWN, + /* INS_0x99 */ Ins_UNKNOWN, + /* INS_0x9A */ Ins_UNKNOWN, + /* INS_0x9B */ Ins_UNKNOWN, + /* INS_0x9C */ Ins_UNKNOWN, + /* INS_0x9D */ Ins_UNKNOWN, + /* INS_0x9E */ Ins_UNKNOWN, + /* INS_0x9F */ Ins_UNKNOWN, + + /* INS_0xA0 */ Ins_UNKNOWN, + /* INS_0xA1 */ Ins_UNKNOWN, + /* INS_0xA2 */ Ins_UNKNOWN, + /* INS_0xA3 */ Ins_UNKNOWN, + /* INS_0xA4 */ Ins_UNKNOWN, + /* INS_0xA5 */ Ins_UNKNOWN, + /* INS_0xA6 */ Ins_UNKNOWN, + /* INS_0xA7 */ Ins_UNKNOWN, + /* INS_0xA8 */ Ins_UNKNOWN, + /* INS_0xA9 */ Ins_UNKNOWN, + /* INS_0xAA */ Ins_UNKNOWN, + /* INS_0xAB */ Ins_UNKNOWN, + /* INS_0xAC */ Ins_UNKNOWN, + /* INS_0xAD */ Ins_UNKNOWN, + /* INS_0xAE */ Ins_UNKNOWN, + /* INS_0xAF */ Ins_UNKNOWN, + + /* PushB[0] */ Ins_PUSHB, + /* PushB[1] */ Ins_PUSHB, + /* PushB[2] */ Ins_PUSHB, + /* PushB[3] */ Ins_PUSHB, + /* PushB[4] */ Ins_PUSHB, + /* PushB[5] */ Ins_PUSHB, + /* PushB[6] */ Ins_PUSHB, + /* PushB[7] */ Ins_PUSHB, + /* PushW[0] */ Ins_PUSHW, + /* PushW[1] */ Ins_PUSHW, + /* PushW[2] */ Ins_PUSHW, + /* PushW[3] */ Ins_PUSHW, + /* PushW[4] */ Ins_PUSHW, + /* PushW[5] */ Ins_PUSHW, + /* PushW[6] */ Ins_PUSHW, + /* PushW[7] */ Ins_PUSHW, + + /* MDRP[00] */ Ins_MDRP, + /* MDRP[01] */ Ins_MDRP, + /* MDRP[02] */ Ins_MDRP, + /* MDRP[03] */ Ins_MDRP, + /* MDRP[04] */ Ins_MDRP, + /* MDRP[05] */ Ins_MDRP, + /* MDRP[06] */ Ins_MDRP, + /* MDRP[07] */ Ins_MDRP, + /* MDRP[08] */ Ins_MDRP, + /* MDRP[09] */ Ins_MDRP, + /* MDRP[10] */ Ins_MDRP, + /* MDRP[11] */ Ins_MDRP, + /* MDRP[12] */ Ins_MDRP, + /* MDRP[13] */ Ins_MDRP, + /* MDRP[14] */ Ins_MDRP, + /* MDRP[15] */ Ins_MDRP, + + /* MDRP[16] */ Ins_MDRP, + /* MDRP[17] */ Ins_MDRP, + /* MDRP[18] */ Ins_MDRP, + /* MDRP[19] */ Ins_MDRP, + /* MDRP[20] */ Ins_MDRP, + /* MDRP[21] */ Ins_MDRP, + /* MDRP[22] */ Ins_MDRP, + /* MDRP[23] */ Ins_MDRP, + /* MDRP[24] */ Ins_MDRP, + /* MDRP[25] */ Ins_MDRP, + /* MDRP[26] */ Ins_MDRP, + /* MDRP[27] */ Ins_MDRP, + /* MDRP[28] */ Ins_MDRP, + /* MDRP[29] */ Ins_MDRP, + /* MDRP[30] */ Ins_MDRP, + /* MDRP[31] */ Ins_MDRP, + + /* MIRP[00] */ Ins_MIRP, + /* MIRP[01] */ Ins_MIRP, + /* MIRP[02] */ Ins_MIRP, + /* MIRP[03] */ Ins_MIRP, + /* MIRP[04] */ Ins_MIRP, + /* MIRP[05] */ Ins_MIRP, + /* MIRP[06] */ Ins_MIRP, + /* MIRP[07] */ Ins_MIRP, + /* MIRP[08] */ Ins_MIRP, + /* MIRP[09] */ Ins_MIRP, + /* MIRP[10] */ Ins_MIRP, + /* MIRP[11] */ Ins_MIRP, + /* MIRP[12] */ Ins_MIRP, + /* MIRP[13] */ Ins_MIRP, + /* MIRP[14] */ Ins_MIRP, + /* MIRP[15] */ Ins_MIRP, + + /* MIRP[16] */ Ins_MIRP, + /* MIRP[17] */ Ins_MIRP, + /* MIRP[18] */ Ins_MIRP, + /* MIRP[19] */ Ins_MIRP, + /* MIRP[20] */ Ins_MIRP, + /* MIRP[21] */ Ins_MIRP, + /* MIRP[22] */ Ins_MIRP, + /* MIRP[23] */ Ins_MIRP, + /* MIRP[24] */ Ins_MIRP, + /* MIRP[25] */ Ins_MIRP, + /* MIRP[26] */ Ins_MIRP, + /* MIRP[27] */ Ins_MIRP, + /* MIRP[28] */ Ins_MIRP, + /* MIRP[29] */ Ins_MIRP, + /* MIRP[30] */ Ins_MIRP, + /* MIRP[31] */ Ins_MIRP +]; + +function TT_RunIns(exc) +{ + var ins_counter = 0; /* executed instructions counter */ + + var _tt_hints = exc.face.driver.library.tt_hint_props; + if (_tt_hints.TT_CONFIG_OPTION_SUBPIXEL_HINTING) //#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + { + if (exc.ignore_x_mode) + exc.iup_called = false; + }//#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + + /* set CVT functions */ + exc.tt_metrics.ratio = 0; + if (exc.metrics.x_ppem != exc.metrics.y_ppem) + { + /* non-square pixels, use the stretched routines */ + exc.func_read_cvt = Read_CVT_Stretched; + exc.func_write_cvt = Write_CVT_Stretched; + exc.func_move_cvt = Move_CVT_Stretched; + } + else + { + /* square pixels, use normal routines */ + exc.func_read_cvt = Read_CVT; + exc.func_write_cvt = Write_CVT; + exc.func_move_cvt = Move_CVT; + } + + Compute_Funcs(exc); + Compute_Round(exc, exc.GS.round_state); + + do + { + exc.opcode = exc.code.data[exc.code.pos + exc.IP]; + + exc.length = opcode_length[exc.opcode]; + if (exc.length < 0) + { + if (exc.IP + 1 >= exc.codeSize) + return SetErrorAndReturn(exc, FT_Common.FT_Err_Code_Overflow); + + exc.length = 2 - exc.length * exc.code.data[exc.code.pos + exc.IP + 1]; + } + + if (exc.IP + exc.length > exc.codeSize) + return SetErrorAndReturn(exc, FT_Common.FT_Err_Code_Overflow); + + /* First, let's check for empty stack and overflow */ + exc.args = exc.top - (Pop_Push_Count[exc.opcode] >> 4); + + /* `args' is the top of the stack once arguments have been popped. */ + /* One can also interpret it as the index of the last argument. */ + if (exc.args < 0) + { + if (exc.pedantic_hinting) + { + exc.error = FT_Common.FT_Err_Too_Few_Arguments; + return SetErrorAndReturn(exc); + } + + /* push zeroes onto the stack */ + var __l = Pop_Push_Count[exc.opcode] >> 4; + for (var i = 0; i < __l; i++) + exc.stack[i] = 0; + exc.args = 0; + } + + exc.new_top = exc.args + (Pop_Push_Count[exc.opcode] & 15); + + /* `new_top' is the new top of the stack, after the instruction's */ + /* execution. `top' will be set to `new_top' after the `switch' */ + /* statement. */ + if (exc.new_top > exc.stackSize) + { + exc.error = FT_Common.FT_Err_Stack_Overflow; + return SetErrorAndReturn(exc); + } + + exc.step_ins = true; + exc.error = 0; + + Instruct_Dispatch[exc.opcode](exc, exc.stack, exc.args); + + var bSuiteLabel = false; + if (exc.error != 0) + { + switch (exc.error) + { + case FT_Common.FT_Err_Invalid_Opcode: /* looking for redefined instructions */ + { + var defs = exc.IDefs; + var limit = exc.numIDefs; + + for (var def = 0; def < limit; def++) + { + var _def = defs[def]; + if (def.active && exc.opcode == def.opc) + { + if (exc.callTop >= exc.callSize) + { + exc.error = FT_Common.FT_Err_Invalid_Reference; + return SetErrorAndReturn(exc); + } + + var callrec = exc.callStack[exc.callTop]; + + callrec.Caller_Range = exc.curRange; + callrec.Caller_IP = exc.IP + 1; + callrec.Cur_Count = 1; + callrec.Cur_Restart = _def.start; + callrec.Cur_End = _def.end; + + if (Ins_Goto_CodeRange(def.range, def.start) == 1) + return SetErrorAndReturn(exc); + + bSuiteLabel = true; + break; + } + } + } + + if (!bSuiteLabel) + { + exc.error = FT_Common.FT_Err_Invalid_Opcode; + return SetErrorAndReturn(exc); + } + + default: + if (!bSuiteLabel) + return SetErrorAndReturn(exc); + } + } + + if (!bSuiteLabel) + { + exc.top = exc.new_top; + + if (exc.step_ins) + exc.IP += exc.length; + + /* increment instruction counter and check if we didn't */ + /* run this program for too long (e.g. infinite loops). */ + if (++ins_counter > FT_Common.MAX_RUNNABLE_OPCODES) + return FT_Common.FT_Err_Execution_Too_Long; + } + + if (exc.IP >= exc.codeSize) + { + if (exc.callTop > 0) + { + exc.error = FT_Common.FT_Err_Code_Overflow; + return SetErrorAndReturn(exc); + } + else + return 0; + } + + } while (!exc.instruction_trap); + + return 0; +} + +function SetErrorAndReturn(exc, err) +{ + if (undefined !== err) + exc.error = err; + + if (exc.error != 0 && !exc.instruction_trap) + { + exc.size.cvt_ready = false; + } + + return exc.error; +} + +function Read_CVT(exc, idx) +{ + return exc.cvt[idx]; +} + +function Read_CVT_Stretched(exc, idx) +{ + return FT_MulFix(exc.cvt[idx], Current_Ratio(exc)); +} + +function Write_CVT(exc, idx, value) +{ + exc.cvt[idx] = value; +} + +function Write_CVT_Stretched(exc, idx, value) +{ + exc.cvt[idx] = FT_DivFix(value, Current_Ratio(exc)); +} + +function Move_CVT(exc, idx, value) +{ + exc.cvt[idx] += value; +} + +function Move_CVT_Stretched(exc, idx, value) +{ + exc.cvt[idx] += FT_DivFix(value, Current_Ratio(exc)); +} + +/*********************************************************************/ +/*********************************************************************/ +/*********************************************************************/ +/*********************************************************************/ +/*********************************************************************/ +/*********************************************************************/ +function CSubpixHintingHacks() +{ + this.FAMILY_CLASS_Rules = {}; + + var _object_MS_Legacy_Fonts = {}; + _object_MS_Legacy_Fonts["Aharoni"] = true; + _object_MS_Legacy_Fonts["Andale Mono"] = true; + _object_MS_Legacy_Fonts["Andalus"] = true; + _object_MS_Legacy_Fonts["Angsana New"] = true; + _object_MS_Legacy_Fonts["AngsanaUPC"] = true; + _object_MS_Legacy_Fonts["Arabic Transparent"] = true; + _object_MS_Legacy_Fonts["Arial Black"] = true; + _object_MS_Legacy_Fonts["Arial Narrow"] = true; + _object_MS_Legacy_Fonts["Arial Unicode MS"] = true; + _object_MS_Legacy_Fonts["Arial"] = true; + _object_MS_Legacy_Fonts["Batang"] = true; + _object_MS_Legacy_Fonts["Browallia New"] = true; + _object_MS_Legacy_Fonts["BrowalliaUPC"] = true; + _object_MS_Legacy_Fonts["Comic Sans MS"] = true; + _object_MS_Legacy_Fonts["Cordia New"] = true; + _object_MS_Legacy_Fonts["CordiaUPC"] = true; + _object_MS_Legacy_Fonts["Courier New"] = true; + _object_MS_Legacy_Fonts["DFKai-SB"] = true; + _object_MS_Legacy_Fonts["David Transparent"] = true; + _object_MS_Legacy_Fonts["David"] = true; + _object_MS_Legacy_Fonts["DilleniaUPC"] = true; + _object_MS_Legacy_Fonts["Estrangelo Edessa"] = true; + _object_MS_Legacy_Fonts["EucrosiaUPC"] = true; + _object_MS_Legacy_Fonts["FangSong_GB2312"] = true; + _object_MS_Legacy_Fonts["Fixed Miriam Transparent"] = true; + _object_MS_Legacy_Fonts["FrankRuehl"] = true; + _object_MS_Legacy_Fonts["Franklin Gothic Medium"] = true; + _object_MS_Legacy_Fonts["FreesiaUPC"] = true; + _object_MS_Legacy_Fonts["Garamond"] = true; + _object_MS_Legacy_Fonts["Gautami"] = true; + _object_MS_Legacy_Fonts["Georgia"] = true; + _object_MS_Legacy_Fonts["Gulim"] = true; + _object_MS_Legacy_Fonts["Impact"] = true; + _object_MS_Legacy_Fonts["IrisUPC"] = true; + _object_MS_Legacy_Fonts["JasmineUPC"] = true; + _object_MS_Legacy_Fonts["KaiTi_GB2312"] = true; + _object_MS_Legacy_Fonts["KodchiangUPC"] = true; + _object_MS_Legacy_Fonts["Latha"] = true; + _object_MS_Legacy_Fonts["Levenim MT"] = true; + _object_MS_Legacy_Fonts["LilyUPC"] = true; + _object_MS_Legacy_Fonts["Lucida Console"] = true; + _object_MS_Legacy_Fonts["Lucida Sans Unicode"] = true; + _object_MS_Legacy_Fonts["MS Gothic"] = true; + _object_MS_Legacy_Fonts["MS Mincho"] = true; + _object_MS_Legacy_Fonts["MV Boli"] = true; + _object_MS_Legacy_Fonts["Mangal"] = true; + _object_MS_Legacy_Fonts["Marlett"] = true; + _object_MS_Legacy_Fonts["Microsoft Sans Serif"] = true; + _object_MS_Legacy_Fonts["Mingliu"] = true; + _object_MS_Legacy_Fonts["Miriam Fixed"] = true; + _object_MS_Legacy_Fonts["Miriam Transparent"] = true; + _object_MS_Legacy_Fonts["Miriam"] = true; + _object_MS_Legacy_Fonts["Narkisim"] = true; + _object_MS_Legacy_Fonts["Palatino Linotype"] = true; + _object_MS_Legacy_Fonts["Raavi"] = true; + _object_MS_Legacy_Fonts["Rod Transparent"] = true; + _object_MS_Legacy_Fonts["Rod"] = true; + _object_MS_Legacy_Fonts["Shruti"] = true; + _object_MS_Legacy_Fonts["SimHei"] = true; + _object_MS_Legacy_Fonts["Simplified Arabic Fixed"] = true; + _object_MS_Legacy_Fonts["Simplified Arabic"] = true; + _object_MS_Legacy_Fonts["Simsun"] = true; + _object_MS_Legacy_Fonts["Sylfaen"] = true; + _object_MS_Legacy_Fonts["Symbol"] = true; + _object_MS_Legacy_Fonts["Tahoma"] = true; + _object_MS_Legacy_Fonts["Times New Roman"] = true; + _object_MS_Legacy_Fonts["Traditional Arabic"] = true; + _object_MS_Legacy_Fonts["Trebuchet MS"] = true; + _object_MS_Legacy_Fonts["Tunga"] = true; + _object_MS_Legacy_Fonts["Verdana"] = true; + _object_MS_Legacy_Fonts["Webdings"] = true; + _object_MS_Legacy_Fonts["Wingdings"] = true; + + var _object_Core_MS_Legacy_Fonts = {}; + _object_Core_MS_Legacy_Fonts["Arial Black"] = true; + _object_Core_MS_Legacy_Fonts["Arial Narrow"] = true; + _object_Core_MS_Legacy_Fonts["Arial Unicode MS"] = true; + _object_Core_MS_Legacy_Fonts["Arial"] = true; + _object_Core_MS_Legacy_Fonts["Comic Sans MS"] = true; + _object_Core_MS_Legacy_Fonts["Courier New"] = true; + _object_Core_MS_Legacy_Fonts["Garamond"] = true; + _object_Core_MS_Legacy_Fonts["Georgia"] = true; + _object_Core_MS_Legacy_Fonts["Impact"] = true; + _object_Core_MS_Legacy_Fonts["Lucida Console"] = true; + _object_Core_MS_Legacy_Fonts["Lucida Sans Unicode"] = true; + _object_Core_MS_Legacy_Fonts["Microsoft Sans Serif"] = true; + _object_Core_MS_Legacy_Fonts["Palatino Linotype"] = true; + _object_Core_MS_Legacy_Fonts["Tahoma"] = true; + _object_Core_MS_Legacy_Fonts["Times New Roman"] = true; + _object_Core_MS_Legacy_Fonts["Trebuchet MS"] = true; + _object_Core_MS_Legacy_Fonts["Verdana"] = true; + + var _object_Apple_Legacy_Fonts = {}; + _object_Apple_Legacy_Fonts["Geneva"] = true; + _object_Apple_Legacy_Fonts["Times"] = true; + _object_Apple_Legacy_Fonts["Monaco"] = true; + _object_Apple_Legacy_Fonts["Century"] = true; + _object_Apple_Legacy_Fonts["Chalkboard"] = true; + _object_Apple_Legacy_Fonts["Lobster"] = true; + _object_Apple_Legacy_Fonts["Century Gothic"] = true; + _object_Apple_Legacy_Fonts["Optima"] = true; + _object_Apple_Legacy_Fonts["Lucida Grande"] = true; + _object_Apple_Legacy_Fonts["Gill Sans"] = true; + _object_Apple_Legacy_Fonts["Baskerville"] = true; + _object_Apple_Legacy_Fonts["Helvetica"] = true; + _object_Apple_Legacy_Fonts["Helvetica Neue"] = true; + + var _object_Legacy_Sans_Fonts = {}; + _object_Legacy_Sans_Fonts["Andale Mono"] = true; + _object_Legacy_Sans_Fonts["Arial Unicode MS"] = true; + _object_Legacy_Sans_Fonts["Arial"] = true; + _object_Legacy_Sans_Fonts["Century Gothic"] = true; + _object_Legacy_Sans_Fonts["Comic Sans MS"] = true; + _object_Legacy_Sans_Fonts["Franklin Gothic Medium"] = true; + _object_Legacy_Sans_Fonts["Geneva"] = true; + _object_Legacy_Sans_Fonts["Lucida Console"] = true; + _object_Legacy_Sans_Fonts["Lucida Grande"] = true; + _object_Legacy_Sans_Fonts["Lucida Sans Unicode"] = true; + _object_Legacy_Sans_Fonts["Lucida Sans Typewriter"] = true; + _object_Legacy_Sans_Fonts["Microsoft Sans Serif"] = true; + _object_Legacy_Sans_Fonts["Monaco"] = true; + _object_Legacy_Sans_Fonts["Tahoma"] = true; + _object_Legacy_Sans_Fonts["Trebuchet MS"] = true; + _object_Legacy_Sans_Fonts["Verdana"] = true; + + var _object_Misc_Legacy_Fonts = {}; + _object_Misc_Legacy_Fonts["Dark Courier"] = true; + + var _object_Verdana_Clones = {}; + _object_Verdana_Clones["DejaVu Sans"] = true; + _object_Verdana_Clones["Bitstream Vera Sans"] = true; + + var _object_Verdana_and_Clones = {}; + _object_Verdana_and_Clones["DejaVu Sans"] = true; + _object_Verdana_and_Clones["Bitstream Vera Sans"] = true; + _object_Verdana_and_Clones["Verdana"] = true; + + this.FAMILY_CLASS_Rules["MS Legacy Fonts"] = _object_MS_Legacy_Fonts; + this.FAMILY_CLASS_Rules["Core MS Legacy Fonts"] = _object_Core_MS_Legacy_Fonts; + this.FAMILY_CLASS_Rules["Apple Legacy Fonts"] = _object_Apple_Legacy_Fonts; + this.FAMILY_CLASS_Rules["Legacy Sans Fonts"] = _object_Legacy_Sans_Fonts; + this.FAMILY_CLASS_Rules["Misc Legacy Fonts"] = _object_Misc_Legacy_Fonts; + this.FAMILY_CLASS_Rules["Verdana Clones"] = _object_Verdana_Clones; + this.FAMILY_CLASS_Rules["Verdana and Clones"] = _object_Verdana_and_Clones; + + _object_MS_Legacy_Fonts = null; + _object_Core_MS_Legacy_Fonts = null; + _object_Apple_Legacy_Fonts = null; + _object_Legacy_Sans_Fonts = null; + _object_Misc_Legacy_Fonts = null; + _object_Verdana_Clones = null; + _object_Verdana_and_Clones = null; + + this.STYLE_CLASS_Rules = {}; + + var _object_Regular_Class = {}; + _object_Regular_Class["Regular"] = true; + _object_Regular_Class["Book"] = true; + _object_Regular_Class["Medium"] = true; + _object_Regular_Class["Roman"] = true; + _object_Regular_Class["Normal"] = true; + + var _object_RegularItalic_Class = {}; + _object_RegularItalic_Class["Regular"] = true; + _object_RegularItalic_Class["Book"] = true; + _object_RegularItalic_Class["Medium"] = true; + _object_RegularItalic_Class["Italic"] = true; + _object_RegularItalic_Class["Oblique"] = true; + _object_RegularItalic_Class["Roman"] = true; + _object_RegularItalic_Class["Normal"] = true; + + var _object_BoldBoldItalic_Class = {}; + _object_BoldBoldItalic_Class["Bold"] = true; + _object_BoldBoldItalic_Class["Bold Italic"] = true; + _object_BoldBoldItalic_Class["Black"] = true; + + var _object_BoldItalicBoldItalic_Class = {}; + _object_BoldItalicBoldItalic_Class["Bold"] = true; + _object_BoldItalicBoldItalic_Class["Bold Italic"] = true; + _object_BoldItalicBoldItalic_Class["Black"] = true; + _object_BoldItalicBoldItalic_Class["Italic"] = true; + _object_BoldItalicBoldItalic_Class["Oblique"] = true; + + var _object_RegularBold_Class = {}; + _object_RegularBold_Class["Regular"] = true; + _object_RegularBold_Class["Book"] = true; + _object_RegularBold_Class["Medium"] = true; + _object_RegularBold_Class["Normal"] = true; + _object_RegularBold_Class["Roman"] = true; + _object_RegularBold_Class["Bold"] = true; + _object_RegularBold_Class["Black"] = true; + + this.STYLE_CLASS_Rules["Regular Class"] = _object_Regular_Class; + this.STYLE_CLASS_Rules["Regular/Italic Class"] = _object_RegularItalic_Class; + this.STYLE_CLASS_Rules["Bold/BoldItalic Class"] = _object_BoldBoldItalic_Class; + this.STYLE_CLASS_Rules["Bold/Italic/BoldItalic Class"] = _object_BoldItalicBoldItalic_Class; + this.STYLE_CLASS_Rules["Regular/Bold Class"] = _object_RegularBold_Class; + + this.is_member_of_family_class = function(detected_font_name, rule_font_name) + { + /* Does font name match rule family? */ + if (detected_font_name == rule_font_name) + return true; + + /* Is font name a wildcard ""? */ + if (rule_font_name == "") + return true; + + var _fcr = this.FAMILY_CLASS_Rules[rule_font_name]; + if (undefined !== _fcr) + { + if (undefined !== _fcr[detected_font_name]) + return true; + } + + return false; + } + + this.is_member_of_style_class = function(detected_font_style, rule_font_style) + { + /* Does font style match rule style? */ + if (detected_font_style == rule_font_style) + return true; + + /* Is font style a wildcard ""? */ + if (rule_font_style == "") + return true; + + /* Is font style contained in a class list? */ + var _scr = this.STYLE_CLASS_Rules[rule_font_style]; + if (undefined !== _scr) + { + if (undefined !== _scr[detected_font_style]) + return true; + } + + return false; + } + + this.sph_test_tweak = function(face, family, ppem, style, glyph_index, rule, num_rules) + { + /* rule checks may be able to be optimized further */ + for (var i = 0; i < num_rules; i++) + { + if (family != "" && this.is_member_of_family_class(family, rule[i].family)) + { + if (rule[i].ppem == 0 || rule[i].ppem == ppem) + { + if (style != "" && this.is_member_of_style_class(style, rule[i].style)) + { + if (rule[i].glyph == 0 || FT_Get_Char_Index(face, rule[i].glyph) == glyph_index) + return true; + } + } + } + } + return false; + } + + this.scale_test_tweak = function(face, family, ppem, style, glyph_index, rule, num_rules) + { + /* rule checks may be able to be optimized further */ + for (var i = 0; i < num_rules; i++) + { + if (family != "" && this.is_member_of_family_class(family, rule[i].family)) + { + if (rule[i].ppem == 0 || rule[i].ppem == ppem) + { + if (style != "" && this.is_member_of_style_class(style, rule[i].style)) + { + if (rule[i].glyph == 0 || FT_Get_Char_Index(face, rule[i].glyph) == glyph_index) + return rule[i].scale; + } + } + } + } + return 1000; + } + + this.sph_set_tweaks = function(loader, glyph_index) + { + var face = loader.face; + var family = face.family_name; + var ppem = loader.size.metrics.x_ppem; + var style = face.style_name; + + /* don't apply rules if style isn't set */ + if (face.style_name == "") + return; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.PIXEL_HINTING_Rules, this.PIXEL_HINTING_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_PIXEL_HINTING; + + if (loader.exec.sph_tweak_flags & FT_Common.SPH_TWEAK_PIXEL_HINTING) + { + loader.exec.ignore_x_mode = false; + return; + } + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.ALLOW_X_DMOVE_Rules, this.ALLOW_X_DMOVE_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_ALLOW_X_DMOVE; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.ALLOW_X_DMOVEX_Rules, this.ALLOW_X_DMOVEX_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_ALLOW_X_DMOVEX; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.ALLOW_X_MOVE_ZP2_Rules, this.ALLOW_X_MOVE_ZP2_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_ALLOW_X_MOVE_ZP2; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.ALWAYS_DO_DELTAP_Rules, this.ALWAYS_DO_DELTAP_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_ALWAYS_DO_DELTAP; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.ALWAYS_SKIP_DELTAP_Rules, this.ALWAYS_SKIP_DELTAP_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_ALWAYS_SKIP_DELTAP; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.DEEMBOLDEN_Rules, this.DEEMBOLDEN_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_DEEMBOLDEN; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.DELTAP_SKIP_EXAGGERATED_VALUES_Rules, this.DELTAP_SKIP_EXAGGERATED_VALUES_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.DO_SHPIX_Rules, this.DO_SHPIX_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_DO_SHPIX; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.EMBOLDEN_Rules, this.EMBOLDEN_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_EMBOLDEN; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.MIAP_HACK_Rules, this.MIAP_HACK_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_MIAP_HACK; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.NORMAL_ROUND_Rules, this.NORMAL_ROUND_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_NORMAL_ROUND; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.NO_ALIGNRP_AFTER_IUP_Rules, this.NO_ALIGNRP_AFTER_IUP_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_NO_ALIGNRP_AFTER_IUP; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.NO_CALL_AFTER_IUP_Rules, this.NO_CALL_AFTER_IUP_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_NO_CALL_AFTER_IUP; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.NO_DELTAP_AFTER_IUP_Rules, this.NO_DELTAP_AFTER_IUP_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_NO_DELTAP_AFTER_IUP; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.RASTERIZER_35_Rules, this.RASTERIZER_35_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_RASTERIZER_35; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.SKIP_INLINE_DELTAS_Rules, this.SKIP_INLINE_DELTAS_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_SKIP_INLINE_DELTAS; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.SKIP_IUP_Rules, this.SKIP_IUP_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_SKIP_IUP; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.MIRP_CVT_ZERO_Rules, this.MIRP_CVT_ZERO_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_MIRP_CVT_ZERO; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.SKIP_OFFPIXEL_Y_MOVES_Rules, this.SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions, this.SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE)) + loader.exec.sph_tweak_flags &= ~FT_Common.SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.SKIP_NONPIXEL_Y_MOVES_Rules, this.SKIP_NONPIXEL_Y_MOVES_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions, this.SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE)) + loader.exec.sph_tweak_flags &= ~FT_Common.SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.ROUND_NONPIXEL_Y_MOVES_Rules, this.ROUND_NONPIXEL_Y_MOVES_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions, this.ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE)) + loader.exec.sph_tweak_flags &= ~FT_Common.SPH_TWEAK_ALLOW_X_DMOVE; + + if (loader.exec.sph_tweak_flags & FT_Common.SPH_TWEAK_RASTERIZER_35) + loader.exec.rasterizer_version = 35; + else + loader.exec.rasterizer_version = FT_Common.SPH_OPTION_SET_RASTERIZER_VERSION; + + /* re-execute fpgm always to avoid problems */ + loader.exec.size.cvt_ready = false; + tt_size_ready_bytecode(loader.exec.size, (loader.load_flags & FT_Common.FT_LOAD_PEDANTIC) != 0); + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) + { + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.TIMES_NEW_ROMAN_HACK_Rules, this.TIMES_NEW_ROMAN_HACK_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_TIMES_NEW_ROMAN_HACK; + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.COURIER_NEW_2_HACK_Rules, this.COURIER_NEW_2_HACK_RULES_SIZE)) + loader.exec.sph_tweak_flags |= FT_Common.SPH_TWEAK_COURIER_NEW_2_HACK; + } + + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.COMPATIBILITY_MODE_Rules, this.COMPATIBILITY_MODE_RULES_SIZE)) + { + loader.exec.compatibility_mode = true; + loader.exec.ignore_x_mode = true; + } + else + loader.exec.compatibility_mode = false; + + if ((loader.load_flags & FT_Common.FT_LOAD_NO_HINTING) == 0) + { + if (this.sph_test_tweak(face, family, ppem, style, glyph_index, this.COMPATIBLE_WIDTHS_Rules, this.COMPATIBLE_WIDTHS_RULES_SIZE)) + loader.exec.compatible_widths = true; + } + } + + /***************************************************************/ + /***************************************************************/ + /***************************************************************/ + this._create_SPH_TweakRule = function(family, ppem, style, glyph) + { + var _ret = new SPH_TweakRule(); + _ret.family = family; + _ret.ppem = ppem; + _ret.style = style; + _ret.glyph = glyph; + return _ret; + } + this._create_SPH_ScaleRule = function(family, ppem, style, glyph, scale) + { + var _ret = new SPH_ScaleRule(); + _ret.family = family; + _ret.ppem = ppem; + _ret.style = style; + _ret.glyph = glyph; + _ret.scale = scale; + return _ret; + } + + this.COMPATIBILITY_MODE_RULES_SIZE = 4; + this.COMPATIBILITY_MODE_Rules = [ + this._create_SPH_TweakRule("MS Legacy Fonts", 0, "", 0), + this._create_SPH_TweakRule("Apple Legacy Fonts", 0, "", 0), + this._create_SPH_TweakRule("Misc Legacy Fonts", 0, "", 0), + this._create_SPH_TweakRule("Verdana Clones", 0, "", 0) + ]; + + this.PIXEL_HINTING_RULES_SIZE = 4; + this.PIXEL_HINTING_Rules = [ + /* these characters are almost always safe */ + this._create_SPH_TweakRule("", 0, "", "<".charCodeAt(0)), + this._create_SPH_TweakRule("", 0, "", ">".charCodeAt(0)), + /* fixes the vanishing stem */ + this._create_SPH_TweakRule("Times New Roman", 0, "Bold", "A".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 0, "Bold", "V".charCodeAt(0)) + ]; + + /* According to Greg Hitchcock and the MS whitepaper, this should work */ + /* on all legacy MS fonts, but creates artifacts with some. Only using */ + /* where absolutely necessary. */ + this.SKIP_INLINE_DELTAS_RULES_SIZE = 1; + this.SKIP_INLINE_DELTAS_Rules = [ + this._create_SPH_TweakRule("-", 0, "", 0) + ]; + + + /* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */ + this.DO_SHPIX_RULES_SIZE = 1; + this.DO_SHPIX_Rules = [ + this._create_SPH_TweakRule("-", 0, "", 0) + ]; + + + /* Skip Y moves that start with a point that is not on a Y pixel */ + /* boundary and don't move that point to a Y pixel boundary. */ + this.SKIP_NONPIXEL_Y_MOVES_RULES_SIZE = 10; + this.SKIP_NONPIXEL_Y_MOVES_Rules = [ + /* fix vwxyz thinness*/ + this._create_SPH_TweakRule("Consolas", 0, "Regular", 0), + /* fix tiny gap at top of m */ + this._create_SPH_TweakRule("Arial", 0, "Regular", "m".charCodeAt(0)), + /* Fix thin middle stems */ + this._create_SPH_TweakRule("Core MS Legacy Fonts", 0, "Regular/Bold Class", "N".charCodeAt(0)), + this._create_SPH_TweakRule("Lucida Grande", 0, "", "N".charCodeAt(0)), + this._create_SPH_TweakRule("Lucida Grande", 0, "Bold", "y".charCodeAt(0)), + /* Cyrillic small letter I */ + this._create_SPH_TweakRule("Legacy Sans Fonts", 0, "", 0x438), + this._create_SPH_TweakRule("Verdana Clones", 0, "","N".charCodeAt(0)), + this._create_SPH_TweakRule("Ubuntu", 0, "Regular Class", "N".charCodeAt(0)), + /* Fix misshapen x */ + this._create_SPH_TweakRule("Verdana", 0, "Bold", "x".charCodeAt(0)), + /* Fix misshapen s */ + this._create_SPH_TweakRule("Tahoma", 0, "", "s".charCodeAt(0)) + ]; + + this.SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE = 6; + this.SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions = [ + this._create_SPH_TweakRule("Tahoma", 0, "", "N".charCodeAt(0)), + this._create_SPH_TweakRule("Comic Sans MS", 0, "", "N".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana", 0, "Regular/Bold Class", "N".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana", 11, "Bold", "x".charCodeAt(0)), + /* Cyrillic small letter I */ + this._create_SPH_TweakRule("Arial", 0, "", 0x438), + this._create_SPH_TweakRule("Trebuchet MS", 0, "Bold", 0) + ]; + + + /* Skip Y moves that move a point off a Y pixel boundary. */ + /* This fixes Tahoma, Trebuchet oddities and some issues with `$'. */ + this.SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE = 5; + this.SKIP_OFFPIXEL_Y_MOVES_Rules = [ + this._create_SPH_TweakRule("MS Legacy Fonts", 0, "", 0), + this._create_SPH_TweakRule("Apple Legacy Fonts", 0, "", 0), + this._create_SPH_TweakRule("Misc Legacy Fonts", 0, "", 0), + this._create_SPH_TweakRule("Ubuntu", 0, "Regular Class", 0), + this._create_SPH_TweakRule("Verdana Clones", 0, "", 0) + ]; + + + this.SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE = 1; + this.SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions = [ + this._create_SPH_TweakRule("-", 0, "", 0) + ]; + + + /* Round moves that don't move a point to a Y pixel boundary. */ + this.ROUND_NONPIXEL_Y_MOVES_RULES_SIZE = 3; + this.ROUND_NONPIXEL_Y_MOVES_Rules = [ + /* Droid font instructions don't snap Y to pixels */ + this._create_SPH_TweakRule("Droid Sans", 0, "Regular/Italic Class", 0), + this._create_SPH_TweakRule("Droid Sans Mono", 0, "", 0), + this._create_SPH_TweakRule("Ubuntu", 0, "", 0) + ]; + + + this.ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE = 3; + this.ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions = [ + this._create_SPH_TweakRule("Droid Sans", 12, "Bold", 0), + this._create_SPH_TweakRule("Droid Sans", 13, "Bold", 0), + this._create_SPH_TweakRule("Droid Sans", 16, "Bold", 0) + ]; + + + /* Allow a Direct_Move_X along X freedom vector if matched. */ + this.ALLOW_X_DMOVEX_RULES_SIZE = 1; + this.ALLOW_X_DMOVEX_Rules = [ + this._create_SPH_TweakRule("-", 0, "Regular", 0) + ]; + + + /* Allow a Direct_Move along X freedom vector if matched. */ + this.ALLOW_X_DMOVE_RULES_SIZE = 1; + this.ALLOW_X_DMOVE_Rules = [ + /* Fixes vanishing diagonal in 4 */ + this._create_SPH_TweakRule("Verdana", 0, "Regular", "4".charCodeAt(0)) + ]; + + + /* Allow a ZP2 move along freedom vector if matched; */ + /* This is called from SHP, SHPIX, SHC, SHZ. */ + this.ALLOW_X_MOVE_ZP2_RULES_SIZE = 1; + this.ALLOW_X_MOVE_ZP2_Rules = [ + this._create_SPH_TweakRule("-", 0, "", 0) + ]; + + + /* Return MS rasterizer version 35 if matched. */ + this.RASTERIZER_35_RULES_SIZE = 8; + this.RASTERIZER_35_Rules = [ + /* This seems to be the only way to make these look good */ + this._create_SPH_TweakRule("Times New Roman", 0, "Regular", "i".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 0, "Regular", "j".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 0, "Regular", "m".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 0, "Regular", "r".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 0, "Regular", "a".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 0, "Regular", "n".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 0, "Regular", "p".charCodeAt(0)), + this._create_SPH_TweakRule("Times", 0, "", 0) + ]; + + + /* Don't round to the subpixel grid. Round to pixel grid. */ + this.NORMAL_ROUND_RULES_SIZE = 2; + this.NORMAL_ROUND_Rules = [ + /* Fix point "explosions" */ + this._create_SPH_TweakRule("Courier New", 0, "", 0), + this._create_SPH_TweakRule("Verdana", 10, "Regular", "4".charCodeAt(0)) + ]; + + + /* Skip IUP instructions if matched. */ + this.SKIP_IUP_RULES_SIZE = 1; + this.SKIP_IUP_Rules = [ + this._create_SPH_TweakRule("Arial", 13, "Regular", "a".charCodeAt(0)) + ]; + + + /* Skip MIAP Twilight hack if matched. */ + this.MIAP_HACK_RULES_SIZE = 1; + this.MIAP_HACK_Rules = [ + this._create_SPH_TweakRule("Geneva", 12, "", 0) + ]; + + + /* Skip DELTAP instructions if matched. */ + this.ALWAYS_SKIP_DELTAP_RULES_SIZE = 16; + this.ALWAYS_SKIP_DELTAP_Rules = [ + this._create_SPH_TweakRule("Georgia", 0, "Regular", "k".charCodeAt(0)), + /* fixes problems with W M w */ + this._create_SPH_TweakRule("Trebuchet MS", 0, "Italic", 0), + /* fix various problems with e in different versions */ + this._create_SPH_TweakRule("Trebuchet MS", 14, "Regular", "e".charCodeAt(0)), + this._create_SPH_TweakRule("Trebuchet MS", 13, "Regular", "e".charCodeAt(0)), + this._create_SPH_TweakRule("Trebuchet MS", 15, "Regular", "e".charCodeAt(0)), + this._create_SPH_TweakRule("Arial", 11, "Regular", "s".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana", 10, "Regular", 0), + this._create_SPH_TweakRule("Verdana", 9, "Regular", 0), + /* Cyrillic small letter short I */ + this._create_SPH_TweakRule("Legacy Sans Fonts", 0, "", 0x438), + this._create_SPH_TweakRule("Legacy Sans Fonts", 0, "", 0x439), + this._create_SPH_TweakRule("Arial", 10, "Regular", "6".charCodeAt(0)), + this._create_SPH_TweakRule("Arial", 0, "Bold/BoldItalic Class", "a".charCodeAt(0)), + /* Make horizontal stems consistent with the rest */ + this._create_SPH_TweakRule("Arial", 24, "Bold", "s".charCodeAt(0)), + this._create_SPH_TweakRule("Arial", 25, "Bold", "s".charCodeAt(0)), + this._create_SPH_TweakRule("Arial", 24, "Bold", "a".charCodeAt(0)), + this._create_SPH_TweakRule("Arial", 25, "Bold", "a".charCodeAt(0)) + ]; + + + /* Always do DELTAP instructions if matched. */ + this.ALWAYS_DO_DELTAP_RULES_SIZE = 2; + this.ALWAYS_DO_DELTAP_Rules = [ + this._create_SPH_TweakRule("Verdana Clones", 17, "Regular Class", "K".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana Clones", 17, "Regular Class", "k".charCodeAt(0)) + ]; + + + /* Do an extra RTG instruction in DELTAP if matched. */ + this.DELTAP_RTG_RULES_SIZE = 1; + this.DELTAP_RTG_Rules = [ + this._create_SPH_TweakRule("-", 0, "", 0) + ]; + + + /* Force CVT distance to zero in MIRP. */ + this.MIRP_CVT_ZERO_RULES_SIZE = 1; + this.MIRP_CVT_ZERO_Rules = [ + this._create_SPH_TweakRule("-", 0, "", 0) + ]; + + + /* Skip moves that meet or exceed 1 pixel. */ + this.DELTAP_SKIP_EXAGGERATED_VALUES_RULES_SIZE = 1; + this.DELTAP_SKIP_EXAGGERATED_VALUES_Rules = [ + /* Fix vanishing stems */ + this._create_SPH_TweakRule("Ubuntu", 0, "Regular", "M".charCodeAt(0)) + ]; + + + /* Don't allow ALIGNRP after IUP. */ + this.NO_ALIGNRP_AFTER_IUP_RULES_SIZE = 4; + this.NO_ALIGNRP_AFTER_IUP_Rules = [ + /* Prevent creation of dents in outline */ + this._create_SPH_TweakRule("Courier New", 0, "Bold", "C".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "D".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "Q".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "0".charCodeAt(0)) + ]; + + + /* Don't allow DELTAP after IUP. */ + this.NO_DELTAP_AFTER_IUP_RULES_SIZE = 2; + this.NO_DELTAP_AFTER_IUP_Rules = [ + this._create_SPH_TweakRule("Arial", 0, "Bold", "N".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana", 0, "Regular", "4".charCodeAt(0)) + ]; + + + /* Don't allow CALL after IUP. */ + this.NO_CALL_AFTER_IUP_RULES_SIZE = 4; + this.NO_CALL_AFTER_IUP_Rules = [ + /* Prevent creation of dents in outline */ + this._create_SPH_TweakRule("Courier New", 0, "Bold", "O".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "Q".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "k".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold Italic", "M".charCodeAt(0)) + ]; + + + /* De-embolden these glyphs slightly. */ + this.DEEMBOLDEN_RULES_SIZE = 9; + this.DEEMBOLDEN_Rules = [ + this._create_SPH_TweakRule("Courier New", 0, "Bold", "A".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "W".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "w".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "M".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "X".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "K".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "x".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "z".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Bold", "v".charCodeAt(0)) + ]; + + + /* Embolden these glyphs slightly. */ + this.EMBOLDEN_RULES_SIZE = 5; + this.EMBOLDEN_Rules = [ + this._create_SPH_TweakRule("Courier New", 12, "Italic", "z".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 11, "Italic", "z".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 10, "Italic", "z".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 0, "Regular", 0), + this._create_SPH_TweakRule("Courier New", 0, "Italic", 0) + ]; + + + /* Do an extra RDTG instruction in DELTAP if matched. */ + this.DELTAP_RDTG_RULES_SIZE = 1; + this.DELTAP_RDTG_Rules = [ + this._create_SPH_TweakRule("-", 0, "", 0) + ]; + + + /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7 */ + /* similar to Windows XP. */ + this.TIMES_NEW_ROMAN_HACK_RULES_SIZE = 12; + this.TIMES_NEW_ROMAN_HACK_Rules = [ + this._create_SPH_TweakRule("Times New Roman", 16, "Italic", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 16, "Italic", "5".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 16, "Italic", "7".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 16, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 16, "Regular", "5".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 16, "Regular", "7".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 17, "Italic", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 17, "Italic", "5".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 17, "Italic", "7".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 17, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 17, "Regular", "5".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 17, "Regular", "7".charCodeAt(0)) + ]; + + + /* This fudges distance on 2 to get rid of the vanishing stem issue. */ + /* A real solution to this is certainly welcome. */ + this.COURIER_NEW_2_HACK_RULES_SIZE = 15; + this.COURIER_NEW_2_HACK_Rules = [ + this._create_SPH_TweakRule("Courier New", 10, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 11, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 12, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 13, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 14, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 15, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 16, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 17, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 18, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 19, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 20, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 21, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 22, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 23, "Regular", "2".charCodeAt(0)), + this._create_SPH_TweakRule("Courier New", 24, "Regular", "2".charCodeAt(0)) + ]; + + + // #ifndef FORCE_NATURAL_WIDTHS ----------------------------------------------- + + /* Use compatible widths with these glyphs. Compatible widths is always */ + /* on when doing B/W TrueType instructing, but is used selectively here, */ + /* typically on glyphs with 3 or more vertical stems. */ + this.COMPATIBLE_WIDTHS_RULES_SIZE = 38; + this.COMPATIBLE_WIDTHS_Rules = [ + this._create_SPH_TweakRule("Arial Unicode MS", 12, "Regular Class", "m".charCodeAt(0)), + this._create_SPH_TweakRule("Arial Unicode MS", 14, "Regular Class", "m".charCodeAt(0)), + /* Cyrillic small letter sha */ + this._create_SPH_TweakRule("Arial", 10, "Regular Class", 0x448), + this._create_SPH_TweakRule("Arial", 11, "Regular Class", "m".charCodeAt(0)), + this._create_SPH_TweakRule("Arial", 12, "Regular Class", "m".charCodeAt(0)), + /* Cyrillic small letter sha */ + this._create_SPH_TweakRule("Arial", 12, "Regular Class", 0x448), + this._create_SPH_TweakRule("Arial", 13, "Regular Class", 0x448), + this._create_SPH_TweakRule("Arial", 14, "Regular Class", "m".charCodeAt(0)), + /* Cyrillic small letter sha */ + this._create_SPH_TweakRule("Arial", 14, "Regular Class", 0x448), + this._create_SPH_TweakRule("Arial", 15, "Regular Class", 0x448), + this._create_SPH_TweakRule("Arial", 17, "Regular Class", "m".charCodeAt(0)), + this._create_SPH_TweakRule("DejaVu Sans", 15, "Regular Class", 0), + this._create_SPH_TweakRule("Microsoft Sans Serif", 11, "Regular Class", 0), + this._create_SPH_TweakRule("Microsoft Sans Serif", 12, "Regular Class", 0), + this._create_SPH_TweakRule("Segoe UI", 11, "Regular Class", 0), + this._create_SPH_TweakRule("Monaco", 0, "Regular Class", 0), + this._create_SPH_TweakRule("Segoe UI", 12, "Regular Class", "m".charCodeAt(0)), + this._create_SPH_TweakRule("Segoe UI", 14, "Regular Class", "m".charCodeAt(0)), + this._create_SPH_TweakRule("Tahoma", 11, "Regular Class", 0), + this._create_SPH_TweakRule("Times New Roman", 16, "Regular Class", "c".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 16, "Regular Class", "m".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 16, "Regular Class", "o".charCodeAt(0)), + this._create_SPH_TweakRule("Times New Roman", 16, "Regular Class", "w".charCodeAt(0)), + this._create_SPH_TweakRule("Trebuchet MS", 11, "Regular Class", 0), + this._create_SPH_TweakRule("Trebuchet MS", 12, "Regular Class", 0), + this._create_SPH_TweakRule("Trebuchet MS", 14, "Regular Class", 0), + this._create_SPH_TweakRule("Trebuchet MS", 15, "Regular Class", 0), + this._create_SPH_TweakRule("Ubuntu", 12, "Regular Class", "m".charCodeAt(0)), + /* Cyrillic small letter sha */ + this._create_SPH_TweakRule("Verdana", 10, "Regular Class", 0x448), + this._create_SPH_TweakRule("Verdana", 11, "Regular Class", 0x448), + this._create_SPH_TweakRule("Verdana and Clones", 12, "Regular Class", "i".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana and Clones", 12, "Regular Class", "j".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana and Clones", 12, "Regular Class", "l".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana and Clones", 12, "Regular Class", "m".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana and Clones", 13, "Regular Class", "i".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana and Clones", 13, "Regular Class", "j".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana and Clones", 13, "Regular Class", "l".charCodeAt(0)), + this._create_SPH_TweakRule("Verdana and Clones", 14, "Regular Class", "m".charCodeAt(0)) + ]; + + + /* Scaling slightly in the x-direction prior to hinting results in */ + /* more visually pleasing glyphs in certain cases. */ + /* This sometimes needs to be coordinated with compatible width rules. */ + /* A value of 1000 corresponds to a scaled value of 1.0. */ + this.X_SCALING_RULES_SIZE = 50; + this.X_SCALING_Rules = [ + this._create_SPH_ScaleRule("DejaVu Sans", 12, "Regular Class", "m".charCodeAt(0), 950), + this._create_SPH_ScaleRule("Verdana and Clones", 12, "Regular Class", "a".charCodeAt(0), 1100), + this._create_SPH_ScaleRule("Verdana and Clones", 13, "Regular Class", "a".charCodeAt(0), 1050), + this._create_SPH_ScaleRule("Arial", 11, "Regular Class", "m".charCodeAt(0), 975), + this._create_SPH_ScaleRule("Arial", 12, "Regular Class", "m".charCodeAt(0), 1050), + /* Cyrillic small letter el */ + this._create_SPH_ScaleRule("Arial", 13, "Regular Class", 0x43B, 950), + this._create_SPH_ScaleRule("Arial", 13, "Regular Class", "o".charCodeAt(0), 950), + this._create_SPH_ScaleRule("Arial", 13, "Regular Class", "e".charCodeAt(0), 950), + this._create_SPH_ScaleRule("Arial", 14, "Regular Class", "m".charCodeAt(0), 950), + /* Cyrillic small letter el */ + this._create_SPH_ScaleRule("Arial", 15, "Regular Class", 0x43B, 925), + this._create_SPH_ScaleRule("Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100), + this._create_SPH_ScaleRule("Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050), + this._create_SPH_ScaleRule("Bitstream Vera Sans", 16, "Regular Class", 0, 1050), + this._create_SPH_ScaleRule("Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050), + this._create_SPH_ScaleRule("DejaVu Sans", 12, "Regular Class", "l".charCodeAt(0), 975), + this._create_SPH_ScaleRule("DejaVu Sans", 12, "Regular Class", "i".charCodeAt(0), 975), + this._create_SPH_ScaleRule("DejaVu Sans", 12, "Regular Class", "j".charCodeAt(0), 975), + this._create_SPH_ScaleRule("DejaVu Sans", 13, "Regular Class", "l".charCodeAt(0), 950), + this._create_SPH_ScaleRule("DejaVu Sans", 13, "Regular Class", "i".charCodeAt(0), 950), + this._create_SPH_ScaleRule("DejaVu Sans", 13, "Regular Class", "j".charCodeAt(0), 950), + this._create_SPH_ScaleRule("DejaVu Sans", 10, "Regular/Italic Class", 0, 1100), + this._create_SPH_ScaleRule("DejaVu Sans", 12, "Regular/Italic Class", 0, 1050), + this._create_SPH_ScaleRule("Georgia", 10, "", 0, 1050), + this._create_SPH_ScaleRule("Georgia", 11, "", 0, 1100), + this._create_SPH_ScaleRule("Georgia", 12, "", 0, 1025), + this._create_SPH_ScaleRule("Georgia", 13, "", 0, 1050), + this._create_SPH_ScaleRule("Georgia", 16, "", 0, 1050), + this._create_SPH_ScaleRule("Georgia", 17, "", 0, 1030), + this._create_SPH_ScaleRule("Liberation Sans", 12, "Regular Class", "m".charCodeAt(0), 1100), + this._create_SPH_ScaleRule("Lucida Grande", 11, "Regular Class", "m".charCodeAt(0), 1100), + this._create_SPH_ScaleRule("Microsoft Sans Serif", 11, "Regular Class", "m".charCodeAt(0), 950), + this._create_SPH_ScaleRule("Microsoft Sans Serif", 12, "Regular Class", "m".charCodeAt(0), 1050), + this._create_SPH_ScaleRule("Segoe UI", 12, "Regular Class", "H".charCodeAt(0), 1050), + this._create_SPH_ScaleRule("Segoe UI", 12, "Regular Class", "m".charCodeAt(0), 1050), + this._create_SPH_ScaleRule("Segoe UI", 14, "Regular Class", "m".charCodeAt(0), 1050), + this._create_SPH_ScaleRule("Tahoma", 11, "Regular Class", "i".charCodeAt(0), 975), + this._create_SPH_ScaleRule("Tahoma", 11, "Regular Class", "l".charCodeAt(0), 975), + this._create_SPH_ScaleRule("Tahoma", 11, "Regular Class", "j".charCodeAt(0), 900), + this._create_SPH_ScaleRule("Tahoma", 11, "Regular Class", "m".charCodeAt(0), 918), + this._create_SPH_ScaleRule("Verdana", 10, "Regular/Italic Class".charCodeAt(0), 0, 1100), + this._create_SPH_ScaleRule("Verdana", 12, "Regular Class", "m".charCodeAt(0), 975), + this._create_SPH_ScaleRule("Verdana", 12, "Regular/Italic Class", 0, 1050), + this._create_SPH_ScaleRule("Verdana", 13, "Regular/Italic Class", "i".charCodeAt(0), 950), + this._create_SPH_ScaleRule("Verdana", 13, "Regular/Italic Class", "j".charCodeAt(0), 950), + this._create_SPH_ScaleRule("Verdana", 13, "Regular/Italic Class", "l".charCodeAt(0), 950), + this._create_SPH_ScaleRule("Verdana", 16, "Regular Class", 0, 1050), + this._create_SPH_ScaleRule("Verdana", 9, "Regular/Italic Class", 0, 1050), + this._create_SPH_ScaleRule("Times New Roman", 16, "Regular Class", "m".charCodeAt(0), 918), + this._create_SPH_ScaleRule("Trebuchet MS", 11, "Regular Class", "m".charCodeAt(0), 800), + this._create_SPH_ScaleRule("Trebuchet MS", 12, "Regular Class", "m".charCodeAt(0), 800) + ]; + + // #else ----------------------------------------------------------------- + /* + this.COMPATIBLE_WIDTHS_RULES_SIZE = 1; + this.COMPATIBLE_WIDTHS_Rules = [ + this._create_SPH_TweakRule("-", 0, "", 0) + ]; + + + this.X_SCALING_RULES_SIZE = 1; + this.X_SCALING_Rules = [ + this._create_SPH_ScaleRule("-", 0, "", 0, 1000) + ]; + */ + // ----------------------------------------------------------------------- +} + +var global_SubpixHintingHacks = new CSubpixHintingHacks(); \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/freetype.js b/Common/FontsFreeType/Private/FreeType/freetype.js new file mode 100644 index 0000000000000000000000000000000000000000..80162a7e7aa21bfa7967e60d0e6bc6e7c0522622 --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/freetype.js @@ -0,0 +1,1307 @@ +var FT_Error = 0; +function FT_Library() +{ + this.Memory = null; + this.generic = new FT_Generic(); + this.version_major = 2; + this.version_minor = 4; + this.version_patch = 8; + + this.modules = []; + this.renderers = []; + this.cur_renderer = null; + this.auto_hinter = null; + + this.raster_pool_size = 16384; + this.raster_pool = null; + + this.m_bUseCIDs = true; + + this.tt_hint_props = new LibraryHintingParams(); + + // #ifdef subpixel + //FT_LcdFilter lcd_filter; + //FT_Int lcd_extra; /* number of extra pixels */ + //FT_Byte lcd_weights[7]; /* filter weights, if any */ + //FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */ + // #endif + + //#ifdef FT_CONFIG_OPTION_PIC + //FT_PIC_Container pic_container; + //#endif + + this.Init = function() + { + this.Memory = new FT_Memory(); + //this.raster_pool = this.Memory.Alloc(this.raster_pool_size); + // теперь пул Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ рендерера Ñвой + // и он хранитÑÑ Ð½ÐµÐ¿Ð¾ÑредÑтвенно в рендерере. + // еÑли не Ñоздавать поÑтоÑнно рендереры - то ÑмыÑл такой же. У Ð½Ð°Ñ Ñ‚Ð°Ðº и еÑÑ‚ÑŒ. + this.FT_Add_Default_Modules(); + } + this.FT_Add_Module = function(module) + { + var clazz = module.clazz; + if (clazz == null) + return FT_Common.FT_Err_Invalid_Argument; + + var version_control = (this.version_major << 16 | this.version_minor); + if (clazz.requires > version_control) + return FT_Common.FT_Err_Invalid_Version; + + var mod_count = this.modules.length; + for (var i = 0; i < mod_count; i++) + { + var _module = this.modules[i]; + if (_module.clazz.name == clazz.name) + { + if (clazz.version < _module.clazz.version) + return FT_Common.FT_Err_Lower_Module_Version; + this.modules.splice(i,1); + break; + } + } + + var error = FT_Common.FT_Err_Ok; + if ((clazz.flags & FT_Common.FT_MODULE_RENDERER) != 0) + { + error = this.ft_add_renderer(module); + if (FT_Common.FT_Err_Ok != error) + { + //delete module; + return error; + } + } + if ((clazz.flags & FT_Common.FT_MODULE_HINTER) != 0) + { + this.auto_hinter = module; + } + if ((clazz.flags & 1) != 0) + { + if (0 == (clazz.flags & FT_Common.FT_MODULE_DRIVER_NO_OUTLINES)) + { + module.glyph_loader = new FT_GlyphLoader(); + } + } + + if (null != clazz.init) + clazz.init(module); + + this.modules[mod_count] = module; + return error; + } + this.FT_Add_Default_Modules = function() + { + // drivers + var driver_tt = create_tt_driver(this); + var driver_cff = create_cff_driver(this); + var driver_t1 = create_t1_driver(this); + //var driver_cid = create_cid_driver(this); + this.FT_Add_Module(driver_tt); + this.FT_Add_Module(driver_cff); + this.FT_Add_Module(driver_t1); + //this.FT_Add_Module(driver_cid); + + // modules + var mod_ps_names = create_psnames_module(this); + var mod_psaux = create_psaux_module(this); + var mod_sfnt = create_sfnt_module(this); + this.FT_Add_Module(mod_ps_names); + this.FT_Add_Module(mod_psaux); + this.FT_Add_Module(mod_sfnt); + + // autohinter + this.auto_hinter = null; + + // renderers + var mod_rend1 = create_renderer_smooth_module(this); + this.FT_Add_Module(mod_rend1); + } + this.ft_add_renderer = function(module) + { + var error = FT_Common.FT_Err_Ok; + var clazz = module.clazz; + + module.glyph_format = clazz.glyph_format; + + if ((clazz.glyph_format == FT_Common.FT_GLYPH_FORMAT_OUTLINE) && (clazz.raster_class.raster_new)) + { + module.raster = new TRaster(); + error = clazz.raster_class.raster_new(this.Memory, module.raster); + + if (error != FT_Common.FT_Err_Ok) + return error; + + module.raster_render = clazz.raster_class.raster_render; + module.render = clazz.render_glyph; + } + + this.renderers[this.renderers.length] = module; + + this.ft_set_current_renderer(); + return error; + } + this.ft_set_current_renderer = function() + { + this.cur_renderer = null; + var count_r = this.renderers.length; + for (var i = 0; i < count_r; i++) + { + if (this.renderers[i].glyph_format == FT_Common.FT_GLYPH_FORMAT_OUTLINE) + { + this.cur_renderer = this.renderers[i]; + return; + } + } + } + this.FT_Open_Face = function(args, face_index) + { + var face = null; + var external_stream = (args.stream && (args.flags & 0x02) != 0) ? true : false; + if (external_stream === true) + { + var stream = args.stream; + + // пробегаем по вÑем драйверам - и ищем первый, который Ñможет открыть + var dr_len = this.modules.length; + for (var i = 0; i < dr_len; i++) + { + if (0 == (this.modules[i].clazz.flags & FT_Common.FT_MODULE_FONT_DRIVER)) + continue; + + var driver = this.modules[i]; + face = driver.open_face(stream, face_index); + + if (0 != FT_Error) + { + //#ifdef FT_CONFIG_OPTION_MAC_FONTS + if (driver.clazz.name == "truetype" && ((FT_Error & 0xFF) == FT_Common.FT_Err_Table_Missing)) + { + face = this.open_face_PS_from_sfnt_stream(stream, face_index); + if (FT_Error != 0) + return null; + } + //#endif + } + else + { + break; + } + + if ((FT_Error & 0xFF) != FT_Common.FT_Err_Unknown_File_Format) + { + if (((FT_Error & 0xFF) == FT_Common.FT_Err_Invalid_Stream_Operation) || + ((FT_Error & 0xFF) == FT_Common.FT_Err_Cannot_Open_Stream)) + { + //#ifdef FT_CONFIG_OPTION_MAC_FONTS + face = this.load_mac_face(stream, face_index); + if (FT_Error == 0) + return face; + FT_Error = FT_Common.FT_Err_Unknown_File_Format; + face = null; + return face; + //#endif + } + } + } + + if (null == face) + return face; + + face.face_flags |= (1 << 10); + face.driver.faces_list[face.driver.faces_list.length] = face; + + if (face_index >= 0) + { + var slot = FT_New_GlyphSlot(face); + slot = null; + if (FT_Error != 0) + { + face = null; + return null; + } + + /* finally, allocate a size object for the face */ + { + var size = FT_New_Size(face); + if (FT_Error != 0) + { + face = null; + return null; + } + + face.size = size; + } + } + + /* some checks */ + + if ((face.face_flags & 1) != 0) + { + if (face.height < 0) + face.height = -face.height; + + if ((face.face_flags & (1 << 5)) == 0) + face.max_advance_height = face.height; + } + + if ((face.face_flags & (1 << 1)) != 0) + { + var _num = face.num_fixed_sizes; + for (var i = 0; i < _num; i++) + { + var bsize = face.available_sizes[i]; + + if (bsize.height < 0) + bsize.height = -bsize.height; + if (bsize.x_ppem < 0) + bsize.x_ppem = -bsize.x_ppem; + if (bsize.y_ppem < 0) + bsize.y_ppem = -bsize.y_ppem; + } + } + + /* initialize internal face data */ + { + var internal = face.internal; + + internal.transform_matrix.xx = 0x10000; + internal.transform_matrix.xy = 0; + internal.transform_matrix.yx = 0; + internal.transform_matrix.yy = 0x10000; + + internal.transform_delta.x = 0; + internal.transform_delta.y = 0; + } + + FT_Error = FT_Common.FT_Err_Ok; + return face; + } + // пока открываем только из уже Ñозданного Ñтрима + FT_Error = FT_Common.FT_Err_Invalid_Argument; + return null; + } + + this.open_face_PS_from_sfnt_stream = function(stream, face_index) + { + } + this.load_mac_face = function(stream, face_index) + { + } + + this.FT_Get_Module_Interface = function(name) + { + var module = this.FT_Get_Module(name); + return (null != module) ? module.clazz.module_interface : null; + } + this.FT_Get_Module = function(name) + { + var count = this.modules.length; + for (var i = 0; i < count; i++) + { + if (this.modules[i].clazz.name == name) + return this.modules[i]; + } + return null; + } +} + +// API +function FT_Select_Size(face, strike_index) +{ + if (!face || (face.face_flags & FT_Common.FT_FACE_FLAG_FIXED_SIZES) == 0) + return FT_Common.FT_Err_Invalid_Face_Handle; + + if (strike_index < 0 || strike_index >= face.num_fixed_sizes) + return FT_Common.FT_Err_Invalid_Argument; + + var clazz = face.driver.clazz; + if (clazz.select_size) + { + return clazz.select_size(face.size, strike_index); + } + + FT_Select_Metrics(face, strike_index); + return FT_Common.FT_Err_Ok; +} + +function FT_Select_Metrics(face, strike_index) +{ + var metrics = face.size.metrics; + var bsize = face.available_sizes[strike_index]; + + metrics.x_ppem = (FT_Common.IntToUInt(bsize.x_ppem + 32) >>> 6) & 0xFFFF; + metrics.y_ppem = (FT_Common.IntToUInt(bsize.y_ppem + 32) >>> 6) & 0xFFFF; + + if ((face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) != 0) + { + metrics.x_scale = FT_DivFix(bsize.x_ppem, face.units_per_EM); + metrics.y_scale = FT_DivFix(bsize.y_ppem, face.units_per_EM); + + ft_recompute_scaled_metrics(face, metrics); + } + else + { + metrics.x_scale = 1 << 16; + metrics.y_scale = 1 << 16; + metrics.ascender = bsize.y_ppem; + metrics.descender = 0; + metrics.height = bsize.height << 6; + metrics.max_advance = bsize.x_ppem; + } +} + +function ft_recompute_scaled_metrics(face, metrics) +{ + metrics.ascender = FT_PIX_CEIL(FT_MulFix(face.ascender, metrics.y_scale)); + metrics.descender = FT_PIX_FLOOR(FT_MulFix(face.descender, metrics.y_scale)); + metrics.height = FT_PIX_ROUND(FT_MulFix(face.height, metrics.y_scale)); + metrics.max_advance = FT_PIX_ROUND(FT_MulFix(face.max_advance_width, metrics.x_scale)); +} + +function FT_Request_Size(face, req) +{ + var strike_index = 0; + + if (!face) + return FT_Common.FT_Err_Invalid_Face_Handle; + + if (!req || req.width < 0 || req.height < 0 || req.type >= FT_Common.FT_SIZE_REQUEST_TYPE_MAX) + return FT_Common.FT_Err_Invalid_Argument; + + var clazz = face.driver.clazz; + + if (clazz.request_size) + { + return clazz.request_size(face.size, req); + } + + if (((face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) == 0) && ((face.face_flags & FT_Common.FT_FACE_FLAG_FIXED_SIZES) != 0)) + { + FT_Error = FT_Common.FT_Err_Ok; + strike_index = FT_Match_Size(face, req, 0); + var error = FT_Error; + FT_Error = FT_Common.FT_Err_Ok; + if (error != FT_Common.FT_Err_Ok) + return error; + + return FT_Select_Size(face, strike_index); + } + + FT_Request_Metrics(face, req); + return FT_Common.FT_Err_Ok; +} + +function FT_Request_Metrics(face, req) +{ + var metrics = face.size.metrics; + + if ((face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) != 0) + { + var w = 0, h = 0, scaled_w = 0, scaled_h = 0; + + switch (req.type) + { + case FT_Common.FT_SIZE_REQUEST_TYPE_NOMINAL: + w = h = face.units_per_EM; + break; + + case FT_Common.FT_SIZE_REQUEST_TYPE_REAL_DIM: + w = h = face.ascender - face.descender; + break; + + case FT_Common.FT_SIZE_REQUEST_TYPE_BBOX: + w = face.bbox.xMax - face.bbox.xMin; + h = face.bbox.yMax - face.bbox.yMin; + break; + + case FT_Common.FT_SIZE_REQUEST_TYPE_CELL: + w = face.max_advance_width; + h = face.ascender - face.descender; + break; + + case FT_Common.FT_SIZE_REQUEST_TYPE_SCALES: + metrics.x_scale = req.width; + metrics.y_scale = req.height; + if (metrics.x_scale == 0) + metrics.x_scale = metrics.y_scale; + else if (metrics.y_scale == 0) + metrics.y_scale = metrics.x_scale; + + scaled_w = FT_MulFix(face.units_per_EM, metrics.x_scale); + scaled_h = FT_MulFix(face.units_per_EM, metrics.y_scale); + + metrics.x_ppem = (FT_Common.IntToUInt(scaled_w + 32) >>> 6) & 0xFFFF; + metrics.y_ppem = (FT_Common.IntToUInt(scaled_h + 32) >>> 6) & 0xFFFF; + + ft_recompute_scaled_metrics( face, metrics ); + return; + + case FT_Common.FT_SIZE_REQUEST_TYPE_MAX: + break; + } + + /* to be on the safe side */ + if (w < 0) + w = -w; + + if (h < 0) + h = -h; + + scaled_w = FT_REQUEST_WIDTH(req); + scaled_h = FT_REQUEST_HEIGHT(req); + + if (req.width != 0) + { + metrics.x_scale = FT_DivFix(scaled_w, w); + + if (req.height != 0) + { + metrics.y_scale = FT_DivFix(scaled_h, h); + + if (req.type == FT_Common.FT_SIZE_REQUEST_TYPE_CELL) + { + if (metrics.y_scale > metrics.x_scale) + metrics.y_scale = metrics.x_scale; + else + metrics.x_scale = metrics.y_scale; + } + } + else + { + metrics.y_scale = metrics.x_scale; + scaled_h = FT_MulDiv(scaled_w, h, w); + } + } + else + { + metrics.x_scale = metrics.y_scale = FT_DivFix(scaled_h, h); + scaled_w = FT_MulDiv(scaled_h, w, h); + } + + if (req.type != FT_Common.FT_SIZE_REQUEST_TYPE_NOMINAL) + { + scaled_w = FT_MulFix(face.units_per_EM, metrics.x_scale); + scaled_h = FT_MulFix(face.units_per_EM, metrics.y_scale); + } + + metrics.x_ppem = (FT_Common.IntToUInt(scaled_w + 32) >>> 6) & 0xFFFF; + metrics.y_ppem = (FT_Common.IntToUInt(scaled_h + 32) >>> 6) & 0xFFFF; + + ft_recompute_scaled_metrics(face, metrics); + } + else + { + metrics.x_ppem = 0; + metrics.y_ppem = 0; + + metrics.ascender = 0; + metrics.descender = 0; + metrics.height = 0; + metrics.max_advance = 0; + + metrics.x_scale = 1 << 16; + metrics.y_scale = 1 << 16; + } +} + +function FT_REQUEST_WIDTH(req) +{ + return (req.horiResolution != 0) ? parseInt((req.width * req.horiResolution + 36) / 72) : req.width; +} + +function FT_REQUEST_HEIGHT(req) +{ + return (req.vertResolution != 0) ? parseInt((req.height * req.vertResolution + 36) / 72) : req.height; +} + +function FT_Match_Size(face, req, ignore_width) +{ + if ((face.face_flags & FT_Common.FT_FACE_FLAG_FIXED_SIZES) == 0) + { + FT_Error = FT_Common.FT_Err_Invalid_Face_Handle; + return 0; + } + + if (req.type != FT_Common.FT_SIZE_REQUEST_TYPE_NOMINAL) + { + FT_Error = FT_Common.FT_Err_Unimplemented_Feature; + return 0; + } + + var w = FT_REQUEST_WIDTH(req); + var h = FT_REQUEST_HEIGHT(req); + + if (req.width != 0 && req.height == 0) + h = w; + else if (req.width == 0 && req.height != 0) + w = h; + + w = FT_PIX_ROUND(w); + h = FT_PIX_ROUND(h); + + var num_fs = face.num_fixed_sizes; + for (var i = 0; i < num_fs; i++) + { + var bsize = face.available_sizes[i]; + + if (h != FT_PIX_ROUND(bsize.y_ppem)) + continue; + + if (w == FT_PIX_ROUND(bsize.x_ppem) || (ignore_width != 0)) + { + FT_Error = 0; + return i; + } + } + + FT_Error = FT_Common.FT_Err_Invalid_Pixel_Size; + return 0; +} + +function FT_Set_Char_Size(face, char_width, char_height, horz_resolution, vert_resolution) +{ + var req = new FT_Size_RequestRec(); + + if (0 == char_width) + char_width = char_height; + else if (0 == char_height) + char_height = char_width; + + if (0 == horz_resolution) + horz_resolution = vert_resolution; + else if (0 == vert_resolution) + vert_resolution = horz_resolution; + + if (char_width < 64) + char_width = 64; + if (char_height < 64) + char_height = 64; + + if (0 == horz_resolution) + horz_resolution = vert_resolution = 72; + + req.type = FT_Common.FT_SIZE_REQUEST_TYPE_NOMINAL; + req.width = char_width; + req.height = char_height; + req.horiResolution = horz_resolution; + req.vertResolution = vert_resolution; + + return FT_Request_Size(face, req); +} + +function FT_Set_Pixel_Sizes(face, pixel_width, pixel_height) +{ + var req = new FT_Size_RequestRec(); + + if (pixel_width == 0) + pixel_width = pixel_height; + else if (pixel_height == 0) + pixel_height = pixel_width; + + if (pixel_width < 1) + pixel_width = 1; + if (pixel_height < 1) + pixel_height = 1; + + /* use `>=' to avoid potential compiler warning on 16bit platforms */ + if (pixel_width >= 0xFFFF) + pixel_width = 0xFFFF; + if (pixel_height >= 0xFFFF) + pixel_height = 0xFFFF; + + req.type = FT_Common.FT_SIZE_REQUEST_TYPE_NOMINAL; + req.width = pixel_width << 6; + req.height = pixel_height << 6; + req.horiResolution = 0; + req.vertResolution = 0; + + return FT_Request_Size(face, req); +} + +function FT_Get_First_Char(face) +{ + var result = {gindex:0,char_code:0}; + if (face && face.charmap && face.num_glyphs != 0) + { + result.gindex = FT_Get_Char_Index(face, 0); + if (result.gindex == 0 || result.gindex >= face.num_glyphs) + result = FT_Get_Next_Char(face, 0); + } + return result; +} + +function FT_Get_Next_Char(face, charcode) +{ + var result = {gindex:0,char_code:0}; + if (face && face.charmap && face.num_glyphs != 0) + { + var code = charcode; + var cmap = face.charmap; + var _cmap = __FT_CMapRec(cmap); + + do + { + var _clazz = _cmap.clazz.clazz; + if (undefined == _clazz) + _clazz = _cmap.clazz; + + result = _clazz.char_next(cmap, code); + code = result.char_code; + } while (result.gindex >= face.num_glyphs); + + result.char_code = (result.gindex == 0) ? 0 : code; + } + return result; +} + +function FT_Get_Char_Index(face, charcode) +{ + var result = 0; + if (face && face.charmap) + { + var _clazz = __FT_CMapRec(face.charmap).clazz; + if (undefined != _clazz.clazz) + _clazz = _clazz.clazz; + + result = _clazz.char_index(face.charmap, charcode); + } + return result; +} + +function FT_Get_Charmap_Index(charmap) +{ + if (!charmap || !charmap.face) + return -1; + + var i = 0; + for (; i < charmap.face.num_charmaps; i++) + if (charmap.face.charmaps[i] == charmap) + break; + + //#ifdef FT_MAX_CHARMAP_CACHEABLE + if (i > 15) + return -i; + //#endif + return i; +} + +function FT_Set_Charmap(face, cmap) +{ + if (!face) + return FT_Common.FT_Err_Invalid_Face_Handle; + + var len = face.num_charmaps; + if (0 == len) + return FT_Common.FT_Err_Invalid_CharMap_Handle; + + if (FT_Get_CMap_Format(cmap) == 14) + return FT_Common.FT_Err_Invalid_Argument; + + for (var i = 0; i < len; i++) + { + if (face.charmaps[i] == cmap) + { + //#ifdef FT_MAX_CHARMAP_CACHEABLE + if (i > 15) + continue; + //#endif + face.charmap = face.charmaps[i]; + return 0; + } + } + return FT_Common.FT_Err_Invalid_Argument; +} + +function FT_Get_CMap_Format(cmap) +{ + var charmap = __FT_CharmapRec(cmap); + if (!charmap || !charmap.face) + return -1; + + var service = FT_FACE_FIND_SERVICE(charmap.face, "tt-cmaps"); + + if (service == null) + return -1; + + var cmap_info = new TT_CMapInfo(); + service.get_cmap_info(cmap, cmap_info); + if (FT_Error != 0) + return -1; + + return cmap_info.format; +} + + +function FT_Glyph_Get_CBox(glyph, bbox_mode, acbox) +{ + acbox.xMin = acbox.yMin = acbox.xMax = acbox.yMax = 0; + + if (!glyph || !glyph.clazz) + return; + + var clazz = glyph.clazz; + if (!clazz.glyph_bbox) + return; + + clazz.glyph_bbox(glyph, acbox); + + if (bbox_mode == FT_Common.FT_GLYPH_BBOX_GRIDFIT || bbox_mode == FT_Common.FT_GLYPH_BBOX_PIXELS) + { + acbox.xMin = FT_PIX_FLOOR(acbox.xMin); + acbox.yMin = FT_PIX_FLOOR(acbox.yMin); + acbox.xMax = FT_PIX_CEIL(acbox.xMax); + acbox.yMax = FT_PIX_CEIL(acbox.yMax); + } + + if (bbox_mode == FT_Common.FT_GLYPH_BBOX_TRUNCATE || bbox_mode == FT_Common.FT_GLYPH_BBOX_PIXELS) + { + acbox.xMin >>= 6; + acbox.yMin >>= 6; + acbox.xMax >>= 6; + acbox.yMax >>= 6; + } +} + +function FT_Get_Glyph(slot) +{ + FT_Error = 0; + var clazz = null; + + if (!slot) + return FT_Common.FT_Err_Invalid_Slot_Handle; + + if (slot.format == FT_Common.FT_GLYPH_FORMAT_BITMAP) + clazz = ft_bitmap_glyph_class; + else if (slot.format == FT_Common.FT_GLYPH_FORMAT_OUTLINE) + clazz = ft_outline_glyph_class; + else + { + var render = FT_Lookup_Renderer(slot.library, slot.format); + if (render) + clazz = render.glyph_class; + } + + if (!clazz) + { + FT_Error = FT_Common.FT_Err_Invalid_Glyph_Format; + return null; + } + + var glyph = ft_new_glyph(slot.library, clazz); + if (FT_Error != 0) + return null; + + glyph.advance.x = slot.advance.x << 10; + glyph.advance.y = slot.advance.y << 10; + + FT_Error = clazz.glyph_init(glyph, slot); + + if (FT_Error != 0) + { + FT_Done_Glyph(glyph); + glyph = null; + } + else + return glyph; + + return null; +} + +function FT_Done_Glyph(glyph) +{ + return 0; +} + +function FT_Get_Name_Index(face, glyph_name) +{ + if (face && ((face.face_flags & FT_Common.FT_FACE_FLAG_GLYPH_NAMES) != 0)) + { + var service = face.internal.services.service_GLYPH_DICT; + if (null != service) + service = FT_FACE_FIND_SERVICE(face, "glyph-dict"); + + if (service && service.name_index) + return service.name_index(face, glyph_name); + } + return 0; +} +function FT_Get_Glyph_Name(face, glyph_index, buffer, buffer_max) +{ + if (face && (glyph_index <= face.num_glyphs) && ((face.face_flags & FT_Common.FT_FACE_FLAG_GLYPH_NAMES) != 0)) + { + var service = face.internal.services.service_GLYPH_DICT; + if (null != service) + service = FT_FACE_FIND_SERVICE(face, "glyph-dict"); + + if (service && service.get_name) + return service.get_name(face, glyph_index, buffer, buffer_max); + } + return 0; +} + +function FT_Get_X11_Font_Format(face) +{ + if (face) + return FT_FACE_FIND_SERVICE(face, "xf86-driver-name"); + return null; +} + +function FT_Lookup_Renderer(library, format) +{ + var r = library.renderers; + var c = r.length; + + for (var i = 0; i < c; i++) + { + if (r[i].glyph_format == format) + return r[i]; + } + + return null; +} + +function FT_Set_Renderer(library, renderer) +{ + if (!library) + return FT_Common.FT_Err_Invalid_Library_Handle; + + if (!renderer) + return FT_Common.FT_Err_Invalid_Argument; + + if (renderer.glyph_format == FT_Common.FT_GLYPH_FORMAT_OUTLINE) + library.cur_renderer = renderer; + + return 0; +} + +function ft_lookup_glyph_renderer(slot) +{ + var library = slot.library; + var res = library.cur_renderer; + + if (!res || (res.glyph_format != slot.format)) + res = FT_Lookup_Renderer(library, slot.format); + + return res; +} + +function ft_set_current_renderer(library) +{ + library.cur_renderer = FT_Lookup_Renderer(library, FT_Common.FT_GLYPH_FORMAT_OUTLINE); +} + + + +function FT_Load_Glyph(face, glyph_index, load_flags) +{ + if (!face || !face.size || !face.glyph) + return FT_Common.FT_Err_Invalid_Face_Handle; + + var slot = face.glyph; + ft_glyphslot_clear(slot); + + var driver = face.driver; + var library = driver.library; + var hinter = library.auto_hinter; + var autohint = false; + + /* resolve load flags dependencies */ + if (load_flags & FT_Common.FT_LOAD_NO_RECURSE) + load_flags |= (FT_Common.FT_LOAD_NO_SCALE | FT_Common.FT_LOAD_IGNORE_TRANSFORM); + + if (load_flags & FT_Common.FT_LOAD_NO_SCALE) + { + load_flags |= (FT_Common.FT_LOAD_NO_HINTING | FT_Common.FT_LOAD_NO_BITMAP); + load_flags &= ~FT_Common.FT_LOAD_RENDER; + } + + // if (hinter && ...){} + // TODO: + + if (true === autohint) + { + // TODO: + } + else + { + var error = driver.clazz.load_glyph(slot, face.size, glyph_index, load_flags); + if (error != FT_Common.FT_Err_Ok) + return error; + + if (slot.format == FT_Common.FT_GLYPH_FORMAT_OUTLINE) + { + /* check that the loaded outline is correct */ + error = FT_Outline_Check(slot.outline); + if (error != FT_Common.FT_Err_Ok) + return error; + + //#ifdef GRID_FIT_METRICS + if (0 == (load_flags & FT_Common.FT_LOAD_NO_HINTING)) + ft_glyphslot_grid_fit_metrics( slot, ((load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT) != 0) ? true : false); + //#endif + } + } + + /* compute the advance */ + if (0 != (load_flags & FT_Common.FT_LOAD_VERTICAL_LAYOUT)) + { + slot.advance.x = 0; + slot.advance.y = slot.metrics.vertAdvance; + } + else + { + slot.advance.x = slot.metrics.horiAdvance; + slot.advance.y = 0; + } + + /* compute the linear advance in 16.16 pixels */ + if ((load_flags & FT_Common.FT_LOAD_LINEAR_DESIGN) == 0 && (0 != (face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE))) + { + var metrics = face.size.metrics; + + /* it's tricky! */ + slot.linearHoriAdvance = FT_MulDiv(slot.linearHoriAdvance, metrics.x_scale, 64); + slot.linearVertAdvance = FT_MulDiv(slot.linearVertAdvance, metrics.y_scale, 64); + } + + if ((load_flags & FT_Common.FT_LOAD_IGNORE_TRANSFORM) == 0) + { + var internal = face.internal; + + /* now, transform the glyph image if needed */ + if (internal.transform_flags != 0) + { + /* get renderer */ + var renderer = ft_lookup_glyph_renderer(slot); + if (renderer != null) + error = renderer.clazz.transform_glyph(renderer, slot, internal.transform_matrix, internal.transform_delta); + else if (slot.format == FT_Common.FT_GLYPH_FORMAT_OUTLINE) + { + /* apply `standard' transformation if no renderer is available */ + if ((internal.transform_flags & 1) != 0) + FT_Outline_Transform(slot.outline, internal.transform_matrix); + + if ((internal.transform_flags & 2) != 0) + FT_Outline_Translate(slot.outline, internal.transform_delta.x, internal.transform_delta.y); + } + + /* transform advance */ + FT_Vector_Transform(slot.advance, internal.transform_matrix); + } + } + + /* do we need to render the image now? */ + if ((error == 0) && (slot.format != FT_Common.FT_GLYPH_FORMAT_BITMAP) && (slot.format != FT_Common.FT_GLYPH_FORMAT_COMPOSITE) && ((load_flags & FT_Common.FT_LOAD_RENDER) != 0)) + { + var mode = FT_LOAD_TARGET_MODE(load_flags); + + if (mode == FT_Common.FT_RENDER_MODE_NORMAL && (load_flags & FT_Common.FT_LOAD_MONOCHROME)) + mode = FT_Common.FT_RENDER_MODE_MONO; + + error = FT_Render_Glyph(slot, mode); + } + return error; +} + +function FT_Load_Char(face, char_code, load_flags) +{ + var glyph_index = 0; + + if ( !face ) + return FT_Common.FT_Err_Invalid_Face_Handle; + + glyph_index = char_code; + if (face.charmap) + glyph_index = FT_Get_Char_Index(face, char_code); + + return FT_Load_Glyph(face, glyph_index, load_flags); +} + +function FT_Set_Transform(face, matrix, delta) +{ + if (!face) + return; + + var internal = face.internal; + internal.transform_flags = 0; + + var m = internal.transform_matrix; + if (!matrix) + { + m.xx = 0x10000; + m.xy = 0; + m.yx = 0; + m.yy = 0x10000; + } + else + { + m.xx = matrix.xx; + m.xy = matrix.xy; + m.yx = matrix.yx; + m.yy = matrix.yy; + } + + /* set transform_flags bit flag 0 if `matrix' isn't the identity */ + if ((m.xy | m.yx) != 0 || m.xx != 0x10000 || m.yy != 0x10000) + internal.transform_flags |= 1; + + var d = internal.transform_delta; + if (!delta) + { + d.x = 0; + d.y = 0; + } + else + { + d.x = delta.x; + d.y = delta.y; + } + + /* set transform_flags bit flag 1 if `delta' isn't the null vector */ + if ((d.x | d.y) != 0) + internal.transform_flags |= 2; +} + +function FT_Render_Glyph(slot, render_mode) +{ + if (!slot || !slot.face) + return FT_Common.FT_Err_Invalid_Argument; + + var library = slot.library; + return FT_Render_Glyph_Internal(library, slot, render_mode); +} + +function FT_Render_Glyph_Internal(library, slot, render_mode) +{ + var error = FT_Common.FT_Err_Ok; + var renderer = null; + var update = false; + + /* if it is already a bitmap, no need to do anything */ + switch (slot.format) + { + case FT_Common.FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */ + break; + + default: + { + /* small shortcut for the very common case */ + if (slot.format == FT_Common.FT_GLYPH_FORMAT_OUTLINE) + { + renderer = library.cur_renderer; + } + else + { + renderer = FT_Lookup_Renderer(library, slot.format); + } + + error = FT_Common.FT_Err_Unimplemented_Feature; + while (renderer != null) + { + error = renderer.render(renderer, slot, render_mode, null); + if ((error == 0) || ((error & 0xFF) != FT_Common.FT_Err_Cannot_Render_Glyph)) + break; + + renderer = FT_Lookup_Renderer(library, slot.format); + update = true; + } + if (error == 0 && update && renderer) + FT_Set_Renderer(library, renderer); + } + } + + return error; +} + +function FT_Get_Kerning(face, left_glyph, right_glyph, kern_mode, akerning) +{ + var error = FT_Common.FT_Err_Ok; + + if (!face) + return FT_Common.FT_Err_Invalid_Face_Handle; + + if (!akerning) + return FT_Common.FT_Err_Invalid_Argument; + + var driver = face.driver; + + akerning.x = 0; + akerning.y = 0; + + if (driver.clazz.get_kerning) + { + error = driver.clazz.get_kerning(face, left_glyph, right_glyph, akerning); + if (error == FT_Common.FT_Err_Ok) + { + if (kern_mode != FT_Common.FT_KERNING_UNSCALED) + { + akerning.x = FT_MulFix(akerning.x, face.size.metrics.x_scale); + akerning.y = FT_MulFix(akerning.y, face.size.metrics.y_scale); + + if (kern_mode != FT_Common.FT_KERNING_UNFITTED) + { + if (face.size.metrics.x_ppem < 25) + akerning.x = FT_MulDiv(akerning.x, face.size.metrics.x_ppem, 25); + if (face.size.metrics.y_ppem < 25) + akerning.y = FT_MulDiv(akerning.y, face.size.metrics.y_ppem, 25); + + akerning.x = FT_PIX_ROUND(akerning.x); + akerning.y = FT_PIX_ROUND(akerning.y); + } + } + } + } + + return error; +} + +function FT_New_GlyphSlot(face) +{ + if (!face || !face.driver) + return FT_Common.FT_Err_Invalid_Argument; + + var slot = null; + var _slot = null; + + if (face.driver.clazz.name == "type1") + { + _slot = new T1_GlyphSlotRec(); + slot = _slot.root; + } + else + { + _slot = new FT_GlyphSlot(); + slot = _slot; + } + + slot.face = face; + FT_Error = ft_glyphslot_init(slot); + if (FT_Error != 0) + { + ft_glyphslot_done(slot); + return null; + } + + slot.next = face.glyph; + face.glyph = slot; + return slot; +} + +function FT_GlyphLoader_New(memory) +{ + var loader = new FT_GlyphLoader(); + loader.memory = memory; + return loader; +} + +function ft_glyphslot_done(slot) +{ + return 0; +} + +function FT_New_Size(face) +{ + if (!face) + return FT_Common.FT_Err_Invalid_Face_Handle; + + if (!face.driver) + return FT_Common.FT_Err_Invalid_Driver_Handle; + + var size = null; + var clazz = face.driver.clazz; + + FT_Error = 0; + if (clazz.init_size) + { + size = clazz.init_size(); + } + size.face = face; + + if (FT_Error == 0) + { + face.sizes_list[face.sizes_list.length] = size; + return size; + } + + return null; +} +function FT_CMap_New(clazz, init_data, charmap) +{ + FT_Error = 0; + + if (clazz == null || charmap == null || charmap.face == null) + { + FT_Error = FT_Common.FT_Err_Invalid_Argument; + return null; + } + + var _clazz = clazz.clazz; + var face = charmap.face; + var cmap = null; + + if (undefined != clazz.format) + { + switch (clazz.format) + { + case 4: + cmap = new TT_CMap4Rec(); + break; + case 12: + cmap = new TT_CMap12Rec(); + break; + case 13: + cmap = new TT_CMap13Rec(); + break; + case 14: + cmap = new TT_CMap14Rec(); + break; + default: + cmap = new TT_CMapRec(); + break; + } + } + else + { + switch (clazz.size) + { + case 101: + case 102: + cmap = new CFF_CMapStdRec(); + break; + default: + cmap = new TT_CMapRec(); + } + } + + var cmap_ = __FT_CMapRec(cmap); + if (undefined == _clazz) + _clazz = clazz; + + if (null != cmap) + { + var charmap_= cmap_.charmap; + charmap_.face = charmap.face; + charmap_.encoding = charmap.encoding; + charmap_.platform_id = charmap.platform_id; + charmap_.encoding_id = charmap.encoding_id; + + cmap_.clazz = clazz; + if (clazz.init != 0) + { + var error = _clazz.init(cmap, init_data); + if (error != 0) + { + FT_Error = error; + cmap = null; + cmap_ = null; + return null; + } + } + if (null == face.charmaps) + face.charmaps = new Array(1); + face.charmaps[face.num_charmaps++] = cmap; + } + + return cmap; +} diff --git a/Common/FontsFreeType/Private/FreeType/modules/psaux.js b/Common/FontsFreeType/Private/FreeType/modules/psaux.js new file mode 100644 index 0000000000000000000000000000000000000000..085fd70c841e6fb47b2bf457594e93af2952c474 --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/modules/psaux.js @@ -0,0 +1,4602 @@ +/******************************************************************************/ +// t1tables +/******************************************************************************/ +function _isdigit(x) +{ + if ((x >= FT_Common.SYMBOL_CONST_0) && (x <= FT_Common.SYMBOL_CONST_9)) + return 1; + return 0; +} +function _isxdigit(x) +{ + if (((x >= FT_Common.SYMBOL_CONST_0) && (x <= FT_Common.SYMBOL_CONST_9)) || + ((x >= FT_Common.SYMBOL_CONST_a) && (x <= FT_Common.SYMBOL_CONST_f)) || + ((x >= FT_Common.SYMBOL_CONST_A) && (x <= FT_Common.SYMBOL_CONST_F))) + return 1; + return 0; +} + +function PS_FontInfoRec() +{ + this.version = ""; + this.notice = ""; + this.full_name = ""; + this.family_name = ""; + this.weight = ""; + this.italic_angle = 0; + this.is_fixed_pitch = 0; + this.underline_position = 0; + this.underline_thickness = 0; + + this.CreateDublicate = function() + { + var _ret = new PS_FontInfoRec(); + + _ret.version = this.version; + _ret.notice = this.notice; + _ret.full_name = this.full_name; + _ret.family_name = this.family_name; + _ret.weight = this.weight; + _ret.italic_angle = this.italic_angle; + _ret.is_fixed_pitch = this.is_fixed_pitch; + _ret.underline_position = this.underline_position; + _ret.underline_thickness = this.underline_thickness; + + return _ret; + } +} +function PS_PrivateRec() +{ + this.unique_id = 0; + this.lenIV = 0; + + this.num_blue_values = 0; + this.num_other_blues = 0; + this.num_family_blues = 0; + this.num_family_other_blues = 0; + + this.blue_values = [0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + this.other_blues = [0,0,0,0,0,0,0,0,0,0]; + + this.family_blues = [0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + this.family_other_blues = [0,0,0,0,0,0,0,0,0,0]; + + this.blue_scale = 0; + this.blue_shift = 0; + this.blue_fuzz = 0; + + this.standard_width = [0]; + this.standard_height = [0]; + + this.num_snap_widths = 0; + this.num_snap_heights = 0; + this.force_bold = 0; + this.round_stem_up = 0; + + this.snap_widths = [0,0,0,0,0,0,0,0,0,0,0,0,0]; + this.snap_heights = [0,0,0,0,0,0,0,0,0,0,0,0,0]; + + this.expansion_factor = 0; + + this.language_group = 0; + this.password = 0; + + this.min_feature = [0,0]; + + this.clear = function() + { + this.unique_id = 0; + this.lenIV = 0; + + this.num_blue_values = 0; + this.num_other_blues = 0; + this.num_family_blues = 0; + this.num_family_other_blues = 0; + + for (var i = 0; i < 14; i++) + this.blue_values[i] = 0; + + for (var i = 0; i < 10; i++) + this.other_blues[i] = 0; + + for (var i = 0; i < 14; i++) + this.family_blues[i] = 0; + + for (var i = 0; i < 10; i++) + this.family_other_blues[i] = 0; + + this.blue_scale = 0; + this.blue_shift = 0; + this.blue_fuzz = 0; + + this.standard_width[0] = 0; + this.standard_height[0] = 0; + + this.num_snap_widths = 0; + this.num_snap_heights = 0; + this.force_bold = 0; + this.round_stem_up = 0; + + for (var i = 0; i < 13; i++) + this.snap_widths[i] = 0; + for (var i = 0; i < 13; i++) + this.snap_heights[i] = 0; + + this.expansion_factor = 0; + + this.language_group = 0; + this.password = 0; + + this.min_feature[0] = 0; + this.min_feature[1] = 0; + } +} + +function PS_DesignMapRec() +{ + this.num_points = 0; + this.design_points = null; + this.blend_points = null; +} + +function PS_BlendRec() +{ + this.num_designs = 0; + this.num_axis = 0; + + this.axis_names = CreateNullArray(FT_Common.T1_MAX_MM_AXIS); + this.design_pos = CreateNullArray(FT_Common.T1_MAX_MM_DESIGNS); + this.design_map = new Array(FT_Common.T1_MAX_MM_AXIS); + for (var i = 0; i < FT_Common.T1_MAX_MM_AXIS; i++) + this.design_map[i] = new PS_DesignMapRec(); + + this.weight_vector = null; + this.default_weight_vector = 0; + + this.font_infos = CreateNullArray(FT_Common.T1_MAX_MM_DESIGNS + 1); + this.privates = CreateNullArray(FT_Common.T1_MAX_MM_DESIGNS + 1); + + this.blend_bitflags = 0; + + this.bboxes = CreateNullArray(FT_Common.T1_MAX_MM_DESIGNS + 1); + + this.default_design_vector = CreateUIntArray(FT_Common.T1_MAX_MM_DESIGNS); + this.num_default_design_vector = 0; +} + +function CID_FaceDictRec() +{ + this.private_dict = new PS_PrivateRec(); + + this.len_buildchar = 0; + this.forcebold_threshold = 0; + this.stroke_width = 0; + this.expansion_factor = 0; + + this.paint_type = 0; + this.font_type = 0; + this.font_matrix = new FT_Matrix(); + this.font_offset = new FT_Vector(); + + this.num_subrs = 0; + this.subrmap_offset = 0; + this.sd_bytes = 0; +} + +function CID_FaceInfoRec() +{ + this.cid_font_name = ""; + this.cid_version = 0; + this.cid_font_type = 0; + + this.registry = ""; + this.ordering = ""; + this.supplement = 0; + + this.font_info = new PS_FontInfoRec(); + this.font_bbox = new FT_BBox(); + this.uid_base = 0; + + this.num_xuid = 0; + this.xuid = CreateUIntArray(16); + + this.cidmap_offset = 0; + this.fd_bytes = 0; + this.gd_bytes = 0; + this.cid_count = 0; + + this.num_dicts = 0; + this.font_dicts = null; + + this.data_offset = 0; +} + +function FT_Has_PS_Glyph_Names(face) +{ + var result = 0; + if (face != null) + { + var service = FT_FACE_FIND_SERVICE(face, FT_SERVICE_ID_POSTSCRIPT_INFO); + + if (service && service.ps_has_glyph_names) + result = service.ps_has_glyph_names(face); + } + return result; +} +function FT_Get_PS_Font_Info(face, afont_info) +{ + var error = FT_Common.FT_Err_Invalid_Argument; + if (face != null) + { + var service = FT_FACE_FIND_SERVICE(face, FT_SERVICE_ID_POSTSCRIPT_INFO); + + if (service && service.ps_get_font_info) + error = service.ps_get_font_info(face, afont_info); + } + return error; +} +function FT_Get_PS_Font_Private(face, afont_private) +{ + var error = FT_Common.FT_Err_Invalid_Argument; + if (face != null) + { + var service = FT_FACE_FIND_SERVICE(face, FT_SERVICE_ID_POSTSCRIPT_INFO); + + if (service && service.ps_get_font_private) + error = service.ps_get_font_private(face, afont_private); + } + return error; +} +function FT_Get_PS_Font_Value(face, key, idx, value, value_len) +{ + var result = 0; + if (face != null) + { + var service = FT_FACE_FIND_SERVICE(face, FT_SERVICE_ID_POSTSCRIPT_INFO); + + if (service && service.ps_get_font_value) + result = service.ps_get_font_value(face, key, idx, value, value_len); + } + return result; +} +/******************************************************************************/ +// t1types +/******************************************************************************/ +function T1_EncodingRec() +{ + this.num_chars = 0; + this.code_first = 0; + this.code_last = 0; + + this.char_index = null; + this.char_name = null; +} +function PS_FontExtraRec() +{ + this.fs_type = 0; + + this.CreateDublicate = function() + { + var _ret = new PS_FontExtraRec(); + _ret.fs_type = this.fs_type; + return _ret; + } +} +function T1_FontRec() +{ + this.font_info = new PS_FontInfoRec(); + this.font_extra = new PS_FontExtraRec(); + this.private_dict = new PS_PrivateRec(); + this.font_name = ""; + + this.encoding_type = 0; + this.encoding = new T1_EncodingRec(); + + this.subrs_block = null; + this.charstrings_block = null; + this.glyph_names_block = null; + + this.num_subrs = 0; + this.subrs = null; + this.subrs_len = null; + + this.num_glyphs = 0; + this.glyph_names = null; + this.charstrings = null; + this.charstrings_len = null; + + this.paint_type = 0; + this.font_type = 0; + this.font_matrix = new FT_Matrix(); + this.font_offset = new FT_Vector(); + this.font_bbox = new FT_BBox(); + this.font_id = 0; + + this.stroke_width = 0; +} +function CID_SubrsRec() +{ + this.num_subrs = 0; + this.code = null; +} + +function AFM_TrackKernRec() +{ + this.degree = 0; + this.min_ptsize = 0; + this.min_kern = 0; + this.max_ptsize = 0; + this.max_kern = 0; +} +function AFM_KernPairRec() +{ + this.index1 = 0; + this.index2 = 0; + this.x = 0; + this.y = 0; +} +function AFM_FontInfoRec() +{ + this.IsCIDFont = 0; + this.FontBBox = new FT_BBox(); + this.Ascender = 0; + this.Descender = 0; + this.TrackKerns = null; + this.NumTrackKern = 0; + this.KernPairs = null; + this.NumKernPair = 0; +} + + + +function T1_Face() +{ + this.num_faces = 0; + this.face_index = 0; + + this.face_flags = 0; + this.style_flags = 0; + + this.num_glyphs = 0; + + this.family_name = ""; + this.style_name = ""; + + this.num_fixed_sizes = 0; + this.available_sizes = []; + + this.num_charmaps = 0; + this.charmaps = []; + + this.generic = new FT_Generic(); + + /*# The following member variables (down to `underline_thickness') */ + /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ + /*# for bitmap fonts. */ + this.bbox = new FT_BBox(); + + this.units_per_EM = 0; + this.ascender = 0; + this.descender = 0; + this.height = 0; + + this.max_advance_width = 0; + this.max_advance_height = 0; + + this.underline_position = 0; + this.underline_thickness = 0; + + this.glyph = null; + this.size = null; + this.charmap = null; + + /*@private begin */ + this.driver = null; + this.memory = null; + this.stream = null; + + this.sizes_list = []; + + this.autohint = []; + this.extensions = null; + + this.internal = null; + /*@private end */ + + this.type1 = new T1_FontRec(); + this.psnames = null; + this.psaux = null; + this.afm_data = null; + + this.charmaprecs = new Array(2); + this.charmaprecs[0] = new FT_CharMapRec(); + this.charmaprecs[1] = new FT_CharMapRec(); + + this.charmaps = new Array(2); + this.charmaps[0] = null; + this.charmaps[1] = null; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.unicode_map = null; + //#endif + + /* support for Multiple Masters fonts */ + this.blend = null; + + /* undocumented, optional: indices of subroutines that express */ + /* the NormalizeDesignVector and the ConvertDesignVector procedure, */ + /* respectively, as Type 2 charstrings; -1 if keywords not present */ + this.ndv_idx = 0; + this.cdv_idx = 0; + + /* undocumented, optional: has the same meaning as len_buildchar */ + /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */ + this.len_buildchar = 0; + this.buildchar = null; + + /* since version 2.1 - interface to PostScript hinter */ + this.pshinter = null; +} + +function CID_Face() +{ + this.num_faces = 0; + this.face_index = 0; + + this.face_flags = 0; + this.style_flags = 0; + + this.num_glyphs = 0; + + this.family_name = ""; + this.style_name = ""; + + this.num_fixed_sizes = 0; + this.available_sizes = []; + + this.num_charmaps = 0; + this.charmaps = []; + + this.generic = new FT_Generic(); + + /*# The following member variables (down to `underline_thickness') */ + /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ + /*# for bitmap fonts. */ + this.bbox = new FT_BBox(); + + this.units_per_EM = 0; + this.ascender = 0; + this.descender = 0; + this.height = 0; + + this.max_advance_width = 0; + this.max_advance_height = 0; + + this.underline_position = 0; + this.underline_thickness = 0; + + this.glyph = null; + this.size = null; + this.charmap = null; + + /*@private begin */ + this.driver = null; + this.memory = null; + this.stream = null; + + this.sizes_list = []; + + this.autohint = []; + this.extensions = null; + + this.internal = null; + /*@private end */ + + this.psnames = null; + this.psaux = null; + this.cid = new CID_FaceInfoRec(); + this.font_extra = new PS_FontExtraRec(); + + this.subrs = null; + + /* since version 2.1 - interface to PostScript hinter */ + this.pshinter = null; + + this.binary_data = new CPointer(); /* used if hex data has been converted */ + this.cid_stream = null; +} + +/******************************************************************************/ +function IS_PS_NEWLINE(ch) +{ + if (ch == FT_Common.SYMBOL_CONST_SR || ch == FT_Common.SYMBOL_CONST_SN) + return true; + return false; +} +function IS_PS_SPACE(ch) +{ + switch (ch) + { + case FT_Common.SYMBOL_CONST_SPACE: + case FT_Common.SYMBOL_CONST_SR: + case FT_Common.SYMBOL_CONST_SN: + case FT_Common.SYMBOL_CONST_ST: + case FT_Common.SYMBOL_CONST_SF: + case FT_Common.SYMBOL_CONST_S0: + return true; + } + return false; +} +function IS_PS_SPECIAL(ch) +{ + switch (ch) + { + case FT_Common.SYMBOL_CONST_BS: + case FT_Common.SYMBOL_CONST_LS1: + case FT_Common.SYMBOL_CONST_LS2: + case FT_Common.SYMBOL_CONST_LS3: + case FT_Common.SYMBOL_CONST_RS1: + case FT_Common.SYMBOL_CONST_RS2: + case FT_Common.SYMBOL_CONST_RS3: + case FT_Common.SYMBOL_CONST_MATH_1: + case FT_Common.SYMBOL_CONST_MATH_2: + case FT_Common.SYMBOL_CONST_MATH_3: + return true; + } + return false; +} +function IS_PS_DELIM(ch) +{ + switch (ch) + { + case FT_Common.SYMBOL_CONST_SPACE: + case FT_Common.SYMBOL_CONST_SR: + case FT_Common.SYMBOL_CONST_SN: + case FT_Common.SYMBOL_CONST_ST: + case FT_Common.SYMBOL_CONST_SF: + case FT_Common.SYMBOL_CONST_S0: + case FT_Common.SYMBOL_CONST_BS: + case FT_Common.SYMBOL_CONST_LS1: + case FT_Common.SYMBOL_CONST_LS2: + case FT_Common.SYMBOL_CONST_LS3: + case FT_Common.SYMBOL_CONST_RS1: + case FT_Common.SYMBOL_CONST_RS2: + case FT_Common.SYMBOL_CONST_RS3: + case FT_Common.SYMBOL_CONST_MATH_1: + case FT_Common.SYMBOL_CONST_MATH_2: + case FT_Common.SYMBOL_CONST_MATH_3: + return true; + } + return false; +} +function IS_PS_DIGIT(ch) +{ + return (ch >= FT_Common.SYMBOL_CONST_0 && ch <= FT_Common.SYMBOL_CONST_9) ? true : false; +} +function IS_PS_XDIGIT(ch) +{ + return (IS_PS_DIGIT(ch) || (ch >= FT_Common.SYMBOL_CONST_A && ch <= FT_Common.SYMBOL_CONST_F) + || (ch >= FT_Common.SYMBOL_CONST_a && ch <= FT_Common.SYMBOL_CONST_f)) ? true : false; +} +function IS_PS_BASE85(ch) +{ + return (ch >= FT_Common.SYMBOL_CONST_VOSCL && ch <= FT_Common.SYMBOL_CONST_u) ? true : false; +} + +function IS_PS_TOKEN(cur, limit, token, len) +{ + if (cur.data[cur.pos] == token.charCodeAt(0) && (((cur.pos + len) == limit) || ((cur.pos + len) < limit && IS_PS_DELIM(cur.data[cur.pos + len - 1]))) && _strncmp_data(cur, token, len - 1) == 0) + return 1; + return 0; +} + +/******************************************************************************/ +// psconv +/******************************************************************************/ +var ft_char_table = +[ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1 +]; + +function PS_Conv_Strtol(cursor, limit, base) +{ + var _data = cursor.data; + var pos = cursor.pos; + + var num = 0; + var sign = 0; + + if (pos == limit || base < 2 || base > 36) + return 0; + + if (_data[pos] == FT_Common.SYMBOL_CONST_MATH_MINUS || _data[pos] == FT_Common.SYMBOL_CONST_MATH_PLUS) + { + sign = (_data[pos] == FT_Common.SYMBOL_CONST_MATH_MINUS) ? 1 : 0; + + pos++; + if (pos == limit) + return 0; + } + + for (; pos < limit; pos++) + { + if (IS_PS_SPACE(_data[pos]) || _data[pos] >= 0x80) + break; + + var c = ft_char_table[_data[pos] & 0x7f]; + + if (c < 0 || c >= base) + break; + + num = num * base + c; + } + + if (sign == 1) + num = -num; + + cursor.pos = pos; + return num; +} +function PS_Conv_ToInt(cursor, limit) +{ + var num = PS_Conv_Strtol(cursor, limit, 10); + var data = cursor.data; + var pos = cursor.pos; + + if (pos < limit && data[pos] == FT_Common.SYMBOL_CONST_SHARP) + { + cursor.pos = pos + 1; + return PS_Conv_Strtol(cursor, limit, num); + } + return num; +} +function PS_Conv_ToFixed(cursor, limit, power_ten) +{ + var p = dublicate_pointer(cursor); + var integral; + var decimal = 0, divider = 1; + var sign = 0; + + if (p.pos == limit) + return 0; + + var _data = p.data; + if (_data[p.pos] == FT_Common.SYMBOL_CONST_MATH_MINUS || _data[p.pos] == FT_Common.SYMBOL_CONST_MATH_PLUS) + { + sign = (_data[p.pos] == FT_Common.SYMBOL_CONST_MATH_MINUS) ? 1 : 0; + + p.pos++; + if (p.pos == limit) + return 0; + } + + if (_data[p.pos] != FT_Common.SYMBOL_CONST_POINT) + integral = PS_Conv_ToInt(p, limit) << 16; + else + integral = 0; + + /* read the decimal part */ + if (p.pos < limit && _data[p.pos] == FT_Common.SYMBOL_CONST_POINT) + { + p.pos++; + for (; p.pos < limit; p.pos++) + { + if (IS_PS_SPACE(_data[p.pos]) || _data[p.pos] >= 0x80) + break; + + var c = ft_char_table[_data[p.pos] & 0x7f]; + + if (c < 0 || c >= 10) + break; + + if (!integral && power_ten > 0) + { + power_ten--; + decimal = decimal * 10 + c; + } + else + { + if (divider < 10000000) + { + decimal = decimal * 10 + c; + divider *= 10; + } + } + } + } + + /* read exponent, if any */ + if (p.pos + 1 < limit && (_data[p.pos] == FT_Common.SYMBOL_CONST_e || _data[p.pos] == FT_Common.SYMBOL_CONST_E)) + { + p.pos++; + power_ten += PS_Conv_ToInt(p, limit); + } + + while (power_ten > 0) + { + integral *= 10; + decimal *= 10; + power_ten--; + } + + while (power_ten < 0) + { + integral /= 10; + divider *= 10; + power_ten++; + } + + if (decimal) + integral += FT_DivFix(decimal, divider); + + if (sign) + integral = -integral; + + cursor.pos = p.pos; + + return integral; +} + +function PS_Conv_ASCIIHexDecode(cursor, limit, buffer, n) +{ + var r = 0; + var w = buffer.pos; + var pad = 0x01; + + n *= 2; + + var p = dublicate_pointer(cursor); + if (n > (limit - p.pos)) + n = (limit - p.pos); + + /* we try to process two nibbles at a time to be as fast as possible */ + var _data = p.data; + for ( ; r < n; r++) + { + var c = _data[p.pos + r]; + + if (IS_PS_SPACE(c)) + continue; + + if (c >= 0x80) + break; + + c = ft_char_table[c & 0x7F]; + var _c = (c >= 0) ? c : c + 256; + if (c >= 16) + break; + + pad = (pad << 4) | c; + if (pad & 0x100) + { + buffer.data[w++] = pad & 0xFF; + pad = 0x01; + } + } + + if (pad != 0x01) + buffer[w++] = ((pad << 4) & 0xFF); + + cursor.pos = p.pos + r; + return w; +} + +function PS_Conv_EexecDecode(cursor, limit, buffer, n, seed) +{ + var r; + var s = seed; + + var _sd = cursor.data; + var _sp = cursor.pos; + + if (n > (limit - _sp)) + n = (limit - _sp); + + var _dd = buffer.data; + var _dp = buffer.pos; + + var v = 0; + var b = 0; + + for (r = 0; r < n; r++, _sp++, _dp++) + { + v = _sd[_sp]; + b = (v ^ (s >> 8)); + + s = ((v + s)*52845 + 22719) & 0xFFFF; + _dd[_dp] = b & 0xFF; + } + + cursor.pos = _sp; + return { r : r, seed : s }; +} +/******************************************************************************/ +// afmparse +/******************************************************************************/ +function AFM_ValueRec() +{ + this.type = 0; + this.u; +} +function AFM_StreamRec() +{ + this.base = null; + this.cursor = 0; + this.limit = 0; + + this.status = 0; +} + +function AFM_IS_NEWLINE(ch) +{ + if (ch == FT_Common.SYMBOL_CONST_SR || ch == FT_Common.SYMBOL_CONST_SN) + return true; + return false; +} +function AFM_IS_EOF(ch) +{ + if (ch == -1 || ch == 0x1A) + return true; + return false; +} +function AFM_IS_SPACE(ch) +{ + if (ch == FT_Common.SYMBOL_CONST_SPACE || ch == FT_Common.SYMBOL_CONST_ST) + return true; + return false; +} +function AFM_IS_SEP(ch) +{ + return (ch == FT_Common.SYMBOL_CONST_SERP) ? true : false; +} +function AFM_GETC(stream) +{ + return (stream.cursor < stream.limit) ? stream.base[stream.cursor++] : -1; +} + +function afm_stream_skip_spaces(stream) +{ + var ch = 0; + + if (stream.status >= FT_Common.AFM_STREAM_STATUS_EOC) + return FT_Common.SYMBOL_CONST_SERP; + + while (true) + { + ch = AFM_GETC(); + if (!AFM_IS_SPACE(ch)) + break; + } + + if (AFM_IS_NEWLINE(ch)) + stream.status = FT_Common.AFM_STREAM_STATUS_EOL; + else if (AFM_IS_SEP(ch)) + stream.status = FT_Common.AFM_STREAM_STATUS_EOC; + else if (AFM_IS_EOF(ch)) + stream.status = FT_Common.AFM_STREAM_STATUS_EOF; + + return ch; +} +function afm_stream_read_one(stream) +{ + afm_stream_skip_spaces( stream ); + if (stream.status >= FT_Common.AFM_STREAM_STATUS_EOC) + return null; + + var str = new CPointer(); + str.data = stream.base; + str.pos = stream.cursor - 1; + var ch; + + while ( 1 ) + { + ch = AFM_GETC(); + if (AFM_IS_SPACE(ch)) + break; + else if (AFM_IS_NEWLINE(ch)) + { + stream.status = FT_Common.AFM_STREAM_STATUS_EOL; + break; + } + else if (AFM_IS_SEP(ch)) + { + stream.status = FT_Common.AFM_STREAM_STATUS_EOC; + break; + } + else if (AFM_IS_EOF(ch)) + { + stream.status = FT_Common.AFM_STREAM_STATUS_EOF; + break; + } + } + + return str; +} +function afm_stream_read_string(stream) +{ + afm_stream_skip_spaces(stream); + if (stream.status >= FT_Common.AFM_STREAM_STATUS_EOL) + return null; + + var str = new CPointer(); + str.data = stream.base; + str.pos = stream.cursor - 1; + var ch; + + /* scan to eol */ + while ( 1 ) + { + ch = AFM_GETC(); + if (AFM_IS_NEWLINE(ch)) + { + stream.status = FT_Common.AFM_STREAM_STATUS_EOL; + break; + } + else if (AFM_IS_EOF(ch)) + { + stream.status = FT_Common.AFM_STREAM_STATUS_EOF; + break; + } + } + + return str; +} +var afm_key_table = +[ + "Ascender", + "AxisLabel", + "AxisType", + "B", + "BlendAxisTypes", + "BlendDesignMap", + "BlendDesignPositions", + "C", + "CC", + "CH", + "CapHeight", + "CharWidth", + "CharacterSet", + "Characters", + "Descender", + "EncodingScheme", + "EndAxis", + "EndCharMetrics", + "EndComposites", + "EndDirection", + "EndFontMetrics", + "EndKernData", + "EndKernPairs", + "EndTrackKern", + "EscChar", + "FamilyName", + "FontBBox", + "FontName", + "FullName", + "IsBaseFont", + "IsCIDFont", + "IsFixedPitch", + "IsFixedV", + "ItalicAngle", + "KP", + "KPH", + "KPX", + "KPY", + "L", + "MappingScheme", + "MetricsSets", + "N", + "Notice", + "PCC", + "StartAxis", + "StartCharMetrics", + "StartComposites", + "StartDirection", + "StartFontMetrics", + "StartKernData", + "StartKernPairs", + "StartKernPairs0", + "StartKernPairs1", + "StartTrackKern", + "StdHW", + "StdVW", + "TrackKern", + "UnderlinePosition", + "UnderlineThickness", + "VV", + "VVector", + "Version", + "W", + "W0", + "W0X", + "W0Y", + "W1", + "W1X", + "W1Y", + "WX", + "WY", + "Weight", + "WeightVector", + "XHeight" +]; + +function afm_parser_read_vals(parser, vals, n) +{ + var stream = parser.stream; + var str = null; + + if (n > FT_Common.AFM_MAX_ARGUMENTS) + return 0; + + var i = 0; + for (; i < n; i++) + { + var val = vals[i]; + + if (val.type == FT_Common.AFM_VALUE_TYPE_STRING) + str = afm_stream_read_string(stream); + else + str = afm_stream_read_one(stream); + + if (str == null) + break; + + var len = stream.cursor - str.pos - 1; + + switch (val.type) + { + case FT_Common.AFM_VALUE_TYPE_STRING: + case FT_Common.AFM_VALUE_TYPE_NAME: + val.u = ""; + for (var j = 0; j < len; j++) + val.u += String.fromCharCode(str.data[str.pos++]); + break; + + case FT_Common.AFM_VALUE_TYPE_FIXED: + val.u = PS_Conv_ToFixed(str, str.pos + len, 0); + break; + + case FT_Common.AFM_VALUE_TYPE_INTEGER: + val.u = PS_Conv_ToInt(str, str.pos + len); + break; + + case FT_Common.AFM_VALUE_TYPE_BOOL: + val.u = (len == 4 && (0 == _strncmp(str, "true", 4))); + break; + + case FT_Common.AFM_VALUE_TYPE_INDEX: + if (parser.get_index != null) + val.u = parser.get_index(str, len, parser.user_data); + else + val.u = 0; + break; + } + } + + return i; +} + +function afm_parser_next_key(parser, line) +{ + var stream = parser.stream; + var key = null; + + if (line) + { + while ( 1 ) + { + /* skip current line */ + if (stream.status < FT_Common.AFM_STREAM_STATUS_EOL) + afm_stream_read_string(stream); + + stream.status = FT_Common.AFM_STREAM_STATUS_NORMAL; + key = afm_stream_read_one(stream); + + /* skip empty line */ + if (key == null && (stream.status < FT_Common.AFM_STREAM_STATUS_EOF) && (stream.status >= FT_Common.AFM_STREAM_STATUS_EOL)) + continue; + + break; + } + } + else + { + while ( 1 ) + { + /* skip current column */ + while (stream.status < FT_Common.AFM_STREAM_STATUS_EOC) + afm_stream_read_one(stream); + + stream.status = FT_Common.AFM_STREAM_STATUS_NORMAL; + key = afm_stream_read_one(stream); + + /* skip empty column */ + if (key == null && (stream.status < FT_Common.AFM_STREAM_STATUS_EOF) && (stream.status >= FT_Common.AFM_STREAM_STATUS_EOC)) + continue; + + break; + } + } + + var ret_len; + ret_len = (key != null) ? (stream.cursor - key.pos - 1) : 0; + + return { key : key, len: ret_len }; +} + +function afm_tokenize(key, len) +{ + var n = 0; + for (; n < FT_Common.N_AFM_TOKENS; n++) + { + if (afm_key_table[n].charCodeAt(0) == key.charCodeAt(0)) + { + for (; n < FT_Common.N_AFM_TOKENS; n++) + { + if (afm_key_table[n].charCodeAt(0) != key.charCodeAt(0)) + return FT_Common.AFM_TOKEN_UNKNOWN; + + if (_strncmp(afm_key_table[n], key, len) == 0) + return n; + } + } + } + return FT_Common.AFM_TOKEN_UNKNOWN; +} + +function afm_parser_init(parser, memory, base, limit) +{ + var stream = new AFM_StreamRec(); + + stream.base = dublicate_pointer(base); + stream.cursor = stream.base.pos; + stream.limit = limit; + + /* don't skip the first line during the first call */ + stream.status = FT_Common.AFM_STREAM_STATUS_EOL; + + parser.memory = memory; + parser.stream = stream; + parser.FontInfo = null; + parser.get_index = null; + + return 0; +} + +function afm_parser_done(parser) +{ + parser.stream = null; +} + +function afm_parser_read_int(parser) +{ + var val = new AFM_ValueRec(); + val.type = FT_Common.AFM_VALUE_TYPE_INTEGER; + + if (afm_parser_read_vals(parser, val, 1) == 1) + { + return { pint: val.u, err: 0 }; + } + return { pint: 0, err: FT_Common.FT_Err_Syntax_Error }; +} + +function afm_parse_track_kern(parser) +{ + var fi = parser.FontInfo; + var n = -1; + + var ret = afm_parser_read_int(parser); + if (0 != ret.err) + return FT_Common.FT_Err_Syntax_Error; + + fi.NumTrackKern = ret.pint; + if (fi.NumTrackKern != 0) + { + fi.TrackKerns = new Array(fi.NumTrackKern); + } + + while (true) + { + var _key_len = afm_parser_next_key(parser, 1); + if (_key_len.key == null) + break; + + var shared_vals = new Array(5); + shared_vals[0] = new AFM_ValueRec(); + shared_vals[1] = new AFM_ValueRec(); + shared_vals[2] = new AFM_ValueRec(); + shared_vals[3] = new AFM_ValueRec(); + shared_vals[4] = new AFM_ValueRec(); + + switch (afm_tokenize(_key_len.key, _key_len.len)) + { + case FT_Common.AFM_TOKEN_TRACKKERN: + n++; + + if (n >= fi.NumTrackKern) + return FT_Common.FT_Err_Syntax_Error; + + var tk = fi.TrackKerns[n]; + + shared_vals[0].type = FT_Common.AFM_VALUE_TYPE_INTEGER; + shared_vals[1].type = FT_Common.AFM_VALUE_TYPE_FIXED; + shared_vals[2].type = FT_Common.AFM_VALUE_TYPE_FIXED; + shared_vals[3].type = FT_Common.AFM_VALUE_TYPE_FIXED; + shared_vals[4].type = FT_Common.AFM_VALUE_TYPE_FIXED; + if (afm_parser_read_vals( parser, shared_vals, 5) != 5) + return FT_Common.FT_Err_Syntax_Error; + + tk.degree = shared_vals[0].u; + tk.min_ptsize = shared_vals[1].u; + tk.min_kern = shared_vals[2].u; + tk.max_ptsize = shared_vals[3].u; + tk.max_kern = shared_vals[4].u; + + /* is this correct? */ + if (tk.degree < 0 && tk.min_kern > 0) + tk.min_kern = -tk.min_kern; + break; + + case FT_Common.AFM_TOKEN_ENDTRACKKERN: + case FT_Common.AFM_TOKEN_ENDKERNDATA: + case FT_Common.AFM_TOKEN_ENDFONTMETRICS: + fi.NumTrackKern = n + 1; + return FT_Common.FT_Err_Ok; + + case FT_Common.AFM_TOKEN_UNKNOWN: + break; + + default: + return FT_Common.FT_Err_Syntax_Error; + } + } + + return FT_Common.FT_Err_Syntax_Error; +} + +function afm_compare_kern_pairs(kp1, kp2) +{ + var index1 = kp1.index1 << 16 | kp1.index2; + var index2 = kp2.index1 << 16 | kp2.index2; + + if ( index1 > index2 ) + return 1; + else if ( index1 < index2 ) + return -1; + else + return 0; +} + +function afm_parse_kern_pairs(parser) +{ + var fi = parser.FontInfo; + var kp = null; + var n = -1; + + var _key_len = afm_parser_read_int(parser); + if (null != _key_len.key) + return FT_Common.FT_Err_Syntax_Error; + + fi.NumKernPair = _key_len.len; + if (fi.NumKernPair != 0) + { + fi.KernPairs = new Array(fi.NumKernPair); + for (var i = 0; i < fi.NumKernPair; i++) + fi.NumKernPair[i] = new AFM_KernPairRec(); + } + + while (true) + { + _key_len = afm_parser_next_key(parser, 1); + if (null == _key_len.key) + break; + + var token = afm_tokenize(_key_len.key, _key_len.len); + switch (token) + { + case FT_Common.AFM_TOKEN_KP: + case FT_Common.AFM_TOKEN_KPX: + case FT_Common.AFM_TOKEN_KPY: + var shared_vals = new Array(4); + shared_vals[0] = new AFM_ValueRec(); + shared_vals[1] = new AFM_ValueRec(); + shared_vals[2] = new AFM_ValueRec(); + shared_vals[3] = new AFM_ValueRec(); + n++; + + if (n >= fi.NumKernPair) + return FT_Common.FT_Err_Syntax_Error; + + kp = fi.KernPairs[n]; + + shared_vals[0].type = FT_Common.AFM_VALUE_TYPE_INDEX; + shared_vals[1].type = FT_Common.AFM_VALUE_TYPE_INDEX; + shared_vals[2].type = FT_Common.AFM_VALUE_TYPE_INTEGER; + shared_vals[3].type = FT_Common.AFM_VALUE_TYPE_INTEGER; + var r = afm_parser_read_vals(parser, shared_vals, 4); + if (r < 3) + return FT_Common.FT_Err_Syntax_Error; + + kp.index1 = shared_vals[0].u; + kp.index2 = shared_vals[1].u; + if (token == FT_Common.AFM_TOKEN_KPY) + { + kp.x = 0; + kp.y = shared_vals[2].u; + } + else + { + kp.x = shared_vals[2].u.i; + kp.y = (token == FT_Common.AFM_TOKEN_KP && r == 4) ? shared_vals[3].u : 0; + } + break; + + case FT_Common.AFM_TOKEN_ENDKERNPAIRS: + case FT_Common.AFM_TOKEN_ENDKERNDATA: + case FT_Common.AFM_TOKEN_ENDFONTMETRICS: + fi.NumKernPair = n + 1; + ft_qsort(fi.KernPairs, fi.NumKernPair, afm_compare_kern_pairs); + return FT_Common.FT_Err_Ok; + + case FT_Common.AFM_TOKEN_UNKNOWN: + break; + + default: + return FT_Common.FT_Err_Syntax_Error; + } + } + + return FT_Common.FT_Err_Syntax_Error; +} + +function afm_parse_kern_data(parser) +{ + while (true) + { + var _key_len = afm_parser_next_key(parser, 1); + if (null != _key_len) + break; + + switch (afm_tokenize(_key_len.key, _key_len.len)) + { + case FT_Common.AFM_TOKEN_STARTTRACKKERN: + var error = afm_parse_track_kern(parser); + if (error != FT_Common.FT_Err_Ok) + return error; + break; + + case FT_Common.AFM_TOKEN_STARTKERNPAIRS: + case FT_Common.AFM_TOKEN_STARTKERNPAIRS0: + var error = afm_parse_kern_pairs(parser); + if (error != FT_Common.FT_Err_Ok) + return error; + break; + + case FT_Common.AFM_TOKEN_ENDKERNDATA: + case FT_Common.AFM_TOKEN_ENDFONTMETRICS: + return FT_Common.FT_Err_Ok; + + case FT_Common.AFM_TOKEN_UNKNOWN: + break; + + default: + return FT_Common.FT_Err_Syntax_Error; + } + } + + return FT_Common.FT_Err_Syntax_Error; +} + +function afm_parser_skip_section(parser, n, end_section) +{ + while ( n-- > 0 ) + { + var _key_len = afm_parser_next_key(parser, 1); + if (_key_len.key != null) + return FT_Common.FT_Err_Syntax_Error; + } + + while (true) + { + var _key_len = afm_parser_next_key(parser, 1); + if (_key_len.key != null) + break; + + var token = afm_tokenize(_key_len.key, _key_len.len); + + if (token == end_section || token == FT_Common.AFM_TOKEN_ENDFONTMETRICS) + return FT_Common.FT_Err_Ok; + } + + return FT_Common.FT_Err_Syntax_Error; +} + +function afm_parser_parse(parser) +{ + var fi = parser.FontInfo; + var error = FT_Common.FT_Err_Syntax_Error; + var metrics_sets = 0; + + if (fi == null) + return FT_Common.FT_Err_Invalid_Argument; + + var _key_len = afm_parser_next_key(parser, 1); + if (null == _key_len.key || _key_len.len != 16 || _strncmp(_key_len.key, "StartFontMetrics", 16) != 0) + return FT_Common.FT_Err_Unknown_File_Format; + + while (true) + { + _key_len = afm_parser_next_key(parser, 1); + if (null == _key_len) + break; + + var shared_vals = new Array(4); + shared_vals[0] = new AFM_ValueRec(); + shared_vals[1] = new AFM_ValueRec(); + shared_vals[2] = new AFM_ValueRec(); + shared_vals[3] = new AFM_ValueRec(); + + var token = afm_tokenize(_key_len.key, _key_len.len); + switch (token) + { + case FT_Common.AFM_TOKEN_METRICSSETS: + var ret = afm_parser_read_int(parser); + if (ret.err != FT_Common.FT_Err_Ok) + { + fi.TrackKerns = null; + fi.NumTrackKern = 0; + + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.IsCIDFont = 0; + + return error; + } + metrics_sets = ret.pint; + if (metrics_sets != 0 && metrics_sets != 2) + { + fi.TrackKerns = null; + fi.NumTrackKern = 0; + + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.IsCIDFont = 0; + + return FT_Common.FT_Err_Unimplemented_Feature; + } + break; + + case FT_Common.AFM_TOKEN_ISCIDFONT: + shared_vals[0].type = FT_Common.AFM_VALUE_TYPE_BOOL; + if (afm_parser_read_vals(parser, shared_vals, 1) != 1) + { + fi.TrackKerns = null; + fi.NumTrackKern = 0; + + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.IsCIDFont = 0; + + return error; + } + + fi.IsCIDFont = shared_vals[0].u; + break; + + case FT_Common.AFM_TOKEN_FONTBBOX: + shared_vals[0].type = FT_Common.AFM_VALUE_TYPE_FIXED; + shared_vals[1].type = FT_Common.AFM_VALUE_TYPE_FIXED; + shared_vals[2].type = FT_Common.AFM_VALUE_TYPE_FIXED; + shared_vals[3].type = FT_Common.AFM_VALUE_TYPE_FIXED; + if (afm_parser_read_vals( parser, shared_vals, 4 ) != 4) + { + fi.TrackKerns = null; + fi.NumTrackKern = 0; + + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.IsCIDFont = 0; + + return error; + } + + fi.FontBBox.xMin = shared_vals[0].u; + fi.FontBBox.yMin = shared_vals[1].u; + fi.FontBBox.xMax = shared_vals[2].u; + fi.FontBBox.yMax = shared_vals[3].u; + break; + + case FT_Common.AFM_TOKEN_ASCENDER: + shared_vals[0].type = FT_Common.AFM_VALUE_TYPE_FIXED; + if (afm_parser_read_vals(parser, shared_vals, 1) != 1) + { + // fail + return error; + } + + fi.Ascender = shared_vals[0].u; + break; + + case FT_Common.AFM_TOKEN_DESCENDER: + shared_vals[0].type = FT_Common.AFM_VALUE_TYPE_FIXED; + if (afm_parser_read_vals( parser, shared_vals, 1 ) != 1) + { + fi.TrackKerns = null; + fi.NumTrackKern = 0; + + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.IsCIDFont = 0; + + return error; + } + + fi.Descender = shared_vals[0].u; + break; + + case FT_Common.AFM_TOKEN_STARTCHARMETRICS: + var ret = afm_parser_read_int(parser); + if (ret.err != FT_Common.FT_Err_Ok) + { + fi.TrackKerns = null; + fi.NumTrackKern = 0; + + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.IsCIDFont = 0; + + return error; + } + var n = ret.pint; + error = afm_parser_skip_section(parser, n, FT_Common.AFM_TOKEN_ENDCHARMETRICS); + if (error != FT_Common.FT_Err_Ok) + return error; + break; + + case FT_Common.AFM_TOKEN_STARTKERNDATA: + error = afm_parse_kern_data(parser); + if (error != FT_Common.FT_Err_Ok) + { + fi.TrackKerns = null; + fi.NumTrackKern = 0; + + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.IsCIDFont = 0; + + return error; + } + /* fall through since we only support kern data */ + case FT_Common.AFM_TOKEN_ENDFONTMETRICS: + return FT_Common.FT_Err_Ok; + + default: + break; + } + } + + fi.TrackKerns = null; + fi.NumTrackKern = 0; + + fi.KernPairs = null; + fi.NumKernPair = 0; + + fi.IsCIDFont = 0; + + return error; +} + +/******************************************************************************/ +// t1cmap +/******************************************************************************/ +function T1_CMapStdRec() +{ + this.cmap = new FT_CMapRec(); + + this.code_to_sid = null; + this.sid_to_string = null; + + this.num_glyphs = 0; + this.glyph_names = null; + + this.type = FT_Common.FT_CMAP_1; +} +function T1_CMapCustomRec() +{ + this.cmap = new FT_CMapRec(); + this.first = 0; + this.count = 0; + this.indices = null; + + this.type = FT_Common.FT_CMAP_1; +} + +// standart +function t1_cmap_std_init(cmap, is_expert) +{ + var face = __FT_CMapRec(cmap).charmap.face; + var psnames = face.psnames; + + cmap.num_glyphs = face.type1.num_glyphs; + cmap.glyph_names = face.type1.glyph_names; + cmap.sid_to_string = psnames.adobe_std_strings; + cmap.code_to_sid = (is_expert == 1) ? psnames.adobe_expert_encoding : psnames.adobe_std_encoding; +} + +function t1_cmap_std_done(cmap) +{ + cmap.num_glyphs = 0; + cmap.glyph_names = null; + cmap.sid_to_string = null; + cmap.code_to_sid = null; +} + +function t1_cmap_std_char_index(cmap, char_code) +{ + var result = 0; + + if (char_code < 256) + { + /* convert character code to Adobe SID string */ + var code = cmap.code_to_sid[char_code]; + var glyph_name = cmap.sid_to_string(code); + + /* look for the corresponding glyph name */ + for (var n = 0; n < cmap.num_glyphs; n++ ) + { + var gname = cmap.glyph_names[n]; + + if (gname != null && gname.charCodeAt(0) == glyph_name.charCodeAt(0) && gname == glyph_name) + { + result = n; + break; + } + } + } + + return result; +} + +function t1_cmap_std_char_next(cmap, char_code) +{ + var result = 0; + var pchar_code = char_code + 1; + + while (pchar_code < 256) + { + result = t1_cmap_std_char_index( cmap, pchar_code ); + if ( result != 0 ) + return {gindex:result,char_code:pchar_code}; + + pchar_code++; + } + pchar_code = 0; + return {gindex:result,char_code:pchar_code}; +} + +function t1_cmap_standard_init(cmap) +{ + t1_cmap_std_init(cmap, 0); + return 0; +} + +var t1_cmap_standard_class_rec = create_cmap_class_rec(0,t1_cmap_standard_init,t1_cmap_std_done,t1_cmap_std_char_index,t1_cmap_std_char_next,null,null,null,null,null); + +// expert +function t1_cmap_expert_init(cmap) +{ + t1_cmap_std_init(cmap, 1); + return 0; +} + +var t1_cmap_expert_class_rec = create_cmap_class_rec(0,t1_cmap_expert_init,t1_cmap_std_done,t1_cmap_std_char_index,t1_cmap_std_char_next,null,null,null,null,null); + +// custom +function t1_cmap_custom_init(cmap) +{ + var face = __FT_CMapRec(cmap).charmap.face; + var encoding = face.type1.encoding; + + cmap.first = encoding.code_first; + cmap.count = (encoding.code_last - cmap.first); + + if (0 > cmap.count) + cmap.count = 0; + + cmap.indices = encoding.char_index; + + return 0; +} + +function t1_cmap_custom_done(cmap) +{ + cmap.indices = null; + cmap.first = 0; + cmap.count = 0; +} + +function t1_cmap_custom_char_index(cmap, char_code) +{ + if (char_code >= cmap.first && char_code < (cmap.first + cmap.count)) + return cmap.indices[char_code]; + return 0; +} + +function t1_cmap_custom_char_next(cmap, _char_code) +{ + var result = 0; + var char_code = _char_code; + ++char_code; + + if (char_code < cmap.first) + char_code = cmap.first; + + var last = cmap.first + cmap.count; + for (; char_code < last; char_code++) + { + result = cmap.indices[char_code]; + if (result != 0) + return {gindex:result,char_code:char_code}; + } + + return {gindex:result,char_code:0}; +} + +var t1_cmap_custom_class_rec = create_cmap_class_rec(0,t1_cmap_custom_init,t1_cmap_custom_done,t1_cmap_custom_char_index,t1_cmap_custom_char_next,null,null,null,null,null); + +// unicode +function t1_get_glyph_name(face, idx) +{ + return face.type1.glyph_names[idx]; +} + +function t1_cmap_unicode_init(unicodes) +{ + var face = __FT_CMapRec(unicodes).charmap.face; + var memory = face.memory; + var psnames = face.psnames; + + return psnames.unicodes_init(memory, unicodes, face.type1.num_glyphs, t1_get_glyph_name, null, face); +} + +function t1_cmap_unicode_done(unicodes) +{ + unicodes.maps = null; + unicodes.num_maps = 0; +} + +function t1_cmap_unicode_char_index(unicodes, char_code) +{ + var face = __FT_CMapRec(unicodes).charmap.face; + var psnames = face.psnames; + + return psnames.unicodes_char_index(unicodes, char_code); +} + +function t1_cmap_unicode_char_next(unicodes, pchar_code) +{ + var face = __FT_CMapRec(unicodes).charmap.face; + var psnames = face.psnames; + + return psnames.unicodes_char_next(unicodes, pchar_code); +} + +var t1_cmap_unicode_class_rec = create_cmap_class_rec(0,t1_cmap_unicode_init,t1_cmap_unicode_done,t1_cmap_unicode_char_index,t1_cmap_unicode_char_next,null,null,null,null,null); + +/******************************************************************************/ +// psobj +/******************************************************************************/ + +function ps_table_new(table, count, memory) +{ + table.memory = memory; + table.elements = new Array(count); + + for (var i = 0; i < count; i++) + table.elements[i] = new CPointer(); + + table.lengths = CreateIntArray(count); + + table.max_elems = count; + table.init = 0xDEADBEEF; + table.num_elems = 0; + table.block = null; + table.capacity = 0; + table.cursor = 0; + + table.funcs = ps_table_funcs; + return 0; +} + +function shift_elements(table, old_base) +{ + var delta = table.block.pos - old_base.pos; + var els = table.elements; + + var limit = table.max_elems; + for (var i = 0; i < limit; i++) + { + if (null != els[i]) + { + els[i].data[els[i].pos] += delta; + } + } +} + +function reallocate_t1_table(table, new_size) +{ + var memory = table.memory; + var old_base = table.block; + + table.block = memory.Alloc(new_size); + var dst = table.block.data; + if (null != old_base) + { + var src = old_base.data; + for (var i = 0; i < table.capacity; i++) + { + dst[i] = src[i]; + } + } + + var _els = table.elements; + var _elc = table.max_elems; + for (var j = 0; j < _elc; j++) + _els[j].data = dst; + + old_base = null; + table.capacity = new_size; + return 0; +} + +function ps_table_add(table, idx, object, length) +{ + if (idx < 0 || idx >= table.max_elems) + return FT_Common.FT_Err_Invalid_Argument; + + if (length < 0) + return FT_Common.FT_Err_Invalid_Argument; + + /* + table.elements[idx] = copy_pointer(object, length); + table.lengths[idx] = length; + table.cursor = idx + 1; + */ + + if (table.cursor + length > table.capacity) + { + var new_size = table.capacity; + + while (new_size < (table.cursor + length)) + { + /* increase size by 25% and round up to the nearest multiple + of 1024 */ + new_size += (new_size >> 2) + 1; + new_size = parseInt((new_size + 1023) / 1024) * 1024; + } + + reallocate_t1_table(table, new_size); + } + + /* add the object to the base block and adjust offset */ + table.elements[idx].pos = table.cursor; + table.lengths[idx] = length; + + var dd = table.block.data; + var dp = table.cursor; + var sd = object.data; + var sp = object.pos; + + for (var i = 0; i < length; i++) + dd[dp++] = sd[sp++]; + + table.cursor += length; + + return 0; +} + +function ps_table_done(table) +{ + if (null == table.block) + return 0; + + reallocate_t1_table(table, table.cursor); + return 0; +} + +function ps_table_release(table) +{ + if (table.init == 0xDEADBEEF) + { + table.block = null; + table.elements = null; + table.lengths = null; + table.init = 0; + } +} + +function skip_comment(cur, limit) +{ + while (cur.pos < limit) + { + if (IS_PS_NEWLINE(cur.data[cur.pos])) + break; + cur.pos++; + } +} + +function skip_spaces(cur, limit) +{ + while (cur.pos < limit) + { + if (!IS_PS_SPACE(cur.data[cur.pos])) + { + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_MATH_3) + { + /* According to the PLRM, a comment is equal to a space. */ + skip_comment(cur, limit); + } + else + break; + } + cur.pos++; + } +} + +function skip_literal_string(cur, limit) +{ + var embed = 0; + var error = FT_Common.FT_Err_Invalid_File_Format; + + while (cur.pos < limit) + { + var c = cur.data[cur.pos]; + cur.pos++; + + if (c == FT_Common.SYMBOL_CONST_SS) + { + /* Red Book 3rd ed., section `Literal Text Strings', p. 29: */ + /* A backslash can introduce three different types */ + /* of escape sequences: */ + /* - a special escaped char like \r, \n, etc. */ + /* - a one-, two-, or three-digit octal number */ + /* - none of the above in which case the backslash is ignored */ + + if (cur.pos == limit) + break;/* error (or to be ignored?) */ + + switch (cur.data[cur.pos]) + { + /* skip `special' escape */ + case FT_Common.SYMBOL_CONST_n: + case FT_Common.SYMBOL_CONST_r: + case FT_Common.SYMBOL_CONST_t: + case FT_Common.SYMBOL_CONST_b: + case FT_Common.SYMBOL_CONST_f: + case FT_Common.SYMBOL_CONST_SS: + case FT_Common.SYMBOL_CONST_LS1: + case FT_Common.SYMBOL_CONST_RS1: + cur.pos++; + break; + + default: + /* skip octal escape or ignore backslash */ + for (var i = 0; i < 3 && cur.pos < limit; i++) + { + if (FT_Common.SYMBOL_CONST_0 > cur.data[cur.pos] || FT_Common.SYMBOL_CONST_7 < cur.data[cur.pos]) + break; + + cur.pos++; + } + } + } + else if (c == FT_Common.SYMBOL_CONST_LS1) + embed++; + else if (c == FT_Common.SYMBOL_CONST_RS1) + { + embed--; + if (embed == 0) + { + error = 0; + break; + } + } + } + return error; +} + +function skip_string(cur, limit) +{ + while (cur.pos < limit) + { + /* All whitespace characters are ignored. */ + skip_spaces(cur, limit); + if (cur.pos >= limit) + break; + + if (!IS_PS_XDIGIT(cur.data[cur.pos])) + break; + } + + if (cur.pos < limit && cur.data[cur.pos] != FT_Common.SYMBOL_CONST_MATH_2) + { + return FT_Common.FT_Err_Invalid_File_Format; + } + else + cur.pos++; + + return 0; +} + +function skip_procedure(cur, limit) +{ + var embed = 0; + + var error = 0; + for (; cur.pos < limit && error == 0; cur.pos++) + { + switch (cur.data[cur.pos]) + { + case FT_Common.SYMBOL_CONST_LS3: + ++embed; + break; + + case FT_Common.SYMBOL_CONST_RS3: + --embed; + if (embed == 0) + { + cur.pos++; + return 0; + } + break; + + case FT_Common.SYMBOL_CONST_LS1: + error = skip_literal_string(cur, limit); + break; + + case FT_Common.SYMBOL_CONST_MATH_1: + error = skip_string(cur, limit); + break; + + case FT_Common.SYMBOL_CONST_MATH_3: + skip_comment(cur, limit); + break; + } + } + + if (embed != 0) + error = FT_Common.FT_Err_Invalid_File_Format; + + return error; +} + +function ps_parser_skip_PS_token(parser) +{ + /* Note: PostScript allows any non-delimiting, non-whitespace */ + /* character in a name (PS Ref Manual, 3rd ed, p31). */ + /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */ + + var cur = dublicate_pointer(parser.cursor); + var limit = parser.limit; + var error = FT_Common.FT_Err_Ok; + + var cursor_pos = cur.pos; + skip_spaces(cur, limit); /* this also skips comments */ + if (cur.pos >= limit) + { + if (cur.pos == cursor_pos) + { + error = FT_Common.FT_Err_Invalid_File_Format; + } + + parser.error = error; + parser.cursor.pos = cur.pos; + return; + } + + /* self-delimiting, single-character tokens */ + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_LS2 || cur.data[cur.pos] == FT_Common.SYMBOL_CONST_RS2) + { + cur.pos++; + if (cur.pos == cursor_pos) + { + error = FT_Common.FT_Err_Invalid_File_Format; + } + + parser.error = error; + parser.cursor.pos = cur.pos; + return; + } + + /* skip balanced expressions (procedures and strings) */ + + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_LS3) /* {...} */ + { + error = skip_procedure(cur, limit); + if (cur.pos == cursor_pos) + { + error = FT_Common.FT_Err_Invalid_File_Format; + } + + parser.error = error; + parser.cursor.pos = cur.pos; + return; + } + + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_LS1) /* (...) */ + { + error = skip_literal_string(cur, limit); + if (cur.pos == cursor_pos) + { + error = FT_Common.FT_Err_Invalid_File_Format; + } + + parser.error = error; + parser.cursor.pos = cur.pos; + return; + } + + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_MATH_1) /* <...> */ + { + if (cur.pos + 1 < limit && cur.data[cur.pos + 1] == FT_Common.SYMBOL_CONST_MATH_1) /* << */ + { + cur.pos += 2; + } + else + error = skip_string(cur, limit); + + if (cur.pos == cursor_pos) + { + error = FT_Common.FT_Err_Invalid_File_Format; + } + + parser.error = error; + parser.cursor.pos = cur.pos; + return; + } + + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_MATH_2) + { + cur.pos++; + if (cur.pos >= limit || cur.data[cur.pos] != FT_Common.SYMBOL_CONST_MATH_2) /* >> */ + { + error = FT_Common.FT_Err_Invalid_File_Format; + + parser.error = error; + parser.cursor.pos = cur.pos; + return; + } + cur.pos++; + if (cur.pos == cursor_pos) + { + error = FT_Common.FT_Err_Invalid_File_Format; + } + + parser.error = error; + parser.cursor.pos = cur.pos; + return; + } + + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_BS) + cur.pos++; + + /* anything else */ + while (cur.pos < limit) + { + /* *cur might be invalid (e.g., ')' or '}'), but this */ + /* is handled by the test `cur == parser->cursor' below */ + if (IS_PS_DELIM(cur.data[cur.pos])) + break; + + cur.pos++; + } + + //exit + if (cur.pos == cursor_pos) + { + error = FT_Common.FT_Err_Invalid_File_Format; + } + + parser.error = error; + parser.cursor.pos = cur.pos; +} + +function ps_parser_skip_spaces(parser) +{ + skip_spaces(parser.cursor, parser.limit); +} + +function ps_parser_to_token(parser, token) +{ + var limit = parser.limit; + var embed = 0; + + token.type = FT_Common.T1_TOKEN_TYPE_NONE; + token.start = null; + token.limit = 0; + + /* first of all, skip leading whitespace */ + ps_parser_skip_spaces(parser); + var cur = dublicate_pointer(parser.cursor); + + if (cur.pos >= limit) + return; + + switch (cur.data[cur.pos]) + { + /************* check for literal string *****************/ + case FT_Common.SYMBOL_CONST_LS1: + token.type = FT_Common.T1_TOKEN_TYPE_STRING; + token.start = dublicate_pointer(cur); + + if (skip_literal_string(cur, limit) == 0) + token.limit = cur.pos; + break; + + /************* check for programs/array *****************/ + case FT_Common.SYMBOL_CONST_LS3: + token.type = FT_Common.T1_TOKEN_TYPE_ARRAY; + token.start = dublicate_pointer(cur); + + if (skip_procedure(cur, limit) == 0) + token.limit = cur.pos; + break; + + /************* check for table/array ********************/ + /* XXX: in theory we should also look for "<<" */ + /* since this is semantically equivalent to "["; */ + /* in practice it doesn't matter (?) */ + case FT_Common.SYMBOL_CONST_LS2: + token.type = FT_Common.T1_TOKEN_TYPE_ARRAY; + embed = 1; + token.start = dublicate_pointer(cur); + cur.pos++; + + /* we need this to catch `[ ]' */ + parser.cursor.pos = cur.pos; + ps_parser_skip_spaces(parser); + cur.pos = parser.cursor.pos; + + while (cur.pos < limit && parser.error == 0) + { + /* XXX: this is wrong because it does not */ + /* skip comments, procedures, and strings */ + if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_LS2) + embed++; + else if (cur.data[cur.pos] == FT_Common.SYMBOL_CONST_RS2) + { + embed--; + if ( embed <= 0 ) + { + cur.pos++; + token.limit = cur.pos; + break; + } + } + + parser.cursor.pos = cur.pos; + ps_parser_skip_PS_token(parser); + /* we need this to catch `[XXX ]' */ + ps_parser_skip_spaces(parser); + cur.pos = parser.cursor.pos; + } + break; + + /* ************ otherwise, it is any token **************/ + default: + token.start = dublicate_pointer(cur); + token.type = ((cur.data[cur.pos] == FT_Common.SYMBOL_CONST_BS) ? FT_Common.T1_TOKEN_TYPE_KEY : FT_Common.T1_TOKEN_TYPE_ANY); + ps_parser_skip_PS_token(parser); + cur.pos = parser.cursor.pos; + if (!parser.error) + token.limit = cur.pos; + } + + if (token.limit == 0) + { + token.start = null; + token.type = FT_Common.T1_TOKEN_TYPE_NONE; + } + + parser.cursor.pos = cur.pos; +} + +function ps_parser_to_token_array(parser, tokens, max_tokens) +{ + var master = new T1_TokenRec(); + var pnum_tokens = -1; + /* this also handles leading whitespace */ + ps_parser_to_token(parser, master); + + if (master.type == FT_Common.T1_TOKEN_TYPE_ARRAY) + { + var old_cursor = parser.cursor.pos; + var old_limit = parser.limit; + var cur = 0; + + /* don't include outermost delimiters */ + parser.cursor = dublicate_pointer(master.start); + parser.cursor.pos += 1; + parser.limit = master.limit - 1; + + while (parser.cursor.pos < parser.limit) + { + var token = new T1_TokenRec(); + ps_parser_to_token(parser, token); + if (token.type == 0) + break; + + if (tokens != null && cur < max_tokens) + { + var _cur = tokens[cur]; + _cur.start = dublicate_pointer(token.start); + _cur.limit = token.limit; + _cur.type = token.type; + } + + cur++; + } + + pnum_tokens = cur; + + parser.cursor.pos = old_cursor; + parser.limit = old_limit; + } + + return pnum_tokens; +} + +function ps_tocoordarray(cur, limit, max_coords, coords) +{ + var count = 0; + if (cur.pos >= limit) + return count; + + /* check for the beginning of an array; otherwise, only one number */ + /* will be read */ + var c = cur.data[cur.pos]; + var ender = 0; + + if (c == FT_Common.SYMBOL_CONST_LS2) + ender = FT_Common.SYMBOL_CONST_RS2; + else if (c == FT_Common.SYMBOL_CONST_LS3) + ender = FT_Common.SYMBOL_CONST_RS3; + + if (ender != 0) + cur.pos++; + + /* now, read the coordinates */ + while ( cur < limit ) + { + /* skip whitespace in front of data */ + skip_spaces(cur, limit); + if (cur.pos >= limit) + return count; + + if (cur.data[cur.pos] == ender) + { + cur.pos++; + break; + } + + var old_cur = cur.pos; + + if ( coords != NULL && count >= max_coords ) + break; + + /* call PS_Conv_ToFixed() even if coords == NULL */ + /* to properly parse number at `cur' */ + var dummy = PS_Conv_ToFixed(cur, limit, 0) >> 16; + if (null != coords) + coords[count] = dummy; + + if (old_cur == cur.pos) + { + count = -1; + return count; + } + else + count++; + + if (ender == 0) + break; + } + + return count; +} + +function ps_tofixedarray(cur, limit, max_values, values, power_ten) +{ + var count = 0; + if (cur.pos >= limit) + return count; + + /* Check for the beginning of an array. Otherwise, only one number */ + /* will be read. */ + var c = cur.data[cur.pos]; + var ender = 0; + + if (c == FT_Common.SYMBOL_CONST_LS2) + ender = FT_Common.SYMBOL_CONST_RS2; + else if (c == FT_Common.SYMBOL_CONST_LS3) + ender = FT_Common.SYMBOL_CONST_RS3; + + if (ender != 0) + cur.pos++; + + /* now, read the values */ + while (cur.pos < limit) + { + /* skip whitespace in front of data */ + skip_spaces(cur, limit); + if (cur.pos >= limit) + return count; + + if (cur.data[cur.pos] == ender) + { + cur.pos++; + break; + } + + var old_cur = cur.pos; + if (values != null && count >= max_values) + break; + + /* call PS_Conv_ToFixed() even if coords == NULL */ + /* to properly parse number at `cur' */ + var dummy = PS_Conv_ToFixed(cur, limit, power_ten); + if (null != values) + values[count] = dummy; + + if (old_cur == cur.pos) + { + count = -1; + return count; + } + else + count++; + + if (ender == 0) + break; + } + + return count; +} + +function ps_tobool(cur, limit) +{ + var result = 0; + var data = cur.data; + var pos = cur.pos; + + /* return 1 if we find `true', 0 otherwise */ + if (cur.pos + 3 < limit && + data[pos] == FT_Common.SYMBOL_CONST_t && + data[pos + 1] == FT_Common.SYMBOL_CONST_r && + data[pos + 2] == FT_Common.SYMBOL_CONST_u && + data[pos + 3] == FT_Common.SYMBOL_CONST_e) + { + result = 1; + cur.pos += 5; + } + else if (cur.pos + 4 < limit && + data[pos] == FT_Common.SYMBOL_CONST_f && + data[pos + 1] == FT_Common.SYMBOL_CONST_a && + data[pos + 2] == FT_Common.SYMBOL_CONST_l && + data[pos + 3] == FT_Common.SYMBOL_CONST_s && + data[pos + 4] == FT_Common.SYMBOL_CONST_e) + { + result = 0; + cur.pos += 6; + } + + return result; +} + +function ps_parser_load_field(parser, field, objects, max_objects, pflags) +{ + var token = new T1_TokenRec(); + /* this also skips leading whitespace */ + ps_parser_to_token(parser, token); + if (token.type == 0) + return FT_Common.FT_Err_Invalid_File_Format; + + var count = 1; + var idx = 0; + var cur = dublicate_pointer(token.start); + var limit = token.limit; + + /* we must detect arrays in /FontBBox */ + if (field.type == FT_Common.T1_FIELD_TYPE_BBOX) + { + var token2 = new T1_TokenRec(); + var old_cur = dublicate_pointer(parser.cursor); + var old_limit = parser.limit; + + /* don't include delimiters */ + parser.cursor = dublicate_pointer(token.start); + parser.cursor.pos += 1; + parser.limit = token.limit - 1; + + ps_parser_to_token(parser, token2); + parser.cursor = dublicate_pointer(old_cur); + parser.limit = old_limit; + + if (token2.type == FT_Common.T1_TOKEN_TYPE_ARRAY) + { + /* if this is an array and we have no blend, an error occurs */ + if (max_objects == 0) + return FT_Common.FT_Err_Invalid_File_Format; + + count = max_objects; + idx = 1; + + /* don't include delimiters */ + cur.pos++; + limit--; + } + } + else if (token.type == FT_Common.T1_TOKEN_TYPE_ARRAY) + { + /* if this is an array and we have no blend, an error occurs */ + if (max_objects == 0) + return FT_Common.FT_Err_Invalid_File_Format; + + count = max_objects; + idx = 1; + + /* don't include delimiters */ + cur.pos++; + limit--; + } + + for (; count > 0; count--, idx++) + { + var __obj = objects[idx]; + var val; + skip_spaces(cur, limit); + + switch (field.type) + { + case FT_Common.T1_FIELD_TYPE_BOOL: + val = ps_tobool(cur, limit); + fire_t1_field(__obj, val, field); + break; + + case FT_Common.T1_FIELD_TYPE_FIXED: + val = PS_Conv_ToFixed(cur, limit, 0); + fire_t1_field(__obj, val, field); + break; + + case FT_Common.T1_FIELD_TYPE_FIXED_1000: + val = PS_Conv_ToFixed(cur, limit, 3); + fire_t1_field(__obj, val, field); + break; + + case FT_Common.T1_FIELD_TYPE_INTEGER: + val = PS_Conv_ToInt(cur, limit); + fire_t1_field(__obj, val, field); + break; + + case FT_Common.T1_FIELD_TYPE_STRING: + case FT_Common.T1_FIELD_TYPE_KEY: + var len = (limit - cur.pos); + + if (cur.pos >= limit) + break; + + /* we allow both a string or a name */ + /* for cases like /FontName (foo) def */ + if (token.type == FT_Common.T1_TOKEN_TYPE_KEY) + { + /* don't include leading `/' */ + len--; + cur.pos++; + } + else if (token.type == FT_Common.T1_TOKEN_TYPE_STRING) + { + /* don't include delimiting parentheses */ + /* XXX we don't handle <<...>> here */ + /* XXX should we convert octal escapes? */ + /* if so, what encoding should we use? */ + cur.pos++; + len -= 2; + } + else + { + return FT_Common.FT_Err_Invalid_File_Format; + } + + /* for this to work (FT_String**)q must have been */ + /* initialized to NULL */ + var _s = ""; + for (var i = 0; i < len; i++) + _s += String.fromCharCode(cur.data[cur.pos + i]); + + fire_t1_field(__obj, _s, field); + break; + + case FT_Common.T1_FIELD_TYPE_BBOX: + var temp = new Array(4); + temp[0] = 0; + temp[1] = 0; + temp[2] = 0; + temp[3] = 0; + + var result = ps_tofixedarray(cur, limit, 4, temp, 0); + + if ( result < 0 ) + { + return FT_Common.FT_Err_Invalid_File_Format; + } + + __obj.xMin = FT_RoundFix(temp[0]); + __obj.yMin = FT_RoundFix(temp[1]); + __obj.xMax = FT_RoundFix(temp[2]); + __obj.yMax = FT_RoundFix(temp[3]); + + break; + + default: + /* an error occurred */ + return FT_Common.FT_Err_Invalid_File_Format; + } + } + + return 0; +} + +function ps_parser_load_field_table(parser, field, objects, max_objects, pflags) +{ + var elements = new Array(FT_Common.T1_MAX_TABLE_ELEMENTS); + for (var i = 0; i < FT_Common.T1_MAX_TABLE_ELEMENTS; i++) + elements[i] = new T1_TokenRec(); + + var fieldrec = create_dublicate_t1_field(field); + + fieldrec.type = FT_Common.T1_FIELD_TYPE_INTEGER; + if (field.type == FT_Common.T1_FIELD_TYPE_FIXED_ARRAY || field.type == FT_Common.T1_FIELD_TYPE_BBOX) + fieldrec.type = FT_Common.T1_FIELD_TYPE_FIXED; + + var num_elements = ps_parser_to_token_array(parser, elements, FT_Common.T1_MAX_TABLE_ELEMENTS); + if (num_elements < 0) + return FT_Common.FT_Err_Ignore; + + if (num_elements > field.array_max) + num_elements = field.array_max; + + var old_cursor = dublicate_pointer(parser.cursor); + var old_limit = parser.limit; + + /* we store the elements count if necessary; */ + /* we further assume that `count_offset' can't be zero */ + if (field.type != FT_Common.T1_FIELD_TYPE_BBOX && field.set_field_count != undefined) + { + fire_t1_field_count(objects[0], num_elements, field); + } + + /* we now load each element, adjusting the field.offset on each one */ + var token = 0; + for ( ; num_elements > 0; num_elements--, token++) + { + fieldrec.offset = token; + parser.cursor = dublicate_pointer(elements[token].start); + parser.limit = elements[token].limit; + ps_parser_load_field(parser, fieldrec, objects, max_objects, 0); + } + + parser.cursor = dublicate_pointer(old_cursor); + parser.limit = old_limit; + + return 0; +} + +function ps_parser_to_int(parser) +{ + ps_parser_skip_spaces(parser); + return PS_Conv_ToInt(parser.cursor, parser.limit); +} + +function ps_parser_to_bytes(parser, bytes, max_bytes, delimiters) +{ + ps_parser_skip_spaces(parser); + var cur = dublicate_pointer(parser.cursor); + + if (cur.pos >= parser.limit) + return 0; + + if (delimiters) + { + if (cur.data[cur.pos] != FT_Common.SYMBOL_CONST_MATH_1) + { + return {err: FT_Common.FT_Err_Invalid_File_Format, num_bytes: 0}; + } + + cur.pos++; + } + + var num_bytes = PS_Conv_ASCIIHexDecode(cur, parser.limit, bytes, max_bytes); + + if (delimiters) + { + if (cur.pos < parser.limit && cur.data[cur.pos] != FT_Common.SYMBOL_CONST_MATH_2) + { + return {err: FT_Common.FT_Err_Invalid_File_Format, num_bytes: num_bytes}; + } + + cur.pos++; + } + + parser.cursor.pos = cur.pos; + return {err: FT_Common.FT_Err_Ok, num_bytes: num_bytes}; +} + +function ps_parser_to_fixed(parser, power_ten) +{ + ps_parser_skip_spaces(parser); + return PS_Conv_ToFixed(parser.cursor, parser.limit, power_ten); +} + +function ps_parser_to_coord_array(parser, max_coords, coords) +{ + ps_parser_skip_spaces(parser); + return PS_Conv_ToFixed(parser.cursor, parser.limit, max_coords, coords); +} + +function ps_parser_to_fixed_array(parser, max_values, values, power_ten) +{ + ps_parser_skip_spaces(parser); + return ps_tofixedarray(parser.cursor, parser.limit, max_values, values, power_ten); +} + +function ps_parser_init(parser, base, limit, memory) +{ + parser.error = 0; + parser.base = dublicate_pointer(base); + parser.limit = limit; + parser.cursor = dublicate_pointer(base); + parser.memory = memory; + parser.funcs = ps_parser_funcs; +} + +function ps_parser_done(parser) +{ +} + +function t1_builder_init(builder, face, size, _glyph, hinting) +{ + var glyph = (null == _glyph) ? null : _glyph.root; + + builder.parse_state = FT_Common.T1_Parse_Start; + builder.load_points = 1; + + builder.face = face; + builder.glyph = glyph; + builder.memory = face.memory; + + if (glyph != null) + { + var loader = glyph.internal.loader; + + builder.loader = loader; + builder.base = loader.base.outline; + builder.current = loader.current.outline; + FT_GlyphLoader_Rewind(loader); + + builder.hints_globals = size.internal; + builder.hints_funcs = null; + + if (hinting) + builder.hints_funcs = glyph.internal.glyph_hints; + } + + builder.pos_x = 0; + builder.pos_y = 0; + + builder.left_bearing.x = 0; + builder.left_bearing.y = 0; + builder.advance.x = 0; + builder.advance.y = 0; + + builder.funcs = t1_builder_funcs; +} + +function t1_builder_done(builder) +{ + var glyph = builder.glyph; + + if (glyph != null) + EquatingOutline(glyph.outline, builder.base); +} + +function t1_builder_check_points(builder, count) +{ + return FT_GLYPHLOADER_CHECK_POINTS(builder.loader, count, 0); +} + +function t1_builder_add_point(builder, x, y, flag) +{ + var outline = builder.current; + var base = builder.base; + + if (builder.load_points) + { + var point = base.points[outline.points + outline.n_points]; + point.x = (FT_RoundFix(x) >> 16); + point.y = (FT_RoundFix(y) >> 16); + + base.tags[outline.tags + outline.n_points] = flag ? FT_Common.FT_CURVE_TAG_ON : FT_Common.FT_CURVE_TAG_CUBIC; + } + outline.n_points++; +} + +function t1_builder_add_point1(builder, x, y) +{ + var error = t1_builder_check_points(builder, 1); + if ( !error ) + t1_builder_add_point(builder, x, y, 1); + + return error; +} + +function t1_builder_add_contour(builder) +{ + var outline = builder.current; + + /* this might happen in invalid fonts */ + if (outline == null) + { + return FT_Common.FT_Err_Invalid_File_Format; + } + + if (builder.load_points == 0) + { + outline.n_contours++; + return FT_Common.FT_Err_Ok; + } + + var error = FT_GLYPHLOADER_CHECK_POINTS(builder.loader, 0, 1); + if (error == 0) + { + if (outline.n_contours > 0) + builder.base.contours[outline.contours + outline.n_contours - 1] = (outline.n_points - 1); + + outline.n_contours++; + } + + return error; +} + +function t1_builder_start_point(builder, x, y) +{ + var error = FT_Common.FT_Err_Invalid_File_Format; + + /* test whether we are building a new contour */ + if (builder.parse_state == FT_Common.T1_Parse_Have_Path) + error = FT_Common.FT_Err_Ok; + else + { + builder.parse_state = FT_Common.T1_Parse_Have_Path; + error = t1_builder_add_contour(builder); + if ( !error ) + error = t1_builder_add_point1(builder, x, y); + } + + return error; +} + +function t1_builder_close_contour(builder) +{ + var outline = builder.current; + + if (outline == null) + return; + + var base = builder.base; + var first = (outline.n_contours <= 1) ? 0 : base.contours[outline.contours + outline.n_contours - 2] + 1; + + /* We must not include the last point in the path if it */ + /* is located on the first point. */ + if (outline.n_points > 1) + { + var p1 = base.points[outline.points + first]; + var p2 = base.points[outline.points + outline.n_points - 1]; + + var control = base.tags[outline.tags + outline.n_points - 1]; + + /* `delete' last point only if it coincides with the first */ + /* point and it is not a control point (which can happen). */ + if (p1.x == p2.x && p1.y == p2.y) + if (control == FT_Common.FT_CURVE_TAG_ON) + outline.n_points--; + } + + if (outline.n_contours > 0) + { + /* Don't add contours only consisting of one point, i.e., */ + /* check whether the first and the last point is the same. */ + if (first == outline.n_points - 1) + { + outline.n_contours--; + outline.n_points--; + } + else + base.contours[outline.contours + outline.n_contours - 1] = (outline.n_points - 1); + } +} + +function t1_decrypt(buffer, length, seed) +{ + var mem = dublicate_pointer(buffer); + PS_Conv_EexecDecode(mem, mem.pos + length, mem, length, seed); +} + +/******************************************************************************/ +// t1decode +/******************************************************************************/ + +var t1_args_count = [ + 0, /* none */ + 0, /* endchar */ + 2, /* hsbw */ + 5, /* seac */ + 4, /* sbw */ + 0, /* closepath */ + 1, /* hlineto */ + 1, /* hmoveto */ + 4, /* hvcurveto */ + 2, /* rlineto */ + 2, /* rmoveto */ + 6, /* rrcurveto */ + 4, /* vhcurveto */ + 1, /* vlineto */ + 1, /* vmoveto */ + 0, /* dotsection */ + 2, /* hstem */ + 6, /* hstem3 */ + 2, /* vstem */ + 6, /* vstem3 */ + 2, /* div */ + -1, /* callothersubr */ + 1, /* callsubr */ + 0, /* pop */ + 0, /* return */ + 2, /* setcurrentpoint */ + 2 /* opcode 15 (undocumented and obsolete) */ +]; + +function t1_lookup_glyph_by_stdcharcode(decoder, charcode) +{ + /* check range of standard char code */ + if (charcode < 0 || charcode > 255) + return -1; + + var glyph_name = decoder.psnames.adobe_std_strings(decoder.psnames.adobe_std_encoding[charcode]); + + for (var n = 0; n < decoder.num_glyphs; n++) + { + var name = decoder.glyph_names[n]; + + if (name != null && name == glyph_name) + return n; + } + + return -1; +} + +function t1operator_seac(decoder, asb, adx, ady, bchar, achar) +{ + var bchar_index, achar_index; + + if (decoder.seac) + return FT_Common.FT_Err_Syntax_Error; + + var error = 0; + var face = decoder.builder.face; + + /* seac weirdness */ + adx += decoder.builder.left_bearing.x; + + /* `glyph_names' is set to 0 for CID fonts which do not */ + /* include an encoding. How can we deal with these? */ + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (decoder.glyph_names == null && null == face.internal.incremental_interface) + return FT_Common.FT_Err_Syntax_Error; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (face.internal.incremental_interface != null) + { + /* the caller must handle the font encoding also */ + bchar_index = bchar; + achar_index = achar; + } + else// #endif + { + bchar_index = t1_lookup_glyph_by_stdcharcode(decoder, bchar); + achar_index = t1_lookup_glyph_by_stdcharcode(decoder, achar); + } + + if (bchar_index < 0 || achar_index < 0) + return FT_Common.FT_Err_Syntax_Error; + + /* if we are trying to load a composite glyph, do not load the */ + /* accent character and return the array of subglyphs. */ + if (decoder.builder.no_recurse) + { + var glyph = decoder.builder.glyph; + var loader = glyph.internal.loader; + + /* reallocate subglyph array if necessary */ + error = FT_GlyphLoader_CheckSubGlyphs(loader, 2); + if (error != 0) + return error; + + var subg = loader.current.subglyphs[0]; + + /* subglyph 0 = base character */ + subg.index = bchar_index; + subg.flags = FT_Common.FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | FT_Common.FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg.arg1 = 0; + subg.arg2 = 0; + + subg = loader.current.subglyphs[1]; + + /* subglyph 1 = accent character */ + subg.index = achar_index; + subg.flags = FT_Common.FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg.arg1 = FT_RoundFix(adx - asb) >> 16; + subg.arg2 = FT_RoundFix(ady) >> 16; + + /* set up remaining glyph fields */ + glyph.num_subglyphs = 2; + glyph.subglyphs = loader.base.subglyphs; + glyph.format = FT_Common.FT_GLYPH_FORMAT_COMPOSITE; + + loader.current.num_subglyphs = 2; + return error; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + + FT_GlyphLoader_Prepare(decoder.builder.loader); /* prepare loader */ + + /* the seac operator must not be nested */ + decoder.seac = 1; + error = t1_decoder_parse_glyph(decoder, bchar_index); + decoder.seac = 0; + if (error != 0) + return error; + + /* save the left bearing and width of the base character */ + /* as they will be erased by the next load. */ + + var left_bearing = dublicate_vector(decoder.builder.left_bearing); + var advance = dublicate_vector(decoder.builder.advance); + + decoder.builder.left_bearing.x = 0; + decoder.builder.left_bearing.y = 0; + + decoder.builder.pos_x = adx - asb; + decoder.builder.pos_y = ady; + + /* Now load `achar' on top of */ + /* the base outline */ + + /* the seac operator must not be nested */ + decoder.seac = 1; + error = t1_decoder_parse_glyph(decoder, achar_index); + decoder.seac = 0; + if (error != 0) + return error; + + /* restore the left side bearing and */ + /* advance width of the base character */ + + decoder.builder.left_bearing = left_bearing; + decoder.builder.advance = advance; + + decoder.builder.pos_x = 0; + decoder.builder.pos_y = 0; + + return error; +} + +function t1_decoder_parse_charstrings(decoder, charstring_base, charstring_len) +{ + var builder = decoder.builder; + var x, y, orig_x, orig_y; + var known_othersubr_result_cnt = 0; + var unknown_othersubr_result_cnt = 0; + var large_int = 0; + + /* compute random seed from stack address of parameter */ + var seed = parseInt(Math.random() * 0xFFFF); + if (seed == 0) + seed = 0x7384; + + /* First of all, initialize the decoder */ + decoder.top = 0; + decoder.zone = 0; + var zone = 0; + var zones = decoder.zones; + + builder.parse_state = FT_Common.T1_Parse_Start; + + var hinter = builder.hints_funcs; + + /* a font that reads BuildCharArray without setting */ + /* its values first is buggy, but ... */ + if (decoder.buildchar != null && decoder.len_buildchar > 0) + { + for (var i = 0; i < decoder.len_buildchar; i++) + { + decoder.buildchar[i] = 0; + } + } + + zones[zone].base = dublicate_pointer(charstring_base); + zones[zone].limit = charstring_base.pos + charstring_len; + var limit = zones[zone].limit; + + zones[zone].cursor = 0; + var ip = dublicate_pointer(zones[zone].base); + + var error = 0; + + x = orig_x = builder.pos_x; + y = orig_y = builder.pos_y; + + /* begin hints recording session, if any */ + if (hinter != null) + hinter.open(hinter.hints); + + large_int = 0; + + /* now, execute loop */ + while (ip.pos < limit) + { + var tops = decoder.stack; + var top = decoder.top; + var op = FT_Common.op_none; + var value = 0; + + /*********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + /* */ + /* first of all, decompress operator or value */ + var _oper = ip.data[ip.pos]; + ip.pos++; + switch (_oper) + { + case 1: + op = FT_Common.op_hstem; + break; + + case 3: + op = FT_Common.op_vstem; + break; + case 4: + op = FT_Common.op_vmoveto; + break; + case 5: + op = FT_Common.op_rlineto; + break; + case 6: + op = FT_Common.op_hlineto; + break; + case 7: + op = FT_Common.op_vlineto; + break; + case 8: + op = FT_Common.op_rrcurveto; + break; + case 9: + op = FT_Common.op_closepath; + break; + case 10: + op = FT_Common.op_callsubr; + break; + case 11: + op = FT_Common.op_return; + break; + + case 13: + op = FT_Common.op_hsbw; + break; + case 14: + op = FT_Common.op_endchar; + break; + + case 15: /* undocumented, obsolete operator */ + op = FT_Common.op_unknown15; + break; + + case 21: + op = FT_Common.op_rmoveto; + break; + case 22: + op = FT_Common.op_hmoveto; + break; + + case 30: + op = FT_Common.op_vhcurveto; + break; + case 31: + op = FT_Common.op_hvcurveto; + break; + + case 12: + if (ip.pos > limit) + return FT_Common.FT_Err_Syntax_Error; + + var _oper2 = ip.data[ip.pos]; + ip.pos++; + switch (_oper2) + { + case 0: + op = FT_Common.op_dotsection; + break; + case 1: + op = FT_Common.op_vstem3; + break; + case 2: + op = FT_Common.op_hstem3; + break; + case 6: + op = FT_Common.op_seac; + break; + case 7: + op = FT_Common.op_sbw; + break; + case 12: + op = FT_Common.op_div; + break; + case 16: + op = FT_Common.op_callothersubr; + break; + case 17: + op = FT_Common.op_pop; + break; + case 33: + op = FT_Common.op_setcurrentpoint; + break; + + default: + return FT_Common.FT_Err_Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if (ip.pos + 4 > limit) + { + return FT_Common.FT_Err_Syntax_Error; + } + + value = ((ip.data[ip.pos] << 24) | (ip.data[ip.pos + 1] << 16) | (ip.data[ip.pos + 2] << 8) | (ip.data[ip.pos + 3])); + ip.pos += 4; + + /* According to the specification, values > 32000 or < -32000 must */ + /* be followed by a `div' operator to make the result be in the */ + /* range [-32000;32000]. We expect that the second argument of */ + /* `div' is not a large number. Additionally, we don't handle */ + /* stuff like `<large1> <large2> <num> div <num> div' or */ + /* <large1> <large2> <num> div div'. This is probably not allowed */ + /* anyway. */ + if (value > 32000 || value < -32000) + { + if (large_int) + { + } + else + large_int = 1; + } + else + { + if (!large_int) + value <<= 16; + } + + break; + + default: + if (ip.data[ip.pos - 1] >= 32) + { + if (ip.data[ip.pos - 1] < 247) + value = ip.data[ip.pos - 1] - 139; + else + { + ip.pos++; + if (ip.pos > limit) + { + return FT_Common.FT_Err_Syntax_Error; + } + + if (ip.data[ip.pos - 2] < 251) + value = ((ip.data[ip.pos - 2] - 247) << 8) + ip.data[ip.pos - 1] + 108; + else + value = -(((ip.data[ip.pos - 2] - 251) << 8) + ip.data[ip.pos - 1] + 108); + } + + if (!large_int) + value <<= 16; + } + else + { + return FT_Common.FT_Err_Syntax_Error; + } + } + + if (unknown_othersubr_result_cnt > 0) + { + switch (op) + { + case FT_Common.op_callsubr: + case FT_Common.op_return: + case FT_Common.op_none: + case FT_Common.op_pop: + break; + + default: + /* all operands have been transferred by previous pops */ + unknown_othersubr_result_cnt = 0; + break; + } + } + + if ( large_int && !(op == FT_Common.op_none || op == FT_Common.op_div)) + { + large_int = 0; + } + + /*********************************************************************/ + /* */ + /* Push value on stack, or process operator */ + /* */ + /* */ + if (op == FT_Common.op_none) + { + if (top >= FT_Common.T1_MAX_CHARSTRINGS_OPERANDS) + { + return FT_Common.FT_Err_Syntax_Error; + } + + tops[top] = value; + top++; + decoder.top = top; + } + else if ( op == FT_Common.op_callothersubr ) /* callothersubr */ + { + if (top < 2) + return FT_Common.FT_Err_Stack_Overflow; + + top -= 2; + + var subr_no = (tops[top + 1] >> 16) & 0xFFFF; + var arg_cnt = (tops[top] >> 16) & 0xFFFF; + + /***********************************************************/ + /* */ + /* remove all operands to callothersubr from the stack */ + /* */ + /* for handled othersubrs, where we know the number of */ + /* arguments, we increase the stack by the value of */ + /* known_othersubr_result_cnt */ + /* */ + /* for unhandled othersubrs the following pops adjust the */ + /* stack pointer as necessary */ + + if (arg_cnt > top) + return FT_Common.FT_Err_Stack_Overflow; + + top -= arg_cnt; + + known_othersubr_result_cnt = 0; + unknown_othersubr_result_cnt = 0; + + /* XXX TODO: The checks to `arg_count == <whatever>' */ + /* might not be correct; an othersubr expects a certain */ + /* number of operands on the PostScript stack (as opposed */ + /* to the T1 stack) but it doesn't have to put them there */ + /* by itself; previous othersubrs might have left the */ + /* operands there if they were not followed by an */ + /* appropriate number of pops */ + /* */ + /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */ + /* accept a font that contains charstrings like */ + /* */ + /* 100 200 2 20 callothersubr */ + /* 300 1 20 callothersubr pop */ + /* */ + /* Perhaps this is the reason why BuildCharArray exists. */ + + switch (subr_no) + { + case 0: /* end flex feature */ + if (arg_cnt != 3) + return FT_Common.FT_Err_Syntax_Error; + + if (decoder.flex_state == 0 || decoder.num_flex_vectors != 7) + { + return FT_Common.FT_Err_Syntax_Error; + } + + /* the two `results' are popped by the following setcurrentpoint */ + tops[top] = x; + tops[top + 1] = y; + known_othersubr_result_cnt = 2; + break; + + case 1: /* start flex feature */ + if (arg_cnt != 0) + return FT_Common.FT_Err_Syntax_Error; + + decoder.flex_state = 1; + decoder.num_flex_vectors = 0; + + error = t1_builder_start_point(builder, x, y); + if (error != FT_Common.FT_Err_Ok) + return error; + + error = t1_builder_check_points(builder, 6); + if (error != FT_Common.FT_Err_Ok) + return error; + + break; + + case 2: /* add flex vectors */ + if (arg_cnt != 0) + return FT_Common.FT_Err_Syntax_Error; + + if (decoder.flex_state == 0) + { + return FT_Common.FT_Err_Syntax_Error; + } + + /* note that we should not add a point for index 0; */ + /* this will move our current position to the flex */ + /* point without adding any point to the outline */ + var idx = decoder.num_flex_vectors; + decoder.num_flex_vectors++; + if (idx > 0 && idx < 7) + t1_builder_add_point(builder, x, y, (idx == 3 || idx == 6) ? 1 : 0); + + break; + + case 3: /* change hints */ + if (arg_cnt != 1) + return FT_Common.FT_Err_Syntax_Error; + + known_othersubr_result_cnt = 1; + + if (hinter) + hinter.reset(hinter.hints, builder.current.n_points); + break; + + case 12: + case 13: + /* counter control hints, clear stack */ + top = 0; + break; + + case 14: + case 15: + case 16: + case 17: + case 18: /* multiple masters */ + { + var blend = decoder.blend; + + if ( !blend ) + { + return FT_Common.FT_Err_Syntax_Error; + } + + var num_points = subr_no - 13; + if (subr_no == 18) + num_points++; + if (arg_cnt != (num_points * blend.num_designs)) + { + return FT_Common.FT_Err_Syntax_Error; + } + + /* We want to compute */ + /* */ + /* a0*w0 + a1*w1 + ... + ak*wk */ + /* */ + /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ + /* */ + /* However, given that w0 + w1 + ... + wk == 1, we can */ + /* rewrite it easily as */ + /* */ + /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ + /* */ + /* where k == num_designs-1. */ + /* */ + /* I guess that's why it's written in this `compact' */ + /* form. */ + /* */ + var delta = top + num_points; + var values = top; + for (var nn = 0; nn < num_points; nn++) + { + var tmp = tops[values]; + + for (var mm = 1; mm < blend.num_designs; mm++) + tmp += FT_MulFix(tops[delta++], blend.weight_vector[mm]); + + tops[values++] = tmp; + } + + known_othersubr_result_cnt = num_points; + break; + } + + case 19: + /* <idx> 1 19 callothersubr */ + /* => replace elements starting from index cvi( <idx> ) */ + /* of BuildCharArray with WeightVector */ + var blend = decoder.blend; + + if (arg_cnt != 1 || blend == null) + return FT_Common.FT_Err_Syntax_Error; + + var idx = (tops[top] >> 16) & 0xFFFF; + + if (idx < 0 || (idx + blend.num_designs) > decoder.len_buildchar) + return FT_Common.FT_Err_Syntax_Error; + + for (var ii = 0; ii < blend.num_designs; ii++) + decoder.buildchar[idx + ii] = blend.weight_vector[ii]; + + break; + + case 20: + /* <arg1> <arg2> 2 20 callothersubr pop */ + /* ==> push <arg1> + <arg2> onto T1 stack */ + if (arg_cnt != 2) + return FT_Common.FT_Err_Syntax_Error; + + tops[top] += tops[top + 1]; /* XXX (over|under)flow */ + + known_othersubr_result_cnt = 1; + break; + + case 21: + /* <arg1> <arg2> 2 21 callothersubr pop */ + /* ==> push <arg1> - <arg2> onto T1 stack */ + if (arg_cnt != 2) + return FT_Common.FT_Err_Syntax_Error; + + tops[top] -= tops[top + 1]; /* XXX (over|under)flow */ + + known_othersubr_result_cnt = 1; + break; + + case 22: + /* <arg1> <arg2> 2 22 callothersubr pop */ + /* ==> push <arg1> * <arg2> onto T1 stack */ + if (arg_cnt != 2) + return FT_Common.FT_Err_Syntax_Error; + + tops[top] = FT_MulFix(tops[top], tops[top + 1]); + + known_othersubr_result_cnt = 1; + break; + + case 23: + /* <arg1> <arg2> 2 23 callothersubr pop */ + /* ==> push <arg1> / <arg2> onto T1 stack */ + if (arg_cnt != 2 || tops[top + 1] == 0) + return FT_Common.FT_Err_Syntax_Error; + + tops[top] = FT_DivFix(tops[top], tops[top + 1]); + + known_othersubr_result_cnt = 1; + break; + + case 24: + /* <val> <idx> 2 24 callothersubr */ + /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ + var blend = decoder.blend; + + if (arg_cnt != 2 || blend == null) + return FT_Common.FT_Err_Syntax_Error; + + var idx = (tops[top + 1] >> 16) & 0xFFFF; + + if (idx < 0 || idx >= decoder.len_buildchar) + return FT_Common.FT_Err_Syntax_Error; + + decoder.buildchar[idx] = tops[top]; + + break; + + case 25: + /* <idx> 1 25 callothersubr pop */ + /* ==> push BuildCharArray[cvi( idx )] */ + /* onto T1 stack */ + var blend = decoder.blend; + + if (arg_cnt != 1 || blend == null) + return FT_Common.FT_Err_Syntax_Error; + + idx = (tops[top] >> 16) & 0xFFFF; + + if (idx < 0 || idx >= decoder.len_buildchar) + return FT_Common.FT_Err_Syntax_Error; + + tops[top] = decoder.buildchar[idx]; + + known_othersubr_result_cnt = 1; + break; + + case 27: + /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ + /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ + /* otherwise push <res2> */ + if (arg_cnt != 4) + return FT_Common.FT_Err_Syntax_Error; + + if (tops[top + 2] > tops[top + 3]) + tops[top] = tops[top + 1]; + + known_othersubr_result_cnt = 1; + break; + + case 28: + /* 0 28 callothersubr pop */ + /* => push random value from interval [0, 1) onto stack */ + if (arg_cnt != 0) + return FT_Common.FT_Err_Syntax_Error; + + var Rand = seed; + if (Rand >= 0x8000) + Rand++; + + tops[top] = Rand; + + seed = FT_MulFix(seed, 0x10000 - seed); + if (seed == 0) + seed += 0x2873; + + known_othersubr_result_cnt = 1; + break; + + default: + if (arg_cnt >= 0 && subr_no >= 0) + { + unknown_othersubr_result_cnt = arg_cnt; + break; + } + /* fall through */ + + return FT_Common.FT_Err_Syntax_Error; + } + + top += known_othersubr_result_cnt; + decoder.top = top; + } + else /* general operator */ + { + var num_args = t1_args_count[op]; + + if (top < num_args) + return FT_Common.FT_Err_Stack_Overflow; + + /* XXX Operators usually take their operands from the */ + /* bottom of the stack, i.e., the operands are */ + /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */ + /* only div, callsubr, and callothersubr are different. */ + /* In practice it doesn't matter (?). */ + + top -= num_args; + + switch (op) + { + case FT_Common.op_endchar: + + t1_builder_close_contour(builder); + + /* close hints recording session */ + if (hinter != null) + { + if (hinter.close(hinter.hints, builder.current.n_points)) + return FT_Common.FT_Err_Syntax_Error; + + /* apply hints to the loaded glyph outline now */ + hinter.apply(hinter.hints, builder.current, builder.hints_globals, decoder.hint_mode); + } + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add(builder.loader); + + /* the compiler should optimize away this empty loop but ... */ + /* return now! */ + return 0; + + case FT_Common.op_hsbw: + builder.parse_state = FT_Common.T1_Parse_Have_Width; + + builder.left_bearing.x += tops[top]; + builder.advance.x = tops[top + 1]; + builder.advance.y = 0; + + orig_x = x = builder.pos_x + tops[top]; + orig_y = y = builder.pos_y; + + /* the `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it; so exit immediately */ + if (builder.metrics_only) + return 0; + + break; + + case FT_Common.op_seac: + return t1operator_seac(decoder, tops[top], tops[top + 1], tops[top + 2], + (tops[top + 3] >> 16) & 0xFFFF, (tops[top + 4] >> 16) & 0xFFFF); + + case FT_Common.op_sbw: + builder.parse_state = FT_Common.T1_Parse_Have_Width; + + builder.left_bearing.x += tops[top]; + builder.left_bearing.y += tops[top + 1]; + builder.advance.x = tops[top + 2]; + builder.advance.y = tops[top + 3]; + + x = builder.pos_x + tops[top]; + y = builder.pos_y + tops[top + 1]; + + /* the `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it; so exit immediately */ + if (builder.metrics_only) + return 0; + + break; + + case FT_Common.op_closepath: + /* if there is no path, `closepath' is a no-op */ + if (builder.parse_state == FT_Common.T1_Parse_Have_Path || builder.parse_state == FT_Common.T1_Parse_Have_Moveto) + t1_builder_close_contour(builder); + + builder.parse_state = FT_Common.T1_Parse_Have_Width; + break; + + case FT_Common.op_hlineto: + + error = t1_builder_start_point(builder, x, y); + if (error != 0) + return error; + + x += tops[top]; + error = t1_builder_add_point1(builder, x, y); + if (error != 0) + return error; + + break; + + case FT_Common.op_hmoveto: + x += tops[top]; + if (decoder.flex_state == 0) + { + if (builder.parse_state == FT_Common.T1_Parse_Start) + return FT_Common.FT_Err_Syntax_Error; + builder.parse_state = FT_Common.T1_Parse_Have_Moveto; + } + break; + + case FT_Common.op_hvcurveto: + + error = t1_builder_start_point(builder, x, y); + if (error != 0) + return error; + error = t1_builder_check_points(builder, 3); + if (error != 0) + return error; + + x += tops[top]; + t1_builder_add_point(builder, x, y, 0); + x += tops[top + 1]; + y += tops[top + 2]; + t1_builder_add_point(builder, x, y, 0); + y += tops[top + 3]; + t1_builder_add_point(builder, x, y, 1); + break; + + case FT_Common.op_rlineto: + error = t1_builder_start_point(builder, x, y); + if (error != 0) + return error; + + x += tops[top]; + y += tops[top + 1]; + + error = t1_builder_add_point1(builder, x, y); + if (error != 0) + return error; + + break; + + case FT_Common.op_rmoveto: + x += tops[top]; + y += tops[top + 1]; + if (decoder.flex_state == 0) + { + if (builder.parse_state == FT_Common.T1_Parse_Start) + return FT_Common.FT_Err_Syntax_Error; + builder.parse_state = FT_Common.T1_Parse_Have_Moveto; + } + break; + + case FT_Common.op_rrcurveto: + + error = t1_builder_start_point(builder, x, y); + if (error != 0) + return error; + error = t1_builder_check_points(builder, 3); + if (error != 0) + return error; + + x += tops[top]; + y += tops[top + 1]; + t1_builder_add_point(builder, x, y, 0); + + x += tops[top + 2]; + y += tops[top + 3]; + t1_builder_add_point(builder, x, y, 0); + + x += tops[top + 4]; + y += tops[top + 5]; + t1_builder_add_point(builder, x, y, 1); + break; + + case FT_Common.op_vhcurveto: + error = t1_builder_start_point(builder, x, y); + if (error != 0) + return error; + error = t1_builder_check_points(builder, 3); + if (error != 0) + return error; + + y += tops[top]; + t1_builder_add_point(builder, x, y, 0); + x += tops[top + 1]; + y += tops[top + 2]; + t1_builder_add_point(builder, x, y, 0); + x += tops[top + 3]; + t1_builder_add_point(builder, x, y, 1); + break; + + case FT_Common.op_vlineto: + error = t1_builder_start_point(builder, x, y); + if (error != 0) + return error; + + y += tops[top]; + error = t1_builder_add_point1(builder, x, y); + if (error != 0) + return error; + break; + + case FT_Common.op_vmoveto: + y += tops[top]; + if (decoder.flex_state == 0) + { + if (builder.parse_state == FT_Common.T1_Parse_Start) + return FT_Common.FT_Err_Syntax_Error; + builder.parse_state = FT_Common.T1_Parse_Have_Moveto; + } + break; + + case FT_Common.op_div: + /* if `large_int' is set, we divide unscaled numbers; */ + /* otherwise, we divide numbers in 16.16 format -- */ + /* in both cases, it is the same operation */ + tops[top] = FT_DivFix(tops[top], tops[top + 1]); + ++top; + + large_int = 0; + break; + + case FT_Common.op_callsubr: + { + var idx = (tops[top] >> 16) & 0xFFFF; + if (idx < 0 || idx >= decoder.num_subrs) + return FT_Common.FT_Err_Syntax_Error; + + if (zone >= FT_Common.T1_MAX_SUBRS_CALLS) + return FT_Common.FT_Err_Syntax_Error; + + zones[zone].cursor = dublicate_pointer(ip); /* save current instruction pointer */ + zone++; + + /* The Type 1 driver stores subroutines without the seed bytes. */ + /* The CID driver stores subroutines with seed bytes. This */ + /* case is taken care of when decoder->subrs_len == 0. */ + zones[zone].base = dublicate_pointer(decoder.subrs[idx]); + + if (decoder.subrs_len != 0) + zones[zone].limit = zones[zone].base.pos + decoder.subrs_len[idx]; + else + { + /* We are using subroutines from a CID font. We must adjust */ + /* for the seed bytes. */ + zones[zone].base.pos += (decoder.lenIV >= 0 ? decoder.lenIV : 0); + zones[zone].limit = decoder.subrs[idx + 1].pos; + } + + zones[zone].cursor = dublicate_pointer(zones[zone].base); + + if (zones[zone].base == null) + return FT_Common.FT_Err_Syntax_Error; + + decoder.zone = zone; + ip = dublicate_pointer(zones[zone].base); + limit = zones[zone].limit; + break; + } + + case FT_Common.op_pop: + + if (known_othersubr_result_cnt > 0) + { + known_othersubr_result_cnt--; + /* ignore, we pushed the operands ourselves */ + break; + } + + if (unknown_othersubr_result_cnt == 0) + return FT_Common.FT_Err_Syntax_Error; + + unknown_othersubr_result_cnt--; + top++; /* `push' the operand to callothersubr onto the stack */ + break; + + case FT_Common.op_return: + + if (zone <= 0) + return FT_Common.FT_Err_Syntax_Error; + + zone--; + ip = dublicate_pointer(zones[zone].cursor); + limit = zones[zone].limit; + decoder.zone = zone; + break; + + case FT_Common.op_dotsection: + break; + + case FT_Common.op_hstem: + /* record horizontal hint */ + if (hinter != null) + { + /* tops[0] += builder->left_bearing.y; */ + hinter.stem(hinter.hints, 1, tops, top); + } + break; + + case FT_Common.op_hstem3: + /* record horizontal counter-controlled hints */ + if (hinter != null) + hinter.stem3(hinter.hints, 1, tops, top); + break; + + case FT_Common.op_vstem: + /* record vertical hint */ + if (hinter != null) + { + tops[top] += orig_x; + hinter.stem(hinter.hints, 0, tops, top); + } + break; + + case FT_Common.op_vstem3: + /* record vertical counter-controlled hints */ + if (hinter != null) + { + tops[top] += orig_x; + tops[top + 2] += orig_x; + tops[top + 4] += orig_x; + hinter.stem3(hinter.hints, 0, tops, top); + } + break; + + case FT_Common.op_setcurrentpoint: + /* From the T1 specification, section 6.4: */ + /* */ + /* The setcurrentpoint command is used only in */ + /* conjunction with results from OtherSubrs procedures. */ + + /* known_othersubr_result_cnt != 0 is already handled */ + /* above. */ + + /* Note, however, that both Ghostscript and Adobe */ + /* Distiller handle this situation by silently ignoring */ + /* the inappropriate `setcurrentpoint' instruction. So */ + /* we do the same. */ + x = tops[top]; + y = tops[top + 1]; + decoder.flex_state = 0; + break; + + case FT_Common.op_unknown15: + /* nothing to do except to pop the two arguments */ + break; + + default: + return FT_Common.FT_Err_Syntax_Error; + } + + /* XXX Operators usually clear the operand stack; */ + /* only div, callsubr, callothersubr, pop, and */ + /* return are different. */ + /* In practice it doesn't matter (?). */ + + decoder.top = top; + + } /* general operator processing */ + + } /* while ip < limit */ + + return error; +} + +function t1_decoder_parse_glyph(decoder, glyph) +{ + return decoder.parse_callback(decoder, glyph); +} + +function t1_decoder_init(decoder, face, size, slot, glyph_names, blend, hinting, hint_mode, parse_callback) +{ + decoder.clear(); + + var psnames = FT_FACE_FIND_GLOBAL_SERVICE(face, FT_SERVICE_ID_POSTSCRIPT_CMAPS); + if (psnames == null) + return FT_Common.FT_Err_Unimplemented_Feature; + + decoder.psnames = psnames; + + t1_builder_init(decoder.builder, face, size, slot, hinting); + + /* decoder->buildchar and decoder->len_buildchar have to be */ + /* initialized by the caller since we cannot know the length */ + /* of the BuildCharArray */ + decoder.num_glyphs = face.num_glyphs; + decoder.glyph_names = glyph_names; + decoder.hint_mode = hint_mode; + decoder.blend = blend; + decoder.parse_callback = parse_callback; + + decoder.funcs = t1_decoder_funcs; + + return 0; +} + +function t1_decoder_done(decoder) +{ + t1_builder_done(decoder.builder); +} + + +/******************************************************************************/ +// psaux +/******************************************************************************/ +function PS_Table_FuncsRec(_init, _done, _add, _release) +{ + this.init = _init; + this.done = _done; + this.add = _add; + this.release = _release; +} + +function PS_TableRec() +{ + this.block = null; + this.cursor = 0; + this.capacity = 0; + this.init = 0; + + this.max_elems = 0; + this.num_elems = 0; + this.elements = null; + this.lengths = null; + + this.memory = null; + this.funcs = new PS_Table_FuncsRec(null, null, null, null); + + this.clear = function() + { + this.block = null; + this.cursor = 0; + this.capacity = 0; + this.init = 0; + + this.max_elems = 0; + this.num_elems = 0; + this.elements = null; + this.lengths = null; + + this.memory = null; + this.funcs = new PS_Table_FuncsRec(null, null, null, null); + } +} + +function T1_TokenRec() +{ + this.start = new CPointer(); + this.limit = 0; + this.type = 0; +} + +function T1_FieldRec() +{ + this.ident = ""; + this.location = 0; + this.type = 0; + this.reader = null; + this.offset = 0; // у Ð½Ð°Ñ Ñто проÑто Ð¸Ð½Ð´ÐµÐºÑ Ñ‡Ð»ÐµÐ½Ð° клаÑÑа. Рне Ñдвиг в памÑти + this.size = 0; + this.array_max = 0; + + this.count_offset = 0; + this.dict = 0; + + this.set_field = null; + this.set_field_count = null; +} + +function create_dublicate_t1_field(_field) +{ + var ret = new T1_FieldRec(); + + ret.ident = _field.ident; + ret.location = _field.location; + ret.type = _field.type; + ret.reader = _field.reader; + ret.offset = _field.offset; // у Ð½Ð°Ñ Ñто проÑто Ð¸Ð½Ð´ÐµÐºÑ Ð² ÐœÐССИВЕ (Ñ‚.е. Ð´Ð»Ñ Ð½Ðµ маÑÑива Ñто поле не нужно) + ret.size = _field.size; // не пользуем (на будущее оÑтавим) + ret.array_max = _field.array_max; + + ret.count_offset = _field.count_offset; + ret.dict = _field.dict; + + ret.set_field = _field.set_field; + ret.set_field_count = _field.set_field_count; + + return ret; +} + +function fire_t1_field(obj, val, f) +{ + f.set_field(obj, val, f); +} +function fire_t1_field_count(obj, val, f) +{ + f.set_field_count(obj, val, f); +} + +function create_t1_field(_ident, _location, _type, _reader, _offset, _size, _array_max, _count_offset, _dict, func_set_field, func_set_field_count) +{ + var ret = new T1_FieldRec(); + ret.ident = _ident; + ret.location = _location; + ret.type = _type; + ret.reader = _reader; + ret.offset = _offset; + ret.size = _size; + ret.array_max = _array_max; + ret.count_offset = _count_offset; + ret.dict = _dict; + + ret.set_field = func_set_field; + ret.set_field_count = func_set_field_count; + + return ret; +} +function create_t1_field2(_ident, _location, _type, func_set_field, func_set_field_count) +{ + var ret = new T1_FieldRec(); + ret.ident = _ident; + ret.location = _location; + ret.type = _type; + + ret.set_field = func_set_field; + ret.set_field_count = func_set_field_count; + + return ret; +} +function create_t1_field4(_ident, _location, _type, _dict, func_set_field, func_set_field_count) +{ + var ret = new T1_FieldRec(); + ret.ident = _ident; + ret.location = _location; + ret.type = _type; + ret.dict = _dict; + + ret.set_field = func_set_field; + ret.set_field_count = func_set_field_count; + + return ret; +} +function create_t1_field3(_ident, _location, _type, _max, func_set_field, func_set_field_count) +{ + var ret = new T1_FieldRec(); + ret.ident = _ident; + ret.location = _location; + ret.type = _type; + ret.array_max = _max; + + ret.set_field = func_set_field; + ret.set_field_count = func_set_field_count; + + return ret; +} +function create_t1_field5(_ident, _location, _type, _max, _dict, func_set_field, func_set_field_count) +{ + var ret = new T1_FieldRec(); + ret.ident = _ident; + ret.location = _location; + ret.type = _type; + ret.array_max = _max; + ret.dict = _dict; + + ret.set_field = func_set_field; + ret.set_field_count = func_set_field_count; + + return ret; +} + +function PS_Parser_FuncsRec(_init,_done,_skip_spaces,_skip_PS_token,_to_int,_to_fixed,_to_bytes,_to_coord_array,_to_fixed_array, + _to_token,_to_token_array,_load_field,_load_field_table) +{ + this.init = _init; + this.done = _done; + + this.skip_spaces = _skip_spaces; + this.skip_PS_token = _skip_PS_token; + + this.to_int = _to_int; + this.to_fixed = _to_fixed; + this.to_bytes = _to_bytes; + this.to_coord_array = _to_coord_array; + this.to_fixed_array = _to_fixed_array; + this.to_token = _to_token; + this.to_token_array = _to_token_array; + this.load_field = _load_field; + this.load_field_table = _load_field_table; +} + +function T1_Builder_FuncsRec(_init,_done,_check_points,_add_point,_add_point1,_add_contour,_start_point,_close_contour) +{ + this.init = _init; + this.done = _done; + + this.check_points = _check_points; + this.add_point = _add_point; + this.add_point1 = _add_point1; + this.add_contour = _add_contour; + this.start_point = _start_point; + this.close_contour = _close_contour; +} + +function PS_ParserRec() +{ + this.cursor = 0; + this.base = null; + this.limit = 0; + this.error = 0; + this.memory = null; + + this.funcs = null; + + this.clear = function() + { + this.cursor = 0; + this.base = null; + this.limit = 0; + this.error = 0; + this.memory = null; + + this.funcs = null; + } +} + +function T1_BuilderRec() +{ + this.memory = null; + this.face = null; + this.glyph = null; + this.loader = null; + this.base = null; + this.current = null; + + this.pos_x = 0; + this.pos_y = 0; + + this.left_bearing = new FT_Vector(); + this.advance = new FT_Vector(); + + this.bbox = new FT_BBox(); + this.parse_state = 0; + this.load_points = 0; + this.no_recurse = 0; + + this.metrics_only = 0; + + this.hints_funcs = null; + this.hints_globals = null; + + this.funcs = null; + + this.clear = function() + { + this.memory = null; + this.face = null; + this.glyph = null; + this.loader = null; + this.base = null; + this.current = null; + + this.pos_x = 0; + this.pos_y = 0; + + this.left_bearing.x = 0; + this.left_bearing.y = 0; + this.advance.x = 0; + this.advance.y = 0; + + this.bbox.xMin = 0; + this.bbox.yMin = 0; + this.bbox.xMax = 0; + this.bbox.yMax = 0; + + this.parse_state = 0; + this.load_points = 0; + this.no_recurse = 0; + + this.metrics_only = 0; + + this.hints_funcs = null; + this.hints_globals = null; + + this.funcs = null; + } +} + +function T1_Decoder_ZoneRec() +{ + this.cursor = 0; + this.base = null; + this.limit = 0; +} + +function T1_Decoder_FuncsRec(_init, _done, _parse_charstrings) +{ + this.init = _init; + this.done = _done; + this.parse_charstrings = _parse_charstrings; +} + +function T1_DecoderRec() +{ + this.builder = new T1_BuilderRec(); + + this.stack = CreateIntArray(FT_Common.T1_MAX_CHARSTRINGS_OPERANDS); + this.top = 0; + + this.zones = new Array(FT_Common.T1_MAX_SUBRS_CALLS + 1); + for (var i = 0; i <= FT_Common.T1_MAX_SUBRS_CALLS; i++) + this.zones[i] = new T1_Decoder_ZoneRec(); + + this.zone = 0; + + this.psnames = null; + this.num_glyphs = 0; + this.glyph_names = null; + + this.lenIV = 0; + this.num_subrs = 0; + this.subrs = null; + this.subrs_len = null; + + this.font_matrix = new FT_Matrix(); + this.font_offset = new FT_Vector(); + + this.flex_state = 0; + this.num_flex_vectors = 0; + this.flex_vectors = new Array(7); + for (var i = 0; i < 7; i++) + this.flex_vectors[i] = new FT_Vector(); + + this.blend = null; + + this.hint_mode = 0; + + this.parse_callback = null; + this.funcs = null; + + this.buildchar = null; + this.len_buildchar = 0; + + this.seac = 0; + + this.clear = function() + { + this.builder.clear(); + + for (var i = 0; i < FT_Common.T1_MAX_CHARSTRINGS_OPERANDS; i++) + this.stack[i] = 0; + + this.top = 0; + + for (var i = 0; i <= FT_Common.T1_MAX_SUBRS_CALLS; i++) + { + var _z = this.zones[i]; + _z.base = null; + _z.cursor = 0; + _z.limit = 0; + } + this.zone = 0; + + this.psnames = null; + this.num_glyphs = 0; + this.glyph_names = null; + + this.lenIV = 0; + this.num_subrs = 0; + this.subrs = null; + this.subrs_len = null; + + this.font_matrix.xx = 0; + this.font_matrix.xy = 0; + this.font_matrix.yx = 0; + this.font_matrix.yy = 0; + + this.font_offset.x = 0; + this.font_offset.y = 0; + + this.flex_state = 0; + this.num_flex_vectors = 0; + for (var i = 0; i < 7; i++) + { + this.flex_vectors[i].x = 0; + this.flex_vectors[i].y = 0; + } + + this.blend = null; + + this.hint_mode = 0; + + this.parse_callback = null; + this.funcs = null; + + this.buildchar = null; + this.len_buildchar = 0; + + this.seac = 0; + } +} + +var ps_table_funcs = { + init : ps_table_new, + done : ps_table_done, + add : ps_table_add, + release : ps_table_release +}; + +var ps_parser_funcs = { + init : ps_parser_init, + done : ps_parser_done, + skip_spaces : ps_parser_skip_spaces, + skip_PS_token : ps_parser_skip_PS_token, + to_int : ps_parser_to_int, + to_fixed : ps_parser_to_fixed, + to_bytes : ps_parser_to_bytes, + to_coord_array : ps_parser_to_coord_array, + to_fixed_array : ps_parser_to_fixed_array, + to_token : ps_parser_to_token, + to_token_array : ps_parser_to_token_array, + load_field : ps_parser_load_field, + load_field_table : ps_parser_load_field_table +}; + +var t1_builder_funcs = { + init : t1_builder_init, + done : t1_builder_done, + check_points : t1_builder_check_points, + add_point : t1_builder_add_point, + add_point1 : t1_builder_add_point1, + add_contour : t1_builder_add_contour, + start_point : t1_builder_start_point, + close_contour : t1_builder_close_contour +}; + +var t1_decoder_funcs = { + init : t1_decoder_init, + done : t1_decoder_done, + parse_charstrings : t1_decoder_parse_charstrings +}; + +var afm_parser_funcs = { + init : afm_parser_init, + done : afm_parser_done, + parse : afm_parser_parse +}; + +var t1_cmap_classes = { + standard : t1_cmap_standard_class_rec, + expert : t1_cmap_expert_class_rec, + custom : t1_cmap_custom_class_rec, + unicode : t1_cmap_unicode_class_rec +}; + +function PSAux_ServiceRec() +{ + this.ps_table_funcs = null; + this.ps_parser_funcs = null; + this.t1_builder_funcs = null; + this.t1_decoder_funcs = null; + + this.t1_decrypt = null; + + this.t1_cmap_classes = null; + + this.afm_parser_funcs = null; +} + +function create_psaux_interface(_table_funcs,_parser_funcs,_builder_funcs,_decoder_funcs,_decrypt,_cmap_classes,_afm_parser_funcs) +{ + var ret = new PSAux_ServiceRec(); + + ret.ps_table_funcs = _table_funcs; + ret.ps_parser_funcs = _parser_funcs; + ret.t1_builder_funcs = _builder_funcs; + ret.t1_decoder_funcs = _decoder_funcs; + ret.t1_decrypt = _decrypt; + ret.t1_cmap_classes = _cmap_classes; + ret.afm_parser_funcs = _afm_parser_funcs; + + return ret; +} +var psaux_interface = create_psaux_interface(ps_table_funcs,ps_parser_funcs,t1_builder_funcs,t1_decoder_funcs, t1_decrypt, t1_cmap_classes, afm_parser_funcs); + +function create_psaux_module(library) +{ + var psaux_mod = new FT_Module(); + psaux_mod.clazz = new FT_Module_Class(); + + var clazz = psaux_mod.clazz; + clazz.flags = 0; + clazz.name = "psaux"; + clazz.version = 0x20000; + clazz.requires = 0x20000; + + clazz.module_interface = psaux_interface; + clazz.init = null; + clazz.done = null; + + clazz.get_interface = null; + + psaux_mod.library = library; + psaux_mod.memory = library.Memory; + psaux_mod.generic = null; + + return psaux_mod; +} diff --git a/Common/FontsFreeType/Private/FreeType/modules/psnames.js b/Common/FontsFreeType/Private/FreeType/modules/psnames.js new file mode 100644 index 0000000000000000000000000000000000000000..3505efac7c30b5c6718a98cce93671c9d00c3676 --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/modules/psnames.js @@ -0,0 +1,4089 @@ +var ft_standard_glyph_names = [".null","nonmarkingreturn","notequal","infinity","lessequal","greaterequal","partialdiff","summation","product","pi","integral", +"Omega","radical","approxequal","Delta","nonbreakingspace","lozenge","apple","franc","Gbreve","gbreve","Idotaccent","Scedilla", +"scedilla","Cacute","cacute","Ccaron","ccaron","dcroat",".notdef","space","exclam","quotedbl","numbersign","dollar","percent", +"ampersand","quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three", +"four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G", +"H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum", +"underscore","quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z", +"braceleft","bar","braceright","asciitilde","exclamdown","cent","sterling","fraction","yen","florin","section","currency", +"quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright","fi","fl","endash","dagger","daggerdbl","periodcentered", +"paragraph","bullet","quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis","perthousand","questiondown","grave", +"acute","circumflex","tilde","macron","breve","dotaccent","dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash","AE", +"ordfeminine","Lslash","Oslash","OE","ordmasculine","ae","dotlessi","lslash","oslash","oe","germandbls","onesuperior","logicalnot", +"mu","trademark","Eth","onehalf","plusminus","Thorn","onequarter","divide","brokenbar","degree","thorn","threequarters","twosuperior", +"registered","minus","eth","multiply","threesuperior","copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring","Atilde", +"Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute","Ocircumflex", +"Odieresis","Ograve","Otilde","Scaron","Uacute","Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron","aacute", +"acircumflex","adieresis","agrave","aring","atilde","ccedilla","eacute","ecircumflex","edieresis","egrave","iacute","icircumflex", +"idieresis","igrave","ntilde","oacute","ocircumflex","odieresis","ograve","otilde","scaron","uacute","ucircumflex","udieresis", +"ugrave","yacute","ydieresis","zcaron","exclamsmall","Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall", +"Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","zerooldstyle","oneoldstyle","twooldstyle", +"threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior", +"threequartersemdash","periodsuperior","questionsmall","asuperior","bsuperior","centsuperior","dsuperior","esuperior","isuperior", +"lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","ffi","ffl","parenleftinferior", +"parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall", +"Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall", +"Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","exclamdownsmall", +"centoldstyle","Lslashsmall","Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall","Dotaccentsmall","Macronsmall", +"figuredash","hypheninferior","Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall","oneeighth","threeeighths","fiveeighths", +"seveneighths","onethird","twothirds","zerosuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior", +"ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior", +"eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior","Agravesmall","Aacutesmall", +"Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall","Eacutesmall", +"Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall", +"Ogravesmall","Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall","Uacutesmall", +"Ucircumflexsmall","Udieresissmall","Yacutesmall","Thornsmall","Ydieresissmall","001.000","001.001","001.002","001.003","Black", +"Bold","Book","Light","Medium","Regular","Roman","Semibold"]; + +var ft_mac_names=[29,0,1,30,31,32,33,34,35,36,133,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65, +66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,153,95,96,97,98,99,100,101,102,103,104,105,106, +107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,202,204,206,207,215,218,224,229,232,230,231,234,233,235,236, +239,237,238,240,243,241,242,244,245,248,246,247,249,251,254,252,253,141,190,126,127,131,145,144,178,194,199,182,154,160,2,167,170,3, +185,4,5,129,181,6,7,8,9,10,168,172,11,173,176,152,125,180,12,130,13,14,135,149,150,15,203,205,220,171,177,140,166,134,148,94,37,188, +16,256,227,128,132,136,137,138,139,142,143,146,147,151,201,208,200,209,210,211,212,213,214,216,217,17,219,222,223,225,174,155,156, +157,158,159,161,162,163,164,165,169,175,221,250,228,257,189,183,196,226,255,186,191,195,197,179,193,198,184,187,192,18,19,20,21,22, +23,24,25,26,27,28]; + +var ft_sid_names=[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68, +69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108, +109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141, +142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, +208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240, +241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273, +274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306, +307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339, +340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372, +373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405, +406,407,408,409,410,411,412,413,414,415,416,417,418,419]; + +var t1_standard_encoding=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, +17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, +33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, +49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, +65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, +81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110, +0,111,112,113,114,0,115,116,117,118,119,120,121,122,0,123, +0,124,125,126,127,128,129,130,131,0,132,133,0,134,135,136, +137,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,138,0,139,0,0,0,0,140,141,142,143,0,0,0,0, +0,144,0,0,0,145,0,0,146,147,148,149,0,0,0,0]; + +var t1_expert_encoding=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,229,230,0,231,232,233,234,235,236,237,238,13,14,15,99, +239,240,241,242,243,244,245,246,247,248,27,28,249,250,251,252, +0,253,254,255,256,257,0,0,0,258,0,0,259,260,261,262, +0,0,263,264,265,0,266,109,110,267,268,269,0,270,271,272, +273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288, +289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,304,305,306,0,0,307,308,309,310,311,0,312,0,0,313, +0,0,314,315,0,0,316,317,318,0,0,0,158,155,163,319, +320,321,322,323,324,325,0,0,326,150,164,169,327,328,329,330, +331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346, +347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362, +363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378]; + +var ft_adobe_glyph_list=[0,52,0,106,2,167,3,63,4,220,6,125,9,143,10,23, +11,137,12,199,14,246,15,87,16,233,17,219,18,104,19,88, +22,110,23,32,23,71,24,77,27,156,29,73,31,247,32,107, +32,222,33,55,34,154,35,218,58,10,64,122,72,188,80,109, +88,104,93,61,98,168,106,91,114,111,115,237,122,180,127,255, +135,164,143,132,149,213,158,108,161,115,168,175,183,147,197,199, +202,25,204,166,208,209,209,81,215,26,65,143,0,65,0,140, +0,175,0,193,1,15,1,147,1,233,1,251,2,7,2,40, +2,57,2,82,2,91,2,128,2,136,2,154,69,131,0,198, +0,150,0,158,0,167,225,227,245,244,101,128,1,252,237,225, +227,242,239,110,128,1,226,243,237,225,236,108,128,247,230,225, +227,245,244,101,129,0,193,0,185,243,237,225,236,108,128,247, +225,226,242,229,246,101,134,1,2,0,213,0,221,0,232,0, +243,0,251,1,7,225,227,245,244,101,128,30,174,227,249,242, +233,236,236,233,99,128,4,208,228,239,244,226,229,236,239,119, +128,30,182,231,242,225,246,101,128,30,176,232,239,239,235,225, +226,239,246,101,128,30,178,244,233,236,228,101,128,30,180,99, +4,1,25,1,32,1,121,1,137,225,242,239,110,128,1,205, +233,242,99,2,1,40,1,45,236,101,128,36,182,245,237,230, +236,229,120,134,0,194,1,66,1,74,1,85,1,93,1,105, +1,113,225,227,245,244,101,128,30,164,228,239,244,226,229,236, +239,119,128,30,172,231,242,225,246,101,128,30,166,232,239,239, +235,225,226,239,246,101,128,30,168,243,237,225,236,108,128,247, +226,244,233,236,228,101,128,30,170,245,244,101,129,246,201,1, +129,243,237,225,236,108,128,247,180,249,242,233,236,236,233,99, +128,4,16,100,3,1,155,1,165,1,209,226,236,231,242,225, +246,101,128,2,0,233,229,242,229,243,233,115,131,0,196,1, +181,1,192,1,201,227,249,242,233,236,236,233,99,128,4,210, +237,225,227,242,239,110,128,1,222,243,237,225,236,108,128,247, +228,239,116,2,1,216,1,224,226,229,236,239,119,128,30,160, +237,225,227,242,239,110,128,1,224,231,242,225,246,101,129,0, +192,1,243,243,237,225,236,108,128,247,224,232,239,239,235,225, +226,239,246,101,128,30,162,105,2,2,13,2,25,229,227,249, +242,233,236,236,233,99,128,4,212,238,246,229,242,244,229,228, +226,242,229,246,101,128,2,2,236,240,232,97,129,3,145,2, +49,244,239,238,239,115,128,3,134,109,2,2,63,2,71,225, +227,242,239,110,128,1,0,239,238,239,243,240,225,227,101,128, +255,33,239,231,239,238,229,107,128,1,4,242,233,238,103,131, +0,197,2,104,2,112,2,120,225,227,245,244,101,128,1,250, +226,229,236,239,119,128,30,0,243,237,225,236,108,128,247,229, +243,237,225,236,108,128,247,97,244,233,236,228,101,129,0,195, +2,146,243,237,225,236,108,128,247,227,249,226,225,242,237,229, +238,233,225,110,128,5,49,66,137,0,66,2,189,2,198,2, +223,3,3,3,10,3,22,3,34,3,46,3,54,227,233,242, +227,236,101,128,36,183,228,239,116,2,2,206,2,215,225,227, +227,229,238,116,128,30,2,226,229,236,239,119,128,30,4,101, +3,2,231,2,242,2,254,227,249,242,233,236,236,233,99,128, +4,17,238,225,242,237,229,238,233,225,110,128,5,50,244,97, +128,3,146,232,239,239,107,128,1,129,236,233,238,229,226,229, +236,239,119,128,30,6,237,239,238,239,243,240,225,227,101,128, +255,34,242,229,246,229,243,237,225,236,108,128,246,244,243,237, +225,236,108,128,247,98,244,239,240,226,225,114,128,1,130,67, +137,0,67,3,85,3,127,3,193,3,210,3,224,4,171,4, +188,4,200,4,212,97,3,3,93,3,104,3,111,225,242,237, +229,238,233,225,110,128,5,62,227,245,244,101,128,1,6,242, +239,110,129,246,202,3,119,243,237,225,236,108,128,246,245,99, +3,3,135,3,142,3,171,225,242,239,110,128,1,12,229,228, +233,236,236,97,130,0,199,3,155,3,163,225,227,245,244,101, +128,30,8,243,237,225,236,108,128,247,231,233,242,99,2,3, +179,3,184,236,101,128,36,184,245,237,230,236,229,120,128,1, +8,228,239,116,129,1,10,3,201,225,227,227,229,238,116,128, +1,10,229,228,233,236,236,225,243,237,225,236,108,128,247,184, +104,4,3,234,3,246,4,161,4,165,225,225,242,237,229,238, +233,225,110,128,5,73,101,6,4,4,4,24,4,35,4,103, +4,115,4,136,225,226,235,232,225,243,233,225,238,227,249,242, +233,236,236,233,99,128,4,188,227,249,242,233,236,236,233,99, +128,4,39,100,2,4,41,4,85,229,243,227,229,238,228,229, +114,2,4,54,4,74,225,226,235,232,225,243,233,225,238,227, +249,242,233,236,236,233,99,128,4,190,227,249,242,233,236,236, +233,99,128,4,182,233,229,242,229,243,233,243,227,249,242,233, +236,236,233,99,128,4,244,232,225,242,237,229,238,233,225,110, +128,5,67,235,232,225,235,225,243,243,233,225,238,227,249,242, +233,236,236,233,99,128,4,203,246,229,242,244,233,227,225,236, +243,244,242,239,235,229,227,249,242,233,236,236,233,99,128,4, +184,105,128,3,167,239,239,107,128,1,135,233,242,227,245,237, +230,236,229,248,243,237,225,236,108,128,246,246,237,239,238,239, +243,240,225,227,101,128,255,35,239,225,242,237,229,238,233,225, +110,128,5,81,243,237,225,236,108,128,247,99,68,142,0,68, +4,252,5,10,5,36,5,96,5,121,5,166,5,173,5,231, +5,244,6,0,6,12,6,28,6,48,6,57,90,129,1,241, +5,2,227,225,242,239,110,128,1,196,97,2,5,16,5,27, +225,242,237,229,238,233,225,110,128,5,52,230,242,233,227,225, +110,128,1,137,99,4,5,46,5,53,5,62,5,89,225,242, +239,110,128,1,14,229,228,233,236,236,97,128,30,16,233,242, +99,2,5,70,5,75,236,101,128,36,185,245,237,230,236,229, +248,226,229,236,239,119,128,30,18,242,239,225,116,128,1,16, +228,239,116,2,5,104,5,113,225,227,227,229,238,116,128,30, +10,226,229,236,239,119,128,30,12,101,3,5,129,5,140,5, +150,227,249,242,233,236,236,233,99,128,4,20,233,227,239,240, +244,233,99,128,3,238,236,244,97,129,34,6,5,158,231,242, +229,229,107,128,3,148,232,239,239,107,128,1,138,105,2,5, +179,5,218,229,242,229,243,233,115,131,246,203,5,194,5,202, +5,210,193,227,245,244,101,128,246,204,199,242,225,246,101,128, +246,205,243,237,225,236,108,128,247,168,231,225,237,237,225,231, +242,229,229,107,128,3,220,234,229,227,249,242,233,236,236,233, +99,128,4,2,236,233,238,229,226,229,236,239,119,128,30,14, +237,239,238,239,243,240,225,227,101,128,255,36,239,244,225,227, +227,229,238,244,243,237,225,236,108,128,246,247,115,2,6,34, +6,41,236,225,243,104,128,1,16,237,225,236,108,128,247,100, +244,239,240,226,225,114,128,1,139,122,131,1,242,6,67,6, +75,6,112,227,225,242,239,110,128,1,197,101,2,6,81,6, +101,225,226,235,232,225,243,233,225,238,227,249,242,233,236,236, +233,99,128,4,224,227,249,242,233,236,236,233,99,128,4,5, +232,229,227,249,242,233,236,236,233,99,128,4,15,69,146,0, +69,6,165,6,183,6,191,7,89,7,153,7,165,7,183,7, +211,8,7,8,36,8,94,8,169,8,189,8,208,8,248,9, +44,9,109,9,115,225,227,245,244,101,129,0,201,6,175,243, +237,225,236,108,128,247,233,226,242,229,246,101,128,1,20,99, +5,6,203,6,210,6,224,6,236,7,79,225,242,239,110,128, +1,26,229,228,233,236,236,225,226,242,229,246,101,128,30,28, +232,225,242,237,229,238,233,225,110,128,5,53,233,242,99,2, +6,244,6,249,236,101,128,36,186,245,237,230,236,229,120,135, +0,202,7,16,7,24,7,32,7,43,7,51,7,63,7,71, +225,227,245,244,101,128,30,190,226,229,236,239,119,128,30,24, +228,239,244,226,229,236,239,119,128,30,198,231,242,225,246,101, +128,30,192,232,239,239,235,225,226,239,246,101,128,30,194,243, +237,225,236,108,128,247,234,244,233,236,228,101,128,30,196,249, +242,233,236,236,233,99,128,4,4,100,3,7,97,7,107,7, +127,226,236,231,242,225,246,101,128,2,4,233,229,242,229,243, +233,115,129,0,203,7,119,243,237,225,236,108,128,247,235,239, +116,130,1,22,7,136,7,145,225,227,227,229,238,116,128,1, +22,226,229,236,239,119,128,30,184,230,227,249,242,233,236,236, +233,99,128,4,36,231,242,225,246,101,129,0,200,7,175,243, +237,225,236,108,128,247,232,104,2,7,189,7,200,225,242,237, +229,238,233,225,110,128,5,55,239,239,235,225,226,239,246,101, +128,30,186,105,3,7,219,7,230,7,245,231,232,244,242,239, +237,225,110,128,33,103,238,246,229,242,244,229,228,226,242,229, +246,101,128,2,6,239,244,233,230,233,229,228,227,249,242,233, +236,236,233,99,128,4,100,108,2,8,13,8,24,227,249,242, +233,236,236,233,99,128,4,27,229,246,229,238,242,239,237,225, +110,128,33,106,109,3,8,44,8,72,8,83,225,227,242,239, +110,130,1,18,8,56,8,64,225,227,245,244,101,128,30,22, +231,242,225,246,101,128,30,20,227,249,242,233,236,236,233,99, +128,4,28,239,238,239,243,240,225,227,101,128,255,37,110,4, +8,104,8,115,8,135,8,154,227,249,242,233,236,236,233,99, +128,4,29,228,229,243,227,229,238,228,229,242,227,249,242,233, +236,236,233,99,128,4,162,103,129,1,74,8,141,232,229,227, +249,242,233,236,236,233,99,128,4,164,232,239,239,235,227,249, +242,233,236,236,233,99,128,4,199,111,2,8,175,8,183,231, +239,238,229,107,128,1,24,240,229,110,128,1,144,240,243,233, +236,239,110,129,3,149,8,200,244,239,238,239,115,128,3,136, +114,2,8,214,8,225,227,249,242,233,236,236,233,99,128,4, +32,229,246,229,242,243,229,100,129,1,142,8,237,227,249,242, +233,236,236,233,99,128,4,45,115,4,9,2,9,13,9,33, +9,37,227,249,242,233,236,236,233,99,128,4,33,228,229,243, +227,229,238,228,229,242,227,249,242,233,236,236,233,99,128,4, +170,104,128,1,169,237,225,236,108,128,247,101,116,3,9,52, +9,78,9,92,97,130,3,151,9,60,9,70,242,237,229,238, +233,225,110,128,5,56,244,239,238,239,115,128,3,137,104,129, +0,208,9,84,243,237,225,236,108,128,247,240,233,236,228,101, +129,30,188,9,101,226,229,236,239,119,128,30,26,245,242,111, +128,32,172,250,104,130,1,183,9,124,9,132,227,225,242,239, +110,128,1,238,242,229,246,229,242,243,229,100,128,1,184,70, +136,0,70,9,163,9,172,9,184,9,212,9,219,9,248,10, +4,10,15,227,233,242,227,236,101,128,36,187,228,239,244,225, +227,227,229,238,116,128,30,30,101,2,9,190,9,202,232,225, +242,237,229,238,233,225,110,128,5,86,233,227,239,240,244,233, +99,128,3,228,232,239,239,107,128,1,145,105,2,9,225,9, +238,244,225,227,249,242,233,236,236,233,99,128,4,114,246,229, +242,239,237,225,110,128,33,100,237,239,238,239,243,240,225,227, +101,128,255,38,239,245,242,242,239,237,225,110,128,33,99,243, +237,225,236,108,128,247,102,71,140,0,71,10,51,10,61,10, +107,10,115,10,176,10,193,10,205,11,39,11,52,11,65,11, +90,11,107,194,243,241,245,225,242,101,128,51,135,97,3,10, +69,10,76,10,94,227,245,244,101,128,1,244,237,237,97,129, +3,147,10,84,225,230,242,233,227,225,110,128,1,148,238,231, +233,225,227,239,240,244,233,99,128,3,234,226,242,229,246,101, +128,1,30,99,4,10,125,10,132,10,141,10,163,225,242,239, +110,128,1,230,229,228,233,236,236,97,128,1,34,233,242,99, +2,10,149,10,154,236,101,128,36,188,245,237,230,236,229,120, +128,1,28,239,237,237,225,225,227,227,229,238,116,128,1,34, +228,239,116,129,1,32,10,184,225,227,227,229,238,116,128,1, +32,229,227,249,242,233,236,236,233,99,128,4,19,104,3,10, +213,10,226,11,33,225,228,225,242,237,229,238,233,225,110,128, +5,66,101,3,10,234,10,255,11,16,237,233,228,228,236,229, +232,239,239,235,227,249,242,233,236,236,233,99,128,4,148,243, +244,242,239,235,229,227,249,242,233,236,236,233,99,128,4,146, +245,240,244,245,242,238,227,249,242,233,236,236,233,99,128,4, +144,239,239,107,128,1,147,233,237,225,242,237,229,238,233,225, +110,128,5,51,234,229,227,249,242,233,236,236,233,99,128,4, +3,109,2,11,71,11,79,225,227,242,239,110,128,30,32,239, +238,239,243,240,225,227,101,128,255,39,242,225,246,101,129,246, +206,11,99,243,237,225,236,108,128,247,96,115,2,11,113,11, +129,237,225,236,108,129,247,103,11,122,232,239,239,107,128,2, +155,244,242,239,235,101,128,1,228,72,140,0,72,11,165,11, +190,11,198,11,208,12,17,12,40,12,77,12,117,12,129,12, +157,12,165,12,189,177,184,53,3,11,175,11,180,11,185,179, +51,128,37,207,180,51,128,37,170,181,49,128,37,171,178,178, +176,183,51,128,37,161,208,243,241,245,225,242,101,128,51,203, +97,3,11,216,11,236,12,0,225,226,235,232,225,243,233,225, +238,227,249,242,233,236,236,233,99,128,4,168,228,229,243,227, +229,238,228,229,242,227,249,242,233,236,236,233,99,128,4,178, +242,228,243,233,231,238,227,249,242,233,236,236,233,99,128,4, +42,98,2,12,23,12,28,225,114,128,1,38,242,229,246,229, +226,229,236,239,119,128,30,42,99,2,12,46,12,55,229,228, +233,236,236,97,128,30,40,233,242,99,2,12,63,12,68,236, +101,128,36,189,245,237,230,236,229,120,128,1,36,100,2,12, +83,12,93,233,229,242,229,243,233,115,128,30,38,239,116,2, +12,100,12,109,225,227,227,229,238,116,128,30,34,226,229,236, +239,119,128,30,36,237,239,238,239,243,240,225,227,101,128,255, +40,111,2,12,135,12,146,225,242,237,229,238,233,225,110,128, +5,64,242,233,227,239,240,244,233,99,128,3,232,243,237,225, +236,108,128,247,104,245,238,231,225,242,245,237,236,225,245,116, +129,246,207,12,181,243,237,225,236,108,128,246,248,250,243,241, +245,225,242,101,128,51,144,73,146,0,73,12,239,12,251,12, +255,13,11,13,29,13,37,13,94,13,181,13,214,13,224,13, +242,13,254,14,48,14,86,14,99,14,166,14,187,14,205,193, +227,249,242,233,236,236,233,99,128,4,47,74,128,1,50,213, +227,249,242,233,236,236,233,99,128,4,46,225,227,245,244,101, +129,0,205,13,21,243,237,225,236,108,128,247,237,226,242,229, +246,101,128,1,44,99,3,13,45,13,52,13,84,225,242,239, +110,128,1,207,233,242,99,2,13,60,13,65,236,101,128,36, +190,245,237,230,236,229,120,129,0,206,13,76,243,237,225,236, +108,128,247,238,249,242,233,236,236,233,99,128,4,6,100,3, +13,102,13,112,13,155,226,236,231,242,225,246,101,128,2,8, +233,229,242,229,243,233,115,131,0,207,13,128,13,136,13,147, +225,227,245,244,101,128,30,46,227,249,242,233,236,236,233,99, +128,4,228,243,237,225,236,108,128,247,239,239,116,130,1,48, +13,164,13,173,225,227,227,229,238,116,128,1,48,226,229,236, +239,119,128,30,202,101,2,13,187,13,203,226,242,229,246,229, +227,249,242,233,236,236,233,99,128,4,214,227,249,242,233,236, +236,233,99,128,4,21,230,242,225,235,244,245,114,128,33,17, +231,242,225,246,101,129,0,204,13,234,243,237,225,236,108,128, +247,236,232,239,239,235,225,226,239,246,101,128,30,200,105,3, +14,6,14,17,14,32,227,249,242,233,236,236,233,99,128,4, +24,238,246,229,242,244,229,228,226,242,229,246,101,128,2,10, +243,232,239,242,244,227,249,242,233,236,236,233,99,128,4,25, +109,2,14,54,14,75,225,227,242,239,110,129,1,42,14,64, +227,249,242,233,236,236,233,99,128,4,226,239,238,239,243,240, +225,227,101,128,255,41,238,233,225,242,237,229,238,233,225,110, +128,5,59,111,3,14,107,14,118,14,126,227,249,242,233,236, +236,233,99,128,4,1,231,239,238,229,107,128,1,46,244,97, +131,3,153,14,137,14,147,14,158,225,230,242,233,227,225,110, +128,1,150,228,233,229,242,229,243,233,115,128,3,170,244,239, +238,239,115,128,3,138,115,2,14,172,14,179,237,225,236,108, +128,247,105,244,242,239,235,101,128,1,151,244,233,236,228,101, +129,1,40,14,197,226,229,236,239,119,128,30,44,250,232,233, +244,243,97,2,14,216,14,227,227,249,242,233,236,236,233,99, +128,4,116,228,226,236,231,242,225,246,229,227,249,242,233,236, +236,233,99,128,4,118,74,134,0,74,15,6,15,18,15,41, +15,53,15,67,15,79,225,225,242,237,229,238,233,225,110,128, +5,65,227,233,242,99,2,15,27,15,32,236,101,128,36,191, +245,237,230,236,229,120,128,1,52,229,227,249,242,233,236,236, +233,99,128,4,8,232,229,232,225,242,237,229,238,233,225,110, +128,5,75,237,239,238,239,243,240,225,227,101,128,255,42,243, +237,225,236,108,128,247,106,75,140,0,75,15,115,15,125,15, +135,16,18,16,65,16,76,16,106,16,143,16,156,16,168,16, +180,16,208,194,243,241,245,225,242,101,128,51,133,203,243,241, +245,225,242,101,128,51,205,97,7,15,151,15,169,15,191,15, +211,15,226,15,232,15,249,226,225,243,232,235,233,242,227,249, +242,233,236,236,233,99,128,4,160,99,2,15,175,15,181,245, +244,101,128,30,48,249,242,233,236,236,233,99,128,4,26,228, +229,243,227,229,238,228,229,242,227,249,242,233,236,236,233,99, +128,4,154,232,239,239,235,227,249,242,233,236,236,233,99,128, +4,195,240,240,97,128,3,154,243,244,242,239,235,229,227,249, +242,233,236,236,233,99,128,4,158,246,229,242,244,233,227,225, +236,243,244,242,239,235,229,227,249,242,233,236,236,233,99,128, +4,156,99,4,16,28,16,35,16,44,16,52,225,242,239,110, +128,1,232,229,228,233,236,236,97,128,1,54,233,242,227,236, +101,128,36,192,239,237,237,225,225,227,227,229,238,116,128,1, +54,228,239,244,226,229,236,239,119,128,30,50,101,2,16,82, +16,94,232,225,242,237,229,238,233,225,110,128,5,84,238,225, +242,237,229,238,233,225,110,128,5,63,104,3,16,114,16,126, +16,137,225,227,249,242,233,236,236,233,99,128,4,37,229,233, +227,239,240,244,233,99,128,3,230,239,239,107,128,1,152,234, +229,227,249,242,233,236,236,233,99,128,4,12,236,233,238,229, +226,229,236,239,119,128,30,52,237,239,238,239,243,240,225,227, +101,128,255,43,239,240,240,97,2,16,189,16,200,227,249,242, +233,236,236,233,99,128,4,128,231,242,229,229,107,128,3,222, +115,2,16,214,16,226,233,227,249,242,233,236,236,233,99,128, +4,110,237,225,236,108,128,247,107,76,138,0,76,17,1,17, +5,17,9,17,29,17,95,17,133,17,147,17,165,17,177,17, +189,74,128,1,199,76,128,246,191,97,2,17,15,17,22,227, +245,244,101,128,1,57,237,226,228,97,128,3,155,99,4,17, +39,17,46,17,55,17,82,225,242,239,110,128,1,61,229,228, +233,236,236,97,128,1,59,233,242,99,2,17,63,17,68,236, +101,128,36,193,245,237,230,236,229,248,226,229,236,239,119,128, +30,60,239,237,237,225,225,227,227,229,238,116,128,1,59,228, +239,116,130,1,63,17,105,17,114,225,227,227,229,238,116,128, +1,63,226,229,236,239,119,129,30,54,17,124,237,225,227,242, +239,110,128,30,56,233,247,238,225,242,237,229,238,233,225,110, +128,5,60,106,129,1,200,17,153,229,227,249,242,233,236,236, +233,99,128,4,9,236,233,238,229,226,229,236,239,119,128,30, +58,237,239,238,239,243,240,225,227,101,128,255,44,115,2,17, +195,17,212,236,225,243,104,129,1,65,17,204,243,237,225,236, +108,128,246,249,237,225,236,108,128,247,108,77,137,0,77,17, +241,17,251,18,24,18,33,18,58,18,71,18,83,18,91,18, +100,194,243,241,245,225,242,101,128,51,134,225,99,2,18,2, +18,18,242,239,110,129,246,208,18,10,243,237,225,236,108,128, +247,175,245,244,101,128,30,62,227,233,242,227,236,101,128,36, +194,228,239,116,2,18,41,18,50,225,227,227,229,238,116,128, +30,64,226,229,236,239,119,128,30,66,229,238,225,242,237,229, +238,233,225,110,128,5,68,237,239,238,239,243,240,225,227,101, +128,255,45,243,237,225,236,108,128,247,109,244,245,242,238,229, +100,128,1,156,117,128,3,156,78,141,0,78,18,134,18,138, +18,146,18,212,18,237,18,248,19,3,19,21,19,33,19,45, +19,58,19,66,19,84,74,128,1,202,225,227,245,244,101,128, +1,67,99,4,18,156,18,163,18,172,18,199,225,242,239,110, +128,1,71,229,228,233,236,236,97,128,1,69,233,242,99,2, +18,180,18,185,236,101,128,36,195,245,237,230,236,229,248,226, +229,236,239,119,128,30,74,239,237,237,225,225,227,227,229,238, +116,128,1,69,228,239,116,2,18,220,18,229,225,227,227,229, +238,116,128,30,68,226,229,236,239,119,128,30,70,232,239,239, +235,236,229,230,116,128,1,157,233,238,229,242,239,237,225,110, +128,33,104,106,129,1,203,19,9,229,227,249,242,233,236,236, +233,99,128,4,10,236,233,238,229,226,229,236,239,119,128,30, +72,237,239,238,239,243,240,225,227,101,128,255,46,239,247,225, +242,237,229,238,233,225,110,128,5,70,243,237,225,236,108,128, +247,110,244,233,236,228,101,129,0,209,19,76,243,237,225,236, +108,128,247,241,117,128,3,157,79,141,0,79,19,118,19,132, +19,150,19,203,20,78,20,152,20,187,21,48,21,69,21,213, +21,223,21,254,22,53,69,129,1,82,19,124,243,237,225,236, +108,128,246,250,225,227,245,244,101,129,0,211,19,142,243,237, +225,236,108,128,247,243,98,2,19,156,19,196,225,242,242,229, +100,2,19,166,19,177,227,249,242,233,236,236,233,99,128,4, +232,228,233,229,242,229,243,233,243,227,249,242,233,236,236,233, +99,128,4,234,242,229,246,101,128,1,78,99,4,19,213,19, +220,19,235,20,68,225,242,239,110,128,1,209,229,238,244,229, +242,229,228,244,233,236,228,101,128,1,159,233,242,99,2,19, +243,19,248,236,101,128,36,196,245,237,230,236,229,120,134,0, +212,20,13,20,21,20,32,20,40,20,52,20,60,225,227,245, +244,101,128,30,208,228,239,244,226,229,236,239,119,128,30,216, +231,242,225,246,101,128,30,210,232,239,239,235,225,226,239,246, +101,128,30,212,243,237,225,236,108,128,247,244,244,233,236,228, +101,128,30,214,249,242,233,236,236,233,99,128,4,30,100,3, +20,86,20,109,20,142,226,108,2,20,93,20,101,225,227,245, +244,101,128,1,80,231,242,225,246,101,128,2,12,233,229,242, +229,243,233,115,130,0,214,20,123,20,134,227,249,242,233,236, +236,233,99,128,4,230,243,237,225,236,108,128,247,246,239,244, +226,229,236,239,119,128,30,204,103,2,20,158,20,170,239,238, +229,235,243,237,225,236,108,128,246,251,242,225,246,101,129,0, +210,20,179,243,237,225,236,108,128,247,242,104,4,20,197,20, +208,20,212,21,34,225,242,237,229,238,233,225,110,128,5,85, +109,128,33,38,111,2,20,218,20,228,239,235,225,226,239,246, +101,128,30,206,242,110,133,1,160,20,243,20,251,21,6,21, +14,21,26,225,227,245,244,101,128,30,218,228,239,244,226,229, +236,239,119,128,30,226,231,242,225,246,101,128,30,220,232,239, +239,235,225,226,239,246,101,128,30,222,244,233,236,228,101,128, +30,224,245,238,231,225,242,245,237,236,225,245,116,128,1,80, +105,129,1,162,21,54,238,246,229,242,244,229,228,226,242,229, +246,101,128,2,14,109,4,21,79,21,107,21,184,21,202,225, +227,242,239,110,130,1,76,21,91,21,99,225,227,245,244,101, +128,30,82,231,242,225,246,101,128,30,80,229,231,97,132,33, +38,21,121,21,132,21,140,21,156,227,249,242,233,236,236,233, +99,128,4,96,231,242,229,229,107,128,3,169,242,239,245,238, +228,227,249,242,233,236,236,233,99,128,4,122,116,2,21,162, +21,177,233,244,236,239,227,249,242,233,236,236,233,99,128,4, +124,239,238,239,115,128,3,143,233,227,242,239,110,129,3,159, +21,194,244,239,238,239,115,128,3,140,239,238,239,243,240,225, +227,101,128,255,47,238,229,242,239,237,225,110,128,33,96,111, +2,21,229,21,248,231,239,238,229,107,129,1,234,21,239,237, +225,227,242,239,110,128,1,236,240,229,110,128,1,134,115,3, +22,6,22,33,22,40,236,225,243,104,130,0,216,22,17,22, +25,225,227,245,244,101,128,1,254,243,237,225,236,108,128,247, +248,237,225,236,108,128,247,111,244,242,239,235,229,225,227,245, +244,101,128,1,254,116,2,22,59,22,70,227,249,242,233,236, +236,233,99,128,4,126,233,236,228,101,131,0,213,22,83,22, +91,22,102,225,227,245,244,101,128,30,76,228,233,229,242,229, +243,233,115,128,30,78,243,237,225,236,108,128,247,245,80,136, +0,80,22,130,22,138,22,147,22,159,22,211,22,227,22,246, +23,2,225,227,245,244,101,128,30,84,227,233,242,227,236,101, +128,36,197,228,239,244,225,227,227,229,238,116,128,30,86,101, +3,22,167,22,178,22,190,227,249,242,233,236,236,233,99,128, +4,31,232,225,242,237,229,238,233,225,110,128,5,74,237,233, +228,228,236,229,232,239,239,235,227,249,242,233,236,236,233,99, +128,4,166,104,2,22,217,22,221,105,128,3,166,239,239,107, +128,1,164,105,129,3,160,22,233,247,242,225,242,237,229,238, +233,225,110,128,5,83,237,239,238,239,243,240,225,227,101,128, +255,48,115,2,23,8,23,25,105,129,3,168,23,14,227,249, +242,233,236,236,233,99,128,4,112,237,225,236,108,128,247,112, +81,131,0,81,23,42,23,51,23,63,227,233,242,227,236,101, +128,36,198,237,239,238,239,243,240,225,227,101,128,255,49,243, +237,225,236,108,128,247,113,82,138,0,82,23,95,23,119,23, +166,23,217,23,230,23,240,23,245,24,19,24,31,24,43,97, +2,23,101,23,112,225,242,237,229,238,233,225,110,128,5,76, +227,245,244,101,128,1,84,99,4,23,129,23,136,23,145,23, +153,225,242,239,110,128,1,88,229,228,233,236,236,97,128,1, +86,233,242,227,236,101,128,36,199,239,237,237,225,225,227,227, +229,238,116,128,1,86,100,2,23,172,23,182,226,236,231,242, +225,246,101,128,2,16,239,116,2,23,189,23,198,225,227,227, +229,238,116,128,30,88,226,229,236,239,119,129,30,90,23,208, +237,225,227,242,239,110,128,30,92,229,232,225,242,237,229,238, +233,225,110,128,5,80,230,242,225,235,244,245,114,128,33,28, +232,111,128,3,161,233,110,2,23,252,24,5,231,243,237,225, +236,108,128,246,252,246,229,242,244,229,228,226,242,229,246,101, +128,2,18,236,233,238,229,226,229,236,239,119,128,30,94,237, +239,238,239,243,240,225,227,101,128,255,50,243,237,225,236,108, +129,247,114,24,53,233,238,246,229,242,244,229,100,129,2,129, +24,66,243,245,240,229,242,233,239,114,128,2,182,83,139,0, +83,24,103,26,17,26,55,26,182,26,221,26,250,27,84,27, +105,27,117,27,135,27,143,70,6,24,117,24,209,24,241,25, +77,25,119,25,221,48,9,24,137,24,145,24,153,24,161,24, +169,24,177,24,185,24,193,24,201,177,176,176,176,48,128,37, +12,178,176,176,176,48,128,37,20,179,176,176,176,48,128,37, +16,180,176,176,176,48,128,37,24,181,176,176,176,48,128,37, +60,182,176,176,176,48,128,37,44,183,176,176,176,48,128,37, +52,184,176,176,176,48,128,37,28,185,176,176,176,48,128,37, +36,49,3,24,217,24,225,24,233,176,176,176,176,48,128,37, +0,177,176,176,176,48,128,37,2,185,176,176,176,48,128,37, +97,50,9,25,5,25,13,25,21,25,29,25,37,25,45,25, +53,25,61,25,69,176,176,176,176,48,128,37,98,177,176,176, +176,48,128,37,86,178,176,176,176,48,128,37,85,179,176,176, +176,48,128,37,99,180,176,176,176,48,128,37,81,181,176,176, +176,48,128,37,87,182,176,176,176,48,128,37,93,183,176,176, +176,48,128,37,92,184,176,176,176,48,128,37,91,51,4,25, +87,25,95,25,103,25,111,182,176,176,176,48,128,37,94,183, +176,176,176,48,128,37,95,184,176,176,176,48,128,37,90,185, +176,176,176,48,128,37,84,52,10,25,141,25,149,25,157,25, +165,25,173,25,181,25,189,25,197,25,205,25,213,176,176,176, +176,48,128,37,105,177,176,176,176,48,128,37,102,178,176,176, +176,48,128,37,96,179,176,176,176,48,128,37,80,180,176,176, +176,48,128,37,108,181,176,176,176,48,128,37,103,182,176,176, +176,48,128,37,104,183,176,176,176,48,128,37,100,184,176,176, +176,48,128,37,101,185,176,176,176,48,128,37,89,53,5,25, +233,25,241,25,249,26,1,26,9,176,176,176,176,48,128,37, +88,177,176,176,176,48,128,37,82,178,176,176,176,48,128,37, +83,179,176,176,176,48,128,37,107,180,176,176,176,48,128,37, +106,97,2,26,23,26,44,227,245,244,101,129,1,90,26,32, +228,239,244,225,227,227,229,238,116,128,30,100,237,240,233,231, +242,229,229,107,128,3,224,99,5,26,67,26,98,26,107,26, +147,26,169,225,242,239,110,130,1,96,26,78,26,90,228,239, +244,225,227,227,229,238,116,128,30,102,243,237,225,236,108,128, +246,253,229,228,233,236,236,97,128,1,94,232,247,97,130,1, +143,26,117,26,128,227,249,242,233,236,236,233,99,128,4,216, +228,233,229,242,229,243,233,243,227,249,242,233,236,236,233,99, +128,4,218,233,242,99,2,26,155,26,160,236,101,128,36,200, +245,237,230,236,229,120,128,1,92,239,237,237,225,225,227,227, +229,238,116,128,2,24,228,239,116,2,26,190,26,199,225,227, +227,229,238,116,128,30,96,226,229,236,239,119,129,30,98,26, +209,228,239,244,225,227,227,229,238,116,128,30,104,101,2,26, +227,26,239,232,225,242,237,229,238,233,225,110,128,5,77,246, +229,238,242,239,237,225,110,128,33,102,104,5,27,6,27,34, +27,48,27,59,27,72,97,2,27,12,27,23,225,242,237,229, +238,233,225,110,128,5,71,227,249,242,233,236,236,233,99,128, +4,40,227,232,225,227,249,242,233,236,236,233,99,128,4,41, +229,233,227,239,240,244,233,99,128,3,226,232,225,227,249,242, +233,236,236,233,99,128,4,186,233,237,225,227,239,240,244,233, +99,128,3,236,105,2,27,90,27,96,231,237,97,128,3,163, +248,242,239,237,225,110,128,33,101,237,239,238,239,243,240,225, +227,101,128,255,51,239,230,244,243,233,231,238,227,249,242,233, +236,236,233,99,128,4,44,243,237,225,236,108,128,247,115,244, +233,231,237,225,231,242,229,229,107,128,3,218,84,141,0,84, +27,186,27,191,27,197,28,7,28,32,28,96,28,147,28,177, +28,189,28,201,28,246,29,6,29,46,225,117,128,3,164,226, +225,114,128,1,102,99,4,27,207,27,214,27,223,27,250,225, +242,239,110,128,1,100,229,228,233,236,236,97,128,1,98,233, +242,99,2,27,231,27,236,236,101,128,36,201,245,237,230,236, +229,248,226,229,236,239,119,128,30,112,239,237,237,225,225,227, +227,229,238,116,128,1,98,228,239,116,2,28,15,28,24,225, +227,227,229,238,116,128,30,106,226,229,236,239,119,128,30,108, +101,4,28,42,28,53,28,73,28,82,227,249,242,233,236,236, +233,99,128,4,34,228,229,243,227,229,238,228,229,242,227,249, +242,233,236,236,233,99,128,4,172,238,242,239,237,225,110,128, +33,105,244,243,229,227,249,242,233,236,236,233,99,128,4,180, +104,3,28,104,28,110,28,136,229,244,97,128,3,152,111,2, +28,116,28,121,239,107,128,1,172,242,110,129,0,222,28,128, +243,237,225,236,108,128,247,254,242,229,229,242,239,237,225,110, +128,33,98,105,2,28,153,28,164,236,228,229,243,237,225,236, +108,128,246,254,247,238,225,242,237,229,238,233,225,110,128,5, +79,236,233,238,229,226,229,236,239,119,128,30,110,237,239,238, +239,243,240,225,227,101,128,255,52,111,2,28,207,28,218,225, +242,237,229,238,233,225,110,128,5,57,238,101,3,28,227,28, +234,28,240,230,233,246,101,128,1,188,243,233,120,128,1,132, +244,247,111,128,1,167,242,229,244,242,239,230,236,229,248,232, +239,239,107,128,1,174,115,3,29,14,29,26,29,39,229,227, +249,242,233,236,236,233,99,128,4,38,232,229,227,249,242,233, +236,236,233,99,128,4,11,237,225,236,108,128,247,116,119,2, +29,52,29,64,229,236,246,229,242,239,237,225,110,128,33,107, +239,242,239,237,225,110,128,33,97,85,142,0,85,29,105,29, +123,29,131,29,198,30,69,30,87,30,198,30,214,30,226,31, +21,31,30,31,142,31,149,31,219,225,227,245,244,101,129,0, +218,29,115,243,237,225,236,108,128,247,250,226,242,229,246,101, +128,1,108,99,3,29,139,29,146,29,188,225,242,239,110,128, +1,211,233,242,99,2,29,154,29,159,236,101,128,36,202,245, +237,230,236,229,120,130,0,219,29,172,29,180,226,229,236,239, +119,128,30,118,243,237,225,236,108,128,247,251,249,242,233,236, +236,233,99,128,4,35,100,3,29,206,29,229,30,59,226,108, +2,29,213,29,221,225,227,245,244,101,128,1,112,231,242,225, +246,101,128,2,20,233,229,242,229,243,233,115,134,0,220,29, +251,30,3,30,11,30,34,30,42,30,51,225,227,245,244,101, +128,1,215,226,229,236,239,119,128,30,114,99,2,30,17,30, +24,225,242,239,110,128,1,217,249,242,233,236,236,233,99,128, +4,240,231,242,225,246,101,128,1,219,237,225,227,242,239,110, +128,1,213,243,237,225,236,108,128,247,252,239,244,226,229,236, +239,119,128,30,228,231,242,225,246,101,129,0,217,30,79,243, +237,225,236,108,128,247,249,104,2,30,93,30,171,111,2,30, +99,30,109,239,235,225,226,239,246,101,128,30,230,242,110,133, +1,175,30,124,30,132,30,143,30,151,30,163,225,227,245,244, +101,128,30,232,228,239,244,226,229,236,239,119,128,30,240,231, +242,225,246,101,128,30,234,232,239,239,235,225,226,239,246,101, +128,30,236,244,233,236,228,101,128,30,238,245,238,231,225,242, +245,237,236,225,245,116,129,1,112,30,187,227,249,242,233,236, +236,233,99,128,4,242,233,238,246,229,242,244,229,228,226,242, +229,246,101,128,2,22,235,227,249,242,233,236,236,233,99,128, +4,120,109,2,30,232,31,10,225,227,242,239,110,130,1,106, +30,244,30,255,227,249,242,233,236,236,233,99,128,4,238,228, +233,229,242,229,243,233,115,128,30,122,239,238,239,243,240,225, +227,101,128,255,53,239,231,239,238,229,107,128,1,114,240,243, +233,236,239,110,133,3,165,31,49,31,53,31,90,31,121,31, +134,49,128,3,210,97,2,31,59,31,81,227,245,244,229,232, +239,239,235,243,249,237,226,239,236,231,242,229,229,107,128,3, +211,230,242,233,227,225,110,128,1,177,228,233,229,242,229,243, +233,115,129,3,171,31,103,232,239,239,235,243,249,237,226,239, +236,231,242,229,229,107,128,3,212,232,239,239,235,243,249,237, +226,239,108,128,3,210,244,239,238,239,115,128,3,142,242,233, +238,103,128,1,110,115,3,31,157,31,172,31,179,232,239,242, +244,227,249,242,233,236,236,233,99,128,4,14,237,225,236,108, +128,247,117,244,242,225,233,231,232,116,2,31,191,31,202,227, +249,242,233,236,236,233,99,128,4,174,243,244,242,239,235,229, +227,249,242,233,236,236,233,99,128,4,176,244,233,236,228,101, +130,1,104,31,231,31,239,225,227,245,244,101,128,30,120,226, +229,236,239,119,128,30,116,86,136,0,86,32,11,32,20,32, +31,32,60,32,67,32,79,32,91,32,99,227,233,242,227,236, +101,128,36,203,228,239,244,226,229,236,239,119,128,30,126,101, +2,32,37,32,48,227,249,242,233,236,236,233,99,128,4,18, +247,225,242,237,229,238,233,225,110,128,5,78,232,239,239,107, +128,1,178,237,239,238,239,243,240,225,227,101,128,255,54,239, +225,242,237,229,238,233,225,110,128,5,72,243,237,225,236,108, +128,247,118,244,233,236,228,101,128,30,124,87,134,0,87,32, +123,32,131,32,154,32,194,32,202,32,214,225,227,245,244,101, +128,30,130,227,233,242,99,2,32,140,32,145,236,101,128,36, +204,245,237,230,236,229,120,128,1,116,100,2,32,160,32,170, +233,229,242,229,243,233,115,128,30,132,239,116,2,32,177,32, +186,225,227,227,229,238,116,128,30,134,226,229,236,239,119,128, +30,136,231,242,225,246,101,128,30,128,237,239,238,239,243,240, +225,227,101,128,255,55,243,237,225,236,108,128,247,119,88,134, +0,88,32,238,32,247,33,18,33,31,33,35,33,47,227,233, +242,227,236,101,128,36,205,100,2,32,253,33,7,233,229,242, +229,243,233,115,128,30,140,239,244,225,227,227,229,238,116,128, +30,138,229,232,225,242,237,229,238,233,225,110,128,5,61,105, +128,3,158,237,239,238,239,243,240,225,227,101,128,255,56,243, +237,225,236,108,128,247,120,89,139,0,89,33,81,33,116,33, +139,33,189,33,228,33,236,33,253,34,40,34,52,34,60,34, +68,97,2,33,87,33,104,227,245,244,101,129,0,221,33,96, +243,237,225,236,108,128,247,253,244,227,249,242,233,236,236,233, +99,128,4,98,227,233,242,99,2,33,125,33,130,236,101,128, +36,206,245,237,230,236,229,120,128,1,118,100,2,33,145,33, +165,233,229,242,229,243,233,115,129,1,120,33,157,243,237,225, +236,108,128,247,255,239,116,2,33,172,33,181,225,227,227,229, +238,116,128,30,142,226,229,236,239,119,128,30,244,229,114,2, +33,196,33,208,233,227,249,242,233,236,236,233,99,128,4,43, +245,228,233,229,242,229,243,233,243,227,249,242,233,236,236,233, +99,128,4,248,231,242,225,246,101,128,30,242,232,239,239,107, +129,1,179,33,245,225,226,239,246,101,128,30,246,105,3,34, +5,34,16,34,27,225,242,237,229,238,233,225,110,128,5,69, +227,249,242,233,236,236,233,99,128,4,7,247,238,225,242,237, +229,238,233,225,110,128,5,82,237,239,238,239,243,240,225,227, +101,128,255,57,243,237,225,236,108,128,247,121,244,233,236,228, +101,128,30,248,245,115,2,34,75,34,113,226,233,103,2,34, +83,34,94,227,249,242,233,236,236,233,99,128,4,106,233,239, +244,233,230,233,229,228,227,249,242,233,236,236,233,99,128,4, +108,236,233,244,244,236,101,2,34,124,34,135,227,249,242,233, +236,236,233,99,128,4,102,233,239,244,233,230,233,229,228,227, +249,242,233,236,236,233,99,128,4,104,90,136,0,90,34,174, +34,198,34,243,35,14,35,81,35,173,35,185,35,197,97,2, +34,180,34,191,225,242,237,229,238,233,225,110,128,5,54,227, +245,244,101,128,1,121,99,2,34,204,34,221,225,242,239,110, +129,1,125,34,213,243,237,225,236,108,128,246,255,233,242,99, +2,34,229,34,234,236,101,128,36,207,245,237,230,236,229,120, +128,30,144,228,239,116,130,1,123,34,253,35,6,225,227,227, +229,238,116,128,1,123,226,229,236,239,119,128,30,146,101,3, +35,22,35,33,35,76,227,249,242,233,236,236,233,99,128,4, +23,100,2,35,39,35,58,229,243,227,229,238,228,229,242,227, +249,242,233,236,236,233,99,128,4,152,233,229,242,229,243,233, +243,227,249,242,233,236,236,233,99,128,4,222,244,97,128,3, +150,232,101,4,35,92,35,103,35,119,35,130,225,242,237,229, +238,233,225,110,128,5,58,226,242,229,246,229,227,249,242,233, +236,236,233,99,128,4,193,227,249,242,233,236,236,233,99,128, +4,22,100,2,35,136,35,155,229,243,227,229,238,228,229,242, +227,249,242,233,236,236,233,99,128,4,150,233,229,242,229,243, +233,243,227,249,242,233,236,236,233,99,128,4,220,236,233,238, +229,226,229,236,239,119,128,30,148,237,239,238,239,243,240,225, +227,101,128,255,58,115,2,35,203,35,210,237,225,236,108,128, +247,122,244,242,239,235,101,128,1,181,97,158,0,97,36,26, +38,154,39,4,39,68,39,132,39,196,40,4,40,68,40,126, +40,190,41,70,41,217,42,137,42,237,43,17,49,192,49,229, +50,0,50,225,51,7,52,96,52,168,53,123,53,132,54,5, +56,13,57,3,57,50,57,201,57,215,49,138,39,1,36,50, +36,114,36,154,36,218,37,26,37,90,37,154,37,218,38,26, +38,90,48,138,39,33,36,74,36,78,36,82,36,86,36,90, +36,94,36,98,36,102,36,106,36,110,48,128,39,94,49,128, +39,97,50,128,39,98,51,128,39,99,52,128,39,100,53,128, +39,16,54,128,39,101,55,128,39,102,56,128,39,103,57,128, +38,96,49,134,38,27,36,130,36,134,36,138,36,142,36,146, +36,150,48,128,38,101,49,128,38,102,50,128,38,99,55,128, +39,9,56,128,39,8,57,128,39,7,50,138,38,30,36,178, +36,182,36,186,36,190,36,194,36,198,36,202,36,206,36,210, +36,214,48,128,36,96,49,128,36,97,50,128,36,98,51,128, +36,99,52,128,36,100,53,128,36,101,54,128,36,102,55,128, +36,103,56,128,36,104,57,128,36,105,51,138,39,12,36,242, +36,246,36,250,36,254,37,2,37,6,37,10,37,14,37,18, +37,22,48,128,39,118,49,128,39,119,50,128,39,120,51,128, +39,121,52,128,39,122,53,128,39,123,54,128,39,124,55,128, +39,125,56,128,39,126,57,128,39,127,52,138,39,13,37,50, +37,54,37,58,37,62,37,66,37,70,37,74,37,78,37,82, +37,86,48,128,39,128,49,128,39,129,50,128,39,130,51,128, +39,131,52,128,39,132,53,128,39,133,54,128,39,134,55,128, +39,135,56,128,39,136,57,128,39,137,53,138,39,14,37,114, +37,118,37,122,37,126,37,130,37,134,37,138,37,142,37,146, +37,150,48,128,39,138,49,128,39,139,50,128,39,140,51,128, +39,141,52,128,39,142,53,128,39,143,54,128,39,144,55,128, +39,145,56,128,39,146,57,128,39,147,54,138,39,15,37,178, +37,182,37,186,37,190,37,194,37,198,37,202,37,206,37,210, +37,214,48,128,39,148,49,128,33,146,50,128,39,163,51,128, +33,148,52,128,33,149,53,128,39,153,54,128,39,155,55,128, +39,156,56,128,39,157,57,128,39,158,55,138,39,17,37,242, +37,246,37,250,37,254,38,2,38,6,38,10,38,14,38,18, +38,22,48,128,39,159,49,128,39,160,50,128,39,161,51,128, +39,162,52,128,39,164,53,128,39,165,54,128,39,166,55,128, +39,167,56,128,39,168,57,128,39,169,56,138,39,18,38,50, +38,54,38,58,38,62,38,66,38,70,38,74,38,78,38,82, +38,86,48,128,39,171,49,128,39,173,50,128,39,175,51,128, +39,178,52,128,39,179,53,128,39,181,54,128,39,184,55,128, +39,186,56,128,39,187,57,128,39,188,57,138,39,19,38,114, +38,118,38,122,38,126,38,130,38,134,38,138,38,142,38,146, +38,150,48,128,39,189,49,128,39,190,50,128,39,154,51,128, +39,170,52,128,39,182,53,128,39,185,54,128,39,152,55,128, +39,180,56,128,39,183,57,128,39,172,50,138,39,2,38,178, +38,224,38,228,38,232,38,236,38,240,38,244,38,248,38,252, +39,0,48,135,39,20,38,196,38,200,38,204,38,208,38,212, +38,216,38,220,48,128,39,174,49,128,39,177,50,128,39,3, +51,128,39,80,52,128,39,82,53,128,39,110,54,128,39,112, +49,128,39,21,50,128,39,22,51,128,39,23,52,128,39,24, +53,128,39,25,54,128,39,26,55,128,39,27,56,128,39,28, +57,128,39,34,51,138,39,4,39,28,39,32,39,36,39,40, +39,44,39,48,39,52,39,56,39,60,39,64,48,128,39,35, +49,128,39,36,50,128,39,37,51,128,39,38,52,128,39,39, +53,128,38,5,54,128,39,41,55,128,39,42,56,128,39,43, +57,128,39,44,52,138,38,14,39,92,39,96,39,100,39,104, +39,108,39,112,39,116,39,120,39,124,39,128,48,128,39,45, +49,128,39,46,50,128,39,47,51,128,39,48,52,128,39,49, +53,128,39,50,54,128,39,51,55,128,39,52,56,128,39,53, +57,128,39,54,53,138,39,6,39,156,39,160,39,164,39,168, +39,172,39,176,39,180,39,184,39,188,39,192,48,128,39,55, +49,128,39,56,50,128,39,57,51,128,39,58,52,128,39,59, +53,128,39,60,54,128,39,61,55,128,39,62,56,128,39,63, +57,128,39,64,54,138,39,29,39,220,39,224,39,228,39,232, +39,236,39,240,39,244,39,248,39,252,40,0,48,128,39,65, +49,128,39,66,50,128,39,67,51,128,39,68,52,128,39,69, +53,128,39,70,54,128,39,71,55,128,39,72,56,128,39,73, +57,128,39,74,55,138,39,30,40,28,40,32,40,36,40,40, +40,44,40,48,40,52,40,56,40,60,40,64,48,128,39,75, +49,128,37,207,50,128,39,77,51,128,37,160,52,128,39,79, +53,128,39,81,54,128,37,178,55,128,37,188,56,128,37,198, +57,128,39,86,56,137,39,31,40,90,40,94,40,98,40,102, +40,106,40,110,40,114,40,118,40,122,49,128,37,215,50,128, +39,88,51,128,39,89,52,128,39,90,53,128,39,111,54,128, +39,113,55,128,39,114,56,128,39,115,57,128,39,104,57,138, +39,32,40,150,40,154,40,158,40,162,40,166,40,170,40,174, +40,178,40,182,40,186,48,128,39,105,49,128,39,108,50,128, +39,109,51,128,39,106,52,128,39,107,53,128,39,116,54,128, +39,117,55,128,39,91,56,128,39,92,57,128,39,93,97,7, +40,206,40,216,40,223,40,230,40,255,41,15,41,26,226,229, +238,231,225,236,105,128,9,134,227,245,244,101,128,0,225,228, +229,246,97,128,9,6,231,117,2,40,237,40,246,234,225,242, +225,244,105,128,10,134,242,237,245,235,232,105,128,10,6,237, +225,244,242,225,231,245,242,237,245,235,232,105,128,10,62,242, +245,243,241,245,225,242,101,128,51,3,246,239,247,229,236,243, +233,231,110,3,41,42,41,52,41,59,226,229,238,231,225,236, +105,128,9,190,228,229,246,97,128,9,62,231,245,234,225,242, +225,244,105,128,10,190,98,4,41,80,41,121,41,130,41,140, +226,242,229,246,233,225,244,233,239,110,2,41,95,41,110,237, +225,242,235,225,242,237,229,238,233,225,110,128,5,95,243,233, +231,238,228,229,246,97,128,9,112,229,238,231,225,236,105,128, +9,133,239,240,239,237,239,230,111,128,49,26,242,229,246,101, +134,1,3,41,159,41,167,41,178,41,189,41,197,41,209,225, +227,245,244,101,128,30,175,227,249,242,233,236,236,233,99,128, +4,209,228,239,244,226,229,236,239,119,128,30,183,231,242,225, +246,101,128,30,177,232,239,239,235,225,226,239,246,101,128,30, +179,244,233,236,228,101,128,30,181,99,4,41,227,41,234,42, +57,42,127,225,242,239,110,128,1,206,233,242,99,2,41,242, +41,247,236,101,128,36,208,245,237,230,236,229,120,133,0,226, +42,10,42,18,42,29,42,37,42,49,225,227,245,244,101,128, +30,165,228,239,244,226,229,236,239,119,128,30,173,231,242,225, +246,101,128,30,167,232,239,239,235,225,226,239,246,101,128,30, +169,244,233,236,228,101,128,30,171,245,244,101,133,0,180,42, +73,42,84,42,101,42,108,42,117,226,229,236,239,247,227,237, +98,128,3,23,99,2,42,90,42,95,237,98,128,3,1,239, +237,98,128,3,1,228,229,246,97,128,9,84,236,239,247,237, +239,100,128,2,207,244,239,238,229,227,237,98,128,3,65,249, +242,233,236,236,233,99,128,4,48,100,5,42,149,42,159,42, +173,42,179,42,213,226,236,231,242,225,246,101,128,2,1,228, +225,235,231,245,242,237,245,235,232,105,128,10,113,229,246,97, +128,9,5,233,229,242,229,243,233,115,130,0,228,42,193,42, +204,227,249,242,233,236,236,233,99,128,4,211,237,225,227,242, +239,110,128,1,223,239,116,2,42,220,42,228,226,229,236,239, +119,128,30,161,237,225,227,242,239,110,128,1,225,101,131,0, +230,42,247,42,255,43,8,225,227,245,244,101,128,1,253,235, +239,242,229,225,110,128,49,80,237,225,227,242,239,110,128,1, +227,230,233,105,6,43,33,43,53,45,246,45,252,46,11,49, +111,48,2,43,39,43,46,176,178,176,56,128,32,21,184,185, +180,49,128,32,164,177,48,3,43,62,45,86,45,221,48,9, +43,82,43,102,43,164,43,226,44,32,44,94,44,156,44,218, +45,24,49,3,43,90,43,94,43,98,55,128,4,16,56,128, +4,17,57,128,4,18,50,10,43,124,43,128,43,132,43,136, +43,140,43,144,43,148,43,152,43,156,43,160,48,128,4,19, +49,128,4,20,50,128,4,21,51,128,4,1,52,128,4,22, +53,128,4,23,54,128,4,24,55,128,4,25,56,128,4,26, +57,128,4,27,51,10,43,186,43,190,43,194,43,198,43,202, +43,206,43,210,43,214,43,218,43,222,48,128,4,28,49,128, +4,29,50,128,4,30,51,128,4,31,52,128,4,32,53,128, +4,33,54,128,4,34,55,128,4,35,56,128,4,36,57,128, +4,37,52,10,43,248,43,252,44,0,44,4,44,8,44,12, +44,16,44,20,44,24,44,28,48,128,4,38,49,128,4,39, +50,128,4,40,51,128,4,41,52,128,4,42,53,128,4,43, +54,128,4,44,55,128,4,45,56,128,4,46,57,128,4,47, +53,10,44,54,44,58,44,62,44,66,44,70,44,74,44,78, +44,82,44,86,44,90,48,128,4,144,49,128,4,2,50,128, +4,3,51,128,4,4,52,128,4,5,53,128,4,6,54,128, +4,7,55,128,4,8,56,128,4,9,57,128,4,10,54,10, +44,116,44,120,44,124,44,128,44,132,44,136,44,140,44,144, +44,148,44,152,48,128,4,11,49,128,4,12,50,128,4,14, +51,128,246,196,52,128,246,197,53,128,4,48,54,128,4,49, +55,128,4,50,56,128,4,51,57,128,4,52,55,10,44,178, +44,182,44,186,44,190,44,194,44,198,44,202,44,206,44,210, +44,214,48,128,4,53,49,128,4,81,50,128,4,54,51,128, +4,55,52,128,4,56,53,128,4,57,54,128,4,58,55,128, +4,59,56,128,4,60,57,128,4,61,56,10,44,240,44,244, +44,248,44,252,45,0,45,4,45,8,45,12,45,16,45,20, +48,128,4,62,49,128,4,63,50,128,4,64,51,128,4,65, +52,128,4,66,53,128,4,67,54,128,4,68,55,128,4,69, +56,128,4,70,57,128,4,71,57,10,45,46,45,50,45,54, +45,58,45,62,45,66,45,70,45,74,45,78,45,82,48,128, +4,72,49,128,4,73,50,128,4,74,51,128,4,75,52,128, +4,76,53,128,4,77,54,128,4,78,55,128,4,79,56,128, +4,145,57,128,4,82,49,4,45,96,45,158,45,163,45,189, +48,10,45,118,45,122,45,126,45,130,45,134,45,138,45,142, +45,146,45,150,45,154,48,128,4,83,49,128,4,84,50,128, +4,85,51,128,4,86,52,128,4,87,53,128,4,88,54,128, +4,89,55,128,4,90,56,128,4,91,57,128,4,92,177,48, +128,4,94,52,4,45,173,45,177,45,181,45,185,53,128,4, +15,54,128,4,98,55,128,4,114,56,128,4,116,57,5,45, +201,45,205,45,209,45,213,45,217,50,128,246,198,51,128,4, +95,52,128,4,99,53,128,4,115,54,128,4,117,56,2,45, +227,45,241,51,2,45,233,45,237,49,128,246,199,50,128,246, +200,180,54,128,4,217,178,185,57,128,32,14,179,48,2,46, +3,46,7,48,128,32,15,49,128,32,13,181,55,7,46,28, +46,98,47,163,47,240,48,197,49,34,49,105,51,2,46,34, +46,48,56,2,46,40,46,44,49,128,6,106,56,128,6,12, +57,8,46,66,46,70,46,74,46,78,46,82,46,86,46,90, +46,94,50,128,6,96,51,128,6,97,52,128,6,98,53,128, +6,99,54,128,6,100,55,128,6,101,56,128,6,102,57,128, +6,103,52,7,46,114,46,146,46,208,47,14,47,46,47,102, +47,158,48,5,46,126,46,130,46,134,46,138,46,142,48,128, +6,104,49,128,6,105,51,128,6,27,55,128,6,31,57,128, +6,33,49,10,46,168,46,172,46,176,46,180,46,184,46,188, +46,192,46,196,46,200,46,204,48,128,6,34,49,128,6,35, +50,128,6,36,51,128,6,37,52,128,6,38,53,128,6,39, +54,128,6,40,55,128,6,41,56,128,6,42,57,128,6,43, +50,10,46,230,46,234,46,238,46,242,46,246,46,250,46,254, +47,2,47,6,47,10,48,128,6,44,49,128,6,45,50,128, +6,46,51,128,6,47,52,128,6,48,53,128,6,49,54,128, +6,50,55,128,6,51,56,128,6,52,57,128,6,53,51,5, +47,26,47,30,47,34,47,38,47,42,48,128,6,54,49,128, +6,55,50,128,6,56,51,128,6,57,52,128,6,58,52,9, +47,66,47,70,47,74,47,78,47,82,47,86,47,90,47,94, +47,98,48,128,6,64,49,128,6,65,50,128,6,66,51,128, +6,67,52,128,6,68,53,128,6,69,54,128,6,70,56,128, +6,72,57,128,6,73,53,9,47,122,47,126,47,130,47,134, +47,138,47,142,47,146,47,150,47,154,48,128,6,74,49,128, +6,75,50,128,6,76,51,128,6,77,52,128,6,78,53,128, +6,79,54,128,6,80,55,128,6,81,56,128,6,82,183,48, +128,6,71,53,3,47,171,47,203,47,235,48,5,47,183,47, +187,47,191,47,195,47,199,53,128,6,164,54,128,6,126,55, +128,6,134,56,128,6,152,57,128,6,175,49,5,47,215,47, +219,47,223,47,227,47,231,49,128,6,121,50,128,6,136,51, +128,6,145,52,128,6,186,57,128,6,210,179,52,128,6,213, +54,7,48,0,48,5,48,10,48,15,48,53,48,115,48,177, +179,54,128,32,170,180,53,128,5,190,181,56,128,5,195,54, +6,48,29,48,33,48,37,48,41,48,45,48,49,52,128,5, +208,53,128,5,209,54,128,5,210,55,128,5,211,56,128,5, +212,57,128,5,213,55,10,48,75,48,79,48,83,48,87,48, +91,48,95,48,99,48,103,48,107,48,111,48,128,5,214,49, +128,5,215,50,128,5,216,51,128,5,217,52,128,5,218,53, +128,5,219,54,128,5,220,55,128,5,221,56,128,5,222,57, +128,5,223,56,10,48,137,48,141,48,145,48,149,48,153,48, +157,48,161,48,165,48,169,48,173,48,128,5,224,49,128,5, +225,50,128,5,226,51,128,5,227,52,128,5,228,53,128,5, +229,54,128,5,230,55,128,5,231,56,128,5,232,57,128,5, +233,57,3,48,185,48,189,48,193,48,128,5,234,52,128,251, +42,53,128,251,43,55,4,48,207,48,221,48,241,48,246,48, +2,48,213,48,217,48,128,251,75,53,128,251,31,49,3,48, +229,48,233,48,237,54,128,5,240,55,128,5,241,56,128,5, +242,178,51,128,251,53,57,7,49,6,49,10,49,14,49,18, +49,22,49,26,49,30,51,128,5,180,52,128,5,181,53,128, +5,182,54,128,5,187,55,128,5,184,56,128,5,183,57,128, +5,176,56,3,49,42,49,86,49,91,48,7,49,58,49,62, +49,66,49,70,49,74,49,78,49,82,48,128,5,178,49,128, +5,177,50,128,5,179,51,128,5,194,52,128,5,193,54,128, +5,185,55,128,5,188,179,57,128,5,189,52,2,49,97,49, +101,49,128,5,191,50,128,5,192,185,178,57,128,2,188,54, +3,49,119,49,178,49,185,49,4,49,129,49,145,49,151,49, +172,50,2,49,135,49,140,180,56,128,33,5,184,57,128,33, +19,179,181,50,128,33,22,181,55,3,49,160,49,164,49,168, +51,128,32,44,52,128,32,45,53,128,32,46,182,182,52,128, +32,12,179,177,182,55,128,6,109,180,185,179,55,128,2,189, +103,2,49,198,49,205,242,225,246,101,128,0,224,117,2,49, +211,49,220,234,225,242,225,244,105,128,10,133,242,237,245,235, +232,105,128,10,5,104,2,49,235,49,245,233,242,225,231,225, +238,97,128,48,66,239,239,235,225,226,239,246,101,128,30,163, +105,7,50,16,50,41,50,48,50,60,50,85,50,101,50,181, +98,2,50,22,50,31,229,238,231,225,236,105,128,9,144,239, +240,239,237,239,230,111,128,49,30,228,229,246,97,128,9,16, +229,227,249,242,233,236,236,233,99,128,4,213,231,117,2,50, +67,50,76,234,225,242,225,244,105,128,10,144,242,237,245,235, +232,105,128,10,16,237,225,244,242,225,231,245,242,237,245,235, +232,105,128,10,72,110,5,50,113,50,122,50,136,50,152,50, +167,225,242,225,226,233,99,128,6,57,230,233,238,225,236,225, +242,225,226,233,99,128,254,202,233,238,233,244,233,225,236,225, +242,225,226,233,99,128,254,203,237,229,228,233,225,236,225,242, +225,226,233,99,128,254,204,246,229,242,244,229,228,226,242,229, +246,101,128,2,3,246,239,247,229,236,243,233,231,110,3,50, +197,50,207,50,214,226,229,238,231,225,236,105,128,9,200,228, +229,246,97,128,9,72,231,245,234,225,242,225,244,105,128,10, +200,107,2,50,231,50,255,225,244,225,235,225,238,97,129,48, +162,50,243,232,225,236,230,247,233,228,244,104,128,255,113,239, +242,229,225,110,128,49,79,108,3,51,15,52,71,52,80,101, +2,51,21,52,66,102,136,5,208,51,41,51,50,51,65,51, +79,51,168,51,182,52,37,52,51,225,242,225,226,233,99,128, +6,39,228,225,231,229,243,232,232,229,226,242,229,119,128,251, +48,230,233,238,225,236,225,242,225,226,233,99,128,254,142,104, +2,51,85,51,160,225,237,250,97,2,51,94,51,127,225,226, +239,246,101,2,51,104,51,113,225,242,225,226,233,99,128,6, +35,230,233,238,225,236,225,242,225,226,233,99,128,254,132,226, +229,236,239,119,2,51,137,51,146,225,242,225,226,233,99,128, +6,37,230,233,238,225,236,225,242,225,226,233,99,128,254,136, +229,226,242,229,119,128,5,208,236,225,237,229,228,232,229,226, +242,229,119,128,251,79,237,97,2,51,189,51,225,228,228,225, +225,226,239,246,101,2,51,202,51,211,225,242,225,226,233,99, +128,6,34,230,233,238,225,236,225,242,225,226,233,99,128,254, +130,235,243,245,242,97,4,51,239,51,248,52,6,52,22,225, +242,225,226,233,99,128,6,73,230,233,238,225,236,225,242,225, +226,233,99,128,254,240,233,238,233,244,233,225,236,225,242,225, +226,233,99,128,254,243,237,229,228,233,225,236,225,242,225,226, +233,99,128,254,244,240,225,244,225,232,232,229,226,242,229,119, +128,251,46,241,225,237,225,244,243,232,229,226,242,229,119,128, +251,47,240,104,128,33,53,236,229,241,245,225,108,128,34,76, +240,232,97,129,3,177,52,88,244,239,238,239,115,128,3,172, +109,4,52,106,52,114,52,125,52,159,225,227,242,239,110,128, +1,1,239,238,239,243,240,225,227,101,128,255,65,240,229,242, +243,225,238,100,130,0,38,52,139,52,151,237,239,238,239,243, +240,225,227,101,128,255,6,243,237,225,236,108,128,247,38,243, +241,245,225,242,101,128,51,194,110,4,52,178,52,189,53,55, +53,65,226,239,240,239,237,239,230,111,128,49,34,103,4,52, +199,52,210,52,224,53,47,226,239,240,239,237,239,230,111,128, +49,36,235,232,225,238,235,232,245,244,232,225,105,128,14,90, +236,101,131,34,32,52,235,53,32,53,39,226,242,225,227,235, +229,116,2,52,247,53,11,236,229,230,116,129,48,8,53,0, +246,229,242,244,233,227,225,108,128,254,63,242,233,231,232,116, +129,48,9,53,21,246,229,242,244,233,227,225,108,128,254,64, +236,229,230,116,128,35,41,242,233,231,232,116,128,35,42,243, +244,242,239,109,128,33,43,239,244,229,236,229,233,97,128,3, +135,117,2,53,71,53,83,228,225,244,244,225,228,229,246,97, +128,9,82,243,246,225,242,97,3,53,95,53,105,53,112,226, +229,238,231,225,236,105,128,9,130,228,229,246,97,128,9,2, +231,245,234,225,242,225,244,105,128,10,130,239,231,239,238,229, +107,128,1,5,112,3,53,140,53,164,53,194,97,2,53,146, +53,158,225,244,239,243,241,245,225,242,101,128,51,0,242,229, +110,128,36,156,239,243,244,242,239,240,232,101,2,53,177,53, +188,225,242,237,229,238,233,225,110,128,5,90,237,239,100,128, +2,188,112,2,53,200,53,205,236,101,128,248,255,242,111,2, +53,212,53,220,225,227,232,229,115,128,34,80,120,2,53,226, +53,246,229,241,245,225,108,129,34,72,53,236,239,242,233,237, +225,231,101,128,34,82,233,237,225,244,229,236,249,229,241,245, +225,108,128,34,69,114,4,54,15,54,42,54,46,54,91,225, +229,97,2,54,23,54,33,229,235,239,242,229,225,110,128,49, +142,235,239,242,229,225,110,128,49,141,99,128,35,18,105,2, +54,52,54,66,231,232,244,232,225,236,230,242,233,238,103,128, +30,154,238,103,130,0,229,54,75,54,83,225,227,245,244,101, +128,1,251,226,229,236,239,119,128,30,1,242,239,119,8,54, +111,54,118,54,247,55,57,55,107,55,162,55,185,56,4,226, +239,244,104,128,33,148,100,3,54,126,54,165,54,212,225,243, +104,4,54,138,54,145,54,152,54,160,228,239,247,110,128,33, +227,236,229,230,116,128,33,224,242,233,231,232,116,128,33,226, +245,112,128,33,225,226,108,5,54,178,54,185,54,192,54,199, +54,207,226,239,244,104,128,33,212,228,239,247,110,128,33,211, +236,229,230,116,128,33,208,242,233,231,232,116,128,33,210,245, +112,128,33,209,239,247,110,131,33,147,54,224,54,231,54,239, +236,229,230,116,128,33,153,242,233,231,232,116,128,33,152,247, +232,233,244,101,128,33,233,104,2,54,253,55,48,229,225,100, +4,55,9,55,19,55,29,55,40,228,239,247,238,237,239,100, +128,2,197,236,229,230,244,237,239,100,128,2,194,242,233,231, +232,244,237,239,100,128,2,195,245,240,237,239,100,128,2,196, +239,242,233,250,229,120,128,248,231,236,229,230,116,131,33,144, +55,70,55,87,55,99,228,226,108,129,33,208,55,78,243,244, +242,239,235,101,128,33,205,239,246,229,242,242,233,231,232,116, +128,33,198,247,232,233,244,101,128,33,230,242,233,231,232,116, +132,33,146,55,123,55,135,55,143,55,154,228,226,236,243,244, +242,239,235,101,128,33,207,232,229,225,246,121,128,39,158,239, +246,229,242,236,229,230,116,128,33,196,247,232,233,244,101,128, +33,232,244,225,98,2,55,170,55,177,236,229,230,116,128,33, +228,242,233,231,232,116,128,33,229,245,112,132,33,145,55,198, +55,226,55,244,55,252,100,2,55,204,55,216,110,129,33,149, +55,210,226,243,101,128,33,168,239,247,238,226,225,243,101,128, +33,168,236,229,230,116,129,33,150,55,235,239,230,228,239,247, +110,128,33,197,242,233,231,232,116,128,33,151,247,232,233,244, +101,128,33,231,246,229,242,244,229,120,128,248,230,115,5,56, +25,56,101,56,146,56,229,56,239,99,2,56,31,56,83,233, +105,2,56,38,56,61,227,233,242,227,245,109,129,0,94,56, +49,237,239,238,239,243,240,225,227,101,128,255,62,244,233,236, +228,101,129,0,126,56,71,237,239,238,239,243,240,225,227,101, +128,255,94,242,233,240,116,129,2,81,56,92,244,245,242,238, +229,100,128,2,82,237,225,236,108,2,56,110,56,121,232,233, +242,225,231,225,238,97,128,48,65,235,225,244,225,235,225,238, +97,129,48,161,56,134,232,225,236,230,247,233,228,244,104,128, +255,103,244,229,242,233,115,2,56,156,56,225,107,131,0,42, +56,166,56,194,56,217,97,2,56,172,56,186,236,244,239,238, +229,225,242,225,226,233,99,128,6,109,242,225,226,233,99,128, +6,109,109,2,56,200,56,206,225,244,104,128,34,23,239,238, +239,243,240,225,227,101,128,255,10,243,237,225,236,108,128,254, +97,109,128,32,66,245,240,229,242,233,239,114,128,246,233,249, +237,240,244,239,244,233,227,225,236,236,249,229,241,245,225,108, +128,34,67,116,132,0,64,57,15,57,22,57,34,57,42,233, +236,228,101,128,0,227,237,239,238,239,243,240,225,227,101,128, +255,32,243,237,225,236,108,128,254,107,245,242,238,229,100,128, +2,80,117,6,57,64,57,89,57,96,57,121,57,141,57,157, +98,2,57,70,57,79,229,238,231,225,236,105,128,9,148,239, +240,239,237,239,230,111,128,49,32,228,229,246,97,128,9,20, +231,117,2,57,103,57,112,234,225,242,225,244,105,128,10,148, +242,237,245,235,232,105,128,10,20,236,229,238,231,244,232,237, +225,242,235,226,229,238,231,225,236,105,128,9,215,237,225,244, +242,225,231,245,242,237,245,235,232,105,128,10,76,246,239,247, +229,236,243,233,231,110,3,57,173,57,183,57,190,226,229,238, +231,225,236,105,128,9,204,228,229,246,97,128,9,76,231,245, +234,225,242,225,244,105,128,10,204,246,225,231,242,225,232,225, +228,229,246,97,128,9,61,121,2,57,221,57,233,226,225,242, +237,229,238,233,225,110,128,5,97,233,110,130,5,226,57,242, +58,1,225,236,244,239,238,229,232,229,226,242,229,119,128,251, +32,232,229,226,242,229,119,128,5,226,98,144,0,98,58,46, +58,181,58,192,58,201,58,226,60,11,60,73,60,146,62,72, +62,84,62,127,62,135,62,145,64,15,64,39,64,48,97,7, +58,62,58,72,58,96,58,103,58,128,58,152,58,163,226,229, +238,231,225,236,105,128,9,172,227,235,243,236,225,243,104,129, +0,92,58,84,237,239,238,239,243,240,225,227,101,128,255,60, +228,229,246,97,128,9,44,231,117,2,58,110,58,119,234,225, +242,225,244,105,128,10,172,242,237,245,235,232,105,128,10,44, +104,2,58,134,58,144,233,242,225,231,225,238,97,128,48,112, +244,244,232,225,105,128,14,63,235,225,244,225,235,225,238,97, +128,48,208,114,129,0,124,58,169,237,239,238,239,243,240,225, +227,101,128,255,92,226,239,240,239,237,239,230,111,128,49,5, +227,233,242,227,236,101,128,36,209,228,239,116,2,58,209,58, +218,225,227,227,229,238,116,128,30,3,226,229,236,239,119,128, +30,5,101,6,58,240,59,5,59,28,59,170,59,181,59,193, +225,237,229,228,243,233,248,244,229,229,238,244,232,238,239,244, +229,115,128,38,108,99,2,59,11,59,18,225,245,243,101,128, +34,53,249,242,233,236,236,233,99,128,4,49,104,5,59,40, +59,49,59,63,59,93,59,152,225,242,225,226,233,99,128,6, +40,230,233,238,225,236,225,242,225,226,233,99,128,254,144,105, +2,59,69,59,84,238,233,244,233,225,236,225,242,225,226,233, +99,128,254,145,242,225,231,225,238,97,128,48,121,237,101,2, +59,100,59,113,228,233,225,236,225,242,225,226,233,99,128,254, +146,229,237,105,2,59,121,59,136,238,233,244,233,225,236,225, +242,225,226,233,99,128,252,159,243,239,236,225,244,229,228,225, +242,225,226,233,99,128,252,8,238,239,239,238,230,233,238,225, +236,225,242,225,226,233,99,128,252,109,235,225,244,225,235,225, +238,97,128,48,217,238,225,242,237,229,238,233,225,110,128,5, +98,116,132,5,209,59,205,59,225,59,245,59,254,97,129,3, +178,59,211,243,249,237,226,239,236,231,242,229,229,107,128,3, +208,228,225,231,229,243,104,129,251,49,59,236,232,229,226,242, +229,119,128,251,49,232,229,226,242,229,119,128,5,209,242,225, +230,229,232,229,226,242,229,119,128,251,76,104,2,60,17,60, +67,97,3,60,25,60,35,60,42,226,229,238,231,225,236,105, +128,9,173,228,229,246,97,128,9,45,231,117,2,60,49,60, +58,234,225,242,225,244,105,128,10,173,242,237,245,235,232,105, +128,10,45,239,239,107,128,2,83,105,5,60,85,60,96,60, +107,60,121,60,135,232,233,242,225,231,225,238,97,128,48,115, +235,225,244,225,235,225,238,97,128,48,211,236,225,226,233,225, +236,227,236,233,227,107,128,2,152,238,228,233,231,245,242,237, +245,235,232,105,128,10,2,242,245,243,241,245,225,242,101,128, +51,49,108,3,60,154,62,55,62,66,97,2,60,160,62,50, +227,107,6,60,175,60,184,60,221,61,114,61,169,61,221,227, +233,242,227,236,101,128,37,207,100,2,60,190,60,199,233,225, +237,239,238,100,128,37,198,239,247,238,240,239,233,238,244,233, +238,231,244,242,233,225,238,231,236,101,128,37,188,108,2,60, +227,61,74,101,2,60,233,61,13,230,244,240,239,233,238,244, +233,238,103,2,60,248,61,2,240,239,233,238,244,229,114,128, +37,196,244,242,233,225,238,231,236,101,128,37,192,238,244,233, +227,245,236,225,242,226,242,225,227,235,229,116,2,61,33,61, +53,236,229,230,116,129,48,16,61,42,246,229,242,244,233,227, +225,108,128,254,59,242,233,231,232,116,129,48,17,61,63,246, +229,242,244,233,227,225,108,128,254,60,239,247,229,114,2,61, +83,61,98,236,229,230,244,244,242,233,225,238,231,236,101,128, +37,227,242,233,231,232,244,244,242,233,225,238,231,236,101,128, +37,226,114,2,61,120,61,131,229,227,244,225,238,231,236,101, +128,37,172,233,231,232,244,240,239,233,238,244,233,238,103,2, +61,148,61,158,240,239,233,238,244,229,114,128,37,186,244,242, +233,225,238,231,236,101,128,37,182,115,3,61,177,61,207,61, +215,109,2,61,183,61,195,225,236,236,243,241,245,225,242,101, +128,37,170,233,236,233,238,231,230,225,227,101,128,38,59,241, +245,225,242,101,128,37,160,244,225,114,128,38,5,245,240,112, +2,61,229,62,11,229,114,2,61,236,61,251,236,229,230,244, +244,242,233,225,238,231,236,101,128,37,228,242,233,231,232,244, +244,242,233,225,238,231,236,101,128,37,229,239,233,238,244,233, +238,103,2,62,23,62,39,243,237,225,236,236,244,242,233,225, +238,231,236,101,128,37,180,244,242,233,225,238,231,236,101,128, +37,178,238,107,128,36,35,233,238,229,226,229,236,239,119,128, +30,7,239,227,107,128,37,136,237,239,238,239,243,240,225,227, +101,128,255,66,111,3,62,92,62,105,62,116,226,225,233,237, +225,233,244,232,225,105,128,14,26,232,233,242,225,231,225,238, +97,128,48,124,235,225,244,225,235,225,238,97,128,48,220,240, +225,242,229,110,128,36,157,241,243,241,245,225,242,101,128,51, +195,114,4,62,155,63,149,63,222,64,5,225,99,2,62,162, +63,56,101,3,62,170,62,175,62,243,229,120,128,248,244,236, +229,230,116,133,0,123,62,192,62,197,62,219,62,227,62,232, +226,116,128,248,243,109,2,62,203,62,208,233,100,128,248,242, +239,238,239,243,240,225,227,101,128,255,91,243,237,225,236,108, +128,254,91,244,112,128,248,241,246,229,242,244,233,227,225,108, +128,254,55,242,233,231,232,116,133,0,125,63,5,63,10,63, +32,63,40,63,45,226,116,128,248,254,109,2,63,16,63,21, +233,100,128,248,253,239,238,239,243,240,225,227,101,128,255,93, +243,237,225,236,108,128,254,92,244,112,128,248,252,246,229,242, +244,233,227,225,108,128,254,56,235,229,116,2,63,64,63,106, +236,229,230,116,132,0,91,63,79,63,84,63,89,63,101,226, +116,128,248,240,229,120,128,248,239,237,239,238,239,243,240,225, +227,101,128,255,59,244,112,128,248,238,242,233,231,232,116,132, +0,93,63,122,63,127,63,132,63,144,226,116,128,248,251,229, +120,128,248,250,237,239,238,239,243,240,225,227,101,128,255,61, +244,112,128,248,249,229,246,101,131,2,216,63,161,63,172,63, +178,226,229,236,239,247,227,237,98,128,3,46,227,237,98,128, +3,6,233,238,246,229,242,244,229,100,3,63,193,63,204,63, +210,226,229,236,239,247,227,237,98,128,3,47,227,237,98,128, +3,17,228,239,245,226,236,229,227,237,98,128,3,97,233,228, +231,101,2,63,231,63,242,226,229,236,239,247,227,237,98,128, +3,42,233,238,246,229,242,244,229,228,226,229,236,239,247,227, +237,98,128,3,58,239,235,229,238,226,225,114,128,0,166,115, +2,64,21,64,29,244,242,239,235,101,128,1,128,245,240,229, +242,233,239,114,128,246,234,244,239,240,226,225,114,128,1,131, +117,3,64,56,64,67,64,78,232,233,242,225,231,225,238,97, +128,48,118,235,225,244,225,235,225,238,97,128,48,214,236,108, +2,64,85,64,115,229,116,130,32,34,64,94,64,104,233,238, +246,229,242,243,101,128,37,216,239,240,229,242,225,244,239,114, +128,34,25,243,229,249,101,128,37,206,99,143,0,99,64,156, +65,105,65,116,65,180,65,211,66,48,67,215,68,199,69,43, +69,92,72,84,72,92,72,102,72,114,72,147,97,9,64,176, +64,187,64,197,64,204,64,211,64,236,64,246,65,42,65,51, +225,242,237,229,238,233,225,110,128,5,110,226,229,238,231,225, +236,105,128,9,154,227,245,244,101,128,1,7,228,229,246,97, +128,9,26,231,117,2,64,218,64,227,234,225,242,225,244,105, +128,10,154,242,237,245,235,232,105,128,10,26,236,243,241,245, +225,242,101,128,51,136,238,228,242,225,226,233,238,228,117,4, +65,8,65,18,65,24,65,31,226,229,238,231,225,236,105,128, +9,129,227,237,98,128,3,16,228,229,246,97,128,9,1,231, +245,234,225,242,225,244,105,128,10,129,240,243,236,239,227,107, +128,33,234,114,3,65,59,65,65,65,91,229,239,102,128,33, +5,239,110,130,2,199,65,74,65,85,226,229,236,239,247,227, +237,98,128,3,44,227,237,98,128,3,12,242,233,225,231,229, +242,229,244,245,242,110,128,33,181,226,239,240,239,237,239,230, +111,128,49,24,99,4,65,126,65,133,65,152,65,174,225,242, +239,110,128,1,13,229,228,233,236,236,97,129,0,231,65,144, +225,227,245,244,101,128,30,9,233,242,99,2,65,160,65,165, +236,101,128,36,210,245,237,230,236,229,120,128,1,9,245,242, +108,128,2,85,100,2,65,186,65,202,239,116,129,1,11,65, +193,225,227,227,229,238,116,128,1,11,243,241,245,225,242,101, +128,51,197,101,2,65,217,65,233,228,233,236,236,97,129,0, +184,65,227,227,237,98,128,3,39,238,116,132,0,162,65,246, +66,14,66,26,66,37,105,2,65,252,66,4,231,242,225,228, +101,128,33,3,238,230,229,242,233,239,114,128,246,223,237,239, +238,239,243,240,225,227,101,128,255,224,239,236,228,243,244,249, +236,101,128,247,162,243,245,240,229,242,233,239,114,128,246,224, +104,5,66,60,66,123,66,134,67,62,67,154,97,4,66,70, +66,81,66,91,66,98,225,242,237,229,238,233,225,110,128,5, +121,226,229,238,231,225,236,105,128,9,155,228,229,246,97,128, +9,27,231,117,2,66,105,66,114,234,225,242,225,244,105,128, +10,155,242,237,245,235,232,105,128,10,27,226,239,240,239,237, +239,230,111,128,49,20,101,6,66,148,66,168,66,192,67,4, +67,16,67,37,225,226,235,232,225,243,233,225,238,227,249,242, +233,236,236,233,99,128,4,189,99,2,66,174,66,182,235,237, +225,242,107,128,39,19,249,242,233,236,236,233,99,128,4,71, +100,2,66,198,66,242,229,243,227,229,238,228,229,114,2,66, +211,66,231,225,226,235,232,225,243,233,225,238,227,249,242,233, +236,236,233,99,128,4,191,227,249,242,233,236,236,233,99,128, +4,183,233,229,242,229,243,233,243,227,249,242,233,236,236,233, +99,128,4,245,232,225,242,237,229,238,233,225,110,128,5,115, +235,232,225,235,225,243,243,233,225,238,227,249,242,233,236,236, +233,99,128,4,204,246,229,242,244,233,227,225,236,243,244,242, +239,235,229,227,249,242,233,236,236,233,99,128,4,185,105,129, +3,199,67,68,229,245,227,104,4,67,81,67,116,67,131,67, +140,97,2,67,87,67,102,227,233,242,227,236,229,235,239,242, +229,225,110,128,50,119,240,225,242,229,238,235,239,242,229,225, +110,128,50,23,227,233,242,227,236,229,235,239,242,229,225,110, +128,50,105,235,239,242,229,225,110,128,49,74,240,225,242,229, +238,235,239,242,229,225,110,128,50,9,111,2,67,160,67,210, +227,104,3,67,169,67,191,67,201,225,110,2,67,176,67,184, +231,244,232,225,105,128,14,10,244,232,225,105,128,14,8,233, +238,231,244,232,225,105,128,14,9,239,229,244,232,225,105,128, +14,12,239,107,128,1,136,105,2,67,221,68,67,229,245,99, +5,67,235,68,14,68,29,68,38,68,52,97,2,67,241,68, +0,227,233,242,227,236,229,235,239,242,229,225,110,128,50,118, +240,225,242,229,238,235,239,242,229,225,110,128,50,22,227,233, +242,227,236,229,235,239,242,229,225,110,128,50,104,235,239,242, +229,225,110,128,49,72,240,225,242,229,238,235,239,242,229,225, +110,128,50,8,245,240,225,242,229,238,235,239,242,229,225,110, +128,50,28,242,99,2,68,74,68,169,236,101,132,37,203,68, +87,68,98,68,103,68,127,237,245,236,244,233,240,236,121,128, +34,151,239,116,128,34,153,112,2,68,109,68,115,236,245,115, +128,34,149,239,243,244,225,236,237,225,242,107,128,48,54,247, +233,244,104,2,68,136,68,152,236,229,230,244,232,225,236,230, +226,236,225,227,107,128,37,208,242,233,231,232,244,232,225,236, +230,226,236,225,227,107,128,37,209,245,237,230,236,229,120,130, +2,198,68,182,68,193,226,229,236,239,247,227,237,98,128,3, +45,227,237,98,128,3,2,108,3,68,207,68,213,69,11,229, +225,114,128,35,39,233,227,107,4,68,225,68,236,68,245,68, +255,225,236,246,229,239,236,225,114,128,1,194,228,229,238,244, +225,108,128,1,192,236,225,244,229,242,225,108,128,1,193,242, +229,244,242,239,230,236,229,120,128,1,195,245,98,129,38,99, +69,18,243,245,233,116,2,69,27,69,35,226,236,225,227,107, +128,38,99,247,232,233,244,101,128,38,103,109,3,69,51,69, +65,69,76,227,245,226,229,228,243,241,245,225,242,101,128,51, +164,239,238,239,243,240,225,227,101,128,255,67,243,241,245,225, +242,229,228,243,241,245,225,242,101,128,51,160,111,8,69,110, +69,121,69,208,70,150,71,179,71,210,72,61,72,70,225,242, +237,229,238,233,225,110,128,5,129,236,239,110,131,0,58,69, +133,69,158,69,177,237,239,110,2,69,141,69,149,229,244,225, +242,121,128,32,161,239,243,240,225,227,101,128,255,26,115,2, +69,164,69,170,233,231,110,128,32,161,237,225,236,108,128,254, +85,244,242,233,225,238,231,245,236,225,114,2,69,192,69,202, +232,225,236,230,237,239,100,128,2,209,237,239,100,128,2,208, +109,2,69,214,70,143,237,97,134,0,44,69,231,70,39,70, +50,70,62,70,92,70,115,97,3,69,239,70,9,70,17,226, +239,246,101,2,69,248,69,254,227,237,98,128,3,19,242,233, +231,232,244,227,237,98,128,3,21,227,227,229,238,116,128,246, +195,114,2,70,23,70,30,225,226,233,99,128,6,12,237,229, +238,233,225,110,128,5,93,233,238,230,229,242,233,239,114,128, +246,225,237,239,238,239,243,240,225,227,101,128,255,12,242,229, +246,229,242,243,229,100,2,70,75,70,86,225,226,239,246,229, +227,237,98,128,3,20,237,239,100,128,2,189,115,2,70,98, +70,105,237,225,236,108,128,254,80,245,240,229,242,233,239,114, +128,246,226,244,245,242,238,229,100,2,70,126,70,137,225,226, +239,246,229,227,237,98,128,3,18,237,239,100,128,2,187,240, +225,243,115,128,38,60,110,2,70,156,70,165,231,242,245,229, +238,116,128,34,69,116,2,70,171,70,185,239,245,242,233,238, +244,229,231,242,225,108,128,34,46,242,239,108,142,35,3,70, +219,70,225,70,240,70,255,71,43,71,88,71,102,71,107,71, +112,71,117,71,123,71,128,71,169,71,174,193,195,75,128,0, +6,66,2,70,231,70,236,197,76,128,0,7,83,128,0,8, +67,2,70,246,70,251,193,78,128,0,24,82,128,0,13,68, +3,71,7,71,33,71,38,67,4,71,17,71,21,71,25,71, +29,49,128,0,17,50,128,0,18,51,128,0,19,52,128,0, +20,197,76,128,0,127,204,69,128,0,16,69,5,71,55,71, +59,71,64,71,69,71,74,77,128,0,25,206,81,128,0,5, +207,84,128,0,4,211,67,128,0,27,84,2,71,80,71,84, +66,128,0,23,88,128,0,3,70,2,71,94,71,98,70,128, +0,12,83,128,0,28,199,83,128,0,29,200,84,128,0,9, +204,70,128,0,10,206,193,75,128,0,21,210,83,128,0,30, +83,5,71,140,71,144,71,154,71,159,71,164,73,128,0,15, +79,129,0,14,71,150,84,128,0,2,212,88,128,0,1,213, +66,128,0,26,217,78,128,0,22,213,83,128,0,31,214,84, +128,0,11,240,249,242,233,231,232,116,129,0,169,71,191,115, +2,71,197,71,203,225,238,115,128,248,233,229,242,233,102,128, +246,217,114,2,71,216,72,44,238,229,242,226,242,225,227,235, +229,116,2,71,231,72,9,236,229,230,116,130,48,12,71,242, +71,254,232,225,236,230,247,233,228,244,104,128,255,98,246,229, +242,244,233,227,225,108,128,254,65,242,233,231,232,116,130,48, +13,72,21,72,33,232,225,236,230,247,233,228,244,104,128,255, +99,246,229,242,244,233,227,225,108,128,254,66,240,239,242,225, +244,233,239,238,243,241,245,225,242,101,128,51,127,243,241,245, +225,242,101,128,51,199,246,229,242,235,231,243,241,245,225,242, +101,128,51,198,240,225,242,229,110,128,36,158,242,245,250,229, +233,242,111,128,32,162,243,244,242,229,244,227,232,229,100,128, +2,151,245,114,2,72,121,72,139,236,121,2,72,128,72,134, +225,238,100,128,34,207,239,114,128,34,206,242,229,238,227,121, +128,0,164,249,114,4,72,158,72,166,72,173,72,181,194,242, +229,246,101,128,246,209,198,236,229,120,128,246,210,226,242,229, +246,101,128,246,212,230,236,229,120,128,246,213,100,146,0,100, +72,228,74,110,75,134,75,194,76,114,77,68,77,130,78,59, +78,72,78,81,78,107,78,132,78,141,79,208,79,216,79,227, +79,247,80,19,97,11,72,252,73,7,73,17,73,89,73,152, +73,163,73,174,73,243,74,49,74,55,74,85,225,242,237,229, +238,233,225,110,128,5,100,226,229,238,231,225,236,105,128,9, +166,100,5,73,29,73,38,73,44,73,58,73,74,225,242,225, +226,233,99,128,6,54,229,246,97,128,9,38,230,233,238,225, +236,225,242,225,226,233,99,128,254,190,233,238,233,244,233,225, +236,225,242,225,226,233,99,128,254,191,237,229,228,233,225,236, +225,242,225,226,233,99,128,254,192,103,3,73,97,73,114,73, +128,229,243,104,129,5,188,73,105,232,229,226,242,229,119,128, +5,188,231,229,114,129,32,32,73,122,228,226,108,128,32,33, +117,2,73,134,73,143,234,225,242,225,244,105,128,10,166,242, +237,245,235,232,105,128,10,38,232,233,242,225,231,225,238,97, +128,48,96,235,225,244,225,235,225,238,97,128,48,192,108,3, +73,182,73,191,73,229,225,242,225,226,233,99,128,6,47,229, +116,130,5,211,73,200,73,220,228,225,231,229,243,104,129,251, +51,73,211,232,229,226,242,229,119,128,251,51,232,229,226,242, +229,119,128,5,211,230,233,238,225,236,225,242,225,226,233,99, +128,254,170,237,237,97,3,73,253,74,6,74,18,225,242,225, +226,233,99,128,6,79,236,239,247,225,242,225,226,233,99,128, +6,79,244,225,238,97,2,74,27,74,41,236,244,239,238,229, +225,242,225,226,233,99,128,6,76,242,225,226,233,99,128,6, +76,238,228,97,128,9,100,242,231,97,2,74,63,74,72,232, +229,226,242,229,119,128,5,167,236,229,230,244,232,229,226,242, +229,119,128,5,167,243,233,225,240,238,229,245,237,225,244,225, +227,249,242,233,236,236,233,227,227,237,98,128,4,133,98,3, +74,118,75,115,75,125,108,9,74,138,74,146,75,3,75,11, +75,27,75,38,75,56,75,70,75,81,199,242,225,246,101,128, +246,211,97,2,74,152,74,209,238,231,236,229,226,242,225,227, +235,229,116,2,74,168,74,188,236,229,230,116,129,48,10,74, +177,246,229,242,244,233,227,225,108,128,254,61,242,233,231,232, +116,129,48,11,74,198,246,229,242,244,233,227,225,108,128,254, +62,114,2,74,215,74,236,227,232,233,238,246,229,242,244,229, +228,226,229,236,239,247,227,237,98,128,3,43,242,239,119,2, +74,244,74,251,236,229,230,116,128,33,212,242,233,231,232,116, +128,33,210,228,225,238,228,97,128,9,101,231,242,225,246,101, +129,246,214,75,21,227,237,98,128,3,15,233,238,244,229,231, +242,225,108,128,34,44,236,239,247,236,233,238,101,129,32,23, +75,50,227,237,98,128,3,51,239,246,229,242,236,233,238,229, +227,237,98,128,3,63,240,242,233,237,229,237,239,100,128,2, +186,246,229,242,244,233,227,225,108,2,75,94,75,100,226,225, +114,128,32,22,236,233,238,229,225,226,239,246,229,227,237,98, +128,3,14,239,240,239,237,239,230,111,128,49,9,243,241,245, +225,242,101,128,51,200,99,4,75,144,75,151,75,160,75,187, +225,242,239,110,128,1,15,229,228,233,236,236,97,128,30,17, +233,242,99,2,75,168,75,173,236,101,128,36,211,245,237,230, +236,229,248,226,229,236,239,119,128,30,19,242,239,225,116,128, +1,17,100,4,75,204,76,29,76,39,76,90,97,4,75,214, +75,224,75,231,76,0,226,229,238,231,225,236,105,128,9,161, +228,229,246,97,128,9,33,231,117,2,75,238,75,247,234,225, +242,225,244,105,128,10,161,242,237,245,235,232,105,128,10,33, +108,2,76,6,76,15,225,242,225,226,233,99,128,6,136,230, +233,238,225,236,225,242,225,226,233,99,128,251,137,228,232,225, +228,229,246,97,128,9,92,232,97,3,76,48,76,58,76,65, +226,229,238,231,225,236,105,128,9,162,228,229,246,97,128,9, +34,231,117,2,76,72,76,81,234,225,242,225,244,105,128,10, +162,242,237,245,235,232,105,128,10,34,239,116,2,76,97,76, +106,225,227,227,229,238,116,128,30,11,226,229,236,239,119,128, +30,13,101,8,76,132,76,185,76,192,76,217,76,227,76,238, +77,27,77,63,99,2,76,138,76,175,233,237,225,236,243,229, +240,225,242,225,244,239,114,2,76,156,76,165,225,242,225,226, +233,99,128,6,107,240,229,242,243,233,225,110,128,6,107,249, +242,233,236,236,233,99,128,4,52,231,242,229,101,128,0,176, +232,105,2,76,199,76,208,232,229,226,242,229,119,128,5,173, +242,225,231,225,238,97,128,48,103,233,227,239,240,244,233,99, +128,3,239,235,225,244,225,235,225,238,97,128,48,199,108,2, +76,244,77,11,229,244,101,2,76,252,77,3,236,229,230,116, +128,35,43,242,233,231,232,116,128,35,38,244,97,129,3,180, +77,18,244,245,242,238,229,100,128,1,141,238,239,237,233,238, +225,244,239,242,237,233,238,245,243,239,238,229,238,245,237,229, +242,225,244,239,242,226,229,238,231,225,236,105,128,9,248,250, +104,128,2,164,104,2,77,74,77,124,97,3,77,82,77,92, +77,99,226,229,238,231,225,236,105,128,9,167,228,229,246,97, +128,9,39,231,117,2,77,106,77,115,234,225,242,225,244,105, +128,10,167,242,237,245,235,232,105,128,10,39,239,239,107,128, +2,87,105,6,77,144,77,193,77,253,78,8,78,19,78,29, +97,2,77,150,77,172,236,249,244,233,235,225,244,239,238,239, +115,129,3,133,77,166,227,237,98,128,3,68,237,239,238,100, +129,38,102,77,181,243,245,233,244,247,232,233,244,101,128,38, +98,229,242,229,243,233,115,133,0,168,77,212,77,220,77,231, +77,237,77,245,225,227,245,244,101,128,246,215,226,229,236,239, +247,227,237,98,128,3,36,227,237,98,128,3,8,231,242,225, +246,101,128,246,216,244,239,238,239,115,128,3,133,232,233,242, +225,231,225,238,97,128,48,98,235,225,244,225,235,225,238,97, +128,48,194,244,244,239,237,225,242,107,128,48,3,246,105,2, +78,36,78,47,228,101,129,0,247,78,43,115,128,34,35,243, +233,239,238,243,236,225,243,104,128,34,21,234,229,227,249,242, +233,236,236,233,99,128,4,82,235,243,232,225,228,101,128,37, +147,108,2,78,87,78,98,233,238,229,226,229,236,239,119,128, +30,15,243,241,245,225,242,101,128,51,151,109,2,78,113,78, +121,225,227,242,239,110,128,1,17,239,238,239,243,240,225,227, +101,128,255,68,238,226,236,239,227,107,128,37,132,111,10,78, +163,78,175,78,185,78,196,78,207,79,23,79,28,79,39,79, +154,79,180,227,232,225,228,225,244,232,225,105,128,14,14,228, +229,235,244,232,225,105,128,14,20,232,233,242,225,231,225,238, +97,128,48,105,235,225,244,225,235,225,238,97,128,48,201,236, +236,225,114,132,0,36,78,222,78,233,78,245,79,0,233,238, +230,229,242,233,239,114,128,246,227,237,239,238,239,243,240,225, +227,101,128,255,4,239,236,228,243,244,249,236,101,128,247,36, +115,2,79,6,79,13,237,225,236,108,128,254,105,245,240,229, +242,233,239,114,128,246,228,238,103,128,32,171,242,245,243,241, +245,225,242,101,128,51,38,116,6,79,53,79,70,79,92,79, +103,79,135,79,142,225,227,227,229,238,116,129,2,217,79,64, +227,237,98,128,3,7,226,229,236,239,247,99,2,79,81,79, +86,237,98,128,3,35,239,237,98,128,3,35,235,225,244,225, +235,225,238,97,128,48,251,236,229,243,115,2,79,112,79,116, +105,128,1,49,106,129,246,190,79,122,243,244,242,239,235,229, +232,239,239,107,128,2,132,237,225,244,104,128,34,197,244,229, +228,227,233,242,227,236,101,128,37,204,245,226,236,229,249,239, +228,240,225,244,225,104,129,251,31,79,171,232,229,226,242,229, +119,128,251,31,247,238,244,225,227,107,2,79,191,79,202,226, +229,236,239,247,227,237,98,128,3,30,237,239,100,128,2,213, +240,225,242,229,110,128,36,159,243,245,240,229,242,233,239,114, +128,246,235,116,2,79,233,79,239,225,233,108,128,2,86,239, +240,226,225,114,128,1,140,117,2,79,253,80,8,232,233,242, +225,231,225,238,97,128,48,101,235,225,244,225,235,225,238,97, +128,48,197,122,132,1,243,80,31,80,40,80,59,80,96,225, +236,244,239,238,101,128,2,163,99,2,80,46,80,53,225,242, +239,110,128,1,198,245,242,108,128,2,165,101,2,80,65,80, +85,225,226,235,232,225,243,233,225,238,227,249,242,233,236,236, +233,99,128,4,225,227,249,242,233,236,236,233,99,128,4,85, +232,229,227,249,242,233,236,236,233,99,128,4,95,101,151,0, +101,80,159,80,178,80,212,81,186,81,248,82,25,82,37,82, +60,82,113,83,225,84,27,84,129,84,245,85,124,85,199,85, +230,86,36,86,89,87,24,87,157,87,177,87,221,88,56,97, +2,80,165,80,172,227,245,244,101,128,0,233,242,244,104,128, +38,65,98,3,80,186,80,195,80,205,229,238,231,225,236,105, +128,9,143,239,240,239,237,239,230,111,128,49,28,242,229,246, +101,128,1,21,99,5,80,224,81,41,81,55,81,87,81,176, +97,2,80,230,81,35,238,228,242,97,3,80,241,80,248,81, +3,228,229,246,97,128,9,13,231,245,234,225,242,225,244,105, +128,10,141,246,239,247,229,236,243,233,231,110,2,81,17,81, +24,228,229,246,97,128,9,69,231,245,234,225,242,225,244,105, +128,10,197,242,239,110,128,1,27,229,228,233,236,236,225,226, +242,229,246,101,128,30,29,104,2,81,61,81,72,225,242,237, +229,238,233,225,110,128,5,101,249,233,247,238,225,242,237,229, +238,233,225,110,128,5,135,233,242,99,2,81,95,81,100,236, +101,128,36,212,245,237,230,236,229,120,134,0,234,81,121,81, +129,81,137,81,148,81,156,81,168,225,227,245,244,101,128,30, +191,226,229,236,239,119,128,30,25,228,239,244,226,229,236,239, +119,128,30,199,231,242,225,246,101,128,30,193,232,239,239,235, +225,226,239,246,101,128,30,195,244,233,236,228,101,128,30,197, +249,242,233,236,236,233,99,128,4,84,100,4,81,196,81,206, +81,212,81,222,226,236,231,242,225,246,101,128,2,5,229,246, +97,128,9,15,233,229,242,229,243,233,115,128,0,235,239,116, +130,1,23,81,231,81,240,225,227,227,229,238,116,128,1,23, +226,229,236,239,119,128,30,185,101,2,81,254,82,9,231,245, +242,237,245,235,232,105,128,10,15,237,225,244,242,225,231,245, +242,237,245,235,232,105,128,10,71,230,227,249,242,233,236,236, +233,99,128,4,68,103,2,82,43,82,50,242,225,246,101,128, +0,232,245,234,225,242,225,244,105,128,10,143,104,4,82,70, +82,81,82,92,82,102,225,242,237,229,238,233,225,110,128,5, +103,226,239,240,239,237,239,230,111,128,49,29,233,242,225,231, +225,238,97,128,48,72,239,239,235,225,226,239,246,101,128,30, +187,105,4,82,123,82,134,83,192,83,207,226,239,240,239,237, +239,230,111,128,49,31,231,232,116,142,0,56,82,168,82,177, +82,187,82,217,82,224,83,6,83,31,83,76,83,110,83,122, +83,133,83,166,83,174,83,185,225,242,225,226,233,99,128,6, +104,226,229,238,231,225,236,105,128,9,238,227,233,242,227,236, +101,129,36,103,82,198,233,238,246,229,242,243,229,243,225,238, +243,243,229,242,233,102,128,39,145,228,229,246,97,128,9,110, +229,229,110,2,82,232,82,241,227,233,242,227,236,101,128,36, +113,112,2,82,247,82,254,225,242,229,110,128,36,133,229,242, +233,239,100,128,36,153,231,117,2,83,13,83,22,234,225,242, +225,244,105,128,10,238,242,237,245,235,232,105,128,10,110,104, +2,83,37,83,63,97,2,83,43,83,54,227,235,225,242,225, +226,233,99,128,6,104,238,231,250,232,239,117,128,48,40,238, +239,244,229,226,229,225,237,229,100,128,38,107,105,2,83,82, +83,100,228,229,239,231,242,225,240,232,233,227,240,225,242,229, +110,128,50,39,238,230,229,242,233,239,114,128,32,136,237,239, +238,239,243,240,225,227,101,128,255,24,239,236,228,243,244,249, +236,101,128,247,56,112,2,83,139,83,146,225,242,229,110,128, +36,123,229,114,2,83,153,83,159,233,239,100,128,36,143,243, +233,225,110,128,6,248,242,239,237,225,110,128,33,119,243,245, +240,229,242,233,239,114,128,32,120,244,232,225,105,128,14,88, +238,246,229,242,244,229,228,226,242,229,246,101,128,2,7,239, +244,233,230,233,229,228,227,249,242,233,236,236,233,99,128,4, +101,107,2,83,231,83,255,225,244,225,235,225,238,97,129,48, +168,83,243,232,225,236,230,247,233,228,244,104,128,255,116,111, +2,84,5,84,20,238,235,225,242,231,245,242,237,245,235,232, +105,128,10,116,242,229,225,110,128,49,84,108,3,84,35,84, +46,84,107,227,249,242,233,236,236,233,99,128,4,59,101,2, +84,52,84,59,237,229,238,116,128,34,8,246,229,110,3,84, +69,84,78,84,99,227,233,242,227,236,101,128,36,106,112,2, +84,84,84,91,225,242,229,110,128,36,126,229,242,233,239,100, +128,36,146,242,239,237,225,110,128,33,122,236,233,240,243,233, +115,129,32,38,84,118,246,229,242,244,233,227,225,108,128,34, +238,109,5,84,141,84,169,84,180,84,200,84,211,225,227,242, +239,110,130,1,19,84,153,84,161,225,227,245,244,101,128,30, +23,231,242,225,246,101,128,30,21,227,249,242,233,236,236,233, +99,128,4,60,228,225,243,104,129,32,20,84,189,246,229,242, +244,233,227,225,108,128,254,49,239,238,239,243,240,225,227,101, +128,255,69,112,2,84,217,84,237,232,225,243,233,243,237,225, +242,235,225,242,237,229,238,233,225,110,128,5,91,244,249,243, +229,116,128,34,5,110,6,85,3,85,14,85,25,85,69,85, +101,85,116,226,239,240,239,237,239,230,111,128,49,35,227,249, +242,233,236,236,233,99,128,4,61,100,2,85,31,85,50,225, +243,104,129,32,19,85,39,246,229,242,244,233,227,225,108,128, +254,50,229,243,227,229,238,228,229,242,227,249,242,233,236,236, +233,99,128,4,163,103,130,1,75,85,77,85,88,226,239,240, +239,237,239,230,111,128,49,37,232,229,227,249,242,233,236,236, +233,99,128,4,165,232,239,239,235,227,249,242,233,236,236,233, +99,128,4,200,243,240,225,227,101,128,32,2,111,3,85,132, +85,140,85,149,231,239,238,229,107,128,1,25,235,239,242,229, +225,110,128,49,83,240,229,110,130,2,91,85,159,85,168,227, +236,239,243,229,100,128,2,154,242,229,246,229,242,243,229,100, +130,2,92,85,183,85,192,227,236,239,243,229,100,128,2,94, +232,239,239,107,128,2,93,112,2,85,205,85,212,225,242,229, +110,128,36,160,243,233,236,239,110,129,3,181,85,222,244,239, +238,239,115,128,3,173,241,117,2,85,237,86,25,225,108,130, +0,61,85,246,86,2,237,239,238,239,243,240,225,227,101,128, +255,29,115,2,86,8,86,15,237,225,236,108,128,254,102,245, +240,229,242,233,239,114,128,32,124,233,246,225,236,229,238,227, +101,128,34,97,114,3,86,44,86,55,86,66,226,239,240,239, +237,239,230,111,128,49,38,227,249,242,233,236,236,233,99,128, +4,64,229,246,229,242,243,229,100,129,2,88,86,78,227,249, +242,233,236,236,233,99,128,4,77,115,6,86,103,86,114,86, +134,86,215,87,4,87,14,227,249,242,233,236,236,233,99,128, +4,65,228,229,243,227,229,238,228,229,242,227,249,242,233,236, +236,233,99,128,4,171,104,132,2,131,86,146,86,153,86,184, +86,199,227,245,242,108,128,2,134,239,242,116,2,86,161,86, +168,228,229,246,97,128,9,14,246,239,247,229,236,243,233,231, +238,228,229,246,97,128,9,70,242,229,246,229,242,243,229,228, +236,239,239,112,128,1,170,243,241,245,225,244,242,229,246,229, +242,243,229,100,128,2,133,237,225,236,108,2,86,224,86,235, +232,233,242,225,231,225,238,97,128,48,71,235,225,244,225,235, +225,238,97,129,48,167,86,248,232,225,236,230,247,233,228,244, +104,128,255,106,244,233,237,225,244,229,100,128,33,46,245,240, +229,242,233,239,114,128,246,236,116,5,87,36,87,62,87,66, +87,83,87,149,97,130,3,183,87,44,87,54,242,237,229,238, +233,225,110,128,5,104,244,239,238,239,115,128,3,174,104,128, +0,240,233,236,228,101,129,30,189,87,75,226,229,236,239,119, +128,30,27,238,225,232,244,97,3,87,95,87,127,87,136,230, +239,245,235,104,2,87,105,87,114,232,229,226,242,229,119,128, +5,145,236,229,230,244,232,229,226,242,229,119,128,5,145,232, +229,226,242,229,119,128,5,145,236,229,230,244,232,229,226,242, +229,119,128,5,145,245,242,238,229,100,128,1,221,117,2,87, +163,87,172,235,239,242,229,225,110,128,49,97,242,111,128,32, +172,246,239,247,229,236,243,233,231,110,3,87,193,87,203,87, +210,226,229,238,231,225,236,105,128,9,199,228,229,246,97,128, +9,71,231,245,234,225,242,225,244,105,128,10,199,120,2,87, +227,88,44,227,236,225,109,132,0,33,87,242,87,253,88,24, +88,36,225,242,237,229,238,233,225,110,128,5,92,100,2,88, +3,88,8,226,108,128,32,60,239,247,110,129,0,161,88,16, +243,237,225,236,108,128,247,161,237,239,238,239,243,240,225,227, +101,128,255,1,243,237,225,236,108,128,247,33,233,243,244,229, +238,244,233,225,108,128,34,3,250,104,131,2,146,88,67,88, +86,88,97,99,2,88,73,88,80,225,242,239,110,128,1,239, +245,242,108,128,2,147,242,229,246,229,242,243,229,100,128,1, +185,244,225,233,108,128,1,186,102,140,0,102,88,132,88,214, +88,225,88,234,88,246,89,93,89,109,91,117,91,130,91,156, +93,33,93,41,97,4,88,142,88,149,88,160,88,171,228,229, +246,97,128,9,94,231,245,242,237,245,235,232,105,128,10,94, +232,242,229,238,232,229,233,116,128,33,9,244,232,97,3,88, +181,88,190,88,202,225,242,225,226,233,99,128,6,78,236,239, +247,225,242,225,226,233,99,128,6,78,244,225,238,225,242,225, +226,233,99,128,6,75,226,239,240,239,237,239,230,111,128,49, +8,227,233,242,227,236,101,128,36,213,228,239,244,225,227,227, +229,238,116,128,30,31,101,3,88,254,89,76,89,86,104,4, +89,8,89,31,89,45,89,61,225,114,2,89,15,89,22,225, +226,233,99,128,6,65,237,229,238,233,225,110,128,5,134,230, +233,238,225,236,225,242,225,226,233,99,128,254,210,233,238,233, +244,233,225,236,225,242,225,226,233,99,128,254,211,237,229,228, +233,225,236,225,242,225,226,233,99,128,254,212,233,227,239,240, +244,233,99,128,3,229,237,225,236,101,128,38,64,102,130,251, +0,89,101,89,105,105,128,251,3,108,128,251,4,105,136,251, +1,89,129,89,169,89,180,89,202,90,68,90,85,90,93,90, +106,230,244,229,229,110,2,89,139,89,148,227,233,242,227,236, +101,128,36,110,112,2,89,154,89,161,225,242,229,110,128,36, +130,229,242,233,239,100,128,36,150,231,245,242,229,228,225,243, +104,128,32,18,236,236,229,100,2,89,189,89,195,226,239,120, +128,37,160,242,229,227,116,128,37,172,238,225,108,5,89,216, +89,255,90,16,90,33,90,49,235,225,102,130,5,218,89,226, +89,246,228,225,231,229,243,104,129,251,58,89,237,232,229,226, +242,229,119,128,251,58,232,229,226,242,229,119,128,5,218,237, +229,109,129,5,221,90,7,232,229,226,242,229,119,128,5,221, +238,245,110,129,5,223,90,24,232,229,226,242,229,119,128,5, +223,240,101,129,5,227,90,40,232,229,226,242,229,119,128,5, +227,244,243,225,228,105,129,5,229,90,59,232,229,226,242,229, +119,128,5,229,242,243,244,244,239,238,229,227,232,233,238,229, +243,101,128,2,201,243,232,229,249,101,128,37,201,244,225,227, +249,242,233,236,236,233,99,128,4,115,246,101,142,0,53,90, +139,90,148,90,158,90,188,90,195,90,205,90,230,91,1,91, +35,91,47,91,58,91,91,91,99,91,110,225,242,225,226,233, +99,128,6,101,226,229,238,231,225,236,105,128,9,235,227,233, +242,227,236,101,129,36,100,90,169,233,238,246,229,242,243,229, +243,225,238,243,243,229,242,233,102,128,39,142,228,229,246,97, +128,9,107,229,233,231,232,244,232,115,128,33,93,231,117,2, +90,212,90,221,234,225,242,225,244,105,128,10,235,242,237,245, +235,232,105,128,10,107,232,97,2,90,237,90,248,227,235,225, +242,225,226,233,99,128,6,101,238,231,250,232,239,117,128,48, +37,105,2,91,7,91,25,228,229,239,231,242,225,240,232,233, +227,240,225,242,229,110,128,50,36,238,230,229,242,233,239,114, +128,32,133,237,239,238,239,243,240,225,227,101,128,255,21,239, +236,228,243,244,249,236,101,128,247,53,112,2,91,64,91,71, +225,242,229,110,128,36,120,229,114,2,91,78,91,84,233,239, +100,128,36,140,243,233,225,110,128,6,245,242,239,237,225,110, +128,33,116,243,245,240,229,242,233,239,114,128,32,117,244,232, +225,105,128,14,85,108,129,251,2,91,123,239,242,233,110,128, +1,146,109,2,91,136,91,147,239,238,239,243,240,225,227,101, +128,255,70,243,241,245,225,242,101,128,51,153,111,4,91,166, +91,188,91,200,91,207,230,97,2,91,173,91,181,238,244,232, +225,105,128,14,31,244,232,225,105,128,14,29,238,231,237,225, +238,244,232,225,105,128,14,79,242,225,236,108,128,34,0,245, +114,142,0,52,91,240,91,249,92,3,92,33,92,40,92,65, +92,92,92,126,92,138,92,157,92,168,92,201,92,209,92,220, +225,242,225,226,233,99,128,6,100,226,229,238,231,225,236,105, +128,9,234,227,233,242,227,236,101,129,36,99,92,14,233,238, +246,229,242,243,229,243,225,238,243,243,229,242,233,102,128,39, +141,228,229,246,97,128,9,106,231,117,2,92,47,92,56,234, +225,242,225,244,105,128,10,234,242,237,245,235,232,105,128,10, +106,232,97,2,92,72,92,83,227,235,225,242,225,226,233,99, +128,6,100,238,231,250,232,239,117,128,48,36,105,2,92,98, +92,116,228,229,239,231,242,225,240,232,233,227,240,225,242,229, +110,128,50,35,238,230,229,242,233,239,114,128,32,132,237,239, +238,239,243,240,225,227,101,128,255,20,238,245,237,229,242,225, +244,239,242,226,229,238,231,225,236,105,128,9,247,239,236,228, +243,244,249,236,101,128,247,52,112,2,92,174,92,181,225,242, +229,110,128,36,119,229,114,2,92,188,92,194,233,239,100,128, +36,139,243,233,225,110,128,6,244,242,239,237,225,110,128,33, +115,243,245,240,229,242,233,239,114,128,32,116,116,2,92,226, +93,8,229,229,110,2,92,234,92,243,227,233,242,227,236,101, +128,36,109,112,2,92,249,93,0,225,242,229,110,128,36,129, +229,242,233,239,100,128,36,149,104,2,93,14,93,19,225,105, +128,14,84,244,239,238,229,227,232,233,238,229,243,101,128,2, +203,240,225,242,229,110,128,36,161,242,97,2,93,48,93,56, +227,244,233,239,110,128,32,68,238,99,128,32,163,103,144,0, +103,93,97,94,43,94,66,94,127,94,144,95,65,96,58,96, +143,96,156,97,14,97,39,97,67,97,89,98,34,98,56,98, +158,97,9,93,117,93,127,93,134,93,141,93,205,93,230,93, +241,93,252,94,30,226,229,238,231,225,236,105,128,9,151,227, +245,244,101,128,1,245,228,229,246,97,128,9,23,102,4,93, +151,93,160,93,174,93,190,225,242,225,226,233,99,128,6,175, +230,233,238,225,236,225,242,225,226,233,99,128,251,147,233,238, +233,244,233,225,236,225,242,225,226,233,99,128,251,148,237,229, +228,233,225,236,225,242,225,226,233,99,128,251,149,231,117,2, +93,212,93,221,234,225,242,225,244,105,128,10,151,242,237,245, +235,232,105,128,10,23,232,233,242,225,231,225,238,97,128,48, +76,235,225,244,225,235,225,238,97,128,48,172,237,237,97,130, +3,179,94,6,94,19,236,225,244,233,238,243,237,225,236,108, +128,2,99,243,245,240,229,242,233,239,114,128,2,224,238,231, +233,225,227,239,240,244,233,99,128,3,235,98,2,94,49,94, +59,239,240,239,237,239,230,111,128,49,13,242,229,246,101,128, +1,31,99,4,94,76,94,83,94,92,94,114,225,242,239,110, +128,1,231,229,228,233,236,236,97,128,1,35,233,242,99,2, +94,100,94,105,236,101,128,36,214,245,237,230,236,229,120,128, +1,29,239,237,237,225,225,227,227,229,238,116,128,1,35,228, +239,116,129,1,33,94,135,225,227,227,229,238,116,128,1,33, +101,6,94,158,94,169,94,180,94,191,94,210,95,56,227,249, +242,233,236,236,233,99,128,4,51,232,233,242,225,231,225,238, +97,128,48,82,235,225,244,225,235,225,238,97,128,48,178,239, +237,229,244,242,233,227,225,236,236,249,229,241,245,225,108,128, +34,81,114,3,94,218,95,11,95,21,229,243,104,3,94,228, +94,243,94,252,225,227,227,229,238,244,232,229,226,242,229,119, +128,5,156,232,229,226,242,229,119,128,5,243,237,245,241,228, +225,237,232,229,226,242,229,119,128,5,157,237,225,238,228,226, +236,115,128,0,223,243,232,225,249,233,109,2,95,32,95,47, +225,227,227,229,238,244,232,229,226,242,229,119,128,5,158,232, +229,226,242,229,119,128,5,244,244,225,237,225,242,107,128,48, +19,104,5,95,77,95,210,96,17,96,42,96,48,97,4,95, +87,95,97,95,120,95,145,226,229,238,231,225,236,105,128,9, +152,100,2,95,103,95,114,225,242,237,229,238,233,225,110,128, +5,114,229,246,97,128,9,24,231,117,2,95,127,95,136,234, +225,242,225,244,105,128,10,152,242,237,245,235,232,105,128,10, +24,233,110,4,95,156,95,165,95,179,95,195,225,242,225,226, +233,99,128,6,58,230,233,238,225,236,225,242,225,226,233,99, +128,254,206,233,238,233,244,233,225,236,225,242,225,226,233,99, +128,254,207,237,229,228,233,225,236,225,242,225,226,233,99,128, +254,208,101,3,95,218,95,239,96,0,237,233,228,228,236,229, +232,239,239,235,227,249,242,233,236,236,233,99,128,4,149,243, +244,242,239,235,229,227,249,242,233,236,236,233,99,128,4,147, +245,240,244,245,242,238,227,249,242,233,236,236,233,99,128,4, +145,232,97,2,96,24,96,31,228,229,246,97,128,9,90,231, +245,242,237,245,235,232,105,128,10,90,239,239,107,128,2,96, +250,243,241,245,225,242,101,128,51,147,105,3,96,66,96,77, +96,88,232,233,242,225,231,225,238,97,128,48,78,235,225,244, +225,235,225,238,97,128,48,174,109,2,96,94,96,105,225,242, +237,229,238,233,225,110,128,5,99,229,108,130,5,210,96,114, +96,134,228,225,231,229,243,104,129,251,50,96,125,232,229,226, +242,229,119,128,251,50,232,229,226,242,229,119,128,5,210,234, +229,227,249,242,233,236,236,233,99,128,4,83,236,239,244,244, +225,108,2,96,167,96,184,233,238,246,229,242,244,229,228,243, +244,242,239,235,101,128,1,190,243,244,239,112,132,2,148,96, +199,96,210,96,216,96,248,233,238,246,229,242,244,229,100,128, +2,150,237,239,100,128,2,192,242,229,246,229,242,243,229,100, +130,2,149,96,231,96,237,237,239,100,128,2,193,243,245,240, +229,242,233,239,114,128,2,228,243,244,242,239,235,101,129,2, +161,97,3,242,229,246,229,242,243,229,100,128,2,162,109,2, +97,20,97,28,225,227,242,239,110,128,30,33,239,238,239,243, +240,225,227,101,128,255,71,111,2,97,45,97,56,232,233,242, +225,231,225,238,97,128,48,84,235,225,244,225,235,225,238,97, +128,48,180,240,97,2,97,74,97,80,242,229,110,128,36,162, +243,241,245,225,242,101,128,51,172,114,2,97,95,97,192,97, +2,97,101,97,109,228,233,229,238,116,128,34,7,246,101,134, +0,96,97,126,97,137,97,154,97,161,97,170,97,182,226,229, +236,239,247,227,237,98,128,3,22,99,2,97,143,97,148,237, +98,128,3,0,239,237,98,128,3,0,228,229,246,97,128,9, +83,236,239,247,237,239,100,128,2,206,237,239,238,239,243,240, +225,227,101,128,255,64,244,239,238,229,227,237,98,128,3,64, +229,225,244,229,114,132,0,62,97,208,97,227,97,239,98,26, +229,241,245,225,108,129,34,101,97,218,239,242,236,229,243,115, +128,34,219,237,239,238,239,243,240,225,227,101,128,255,30,111, +2,97,245,98,15,114,2,97,251,98,8,229,241,245,233,246, +225,236,229,238,116,128,34,115,236,229,243,115,128,34,119,246, +229,242,229,241,245,225,108,128,34,103,243,237,225,236,108,128, +254,101,115,2,98,40,98,48,227,242,233,240,116,128,2,97, +244,242,239,235,101,128,1,229,117,4,98,66,98,77,98,134, +98,145,232,233,242,225,231,225,238,97,128,48,80,233,108,2, +98,84,98,109,236,229,237,239,116,2,98,94,98,101,236,229, +230,116,128,0,171,242,233,231,232,116,128,0,187,243,233,238, +231,108,2,98,119,98,126,236,229,230,116,128,32,57,242,233, +231,232,116,128,32,58,235,225,244,225,235,225,238,97,128,48, +176,242,225,237,245,243,241,245,225,242,101,128,51,24,249,243, +241,245,225,242,101,128,51,201,104,144,0,104,98,204,101,90, +101,125,101,162,101,202,103,90,103,110,104,75,104,87,104,99, +105,167,105,175,105,186,105,195,106,19,106,23,97,13,98,232, +99,15,99,25,99,55,99,80,99,158,99,170,99,195,99,210, +99,239,99,252,100,54,100,63,97,2,98,238,99,1,226,235, +232,225,243,233,225,238,227,249,242,233,236,236,233,99,128,4, +169,236,244,239,238,229,225,242,225,226,233,99,128,6,193,226, +229,238,231,225,236,105,128,9,185,228,101,2,99,32,99,50, +243,227,229,238,228,229,242,227,249,242,233,236,236,233,99,128, +4,179,246,97,128,9,57,231,117,2,99,62,99,71,234,225, +242,225,244,105,128,10,185,242,237,245,235,232,105,128,10,57, +104,4,99,90,99,99,99,113,99,143,225,242,225,226,233,99, +128,6,45,230,233,238,225,236,225,242,225,226,233,99,128,254, +162,105,2,99,119,99,134,238,233,244,233,225,236,225,242,225, +226,233,99,128,254,163,242,225,231,225,238,97,128,48,111,237, +229,228,233,225,236,225,242,225,226,233,99,128,254,164,233,244, +245,243,241,245,225,242,101,128,51,42,235,225,244,225,235,225, +238,97,129,48,207,99,183,232,225,236,230,247,233,228,244,104, +128,255,138,236,225,238,244,231,245,242,237,245,235,232,105,128, +10,77,237,250,97,2,99,218,99,227,225,242,225,226,233,99, +128,6,33,236,239,247,225,242,225,226,233,99,128,6,33,238, +231,245,236,230,233,236,236,229,114,128,49,100,114,2,100,2, +100,18,228,243,233,231,238,227,249,242,233,236,236,233,99,128, +4,74,240,239,239,110,2,100,27,100,40,236,229,230,244,226, +225,242,226,245,112,128,33,188,242,233,231,232,244,226,225,242, +226,245,112,128,33,192,243,241,245,225,242,101,128,51,202,244, +225,102,3,100,73,100,165,101,0,240,225,244,225,104,134,5, +178,100,93,100,98,100,112,100,121,100,136,100,152,177,54,128, +5,178,50,2,100,104,100,108,51,128,5,178,102,128,5,178, +232,229,226,242,229,119,128,5,178,238,225,242,242,239,247,232, +229,226,242,229,119,128,5,178,241,245,225,242,244,229,242,232, +229,226,242,229,119,128,5,178,247,233,228,229,232,229,226,242, +229,119,128,5,178,241,225,237,225,244,115,135,5,179,100,188, +100,193,100,198,100,203,100,212,100,227,100,243,177,98,128,5, +179,178,56,128,5,179,179,52,128,5,179,232,229,226,242,229, +119,128,5,179,238,225,242,242,239,247,232,229,226,242,229,119, +128,5,179,241,245,225,242,244,229,242,232,229,226,242,229,119, +128,5,179,247,233,228,229,232,229,226,242,229,119,128,5,179, +243,229,231,239,108,135,5,177,101,22,101,27,101,32,101,37, +101,46,101,61,101,77,177,55,128,5,177,178,52,128,5,177, +179,48,128,5,177,232,229,226,242,229,119,128,5,177,238,225, +242,242,239,247,232,229,226,242,229,119,128,5,177,241,245,225, +242,244,229,242,232,229,226,242,229,119,128,5,177,247,233,228, +229,232,229,226,242,229,119,128,5,177,98,3,101,98,101,103, +101,113,225,114,128,1,39,239,240,239,237,239,230,111,128,49, +15,242,229,246,229,226,229,236,239,119,128,30,43,99,2,101, +131,101,140,229,228,233,236,236,97,128,30,41,233,242,99,2, +101,148,101,153,236,101,128,36,215,245,237,230,236,229,120,128, +1,37,100,2,101,168,101,178,233,229,242,229,243,233,115,128, +30,39,239,116,2,101,185,101,194,225,227,227,229,238,116,128, +30,35,226,229,236,239,119,128,30,37,101,136,5,212,101,222, +101,255,102,19,102,248,103,8,103,53,103,62,103,75,225,242, +116,129,38,101,101,230,243,245,233,116,2,101,239,101,247,226, +236,225,227,107,128,38,101,247,232,233,244,101,128,38,97,228, +225,231,229,243,104,129,251,52,102,10,232,229,226,242,229,119, +128,251,52,104,6,102,33,102,61,102,69,102,119,102,165,102, +214,97,2,102,39,102,53,236,244,239,238,229,225,242,225,226, +233,99,128,6,193,242,225,226,233,99,128,6,71,229,226,242, +229,119,128,5,212,230,233,238,225,236,97,2,102,80,102,111, +236,116,2,102,87,102,99,239,238,229,225,242,225,226,233,99, +128,251,167,244,247,239,225,242,225,226,233,99,128,254,234,242, +225,226,233,99,128,254,234,232,225,237,250,225,225,226,239,246, +101,2,102,134,102,148,230,233,238,225,236,225,242,225,226,233, +99,128,251,165,233,243,239,236,225,244,229,228,225,242,225,226, +233,99,128,251,164,105,2,102,171,102,205,238,233,244,233,225, +236,97,2,102,183,102,197,236,244,239,238,229,225,242,225,226, +233,99,128,251,168,242,225,226,233,99,128,254,235,242,225,231, +225,238,97,128,48,120,237,229,228,233,225,236,97,2,102,226, +102,240,236,244,239,238,229,225,242,225,226,233,99,128,251,169, +242,225,226,233,99,128,254,236,233,243,229,233,229,242,225,243, +241,245,225,242,101,128,51,123,107,2,103,14,103,38,225,244, +225,235,225,238,97,129,48,216,103,26,232,225,236,230,247,233, +228,244,104,128,255,141,245,244,225,225,242,245,243,241,245,225, +242,101,128,51,54,238,231,232,239,239,107,128,2,103,242,245, +244,245,243,241,245,225,242,101,128,51,57,116,129,5,215,103, +81,232,229,226,242,229,119,128,5,215,232,239,239,107,129,2, +102,103,99,243,245,240,229,242,233,239,114,128,2,177,105,4, +103,120,103,205,103,216,103,241,229,245,104,4,103,132,103,167, +103,182,103,191,97,2,103,138,103,153,227,233,242,227,236,229, +235,239,242,229,225,110,128,50,123,240,225,242,229,238,235,239, +242,229,225,110,128,50,27,227,233,242,227,236,229,235,239,242, +229,225,110,128,50,109,235,239,242,229,225,110,128,49,78,240, +225,242,229,238,235,239,242,229,225,110,128,50,13,232,233,242, +225,231,225,238,97,128,48,114,235,225,244,225,235,225,238,97, +129,48,210,103,229,232,225,236,230,247,233,228,244,104,128,255, +139,242,233,113,134,5,180,104,3,104,8,104,22,104,31,104, +46,104,62,177,52,128,5,180,50,2,104,14,104,18,49,128, +5,180,100,128,5,180,232,229,226,242,229,119,128,5,180,238, +225,242,242,239,247,232,229,226,242,229,119,128,5,180,241,245, +225,242,244,229,242,232,229,226,242,229,119,128,5,180,247,233, +228,229,232,229,226,242,229,119,128,5,180,236,233,238,229,226, +229,236,239,119,128,30,150,237,239,238,239,243,240,225,227,101, +128,255,72,111,9,104,119,104,130,104,154,104,179,105,11,105, +24,105,110,105,150,105,161,225,242,237,229,238,233,225,110,128, +5,112,232,105,2,104,137,104,145,240,244,232,225,105,128,14, +43,242,225,231,225,238,97,128,48,123,235,225,244,225,235,225, +238,97,129,48,219,104,167,232,225,236,230,247,233,228,244,104, +128,255,142,236,225,109,135,5,185,104,199,104,204,104,209,104, +214,104,223,104,238,104,254,177,57,128,5,185,178,54,128,5, +185,179,50,128,5,185,232,229,226,242,229,119,128,5,185,238, +225,242,242,239,247,232,229,226,242,229,119,128,5,185,241,245, +225,242,244,229,242,232,229,226,242,229,119,128,5,185,247,233, +228,229,232,229,226,242,229,119,128,5,185,238,239,235,232,245, +235,244,232,225,105,128,14,46,111,2,105,30,105,100,107,4, +105,40,105,52,105,58,105,80,225,226,239,246,229,227,239,237, +98,128,3,9,227,237,98,128,3,9,240,225,236,225,244,225, +236,233,250,229,228,226,229,236,239,247,227,237,98,128,3,33, +242,229,244,242,239,230,236,229,248,226,229,236,239,247,227,237, +98,128,3,34,238,243,241,245,225,242,101,128,51,66,114,2, +105,116,105,143,105,2,105,122,105,131,227,239,240,244,233,99, +128,3,233,250,239,238,244,225,236,226,225,114,128,32,21,238, +227,237,98,128,3,27,244,243,240,242,233,238,231,115,128,38, +104,245,243,101,128,35,2,240,225,242,229,110,128,36,163,243, +245,240,229,242,233,239,114,128,2,176,244,245,242,238,229,100, +128,2,101,117,4,105,205,105,216,105,229,105,254,232,233,242, +225,231,225,238,97,128,48,117,233,233,244,239,243,241,245,225, +242,101,128,51,51,235,225,244,225,235,225,238,97,129,48,213, +105,242,232,225,236,230,247,233,228,244,104,128,255,140,238,231, +225,242,245,237,236,225,245,116,129,2,221,106,13,227,237,98, +128,3,11,118,128,1,149,249,240,232,229,110,132,0,45,106, +39,106,50,106,62,106,85,233,238,230,229,242,233,239,114,128, +246,229,237,239,238,239,243,240,225,227,101,128,255,13,115,2, +106,68,106,75,237,225,236,108,128,254,99,245,240,229,242,233, +239,114,128,246,230,244,247,111,128,32,16,105,149,0,105,106, +137,106,160,106,194,106,241,110,123,110,243,111,24,111,51,111, +213,111,217,111,255,112,21,112,105,113,14,113,89,113,97,113, +110,113,197,113,254,114,26,114,70,225,99,2,106,144,106,150, +245,244,101,128,0,237,249,242,233,236,236,233,99,128,4,79, +98,3,106,168,106,177,106,187,229,238,231,225,236,105,128,9, +135,239,240,239,237,239,230,111,128,49,39,242,229,246,101,128, +1,45,99,3,106,202,106,209,106,231,225,242,239,110,128,1, +208,233,242,99,2,106,217,106,222,236,101,128,36,216,245,237, +230,236,229,120,128,0,238,249,242,233,236,236,233,99,128,4, +86,100,4,106,251,107,5,110,80,110,113,226,236,231,242,225, +246,101,128,2,9,101,2,107,11,110,75,239,231,242,225,240, +104,7,107,32,107,46,107,59,109,244,110,19,110,32,110,44, +229,225,242,244,232,227,233,242,227,236,101,128,50,143,230,233, +242,229,227,233,242,227,236,101,128,50,139,233,99,14,107,90, +107,106,107,205,108,3,108,69,108,98,108,114,108,171,108,220, +108,232,109,3,109,70,109,208,109,237,225,236,236,233,225,238, +227,229,240,225,242,229,110,128,50,63,99,4,107,116,107,127, +107,141,107,148,225,236,236,240,225,242,229,110,128,50,58,229, +238,244,242,229,227,233,242,227,236,101,128,50,165,236,239,243, +101,128,48,6,111,3,107,156,107,171,107,191,237,237,97,129, +48,1,107,164,236,229,230,116,128,255,100,238,231,242,225,244, +245,236,225,244,233,239,238,240,225,242,229,110,128,50,55,242, +242,229,227,244,227,233,242,227,236,101,128,50,163,101,3,107, +213,107,225,107,242,225,242,244,232,240,225,242,229,110,128,50, +47,238,244,229,242,240,242,233,243,229,240,225,242,229,110,128, +50,61,248,227,229,236,236,229,238,244,227,233,242,227,236,101, +128,50,157,102,2,108,9,108,24,229,243,244,233,246,225,236, +240,225,242,229,110,128,50,64,105,2,108,30,108,59,238,225, +238,227,233,225,108,2,108,42,108,51,227,233,242,227,236,101, +128,50,150,240,225,242,229,110,128,50,54,242,229,240,225,242, +229,110,128,50,43,104,2,108,75,108,86,225,246,229,240,225, +242,229,110,128,50,50,233,231,232,227,233,242,227,236,101,128, +50,164,233,244,229,242,225,244,233,239,238,237,225,242,107,128, +48,5,108,3,108,122,108,148,108,160,225,226,239,114,2,108, +131,108,140,227,233,242,227,236,101,128,50,152,240,225,242,229, +110,128,50,56,229,230,244,227,233,242,227,236,101,128,50,167, +239,247,227,233,242,227,236,101,128,50,166,109,2,108,177,108, +209,101,2,108,183,108,198,228,233,227,233,238,229,227,233,242, +227,236,101,128,50,169,244,225,236,240,225,242,229,110,128,50, +46,239,239,238,240,225,242,229,110,128,50,42,238,225,237,229, +240,225,242,229,110,128,50,52,112,2,108,238,108,246,229,242, +233,239,100,128,48,2,242,233,238,244,227,233,242,227,236,101, +128,50,158,114,2,109,9,109,57,101,3,109,17,109,28,109, +43,225,227,232,240,225,242,229,110,128,50,67,240,242,229,243, +229,238,244,240,225,242,229,110,128,50,57,243,239,245,242,227, +229,240,225,242,229,110,128,50,62,233,231,232,244,227,233,242, +227,236,101,128,50,168,115,5,109,82,109,111,109,125,109,150, +109,178,101,2,109,88,109,101,227,242,229,244,227,233,242,227, +236,101,128,50,153,236,230,240,225,242,229,110,128,50,66,239, +227,233,229,244,249,240,225,242,229,110,128,50,51,112,2,109, +131,109,137,225,227,101,128,48,0,229,227,233,225,236,240,225, +242,229,110,128,50,53,116,2,109,156,109,167,239,227,235,240, +225,242,229,110,128,50,49,245,228,249,240,225,242,229,110,128, +50,59,117,2,109,184,109,193,238,240,225,242,229,110,128,50, +48,240,229,242,246,233,243,229,240,225,242,229,110,128,50,60, +119,2,109,214,109,226,225,244,229,242,240,225,242,229,110,128, +50,44,239,239,228,240,225,242,229,110,128,50,45,250,229,242, +111,128,48,7,109,2,109,250,110,7,229,244,225,236,227,233, +242,227,236,101,128,50,142,239,239,238,227,233,242,227,236,101, +128,50,138,238,225,237,229,227,233,242,227,236,101,128,50,148, +243,245,238,227,233,242,227,236,101,128,50,144,119,2,110,50, +110,63,225,244,229,242,227,233,242,227,236,101,128,50,140,239, +239,228,227,233,242,227,236,101,128,50,141,246,97,128,9,7, +233,229,242,229,243,233,115,130,0,239,110,94,110,102,225,227, +245,244,101,128,30,47,227,249,242,233,236,236,233,99,128,4, +229,239,244,226,229,236,239,119,128,30,203,101,3,110,131,110, +147,110,158,226,242,229,246,229,227,249,242,233,236,236,233,99, +128,4,215,227,249,242,233,236,236,233,99,128,4,53,245,238, +103,4,110,170,110,205,110,220,110,229,97,2,110,176,110,191, +227,233,242,227,236,229,235,239,242,229,225,110,128,50,117,240, +225,242,229,238,235,239,242,229,225,110,128,50,21,227,233,242, +227,236,229,235,239,242,229,225,110,128,50,103,235,239,242,229, +225,110,128,49,71,240,225,242,229,238,235,239,242,229,225,110, +128,50,7,103,2,110,249,111,0,242,225,246,101,128,0,236, +117,2,111,6,111,15,234,225,242,225,244,105,128,10,135,242, +237,245,235,232,105,128,10,7,104,2,111,30,111,40,233,242, +225,231,225,238,97,128,48,68,239,239,235,225,226,239,246,101, +128,30,201,105,8,111,69,111,79,111,90,111,97,111,122,111, +138,111,153,111,169,226,229,238,231,225,236,105,128,9,136,227, +249,242,233,236,236,233,99,128,4,56,228,229,246,97,128,9, +8,231,117,2,111,104,111,113,234,225,242,225,244,105,128,10, +136,242,237,245,235,232,105,128,10,8,237,225,244,242,225,231, +245,242,237,245,235,232,105,128,10,64,238,246,229,242,244,229, +228,226,242,229,246,101,128,2,11,243,232,239,242,244,227,249, +242,233,236,236,233,99,128,4,57,246,239,247,229,236,243,233, +231,110,3,111,185,111,195,111,202,226,229,238,231,225,236,105, +128,9,192,228,229,246,97,128,9,64,231,245,234,225,242,225, +244,105,128,10,192,106,128,1,51,107,2,111,223,111,247,225, +244,225,235,225,238,97,129,48,164,111,235,232,225,236,230,247, +233,228,244,104,128,255,114,239,242,229,225,110,128,49,99,108, +2,112,5,112,10,228,101,128,2,220,245,249,232,229,226,242, +229,119,128,5,172,109,2,112,27,112,94,97,3,112,35,112, +55,112,80,227,242,239,110,129,1,43,112,44,227,249,242,233, +236,236,233,99,128,4,227,231,229,239,242,225,240,240,242,239, +248,233,237,225,244,229,236,249,229,241,245,225,108,128,34,83, +244,242,225,231,245,242,237,245,235,232,105,128,10,63,239,238, +239,243,240,225,227,101,128,255,73,110,5,112,117,112,127,112, +136,112,148,112,232,227,242,229,237,229,238,116,128,34,6,230, +233,238,233,244,121,128,34,30,233,225,242,237,229,238,233,225, +110,128,5,107,116,2,112,154,112,222,101,2,112,160,112,211, +231,242,225,108,131,34,43,112,173,112,191,112,196,98,2,112, +179,112,187,239,244,244,239,109,128,35,33,116,128,35,33,229, +120,128,248,245,116,2,112,202,112,207,239,112,128,35,32,112, +128,35,32,242,243,229,227,244,233,239,110,128,34,41,233,243, +241,245,225,242,101,128,51,5,118,3,112,240,112,249,113,2, +226,245,236,236,229,116,128,37,216,227,233,242,227,236,101,128, +37,217,243,237,233,236,229,230,225,227,101,128,38,59,111,3, +113,22,113,33,113,41,227,249,242,233,236,236,233,99,128,4, +81,231,239,238,229,107,128,1,47,244,97,131,3,185,113,52, +113,73,113,81,228,233,229,242,229,243,233,115,129,3,202,113, +65,244,239,238,239,115,128,3,144,236,225,244,233,110,128,2, +105,244,239,238,239,115,128,3,175,240,225,242,229,110,128,36, +164,242,233,231,245,242,237,245,235,232,105,128,10,114,115,4, +113,120,113,165,113,179,113,187,237,225,236,108,2,113,129,113, +140,232,233,242,225,231,225,238,97,128,48,67,235,225,244,225, +235,225,238,97,129,48,163,113,153,232,225,236,230,247,233,228, +244,104,128,255,104,243,232,225,242,226,229,238,231,225,236,105, +128,9,250,244,242,239,235,101,128,2,104,245,240,229,242,233, +239,114,128,246,237,116,2,113,203,113,237,229,242,225,244,233, +239,110,2,113,215,113,226,232,233,242,225,231,225,238,97,128, +48,157,235,225,244,225,235,225,238,97,128,48,253,233,236,228, +101,129,1,41,113,246,226,229,236,239,119,128,30,45,117,2, +114,4,114,15,226,239,240,239,237,239,230,111,128,49,41,227, +249,242,233,236,236,233,99,128,4,78,246,239,247,229,236,243, +233,231,110,3,114,42,114,52,114,59,226,229,238,231,225,236, +105,128,9,191,228,229,246,97,128,9,63,231,245,234,225,242, +225,244,105,128,10,191,250,232,233,244,243,97,2,114,81,114, +92,227,249,242,233,236,236,233,99,128,4,117,228,226,236,231, +242,225,246,229,227,249,242,233,236,236,233,99,128,4,119,106, +138,0,106,114,135,114,198,114,209,115,3,115,19,115,132,115, +201,115,206,115,218,115,226,97,4,114,145,114,156,114,166,114, +173,225,242,237,229,238,233,225,110,128,5,113,226,229,238,231, +225,236,105,128,9,156,228,229,246,97,128,9,28,231,117,2, +114,180,114,189,234,225,242,225,244,105,128,10,156,242,237,245, +235,232,105,128,10,28,226,239,240,239,237,239,230,111,128,49, +16,99,3,114,217,114,224,114,246,225,242,239,110,128,1,240, +233,242,99,2,114,232,114,237,236,101,128,36,217,245,237,230, +236,229,120,128,1,53,242,239,243,243,229,228,244,225,233,108, +128,2,157,228,239,244,236,229,243,243,243,244,242,239,235,101, +128,2,95,101,3,115,27,115,38,115,103,227,249,242,233,236, +236,233,99,128,4,88,229,109,4,115,49,115,58,115,72,115, +88,225,242,225,226,233,99,128,6,44,230,233,238,225,236,225, +242,225,226,233,99,128,254,158,233,238,233,244,233,225,236,225, +242,225,226,233,99,128,254,159,237,229,228,233,225,236,225,242, +225,226,233,99,128,254,160,104,2,115,109,115,118,225,242,225, +226,233,99,128,6,152,230,233,238,225,236,225,242,225,226,233, +99,128,251,139,104,2,115,138,115,188,97,3,115,146,115,156, +115,163,226,229,238,231,225,236,105,128,9,157,228,229,246,97, +128,9,29,231,117,2,115,170,115,179,234,225,242,225,244,105, +128,10,157,242,237,245,235,232,105,128,10,29,229,232,225,242, +237,229,238,233,225,110,128,5,123,233,115,128,48,4,237,239, +238,239,243,240,225,227,101,128,255,74,240,225,242,229,110,128, +36,165,243,245,240,229,242,233,239,114,128,2,178,107,146,0, +107,116,21,118,110,118,121,118,183,118,194,119,28,119,42,120, +150,121,90,121,103,121,129,121,178,122,60,122,82,122,95,122, +118,122,160,122,170,97,12,116,47,116,79,116,101,116,131,116, +245,117,14,117,44,117,69,117,175,117,189,118,56,118,85,98, +2,116,53,116,70,225,243,232,235,233,242,227,249,242,233,236, +236,233,99,128,4,161,229,238,231,225,236,105,128,9,149,99, +2,116,85,116,91,245,244,101,128,30,49,249,242,233,236,236, +233,99,128,4,58,228,101,2,116,108,116,126,243,227,229,238, +228,229,242,227,249,242,233,236,236,233,99,128,4,155,246,97, +128,9,21,102,135,5,219,116,149,116,158,116,178,116,192,116, +201,116,217,116,232,225,242,225,226,233,99,128,6,67,228,225, +231,229,243,104,129,251,59,116,169,232,229,226,242,229,119,128, +251,59,230,233,238,225,236,225,242,225,226,233,99,128,254,218, +232,229,226,242,229,119,128,5,219,233,238,233,244,233,225,236, +225,242,225,226,233,99,128,254,219,237,229,228,233,225,236,225, +242,225,226,233,99,128,254,220,242,225,230,229,232,229,226,242, +229,119,128,251,77,231,117,2,116,252,117,5,234,225,242,225, +244,105,128,10,149,242,237,245,235,232,105,128,10,21,104,2, +117,20,117,30,233,242,225,231,225,238,97,128,48,75,239,239, +235,227,249,242,233,236,236,233,99,128,4,196,235,225,244,225, +235,225,238,97,129,48,171,117,57,232,225,236,230,247,233,228, +244,104,128,255,118,112,2,117,75,117,96,240,97,129,3,186, +117,82,243,249,237,226,239,236,231,242,229,229,107,128,3,240, +249,229,239,245,110,3,117,108,117,122,117,156,237,233,229,245, +237,235,239,242,229,225,110,128,49,113,112,2,117,128,117,143, +232,233,229,245,240,232,235,239,242,229,225,110,128,49,132,233, +229,245,240,235,239,242,229,225,110,128,49,120,243,243,225,238, +231,240,233,229,245,240,235,239,242,229,225,110,128,49,121,242, +239,242,233,233,243,241,245,225,242,101,128,51,13,115,5,117, +201,117,245,118,4,118,12,118,40,232,233,228,225,225,245,244, +111,2,117,214,117,223,225,242,225,226,233,99,128,6,64,238, +239,243,233,228,229,226,229,225,242,233,238,231,225,242,225,226, +233,99,128,6,64,237,225,236,236,235,225,244,225,235,225,238, +97,128,48,245,241,245,225,242,101,128,51,132,242,97,2,118, +19,118,28,225,242,225,226,233,99,128,6,80,244,225,238,225, +242,225,226,233,99,128,6,77,244,242,239,235,229,227,249,242, +233,236,236,233,99,128,4,159,244,225,232,233,242,225,240,242, +239,236,239,238,231,237,225,242,235,232,225,236,230,247,233,228, +244,104,128,255,112,246,229,242,244,233,227,225,236,243,244,242, +239,235,229,227,249,242,233,236,236,233,99,128,4,157,226,239, +240,239,237,239,230,111,128,49,14,99,4,118,131,118,153,118, +162,118,170,97,2,118,137,118,147,236,243,241,245,225,242,101, +128,51,137,242,239,110,128,1,233,229,228,233,236,236,97,128, +1,55,233,242,227,236,101,128,36,218,239,237,237,225,225,227, +227,229,238,116,128,1,55,228,239,244,226,229,236,239,119,128, +30,51,101,4,118,204,118,231,119,0,119,12,104,2,118,210, +118,221,225,242,237,229,238,233,225,110,128,5,132,233,242,225, +231,225,238,97,128,48,81,235,225,244,225,235,225,238,97,129, +48,177,118,244,232,225,236,230,247,233,228,244,104,128,255,121, +238,225,242,237,229,238,233,225,110,128,5,111,243,237,225,236, +236,235,225,244,225,235,225,238,97,128,48,246,231,242,229,229, +238,236,225,238,228,233,99,128,1,56,104,6,119,56,119,185, +119,196,119,221,120,52,120,140,97,5,119,68,119,78,119,89, +119,96,119,121,226,229,238,231,225,236,105,128,9,150,227,249, +242,233,236,236,233,99,128,4,69,228,229,246,97,128,9,22, +231,117,2,119,103,119,112,234,225,242,225,244,105,128,10,150, +242,237,245,235,232,105,128,10,22,104,4,119,131,119,140,119, +154,119,170,225,242,225,226,233,99,128,6,46,230,233,238,225, +236,225,242,225,226,233,99,128,254,166,233,238,233,244,233,225, +236,225,242,225,226,233,99,128,254,167,237,229,228,233,225,236, +225,242,225,226,233,99,128,254,168,229,233,227,239,240,244,233, +99,128,3,231,232,97,2,119,203,119,210,228,229,246,97,128, +9,89,231,245,242,237,245,235,232,105,128,10,89,233,229,245, +235,104,4,119,235,120,14,120,29,120,38,97,2,119,241,120, +0,227,233,242,227,236,229,235,239,242,229,225,110,128,50,120, +240,225,242,229,238,235,239,242,229,225,110,128,50,24,227,233, +242,227,236,229,235,239,242,229,225,110,128,50,106,235,239,242, +229,225,110,128,49,75,240,225,242,229,238,235,239,242,229,225, +110,128,50,10,111,4,120,62,120,111,120,121,120,126,235,104, +4,120,73,120,82,120,91,120,101,225,233,244,232,225,105,128, +14,2,239,238,244,232,225,105,128,14,5,245,225,244,244,232, +225,105,128,14,3,247,225,233,244,232,225,105,128,14,4,237, +245,244,244,232,225,105,128,14,91,239,107,128,1,153,242,225, +235,232,225,238,231,244,232,225,105,128,14,6,250,243,241,245, +225,242,101,128,51,145,105,4,120,160,120,171,120,196,120,245, +232,233,242,225,231,225,238,97,128,48,77,235,225,244,225,235, +225,238,97,129,48,173,120,184,232,225,236,230,247,233,228,244, +104,128,255,119,242,111,3,120,205,120,220,120,236,231,245,242, +225,237,245,243,241,245,225,242,101,128,51,21,237,229,229,244, +239,242,245,243,241,245,225,242,101,128,51,22,243,241,245,225, +242,101,128,51,20,249,229,239,107,5,121,4,121,39,121,54, +121,63,121,77,97,2,121,10,121,25,227,233,242,227,236,229, +235,239,242,229,225,110,128,50,110,240,225,242,229,238,235,239, +242,229,225,110,128,50,14,227,233,242,227,236,229,235,239,242, +229,225,110,128,50,96,235,239,242,229,225,110,128,49,49,240, +225,242,229,238,235,239,242,229,225,110,128,50,0,243,233,239, +243,235,239,242,229,225,110,128,49,51,234,229,227,249,242,233, +236,236,233,99,128,4,92,108,2,121,109,121,120,233,238,229, +226,229,236,239,119,128,30,53,243,241,245,225,242,101,128,51, +152,109,3,121,137,121,151,121,162,227,245,226,229,228,243,241, +245,225,242,101,128,51,166,239,238,239,243,240,225,227,101,128, +255,75,243,241,245,225,242,229,228,243,241,245,225,242,101,128, +51,162,111,5,121,190,121,216,121,254,122,10,122,24,104,2, +121,196,121,206,233,242,225,231,225,238,97,128,48,83,237,243, +241,245,225,242,101,128,51,192,235,97,2,121,223,121,231,233, +244,232,225,105,128,14,1,244,225,235,225,238,97,129,48,179, +121,242,232,225,236,230,247,233,228,244,104,128,255,122,239,240, +239,243,241,245,225,242,101,128,51,30,240,240,225,227,249,242, +233,236,236,233,99,128,4,129,114,2,122,30,122,50,229,225, +238,243,244,225,238,228,225,242,228,243,249,237,226,239,108,128, +50,127,239,238,233,243,227,237,98,128,3,67,240,97,2,122, +67,122,73,242,229,110,128,36,166,243,241,245,225,242,101,128, +51,170,243,233,227,249,242,233,236,236,233,99,128,4,111,116, +2,122,101,122,110,243,241,245,225,242,101,128,51,207,245,242, +238,229,100,128,2,158,117,2,122,124,122,135,232,233,242,225, +231,225,238,97,128,48,79,235,225,244,225,235,225,238,97,129, +48,175,122,148,232,225,236,230,247,233,228,244,104,128,255,120, +246,243,241,245,225,242,101,128,51,184,247,243,241,245,225,242, +101,128,51,190,108,146,0,108,122,220,124,247,125,20,125,86, +125,124,126,20,126,29,126,45,126,69,126,87,126,205,126,246, +127,125,127,133,127,166,127,175,127,183,127,245,97,7,122,236, +122,246,122,253,123,4,123,29,123,45,124,235,226,229,238,231, +225,236,105,128,9,178,227,245,244,101,128,1,58,228,229,246, +97,128,9,50,231,117,2,123,11,123,20,234,225,242,225,244, +105,128,10,178,242,237,245,235,232,105,128,10,50,235,235,232, +225,238,231,249,225,239,244,232,225,105,128,14,69,109,10,123, +67,124,6,124,23,124,61,124,75,124,94,124,110,124,130,124, +150,124,173,97,2,123,73,123,254,236,229,102,4,123,85,123, +99,123,191,123,208,230,233,238,225,236,225,242,225,226,233,99, +128,254,252,232,225,237,250,97,2,123,109,123,150,225,226,239, +246,101,2,123,119,123,133,230,233,238,225,236,225,242,225,226, +233,99,128,254,248,233,243,239,236,225,244,229,228,225,242,225, +226,233,99,128,254,247,226,229,236,239,119,2,123,160,123,174, +230,233,238,225,236,225,242,225,226,233,99,128,254,250,233,243, +239,236,225,244,229,228,225,242,225,226,233,99,128,254,249,233, +243,239,236,225,244,229,228,225,242,225,226,233,99,128,254,251, +237,225,228,228,225,225,226,239,246,101,2,123,223,123,237,230, +233,238,225,236,225,242,225,226,233,99,128,254,246,233,243,239, +236,225,244,229,228,225,242,225,226,233,99,128,254,245,242,225, +226,233,99,128,6,68,226,228,97,129,3,187,124,14,243,244, +242,239,235,101,128,1,155,229,100,130,5,220,124,32,124,52, +228,225,231,229,243,104,129,251,60,124,43,232,229,226,242,229, +119,128,251,60,232,229,226,242,229,119,128,5,220,230,233,238, +225,236,225,242,225,226,233,99,128,254,222,232,225,232,233,238, +233,244,233,225,236,225,242,225,226,233,99,128,252,202,233,238, +233,244,233,225,236,225,242,225,226,233,99,128,254,223,234,229, +229,237,233,238,233,244,233,225,236,225,242,225,226,233,99,128, +252,201,235,232,225,232,233,238,233,244,233,225,236,225,242,225, +226,233,99,128,252,203,236,225,237,232,229,232,233,243,239,236, +225,244,229,228,225,242,225,226,233,99,128,253,242,237,101,2, +124,180,124,193,228,233,225,236,225,242,225,226,233,99,128,254, +224,229,109,2,124,200,124,219,232,225,232,233,238,233,244,233, +225,236,225,242,225,226,233,99,128,253,136,233,238,233,244,233, +225,236,225,242,225,226,233,99,128,252,204,242,231,229,227,233, +242,227,236,101,128,37,239,98,3,124,255,125,4,125,10,225, +114,128,1,154,229,236,116,128,2,108,239,240,239,237,239,230, +111,128,49,12,99,4,125,30,125,37,125,46,125,73,225,242, +239,110,128,1,62,229,228,233,236,236,97,128,1,60,233,242, +99,2,125,54,125,59,236,101,128,36,219,245,237,230,236,229, +248,226,229,236,239,119,128,30,61,239,237,237,225,225,227,227, +229,238,116,128,1,60,228,239,116,130,1,64,125,96,125,105, +225,227,227,229,238,116,128,1,64,226,229,236,239,119,129,30, +55,125,115,237,225,227,242,239,110,128,30,57,101,3,125,132, +125,170,126,15,230,116,2,125,139,125,155,225,238,231,236,229, +225,226,239,246,229,227,237,98,128,3,26,244,225,227,235,226, +229,236,239,247,227,237,98,128,3,24,243,115,132,0,60,125, +183,125,205,125,217,126,7,229,241,245,225,108,129,34,100,125, +193,239,242,231,242,229,225,244,229,114,128,34,218,237,239,238, +239,243,240,225,227,101,128,255,28,111,2,125,223,125,252,114, +2,125,229,125,242,229,241,245,233,246,225,236,229,238,116,128, +34,114,231,242,229,225,244,229,114,128,34,118,246,229,242,229, +241,245,225,108,128,34,102,243,237,225,236,108,128,254,100,250, +104,128,2,110,230,226,236,239,227,107,128,37,140,232,239,239, +235,242,229,244,242,239,230,236,229,120,128,2,109,105,2,126, +51,126,56,242,97,128,32,164,247,238,225,242,237,229,238,233, +225,110,128,5,108,106,129,1,201,126,75,229,227,249,242,233, +236,236,233,99,128,4,89,108,132,246,192,126,99,126,123,126, +134,126,143,97,2,126,105,126,112,228,229,246,97,128,9,51, +231,245,234,225,242,225,244,105,128,10,179,233,238,229,226,229, +236,239,119,128,30,59,236,225,228,229,246,97,128,9,52,246, +239,227,225,236,233,99,3,126,157,126,167,126,174,226,229,238, +231,225,236,105,128,9,225,228,229,246,97,128,9,97,246,239, +247,229,236,243,233,231,110,2,126,188,126,198,226,229,238,231, +225,236,105,128,9,227,228,229,246,97,128,9,99,109,3,126, +213,126,226,126,237,233,228,228,236,229,244,233,236,228,101,128, +2,107,239,238,239,243,240,225,227,101,128,255,76,243,241,245, +225,242,101,128,51,208,111,6,127,4,127,16,127,58,127,69, +127,75,127,117,227,232,245,236,225,244,232,225,105,128,14,44, +231,233,227,225,108,3,127,28,127,34,127,53,225,238,100,128, +34,39,238,239,116,129,0,172,127,42,242,229,246,229,242,243, +229,100,128,35,16,239,114,128,34,40,236,233,238,231,244,232, +225,105,128,14,37,238,231,115,128,1,127,247,236,233,238,101, +2,127,85,127,108,99,2,127,91,127,103,229,238,244,229,242, +236,233,238,101,128,254,78,237,98,128,3,50,228,225,243,232, +229,100,128,254,77,250,229,238,231,101,128,37,202,240,225,242, +229,110,128,36,167,115,3,127,141,127,148,127,156,236,225,243, +104,128,1,66,241,245,225,242,101,128,33,19,245,240,229,242, +233,239,114,128,246,238,244,243,232,225,228,101,128,37,145,245, +244,232,225,105,128,14,38,246,239,227,225,236,233,99,3,127, +197,127,207,127,214,226,229,238,231,225,236,105,128,9,140,228, +229,246,97,128,9,12,246,239,247,229,236,243,233,231,110,2, +127,228,127,238,226,229,238,231,225,236,105,128,9,226,228,229, +246,97,128,9,98,248,243,241,245,225,242,101,128,51,211,109, +144,0,109,128,35,130,144,130,169,130,196,130,221,132,18,132, +40,133,95,133,125,133,174,134,25,134,47,134,72,134,81,135, +108,135,136,97,12,128,61,128,71,128,135,128,142,128,167,128, +215,130,51,130,76,130,81,130,95,130,107,130,112,226,229,238, +231,225,236,105,128,9,174,99,2,128,77,128,129,242,239,110, +132,0,175,128,91,128,102,128,108,128,117,226,229,236,239,247, +227,237,98,128,3,49,227,237,98,128,3,4,236,239,247,237, +239,100,128,2,205,237,239,238,239,243,240,225,227,101,128,255, +227,245,244,101,128,30,63,228,229,246,97,128,9,46,231,117, +2,128,149,128,158,234,225,242,225,244,105,128,10,174,242,237, +245,235,232,105,128,10,46,104,2,128,173,128,205,225,240,225, +235,104,2,128,183,128,192,232,229,226,242,229,119,128,5,164, +236,229,230,244,232,229,226,242,229,119,128,5,164,233,242,225, +231,225,238,97,128,48,126,105,5,128,227,129,40,129,103,129, +133,130,39,227,232,225,244,244,225,247,97,3,128,242,129,17, +129,24,236,239,119,2,128,250,129,5,236,229,230,244,244,232, +225,105,128,248,149,242,233,231,232,244,244,232,225,105,128,248, +148,244,232,225,105,128,14,75,245,240,240,229,242,236,229,230, +244,244,232,225,105,128,248,147,229,107,3,129,49,129,80,129, +87,236,239,119,2,129,57,129,68,236,229,230,244,244,232,225, +105,128,248,140,242,233,231,232,244,244,232,225,105,128,248,139, +244,232,225,105,128,14,72,245,240,240,229,242,236,229,230,244, +244,232,225,105,128,248,138,232,225,238,225,235,225,116,2,129, +115,129,126,236,229,230,244,244,232,225,105,128,248,132,244,232, +225,105,128,14,49,116,3,129,141,129,169,129,232,225,233,235, +232,117,2,129,151,129,162,236,229,230,244,244,232,225,105,128, +248,137,244,232,225,105,128,14,71,232,111,3,129,178,129,209, +129,216,236,239,119,2,129,186,129,197,236,229,230,244,244,232, +225,105,128,248,143,242,233,231,232,244,244,232,225,105,128,248, +142,244,232,225,105,128,14,73,245,240,240,229,242,236,229,230, +244,244,232,225,105,128,248,141,242,105,3,129,241,130,16,130, +23,236,239,119,2,129,249,130,4,236,229,230,244,244,232,225, +105,128,248,146,242,233,231,232,244,244,232,225,105,128,248,145, +244,232,225,105,128,14,74,245,240,240,229,242,236,229,230,244, +244,232,225,105,128,248,144,249,225,237,239,235,244,232,225,105, +128,14,70,235,225,244,225,235,225,238,97,129,48,222,130,64, +232,225,236,230,247,233,228,244,104,128,255,143,236,101,128,38, +66,238,243,249,239,238,243,241,245,225,242,101,128,51,71,241, +225,230,232,229,226,242,229,119,128,5,190,242,115,128,38,66, +115,2,130,118,130,136,239,242,225,227,233,242,227,236,229,232, +229,226,242,229,119,128,5,175,241,245,225,242,101,128,51,131, +98,2,130,150,130,160,239,240,239,237,239,230,111,128,49,7, +243,241,245,225,242,101,128,51,212,99,2,130,175,130,183,233, +242,227,236,101,128,36,220,245,226,229,228,243,241,245,225,242, +101,128,51,165,228,239,116,2,130,204,130,213,225,227,227,229, +238,116,128,30,65,226,229,236,239,119,128,30,67,101,7,130, +237,131,108,131,119,131,134,131,159,131,196,131,208,101,2,130, +243,131,95,109,4,130,253,131,6,131,20,131,36,225,242,225, +226,233,99,128,6,69,230,233,238,225,236,225,242,225,226,233, +99,128,254,226,233,238,233,244,233,225,236,225,242,225,226,233, +99,128,254,227,237,101,2,131,43,131,56,228,233,225,236,225, +242,225,226,233,99,128,254,228,229,237,105,2,131,64,131,79, +238,233,244,233,225,236,225,242,225,226,233,99,128,252,209,243, +239,236,225,244,229,228,225,242,225,226,233,99,128,252,72,244, +239,242,245,243,241,245,225,242,101,128,51,77,232,233,242,225, +231,225,238,97,128,48,129,233,250,233,229,242,225,243,241,245, +225,242,101,128,51,126,235,225,244,225,235,225,238,97,129,48, +225,131,147,232,225,236,230,247,233,228,244,104,128,255,146,109, +130,5,222,131,167,131,187,228,225,231,229,243,104,129,251,62, +131,178,232,229,226,242,229,119,128,251,62,232,229,226,242,229, +119,128,5,222,238,225,242,237,229,238,233,225,110,128,5,116, +242,235,232,97,3,131,219,131,228,132,5,232,229,226,242,229, +119,128,5,165,235,229,230,245,236,97,2,131,239,131,248,232, +229,226,242,229,119,128,5,166,236,229,230,244,232,229,226,242, +229,119,128,5,166,236,229,230,244,232,229,226,242,229,119,128, +5,165,104,2,132,24,132,30,239,239,107,128,2,113,250,243, +241,245,225,242,101,128,51,146,105,6,132,54,132,91,132,228, +132,239,133,8,133,65,228,100,2,132,61,132,86,236,229,228, +239,244,235,225,244,225,235,225,238,225,232,225,236,230,247,233, +228,244,104,128,255,101,239,116,128,0,183,229,245,109,5,132, +105,132,140,132,155,132,164,132,215,97,2,132,111,132,126,227, +233,242,227,236,229,235,239,242,229,225,110,128,50,114,240,225, +242,229,238,235,239,242,229,225,110,128,50,18,227,233,242,227, +236,229,235,239,242,229,225,110,128,50,100,235,239,242,229,225, +110,128,49,65,112,2,132,170,132,202,97,2,132,176,132,190, +238,243,233,239,243,235,239,242,229,225,110,128,49,112,242,229, +238,235,239,242,229,225,110,128,50,4,233,229,245,240,235,239, +242,229,225,110,128,49,110,243,233,239,243,235,239,242,229,225, +110,128,49,111,232,233,242,225,231,225,238,97,128,48,127,235, +225,244,225,235,225,238,97,129,48,223,132,252,232,225,236,230, +247,233,228,244,104,128,255,144,238,117,2,133,15,133,60,115, +132,34,18,133,27,133,38,133,47,133,53,226,229,236,239,247, +227,237,98,128,3,32,227,233,242,227,236,101,128,34,150,237, +239,100,128,2,215,240,236,245,115,128,34,19,244,101,128,32, +50,242,105,2,133,72,133,86,226,225,225,242,245,243,241,245, +225,242,101,128,51,74,243,241,245,225,242,101,128,51,73,108, +2,133,101,133,116,239,238,231,236,229,231,244,245,242,238,229, +100,128,2,112,243,241,245,225,242,101,128,51,150,109,3,133, +133,133,147,133,158,227,245,226,229,228,243,241,245,225,242,101, +128,51,163,239,238,239,243,240,225,227,101,128,255,77,243,241, +245,225,242,229,228,243,241,245,225,242,101,128,51,159,111,5, +133,186,133,212,133,237,133,247,134,0,104,2,133,192,133,202, +233,242,225,231,225,238,97,128,48,130,237,243,241,245,225,242, +101,128,51,193,235,225,244,225,235,225,238,97,129,48,226,133, +225,232,225,236,230,247,233,228,244,104,128,255,147,236,243,241, +245,225,242,101,128,51,214,237,225,244,232,225,105,128,14,33, +246,229,242,243,243,241,245,225,242,101,129,51,167,134,15,228, +243,241,245,225,242,101,128,51,168,240,97,2,134,32,134,38, +242,229,110,128,36,168,243,241,245,225,242,101,128,51,171,115, +2,134,53,134,62,243,241,245,225,242,101,128,51,179,245,240, +229,242,233,239,114,128,246,239,244,245,242,238,229,100,128,2, +111,117,141,0,181,134,111,134,115,134,125,134,149,134,159,134, +181,134,192,134,217,134,240,134,250,135,24,135,88,135,98,49, +128,0,181,225,243,241,245,225,242,101,128,51,130,227,104,2, +134,132,134,142,231,242,229,225,244,229,114,128,34,107,236,229, +243,115,128,34,106,230,243,241,245,225,242,101,128,51,140,103, +2,134,165,134,172,242,229,229,107,128,3,188,243,241,245,225, +242,101,128,51,141,232,233,242,225,231,225,238,97,128,48,128, +235,225,244,225,235,225,238,97,129,48,224,134,205,232,225,236, +230,247,233,228,244,104,128,255,145,108,2,134,223,134,232,243, +241,245,225,242,101,128,51,149,244,233,240,236,121,128,0,215, +237,243,241,245,225,242,101,128,51,155,238,225,104,2,135,2, +135,11,232,229,226,242,229,119,128,5,163,236,229,230,244,232, +229,226,242,229,119,128,5,163,115,2,135,30,135,79,233,99, +3,135,39,135,56,135,67,225,236,238,239,244,101,129,38,106, +135,50,228,226,108,128,38,107,230,236,225,244,243,233,231,110, +128,38,109,243,232,225,242,240,243,233,231,110,128,38,111,243, +241,245,225,242,101,128,51,178,246,243,241,245,225,242,101,128, +51,182,247,243,241,245,225,242,101,128,51,188,118,2,135,114, +135,127,237,229,231,225,243,241,245,225,242,101,128,51,185,243, +241,245,225,242,101,128,51,183,119,2,135,142,135,155,237,229, +231,225,243,241,245,225,242,101,128,51,191,243,241,245,225,242, +101,128,51,189,110,150,0,110,135,212,136,90,136,114,136,180, +136,205,137,7,137,17,137,84,137,127,139,161,139,179,139,204, +139,235,140,5,140,70,142,52,142,60,142,85,142,93,143,61, +143,71,143,81,97,8,135,230,135,250,136,1,136,8,136,33, +136,44,136,69,136,81,98,2,135,236,135,245,229,238,231,225, +236,105,128,9,168,236,97,128,34,7,227,245,244,101,128,1, +68,228,229,246,97,128,9,40,231,117,2,136,15,136,24,234, +225,242,225,244,105,128,10,168,242,237,245,235,232,105,128,10, +40,232,233,242,225,231,225,238,97,128,48,106,235,225,244,225, +235,225,238,97,129,48,202,136,57,232,225,236,230,247,233,228, +244,104,128,255,133,240,239,243,244,242,239,240,232,101,128,1, +73,243,241,245,225,242,101,128,51,129,98,2,136,96,136,106, +239,240,239,237,239,230,111,128,49,11,243,240,225,227,101,128, +0,160,99,4,136,124,136,131,136,140,136,167,225,242,239,110, +128,1,72,229,228,233,236,236,97,128,1,70,233,242,99,2, +136,148,136,153,236,101,128,36,221,245,237,230,236,229,248,226, +229,236,239,119,128,30,75,239,237,237,225,225,227,227,229,238, +116,128,1,70,228,239,116,2,136,188,136,197,225,227,227,229, +238,116,128,30,69,226,229,236,239,119,128,30,71,101,3,136, +213,136,224,136,249,232,233,242,225,231,225,238,97,128,48,109, +235,225,244,225,235,225,238,97,129,48,205,136,237,232,225,236, +230,247,233,228,244,104,128,255,136,247,243,232,229,241,229,236, +243,233,231,110,128,32,170,230,243,241,245,225,242,101,128,51, +139,103,2,137,23,137,73,97,3,137,31,137,41,137,48,226, +229,238,231,225,236,105,128,9,153,228,229,246,97,128,9,25, +231,117,2,137,55,137,64,234,225,242,225,244,105,128,10,153, +242,237,245,235,232,105,128,10,25,239,238,231,245,244,232,225, +105,128,14,7,104,2,137,90,137,100,233,242,225,231,225,238, +97,128,48,147,239,239,107,2,137,108,137,115,236,229,230,116, +128,2,114,242,229,244,242,239,230,236,229,120,128,2,115,105, +4,137,137,138,50,138,61,138,119,229,245,110,7,137,155,137, +190,137,222,137,236,137,245,138,22,138,35,97,2,137,161,137, +176,227,233,242,227,236,229,235,239,242,229,225,110,128,50,111, +240,225,242,229,238,235,239,242,229,225,110,128,50,15,227,105, +2,137,197,137,209,229,245,227,235,239,242,229,225,110,128,49, +53,242,227,236,229,235,239,242,229,225,110,128,50,97,232,233, +229,245,232,235,239,242,229,225,110,128,49,54,235,239,242,229, +225,110,128,49,52,240,97,2,137,252,138,10,238,243,233,239, +243,235,239,242,229,225,110,128,49,104,242,229,238,235,239,242, +229,225,110,128,50,1,243,233,239,243,235,239,242,229,225,110, +128,49,103,244,233,235,229,245,244,235,239,242,229,225,110,128, +49,102,232,233,242,225,231,225,238,97,128,48,107,107,2,138, +67,138,91,225,244,225,235,225,238,97,129,48,203,138,79,232, +225,236,230,247,233,228,244,104,128,255,134,232,225,232,233,116, +2,138,101,138,112,236,229,230,244,244,232,225,105,128,248,153, +244,232,225,105,128,14,77,238,101,141,0,57,138,150,138,159, +138,169,138,199,138,206,138,231,139,2,139,36,139,48,139,59, +139,92,139,100,139,111,225,242,225,226,233,99,128,6,105,226, +229,238,231,225,236,105,128,9,239,227,233,242,227,236,101,129, +36,104,138,180,233,238,246,229,242,243,229,243,225,238,243,243, +229,242,233,102,128,39,146,228,229,246,97,128,9,111,231,117, +2,138,213,138,222,234,225,242,225,244,105,128,10,239,242,237, +245,235,232,105,128,10,111,232,97,2,138,238,138,249,227,235, +225,242,225,226,233,99,128,6,105,238,231,250,232,239,117,128, +48,41,105,2,139,8,139,26,228,229,239,231,242,225,240,232, +233,227,240,225,242,229,110,128,50,40,238,230,229,242,233,239, +114,128,32,137,237,239,238,239,243,240,225,227,101,128,255,25, +239,236,228,243,244,249,236,101,128,247,57,112,2,139,65,139, +72,225,242,229,110,128,36,124,229,114,2,139,79,139,85,233, +239,100,128,36,144,243,233,225,110,128,6,249,242,239,237,225, +110,128,33,120,243,245,240,229,242,233,239,114,128,32,121,116, +2,139,117,139,155,229,229,110,2,139,125,139,134,227,233,242, +227,236,101,128,36,114,112,2,139,140,139,147,225,242,229,110, +128,36,134,229,242,233,239,100,128,36,154,232,225,105,128,14, +89,106,129,1,204,139,167,229,227,249,242,233,236,236,233,99, +128,4,90,235,225,244,225,235,225,238,97,129,48,243,139,192, +232,225,236,230,247,233,228,244,104,128,255,157,108,2,139,210, +139,224,229,231,242,233,231,232,244,236,239,238,103,128,1,158, +233,238,229,226,229,236,239,119,128,30,73,109,2,139,241,139, +252,239,238,239,243,240,225,227,101,128,255,78,243,241,245,225, +242,101,128,51,154,110,2,140,11,140,61,97,3,140,19,140, +29,140,36,226,229,238,231,225,236,105,128,9,163,228,229,246, +97,128,9,35,231,117,2,140,43,140,52,234,225,242,225,244, +105,128,10,163,242,237,245,235,232,105,128,10,35,238,225,228, +229,246,97,128,9,41,111,6,140,84,140,95,140,120,140,161, +141,113,142,40,232,233,242,225,231,225,238,97,128,48,110,235, +225,244,225,235,225,238,97,129,48,206,140,108,232,225,236,230, +247,233,228,244,104,128,255,137,110,3,140,128,140,144,140,153, +226,242,229,225,235,233,238,231,243,240,225,227,101,128,0,160, +229,238,244,232,225,105,128,14,19,245,244,232,225,105,128,14, +25,239,110,7,140,178,140,187,140,201,140,235,140,251,141,36, +141,95,225,242,225,226,233,99,128,6,70,230,233,238,225,236, +225,242,225,226,233,99,128,254,230,231,232,245,238,238,97,2, +140,212,140,221,225,242,225,226,233,99,128,6,186,230,233,238, +225,236,225,242,225,226,233,99,128,251,159,233,238,233,244,233, +225,236,225,242,225,226,233,99,128,254,231,234,229,229,237,105, +2,141,5,141,20,238,233,244,233,225,236,225,242,225,226,233, +99,128,252,210,243,239,236,225,244,229,228,225,242,225,226,233, +99,128,252,75,237,101,2,141,43,141,56,228,233,225,236,225, +242,225,226,233,99,128,254,232,229,237,105,2,141,64,141,79, +238,233,244,233,225,236,225,242,225,226,233,99,128,252,213,243, +239,236,225,244,229,228,225,242,225,226,233,99,128,252,78,238, +239,239,238,230,233,238,225,236,225,242,225,226,233,99,128,252, +141,116,7,141,129,141,140,141,169,141,204,141,216,141,236,142, +6,227,239,238,244,225,233,238,115,128,34,12,101,2,141,146, +141,162,236,229,237,229,238,116,129,34,9,141,157,239,102,128, +34,9,241,245,225,108,128,34,96,231,242,229,225,244,229,114, +129,34,111,141,181,238,239,114,2,141,189,141,197,229,241,245, +225,108,128,34,113,236,229,243,115,128,34,121,233,228,229,238, +244,233,227,225,108,128,34,98,236,229,243,115,129,34,110,141, +225,238,239,242,229,241,245,225,108,128,34,112,112,2,141,242, +141,252,225,242,225,236,236,229,108,128,34,38,242,229,227,229, +228,229,115,128,34,128,243,117,3,142,15,142,22,142,31,226, +243,229,116,128,34,132,227,227,229,229,228,115,128,34,129,240, +229,242,243,229,116,128,34,133,247,225,242,237,229,238,233,225, +110,128,5,118,240,225,242,229,110,128,36,169,115,2,142,66, +142,75,243,241,245,225,242,101,128,51,177,245,240,229,242,233, +239,114,128,32,127,244,233,236,228,101,128,0,241,117,132,3, +189,142,105,142,116,142,197,143,24,232,233,242,225,231,225,238, +97,128,48,108,107,2,142,122,142,146,225,244,225,235,225,238, +97,129,48,204,142,134,232,225,236,230,247,233,228,244,104,128, +255,135,244,97,3,142,155,142,165,142,172,226,229,238,231,225, +236,105,128,9,188,228,229,246,97,128,9,60,231,117,2,142, +179,142,188,234,225,242,225,244,105,128,10,188,242,237,245,235, +232,105,128,10,60,109,2,142,203,142,237,226,229,242,243,233, +231,110,130,0,35,142,217,142,229,237,239,238,239,243,240,225, +227,101,128,255,3,243,237,225,236,108,128,254,95,229,114,2, +142,244,143,20,225,236,243,233,231,110,2,142,255,143,7,231, +242,229,229,107,128,3,116,236,239,247,229,242,231,242,229,229, +107,128,3,117,111,128,33,22,110,130,5,224,143,32,143,52, +228,225,231,229,243,104,129,251,64,143,43,232,229,226,242,229, +119,128,251,64,232,229,226,242,229,119,128,5,224,246,243,241, +245,225,242,101,128,51,181,247,243,241,245,225,242,101,128,51, +187,249,97,3,143,90,143,100,143,107,226,229,238,231,225,236, +105,128,9,158,228,229,246,97,128,9,30,231,117,2,143,114, +143,123,234,225,242,225,244,105,128,10,158,242,237,245,235,232, +105,128,10,30,111,147,0,111,143,174,143,196,144,18,144,188, +145,4,145,19,145,59,145,182,145,203,145,241,145,252,146,174, +148,8,148,72,148,105,148,151,149,24,149,71,149,83,97,2, +143,180,143,187,227,245,244,101,128,0,243,238,231,244,232,225, +105,128,14,45,98,4,143,206,143,248,144,1,144,11,225,242, +242,229,100,130,2,117,143,218,143,229,227,249,242,233,236,236, +233,99,128,4,233,228,233,229,242,229,243,233,243,227,249,242, +233,236,236,233,99,128,4,235,229,238,231,225,236,105,128,9, +147,239,240,239,237,239,230,111,128,49,27,242,229,246,101,128, +1,79,99,3,144,26,144,99,144,178,97,2,144,32,144,93, +238,228,242,97,3,144,43,144,50,144,61,228,229,246,97,128, +9,17,231,245,234,225,242,225,244,105,128,10,145,246,239,247, +229,236,243,233,231,110,2,144,75,144,82,228,229,246,97,128, +9,73,231,245,234,225,242,225,244,105,128,10,201,242,239,110, +128,1,210,233,242,99,2,144,107,144,112,236,101,128,36,222, +245,237,230,236,229,120,133,0,244,144,131,144,139,144,150,144, +158,144,170,225,227,245,244,101,128,30,209,228,239,244,226,229, +236,239,119,128,30,217,231,242,225,246,101,128,30,211,232,239, +239,235,225,226,239,246,101,128,30,213,244,233,236,228,101,128, +30,215,249,242,233,236,236,233,99,128,4,62,100,4,144,198, +144,221,144,227,144,250,226,108,2,144,205,144,213,225,227,245, +244,101,128,1,81,231,242,225,246,101,128,2,13,229,246,97, +128,9,19,233,229,242,229,243,233,115,129,0,246,144,239,227, +249,242,233,236,236,233,99,128,4,231,239,244,226,229,236,239, +119,128,30,205,101,129,1,83,145,10,235,239,242,229,225,110, +128,49,90,103,3,145,27,145,42,145,49,239,238,229,107,129, +2,219,145,36,227,237,98,128,3,40,242,225,246,101,128,0, +242,245,234,225,242,225,244,105,128,10,147,104,4,145,69,145, +80,145,90,145,168,225,242,237,229,238,233,225,110,128,5,133, +233,242,225,231,225,238,97,128,48,74,111,2,145,96,145,106, +239,235,225,226,239,246,101,128,30,207,242,110,133,1,161,145, +121,145,129,145,140,145,148,145,160,225,227,245,244,101,128,30, +219,228,239,244,226,229,236,239,119,128,30,227,231,242,225,246, +101,128,30,221,232,239,239,235,225,226,239,246,101,128,30,223, +244,233,236,228,101,128,30,225,245,238,231,225,242,245,237,236, +225,245,116,128,1,81,105,129,1,163,145,188,238,246,229,242, +244,229,228,226,242,229,246,101,128,2,15,107,2,145,209,145, +233,225,244,225,235,225,238,97,129,48,170,145,221,232,225,236, +230,247,233,228,244,104,128,255,117,239,242,229,225,110,128,49, +87,236,229,232,229,226,242,229,119,128,5,171,109,6,146,10, +146,38,146,45,146,134,146,145,146,163,225,227,242,239,110,130, +1,77,146,22,146,30,225,227,245,244,101,128,30,83,231,242, +225,246,101,128,30,81,228,229,246,97,128,9,80,229,231,97, +133,3,201,146,61,146,65,146,76,146,90,146,106,49,128,3, +214,227,249,242,233,236,236,233,99,128,4,97,236,225,244,233, +238,227,236,239,243,229,100,128,2,119,242,239,245,238,228,227, +249,242,233,236,236,233,99,128,4,123,116,2,146,112,146,127, +233,244,236,239,227,249,242,233,236,236,233,99,128,4,125,239, +238,239,115,128,3,206,231,245,234,225,242,225,244,105,128,10, +208,233,227,242,239,110,129,3,191,146,155,244,239,238,239,115, +128,3,204,239,238,239,243,240,225,227,101,128,255,79,238,101, +145,0,49,146,213,146,222,146,232,147,6,147,31,147,40,147, +49,147,74,147,108,147,142,147,154,147,173,147,184,147,217,147, +227,147,235,147,246,225,242,225,226,233,99,128,6,97,226,229, +238,231,225,236,105,128,9,231,227,233,242,227,236,101,129,36, +96,146,243,233,238,246,229,242,243,229,243,225,238,243,243,229, +242,233,102,128,39,138,100,2,147,12,147,18,229,246,97,128, +9,103,239,244,229,238,236,229,225,228,229,114,128,32,36,229, +233,231,232,244,104,128,33,91,230,233,244,244,229,100,128,246, +220,231,117,2,147,56,147,65,234,225,242,225,244,105,128,10, +231,242,237,245,235,232,105,128,10,103,232,97,3,147,83,147, +94,147,99,227,235,225,242,225,226,233,99,128,6,97,236,102, +128,0,189,238,231,250,232,239,117,128,48,33,105,2,147,114, +147,132,228,229,239,231,242,225,240,232,233,227,240,225,242,229, +110,128,50,32,238,230,229,242,233,239,114,128,32,129,237,239, +238,239,243,240,225,227,101,128,255,17,238,245,237,229,242,225, +244,239,242,226,229,238,231,225,236,105,128,9,244,239,236,228, +243,244,249,236,101,128,247,49,112,2,147,190,147,197,225,242, +229,110,128,36,116,229,114,2,147,204,147,210,233,239,100,128, +36,136,243,233,225,110,128,6,241,241,245,225,242,244,229,114, +128,0,188,242,239,237,225,110,128,33,112,243,245,240,229,242, +233,239,114,128,0,185,244,104,2,147,253,148,2,225,105,128, +14,81,233,242,100,128,33,83,111,3,148,16,148,50,148,66, +103,2,148,22,148,40,239,238,229,107,129,1,235,148,31,237, +225,227,242,239,110,128,1,237,245,242,237,245,235,232,105,128, +10,19,237,225,244,242,225,231,245,242,237,245,235,232,105,128, +10,75,240,229,110,128,2,84,112,3,148,80,148,87,148,98, +225,242,229,110,128,36,170,229,238,226,245,236,236,229,116,128, +37,230,244,233,239,110,128,35,37,114,2,148,111,148,140,100, +2,148,117,148,128,230,229,237,233,238,233,238,101,128,0,170, +237,225,243,227,245,236,233,238,101,128,0,186,244,232,239,231, +239,238,225,108,128,34,31,115,5,148,163,148,195,148,212,149, +1,149,14,232,239,242,116,2,148,172,148,179,228,229,246,97, +128,9,18,246,239,247,229,236,243,233,231,238,228,229,246,97, +128,9,74,236,225,243,104,129,0,248,148,204,225,227,245,244, +101,128,1,255,237,225,236,108,2,148,221,148,232,232,233,242, +225,231,225,238,97,128,48,73,235,225,244,225,235,225,238,97, +129,48,169,148,245,232,225,236,230,247,233,228,244,104,128,255, +107,244,242,239,235,229,225,227,245,244,101,128,1,255,245,240, +229,242,233,239,114,128,246,240,116,2,149,30,149,41,227,249, +242,233,236,236,233,99,128,4,127,233,236,228,101,130,0,245, +149,52,149,60,225,227,245,244,101,128,30,77,228,233,229,242, +229,243,233,115,128,30,79,245,226,239,240,239,237,239,230,111, +128,49,33,118,2,149,89,149,170,229,114,2,149,96,149,162, +236,233,238,101,131,32,62,149,109,149,132,149,155,99,2,149, +115,149,127,229,238,244,229,242,236,233,238,101,128,254,74,237, +98,128,3,5,100,2,149,138,149,146,225,243,232,229,100,128, +254,73,226,236,247,225,246,121,128,254,76,247,225,246,121,128, +254,75,243,227,239,242,101,128,0,175,239,247,229,236,243,233, +231,110,3,149,185,149,195,149,202,226,229,238,231,225,236,105, +128,9,203,228,229,246,97,128,9,75,231,245,234,225,242,225, +244,105,128,10,203,112,145,0,112,149,251,152,123,152,134,152, +143,152,155,154,80,154,90,155,82,156,101,156,191,156,217,157, +92,157,100,158,2,158,60,158,88,158,98,97,14,150,25,150, +57,150,67,150,74,150,81,150,129,150,140,150,154,150,165,150, +212,150,226,151,238,152,21,152,111,97,2,150,31,150,43,237, +240,243,243,241,245,225,242,101,128,51,128,243,229,238,244,239, +243,241,245,225,242,101,128,51,43,226,229,238,231,225,236,105, +128,9,170,227,245,244,101,128,30,85,228,229,246,97,128,9, +42,103,2,150,87,150,105,101,2,150,93,150,100,228,239,247, +110,128,33,223,245,112,128,33,222,117,2,150,111,150,120,234, +225,242,225,244,105,128,10,170,242,237,245,235,232,105,128,10, +42,232,233,242,225,231,225,238,97,128,48,113,233,249,225,238, +238,239,233,244,232,225,105,128,14,47,235,225,244,225,235,225, +238,97,128,48,209,108,2,150,171,150,196,225,244,225,236,233, +250,225,244,233,239,238,227,249,242,233,236,236,233,227,227,237, +98,128,4,132,239,227,232,235,225,227,249,242,233,236,236,233, +99,128,4,192,238,243,233,239,243,235,239,242,229,225,110,128, +49,127,114,3,150,234,150,255,151,227,97,2,150,240,150,248, +231,242,225,240,104,128,0,182,236,236,229,108,128,34,37,229, +110,2,151,6,151,116,236,229,230,116,136,0,40,151,29,151, +44,151,49,151,54,151,65,151,77,151,100,151,105,225,236,244, +239,238,229,225,242,225,226,233,99,128,253,62,226,116,128,248, +237,229,120,128,248,236,233,238,230,229,242,233,239,114,128,32, +141,237,239,238,239,243,240,225,227,101,128,255,8,115,2,151, +83,151,90,237,225,236,108,128,254,89,245,240,229,242,233,239, +114,128,32,125,244,112,128,248,235,246,229,242,244,233,227,225, +108,128,254,53,242,233,231,232,116,136,0,41,151,140,151,155, +151,160,151,165,151,176,151,188,151,211,151,216,225,236,244,239, +238,229,225,242,225,226,233,99,128,253,63,226,116,128,248,248, +229,120,128,248,247,233,238,230,229,242,233,239,114,128,32,142, +237,239,238,239,243,240,225,227,101,128,255,9,115,2,151,194, +151,201,237,225,236,108,128,254,90,245,240,229,242,233,239,114, +128,32,126,244,112,128,248,246,246,229,242,244,233,227,225,108, +128,254,54,244,233,225,236,228,233,230,102,128,34,2,115,3, +151,246,152,1,152,13,229,241,232,229,226,242,229,119,128,5, +192,232,244,225,232,229,226,242,229,119,128,5,153,241,245,225, +242,101,128,51,169,244,225,104,134,5,183,152,39,152,53,152, +58,152,67,152,82,152,98,49,2,152,45,152,49,49,128,5, +183,100,128,5,183,178,97,128,5,183,232,229,226,242,229,119, +128,5,183,238,225,242,242,239,247,232,229,226,242,229,119,128, +5,183,241,245,225,242,244,229,242,232,229,226,242,229,119,128, +5,183,247,233,228,229,232,229,226,242,229,119,128,5,183,250, +229,242,232,229,226,242,229,119,128,5,161,226,239,240,239,237, +239,230,111,128,49,6,227,233,242,227,236,101,128,36,223,228, +239,244,225,227,227,229,238,116,128,30,87,101,137,5,228,152, +177,152,188,152,208,152,220,152,240,153,86,153,97,153,118,154, +73,227,249,242,233,236,236,233,99,128,4,63,228,225,231,229, +243,104,129,251,68,152,199,232,229,226,242,229,119,128,251,68, +229,250,233,243,241,245,225,242,101,128,51,59,230,233,238,225, +236,228,225,231,229,243,232,232,229,226,242,229,119,128,251,67, +104,5,152,252,153,19,153,27,153,41,153,71,225,114,2,153, +3,153,10,225,226,233,99,128,6,126,237,229,238,233,225,110, +128,5,122,229,226,242,229,119,128,5,228,230,233,238,225,236, +225,242,225,226,233,99,128,251,87,105,2,153,47,153,62,238, +233,244,233,225,236,225,242,225,226,233,99,128,251,88,242,225, +231,225,238,97,128,48,122,237,229,228,233,225,236,225,242,225, +226,233,99,128,251,89,235,225,244,225,235,225,238,97,128,48, +218,237,233,228,228,236,229,232,239,239,235,227,249,242,233,236, +236,233,99,128,4,167,114,5,153,130,153,142,153,184,154,49, +154,62,225,230,229,232,229,226,242,229,119,128,251,78,227,229, +238,116,131,0,37,153,155,153,164,153,176,225,242,225,226,233, +99,128,6,106,237,239,238,239,243,240,225,227,101,128,255,5, +243,237,225,236,108,128,254,106,105,2,153,190,154,31,239,100, +134,0,46,153,207,153,218,153,229,153,241,153,252,154,8,225, +242,237,229,238,233,225,110,128,5,137,227,229,238,244,229,242, +229,100,128,0,183,232,225,236,230,247,233,228,244,104,128,255, +97,233,238,230,229,242,233,239,114,128,246,231,237,239,238,239, +243,240,225,227,101,128,255,14,115,2,154,14,154,21,237,225, +236,108,128,254,82,245,240,229,242,233,239,114,128,246,232,243, +240,239,237,229,238,233,231,242,229,229,235,227,237,98,128,3, +66,240,229,238,228,233,227,245,236,225,114,128,34,165,244,232, +239,245,243,225,238,100,128,32,48,243,229,244,97,128,32,167, +230,243,241,245,225,242,101,128,51,138,104,3,154,98,154,148, +155,29,97,3,154,106,154,116,154,123,226,229,238,231,225,236, +105,128,9,171,228,229,246,97,128,9,43,231,117,2,154,130, +154,139,234,225,242,225,244,105,128,10,171,242,237,245,235,232, +105,128,10,43,105,133,3,198,154,162,154,166,154,252,155,4, +155,15,49,128,3,213,229,245,240,104,4,154,179,154,214,154, +229,154,238,97,2,154,185,154,200,227,233,242,227,236,229,235, +239,242,229,225,110,128,50,122,240,225,242,229,238,235,239,242, +229,225,110,128,50,26,227,233,242,227,236,229,235,239,242,229, +225,110,128,50,108,235,239,242,229,225,110,128,49,77,240,225, +242,229,238,235,239,242,229,225,110,128,50,12,236,225,244,233, +110,128,2,120,238,244,232,245,244,232,225,105,128,14,58,243, +249,237,226,239,236,231,242,229,229,107,128,3,213,111,3,155, +37,155,42,155,68,239,107,128,1,165,240,104,2,155,49,155, +58,225,238,244,232,225,105,128,14,30,245,238,231,244,232,225, +105,128,14,28,243,225,237,240,232,225,239,244,232,225,105,128, +14,32,105,133,3,192,155,96,156,52,156,63,156,74,156,88, +229,245,112,6,155,112,155,147,155,179,155,207,155,221,156,17, +97,2,155,118,155,133,227,233,242,227,236,229,235,239,242,229, +225,110,128,50,115,240,225,242,229,238,235,239,242,229,225,110, +128,50,19,227,105,2,155,154,155,166,229,245,227,235,239,242, +229,225,110,128,49,118,242,227,236,229,235,239,242,229,225,110, +128,50,101,107,2,155,185,155,199,233,249,229,239,235,235,239, +242,229,225,110,128,49,114,239,242,229,225,110,128,49,66,240, +225,242,229,238,235,239,242,229,225,110,128,50,5,243,233,239, +115,2,155,230,156,2,107,2,155,236,155,250,233,249,229,239, +235,235,239,242,229,225,110,128,49,116,239,242,229,225,110,128, +49,68,244,233,235,229,245,244,235,239,242,229,225,110,128,49, +117,116,2,156,23,156,38,232,233,229,245,244,232,235,239,242, +229,225,110,128,49,119,233,235,229,245,244,235,239,242,229,225, +110,128,49,115,232,233,242,225,231,225,238,97,128,48,116,235, +225,244,225,235,225,238,97,128,48,212,243,249,237,226,239,236, +231,242,229,229,107,128,3,214,247,242,225,242,237,229,238,233, +225,110,128,5,131,236,245,115,132,0,43,156,115,156,126,156, +135,156,168,226,229,236,239,247,227,237,98,128,3,31,227,233, +242,227,236,101,128,34,149,109,2,156,141,156,148,233,238,245, +115,128,0,177,111,2,156,154,156,158,100,128,2,214,238,239, +243,240,225,227,101,128,255,11,115,2,156,174,156,181,237,225, +236,108,128,254,98,245,240,229,242,233,239,114,128,32,122,109, +2,156,197,156,208,239,238,239,243,240,225,227,101,128,255,80, +243,241,245,225,242,101,128,51,216,111,5,156,229,156,240,157, +51,157,62,157,72,232,233,242,225,231,225,238,97,128,48,125, +233,238,244,233,238,231,233,238,228,229,120,4,157,4,157,16, +157,28,157,41,228,239,247,238,247,232,233,244,101,128,38,31, +236,229,230,244,247,232,233,244,101,128,38,28,242,233,231,232, +244,247,232,233,244,101,128,38,30,245,240,247,232,233,244,101, +128,38,29,235,225,244,225,235,225,238,97,128,48,221,240,236, +225,244,232,225,105,128,14,27,243,244,225,236,237,225,242,107, +129,48,18,157,85,230,225,227,101,128,48,32,240,225,242,229, +110,128,36,171,114,3,157,108,157,134,157,159,101,2,157,114, +157,122,227,229,228,229,115,128,34,122,243,227,242,233,240,244, +233,239,110,128,33,30,233,237,101,2,157,142,157,148,237,239, +100,128,2,185,242,229,246,229,242,243,229,100,128,32,53,111, +4,157,169,157,176,157,186,157,199,228,245,227,116,128,34,15, +234,229,227,244,233,246,101,128,35,5,236,239,238,231,229,228, +235,225,238,97,128,48,252,112,2,157,205,157,242,101,2,157, +211,157,218,236,236,239,114,128,35,24,242,243,117,2,157,226, +157,233,226,243,229,116,128,34,130,240,229,242,243,229,116,128, +34,131,239,242,244,233,239,110,129,34,55,157,253,225,108,128, +34,29,115,2,158,8,158,51,105,130,3,200,158,16,158,27, +227,249,242,233,236,236,233,99,128,4,113,236,233,240,238,229, +245,237,225,244,225,227,249,242,233,236,236,233,227,227,237,98, +128,4,134,243,241,245,225,242,101,128,51,176,117,2,158,66, +158,77,232,233,242,225,231,225,238,97,128,48,119,235,225,244, +225,235,225,238,97,128,48,215,246,243,241,245,225,242,101,128, +51,180,247,243,241,245,225,242,101,128,51,186,113,136,0,113, +158,128,159,177,159,188,159,197,159,204,159,216,159,254,160,6, +97,4,158,138,158,161,158,225,159,160,100,2,158,144,158,150, +229,246,97,128,9,88,237,225,232,229,226,242,229,119,128,5, +168,102,4,158,171,158,180,158,194,158,210,225,242,225,226,233, +99,128,6,66,230,233,238,225,236,225,242,225,226,233,99,128, +254,214,233,238,233,244,233,225,236,225,242,225,226,233,99,128, +254,215,237,229,228,233,225,236,225,242,225,226,233,99,128,254, +216,237,225,244,115,136,5,184,158,248,159,12,159,26,159,31, +159,36,159,45,159,60,159,147,49,3,159,0,159,4,159,8, +48,128,5,184,97,128,5,184,99,128,5,184,50,2,159,18, +159,22,55,128,5,184,57,128,5,184,179,51,128,5,184,228, +101,128,5,184,232,229,226,242,229,119,128,5,184,238,225,242, +242,239,247,232,229,226,242,229,119,128,5,184,113,2,159,66, +159,132,225,244,225,110,4,159,79,159,88,159,103,159,119,232, +229,226,242,229,119,128,5,184,238,225,242,242,239,247,232,229, +226,242,229,119,128,5,184,241,245,225,242,244,229,242,232,229, +226,242,229,119,128,5,184,247,233,228,229,232,229,226,242,229, +119,128,5,184,245,225,242,244,229,242,232,229,226,242,229,119, +128,5,184,247,233,228,229,232,229,226,242,229,119,128,5,184, +242,238,229,249,240,225,242,225,232,229,226,242,229,119,128,5, +159,226,239,240,239,237,239,230,111,128,49,17,227,233,242,227, +236,101,128,36,224,232,239,239,107,128,2,160,237,239,238,239, +243,240,225,227,101,128,255,81,239,102,130,5,231,159,225,159, +245,228,225,231,229,243,104,129,251,71,159,236,232,229,226,242, +229,119,128,251,71,232,229,226,242,229,119,128,5,231,240,225, +242,229,110,128,36,172,117,4,160,16,160,28,160,117,160,204, +225,242,244,229,242,238,239,244,101,128,38,105,226,245,244,115, +135,5,187,160,49,160,54,160,59,160,64,160,73,160,88,160, +104,177,56,128,5,187,178,53,128,5,187,179,49,128,5,187, +232,229,226,242,229,119,128,5,187,238,225,242,242,239,247,232, +229,226,242,229,119,128,5,187,241,245,225,242,244,229,242,232, +229,226,242,229,119,128,5,187,247,233,228,229,232,229,226,242, +229,119,128,5,187,229,243,244,233,239,110,133,0,63,160,136, +160,159,160,176,160,184,160,196,225,114,2,160,143,160,150,225, +226,233,99,128,6,31,237,229,238,233,225,110,128,5,94,228, +239,247,110,129,0,191,160,168,243,237,225,236,108,128,247,191, +231,242,229,229,107,128,3,126,237,239,238,239,243,240,225,227, +101,128,255,31,243,237,225,236,108,128,247,63,239,244,101,4, +160,216,161,31,161,51,161,80,228,226,108,133,0,34,160,232, +160,239,160,246,161,2,161,23,226,225,243,101,128,32,30,236, +229,230,116,128,32,28,237,239,238,239,243,240,225,227,101,128, +255,2,240,242,233,237,101,129,48,30,161,12,242,229,246,229, +242,243,229,100,128,48,29,242,233,231,232,116,128,32,29,236, +229,230,116,129,32,24,161,40,242,229,246,229,242,243,229,100, +128,32,27,114,2,161,57,161,67,229,246,229,242,243,229,100, +128,32,27,233,231,232,116,129,32,25,161,76,110,128,1,73, +243,233,238,231,108,2,161,90,161,97,226,225,243,101,128,32, +26,101,129,0,39,161,103,237,239,238,239,243,240,225,227,101, +128,255,7,114,145,0,114,161,153,162,157,162,168,162,215,163, +10,164,27,164,51,164,146,166,180,166,217,166,229,167,27,167, +35,167,197,167,208,167,243,168,87,97,11,161,177,161,188,161, +198,161,205,162,14,162,30,162,55,162,66,162,91,162,114,162, +151,225,242,237,229,238,233,225,110,128,5,124,226,229,238,231, +225,236,105,128,9,176,227,245,244,101,128,1,85,100,4,161, +215,161,221,161,235,162,5,229,246,97,128,9,48,233,227,225, +108,129,34,26,161,230,229,120,128,248,229,239,246,229,242,243, +243,241,245,225,242,101,129,51,174,161,251,228,243,241,245,225, +242,101,128,51,175,243,241,245,225,242,101,128,51,173,230,101, +129,5,191,162,21,232,229,226,242,229,119,128,5,191,231,117, +2,162,37,162,46,234,225,242,225,244,105,128,10,176,242,237, +245,235,232,105,128,10,48,232,233,242,225,231,225,238,97,128, +48,137,235,225,244,225,235,225,238,97,129,48,233,162,79,232, +225,236,230,247,233,228,244,104,128,255,151,236,239,247,229,242, +228,233,225,231,239,238,225,236,226,229,238,231,225,236,105,128, +9,241,109,2,162,120,162,143,233,228,228,236,229,228,233,225, +231,239,238,225,236,226,229,238,231,225,236,105,128,9,240,243, +232,239,242,110,128,2,100,244,233,111,128,34,54,226,239,240, +239,237,239,230,111,128,49,22,99,4,162,178,162,185,162,194, +162,202,225,242,239,110,128,1,89,229,228,233,236,236,97,128, +1,87,233,242,227,236,101,128,36,225,239,237,237,225,225,227, +227,229,238,116,128,1,87,100,2,162,221,162,231,226,236,231, +242,225,246,101,128,2,17,239,116,2,162,238,162,247,225,227, +227,229,238,116,128,30,89,226,229,236,239,119,129,30,91,163, +1,237,225,227,242,239,110,128,30,93,101,6,163,24,163,69, +163,104,163,159,163,184,163,217,102,2,163,30,163,43,229,242, +229,238,227,229,237,225,242,107,128,32,59,236,229,248,243,117, +2,163,53,163,60,226,243,229,116,128,34,134,240,229,242,243, +229,116,128,34,135,231,233,243,244,229,114,2,163,80,163,85, +229,100,128,0,174,115,2,163,91,163,97,225,238,115,128,248, +232,229,242,233,102,128,246,218,104,3,163,112,163,135,163,149, +225,114,2,163,119,163,126,225,226,233,99,128,6,49,237,229, +238,233,225,110,128,5,128,230,233,238,225,236,225,242,225,226, +233,99,128,254,174,233,242,225,231,225,238,97,128,48,140,235, +225,244,225,235,225,238,97,129,48,236,163,172,232,225,236,230, +247,233,228,244,104,128,255,154,243,104,130,5,232,163,193,163, +208,228,225,231,229,243,232,232,229,226,242,229,119,128,251,72, +232,229,226,242,229,119,128,5,232,118,3,163,225,163,238,164, +14,229,242,243,229,228,244,233,236,228,101,128,34,61,233,97, +2,163,245,163,254,232,229,226,242,229,119,128,5,151,237,245, +231,242,225,243,232,232,229,226,242,229,119,128,5,151,236,239, +231,233,227,225,236,238,239,116,128,35,16,230,233,243,232,232, +239,239,107,129,2,126,164,40,242,229,246,229,242,243,229,100, +128,2,127,104,2,164,57,164,80,97,2,164,63,164,73,226, +229,238,231,225,236,105,128,9,221,228,229,246,97,128,9,93, +111,131,3,193,164,90,164,119,164,133,239,107,129,2,125,164, +97,244,245,242,238,229,100,129,2,123,164,108,243,245,240,229, +242,233,239,114,128,2,181,243,249,237,226,239,236,231,242,229, +229,107,128,3,241,244,233,227,232,239,239,235,237,239,100,128, +2,222,105,6,164,160,165,204,165,250,166,5,166,30,166,166, +229,245,108,9,164,182,164,217,164,232,164,246,165,36,165,50, +165,136,165,149,165,184,97,2,164,188,164,203,227,233,242,227, +236,229,235,239,242,229,225,110,128,50,113,240,225,242,229,238, +235,239,242,229,225,110,128,50,17,227,233,242,227,236,229,235, +239,242,229,225,110,128,50,99,232,233,229,245,232,235,239,242, +229,225,110,128,49,64,107,2,164,252,165,28,233,249,229,239, +107,2,165,6,165,15,235,239,242,229,225,110,128,49,58,243, +233,239,243,235,239,242,229,225,110,128,49,105,239,242,229,225, +110,128,49,57,237,233,229,245,237,235,239,242,229,225,110,128, +49,59,112,3,165,58,165,90,165,105,97,2,165,64,165,78, +238,243,233,239,243,235,239,242,229,225,110,128,49,108,242,229, +238,235,239,242,229,225,110,128,50,3,232,233,229,245,240,232, +235,239,242,229,225,110,128,49,63,233,229,245,112,2,165,114, +165,123,235,239,242,229,225,110,128,49,60,243,233,239,243,235, +239,242,229,225,110,128,49,107,243,233,239,243,235,239,242,229, +225,110,128,49,61,116,2,165,155,165,170,232,233,229,245,244, +232,235,239,242,229,225,110,128,49,62,233,235,229,245,244,235, +239,242,229,225,110,128,49,106,249,229,239,242,233,238,232,233, +229,245,232,235,239,242,229,225,110,128,49,109,231,232,116,2, +165,212,165,220,225,238,231,236,101,128,34,31,116,2,165,226, +165,240,225,227,235,226,229,236,239,247,227,237,98,128,3,25, +242,233,225,238,231,236,101,128,34,191,232,233,242,225,231,225, +238,97,128,48,138,235,225,244,225,235,225,238,97,129,48,234, +166,18,232,225,236,230,247,233,228,244,104,128,255,152,110,2, +166,36,166,152,103,131,2,218,166,46,166,57,166,63,226,229, +236,239,247,227,237,98,128,3,37,227,237,98,128,3,10,232, +225,236,102,2,166,72,166,118,236,229,230,116,131,2,191,166, +85,166,96,166,107,225,242,237,229,238,233,225,110,128,5,89, +226,229,236,239,247,227,237,98,128,3,28,227,229,238,244,229, +242,229,100,128,2,211,242,233,231,232,116,130,2,190,166,130, +166,141,226,229,236,239,247,227,237,98,128,3,57,227,229,238, +244,229,242,229,100,128,2,210,246,229,242,244,229,228,226,242, +229,246,101,128,2,19,244,244,239,242,245,243,241,245,225,242, +101,128,51,81,108,2,166,186,166,197,233,238,229,226,229,236, +239,119,128,30,95,239,238,231,236,229,103,129,2,124,166,208, +244,245,242,238,229,100,128,2,122,237,239,238,239,243,240,225, +227,101,128,255,82,111,3,166,237,166,248,167,17,232,233,242, +225,231,225,238,97,128,48,141,235,225,244,225,235,225,238,97, +129,48,237,167,5,232,225,236,230,247,233,228,244,104,128,255, +155,242,245,225,244,232,225,105,128,14,35,240,225,242,229,110, +128,36,173,114,3,167,43,167,79,167,109,97,3,167,51,167, +61,167,68,226,229,238,231,225,236,105,128,9,220,228,229,246, +97,128,9,49,231,245,242,237,245,235,232,105,128,10,92,229, +104,2,167,86,167,95,225,242,225,226,233,99,128,6,145,230, +233,238,225,236,225,242,225,226,233,99,128,251,141,246,239,227, +225,236,233,99,4,167,125,167,135,167,142,167,153,226,229,238, +231,225,236,105,128,9,224,228,229,246,97,128,9,96,231,245, +234,225,242,225,244,105,128,10,224,246,239,247,229,236,243,233, +231,110,3,167,169,167,179,167,186,226,229,238,231,225,236,105, +128,9,196,228,229,246,97,128,9,68,231,245,234,225,242,225, +244,105,128,10,196,243,245,240,229,242,233,239,114,128,246,241, +116,2,167,214,167,222,226,236,239,227,107,128,37,144,245,242, +238,229,100,129,2,121,167,232,243,245,240,229,242,233,239,114, +128,2,180,117,4,167,253,168,8,168,33,168,80,232,233,242, +225,231,225,238,97,128,48,139,235,225,244,225,235,225,238,97, +129,48,235,168,21,232,225,236,230,247,233,228,244,104,128,255, +153,112,2,168,39,168,74,229,101,2,168,46,168,60,237,225, +242,235,226,229,238,231,225,236,105,128,9,242,243,233,231,238, +226,229,238,231,225,236,105,128,9,243,233,225,104,128,246,221, +244,232,225,105,128,14,36,246,239,227,225,236,233,99,4,168, +103,168,113,168,120,168,131,226,229,238,231,225,236,105,128,9, +139,228,229,246,97,128,9,11,231,245,234,225,242,225,244,105, +128,10,139,246,239,247,229,236,243,233,231,110,3,168,147,168, +157,168,164,226,229,238,231,225,236,105,128,9,195,228,229,246, +97,128,9,67,231,245,234,225,242,225,244,105,128,10,195,115, +147,0,115,168,217,170,187,170,198,171,68,171,107,174,49,174, +60,176,203,179,85,179,131,179,158,180,93,180,160,181,193,181, +203,182,133,182,206,183,120,183,130,97,9,168,237,168,247,169, +12,169,84,169,109,169,120,169,145,169,177,169,217,226,229,238, +231,225,236,105,128,9,184,227,245,244,101,129,1,91,169,0, +228,239,244,225,227,227,229,238,116,128,30,101,100,5,169,24, +169,33,169,39,169,53,169,69,225,242,225,226,233,99,128,6, +53,229,246,97,128,9,56,230,233,238,225,236,225,242,225,226, +233,99,128,254,186,233,238,233,244,233,225,236,225,242,225,226, +233,99,128,254,187,237,229,228,233,225,236,225,242,225,226,233, +99,128,254,188,231,117,2,169,91,169,100,234,225,242,225,244, +105,128,10,184,242,237,245,235,232,105,128,10,56,232,233,242, +225,231,225,238,97,128,48,85,235,225,244,225,235,225,238,97, +129,48,181,169,133,232,225,236,230,247,233,228,244,104,128,255, +123,236,236,225,236,236,225,232,239,245,225,236,225,249,232,229, +247,225,243,225,236,236,225,237,225,242,225,226,233,99,128,253, +250,237,229,235,104,130,5,225,169,188,169,208,228,225,231,229, +243,104,129,251,65,169,199,232,229,226,242,229,119,128,251,65, +232,229,226,242,229,119,128,5,225,242,97,5,169,230,170,48, +170,56,170,106,170,114,97,5,169,242,169,250,170,2,170,33, +170,41,225,244,232,225,105,128,14,50,229,244,232,225,105,128, +14,65,233,237,225,233,109,2,170,12,170,23,225,236,225,233, +244,232,225,105,128,14,68,245,225,238,244,232,225,105,128,14, +67,237,244,232,225,105,128,14,51,244,232,225,105,128,14,48, +229,244,232,225,105,128,14,64,105,3,170,64,170,88,170,99, +105,2,170,70,170,81,236,229,230,244,244,232,225,105,128,248, +134,244,232,225,105,128,14,53,236,229,230,244,244,232,225,105, +128,248,133,244,232,225,105,128,14,52,239,244,232,225,105,128, +14,66,117,3,170,122,170,172,170,179,101,3,170,130,170,154, +170,165,101,2,170,136,170,147,236,229,230,244,244,232,225,105, +128,248,136,244,232,225,105,128,14,55,236,229,230,244,244,232, +225,105,128,248,135,244,232,225,105,128,14,54,244,232,225,105, +128,14,56,245,244,232,225,105,128,14,57,226,239,240,239,237, +239,230,111,128,49,25,99,5,170,210,170,231,170,240,171,33, +171,55,225,242,239,110,129,1,97,170,219,228,239,244,225,227, +227,229,238,116,128,30,103,229,228,233,236,236,97,128,1,95, +232,247,97,131,2,89,170,252,171,7,171,26,227,249,242,233, +236,236,233,99,128,4,217,228,233,229,242,229,243,233,243,227, +249,242,233,236,236,233,99,128,4,219,232,239,239,107,128,2, +90,233,242,99,2,171,41,171,46,236,101,128,36,226,245,237, +230,236,229,120,128,1,93,239,237,237,225,225,227,227,229,238, +116,128,2,25,228,239,116,2,171,76,171,85,225,227,227,229, +238,116,128,30,97,226,229,236,239,119,129,30,99,171,95,228, +239,244,225,227,227,229,238,116,128,30,105,101,9,171,127,171, +143,171,178,171,243,172,90,172,117,172,142,172,223,172,250,225, +231,245,236,236,226,229,236,239,247,227,237,98,128,3,60,99, +2,171,149,171,171,239,238,100,129,32,51,171,157,244,239,238, +229,227,232,233,238,229,243,101,128,2,202,244,233,239,110,128, +0,167,229,110,4,171,189,171,198,171,212,171,228,225,242,225, +226,233,99,128,6,51,230,233,238,225,236,225,242,225,226,233, +99,128,254,178,233,238,233,244,233,225,236,225,242,225,226,233, +99,128,254,179,237,229,228,233,225,236,225,242,225,226,233,99, +128,254,180,231,239,108,135,5,182,172,7,172,21,172,26,172, +35,172,50,172,66,172,77,49,2,172,13,172,17,51,128,5, +182,102,128,5,182,178,99,128,5,182,232,229,226,242,229,119, +128,5,182,238,225,242,242,239,247,232,229,226,242,229,119,128, +5,182,241,245,225,242,244,229,242,232,229,226,242,229,119,128, +5,182,244,225,232,229,226,242,229,119,128,5,146,247,233,228, +229,232,229,226,242,229,119,128,5,182,104,2,172,96,172,107, +225,242,237,229,238,233,225,110,128,5,125,233,242,225,231,225, +238,97,128,48,91,235,225,244,225,235,225,238,97,129,48,187, +172,130,232,225,236,230,247,233,228,244,104,128,255,126,237,105, +2,172,149,172,192,227,239,236,239,110,131,0,59,172,163,172, +172,172,184,225,242,225,226,233,99,128,6,27,237,239,238,239, +243,240,225,227,101,128,255,27,243,237,225,236,108,128,254,84, +246,239,233,227,229,228,237,225,242,235,235,225,238,97,129,48, +156,172,211,232,225,236,230,247,233,228,244,104,128,255,159,238, +116,2,172,230,172,240,233,243,241,245,225,242,101,128,51,34, +239,243,241,245,225,242,101,128,51,35,246,229,110,142,0,55, +173,28,173,37,173,47,173,77,173,84,173,94,173,119,173,146, +173,180,173,192,173,203,173,236,173,244,173,255,225,242,225,226, +233,99,128,6,103,226,229,238,231,225,236,105,128,9,237,227, +233,242,227,236,101,129,36,102,173,58,233,238,246,229,242,243, +229,243,225,238,243,243,229,242,233,102,128,39,144,228,229,246, +97,128,9,109,229,233,231,232,244,232,115,128,33,94,231,117, +2,173,101,173,110,234,225,242,225,244,105,128,10,237,242,237, +245,235,232,105,128,10,109,232,97,2,173,126,173,137,227,235, +225,242,225,226,233,99,128,6,103,238,231,250,232,239,117,128, +48,39,105,2,173,152,173,170,228,229,239,231,242,225,240,232, +233,227,240,225,242,229,110,128,50,38,238,230,229,242,233,239, +114,128,32,135,237,239,238,239,243,240,225,227,101,128,255,23, +239,236,228,243,244,249,236,101,128,247,55,112,2,173,209,173, +216,225,242,229,110,128,36,122,229,114,2,173,223,173,229,233, +239,100,128,36,142,243,233,225,110,128,6,247,242,239,237,225, +110,128,33,118,243,245,240,229,242,233,239,114,128,32,119,116, +2,174,5,174,43,229,229,110,2,174,13,174,22,227,233,242, +227,236,101,128,36,112,112,2,174,28,174,35,225,242,229,110, +128,36,132,229,242,233,239,100,128,36,152,232,225,105,128,14, +87,230,244,232,249,240,232,229,110,128,0,173,104,7,174,76, +175,50,175,61,175,75,176,20,176,33,176,197,97,6,174,90, +174,101,174,111,174,122,175,9,175,34,225,242,237,229,238,233, +225,110,128,5,119,226,229,238,231,225,236,105,128,9,182,227, +249,242,233,236,236,233,99,128,4,72,100,2,174,128,174,224, +228,97,4,174,139,174,148,174,179,174,193,225,242,225,226,233, +99,128,6,81,228,225,237,237,97,2,174,158,174,167,225,242, +225,226,233,99,128,252,97,244,225,238,225,242,225,226,233,99, +128,252,94,230,225,244,232,225,225,242,225,226,233,99,128,252, +96,235,225,243,242,97,2,174,203,174,212,225,242,225,226,233, +99,128,252,98,244,225,238,225,242,225,226,233,99,128,252,95, +101,132,37,146,174,236,174,243,174,251,175,4,228,225,242,107, +128,37,147,236,233,231,232,116,128,37,145,237,229,228,233,245, +109,128,37,146,246,97,128,9,54,231,117,2,175,16,175,25, +234,225,242,225,244,105,128,10,182,242,237,245,235,232,105,128, +10,54,236,243,232,229,236,229,244,232,229,226,242,229,119,128, +5,147,226,239,240,239,237,239,230,111,128,49,21,227,232,225, +227,249,242,233,236,236,233,99,128,4,73,101,4,175,85,175, +150,175,160,175,177,229,110,4,175,96,175,105,175,119,175,135, +225,242,225,226,233,99,128,6,52,230,233,238,225,236,225,242, +225,226,233,99,128,254,182,233,238,233,244,233,225,236,225,242, +225,226,233,99,128,254,183,237,229,228,233,225,236,225,242,225, +226,233,99,128,254,184,233,227,239,240,244,233,99,128,3,227, +241,229,108,129,32,170,175,168,232,229,226,242,229,119,128,32, +170,246,97,134,5,176,175,194,175,209,175,223,175,232,175,247, +176,7,49,2,175,200,175,205,177,53,128,5,176,53,128,5, +176,50,2,175,215,175,219,50,128,5,176,101,128,5,176,232, +229,226,242,229,119,128,5,176,238,225,242,242,239,247,232,229, +226,242,229,119,128,5,176,241,245,225,242,244,229,242,232,229, +226,242,229,119,128,5,176,247,233,228,229,232,229,226,242,229, +119,128,5,176,232,225,227,249,242,233,236,236,233,99,128,4, +187,105,2,176,39,176,50,237,225,227,239,240,244,233,99,128, +3,237,110,131,5,233,176,60,176,143,176,152,100,2,176,66, +176,132,225,231,229,243,104,130,251,73,176,78,176,87,232,229, +226,242,229,119,128,251,73,115,2,176,93,176,113,232,233,238, +228,239,116,129,251,44,176,104,232,229,226,242,229,119,128,251, +44,233,238,228,239,116,129,251,45,176,123,232,229,226,242,229, +119,128,251,45,239,244,232,229,226,242,229,119,128,5,193,232, +229,226,242,229,119,128,5,233,115,2,176,158,176,178,232,233, +238,228,239,116,129,251,42,176,169,232,229,226,242,229,119,128, +251,42,233,238,228,239,116,129,251,43,176,188,232,229,226,242, +229,119,128,251,43,239,239,107,128,2,130,105,8,176,221,177, +9,177,20,177,45,177,75,177,83,177,96,178,11,231,237,97, +131,3,195,176,233,176,237,176,245,49,128,3,194,230,233,238, +225,108,128,3,194,236,245,238,225,244,229,243,249,237,226,239, +236,231,242,229,229,107,128,3,242,232,233,242,225,231,225,238, +97,128,48,87,235,225,244,225,235,225,238,97,129,48,183,177, +33,232,225,236,230,247,233,228,244,104,128,255,124,236,245,113, +2,177,53,177,62,232,229,226,242,229,119,128,5,189,236,229, +230,244,232,229,226,242,229,119,128,5,189,237,233,236,225,114, +128,34,60,238,228,239,244,232,229,226,242,229,119,128,5,194, +239,115,6,177,111,177,146,177,178,177,206,177,220,177,252,97, +2,177,117,177,132,227,233,242,227,236,229,235,239,242,229,225, +110,128,50,116,240,225,242,229,238,235,239,242,229,225,110,128, +50,20,227,105,2,177,153,177,165,229,245,227,235,239,242,229, +225,110,128,49,126,242,227,236,229,235,239,242,229,225,110,128, +50,102,107,2,177,184,177,198,233,249,229,239,235,235,239,242, +229,225,110,128,49,122,239,242,229,225,110,128,49,69,238,233, +229,245,238,235,239,242,229,225,110,128,49,123,112,2,177,226, +177,239,225,242,229,238,235,239,242,229,225,110,128,50,6,233, +229,245,240,235,239,242,229,225,110,128,49,125,244,233,235,229, +245,244,235,239,242,229,225,110,128,49,124,120,141,0,54,178, +41,178,50,178,60,178,90,178,97,178,122,178,149,178,183,178, +195,178,206,178,239,178,247,179,2,225,242,225,226,233,99,128, +6,102,226,229,238,231,225,236,105,128,9,236,227,233,242,227, +236,101,129,36,101,178,71,233,238,246,229,242,243,229,243,225, +238,243,243,229,242,233,102,128,39,143,228,229,246,97,128,9, +108,231,117,2,178,104,178,113,234,225,242,225,244,105,128,10, +236,242,237,245,235,232,105,128,10,108,232,97,2,178,129,178, +140,227,235,225,242,225,226,233,99,128,6,102,238,231,250,232, +239,117,128,48,38,105,2,178,155,178,173,228,229,239,231,242, +225,240,232,233,227,240,225,242,229,110,128,50,37,238,230,229, +242,233,239,114,128,32,134,237,239,238,239,243,240,225,227,101, +128,255,22,239,236,228,243,244,249,236,101,128,247,54,112,2, +178,212,178,219,225,242,229,110,128,36,121,229,114,2,178,226, +178,232,233,239,100,128,36,141,243,233,225,110,128,6,246,242, +239,237,225,110,128,33,117,243,245,240,229,242,233,239,114,128, +32,118,116,2,179,8,179,79,229,229,110,2,179,16,179,58, +99,2,179,22,179,30,233,242,227,236,101,128,36,111,245,242, +242,229,238,227,249,228,229,238,239,237,233,238,225,244,239,242, +226,229,238,231,225,236,105,128,9,249,112,2,179,64,179,71, +225,242,229,110,128,36,131,229,242,233,239,100,128,36,151,232, +225,105,128,14,86,108,2,179,91,179,111,225,243,104,129,0, +47,179,99,237,239,238,239,243,240,225,227,101,128,255,15,239, +238,103,129,1,127,179,119,228,239,244,225,227,227,229,238,116, +128,30,155,109,2,179,137,179,147,233,236,229,230,225,227,101, +128,38,58,239,238,239,243,240,225,227,101,128,255,83,111,6, +179,172,179,222,179,233,180,2,180,47,180,58,102,2,179,178, +179,192,240,225,243,245,241,232,229,226,242,229,119,128,5,195, +116,2,179,198,179,207,232,249,240,232,229,110,128,0,173,243, +233,231,238,227,249,242,233,236,236,233,99,128,4,76,232,233, +242,225,231,225,238,97,128,48,93,235,225,244,225,235,225,238, +97,129,48,189,179,246,232,225,236,230,247,233,228,244,104,128, +255,127,236,233,228,245,115,2,180,12,180,29,236,239,238,231, +239,246,229,242,236,225,249,227,237,98,128,3,56,243,232,239, +242,244,239,246,229,242,236,225,249,227,237,98,128,3,55,242, +245,243,233,244,232,225,105,128,14,41,115,3,180,66,180,76, +180,84,225,236,225,244,232,225,105,128,14,40,239,244,232,225, +105,128,14,11,245,225,244,232,225,105,128,14,42,240,97,3, +180,102,180,122,180,154,227,101,129,0,32,180,109,232,225,227, +235,225,242,225,226,233,99,128,0,32,228,101,129,38,96,180, +129,243,245,233,116,2,180,138,180,146,226,236,225,227,107,128, +38,96,247,232,233,244,101,128,38,100,242,229,110,128,36,174, +241,245,225,242,101,11,180,188,180,199,180,213,180,238,180,255, +181,25,181,40,181,73,181,100,181,156,181,171,226,229,236,239, +247,227,237,98,128,3,59,99,2,180,205,180,209,99,128,51, +196,109,128,51,157,228,233,225,231,239,238,225,236,227,242,239, +243,243,232,225,244,227,232,230,233,236,108,128,37,169,232,239, +242,233,250,239,238,244,225,236,230,233,236,108,128,37,164,107, +2,181,5,181,9,103,128,51,143,109,129,51,158,181,15,227, +225,240,233,244,225,108,128,51,206,108,2,181,31,181,35,110, +128,51,209,239,103,128,51,210,109,4,181,50,181,54,181,59, +181,63,103,128,51,142,233,108,128,51,213,109,128,51,156,243, +241,245,225,242,229,100,128,51,161,239,242,244,232,239,231,239, +238,225,236,227,242,239,243,243,232,225,244,227,232,230,233,236, +108,128,37,166,245,240,240,229,114,2,181,110,181,133,236,229, +230,244,244,239,236,239,247,229,242,242,233,231,232,244,230,233, +236,108,128,37,167,242,233,231,232,244,244,239,236,239,247,229, +242,236,229,230,244,230,233,236,108,128,37,168,246,229,242,244, +233,227,225,236,230,233,236,108,128,37,165,247,232,233,244,229, +247,233,244,232,243,237,225,236,236,226,236,225,227,107,128,37, +163,242,243,241,245,225,242,101,128,51,219,115,2,181,209,182, +123,97,4,181,219,181,229,181,236,181,247,226,229,238,231,225, +236,105,128,9,183,228,229,246,97,128,9,55,231,245,234,225, +242,225,244,105,128,10,183,238,103,8,182,10,182,24,182,38, +182,52,182,67,182,81,182,95,182,108,227,233,229,245,227,235, +239,242,229,225,110,128,49,73,232,233,229,245,232,235,239,242, +229,225,110,128,49,133,233,229,245,238,231,235,239,242,229,225, +110,128,49,128,235,233,249,229,239,235,235,239,242,229,225,110, +128,49,50,238,233,229,245,238,235,239,242,229,225,110,128,49, +101,240,233,229,245,240,235,239,242,229,225,110,128,49,67,243, +233,239,243,235,239,242,229,225,110,128,49,70,244,233,235,229, +245,244,235,239,242,229,225,110,128,49,56,245,240,229,242,233, +239,114,128,246,242,116,2,182,139,182,162,229,242,236,233,238, +103,129,0,163,182,150,237,239,238,239,243,240,225,227,101,128, +255,225,242,239,235,101,2,182,171,182,188,236,239,238,231,239, +246,229,242,236,225,249,227,237,98,128,3,54,243,232,239,242, +244,239,246,229,242,236,225,249,227,237,98,128,3,53,117,7, +182,222,182,254,183,20,183,31,183,72,183,82,183,86,226,243, +229,116,130,34,130,182,233,182,244,238,239,244,229,241,245,225, +108,128,34,138,239,242,229,241,245,225,108,128,34,134,99,2, +183,4,183,12,227,229,229,228,115,128,34,123,232,244,232,225, +116,128,34,11,232,233,242,225,231,225,238,97,128,48,89,107, +2,183,37,183,61,225,244,225,235,225,238,97,129,48,185,183, +49,232,225,236,230,247,233,228,244,104,128,255,125,245,238,225, +242,225,226,233,99,128,6,82,237,237,225,244,233,239,110,128, +34,17,110,128,38,60,240,229,242,243,229,116,130,34,131,183, +99,183,110,238,239,244,229,241,245,225,108,128,34,139,239,242, +229,241,245,225,108,128,34,135,246,243,241,245,225,242,101,128, +51,220,249,239,245,247,225,229,242,225,243,241,245,225,242,101, +128,51,124,116,144,0,116,183,183,184,192,184,213,185,100,185, +140,187,188,191,70,192,145,192,157,192,169,193,202,193,227,194, +57,194,237,195,165,195,255,97,10,183,205,183,215,183,236,183, +243,184,12,184,90,184,107,184,132,184,146,184,150,226,229,238, +231,225,236,105,128,9,164,227,107,2,183,222,183,229,228,239, +247,110,128,34,164,236,229,230,116,128,34,163,228,229,246,97, +128,9,36,231,117,2,183,250,184,3,234,225,242,225,244,105, +128,10,164,242,237,245,235,232,105,128,10,36,104,4,184,22, +184,31,184,45,184,75,225,242,225,226,233,99,128,6,55,230, +233,238,225,236,225,242,225,226,233,99,128,254,194,105,2,184, +51,184,66,238,233,244,233,225,236,225,242,225,226,233,99,128, +254,195,242,225,231,225,238,97,128,48,95,237,229,228,233,225, +236,225,242,225,226,233,99,128,254,196,233,243,249,239,245,229, +242,225,243,241,245,225,242,101,128,51,125,235,225,244,225,235, +225,238,97,129,48,191,184,120,232,225,236,230,247,233,228,244, +104,128,255,128,244,247,229,229,236,225,242,225,226,233,99,128, +6,64,117,128,3,196,118,130,5,234,184,158,184,183,228,225, +231,229,115,129,251,74,184,168,104,129,251,74,184,174,232,229, +226,242,229,119,128,251,74,232,229,226,242,229,119,128,5,234, +98,2,184,198,184,203,225,114,128,1,103,239,240,239,237,239, +230,111,128,49,10,99,6,184,227,184,234,184,241,184,250,185, +60,185,87,225,242,239,110,128,1,101,227,245,242,108,128,2, +168,229,228,233,236,236,97,128,1,99,232,229,104,4,185,6, +185,15,185,29,185,45,225,242,225,226,233,99,128,6,134,230, +233,238,225,236,225,242,225,226,233,99,128,251,123,233,238,233, +244,233,225,236,225,242,225,226,233,99,128,251,124,237,229,228, +233,225,236,225,242,225,226,233,99,128,251,125,233,242,99,2, +185,68,185,73,236,101,128,36,227,245,237,230,236,229,248,226, +229,236,239,119,128,30,113,239,237,237,225,225,227,227,229,238, +116,128,1,99,100,2,185,106,185,116,233,229,242,229,243,233, +115,128,30,151,239,116,2,185,123,185,132,225,227,227,229,238, +116,128,30,107,226,229,236,239,119,128,30,109,101,9,185,160, +185,171,185,191,186,201,186,226,187,34,187,101,187,106,187,158, +227,249,242,233,236,236,233,99,128,4,66,228,229,243,227,229, +238,228,229,242,227,249,242,233,236,236,233,99,128,4,173,104, +7,185,207,185,216,185,230,186,14,186,44,186,85,186,183,225, +242,225,226,233,99,128,6,42,230,233,238,225,236,225,242,225, +226,233,99,128,254,150,232,225,232,105,2,185,239,185,254,238, +233,244,233,225,236,225,242,225,226,233,99,128,252,162,243,239, +236,225,244,229,228,225,242,225,226,233,99,128,252,12,105,2, +186,20,186,35,238,233,244,233,225,236,225,242,225,226,233,99, +128,254,151,242,225,231,225,238,97,128,48,102,234,229,229,237, +105,2,186,54,186,69,238,233,244,233,225,236,225,242,225,226, +233,99,128,252,161,243,239,236,225,244,229,228,225,242,225,226, +233,99,128,252,11,109,2,186,91,186,125,225,242,226,245,244, +97,2,186,102,186,111,225,242,225,226,233,99,128,6,41,230, +233,238,225,236,225,242,225,226,233,99,128,254,148,101,2,186, +131,186,144,228,233,225,236,225,242,225,226,233,99,128,254,152, +229,237,105,2,186,152,186,167,238,233,244,233,225,236,225,242, +225,226,233,99,128,252,164,243,239,236,225,244,229,228,225,242, +225,226,233,99,128,252,14,238,239,239,238,230,233,238,225,236, +225,242,225,226,233,99,128,252,115,235,225,244,225,235,225,238, +97,129,48,198,186,214,232,225,236,230,247,233,228,244,104,128, +255,131,108,2,186,232,186,251,229,240,232,239,238,101,129,33, +33,186,243,226,236,225,227,107,128,38,14,233,243,232,97,2, +187,4,187,19,231,229,228,239,236,225,232,229,226,242,229,119, +128,5,160,241,229,244,225,238,225,232,229,226,242,229,119,128, +5,169,110,4,187,44,187,53,187,72,187,93,227,233,242,227, +236,101,128,36,105,233,228,229,239,231,242,225,240,232,233,227, +240,225,242,229,110,128,50,41,112,2,187,78,187,85,225,242, +229,110,128,36,125,229,242,233,239,100,128,36,145,242,239,237, +225,110,128,33,121,243,104,128,2,167,116,131,5,216,187,116, +187,136,187,145,228,225,231,229,243,104,129,251,56,187,127,232, +229,226,242,229,119,128,251,56,232,229,226,242,229,119,128,5, +216,243,229,227,249,242,233,236,236,233,99,128,4,181,246,233, +114,2,187,166,187,175,232,229,226,242,229,119,128,5,155,236, +229,230,244,232,229,226,242,229,119,128,5,155,104,6,187,202, +188,98,188,220,189,96,190,3,191,60,97,5,187,214,187,224, +187,231,188,0,188,29,226,229,238,231,225,236,105,128,9,165, +228,229,246,97,128,9,37,231,117,2,187,238,187,247,234,225, +242,225,244,105,128,10,165,242,237,245,235,232,105,128,10,37, +108,2,188,6,188,15,225,242,225,226,233,99,128,6,48,230, +233,238,225,236,225,242,225,226,233,99,128,254,172,238,244,232, +225,235,232,225,116,3,188,44,188,75,188,82,236,239,119,2, +188,52,188,63,236,229,230,244,244,232,225,105,128,248,152,242, +233,231,232,244,244,232,225,105,128,248,151,244,232,225,105,128, +14,76,245,240,240,229,242,236,229,230,244,244,232,225,105,128, +248,150,101,3,188,106,188,170,188,193,104,4,188,116,188,125, +188,139,188,155,225,242,225,226,233,99,128,6,43,230,233,238, +225,236,225,242,225,226,233,99,128,254,154,233,238,233,244,233, +225,236,225,242,225,226,233,99,128,254,155,237,229,228,233,225, +236,225,242,225,226,233,99,128,254,156,242,101,2,188,177,188, +186,229,248,233,243,244,115,128,34,3,230,239,242,101,128,34, +52,244,97,130,3,184,188,202,188,206,49,128,3,209,243,249, +237,226,239,236,231,242,229,229,107,128,3,209,105,2,188,226, +189,56,229,245,244,104,4,188,239,189,18,189,33,189,42,97, +2,188,245,189,4,227,233,242,227,236,229,235,239,242,229,225, +110,128,50,121,240,225,242,229,238,235,239,242,229,225,110,128, +50,25,227,233,242,227,236,229,235,239,242,229,225,110,128,50, +107,235,239,242,229,225,110,128,49,76,240,225,242,229,238,235, +239,242,229,225,110,128,50,11,242,244,229,229,110,2,189,66, +189,75,227,233,242,227,236,101,128,36,108,112,2,189,81,189, +88,225,242,229,110,128,36,128,229,242,233,239,100,128,36,148, +111,6,189,110,189,127,189,132,189,146,189,151,189,204,238,225, +238,231,237,239,238,244,232,239,244,232,225,105,128,14,17,239, +107,128,1,173,240,232,245,244,232,225,239,244,232,225,105,128, +14,18,242,110,128,0,254,244,104,3,189,160,189,184,189,194, +97,2,189,166,189,176,232,225,238,244,232,225,105,128,14,23, +238,244,232,225,105,128,14,16,239,238,231,244,232,225,105,128, +14,24,245,238,231,244,232,225,105,128,14,22,245,243,225,238, +100,2,189,214,189,225,227,249,242,233,236,236,233,99,128,4, +130,243,243,229,240,225,242,225,244,239,114,2,189,240,189,249, +225,242,225,226,233,99,128,6,108,240,229,242,243,233,225,110, +128,6,108,242,229,101,144,0,51,190,41,190,50,190,60,190, +90,190,97,190,107,190,132,190,159,190,193,190,205,190,224,190, +235,191,12,191,34,191,42,191,53,225,242,225,226,233,99,128, +6,99,226,229,238,231,225,236,105,128,9,233,227,233,242,227, +236,101,129,36,98,190,71,233,238,246,229,242,243,229,243,225, +238,243,243,229,242,233,102,128,39,140,228,229,246,97,128,9, +105,229,233,231,232,244,232,115,128,33,92,231,117,2,190,114, +190,123,234,225,242,225,244,105,128,10,233,242,237,245,235,232, +105,128,10,105,232,97,2,190,139,190,150,227,235,225,242,225, +226,233,99,128,6,99,238,231,250,232,239,117,128,48,35,105, +2,190,165,190,183,228,229,239,231,242,225,240,232,233,227,240, +225,242,229,110,128,50,34,238,230,229,242,233,239,114,128,32, +131,237,239,238,239,243,240,225,227,101,128,255,19,238,245,237, +229,242,225,244,239,242,226,229,238,231,225,236,105,128,9,246, +239,236,228,243,244,249,236,101,128,247,51,112,2,190,241,190, +248,225,242,229,110,128,36,118,229,114,2,190,255,191,5,233, +239,100,128,36,138,243,233,225,110,128,6,243,241,245,225,242, +244,229,242,115,129,0,190,191,25,229,237,228,225,243,104,128, +246,222,242,239,237,225,110,128,33,114,243,245,240,229,242,233, +239,114,128,0,179,244,232,225,105,128,14,83,250,243,241,245, +225,242,101,128,51,148,105,7,191,86,191,97,191,212,192,54, +192,66,192,115,192,132,232,233,242,225,231,225,238,97,128,48, +97,107,2,191,103,191,127,225,244,225,235,225,238,97,129,48, +193,191,115,232,225,236,230,247,233,228,244,104,128,255,129,229, +245,116,4,191,139,191,174,191,189,191,198,97,2,191,145,191, +160,227,233,242,227,236,229,235,239,242,229,225,110,128,50,112, +240,225,242,229,238,235,239,242,229,225,110,128,50,16,227,233, +242,227,236,229,235,239,242,229,225,110,128,50,98,235,239,242, +229,225,110,128,49,55,240,225,242,229,238,235,239,242,229,225, +110,128,50,2,236,228,101,133,2,220,191,228,191,239,192,0, +192,12,192,40,226,229,236,239,247,227,237,98,128,3,48,99, +2,191,245,191,250,237,98,128,3,3,239,237,98,128,3,3, +228,239,245,226,236,229,227,237,98,128,3,96,111,2,192,18, +192,28,240,229,242,225,244,239,114,128,34,60,246,229,242,236, +225,249,227,237,98,128,3,52,246,229,242,244,233,227,225,236, +227,237,98,128,3,62,237,229,243,227,233,242,227,236,101,128, +34,151,112,2,192,72,192,102,229,232,97,2,192,80,192,89, +232,229,226,242,229,119,128,5,150,236,229,230,244,232,229,226, +242,229,119,128,5,150,240,233,231,245,242,237,245,235,232,105, +128,10,112,244,236,239,227,249,242,233,236,236,233,227,227,237, +98,128,4,131,247,238,225,242,237,229,238,233,225,110,128,5, +127,236,233,238,229,226,229,236,239,119,128,30,111,237,239,238, +239,243,240,225,227,101,128,255,84,111,7,192,185,192,196,192, +207,192,232,193,96,193,108,193,192,225,242,237,229,238,233,225, +110,128,5,105,232,233,242,225,231,225,238,97,128,48,104,235, +225,244,225,235,225,238,97,129,48,200,192,220,232,225,236,230, +247,233,228,244,104,128,255,132,110,3,192,240,193,82,193,87, +101,4,192,250,193,63,193,70,193,76,226,225,114,4,193,6, +193,35,193,45,193,54,229,248,244,242,97,2,193,16,193,26, +232,233,231,232,237,239,100,128,2,229,236,239,247,237,239,100, +128,2,233,232,233,231,232,237,239,100,128,2,230,236,239,247, +237,239,100,128,2,232,237,233,228,237,239,100,128,2,231,230, +233,246,101,128,1,189,243,233,120,128,1,133,244,247,111,128, +1,168,239,115,128,3,132,243,241,245,225,242,101,128,51,39, +240,225,244,225,235,244,232,225,105,128,14,15,242,244,239,233, +243,229,243,232,229,236,236,226,242,225,227,235,229,116,2,193, +131,193,161,236,229,230,116,130,48,20,193,142,193,150,243,237, +225,236,108,128,254,93,246,229,242,244,233,227,225,108,128,254, +57,242,233,231,232,116,130,48,21,193,173,193,181,243,237,225, +236,108,128,254,94,246,229,242,244,233,227,225,108,128,254,58, +244,225,239,244,232,225,105,128,14,21,240,97,2,193,209,193, +221,236,225,244,225,236,232,239,239,107,128,1,171,242,229,110, +128,36,175,114,3,193,235,194,10,194,25,225,228,229,237,225, +242,107,129,33,34,193,247,115,2,193,253,194,3,225,238,115, +128,248,234,229,242,233,102,128,246,219,229,244,242,239,230,236, +229,248,232,239,239,107,128,2,136,233,225,103,4,194,37,194, +42,194,47,194,52,228,110,128,37,188,236,102,128,37,196,242, +116,128,37,186,245,112,128,37,178,115,132,2,166,194,69,194, +108,194,214,194,227,225,228,105,130,5,230,194,79,194,99,228, +225,231,229,243,104,129,251,70,194,90,232,229,226,242,229,119, +128,251,70,232,229,226,242,229,119,128,5,230,101,2,194,114, +194,125,227,249,242,233,236,236,233,99,128,4,70,242,101,134, +5,181,194,142,194,156,194,161,194,170,194,185,194,201,49,2, +194,148,194,152,50,128,5,181,101,128,5,181,178,98,128,5, +181,232,229,226,242,229,119,128,5,181,238,225,242,242,239,247, +232,229,226,242,229,119,128,5,181,241,245,225,242,244,229,242, +232,229,226,242,229,119,128,5,181,247,233,228,229,232,229,226, +242,229,119,128,5,181,232,229,227,249,242,233,236,236,233,99, +128,4,91,245,240,229,242,233,239,114,128,246,243,116,4,194, +247,195,41,195,106,195,157,97,3,194,255,195,9,195,16,226, +229,238,231,225,236,105,128,9,159,228,229,246,97,128,9,31, +231,117,2,195,23,195,32,234,225,242,225,244,105,128,10,159, +242,237,245,235,232,105,128,10,31,229,104,4,195,52,195,61, +195,75,195,91,225,242,225,226,233,99,128,6,121,230,233,238, +225,236,225,242,225,226,233,99,128,251,103,233,238,233,244,233, +225,236,225,242,225,226,233,99,128,251,104,237,229,228,233,225, +236,225,242,225,226,233,99,128,251,105,232,97,3,195,115,195, +125,195,132,226,229,238,231,225,236,105,128,9,160,228,229,246, +97,128,9,32,231,117,2,195,139,195,148,234,225,242,225,244, +105,128,10,160,242,237,245,235,232,105,128,10,32,245,242,238, +229,100,128,2,135,117,3,195,173,195,184,195,209,232,233,242, +225,231,225,238,97,128,48,100,235,225,244,225,235,225,238,97, +129,48,196,195,197,232,225,236,230,247,233,228,244,104,128,255, +130,243,237,225,236,108,2,195,219,195,230,232,233,242,225,231, +225,238,97,128,48,99,235,225,244,225,235,225,238,97,129,48, +195,195,243,232,225,236,230,247,233,228,244,104,128,255,111,119, +2,196,5,196,110,101,2,196,11,196,59,236,246,101,3,196, +21,196,30,196,51,227,233,242,227,236,101,128,36,107,112,2, +196,36,196,43,225,242,229,110,128,36,127,229,242,233,239,100, +128,36,147,242,239,237,225,110,128,33,123,238,244,121,3,196, +69,196,78,196,89,227,233,242,227,236,101,128,36,115,232,225, +238,231,250,232,239,117,128,83,68,112,2,196,95,196,102,225, +242,229,110,128,36,135,229,242,233,239,100,128,36,155,111,142, +0,50,196,142,196,151,196,161,196,191,196,243,197,12,197,39, +197,73,197,85,197,104,197,115,197,148,197,156,197,180,225,242, +225,226,233,99,128,6,98,226,229,238,231,225,236,105,128,9, +232,227,233,242,227,236,101,129,36,97,196,172,233,238,246,229, +242,243,229,243,225,238,243,243,229,242,233,102,128,39,139,100, +2,196,197,196,203,229,246,97,128,9,104,239,116,2,196,210, +196,221,229,238,236,229,225,228,229,114,128,32,37,236,229,225, +228,229,114,129,32,37,196,232,246,229,242,244,233,227,225,108, +128,254,48,231,117,2,196,250,197,3,234,225,242,225,244,105, +128,10,232,242,237,245,235,232,105,128,10,104,232,97,2,197, +19,197,30,227,235,225,242,225,226,233,99,128,6,98,238,231, +250,232,239,117,128,48,34,105,2,197,45,197,63,228,229,239, +231,242,225,240,232,233,227,240,225,242,229,110,128,50,33,238, +230,229,242,233,239,114,128,32,130,237,239,238,239,243,240,225, +227,101,128,255,18,238,245,237,229,242,225,244,239,242,226,229, +238,231,225,236,105,128,9,245,239,236,228,243,244,249,236,101, +128,247,50,112,2,197,121,197,128,225,242,229,110,128,36,117, +229,114,2,197,135,197,141,233,239,100,128,36,137,243,233,225, +110,128,6,242,242,239,237,225,110,128,33,113,115,2,197,162, +197,170,244,242,239,235,101,128,1,187,245,240,229,242,233,239, +114,128,0,178,244,104,2,197,187,197,192,225,105,128,14,82, +233,242,228,115,128,33,84,117,145,0,117,197,237,197,245,198, +30,198,87,198,225,199,6,199,129,199,145,199,196,200,10,200, +91,200,100,200,219,200,243,201,95,201,123,201,237,225,227,245, +244,101,128,0,250,98,4,197,255,198,4,198,13,198,23,225, +114,128,2,137,229,238,231,225,236,105,128,9,137,239,240,239, +237,239,230,111,128,49,40,242,229,246,101,128,1,109,99,3, +198,38,198,45,198,77,225,242,239,110,128,1,212,233,242,99, +2,198,53,198,58,236,101,128,36,228,245,237,230,236,229,120, +129,0,251,198,69,226,229,236,239,119,128,30,119,249,242,233, +236,236,233,99,128,4,67,100,5,198,99,198,110,198,133,198, +139,198,215,225,244,244,225,228,229,246,97,128,9,81,226,108, +2,198,117,198,125,225,227,245,244,101,128,1,113,231,242,225, +246,101,128,2,21,229,246,97,128,9,9,233,229,242,229,243, +233,115,133,0,252,198,159,198,167,198,175,198,198,198,206,225, +227,245,244,101,128,1,216,226,229,236,239,119,128,30,115,99, +2,198,181,198,188,225,242,239,110,128,1,218,249,242,233,236, +236,233,99,128,4,241,231,242,225,246,101,128,1,220,237,225, +227,242,239,110,128,1,214,239,244,226,229,236,239,119,128,30, +229,103,2,198,231,198,238,242,225,246,101,128,0,249,117,2, +198,244,198,253,234,225,242,225,244,105,128,10,137,242,237,245, +235,232,105,128,10,9,104,3,199,14,199,24,199,102,233,242, +225,231,225,238,97,128,48,70,111,2,199,30,199,40,239,235, +225,226,239,246,101,128,30,231,242,110,133,1,176,199,55,199, +63,199,74,199,82,199,94,225,227,245,244,101,128,30,233,228, +239,244,226,229,236,239,119,128,30,241,231,242,225,246,101,128, +30,235,232,239,239,235,225,226,239,246,101,128,30,237,244,233, +236,228,101,128,30,239,245,238,231,225,242,245,237,236,225,245, +116,129,1,113,199,118,227,249,242,233,236,236,233,99,128,4, +243,233,238,246,229,242,244,229,228,226,242,229,246,101,128,2, +23,107,3,199,153,199,177,199,188,225,244,225,235,225,238,97, +129,48,166,199,165,232,225,236,230,247,233,228,244,104,128,255, +115,227,249,242,233,236,236,233,99,128,4,121,239,242,229,225, +110,128,49,92,109,2,199,202,199,255,97,2,199,208,199,241, +227,242,239,110,130,1,107,199,219,199,230,227,249,242,233,236, +236,233,99,128,4,239,228,233,229,242,229,243,233,115,128,30, +123,244,242,225,231,245,242,237,245,235,232,105,128,10,65,239, +238,239,243,240,225,227,101,128,255,85,110,2,200,16,200,71, +228,229,242,243,227,239,242,101,132,0,95,200,35,200,41,200, +53,200,64,228,226,108,128,32,23,237,239,238,239,243,240,225, +227,101,128,255,63,246,229,242,244,233,227,225,108,128,254,51, +247,225,246,121,128,254,79,105,2,200,77,200,82,239,110,128, +34,42,246,229,242,243,225,108,128,34,0,239,231,239,238,229, +107,128,1,115,112,5,200,112,200,119,200,127,200,142,200,193, +225,242,229,110,128,36,176,226,236,239,227,107,128,37,128,240, +229,242,228,239,244,232,229,226,242,229,119,128,5,196,243,233, +236,239,110,131,3,197,200,156,200,177,200,185,228,233,229,242, +229,243,233,115,129,3,203,200,169,244,239,238,239,115,128,3, +176,236,225,244,233,110,128,2,138,244,239,238,239,115,128,3, +205,244,225,227,107,2,200,202,200,213,226,229,236,239,247,227, +237,98,128,3,29,237,239,100,128,2,212,114,2,200,225,200, +237,225,231,245,242,237,245,235,232,105,128,10,115,233,238,103, +128,1,111,115,3,200,251,201,10,201,55,232,239,242,244,227, +249,242,233,236,236,233,99,128,4,94,237,225,236,108,2,201, +19,201,30,232,233,242,225,231,225,238,97,128,48,69,235,225, +244,225,235,225,238,97,129,48,165,201,43,232,225,236,230,247, +233,228,244,104,128,255,105,244,242,225,233,231,232,116,2,201, +67,201,78,227,249,242,233,236,236,233,99,128,4,175,243,244, +242,239,235,229,227,249,242,233,236,236,233,99,128,4,177,244, +233,236,228,101,130,1,105,201,107,201,115,225,227,245,244,101, +128,30,121,226,229,236,239,119,128,30,117,117,5,201,135,201, +145,201,152,201,177,201,193,226,229,238,231,225,236,105,128,9, +138,228,229,246,97,128,9,10,231,117,2,201,159,201,168,234, +225,242,225,244,105,128,10,138,242,237,245,235,232,105,128,10, +10,237,225,244,242,225,231,245,242,237,245,235,232,105,128,10, +66,246,239,247,229,236,243,233,231,110,3,201,209,201,219,201, +226,226,229,238,231,225,236,105,128,9,194,228,229,246,97,128, +9,66,231,245,234,225,242,225,244,105,128,10,194,246,239,247, +229,236,243,233,231,110,3,201,253,202,7,202,14,226,229,238, +231,225,236,105,128,9,193,228,229,246,97,128,9,65,231,245, +234,225,242,225,244,105,128,10,193,118,139,0,118,202,51,202, +199,202,208,202,219,203,148,203,155,203,253,204,9,204,109,204, +117,204,138,97,4,202,61,202,68,202,93,202,104,228,229,246, +97,128,9,53,231,117,2,202,75,202,84,234,225,242,225,244, +105,128,10,181,242,237,245,235,232,105,128,10,53,235,225,244, +225,235,225,238,97,128,48,247,118,132,5,213,202,116,202,143, +202,175,202,187,228,225,231,229,243,104,130,251,53,202,129,202, +134,182,53,128,251,53,232,229,226,242,229,119,128,251,53,104, +2,202,149,202,157,229,226,242,229,119,128,5,213,239,236,225, +109,129,251,75,202,166,232,229,226,242,229,119,128,251,75,246, +225,246,232,229,226,242,229,119,128,5,240,249,239,228,232,229, +226,242,229,119,128,5,241,227,233,242,227,236,101,128,36,229, +228,239,244,226,229,236,239,119,128,30,127,101,6,202,233,202, +244,203,52,203,63,203,69,203,136,227,249,242,233,236,236,233, +99,128,4,50,104,4,202,254,203,7,203,21,203,37,225,242, +225,226,233,99,128,6,164,230,233,238,225,236,225,242,225,226, +233,99,128,251,107,233,238,233,244,233,225,236,225,242,225,226, +233,99,128,251,108,237,229,228,233,225,236,225,242,225,226,233, +99,128,251,109,235,225,244,225,235,225,238,97,128,48,249,238, +245,115,128,38,64,242,244,233,227,225,108,2,203,80,203,86, +226,225,114,128,0,124,236,233,238,101,4,203,99,203,110,203, +121,203,130,225,226,239,246,229,227,237,98,128,3,13,226,229, +236,239,247,227,237,98,128,3,41,236,239,247,237,239,100,128, +2,204,237,239,100,128,2,200,247,225,242,237,229,238,233,225, +110,128,5,126,232,239,239,107,128,2,139,105,3,203,163,203, +174,203,213,235,225,244,225,235,225,238,97,128,48,248,242,225, +237,97,3,203,185,203,195,203,202,226,229,238,231,225,236,105, +128,9,205,228,229,246,97,128,9,77,231,245,234,225,242,225, +244,105,128,10,205,243,225,242,231,97,3,203,225,203,235,203, +242,226,229,238,231,225,236,105,128,9,131,228,229,246,97,128, +9,3,231,245,234,225,242,225,244,105,128,10,131,237,239,238, +239,243,240,225,227,101,128,255,86,111,3,204,17,204,28,204, +98,225,242,237,229,238,233,225,110,128,5,120,233,227,229,100, +2,204,37,204,73,233,244,229,242,225,244,233,239,110,2,204, +51,204,62,232,233,242,225,231,225,238,97,128,48,158,235,225, +244,225,235,225,238,97,128,48,254,237,225,242,235,235,225,238, +97,129,48,155,204,86,232,225,236,230,247,233,228,244,104,128, +255,158,235,225,244,225,235,225,238,97,128,48,250,240,225,242, +229,110,128,36,177,116,2,204,123,204,130,233,236,228,101,128, +30,125,245,242,238,229,100,128,2,140,117,2,204,144,204,155, +232,233,242,225,231,225,238,97,128,48,148,235,225,244,225,235, +225,238,97,128,48,244,119,143,0,119,204,200,205,177,205,187, +205,210,205,250,206,61,206,69,208,40,208,81,208,93,208,168, +208,176,208,183,208,194,208,203,97,8,204,218,204,225,204,235, +204,246,205,28,205,60,205,72,205,108,227,245,244,101,128,30, +131,229,235,239,242,229,225,110,128,49,89,232,233,242,225,231, +225,238,97,128,48,143,107,2,204,252,205,20,225,244,225,235, +225,238,97,129,48,239,205,8,232,225,236,230,247,233,228,244, +104,128,255,156,239,242,229,225,110,128,49,88,243,237,225,236, +108,2,205,38,205,49,232,233,242,225,231,225,238,97,128,48, +142,235,225,244,225,235,225,238,97,128,48,238,244,244,239,243, +241,245,225,242,101,128,51,87,118,2,205,78,205,86,229,228, +225,243,104,128,48,28,249,245,238,228,229,242,243,227,239,242, +229,246,229,242,244,233,227,225,108,128,254,52,119,3,205,116, +205,125,205,139,225,242,225,226,233,99,128,6,72,230,233,238, +225,236,225,242,225,226,233,99,128,254,238,232,225,237,250,225, +225,226,239,246,101,2,205,154,205,163,225,242,225,226,233,99, +128,6,36,230,233,238,225,236,225,242,225,226,233,99,128,254, +134,226,243,241,245,225,242,101,128,51,221,227,233,242,99,2, +205,196,205,201,236,101,128,36,230,245,237,230,236,229,120,128, +1,117,100,2,205,216,205,226,233,229,242,229,243,233,115,128, +30,133,239,116,2,205,233,205,242,225,227,227,229,238,116,128, +30,135,226,229,236,239,119,128,30,137,101,4,206,4,206,15, +206,27,206,51,232,233,242,225,231,225,238,97,128,48,145,233, +229,242,243,244,242,225,243,115,128,33,24,107,2,206,33,206, +43,225,244,225,235,225,238,97,128,48,241,239,242,229,225,110, +128,49,94,239,235,239,242,229,225,110,128,49,93,231,242,225, +246,101,128,30,129,232,233,244,101,8,206,90,206,99,206,183, +207,17,207,101,207,146,207,198,207,254,226,245,236,236,229,116, +128,37,230,99,2,206,105,206,125,233,242,227,236,101,129,37, +203,206,115,233,238,246,229,242,243,101,128,37,217,239,242,238, +229,242,226,242,225,227,235,229,116,2,206,142,206,162,236,229, +230,116,129,48,14,206,151,246,229,242,244,233,227,225,108,128, +254,67,242,233,231,232,116,129,48,15,206,172,246,229,242,244, +233,227,225,108,128,254,68,100,2,206,189,206,230,233,225,237, +239,238,100,129,37,199,206,200,227,239,238,244,225,233,238,233, +238,231,226,236,225,227,235,243,237,225,236,236,228,233,225,237, +239,238,100,128,37,200,239,247,238,240,239,233,238,244,233,238, +103,2,206,246,207,6,243,237,225,236,236,244,242,233,225,238, +231,236,101,128,37,191,244,242,233,225,238,231,236,101,128,37, +189,236,101,2,207,24,207,66,230,244,240,239,233,238,244,233, +238,103,2,207,39,207,55,243,237,225,236,236,244,242,233,225, +238,231,236,101,128,37,195,244,242,233,225,238,231,236,101,128, +37,193,238,244,233,227,245,236,225,242,226,242,225,227,235,229, +116,2,207,86,207,93,236,229,230,116,128,48,22,242,233,231, +232,116,128,48,23,242,233,231,232,244,240,239,233,238,244,233, +238,103,2,207,119,207,135,243,237,225,236,236,244,242,233,225, +238,231,236,101,128,37,185,244,242,233,225,238,231,236,101,128, +37,183,115,3,207,154,207,184,207,192,109,2,207,160,207,172, +225,236,236,243,241,245,225,242,101,128,37,171,233,236,233,238, +231,230,225,227,101,128,38,58,241,245,225,242,101,128,37,161, +244,225,114,128,38,6,116,2,207,204,207,215,229,236,229,240, +232,239,238,101,128,38,15,239,242,244,239,233,243,229,243,232, +229,236,236,226,242,225,227,235,229,116,2,207,239,207,246,236, +229,230,116,128,48,24,242,233,231,232,116,128,48,25,245,240, +240,239,233,238,244,233,238,103,2,208,13,208,29,243,237,225, +236,236,244,242,233,225,238,231,236,101,128,37,181,244,242,233, +225,238,231,236,101,128,37,179,105,2,208,46,208,57,232,233, +242,225,231,225,238,97,128,48,144,107,2,208,63,208,73,225, +244,225,235,225,238,97,128,48,240,239,242,229,225,110,128,49, +95,237,239,238,239,243,240,225,227,101,128,255,87,111,4,208, +103,208,114,208,139,208,157,232,233,242,225,231,225,238,97,128, +48,146,235,225,244,225,235,225,238,97,129,48,242,208,127,232, +225,236,230,247,233,228,244,104,128,255,102,110,129,32,169,208, +145,237,239,238,239,243,240,225,227,101,128,255,230,247,225,229, +238,244,232,225,105,128,14,39,240,225,242,229,110,128,36,178, +242,233,238,103,128,30,152,243,245,240,229,242,233,239,114,128, +2,183,244,245,242,238,229,100,128,2,141,249,238,110,128,1, +191,120,137,0,120,208,231,208,242,208,253,209,6,209,33,209, +46,209,50,209,62,209,70,225,226,239,246,229,227,237,98,128, +3,61,226,239,240,239,237,239,230,111,128,49,18,227,233,242, +227,236,101,128,36,231,100,2,209,12,209,22,233,229,242,229, +243,233,115,128,30,141,239,244,225,227,227,229,238,116,128,30, +139,229,232,225,242,237,229,238,233,225,110,128,5,109,105,128, +3,190,237,239,238,239,243,240,225,227,101,128,255,88,240,225, +242,229,110,128,36,179,243,245,240,229,242,233,239,114,128,2, +227,121,143,0,121,209,115,210,74,210,97,210,137,212,103,212, +111,212,128,212,192,212,204,213,201,213,241,213,253,214,8,214, +29,215,2,97,11,209,139,209,151,209,161,209,168,209,175,209, +185,209,210,209,221,210,3,210,16,210,62,225,228,239,243,241, +245,225,242,101,128,51,78,226,229,238,231,225,236,105,128,9, +175,227,245,244,101,128,0,253,228,229,246,97,128,9,47,229, +235,239,242,229,225,110,128,49,82,231,117,2,209,192,209,201, +234,225,242,225,244,105,128,10,175,242,237,245,235,232,105,128, +10,47,232,233,242,225,231,225,238,97,128,48,132,107,2,209, +227,209,251,225,244,225,235,225,238,97,129,48,228,209,239,232, +225,236,230,247,233,228,244,104,128,255,148,239,242,229,225,110, +128,49,81,237,225,235,235,225,238,244,232,225,105,128,14,78, +243,237,225,236,108,2,210,26,210,37,232,233,242,225,231,225, +238,97,128,48,131,235,225,244,225,235,225,238,97,129,48,227, +210,50,232,225,236,230,247,233,228,244,104,128,255,108,244,227, +249,242,233,236,236,233,99,128,4,99,227,233,242,99,2,210, +83,210,88,236,101,128,36,232,245,237,230,236,229,120,128,1, +119,100,2,210,103,210,113,233,229,242,229,243,233,115,128,0, +255,239,116,2,210,120,210,129,225,227,227,229,238,116,128,30, +143,226,229,236,239,119,128,30,245,101,7,210,153,211,161,211, +170,211,188,211,220,212,40,212,91,104,8,210,171,210,180,210, +214,210,228,211,45,211,61,211,120,211,138,225,242,225,226,233, +99,128,6,74,226,225,242,242,229,101,2,210,191,210,200,225, +242,225,226,233,99,128,6,210,230,233,238,225,236,225,242,225, +226,233,99,128,251,175,230,233,238,225,236,225,242,225,226,233, +99,128,254,242,232,225,237,250,225,225,226,239,246,101,4,210, +247,211,0,211,14,211,30,225,242,225,226,233,99,128,6,38, +230,233,238,225,236,225,242,225,226,233,99,128,254,138,233,238, +233,244,233,225,236,225,242,225,226,233,99,128,254,139,237,229, +228,233,225,236,225,242,225,226,233,99,128,254,140,233,238,233, +244,233,225,236,225,242,225,226,233,99,128,254,243,237,101,2, +211,68,211,81,228,233,225,236,225,242,225,226,233,99,128,254, +244,229,237,105,2,211,89,211,104,238,233,244,233,225,236,225, +242,225,226,233,99,128,252,221,243,239,236,225,244,229,228,225, +242,225,226,233,99,128,252,88,238,239,239,238,230,233,238,225, +236,225,242,225,226,233,99,128,252,148,244,232,242,229,229,228, +239,244,243,226,229,236,239,247,225,242,225,226,233,99,128,6, +209,235,239,242,229,225,110,128,49,86,110,129,0,165,211,176, +237,239,238,239,243,240,225,227,101,128,255,229,111,2,211,194, +211,203,235,239,242,229,225,110,128,49,85,242,233,238,232,233, +229,245,232,235,239,242,229,225,110,128,49,134,114,3,211,228, +212,8,212,20,225,232,226,229,238,249,239,237,111,2,211,242, +211,251,232,229,226,242,229,119,128,5,170,236,229,230,244,232, +229,226,242,229,119,128,5,170,233,227,249,242,233,236,236,233, +99,128,4,75,245,228,233,229,242,229,243,233,243,227,249,242, +233,236,236,233,99,128,4,249,243,233,229,245,238,103,3,212, +53,212,62,212,78,235,239,242,229,225,110,128,49,129,240,225, +238,243,233,239,243,235,239,242,229,225,110,128,49,131,243,233, +239,243,235,239,242,229,225,110,128,49,130,244,233,246,232,229, +226,242,229,119,128,5,154,231,242,225,246,101,128,30,243,232, +239,239,107,129,1,180,212,120,225,226,239,246,101,128,30,247, +105,5,212,140,212,151,212,162,212,171,212,179,225,242,237,229, +238,233,225,110,128,5,117,227,249,242,233,236,236,233,99,128, +4,87,235,239,242,229,225,110,128,49,98,238,249,225,238,103, +128,38,47,247,238,225,242,237,229,238,233,225,110,128,5,130, +237,239,238,239,243,240,225,227,101,128,255,89,111,7,212,220, +213,34,213,45,213,55,213,93,213,139,213,148,100,131,5,217, +212,230,212,250,213,3,228,225,231,229,243,104,129,251,57,212, +241,232,229,226,242,229,119,128,251,57,232,229,226,242,229,119, +128,5,217,249,239,100,2,213,11,213,20,232,229,226,242,229, +119,128,5,242,240,225,244,225,232,232,229,226,242,229,119,128, +251,31,232,233,242,225,231,225,238,97,128,48,136,233,235,239, +242,229,225,110,128,49,137,107,2,213,61,213,85,225,244,225, +235,225,238,97,129,48,232,213,73,232,225,236,230,247,233,228, +244,104,128,255,150,239,242,229,225,110,128,49,91,243,237,225, +236,108,2,213,103,213,114,232,233,242,225,231,225,238,97,128, +48,135,235,225,244,225,235,225,238,97,129,48,231,213,127,232, +225,236,230,247,233,228,244,104,128,255,110,244,231,242,229,229, +107,128,3,243,121,2,213,154,213,191,97,2,213,160,213,170, +229,235,239,242,229,225,110,128,49,136,107,2,213,176,213,184, +239,242,229,225,110,128,49,135,244,232,225,105,128,14,34,233, +238,231,244,232,225,105,128,14,13,112,2,213,207,213,214,225, +242,229,110,128,36,180,239,231,229,231,242,225,237,237,229,238, +105,129,3,122,213,230,231,242,229,229,235,227,237,98,128,3, +69,114,129,1,166,213,247,233,238,103,128,30,153,243,245,240, +229,242,233,239,114,128,2,184,116,2,214,14,214,21,233,236, +228,101,128,30,249,245,242,238,229,100,128,2,142,117,5,214, +41,214,52,214,62,214,100,214,232,232,233,242,225,231,225,238, +97,128,48,134,233,235,239,242,229,225,110,128,49,140,107,2, +214,68,214,92,225,244,225,235,225,238,97,129,48,230,214,80, +232,225,236,230,247,233,228,244,104,128,255,149,239,242,229,225, +110,128,49,96,115,3,214,108,214,146,214,187,226,233,103,2, +214,116,214,127,227,249,242,233,236,236,233,99,128,4,107,233, +239,244,233,230,233,229,228,227,249,242,233,236,236,233,99,128, +4,109,236,233,244,244,236,101,2,214,157,214,168,227,249,242, +233,236,236,233,99,128,4,103,233,239,244,233,230,233,229,228, +227,249,242,233,236,236,233,99,128,4,105,237,225,236,108,2, +214,196,214,207,232,233,242,225,231,225,238,97,128,48,133,235, +225,244,225,235,225,238,97,129,48,229,214,220,232,225,236,230, +247,233,228,244,104,128,255,109,249,101,2,214,239,214,248,235, +239,242,229,225,110,128,49,139,239,235,239,242,229,225,110,128, +49,138,249,97,2,215,9,215,19,226,229,238,231,225,236,105, +128,9,223,228,229,246,97,128,9,95,122,142,0,122,215,58, +216,66,216,77,216,120,216,147,217,182,218,34,218,76,218,88, +218,100,218,128,218,136,218,152,218,161,97,10,215,80,215,91, +215,98,215,105,215,116,215,194,215,224,215,235,216,15,216,27, +225,242,237,229,238,233,225,110,128,5,102,227,245,244,101,128, +1,122,228,229,246,97,128,9,91,231,245,242,237,245,235,232, +105,128,10,91,104,4,215,126,215,135,215,149,215,179,225,242, +225,226,233,99,128,6,56,230,233,238,225,236,225,242,225,226, +233,99,128,254,198,105,2,215,155,215,170,238,233,244,233,225, +236,225,242,225,226,233,99,128,254,199,242,225,231,225,238,97, +128,48,86,237,229,228,233,225,236,225,242,225,226,233,99,128, +254,200,233,110,2,215,201,215,210,225,242,225,226,233,99,128, +6,50,230,233,238,225,236,225,242,225,226,233,99,128,254,176, +235,225,244,225,235,225,238,97,128,48,182,241,229,102,2,215, +243,216,1,231,225,228,239,236,232,229,226,242,229,119,128,5, +149,241,225,244,225,238,232,229,226,242,229,119,128,5,148,242, +241,225,232,229,226,242,229,119,128,5,152,249,233,110,130,5, +214,216,37,216,57,228,225,231,229,243,104,129,251,54,216,48, +232,229,226,242,229,119,128,251,54,232,229,226,242,229,119,128, +5,214,226,239,240,239,237,239,230,111,128,49,23,99,3,216, +85,216,92,216,114,225,242,239,110,128,1,126,233,242,99,2, +216,100,216,105,236,101,128,36,233,245,237,230,236,229,120,128, +30,145,245,242,108,128,2,145,228,239,116,130,1,124,216,130, +216,139,225,227,227,229,238,116,128,1,124,226,229,236,239,119, +128,30,147,101,6,216,161,216,172,216,215,216,226,216,237,217, +177,227,249,242,233,236,236,233,99,128,4,55,100,2,216,178, +216,197,229,243,227,229,238,228,229,242,227,249,242,233,236,236, +233,99,128,4,153,233,229,242,229,243,233,243,227,249,242,233, +236,236,233,99,128,4,223,232,233,242,225,231,225,238,97,128, +48,92,235,225,244,225,235,225,238,97,128,48,188,242,111,140, +0,48,217,10,217,19,217,29,217,36,217,61,217,74,217,85, +217,97,217,108,217,118,217,129,217,136,225,242,225,226,233,99, +128,6,96,226,229,238,231,225,236,105,128,9,230,228,229,246, +97,128,9,102,231,117,2,217,43,217,52,234,225,242,225,244, +105,128,10,230,242,237,245,235,232,105,128,10,102,232,225,227, +235,225,242,225,226,233,99,128,6,96,233,238,230,229,242,233, +239,114,128,32,128,237,239,238,239,243,240,225,227,101,128,255, +16,239,236,228,243,244,249,236,101,128,247,48,240,229,242,243, +233,225,110,128,6,240,243,245,240,229,242,233,239,114,128,32, +112,244,232,225,105,128,14,80,247,233,228,244,104,3,217,148, +217,157,217,169,234,239,233,238,229,114,128,254,255,238,239,238, +234,239,233,238,229,114,128,32,12,243,240,225,227,101,128,32, +11,244,97,128,3,182,104,2,217,188,217,199,226,239,240,239, +237,239,230,111,128,49,19,101,4,217,209,217,220,217,236,217, +247,225,242,237,229,238,233,225,110,128,5,106,226,242,229,246, +229,227,249,242,233,236,236,233,99,128,4,194,227,249,242,233, +236,236,233,99,128,4,54,100,2,217,253,218,16,229,243,227, +229,238,228,229,242,227,249,242,233,236,236,233,99,128,4,151, +233,229,242,229,243,233,243,227,249,242,233,236,236,233,99,128, +4,221,105,3,218,42,218,53,218,64,232,233,242,225,231,225, +238,97,128,48,88,235,225,244,225,235,225,238,97,128,48,184, +238,239,242,232,229,226,242,229,119,128,5,174,236,233,238,229, +226,229,236,239,119,128,30,149,237,239,238,239,243,240,225,227, +101,128,255,90,111,2,218,106,218,117,232,233,242,225,231,225, +238,97,128,48,94,235,225,244,225,235,225,238,97,128,48,190, +240,225,242,229,110,128,36,181,242,229,244,242,239,230,236,229, +248,232,239,239,107,128,2,144,243,244,242,239,235,101,128,1, +182,117,2,218,167,218,178,232,233,242,225,231,225,238,97,128, +48,90,235,225,244,225,235,225,238,97,128,48,186]; + +function ft_get_adobe_glyph_index(_name,limit) +{ + var name = 0; + var c = 0; + var count, min, max; + var p = 0; + + if (_name == null || _name == "" || 0 >= limit) + return 0; + + c = _name.charCodeAt(name); + name++; + count = ft_adobe_glyph_list[1]; + p += 2; + + min = 0; + max = count; + + var go_to_found = 0; + var go_to_next = 0; + while (min < max) + { + var mid = (min + max) >>> 1; + var q = p + mid * 2; + q = ((ft_adobe_glyph_list[q] << 8) | ft_adobe_glyph_list[q+1]); + var c2 = ft_adobe_glyph_list[q] & 127; + if (c2 == c) + { + p = q; + go_to_found = 1; + break; + } + if ( c2 < c ) + min = mid + 1; + else + max = mid; + } + if (0 == go_to_found) + return 0; + + for (;;) + { + if (name >= limit) + { + if ((ft_adobe_glyph_list[p] & 128) == 0 && (ft_adobe_glyph_list[p+1] & 128) != 0) + return ((ft_adobe_glyph_list[p+2] << 8) | ft_adobe_glyph_list[p+3]); + return 0; + } + c = _name.charCodeAt(name++); + if (ft_adobe_glyph_list[p] & 128) + { + p++; + if (c != (ft_adobe_glyph_list[p] & 127)) + return 0; + continue; + } + + p++; + count = ft_adobe_glyph_list[p] & 127; + if (ft_adobe_glyph_list[p] & 128) + p += 2; + + p++; + for (; count > 0; count--, p += 2) + { + var offset = (ft_adobe_glyph_list[p] << 8) | ft_adobe_glyph_list[p+1]; + var q = offset; + if (c == (ft_adobe_glyph_list[q] & 127)) + { + p = q; + go_to_next = 1; + break; + } + } + if (0 == go_to_next) + return 0; + } + return 0; +} + +function PS_UniMap() +{ + this.unicode = 0; + this.glyph_index = 0; +} +function PS_UnicodesRec() +{ + this.cmap = null; + this.num_maps = 0; + this.maps = null; +} + +function ps_unicode_value(glyph_name) +{ + var len = glyph_name.length; + if (glyph_name.charCodeAt(0) == FT_Common.SYMBOL_CONST_u && glyph_name.charCodeAt(1) == FT_Common.SYMBOL_CONST_n && glyph_name.charCodeAt(2) == FT_Common.SYMBOL_CONST_i) + { + var count; + var value = 0; + var p = 3; + + for ( count = 4; count > 0; count--, p++ ) + { + var c = 0; + if (p < len) + c = glyph_name.charCodeAt(p); + if (c<0) + c+=256; + var d = c - FT_Common.SYMBOL_CONST_0; + if (d < 0) + d += 256; + if (d >= 10) + { + d = c - FT_Common.SYMBOL_CONST_A; + if (d < 0) + d += 256; + if (d >= 6) + d = 16; + else + d += 10; + } + + if (d >= 16) + break; + + value = (value << 4) + d; + } + + if (count == 0) + { + if (p >= len) + return value; + if (glyph_name.charCodeAt(p) == FT_Common.SYMBOL_CONST_POINT) + return (value | 0x7FFFFFFF); + } + } + + if (glyph_name.charCodeAt(0) == FT_Common.SYMBOL_CONST_u) + { + var count; + var value = 0; + var p = 1; + + for (count = 6; count > 0; count--, p++) + { + var c = 0; + if (p < len) + c = glyph_name.charCodeAt(p); + if (c<0) + c+=256; + var d = c - FT_Common.SYMBOL_CONST_0; + if (d < 0) + d += 256; + if (d >= 10) + { + d = c - FT_Common.SYMBOL_CONST_A; + if (d < 0) + d += 256; + if (d >= 6) + d = 16; + else + d += 10; + } + + if (d >= 16) + break; + + value = (value << 4) + d; + } + + if (count <= 2) + { + if (p >= len) + return value; + if (glyph_name.charCodeAt(p) == FT_Common.SYMBOL_CONST_POINT) + return (value | 0x7FFFFFFF); + } + } + + var p = 0; + var dot = 0; + + for (; p<len; p++) + { + if (glyph_name.charCodeAt(p) == FT_Common.SYMBOL_CONST_POINT && p > 0) + { + dot = p; + break; + } + } + + if (dot == 0) + return ft_get_adobe_glyph_index(glyph_name, p); + else + return ft_get_adobe_glyph_index(glyph_name, dot | 0x7FFFFFFF); +} + +function compare_uni_maps(map1, map2) +{ + var unicode1 = map1.unicode & 0x7FFFFFFF; + var unicode2 = map2.unicode & 0x7FFFFFFF; + if (unicode1 == unicode2) + { + if (map1.unicode > map2.unicode) + return 1; + else if (map1.unicode < map2.unicode) + return -1; + else + return 0; + } + else + { + if (unicode1 > unicode2) + return 1; + else if (unicode1 < unicode2) + return -1; + else + return 0; + } +} + +function ft_qsort(mass, count, compare) +{ + var t; + for (var i=0;i<count;i++) + { + for (var j=i+1;j<count;j++) + { + if (compare(mass[i],mass[j]) == 1) + { + t=mass[i]; + mass[i]=mass[j]; + mass[j]=t; + } + } + } +} + +var ft_extra_glyph_unicodes=[0x0394,0x03A9,0x2215,0x00AD,0x02C9,0x03BC,0x2219,0x00A0,0x021A,0x021B]; +var ft_extra_glyph_names=["Delta","Omega","fraction","hyphen","macron","mu","periodcentered","space","Tcommaaccent","tcommaaccent"]; + +function ps_check_extra_glyph_name(gname,glyph,extra_glyphs,states) +{ + for (var n = 0; n < 10; n++) + { + if (ft_extra_glyph_names[n] == gname) + { + if ( states[n] == 0 ) + { + states[n] = 1; + extra_glyphs[n] = glyph; + } + + return; + } + } +} +function ps_check_extra_glyph_unicode(uni_char,states) +{ + for (var n = 0; n < 10; n++) + { + if (uni_char == ft_extra_glyph_unicodes[n]) + { + states[n] = 2; + return; + } + } +} + +function ps_unicodes_init(memory,table,num_glyphs,get_glyph_name,free_glyph_name,glyph_data) +{ + var error = 0; + + var extra_glyph_list_states = [0,0,0,0,0,0,0,0,0,0]; + var extra_glyphs = [0,0,0,0,0,0,0,0,0,0]; + + table.num_maps = 0; + table.maps = new Array(num_glyphs + 10); + for (var i = 0; i < (num_glyphs + 10); i++) + table.maps[i] = new PS_UniMap(); + + var n; + var map = 0; + var maps = table.maps; + var uni_char; + + for ( n = 0; n < num_glyphs; n++) + { + var gname = get_glyph_name(glyph_data, n); + if (gname != null) + { + ps_check_extra_glyph_name(gname, n, extra_glyphs, extra_glyph_list_states); + + if (n == 86) + { + var __nnn = 0; + __nnn += 1; + __nnn += 1; + __nnn += 1; + } + + uni_char = ps_unicode_value(gname); + + if ((uni_char & 0x7FFFFFFF) != 0) + { + ps_check_extra_glyph_unicode(uni_char, extra_glyph_list_states); + maps[map].unicode = uni_char; + maps[map].glyph_index = n; + map++; + } + + if (free_glyph_name) + free_glyph_name(glyph_data, gname); + } + } + + for (n = 0; n < 10; n++) + { + if (extra_glyph_list_states[n] == 1) + { + maps[map].unicode = ft_extra_glyph_unicodes[n]; + maps[map].glyph_index = extra_glyphs[n]; + map++; + } + } + + var count = map; + if ( count == 0 ) + { + table.maps = null; + if (!error) + error = 163; + } + else + { + if (count < num_glyphs / 2) + { + table.maps[count-1] = new PS_UniMap(); + error = 0; + } + + var del_count = num_glyphs + 10 - count; + if (del_count > 10) + maps.splice(count, del_count); + maps.sort(compare_uni_maps); + //ft_qsort(table.maps, count, compare_uni_maps); + } + + table.num_maps = count; + + return error; +} + +function ps_unicodes_char_index(table, unicode) +{ + var mid, result = -1; + + var maps = table.maps; + var min = 0; + var max = table.num_maps - 1; + + while (min <= max) + { + mid = min + ((max - min) >>> 1); + + if (maps[mid].unicode == unicode) + { + result = mid; + break; + } + + var base_glyph = maps[mid].unicode & 0x7FFFFFFF; + if (base_glyph == unicode) + result = mid; + + if (min == max) + break; + + if (base_glyph < unicode) + min = mid + 1; + else + max = mid - 1; + } + + if (result != -1) + return maps[result].glyph_index; + return 0; +} + +function ps_unicodes_char_next(table, unicode) +{ + var result = 0; + var char_code = unicode + 1; + + var min = 0; + var max = table.num_maps; + var mid; + var map; + var base_glyph; + + while ( min < max ) + { + mid = min + ((max - min) >>> 1); + map = table.maps[mid]; + + if (map.unicode == char_code) + { + result = map.glyph_index; + return {unicode:char_code, result:result}; + } + + base_glyph = (map.unicode & 0x7FFFFFFF); + + if (base_glyph == char_code) + result = map.glyph_index; + + if (base_glyph < char_code) + min = mid + 1; + else + max = mid; + } + + if (result != 0) + return {unicode:char_code, result:result}; + + char_code = 0; + + if (min < table.num_maps) + { + map = table.maps[min]; + result = map.glyph_index; + char_code = (map.unicode & 0x7FFFFFFF); + } + + return {unicode:char_code, result:result}; +} + +function ps_get_macintosh_name(name_index) +{ + if (name_index >= 258) + name_index = 0; + + return ft_standard_glyph_names[ft_mac_names[name_index]]; +} + +function ps_get_standard_strings(sid) +{ + if (sid >= 391) + return 0; + + return ft_standard_glyph_names[ft_sid_names[sid]]; +} + +function _pscmaps_interface() +{ + this.unicode_value = ps_unicode_value; + this.unicodes_init = ps_unicodes_init; + this.unicodes_char_index = ps_unicodes_char_index; + this.unicodes_char_next = ps_unicodes_char_next; + + this.macintosh_name = ps_get_macintosh_name; + this.adobe_std_strings = ps_get_standard_strings; + this.adobe_std_encoding = t1_standard_encoding; + this.adobe_expert_encoding = t1_expert_encoding; +} + +var pscmaps_interface = new _pscmaps_interface(); +function create_psnames_module(library) +{ + var psnames_mod = new FT_Module(); + psnames_mod.clazz = new FT_Module_Class(); + + var clazz = psnames_mod.clazz; + clazz.flags = 0; + clazz.name = "psnames"; + clazz.version = 0x10000; + clazz.requires = 0x20000; + + clazz.module_interface = pscmaps_interface; + clazz.init = null; + clazz.done = null; + + clazz.get_interface = function(module, name) + { + if (name == "postscript-cmaps") + return pscmaps_interface; + return null; + } + + psnames_mod.library = library; + psnames_mod.memory = library.Memory; + psnames_mod.generic = null; + + return psnames_mod; +} \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/modules/render.js b/Common/FontsFreeType/Private/FreeType/modules/render.js new file mode 100644 index 0000000000000000000000000000000000000000..5edede2a5ea4eb15890544891218e2ce9fdc1039 --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/modules/render.js @@ -0,0 +1,2426 @@ +function CRasterMemory() +{ + this.width = 0; + this.height = 0; + this.pitch = 0; + + this.m_oBuffer = null; + this.CheckSize = function(w, h) + { + if (this.width < (w + 1) || this.height < (h + 1)) + { + this.width = Math.max(this.width, w + 1); + this.pitch = 4 * this.width; + this.height = Math.max(this.height, h + 1); + + this.m_oBuffer = null; + this.m_oBuffer = g_memory.ctx.createImageData(this.width, this.height); + } + } +} +var raster_memory = new CRasterMemory(); + +// outline --- +function _FT_Outline_Funcs_Gray() +{ + this.move_to = function(to, worker) + { + /* record current cell, if any */ + var err = gray_record_cell(worker); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + + /* start to a new position */ + var x = to.x << 2; + var y = to.y << 2; + + err = gray_start_cell(worker, x >> 8, y >> 8); + + worker.x = x; + worker.y = y; + return err; + } + + this.line_to = function(to, worker) + { + return gray_render_line(worker, to.x << 2, to.y << 2); + } + + this.conic_to = function(control, to, worker) + { + return gray_render_conic(worker, control, to); + } + + this.cubic_to = function(control1, control2, to, worker) + { + return gray_render_cubic(worker, control1, control2, to); + } + + this.shift = 0; + this.delta = 0; +} +var ft_outline_funcs_gray = new _FT_Outline_Funcs_Gray(); + +function FT_Outline_Decompose(outline, func_interface, user) +{ + if (!outline || !func_interface) + return FT_Common.FT_Err_Invalid_Argument; + + var v_last = new FT_Vector(); + var v_control = new FT_Vector(); + var v_start = new FT_Vector(); + + var point; + var limit; + + var tags = 0; + var first = 0; + var tag = 0; + + var shift = func_interface.shift; + var delta = func_interface.delta; + + var error = 0; + + var count = outline.n_contours; + var _c = outline.contours; + var _p = outline.points; + var _t = outline.tags; + for (var n = 0; n < count; n++) + { + var last = _c[n]; + if (last < 0) + return FT_Common.FT_Err_Invalid_Outline; + limit = last; + + v_start.x = (_p[first].x << shift) - delta; + v_start.y = (_p[first].y << shift) - delta; + + v_last.x = (_p[last].x << shift) - delta; + v_last.y = (_p[last].y << shift) - delta; + + v_control.x = v_start.x; + v_control.y = v_start.y; + + point = first; + tags = first; + tag = _t[tags] & 3; + + /* A contour cannot start with a cubic control point! */ + if (tag == FT_Common.FT_CURVE_TAG_CUBIC) + return FT_Common.FT_Err_Invalid_Outline; + + /* check first point to determine origin */ + if (tag == FT_Common.FT_CURVE_TAG_CONIC) + { + /* first point is conic control. Yes, this happens. */ + if ((_t[last] & 3) == FT_Common.FT_CURVE_TAG_ON) + { + /* start at last point if it is on the curve */ + v_start.x = v_last.x; + v_start.y = v_last.y; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = parseInt((v_start.x + v_last.x) / 2); + v_start.y = parseInt((v_start.y + v_last.y) / 2); + + v_last.x = v_start.x; + v_last.y = v_start.y; + } + point--; + tags--; + } + + error = func_interface.move_to(v_start, user); + if (error != 0) + return error; + + var isClose = 0; + while (point < limit) + { + point++; + tags++; + + tag = _t[tags] & 3; + switch ( tag ) + { + case FT_Common.FT_CURVE_TAG_ON: /* emit a single line_to */ + { + var vec = new FT_Vector(); + + vec.x = (_p[point].x << shift) - delta; + vec.y = (_p[point].y << shift) - delta; + + error = func_interface.line_to(vec, user); + if (0 != error) + return error; + continue; + } + + case FT_Common.FT_CURVE_TAG_CONIC: /* consume conic arcs */ + v_control.x = (_p[point].x << shift) - delta; + v_control.y = (_p[point].y << shift) - delta; + + var isCont = 0; + while (true) + { + if (point < limit) + { + var vec = new FT_Vector(); + var v_middle = new FT_Vector(); + + point++; + tags++; + tag = _t[tags] & 3; + + vec.x = (_p[point].x << shift) - delta; + vec.y = (_p[point].y << shift) - delta; + + if (tag == FT_Common.FT_CURVE_TAG_ON) + { + error = func_interface.conic_to(v_control, vec, user); + if (0 != error) + return error; + isCont = 1; + break; + } + + if (tag != FT_Common.FT_CURVE_TAG_CONIC) + return FT_Common.FT_Err_Invalid_Outline; + + v_middle.x = parseInt((v_control.x + vec.x) / 2); + v_middle.y = parseInt((v_control.y + vec.y) / 2); + + error = func_interface.conic_to(v_control, v_middle, user); + if (0 != error) + return error; + + v_control.x = vec.x; + v_control.y = vec.y; + + continue; + } + break; + } + if (1 == isCont/* && (point < limit)*/) + continue; + + error = func_interface.conic_to(v_control, v_start, user); + isClose = 1; + break; + + default: /* FT_CURVE_TAG_CUBIC */ + { + var vec1 = new FT_Vector(); + var vec2 = new FT_Vector(); + + if ((point + 1 > limit) || (_t[tags+1]&3) != FT_Common.FT_CURVE_TAG_CUBIC) + return FT_Common.FT_Err_Invalid_Outline; + + point += 2; + tags += 2; + + vec1.x = (_p[point-2].x << shift) - delta; + vec1.y = (_p[point-2].y << shift) - delta; + + vec2.x = (_p[point-1].x << shift) - delta; + vec2.y = (_p[point-1].y << shift) - delta; + + if (point <= limit) + { + var vec = new FT_Vector(); + vec.x = (_p[point].x << shift) - delta; + vec.y = (_p[point].y << shift) - delta; + + error = func_interface.cubic_to(vec1, vec2, vec, user); + if (0 != error) + return error; + continue; + } + + error = func_interface.cubic_to(vec1, vec2, v_start, user); + isClose = 1; + break; + } + } + + if (isClose == 1) + break; + } + + if (error != 0) + return error; + + /* close the contour with a line segment */ + if (0 == isClose) + error = func_interface.line_to(v_start, user); + + if (error != 0) + return error; + + isClose = 0; + first = last + 1; + } + return 0; +} + +function FT_Outline_Get_Orientation(outline) +{ + if (outline == null || outline.n_points <= 0) + return FT_Common.FT_ORIENTATION_TRUETYPE; + + /* We use the nonzero winding rule to find the orientation. */ + /* Since glyph outlines behave much more `regular' than arbitrary */ + /* cubic or quadratic curves, this test deals with the polygon */ + /* only which is spanned up by the control points. */ + var points = outline.points; + + var v_cur; + var first = 0; + var area = 0; + for (var c = 0; c < outline.n_contours; c++) + { + var last = outline.contours[c]; + var v_prev = points[last]; + + for (var n = first; n <= last; n++) + { + v_cur = points[n]; + area += (v_cur.y - v_prev.y) * (v_cur.x + v_prev.x); + v_prev = v_cur; + } + + first = last + 1; + } + + if (area > 0) + return FT_Common.FT_ORIENTATION_POSTSCRIPT; + else if ( area < 0 ) + return FT_Common.FT_ORIENTATION_TRUETYPE; + return FT_Common.FT_ORIENTATION_NONE; +} + +function FT_Outline_Get_Orientation_Cur(outline, base) +{ + if (outline == null || outline.n_points <= 0) + return FT_Common.FT_ORIENTATION_TRUETYPE; + + /* We use the nonzero winding rule to find the orientation. */ + /* Since glyph outlines behave much more `regular' than arbitrary */ + /* cubic or quadratic curves, this test deals with the polygon */ + /* only which is spanned up by the control points. */ + var points = base.points; + var contours = base.contours; + var _p_off = outline.points; + var _c_off = outline.contours; + + var v_prev = new FT_Vector(); + var v_cur = new FT_Vector(); + + var first = 0; + var area = 0; + for (var c = 0; c < outline.n_contours; c++) + { + var last = contours[_c_off + c]; + v_prev.x = points[_p_off + last].x; + v_prev.y = points[_p_off + last].y; + + for (var n = first; n <= last; n++) + { + v_cur.x = points[_p_off + n].x; + v_cur.y = points[_p_off + n].y; + area += (v_cur.y - v_prev.y) * (v_cur.x + v_prev.x); + v_prev.x = v_cur.x; + v_prev.y = v_cur.y; + } + + first = last + 1; + } + + if (area > 0) + return FT_Common.FT_ORIENTATION_POSTSCRIPT; + else if ( area < 0 ) + return FT_Common.FT_ORIENTATION_TRUETYPE; + return FT_Common.FT_ORIENTATION_NONE; +} + +function ft_trig_prenorm(vec) +{ + var x = vec.x; + var y = vec.y; + + var z = ((x >= 0) ? x : - x) | ((y >= 0) ? y : -y); + var shift = 0; + + /* determine msb bit index in `shift' */ + if (z >= (1 << 16)) + { + z >>= 16; + shift += 16; + } + if (z >= (1 << 8)) + { + z >>= 8; + shift += 8; + } + if (z >= (1 << 4)) + { + z >>= 4; + shift += 4; + } + if (z >= (1 << 2)) + { + z >>= 2; + shift += 2; + } + if (z >= (1 << 1)) + { + z >>= 1; + shift += 1; + } + + if (shift <= 27) + { + shift = 27 - shift; + vec.x = x << shift; + vec.y = y << shift; + } + else + { + shift -= 27; + vec.x = x >> shift; + vec.y = y >> shift; + shift = -shift; + } + + return shift; +} + +var ft_trig_arctan_table = [2949120, 1740967, 919879, 466945, 234379, 117304, 58666, 29335, 14668, 7334, + 3667, 1833, 917, 458, 229, 115, 57, 29, 14, 7, 4, 2, 1]; + +function ft_trig_pseudo_polarize(vec) +{ + var x = vec.x; + var y = vec.y; + + /* Get the vector into the right half plane */ + var theta = 0; + if (x < 0) + { + x = -x; + y = -y; + theta = 2 * FT_Common.FT_ANGLE_PI2; + } + + if (y > 0) + theta = - theta; + + var arctanptr = 0; + var xtemp = 0; + /* Pseudorotations, with right shifts */ + i = 0; + do + { + if ( y > 0 ) + { + xtemp = x + (y >> i); + y = y - (x >> i); + x = xtemp; + theta += ft_trig_arctan_table[arctanptr++]; + } + else + { + xtemp = x - (y >> i); + y = y + (x >> i); + x = xtemp; + theta -= ft_trig_arctan_table[arctanptr++]; + } + } while (++i < FT_Common.FT_TRIG_MAX_ITERS); + + /* round theta */ + if (theta >= 0) + theta = ((theta + 16) & ~31); + else + theta = -((-theta + 16) & ~31); + + vec.x = x; + vec.y = theta; +} + +function ft_trig_downscale(val) +{ + var s = val; + val = (val >= 0) ? val : -val; + + var v1 = FT_Common.IntToUInt(val >> 16); + var v2 = FT_Common.IntToUInt(val & 0xFFFF); + + var k1 = 0x9B74; /* constant */ + var k2 = 0xEDA8; /* constant */ + + var hi = k1 * v1; + var lo1 = k1 * v2 + k2 * v1; /* can't overflow */ + + var lo2 = ( k2 * v2 ) / 65536; + lo2 = lo2 >> 0; + var lo3 = ( lo1 >= lo2 ) ? lo1 : lo2; + lo1 += lo2; + + lo1 = FT_Common.IntToUInt(lo1); + + hi += lo1 >> 16; + if (lo1 < lo3) + hi += 0x10000; + + val = hi; + val = FT_Common.UintToInt(val); + + return (s >= 0) ? val : -val; +} + +function FT_Vector_Length(vec) +{ + var v = new FT_Vector(); + v.x = vec.x; + v.y = vec.y; + + /* handle trivial cases */ + if (v.x == 0) + { + return (v.y >= 0) ? v.y : -v.y; + } + else if (v.y == 0) + { + return (v.x >= 0) ? v.x : -v.x; + } + + /* general case */ + var shift = ft_trig_prenorm(v); + ft_trig_pseudo_polarize(v); + + v.x = ft_trig_downscale(v.x); + + if (shift > 0) + return (v.x + (1 << (shift - 1))) >> shift; + return v.x << -shift; +} + +function FT_Outline_EmboldenXY(outline, xstrength, ystrength) +{ + if (outline == null) + return FT_Common.FT_Err_Invalid_Argument; + + xstrength /= 2; + ystrength /= 2; + + if (xstrength == 0 && ystrength == 0) + return 0; + + var orientation = FT_Outline_Get_Orientation(outline); + if (orientation == FT_Common.FT_ORIENTATION_NONE) + { + if (outline.n_contours != 0) + return FT_Common.FT_Err_Invalid_Argument; + else + return 0; + } + + var points = outline.points; + var contours = outline.contours; + + var v_first = new FT_Vector(); + var v_prev = new FT_Vector(); + var v_cur = new FT_Vector(); + var v_next = new FT_Vector(); + + var first = 0; + var last = 0; + for (var c = 0; c < outline.n_contours; c++) + { + var _in = new FT_Vector(); + var out = new FT_Vector(); + var shift = new FT_Vector(); + + last = contours[c]; + + v_first.x = points[first].x; + v_first.y = points[first].y; + + v_prev.x = points[last].x; + v_prev.y = points[last].y; + + v_cur.x = v_first.x; + v_cur.y = v_first.y; + + /* compute the incoming vector and its length */ + _in.x = v_cur.x - v_prev.x; + _in.y = v_cur.y - v_prev.y; + var l_in = FT_Vector_Length(_in); + + for (var n = first; n <= last; n++) + { + if (n < last) + v_next = points[n + 1]; + else + v_next = v_first; + + /* compute the outgoing vector and its length */ + out.x = v_next.x - v_cur.x; + out.y = v_next.y - v_cur.y; + var l_out = FT_Vector_Length(out); + + var d = l_in * l_out + _in.x * out.x + _in.y * out.y; + + /* shift only if turn is less then ~160 degrees */ + if (16 * d > l_in * l_out) + { + /* shift components are aligned along bisector */ + /* and directed according to the outline orientation. */ + shift.x = l_out * _in.y + l_in * out.y; + shift.y = l_out * _in.x + l_in * out.x; + + if (orientation == FT_Common.FT_ORIENTATION_TRUETYPE) + shift.x = -shift.x; + else + shift.y = -shift.y; + + /* threshold strength to better handle collapsing segments */ + var l = Math.min(l_in, l_out); + var q = out.x * _in.y - out.y * _in.x; + if (orientation == FT_Common.FT_ORIENTATION_TRUETYPE) + q = -q; + + if (FT_MulDiv(xstrength, q, l) < d) + shift.x = FT_MulDiv(shift.x, xstrength, d); + else + shift.x = FT_MulDiv(shift.x, l, q); + + if (FT_MulDiv(ystrength, q, l) < d) + shift.y = FT_MulDiv(shift.y, ystrength, d); + else + shift.y = FT_MulDiv(shift.y, l, q); + } + else + shift.x = shift.y = 0; + + points[n].x = v_cur.x + xstrength + shift.x; + points[n].y = v_cur.y + ystrength + shift.y; + + _in = out; + l_in = l_out; + v_cur.x = v_next.x; + v_cur.y = v_next.y; + } + + first = last + 1; + } + + return 0; +} + +function FT_Outline_EmboldenXY_cur(outline, base, xstrength, ystrength) +{ + if (outline == null) + return FT_Common.FT_Err_Invalid_Argument; + + xstrength /= 2; + ystrength /= 2; + + if (xstrength == 0 && ystrength == 0) + return 0; + + var orientation = FT_Outline_Get_Orientation_Cur(outline, base); + if (orientation == FT_Common.FT_ORIENTATION_NONE) + { + if (outline.n_contours != 0) + return FT_Common.FT_Err_Invalid_Argument; + else + return 0; + } + + var points = base.points; + var contours = base.contours; + + var _p_off = outline.points; + var _c_off = outline.contours; + + var v_first = new FT_Vector(); + var v_prev = new FT_Vector(); + var v_cur = new FT_Vector(); + var v_next = new FT_Vector(); + + var first = 0; + var last = 0; + for (var c = 0; c < outline.n_contours; c++) + { + var _in = new FT_Vector(); + var out = new FT_Vector(); + var shift = new FT_Vector(); + + last = contours[_c_off + c]; + + v_first.x = points[_p_off + first].x; + v_first.y = points[_p_off + first].y; + + v_prev.x = points[_p_off + last].x; + v_prev.y = points[_p_off + last].y; + + v_cur.x = v_first.x; + v_cur.y = v_first.y; + + /* compute the incoming vector and its length */ + _in.x = v_cur.x - v_prev.x; + _in.y = v_cur.y - v_prev.y; + var l_in = FT_Vector_Length(_in); + + for (var n = first; n <= last; n++) + { + if (n < last) + { + v_next.x = points[_p_off + n + 1].x; + v_next.y = points[_p_off + n + 1].y; + } + else + { + v_next.x = v_first.x; + v_next.y = v_first.y; + } + + /* compute the outgoing vector and its length */ + out.x = v_next.x - v_cur.x; + out.y = v_next.y - v_cur.y; + var l_out = FT_Vector_Length(out); + + var d = l_in * l_out + _in.x * out.x + _in.y * out.y; + + /* shift only if turn is less then ~160 degrees */ + if (16 * d > l_in * l_out) + { + /* shift components are aligned along bisector */ + /* and directed according to the outline orientation. */ + shift.x = l_out * _in.y + l_in * out.y; + shift.y = l_out * _in.x + l_in * out.x; + + if (orientation == FT_Common.FT_ORIENTATION_TRUETYPE) + shift.x = -shift.x; + else + shift.y = -shift.y; + + /* threshold strength to better handle collapsing segments */ + var l = Math.min(l_in, l_out); + var q = out.x * _in.y - out.y * _in.x; + if (orientation == FT_Common.FT_ORIENTATION_TRUETYPE) + q = -q; + + if (FT_MulDiv(xstrength, q, l) < d) + shift.x = FT_MulDiv(shift.x, xstrength, d); + else + shift.x = FT_MulDiv(shift.x, l, q); + + if (FT_MulDiv(ystrength, q, l) < d) + shift.y = FT_MulDiv(shift.y, ystrength, d); + else + shift.y = FT_MulDiv(shift.y, l, q); + } + else + shift.x = shift.y = 0; + + points[_p_off + n].x = v_cur.x + xstrength + shift.x; + points[_p_off + n].y = v_cur.y + ystrength + shift.y; + + _in = out; + l_in = l_out; + v_cur.x = v_next.x; + v_cur.y = v_next.y; + } + + first = last + 1; + } + + return 0; +} + + +function FT_Outline_Embolden(outline, strength) +{ + return FT_Outline_EmboldenXY(outline, strength, strength); +} +//------------ + +function FT_Outline_Transform(outline, matrix) +{ + if ( !outline || !matrix ) + return; + + var vec = outline.points; + var len = outline.n_points; + + for (var i=0; i < len; i++) + FT_Vector_Transform(vec[i], matrix); +} + +function FT_Vector_Transform(vector, matrix) +{ + if ( !vector || !matrix ) + return; + + var xz = FT_MulFix(vector.x, matrix.xx) + FT_MulFix(vector.y, matrix.xy); + var yz = FT_MulFix(vector.x, matrix.yx) + FT_MulFix(vector.y, matrix.yy); + + vector.x = xz; + vector.y = yz; +} + +function FT_Outline_Translate(outline, xOffset, yOffset) +{ + if ( !outline ) + return; + + var vec = outline.points; + var c = outline.n_points; + + for (var n=0;n<c;n++) + { + vec[n].x += xOffset; + vec[n].y += yOffset; + } +} + +function FT_Outline_Get_CBox(outline, acbox) +{ + var xMin, yMin, xMax, yMax; + + if (outline != null && acbox != null) + { + if (outline.n_points == 0) + { + xMin = 0; + yMin = 0; + xMax = 0; + yMax = 0; + } + else + { + var p = outline.points; + var vec = p[0]; + var count = outline.n_points; + + xMin = xMax = vec.x; + yMin = yMax = vec.y; + + for (var i = 1; i < count; i++) + { + var x = p[i].x; + if ( x < xMin ) xMin = x; + if ( x > xMax ) xMax = x; + + var y = p[i].y; + if ( y < yMin ) yMin = y; + if ( y > yMax ) yMax = y; + } + } + acbox.xMin = xMin; + acbox.xMax = xMax; + acbox.yMin = yMin; + acbox.yMax = yMax; + } +} + +function FT_Glyph_Class() +{ + this.glyph_size = 0; + this.glyph_format = 0; + this.glyph_init = null; + this.glyph_done = null; + this.glyph_copy = null; + this.glyph_transform = null; + this.glyph_bbox = null; + this.glyph_prepare = null; +} + +// Ð´Ð»Ñ Ð±Ñ‹Ñтроты работы не пользуетÑÑ Ñта Ñтруктура. +// вÑе ради вÑех браузеров, кроме ie9. в них типизированные маÑÑивы +// быÑтрее обычных (а тут ÑкороÑÑ‚ÑŒ доÑтупа - Ñамое главное) +function TCell() +{ + this.x = 0; + this.cover = 0; + this.area = 0; + this.next = 0; +} + +function TRaster() +{ + this.worker = new TWorker(); + + this.memory = null; + + this.cell_x = CreateIntArray(1024); + this.cell_cover = CreateIntArray(1024); + this.cell_area = CreateIntArray(1024); + this.cell_next = CreateIntArray(1024); + + this.buffer_size = 0; + this.band_size = 0; +} + +// - smooth ----------------------------------------------------------- +// ------------ rasterizer -------------------------------------------- +// пул памÑти Ð´Ð»Ñ Ñ€Ð°Ñтеризатора делаем Array int'ов. Почему не маÑÑив Ñтруктур? +// 1) не выделÑÑ‚ÑŒ памÑÑ‚ÑŒ под Ñаму Ñтруктуру (Ñ…Ð¾Ñ‚Ñ ÐºÑ‚Ð¾ знает как работает js) +// 2) Ñамое главное - Ñто возможноÑÑ‚ÑŒ замены на типизированный маÑÑив!!! +// Ñам раÑтеризатор ничего не знает о проиÑхождении маÑÑива. За Ñоздание +// его отвечает Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ CreateIntArray +function CreateIntArray(size) +{ + var arr = null; + if (typeof(Int32Array) != 'undefined' && !window.opera) + arr = new Int32Array(size); + else + arr = new Array(size); + for (var i=0;i<size;i++) + arr[i] = 0; + return arr; +} +function CreateUIntArray(size) +{ + var arr = null; + if (typeof(Uint32Array) != 'undefined' && !window.opera) + arr = new Uint32Array(size); + else + arr = new Array(size); + for (var i=0;i<size;i++) + arr[i] = 0; + return arr; +} +function CreateCharArray(size) +{ + var arr = null; + if (typeof(Int8Array) != 'undefined' && !window.opera) + arr = new Int8Array(size); + else + arr = new Array(size); + for (var i=0;i<size;i++) + arr[i] = 0; + return arr; +} +function CreateNullArray(size) +{ + var arr = new Array(size); + for (var i=0;i<size;i++) + arr[i] = null; + return arr; +} +function TWorker() +{ + this.ex = 0; + this.ey = 0; + + this.min_ex = 0; + this.max_ex = 0; + this.min_ey = 0; + this.max_ey = 0; + + this.count_ex = 0; + this.count_ey = 0; + + this.area = 0; + this.cover = 0; + this.invalid = 0; + + this.max_cells = 0; + this.num_cells = 0; + + this.cx = 0; + this.cy = 0; + this.x = 0; + this.y = 0; + + this.last_ey = 0; + + this.bez_stack_x = CreateIntArray(97); + this.bez_stack_y = CreateIntArray(97); + this.lev_stack = CreateIntArray(32); + + this.outline = null; + this.target = null; + this.clip_box = new FT_BBox(); + + this.gray_spans = new Array(32); + for (var i=0;i<32;i++) + this.gray_spans[i] = new FT_Span(); + + this.num_gray_spans = 0; + + this.render_span = null; + + this.render_span_data = null; + this.span_y = 0; + + this.band_size = 0; + this.band_shoot = 0; + + this.cell_x = null; + this.cell_cover = null; + this.cell_area = null; + this.cell_next = null; + this.buffer_size = 1024; + + this.ycells = CreateIntArray(this.buffer_size); + this.ycount = 0; + + this.raster_memory = raster_memory; +} + +function gray_init_cells(worker, raster) +{ + worker.cell_x = raster.cell_x; + worker.cell_cover = raster.cell_cover; + worker.cell_area = raster.cell_area; + worker.cell_next = raster.cell_next; + worker.buffer_size = 1024; + + worker.max_cells = 0; + worker.num_cells = 0; + worker.area = 0; + worker.cover = 0; + worker.invalid = 1; +} + +function gray_compute_cbox(worker) +{ + var outline = worker.outline; + var p = outline.points; + var c = outline.n_points; + + if ( c <= 0 ) + { + worker.min_ex = worker.max_ex = 0; + worker.min_ey = worker.max_ey = 0; + return; + } + + worker.min_ex = worker.max_ex = p[0].x; + worker.min_ey = worker.max_ey = p[0].y; + + for (var i = 1; i < c; i++) + { + var x = p[i].x; + var y = p[i].y; + + if ( x < worker.min_ex ) worker.min_ex = x; + if ( x > worker.max_ex ) worker.max_ex = x; + if ( y < worker.min_ey ) worker.min_ey = y; + if ( y > worker.max_ey ) worker.max_ey = y; + } + + /* truncate the bounding box to integer pixels */ + worker.min_ex = worker.min_ex >> 6; + worker.min_ey = worker.min_ey >> 6; + worker.max_ex = ( worker.max_ex + 63 ) >> 6; + worker.max_ey = ( worker.max_ey + 63 ) >> 6; +} + +function TBand() +{ + this.min = 0; + this.max = 0; +} + +function gray_find_cell(ras) +{ + var x = ras.ex; + + if ( x > ras.count_ex ) + x = ras.count_ex; + + var pcell = ras.ey; + var cell = ras.ycells[pcell]; + + var bis_y = 1; + for (;;) + { + if (cell == -1 || ras.cell_x[cell] > x) + break; + + if (ras.cell_x[cell] == x) + return cell; + + bis_y = 0; + pcell = cell; + cell = ras.cell_next[cell]; + } + + if (ras.num_cells >= ras.max_cells) + return -1; + + var oldcell = cell; + + cell = ras.num_cells++; + ras.cell_x[cell] = x; + ras.cell_area[cell] = 0; + ras.cell_cover[cell] = 0; + ras.cell_next[cell] = oldcell; + + if (1 == bis_y) + ras.ycells[pcell] = cell; + else + ras.cell_next[pcell] = cell; + return cell; +} + +function gray_record_cell(ras) +{ + if (0 == ras.invalid && ((ras.area | ras.cover) != 0)) + { + var cell = gray_find_cell(ras); + if (-1 == cell) + return FT_Common.ErrorLongJump; + + ras.cell_area[cell] += ras.area; + ras.cell_cover[cell] += ras.cover; + } + return 0; +} + +function gray_set_cell(ras, ex, ey) +{ + ey -= ras.min_ey; + + if ( ex > ras.max_ex ) + ex = ras.max_ex; + + ex -= ras.min_ex; + if ( ex < 0 ) + ex = -1; + + /* are we moving to a different cell ? */ + if ( ex != ras.ex || ey != ras.ey ) + { + /* record the current one if it is valid */ + if (0 == ras.invalid) + { + var err = gray_record_cell(ras); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + } + + ras.area = 0; + ras.cover = 0; + } + + ras.ex = ex; + ras.ey = ey; + + var _ey = ey >= 0 ? ey : ey + FT_Common.a_i; + var _cy = ras.count_ey >= 0 ? ras.count_ey : ras.count_ey + FT_Common.a_i; + + ras.invalid = (_ey >= _cy || ex >= ras.count_ex) ? 1 : 0; + return 0; +} + +function gray_start_cell(ras, ex, ey) +{ + if (ex > ras.max_ex) + ex = ras.max_ex; + + if (ex < ras.min_ex) + ex = (ras.min_ex - 1); + + ras.area = 0; + ras.cover = 0; + ras.ex = ex - ras.min_ex; + ras.ey = ey - ras.min_ey; + ras.last_ey = ey << 8; + ras.invalid = 0; + + return gray_set_cell(ras, ex, ey); +} + +function gray_render_line(ras, to_x, to_y) +{ + var ey1, ey2, fy1, fy2, mod; + var dx, dy, x, x2; + var p, first; + var delta, rem, lift, incr; + + ey1 = (ras.last_ey >> 8); + ey2 = (to_y >> 8); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */ + fy1 = (ras.y - ras.last_ey); + fy2 = (to_y - (ey2 << 8)); + + dx = to_x - ras.x; + dy = to_y - ras.y; + + var min = ey1; + var max = ey2; + + if (ey1 > ey2) + { + min = ey2; + max = ey1; + } + if (min >= ras.max_ey || max < ras.min_ey) + { + ras.x = to_x; + ras.y = to_y; + ras.last_ey = ey2 << 8; + return 0; + } + + var err = 0; + /* everything is on a single scanline */ + if (ey1 == ey2) + { + err = gray_render_scanline(ras, ey1, ras.x, fy1, to_x, fy2); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + ras.x = to_x; + ras.y = to_y; + ras.last_ey = ey2 << 8; + return 0; + } + + /* vertical line - avoid calling gray_render_scanline */ + incr = 1; + + if (dx == 0) + { + var ex = ras.x >> 8; + var two_fx = ((ras.x - (ex << 8)) << 1); + var area; + + first = 256; + if (dy < 0) + { + first = 0; + incr = -1; + } + + delta = (first - fy1); + ras.area += (two_fx * delta); + ras.cover += delta; + ey1 += incr; + + err = gray_set_cell(ras, ex, ey1); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + + delta = (first + first - 256); + area = two_fx * delta; + while (ey1 != ey2) + { + ras.area += area; + ras.cover += delta; + ey1 += incr; + + err = gray_set_cell(ras, ex, ey1); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + } + + delta = (fy2 - 256 + first); + ras.area += (two_fx * delta); + ras.cover += delta; + + ras.x = to_x; + ras.y = to_y; + ras.last_ey = ey2 << 8; + return 0; + } + + /* ok, we have to render several scanlines */ + p = (256 - fy1) * dx; + first = 256; + incr = 1; + + if (dy < 0) + { + p = fy1 * dx; + first = 0; + incr = -1; + dy = -dy; + } + + delta = parseInt(p / dy); + mod = (p % dy); + if (mod < 0) + { + delta--; + mod += dy; + } + + x = ras.x + delta; + err = gray_render_scanline(ras, ey1, ras.x, fy1, x, first); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + + ey1 += incr; + err = gray_set_cell(ras, x >> 8, ey1); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + + if (ey1 != ey2) + { + p = 256 * dx; + lift = parseInt(p / dy); + rem = (p % dy); + if (rem < 0) + { + lift--; + rem += dy; + } + mod -= dy; + + while (ey1 != ey2) + { + delta = lift; + mod += rem; + if (mod >= 0) + { + mod -= dy; + delta++; + } + + x2 = x + delta; + err = gray_render_scanline(ras, ey1, x, 256 - first, x2, first); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + x = x2; + + ey1 += incr; + err = gray_set_cell(ras, x >> 8, ey1); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + } + } + + err = gray_render_scanline(ras, ey1, x, 256 - first, to_x, fy2); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + + ras.x = to_x; + ras.y = to_y; + ras.last_ey = (ey2 << 8); + return 0; +} + +function gray_split_conic(bx,by,base) +{ + var a,b; + bx[base+4] = bx[base+2]; + b = bx[base+1]; + a=bx[base+3] = parseInt((bx[base+2]+b)/2); + b=bx[base+1] = parseInt((bx[base]+b)/2); + bx[base+2] = parseInt((a+b)/2); + + by[base+4] = by[base+2]; + b = by[base+1]; + a=by[base+3] = parseInt((by[base+2]+b)/2); + b=by[base+1] = parseInt((by[base]+b)/2); + by[base+2] = parseInt((a+b)/2); +} + +function gray_render_conic(ras, control, to) +{ + var dx, dy; + var min, max, y; + var top, level; + var arc = 0; + + var arcx = ras.bez_stack_x; + var arcy = ras.bez_stack_y; + + arcx[arc] = (to.x << 2); + arcy[arc] = (to.y << 2); + arcx[arc+1] = (control.x << 2); + arcy[arc+1] = (control.y << 2); + arcx[arc+2] = ras.x; + arcy[arc+2] = ras.y; + top = 0; + + dx = Math.abs(arcx[arc+2] + arcx[arc] - 2*arcx[arc+1]); + dy = Math.abs(arcy[arc+2] + arcy[arc] - 2*arcy[arc+1]); + if (dx < dy) + dx = dy; + + if (dx < 64) + { + return gray_render_line(ras, arcx[arc], arcy[arc]); + } + + /* short-cut the arc that crosses the current band */ + min = max = arcy[arc]; + + y = arcy[arc+1]; + if (y < min) min = y; + if (y > max) max = y; + + y = arcy[arc+2]; + if (y < min) min = y; + if (y > max) max = y; + + if (((min >> 8) >= ras.max_ey) || ((max >> 8) < ras.min_ey)) + { + return gray_render_line(ras, arcx[arc], arcy[arc]); + } + + level = 0; + do + { + dx >>= 2; + level++; + } while (dx > 64); + + var levels = ras.lev_stack; + levels[0] = level; + + var err = 0; + do + { + level = levels[top]; + if (level > 0) + { + gray_split_conic(arcx, arcy, arc); + arc += 2; + top++; + levels[top] = levels[top - 1] = level - 1; + continue; + } + + err = gray_render_line(ras, arcx[arc], arcy[arc]); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + top--; + arc -= 2; + + } + while (top >= 0); + return 0; +} + +function gray_split_cubic(bx,by,base) +{ + var a,b,c,d; + bx[base+6] = bx[base+3]; + c = bx[base+1]; + d = bx[base+2]; + bx[base+1] = a = parseInt((bx[base]+c)/2); + bx[base+5] = b = parseInt((bx[base+3]+d)/2); + c = parseInt((c+d)/2); + bx[base+2] = a = parseInt((a+c)/2); + bx[base+4] = b = parseInt((b+c)/2); + bx[base+3] = parseInt((a+b)/2); + + by[base+6] = by[base+3]; + c = by[base+1]; + d = by[base+2]; + by[base+1] = a = parseInt((by[base]+c)/2); + by[base+5] = b = parseInt((by[base+3]+d)/2); + c = parseInt((c+d)/2); + by[base+2] = a = parseInt((a+c)/2); + by[base+4] = b = parseInt((b+c)/2); + by[base+3] = parseInt((a+b)/2); +} + +function gray_render_cubic(ras, control1, control2, to) +{ + var min, max, y; + + var arcx = ras.bez_stack_x; + var arcy = ras.bez_stack_y; + arcx[0] = to.x << 2; + arcy[0] = to.y << 2; + arcx[1] = control2.x << 2; + arcy[1] = control2.y << 2; + arcx[2] = control1.x << 2; + arcy[2] = control1.y << 2; + arcx[3] = ras.x; + arcy[3] = ras.y; + + var arc = 0; + + /* Short-cut the arc that crosses the current band. */ + min = max = arcy[0]; + + y = arcy[arc+1]; + if (y<min) + min = y; + if (y>max) + max = y; + + y = arcy[arc+2]; + if (y<min) + min = y; + if (y>max) + max = y; + + y = arcy[arc+3]; + if (y<min) + min = y; + if (y>max) + max = y; + + var err = 0; + if ((min >> 8) >= ras.max_ey || (max >> 8) < ras.min_ey) + { + return gray_render_line(ras, arcx[arc], arcy[arc]); + } + + for (;;) + { + var dx, dy, dx_, dy_; + var dx1, dy1, dx2, dy2; + var L, s, s_limit; + + dx = arcx[arc+3] - arcx[arc]; + dy = arcy[arc+3] - arcy[arc]; + + dx_ = Math.abs(dx); + dy_ = Math.abs(dy); + + L = ((dx_ > dy_) ? (236 * dx_ + 97 * dy_) : (97 * dx_ + 236 * dy_)) >>> 8; + + if ( L > 32767 ) + { + gray_split_cubic(arcx,arcy,arc); + arc += 3; + continue; + } + + s_limit = L * 42; + + dx1 = arcx[arc+1] - arcx[arc]; + dy1 = arcy[arc+1] - arcy[arc]; + s = Math.abs(dy*dx1 - dx*dy1); + + if (s>s_limit) + { + gray_split_cubic(arcx,arcy,arc); + arc += 3; + continue; + } + + dx2 = arcx[arc+2] - arcx[arc]; + dy2 = arcy[arc+2] - arcy[arc]; + s = Math.abs(dy*dx2 - dx*dy2); + + if (s>s_limit) + { + gray_split_cubic(arcx,arcy,arc); + arc += 3; + continue; + } + + if (((dy*dy1 + dx*dx1) < 0) || ((dy*dy2 + dx*dx2) < 0) || + ((dy*(arcy[arc+3]-arcy[arc+1]) + dx*(arcx[arc+3]-arcx[arc+1])) < 0) || + ((dy*(arcy[arc+3]-arcy[arc+2]) + dx*(arcx[arc+3]-arcx[arc+2])) < 0)) + { + gray_split_cubic(arcx,arcy,arc); + arc += 3; + continue; + } + + /* No reason to split. */ + err = gray_render_line(ras, arcx[arc], arcy[arc]); + if (err == FT_Common.ErrorLongJump) + return FT_Common.ErrorLongJump; + + if (arc == 0) + return 0; + + arc -= 3; + } + return 0; +} + +function gray_render_scanline(ras, ey, x1, y1, x2, y2) +{ + var ex1, ex2, fx1, fx2, delta, mod, lift, rem; + var p, first, dx; + var incr; + + dx = x2 - x1; + + ex1 = (x1 >> 8); + ex2 = (x2 >> 8); + fx1 = x1 - (ex1 << 8); + fx2 = x2 - (ex2 << 8); + + /* trivial case. Happens often */ + if (y1 == y2) + { + return gray_set_cell(ras, ex2, ey); + } + + /* everything is located in a single cell. That is easy! */ + if (ex1 == ex2) + { + delta = y2 - y1; + ras.area += ((fx1+fx2)*delta); + ras.cover += delta; + return 0; + } + + /* ok, we'll have to render a run of adjacent cells on the same scanline */ + p = (256 - fx1)*(y2-y1); + first = 256; + incr = 1; + + if (dx < 0) + { + p = fx1*(y2-y1); + first = 0; + incr = -1; + dx = -dx; + } + + delta = parseInt(p/dx); + mod = p%dx; + if (mod < 0) + { + delta--; + mod += dx; + } + + ras.area += ((fx1+first)*delta); + ras.cover += delta; + + ex1 += incr; + var err = gray_set_cell(ras, ex1, ey); + if (err == FT_Common.ErrorLongJump) + return err; + y1 += delta; + + if (ex1 != ex2) + { + p = 256 * (y2 - y1 + delta); + lift = parseInt(p/dx); + rem = (p%dx); + if (rem < 0) + { + lift--; + rem += dx; + } + + mod -= dx; + + while (ex1 != ex2) + { + delta = lift; + mod += rem; + if (mod >= 0) + { + mod -= dx; + delta++; + } + + ras.area += (256*delta); + ras.cover += delta; + y1 += delta; + ex1 += incr; + err = gray_set_cell(ras, ex1, ey); + if (err == FT_Common.ErrorLongJump) + return err; + } + } + + delta = y2 - y1; + ras.area += ((fx2 + 256 - first)*delta); + ras.cover += delta; + return 0; +} + +function _gray_render_span(y, count, spans, span_start, worker) +{ + var map = worker.target; + var pixels = map.buffer.data; + var p = -y * map.pitch; + if (map.pitch >= 0) + p += ((map.rows-1)*map.pitch); + + var s = span_start; + for (;count > 0;count--,s++) + { + var coverage = spans[s].coverage; + + if (coverage != 0) + { + var len = spans[s].len; + var q = spans[s].x + p; + for (;len>0;len--) + pixels[q++] = coverage; + } + } +} +function gray_render_span(y, count, spans, span_start, worker) +{ + var map = worker.raster_memory; + var pixels = map.m_oBuffer.data; + var p = -y * map.pitch; + if (worker.target.pitch >= 0) + p += ((worker.target.rows-1)*map.pitch); + + p+=3; + + var s = span_start; + for (;count > 0;count--,s++) + { + var coverage = spans[s].coverage; + + if (coverage != 0) + { + var len = spans[s].len; + var q = (spans[s].x * 4) + p; + for (;len>0;len--,q+=4) + pixels[q] = coverage; + } + } +} + +function gray_hline(ras, x, y, area, acount) +{ + var spans = ras.gray_spans; + var span_i = 0; + var span; + + var count; + + var coverage = (area >> 9); + /* use range 0..256 */ + if (coverage < 0) + coverage = -coverage; + + if ((ras.outline.flags & FT_Common.FT_OUTLINE_EVEN_ODD_FILL) != 0) + { + coverage &= 511; + if (coverage > 256) + coverage = 512 - coverage; + else if (coverage == 256) + coverage = 255; + } + else + { + if ( coverage >= 256 ) + coverage = 255; + } + + y += ras.min_ey; + x += ras.min_ex; + + if (x >= 32767) + x = 32767; + + /* FT_Span.y is an integer, so limit our coordinates appropriately */ + if (y >= 2147483647) + y = 2147483647; + + if (coverage != 0) + { + /* see whether we can add this span to the current list */ + count = ras.num_gray_spans; + span_i = count - 1; + span = spans[span_i]; + if ((count > 0) && (ras.span_y == y) && ((span.x + span.len) == x) && (span.coverage == coverage)) + { + span.len = (span.len + acount) & 0xFFFF; + return; + } + + if (ras.span_y != y || count >= 32) + { + if (ras.render_span && count > 0) + ras.render_span(ras.span_y,count,ras.gray_spans,0,ras.render_span_data); + + ras.num_gray_spans = 0; + ras.span_y = y; + + count = 0; + span_i = 0; + span = spans[0]; + } + else + { + span_i++; + span = spans[span_i]; + } + + /* add a gray span to the current list */ + span.x = x; + span.len = acount & 0xFFFF; + span.coverage = coverage & 0xFF; + + ras.num_gray_spans++; + } +} + +function gray_sweep(ras, target) +{ + if (ras.num_cells == 0) + return; + + ras.num_gray_spans = 0; + + var _next = ras.cell_next; + var _cover = ras.cell_cover; + var _area = ras.cell_area; + var _x = ras.cell_x; + + for (var yindex = 0; yindex < ras.ycount; yindex++) + { + var cell = ras.ycells[yindex]; + var cover = 0; + var x = 0; + + for (; cell != -1; cell = _next[cell]) + { + if (_x[cell] > x && cover != 0) + gray_hline(ras, x, yindex, cover * 512, _x[cell] - x); + + cover += _cover[cell]; + var area = cover * 512 - _area[cell]; + + if (area != 0 && _x[cell] >= 0) + gray_hline(ras, _x[cell], yindex, area, 1); + + x = _x[cell] + 1; + } + + if ( cover != 0 ) + gray_hline(ras, x, yindex, cover * 512, ras.count_ex - x); + } + + if (ras.render_span && ras.num_gray_spans > 0) + ras.render_span(ras.span_y, ras.num_gray_spans, ras.gray_spans, 0, ras.render_span_data); +} + +function __grays_raster_render(raster, params) +{ + var outline = params.source; + var target_map = params.target; + + if (raster == null) + return FT_Common.FT_Err_Invalid_Argument; + + if (outline == null) + return FT_Common.FT_Err_Invalid_Outline; + + /* return immediately if the outline is empty */ + if (outline.n_points == 0 || outline.n_contours <= 0) + return 0; + + if (outline.contours == null || outline.points == null) + return FT_Common.FT_Err_Invalid_Outline; + + if (outline.n_points != outline.contours[outline.n_contours - 1] + 1) + return FT_Common.FT_Err_Invalid_Outline; + + var worker = raster.worker; + + /* if direct mode is not set, we must have a target bitmap */ + if (0 == (params.flags & FT_Common.FT_RASTER_FLAG_DIRECT)) + { + if (target_map == null) + return FT_Common.FT_Err_Invalid_Argument; + + /* nothing to do */ + if (0 == target_map.width || 0 == target_map.rows) + return 0; + + if (null == target_map.buffer && null == worker.raster_memory) + return FT_Common.FT_Err_Invalid_Argument; + } + + /* this version does not support monochrome rendering */ + if (0 == (params.flags & FT_Common.FT_RASTER_FLAG_AA)) + return FT_Common.FT_Err_Invalid_Argument; + + /* compute clipping box */ + if (0 == (params.flags & FT_Common.FT_RASTER_FLAG_DIRECT)) + { + /* compute clip box from target pixmap */ + worker.clip_box.xMin = 0; + worker.clip_box.yMin = 0; + worker.clip_box.xMax = target_map.width; + worker.clip_box.yMax = target_map.rows; + } + else if (params.flags & FT_Common.FT_RASTER_FLAG_CLIP) + { + worker.clip_box.xMin = params.clip_box.xMin; + worker.clip_box.yMin = params.clip_box.yMin; + worker.clip_box.xMax = params.clip_box.xMax; + worker.clip_box.yMax = params.clip_box.yMax; + } + else + { + worker.clip_box.xMin = -32768; + worker.clip_box.yMin = -32768; + worker.clip_box.xMax = 32767; + worker.clip_box.yMax = 32767; + } + + gray_init_cells(worker, raster); + + worker.outline = outline; + worker.num_cells = 0; + worker.invalid = 1; + worker.band_size = raster.band_size; + worker.num_gray_spans = 0; + + if (0 != (params.flags & FT_Common.FT_RASTER_FLAG_DIRECT)) + { + worker.render_span = params.gray_spans; + worker.render_span_data = params.user; + } + else + { + worker.target = target_map; + worker.render_span = gray_render_span; + worker.render_span_data = worker; + } + + if (worker.raster_memory != null) + worker.raster_memory.CheckSize(target_map.width, target_map.rows); + + return __gray_convert_glyph(worker); +} +function __gray_convert_glyph(ras) +{ + var bands = m_bands; + var band = 0; + var n = 0; + var num_bands = 0; + var min = 0; + var max = 0; + var max_y = 0; + var clip = null; + + gray_compute_cbox(ras); + + /* clip to target bitmap, exit if nothing to do */ + clip = ras.clip_box; + + if (ras.max_ex <= clip.xMin || ras.min_ex >= clip.xMax || + ras.max_ey <= clip.yMin || ras.min_ey >= clip.yMax ) + return 0; + + if (ras.min_ex < clip.xMin) ras.min_ex = clip.xMin; + if (ras.min_ey < clip.yMin) ras.min_ey = clip.yMin; + + if (ras.max_ex > clip.xMax ) ras.max_ex = clip.xMax; + if (ras.max_ey > clip.yMax ) ras.max_ey = clip.yMax; + + ras.count_ex = ras.max_ex - ras.min_ex; + ras.count_ey = ras.max_ey - ras.min_ey; + + /* set up vertical bands */ + num_bands = parseInt((ras.max_ey - ras.min_ey) / ras.band_size); + if (num_bands == 0) + num_bands = 1; + if (num_bands >= 39) + num_bands = 39; + + ras.band_shoot = 0; + + min = ras.min_ey; + max_y = ras.max_ey; + + for (n = 0; n < num_bands; n++, min = max) + { + max = min + ras.band_size; + if ((n == num_bands - 1) || (max > max_y)) + max = max_y; + + bands[0].min = min; + bands[0].max = max; + band = 0; + + while (band >= 0) + { + var isReduceBands = 0; + + var bottom, top, middle; + var error = 0; + var _band = bands[band]; + + var cells_max; + + ras.ycount = _band.max - _band.min; + if (ras.ycount >= ras.buffer_size) + isReduceBands = 1; + + if (0 == isReduceBands) + { + ras.max_cells = ras.buffer_size; + if (ras.max_cells < 2) + { + // такого быть не может из-за лишнего килобайтика) + isReduceBands = 1; + } + + if (0 == isReduceBands) + { + for (var yindex = 0; yindex < ras.ycount; yindex++) + ras.ycells[yindex] = -1; + + ras.num_cells = 0; + ras.invalid = 1; + ras.min_ey = _band.min; + ras.max_ey = _band.max; + ras.count_ey = _band.max - _band.min; + + error = __gray_convert_glyph_inner(ras); + + if (0 == error) + { + gray_sweep(ras, ras.target); + band--; + continue; + } + else if (error != FT_Common.FT_Err_Raster_Overflow) + return 1; + } + } + + /* render pool overflow; we will reduce the render band by half */ + bottom = _band.min; + top = _band.max; + middle = bottom + ((top - bottom) >> 1); + + /* This is too complex for a single scanline; there must */ + /* be some problems. */ + if (middle == bottom) + return 1; + + if (bottom-top >= ras.band_size) + ras.band_shoot++; + + + bands[band+1].min = bottom; + bands[band+1].max = middle; + bands[band].min = middle; + bands[band].max = top; + + band++; + } + } + + if (ras.band_shoot > 8 && ras.band_size > 16) + ras.band_size = parseInt(ras.band_size / 2); + + return 0; +} + +function __gray_convert_glyph_inner(ras) +{ + var error1 = FT_Outline_Decompose(ras.outline, ft_outline_funcs_gray, ras); + + if (FT_Common.ErrorLongJump == error1) + return FT_Common.FT_Err_Raster_Overflow; + + var error2 = gray_record_cell(ras); + if (FT_Common.ErrorLongJump == error2) + return FT_Common.FT_Err_Raster_Overflow; + + return error1; +} + +var m_bands = new Array(40); +for (var i = 0; i < 40; i++) + m_bands[i] = new TBand(); + +function FT_Grays_Raster() +{ + // -------- + this.glyph_format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + + this.raster_new = function(memory, raster) + { + raster.memory = memory; + return 0; + } + this.raster_reset = function(raster, pool_base, pool_size) + { + raster.buffer_size = 1024; + raster.band_size = 117; // Ñделал как в Ñи-шной либе, чтобы было удобно дебажитьÑÑ. + // а вообще - нужно так: (мы памÑти выделÑем больше на 1kb (под указатели ycells)) + //raster.band_size = 128; + } + this.raster_set_mode = null; + this.raster_render = __grays_raster_render; + this.raster_done = function() + { + } +} +// -------------------------------------------------------------------- + +function FT_Smooth_Renderer_Class() +{ + this.flags = FT_Common.FT_MODULE_RENDERER; + this.name = "smooth"; + this.version = 0x10000; + this.requires = 0x20000; + + this.module_interface = null; + + this.init = ft_smooth_init; + this.done = null; + this.get_interface = null; + + this.glyph_format = FT_Common.FT_GLYPH_FORMAT_OUTLINE; + + this.render_glyph = ft_smooth_render; + this.transform_glyph = ft_smooth_transform; + this.get_glyph_cbox = ft_smooth_get_cbox; + this.set_mode = ft_smooth_set_mode; + + this.raster_class = new FT_Grays_Raster(); +} +function FT_Smooth_Renderer() +{ + this.clazz = new FT_Smooth_Renderer_Class(); + this.library = null; + this.memory = null; + this.generic = null; + + this.glyph_format = 0; + this.glyph_class = new FT_Glyph_Class(); + this.raster = null; + + this.raster_render = null; + this.render = null; +} + +function create_renderer_smooth_module(library) +{ + var ren1_mod = new FT_Smooth_Renderer(); + ren1_mod.clazz = new FT_Smooth_Renderer_Class(); + ren1_mod.clazz.render_glyph = ft_smooth_render; + + ren1_mod.library = library; + ren1_mod.memory = library.Memory; + ren1_mod.generic = null; + + return ren1_mod; +} +function create_renderer_smooth_lcd_module(library) +{ + var ren1_mod = new FT_Smooth_Renderer(); + ren1_mod.clazz = new FT_Smooth_Renderer_Class(); + ren1_mod.clazz.render_glyph = ft_smooth_render_lcd; + + ren1_mod.library = library; + ren1_mod.memory = library.Memory; + ren1_mod.generic = null; + + return ren1_mod; +} +function create_renderer_smooth_lcd_v_module(library) +{ + var ren1_mod = new FT_Smooth_Renderer(); + ren1_mod.clazz = new FT_Smooth_Renderer_Class(); + ren1_mod.clazz.render_glyph = ft_smooth_render_lcd_v; + + ren1_mod.library = library; + ren1_mod.memory = library.Memory; + ren1_mod.generic = null; + + return ren1_mod; +} + +function ft_smooth_init(render) +{ + render.clazz.raster_class.raster_reset(render.raster, render.library.raster_pool, render.library.raster_pool_size); + return 0; +} + +function ft_smooth_set_mode(render, mode_tag, data) +{ + return render.clazz.raster_class.raster_set_mode(render.raster, mode_tag, data); +} + +function ft_smooth_transform(render, slot, matrix, delta) +{ + if (slot.format != render.glyph_format) + return FT_Common.FT_Err_Invalid_Argument; + + if (matrix) + FT_Outline_Transform(slot.outline, matrix); + + if (delta) + FT_Outline_Translate(slot.outline, delta.x, delta.y); + + return 0; +} + +function ft_smooth_get_cbox(render, slot, cbox) +{ + cbox.xMin = 0; + cbox.yMin = 0; + cbox.xMax = 0; + cbox.yMax = 0; + + if (slot.format == render.glyph_format) + FT_Outline_Get_CBox(slot.outline, cbox); +} + +function ft_smooth_render(render, slot, mode, origin) +{ + if (mode == FT_Common.FT_RENDER_MODE_LIGHT) + mode = FT_Common.FT_RENDER_MODE_NORMAL; + + return ft_smooth_render_generic(render, slot, mode, origin, FT_Common.FT_RENDER_MODE_NORMAL); +} + +function ft_smooth_render_lcd(render, slot, mode, origin) +{ + var error = ft_smooth_render_generic(render, slot, mode, origin, FT_Common.FT_RENDER_MODE_LCD); + if (error == 0) + slot.bitmap.pixel_mode = FT_Common.FT_PIXEL_MODE_LCD; + + return error; +} + +function ft_smooth_render_lcd_v(render, slot, mode, origin) +{ + var error = ft_smooth_render_generic(render, slot, mode, origin, FT_Common.FT_RENDER_MODE_LCD_V); + if (error == 0) + slot.bitmap.pixel_mode = FT_Common.FT_PIXEL_MODE_LCD_V; + + return error; +} + +function ft_smooth_render_generic(render, slot, mode, origin, required_mode) +{ + var error = 0; + var outline = null; + var cbox = new FT_BBox(); + var width, height, pitch; + + //#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + var height_org, width_org; + //#endif + + var hmul = (mode == FT_Common.FT_RENDER_MODE_LCD) ? 1 : 0; + var vmul = (mode == FT_Common.FT_RENDER_MODE_LCD_V) ? 1 : 0; + var x_shift, y_shift, x_left, y_top; + + var params = new FT_Raster_Params(); + + /* check glyph image format */ + if (slot.format != render.glyph_format) + return FT_Common.FT_Err_Invalid_Argument; + + /* check mode */ + if (mode != required_mode) + return FT_Common.FT_Err_Cannot_Render_Glyph; + + outline = slot.outline; + + /* translate the outline to the new origin if needed */ + if (origin != null) + FT_Outline_Translate(outline, origin.x, origin.y); + + /* compute the control box, and grid fit it */ + FT_Outline_Get_CBox(outline, cbox); + + cbox.xMin = (cbox.xMin & ~63); + cbox.yMin = (cbox.yMin & ~63); + cbox.xMax = ((cbox.xMax+63) & ~63); + cbox.yMax = ((cbox.yMax+63) & ~63); + + if (cbox.xMin < 0 && cbox.xMax > 2147483647 + cbox.xMin) + { + if (outline && origin) + FT_Outline_Translate(outline, -origin.x, -origin.y); + return FT_Common.FT_Err_Raster_Overflow; + } + else + width = ((cbox.xMax - cbox.xMin) >>> 6); + + if ( cbox.yMin < 0 && cbox.yMax > 2147483647 + cbox.yMin ) + { + if ( outline && origin ) + FT_Outline_Translate( outline, -origin.x, -origin.y ); + return FT_Common.FT_Err_Raster_Overflow; + } + else + height = ((cbox.yMax - cbox.yMin) >>> 6); + + var bitmap = slot.bitmap; + var memory = render.memory; + + //#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + width_org = width; + height_org = height; + //#endif + + /* release old bitmap buffer */ + if (slot.internal.flags & FT_Common.FT_GLYPH_OWN_BITMAP) + { + delete bitmap.buffer; + slot.internal.flags &= ~FT_Common.FT_GLYPH_OWN_BITMAP; + } + + /* allocate new one */ + pitch = width; + if (hmul == 1) + { + width = width * 3; + pitch = (width + 3) & ~3; + } + + if (vmul == 1) + height *= 3; + + x_shift = cbox.xMin; + y_shift = cbox.yMin; + x_left = cbox.xMin >> 6; + y_top = cbox.yMax >> 6; + + //#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + /* + if (slot.library.lcd_filter_func) + { + var extra = slot.library.lcd_extra; + if (hmul == 1) + { + x_shift -= 64 * (extra >>> 1); + width += 3 * extra; + pitch = (width + 3) & ~3; + x_left -= (extra >>> 1); + } + if (vmul == 1) + { + y_shift -= 64 * (extra >>> 1); + height += 3 * extra; + y_top += (extra >>> 1); + } + } + */ + //#endif + + if (width > 0x7FFF || height > 0x7FFF) + { + if (outline && origin) + FT_Outline_Translate(outline, -origin.x, -origin.y); + return FT_Common.FT_Err_Raster_Overflow; + } + + bitmap.pixel_mode = FT_Common.FT_PIXEL_MODE_GRAY; + bitmap.num_grays = 256; + bitmap.width = width; + bitmap.rows = height; + bitmap.pitch = pitch; + + if (bitmap.width > 1000 || bitmap.height > 1000) + return 130; + + /* translate outline to render it into the bitmap */ + FT_Outline_Translate(outline, -x_shift, -y_shift); + var memory = slot.library.Memory; + + //bitmap.buffer = memory.Alloc(pitch * height); + + slot.internal.flags |= FT_Common.FT_GLYPH_OWN_BITMAP; + + /* set up parameters */ + params.target = bitmap; + params.source = outline; + params.flags = FT_Common.FT_RASTER_FLAG_AA; + + //#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + /* + var points = outline.points; + var count = outline.n_points; + + if (hmul == 1) + for (var i = 0; i < count; i++) + points[i].x = points[i].x * 3; + + if (vmul == 1) + for (var i = 0; i < count; i++) + points[i].y = points[i].y * 3; + error = render.raster_render(render.raster, params); + if (hmul == 1) + for (var i = 0; i < count; i++) + points[i].x = parseInt(points[i].x / 3); + + if (vmul == 1) + for (var i = 0; i < count; i++) + points[i].y = parseInt(points[i].y / 3); + + if (slot.library.lcd_filter_func) + slot.library.lcd_filter_func(bitmap, mode, slot.library); + */ + + //#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + error = render.raster_render(render.raster, params); + if (hmul == 1) + { + var pixels = bitmap.buffer.data; + var line = 0; + for (var hh = height_org; hh > 0; hh--, line += pitch) + { + var end = line + width; + for (var xx = width_org; xx > 0; xx--) + { + var pixel = pixels[line+xx-1]; + + pixels[end-3] = pixel; + pixels[end-2] = pixel; + pixels[end-1] = pixel; + end -= 3; + } + } + } + if (vmul == 1) + { + var pixels = bitmap.buffer.data; + var read = (height - height_org) * pitch; + var write = 0; + var ii = 0; + for (var hh = height_org; hh > 0; hh--) + { + for (ii=0;ii<pitch;ii++) + pixels[write+ii] = pixels[read+ii]; + + write += pitch; + + for (ii=0;ii<pitch;ii++) + pixels[write+ii] = pixels[read+ii]; + + write += pitch; + + for (ii=0;ii<pitch;ii++) + pixels[write+ii] = pixels[read+ii]; + + write += pitch; + read += pitch; + } + } + //#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + + FT_Outline_Translate(outline, x_shift, y_shift); + + if (x_left > 0x7FFFFFFF || y_top > 0x7FFFFFFF) + return FT_Common.FT_Err_Invalid_Pixel_Size; + + if (error == 0) + { + slot.format = FT_Common.FT_GLYPH_FORMAT_BITMAP; + slot.bitmap_left = x_left; + slot.bitmap_top = y_top; + } + + if ( outline && origin ) + FT_Outline_Translate(outline, -origin.x, -origin.y); + + return error; +} \ No newline at end of file diff --git a/Common/FontsFreeType/Private/FreeType/modules/sfnt.js b/Common/FontsFreeType/Private/FreeType/modules/sfnt.js new file mode 100644 index 0000000000000000000000000000000000000000..d1a63c58bcdb63f48b75cea040e01f42ada37d3a --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/modules/sfnt.js @@ -0,0 +1,5530 @@ +/******************************************************************************/ +// bdf +/******************************************************************************/ +function BDF_PropertyRec() +{ + this.type; + this.u; +} + +function tt_face_free_bdf_props(face) +{ + var bdf = face.bdf; + if (bdf.loaded == 1) + { + bdf.table = null; + bdf.table_end = 0; + bdf.strings = null; + bdf.strings_size = 0; + } +} + +function tt_face_load_bdf_props(face, stream) +{ + var bdf = face.bdf; + var error = 0; + + bdf.table = null; + bdf.table_end = 0; + bdf.strings = null; + bdf.strings_size = 0; + bdf.num_strikes = 0; + bdf.loaded = 0; + + var length = tt_face_goto_table(face, FT_Common.TTAG_BDF, stream); + error = FT_Error; + if (error != 0 || length < 8) + return FT_Common.FT_Err_Invalid_Table; + + bdf.table = new CPointer(); + error = stream.ExtractFrame(length, bdf.table); + + if (error != 0) + return FT_Common.FT_Err_Invalid_Table; + + bdf.table_end = length; + + var p = dublicate_pointer(bdf.table); + var version = FT_NEXT_USHORT(p); + var num_strikes = FT_NEXT_USHORT(p); + var strings = FT_NEXT_ULONG (p); + + if (version != 0x0001 || strings < 8 || (strings - 8) / 4 < num_strikes || strings + 1 > length) + { + bdf.table = null; + return FT_Common.FT_Err_Invalid_Table; + } + + bdf.num_strikes = num_strikes; + bdf.strings = new CPointer(); + bdf.strings.data = bdf.table.data; + bdf.strings.pos = bdf.table.pos + strings; + bdf.strings_size = length - strings; + + var count = bdf.num_strikes; + p.pos = bdf.table.pos + 8; + var strike = p.pos + count * 4; + + for ( ; count > 0; count--) + { + p.pos+=2; + var num_items = FT_PEEK_USHORT(p); + + strike += 10 * num_items; + p.pos+=2; + } + + if (strike > bdf.strings) + { + bdf.table = null; + bdf.table_end = 0; + bdf.strings = null; + bdf.strings_size = 0; + bdf.num_strikes = 0; + bdf.loaded = 0; + return FT_Common.FT_Err_Invalid_Table; + } + + bdf.loaded = 1; + return error; +} + +function tt_face_find_bdf_prop(face,property_name,aprop) +{ + var bdf = face.bdf; + var size = face.size; + var error = 0; + + aprop.type = FT_Common.BDF_PROPERTY_TYPE_NONE; + + if (bdf.loaded == 0) + { + error = tt_face_load_bdf_props(face, face.stream); + if (error != 0) + return error; + } + + var count = bdf.num_strikes; + var p = dublicate_pointer(bdf.table); + p.pos += 8; + + var strike = dublicate_pointer(p); + strike.pos += 4 * count; + + error = FT_Common.FT_Err_Invalid_Argument; + + var property_len = property_name.length; + if (size == null || property_len == 0) + return error; + + var is_strike = 0; + for ( ; count > 0; count-- ) + { + var _ppem = FT_NEXT_USHORT(p); + var _count = FT_NEXT_USHORT(p); + + if (_ppem == size.metrics.y_ppem) + { + count = _count; + is_strike = 1; + break; + } + + strike.pos += 10 * _count; + } + if (0 == is_strike) + return error; + + p.pos = strike.pos; + var point = dublicate_pointer(bdf.strings); + for (; count > 0; count--) + { + p.pos+=4; + var type = FT_PEEK_USHORT(p); + p.pos-=4; + + if ((type & 0x10) != 0) + { + var name_offset = FT_PEEK_ULONG(p); + p.pos+=6; + var value = FT_PEEK_ULONG(p); + p.pos-=6; + + point.pos = bdf.strings.pos + name_offset; + if (name_offset < bdf.strings_size && property_len < bdf.strings_size - name_offset && + property_name == FT_PEEK_String1(point,bdf.strings_size-name_offset)) + { + switch ( type & 0x0F ) + { + case 0x00: + case 0x01: + point.pos = bdf.strings.pos + value; + if (value < bdf.strings_size && -1 != ft_memchr(point, 0, bdf.strings_size)) + { + aprop.type = FT_Common.BDF_PROPERTY_TYPE_ATOM; + aprop.u = FT_PEEK_String1(point,bdf.strings_size); + return 0; + } + break; + + case 0x02: + aprop.type = FT_Common.BDF_PROPERTY_TYPE_INTEGER; + aprop.u = ((value > FT_Common.m_i) ? value-FT_Common.a_i : value); + return 0; + case 0x03: + aprop.type = FT_Common.BDF_PROPERTY_TYPE_CARDINAL; + aprop.u = ((value >= 0) ? value : value + FT_Common.m_i); + return 0; + default: + break; + } + } + } + p.pos += 10; + } + + return error; +} + +function sfnt_get_charset_id(face,acharset_encoding,acharset_registry) +{ + var encoding = new BDF_PropertyRec(); + var registry = new BDF_PropertyRec(); + + FT_Error = tt_face_find_bdf_prop(face, "CHARSET_REGISTRY", registry); + if (FT_Error == 0) + { + FT_Error = tt_face_find_bdf_prop(face, "CHARSET_ENCODING", encoding); + if (FT_Error == 0) + { + if (registry.type == BDF_PROPERTY_TYPE_ATOM && encoding.type == BDF_PROPERTY_TYPE_ATOM) + { + return {enc:encoding.u,reg:registry.u}; + } + else + FT_Error = FT_Common.FT_Err_Invalid_Argument; + } + } + + return {enc:"",reg:""}; +} +/******************************************************************************/ +// ttkern +/******************************************************************************/ +function tt_face_load_kern(face, stream) +{ + var error = 0; + var table_size = face.goto_table(face, FT_Common.TTAG_kern, stream); + error = FT_Error; + + if (error != 0) + return error; + + if (table_size < 4) + return FT_Common.FT_Err_Table_Missing; + + face.kern_table = new CPointer(); + error = stream.ExtractFrame(table_size, face.kern_table); + if (error != 0) + return error; + + face.kern_table_size = table_size; + stream.cur = face.kern_table.pos; + var p_limit = stream.cur + table_size; + + stream.cur += 2; // skip version + var num_tables = stream.GetUShort(); + + if (num_tables > 32) + num_tables = 32; + + var avail = 0; + var ordered = 0; + + var nn = 0; + for (; nn < num_tables; nn++) + { + var mask = 1 << nn; + + var p_next = stream.cur; + + if (stream.cur + 6 < p_limit) + break; + + stream.cur += 2; // skip version + var length = stream.GetUShort(); + var coverage = stream.GetUShort(); + + if (length <= 6) + break; + + p_next += length; + + if (p_next > p_limit) + p_next = p_limit; + + if ((coverage & ~8) != 0x0001 || (stream.cur + 8) > p_limit) + { + stream.cur = p_next; + continue; + } + + var num_pairs = stream.GetUShort(); + stream.cur += 6; + + if ((p_next - stream.cur) < (6 * num_pairs)) + num_pairs = parseInt((p_next - stream.cur) / 6); + + avail |= mask; + + if (num_pairs > 0) + { + var count = 0; + var old_pair = stream.GetULong(); + + stream.cur += 2; + + for (count = num_pairs - 1; count > 0; count--) + { + var cur_pair = stream.GetULong(); + if (cur_pair <= old_pair) + break; + + stream.cur += 2; + old_pair = cur_pair; + } + + if (count == 0) + ordered |= mask; + } + + stream.cur = p_next; + } + + face.num_kern_tables = nn; + face.kern_avail_bits = avail; + face.kern_order_bits = ordered; + + return error; +} +function tt_face_done_kern(face) +{ + face.kern_table = null; + face.kern_table_size = 0; + face.num_kern_tables = 0; + face.kern_avail_bits = 0; + face.kern_order_bits = 0; +} +function tt_face_get_kerning(face,left_glyph,right_glyph) +{ + var result = 0; + var count, mask = 1; + var p = dublicate_pointer(face.kern_table); + if (null == p) + return result; + + var p_limit = p.pos + face.kern_table_size; + + p.pos += 4; + mask = 0x0001; + + for (count = face.num_kern_tables; count > 0 && p.pos + 6 <= p_limit; count--, mask <<= 1) + { + if (mask < 0) + mask+=FT_Common.a_i; + var version = FT_NEXT_USHORT( p ); + var length = FT_NEXT_USHORT( p ); + var coverage = FT_NEXT_USHORT( p ); + var value = 0; + + var base = p.pos; + var next = base + length; + + if (next > p_limit) + next = p_limit; + + if ((face.kern_avail_bits & mask) == 0) + { + p.pos = next; + continue; + } + + if (p.pos + 8 > next) + { + p.pos = next; + continue; + } + + var num_pairs = FT_NEXT_USHORT( p ); + p.pos += 6; + + if (( next - p.pos) < 6 * num_pairs) + num_pairs = parseInt((next - p.pos)/6); + + switch (coverage >>> 8) + { + case 0: + { + var key0 = (left_glyph<<16 | right_glyph)&0xFFFFFFFF; + if (key0 < 0) + key0 += FT_Common.a_i; + + if ((face.kern_order_bits & mask) != 0) + { + var min = 0; + var max = num_pairs; + + var q = dublicate_pointer(p); + var is_found = 0; + while ( min < max ) + { + var mid = (min + max) >>> 1; + q.pos = p.pos + 6 * mid; + var key = FT_NEXT_ULONG(q); + + if (key == key0) + { + value = FT_PEEK_SHORT( q ); + if ((coverage & 8) != 0) + result = value; + else + result += value; + p.pos = next; + is_found = 1; + break; + } + if (key < key0) + min = mid + 1; + else + max = mid; + } + if (1 == is_found) + continue; + } + else + { + var is_found = 0; + for (var count2 = num_pairs; count2 > 0; count2--) + { + var key = FT_NEXT_ULONG(p); + + if (key == key0) + { + value = FT_PEEK_SHORT(p); + if ((coverage & 8) != 0) + result = value; + else + result += value; + p.pos = next; + is_found = 1; + break; + } + p.pos += 2; + } + if (is_found == 1) + continue; + } + } + break; + default: + break; + } + p.pos = next; + } + + return result; +} +/******************************************************************************/ +// ttload +/******************************************************************************/ +function tt_face_lookup_table(face, tag) +{ + var count = face.num_tables; + for (var i=0; i<count; i++) + { + var entry = face.dir_tables[i]; + if (entry.Tag == tag && entry.Length != 0) + return entry; + } + return null; +} +function tt_face_goto_table(face, tag, stream) +{ + var length = 0; + var table = tt_face_lookup_table(face, tag); + if (table != null) + { + length = table.Length; + FT_Error = stream.Seek(table.Offset); + return table.Length; + } + FT_Error = FT_Common.FT_Err_Table_Missing; + return 0; +} +function check_table_dir(sfnt, stream) +{ + var error = 0; + var nn = 0; + var valid_entries = 0; + var has_head = 0; + var has_sing = 0; + var has_meta = 0; + var offset = sfnt.offset + 12; + + error = stream.Seek(offset); + if (FT_Common.FT_Err_Ok != error) + return error; + + var num_t = sfnt.num_tables; + for (nn = 0; nn < num_t; nn++) + { + error = stream.EnterFrame(16); + if (error != 0) + { + nn--; + sfnt.num_tables = nn; + break; + } + + var Tag = stream.GetULong(); + var CheckSum = stream.GetULong(); + var Offset = stream.GetULong(); + var Length = stream.GetULong(); + + stream.ExitFrame(); + + if (Offset + Length > stream.size) + continue; + else + valid_entries++; + + if (Tag == FT_Common.TTAG_head || Tag == FT_Common.TTAG_bhed) + { + has_head = 1; + if (Length < 0x36) + return FT_Common.FT_Err_Table_Missing; + + error = stream.Seek(Offset + 12); + if (error != FT_Common.FT_Err_Ok) + return error; + + var magic = stream.ReadULong(); + if (magic != 0x5F0F3CF5) + return FT_Common.FT_Err_Table_Missing; + + error = stream.Seek(offset + (nn+1)*16); + if (error != FT_Common.FT_Err_Ok) + return error; + } + else if (Tag == FT_Common.TTAG_SING) + has_sing = 1; + else if (Tag == FT_Common.TTAG_META) + has_meta = 1; + } + + sfnt.num_tables = valid_entries; + + if (sfnt.num_tables == 0) + return FT_Common.FT_Err_Unknown_File_Format; + + if ((has_head == 1) || ((has_sing == 1) && (has_meta == 1))) + return FT_Common.FT_Err_Ok; + else + return FT_Common.FT_Err_Table_Missing; + + return error; +} +function tt_face_load_font_dir(face, stream) +{ + var sfnt = new SFNT_HeaderRec(); + var error = 0; + + sfnt.offset = stream.pos; + sfnt.format_tag = stream.ReadULong(); + + error = FT_Error; + if (error != 0) + return error; + + error = stream.EnterFrame(8); + if (error != 0) + return error; + + sfnt.num_tables = stream.GetUShort(); + sfnt.search_range = stream.GetUShort(); + sfnt.entry_selector = stream.GetUShort(); + sfnt.range_shift = stream.GetUShort(); + + stream.ExitFrame(); + + error = check_table_dir(sfnt, stream); + if (0 != error) + return error; + + face.num_tables = sfnt.num_tables; + face.format_tag = sfnt.format_tag; + + face.dir_tables = new Array(face.num_tables); + + error = stream.Seek(sfnt.offset + 12); + if (0 == error) + { + error = stream.EnterFrame(face.num_tables * 16); + } + if (0 != error) + return error; + + var cur = 0; + for (var nn = 0; nn < sfnt.num_tables; nn++ ) + { + face.dir_tables[cur] = new TT_Table(); + var entry = face.dir_tables[cur]; + entry.Tag = stream.GetULong(); + entry.CheckSum = stream.GetULong(); + entry.Offset = stream.GetLong(); + entry.Length = stream.GetLong(); + + /* ignore invalid tables */ + if (entry.Offset + entry.Length > stream.size) + continue; + cur++; + } + + stream.ExitFrame(); + return error; +} +function tt_face_load_any(face,tag,offset,buffer,length) +{ + var error = 0; + var table; + var size; + + if (tag != 0) + { + table = tt_face_lookup_table(face, tag); + if (null == table) + return FT_Common.FT_Err_Table_Missing; + + offset += table.Offset; + size = table.Length; + } + else + { + size = face.stream.size; + } + + if (length == 0) + { + FT_Error = 0; + return size; + } + + if (null != length) + size = length; + + error = face.stream.ReadAt(offset,buffer,size); + FT_Error = error; + return size; +} +function tt_face_load_generic_header(face, stream, tag) +{ + var error = 0; + face.goto_table(face, tag, stream); + error = FT_Error; + if (error != FT_Common.FT_Err_Ok) + return error; + + error = stream.EnterFrame(54); + if (error != 0) + return error; + + var header = face.header; + + header.Table_Version = stream.GetULong(); + header.Font_Revision = stream.GetULong(); + header.CheckSum_Adjust = stream.GetLong(); + header.Magic_Number = stream.GetLong(); + header.Flags = stream.GetUShort(); + header.Units_Per_EM = stream.GetUShort(); + header.Created1 = stream.GetLong(); + header.Created2 = stream.GetLong(); + header.Modified1 = stream.GetLong(); + header.Modified2 = stream.GetLong(); + header.xMin = stream.GetShort(); + header.yMin = stream.GetShort(); + header.xMax = stream.GetShort(); + header.yMax = stream.GetShort(); + header.Mac_Style = stream.GetUShort(); + header.Lowest_Rec_PPEM = stream.GetUShort(); + header.Font_Direction = stream.GetShort(); + header.Index_To_Loc_Format = stream.GetShort(); + header.Glyph_Data_Format = stream.GetShort(); + + stream.ExitFrame(); + + return error; +} +function tt_face_load_head(face, stream) +{ + return tt_face_load_generic_header(face, stream, FT_Common.TTAG_head); +} +function tt_face_load_bhed(face, stream) +{ + return tt_face_load_generic_header(face, stream, FT_Common.TTAG_bhed); +} +function tt_face_load_maxp(face, stream) +{ + var error = 0; + face.goto_table(face, FT_Common.TTAG_maxp, stream); + error = FT_Error; + if (error != 0) + return error; + + error = stream.EnterFrame(6); + if (error != 0) + return error; + + var maxProfile = face.max_profile; + maxProfile.version = stream.GetLong(); + maxProfile.numGlyphs = stream.GetUShort(); + stream.ExitFrame(); + + maxProfile.maxPoints = 0; + maxProfile.maxContours = 0; + maxProfile.maxCompositePoints = 0; + maxProfile.maxCompositeContours = 0; + maxProfile.maxZones = 0; + maxProfile.maxTwilightPoints = 0; + maxProfile.maxStorage = 0; + maxProfile.maxFunctionDefs = 0; + maxProfile.maxInstructionDefs = 0; + maxProfile.maxStackElements = 0; + maxProfile.maxSizeOfInstructions = 0; + maxProfile.maxComponentElements = 0; + maxProfile.maxComponentDepth = 0; + + if (maxProfile.version >= 0x10000) + { + error = stream.EnterFrame(26); + if (error != 0) + return error; + + maxProfile.maxPoints = stream.GetUShort(); + maxProfile.maxContours = stream.GetUShort(); + maxProfile.maxCompositePoints = stream.GetUShort(); + maxProfile.maxCompositeContours = stream.GetUShort(); + maxProfile.maxZones = stream.GetUShort(); + maxProfile.maxTwilightPoints = stream.GetUShort(); + maxProfile.maxStorage = stream.GetUShort(); + maxProfile.maxFunctionDefs = stream.GetUShort(); + maxProfile.maxInstructionDefs = stream.GetUShort(); + maxProfile.maxStackElements = stream.GetUShort(); + maxProfile.maxSizeOfInstructions = stream.GetUShort(); + maxProfile.maxComponentElements = stream.GetUShort(); + maxProfile.maxComponentDepth = stream.GetUShort(); + + if (maxProfile.maxFunctionDefs < 64) + maxProfile.maxFunctionDefs = 64; + + /* we add 4 phantom points later */ + if (maxProfile.maxTwilightPoints > (0xFFFF - 4)) + maxProfile.maxTwilightPoints = 0xFFFF - 4; + + /* we arbitrarily limit recursion to avoid stack exhaustion */ + if (maxProfile.maxComponentDepth > 100) + maxProfile.maxComponentDepth = 100; + + stream.ExitFrame(); + } + return error; +} +function tt_face_load_name(face, stream) +{ + var error = 0; + var table_pos = 0; + var table_len = 0; + var storage_start = 0; + var storage_limit = 0; + var count = 0; + + table_len = face.goto_table(face, FT_Common.TTAG_name, stream); + error = FT_Error; + if (error != 0) + return error; + + var table = face.name_table; + table.stream = stream; + + table_pos = stream.pos; + + error = stream.EnterFrame(6); + if (error != 0) + return error; + + table.format = stream.GetUShort(); + table.numNameRecords = stream.GetUShort(); + table.storageOffset = stream.GetUShort(); + + stream.ExitFrame(); + + storage_start = table_pos + 6 + 12*table.numNameRecords; + storage_limit = table_pos + table_len; + + if (storage_start > storage_limit) + return FT_Common.FT_Err_Name_Table_Missing; + + /* Allocate the array of name records. */ + count = table.numNameRecords; + table.numNameRecords = 0; + + table.names = new Array(count); + + error = stream.EnterFrame(count * 12); + for (; count > 0; count--) + { + var entry = new TT_NameEntryRec(); + entry.platformID = stream.GetUShort(); + entry.encodingID = stream.GetUShort(); + entry.languageID = stream.GetUShort(); + entry.nameID = stream.GetUShort(); + entry.stringLength = stream.GetUShort(); + entry.stringOffset = stream.GetUShort(); + + if (entry.stringLength == 0) + continue; + + entry.stringOffset += (table_pos + table.storageOffset); + if (entry.stringOffset < storage_start || (entry.stringOffset + entry.stringLength) > storage_limit) + continue; + + table.names[table.numNameRecords] = entry; + table.numNameRecords++; + } + + stream.ExitFrame(); + + /* everything went well, update face->num_names */ + face.num_names = table.numNameRecords; + return error; +} +function tt_face_free_name(face) +{ + face.name_table.names = null; + var table = face.num_table; + table.names = null; + table.numNameRecords = 0; + table.format = 0; + table.storageOffset = 0; +} +function tt_face_load_cmap(face, stream) +{ + face.cmap_size = face.goto_table(face, FT_Common.TTAG_cmap, stream); + if (FT_Error != 0) + return FT_Error; + + face.cmap_table = new CPointer(); + var error = stream.ExtractFrame(face.cmap_size, face.cmap_table); + if (error != 0) + { + face.cmap_size = 0; + face.cmap_table = null; + } + return error; +} +function tt_face_load_os2(face, stream) +{ + var error = 0; + + var os2 = face.os2; + + face.goto_table(face, FT_Common.TTAG_OS2, stream); + if (error != 0) + return error; + + error = stream.EnterFrame(78); + if (error != 0) + return error; + + os2.version = stream.GetUShort(); + os2.xAvgCharWidth = stream.GetShort(); + os2.usWeightClass = stream.GetUShort(); + os2.usWidthClass = stream.GetUShort(); + os2.fsType = stream.GetShort(); + os2.ySubscriptXSize = stream.GetShort(); + os2.ySubscriptYSize = stream.GetShort(); + os2.ySubscriptXOffset = stream.GetShort(); + os2.ySubscriptYOffset = stream.GetShort(); + os2.ySuperscriptXSize = stream.GetShort(); + os2.ySuperscriptYSize = stream.GetShort(); + os2.ySuperscriptXOffset = stream.GetShort(); + os2.ySuperscriptYOffset = stream.GetShort(); + os2.yStrikeoutSize = stream.GetShort(); + os2.yStrikeoutPosition = stream.GetShort(); + os2.sFamilyClass = stream.GetShort(); + + os2.panose = new Array(10); + os2.panose[0] = stream.GetUChar(); + os2.panose[1] = stream.GetUChar(); + os2.panose[2] = stream.GetUChar(); + os2.panose[3] = stream.GetUChar(); + os2.panose[4] = stream.GetUChar(); + os2.panose[5] = stream.GetUChar(); + os2.panose[6] = stream.GetUChar(); + os2.panose[7] = stream.GetUChar(); + os2.panose[8] = stream.GetUChar(); + os2.panose[9] = stream.GetUChar(); + + os2.ulUnicodeRange1 = stream.GetULong(); + os2.ulUnicodeRange2 = stream.GetULong(); + os2.ulUnicodeRange3 = stream.GetULong(); + os2.ulUnicodeRange4 = stream.GetULong(); + + os2.achVendID = new Array(4); + os2.achVendID[0] = stream.GetUChar(); + os2.achVendID[1] = stream.GetUChar(); + os2.achVendID[2] = stream.GetUChar(); + os2.achVendID[3] = stream.GetUChar(); + + os2.fsSelection = stream.GetUShort(); + os2.usFirstCharIndex = stream.GetUShort(); + os2.usLastCharIndex = stream.GetUShort(); + os2.sTypoAscender = stream.GetShort(); + os2.sTypoDescender = stream.GetShort(); + os2.sTypoLineGap = stream.GetShort(); + os2.usWinAscent = stream.GetUShort(); + os2.usWinDescent = stream.GetUShort(); + + os2.ulCodePageRange1 = 0; + os2.ulCodePageRange2 = 0; + os2.sxHeight = 0; + os2.sCapHeight = 0; + os2.usDefaultChar = 0; + os2.usBreakChar = 0; + os2.usMaxContext = 0; + + stream.ExitFrame(); + + if (os2.version >= 0x0001) + { + error = stream.EnterFrame(8); + if (error != 0) + return error; + + os2.ulCodePageRange1 = stream.GetULong(); + os2.ulCodePageRange2 = stream.GetULong(); + + if (os2.version >= 0x0002) + { + error = stream.EnterFrame(10); + if (error != 0) + return error; + + os2.sxHeight = stream.GetShort(); + os2.sCapHeight = stream.GetShort(); + os2.usDefaultChar = stream.GetUShort(); + os2.usBreakChar = stream.GetUShort(); + os2.usMaxContext = stream.GetUShort(); + } + } + + return error; +} +function tt_face_load_post(face, stream) +{ + var error = 0; + + face.goto_table(face, FT_Common.TTAG_post, stream); + error = FT_Error; + if (error != 0) + return error; + + error = stream.EnterFrame(32); + if (error != 0) + return error; + + var post = face.postscript; + post.FormatType = stream.GetLong(); + post.italicAngle = stream.GetLong(); + post.underlinePosition = stream.GetShort(); + post.underlineThickness = stream.GetShort(); + post.isFixedPitch = stream.GetULong(); + post.minMemType42 = stream.GetULong(); + post.maxMemType42 = stream.GetULong(); + post.minMemType1 = stream.GetULong(); + post.maxMemType1 = stream.GetULong(); + + stream.ExitFrame(); + + return error; +} +function tt_face_load_pclt(face, stream) +{ + var error = 0; + var pclt = face.pclt; + + /* optional table */ + face.goto_table(face, FT_Common.TTAG_PCLT, stream); + error = FT_Error; + if (error != 0) + return error; + + error = stream.EnterFrame(54); + if (error != 0) + return error; + + pclt.Version = stream.GetULong(); + pclt.FontNumber = stream.GetULong(); + pclt.Pitch = stream.GetUShort(); + pclt.xHeight = stream.GetUShort(); + pclt.Style = stream.GetUShort(); + pclt.TypeFamily = stream.GetUShort(); + pclt.CapHeight = stream.GetUShort(); + pclt.SymbolSet = stream.GetUShort(); + pclt.TypeFace = stream.GetString1(16); + pclt.CharacterComplement = stream.GetString1(8); + pclt.FileName = stream.GetString1(6); + pclt.StrokeWeight = stream.GetChar(); + pclt.WidthType = stream.GetChar(); + pclt.SerifStyle = stream.GetUChar(); + pclt.Reserved = stream.GetUChar(); + + stream.ExitFrame(); + return error; +} +function tt_face_load_gasp(face, stream) +{ + var error = 0; + face.goto_table(face, FT_Common.TTAG_gasp, stream); + error = FT_Error; + if (error != 0) + return error; + + error = stream.EnterFrame(4); + if (error != 0) + return error; + + face.gasp.version = stream.GetUShort(); + face.gasp.numRanges = stream.GetUShort(); + + stream.ExitFrame(); + + if (face.gasp.version >= 2) + { + face.gasp.numRanges = 0; + return FT_Common.FT_Err_Invalid_Table; + } + + var num_ranges = face.gasp.numRanges; + face.gasp.gaspRanges = new Array(num_ranges); + var ranges = face.gasp.gaspRanges; + + error = stream.EnterFrame(num_ranges * 4); + if (error != 0) + return error; + + for (var i = 0; i < num_ranges; i++) + { + ranges[i] = new TT_GaspRange(); + ranges[i].maxPPEM = stream.GetUShort(); + ranges[i].gaspFlag = stream.GetUShort(); + } + + stream.ExitFrame(); + return error; +} +/******************************************************************************/ +// ttmtx +/******************************************************************************/ +function tt_face_load_hmtx(face, stream, isvertical) +{ + var error = 0; + + var table_len = 0; + var num_shorts = 0; + var num_longs = 0; + var num_shorts_checked = 0; + + var lm = null; + + if (isvertical == 1) + { + table_len = face.goto_table(face, FT_Common.TTAG_vmtx, stream); + error = FT_Error; + if (error != 0) + return error; + + num_longs = face.vertical.number_Of_VMetrics; + if (num_longs > (table_len / 4)) + num_longs = parseInt(table_len / 4); + + face.vertical.number_Of_VMetrics = 0; + + lm = face.vertical; + } + else + { + table_len = face.goto_table(face, FT_Common.TTAG_hmtx, stream); + error = FT_Error; + if (error != 0) + return error; + + num_longs = face.horizontal.number_Of_HMetrics; + if (num_longs > (table_len / 4)) + num_longs = parseInt(table_len / 4); + + face.horizontal.number_Of_HMetrics = 0; + + lm = face.horizontal; + } + + /* never trust derived values */ + num_shorts = face.max_profile.numGlyphs - num_longs; + num_shorts_checked = parseInt((table_len - num_longs * 4) / 2); + + if (num_longs > 0) + lm.long_metrics = new Array(num_longs); + if (num_shorts > 0) + lm.short_metrics = new Array(num_shorts); + + var longs = lm.long_metrics; + var shorts = lm.short_metrics; + + if (num_shorts < 0) + num_shorts = 0; + + error = stream.EnterFrame(table_len); + + for (var i = 0; i < num_longs; i++) + { + longs[i] = new TT_LongMetricsRec(); + longs[i].advance = stream.GetUShort(); + longs[i].bearing = stream.GetShort(); + } + + var count_s = Math.min(num_shorts, num_shorts_checked); + for (var i = 0; i < count_s; i++) + { + shorts[i] = stream.GetShort(); + } + + if (num_shorts > num_shorts_checked && num_shorts_checked > 0) + { + var ind = shorts.length; + var val = shorts[num_shorts_checked - 1]; + for (var i = ind; i < num_shorts; i++) + shorts[i] = val; + } + + stream.ExitFrame(); + + if (isvertical) + face.vertical.number_Of_VMetrics = num_longs; + else + face.horizontal.number_Of_HMetrics = num_longs; + + return error; +} +function tt_face_load_hhea(face, stream, isvertical) +{ + var error = 0; + var header = null; + if (1 == isvertical) + { + face.goto_table(face, FT_Common.TTAG_vhea, stream); + error = FT_Error; + if (error != 0) + return error; + + header = face.vertical; + } + else + { + face.goto_table(face, FT_Common.TTAG_hhea, stream); + error = FT_Error; + if (error != 0) + return error; + + header = face.horizontal; + } + + error = stream.EnterFrame(36); + if (error != 0) + return error; + + if (0 == isvertical) + { + header.Version = stream.GetULong(); + header.Ascender = stream.GetShort(); + header.Descender = stream.GetShort(); + header.Line_Gap = stream.GetShort(); + + header.advance_Width_Max = stream.GetUShort(); + + header.min_Left_Side_Bearing = stream.GetShort(); + header.min_Right_Side_Bearing = stream.GetShort(); + header.xMax_Extent = stream.GetShort(); + header.caret_Slope_Rise = stream.GetShort(); + header.caret_Slope_Run = stream.GetShort(); + header.caret_Offset = stream.GetShort(); + + header.Reserved1 = stream.GetShort(); + header.Reserved2 = stream.GetShort(); + header.Reserved3 = stream.GetShort(); + header.Reserved4 = stream.GetShort(); + + header.metric_Data_Format = stream.GetShort(); + header.number_Of_HMetrics = stream.GetUShort(); + } + else + { + header.Version = stream.GetULong(); + header.Ascender = stream.GetShort(); + header.Descender = stream.GetShort(); + header.Line_Gap = stream.GetShort(); + + header.advance_Height_Max = stream.GetUShort(); + + header.min_Top_Side_Bearing = stream.GetShort(); + header.min_Bottom_Side_Bearing = stream.GetShort(); + header.yMax_Extent = stream.GetShort(); + header.caret_Slope_Rise = stream.GetShort(); + header.caret_Slope_Run = stream.GetShort(); + header.caret_Offset = stream.GetShort(); + + header.Reserved1 = stream.GetShort(); + header.Reserved2 = stream.GetShort(); + header.Reserved3 = stream.GetShort(); + header.Reserved4 = stream.GetShort(); + + header.metric_Data_Format = stream.GetShort(); + header.number_Of_VMetrics = stream.GetUShort(); + } + + stream.ExitFrame(); + + header.long_metrics = null; + header.short_metrics = null; + + return error; +} +function tt_face_get_metrics(face, vertical, gindex) +{ + var header = (vertical == 1) ? face.vertical : face.horizontal; + + var longs_m = null; + var k = header.number_Of_HMetrics; + + var v1 = 0; + var v2 = 0; + if (k == 0 || null == header.long_metrics || gindex >= face.max_profile.numGlyphs) + return { bearing:0,advance:0 }; + + if (gindex < k) + { + longs_m = header.long_metrics[gindex]; + v1 = longs_m.bearing; + v2 = longs_m.advance; + } + else + { + v1 = header.short_metrics[gindex - k]; + v2 = header.long_metrics[k - 1].advance; + } + return { bearing:v1,advance:v2 }; +} +/******************************************************************************/ +// ttpost +/******************************************************************************/ +function load_format_20(face, stream, post_limit) +{ + var error = 0; + + var num_glyphs = stream.ReadUShort(); + error = FT_Error; + if (error != 0) + return error; + + if (num_glyphs > face.max_profile.numGlyphs) + return FT_Common.FT_Err_Invalid_File_Format; + + error = stream.EnterFrame(num_glyphs*2); + if (error != 0) + return error; + + var glyph_indices = new Array(num_glyphs); + for (var n=0;n<num_glyphs;n++) + glyph_indices[n] = stream.GetUShort(); + stream.ExitFrame(); + + var num_names = 0; + for ( n = 0; n < num_glyphs; n++ ) + { + var idx = glyph_indices[n]; + if (idx >= 258) + { + idx -= 257; + if (idx > num_names) + num_names = idx; + } + } + + var name_strings = new Array(num_names); + var n=0; + for (n = 0; n < num_names; n++) + { + var len = 0; + if (stream.pos >= post_limit) + break; + else + { + len = stream.ReadUChar(); + error = FT_Error; + if (error != 0) + return error; + } + + if (len > post_limit || stream.pos > post_limit - len) + { + len = Math.max(0, post_limit - stream.pos); + } + + name_strings[n] = stream.ReadString1(len); + } + + if (n < num_names) + { + for (; n < num_names; n++) + name_strings[n] = ""; + } + + var table = face.postscript_names.names.format_20; + table.num_glyphs = num_glyphs; + table.num_names = num_names; + table.glyph_indices = glyph_indices; + table.glyph_names = name_strings; + + return 0; +} +function load_format_25(face, stream, post_limit) +{ + var num_glyphs = stream.ReadUShort(); + var error = FT_Error; + if (error != 0) + return error; + + if (num_glyphs > face.max_profile.numGlyphs || num_glyphs > 258) + return FT_Common.FT_Err_Invalid_File_Format; + + var offset_table = g_memory.Alloc(num_glyphs); + error = stream.Read(offset_table,num_glyphs); + + if (error != 0) + return error; + + for (var n = 0; n < num_glyphs; n++ ) + { + var idx = n + offset_table[n]; + if ( idx < 0 || idx > num_glyphs ) + return FT_Common.FT_Err_Invalid_File_Format; + } + + var table = face.postscript_names.names.format_25; + table.num_glyphs = num_glyphs; + table.offsets = offset_table; + return 0; +} +function load_post_names(face) +{ + var stream = face.stream; + var post_len = face.goto_table(face, FT_Common.TTAG_post, stream); + var error = FT_Error; + if (error != 0) + return error; + + var post_limit = stream.pos + post_len; + var format = face.postscript.FormatType; + + error = stream.Skip(32); + if (error != 0) + return error; + + if (format == 0x00020000) + error = load_format_20(face, stream, post_limit); + else if (format == 0x00028000) + error = load_format_25(face, stream, post_limit); + else + error = FT_Common.FT_Err_Invalid_File_Format; + + face.postscript_names.loaded = 1; + return error; +} +function tt_face_free_ps_names(face) +{ + var names = face.postscript_names; + + if (names.loaded == 1) + { + var format = face.postscript.FormatType; + if (format == 0x00020000) + { + var table = names.names.format_20; + + table.glyph_indices = null; + table.num_glyphs = 0; + + table.glyph_names = null; + table.num_names = 0; + } + else if (format == 0x00028000) + { + var table = names.names.format_25; + table.offsets = null; + table.num_glyphs = 0; + } + } + names.loaded = 0; +} +function tt_face_get_ps_name(face, idx) +{ + if (null == face) + { + FT_Error = FT_Common.FT_Err_Invalid_Face_Handle; + return ""; + } + if (idx >= face.max_profile.numGlyphs) + { + FT_Error = FT_Common.FT_Err_Invalid_Glyph_Index; + return ""; + } + var psnames = face.psnames; + if (null == psnames) + { + FT_Error = FT_Common.FT_Err_Unimplemented_Feature; + return ""; + } + + FT_Error = 0; + var names = face.postscript_names; + var format = face.postscript.FormatType; + + var res = psnames.macintosh_name(0); + if (format == 0x00010000) + { + if (idx < 258) + res = psnames.macintosh_name(idx); + } + else if (format == 0x00020000) + { + var table = names.names.format_20; + if (0 == names.loaded) + { + FT_Error = load_post_names(face); + if (FT_Error != 0) + return res; + } + + if (idx < table.num_glyphs) + { + var name_index = table.glyph_indices[idx]; + + if (name_index < 258) + res = psnames.macintosh_name(name_index); + else + res = table.glyph_names[name_index - 258]; + } + } + else if (format == 0x00028000) + { + var table = names.names.format_25; + if (0 == names.loaded) + { + FT_Error = load_post_names( face ); + if (FT_Error != 0) + return res; + } + + if (idx < table.num_glyphs) + { + idx += table.offsets[idx]; + res = psnames.macintosh_name(idx); + } + } + return res; +} +/******************************************************************************/ +// ttsbit +/******************************************************************************/ +function blit_sbit(target, _source, line_bits, byte_padded, x_offset, y_offset, source_height) +{ + var line_incr = target.pitch; + var line_buff = target.buffer; + + var source = dublicate_pointer(_source); + + if (line_incr < 0) + line_buff -= line_incr * (target.rows - 1); + + line_buff.pos += (x_offset >> 3) + y_offset * line_incr; + + var acc = 0; + var loaded = 0; + + for (var height = source_height; height > 0; height--) + { + var cur = dublicate_pointer(line_buff); + var count = line_bits; + var shift = (x_offset & 7); + var space = (8 - shift); + + if ( count >= 8 ) + { + count -= 8; + do + { + if (loaded < 8) + { + acc |= (source.data[source.pos++] << ( 8 - loaded)); + loaded += 8; + } + + val = (0xFF & (acc >>> 8)); + if (shift != 0) + { + cur.data[cur.pos] |= (0xFF & (val >>> shift)); + cur.data[cur.pos+1] |= (0xFF & (val << space)); + } + else + cur.data[cur.pos] |= val; + + cur.pos++; + acc <<= 8; + loaded -= 8; + count -= 8; + } while (count >= 0); + count += 8; + } + + if (count > 0) + { + if (loaded < count) + { + acc |= ((source.data[source.pos++]) << (8 - loaded)); + loaded += 8; + } + + var val = ((0xFF&(acc >>> 8)) & ~(0xFF >>> count)); + cur.data[cur.pos] |= (0xFF & (val >>> shift)); + + if (count > space) + cur.data[cur.pos+1] |= (0xFF & (val << space)); + + acc <<= count; + loaded -= count; + } + + if ( byte_padded ) + { + acc = 0; + loaded = 0; + } + line_buff.pos += line_incr; + } +} +function Load_SBit_Const_Metrics(range, stream) +{ + range.image_size = stream.ReadULong(); + if (FT_Error != 0) + return FT_Error; + + var error = stream.EnterFrame(8); + if (0 == error) + { + var metrics = range.metrics; + + metrics.height = stream.GetUChar(); + metrics.width = stream.GetUChar(); + + metrics.horiBearingX = stream.GetChar(); + metrics.horiBearingY = stream.GetChar(); + metrics.horiAdvance = stream.GetUChar(); + + metrics.vertBearingX = stream.GetChar(); + metrics.vertBearingY = stream.GetChar(); + metrics.vertAdvance = stream.GetUChar(); + } + stream.ExitFrame(); + return error; +} +function Load_SBit_Range_Codes(range, stream, load_offsets) +{ + var count = stream.ReadULong(); + if (FT_Error != 0) + return FT_Error; + + range.num_glyphs = count; + + var size = 2 * count; + if (load_offsets != 0) + { + range.glyph_offsets = new Array(count); + size *= 2; + } + + var error = stream.EnterFrame(size); + if (0 != error) + return error; + + range.glyph_codes = new Array(count); + + for (var n = 0; n < count; n++) + { + range.glyph_codes[n] = stream.GetUShort(); + + if (load_offsets != 0) + range.glyph_offsets[n] = range.image_offset + stream.GetUShort(); + } + + stream.ExitFrame(); + return error; +} +function Load_SBit_Range(range, stream) +{ + var error = 0; + + switch(range.index_format) + { + case 1: + case 3: + if (range.last_glyph < range.first_glyph) + return FT_Common.FT_Err_Invalid_File_Format; + + var num_glyphs = range.last_glyph - range.first_glyph + 1; + range.num_glyphs = num_glyphs; + num_glyphs++; + + var large = (range.index_format == 1) ? 1 : 0; + var size_elem = large ? 4 : 2; + + error = stream.EnterFrame(num_glyphs*size_elem); + if (error != 0) + return error; + range.glyph_offsets = new Array(num_glyphs); + + for (var n = 0; n < num_glyphs; n++) + range.glyph_offsets[n] = (range.image_offset + ((large == 1) ? stream.GetULong() : stream.GetUShort())); + stream.ExitFrame(); + break; + + case 2: + error = Load_SBit_Const_Metrics(range, stream); + break; + case 4: + error = Load_SBit_Range_Codes(range, stream, 1); + break; + case 5: + error = Load_SBit_Const_Metrics(range, stream); + if (error != 0) + error = Load_SBit_Range_Codes(range, stream, 0); + break; + default: + error = FT_Common.FT_Err_Invalid_File_Format; + } + return error; +} + +function tt_face_load_eblc(face, stream) +{ + var error = 0; + + face.num_sbit_strikes = 0; + face.goto_table(face, FT_Common.TTAG_EBLC, stream); + if (FT_Error != 0) + face.goto_table(face, FT_Common.TTAG_bloc, stream); + error = FT_Error; + if (error != 0) + return error; + + var table_base = stream.pos; + error = stream.EnterFrame(8); + if (error != 0) + return error; + + var version = stream.GetLong(); + var num_strikes = stream.GetULong(); + + stream.ExitFrame(); + + if (version != 0x00020000 || num_strikes >= 0x10000) + return FT_Common.FT_Err_Invalid_File_Format; + + face.sbit_strikes = new Array(num_strikes); + face.num_sbit_strikes = num_strikes; + + for (var i = 0; i < num_strikes; i++) + face.sbit_strikes[i] = new TT_SBit_StrikeRec(); + + var strike_ind = 0; + var count = num_strikes; + + error = stream.EnterFrame(48*num_strikes); + if (error != 0) + return error; + + while ( count > 0 ) + { + var strike = face.sbit_strikes[strike_ind]; + + strike.ranges_offset = stream.GetULong(); + stream.cur += 4; + strike.num_ranges = stream.GetULong(); + strike.color_ref = stream.GetULong(); + + var h = strike.hori; + var v = strike.vert; + + h.ascender = stream.GetChar(); + h.descender = stream.GetChar(); + h.max_width = stream.GetUChar(); + h.caret_slope_numerator = stream.GetChar(); + h.caret_slope_denominator = stream.GetChar(); + h.caret_offset = stream.GetChar(); + h.min_origin_SB = stream.GetChar(); + h.min_advance_SB = stream.GetChar(); + h.max_before_BL = stream.GetChar(); + h.min_after_BL = stream.GetChar(); + h.pads1 = stream.GetChar(); + h.pads2 = stream.GetChar(); + + v.ascender = stream.GetChar(); + v.descender = stream.GetChar(); + v.max_width = stream.GetUChar(); + v.caret_slope_numerator = stream.GetChar(); + v.caret_slope_denominator = stream.GetChar(); + v.caret_offset = stream.GetChar(); + v.min_origin_SB = stream.GetChar(); + v.min_advance_SB = stream.GetChar(); + v.max_before_BL = stream.GetChar(); + v.min_after_BL = stream.GetChar(); + v.pads1 = stream.GetChar(); + v.pads2 = stream.GetChar(); + + strike.start_glyph = stream.GetUShort(); + strike.end_glyph = stream.GetUShort(); + strike.x_ppem = stream.GetUChar(); + strike.y_ppem = stream.GetUChar(); + strike.bit_depth = stream.GetUChar(); + strike.flags = stream.GetChar(); + + count--; + strike_ind++; + } + + stream.ExitFrame(); + strike_ind = 0; + count = num_strikes; + + while ( count > 0 ) + { + var strike = face.sbit_strikes[strike_ind]; + var range; + var count2 = strike.num_ranges; + + error = stream.Seek(table_base + strike.ranges_offset); + if (0 != error) + return error; + + error = stream.EnterFrame(strike.num_ranges * 8); + if (0 != error) + return error; + + strike.sbit_ranges = new Array(strike.num_ranges); + var __count = strike.num_ranges; + for (var i = 0; i < __count; i++) + strike.sbit_ranges[i] = new TT_SBit_RangeRec(); + + var range_ind = 0; + while ( count2 > 0 ) + { + range = strike.sbit_ranges[range_ind]; + range.first_glyph = stream.GetUShort(); + range.last_glyph = stream.GetUShort(); + range.table_offset = table_base + strike.ranges_offset + stream.GetULong(); + count2--; + range_ind++; + } + + stream.ExitFrame(); + + count2 = strike.num_ranges; + range_ind = 0; + while (count2 > 0) + { + range = strike.sbit_ranges[range_ind]; + error = stream.Seek(range.table_offset); + if (error != 0) + return error; + error = stream.EnterFrame(8); + if (error != 0) + return error; + + range.index_format = stream.GetUShort(); + range.image_format = stream.GetUShort(); + range.image_offset = stream.GetULong(); + + stream.ExitFrame(); + + error = Load_SBit_Range(range, stream); + if (error != 0) + return error; + + count2--; + range_ind++; + } + + count--; + strike_ind++; + } + + return error; +} +function tt_face_free_eblc(face) +{ + face.sbit_strikes = null; + face.num_sbit_strikes = 0; +} +function tt_face_set_sbit_strike(face, req) +{ + return FT_Match_Size(face, req, 0); +} +function tt_face_load_strike_metrics(face, strike_index, metrics) +{ + if (strike_index >= face.num_sbit_strikes) + return FT_Common.FT_Err_Invalid_Argument; + + var strike = face.sbit_strikes[strike_index]; + + metrics.x_ppem = strike.x_ppem; + metrics.y_ppem = strike.y_ppem; + + metrics.ascender = strike.hori.ascender << 6; + metrics.descender = strike.hori.descender << 6; + + metrics.max_advance = (strike.hori.min_origin_SB + strike.hori.max_width + strike.hori.min_advance_SB) << 6; + + metrics.height = metrics.ascender - metrics.descender; + + return 0; +} +function find_sbit_range(glyph_index, strike) +{ + FT_Error = 0; + var range = null; + var glyph_offset = 0; + + if (glyph_index < strike.start_glyph || glyph_index > strike.end_glyph) + { + FT_Error = FT_Common.FT_Err_Invalid_Argument; + } + + var range_ind = 0; + var range_limit = strike.num_ranges; + + for ( ; range_ind < range_limit; range_ind++) + { + range = strike.sbit_ranges[range_ind]; + if (glyph_index >= range.first_glyph && glyph_index <= range.last_glyph) + { + var delta = (glyph_index - range.first_glyph); + + switch (range.index_format) + { + case 1: + case 3: + glyph_offset = range.glyph_offsets[delta]; + break; + case 2: + glyph_offset = range.image_offset + range.image_size * delta; + break; + case 4: + case 5: + for (var n = 0; n < range.num_glyphs; n++) + { + if (range.glyph_codes[n] == glyph_index) + { + if (range.index_format == 4) + glyph_offset = range.glyph_offsets[n]; + else + glyph_offset = range.image_offset + n * range.image_size; + return {range:range,glyph_offset:glyph_offset}; + } + } + break; + default: + break; + } + + return {range:range,glyph_offset:glyph_offset}; + } + } + + FT_Error = FT_Common.FT_Err_Invalid_Argument; + return {range:range,glyph_offset:glyph_offset}; +} +function tt_find_sbit_image(face, glyph_index, strike_index) +{ + FT_Error = 0; + if (null == face.sbit_strikes || (face.num_sbit_strikes <= strike_index)) + { + FT_Error = FT_Common.FT_Err_Invalid_Argument; + return {strike:null,range:null,glyph_offset:0}; + } + + var strike = face.sbit_strikes[strike_index]; + var ret = find_sbit_range(glyph_index, strike); + if (FT_Error != 0) + { + FT_Error = FT_Common.FT_Err_Invalid_Argument; + return {strike:null,range:null,glyph_offset:0}; + } + + return {strike:strike,range:ret.range,glyph_offset:ret.glyph_offset}; +} +function tt_load_sbit_metrics(stream, range, metrics) +{ + var error = 0; + switch (range.image_format) + { + case 1: + case 2: + case 8: + error = stream.EnterFrame(5); + if (error != 0) + return error; + + metrics.height = stream.GetUChar(); + metrics.width = stream.GetUChar(); + metrics.horiBearingX = stream.GetChar(); + metrics.horiBearingY = stream.GetChar(); + metrics.horiAdvance = stream.GetUChar(); + + metrics.vertBearingX = 0; + metrics.vertBearingY = 0; + metrics.vertAdvance = 0; + + stream.ExitFrame(); + break; + + case 6: + case 7: + case 9: + error = stream.EnterFrame(8); + if (error != 0) + return error; + + metrics.height = stream.GetUChar(); + metrics.width = stream.GetUChar(); + metrics.horiBearingX = stream.GetChar(); + metrics.horiBearingY = stream.GetChar(); + metrics.horiAdvance = stream.GetUChar(); + + metrics.vertBearingX = stream.GetChar(); + metrics.vertBearingY = stream.GetChar(); + metrics.vertAdvance = stream.GetUChar(); + + stream.ExitFrame(); + break; + case 5: + default: + if (range.index_format == 2 || range.index_format == 5) + { + var s = range.metrics; + metrics.height = s.height; + metrics.width = s.width; + metrics.horiBearingX = s.horiBearingX; + metrics.horiBearingY = s.horiBearingY; + metrics.horiAdvance = s.horiAdvance; + + metrics.vertBearingX = s.vertBearingX; + metrics.vertBearingY = s.vertBearingY; + metrics.vertAdvance = s.vertAdvance; + } + else + return FT_Common.FT_Err_Invalid_File_Format; + } + + return error; +} +function crop_bitmap(map, metrics) +{ + var rows, count; + var line_len; + var line = new CPointer(); + line.data = map.buffer.data; + var d = line.data; + + // 1 + line.pos = map.buffer.pos; + rows = map.rows; + line_len = map.pitch; + + var is_go_to = 0; + for (count = 0; count < rows; count++) + { + for (var cur=0; cur < line_len; cur++) + { + if (d[line.pos+cur] != 0) + { + is_go_to = 1; + break; + } + } + if (1 == is_go_to) + break; + line.pos += line_len; + } + + if (count >= rows) + { + map.width = 0; + map.rows = 0; + map.pitch = 0; + map.pixel_mode = FT_Common.FT_PIXEL_MODE_MONO; + } + + if ( count > 0 ) + { + line.pos = map.buffer.pos; + var pos1 = line.pos; + var pos2 = line.pos + count * line_len; + + var c = (rows - count)*line_len; + + for (var i=0;i<c;i++) + d[pos1+i] = d[pos2+i]; + + metrics.height = (metrics.height - count)&0xFF; + metrics.horiBearingY = (metrics.horiBearingY - count); + metrics.vertBearingY = (metrics.vertBearingY - count); + + map.rows -= count; + rows -= count; + } + + //2 + is_go_to = 0; + line.pos = (rows - 1) * line_len; + + for (count = 0; count < rows; count++) + { + for (var cur=0; cur < line_len; cur++) + { + if (d[line.pos+cur] != 0) + { + is_go_to = 1; + break; + } + } + if (is_go_to == 1) + break; + + line.pos -= line_len; + } + + if (count > 0) + { + metrics.height = (metrics.height - count); + rows -= count; + map.rows -= count; + } + + // 3 + is_go_to = 0; + do + { + line.pos = map.buffer.pos; + var limit = line.pos + rows * line_len; + + for (; line.pos < limit; line.pos += line_len) + { + if ((d[line.pos] & 0x80) != 0) + { + is_go_to = 1; + break; + } + } + if (1 == is_go_to) + break; + + line.pos = map.buffer.pos; + limit = line.pos + rows * line_len; + + for (; line.pos < limit; line.pos += line_len) + { + var width = map.width; + var cur = line.pos; + var old = 0xFF & (d[cur] << 1); + for (var n = 8; n < width; n += 8) + { + var val = d[cur+1]; + d[cur] = 0xFF & (old | (val >>> 7)); + old = 0xFF & (val << 1); + cur++; + } + d[cur] = old; + } + + map.width--; + metrics.horiBearingX++; + metrics.vertBearingX++; + metrics.width--; + + } while (map.width > 0); + + // 4 + do + { + var right = map.width - 1; + line.pos = (right >>> 3); + var limit = line.pos + rows * line_len; + var mask = 0xFF & (0x80 >>> (right & 7)); + + for ( ; line.pos < limit; line.pos += line_len) + if ((d[line.pos] & mask)!=0) + return; + + map.width--; + metrics.width--; + + } while ( map.width > 0 ); +} +function Load_SBit_Single(map, x_offset, y_offset, pix_bits, image_format, metrics, stream) +{ + var error = 0; + if (x_offset < 0 || x_offset + metrics.width > map.width || y_offset < 0 || y_offset + metrics.height > map.rows) + return FT_Common.FT_Err_Invalid_Argument; + + var glyph_width = metrics.width; + var glyph_height = metrics.height; + var glyph_size; + var line_bits = pix_bits * glyph_width; + var pad_bytes = 0; + + switch ( image_format ) + { + case 1: /* byte-padded formats */ + case 6: + var line_length; + switch ( pix_bits ) + { + case 1: + line_length = (glyph_width + 7) >>> 3; + break; + case 2: + line_length = (glyph_width + 3) >>> 2; + break; + case 4: + line_length = (glyph_width + 1) >>> 1; + break; + default: + line_length = glyph_width; + } + + glyph_size = glyph_height * line_length; + pad_bytes = 1; + break; + case 2: + case 5: + case 7: + line_bits = glyph_width * pix_bits; + glyph_size = (glyph_height * line_bits + 7) >>> 3; + break; + default: + return FT_Common.FT_Err_Invalid_File_Format; + } + + error = stream.EnterFrame(glyph_size); + if (0 != error) + return error; + + var s = new CPointer(); + s.data = stream.data; + s.pos = stream.cur; + blit_sbit(map, s, line_bits, pad_bytes, x_offset * pix_bits, y_offset, metrics.height); + + stream.ExitFrame(); + return error; +} +function Load_SBit_Image(strike, range, ebdt_pos, glyph_offset, slot, x_offset, y_offset, stream, metrics, depth) +{ + var map = slot.bitmap; + var error = stream.Seek(ebdt_pos + glyph_offset); + if (0 != error) + return error; + + error = tt_load_sbit_metrics(stream, range, metrics); + if (error != 0) + return 0; + + if (depth == 0) + { + map.width = metrics.width; + map.rows = metrics.height; + + switch (strike.bit_depth) + { + case 1: + map.pixel_mode = FT_Common.FT_PIXEL_MODE_MONO; + map.pitch = (map.width + 7) >>> 3; + break; + case 2: + map.pixel_mode = FT_Common.FT_PIXEL_MODE_GRAY2; + map.pitch = (map.width + 3) >>> 2; + break; + case 4: + map.pixel_mode = FT_Common.FT_PIXEL_MODE_GRAY4; + map.pitch = (map.width + 1) >>> 1; + break; + case 8: + map.pixel_mode = FT_Common.FT_PIXEL_MODE_GRAY; + map.pitch = map.width; + break; + default: + return FT_Common.FT_Err_Invalid_File_Format; + } + + var size = map.rows * map.pitch; + if (size == 0) + return error; + + error = ft_glyphslot_alloc_bitmap(slot, size); + if (error != 0) + return error; + } + + switch (range.image_format) + { + case 1: + case 2: + case 5: + case 6: + case 7: + return Load_SBit_Single(map, x_offset, y_offset, strike.bit_depth, range.image_format, metrics, stream); + + case 8: + error = stream.Skip(1); + if (error != 0) + return FT_Common.FT_Err_Invalid_Stream_Skip; + case 9: + break; + + default: + return FT_Common.FT_Err_Invalid_File_Format; + } + + var num_components = stream.ReadUShort(); + FT_Error = error; + if (error != 0) + return error; + + error = stream.EnterFrame(4*num_components); + if (error != 0) + return error; + + var components = new Array(num_components); + var count = num_components; + var comp = 0; + + for (; count > 0; count--, comp++) + { + var _comp = components[comp]; + _comp.glyph_code = stream.GetUShort(); + _comp.x_offset = stream.GetChar(); + _comp.y_offset = stream.GetChar(); + } + + stream.ExitFrame(); + count = num_components; + comp = 0; + for ( ; count > 0; count--, comp++ ) + { + var elem_metrics = new TT_SBit_MetricsRec(); + + var _comp = components[comp]; + var elem = find_sbit_range(_comp.glyph_code, strike); + error = FT_Error; + if (error != 0) + { + components = null; + return error; + } + + error = Load_SBit_Image(strike, elem.range, ebdt_pos, elem.glyph_offset, slot, x_offset + _comp.x_offset, + y_offset + _comp.y_offset, stream, elem_metrics, depth + 1); + if (error != 0) + { + components = null; + return error; + } + } + + return error; +} +function tt_face_load_sbit_image(face, strike_index, glyph_index, load_flags, stream, map, metrics) +{ + var elem = tt_find_sbit_image(face, glyph_index, strike_index); + var error = FT_Error; + if (error != 0) + return error; + + face.goto_table(face, FT_Common.TTAG_EBDT, stream); + error = FT_Error; + if (error != 0) + { + face.goto_table(face, FT_Common.TTAG_bdat, stream); + error = FT_Error; + } + if (error != 0) + return error; + + var ebdt_pos = stream.pos; + var strike = elem.strike; + + error = Load_SBit_Image(strike, elem.range, ebdt_pos, elem.glyph_offset, + face.glyph, 0, 0, stream, metrics, 0); + if (error != 0) + return error; + + if (strike.flags & 1) + { + var advance = strike.hori.ascender - strike.hori.descender; + + metrics.vertBearingX = parseInt((-metrics.width / 2)); + metrics.vertBearingY = parseInt((advance - metrics.height)/2); + metrics.vertAdvance = parseInt(advance*12/10); + } + + if (load_flags & FT_Common.FT_LOAD_CROP_BITMAP) + crop_bitmap(map, metrics); + return error; +} +/******************************************************************************/ +// ttcmap +/******************************************************************************/ +function TT_CMapRec() +{ + this.cmap = new FT_CMapRec(); + this.data = null; + this.flags = 0; + + this.type = FT_Common.FT_CMAP_1; +} +function TT_CMap_ClassRec() +{ + this.clazz = new FT_CMap_ClassRec(); + this.format = 0; + this.validate = null; + this.get_cmap_info = null; +} +function TT_Validator() +{ + this.validator = new FT_ValidatorRec(); + this.num_glyphs = 0; +} +function tt_cmap_init(cmap, table) +{ + cmap.data = dublicate_pointer(table); + return 0; +} +// cmap0 ---------------------------------------------------------------------------------- +function tt_cmap0_char_index(cmap, char_code) +{ + var table = cmap.data; + return char_code < 256 ? table.data[table.pos + 6 + char_code] : 0; +} +function tt_cmap0_char_next(cmap, char_code) +{ + var table = cmap.data; + var pos_base = table.pos + 6; + var charcode = char_code; + var result = 0; + var gindex = 0; + + var d = table.data; + while (++charcode < 256) + { + gindex = d[pos_base + charcode]; + if (gindex != 0) + { + result = charcode; + break; + } + } + + return {gindex:gindex,char_code:result}; +} +function tt_cmap0_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap_init,null,tt_cmap0_char_index,tt_cmap0_char_next,null,null,null,null,null); + this.format = 0; + this.validate = function(table, valid) + { + var p = dublicate_pointer(table); + p.pos += 2; + var length = FT_NEXT_USHORT(p); + + if (length > valid.limit || length < 262) + return FT_Common.FT_Err_Invalid_Table; + + if (valid.level >= 1) + { + var idx; + var d = p.data; + var c = table.pos + 6; + for (var n = 0; n < 256; n++) + { + idx = d[c++]; + if (idx >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + } + } + return 0; + } + this.get_cmap_info = function(cmap, cmap_info) + { + var data = cmap.data; + data.pos += 4; + cmap_info.format = 0; + cmap_info.language = FT_PEEK_USHORT(data); + data.pos -= 4; + return 0; + } +} +// cmap2 ---------------------------------------------------------------------------------- +function tt_cmap2_get_subheader(table, char_code) +{ + if (char_code < 0x10000) + { + var char_lo = (char_code & 0xFF); + var char_hi = (char_code >>> 8); + var p = dublicate_pointer(table); + p.pos += 6; + + var subs = table.pos + 518; + var sub = subs; + + if (char_hi == 0) + { + sub = subs; + p.pos += char_lo * 2; + if (FT_PEEK_USHORT(p) != 0) + return null; + } + else + { + p.pos += char_hi * 2; + sub = subs + (FT_PEEK_USHORT(p) & ~7); + if (sub == subs) + return null; + } + var result = new CPointer(); + result.data = table.data; + result.pos = sub; + return result; + } + return null; +} +function tt_cmap2_char_index(cmap, char_code) +{ + var table = dublicate_pointer(cmap.data); + var result = 0; + var subheader = tt_cmap2_get_subheader(table, char_code); + if (subheader != null) + { + var p = subheader; + var idx = (char_code & 0xFF); + + var start = FT_NEXT_USHORT(p); + var count = FT_NEXT_USHORT(p); + var delta = FT_NEXT_SHORT (p); + var offset = FT_PEEK_USHORT(p); + + idx -= start; + if ( idx < count && offset != 0 ) + { + p.pos += offset + 2 * idx; + idx = FT_PEEK_USHORT(p); + if (idx != 0) + result = (idx + delta) & 0xFFFF; + } + } + return result; +} +function tt_cmap2_char_next(cmap, charcode_) +{ + var table = dublicate_pointer(cmap.data); + var gindex = 0; + var result = 0; + var charcode = charcode_ + 1; + var subheader = null; + + while (charcode < 0x10000) + { + subheader = tt_cmap2_get_subheader(table, charcode); + if (subheader != null) + { + var p = subheader; + var start = FT_NEXT_USHORT(p); + var count = FT_NEXT_USHORT(p); + var delta = FT_NEXT_SHORT(p); + var offset = FT_PEEK_USHORT(p); + var char_lo = (charcode & 0xFF); + var pos, idx; + + if (offset == 0) + { + charcode = charcode & ~255 + 256; + continue; + } + + if (char_lo < start) + { + char_lo = start; + pos = 0; + } + else + pos = (char_lo - start); + + p.pos += offset + pos * 2; + charcode = charcode & ~255 + char_lo; + + for ( ; pos < count; pos++, charcode++ ) + { + idx = FT_NEXT_USHORT(p); + + if ( idx != 0 ) + { + gindex = (idx + delta) & 0xFFFF; + if ( gindex != 0 ) + { + result = charcode; + return {gindex:gindex,char_code:result}; + } + } + } + } + charcode = charcode & ~255 + 256; + } + return {gindex:gindex,char_code:result}; +} +function tt_cmap2_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap_init,null,tt_cmap2_char_index,tt_cmap2_char_next,null,null,null,null,null); + this.format = 2; + this.validate = function(table, valid) + { + var p = dublicate_pointer(table); + p.pos += 2; + var length = FT_PEEK_USHORT(p); + var n = 0; + + if (length > valid.limit || length < 6 + 512) + return FT_Common.FT_Err_Invalid_Table; + + p.pos = table.pos + 6; + var max_subs = 0; + for ( n = 0; n < 256; n++ ) + { + var idx = FT_NEXT_USHORT(p); + if (valid.level >= 2 && (idx & 7) != 0) + return FT_Common.FT_Err_Invalid_Table; + + idx >>>= 3; + + if (idx > max_subs) + max_subs = idx; + } + + var glyph_ids = p.pos + (max_subs + 1) * 8; + if (glyph_ids > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + + for (n = 0; n <= max_subs; n++) + { + var first_code = FT_NEXT_USHORT(p); + var code_count = FT_NEXT_USHORT(p); + var delta = FT_NEXT_SHORT(p); + var offset = FT_NEXT_USHORT(p); + + if (code_count == 0) + continue; + + if (valid.level >= 2) + { + if (first_code >= 256 || first_code + code_count > 256) + return FT_Common.FT_Err_Invalid_Table; + } + + if (offset != 0) + { + var ids = p.pos - 2 + offset; + if (ids < glyph_ids || ids + code_count*2 > (table.pos+length)) + return FT_Common.FT_Err_Invalid_Offset; + + if (valid.level >= 1) + { + var limit = p.pos + code_count * 2; + var idx; + for (; p.pos < limit;) + { + idx = FT_NEXT_USHORT(p); + if ( idx != 0 ) + { + idx = (idx + delta) & 0xFFFF; + if (idx >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + } + } + } + } + } + return 0; + } + this.get_cmap_info = function(cmap, cmap_info) + { + cmap.data.pos += 4; + cmap_info.format = 2; + cmap_info.language = FT_PEEK_USHORT(cmap.data); + cmap.data.pos -= 4; + return 0; + } +} +// cmap4 ---------------------------------------------------------------------------------- +function TT_CMap4Rec() +{ + this.cmap = new TT_CMapRec(); + this.cur_charcode; + this.cur_gindex; + + this.num_ranges; + this.cur_range; + this.cur_start; + this.cur_end; + this.cur_delta; + this.cur_values; + + this.type = FT_Common.FT_CMAP_4; +} +function tt_cmap4_init(cmap,table) +{ + var p = dublicate_pointer(table); + p.pos += 6; + cmap.cmap.data = dublicate_pointer(table); + cmap.num_ranges = FT_PEEK_USHORT(p) >>> 1; + cmap.cur_charcode = 0xFFFFFFFF; + cmap.cur_gindex = 0; + return 0; +} +function tt_cmap4_set_range(cmap, range_index) +{ + var table = cmap.cmap.data.pos; + var p = dublicate_pointer(cmap.cmap.data); + var num_ranges = cmap.num_ranges; + + while (range_index < num_ranges) + { + p.pos = table + 14 + range_index * 2; + cmap.cur_end = FT_PEEK_USHORT(p); + + p.pos += 2 + num_ranges * 2; + cmap.cur_start = FT_PEEK_USHORT(p); + + p.pos += num_ranges * 2; + cmap.cur_delta = FT_PEEK_SHORT(p); + + p.pos += num_ranges * 2; + var offset = FT_PEEK_USHORT(p); + + if (range_index >= num_ranges - 1 && cmap.cur_start == 0xFFFF && cmap.cur_end == 0xFFFF) + { + var face = cmap.cmap.cmap.charmap.face; + var limit = face.cmap_table.pos + face.cmap_size; + if (offset && p.pos + offset + 2 > limit) + { + cmap.cur_delta = 1; + offset = 0; + } + } + if (offset != 0xFFFF) + { + cmap.cur_values = null; + if (offset != 0) + { + cmap.cur_values = dublicate_pointer(p); + cmap.cur_values.pos += offset; + } + cmap.cur_range = range_index; + return 0; + } + range_index++; + } + return -1; +} +function tt_cmap4_next(cmap) +{ + if (cmap.cur_charcode >= 0xFFFF) + { + cmap.cur_charcode = 0xFFFFFFFF; + cmap.cur_gindex = 0; + return; + } + + var charcode = cmap.cur_charcode + 1; + + if (charcode < cmap.cur_start) + charcode = cmap.cur_start; + + while(true) + { + var p = new CPointer(); + var values = cmap.cur_values; + var end = cmap.cur_end; + var delta = cmap.cur_delta; + + if ( charcode <= end ) + { + if (values != null) + { + p.data = values.data; + p.pos = values.pos; + p.pos += 2*(charcode - cmap.cur_start); + do + { + var gindex = FT_NEXT_USHORT(p); + if (gindex != 0) + { + gindex = ((gindex + delta) & 0xFFFF); + if (gindex != 0) + { + cmap.cur_charcode = charcode; + cmap.cur_gindex = gindex; + return; + } + } + } while ( ++charcode <= end ); + } + else + { + do + { + var gindex = ((charcode + delta)&0xFFFF); + if (gindex != 0) + { + cmap.cur_charcode = charcode; + cmap.cur_gindex = gindex; + return; + } + } while ( ++charcode <= end ); + } + } + + if (tt_cmap4_set_range(cmap, cmap.cur_range + 1) < 0) + break; + + if (charcode < cmap.cur_start) + charcode = cmap.cur_start; + } + cmap.cur_charcode = 0xFFFFFFFF; + cmap.cur_gindex = 0; +} +function tt_cmap4_char_map_linear(cmap, _charcode, next) +{ + var num_segs2, start, end, offset; + var delta; + var i, num_segs; + var charcode = _charcode; + var gindex = 0; + var base = cmap.cmap.data.pos; + var p = dublicate_pointer(cmap.cmap.data); + p.pos += 6; + + num_segs2 = FT_PEEK_USHORT(p) & ~1; + num_segs = num_segs2 >>> 1; + + if (num_segs == 0) + return {gindex:0,char_code:_charcode}; + + if (next != 0) + charcode++; + + for (; charcode <= 0xFFFF; charcode++) + { + p.pos = base + 14; + var q = dublicate_pointer(p); + q.pos = base + 16 + num_segs2; + + for ( i = 0; i < num_segs; i++ ) + { + end = FT_NEXT_USHORT(p); + start = FT_NEXT_USHORT(q); + + if ( charcode >= start && charcode <= end ) + { + p.pos = q.pos - 2 + num_segs2; + delta = FT_PEEK_SHORT(p); + p.pos += num_segs2; + offset = FT_PEEK_USHORT(p); + + if (i >= num_segs - 1 && start == 0xFFFF && end == 0xFFFF) + { + var face = cmap.cmap.cmap.charmap.face; + var limit = face.cmap_table.pos + face.cmap_size; + if (offset != 0 && p.pos + offset + 2 > limit) + { + delta = 1; + offset = 0; + } + } + + if (offset == 0xFFFF) + continue; + + if (offset != 0) + { + p.pos += offset + (charcode - start) * 2; + gindex = FT_PEEK_USHORT(p); + if (gindex != 0) + gindex = (gindex + delta) & 0xFFFF; + } + else + gindex = (charcode + delta) & 0xFFFF; + + break; + } + } + + if (next == 0 || gindex != 0) + break; + } + + if (next != 0 && gindex != 0) + return {gindex:gindex,char_code:charcode}; + + return {gindex:gindex,char_code:_char_code}; +} +function tt_cmap4_char_map_binary(cmap, _charcode, next) +{ + var num_segs2, start, end, offset; + var delta; + var max, min, mid, num_segs; + var __charcode = _charcode; + var charcode = _charcode; + var gindex = 0; + var p = dublicate_pointer(cmap.cmap.data); + var base = p.pos; + + p.pos += 6; + num_segs2 = FT_PEEK_USHORT(p) & ~1; + + if (num_segs2 == 0) + return {gindex:gindex,char_code:__charcode}; + + num_segs = num_segs2 >>> 1; + + mid = num_segs; + end = 0xFFFF; + + if (next != 0) + charcode++; + + min = 0; + max = num_segs; + + while (min < max) + { + mid = (min + max) >>> 1; + p.pos = base + 14 + mid * 2; + end = FT_PEEK_USHORT(p); + p.pos += 2 + num_segs2; + start = FT_PEEK_USHORT(p); + + if (charcode < start) + max = mid; + else if (charcode > end) + min = mid + 1; + else + { + p.pos += num_segs2; + delta = FT_PEEK_SHORT(p); + p.pos += num_segs2; + offset = FT_PEEK_USHORT(p); + + if (mid >= num_segs - 1 && start == 0xFFFF && end == 0xFFFF) + { + var face = cmap.cmap.cmap.charmap.face; + var limit = face.cmap_table.pos + face.cmap_size; + if (offset && p.pos + offset + 2 > limit) + { + delta = 1; + offset = 0; + } + } + + if ((cmap.flags & 2) != 0) + { + var i; + max = mid; + if (offset == 0xFFFF) + mid = max + 1; + + for (i = max ; i > 0; i--) + { + var old_p = p.pos; + p.pos = base + 14 + (i - 1) * 2; + var prev_end = FT_PEEK_USHORT(p); + + if ( charcode > prev_end ) + { + p.pos = old_p.pos; + break; + } + + end = prev_end; + p.pos += 2 + num_segs2; + start = FT_PEEK_USHORT(p); + p.pos += num_segs2; + delta = FT_PEEK_SHORT(p); + p.pos += num_segs2; + offset = FT_PEEK_USHORT(p); + + if (offset != 0xFFFF) + mid = i - 1; + } + + if (mid == max + 1) + { + if (i != max) + { + p.pos = base + 14 + max * 2; + end = FT_PEEK_USHORT(p); + p.pos += 2 + num_segs2; + start = FT_PEEK_USHORT(p); + p.pos += num_segs2; + delta = FT_PEEK_SHORT(p); + p.pos += num_segs2; + offset = FT_PEEK_USHORT(p); + } + mid = max; + for (i = max + 1; i < num_segs; i++) + { + p.pos = base + 14 + i * 2; + var next_end = FT_PEEK_USHORT(p); + p.pos += 2 + num_segs2; + var next_start = FT_PEEK_USHORT(p); + + if (charcode < next_start) + break; + + end = next_end; + start = next_start; + p.pos += num_segs2; + delta = FT_PEEK_SHORT(p); + p.pos += num_segs2; + offset = FT_PEEK_USHORT(p); + + if (offset != 0xFFFF) + mid = i; + } + i--; + + if (mid == max) + { + mid = i; + break; + } + } + + if (mid != i) + { + p.pos = base + 14 + mid * 2; + end = FT_PEEK_USHORT(p); + p.pos += 2 + num_segs2; + start = FT_PEEK_USHORT(p); + p.pos += num_segs2; + delta = FT_PEEK_SHORT(p); + p.pos += num_segs2; + offset = FT_PEEK_USHORT(p); + } + } + else + { + if (offset == 0xFFFF) + break; + } + + if (offset != 0) + { + p.pos += offset + (charcode - start) * 2; + gindex = FT_PEEK_USHORT(p); + if (gindex != 0) + gindex = (gindex + delta) & 0xFFFF; + } + else + gindex = (charcode + delta) & 0xFFFF; + + break; + } + } + + if (next != 0) + { + if ( charcode > end ) + { + mid++; + if ( mid == num_segs ) + return {gindex:0,char_code:__charcode}; + } + + if (tt_cmap4_set_range(cmap, mid) != 0) + { + if (gindex != 0) + __charcode = charcode; + } + else + { + cmap.cur_charcode = charcode; + if (gindex != 0) + cmap.cur_gindex = gindex; + else + { + cmap.cur_charcode = charcode; + tt_cmap4_next(cmap); + gindex = cmap.cur_gindex; + } + + if (gindex != 0) + __charcode = cmap.cur_charcode; + } + } + + return {gindex:gindex,char_code:__charcode}; +} +function tt_cmap4_char_index(cmap,char_code) +{ + if (char_code >= 0x10000) + return 0; + + if ((cmap.cmap.flags & 1) != 0) + return tt_cmap4_char_map_linear(cmap, char_code, 0).gindex; + else + return tt_cmap4_char_map_binary(cmap, char_code, 0).gindex; +} +function tt_cmap4_char_next(cmap,char_code) +{ + var gindex = 0; + var _char_code = char_code; + if (_char_code >= 0xFFFF) + return {gindex:gindex,char_code:_char_code}; + + if ((cmap.flags & 1) != 0) + { + var r = tt_cmap4_char_map_linear(cmap, char_code, 1); + gindex = r.gindex; + _char_code = r.char_code; + } + else + { + if (_char_code == cmap.cur_charcode) + { + tt_cmap4_next(cmap); + gindex = cmap.cur_gindex; + if (gindex) + _char_code = cmap.cur_charcode; + } + else + { + var r = tt_cmap4_char_map_binary(cmap, char_code, 1); + gindex = r.gindex; + _char_code = r.char_code; + } + } + return {gindex:gindex,char_code:_char_code}; +} +function tt_cmap4_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap4_init,null,tt_cmap4_char_index,tt_cmap4_char_next,null,null,null,null,null); + this.format = 4; + this.validate = function(table, valid) + { + var p = dublicate_pointer(table); + p.pos += 2; + var length = FT_NEXT_USHORT(p); + var error = 0; + + if (length < 16) + return FT_Common.FT_Err_Invalid_Table; + + if (table.pos + length > valid.limit) + { + if (valid.level >= 1) + return FT_Common.FT_Err_Invalid_Table; + + length = (valid.limit - table.pos); + } + + p.pos = table.pos + 6; + var num_segs = FT_NEXT_USHORT(p); + + if (valid.level >= 2) + { + if ((num_segs & 1) != 0) + return FT_Common.FT_Err_Invalid_Table; + } + + num_segs >>>= 1; + + if (length < 16 + num_segs * 2 * 4) + return FT_Common.FT_Err_Invalid_Table; + + if (valid.level >= 2) + { + var search_range = FT_NEXT_USHORT(p); + var entry_selector = FT_NEXT_USHORT(p); + var range_shift = FT_NEXT_USHORT(p); + + if (((search_range | range_shift) & 1) != 0) + return FT_Common.FT_Err_Invalid_Table; + + search_range >>>= 1; + range_shift >>>= 1; + + if (search_range > num_segs || search_range * 2 < num_segs || search_range + range_shift != num_segs || + search_range != (1 << entry_selector)) + return FT_Common.FT_Err_Invalid_Table; + } + + var ends = table.pos + 14; + var starts = table.pos + 16 + num_segs * 2; + var deltas = starts + num_segs * 2; + var offsets = deltas + num_segs * 2; + var glyph_ids = offsets + num_segs * 2; + + if (valid.level >= 2) + { + p.pos = ends + (num_segs - 1) * 2; + if (FT_PEEK_USHORT(p) != 0xFFFF) + return FT_Common.FT_Err_Invalid_Table; + } + + var start, end, offset, n; + var last_start = 0, last_end = 0; + var delta; + var p_start = new CPointer(); p_start.data = p.data; p_start.pos = starts; + var p_end = new CPointer(); p_end.data = p.data; p_end.pos = ends; + var p_delta = new CPointer(); p_delta.data = p.data; p_delta.pos = deltas; + var p_offset = new CPointer(); p_offset.data = p.data; p_offset.pos = offsets; + + for ( n = 0; n < num_segs; n++ ) + { + p.pos = p_offset.pos; + start = FT_NEXT_USHORT(p_start); + end = FT_NEXT_USHORT(p_end); + delta = FT_NEXT_SHORT(p_delta); + offset = FT_NEXT_USHORT(p_offset); + + if (start > end) + return FT_Common.FT_Err_Invalid_Table;; + + if (start <= last_end && n > 0) + { + if (valid.level >= 1) + return FT_Common.FT_Err_Invalid_Table; + else + { + if (last_start > start || last_end > end) + error |= 1; + else + error |= 2; + } + } + + if (offset && offset != 0xFFFF) + { + p.pos += offset; + if (valid.level >= 1) + { + if (p.pos < glyph_ids || p.pos + (end - start + 1) * 2 > table.pos + length) + return FT_Common.FT_Err_Invalid_Table; + } + else if (n != num_segs - 1 || !(start == 0xFFFF && end == 0xFFFF)) + { + if (p.pos < glyph_ids || p.pos + (end - start + 1) * 2 > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + } + + if (valid.level >= 1) + { + var idx; + for (var i = start; i < end; i++ ) + { + idx = FT_NEXT_USHORT(p); + if (idx != 0) + { + idx = (idx + delta) & 0xFFFF; + if (idx >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + } + } + } + } + else if (offset == 0xFFFF) + { + if (valid.level >= 2 || n != num_segs - 1 || !( start == 0xFFFF && end == 0xFFFF)) + return FT_Common.FT_Err_Invalid_Table; + } + + last_start = start; + last_end = end; + } + + return error; + } + this.get_cmap_info = function(cmap, cmap_info) + { + var data = cmap.cmap.data; + data.pos += 4; + cmap_info.format = 4; + cmap_info.language = FT_PEEK_USHORT(data); + data.pos -= 4; + return 0; + } +} +// cmap6 ---------------------------------------------------------------------------------- +function tt_cmap6_char_index(cmap, char_code) +{ + var p = dublicate_pointer(cmap.data); + p.pos += 6; + var result = 0; + var start = FT_NEXT_USHORT(p); + var count = FT_NEXT_USHORT(p); + var idx = char_code - start; + + if ( idx < count ) + { + p.pos += 2 * idx; + result = FT_PEEK_USHORT(p); + } + return result; +} +function tt_cmap6_char_next(cmap, _char_code) +{ + var p = dublicate_pointer(cmap.data); + p.pos += 6; + var result = 0; + var char_code = _char_code + 1; + var gindex = 0; + + var start = FT_NEXT_USHORT(p); + var count = FT_NEXT_USHORT(p); + + if (char_code >= 0x10000) + return {gindex:gindex,char_code:_char_code}; + + if (char_code < start) + char_code = start; + + var idx = char_code - start; + p.pos += 2 * idx; + for (; idx < count; idx++) + { + gindex = FT_NEXT_USHORT(p); + if (gindex != 0) + { + result = char_code; + break; + } + char_code++; + } + return {gindex:gindex,char_code:result}; +} +function tt_cmap6_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap_init,null,tt_cmap6_char_index,tt_cmap6_char_next,null,null,null,null,null); + this.format = 6; + this.validate = function(table, valid) + { + var base = table.pos; + var p = new CPointer(); + p.data = table.data; + + if (base + 10 > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + + p.pos = base + 2; + var length = FT_NEXT_USHORT(p); + p.pos = base + 8; + var count = FT_NEXT_USHORT(p); + + if (base + length > valid.limit || length < 10 + count * 2) + return FT_Common.FT_Err_Invalid_Table; + + if (valid.level >= 1) + { + var gindex; + for (; count > 0; count--) + { + gindex = FT_NEXT_USHORT(p); + if (gindex >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + } + } + return 0; + } + this.get_cmap_info = function(cmap, cmap_info) + { + var data = cmap.data; + data.pos += 4; + cmap_info.format = 6; + cmap_info.language = FT_PEEK_USHORT(data); + data.pos -= 4; + return 0; + } +} +// cmap8 ---------------------------------------------------------------------------------- +function tt_cmap8_char_index(cmap, char_code) +{ + var result = 0; + var p = dublicate_pointer(cmap.cmap.data); + p.pos += 8204; + var num_groups = FT_NEXT_ULONG(p); + var start, end, start_id; + for (; num_groups > 0; num_groups--) + { + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p); + start_id = FT_NEXT_ULONG(p); + + if (char_code < start) + break; + + if (char_code <= end) + { + result = (start_id + char_code - start); + break; + } + } + return result; +} +function tt_cmap8_char_next(cmap, _char_code) +{ + var result = 0; + var char_code = _char_code + 1; + var gindex = 0; + var p = dublicate_pointer(cmap.cmap.data); + p.pos += 8204; + var num_groups = FT_NEXT_ULONG(p); + var start, end, start_id; + + for ( ; num_groups > 0; num_groups-- ) + { + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p); + start_id = FT_NEXT_ULONG(p); + + if (char_code < start) + char_code = start; + + if (char_code <= end) + { + gindex = (char_code - start + start_id); + if ( gindex != 0 ) + { + result = char_code; + break; + } + } + } + return {gindex:gindex,char_code:result}; +} +function tt_cmap8_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap_init,null,tt_cmap8_char_index,tt_cmap8_char_next,null,null,null,null,null); + this.format = 8; + this.validate = function(table, valid) + { + var base = table.pos; + var p = dublicate_pointer(table); + p.pos += 4; + + if (base + 16 + 8192 > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + + var length = FT_NEXT_ULONG(p); + if (length > (valid.limit - base) || length < 8192 + 16) + return FT_Common.FT_Err_Invalid_Table; + + var is32 = base + 12; + p.pos = is32 + 8192; + var num_groups = FT_NEXT_ULONG(p); + + if (p.pos + num_groups * 12 > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + + var n, start, end, start_id, count, last = 0; + for ( n = 0; n < num_groups; n++ ) + { + var hi, lo; + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p ); + start_id = FT_NEXT_ULONG(p); + + if (start > end) + return FT_Common.FT_Err_Invalid_Table; + + if (n > 0 && start <= last) + return FT_Common.FT_Err_Invalid_Table; + + if (valid.level >= 1) + { + if (start_id + end - start >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + + count = (end - start + 1); + if ((start & ~0xFFFF) != 0) + { + for (; count > 0; count--, start++) + { + hi = (start >>> 16); + lo = (start & 0xFFFF); + + if ((p.data[is32 + hi >>> 3] & (0x80 >>> (hi & 7))) == 0) + return FT_Common.FT_Err_Invalid_Table; + + if ((p.data[is32 + lo >>> 3] & (0x80 >>> (lo & 7))) == 0) + return FT_Common.FT_Err_Invalid_Table; + } + } + else + { + if ((end & ~0xFFFF) != 0) + return FT_Common.FT_Err_Invalid_Table; + + for ( ; count > 0; count--, start++ ) + { + lo = (start & 0xFFFF); + if ((p.data[is32 + lo >>> 3] & (0x80 >>> (lo & 7))) != 0) + return FT_Common.FT_Err_Invalid_Table; + } + } + } + last = end; + } + + return 0; + } + this.get_cmap_info = function(cmap, cmap_info) + { + var data = cmap.cmap.data; + data.pos += 8; + cmap_info.format = 8; + cmap_info.language = FT_PEEK_ULONG(data); + data.pos -= 8; + return 0; + } +} +// cmap10 --------------------------------------------------------------------------------- +function tt_cmap10_char_index(cmap, char_code) +{ + var p = dublicate_pointer(cmap.cmap.data); + p.pos += 12; + var result = 0; + var start = FT_NEXT_ULONG(p); + var count = FT_NEXT_ULONG(p); + var idx = (char_code - start); + + if (idx < count) + { + p.pos += 2 * idx; + result = FT_PEEK_USHORT(p); + } + return result; +} +function tt_cmap10_char_next(cmap, _char_code) +{ + var p = dublicate_pointer(cmap.cmap.data); + p.pos += 12; + var char_code = _char_code + 1; + var gindex = 0; + var start = FT_NEXT_ULONG(p); + var count = FT_NEXT_ULONG(p); + + if (char_code < start) + char_code = start; + + var idx = char_code - start; + p.pos += 2 * idx; + + for (; idx < count; idx++) + { + gindex = FT_NEXT_USHORT(p); + if (gindex != 0) + break; + char_code++; + } + return {gindex:gindex,char_code:char_code}; +} +function tt_cmap10_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap_init,null,tt_cmap10_char_index,tt_cmap10_char_next,null,null,null,null,null); + this.format = 10; + this.validate = function(table, valid) + { + var p = dublicate_pointer(table); + var base = table.pos; + p.pos += 4; + + if (base + 20 > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + + var length = FT_NEXT_ULONG(p); + p.pos = base + 16; + var count = FT_NEXT_ULONG(p); + + if (length > (valid.limit - base) || length < 20 + count * 2) + return FT_Common.FT_Err_Invalid_Table; + + if (valid.level >= 1) + { + var gindex; + for (; count > 0; count--) + { + gindex = FT_NEXT_USHORT(p); + if (gindex >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + } + } + return 0; + } + this.get_cmap_info = function(cmap, cmap_info) + { + var data = cmap.cmap.data; + data.pos += 8; + cmap_info.format = 10; + cmap_info.language = FT_PEEK_ULONG(data); + data.pos -= 8; + return 0; + } +} +// cmap12 --------------------------------------------------------------------------------- +function TT_CMap12Rec() +{ + this.cmap = new TT_CMapRec(); + this.valid; + this.cur_charcode; + this.cur_gindex; + this.cur_group; + this.num_groups; + + this.type = FT_Common.FT_CMAP_12; +} +function tt_cmap12_init(cmap, table) +{ + cmap.cmap.data = dublicate_pointer(table); + table.pos += 12; + cmap.num_groups = FT_PEEK_ULONG(table); + table.pos -= 12; + cmap.valid = 0; + return 0; +} +function tt_cmap12_next(cmap) +{ + if (cmap.cur_charcode >= 0xFFFFFFFF) + { + cmap.valid = 0; + return; + } + + var p = dublicate_pointer(cmap.cmap.data); + var base = p.pos; + var start, end, start_id; + var gindex; + + var char_code = cmap.cur_charcode + 1; + for (var n = cmap.cur_group; n < cmap.num_groups; n++) + { + p.pos = base + 16 + 12 * n; + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p); + start_id = FT_PEEK_ULONG(p); + + if (char_code < start) + char_code = start; + + for ( ; char_code <= end; char_code++ ) + { + gindex = (start_id + char_code - start); + if (gindex != 0) + { + cmap.cur_charcode = char_code; + cmap.cur_gindex = gindex; + cmap.cur_group = n; + return; + } + } + } + cmap.valid = 0; +} +function tt_cmap12_char_map_binary(cmap, _char_code, next) +{ + var gindex = 0; + var p = dublicate_pointer(cmap.cmap.data); + var base = p.pos; + p.pos += 12; + var num_groups = FT_PEEK_ULONG(p); + var char_code = _char_code; + var __char_code = _char_code; + var start, end, start_id; + var max, min, mid; + + if (num_groups == 0) + return {gindex:gindex,char_code:__char_code}; + + mid = num_groups; + end = 0xFFFFFFFF; + + if (next != 0) + char_code++; + + min = 0; + max = num_groups; + + while (min < max) + { + mid = (min + max) >>> 1; + p.pos = base + 16 + 12 * mid; + + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p); + + if (char_code < start) + max = mid; + else if (char_code > end) + min = mid + 1; + else + { + start_id = FT_PEEK_ULONG(p); + gindex = (start_id + char_code - start); + break; + } + } + + if (next != 0) + { + if (char_code > end) + { + mid++; + if (mid == num_groups) + return 0; + } + + cmap.valid = 1; + cmap.cur_charcode = char_code; + cmap12.cur_group = mid; + + if (gindex == 0) + { + tt_cmap12_next(cmap); + + if (cmap.valid == 1) + gindex = cmap.cur_gindex; + } + else + cmap.cur_gindex = gindex; + + if (gindex != 0) + __char_code = cmap.cur_charcode; + } + + return {gindex:gindex,char_code:__char_code}; +} +function tt_cmap12_char_index(cmap, char_code) +{ + return tt_cmap12_char_map_binary(cmap, char_code, 0).gindex; +} +function tt_cmap12_char_next(cmap, _char_code) +{ + var gindex = 0; + var __char_code = _char_code; + + if (cmap.cur_charcode >= 0xFFFFFFFF) + return {gindex:gindex,char_code:__char_code}; + + if (cmap12.valid == 1 && cmap.cur_charcode == _char_code) + { + tt_cmap12_next(cmap); + if (1 == cmap.valid) + { + gindex = cmap.cur_gindex; + if (gindex != 0) + __char_code = cmap.cur_charcode; + } + else + gindex = 0; + } + else + return tt_cmap12_char_map_binary(cmap, _char_code, 1); + + return {gindex:gindex,char_code:__char_code}; +} +function tt_cmap12_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap12_init,null,tt_cmap12_char_index,tt_cmap12_char_next,null,null,null,null,null); + this.format = 12; + this.validate = function(table, valid) + { + var base = table.pos; + var p = dublicate_pointer(table); + if (p.pos + 16 > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + p.pos = base + 4; + var length = FT_NEXT_ULONG(p); + p.pos = base + 12; + var num_groups = FT_NEXT_ULONG(p); + if (length > (valid.limit - base) || length < 16 + 12 * num_groups) + return FT_Common.FT_Err_Invalid_Table; + var n, start, end, start_id, last = 0; + for (n = 0; n < num_groups; n++) + { + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p); + start_id = FT_NEXT_ULONG(p); + + if (start > end) + return FT_Common.FT_Err_Invalid_Table; + if (n > 0 && start <= last) + return FT_Common.FT_Err_Invalid_Table; + if (valid.level >= 1) + { + if (start_id + end - start >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + } + last = end; + } + return 0; + } + this.get_cmap_info = function(cmap, cmap_info) + { + var data = cmap.cmap.data; + data.pos += 8; + cmap_info.format = 12; + cmap_info.language = FT_PEEK_ULONG(data); + data.pos -= 8; + return 0; + } +} +// cmap13 --------------------------------------------------------------------------------- +function TT_CMap13Rec() +{ + this.cmap = new TT_CMapRec(); + this.valid; + this.cur_charcode; + this.cur_gindex; + this.cur_group; + this.num_groups; + + this.type = FT_Common.FT_CMAP_13; +} +function tt_cmap13_init(cmap, table) +{ + cmap.cmap.data = dublicate_pointer(table); + table.pos += 12; + cmap.num_groups = FT_PEEK_ULONG(table); + table.pos -= 12; + cmap.valid = 0; + return 0; +} +function tt_cmap13_next(cmap) +{ + if (cmap.cur_charcode >= 0xFFFFFFFF) + { + cmap.valid = 0; + return; + } + + var p = dublicate_pointer(cmap.cmap.data); + var base = p.pos; + var start, end, glyph_id, char_code; + var gindex; + + char_code = cmap.cur_charcode + 1; + for (var n = cmap.cur_group; n < cmap.num_groups; n++ ) + { + p.pos = base + 16 + 12 * n; + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p); + glyph_id = FT_PEEK_ULONG(p); + + if (char_code < start) + char_code = start; + + if ( char_code <= end ) + { + gindex = glyph_id; + if (gindex != 0) + { + cmap.cur_charcode = char_code; + cmap.cur_gindex = gindex; + cmap.cur_group = n; + return; + } + } + } + cmap.valid = 0; +} +function tt_cmap13_char_map_binary(cmap, _char_code, next) +{ + var gindex = 0; + var p = dublicate_pointer(cmap.cmap.data); + var base = p.pos; + p.pos += 12; + var num_groups = FT_PEEK_ULONG(p); + var char_code = _char_code; + var __char_code = _char_code; + var start, end; + var max, min, mid; + + if (num_groups == 0) + return {gindex:gindex,char_code:__char_code}; + + mid = num_groups; + end = 0xFFFFFFFF; + + if (next != 0) + char_code++; + + min = 0; + max = num_groups; + + while (min < max) + { + mid = (min + max) >>> 1; + p.pos = base + 16 + 12 * mid; + + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p); + + if (char_code < start) + max = mid; + else if (char_code > end) + min = mid + 1; + else + { + gindex = FT_PEEK_ULONG(p); + break; + } + } + + if (next != 0) + { + if (char_code > end) + { + mid++; + if (mid == num_groups) + return 0; + } + + cmap.valid = 1; + cmap.cur_charcode = char_code; + cmap.cur_group = mid; + + if (gindex == 0) + { + tt_cmap13_next( cmap13 ); + if (cmap.valid == 1) + gindex = cmap.cur_gindex; + } + else + cmap.cur_gindex = gindex; + + if (gindex != 0) + __char_code = cmap.cur_charcode; + } + + return {gindex:gindex,char_code:__char_code}; +} +function tt_cmap13_char_index(cmap, char_code) +{ + return tt_cmap13_char_map_binary(cmap, char_code, 0).gindex; +} +function tt_cmap13_char_next(cmap, _char_code) +{ + if (cmap.cur_charcode >= 0xFFFFFFFF) + return {gindex:0,char_code:_char_code}; + + var gindex; + var __char_code = _char_code; + if (cmap.valid == 1 && cmap.cur_charcode == _char_code) + { + tt_cmap13_next(cmap); + if (cmap.valid == 1) + { + gindex = cmap.cur_gindex; + if (gindex != 0) + __char_code = cmap.cur_charcode; + } + else + gindex = 0; + } + else + return tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); + + return {gindex:gindex,char_code:__char_code}; +} +function tt_cmap13_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap13_init,null,tt_cmap13_char_index,tt_cmap13_char_next,null,null,null,null,null); + this.format = 13; + this.validate = function(table, valid) + { + var p = dublicate_pointer(table); + var base = p.pos; + + if (bae + 16 > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + + p.pos = base + 4; + var length = FT_NEXT_ULONG(p); + p.pos = base + 12; + var num_groups = FT_NEXT_ULONG(p); + + if (length > (valid.limit - base) || length < 16 + 12 * num_groups) + return FT_Common.FT_Err_Invalid_Table; + + var start, end, glyph_id, last = 0; + for (var n = 0; n < num_groups; n++) + { + start = FT_NEXT_ULONG(p); + end = FT_NEXT_ULONG(p); + glyph_id = FT_NEXT_ULONG(p); + + if (start > end) + return FT_Common.FT_Err_Invalid_Table; + + if (n > 0 && start <= last) + return FT_Common.FT_Err_Invalid_Table; + + if (valid.level >= 1) + { + if (glyph_id >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + } + + last = end; + } + return 0; + } + this.get_cmap_info = function(cmap, cmap_info) + { + var data = cmap.data; + data.pos += 8; + cmap_info.format = 13; + cmap_info.language = FT_PEEK_ULONG(data); + data.pos -= 8; + return 0; + } +} +// cmap14 --------------------------------------------------------------------------------- +function TT_CMap14Rec() +{ + this.cmap = new TT_CMapRec(); + this.num_selectors; + this.max_results; + this.results = null; + + this.type = FT_Common.FT_CMAP_14; +} +function tt_cmap14_done(cmap) +{ + cmap.results = null; +} +function tt_cmap14_ensure(cmap, num_results, memory) +{ + var old_max = cmap.max_results; + if (num_results > cmap.max_results) + { + var c = num_results - old_max; + for (;c>0;c--) + cmap.results[old_max+c-1] = 0; + cmap.max_results = num_results; + } + return 0; +} +function tt_cmap14_init(cmap, table) +{ + cmap.cmap.data = dublicate_pointer(table); + table.pos += 6; + cmap.num_selectors = FT_PEEK_ULONG(table); + table.pos -= 6; + cmap.max_results = 0; + cmap.results = null; + return 0; +} +function tt_cmap14_char_index(cmap,char_code) +{ + return 0; +} +function tt_cmap14_char_next(cmap, _char_code) +{ + return {gindex:0,char_code:0}; +} +function tt_cmap14_char_map_def_binary(base, char_code) +{ + var p = dublicate_pointer(base); + var numRanges = FT_PEEK_ULONG(p); + var min = 0; + var max = numRanges; + + while (min < max) + { + var mid = (min + max) >>> 1; + p.pos = base.pos + 4 + 4 * mid; + var start = FT_NEXT_UOFF3(p); + var cnt = FT_NEXT_BYTE(p); + + if (char_code < start) + max = mid; + else if (char_code > start+cnt) + min = mid + 1; + else + return 1; + } + return 0; +} +function tt_cmap14_char_map_nondef_binary(base, char_code) +{ + var p = dublicate_pointer(base); + var numMappings = FT_PEEK_ULONG(p); + var min = 0; + var max = numMappings; + + while (min < max) + { + var mid = (min + max) >>> 1; + p.pos = base.pos + 4 + 5 * mid; + var uni = FT_NEXT_UOFF3(p); + + if (char_code < uni) + max = mid; + else if (char_code > uni) + min = mid + 1; + else + return FT_PEEK_USHORT(p); + } + return 0; +} +function tt_cmap14_find_variant(base, variantCode) +{ + var p = dublicate_pointer(base); + var numVar = FT_PEEK_ULONG(p); + var min = 0; + var max = numVar; + + while (min < max) + { + var mid = (min + max) >>> 1; + p.pos = base.pos + 4 + 11 * mid; + var varSel = FT_NEXT_UOFF3(p); + + if (variantCode < varSel) + max = mid; + else if (variantCode > varSel) + min = mid + 1; + else + return p; + } + return null; +} +function tt_cmap14_char_var_index(cmap, ucmap, charcode, variantSelector) +{ + var base = dublicate_pointer(cmap.cmap.data); + base.pos += 6; + var p = tt_cmap14_find_variant(base, variantSelector); + if (null == p) + return 0; + + var defOff = FT_NEXT_ULONG(p); + var nondefOff = FT_PEEK_ULONG(p); + + base.pos = cmap.cmap.data.pos + defOff; + if (defOff != 0 && 0 != tt_cmap14_char_map_def_binary(base, charcode)) + { + return ucmap.cmap.clazz.char_index(ucmap.cmap, charcode); + } + + base.pos = cmap.cmap.data.pos + nondefOff; + if (nondefOff != 0) + return tt_cmap14_char_map_nondef_binary(base, charcode); + + return 0; +} +function tt_cmap14_char_var_isdefault(cmap, charcode, variantSelector) +{ + var base = dublicate_pointer(cmap.cmap.data); + var base_pos = base.pos; + base += 6; + var p = tt_cmap14_find_variant(base, variantSelector); + if (null == p) + return -1; + + var defOff = FT_NEXT_ULONG(p); + var nondefOff = FT_NEXT_ULONG(p); + + base.pos = base_pos + defOff; + if (defOff != 0 && 0 != tt_cmap14_char_map_def_binary(base, charcode)) + return 1; + + base.pos = base_pos + nondefOff; + if (nondefOff != 0 && tt_cmap14_char_map_nondef_binary(base, charcode) != 0) + return 0; + + return -1; +} +function tt_cmap14_variants(cmap, memory) +{ + var count = cmap.num_selectors; + var p = dublicate_pointer(cmap.cmap.data); + p.pos += 10; + + if (0 != tt_cmap14_ensure(cmap, (count + 1), memory)) + return null; + + var result = cmap.results; + var i = 0; + for (; i < count; i++) + { + result[i] = FT_NEXT_UOFF3(p); + p.pos += 8; + } + result[i] = 0; + + p.data = result; + p.pos = 0; + return p; +} +function tt_cmap14_char_variants(cmap, memory, charCode) +{ + var count = cmap.num_selectors; + var p = dublicate_pointer(cmap.cmap.data); + var base_pos = p.pos; + p.pos += 10; + + if (0 != tt_cmap14_ensure(cmap, (count + 1), memory)) + return null; + + var p1 = dublicate_pointer(p); + var p2 = dublicate_pointer(p); + + var results = cmap.results; + var q = 0; + for (; count > 0; --count) + { + var varSel = FT_NEXT_UOFF3(p); + var defOff = FT_NEXT_ULONG(p); + var nondefOff = FT_NEXT_ULONG(p); + + p1.pos = base_pos + defOff; + p2.pos = base_pos + nondefOff; + if ((defOff != 0 && 0 != tt_cmap14_char_map_def_binary(p1, charCode)) || + (nondefOff != 0 && 0 != tt_cmap14_char_map_nondef_binary(p2, charCode))) + { + results[q] = varSel; + q++; + } + } + results[q] = 0; + p.data = results; + p.pos = 0; + return p; +} +function tt_cmap14_def_char_count(_p) +{ + var p = dublicate_pointer(_p); + var numRanges = FT_NEXT_ULONG(p); + var tot = 0; + p.pos += 3; + for (; numRanges > 0; numRanges--) + { + tot += 1 + p.data[p.pos]; + p.pos += 4; + } + return tot; +} +function tt_cmap14_get_def_chars(cmap, _p, memory) +{ + var p = dublicate_pointer(_p); + var cnt = tt_cmap14_def_char_count(p); + var numRanges = FT_NEXT_ULONG(p); + + if (0 != tt_cmap14_ensure(cmap, (cnt + 1), memory)) + return null; + + var results = cmap.results; + var q = 0; + for (; numRanges > 0; --numRanges) + { + var uni = FT_NEXT_UOFF3(p); + cnt = FT_NEXT_BYTE(p) + 1; + do + { + results[q] = uni; + uni += 1; + q += 1; + } while (--cnt != 0); + } + results[q] = 0; + p.data = results; + p.pos = 0; + return p; +} +function tt_cmap14_get_nondef_chars(cmap, _p, memory) +{ + var p = dublicate_pointer(_p); + var numMappings = FT_NEXT_ULONG(p); + + if (0 != tt_cmap14_ensure(cmap, (numMappings + 1), memory)) + return null; + + var ret = cmap.results; + var i = 0; + for (; i < numMappings; i++) + { + ret[i] = FT_NEXT_UOFF3(p); + p.pos += 2; + } + ret[i] = 0; + p.data = ret; + p.pos = 0; + return p; +} +function tt_cmap14_variant_chars(cmap, memory, variantSelector) +{ + var base = dublicate_pointer(cmap.cmap.data); + var base_pos = base.pos; + base.pos += 6; + var p = tt_cmap14_find_variant(base, variantSelector); + if (null == p) + return null; + + var defOff = FT_NEXT_ULONG(p); + var nondefOff = FT_NEXT_ULONG(p); + + if (defOff == 0 && nondefOff == 0) + return null; + + base.pos = base_pos + nondefOff; + if (defOff == 0) + return tt_cmap14_get_nondef_chars(cmap, base, memory); + base.pos = base_pos + defOff; + if (nondefOff == 0) + return tt_cmap14_get_def_chars(cmap, base, memory); + + var numRanges; + var numMappings; + var duni; + var dcnt; + var nuni; + var dp; + var di, ni, k; + + var _cmap_data = cmap.cmap.data; + p = dublicate_pointer(_cmap_data); + p.pos += nondefOff; + dp = dublicate_pointer(_cmap_data); + dp.pos += defOff; + + numMappings = FT_NEXT_ULONG(p); + dcnt = tt_cmap14_def_char_count(dp); + numRanges = FT_NEXT_ULONG(dp); + + if (numMappings == 0) + { + var __pp = dublicate_pointer(_cmap_data); + __pp += defOff; + return tt_cmap14_get_def_chars(cmap, _p, memory); + } + if (dcnt == 0) + { + var __pp = dublicate_pointer(_cmap_data); + __pp += nondefOff; + return tt_cmap14_get_nondef_chars(cmap, __p, memory); + } + + if (0 != tt_cmap14_ensure(cmap, (dcnt + numMappings + 1), memory)) + return null; + + var ret = cmap.results; + duni = FT_NEXT_UOFF3(dp); + dcnt = FT_NEXT_BYTE(dp); + di = 1; + nuni = FT_NEXT_UOFF3(p); + p.pos += 2; + ni = 1; + i = 0; + + for ( ;; ) + { + if (nuni > duni + dcnt) + { + for (k = 0; k <= dcnt; k++) + ret[i++] = duni + k; + + ++di; + + if (di > numRanges) + break; + + duni = FT_NEXT_UOFF3(dp); + dcnt = FT_NEXT_BYTE(dp); + } + else + { + if (nuni < duni) + ret[i++] = nuni; + ++ni; + if (ni > numMappings) + break; + + nuni = FT_NEXT_UOFF3(p); + p.pos += 2; + } + } + + if (ni <= numMappings) + { + ret[i++] = nuni; + while (ni < numMappings) + { + ret[i++] = FT_NEXT_UOFF3(p); + p.pos += 2; + ++ni; + } + } + else if (di <= numRanges) + { + for (k = 0; k <= dcnt; k++) + ret[i++] = duni + k; + + while (di < numRanges) + { + duni = FT_NEXT_UOFF3(dp); + dcnt = FT_NEXT_BYTE(dp); + + for (k = 0; k <= dcnt; k++) + ret[i++] = duni + k; + ++di; + } + } + ret[i] = 0; + p.data = ret; + p.pos = 0; + return p; +} +function tt_cmap14_class_rec() +{ + this.clazz = create_cmap_class_rec(0,tt_cmap14_init,tt_cmap14_done,tt_cmap14_char_index,tt_cmap14_char_next, + tt_cmap14_char_var_index,tt_cmap14_char_var_isdefault,tt_cmap14_variants, + tt_cmap14_char_variants,tt_cmap14_variant_chars); + this.format = 14; + this.validate = function(table, valid) + { + var p = dublicate_pointer(table); + var defp = dublicate_pointer(table); + var base = p.pos; + p.pos += 2; + var length = FT_NEXT_ULONG(p); + var num_selectors = FT_NEXT_ULONG(p); + + if (length > (valid.limit - base) || length < 10 + 11 * num_selectors) + return FT_Common.FT_Err_Invalid_Table; + + var n, lastVarSel = 1; + for ( n = 0; n < num_selectors; n++ ) + { + var varSel = FT_NEXT_UOFF3(p); + var defOff = FT_NEXT_ULONG(p); + var nondefOff = FT_NEXT_ULONG(p); + + if (defOff >= length || nondefOff >= length) + return FT_Common.FT_Err_Invalid_Table; + + if (varSel < lastVarSel) + return FT_Common.FT_Err_Invalid_Table; + + lastVarSel = varSel + 1; + if (defOff != 0) + { + defp.pos = base + defOff; + var numRanges = FT_NEXT_ULONG(defp); + var lastBase = 0; + + if (defp.pos + numRanges * 4 > valid.limit) + return FT_Common.FT_Err_Invalid_Table; + + for (var i = 0; i < numRanges; ++i) + { + var _base = FT_NEXT_UOFF3(defp); + var cnt = FT_NEXT_BYTE(defp); + + if (_base + cnt >= 0x110000) + return FT_Common.FT_Err_Invalid_Table; + + if (_base < lastBase) + return FT_Common.FT_Err_Invalid_Table; + + lastBase = _base + cnt + 1; + } + } + + if (nondefOff != 0) + { + defp.pos = base + nondefOff; + var numMappings = FT_NEXT_ULONG(defp); + var lastUni = 0; + + if (numMappings * 4 > (valid.limit - defp.pos)) + return FT_Common.FT_Err_Invalid_Table; + + for (var i = 0; i < numMappings; ++i) + { + var uni = FT_NEXT_UOFF3(defp); + var gid = FT_NEXT_USHORT(defp); + + if ( uni >= 0x110000) + return FT_Common.FT_Err_Invalid_Table; + if (uni < lastUni) + return FT_Common.FT_Err_Invalid_Table; + lastUni = uni + 1; + if (valid.level >= 1 && gid >= valid.num_glyphs) + return FT_Common.FT_Err_Invalid_Glyph_Index; + } + } + } + + return 0; + } + this.get_cmap_info = function(cmap, cmap_info) + { + cmap_info.format = 14; + cmap_info.language = 0xFFFFFFFF; + return 0; + } +} +// finally +function tt_face_build_cmaps(face) +{ + var table = dublicate_pointer(face.cmap_table); + + if (null == table) + return FT_Common.FT_Err_Invalid_Table; + + var limit = table.pos + face.cmap_size; + var p = dublicate_pointer(table); + + if (p.data == null || p.pos + 4 > limit) + return FT_Common.FT_Err_Invalid_Table; + + if (FT_NEXT_USHORT(p) != 0) + return FT_Common.FT_Err_Invalid_Table; + + var num_cmaps = FT_NEXT_USHORT(p); + //#ifdef FT_MAX_CHARMAP_CACHEABLE + if (num_cmaps > FT_Common.FT_MAX_CHARMAP_CACHEABLE) + { + } + //#endif + + var pclazz = FT_TT_CMAP_CLASSES_GET; + var pclazz_len = pclazz.length; + var clazz; + for (; num_cmaps > 0 && p.pos + 8 <= limit; num_cmaps--) + { + var charmap = new FT_CharMapRec(); + charmap.platform_id = FT_NEXT_USHORT(p); + charmap.encoding_id = FT_NEXT_USHORT(p); + charmap.face = face; + charmap.encoding = FT_Common.FT_ENCODING_NONE; + var offset = FT_NEXT_ULONG(p); + + if (offset && offset <= face.cmap_size - 2) + { + var cmap = dublicate_pointer(table); + cmap.pos += offset; + var format = FT_PEEK_USHORT(cmap); + for (var i = 0; i < pclazz_len; i++) + { + clazz = pclazz[i]; + if (clazz.format == format) + { + var valid = new TT_Validator(); + valid.base = cmap; + valid.limit = limit; + valid.level = 0; + valid.error = 0; + valid.num_glyphs = face.max_profile.numGlyphs; + + var error = clazz.validate(cmap, valid); + if (error == 0) + { + var ttcmap = FT_CMap_New(clazz, cmap, charmap); + if (null != ttcmap) + { + ttcmap.flags = 0; + } + } + break; + } + } + } + } + return 0; +} +function tt_get_cmap_info(cmap, cmap_info) +{ + var clazz = __FT_CMapRec(cmap).clazz; + return clazz.get_cmap_info(cmap, cmap_info); +} +/******************************************************************************/ +// driver +/******************************************************************************/ +function tt_face_load_sfnt_header_stub(face,stream,face_index,header) +{ + return FT_Common.FT_Err_Unimplemented_Feature; +} +function tt_face_load_directory_stub(face,stream,header) +{ + return FT_Common.FT_Err_Unimplemented_Feature; +} +function tt_face_load_hdmx_stub(face,stream) +{ + return FT_Common.FT_Err_Unimplemented_Feature; +} +function tt_face_free_hdmx_stub(face) +{ +} +function tt_face_set_sbit_strike_stub(face,x_ppem,y_ppem) +{ + var req = new FT_Size_RequestRec(); + req.type = FT_Common.FT_SIZE_REQUEST_TYPE_NOMINAL; + req.width = x_ppem; + req.height = y_ppem; + req.horiResolution = 0; + req.vertResolution = 0; + + var strikeindex = 0x7FFFFFFF; + return tt_face_set_sbit_strike(face, req, strikeindex); +} + +function tt_face_load_sbit_stub(face,stream) +{ + return FT_Common.FT_Err_Unimplemented_Feature; +} +function tt_face_free_sbit_stub(face) +{ +} + +function tt_face_load_charmap_stub(face,cmap,input) +{ + return FT_Common.FT_Err_Unimplemented_Feature; +} +function tt_face_free_charmap_stub(face,cmap) +{ + return 0; +} + +function get_sfnt_table(face, tag) +{ + var table = null; + switch ( tag ) + { + case 0: + table = face.header; + break; + case 3: + table = face.horizontal; + break; + case 4: + table = (face.vertical_info == 1) ? face.vertical : null; + break; + case 2: + table = (face.os2.version == 0xFFFF) ? null : face.os2; + break; + case 5: + table = face.postscript; + break; + case 1: + table = face.max_profile; + break; + case 6: + table = (face.pclt.Version != 0) ? face.pclt : null; + break; + default: + break; + } + return table; +} +function sfnt_table_info(face, idx, tag) +{ + if (tag != null) + return {tag:0,offset:0,length:face.num_tables}; + + if (idx >= face.num_tables) + return null; + var t = face.dir_tables[idx]; + return {tag:t.Tag,offset:t.Offset,length:t.Length}; +} +function ft_mem_strcpyn(dst, src, size) +{ + var len = src.length; + var ret = 1; + if (len > size) + { + len = size; + ret = 0; + } + var i=0; + while (len > 1) + { + dst[dst.pos + i] = src.charCodeAt(i); + i++; + size--; + } + dst[dst.pos + i] = 0; + return ret; +} +function sfnt_get_glyph_name(face, glyph_index, buffer, buffer_max) +{ + var gname = tt_face_get_ps_name(face, glyph_index); + var error = FT_Error; + if (error == 0) + ft_mem_strcpyn(buffer, gname, buffer_max); + return error; +} +function sfnt_get_name_index(face, glyph_name) +{ + var max_gid = 0xFFFFFFFF; + if (face.num_glyphs < 0) + return 0; + else if (face.num_glyphs < 0xFFFFFFFF) + max_gid = face.num_glyphs; + for (var i = 0; i < max_gid; i++) + { + var gname = tt_face_get_ps_name(face, i); + var error = FT_Error; + if (error != 0) + continue; + + if (glyph_name == gname) + return i; + } + return 0; +} +function sfnt_get_ps_name(face) +{ + var n, found_win, found_apple; + var result = ""; + + if (face.postscript_name != "") + return face.postscript_name; + + found_win = -1; + found_apple = -1; + + var num_faces = face.num_faces; + for (n = 0; n < num_faces; n++) + { + var name = face.name_table.names[n]; + if (name.nameID == 6 && name.stringLength > 0) + { + if (name.platformID == 3 && name.encodingID == 1 && name.languageID == 0x409) + found_win = n; + + if (name.platformID == 1 && name.encodingID == 0 && name.languageID == 0) + found_apple = n; + } + } + + if (found_win != -1) + { + var stream = face.name_table.stream; + var name = face.name_table.names[found_win]; + var len = parseInt(name.stringLength / 2); + + var error = stream.Seek(name.stringOffset); + if (error == 0) + error = stream.EnterFrame(name.stringLength); + if (error != 0) + { + name.stringOffset = 0; + name.stringLength = 0; + face.postscript_name = ""; + return ""; + } + var d = stream.data; + var cur = stream.cur; + for (; len > 0; len--, cur += 2) + { + if (d[cur] == 0 && d[cur+1] >= 32 && d[cur+1] < 128) + result += String.fromCharCode(d[cur+1]); + } + stream.ExitFrame(); + face.postscript_name = result; + return result; + } + + if (found_apple != -1) + { + var stream = face.name_table.stream; + var name = face.name_table.names[found_apple]; + var len = name.stringLength; + + var error = stream.Seek(name.stringOffset); + if (error == 0) + { + result = stream.ReadString1(name.stringLength); + error = FT_Error; + } + if (error != 0) + { + name.stringOffset = 0; + name.stringLength = 0; + face.postscript_name = ""; + return ""; + } + + face.postscript_name = result; + return result; + } + + face.postscript_name = result; + return result; +} + +var sfnt_service_glyph_dict = new FT_Service_GlyphDictRec(sfnt_get_glyph_name,sfnt_get_name_index); +var sfnt_service_ps_name = new FT_Service_PsFontNameRec(sfnt_get_ps_name); +var tt_service_get_cmap_info = new FT_Service_TTCMapsRec(tt_get_cmap_info); + +var tt_cmap_classes = new Array(9); +tt_cmap_classes[0] = new tt_cmap0_class_rec(); +tt_cmap_classes[1] = new tt_cmap2_class_rec(); +tt_cmap_classes[2] = new tt_cmap4_class_rec(); +tt_cmap_classes[3] = new tt_cmap6_class_rec(); +tt_cmap_classes[4] = new tt_cmap8_class_rec(); +tt_cmap_classes[5] = new tt_cmap10_class_rec(); +tt_cmap_classes[6] = new tt_cmap12_class_rec(); +tt_cmap_classes[7] = new tt_cmap13_class_rec(); +tt_cmap_classes[8] = new tt_cmap14_class_rec(); + +var sfnt_service_sfnt_table = new FT_Service_SFNT_TableRec(tt_face_load_any,get_sfnt_table,sfnt_table_info); +var sfnt_service_bdf = new FT_Service_BDFRec(sfnt_get_charset_id,tt_face_find_bdf_prop); + +var sfnt_services = new Array(5); +sfnt_services[0] = new FT_ServiceDescRec(FT_SERVICE_ID_SFNT_TABLE,sfnt_service_sfnt_table); +sfnt_services[1] = new FT_ServiceDescRec(FT_SERVICE_ID_POSTSCRIPT_FONT_NAME,sfnt_service_ps_name); +sfnt_services[2] = new FT_ServiceDescRec(FT_SERVICE_ID_GLYPH_DICT,sfnt_service_glyph_dict); +sfnt_services[3] = new FT_ServiceDescRec(FT_SERVICE_ID_BDF,sfnt_service_bdf); +sfnt_services[4] = new FT_ServiceDescRec(FT_SERVICE_ID_TT_CMAP,tt_service_get_cmap_info); + +function tt_face_get_name(face, nameid) +{ + FT_Error = 0; + var found_apple = -1; + var found_apple_roman = -1; + var found_apple_english = -1; + var found_win = -1; + var found_unicode = -1; + + var is_english = false; + var convert = null; + var rec = null; + var num_names = face.num_names; + var n = 0; + for (; n < face.num_names; n++) + { + rec = face.name_table.names[n]; + if (rec.nameID == nameid && rec.stringLength > 0) + { + switch (rec.platformID) + { + case FT_Common.TT_PLATFORM_APPLE_UNICODE: + case FT_Common.TT_PLATFORM_ISO: + found_unicode = n; + break; + + case FT_Common.TT_PLATFORM_MACINTOSH: + if ( rec.languageID == 0) + found_apple_english = n; + else if (rec.encodingID == 0) + found_apple_roman = n; + break; + + case FT_Common.TT_PLATFORM_MICROSOFT: + if (found_win == -1 || (rec.languageID & 0x3FF) == 0x009) + { + switch ( rec.encodingID ) + { + case FT_Common.TT_MS_ID_SYMBOL_CS: + case FT_Common.TT_MS_ID_UNICODE_CS: + case FT_Common.TT_MS_ID_UCS_4: + is_english = ((rec.languageID & 0x3FF) == 0x009) ? true : false; + found_win = n; + break; + + default: + break; + } + } + break; + default: + break; + } + } + } + + found_apple = found_apple_roman; + if (found_apple_english >= 0) + found_apple = found_apple_english; + + if (found_win >= 0 && !(found_apple >= 0 && false === is_english)) + { + rec = face.name_table.names[found_win]; + switch (rec.encodingID) + { + case FT_Common.TT_MS_ID_UNICODE_CS: + case FT_Common.TT_MS_ID_SYMBOL_CS: + convert = tt_name_entry_ascii_from_utf16; + break; + + case FT_Common.TT_MS_ID_UCS_4: + convert = tt_name_entry_ascii_from_utf16; + break; + + default: + break; + } + } + else if (found_apple >= 0) + { + rec = face.name_table.names[found_apple]; + convert = tt_name_entry_ascii_from_other; + } + else if (found_unicode >= 0) + { + rec = face.name_table.names[found_unicode]; + convert = tt_name_entry_ascii_from_utf16; + } + + if (rec && convert) + { + if (rec.string == null) + { + var stream = face.name_table.stream; + FT_Error = stream.Seek(rec.stringOffset); + if (FT_Error == 0) + { + rec.string = stream.ReadArray(rec.stringLength); + } + if (FT_Error != 0 || null == rec.string) + return ""; + } + return convert(rec); + } + return ""; +} +/* convert an Apple Roman or symbol name entry to ASCII */ +function tt_name_entry_ascii_from_utf16(entry) +{ + var string = ""; + var p = entry.string; + var len = parseInt(entry.stringLength / 2); + if (len > p.length) + len = p.length; + + var code = 0; + for (var n = 0; n < len; n++) + { + code = p[2*n] << 8 | p[2*n+1]; + if (code < 32 || code > 127) + code = FT_Common.SYMBOL_CONST_VOPROS; + + string += String.fromCharCode(code); + } + return string; +} + +/* convert an Apple Roman or symbol name entry to ASCII */ +function tt_name_entry_ascii_from_other(entry) +{ + var string = ""; + var p = entry.string; + var len = entry.stringLength; + if (len > p.length) + len = p.length; + + var code = 0; + for (var n = 0; n < len; n++) + { + code = p[n]; + if ( code < 32 || code > 127 ) + code = FT_Common.SYMBOL_CONST_VOPROS; + + string += String.fromCharCode(code); + } + return string; +} + +function sfnt_init_face(stream, face, face_index) +{ + var error = 0; + var library = face.driver.library; + + var sfnt = face.sfnt; + if (null == sfnt) + { + sfnt = library.FT_Get_Module_Interface("sfnt"); + if (null == sfnt) + return FT_Common.FT_Err_Invalid_File_Format; + + face.sfnt = sfnt; + face.goto_table = sfnt.goto_table; + } + + face.psnames = FT_FACE_FIND_GLOBAL_SERVICE(face, "postscript-cmaps"); + + error = sfnt_open_font(stream, face); + if (error != FT_Common.FT_Err_Ok) + return error; + + if (face_index < 0) + face_index = 0; + + if (face_index >= face.ttc_header.count) + return FT_Common.FT_Err_Invalid_Argument; + + error = stream.Seek(face.ttc_header.offsets[face_index]) + if (error != FT_Common.FT_Err_Ok) + return error; + + /* check that we have a valid TrueType file */ + error = sfnt.load_font_dir(face, stream); + if (error != FT_Common.FT_Err_Ok) + return error; + + face.num_faces = face.ttc_header.count; + face.face_index = face_index; + + return error; +} +function sfnt_load_face(stream, face, face_index) +{ + var error = FT_Common.FT_Err_Ok; + var psnames_error = FT_Common.FT_Err_Ok; + + var has_outline = false; + var is_apple_sbit = false; + var ignore_preferred_family = false; + var ignore_preferred_subfamily = false; + + var sfnt = face.sfnt; + + if (face.internal.incremental_interface != null) + has_outline = true; + else if (null != tt_face_lookup_table(face, FT_Common.TTAG_glyf)) + has_outline = true; + else if (null != tt_face_lookup_table(face, FT_Common.TTAG_CFF)) + has_outline = true; + + if (false === has_outline && sfnt.load_bhed != null) + { + error = sfnt.load_bhed(face, stream); + is_apple_sbit = (error == 0) ? false : true; + } + + if (false === is_apple_sbit) + { + error = sfnt.load_head(face, stream); + if (error != 0) + return error; + } + + if (0 == face.header.Units_Per_EM) + return FT_Common.FT_Err_Invalid_Table; + + error = sfnt.load_maxp(face, stream); + error = sfnt.load_cmap(face, stream); + + error = sfnt.load_name(face, stream); + error = sfnt.load_post(face, stream); + + psnames_error = error; + + if (false === is_apple_sbit) + { + error = sfnt.load_hhea(face, stream, 0); + if (error == 0) + { + error = sfnt.load_hmtx(face, stream, 0); + if (error == FT_Common.FT_Err_Table_Missing) + { + error = FT_Common.FT_Err_Hmtx_Table_Missing; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (face.internal.incremental_interface && + face.internal.incremental_interface.funcs.get_glyph_metrics) + { + face.horizontal.number_Of_HMetrics = 0; + error = FT_Common.FT_Err_Ok; + } + //#endif + } + } + else if (error == FT_Common.FT_Err_Table_Missing) + { + if (face.format_tag == FT_Common.TTAG_true) + { + has_outline = false; + error = FT_Common.FT_Err_Ok; + } + else + { + error = FT_Common.FT_Err_Horiz_Header_Missing; + + //#ifdef FT_CONFIG_OPTION_INCREMENTAL + if (face.internal.incremental_interface && + face.internal.incremental_interface.funcs.get_glyph_metrics) + { + face.horizontal.number_Of_HMetrics = 0; + error = FT_Common.FT_Err_Ok; + } + //#endif + } + } + + if (error != 0) + return error; + + error = sfnt.load_hhea(face, stream, 1); + if (error == 0) + { + error = sfnt.load_hmtx(face, stream, 1); + if (error == 0) + face.vertical_info = 1; + } + + if (error != 0 && error != FT_Common.FT_Err_Table_Missing) + return error; + + error = sfnt.load_os2(face, stream); + if (error != 0) + { + /* we treat the table as missing if there are any errors */ + face.os2.version = 0xFFFF; + } + } + + if (sfnt.load_eblc) + { + error = sfnt.load_eblc(face, stream); + if (error != 0) + { + if (error == FT_Common.FT_Err_Table_Missing) + error = FT_Common.FT_Err_Ok; + else + return error; + } + } + + error = sfnt.load_pclt(face, stream); + if (error != 0) + { + if (error != FT_Common.FT_Err_Table_Missing) + return error; + + face.pclt.Version = 0; + } + + error = sfnt.load_gasp(face, stream); + error = sfnt.load_kern(face, stream); + + face.num_glyphs = face.max_profile.numGlyphs; + + face.family_name = ""; + face.style_name = ""; + + if (face.os2.version != 0xFFFF && (face.os2.fsSelection & 256) != 0) + { + /* + if (false == ignore_preferred_family) + { + face.family_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_PREFERRED_FAMILY); + error = FT_Error; + if (error != 0) + return error; + } + */ + if ("" == face.family_name) + { + face.family_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_FONT_FAMILY); + error = FT_Error; + if (error != 0) + return error; + } + + /* + if (false == ignore_preferred_subfamily) + { + face.style_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_PREFERRED_SUBFAMILY); + error = FT_Error; + if (error != 0) + return error; + } + */ + if ("" == face.style_name) + { + face.style_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_FONT_SUBFAMILY); + error = FT_Error; + if (error != 0) + return error; + } + } + else + { + face.family_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_WWS_FAMILY); + error = FT_Error; + if (error != 0) + return error; + + /* + if (face.family_name == "" && false == ignore_preferred_family) + { + face.family_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_PREFERRED_FAMILY); + error = FT_Error; + if (error != 0) + return error; + } + */ + if (face.family_name == "") + { + face.family_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_FONT_FAMILY); + error = FT_Error; + if (error != 0) + return error; + } + + face.style_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_WWS_SUBFAMILY); + error = FT_Error; + if (error != 0) + return error; + + /* + if (face.style_name == "" && false == ignore_preferred_subfamily) + { + face.style_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_PREFERRED_SUBFAMILY); + error = FT_Error; + if (error != 0) + return error; + } + */ + if (face.style_name == "") + { + face.style_name = tt_face_get_name(face, FT_Common.TT_NAME_ID_FONT_SUBFAMILY); + error = FT_Error; + if (error != 0) + return error; + } + } + + // face_flags + var flags = face.face_flags; + if (has_outline === true) + flags |= FT_Common.FT_FACE_FLAG_SCALABLE; + + flags |= (FT_Common.FT_FACE_FLAG_SFNT | FT_Common.FT_FACE_FLAG_HORIZONTAL); + + //#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + if (psnames_error == 0 && face.postscript.FormatType != 0x00030000) + flags |= FT_Common.FT_FACE_FLAG_GLYPH_NAMES; + //#endif + + /* fixed width font? */ + if (face.postscript.isFixedPitch) + flags |= FT_Common.FT_FACE_FLAG_FIXED_WIDTH; + + /* vertical information? */ + if (face.vertical_info) + flags |= FT_Common.FT_FACE_FLAG_VERTICAL; + + /* kerning available ? */ + if (face.kern_avail_bits != 0) + flags |= FT_Common.FT_FACE_FLAG_KERNING; + + //#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /* Don't bother to load the tables unless somebody asks for them. */ + /* No need to do work which will (probably) not be used. */ + if (null != tt_face_lookup_table(face, FT_Common.TTAG_glyf) && + null != tt_face_lookup_table(face, FT_Common.TTAG_fvar) && + null != tt_face_lookup_table(face, FT_Common.TTAG_gvar)) + flags |= FT_Common.FT_FACE_FLAG_MULTIPLE_MASTERS; + //#endif + + face.face_flags = flags; + + // Compute style flags. + flags = 0; + if (has_outline === true && face.os2.version != 0xFFFF) + { + if ((face.os2.fsSelection & 512) != 0) + flags |= FT_Common.FT_STYLE_FLAG_ITALIC; + else if ((face.os2.fsSelection & 1) != 0) + flags |= FT_Common.FT_STYLE_FLAG_ITALIC; + + if ((face.os2.fsSelection & 32) != 0) + flags |= FT_Common.FT_STYLE_FLAG_BOLD; + } + else + { + if ((face.header.Mac_Style & 1) != 0) + flags |= FT_Common.FT_STYLE_FLAG_BOLD; + + if ((face.header.Mac_Style & 2) != 0) + flags |= FT_Common.FT_STYLE_FLAG_ITALIC; + } + + face.style_flags = flags; + + // TODO: --- + tt_face_build_cmaps(face); + + for (var m = 0; m < face.num_charmaps; m++) + { + var charmap = __FT_CharmapRec(face.charmaps[m]); + charmap.encoding = 0; + charmap.encoding = sfnt_find_encoding(charmap.platform_id, charmap.encoding_id); + } + + //#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + var count = face.num_sbit_strikes; + + if (count > 0) + { + var em_size = face.header.Units_Per_EM; + var avgwidth = face.os2.xAvgCharWidth; + var metrics = new FT_Size_Metrics(); + + if (em_size == 0 || face.os2.version == 0xFFFF) + { + avgwidth = 0; + em_size = 1; + } + + face.available_sizes = new Array(count); + + for (var i = 0; i < count; i++) + { + face.available_sizes[i] = new FT_Bitmap_Size(); + var bsize = face.available_sizes[i]; + + error = sfnt.load_strike_metrics(face, i, metrics); + if (error != 0) + return error; + + bsize.height = (metrics.height >>> 6) & 0xFFFF; + bsize.width = parseInt((avgwidth * metrics.x_ppem + parseInt(em_size / 2)) / em_size) & 0xFFFF; + + bsize.x_ppem = metrics.x_ppem << 6; + bsize.y_ppem = metrics.y_ppem << 6; + + /* assume 72dpi */ + bsize.size = metrics.y_ppem << 6; + } + + face.face_flags |= FT_Common.FT_FACE_FLAG_FIXED_SIZES; + face.num_fixed_sizes = count; + } + + //#endif TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* a font with no bitmaps and no outlines is scalable; */ + /* it has only empty glyphs then */ + if (((face.face_flags & FT_Common.FT_FACE_FLAG_FIXED_SIZES) == 0) && + ((face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) == 0)) + face.face_flags |= FT_Common.FT_FACE_FLAG_SCALABLE; + + // Set up metrics + if ((face.face_flags & FT_Common.FT_FACE_FLAG_SCALABLE) != 0) + { + face.bbox.xMin = face.header.xMin; + face.bbox.yMin = face.header.yMin; + face.bbox.xMax = face.header.xMax; + face.bbox.yMax = face.header.yMax; + face.units_per_EM = face.header.Units_Per_EM; + + face.ascender = face.horizontal.Ascender; + face.descender = face.horizontal.Descender; + + face.height = (face.ascender - face.descender + face.horizontal.Line_Gap); + + if (face.ascender == 0 && face.descender == 0) + { + if (face.os2.version != 0xFFFF) + { + if (face.os2.sTypoAscender || face.os2.sTypoDescender) + { + face.ascender = face.os2.sTypoAscender; + face.descender = face.os2.sTypoDescender; + + face.height = (face.ascender - face.descender + face.os2.sTypoLineGap); + } + else + { + face.ascender = face.os2.usWinAscent; + face.descender = -face.os2.usWinDescent; + + face.height = (face.ascender - face.descender); + } + } + } + + face.max_advance_width = face.horizontal.advance_Width_Max; + face.max_advance_height = ((face.vertical_info != 0) ? face.vertical.advance_Height_Max : face.height); + + face.underline_position = face.postscript.underlinePosition - parseInt(face.postscript.underlineThickness / 2); + face.underline_thickness = face.postscript.underlineThickness; + } + return error; +} +function sfnt_done_face() +{ +} + +function sfnt_find_encoding(platform_id, encoding_id) +{ + switch (platform_id) + { + case FT_Common.TT_PLATFORM_ISO: + { + return FT_Common.FT_ENCODING_UNICODE; + } + case FT_Common.TT_PLATFORM_APPLE_UNICODE: + { + return FT_Common.FT_ENCODING_UNICODE; + } + case FT_Common.TT_PLATFORM_MACINTOSH: + { + if (FT_Common.TT_MAC_ID_ROMAN == encoding_id) + return FT_Common.FT_ENCODING_APPLE_ROMAN; + break; + } + case FT_Common.TT_PLATFORM_MICROSOFT: + { + if (FT_Common.TT_MS_ID_SYMBOL_CS == encoding_id) + return FT_Common.FT_ENCODING_MS_SYMBOL; + if (FT_Common.TT_MS_ID_UCS_4 == encoding_id) + return FT_Common.FT_ENCODING_UNICODE; + if (FT_Common.TT_MS_ID_UNICODE_CS == encoding_id) + return FT_Common.FT_ENCODING_UNICODE; + if (FT_Common.TT_MS_ID_SJIS == encoding_id) + return FT_Common.FT_ENCODING_SJIS; + if (FT_Common.TT_MS_ID_GB2312 == encoding_id) + return FT_Common.FT_ENCODING_GB2312; + if (FT_Common.TT_MS_ID_BIG_5 == encoding_id) + return FT_Common.FT_ENCODING_BIG5; + if (FT_Common.TT_MS_ID_WANSUNG == encoding_id) + return FT_Common.FT_ENCODING_WANSUNG; + if (FT_Common.TT_MS_ID_JOHAB == encoding_id) + return FT_Common.FT_ENCODING_JOHAB; + break; + } + default: + break; + } + return FT_Common.FT_ENCODING_NONE; +} + +function sfnt_open_font(stream, face) +{ + var error = 0; + + face.ttc_header.tag = 0; + face.ttc_header.version = 0; + face.ttc_header.count = 0; + + var offset = stream.pos; + var tag = stream.ReadULong(); + error = FT_Error; + FT_Error = 0; + + if (error != FT_Common.FT_Err_Ok) + return error; + + if (tag != 0x00010000 && tag != FT_Common.TTAG_ttcf && tag != FT_Common.TTAG_OTTO && + tag != FT_Common.TTAG_true && tag != FT_Common.TTAG_typ1 && tag != 0x00020000) + return FT_Common.FT_Err_Unknown_File_Format; + + face.ttc_header.tag = FT_Common.TTAG_ttcf; + + if (tag == FT_Common.TTAG_ttcf) + { + error = stream.EnterFrame(8); + if (error != 0) + return error; + + face.ttc_header.version = stream.GetLong(); + face.ttc_header.count = stream.GetLong(); + + stream.ExitFrame(); + + if (face.ttc_header.count == 0) + return FT_Common.FT_Err_Invalid_Table; + + var ul = FT_Common.IntToUInt(face.ttc_header.count); + if (ul > (stream.size / (28 + 4))) + return FT_Common.FT_Err_Array_Too_Large; + + face.ttc_header.offsets = new Array(ul); + error = stream.EnterFrame(4*ul); + + if (error != FT_Common.FT_Err_Ok) + return error; + + for (var n = 0; n < ul; n++) + face.ttc_header.offsets[n] = stream.GetULong(); + + stream.ExitFrame(); + } + else + { + face.ttc_header.version = 1 << 16; + face.ttc_header.count = 1; + + face.ttc_header.offsets = new Array(1); + face.ttc_header.offsets[0] = offset; + } + + return error; +} + +function _sfnt_interface() +{ + this.goto_table = tt_face_goto_table; + + this.init_face = sfnt_init_face; + this.load_face = sfnt_load_face; + this.done_face = sfnt_done_face; + this.get_interface = sfnt_get_interface; + + this.load_any = tt_face_load_any; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.load_sfnt_header = tt_face_load_sfnt_header_stub; + this.load_directory = tt_face_load_directory_stub; + //#endif + + this.load_head = tt_face_load_head; + this.load_hhea = tt_face_load_hhea; + this.load_cmap = tt_face_load_cmap; + this.load_maxp = tt_face_load_maxp; + this.load_os2 = tt_face_load_os2; + this.load_post = tt_face_load_post; + + this.load_name = tt_face_load_name; + this.free_name = tt_face_free_name; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.load_hdmx_stub = tt_face_load_hdmx_stub; + this.free_hdmx_stub = tt_face_free_hdmx_stub; + //#endif + + this.load_kern = tt_face_load_kern; + + this.load_gasp = tt_face_load_gasp; + this.load_pclt = tt_face_load_pclt; + + this.load_bhed = tt_face_load_bhed; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.set_sbit_strike_stub = tt_face_set_sbit_strike_stub; + this.load_sbits_stub = tt_face_load_sbit_stub; + + this.find_sbit_image = tt_find_sbit_image; + this.load_sbit_metrics = tt_load_sbit_metrics; + //#endif + + this.load_sbit_image = tt_face_load_sbit_image; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.free_sbits_stub = tt_face_free_sbit_stub; + //#endif + + this.get_psname = tt_face_get_ps_name; + this.free_psnames = tt_face_free_ps_names; + + //#ifdef FT_CONFIG_OPTION_OLD_INTERNALS + this.load_charmap_stub = tt_face_load_charmap_stub; + this.free_charmap_stub = tt_face_free_charmap_stub; + //#endif + + this.get_kerning = tt_face_get_kerning; + + this.load_font_dir = tt_face_load_font_dir; + this.load_hmtx = tt_face_load_hmtx; + + this.load_eblc = tt_face_load_eblc; + this.free_eblc = tt_face_free_eblc; + + this.set_sbit_strike = tt_face_set_sbit_strike; + this.load_strike_metrics = tt_face_load_strike_metrics; + + this.get_metrics = tt_face_get_metrics; +} +var sfnt_interface = new _sfnt_interface(); + +/******************************************************************************/ +// pic +/******************************************************************************/ +var FT_SFNT_SERVICES_GET = sfnt_services; +var FT_SFNT_SERVICE_GLYPH_DICT_GET = sfnt_service_glyph_dict; +var FT_SFNT_SERVICE_PS_NAME_GET = sfnt_service_ps_name; +var FT_TT_SERVICE_GET_CMAP_INFO_GET = tt_service_get_cmap_info; +var FT_TT_CMAP_CLASSES_GET = tt_cmap_classes; +var FT_SFNT_SERVICE_SFNT_TABLE_GET = sfnt_service_sfnt_table; +var FT_SFNT_SERVICE_BDF_GET = sfnt_service_bdf; +var FT_SFNT_INTERFACE_GET = sfnt_interface; + +function sfnt_get_interface(module,name) +{ + return ft_service_list_lookup(FT_SFNT_SERVICES_GET, name); +} + +function create_sfnt_module(library) +{ + var sfnt_mod = new FT_Module(); + sfnt_mod.clazz = new FT_Module_Class(); + + var clazz = sfnt_mod.clazz; + clazz.flags = 0; + clazz.name = "sfnt"; + clazz.version = 0x10000; + clazz.requires = 0x20000; + + clazz.module_interface = FT_SFNT_INTERFACE_GET; + clazz.init = null; + clazz.done = null; + + clazz.get_interface = sfnt_get_interface; + + sfnt_mod.library = library; + sfnt_mod.memory = library.Memory; + sfnt_mod.generic = null; + + return sfnt_mod; +} + diff --git a/Common/FontsFreeType/Private/FreeType/services.js b/Common/FontsFreeType/Private/FreeType/services.js new file mode 100644 index 0000000000000000000000000000000000000000..2fa84548aa7f8c9ae16057bbf8d0d9b4bc49c57a --- /dev/null +++ b/Common/FontsFreeType/Private/FreeType/services.js @@ -0,0 +1,258 @@ +/******************************************************************************/ +// SERVICES +/******************************************************************************/ + +/******************************************************************************/ +// bdf +/******************************************************************************/ +var FT_SERVICE_ID_BDF = "bdf"; +function FT_Service_BDFRec(get_charset_id_,get_property_) +{ + this.get_charset_id = get_charset_id_; + this.get_property = get_property_; +} +/******************************************************************************/ +// cid +/******************************************************************************/ +var FT_SERVICE_ID_CID = "CID"; +function FT_Service_CIDRec(get_ros_, get_is_cid_, get_cid_from_glyph_index_) +{ + this.get_ros = get_ros_; + this.get_is_cid = get_is_cid_; + this.get_cid_from_glyph_index = get_cid_from_glyph_index_; +} +/******************************************************************************/ +// glyph-dict +/******************************************************************************/ +var FT_SERVICE_ID_GLYPH_DICT = "glyph-dict"; +function FT_Service_GlyphDictRec(get_name_, name_index_) +{ + this.get_name = get_name_; + this.name_index = name_index_; +} +/******************************************************************************/ +// gxval +/******************************************************************************/ +var FT_SERVICE_ID_GX_VALIDATE = "truetypegx-validate"; +var FT_SERVICE_ID_CLASSICKERN_VALIDATE = "classickern-validate"; + +function FT_Service_GXvalidateRec(validate_) +{ + this.validate = validate_; +} +function FT_Service_CKERNvalidateRec(validate_) +{ + this.validate = validate_; +} +/******************************************************************************/ +// kerning +/******************************************************************************/ +var FT_SERVICE_ID_KERNING = "kerning"; +function FT_Service_KerningRec(get_track_) +{ + this.get_track = get_track_; +} +/******************************************************************************/ +// multi-masters +/******************************************************************************/ +var FT_SERVICE_ID_MULTI_MASTERS = "multi-masters"; +function FT_Service_MultiMastersRec(get_mm_, set_mm_design_, set_mm_blend_, get_mm_var_, set_var_design_) +{ + this.get_mm = get_mm_; + this.set_mm_design = set_mm_design_; + this.set_mm_blend = set_mm_blend_; + this.get_mm_var = get_mm_var_; + this.set_var_design = set_var_design_; +} +/******************************************************************************/ +// opentype-validate +/******************************************************************************/ +var FT_SERVICE_ID_OPENTYPE_VALIDATE = "opentype-validate"; +function FT_Service_OTvalidateRec(validate_) +{ + this.validate = validate_; +} +/******************************************************************************/ +// pfr-metrics +/******************************************************************************/ +var FT_SERVICE_ID_PFR_METRICS = "pfr-metrics"; +function FT_Service_PfrMetricsRec(get_metrics_,get_kerning_,get_advance_) +{ + this.get_metrics = get_metrics_; + this.get_kerning = get_kerning_; + this.get_advance = get_advance_; +} +/******************************************************************************/ +// postscript-font-name +/******************************************************************************/ +var FT_SERVICE_ID_POSTSCRIPT_FONT_NAME = "postscript-font-name"; +function FT_Service_PsFontNameRec(get_ps_font_name_) +{ + this.get_ps_font_name = get_ps_font_name_; +} +/******************************************************************************/ +// postscript-cmaps +/******************************************************************************/ +var FT_SERVICE_ID_POSTSCRIPT_CMAPS = "postscript-cmaps"; + +function PS_UniMap() +{ + this.unicode; + this.glyph_index; +} +function PS_UnicodesRec() +{ + this.cmap; + this.num_maps; + this.maps; +} +function FT_Service_PsCMapsRec(unicode_value_, unicodes_init_,unicodes_char_index_, unicodes_char_next_, macintosh_name_, + adobe_std_strings_, adobe_std_encoding_, adobe_expert_encoding_) +{ + this.unicode_value = unicode_value_; + + this.unicodes_init = unicodes_init_; + this.unicodes_char_index = unicodes_char_index_; + this.unicodes_char_next = unicodes_char_next_; + + this.macintosh_name = macintosh_name_; + this.adobe_std_strings = adobe_std_strings_; + this.adobe_std_encoding = adobe_std_strings_; + this.adobe_expert_encoding = adobe_expert_encoding_; +} +/******************************************************************************/ +// postscript-info +/******************************************************************************/ +var FT_SERVICE_ID_POSTSCRIPT_INFO = "postscript-info"; +function FT_Service_PsInfoRec(get_font_info_, ps_get_font_extra_, has_glyph_names_,get_font_private_, get_font_value_) +{ + this.ps_get_font_info = get_font_info_; + this.ps_get_font_extra = ps_get_font_extra_; + this.ps_has_glyph_names = has_glyph_names_; + this.ps_get_font_private = get_font_private_; + this.ps_get_font_value = get_font_value_; +} +/******************************************************************************/ +// sfnt-table +/******************************************************************************/ +var FT_SERVICE_ID_SFNT_TABLE = "sfnt-table"; +function FT_Service_SFNT_TableRec(load_, get_, info_) +{ + this.load_table = load_; + this.get_table = get_; + this.table_info = info_; +} +/******************************************************************************/ +// tt-cmaps +/******************************************************************************/ +var FT_SERVICE_ID_TT_CMAP = "tt-cmaps"; +function TT_CMapInfo() +{ + this.language; + this.format; +} +function FT_Service_TTCMapsRec(get_cmap_info_) +{ + this.get_cmap_info = get_cmap_info_; +} +/******************************************************************************/ +// truetype-engine +/******************************************************************************/ +var FT_SERVICE_ID_TRUETYPE_ENGINE = "truetype-engine"; +function FT_Service_TrueTypeEngineRec(engine_type_) +{ + this.engine_type = engine_type_; +} +/******************************************************************************/ +// tt-glyf +/******************************************************************************/ +var FT_SERVICE_ID_TT_GLYF = "tt-glyf"; +function FT_Service_TTGlyfRec(get_location_) +{ + this.get_location = get_location_; +} +/******************************************************************************/ +// winfonts +/******************************************************************************/ +var FT_SERVICE_ID_WINFNT = "winfonts"; +function FT_Service_WinFntRec(get_header_) +{ + this.get_header = get_header_; +} +/******************************************************************************/ +// xf86 +/******************************************************************************/ +var FT_SERVICE_ID_XF86_NAME = "xf86-driver-name"; +var FT_XF86_FORMAT_TRUETYPE = "TrueType"; +var FT_XF86_FORMAT_TYPE_1 = "Type 1"; +var FT_XF86_FORMAT_BDF = "BDF"; +var FT_XF86_FORMAT_PCF = "PCF"; +var FT_XF86_FORMAT_TYPE_42 = "Type 42"; +var FT_XF86_FORMAT_CID = "CID Type 1"; +var FT_XF86_FORMAT_CFF = "CFF"; +var FT_XF86_FORMAT_PFR = "PFR"; +var FT_XF86_FORMAT_WINFNT = "Windows FNT"; + +/******************************************************************************/ +function FT_ServiceDescRec(id,data) +{ + this.serv_id = id; + this.serv_data = data; +} +function ft_service_list_lookup(service_descriptors,service_id) +{ + var c = service_descriptors.length; + for (var i=0;i<c;i++) + { + if (service_descriptors[i].serv_id == service_id) + return service_descriptors[i].serv_data; + } + return null; +} + +function FT_FACE_FIND_SERVICE(face, id) +{ + var module = face.driver; + if (module.clazz.get_interface) + return module.clazz.get_interface(module, id); + return null; +} +function FT_FACE_FIND_GLOBAL_SERVICE(face, name) +{ + return ft_module_get_service(face.driver, name); +} +function ft_module_get_service(module, name) +{ + var result = null; + + if (module != null) + { + if (null != module.clazz.get_interface) + result = module.clazz.get_interface(module, name); + if (null == result) + { + var modules = module.library.modules; + var count = modules.length; + for (var i = 0;i<count;i++) + { + if (modules[i].clazz.get_interface) + { + result = modules[i].clazz.get_interface(modules[i], name); + if (null != result) + break; + } + } + } + } + + return result; +} + +function FT_ServiceCache() +{ + this.service_POSTSCRIPT_FONT_NAME = null; + this.service_MULTI_MASTERS = null; + this.service_GLYPH_DICT = null; + this.service_PFR_METRICS = null; + this.service_WINFNT = null; +} \ No newline at end of file diff --git a/Common/FontsFreeType/Private/generator/Readme.txt b/Common/FontsFreeType/Private/generator/Readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..dca4551dfd71ea43d767765acc9c4ef01bbd6a52 --- /dev/null +++ b/Common/FontsFreeType/Private/generator/Readme.txt @@ -0,0 +1,5 @@ +Как пользоватьÑÑ: +1) открыть index.html +2) Ñкопировать вÑе из Ñтранички +3) вÑтавить в функцию GetConfigMap (main.cpp) +4) запуÑтить generator (из папки Debug/Release, чтобы файл font_engine.js положилÑÑ Ñ‚ÑƒÐ´Ð°, куда надо) \ No newline at end of file diff --git a/Common/FontsFreeType/Private/generator/generator.pro b/Common/FontsFreeType/Private/generator/generator.pro new file mode 100644 index 0000000000000000000000000000000000000000..3a133d751bd0308ecdf81bdfdea594bb67631ecc --- /dev/null +++ b/Common/FontsFreeType/Private/generator/generator.pro @@ -0,0 +1,30 @@ +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt + +CONFIG -= debug_and_release debug_and_release_target + +SOURCES += main.cpp + +linux-g++ | linux-g++-64 | linux-g++-32 { + DEFINES += \ + LINUX \ + _LINUX \ + _LINUX_QT +} +mac { + DEFINES += \ + LINUX \ + _LINUX \ + _LINUX_QT \ + _MAC \ + MAC \ + QT_MAC \ + _MAC_ \ + __MAC__ +} +win32 { + DEFINES += \ + WIN32 +} diff --git a/Common/FontsFreeType/Private/generator/index.html b/Common/FontsFreeType/Private/generator/index.html new file mode 100644 index 0000000000000000000000000000000000000000..74721ec994befc597673bd9d6aaad271c4a774ee --- /dev/null +++ b/Common/FontsFreeType/Private/generator/index.html @@ -0,0 +1,132 @@ +<!doctype html> +<html> +<head> + + <title>FontEngine</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=IE8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> + + <script type="text/javascript" src="../Freetype/config.js"></script> + <script type="text/javascript" src="../Freetype/base.js"></script> + <script type="text/javascript" src="../Freetype/services.js"></script> + + <script type="text/javascript" src="../Freetype/modules/psaux.js"></script> + <script type="text/javascript" src="../Freetype/modules/psnames.js"></script> + <script type="text/javascript" src="../Freetype/modules/render.js"></script> + <script type="text/javascript" src="../Freetype/modules/sfnt.js"></script> + + <script type="text/javascript" src="../Freetype/drivers/truetype.js"></script> + <script type="text/javascript" src="../Freetype/drivers/cff.js"></script> + <script type="text/javascript" src="../Freetype/drivers/cid.js"></script> + <script type="text/javascript" src="../Freetype/drivers/t1.js"></script> + <script type="text/javascript" src="../Freetype/drivers/ttinterp.js"></script> + + <script type="text/javascript" src="../Freetype/freetype.js"></script> + +</head> +<body> + + <div id="log" style="font-family:Courier New"/> + + <script> + + function _correct(_src) + { + var res = _src; + res = res.replace(/&/g,'&'); + res = res.replace(/</g,'<'); + res = res.replace(/>/g,'>'); + res = res.replace(/'/g,'''); + res = res.replace(/"/g,'"'); + return res; + } + + var _log = ""; + var _br = "<br/>"; + + var __obj = {}; + var __arr = []; + + for (var i in FT_Common) + { + if (true === FT_Common[i]) + { + __arr.push("" + i); + __obj["" + i] = "true"; + } + else if (false === FT_Common[i]) + { + __arr.push("" + i); + __obj["" + i] = "false"; + } + else + { + var tof = typeof FT_Common[i]; + + if (tof == "number") + { + __arr.push("" + i); + __obj["" + i] = "" + FT_Common[i]; + } + } + } + + function compareStrings(a, b) + { + if (a == b) + return 0; + + if (a.indexOf(b) != -1) + return -1; + + if (b.indexOf(a) != -1) + return 1; + + return (a < b) ? -1 : (a > b) ? 1 : 0; + } + + __arr.sort(compareStrings); + + for (var i = 0; i < __arr.length; i++) + { + _log += _correct("_vec1.push_back(L\"FT_Common." + __arr[i] + "\"); "); + _log += _correct("_vec2.push_back(L\"" + __obj[__arr[i]] + "\");"); + _log += _br; + } + + /* + for (var i in FT_Common) + { + if (true === FT_Common[i]) + { + _log += _correct("_vec1.push_back(L\"FT_Common." + i + "\"); "); + _log += _correct("_vec2.push_back(L\"true\");"); + _log += _br; + } + else if (false === FT_Common[i]) + { + _log += _correct("_vec1.push_back(L\"FT_Common." + i + "\"); "); + _log += _correct("_vec2.push_back(L\"false\");"); + _log += _br; + } + else + { + var tof = typeof FT_Common[i]; + + if (tof == "number") + { + _log += _correct("_vec1.push_back(L\"FT_Common." + i + "\"); "); + _log += _correct("_vec2.push_back(L\"" + FT_Common[i] + "\");"); + _log += _br; + } + } + } + */ + + document.getElementById("log").innerHTML = _log; + + </script> + +</body> +</html> \ No newline at end of file diff --git a/Common/FontsFreeType/Private/generator/main.cpp b/Common/FontsFreeType/Private/generator/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a4fa850134f64c88293d846125888ab1f9e9930 --- /dev/null +++ b/Common/FontsFreeType/Private/generator/main.cpp @@ -0,0 +1,897 @@ +#include <iostream> +#include <vector> +#include <map> + +#include "../../../../../ServerComponents/DesktopEditor/common/File.h" + +using namespace std; + +void GetConfigMap(std::vector<std::wstring>& _vec1, std::vector<std::wstring>& _vec2) +{ + _vec1.push_back(L"FT_Common.AFM_MAX_ARGUMENTS"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.AFM_STREAM_STATUS_EOC"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.AFM_STREAM_STATUS_EOF"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.AFM_STREAM_STATUS_EOL"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.AFM_STREAM_STATUS_NORMAL"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ASCENDER"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_AXISLABEL"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_AXISTYPE"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_BLENDAXISTYPES"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_BLENDDESIGNMAP"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_BLENDDESIGNPOSITIONS"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_B"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_CAPHEIGHT"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_CC"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_CHARACTERSET"); _vec2.push_back(L"12"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_CHARACTERS"); _vec2.push_back(L"13"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_CHARWIDTH"); _vec2.push_back(L"11"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_CH"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_C"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_DESCENDER"); _vec2.push_back(L"14"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENCODINGSCHEME"); _vec2.push_back(L"15"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENDAXIS"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENDCHARMETRICS"); _vec2.push_back(L"17"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENDCOMPOSITES"); _vec2.push_back(L"18"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENDDIRECTION"); _vec2.push_back(L"19"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENDFONTMETRICS"); _vec2.push_back(L"20"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENDKERNDATA"); _vec2.push_back(L"21"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENDKERNPAIRS"); _vec2.push_back(L"22"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ENDTRACKKERN"); _vec2.push_back(L"23"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ESCCHAR"); _vec2.push_back(L"24"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_FAMILYNAME"); _vec2.push_back(L"25"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_FONTBBOX"); _vec2.push_back(L"26"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_FONTNAME"); _vec2.push_back(L"27"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_FULLNAME"); _vec2.push_back(L"28"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ISBASEFONT"); _vec2.push_back(L"29"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ISCIDFONT"); _vec2.push_back(L"30"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ISFIXEDPITCH"); _vec2.push_back(L"31"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ISFIXEDV"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_ITALICANGLE"); _vec2.push_back(L"33"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_KPH"); _vec2.push_back(L"35"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_KPX"); _vec2.push_back(L"36"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_KPY"); _vec2.push_back(L"37"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_KP"); _vec2.push_back(L"34"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_L"); _vec2.push_back(L"38"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_MAPPINGSCHEME"); _vec2.push_back(L"39"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_METRICSSETS"); _vec2.push_back(L"40"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_NOTICE"); _vec2.push_back(L"42"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_N"); _vec2.push_back(L"41"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_PCC"); _vec2.push_back(L"43"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTAXIS"); _vec2.push_back(L"44"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTCHARMETRICS"); _vec2.push_back(L"45"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTCOMPOSITES"); _vec2.push_back(L"46"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTDIRECTION"); _vec2.push_back(L"47"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTFONTMETRICS"); _vec2.push_back(L"48"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTKERNDATA"); _vec2.push_back(L"49"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTKERNPAIRS0"); _vec2.push_back(L"51"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTKERNPAIRS1"); _vec2.push_back(L"52"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTKERNPAIRS"); _vec2.push_back(L"50"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STARTTRACKKERN"); _vec2.push_back(L"53"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STDHW"); _vec2.push_back(L"54"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_STDVW"); _vec2.push_back(L"55"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_TRACKKERN"); _vec2.push_back(L"56"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_UNDERLINEPOSITION"); _vec2.push_back(L"57"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_UNDERLINETHICKNESS"); _vec2.push_back(L"58"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_UNKNOWN"); _vec2.push_back(L"75"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_VERSION"); _vec2.push_back(L"61"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_VVECTOR"); _vec2.push_back(L"60"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_VV"); _vec2.push_back(L"59"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_W0X"); _vec2.push_back(L"64"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_W0Y"); _vec2.push_back(L"65"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_W0"); _vec2.push_back(L"63"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_W1X"); _vec2.push_back(L"67"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_W1Y"); _vec2.push_back(L"68"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_W1"); _vec2.push_back(L"66"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_WEIGHTVECTOR"); _vec2.push_back(L"72"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_WEIGHT"); _vec2.push_back(L"71"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_WX"); _vec2.push_back(L"69"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_WY"); _vec2.push_back(L"70"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_W"); _vec2.push_back(L"62"); + _vec1.push_back(L"FT_Common.AFM_TOKEN_XHEIGHT"); _vec2.push_back(L"73"); + _vec1.push_back(L"FT_Common.AFM_VALUE_TYPE_BOOL"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.AFM_VALUE_TYPE_FIXED"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.AFM_VALUE_TYPE_INDEX"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.AFM_VALUE_TYPE_INTEGER"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.AFM_VALUE_TYPE_NAME"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.AFM_VALUE_TYPE_STRING"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.ARGS_ARE_WORDS"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.ARGS_ARE_XY_VALUES"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.BDF_PROPERTY_TYPE_ATOM"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.BDF_PROPERTY_TYPE_CARDINAL"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.BDF_PROPERTY_TYPE_INTEGER"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.BDF_PROPERTY_TYPE_NONE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.CFFCODE_PRIVATE"); _vec2.push_back(L"8192"); + _vec1.push_back(L"FT_Common.CFFCODE_TOPDICT"); _vec2.push_back(L"4096"); + _vec1.push_back(L"FT_Common.CFF_CODE_PRIVATE"); _vec2.push_back(L"8192"); + _vec1.push_back(L"FT_Common.CFF_CODE_TOPDICT"); _vec2.push_back(L"4096"); + _vec1.push_back(L"FT_Common.CFF_COUNT_CHECK_WIDTH"); _vec2.push_back(L"128"); + _vec1.push_back(L"FT_Common.CFF_COUNT_CLEAR_STACK"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.CFF_COUNT_EXACT"); _vec2.push_back(L"64"); + _vec1.push_back(L"FT_Common.CFF_MAX_CID_FONTS"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.CFF_MAX_OPERANDS"); _vec2.push_back(L"48"); + _vec1.push_back(L"FT_Common.CFF_MAX_STACK_DEPTH"); _vec2.push_back(L"96"); + _vec1.push_back(L"FT_Common.CFF_MAX_SUBRS_CALLS"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.CFF_MAX_TRANS_ELEMENTS"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.ErrorLongJump"); _vec2.push_back(L"-100"); + _vec1.push_back(L"FT_Common.FT_ANGLE_PI2"); _vec2.push_back(L"5898240"); + _vec1.push_back(L"FT_Common.FT_ANGLE_PI"); _vec2.push_back(L"11796480"); + _vec1.push_back(L"FT_Common.FT_CMAP_0"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_CMAP_12"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.FT_CMAP_13"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_CMAP_14"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.FT_CMAP_1"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_CMAP_4"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_CURVE_TAG_CONIC"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_CURVE_TAG_CUBIC"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_CURVE_TAG_HAS_SCANMODE"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_CURVE_TAG_ON"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_CURVE_TAG_TOUCH_BOTH"); _vec2.push_back(L"24"); + _vec1.push_back(L"FT_Common.FT_CURVE_TAG_TOUCH_X"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.FT_CURVE_TAG_TOUCH_Y"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.FT_ENCODING_ADOBE_CUSTOM"); _vec2.push_back(L"1094992451"); + _vec1.push_back(L"FT_Common.FT_ENCODING_ADOBE_EXPERT"); _vec2.push_back(L"1094992453"); + _vec1.push_back(L"FT_Common.FT_ENCODING_ADOBE_LATIN_1"); _vec2.push_back(L"1818326065"); + _vec1.push_back(L"FT_Common.FT_ENCODING_ADOBE_STANDARD"); _vec2.push_back(L"1094995778"); + _vec1.push_back(L"FT_Common.FT_ENCODING_APPLE_ROMAN"); _vec2.push_back(L"1634889070"); + _vec1.push_back(L"FT_Common.FT_ENCODING_BIG5"); _vec2.push_back(L"1651074869"); + _vec1.push_back(L"FT_Common.FT_ENCODING_GB2312"); _vec2.push_back(L"1734484000"); + _vec1.push_back(L"FT_Common.FT_ENCODING_JOHAB"); _vec2.push_back(L"1785686113"); + _vec1.push_back(L"FT_Common.FT_ENCODING_MS_BIG5"); _vec2.push_back(L"1651074869"); + _vec1.push_back(L"FT_Common.FT_ENCODING_MS_GB2312"); _vec2.push_back(L"1734484000"); + _vec1.push_back(L"FT_Common.FT_ENCODING_MS_JOHAB"); _vec2.push_back(L"1785686113"); + _vec1.push_back(L"FT_Common.FT_ENCODING_MS_SJIS"); _vec2.push_back(L"1936353651"); + _vec1.push_back(L"FT_Common.FT_ENCODING_MS_SYMBOL"); _vec2.push_back(L"1937337698"); + _vec1.push_back(L"FT_Common.FT_ENCODING_MS_WANSUNG"); _vec2.push_back(L"2002873971"); + _vec1.push_back(L"FT_Common.FT_ENCODING_NONE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_ENCODING_OLD_LATIN_2"); _vec2.push_back(L"1818326066"); + _vec1.push_back(L"FT_Common.FT_ENCODING_SJIS"); _vec2.push_back(L"1936353651"); + _vec1.push_back(L"FT_Common.FT_ENCODING_UNICODE"); _vec2.push_back(L"1970170211"); + _vec1.push_back(L"FT_Common.FT_ENCODING_WANSUNG"); _vec2.push_back(L"2002873971"); + _vec1.push_back(L"FT_Common.FT_Err_Array_Too_Large"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.FT_Err_Bad_Argument"); _vec2.push_back(L"132"); + _vec1.push_back(L"FT_Common.FT_Err_Bbx_Too_Big"); _vec2.push_back(L"184"); + _vec1.push_back(L"FT_Common.FT_Err_CMap_Table_Missing"); _vec2.push_back(L"146"); + _vec1.push_back(L"FT_Common.FT_Err_Cannot_Open_Resource"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_Err_Cannot_Open_Stream"); _vec2.push_back(L"81"); + _vec1.push_back(L"FT_Common.FT_Err_Cannot_Render_Glyph"); _vec2.push_back(L"19"); + _vec1.push_back(L"FT_Common.FT_Err_Code_Overflow"); _vec2.push_back(L"131"); + _vec1.push_back(L"FT_Common.FT_Err_Corrupted_Font_Glyphs"); _vec2.push_back(L"186"); + _vec1.push_back(L"FT_Common.FT_Err_Corrupted_Font_Header"); _vec2.push_back(L"185"); + _vec1.push_back(L"FT_Common.FT_Err_Could_Not_Find_Context"); _vec2.push_back(L"153"); + _vec1.push_back(L"FT_Common.FT_Err_Debug_OpCode"); _vec2.push_back(L"135"); + _vec1.push_back(L"FT_Common.FT_Err_Divide_By_Zero"); _vec2.push_back(L"133"); + _vec1.push_back(L"FT_Common.FT_Err_ENDF_In_Exec_Stream"); _vec2.push_back(L"136"); + _vec1.push_back(L"FT_Common.FT_Err_Execution_Too_Long"); _vec2.push_back(L"139"); + _vec1.push_back(L"FT_Common.FT_Err_Hmtx_Table_Missing"); _vec2.push_back(L"147"); + _vec1.push_back(L"FT_Common.FT_Err_Horiz_Header_Missing"); _vec2.push_back(L"143"); + _vec1.push_back(L"FT_Common.FT_Err_Ignore"); _vec2.push_back(L"162"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Argument"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Cache_Handle"); _vec2.push_back(L"39"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_CharMap_Format"); _vec2.push_back(L"150"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_CharMap_Handle"); _vec2.push_back(L"38"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Character_Code"); _vec2.push_back(L"17"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_CodeRange"); _vec2.push_back(L"138"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Composite"); _vec2.push_back(L"21"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Driver_Handle"); _vec2.push_back(L"34"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Face_Handle"); _vec2.push_back(L"35"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_File_Format"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Frame_Operation"); _vec2.push_back(L"86"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Frame_Read"); _vec2.push_back(L"88"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Glyph_Format"); _vec2.push_back(L"18"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Glyph_Index"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Handle"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Horiz_Metrics"); _vec2.push_back(L"149"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Library_Handle"); _vec2.push_back(L"33"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Offset"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Opcode"); _vec2.push_back(L"128"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Outline"); _vec2.push_back(L"20"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_PPem"); _vec2.push_back(L"151"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Pixel_Size"); _vec2.push_back(L"23"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Post_Table_Format"); _vec2.push_back(L"154"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Post_Table"); _vec2.push_back(L"155"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Reference"); _vec2.push_back(L"134"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Size_Handle"); _vec2.push_back(L"36"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Slot_Handle"); _vec2.push_back(L"37"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Stream_Handle"); _vec2.push_back(L"40"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Stream_Operation"); _vec2.push_back(L"85"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Stream_Read"); _vec2.push_back(L"84"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Stream_Seek"); _vec2.push_back(L"82"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Stream_Skip"); _vec2.push_back(L"83"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Table"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Version"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_Err_Invalid_Vert_Metrics"); _vec2.push_back(L"152"); + _vec1.push_back(L"FT_Common.FT_Err_Locations_Missing"); _vec2.push_back(L"144"); + _vec1.push_back(L"FT_Common.FT_Err_Lower_Module_Version"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.FT_Err_Missing_Bbx_Field"); _vec2.push_back(L"183"); + _vec1.push_back(L"FT_Common.FT_Err_Missing_Chars_Field"); _vec2.push_back(L"180"); + _vec1.push_back(L"FT_Common.FT_Err_Missing_Encoding_Field"); _vec2.push_back(L"182"); + _vec1.push_back(L"FT_Common.FT_Err_Missing_Font_Field"); _vec2.push_back(L"177"); + _vec1.push_back(L"FT_Common.FT_Err_Missing_Fontboundingbox_Field"); _vec2.push_back(L"179"); + _vec1.push_back(L"FT_Common.FT_Err_Missing_Size_Field"); _vec2.push_back(L"178"); + _vec1.push_back(L"FT_Common.FT_Err_Missing_Startchar_Field"); _vec2.push_back(L"181"); + _vec1.push_back(L"FT_Common.FT_Err_Missing_Startfont_Field"); _vec2.push_back(L"176"); + _vec1.push_back(L"FT_Common.FT_Err_Name_Table_Missing"); _vec2.push_back(L"145"); + _vec1.push_back(L"FT_Common.FT_Err_Nested_DEFS"); _vec2.push_back(L"137"); + _vec1.push_back(L"FT_Common.FT_Err_Nested_Frame_Access"); _vec2.push_back(L"87"); + _vec1.push_back(L"FT_Common.FT_Err_No_Unicode_Glyph_Name"); _vec2.push_back(L"163"); + _vec1.push_back(L"FT_Common.FT_Err_Ok"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_Err_Out_Of_Memory"); _vec2.push_back(L"64"); + _vec1.push_back(L"FT_Common.FT_Err_Post_Table_Missing"); _vec2.push_back(L"148"); + _vec1.push_back(L"FT_Common.FT_Err_Raster_Corrupted"); _vec2.push_back(L"97"); + _vec1.push_back(L"FT_Common.FT_Err_Raster_Negative_Height"); _vec2.push_back(L"99"); + _vec1.push_back(L"FT_Common.FT_Err_Raster_Overflow"); _vec2.push_back(L"98"); + _vec1.push_back(L"FT_Common.FT_Err_Raster_Uninitialized"); _vec2.push_back(L"96"); + _vec1.push_back(L"FT_Common.FT_Err_Stack_Overflow"); _vec2.push_back(L"130"); + _vec1.push_back(L"FT_Common.FT_Err_Stack_Underflow"); _vec2.push_back(L"161"); + _vec1.push_back(L"FT_Common.FT_Err_Syntax_Error"); _vec2.push_back(L"160"); + _vec1.push_back(L"FT_Common.FT_Err_Table_Missing"); _vec2.push_back(L"142"); + _vec1.push_back(L"FT_Common.FT_Err_Too_Few_Arguments"); _vec2.push_back(L"129"); + _vec1.push_back(L"FT_Common.FT_Err_Too_Many_Caches"); _vec2.push_back(L"112"); + _vec1.push_back(L"FT_Common.FT_Err_Too_Many_Drivers"); _vec2.push_back(L"48"); + _vec1.push_back(L"FT_Common.FT_Err_Too_Many_Extensions"); _vec2.push_back(L"49"); + _vec1.push_back(L"FT_Common.FT_Err_Too_Many_Function_Defs"); _vec2.push_back(L"140"); + _vec1.push_back(L"FT_Common.FT_Err_Too_Many_Hints"); _vec2.push_back(L"22"); + _vec1.push_back(L"FT_Common.FT_Err_Too_Many_Instruction_Defs"); _vec2.push_back(L"141"); + _vec1.push_back(L"FT_Common.FT_Err_Unimplemented_Feature"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.FT_Err_Unknown_File_Format"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_Err_Unlisted_Object"); _vec2.push_back(L"65"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_CID_KEYED"); _vec2.push_back(L"4096"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_EXTERNAL_STREAM"); _vec2.push_back(L"1024"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_FAST_GLYPHS"); _vec2.push_back(L"128"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_FIXED_SIZES"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_FIXED_WIDTH"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_GLYPH_NAMES"); _vec2.push_back(L"512"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_HINTER"); _vec2.push_back(L"2048"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_HORIZONTAL"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_KERNING"); _vec2.push_back(L"64"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_MULTIPLE_MASTERS"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_SCALABLE"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_SFNT"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_TRICKY"); _vec2.push_back(L"8192"); + _vec1.push_back(L"FT_Common.FT_FACE_FLAG_VERTICAL"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.FT_GLYPH_BBOX_GRIDFIT"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_GLYPH_BBOX_PIXELS"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.FT_GLYPH_BBOX_SUBPIXELS"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_GLYPH_BBOX_TRUNCATE"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_GLYPH_BBOX_UNSCALED"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_GLYPH_FORMAT_BITMAP"); _vec2.push_back(L"1651078259"); + _vec1.push_back(L"FT_Common.FT_GLYPH_FORMAT_COMPOSITE"); _vec2.push_back(L"1668246896"); + _vec1.push_back(L"FT_Common.FT_GLYPH_FORMAT_NONE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_GLYPH_FORMAT_OUTLINE"); _vec2.push_back(L"1869968492"); + _vec1.push_back(L"FT_Common.FT_GLYPH_FORMAT_PLOTTER"); _vec2.push_back(L"1886154612"); + _vec1.push_back(L"FT_Common.FT_GLYPH_OWN_BITMAP"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_KERNING_DEFAULT"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_KERNING_UNFITTED"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_KERNING_UNSCALED"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_LOAD_ADVANCE_ONLY"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.FT_LOAD_CROP_BITMAP"); _vec2.push_back(L"64"); + _vec1.push_back(L"FT_Common.FT_LOAD_DEFAULT"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_LOAD_FORCE_AUTOHINT"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH"); _vec2.push_back(L"512"); + _vec1.push_back(L"FT_Common.FT_LOAD_IGNORE_TRANSFORM"); _vec2.push_back(L"2048"); + _vec1.push_back(L"FT_Common.FT_LOAD_LINEAR_DESIGN"); _vec2.push_back(L"8192"); + _vec1.push_back(L"FT_Common.FT_LOAD_MONOCHROME"); _vec2.push_back(L"4096"); + _vec1.push_back(L"FT_Common.FT_LOAD_NO_AUTOHINT"); _vec2.push_back(L"32768"); + _vec1.push_back(L"FT_Common.FT_LOAD_NO_BITMAP"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.FT_LOAD_NO_HINTING"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_LOAD_NO_RECURSE"); _vec2.push_back(L"1024"); + _vec1.push_back(L"FT_Common.FT_LOAD_NO_SCALE"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_LOAD_PEDANTIC"); _vec2.push_back(L"128"); + _vec1.push_back(L"FT_Common.FT_LOAD_RENDER"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_LOAD_SBITS_ONLY"); _vec2.push_back(L"16384"); + _vec1.push_back(L"FT_Common.FT_LOAD_VERTICAL_LAYOUT"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.FT_MAX_CHARMAP_CACHEABLE"); _vec2.push_back(L"15"); + _vec1.push_back(L"FT_Common.FT_MODULE_DRIVER_HAS_HINTER"); _vec2.push_back(L"1024"); + _vec1.push_back(L"FT_Common.FT_MODULE_DRIVER_NO_OUTLINES"); _vec2.push_back(L"512"); + _vec1.push_back(L"FT_Common.FT_MODULE_DRIVER_SCALABLE"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.FT_MODULE_FONT_DRIVER"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_MODULE_HINTER"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_MODULE_RENDERER"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_MODULE_STYLER"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.FT_Mod_Err"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.FT_ORIENTATION_FILL_LEFT"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_ORIENTATION_FILL_RIGHT"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_ORIENTATION_NONE"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_ORIENTATION_POSTSCRIPT"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_ORIENTATION_TRUETYPE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_EVEN_ODD_FILL"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_HIGH_PRECISION"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_IGNORE_DROPOUTS"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_INCLUDE_STUBS"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_NONE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_OWNER"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_REVERSE_FILL"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_SINGLE_PASS"); _vec2.push_back(L"512"); + _vec1.push_back(L"FT_Common.FT_OUTLINE_SMART_DROPOUTS"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.FT_PARAM_TAG_UNPATENTED_HINTING"); _vec2.push_back(L"1970172001"); + _vec1.push_back(L"FT_Common.FT_PIXEL_MODE_GRAY2"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.FT_PIXEL_MODE_GRAY4"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_PIXEL_MODE_GRAY"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_PIXEL_MODE_LCD_V"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.FT_PIXEL_MODE_LCD"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.FT_PIXEL_MODE_MAX"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.FT_PIXEL_MODE_MONO"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_PIXEL_MODE_NONE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_RASTER_FLAG_AA"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_RASTER_FLAG_CLIP"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_RASTER_FLAG_DEFAULT"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_RASTER_FLAG_DIRECT"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_RENDER_MODE_LCD_V"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_RENDER_MODE_LCD"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.FT_RENDER_MODE_LIGHT"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_RENDER_MODE_MAX"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.FT_RENDER_MODE_MONO"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_RENDER_MODE_NORMAL"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_SIZE_REQUEST_TYPE_BBOX"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_SIZE_REQUEST_TYPE_CELL"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.FT_SIZE_REQUEST_TYPE_MAX"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.FT_SIZE_REQUEST_TYPE_NOMINAL"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.FT_SIZE_REQUEST_TYPE_REAL_DIM"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_SIZE_REQUEST_TYPE_SCALES"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_STYLE_FLAG_BOLD"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_STYLE_FLAG_ITALIC"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_SUBGLYPH_FLAG_2X2"); _vec2.push_back(L"128"); + _vec1.push_back(L"FT_Common.FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.FT_SUBGLYPH_FLAG_SCALE"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.FT_SUBGLYPH_FLAG_USE_MY_METRICS"); _vec2.push_back(L"512"); + _vec1.push_back(L"FT_Common.FT_SUBGLYPH_FLAG_XY_SCALE"); _vec2.push_back(L"64"); + _vec1.push_back(L"FT_Common.FT_TRIG_MAX_ITERS"); _vec2.push_back(L"23"); + _vec1.push_back(L"FT_Common.FT_TRIG_SCALE"); _vec2.push_back(L"2608131496"); + _vec1.push_back(L"FT_Common.GX_TC_RESERVED_TUPLE_FLAGS"); _vec2.push_back(L"28672"); + _vec1.push_back(L"FT_Common.GX_TC_TUPLES_SHARE_POINT_NUMBERS"); _vec2.push_back(L"32768"); + _vec1.push_back(L"FT_Common.GX_TC_TUPLE_COUNT_MASK"); _vec2.push_back(L"4095"); + _vec1.push_back(L"FT_Common.GX_TI_EMBEDDED_TUPLE_COORD"); _vec2.push_back(L"32768"); + _vec1.push_back(L"FT_Common.GX_TI_INTERMEDIATE_TUPLE"); _vec2.push_back(L"16384"); + _vec1.push_back(L"FT_Common.GX_TI_PRIVATE_POINT_NUMBERS"); _vec2.push_back(L"8192"); + _vec1.push_back(L"FT_Common.GX_TI_RESERVED_TUPLE_FLAG"); _vec2.push_back(L"4096"); + _vec1.push_back(L"FT_Common.GX_TI_TUPLE_INDEX_MASK"); _vec2.push_back(L"4095"); + _vec1.push_back(L"FT_Common.MAX_RUNNABLE_OPCODES"); _vec2.push_back(L"1000000"); + _vec1.push_back(L"FT_Common.MORE_COMPONENTS"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.N_AFM_TOKENS"); _vec2.push_back(L"74"); + _vec1.push_back(L"FT_Common.OVERLAP_COMPOUND"); _vec2.push_back(L"1024"); + _vec1.push_back(L"FT_Common.PS_DICT_BLUE_FUZZ"); _vec2.push_back(L"17"); + _vec1.push_back(L"FT_Common.PS_DICT_BLUE_SCALE"); _vec2.push_back(L"24"); + _vec1.push_back(L"FT_Common.PS_DICT_BLUE_SHIFT"); _vec2.push_back(L"25"); + _vec1.push_back(L"FT_Common.PS_DICT_BLUE_VALUE"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.PS_DICT_CHAR_STRING_KEY"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.PS_DICT_CHAR_STRING"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.PS_DICT_ENCODING_ENTRY"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.PS_DICT_ENCODING_TYPE"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.PS_DICT_FAMILY_BLUE"); _vec2.push_back(L"21"); + _vec1.push_back(L"FT_Common.PS_DICT_FAMILY_NAME"); _vec2.push_back(L"39"); + _vec1.push_back(L"FT_Common.PS_DICT_FAMILY_OTHER_BLUE"); _vec2.push_back(L"23"); + _vec1.push_back(L"FT_Common.PS_DICT_FONT_BBOX"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.PS_DICT_FONT_MATRIX"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.PS_DICT_FONT_NAME"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.PS_DICT_FONT_TYPE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.PS_DICT_FORCE_BOLD"); _vec2.push_back(L"30"); + _vec1.push_back(L"FT_Common.PS_DICT_FS_TYPE"); _vec2.push_back(L"44"); + _vec1.push_back(L"FT_Common.PS_DICT_FULL_NAME"); _vec2.push_back(L"38"); + _vec1.push_back(L"FT_Common.PS_DICT_IS_FIXED_PITCH"); _vec2.push_back(L"41"); + _vec1.push_back(L"FT_Common.PS_DICT_ITALIC_ANGLE"); _vec2.push_back(L"45"); + _vec1.push_back(L"FT_Common.PS_DICT_LANGUAGE_GROUP"); _vec2.push_back(L"35"); + _vec1.push_back(L"FT_Common.PS_DICT_LEN_IV"); _vec2.push_back(L"33"); + _vec1.push_back(L"FT_Common.PS_DICT_MAX"); _vec2.push_back(L"45"); + _vec1.push_back(L"FT_Common.PS_DICT_MIN_FEATURE"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.PS_DICT_NOTICE"); _vec2.push_back(L"37"); + _vec1.push_back(L"FT_Common.PS_DICT_NUM_BLUE_VALUES"); _vec2.push_back(L"15"); + _vec1.push_back(L"FT_Common.PS_DICT_NUM_CHAR_STRINGS"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.PS_DICT_NUM_FAMILY_BLUES"); _vec2.push_back(L"20"); + _vec1.push_back(L"FT_Common.PS_DICT_NUM_FAMILY_OTHER_BLUES"); _vec2.push_back(L"22"); + _vec1.push_back(L"FT_Common.PS_DICT_NUM_OTHER_BLUES"); _vec2.push_back(L"18"); + _vec1.push_back(L"FT_Common.PS_DICT_NUM_STEM_SNAP_H"); _vec2.push_back(L"26"); + _vec1.push_back(L"FT_Common.PS_DICT_NUM_STEM_SNAP_V"); _vec2.push_back(L"28"); + _vec1.push_back(L"FT_Common.PS_DICT_NUM_SUBRS"); _vec2.push_back(L"11"); + _vec1.push_back(L"FT_Common.PS_DICT_OTHER_BLUE"); _vec2.push_back(L"19"); + _vec1.push_back(L"FT_Common.PS_DICT_PAINT_TYPE"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.PS_DICT_PASSWORD"); _vec2.push_back(L"34"); + _vec1.push_back(L"FT_Common.PS_DICT_RND_STEM_UP"); _vec2.push_back(L"31"); + _vec1.push_back(L"FT_Common.PS_DICT_STD_HW"); _vec2.push_back(L"13"); + _vec1.push_back(L"FT_Common.PS_DICT_STD_VW"); _vec2.push_back(L"14"); + _vec1.push_back(L"FT_Common.PS_DICT_STEM_SNAP_H"); _vec2.push_back(L"27"); + _vec1.push_back(L"FT_Common.PS_DICT_STEM_SNAP_V"); _vec2.push_back(L"29"); + _vec1.push_back(L"FT_Common.PS_DICT_SUBR"); _vec2.push_back(L"12"); + _vec1.push_back(L"FT_Common.PS_DICT_UNDERLINE_POSITION"); _vec2.push_back(L"42"); + _vec1.push_back(L"FT_Common.PS_DICT_UNDERLINE_THICKNESS"); _vec2.push_back(L"43"); + _vec1.push_back(L"FT_Common.PS_DICT_UNIQUE_ID"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.PS_DICT_VERSION"); _vec2.push_back(L"36"); + _vec1.push_back(L"FT_Common.PS_DICT_WEIGHT"); _vec2.push_back(L"40"); + _vec1.push_back(L"FT_Common.ROUND_XY_TO_GRID"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.SCALED_COMPONENT_OFFSET"); _vec2.push_back(L"2048"); + _vec1.push_back(L"FT_Common.SPH_OPTION_BITMAP_WIDTHS"); _vec2.push_back(L"false"); + _vec1.push_back(L"FT_Common.SPH_OPTION_SET_COMPATIBLE_WIDTHS"); _vec2.push_back(L"false"); + _vec1.push_back(L"FT_Common.SPH_OPTION_SET_GRAYSCALE"); _vec2.push_back(L"false"); + _vec1.push_back(L"FT_Common.SPH_OPTION_SET_RASTERIZER_VERSION"); _vec2.push_back(L"38"); + _vec1.push_back(L"FT_Common.SPH_OPTION_SET_SUBPIXEL"); _vec2.push_back(L"true"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_ALLOW_X_DMOVEX"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_ALLOW_X_DMOVE"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_ALLOW_X_MOVE_ZP2"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_ALWAYS_DO_DELTAP"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_ALWAYS_SKIP_DELTAP"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_COURIER_NEW_2_HACK"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_DEEMBOLDEN"); _vec2.push_back(L"64"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES"); _vec2.push_back(L"128"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_DO_SHPIX"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_EMBOLDEN"); _vec2.push_back(L"512"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_MIAP_HACK"); _vec2.push_back(L"1024"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_MIRP_CVT_ZERO"); _vec2.push_back(L"8388608"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_NORMAL_ROUND"); _vec2.push_back(L"2048"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_NO_ALIGNRP_AFTER_IUP"); _vec2.push_back(L"4096"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_NO_CALL_AFTER_IUP"); _vec2.push_back(L"8192"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_NO_DELTAP_AFTER_IUP"); _vec2.push_back(L"16384"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_PIXEL_HINTING"); _vec2.push_back(L"32768"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_RASTERIZER_35"); _vec2.push_back(L"65536"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES"); _vec2.push_back(L"131072"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_SKIP_INLINE_DELTAS"); _vec2.push_back(L"262144"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_SKIP_IUP"); _vec2.push_back(L"524288"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES"); _vec2.push_back(L"1048576"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES"); _vec2.push_back(L"2097152"); + _vec1.push_back(L"FT_Common.SPH_TWEAK_TIMES_NEW_ROMAN_HACK"); _vec2.push_back(L"4194304"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_0"); _vec2.push_back(L"48"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_7"); _vec2.push_back(L"55"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_9"); _vec2.push_back(L"57"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_A"); _vec2.push_back(L"65"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_BS"); _vec2.push_back(L"47"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_B"); _vec2.push_back(L"66"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_C"); _vec2.push_back(L"67"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_D"); _vec2.push_back(L"68"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_E"); _vec2.push_back(L"69"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_F"); _vec2.push_back(L"70"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_G"); _vec2.push_back(L"71"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_H"); _vec2.push_back(L"72"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_I"); _vec2.push_back(L"73"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_J"); _vec2.push_back(L"74"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_K"); _vec2.push_back(L"75"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_LOGOR"); _vec2.push_back(L"124"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_LS1"); _vec2.push_back(L"40"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_LS2"); _vec2.push_back(L"91"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_LS3"); _vec2.push_back(L"123"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_L"); _vec2.push_back(L"76"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_MATH_1"); _vec2.push_back(L"60"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_MATH_2"); _vec2.push_back(L"62"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_MATH_3"); _vec2.push_back(L"37"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_MATH_MINUS"); _vec2.push_back(L"45"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_MATH_PLUS"); _vec2.push_back(L"43"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_M"); _vec2.push_back(L"77"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_N"); _vec2.push_back(L"78"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_O"); _vec2.push_back(L"79"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_POINT"); _vec2.push_back(L"46"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_P"); _vec2.push_back(L"80"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_Q"); _vec2.push_back(L"81"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_RS1"); _vec2.push_back(L"41"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_RS2"); _vec2.push_back(L"93"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_RS3"); _vec2.push_back(L"125"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_R"); _vec2.push_back(L"82"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_S0"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_SERP"); _vec2.push_back(L"59"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_SF"); _vec2.push_back(L"12"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_SHARP"); _vec2.push_back(L"35"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_SN"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_SPACE"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_SR"); _vec2.push_back(L"13"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_SS"); _vec2.push_back(L"92"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_ST"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_S"); _vec2.push_back(L"83"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_T"); _vec2.push_back(L"84"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_U"); _vec2.push_back(L"85"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_VOPROS"); _vec2.push_back(L"63"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_VOSCL"); _vec2.push_back(L"33"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_V"); _vec2.push_back(L"86"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_W"); _vec2.push_back(L"87"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_X"); _vec2.push_back(L"88"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_Y"); _vec2.push_back(L"89"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_Z"); _vec2.push_back(L"90"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST__"); _vec2.push_back(L"95"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_a"); _vec2.push_back(L"97"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_b"); _vec2.push_back(L"98"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_c"); _vec2.push_back(L"99"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_d"); _vec2.push_back(L"100"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_e"); _vec2.push_back(L"101"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_f"); _vec2.push_back(L"102"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_g"); _vec2.push_back(L"103"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_h"); _vec2.push_back(L"104"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_i"); _vec2.push_back(L"105"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_j"); _vec2.push_back(L"106"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_k"); _vec2.push_back(L"107"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_l"); _vec2.push_back(L"108"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_m"); _vec2.push_back(L"109"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_n"); _vec2.push_back(L"110"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_o"); _vec2.push_back(L"111"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_p"); _vec2.push_back(L"112"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_q"); _vec2.push_back(L"113"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_r"); _vec2.push_back(L"114"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_s"); _vec2.push_back(L"115"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_t"); _vec2.push_back(L"116"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_u"); _vec2.push_back(L"117"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_v"); _vec2.push_back(L"118"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_w"); _vec2.push_back(L"119"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_x"); _vec2.push_back(L"120"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_y"); _vec2.push_back(L"121"); + _vec1.push_back(L"FT_Common.SYMBOL_CONST_z"); _vec2.push_back(L"122"); + _vec1.push_back(L"FT_Common.T1_BLEND_BLUE_SCALE"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.T1_BLEND_BLUE_SHIFT"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.T1_BLEND_BLUE_VALUES"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.T1_BLEND_FAMILY_BLUES"); _vec2.push_back(L"11"); + _vec1.push_back(L"FT_Common.T1_BLEND_FAMILY_OTHER_BLUES"); _vec2.push_back(L"12"); + _vec1.push_back(L"FT_Common.T1_BLEND_FORCE_BOLD"); _vec2.push_back(L"13"); + _vec1.push_back(L"FT_Common.T1_BLEND_ITALIC_ANGLE"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.T1_BLEND_MAX"); _vec2.push_back(L"14"); + _vec1.push_back(L"FT_Common.T1_BLEND_OTHER_BLUES"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.T1_BLEND_STANDARD_HEIGHT"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.T1_BLEND_STANDARD_WIDTH"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.T1_BLEND_STEM_SNAP_HEIGHTS"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.T1_BLEND_STEM_SNAP_WIDTHS"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.T1_BLEND_UNDERLINE_POSITION"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.T1_BLEND_UNDERLINE_THICKNESS"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.T1_ENCODING_TYPE_ARRAY"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.T1_ENCODING_TYPE_EXPERT"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.T1_ENCODING_TYPE_ISOLATIN1"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.T1_ENCODING_TYPE_NONE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.T1_ENCODING_TYPE_STANDARD"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.T1_FIELD_DICT_FONTDICT"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.T1_FIELD_DICT_PRIVATE"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_BBOX"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_BLEND"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_CID_INFO"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_FACE"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_FONT_DICT"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_FONT_EXTRA"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_FONT_INFO"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_LOADER"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_MAX"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.T1_FIELD_LOCATION_PRIVATE"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_BBOX"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_BOOL"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_CALLBACK"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_FIXED_1000"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_FIXED_ARRAY"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_FIXED"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_INTEGER_ARRAY"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_INTEGER"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_KEY"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_MAX"); _vec2.push_back(L"11"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_NONE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.T1_FIELD_TYPE_STRING"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.T1_FONTDIR_AFTER_PRIVATE"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.T1_MAX_CHARSTRINGS_OPERANDS"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.T1_MAX_MM_AXIS"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.T1_MAX_MM_DESIGNS"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.T1_MAX_MM_MAP_POINTS"); _vec2.push_back(L"20"); + _vec1.push_back(L"FT_Common.T1_MAX_SUBRS_CALLS"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.T1_MAX_TABLE_ELEMENTS"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.T1_PRIVATE"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.T1_Parse_Have_Moveto"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.T1_Parse_Have_Path"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.T1_Parse_Have_Width"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.T1_Parse_Start"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.T1_TOKEN_TYPE_ANY"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.T1_TOKEN_TYPE_ARRAY"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.T1_TOKEN_TYPE_KEY"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.T1_TOKEN_TYPE_MAX"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.T1_TOKEN_TYPE_NONE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.T1_TOKEN_TYPE_STRING"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.TABLE_EXTEND"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.TTAG_BASE"); _vec2.push_back(L"1111577413"); + _vec1.push_back(L"FT_Common.TTAG_BDF"); _vec2.push_back(L"1111770656"); + _vec1.push_back(L"FT_Common.TTAG_CFF"); _vec2.push_back(L"1128678944"); + _vec1.push_back(L"FT_Common.TTAG_CID"); _vec2.push_back(L"1128875040"); + _vec1.push_back(L"FT_Common.TTAG_DSIG"); _vec2.push_back(L"1146308935"); + _vec1.push_back(L"FT_Common.TTAG_EBDT"); _vec2.push_back(L"1161970772"); + _vec1.push_back(L"FT_Common.TTAG_EBLC"); _vec2.push_back(L"1161972803"); + _vec1.push_back(L"FT_Common.TTAG_EBSC"); _vec2.push_back(L"1161974595"); + _vec1.push_back(L"FT_Common.TTAG_FOND"); _vec2.push_back(L"1179602500"); + _vec1.push_back(L"FT_Common.TTAG_GDEF"); _vec2.push_back(L"1195656518"); + _vec1.push_back(L"FT_Common.TTAG_GPOS"); _vec2.push_back(L"1196445523"); + _vec1.push_back(L"FT_Common.TTAG_GSUB"); _vec2.push_back(L"1196643650"); + _vec1.push_back(L"FT_Common.TTAG_JSTF"); _vec2.push_back(L"1246975046"); + _vec1.push_back(L"FT_Common.TTAG_LTSH"); _vec2.push_back(L"1280594760"); + _vec1.push_back(L"FT_Common.TTAG_LWFN"); _vec2.push_back(L"1280788046"); + _vec1.push_back(L"FT_Common.TTAG_MATH"); _vec2.push_back(L"1296127048"); + _vec1.push_back(L"FT_Common.TTAG_META"); _vec2.push_back(L"1296389185"); + _vec1.push_back(L"FT_Common.TTAG_MMFX"); _vec2.push_back(L"1296909912"); + _vec1.push_back(L"FT_Common.TTAG_MMSD"); _vec2.push_back(L"1296913220"); + _vec1.push_back(L"FT_Common.TTAG_OS2"); _vec2.push_back(L"1330851634"); + _vec1.push_back(L"FT_Common.TTAG_OTTO"); _vec2.push_back(L"1330926671"); + _vec1.push_back(L"FT_Common.TTAG_PCLT"); _vec2.push_back(L"1346587732"); + _vec1.push_back(L"FT_Common.TTAG_POST"); _vec2.push_back(L"1347375956"); + _vec1.push_back(L"FT_Common.TTAG_SING"); _vec2.push_back(L"1397313095"); + _vec1.push_back(L"FT_Common.TTAG_TYP1"); _vec2.push_back(L"1415139377"); + _vec1.push_back(L"FT_Common.TTAG_VDMX"); _vec2.push_back(L"1447316824"); + _vec1.push_back(L"FT_Common.TTAG_avar"); _vec2.push_back(L"1635148146"); + _vec1.push_back(L"FT_Common.TTAG_bdat"); _vec2.push_back(L"1650745716"); + _vec1.push_back(L"FT_Common.TTAG_bhed"); _vec2.push_back(L"1651008868"); + _vec1.push_back(L"FT_Common.TTAG_bloc"); _vec2.push_back(L"1651273571"); + _vec1.push_back(L"FT_Common.TTAG_bsln"); _vec2.push_back(L"1651731566"); + _vec1.push_back(L"FT_Common.TTAG_cmap"); _vec2.push_back(L"1668112752"); + _vec1.push_back(L"FT_Common.TTAG_cvar"); _vec2.push_back(L"1668702578"); + _vec1.push_back(L"FT_Common.TTAG_cvt"); _vec2.push_back(L"1668707360"); + _vec1.push_back(L"FT_Common.TTAG_feat"); _vec2.push_back(L"1717920116"); + _vec1.push_back(L"FT_Common.TTAG_fpgm"); _vec2.push_back(L"1718642541"); + _vec1.push_back(L"FT_Common.TTAG_fvar"); _vec2.push_back(L"1719034226"); + _vec1.push_back(L"FT_Common.TTAG_gasp"); _vec2.push_back(L"1734439792"); + _vec1.push_back(L"FT_Common.TTAG_glyf"); _vec2.push_back(L"1735162214"); + _vec1.push_back(L"FT_Common.TTAG_gvar"); _vec2.push_back(L"1735811442"); + _vec1.push_back(L"FT_Common.TTAG_hdmx"); _vec2.push_back(L"1751412088"); + _vec1.push_back(L"FT_Common.TTAG_head"); _vec2.push_back(L"1751474532"); + _vec1.push_back(L"FT_Common.TTAG_hhea"); _vec2.push_back(L"1751672161"); + _vec1.push_back(L"FT_Common.TTAG_hmtx"); _vec2.push_back(L"1752003704"); + _vec1.push_back(L"FT_Common.TTAG_just"); _vec2.push_back(L"1786082164"); + _vec1.push_back(L"FT_Common.TTAG_kern"); _vec2.push_back(L"1801810542"); + _vec1.push_back(L"FT_Common.TTAG_lcar"); _vec2.push_back(L"1818452338"); + _vec1.push_back(L"FT_Common.TTAG_loca"); _vec2.push_back(L"1819239265"); + _vec1.push_back(L"FT_Common.TTAG_maxp"); _vec2.push_back(L"1835104368"); + _vec1.push_back(L"FT_Common.TTAG_mort"); _vec2.push_back(L"1836020340"); + _vec1.push_back(L"FT_Common.TTAG_morx"); _vec2.push_back(L"1836020344"); + _vec1.push_back(L"FT_Common.TTAG_name"); _vec2.push_back(L"1851878757"); + _vec1.push_back(L"FT_Common.TTAG_opbd"); _vec2.push_back(L"1869636196"); + _vec1.push_back(L"FT_Common.TTAG_opsz"); _vec2.push_back(L"1869640570"); + _vec1.push_back(L"FT_Common.TTAG_post"); _vec2.push_back(L"1886352244"); + _vec1.push_back(L"FT_Common.TTAG_prep"); _vec2.push_back(L"1886545264"); + _vec1.push_back(L"FT_Common.TTAG_prop"); _vec2.push_back(L"1886547824"); + _vec1.push_back(L"FT_Common.TTAG_sfnt"); _vec2.push_back(L"1936092788"); + _vec1.push_back(L"FT_Common.TTAG_slnt"); _vec2.push_back(L"1936486004"); + _vec1.push_back(L"FT_Common.TTAG_trak"); _vec2.push_back(L"1953653099"); + _vec1.push_back(L"FT_Common.TTAG_true"); _vec2.push_back(L"1953658213"); + _vec1.push_back(L"FT_Common.TTAG_ttcf"); _vec2.push_back(L"1953784678"); + _vec1.push_back(L"FT_Common.TTAG_ttc"); _vec2.push_back(L"1953784608"); + _vec1.push_back(L"FT_Common.TTAG_typ1"); _vec2.push_back(L"1954115633"); + _vec1.push_back(L"FT_Common.TTAG_vhea"); _vec2.push_back(L"1986553185"); + _vec1.push_back(L"FT_Common.TTAG_vmtx"); _vec2.push_back(L"1986884728"); + _vec1.push_back(L"FT_Common.TTAG_wdth"); _vec2.push_back(L"2003072104"); + _vec1.push_back(L"FT_Common.TTAG_wght"); _vec2.push_back(L"2003265652"); + _vec1.push_back(L"FT_Common.TT_ADOBE_ID_CUSTOM"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.TT_ADOBE_ID_EXPERT"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.TT_ADOBE_ID_LATIN_1"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.TT_ADOBE_ID_STANDARD"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.TT_APPLE_ID_DEFAULT"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.TT_APPLE_ID_ISO_10646"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.TT_APPLE_ID_UNICODE_1_1"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.TT_APPLE_ID_UNICODE_2_0"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.TT_APPLE_ID_UNICODE_32"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.TT_APPLE_ID_VARIANT_SELECTOR"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.TT_CMAP_FLAG_OVERLAPPING"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.TT_CMAP_FLAG_UNSORTED"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.TT_MAC_ID_ROMAN"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.TT_MAX_CODE_RANGES"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.TT_MS_ID_BIG_5"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.TT_MS_ID_GB2312"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.TT_MS_ID_JOHAB"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.TT_MS_ID_SJIS"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.TT_MS_ID_SYMBOL_CS"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.TT_MS_ID_UCS_4"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.TT_MS_ID_UNICODE_CS"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.TT_MS_ID_WANSUNG"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_CID_FINDFONT_NAME"); _vec2.push_back(L"20"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_COPYRIGHT"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_DESCRIPTION"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_DESIGNER_URL"); _vec2.push_back(L"12"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_DESIGNER"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_FONT_FAMILY"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_FONT_SUBFAMILY"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_FULL_NAME"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_LICENSE_URL"); _vec2.push_back(L"14"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_LICENSE"); _vec2.push_back(L"13"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_MAC_FULL_NAME"); _vec2.push_back(L"18"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_MANUFACTURER"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_PREFERRED_FAMILY"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_PREFERRED_SUBFAMILY"); _vec2.push_back(L"17"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_PS_NAME"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_SAMPLE_TEXT"); _vec2.push_back(L"19"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_TRADEMARK"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_UNIQUE_ID"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_VENDOR_URL"); _vec2.push_back(L"11"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_VERSION_STRING"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_WWS_FAMILY"); _vec2.push_back(L"21"); + _vec1.push_back(L"FT_Common.TT_NAME_ID_WWS_SUBFAMILY"); _vec2.push_back(L"22"); + _vec1.push_back(L"FT_Common.TT_PLATFORM_ADOBE"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.TT_PLATFORM_APPLE_UNICODE"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.TT_PLATFORM_CUSTOM"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.TT_PLATFORM_ISO"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.TT_PLATFORM_MACINTOSH"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.TT_PLATFORM_MICROSOFT"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.UNSCALED_COMPONENT_OFFSET"); _vec2.push_back(L"4096"); + _vec1.push_back(L"FT_Common.USE_MY_METRICS"); _vec2.push_back(L"512"); + _vec1.push_back(L"FT_Common.WE_HAVE_AN_XY_SCALE"); _vec2.push_back(L"64"); + _vec1.push_back(L"FT_Common.WE_HAVE_A_2X2"); _vec2.push_back(L"128"); + _vec1.push_back(L"FT_Common.WE_HAVE_A_SCALE"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.WE_HAVE_INSTR"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.a_c"); _vec2.push_back(L"256"); + _vec1.push_back(L"FT_Common.a_i"); _vec2.push_back(L"4294967296"); + _vec1.push_back(L"FT_Common.a_s"); _vec2.push_back(L"65536"); + _vec1.push_back(L"FT_Common.cff_kind_bool"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.cff_kind_callback"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.cff_kind_delta"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.cff_kind_fixed_thousand"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.cff_kind_fixed"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.cff_kind_max"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.cff_kind_none"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.cff_kind_num"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.cff_kind_string"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.cff_op_abs"); _vec2.push_back(L"26"); + _vec1.push_back(L"FT_Common.cff_op_add"); _vec2.push_back(L"27"); + _vec1.push_back(L"FT_Common.cff_op_and"); _vec2.push_back(L"44"); + _vec1.push_back(L"FT_Common.cff_op_blend"); _vec2.push_back(L"34"); + _vec1.push_back(L"FT_Common.cff_op_callgsubr"); _vec2.push_back(L"50"); + _vec1.push_back(L"FT_Common.cff_op_callothersubr"); _vec2.push_back(L"54"); + _vec1.push_back(L"FT_Common.cff_op_callsubr"); _vec2.push_back(L"49"); + _vec1.push_back(L"FT_Common.cff_op_closepath"); _vec2.push_back(L"53"); + _vec1.push_back(L"FT_Common.cff_op_cntrmask"); _vec2.push_back(L"24"); + _vec1.push_back(L"FT_Common.cff_op_div"); _vec2.push_back(L"29"); + _vec1.push_back(L"FT_Common.cff_op_dotsection"); _vec2.push_back(L"25"); + _vec1.push_back(L"FT_Common.cff_op_drop"); _vec2.push_back(L"35"); + _vec1.push_back(L"FT_Common.cff_op_dup"); _vec2.push_back(L"39"); + _vec1.push_back(L"FT_Common.cff_op_endchar"); _vec2.push_back(L"18"); + _vec1.push_back(L"FT_Common.cff_op_eq"); _vec2.push_back(L"47"); + _vec1.push_back(L"FT_Common.cff_op_exch"); _vec2.push_back(L"36"); + _vec1.push_back(L"FT_Common.cff_op_flex1"); _vec2.push_back(L"17"); + _vec1.push_back(L"FT_Common.cff_op_flex"); _vec2.push_back(L"14"); + _vec1.push_back(L"FT_Common.cff_op_get"); _vec2.push_back(L"41"); + _vec1.push_back(L"FT_Common.cff_op_hflex1"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.cff_op_hflex"); _vec2.push_back(L"15"); + _vec1.push_back(L"FT_Common.cff_op_hhcurveto"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.cff_op_hintmask"); _vec2.push_back(L"23"); + _vec1.push_back(L"FT_Common.cff_op_hlineto"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.cff_op_hmoveto"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.cff_op_hsbw"); _vec2.push_back(L"52"); + _vec1.push_back(L"FT_Common.cff_op_hstemhm"); _vec2.push_back(L"21"); + _vec1.push_back(L"FT_Common.cff_op_hstem"); _vec2.push_back(L"19"); + _vec1.push_back(L"FT_Common.cff_op_hvcurveto"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.cff_op_ifelse"); _vec2.push_back(L"48"); + _vec1.push_back(L"FT_Common.cff_op_index"); _vec2.push_back(L"37"); + _vec1.push_back(L"FT_Common.cff_op_load"); _vec2.push_back(L"43"); + _vec1.push_back(L"FT_Common.cff_op_max"); _vec2.push_back(L"59"); + _vec1.push_back(L"FT_Common.cff_op_mul"); _vec2.push_back(L"32"); + _vec1.push_back(L"FT_Common.cff_op_neg"); _vec2.push_back(L"30"); + _vec1.push_back(L"FT_Common.cff_op_not"); _vec2.push_back(L"46"); + _vec1.push_back(L"FT_Common.cff_op_or"); _vec2.push_back(L"45"); + _vec1.push_back(L"FT_Common.cff_op_pop"); _vec2.push_back(L"55"); + _vec1.push_back(L"FT_Common.cff_op_put"); _vec2.push_back(L"40"); + _vec1.push_back(L"FT_Common.cff_op_random"); _vec2.push_back(L"31"); + _vec1.push_back(L"FT_Common.cff_op_rcurveline"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.cff_op_return"); _vec2.push_back(L"51"); + _vec1.push_back(L"FT_Common.cff_op_rlinecurve"); _vec2.push_back(L"11"); + _vec1.push_back(L"FT_Common.cff_op_rlineto"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.cff_op_rmoveto"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.cff_op_roll"); _vec2.push_back(L"38"); + _vec1.push_back(L"FT_Common.cff_op_rrcurveto"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.cff_op_sbw"); _vec2.push_back(L"57"); + _vec1.push_back(L"FT_Common.cff_op_seac"); _vec2.push_back(L"56"); + _vec1.push_back(L"FT_Common.cff_op_setcurrentpoint"); _vec2.push_back(L"58"); + _vec1.push_back(L"FT_Common.cff_op_sqrt"); _vec2.push_back(L"33"); + _vec1.push_back(L"FT_Common.cff_op_store"); _vec2.push_back(L"42"); + _vec1.push_back(L"FT_Common.cff_op_sub"); _vec2.push_back(L"28"); + _vec1.push_back(L"FT_Common.cff_op_unknown"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.cff_op_vhcurveto"); _vec2.push_back(L"12"); + _vec1.push_back(L"FT_Common.cff_op_vlineto"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.cff_op_vmoveto"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.cff_op_vstemhm"); _vec2.push_back(L"22"); + _vec1.push_back(L"FT_Common.cff_op_vstem"); _vec2.push_back(L"20"); + _vec1.push_back(L"FT_Common.cff_op_vvcurveto"); _vec2.push_back(L"13"); + _vec1.push_back(L"FT_Common.m_c"); _vec2.push_back(L"127"); + _vec1.push_back(L"FT_Common.m_i"); _vec2.push_back(L"2147483647"); + _vec1.push_back(L"FT_Common.m_s"); _vec2.push_back(L"32767"); + _vec1.push_back(L"FT_Common.op_callothersubr"); _vec2.push_back(L"21"); + _vec1.push_back(L"FT_Common.op_callsubr"); _vec2.push_back(L"22"); + _vec1.push_back(L"FT_Common.op_closepath"); _vec2.push_back(L"5"); + _vec1.push_back(L"FT_Common.op_div"); _vec2.push_back(L"20"); + _vec1.push_back(L"FT_Common.op_dotsection"); _vec2.push_back(L"15"); + _vec1.push_back(L"FT_Common.op_endchar"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.op_hlineto"); _vec2.push_back(L"6"); + _vec1.push_back(L"FT_Common.op_hmoveto"); _vec2.push_back(L"7"); + _vec1.push_back(L"FT_Common.op_hsbw"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.op_hstem3"); _vec2.push_back(L"17"); + _vec1.push_back(L"FT_Common.op_hstem"); _vec2.push_back(L"16"); + _vec1.push_back(L"FT_Common.op_hvcurveto"); _vec2.push_back(L"8"); + _vec1.push_back(L"FT_Common.op_max"); _vec2.push_back(L"27"); + _vec1.push_back(L"FT_Common.op_none"); _vec2.push_back(L"0"); + _vec1.push_back(L"FT_Common.op_pop"); _vec2.push_back(L"23"); + _vec1.push_back(L"FT_Common.op_return"); _vec2.push_back(L"24"); + _vec1.push_back(L"FT_Common.op_rlineto"); _vec2.push_back(L"9"); + _vec1.push_back(L"FT_Common.op_rmoveto"); _vec2.push_back(L"10"); + _vec1.push_back(L"FT_Common.op_rrcurveto"); _vec2.push_back(L"11"); + _vec1.push_back(L"FT_Common.op_sbw"); _vec2.push_back(L"4"); + _vec1.push_back(L"FT_Common.op_seac"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.op_setcurrentpoint"); _vec2.push_back(L"25"); + _vec1.push_back(L"FT_Common.op_unknown15"); _vec2.push_back(L"26"); + _vec1.push_back(L"FT_Common.op_vhcurveto"); _vec2.push_back(L"12"); + _vec1.push_back(L"FT_Common.op_vlineto"); _vec2.push_back(L"13"); + _vec1.push_back(L"FT_Common.op_vmoveto"); _vec2.push_back(L"14"); + _vec1.push_back(L"FT_Common.op_vstem3"); _vec2.push_back(L"19"); + _vec1.push_back(L"FT_Common.op_vstem"); _vec2.push_back(L"18"); + _vec1.push_back(L"FT_Common.tt_coderange_cvt"); _vec2.push_back(L"2"); + _vec1.push_back(L"FT_Common.tt_coderange_font"); _vec2.push_back(L"1"); + _vec1.push_back(L"FT_Common.tt_coderange_glyph"); _vec2.push_back(L"3"); + _vec1.push_back(L"FT_Common.tt_coderange_none"); _vec2.push_back(L"0"); +} + +void string_replace(std::wstring& text, const std::wstring& replaceFrom, const std::wstring& replaceTo) +{ + size_t posn = 0; + while (std::wstring::npos != (posn = text.find(replaceFrom, posn))) + { + text.replace(posn, replaceFrom.length(), replaceTo); + posn += replaceTo.length(); + } +} + +void CorrectScript(std::wstring& sData, std::vector<std::wstring>& _vec1, std::vector<std::wstring>& _vec2) +{ + std::vector<std::wstring>::iterator i = _vec1.begin(); + std::vector<std::wstring>::iterator j = _vec2.begin(); + for (; i != _vec1.end(); i++, j++) + { + string_replace(sData, *i, *j); + } +} + +int main() +{ + std::wstring sBasePath = NSFile::GetProcessDirectory() + L"/../../Freetype/"; + + // FILES + std::vector<std::wstring> arFiles; + arFiles.push_back(sBasePath + L"config.js"); + arFiles.push_back(sBasePath + L"services.js"); + arFiles.push_back(sBasePath + L"base.js"); + + arFiles.push_back(sBasePath + L"modules/psnames.js"); + arFiles.push_back(sBasePath + L"modules/psaux.js"); + arFiles.push_back(sBasePath + L"modules/sfnt.js"); + arFiles.push_back(sBasePath + L"modules/render.js"); + + arFiles.push_back(sBasePath + L"drivers/ttinterp.js"); + arFiles.push_back(sBasePath + L"drivers/truetype.js"); + arFiles.push_back(sBasePath + L"drivers/cff.js"); + arFiles.push_back(sBasePath + L"drivers/t1.js"); + + arFiles.push_back(sBasePath + L"freetype.js"); + + // CONFIG MAP + std::vector<std::wstring> _vec1; + std::vector<std::wstring> _vec2; + GetConfigMap(_vec1, _vec2); + + // READ + std::wstring sOutput = L"\"use strict\";\r\n\r\n"; + for (std::vector<std::wstring>::iterator i = arFiles.begin(); i != arFiles.end(); i++) + { + std::wstring sFileInput = *i; + + std::wstring sData = L""; + NSFile::CFileBinary::ReadAllTextUtf8(sFileInput, sData); + + if (sFileInput.find(L"config.js") != std::wstring::npos) + { + std::wstring s0 = L"function _FT_Common()"; + std::wstring::size_type nPos0 = sData.find(s0); + if (nPos0 != std::wstring::npos) + { + sData = sData.substr(nPos0); + } + + std::wstring s1 = L"// GENERATOR_START_CONSTANTS"; + std::wstring s2 = L"// GENERATOR_END_CONSTANTS"; + + std::wstring::size_type nPos1 = sData.find(s1); + std::wstring::size_type nPos2 = sData.find(s2); + + if (nPos1 != std::wstring::npos && nPos2 != std::wstring::npos) + { + std::wstring sRes = sData.substr(0, nPos1) + sData.substr(nPos2 + s2.length()); + sData = sRes; + } + } + + CorrectScript(sData, _vec1, _vec2); + + sOutput += sData; + sOutput += L"\n"; + } + + NSFile::CFileBinary::SaveToFile(sBasePath + L"../../font_engine.js", sOutput); + + return 0; +} + diff --git a/Common/FontsFreeType/font_engine.js b/Common/FontsFreeType/font_engine.js index 77990a7df297cd9d263563680f9d3234cd326625..b6f206f0b7a34f44770f0858898f6258a3c82df0 100644 --- a/Common/FontsFreeType/font_engine.js +++ b/Common/FontsFreeType/font_engine.js @@ -1,8 +1,10 @@ "use strict"; function _FT_Common() -{ - this.UintToInt = function(v){ +{ + + + this.UintToInt = function(v){ return (v>2147483647)?v-4294967296:v; } this.UShort_To_Short = function(v){ @@ -100,7 +102,8 @@ function _FT_Common() return ret; } } -var FT_Common = new _FT_Common();/******************************************************************************/ +var FT_Common = new _FT_Common(); +/******************************************************************************/ // SERVICES /******************************************************************************/ @@ -357,7 +360,8 @@ function FT_ServiceCache() this.service_GLYPH_DICT = null; this.service_PFR_METRICS = null; this.service_WINFNT = null; -}/******************************************************************************/ +} +/******************************************************************************/ // stream /******************************************************************************/ function FT_Frame_Field(v,s,o) @@ -3909,7 +3913,8 @@ function ft_synthesize_vertical_metrics(metrics, advance) metrics.vertBearingX = parseInt(metrics.horiBearingX - metrics.horiAdvance / 2); metrics.vertBearingY = parseInt((advance - height) / 2); metrics.vertAdvance = advance; -}var ft_standard_glyph_names = [".null","nonmarkingreturn","notequal","infinity","lessequal","greaterequal","partialdiff","summation","product","pi","integral", +} +var ft_standard_glyph_names = [".null","nonmarkingreturn","notequal","infinity","lessequal","greaterequal","partialdiff","summation","product","pi","integral", "Omega","radical","approxequal","Delta","nonbreakingspace","lozenge","apple","franc","Gbreve","gbreve","Idotaccent","Scedilla", "scedilla","Cacute","cacute","Ccaron","ccaron","dcroat",".notdef","space","exclam","quotedbl","numbersign","dollar","percent", "ampersand","quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three", @@ -7997,7 +8002,8 @@ function create_psnames_module(library) psnames_mod.generic = null; return psnames_mod; -}/******************************************************************************/ +} +/******************************************************************************/ // t1tables /******************************************************************************/ function _isdigit(x) @@ -12150,7 +12156,7 @@ function T1_FieldRec() this.location = 0; this.type = 0; this.reader = null; - this.offset = 0; // � ��� ��� ������ ������ ����� ������. � �� ����� � ������ + this.offset = 0; // у Ð½Ð°Ñ Ñто проÑто Ð¸Ð½Ð´ÐµÐºÑ Ñ‡Ð»ÐµÐ½Ð° клаÑÑа. Рне Ñдвиг в памÑти this.size = 0; this.array_max = 0; @@ -12169,8 +12175,8 @@ function create_dublicate_t1_field(_field) ret.location = _field.location; ret.type = _field.type; ret.reader = _field.reader; - ret.offset = _field.offset; // � ��� ��� ������ ������ � ������� (�.�. ��� �� ������� ��� ���� �� �����) - ret.size = _field.size; // �� �������� (�� ������� �������) + ret.offset = _field.offset; // у Ð½Ð°Ñ Ñто проÑто Ð¸Ð½Ð´ÐµÐºÑ Ð² ÐœÐССИВЕ (Ñ‚.е. Ð´Ð»Ñ Ð½Ðµ маÑÑива Ñто поле не нужно) + ret.size = _field.size; // не пользуем (на будущее оÑтавим) ret.array_max = _field.array_max; ret.count_offset = _field.count_offset; @@ -12599,6 +12605,7 @@ function create_psaux_module(library) return psaux_mod; } + /******************************************************************************/ // bdf /******************************************************************************/ @@ -18129,6 +18136,7 @@ function create_sfnt_module(library) return sfnt_mod; } + function CRasterMemory() { this.width = 0; @@ -20554,7 +20562,8 @@ function ft_smooth_render_generic(render, slot, mode, origin, required_mode) FT_Outline_Translate(outline, -origin.x, -origin.y); return error; -}var TT_Round_Off = 5; +} +var TT_Round_Off = 5; var TT_Round_To_Half_Grid = 0; var TT_Round_To_Grid = 1; var TT_Round_To_Double_Grid = 2; @@ -26997,7 +27006,8 @@ function CSubpixHintingHacks() // ----------------------------------------------------------------------- } -var global_SubpixHintingHacks = new CSubpixHintingHacks();/******************************************************************************/ +var global_SubpixHintingHacks = new CSubpixHintingHacks(); +/******************************************************************************/ // classes /******************************************************************************/ function TT_Size_Metrics() @@ -28166,19 +28176,6 @@ function tt_done_blend(memory, blend) /******************************************************************************/ // glyphloader /******************************************************************************/ -FT_Common.ARGS_ARE_WORDS = 0x0001; -FT_Common.ARGS_ARE_XY_VALUES = 0x0002; -FT_Common.ROUND_XY_TO_GRID = 0x0004; -FT_Common.WE_HAVE_A_SCALE = 0x0008; -FT_Common.MORE_COMPONENTS = 0x0020; -FT_Common.WE_HAVE_AN_XY_SCALE = 0x0040; -FT_Common.WE_HAVE_A_2X2 = 0x0080; -FT_Common.WE_HAVE_INSTR = 0x0100; -FT_Common.USE_MY_METRICS = 0x0200; -FT_Common.OVERLAP_COMPOUND = 0x0400; -FT_Common.SCALED_COMPONENT_OFFSET = 0x0800; -FT_Common.UNSCALED_COMPONENT_OFFSET = 0x1000; - function load_sbit_image(size, glyph, glyph_index, load_flags) { var metrics = new TT_SBit_MetricsRec(); @@ -28585,19 +28582,19 @@ function TT_Load_Composite_Glyph(loader) count_read += 4; count = 2; - if (subglyph.flags & FT_Common.ARGS_ARE_WORDS) + if (subglyph.flags & 1) count += 2; - if (subglyph.flags & FT_Common.WE_HAVE_A_SCALE) + if (subglyph.flags & 8) count += 2; - else if (subglyph.flags & FT_Common.WE_HAVE_AN_XY_SCALE) + else if (subglyph.flags & 64) count += 4; - else if (subglyph.flags & FT_Common.WE_HAVE_A_2X2) + else if (subglyph.flags & 128) count += 8; if (count_read + count > size_read) return 21; - if (subglyph.flags & FT_Common.ARGS_ARE_WORDS) + if (subglyph.flags & 1) { subglyph.arg1 = s.GetShort(); subglyph.arg2 = s.GetShort(); @@ -28611,17 +28608,17 @@ function TT_Load_Composite_Glyph(loader) xx = yy = 0x10000; xy = yx = 0; - if (subglyph.flags & FT_Common.WE_HAVE_A_SCALE) + if (subglyph.flags & 8) { xx = s.GetShort() << 2; yy = xx; } - else if (subglyph.flags & FT_Common.WE_HAVE_AN_XY_SCALE) + else if (subglyph.flags & 64) { xx = s.GetShort() << 2; yy = s.GetShort() << 2; } - else if (subglyph.flags & FT_Common.WE_HAVE_A_2X2) + else if (subglyph.flags & 128) { xx = s.GetShort() << 2; yx = s.GetShort() << 2; @@ -28638,7 +28635,7 @@ function TT_Load_Composite_Glyph(loader) count_read += count; - } while (subglyph.flags & FT_Common.MORE_COMPONENTS); + } while (subglyph.flags & 32); gloader.current.num_subglyphs = num_subglyphs; @@ -28795,7 +28792,7 @@ function TT_Process_Composite_Component(loader, subglyph, start_point, num_base_ var num_points = gloader.base.outline.n_points; var x, y; - var have_scale = (0 == (subglyph.flags & (FT_Common.WE_HAVE_A_SCALE | FT_Common.WE_HAVE_AN_XY_SCALE | FT_Common.WE_HAVE_A_2X2))) ? 0 : 1; + var have_scale = (0 == (subglyph.flags & (8 | 64 | 128))) ? 0 : 1; if (have_scale != 0) { @@ -28803,7 +28800,7 @@ function TT_Process_Composite_Component(loader, subglyph, start_point, num_base_ FT_Vector_Transform(base_vecs[i], subglyph.transform); } - if (0 == (subglyph.flags & FT_Common.ARGS_ARE_XY_VALUES)) + if (0 == (subglyph.flags & 2)) { var k = subglyph.arg1; var l = subglyph.arg2; @@ -28826,7 +28823,7 @@ function TT_Process_Composite_Component(loader, subglyph, start_point, num_base_ if (x == 0 && y == 0) return 0; - if (have_scale != 0 && 0 != (subglyph.flags & FT_Common.SCALED_COMPONENT_OFFSET)) + if (have_scale != 0 && 0 != (subglyph.flags & 2048)) { var mac_xscale = FT_SqrtFixed(FT_MulFix(subglyph.transform.xx, subglyph.transform.xx) + FT_MulFix(subglyph.transform.xy, subglyph.transform.xy)); @@ -28846,7 +28843,7 @@ function TT_Process_Composite_Component(loader, subglyph, start_point, num_base_ x = FT_MulFix(x, x_scale); y = FT_MulFix(y, y_scale); - if (subglyph.flags & FT_Common.ROUND_XY_TO_GRID) + if (subglyph.flags & 4) { x = FT_PIX_ROUND(x); y = FT_PIX_ROUND(y); @@ -29705,7 +29702,7 @@ function load_truetype_glyph(loader, glyph_index, recurse_count, header_only) var i = 0; for (; i < limit; ++i, ++subglyph ) { - if (subglyph.flags & FT_Common.ARGS_ARE_XY_VALUES) + if (subglyph.flags & 2) { subglyph.arg1 += (deltas[i].x & 0xFFFF); subglyph.arg2 += (deltas[i].y & 0xFFFF); @@ -29788,7 +29785,7 @@ function load_truetype_glyph(loader, glyph_index, recurse_count, header_only) var bIsSubFlags = true; if (bIsSubFlags && face.driver.library.tt_hint_props.TT_USE_BYTECODE_INTERPRETER) - bIsSubFlags = ((subglyph.flags & FT_Common.WE_HAVE_INSTR) != 0); + bIsSubFlags = ((subglyph.flags & 256) != 0); if (((loader.load_flags & 2) == 0) && bIsSubFlags && num_points > start_point) TT_Process_Composite_Glyph(loader, start_point, start_contour); @@ -30796,7 +30793,8 @@ function create_tt_driver(library) driver.clazz = new TT_Driver_Class(); return driver; -}/******************************************************************************/ +} +/******************************************************************************/ // cfftypes /******************************************************************************/ function CFF_IndexRec() @@ -36762,7 +36760,8 @@ function create_cff_driver(library) driver.memory = library.Memory; return driver; -}/******************************************************************************/ +} +/******************************************************************************/ // afm /******************************************************************************/ function T1_Done_Metrics(memory, fi) @@ -40399,7 +40398,8 @@ function create_t1_driver(library) driver.clazz = new T1_Driver_Class(); return driver; -}var FT_Error = 0; +} +var FT_Error = 0; function FT_Library() { this.Memory = null; @@ -40469,6 +40469,7 @@ function FT_Library() error = this.ft_add_renderer(module); if (0 != error) { + //delete module; return error; } } @@ -40617,7 +40618,7 @@ function FT_Library() slot = null; if (FT_Error != 0) { - face = null; + face = null; return null; } @@ -40626,7 +40627,7 @@ function FT_Library() var size = FT_New_Size(face); if (FT_Error != 0) { - face = null; + face = null; return null; } @@ -41705,3 +41706,4 @@ function FT_CMap_New(clazz, init_data, charmap) return cmap; } +