From faf8b8ac0bdec7b22755ba139e7f82d98a583ca9 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sat, 10 Sep 2011 20:21:20 -0500 Subject: [PATCH 1/7] Refactoring charsToUnicode into charsToGlyphs --- fonts.js | 24 +++++++----------------- pdf.js | 29 ++++++++++++++++------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/fonts.js b/fonts.js index cc353c03b..ac070ed18 100755 --- a/fonts.js +++ b/fonts.js @@ -1296,7 +1296,7 @@ var Font = (function Font() { return rule; }, - charsToUnicode: function fonts_chars2Unicode(chars) { + charsToGlyphs: function fonts_chars2Glyphs(chars) { var charsCache = this.charsCache; var str; @@ -1315,7 +1315,7 @@ var Font = (function Font() { var encoding = this.encoding; if (!encoding) return chars; - str = ''; + var glyphs = []; if (this.composite) { // composite fonts have multi-byte strings convert the string from @@ -1329,11 +1329,9 @@ var Font = (function Font() { var unicode = encoding[charcode]; if ('undefined' == typeof(unicode)) { warn('Unencoded charcode ' + charcode); - unicode = charcode; - } else { - unicode = unicode.unicode; + unicode = { unicode: charcode }; } - str += String.fromCharCode(unicode); + glyphs.push(unicode); } } else { @@ -1342,22 +1340,14 @@ var Font = (function Font() { var unicode = encoding[charcode]; if ('undefined' == typeof(unicode)) { warn('Unencoded charcode ' + charcode); - unicode = charcode; - } else { - unicode = unicode.unicode; + unicode = { unicode: charcode }; } - - // Handle surrogate pairs - if (unicode > 0xFFFF) { - str += String.fromCharCode(unicode & 0xFFFF); - unicode >>= 16; - } - str += String.fromCharCode(unicode); + glyphs.push(unicode); } } // Enter the translated string into the cache - return charsCache[chars] = str; + return charsCache[chars] = glyphs; } }; diff --git a/pdf.js b/pdf.js index 3e8249524..17ef1f3ca 100644 --- a/pdf.js +++ b/pdf.js @@ -4954,7 +4954,6 @@ var CanvasGraphics = (function() { showText: function(text) { var ctx = this.ctx; var current = this.current; - var originalText = text; ctx.save(); ctx.transform.apply(ctx, current.textMatrix); @@ -4963,9 +4962,15 @@ var CanvasGraphics = (function() { ctx.translate(current.x, -1 * current.y); var font = current.font; + var glyphs = []; if (font) { ctx.transform.apply(ctx, font.textMatrix || IDENTITY_MATRIX); - text = font.charsToUnicode(text); + glyphs = font.charsToGlyphs(text); + } else { + // fallback to simple glyphs + glyphs = []; + for (var i = 0; i < text.length; ++i) + glyphs.push({unicode: text.charCodeAt(i)}); } var composite = font.composite; @@ -4977,21 +4982,19 @@ var CanvasGraphics = (function() { ctx.scale(1 / textHScale, 1); var width = 0; - for (var i = 0; i < text.length; i++) { - if (composite) { - var position = i * 2 + 1; - var charcode = (originalText.charCodeAt(position - 1) << 8) + - originalText.charCodeAt(position); - } else { - var charcode = originalText.charCodeAt(i); - } + for (var i = 0; i < glyphs.length; i++) { + var glyph = glyphs[i]; + var unicode = glyph.unicode; + var char = unicode >= 0x10000 ? + String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10), + 0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode); - var charWidth = font.encoding[charcode].width * fontSize * 0.001; + var charWidth = glyph.width * fontSize * 0.001; charWidth += charSpacing; - if (charcode == 32) + if (unicode == 32) charWidth += wordSpacing; - ctx.fillText(text.charAt(i), 0, 0); + ctx.fillText(char, 0, 0); ctx.translate(charWidth, 0); width += charWidth; } From eaa5b8dab38f28de738bd8d8b8165d92bd6d5a44 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 11 Sep 2011 13:32:08 -0500 Subject: [PATCH 2/7] Pruning unreachable code; misc font fixes --- pdf.js | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/pdf.js b/pdf.js index 17ef1f3ca..193f8e13e 100644 --- a/pdf.js +++ b/pdf.js @@ -4339,11 +4339,12 @@ var PartialEvaluator = (function() { // merge in the differences var firstChar = properties.firstChar; var lastChar = properties.lastChar; + var widths = properties.widths || []; var glyphs = {}; for (var i = firstChar; i <= lastChar; i++) { var glyph = differences[i] || baseEncoding[i]; var index = GlyphsUnicode[glyph] || i; - var width = properties.widths[i] || properties.widths[glyph]; + var width = widths[i] || widths[glyph]; map[i] = { unicode: index, width: IsNum(width) ? width : properties.defaultWidth @@ -4501,7 +4502,8 @@ var PartialEvaluator = (function() { } } - var defaultWidth = 0; + // TODO implement default widths for standard fonts metrics + var defaultWidth = 1000; var widths = Metrics[stdFontMap[baseFontName] || baseFontName]; if (IsNum(widths)) { defaultWidth = widths; @@ -4902,7 +4904,7 @@ var CanvasGraphics = (function() { font = font.get(fontRef.name); font = this.xref.fetchIfRef(font); if (!font) - return; + error('Referenced font is not found'); var fontObj = font.fontObj; this.current.font = fontObj; @@ -4954,27 +4956,16 @@ var CanvasGraphics = (function() { showText: function(text) { var ctx = this.ctx; var current = this.current; + var font = current.font; ctx.save(); ctx.transform.apply(ctx, current.textMatrix); ctx.scale(1, -1); - ctx.translate(current.x, -1 * current.y); + ctx.transform.apply(ctx, font.textMatrix || IDENTITY_MATRIX); - var font = current.font; - var glyphs = []; - if (font) { - ctx.transform.apply(ctx, font.textMatrix || IDENTITY_MATRIX); - glyphs = font.charsToGlyphs(text); - } else { - // fallback to simple glyphs - glyphs = []; - for (var i = 0; i < text.length; ++i) - glyphs.push({unicode: text.charCodeAt(i)}); - } - - var composite = font.composite; - var encoding = font.encoding; + var glyphs = font.charsToGlyphs(text); + var defaultCharWidth = font.defaultWidth; var fontSize = current.fontSize; var charSpacing = current.charSpacing; var wordSpacing = current.wordSpacing; @@ -4989,7 +4980,7 @@ var CanvasGraphics = (function() { String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10), 0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode); - var charWidth = glyph.width * fontSize * 0.001; + var charWidth = (glyph.width || defaultCharWidth) * fontSize * 0.001; charWidth += charSpacing; if (unicode == 32) charWidth += wordSpacing; From b5b0357dca98233981c00523943f95388084d5b2 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 11 Sep 2011 13:37:13 -0500 Subject: [PATCH 3/7] Remove extra space --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 193f8e13e..ed1c09ab3 100644 --- a/pdf.js +++ b/pdf.js @@ -4502,7 +4502,7 @@ var PartialEvaluator = (function() { } } - // TODO implement default widths for standard fonts metrics + // TODO implement default widths for standard fonts metrics var defaultWidth = 1000; var widths = Metrics[stdFontMap[baseFontName] || baseFontName]; if (IsNum(widths)) { From e512000877759a429c36bd7159ca895e6fca03bb Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Wed, 14 Sep 2011 21:29:32 -0500 Subject: [PATCH 4/7] Fixing properties.widths is null issue; fips197 test file --- pdf.js | 2 +- test/pdfs/fips197.pdf.link | 1 + test/test_manifest.json | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 test/pdfs/fips197.pdf.link diff --git a/pdf.js b/pdf.js index 7514f4d96..640cd637d 100644 --- a/pdf.js +++ b/pdf.js @@ -4506,7 +4506,7 @@ var PartialEvaluator = (function() { type: type.name, encoding: map, differences: [], - widths: widths, + widths: widths || {}, defaultWidth: defaultWidth, firstChar: 0, lastChar: 256 diff --git a/test/pdfs/fips197.pdf.link b/test/pdfs/fips197.pdf.link new file mode 100644 index 000000000..815eb1d48 --- /dev/null +++ b/test/pdfs/fips197.pdf.link @@ -0,0 +1 @@ +http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 1155195cb..7893faa18 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -109,5 +109,11 @@ "link": true, "rounds": 1, "type": "eq" + }, + { "id": "fips197", + "file": "pdfs/fips197.pdf", + "link": true, + "rounds": 1, + "type": "load" } ] From 10a2fa66c2ae6e75680e6624721401e50f82c727 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 15 Sep 2011 19:26:32 -0500 Subject: [PATCH 5/7] Fixing defaultWidth; variables names --- fonts.js | 33 ++++++++++++++++++++------------- pdf.js | 15 ++++++++------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/fonts.js b/fonts.js index 404c3f853..2b40c1f49 100755 --- a/fonts.js +++ b/fonts.js @@ -472,6 +472,7 @@ var Font = (function Font() { this.data = data; this.type = properties.type; this.textMatrix = properties.textMatrix; + this.defaultWidth = properties.defaultWidth; this.loadedName = getUniqueName(); this.composite = properties.composite; this.loading = true; @@ -1298,13 +1299,13 @@ var Font = (function Font() { charsToGlyphs: function fonts_chars2Glyphs(chars) { var charsCache = this.charsCache; - var str; + var glyphs; // if we translated this string before, just grab it from the cache if (charsCache) { - str = charsCache[chars]; - if (str) - return str; + glyphs = charsCache[chars]; + if (glyphs) + return glyphs; } // lazily create the translation cache @@ -1315,7 +1316,8 @@ var Font = (function Font() { var encoding = this.encoding; if (!encoding) return chars; - var glyphs = []; + + glyphs = []; if (this.composite) { // composite fonts have multi-byte strings convert the string from @@ -1326,23 +1328,28 @@ var Font = (function Font() { // loop should never end on the last byte for (var i = 0; i < length; i++) { var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]); - var unicode = encoding[charcode]; - if ('undefined' == typeof(unicode)) { + var glyph = encoding[charcode]; + if ('undefined' == typeof(glyph)) { warn('Unencoded charcode ' + charcode); - unicode = { unicode: charcode }; + glyph = { unicode: charcode }; } - glyphs.push(unicode); + glyphs.push(glyph); + // placing null after each word break charcode (ASCII SPACE) + if (charcode == 0x20) + glyphs.push(null); } } else { for (var i = 0; i < chars.length; ++i) { var charcode = chars.charCodeAt(i); - var unicode = encoding[charcode]; - if ('undefined' == typeof(unicode)) { + var glyph = encoding[charcode]; + if ('undefined' == typeof(glyph)) { warn('Unencoded charcode ' + charcode); - unicode = { unicode: charcode }; + glyph = { unicode: charcode }; } - glyphs.push(unicode); + glyphs.push(glyph); + if (charcode == 0x20) + glyphs.push(null); } } diff --git a/pdf.js b/pdf.js index b4fd9c7a2..a8ae55234 100644 --- a/pdf.js +++ b/pdf.js @@ -4294,7 +4294,6 @@ var PartialEvaluator = (function() { }; } } else if (type == 'CIDFontType0') { - encoding = xref.fetchIfRef(dict.get('Encoding')); if (IsName(encoding)) { // Encoding is a predefined CMap if (encoding.name == 'Identity-H') { @@ -4521,8 +4520,7 @@ var PartialEvaluator = (function() { } } - // TODO implement default widths for standard fonts metrics - var defaultWidth = 1000; + var defaultWidth = 0; var widths = Metrics[stdFontMap[baseFontName] || baseFontName]; if (IsNum(widths)) { defaultWidth = widths; @@ -4994,6 +4992,12 @@ var CanvasGraphics = (function() { var width = 0; for (var i = 0; i < glyphs.length; i++) { var glyph = glyphs[i]; + if (glyph === null) { + // word break + width += wordSpacing; + continue; + } + var unicode = glyph.unicode; var char = unicode >= 0x10000 ? String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10), @@ -5001,11 +5005,8 @@ var CanvasGraphics = (function() { var charWidth = (glyph.width || defaultCharWidth) * fontSize * 0.001; charWidth += charSpacing; - if (unicode == 32) - charWidth += wordSpacing; - ctx.fillText(char, 0, 0); - ctx.translate(charWidth, 0); + ctx.fillText(char, width, 0); width += charWidth; } current.x += width; From a0ef97fb6044c6028b7ca4b63a4cd884d9181933 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 15 Sep 2011 19:32:36 -0500 Subject: [PATCH 6/7] Transfer defaultWidth for files without the file --- fonts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/fonts.js b/fonts.js index 2b40c1f49..e8d629084 100755 --- a/fonts.js +++ b/fonts.js @@ -436,6 +436,7 @@ var Font = (function Font() { // name ArialBlack for example will be replaced by Helvetica. this.black = (name.search(/Black/g) != -1); + this.defaultWidth = properties.defaultWidth; this.loadedName = fontName.split('-')[0]; this.loading = false; return; From 391ec1f99a02f37af7e7a2777e22e27e5303f84f Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 18 Sep 2011 09:11:31 -0500 Subject: [PATCH 7/7] Moving defaultWidth into the charsToGlyphs function --- fonts.js | 10 ++++++++-- pdf.js | 3 +-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/fonts.js b/fonts.js index 3beac011a..ce4215663 100644 --- a/fonts.js +++ b/fonts.js @@ -1373,7 +1373,10 @@ var Font = (function Font() { var glyph = encoding[charcode]; if ('undefined' == typeof(glyph)) { warn('Unencoded charcode ' + charcode); - glyph = { unicode: charcode }; + glyph = { + unicode: charcode, + width: this.defaultWidth + }; } glyphs.push(glyph); // placing null after each word break charcode (ASCII SPACE) @@ -1387,7 +1390,10 @@ var Font = (function Font() { var glyph = encoding[charcode]; if ('undefined' == typeof(glyph)) { warn('Unencoded charcode ' + charcode); - glyph = { unicode: charcode }; + glyph = { + unicode: charcode, + width: this.defaultWidth + }; } glyphs.push(glyph); if (charcode == 0x20) diff --git a/pdf.js b/pdf.js index 975792141..5c3102b85 100644 --- a/pdf.js +++ b/pdf.js @@ -4989,7 +4989,6 @@ var CanvasGraphics = (function() { ctx.transform.apply(ctx, font.textMatrix || IDENTITY_MATRIX); var glyphs = font.charsToGlyphs(text); - var defaultCharWidth = font.defaultWidth; var fontSize = current.fontSize; var charSpacing = current.charSpacing; var wordSpacing = current.wordSpacing; @@ -5010,7 +5009,7 @@ var CanvasGraphics = (function() { String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10), 0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode); - var charWidth = (glyph.width || defaultCharWidth) * fontSize * 0.001; + var charWidth = glyph.width * fontSize * 0.001; charWidth += charSpacing; ctx.fillText(char, width, 0);