diff --git a/fonts.js b/fonts.js index d8f9eec04..550c469b6 100644 --- a/fonts.js +++ b/fonts.js @@ -2519,7 +2519,7 @@ var Type2CFF = (function type2CFF() { var charStrings = this.parseIndex(topDict.CharStrings); var charset = this.parseCharsets(topDict.charset, charStrings.length, strings); - var hasSupplement = this.parseEncoding(topDict.Encoding, properties, + var encoding = this.parseEncoding(topDict.Encoding, properties, strings, charset); // The font sanitizer does not support CFF encoding with a @@ -2527,8 +2527,8 @@ var Type2CFF = (function type2CFF() { // between gid to glyph, let's overwrite what is declared in // the top dictionary to let the sanitizer think the font use // StandardEncoding, that's a lie but that's ok. - if (hasSupplement) - bytes[topDict.Encoding] = 0; + if (encoding.hasSupplement) + bytes[topDict.Encoding] &= 0x7F; // The CFF specification state that the 'dotsection' command // (12, 0) is deprecated and treated as a no-op, but all Type2 @@ -2559,7 +2559,7 @@ var Type2CFF = (function type2CFF() { // charstrings contains info about glyphs (one element per glyph // containing mappings for {unicode, width}) - var charstrings = this.getCharStrings(charset, charStrings, + var charstrings = this.getCharStrings(charset, encoding.encoding, privateDict, this.properties); // create the mapping between charstring and glyph id @@ -2576,49 +2576,85 @@ var Type2CFF = (function type2CFF() { return data; }, - getCharStrings: function cff_charstrings(charsets, charStrings, + getCharStrings: function cff_charstrings(charsets, encoding, privateDict, properties) { var defaultWidth = privateDict['defaultWidthX']; var charstrings = []; - var differences = properties.differences; - var index = properties.firstChar || 0; - for (var i = 1; i < charsets.length; i++) { - var code = -1; + var firstChar = properties.firstChar; + var glyphMap = {}; + for (var i = 0; i < charsets.length; i++) { var glyph = charsets[i]; - for (var j = 0; j < differences.length; j++) { - if (differences[j] == glyph) { - index = j; - code = differences.indexOf(glyph); - break; - } + for (var charcode in encoding) { + if (encoding[charcode] == i) + glyphMap[glyph] = charcode | 0; } + } - var mapping = - properties.glyphs[glyph] || properties.glyphs[index] || {}; - if (code == -1) - index = code = mapping.unicode || index; + var differences = properties.differences; + for (var i = 0; i < differences.length; ++i) { + var glyph = differences[i]; + if (!glyph) + continue; + var oldGlyph = charsets[i]; + if (oldGlyph) + delete glyphMap[oldGlyph]; + glyphMap[differences[i]] = i; + } - if (code <= 0x1f || (code >= 127 && code <= 255)) - code += kCmapGlyphOffset; + var glyphs = properties.glyphs; + for (var i = 1; i < charsets.length; i++) { + var glyph = charsets[i]; + var code = glyphMap[glyph] || 0; - var width = mapping.width; - properties.glyphs[glyph] = properties.encoding[index] = { - unicode: code, - width: isNum(width) ? width : defaultWidth + var mapping = glyphs[code] || glyphs[glyph] || {}; + var unicode = mapping.unicode; + + if (unicode <= 0x1f || (unicode >= 127 && unicode <= 255)) + unicode += kCmapGlyphOffset; + + var width = isNum(mapping.width) ? mapping.width : defaultWidth; + properties.encoding[code] = { + unicode: unicode, + width: width }; charstrings.push({ - unicode: code, + unicode: unicode, width: width, + code: code, gid: i }); - index++; } // sort the array by the unicode value charstrings.sort(function type2CFFGetCharStringsSort(a, b) { return a.unicode - b.unicode; }); + + // remove duplicates -- they might appear during selection: + // properties.glyphs[code] || properties.glyphs[glyph] + var nextUnusedUnicode = kCmapGlyphOffset + 0x0020; + var lastUnicode = charstrings[0].unicode, wasModified = false; + for (var i = 1; i < charstrings.length; ++i) { + if (lastUnicode != charstrings[i].unicode) { + lastUnicode = charstrings[i].unicode; + continue; + } + // duplicate found -- keeping the item that has + // different code and unicode, that one created + // as result of modification of the base encoding + var duplicateIndex = + charstrings[i].unicode == charstrings[i].code ? i : i - 1; + charstrings[duplicateIndex].unicode = nextUnusedUnicode++; + wasModified = true; + } + if (!wasModified) + return charstrings; + + // sort the array by the unicode value (again) + charstrings.sort(function type2CFFGetCharStringsSort(a, b) { + return a.unicode - b.unicode; + }); return charstrings; }, @@ -2626,6 +2662,10 @@ var Type2CFF = (function type2CFF() { charset) { var encoding = {}; var bytes = this.bytes; + var result = { + encoding: encoding, + hasSupplement: false + }; function readSupplement() { var supplementsCount = bytes[pos++]; @@ -2652,11 +2692,6 @@ var Type2CFF = (function type2CFF() { var glyphsCount = bytes[pos++]; for (var i = 1; i <= glyphsCount; i++) encoding[bytes[pos++]] = i; - - if (format & 0x80) { - readSupplement(); - return true; - } break; case 1: @@ -2668,19 +2703,18 @@ var Type2CFF = (function type2CFF() { for (var j = start; j <= start + count; j++) encoding[j] = gid++; } - - if (format & 0x80) { - readSupplement(); - return true; - } break; default: error('Unknow encoding format: ' + format + ' in CFF'); break; } + if (format & 0x80) { + readSupplement(); + result.hasSupplement = true; + } } - return false; + return result; }, parseCharsets: function cff_parsecharsets(pos, length, strings) { diff --git a/pdf.js b/pdf.js index 9b78a8b2a..c76ae7da0 100644 --- a/pdf.js +++ b/pdf.js @@ -3558,6 +3558,12 @@ var Page = (function pagePage() { var self = this; var stats = self.stats; stats.compile = stats.fonts = stats.render = 0; + if (!this.content) { + setTimeout(function norenderingSetTimeout() { + if (continuation) continuation(null); + }); + return; + } var gfx = new CanvasGraphics(canvasCtx); var fonts = []; @@ -4609,7 +4615,9 @@ var PartialEvaluator = (function partialEvaluator() { }; if (replaceGlyph || !glyphs[glyph]) - glyphs[glyph] = map[i]; + glyphs[glyph] = map[i]; + if (replaceGlyph || !glyphs[index]) + glyphs[index] = map[i]; // If there is no file, the character mapping can't be modified // but this is unlikely that there is any standard encoding with