From 5970020f3b2ab989ef245a616bf7f9b4142ae9af Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Mon, 5 Sep 2011 15:36:38 +0200 Subject: [PATCH 1/7] Fix wrong mapping for issue #434 --- fonts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index 95f136395..231124783 100755 --- a/fonts.js +++ b/fonts.js @@ -2248,8 +2248,8 @@ var Type2CFF = (function() { for (var i = 1; i < charsets.length; i++) { var code = -1; var glyph = charsets[i]; - for (var j = index; j < differences.length; j++) { - if (differences[j]) { + for (var j = 0; j < differences.length; j++) { + if (differences[j] == glyph) { index = j; code = differences.indexOf(glyph); break; From 9701f934edf561163e64950641be9342dd46e658 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Mon, 5 Sep 2011 17:30:01 +0200 Subject: [PATCH 2/7] Move all format 0 characters to the private area --- fonts.js | 14 +++----------- pdf.js | 6 +++++- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/fonts.js b/fonts.js index 231124783..03b87a84f 100755 --- a/fonts.js +++ b/fonts.js @@ -12,7 +12,6 @@ var kMaxWaitForFontFace = 1000; // Unicode Private Use Area var kCmapGlyphOffset = 0xE000; - /** * Hold a map of decoded fonts and of the standard fourteen Type1 * fonts and their acronyms. @@ -887,16 +886,9 @@ var Font = (function Font() { break; } - glyphs.push({ glyph: glyph, unicode: j }); - } - } - - if (properties.firstChar < 0x20) { - for (var j = 0; j < glyphs.length; j++) { - var glyph = glyphs[j]; - var code = glyph.unicode + kCmapGlyphOffset; - properties.glyphs[glyph.glyph] = encoding[glyph.unicode] = code; - glyph.unicode = code; + var unicode = j + kCmapGlyphOffset; + properties.glyphs[glyph] = encoding[j] = unicode; + glyphs.push({ glyph: glyph, unicode: unicode }); } } diff --git a/pdf.js b/pdf.js index dcc9f8887..2d05295c1 100644 --- a/pdf.js +++ b/pdf.js @@ -4297,6 +4297,10 @@ var PartialEvaluator = (function() { lastChar = diffEncoding.length || baseEncoding.length; // merge in the differences + function isDisplayable(code) { + return code > 0x1f && (code < 128 || code > 255); + } + var glyphsMap = {}; for (var i = firstChar; i <= lastChar; i++) { var glyph = diffEncoding[i] || baseEncoding[i]; @@ -4304,7 +4308,7 @@ var PartialEvaluator = (function() { var index = GlyphsUnicode[glyph] || i; glyphsMap[glyph] = encodingMap[i] = index; - if (index <= 0x1f || (index >= 127 && index <= 255)) + if (!isDisplayable(index)) glyphsMap[glyph] = encodingMap[i] += kCmapGlyphOffset; } From a36436ac7860cb81f22a19583d8e779a1b6bb4e5 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Mon, 5 Sep 2011 17:34:52 +0200 Subject: [PATCH 3/7] Remove the isDisplayable function and use inline code instead --- pdf.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pdf.js b/pdf.js index 82cfb4c81..51d297257 100644 --- a/pdf.js +++ b/pdf.js @@ -4297,10 +4297,6 @@ var PartialEvaluator = (function() { lastChar = diffEncoding.length || baseEncoding.length; // merge in the differences - function isDisplayable(code) { - return code > 0x1f && (code < 128 || code > 255); - } - var glyphsMap = {}; for (var i = firstChar; i <= lastChar; i++) { var glyph = diffEncoding[i] || baseEncoding[i]; @@ -4308,7 +4304,7 @@ var PartialEvaluator = (function() { var index = GlyphsUnicode[glyph] || i; glyphsMap[glyph] = encodingMap[i] = index; - if (!isDisplayable(index)) + if (index <= 0x1f || (index >= 128 && code <= 255)) glyphsMap[glyph] = encodingMap[i] += kCmapGlyphOffset; } } From cea04080677f7f9cbc245d2db4ccba039ce5d535 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Mon, 5 Sep 2011 18:04:41 +0200 Subject: [PATCH 4/7] Do not add kCmapGlyphOffset to Type1C mapping unless it is necessary --- fonts.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index 03b87a84f..d19940298 100755 --- a/fonts.js +++ b/fonts.js @@ -2252,9 +2252,12 @@ var Type2CFF = (function() { index = code = properties.glyphs[glyph] || index; var width = widths[code] || defaultWidth; - properties.encoding[index] = index + kCmapGlyphOffset; + if (index <= 0x1f || (index >= 127 && code <= 255)) + code += kCmapGlyphOffset; + + properties.encoding[index] = code; charstrings.push({ - unicode: code + kCmapGlyphOffset, + unicode: code, width: width, gid: i }); index++; From 3c77972b8eb5b8d8bf6708ef67cc0c317ef06ece Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Mon, 5 Sep 2011 21:01:39 +0200 Subject: [PATCH 5/7] Length[1-2] can be a reference --- fonts.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fonts.js b/fonts.js index d19940298..3234fa1d3 100755 --- a/fonts.js +++ b/fonts.js @@ -1828,7 +1828,12 @@ var type1Parser = new Type1Parser(); var CFF = function(name, file, properties) { // Get the data block containing glyphs and subrs informations var length1 = file.dict.get('Length1'); + if (!IsNum(length1)) + length1 = length1.num; + var length2 = file.dict.get('Length2'); + if (!IsNum(length2)) + length2 = length2.num; var headerBlock = file.getBytes(length1); type1Parser.extractFontHeader(headerBlock, properties); From 83f930abd62f5471ceb8f13cfcc21b8dbb47e221 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Mon, 5 Sep 2011 22:09:40 +0200 Subject: [PATCH 6/7] Add '^M' support in the ASCII85Decode filter and fix the fonts code to load the Type1 spec --- fonts.js | 38 +++++++++++++++++--------------------- pdf.js | 15 +++++++++++++-- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/fonts.js b/fonts.js index 3234fa1d3..829d783e6 100755 --- a/fonts.js +++ b/fonts.js @@ -1562,6 +1562,10 @@ var Type1Parser = function() { return parseFloat(str.substr(start, count) || 0); }; + function isSeparator(c) { + return c == ' ' || c == '\n' || c == '\x0d'; + }; + this.extractFontProgram = function t1_extractFontProgram(stream) { var eexec = decrypt(stream, kEexecEncryptionKey, 4); var eexecStr = ''; @@ -1586,12 +1590,12 @@ var Type1Parser = function() { var c = ''; var count = eexecStr.length; for (var i = 0; i < count; i++) { - var getToken = function() { - while (i < count && (eexecStr[i] == ' ' || eexecStr[i] == '\n')) + var getToken = function getToken() { + while (i < count && isSeparator(eexecStr[i])) ++i; var token = ''; - while (i < count && !(eexecStr[i] == ' ' || eexecStr[i] == '\n')) + while (i < count && !isSeparator(eexecStr[i])) token += eexecStr[i++]; return token; @@ -1618,7 +1622,7 @@ var Type1Parser = function() { } i += length; token = ''; - } else if (c == ' ' || c == '\n') { + } else if (isSeparator(c)) { length = parseInt(token); token = ''; } else { @@ -1695,13 +1699,13 @@ var Type1Parser = function() { var token = ''; var count = headerString.length; for (var i = 0; i < count; i++) { - var getToken = function() { + var getToken = function getToken() { var char = headerString[i]; - while (i < count && (char == ' ' || char == '\n' || char == '/')) + while (i < count && (isSeparator(char) || char == '/')) char = headerString[++i]; var token = ''; - while (i < count && !(char == ' ' || char == '\n' || char == '/')) { + while (i < count && !(isSeparator(char) || char == '/')) { token += char; char = headerString[++i]; } @@ -1710,7 +1714,7 @@ var Type1Parser = function() { }; var c = headerString[i]; - if (c == ' ' || c == '\n') { + if (isSeparator(c)) { switch (token) { case '/FontMatrix': var matrix = readNumberArray(headerString, i + 1); @@ -1736,7 +1740,7 @@ var Type1Parser = function() { if ('undefined' == typeof(properties.differences[index])) { properties.encoding[index] = glyph; - properties.glyphs[glyph] = GlyphsUnicode[glyph]; + properties.glyphs[glyph] = GlyphsUnicode[glyph] || index; } getToken(); // read the in 'put' } @@ -1752,8 +1756,8 @@ var Type1Parser = function() { }; /** - * The CFF class takes a Type1 file and wrap it into a 'Compact Font Format', - * which itself embed Type2 charstrings. + * The CFF class takes a Type1 file and wrap it into a + * 'Compact Font Format' which itself embed Type2 charstrings. */ var CFFStrings = [ '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', @@ -1827,19 +1831,11 @@ var type1Parser = new Type1Parser(); var CFF = function(name, file, properties) { // Get the data block containing glyphs and subrs informations - var length1 = file.dict.get('Length1'); - if (!IsNum(length1)) - length1 = length1.num; - - var length2 = file.dict.get('Length2'); - if (!IsNum(length2)) - length2 = length2.num; - - var headerBlock = file.getBytes(length1); + var headerBlock = file.getBytes(properties.length1); type1Parser.extractFontHeader(headerBlock, properties); // Decrypt the data blocks and retrieve it's content - var eexecBlock = file.getBytes(length2); + var eexecBlock = file.getBytes(properties.length2); var data = type1Parser.extractFontProgram(eexecBlock); for (var info in data.properties) properties[info] = data.properties[info]; diff --git a/pdf.js b/pdf.js index 51d297257..51802d9c7 100644 --- a/pdf.js +++ b/pdf.js @@ -2358,7 +2358,7 @@ var Lexer = (function() { } constructor.isSpace = function(ch) { - return ch == ' ' || ch == '\t'; + return ch == ' ' || ch == '\t' || ch == '\x0d'; }; // A '1' in this array means the character is white space. A '1' or @@ -4428,6 +4428,7 @@ var PartialEvaluator = (function() { fontName = fontName.name.replace(/[\+,\-]/g, '_'); var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3'); + var length1, length2; if (fontFile) { fontFile = xref.fetchIfRef(fontFile); @@ -4436,6 +4437,14 @@ var PartialEvaluator = (function() { if (fileType) fileType = fileType.name; } + + length1 = fontFile.dict.get('Length1'); + if (!IsInt(length1)) + length1 = xref.fetchIfRef(length1); + + length2 = fontFile.dict.get('Length2'); + if (!IsInt(length2)) + length2 = xref.fetchIfRef(length2); } var widths = fontDict.get('Widths'); @@ -4464,7 +4473,9 @@ var PartialEvaluator = (function() { italicAngle: descriptor.get('ItalicAngle'), fixedPitch: false, textMatrix: IDENTITY_MATRIX, - compositeFont: compositeFont + compositeFont: compositeFont, + length1: length1, + length2: length2 }; return { From f7ee90cc8c084365bf1b963fd1e95888a5ee5f4e Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 6 Sep 2011 02:28:06 +0200 Subject: [PATCH 7/7] Fix review comments for #436 --- fonts.js | 2 +- pdf.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index 829d783e6..50eafc566 100755 --- a/fonts.js +++ b/fonts.js @@ -2253,7 +2253,7 @@ var Type2CFF = (function() { index = code = properties.glyphs[glyph] || index; var width = widths[code] || defaultWidth; - if (index <= 0x1f || (index >= 127 && code <= 255)) + if (code <= 0x1f || (code >= 127 && code <= 255)) code += kCmapGlyphOffset; properties.encoding[index] = code; diff --git a/pdf.js b/pdf.js index 51802d9c7..35da1e332 100644 --- a/pdf.js +++ b/pdf.js @@ -4304,7 +4304,7 @@ var PartialEvaluator = (function() { var index = GlyphsUnicode[glyph] || i; glyphsMap[glyph] = encodingMap[i] = index; - if (index <= 0x1f || (index >= 128 && code <= 255)) + if (index <= 0x1f || (index >= 127 && index <= 255)) glyphsMap[glyph] = encodingMap[i] += kCmapGlyphOffset; } }