diff --git a/Makefile b/Makefile index fb4ffe9cb..56b597e5f 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,8 @@ PDF_JS_FILES = \ pdf.js \ crypto.js \ fonts.js \ + metrics.js \ + charsets.js \ glyphlist.js \ $(NULL) diff --git a/charsets.js b/charsets.js new file mode 100644 index 000000000..59fcdf5cf --- /dev/null +++ b/charsets.js @@ -0,0 +1,101 @@ + +var ISOAdobeCharset = [ + '.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' +]; + +var ExpertCharset = [ + '.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', + 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', + 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', + 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', + 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', + 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', + 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', + 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', + 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', + 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'fi', 'fl', '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', 'onequarter', 'onehalf', 'threequarters', + 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', + 'twosuperior', 'threesuperior', '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' +]; + +var ExpertSubsetCharset = [ + '.notdef', 'space', 'dollaroldstyle', 'dollarsuperior', + 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', + 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', + 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', + 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', + 'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior', + 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', + 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', + 'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted', + 'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter', + 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', + 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', + 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', + 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', + 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', + 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', + 'periodinferior', 'commainferior' +]; + diff --git a/fonts.js b/fonts.js index eeefa02f8..e5cce0b4f 100644 --- a/fonts.js +++ b/fonts.js @@ -447,13 +447,14 @@ var Font = (function Font() { } var data; - switch (properties.type) { + var type = properties.type; + switch (type) { case 'Type1': case 'CIDFontType0': this.mimetype = 'font/opentype'; var subtype = properties.subtype; - var cff = (subtype === 'Type1C') ? + var cff = (subtype == 'Type1C' || subtype == 'CIDFontType0C') ? new Type2CFF(file, properties) : new CFF(name, file, properties); // Wrap the CFF data inside an OTF font file @@ -475,7 +476,7 @@ var Font = (function Font() { } this.data = data; - this.type = properties.type; + this.type = type; this.textMatrix = properties.textMatrix; this.defaultWidth = properties.defaultWidth; this.loadedName = getUniqueName(); @@ -2387,16 +2388,21 @@ var Type2CFF = (function() { var strings = this.getStrings(stringIndex); - var baseDict = this.parseDict(dictIndex.get(0)); + var baseDict = this.parseDict(dictIndex.get(0).data); var topDict = this.getTopDict(baseDict, strings); var bytes = this.bytes; + var privateDict = {}; var privateInfo = topDict.Private; - var privOffset = privateInfo[1], privLength = privateInfo[0]; - var privBytes = bytes.subarray(privOffset, privOffset + privLength); - baseDict = this.parseDict(privBytes); - var privDict = this.getPrivDict(baseDict, strings); + if (privateInfo) { + var privOffset = privateInfo[1], privLength = privateInfo[0]; + var privBytes = bytes.subarray(privOffset, privOffset + privLength); + baseDict = this.parseDict(privBytes); + privateDict = this.getPrivDict(baseDict, strings); + } else { + privateDict.defaultWidthX = properties.defaultWidth; + } var charStrings = this.parseIndex(topDict.CharStrings); var charset = this.parseCharsets(topDict.charset, @@ -2412,10 +2418,37 @@ var Type2CFF = (function() { if (hasSupplement) bytes[topDict.Encoding] = 0; + // The CFF specification state that the 'dotsection' command + // (12, 0) is deprecated and treated as a no-op, but all Type2 + // charstrings processors should support them. Unfortunately + // the font sanitizer don't. As a workaround the sequence (12, 0) + // is replaced by a useless (0, hmoveto). + var count = charStrings.length; + for (var i = 0; i < count; i++) { + var charstring = charStrings.get(i); + + var start = charstring.start; + var data = charstring.data; + var length = data.length; + for (var j = 0; j <= length; j) { + var value = data[j++]; + if (value == 12 && data[j++] == 0) { + bytes[start + j - 2] = 139; + bytes[start + j - 1] = 22; + } else if (value === 28) { + j += 2; + } else if (value >= 247 && value <= 254) { + j++; + } else if (value == 255) { + j += 4; + } + } + } + // charstrings contains info about glyphs (one element per glyph // containing mappings for {unicode, width}) var charstrings = this.getCharStrings(charset, charStrings, - privDict, this.properties); + privateDict, this.properties); // create the mapping between charstring and glyph id var glyphIds = []; @@ -2432,10 +2465,8 @@ var Type2CFF = (function() { }, getCharStrings: function cff_charstrings(charsets, charStrings, - privDict, properties) { - var defaultWidth = privDict['defaultWidthX']; - var nominalWidth = privDict['nominalWidthX']; - + privateDict, properties) { + var defaultWidth = privateDict['defaultWidthX']; var charstrings = []; var differences = properties.differences; var index = 0; @@ -2492,8 +2523,8 @@ var Type2CFF = (function() { if (pos == 0 || pos == 1) { var gid = 1; - var baseEncoding = - pos ? Encodings.ExpertEncoding : Encodings.StandardEncoding; + var baseEncoding = pos ? Encodings.ExpertEncoding.slice() : + Encodings.StandardEncoding.slice(); for (var i = 0; i < charset.length; i++) { var index = baseEncoding.indexOf(charset[i]); if (index != -1) @@ -2538,37 +2569,42 @@ var Type2CFF = (function() { }, parseCharsets: function cff_parsecharsets(pos, length, strings) { + if (pos == 0) { + return ISOAdobeCharset.slice(); + } else if (pos == 1) { + return ExpertCharset.slice(); + } else if (pos == 2) { + return ExpertSubsetCharset.slice(); + } + var bytes = this.bytes; var format = bytes[pos++]; var charset = ['.notdef']; + // subtract 1 for the .notdef glyph length -= 1; switch (format) { case 0: - for (var i = 0; i < length; ++i) { - var id = bytes[pos++]; - id = (id << 8) | bytes[pos++]; - charset.push(strings[id]); + for (var i = 0; i < length; i++) { + var sid = (bytes[pos++] << 8) | bytes[pos++]; + charset.push(strings[sid]); } break; case 1: while (charset.length <= length) { - var first = bytes[pos++]; - first = (first << 8) | bytes[pos++]; - var numLeft = bytes[pos++]; - for (var i = 0; i <= numLeft; ++i) - charset.push(strings[first++]); + var sid = (bytes[pos++] << 8) | bytes[pos++]; + var count = bytes[pos++]; + for (var i = 0; i <= count; i++) + charset.push(strings[sid++]); } break; case 2: while (charset.length <= length) { - var first = bytes[pos++]; - first = (first << 8) | bytes[pos++]; - var numLeft = bytes[pos++]; - numLeft = (numLeft << 8) | bytes[pos++]; - for (var i = 0; i <= numLeft; ++i) - charset.push(strings[first++]); + var sid = (bytes[pos++] << 8) | bytes[pos++]; + var count = (bytes[pos++] << 8) | bytes[pos++]; + for (var i = 0; i <= count; i++) + charset.push(strings[sid++]); } break; default: @@ -2643,20 +2679,20 @@ var Type2CFF = (function() { } return dict; }, - getStrings: function cff_getstrings(stringIndex) { - function bytesToString(bytesArr) { - var s = ''; - for (var i = 0, ii = bytesArr.length; i < ii; ++i) - s += String.fromCharCode(bytesArr[i]); - return s; + getStrings: function cff_getStrings(stringIndex) { + function bytesToString(bytesArray) { + var str = ''; + for (var i = 0, length = bytesArray.length; i < length; i++) + str += String.fromCharCode(bytesArray[i]); + return str; } var stringArray = []; - for (var i = 0, ii = CFFStrings.length; i < ii; ++i) + for (var i = 0, length = CFFStrings.length; i < length; i++) stringArray.push(CFFStrings[i]); - for (var i = 0, ii = stringIndex.length; i < ii; ++i) - stringArray.push(bytesToString(stringIndex.get(i))); + for (var i = 0, length = stringIndex.length; i < length; i++) + stringArray.push(bytesToString(stringIndex.get(i).data)); return stringArray; }, @@ -2702,7 +2738,7 @@ var Type2CFF = (function() { } else if (value <= 254) { return -((value - 251) * 256) - dict[pos++] - 108; } else { - error('Incorrect byte'); + error('255 is not a valid DICT command'); } return -1; } @@ -2779,7 +2815,11 @@ var Type2CFF = (function() { var start = offsets[index]; var end = offsets[index + 1]; - return bytes.subarray(start, end); + return { + start: start, + end: end, + data: bytes.subarray(start, end) + }; }, length: count, endPos: end diff --git a/pdf.js b/pdf.js index 1a5bf4854..1b80424d6 100644 --- a/pdf.js +++ b/pdf.js @@ -4280,8 +4280,9 @@ var PartialEvaluator = (function partialEvaluator() { properties.widths = glyphsWidths; var cidToGidMap = dict.get('CIDToGIDMap'); - if (!cidToGidMap || !IsRef(cidToGidMap)) - return GlyphsUnicode; + if (!cidToGidMap || !IsRef(cidToGidMap)) { + return Object.create(GlyphsUnicode); + } // Extract the encoding from the CIDToGIDMap var glyphsStream = xref.fetchIfRef(cidToGidMap); @@ -4318,7 +4319,7 @@ var PartialEvaluator = (function partialEvaluator() { '9.7.5.3'); } } - return GlyphsUnicode; + return Object.create(GlyphsUnicode); } var differences = properties.differences; @@ -4494,7 +4495,7 @@ var PartialEvaluator = (function partialEvaluator() { var map = {}; if (/^Symbol(-?(Bold|Italic))*$/.test(name)) { // special case for symbols - var encoding = Encodings.symbolsEncoding; + var encoding = Encodings.symbolsEncoding.slice(); for (var i = 0, n = encoding.length, j; i < n; i++) { if (!(j = encoding[i])) continue; diff --git a/test/test_slave.html b/test/test_slave.html index 91b8a6850..b46e29d6b 100644 --- a/test/test_slave.html +++ b/test/test_slave.html @@ -7,6 +7,7 @@ + diff --git a/utils/cffStandardStrings.js b/utils/cffStandardStrings.js index 8a6570551..743c60b25 100644 --- a/utils/cffStandardStrings.js +++ b/utils/cffStandardStrings.js @@ -3,400 +3,6 @@ 'use strict'; -var CFFStrings = [ - '.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', - '266 ff', - '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 CFFEncodingMap = { '0': '-reserved-', '1': 'hstem', diff --git a/utils/fonts_utils.js b/utils/fonts_utils.js index a51469c53..550637fff 100644 --- a/utils/fonts_utils.js +++ b/utils/fonts_utils.js @@ -20,17 +20,27 @@ function readCharset(aStream, aCharstrings) { var charset = {}; var format = aStream.getByte(); + var count = aCharstrings.length - 1; if (format == 0) { charset['.notdef'] = readCharstringEncoding(aCharstrings[0]); - var count = aCharstrings.length - 1; for (var i = 1; i < count + 1; i++) { var sid = aStream.getByte() << 8 | aStream.getByte(); charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]); //log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]); } } else if (format == 1) { - error('Charset Range are not supported'); + for (var i = 1; i < count + 1; i++) { + var first = aStream.getByte(); + first = (first << 8) | aStream.getByte(); + var numLeft = aStream.getByte(); + for (var j = 0; j <= numLeft; j++) { + var sid = first++; + if (CFFStrings[sid] == 'three') + log(aCharstrings[j]); + charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[j]); + } + } } else { error('Invalid charset format'); } @@ -44,6 +54,9 @@ function readCharset(aStream, aCharstrings) { * chapter 3.1. */ function readCharstringEncoding(aString) { + if (!aString) + return ''; + var charstringTokens = []; var count = aString.length; @@ -71,9 +84,9 @@ function readCharstringEncoding(aString) { } else if (value < 247) { token = parseInt(value, 10) - 139; } else if (value < 251) { - token = ((value - 247) * 256) + aString[i++] + 108; + token = (value - 247) * 256 + aString[i++] + 108; } else if (value < 255) { - token = -((value - 251) * 256) - aString[i++] - 108; + token = -(value - 251) * 256 - aString[i++] - 108; } else {// value == 255 token = aString[i++] << 24 | aString[i++] << 16 | aString[i++] << 8 | aString[i]; @@ -146,9 +159,9 @@ function readFontDictData(aString, aMap) { } else if (value <= 246) { token = parseInt(value, 10) - 139; } else if (value <= 250) { - token = ((value - 247) * 256) + aString[i++] + 108; + token = (value - 247) * 256 + aString[i++] + 108; } else if (value <= 254) { - token = -((value - 251) * 256) - aString[i++] - 108; + token = -(value - 251) * 256 - aString[i++] - 108; } else if (value == 255) { error('255 is not a valid DICT command'); } @@ -199,7 +212,7 @@ function readFontIndexData(aStream, aIsByte) { for (var i = 0; i < count + 1; i++) offsets.push(getNextOffset()); - log('Found ' + count + ' objects at offsets :' + + dump('Found ' + count + ' objects at offsets :' + offsets + ' (offsize: ' + offsize + ')'); // Now extract the objects @@ -285,23 +298,20 @@ var Type2Parser = function(aFilePath) { font.set('hdrSize', aStream.getByte()); font.set('offsize', aStream.getByte()); - // Move the cursor after the header - aStream.skip(font.get('hdrSize') - aStream.pos); - // Read the NAME Index dump('Reading Index: Names'); font.set('Names', readFontIndexData(aStream)); - log('Names: ' + font.get('Names')); + dump('Names: ' + font.get('Names')); // Read the Top Dict Index dump('Reading Index: TopDict'); var topDict = readFontIndexData(aStream, true); - log('TopDict: ' + topDict); + dump('TopDict: ' + topDict); // Read the String Index dump('Reading Index: Strings'); var strings = readFontIndexData(aStream); - log('strings: ' + strings); + dump('strings: ' + strings); // Fill up the Strings dictionary with the new unique strings for (var i = 0; i < strings.length; i++) @@ -321,7 +331,7 @@ var Type2Parser = function(aFilePath) { // Reading Private Dict var priv = font.get('Private'); - log('Reading Private Dict (offset: ' + priv.offset + + dump('Reading Private Dict (offset: ' + priv.offset + ' size: ' + priv.size + ')'); aStream.pos = priv.offset; diff --git a/web/viewer.html b/web/viewer.html index ecb869668..e22cacbf6 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -11,6 +11,7 @@ +