From c67037e268bf5d70fd002891e4673cae43eb4d6e Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 21 Jul 2011 11:51:39 -0700 Subject: [PATCH 01/89] added ability to write data to file --- fonts.js | 8 ++++++++ utils/fonts_utils.js | 4 +--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fonts.js b/fonts.js index 77ad85a00..e4a426cbe 100755 --- a/fonts.js +++ b/fonts.js @@ -384,6 +384,14 @@ var Font = (function Font() { break; } + var fileArr = []; + file.reset(); + for (var i = 0, ii = file.length; i < ii; ++i) + fileArr.push(file[i]); + + writeToFile(data, '/tmp/' + name + '_orig'); + writeToFile(fileArr, '/tmp/' + name + '_new'); + this.data = data; this.textMatrix = properties.textMatrix || IDENTITY_MATRIX; this.type = properties.type; diff --git a/utils/fonts_utils.js b/utils/fonts_utils.js index edfc22186..98ea60757 100644 --- a/utils/fonts_utils.js +++ b/utils/fonts_utils.js @@ -1,8 +1,6 @@ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ -'use strict'; - /** * The Type2 reader code below is only used for debugging purpose since Type2 * is only a CharString format and is never used directly as a Font file. @@ -391,7 +389,7 @@ function writeToFile(aBytes, aFilePath) { var stream = Cc['@mozilla.org/network/file-output-stream;1'] .createInstance(Ci.nsIFileOutputStream); - stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0); + stream.init(file, 0x04 | 0x08 | 0x20, 0666, 0); var bos = Cc['@mozilla.org/binaryoutputstream;1'] .createInstance(Ci.nsIBinaryOutputStream); From dbc6d67ea6fc8d37628d45f34bb67f79e3ecaba8 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 21 Jul 2011 15:13:18 -0700 Subject: [PATCH 02/89] added include to fonts_util.js --- web/viewer.html | 1 + 1 file changed, 1 insertion(+) diff --git a/web/viewer.html b/web/viewer.html index df9604db4..96012d6d8 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -10,6 +10,7 @@ + From 7d5470a7e551c2f6b8383362f73bdff22ddd7fca Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 21 Jul 2011 15:13:49 -0700 Subject: [PATCH 03/89] added include to fonts_util.js --- web/viewer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/viewer.html b/web/viewer.html index 96012d6d8..bf708c4ff 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -10,7 +10,7 @@ - + From c4d81646dc558f76e1cac3b06a351314c391cfb7 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 21 Jul 2011 15:18:00 -0700 Subject: [PATCH 04/89] fixed reading from sream --- fonts.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index e4a426cbe..3a52ae83a 100755 --- a/fonts.js +++ b/fonts.js @@ -386,11 +386,12 @@ var Font = (function Font() { var fileArr = []; file.reset(); + file = file.getBytes(); for (var i = 0, ii = file.length; i < ii; ++i) fileArr.push(file[i]); - writeToFile(data, '/tmp/' + name + '_orig'); - writeToFile(fileArr, '/tmp/' + name + '_new'); + writeToFile(data, '/tmp/' + name + '_new'); + writeToFile(fileArr, '/tmp/' + name + '_orig'); this.data = data; this.textMatrix = properties.textMatrix || IDENTITY_MATRIX; From 9bcf2d8b7cbf07e01eafe98f98d892cc695dd651 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 31 Jul 2011 22:56:41 -0500 Subject: [PATCH 05/89] Fixing the maxAdvanceWidth and the amount of the missing sidebearing --- fonts.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 792b552ba..0b2ab5338 100755 --- a/fonts.js +++ b/fonts.js @@ -1001,7 +1001,8 @@ var Font = (function Font() { var numOfHMetrics = int16(font.getBytes(2)); var numOfSidebearings = numGlyphs - numOfHMetrics; - var numMissing = numOfSidebearings - (hmtx.length - numOfHMetrics * 4); + var numMissing = numOfSidebearings - + ((hmtx.length - numOfHMetrics * 4) >> 1); if (numMissing > 0) { font.pos = (font.start ? font.start : 0) + hmtx.offset; var metrics = ""; @@ -1012,6 +1013,12 @@ var Font = (function Font() { hmtx.data = stringToArray(metrics); } + // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth + // Sometimes it's 0. That needs to be fixed + if (hhea.data[10] == 0 && hhea.data[11] == 0) { + hhea.data[10] = 0xFF; + hhea.data[11] = 0xFF; + } // Replace the old CMAP table with a shiny new one if (properties.type == 'CIDFontType2') { From 02a6e3ffec44118cdf608ee96856ce828e55c1e3 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Mon, 1 Aug 2011 17:30:17 -0400 Subject: [PATCH 06/89] Updated test/pdfs link (intelisa.pdf) --- test/pdfs/intelisa.pdf.link | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pdfs/intelisa.pdf.link b/test/pdfs/intelisa.pdf.link index 371cdf947..3ccbd1759 100644 --- a/test/pdfs/intelisa.pdf.link +++ b/test/pdfs/intelisa.pdf.link @@ -1 +1 @@ -http://www.intel.com/Assets/PDF/manual/253665.pdf \ No newline at end of file +http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-software-developer-vol-1-manual.pdf From 157ee749409045fca461f2cf49471ab9c9a333ea Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 2 Aug 2011 12:32:37 -0700 Subject: [PATCH 07/89] compiled code for tiling patterns --- pdf.js | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/pdf.js b/pdf.js index 66d922df2..c72ce4f88 100644 --- a/pdf.js +++ b/pdf.js @@ -2997,12 +2997,12 @@ var Page = (function() { // Firefox error reporting from XHR callbacks. setTimeout(function () { var exc = null; - try { + // try { self.display(gfx); stats.render = Date.now(); - } catch (e) { - exc = e.toString(); - } + // } catch (e) { + // exc = e.toString(); + // } continuation(exc); }); }); @@ -3571,6 +3571,7 @@ var PartialEvaluator = (function() { eval: function(stream, xref, resources, fonts) { resources = xref.fetchIfRef(resources) || new Dict(); var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict(); + var patterns = xref.fetchIfRef(resources.get("Pattern")) || new Dict(); var parser = new Parser(new Lexer(stream), false); var args = [], argsArray = [], fnArray = [], obj; @@ -3581,7 +3582,23 @@ var PartialEvaluator = (function() { assertWellFormed(fn, "Unknown command '" + cmd + "'"); // TODO figure out how to type-check vararg functions - if (cmd == 'Do' && !args[0].code) { // eagerly compile XForm objects + if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) { + // compile tiling patterns + var patternName = args[args.length - 1]; + // SCN/scn applies patterns along with normal colors + if (IsName(patternName)) { + var pattern = xref.fetchIfRef(patterns.get(patternName.name)); + if (pattern) { + var dict = IsStream(pattern) ? pattern.dict : pattern; + var typeNum = dict.get("PatternType"); + if (typeNum == 1) { + patternName.code = this.eval(pattern, xref, + dict.get('Resources'), fonts); + } + } + } + } else if (cmd == 'Do' && !args[0].code) { + // eagerly compile XForm objects var name = args[0].name; var xobj = xobjs.get(name); if (xobj) { @@ -3595,7 +3612,8 @@ var PartialEvaluator = (function() { ); if ('Form' == type.name) { - args[0].code = this.eval(xobj, xref, xobj.dict.get('Resources'), fonts); + args[0].code = this.eval(xobj, xref, xobj.dict.get('Resources'), + fonts); } } } else if (cmd == 'Tf') { // eagerly collect all fonts @@ -4984,7 +5002,8 @@ var Pattern = (function() { color = base.getRgb(color); } - return new TilingPattern(pattern, dict, color, xref, ctx); + var code = patternName.code; + return new TilingPattern(pattern, code, dict, color, xref, ctx); case 2: var shading = xref.fetchIfRef(dict.get('Shading')); var matrix = dict.get('Matrix'); @@ -5136,7 +5155,7 @@ var RadialAxialShading = (function() { var TilingPattern = (function() { var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; - function constructor(pattern, dict, color, xref, ctx) { + function constructor(pattern, code, dict, color, xref, ctx) { function multiply(m, tm) { var a = m[0] * tm[0] + m[1] * tm[2]; var b = m[0] * tm[1] + m[1] * tm[3]; @@ -5214,9 +5233,7 @@ var TilingPattern = (function() { } var res = xref.fetchIfRef(dict.get('Resources')); - if (!pattern.code) - pattern.code = graphics.compile(pattern, xref, res, []); - graphics.execute(pattern.code, xref, res); + graphics.execute(code, xref, res); this.canvas = tmpCanvas; }; From 19b36f6a6629d6d8267d37ce7273f854acf2dab1 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 2 Aug 2011 12:37:23 -0700 Subject: [PATCH 08/89] removed comments --- pdf.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pdf.js b/pdf.js index c72ce4f88..605886230 100644 --- a/pdf.js +++ b/pdf.js @@ -2997,12 +2997,12 @@ var Page = (function() { // Firefox error reporting from XHR callbacks. setTimeout(function () { var exc = null; - // try { + try { self.display(gfx); stats.render = Date.now(); - // } catch (e) { - // exc = e.toString(); - // } + } catch (e) { + exc = e.toString(); + } continuation(exc); }); }); From cffcac597c488580dfd608d27b0a94c60e05cdfc Mon Sep 17 00:00:00 2001 From: Ivars Veksins Date: Wed, 3 Aug 2011 11:56:43 +0100 Subject: [PATCH 09/89] fontName can be stored in xref --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 605886230..b3d6a3da6 100644 --- a/pdf.js +++ b/pdf.js @@ -3681,7 +3681,7 @@ var PartialEvaluator = (function() { var descriptor = xref.fetch(fd); - var fontName = descriptor.get('FontName'); + var fontName = xref.fetchIfRef(descriptor.get('FontName')); assertWellFormed(IsName(fontName), 'invalid font name'); fontName = fontName.name.replace(/[\+,\-]/g, '_'); From 5434cd3a0b16a1b195349f081a80b7cd649adfd8 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 3 Aug 2011 14:08:35 -0700 Subject: [PATCH 10/89] fix for bug with empty strings --- pdf.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/pdf.js b/pdf.js index b3d6a3da6..6efec7569 100644 --- a/pdf.js +++ b/pdf.js @@ -2187,7 +2187,6 @@ var Lexer = (function() { return value; }, getString: function() { - var n = 0; var numParen = 1; var done = false; var str = ''; @@ -2269,8 +2268,6 @@ var Lexer = (function() { break; } } while (!done); - if (!str.length) - return EOF; return str; }, getName: function(ch) { From ececccfa80db9f63daaf925bfb12a8d4e9688077 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 3 Aug 2011 14:14:42 -0700 Subject: [PATCH 11/89] added skip to lexer --- pdf.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pdf.js b/pdf.js index b3d6a3da6..b8d2fba70 100644 --- a/pdf.js +++ b/pdf.js @@ -2415,6 +2415,9 @@ var Lexer = (function() { return; } } + }, + skip: function() { + this.stream.skip(); } }; From a32b56ae854c7963a0a81f5776dafa1942352c7a Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 3 Aug 2011 21:11:57 -0700 Subject: [PATCH 12/89] inline images working --- pdf.js | 108 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/pdf.js b/pdf.js index fd92f4140..b2aa77694 100644 --- a/pdf.js +++ b/pdf.js @@ -228,6 +228,13 @@ var DecodeStream = (function() { } return String.fromCharCode(this.buffer[this.pos++]); }, + makeSubStream: function decodestream_makeSubstream(start, length, dict) { + var end = start + length; + while (this.bufferLength <= end && !this.eof) { + this.readBlock(); + } + return new Stream(this.buffer, start, length, dict); + }, skip: function decodestream_skip(n) { if (!n) n = 1; @@ -2436,28 +2443,21 @@ var Parser = (function() { this.buf2 = this.lexer.getObj(); }, shift: function() { - if (this.inlineImg > 0) { - if (this.inlineImg < 2) { - this.inlineImg++; - } else { - // in a damaged content stream, if 'ID' shows up in the middle - // of a dictionary, we need to reset - this.inlineImg = 0; - } - } else if (IsCmd(this.buf2, 'ID')) { - this.lexer.skip(); // skip char after 'ID' command - this.inlineImg = 1; - } - this.buf1 = this.buf2; - // don't buffer inline image data - this.buf2 = (this.inlineImg > 0) ? null : this.lexer.getObj(); + if (IsCmd(this.buf2, 'ID')) { + this.buf1 = this.buf2; + this.buf2 = null; + // skip byte after ID + this.lexer.skip(); + } else { + this.buf1 = this.buf2; + this.buf2 = this.lexer.getObj(); + } }, getObj: function(cipherTransform) { - // refill buffer after inline image data - if (this.inlineImg == 2) - this.refill(); - - if (IsCmd(this.buf1, '[')) { // array + if (IsCmd(this.buf1, 'BI')) { // inline image + this.shift(); + return this.makeInlineImage(cipherTransform); + } else if (IsCmd(this.buf1, '[')) { // array this.shift(); var array = []; while (!IsCmd(this.buf1, ']') && !IsEOF(this.buf1)) @@ -2472,7 +2472,6 @@ var Parser = (function() { while (!IsCmd(this.buf1, '>>') && !IsEOF(this.buf1)) { if (!IsName(this.buf1)) { error('Dictionary key must be a name object'); - shift(); } else { var key = this.buf1.name; this.shift(); @@ -2492,7 +2491,6 @@ var Parser = (function() { this.shift(); } return dict; - } else if (IsInt(this.buf1)) { // indirect reference or integer var num = this.buf1; this.shift(); @@ -2516,6 +2514,46 @@ var Parser = (function() { this.shift(); return obj; }, + makeInlineImage: function(cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + + // parse dictionary + var dict = new Dict(); + while (!IsCmd(this.buf1, 'ID') && !IsEOF(this.buf1)) { + if (!IsName(this.buf1)) { + error('Dictionary key must be a name object'); + } else { + var key = this.buf1.name; + this.shift(); + if (IsEOF(this.buf1)) + break; + dict.set(key, this.getObj(cipherTransform)); + } + } + + // parse image stream + var startPos = stream.pos; + + var c1 = stream.getChar(); + var c2 = stream.getChar(); + while (!(c1 == 'E' && c2 == 'I') && c2 != null) { + c1 = c2; + c2 = stream.getChar(); + } + + var length = (stream.pos - 2) - startPos; + var imageStream = stream.makeSubStream(startPos, length, dict); + if (cipherTransform) + imageStream = cipherTransform.createStream(imageStream); + imageStream = this.filter(imageStream, dict, length); + imageStream.parameters = dict; + + this.buf2 = new Cmd('EI'); + this.shift(); + + return imageStream; + }, makeStream: function(dict, cipherTransform) { var lexer = this.lexer; var stream = lexer.stream; @@ -2577,15 +2615,14 @@ var Parser = (function() { return new PredictorStream(new FlateStream(stream), params); } return new FlateStream(stream); - } else if (name == 'DCTDecode') { + } else if (name == 'DCTDecode' || name == 'DCT') { var bytes = stream.getBytes(length); return new JpegStream(bytes, stream.dict); - } else if (name == 'ASCII85Decode') { + } else if (name == 'ASCII85Decode' || name == 'A85') { return new Ascii85Stream(stream); - } else if (name == 'ASCIIHexDecode') { + } else if (name == 'ASCIIHexDecode' || name == 'AHx') { return new AsciiHexStream(stream); - } else if (name == 'CCITTFaxDecode') { - TODO('implement fax stream'); + } else if (name == 'CCITTFaxDecode' || name == 'CCF') { return new CCITTFaxStream(stream, params); } else { error("filter '" + name + "' not supported yet"); @@ -3551,6 +3588,8 @@ var PartialEvaluator = (function() { // Images BI: 'beginInlineImage', + ID: 'beginImageData', + EI: 'endInlineImage', // XObjects Do: 'paintXObject', @@ -3579,6 +3618,9 @@ var PartialEvaluator = (function() { if (IsCmd(obj)) { var cmd = obj.cmd; var fn = OP_MAP[cmd]; + if (!fn) { + log('blah'); + } assertWellFormed(fn, "Unknown command '" + cmd + "'"); // TODO figure out how to type-check vararg functions @@ -4438,11 +4480,13 @@ var CanvasGraphics = (function() { // Images beginInlineImage: function() { - TODO('inline images'); - error('(Stream will not be parsed properly, bailing now)'); - // Like an inline stream: - // - key/value pairs up to Cmd(ID) - // - then image data up to Cmd(EI) + error('Should not call beginInlineImage'); + }, + beginImageData: function() { + error('Should not call beginImageData'); + }, + endInlineImage: function(image) { + this.paintImageXObject(null, image, true); }, // XObjects From 80c1bab604a85155ebeeb91d41c70ba16e628b1e Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 3 Aug 2011 21:19:27 -0700 Subject: [PATCH 13/89] cleanup --- pdf.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/pdf.js b/pdf.js index b2aa77694..70d828fc3 100644 --- a/pdf.js +++ b/pdf.js @@ -3618,9 +3618,6 @@ var PartialEvaluator = (function() { if (IsCmd(obj)) { var cmd = obj.cmd; var fn = OP_MAP[cmd]; - if (!fn) { - log('blah'); - } assertWellFormed(fn, "Unknown command '" + cmd + "'"); // TODO figure out how to type-check vararg functions From 4b132a7b3ea726caa4111caceeccd621333a20f0 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 3 Aug 2011 22:22:24 -0700 Subject: [PATCH 14/89] Added test for inline images --- test/test_manifest.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test_manifest.json b/test/test_manifest.json index c5c196397..bea4cf444 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -69,5 +69,11 @@ "link": true, "rounds": 1, "type": "eq" + }, + { "id": "hmm-pdf", + "file": "pdfs/hmm.pdf", + "link": true, + "rounds": 1, + "type": "load" } ] From 7a7ff9e8c5398d7129c2693075e97c8d6f1ecf2f Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 3 Aug 2011 22:43:15 -0700 Subject: [PATCH 15/89] cleanup --- pdf.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pdf.js b/pdf.js index 70d828fc3..3cd2d80ba 100644 --- a/pdf.js +++ b/pdf.js @@ -230,9 +230,8 @@ var DecodeStream = (function() { }, makeSubStream: function decodestream_makeSubstream(start, length, dict) { var end = start + length; - while (this.bufferLength <= end && !this.eof) { + while (this.bufferLength <= end && !this.eof) this.readBlock(); - } return new Stream(this.buffer, start, length, dict); }, skip: function decodestream_skip(n) { From ed2368fed76e6513ec391542a561db5f5a875a7f Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Fri, 5 Aug 2011 02:32:47 +0300 Subject: [PATCH 16/89] Correct the return values for lookChar function. Also refactor the code slightly for an early return. --- pdf.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pdf.js b/pdf.js index 3cd2d80ba..9d915b8ec 100644 --- a/pdf.js +++ b/pdf.js @@ -1523,18 +1523,18 @@ var CCITTFaxStream = (function() { }; constructor.prototype.lookChar = function() { + if (this.buf != EOF) + return this.buf; + var refLine = this.refLine; var codingLine = this.codingLine; var columns = this.columns; var refPos, blackPixels, bits; - if (this.buf != EOF) - return buf; - if (this.outputBits == 0) { if (this.eof) - return; + return null; this.err = false; @@ -1753,7 +1753,7 @@ var CCITTFaxStream = (function() { code1 = this.lookBits(13); if (code1 == EOF) { this.eof = true; - return; + return null; } if ((code1 >> 1) == 1) { break; From 41bdf821374cd60063f5c5622ddd9e8c9089e3b9 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Sat, 6 Aug 2011 00:07:33 -0700 Subject: [PATCH 17/89] Fix bug in ref-updating code --- test/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.py b/test/test.py index b61ba816b..c76df3fd4 100644 --- a/test/test.py +++ b/test/test.py @@ -469,7 +469,7 @@ def maybeUpdateRefImages(options, browser): else: print ' Yes! The references in tmp/ can be synced with ref/.' if options.reftest: - startReftest(browser) + startReftest(browser, options) if not prompt('Would you like to update the master copy in ref/?'): print ' OK, not updating.' else: From 3c0ba19c8847edc15cb4284fe8210965965d3f2f Mon Sep 17 00:00:00 2001 From: sbarman Date: Sat, 6 Aug 2011 00:22:57 -0700 Subject: [PATCH 18/89] Added new link file --- test/pdfs/hmm.pdf.link | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/pdfs/hmm.pdf.link diff --git a/test/pdfs/hmm.pdf.link b/test/pdfs/hmm.pdf.link new file mode 100644 index 000000000..5ba2534d0 --- /dev/null +++ b/test/pdfs/hmm.pdf.link @@ -0,0 +1 @@ +http://speech.tifr.res.in/tutorials/hmmTutExamplesAlgo.pdf From 1cca10251728917442ab6354213f541bd56de2e8 Mon Sep 17 00:00:00 2001 From: Christian Mehlis Date: Sat, 6 Aug 2011 11:45:33 +0200 Subject: [PATCH 19/89] fix url to demo site the name of the created file is viewer.html --- web/index.html.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/index.html.template b/web/index.html.template index c3086f078..12e606371 100644 --- a/web/index.html.template +++ b/web/index.html.template @@ -50,7 +50,7 @@

Try it out!

-

Live demo lives here.

+

Live demo lives here.

Authors

Vivien Nicolas (21@vingtetun.org) From 17e02e3c39b6af3468e0f857adccdb03d98e39a7 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Sat, 6 Aug 2011 22:54:16 +0300 Subject: [PATCH 20/89] Use strict in driver.js. And declare undeclared variables. --- test/driver.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/driver.js b/test/driver.js index a6b0b1dc2..8d2553950 100644 --- a/test/driver.js +++ b/test/driver.js @@ -5,6 +5,8 @@ * A Test Driver for PDF.js */ +'use strict'; + var appPath, browser, canvas, currentTaskIdx, manifest, stdout; function queryParams() { @@ -21,7 +23,7 @@ function queryParams() { function load() { var params = queryParams(); browser = params.browser; - manifestFile = params.manifestFile; + var manifestFile = params.manifestFile; appPath = params.path; canvas = document.createElement("canvas"); @@ -134,7 +136,7 @@ function snapshotCurrentPage(page, task, failure) { log("done"+ (failure ? " (failed!: "+ failure +")" : "") +"\n"); // Set up the next request - backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; + var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; setTimeout(function() { ++task.pageNum, nextPage(task); }, @@ -209,4 +211,4 @@ function checkScrolling() { function log(str) { stdout.innerHTML += str; checkScrolling(); -} \ No newline at end of file +} From b1ea9332b8ca0a80884e535a5977486b81646e73 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Sat, 6 Aug 2011 23:33:07 +0300 Subject: [PATCH 21/89] Avoid browser-test stoppage when task.pdfDoc is undefined. If nextTask leaves task.pdfDoc as undefined then sendTaskResult will fail on that. SendTaskResult tries to access task.pdfDoc.numPages which cannot succeed. This leads to a complete stop in the browser-test. --- test/driver.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/driver.js b/test/driver.js index 8d2553950..642c5273c 100644 --- a/test/driver.js +++ b/test/driver.js @@ -79,7 +79,7 @@ function nextTask() { } function isLastPage(task) { - return (task.pdfDoc && (task.pageNum > task.pdfDoc.numPages)); + return (!task.pdfDoc || (task.pageNum > task.pdfDoc.numPages)); } function nextPage(task, loadError) { From dc01974aa4a9e420827866516d025bc7dcf554b5 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Sat, 6 Aug 2011 23:53:08 +0300 Subject: [PATCH 22/89] Create an example browser_manifest.json for windows. --- .../browser_manifests/browser_manifest.json.windows | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/resources/browser_manifests/browser_manifest.json.windows diff --git a/test/resources/browser_manifests/browser_manifest.json.windows b/test/resources/browser_manifests/browser_manifest.json.windows new file mode 100644 index 000000000..a19727b05 --- /dev/null +++ b/test/resources/browser_manifests/browser_manifest.json.windows @@ -0,0 +1,10 @@ +[ + { + "name":"firefox", + "path":"C:/Program Files (x86)/Firefox/firefox.exe" + }, + { + "name":"aurora", + "path":"C:/Program Files (x86)/Aurora/firefox.exe" + } +] From 25a6e09d78fe04b79afd832a748137b070ac6489 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Sun, 7 Aug 2011 00:29:34 +0300 Subject: [PATCH 23/89] Show browser-test results in pageNum/numPages format. This is only for convenience in order to see how far in the pdf the test currently is. --- test/driver.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/driver.js b/test/driver.js index 642c5273c..2f459e430 100644 --- a/test/driver.js +++ b/test/driver.js @@ -99,7 +99,7 @@ function nextPage(task, loadError) { var page = null; if (!failure) { try { - log(" loading page "+ task.pageNum +"... "); + log(" loading page "+ task.pageNum +"/"+ task.pdfDoc.numPages +"... "); ctx = canvas.getContext("2d"); page = task.pdfDoc.getPage(task.pageNum); From 4377eed920762c42a3cf7af8feea291d29b9ce90 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Sat, 6 Aug 2011 14:41:18 -0700 Subject: [PATCH 24/89] Adding support for page rotation --- pdf.js | 50 ++++++++++++++++++++++++++++++++++++---- test/driver.js | 4 ++-- test/pdfs/rotation.pdf | Bin 0 -> 6605 bytes test/test_manifest.json | 5 ++++ web/viewer.js | 5 +--- 5 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 test/pdfs/rotation.pdf diff --git a/pdf.js b/pdf.js index 9d915b8ec..50594f2ad 100644 --- a/pdf.js +++ b/pdf.js @@ -2995,7 +2995,7 @@ var Page = (function() { inheritPageProp: function(key) { var dict = this.pageDict; var obj = dict.get(key); - while (!obj) { + while (typeof obj == 'undefined') { dict = this.xref.fetchIfRef(dict.get('Parent')); if (!dict) break; @@ -3014,6 +3014,32 @@ var Page = (function() { return shadow(this, 'mediaBox', ((IsArray(obj) && obj.length == 4) ? obj : null)); }, + get width() { + var mediaBox = this.mediaBox; + var rotate = this.rotate; + var width; + if (rotate == 0 || rotate == 180) { + width = (mediaBox[2] - mediaBox[0]); + } else { + width = (mediaBox[3] - mediaBox[1]); + } + return shadow(this, 'width', width); + }, + get height() { + var mediaBox = this.mediaBox; + var rotate = this.rotate; + var height; + if (rotate == 0 || rotate == 180) { + height = (mediaBox[3] - mediaBox[1]); + } else { + height = (mediaBox[2] - mediaBox[0]); + } + return shadow(this, 'height', height); + }, + get rotate() { + var rotate = this.inheritPageProp("Rotate") || 0; + return shadow(this, 'rotate', rotate); + }, startRendering: function(canvasCtx, continuation, onerror) { var self = this; var stats = self.stats; @@ -3085,8 +3111,9 @@ var Page = (function() { var mediaBox = xref.fetchIfRef(this.mediaBox); assertWellFormed(IsDict(resources), 'invalid page resources'); gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1], - width: mediaBox[2] - mediaBox[0], - height: mediaBox[3] - mediaBox[1] }); + width: this.width, + height: this.height, + rotate: this.rotate }); gfx.execute(this.code, xref, resources); gfx.endDrawing(); } @@ -3994,8 +4021,21 @@ var CanvasGraphics = (function() { beginDrawing: function(mediaBox) { var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height; this.ctx.save(); - this.ctx.scale(cw / mediaBox.width, -ch / mediaBox.height); - this.ctx.translate(0, -mediaBox.height); + switch (mediaBox.rotate) { + case 0: + this.ctx.transform(1, 0, 0, -1, 0, ch); + break; + case 90: + this.ctx.transform(0, 1, 1, 0, 0, 0); + break; + case 180: + this.ctx.transform(-1, 0, 0, 1, cw, 0); + break; + case 270: + this.ctx.transform(0, -1, -1, 0, cw, ch); + break; + } + this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height); }, compile: function(stream, xref, resources, fonts) { diff --git a/test/driver.js b/test/driver.js index 642c5273c..8d962eac8 100644 --- a/test/driver.js +++ b/test/driver.js @@ -105,8 +105,8 @@ function nextPage(task, loadError) { var pdfToCssUnitsCoef = 96.0 / 72.0; // using mediaBox for the canvas size - var pageWidth = (page.mediaBox[2] - page.mediaBox[0]); - var pageHeight = (page.mediaBox[3] - page.mediaBox[1]); + var pageWidth = page.width; + var pageHeight = page.height; canvas.width = pageWidth * pdfToCssUnitsCoef; canvas.height = pageHeight * pdfToCssUnitsCoef; clear(ctx); diff --git a/test/pdfs/rotation.pdf b/test/pdfs/rotation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..807dafe5f8b5b1e9b932104d84e1cc13276c6dbf GIT binary patch literal 6605 zcmeHMe{3699gpZ1BsXp+_Cp(m?bTg7ht_`g?w5VW@#@6!8ZAzu*feEnOU`%C$+hP@ z@9w-fEubzfTGx&Wm?~9kw+VG?CpL)z64PL%Wug@f*rv7;qf@IcxN@w150j`z;L z*s{)?@|@80{q@AvyY-yiS$-mM%;Bm*eOdsklk^&4lr9tkkO%x>{Uqp)8yuxx4D zunG|D2cpOba1bB_djXOd5e@(rW`M|rB)ATY0zM=H6k<2UVqR>hln0pg|qcxGlF;#%h-K_u&?pSoNm@~txH+G=!;C2Kmi zydHv4n!p247!FzZAp(Uc!C}*M03zbSFzhpOCLpVz&BSOF^(MNzS;X-@91}`#-8@V5 zWP1fMAtFZNdSg+B6Pbj>Cndy--Q7IX%?QavBA!H&AoV1>nHWXaV>`0tltE;?o|P+m z2a{e;3)Wr_3N;uL8{^Id2!~-((;aNVq%J!+ffZB5un$OKV&O0g(?DQiG25}QoF|4l zmmM1$%Z-hl&W@2*^yG~_-od}w-@Y2WJ2rOH(vO~gZ0+Zlf)i~kPI>%Z5Al$SkczLkh*caf zg&kRy9T`ylhvASsj%`2;K-!t90){wC;Hb)mPqQnT2k%G)he( zA{K-sb`zOuVZ*5~?J*69JlTMHArUfcIs_ZQz!X+Bxn=G!w#}lY5S<9Ono?BD1_kIy zWjRU0p14XT!ve(739%UQ7gI@NXB3j~gBe_MHo@MKb6=VYCbajZ5kSPPDQyE&I=jL& zUCcTZi;PvoE+|w=0^5qE6&%w7$VCM9%eK=qA(Lko!4XY$ChSpGpis>9z4qu_vlzf} zRJ)m9K@bV()EcvYd7kP?{|h7t=`ZC&+w_kO(cmfnhDf{GPk+l2xv=C?RYyWB1)e-@ zg59!>DJU?b<*_}0Cx^|vYz(DS84?0k1s0Bly#|Q^%@`-}7;(eaYR@%T8!SMzty;jr z`SmnrsE`3UPi)aDhzzAkFgeNu95AiCth>}BSR0>k0M9Tq499K2@sQe%x@3SwqD$0G z9WNk=VGtnc0_{?q9DQzm3Bbj z#c~)mdkpL&L8U2iV_YY$->_urhLt4`4yDLeFgOHqvTkE&7Ag%Fsha=7biC4^P5~y! zuno*;fK{0FmopOCN@ht(^&B*D!5RFiXL{`|=ieAP^xOV-!iUxGec3nh_W9n$=&qY% z-QGW4T9z8U;la;6VlRDU`}s4yD=xkD)Pehd6W_@m>GCgoDB=0^t*`mpKGVParQV;M zZ9ldAJ^Aa0pS>`>WO01is{O-PpRsS_UtE3kRp-UeK034|=J}niCc_UuR(ktyrBhRT ze)!iLe}Cl4?(DDL!jH0d9vp$o4QKO}W8XX;y6ZdVF8A&Urk?oczSCzrpV)R})#S?; zE`PA|*{ct)_|{8pi`w3OE%~@-woF%t;J-*sZsMqBCIZ=iN=}XuT1-%CI)ksJoAn1|CrjfZ2t}E z=T5gBTm97gw>}wo@+12ey}I|%?q44M_Q5+g-~Ra317j~7Y~Oz+yn+AjvA=)m{X>Ii z{?g^&WgY$TFIKF7W%F)*`TE?dKYw`Ui1Eo!UA8_vxB0!*C)(Dmj4Ynbk`2jVpqRJG z4&$cmh6<=5cG56WkAsFV=rM~V>PaOc`^SAiQ@ea4LW)Thdhmp{ZkvVE+Xgbq zwylb!`tFT+qNPYFU&xak8Ij#5 zRG~qTVF%p>1{E_8$pAz_4%RqR=A<)1HgL75U@I0^EHf)RAfefgrjxo5go7x^06*DI zRCChqj8Z0b`ik@@q$)M2=&t{NP`xA@2U8^{Z3dB0j)2fhwh?+rEl}L_m=1xp56v&<_I|Maq zn}tA>v2PIGT{K-XvtM0D90@A8!bD$dD8-SNdz8u2&V%sF7h zv{VoP2~#OjJyF@Cbgh|Rxwl!2tL99NqC`uj>=`pSP)AMU2b+8Add9MrCL7AN#5d1& z#m^9RJ;NcDs@ZeafXL^Y%}Ja&m5Nkx>`TOoMNN(1Fr%shg98%EWdl6NWdo9|$bk@} zhFC6_4TUi0x_9&32D6v>_8H{3W+=GIS5V1el9j|j2uWOk4|8lFtFpO(oRx)87%PGz z5I<^}drhY=qet>4$=9%!uv-j9z3#ey>I=T^tm_OHgw(N^M{5DDd4N`cDbu8x5T7YXFAk|5(1(&COMsXa zMDNsR^l>7&2$ Date: Sat, 6 Aug 2011 15:47:08 -0700 Subject: [PATCH 25/89] Better undefined check --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 50594f2ad..57d8ffd22 100644 --- a/pdf.js +++ b/pdf.js @@ -2995,7 +2995,7 @@ var Page = (function() { inheritPageProp: function(key) { var dict = this.pageDict; var obj = dict.get(key); - while (typeof obj == 'undefined') { + while (obj === undefined) { dict = this.xref.fetchIfRef(dict.get('Parent')); if (!dict) break; From 850c042af75f8a1d3d3d8f788c3f27b508bf3f4c Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Sun, 7 Aug 2011 21:54:11 -0700 Subject: [PATCH 26/89] Normalizing rotation --- pdf.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pdf.js b/pdf.js index 57d8ffd22..3642ad628 100644 --- a/pdf.js +++ b/pdf.js @@ -3038,6 +3038,16 @@ var Page = (function() { }, get rotate() { var rotate = this.inheritPageProp("Rotate") || 0; + // Normalize rotation so it's a multiple of 90 and between 0 and 270 + if (rotate % 90 != 0) { + rotate = 0; + } else if (rotate >= 360) { + rotate = rotate % 360; + } else if (rotate < 0) { + // The spec doesn't cover negatives, assume its counterclockwise + // rotation. The following is the other implementation of modulo. + rotate = ((rotate % 360) + 360) % 360; + } return shadow(this, 'rotate', rotate); }, startRendering: function(canvasCtx, continuation, onerror) { From f656e841acbd9697dfeffad74accb69796fba679 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Mon, 8 Aug 2011 23:13:32 +0300 Subject: [PATCH 27/89] Correct the coding style according to gjslint. And remove stray tabs. --- fonts.js | 186 +++++++++++++++++++++++++------------------------- pdf.js | 168 ++++++++++++++++++++++----------------------- web/viewer.js | 26 +++---- 3 files changed, 190 insertions(+), 190 deletions(-) diff --git a/fonts.js b/fonts.js index 0b2ab5338..ff2f46d7a 100755 --- a/fonts.js +++ b/fonts.js @@ -19,46 +19,46 @@ var kMaxWaitForFontFace = 1000; * fonts and their acronyms. */ var stdFontMap = { - "Arial": "Helvetica", - "Arial_Bold": "Helvetica-Bold", - "Arial_BoldItalic": "Helvetica-BoldOblique", - "Arial_Italic": "Helvetica-Oblique", - "Arial_BoldItalicMT": "Helvetica-BoldOblique", - "Arial_BoldMT": "Helvetica-Bold", - "Arial_ItalicMT": "Helvetica-Oblique", - "ArialMT": "Helvetica", - "Courier_Bold": "Courier-Bold", - "Courier_BoldItalic": "Courier-BoldOblique", - "Courier_Italic": "Courier-Oblique", - "CourierNew": "Courier", - "CourierNew_Bold": "Courier-Bold", - "CourierNew_BoldItalic": "Courier-BoldOblique", - "CourierNew_Italic": "Courier-Oblique", - "CourierNewPS_BoldItalicMT": "Courier-BoldOblique", - "CourierNewPS_BoldMT": "Courier-Bold", - "CourierNewPS_ItalicMT": "Courier-Oblique", - "CourierNewPSMT": "Courier", - "Helvetica_Bold": "Helvetica-Bold", - "Helvetica_BoldItalic": "Helvetica-BoldOblique", - "Helvetica_Italic": "Helvetica-Oblique", - "Symbol_Bold": "Symbol", - "Symbol_BoldItalic": "Symbol", - "Symbol_Italic": "Symbol", - "TimesNewRoman": "Times-Roman", - "TimesNewRoman_Bold": "Times-Bold", - "TimesNewRoman_BoldItalic": "Times-BoldItalic", - "TimesNewRoman_Italic": "Times-Italic", - "TimesNewRomanPS": "Times-Roman", - "TimesNewRomanPS_Bold": "Times-Bold", - "TimesNewRomanPS_BoldItalic": "Times-BoldItalic", - "TimesNewRomanPS_BoldItalicMT": "Times-BoldItalic", - "TimesNewRomanPS_BoldMT": "Times-Bold", - "TimesNewRomanPS_Italic": "Times-Italic", - "TimesNewRomanPS_ItalicMT": "Times-Italic", - "TimesNewRomanPSMT": "Times-Roman", - "TimesNewRomanPSMT_Bold": "Times-Bold", - "TimesNewRomanPSMT_BoldItalic": "Times-BoldItalic", - "TimesNewRomanPSMT_Italic": "Times-Italic" + 'Arial': 'Helvetica', + 'Arial_Bold': 'Helvetica-Bold', + 'Arial_BoldItalic': 'Helvetica-BoldOblique', + 'Arial_Italic': 'Helvetica-Oblique', + 'Arial_BoldItalicMT': 'Helvetica-BoldOblique', + 'Arial_BoldMT': 'Helvetica-Bold', + 'Arial_ItalicMT': 'Helvetica-Oblique', + 'ArialMT': 'Helvetica', + 'Courier_Bold': 'Courier-Bold', + 'Courier_BoldItalic': 'Courier-BoldOblique', + 'Courier_Italic': 'Courier-Oblique', + 'CourierNew': 'Courier', + 'CourierNew_Bold': 'Courier-Bold', + 'CourierNew_BoldItalic': 'Courier-BoldOblique', + 'CourierNew_Italic': 'Courier-Oblique', + 'CourierNewPS_BoldItalicMT': 'Courier-BoldOblique', + 'CourierNewPS_BoldMT': 'Courier-Bold', + 'CourierNewPS_ItalicMT': 'Courier-Oblique', + 'CourierNewPSMT': 'Courier', + 'Helvetica_Bold': 'Helvetica-Bold', + 'Helvetica_BoldItalic': 'Helvetica-BoldOblique', + 'Helvetica_Italic': 'Helvetica-Oblique', + 'Symbol_Bold': 'Symbol', + 'Symbol_BoldItalic': 'Symbol', + 'Symbol_Italic': 'Symbol', + 'TimesNewRoman': 'Times-Roman', + 'TimesNewRoman_Bold': 'Times-Bold', + 'TimesNewRoman_BoldItalic': 'Times-BoldItalic', + 'TimesNewRoman_Italic': 'Times-Italic', + 'TimesNewRomanPS': 'Times-Roman', + 'TimesNewRomanPS_Bold': 'Times-Bold', + 'TimesNewRomanPS_BoldItalic': 'Times-BoldItalic', + 'TimesNewRomanPS_BoldItalicMT': 'Times-BoldItalic', + 'TimesNewRomanPS_BoldMT': 'Times-Bold', + 'TimesNewRomanPS_Italic': 'Times-Italic', + 'TimesNewRomanPS_ItalicMT': 'Times-Italic', + 'TimesNewRomanPSMT': 'Times-Roman', + 'TimesNewRomanPSMT_Bold': 'Times-Bold', + 'TimesNewRomanPSMT_BoldItalic': 'Times-BoldItalic', + 'TimesNewRomanPSMT_Italic': 'Times-Italic' }; var FontMeasure = (function FontMeasure() { @@ -76,14 +76,14 @@ var FontMeasure = (function FontMeasure() { if (!(measureCache = sizes[size])) measureCache = sizes[size] = Object.create(null); } else { - measureCache = null + measureCache = null; } var name = font.loadedName; - var bold = font.bold ? "bold" : "normal"; - var italic = font.italic ? "italic" : "normal"; + var bold = font.bold ? 'bold' : 'normal'; + var italic = font.italic ? 'italic' : 'normal'; size *= kScalePrecision; - var rule = bold + " " + italic + " " + size + 'px "' + name + '"'; + var rule = bold + ' ' + italic + ' ' + size + 'px "' + name + '"'; ctx.font = rule; }, measureText: function fonts_measureText(text) { @@ -144,7 +144,7 @@ var FontLoader = { if (!isWorker && rules.length) { FontLoader.prepareFontLoadEvent(rules, names, objs); } - + if (!checkFontsLoaded()) { document.documentElement.addEventListener( 'pdfjsFontLoad', checkFontsLoaded, false); @@ -402,9 +402,9 @@ var Font = (function Font() { if (!file) { var fontName = stdFontMap[name]; - this.bold = (fontName.indexOf("Bold") != -1); - this.italic = (fontName.indexOf("Oblique") != -1); - this.loadedName = fontName.split("-")[0]; + this.bold = (fontName.indexOf('Bold') != -1); + this.italic = (fontName.indexOf('Oblique') != -1); + this.loadedName = fontName.split('-')[0]; this.loading = false; return; } @@ -414,7 +414,7 @@ var Font = (function Font() { case 'Type1': case 'CIDFontType0': this.mimetype = 'font/opentype'; - + var subtype = properties.subtype; if (subtype === 'Type1C') { var cff = new Type2CFF(file, properties); @@ -535,8 +535,8 @@ var Font = (function Font() { // checksum var checksum = 0, n = data.length; - for (var i = 0; i < n; i+=4) - checksum = (checksum + int32([data[i], data[i+1], data[i+2], data[i+3]])) | 0; + for (var i = 0; i < n; i += 4) + checksum = (checksum + int32([data[i], data[i + 1], data[i + 2], data[i + 3]])) | 0; var tableEntry = (tag + string32(checksum) + string32(offset) + string32(length)); @@ -567,7 +567,7 @@ var Font = (function Font() { } ranges.push([start, end]); } - + return ranges; }; @@ -598,7 +598,7 @@ var Font = (function Font() { var range = ranges[i]; var start = range[0]; var end = range[1]; - var offset = (segCount - i) * 2 + bias * 2; + var offset = (segCount - i) * 2 + bias * 2; bias += (end - start + 1); startCount += string16(start); @@ -730,30 +730,30 @@ var Font = (function Font() { 'Unknown', // 8.Manufacturer 'Unknown' // 9.Designer ]; - + // Mac want 1-byte per character strings while Windows want // 2-bytes per character, so duplicate the names table var stringsUnicode = []; for (var i = 0; i < strings.length; i++) { var str = strings[i]; - + var strUnicode = ''; for (var j = 0; j < str.length; j++) strUnicode += string16(str.charCodeAt(j)); stringsUnicode.push(strUnicode); } - + var names = [strings, stringsUnicode]; var platforms = ['\x00\x01', '\x00\x03']; var encodings = ['\x00\x00', '\x00\x01']; var languages = ['\x00\x00', '\x04\x09']; - + var namesRecordCount = strings.length * platforms.length; var nameTable = '\x00\x00' + // format string16(namesRecordCount) + // Number of names Record string16(namesRecordCount * 12 + 6); // Storage - + // Build the name records field var strOffset = 0; for (var i = 0; i < platforms.length; i++) { @@ -771,7 +771,7 @@ var Font = (function Font() { strOffset += str.length; } } - + nameTable += strings.join('') + stringsUnicode.join(''); return nameTable; } @@ -838,14 +838,14 @@ var Font = (function Font() { encodingID: int16(font.getBytes(2)), offset: int32(font.getBytes(4)) }); - }; + } var encoding = properties.encoding; var charset = properties.charset; for (var i = 0; i < numRecords; i++) { var table = records[i]; font.pos = start + table.offset; - + var format = int16(font.getBytes(2)); var length = int16(font.getBytes(2)); var language = int16(font.getBytes(2)); @@ -855,19 +855,19 @@ var Font = (function Font() { // into the platform so if some characters in the font are assigned // under this limit they will not be displayed so let's rewrite the // CMap. - var glyphs = []; + var glyphs = []; var deltas = []; for (var j = 0; j < 256; j++) { var index = font.getByte(); if (index) { deltas.push(index); - glyphs.push({ unicode : j }); + glyphs.push({ unicode: j }); } } var rewrite = false; for (var code in encoding) { - if (code < 0x20 && encoding[code]) + if (code < 0x20 && encoding[code]) rewrite = true; if (rewrite) @@ -1005,11 +1005,11 @@ var Font = (function Font() { ((hmtx.length - numOfHMetrics * 4) >> 1); if (numMissing > 0) { font.pos = (font.start ? font.start : 0) + hmtx.offset; - var metrics = ""; + var metrics = ''; for (var i = 0; i < hmtx.length; i++) metrics += String.fromCharCode(font.getByte()); for (var i = 0; i < numMissing; i++) - metrics += "\x00\x00"; + metrics += '\x00\x00'; hmtx.data = stringToArray(metrics); } @@ -1024,7 +1024,7 @@ var Font = (function Font() { if (properties.type == 'CIDFontType2') { // Type2 composite fonts map characters directly to glyphs so the cmap // table must be replaced. - + var glyphs = []; var charset = properties.charset; if (!charset.length) { @@ -1254,25 +1254,25 @@ var Font = (function Font() { charsToUnicode: function fonts_chars2Unicode(chars) { var charsCache = this.charsCache; var str; - + // if we translated this string before, just grab it from the cache if (charsCache) { str = charsCache[chars]; if (str) return str; } - + // lazily create the translation cache if (!charsCache) charsCache = this.charsCache = Object.create(null); - + if (this.compositeFont) { // composite fonts have multi-byte strings // convert the string from single-byte to multi-byte // XXX assuming CIDFonts are two-byte - later need to extract the correct byte encoding // according to the PDF spec str = ''; - var multiByteStr = ""; + var multiByteStr = ''; var length = chars.length; for (var i = 0; i < length; i++) { var byte1 = chars.charCodeAt(i++) & 0xFF; @@ -1290,7 +1290,7 @@ var Font = (function Font() { var encoding = this.encoding; if (!encoding) return chars; - + str = ''; for (var i = 0; i < chars.length; ++i) { var charcode = chars.charCodeAt(i); @@ -1298,14 +1298,14 @@ var Font = (function Font() { if ('undefined' == typeof(unicode)) { // FIXME/issue 233: we're hitting this in test/pdf/sizes.pdf // at the moment, for unknown reasons. - warn('Unencoded charcode '+ charcode); + warn('Unencoded charcode ' + charcode); unicode = charcode; } - + // Check if the glyph has already been converted if (!IsNum(unicode)) unicode = encoding[unicode] = GlyphsUnicode[unicode.name]; - + // Handle surrogate pairs if (unicode > 0xFFFF) { str += String.fromCharCode(unicode & 0xFFFF); @@ -2043,7 +2043,7 @@ CFF.prototype = { BlueFuzz: '\x0c\x0b', BlueScale: '\x0c\x09', LanguageGroup: '\x0c\x11', - ExpansionFactor: '\x0c\x18' + ExpansionFactor: '\x0c\x18' }; for (var field in fieldMap) { if (!properties.private.hasOwnProperty(field)) continue; @@ -2087,10 +2087,10 @@ var Type2CFF = (function() { var bytes = file.getBytes(); this.bytes = bytes; this.properties = properties; - + // Other classes expect this.data to be a Javascript array - var data = [] - for (var i = 0, ii = bytes.length; i < ii; ++i) + var data = []; + for (var i = 0, ii = bytes.length; i < ii; ++i) data.push(bytes[i]); this.data = data; @@ -2101,11 +2101,11 @@ var Type2CFF = (function() { parse: function cff_parse() { var header = this.parseHeader(); var nameIndex = this.parseIndex(header.endPos); - + var dictIndex = this.parseIndex(nameIndex.endPos); if (dictIndex.length != 1) error('More than 1 font'); - + var stringIndex = this.parseIndex(dictIndex.endPos); var gsubrIndex = this.parseIndex(stringIndex.endPos); @@ -2121,7 +2121,7 @@ var Type2CFF = (function() { var privOffset = privInfo[1], privLength = privInfo[0]; var privBytes = bytes.subarray(privOffset, privOffset + privLength); baseDict = this.parseDict(privBytes); - var privDict = this.getPrivDict(baseDict, strings); + var privDict = this.getPrivDict(baseDict, strings); TODO('Parse encoding'); var charStrings = this.parseIndex(topDict['CharStrings']); @@ -2132,7 +2132,7 @@ var Type2CFF = (function() { // containing mappings for {unicode, width}) var charstrings = this.getCharStrings(charset, charStrings, privDict, this.properties); - + // create the mapping between charstring and glyph id var glyphIds = []; for (var i = 0, ii = charstrings.length; i < ii; ++i) { @@ -2225,7 +2225,7 @@ var Type2CFF = (function() { var pair = baseDict[i]; var key = pair[0]; var value = pair[1]; - switch(key) { + switch (key) { case 20: dict['defaultWidthX'] = value[0]; case 21: @@ -2247,7 +2247,7 @@ var Type2CFF = (function() { var pair = baseDict[i]; var key = pair[0]; var value = pair[1]; - switch(key) { + switch (key) { case 1: dict['Notice'] = strings[value[0]]; break; @@ -2283,7 +2283,7 @@ var Type2CFF = (function() { }, getStrings: function cff_getstrings(stringIndex) { function bytesToString(bytesArr) { - var s = ""; + var s = ''; for (var i = 0, ii = bytesArr.length; i < ii; ++i) s += String.fromCharCode(bytesArr[i]); return s; @@ -2302,11 +2302,11 @@ var Type2CFF = (function() { var bytes = this.bytes; var offset = 0; - while(bytes[offset] != 1) + while (bytes[offset] != 1) ++offset; if (offset != 0) { - warning("cff data is shifted"); + warning('cff data is shifted'); bytes = bytes.subarray(offset); this.bytes = bytes; } @@ -2314,7 +2314,7 @@ var Type2CFF = (function() { return { endPos: bytes[2], offsetSize: bytes[3] - } + }; }, parseDict: function cff_parseDict(dict) { var pos = 0; @@ -2345,7 +2345,7 @@ var Type2CFF = (function() { }; function parseFloatOperand() { - var str = ""; + var str = ''; var eof = 15; var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-']; @@ -2368,7 +2368,7 @@ var Type2CFF = (function() { var operands = []; var entries = []; - + var pos = 0; var end = dict.length; while (pos < end) { @@ -2421,8 +2421,8 @@ var Type2CFF = (function() { }, length: count, endPos: end - } - }, + }; + } }; return constructor; diff --git a/pdf.js b/pdf.js index 3642ad628..7550da23d 100644 --- a/pdf.js +++ b/pdf.js @@ -48,9 +48,9 @@ function backtrace() { var stackStr; try { throw new Error(); - } catch(e) { + } catch (e) { stackStr = e.stack; - }; + } return stackStr.split('\n').slice(1).join('\n'); } @@ -927,10 +927,10 @@ var AsciiHexStream = (function() { function constructor(str) { this.str = str; this.dict = str.dict; - + DecodeStream.call(this); } - + var hexvalueMap = { 9: -1, // \t 32: -1, // space @@ -959,35 +959,35 @@ var AsciiHexStream = (function() { }; constructor.prototype = Object.create(DecodeStream.prototype); - + constructor.prototype.readBlock = function() { - var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, + var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, decodeLength, buffer, bufferLength, i, length; - + decodeLength = (bytes.length + 1) >> 1; buffer = this.ensureBuffer(this.bufferLength + decodeLength); bufferLength = this.bufferLength; - - for(i = 0, length = bytes.length; i < length; i++) { + + for (i = 0, length = bytes.length; i < length; i++) { c = hexvalueMap[bytes[i]]; - while (c == -1 && (i+1) < length) { + while (c == -1 && (i + 1) < length) { c = hexvalueMap[bytes[++i]]; } - - if((i+1) < length && (bytes[i+1] !== gtCode)) { + + if ((i + 1) < length && (bytes[i + 1] !== gtCode)) { n = hexvalueMap[bytes[++i]]; - buffer[bufferLength++] = c*16+n; + buffer[bufferLength++] = c * 16 + n; } else { - if(bytes[i] !== gtCode) { // EOD marker at an odd number, behave as if a 0 followed the last digit. - buffer[bufferLength++] = c*16; + if (bytes[i] !== gtCode) { // EOD marker at an odd number, behave as if a 0 followed the last digit. + buffer[bufferLength++] = c * 16; } } } - + this.bufferLength = bufferLength; this.eof = true; }; - + return constructor; })(); @@ -2983,7 +2983,7 @@ var Page = (function() { create: Date.now(), compile: 0.0, fonts: 0.0, - render: 0.0, + render: 0.0 }; this.xref = xref; } @@ -3037,7 +3037,7 @@ var Page = (function() { return shadow(this, 'height', height); }, get rotate() { - var rotate = this.inheritPageProp("Rotate") || 0; + var rotate = this.inheritPageProp('Rotate') || 0; // Normalize rotation so it's a multiple of 90 and between 0 and 270 if (rotate % 90 != 0) { rotate = 0; @@ -3056,7 +3056,7 @@ var Page = (function() { stats.compile = stats.fonts = stats.render = 0; var gfx = new CanvasGraphics(canvasCtx); - var fonts = [ ]; + var fonts = []; this.compile(gfx, fonts); stats.compile = Date.now(); @@ -3067,7 +3067,7 @@ var Page = (function() { stats.fonts = Date.now(); // Always defer call to display() to work around bug in // Firefox error reporting from XHR callbacks. - setTimeout(function () { + setTimeout(function() { var exc = null; try { self.display(gfx); @@ -3542,7 +3542,7 @@ var EvalState = (function() { var PartialEvaluator = (function() { function constructor() { this.state = new EvalState(); - this.stateStack = [ ]; + this.stateStack = []; } var OP_MAP = { @@ -3646,10 +3646,10 @@ var PartialEvaluator = (function() { eval: function(stream, xref, resources, fonts) { resources = xref.fetchIfRef(resources) || new Dict(); var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict(); - var patterns = xref.fetchIfRef(resources.get("Pattern")) || new Dict(); + var patterns = xref.fetchIfRef(resources.get('Pattern')) || new Dict(); var parser = new Parser(new Lexer(stream), false); var args = [], argsArray = [], fnArray = [], obj; - + while (!IsEOF(obj = parser.getObj())) { if (IsCmd(obj)) { var cmd = obj.cmd; @@ -3665,7 +3665,7 @@ var PartialEvaluator = (function() { var pattern = xref.fetchIfRef(patterns.get(patternName.name)); if (pattern) { var dict = IsStream(pattern) ? pattern.dict : pattern; - var typeNum = dict.get("PatternType"); + var typeNum = dict.get('PatternType'); if (typeNum == 1) { patternName.code = this.eval(pattern, xref, dict.get('Resources'), fonts); @@ -3718,7 +3718,7 @@ var PartialEvaluator = (function() { } return function(gfx) { - for(var i = 0, length = argsArray.length; i < length; i++) + for (var i = 0, length = argsArray.length; i < length; i++) gfx[fnArray[i]].apply(gfx, argsArray[i]); } }, @@ -3729,8 +3729,8 @@ var PartialEvaluator = (function() { var subType = fontDict.get('Subtype'); var compositeFont = false; assertWellFormed(IsName(subType), 'invalid font Subtype'); - - // If font is a composite + + // If font is a composite // - get the descendant font // - set the type according to the descendant font // - get the FontDescriptor from the descendant font @@ -3750,10 +3750,10 @@ var PartialEvaluator = (function() { } else { fd = fontDict.get('FontDescriptor'); } - + if (!fd) return null; - + var descriptor = xref.fetch(fd); var fontName = xref.fetchIfRef(descriptor.get('FontName')); @@ -3773,7 +3773,7 @@ var PartialEvaluator = (function() { var glyphsData = glyphsStream.getBytes(0); var i = 0; // Glyph ids are big-endian 2-byte values - for (var j=0; j 512 || Math.abs(height) > 512) { width = 512; @@ -5676,7 +5676,7 @@ var PDFFunction = (function() { var c0 = dict.get('C0') || [0]; var c1 = dict.get('C1') || [1]; var n = dict.get('N'); - + if (!IsArray(c0) || !IsArray(c1)) error('Illegal dictionary for interpolated function'); @@ -5685,7 +5685,7 @@ var PDFFunction = (function() { for (var i = 0; i < length; ++i) diff.push(c1[i] - c0[i]); - this.func = function (args) { + this.func = function(args) { var x = args[0]; var out = []; @@ -5697,11 +5697,11 @@ var PDFFunction = (function() { }, constructStiched: function() { TODO('unhandled type of function'); - this.func = function () { return [ 255, 105, 180 ]; } + this.func = function() { return [255, 105, 180]; } }, constructPostScript: function() { TODO('unhandled type of function'); - this.func = function () { return [ 255, 105, 180 ]; } + this.func = function() { return [255, 105, 180]; } } }; diff --git a/web/viewer.js b/web/viewer.js index 37a0d89b6..50d6f8e15 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -41,15 +41,15 @@ var PDFView = { set page(val) { var pages = this.pages; - var input = document.getElementById("pageNumber"); + var input = document.getElementById('pageNumber'); if (val <= 0 || val > pages.length) { input.value = this.page; return; } - + document.location.hash = val; - document.getElementById("previous").disabled = (val == 1); - document.getElementById("next").disabled = (val == pages.length); + document.getElementById('previous').disabled = (val == 1); + document.getElementById('next').disabled = (val == pages.length); if (input.value == val) return; @@ -62,7 +62,7 @@ var PDFView = { }, open: function(url, scale) { - if (url.indexOf("http") == 0) + if (url.indexOf('http') == 0) return; document.title = url; @@ -106,7 +106,7 @@ var PDFView = { var page = pdf.getPage(i); pages.push(new PageView(container, page, i, page.width, page.height, page.stats)); thumbnails.push(new ThumbnailView(sidebar, pages[i - 1])); - }; + } this.scale = (scale || kDefaultScale); this.page = parseInt(document.location.hash.substring(1)) || 1; @@ -136,7 +136,7 @@ var PDFView = { } return visiblePages; - }, + } }; var PageView = function(container, content, id, width, height, stats) { @@ -157,7 +157,7 @@ var PageView = function(container, content, id, width, height, stats) { this.update = function(scale) { this.scale = scale || this.scale; - div.style.width = (this.width * this.scale)+ 'px'; + div.style.width = (this.width * this.scale) + 'px'; div.style.height = (this.height * this.scale) + 'px'; while (div.hasChildNodes()) @@ -192,7 +192,7 @@ var PageView = function(container, content, id, width, height, stats) { this.updateStats = function() { var t1 = stats.compile, t2 = stats.fonts, t3 = stats.render; - var str = 'Time to compile/fonts/render: ' + + var str = 'Time to compile/fonts/render: ' + (t1 - stats.begin) + '/' + (t2 - t1) + '/' + (t3 - t2) + ' ms'; document.getElementById('info').innerHTML = str; }; @@ -270,11 +270,11 @@ window.addEventListener('scroll', function(evt) { PDFView.page = firstPage.id; }, true); -window.addEventListener("hashchange", function(evt) { +window.addEventListener('hashchange', function(evt) { PDFView.page = PDFView.page; }); -window.addEventListener("change", function(evt) { +window.addEventListener('change', function(evt) { var files = evt.target.files; if (!files || files.length == 0) return; @@ -300,7 +300,7 @@ window.addEventListener("change", function(evt) { document.location.hash = 1; }, true); -window.addEventListener("transitionend", function(evt) { +window.addEventListener('transitionend', function(evt) { var pageIndex = 0; var pagesCount = PDFView.pages.length; @@ -308,7 +308,7 @@ window.addEventListener("transitionend", function(evt) { container._interval = window.setInterval(function() { if (pageIndex >= pagesCount) return window.clearInterval(container._interval); - + PDFView.thumbnails[pageIndex++].draw(); }, 500); }, true); From 30ecf43676dbc448f04ba66341889b0e1085b55f Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Tue, 9 Aug 2011 00:03:08 +0300 Subject: [PATCH 28/89] Correct the coding style according to gjslint for driver.js. And remove stray tabs. --- test/driver.js | 74 +++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/test/driver.js b/test/driver.js index 75797fa5c..5c091a2ce 100644 --- a/test/driver.js +++ b/test/driver.js @@ -11,10 +11,10 @@ var appPath, browser, canvas, currentTaskIdx, manifest, stdout; function queryParams() { var qs = window.location.search.substring(1); - var kvs = qs.split("&"); + var kvs = qs.split('&'); var params = { }; for (var i = 0; i < kvs.length; ++i) { - var kv = kvs[i].split("="); + var kv = kvs[i].split('='); params[unescape(kv[0])] = unescape(kv[1]); } return params; @@ -26,20 +26,20 @@ function load() { var manifestFile = params.manifestFile; appPath = params.path; - canvas = document.createElement("canvas"); + canvas = document.createElement('canvas'); canvas.mozOpaque = true; - stdout = document.getElementById("stdout"); + stdout = document.getElementById('stdout'); - log("load...\n"); + log('load...\n'); - log("Harness thinks this browser is '"+ browser + "' with path " + appPath + "\n"); - log("Fetching manifest "+ manifestFile +"..."); + log('Harness thinks this browser is "' + browser + '" with path "' + appPath + '"\n'); + log('Fetching manifest "' + manifestFile + '"... '); var r = new XMLHttpRequest(); - r.open("GET", manifestFile, false); + r.open('GET', manifestFile, false); r.onreadystatechange = function(e) { if (r.readyState == 4) { - log("done\n"); + log('done\n'); manifest = JSON.parse(r.responseText); currentTaskIdx = 0, nextTask(); } @@ -55,11 +55,11 @@ function nextTask() { var task = manifest[currentTaskIdx]; task.round = 0; - log("Loading file "+ task.file +"\n"); + log('Loading file "' + task.file + '"\n'); var r = new XMLHttpRequest(); - r.open("GET", task.file); - r.mozResponseType = r.responseType = "arraybuffer"; + r.open('GET', task.file); + r.mozResponseType = r.responseType = 'arraybuffer'; r.onreadystatechange = function() { var failure; if (r.readyState == 4) { @@ -68,8 +68,8 @@ function nextTask() { try { task.pdfDoc = new PDFDoc(new Stream(data)); - } catch(e) { - failure = 'load PDF doc: '+ e.toString(); + } catch (e) { + failure = 'load PDF doc : ' + e.toString(); } task.pageNum = 1, nextPage(task, failure); @@ -84,12 +84,12 @@ function isLastPage(task) { function nextPage(task, loadError) { if (isLastPage(task)) { - if (++task.round < task.rounds) { - log(" Round "+ (1 + task.round) +"\n"); - task.pageNum = 1; - } else { - ++currentTaskIdx, nextTask(); - return; + if (++task.round < task.rounds) { + log(' Round ' + (1 + task.round) + '\n'); + task.pageNum = 1; + } else { + ++currentTaskIdx, nextTask(); + return; } } @@ -99,8 +99,8 @@ function nextPage(task, loadError) { var page = null; if (!failure) { try { - log(" loading page "+ task.pageNum +"/"+ task.pdfDoc.numPages +"... "); - ctx = canvas.getContext("2d"); + log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages + '... '); + ctx = canvas.getContext('2d'); page = task.pdfDoc.getPage(task.pageNum); var pdfToCssUnitsCoef = 96.0 / 72.0; @@ -115,10 +115,10 @@ function nextPage(task, loadError) { ctx, function(e) { snapshotCurrentPage(page, task, - (!failure && e) ? ('render: '+ e) : failure); + (!failure && e) ? ('render : ' + e) : failure); }); - } catch(e) { - failure = 'page setup: '+ e.toString(); + } catch (e) { + failure = 'page setup : ' + e.toString(); } } @@ -130,10 +130,10 @@ function nextPage(task, loadError) { } function snapshotCurrentPage(page, task, failure) { - log("done, snapshotting... "); + log('done, snapshotting... '); - sendTaskResult(canvas.toDataURL("image/png"), task, failure); - log("done"+ (failure ? " (failed!: "+ failure +")" : "") +"\n"); + sendTaskResult(canvas.toDataURL('image/png'), task, failure); + log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); // Set up the next request var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; @@ -146,13 +146,13 @@ function snapshotCurrentPage(page, task, failure) { function sendQuitRequest() { var r = new XMLHttpRequest(); - r.open("POST", "/tellMeToQuit?path=" + escape(appPath), false); - r.send(""); + r.open('POST', '/tellMeToQuit?path = ' + escape(appPath), false); + r.send(''); } function quitApp() { - log("Done!"); - document.body.innerHTML = "Tests are finished.

CLOSE ME!

"; + log('Done !'); + document.body.innerHTML = 'Tests are finished.

CLOSE ME!

'; if (window.SpecialPowers) { SpecialPowers.quitApplication(); } else { @@ -163,7 +163,7 @@ function quitApp() { function done() { if (inFlightRequests > 0) { - document.getElementById("inFlightCount").innerHTML = inFlightRequests; + document.getElementById('inFlightCount').innerHTML = inFlightRequests; setTimeout(done, 100); } else { setTimeout(quitApp, 100); @@ -183,20 +183,20 @@ function sendTaskResult(snapshot, task, failure) { var r = new XMLHttpRequest(); // (The POST URI is ignored atm.) - r.open("POST", "/submit_task_results", true); - r.setRequestHeader("Content-Type", "application/json"); + r.open('POST', '/submit_task_results', true); + r.setRequestHeader('Content-Type', 'application/json'); r.onreadystatechange = function(e) { if (r.readyState == 4) { inFlightRequests--; } } - document.getElementById("inFlightCount").innerHTML = inFlightRequests++; + document.getElementById('inFlightCount').innerHTML = inFlightRequests++; r.send(JSON.stringify(result)); } function clear(ctx) { ctx.save(); - ctx.fillStyle = "rgb(255, 255, 255)"; + ctx.fillStyle = 'rgb(255, 255, 255)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.restore(); } From 9634eab60b7a786a95ba60a76d93872d127f2bc4 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Tue, 9 Aug 2011 00:24:01 +0300 Subject: [PATCH 29/89] Use strict in user.js. And correct the coding style according to gjslint. --- test/resources/firefox/user.js | 78 +++++++++++++++++----------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/test/resources/firefox/user.js b/test/resources/firefox/user.js index c92af9167..b7f9845f7 100644 --- a/test/resources/firefox/user.js +++ b/test/resources/firefox/user.js @@ -1,38 +1,40 @@ -user_pref("browser.console.showInPanel", true); -user_pref("browser.dom.window.dump.enabled", true); -user_pref("browser.firstrun.show.localepicker", false); -user_pref("browser.firstrun.show.uidiscovery", false); -user_pref("dom.allow_scripts_to_close_windows", true); -user_pref("dom.disable_open_during_load", false); -user_pref("dom.max_script_run_time", 0); // no slow script dialogs -user_pref("dom.max_chrome_script_run_time", 0); -user_pref("dom.popup_maximum", -1); -user_pref("dom.send_after_paint_to_content", true); -user_pref("dom.successive_dialog_time_limit", 0); -user_pref("security.warn_submit_insecure", false); -user_pref("browser.shell.checkDefaultBrowser", false); -user_pref("shell.checkDefaultClient", false); -user_pref("browser.warnOnQuit", false); -user_pref("accessibility.typeaheadfind.autostart", false); -user_pref("javascript.options.showInConsole", true); -user_pref("devtools.errorconsole.enabled", true); -user_pref("layout.debug.enable_data_xbl", true); -user_pref("browser.EULA.override", true); -user_pref("javascript.options.tracejit.content", true); -user_pref("javascript.options.methodjit.content", true); -user_pref("javascript.options.jitprofiling.content", true); -user_pref("javascript.options.methodjit_always", false); -user_pref("gfx.color_management.force_srgb", true); -user_pref("network.manage-offline-status", false); -user_pref("test.mousescroll", true); -user_pref("network.http.prompt-temp-redirect", false); -user_pref("media.cache_size", 100); -user_pref("security.warn_viewing_mixed", false); -user_pref("app.update.enabled", false); -user_pref("browser.panorama.experienced_first_run", true); // Assume experienced -user_pref("dom.w3c_touch_events.enabled", true); -user_pref("extensions.checkCompatibility", false); -user_pref("extensions.installDistroAddons", false); // prevent testpilot etc -user_pref("browser.safebrowsing.enable", false); // prevent traffic to google servers -user_pref("toolkit.telemetry.prompted", true); // prevent telemetry banner -user_pref("toolkit.telemetry.enabled", false); +'use strict'; + +user_pref('browser.console.showInPanel', true); +user_pref('browser.dom.window.dump.enabled', true); +user_pref('browser.firstrun.show.localepicker', false); +user_pref('browser.firstrun.show.uidiscovery', false); +user_pref('dom.allow_scripts_to_close_windows', true); +user_pref('dom.disable_open_during_load', false); +user_pref('dom.max_script_run_time', 0); // no slow script dialogs +user_pref('dom.max_chrome_script_run_time', 0); +user_pref('dom.popup_maximum', -1); +user_pref('dom.send_after_paint_to_content', true); +user_pref('dom.successive_dialog_time_limit', 0); +user_pref('security.warn_submit_insecure', false); +user_pref('browser.shell.checkDefaultBrowser', false); +user_pref('shell.checkDefaultClient', false); +user_pref('browser.warnOnQuit', false); +user_pref('accessibility.typeaheadfind.autostart', false); +user_pref('javascript.options.showInConsole', true); +user_pref('devtools.errorconsole.enabled', true); +user_pref('layout.debug.enable_data_xbl', true); +user_pref('browser.EULA.override', true); +user_pref('javascript.options.tracejit.content', true); +user_pref('javascript.options.methodjit.content', true); +user_pref('javascript.options.jitprofiling.content', true); +user_pref('javascript.options.methodjit_always', false); +user_pref('gfx.color_management.force_srgb', true); +user_pref('network.manage-offline-status', false); +user_pref('test.mousescroll', true); +user_pref('network.http.prompt-temp-redirect', false); +user_pref('media.cache_size', 100); +user_pref('security.warn_viewing_mixed', false); +user_pref('app.update.enabled', false); +user_pref('browser.panorama.experienced_first_run', true); // Assume experienced +user_pref('dom.w3c_touch_events.enabled', true); +user_pref('extensions.checkCompatibility', false); +user_pref('extensions.installDistroAddons', false); // prevent testpilot etc +user_pref('browser.safebrowsing.enable', false); // prevent traffic to google servers +user_pref('toolkit.telemetry.prompted', true); // prevent telemetry banner +user_pref('toolkit.telemetry.enabled', false); From 77104f92709cf48bdf12059a80f7187158b130bf Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Tue, 9 Aug 2011 23:10:44 +0300 Subject: [PATCH 30/89] Refactor the lines that are longer than 80 characters in pdf.js. --- pdf.js | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/pdf.js b/pdf.js index 7550da23d..fbe9b7717 100644 --- a/pdf.js +++ b/pdf.js @@ -55,7 +55,10 @@ function backtrace() { } function shadow(obj, prop, value) { - Object.defineProperty(obj, prop, { value: value, enumerable: true, configurable: true, writable: false }); + Object.defineProperty(obj, prop, { value: value, + enumerable: true, + configurable: true, + writable: false }); return value; } @@ -978,7 +981,9 @@ var AsciiHexStream = (function() { n = hexvalueMap[bytes[++i]]; buffer[bufferLength++] = c * 16 + n; } else { - if (bytes[i] !== gtCode) { // EOD marker at an odd number, behave as if a 0 followed the last digit. + // EOD marker at an odd number, behave as if a 0 followed the last + // digit. + if (bytes[i] !== gtCode) { buffer[bufferLength++] = c * 16; } } @@ -2010,10 +2015,12 @@ var Dict = (function() { constructor.prototype = { get: function(key1, key2, key3) { var value; - if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map || typeof key2 == 'undefined') { + if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map || + typeof key2 == 'undefined') { return value; } - if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map || typeof key3 == 'undefined') { + if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map || + typeof key3 == 'undefined') { return value; } @@ -3780,17 +3787,20 @@ var PartialEvaluator = (function() { } } else { - // XXX This is a placeholder for handling of the encoding of CIDFontType0 fonts + // XXX This is a placeholder for handling of the encoding of + // CIDFontType0 fonts var encoding = xref.fetchIfRef(fontDict.get('Encoding')); if (IsName(encoding)) { // Encoding is a predefined CMap if (encoding.name == 'Identity-H') { TODO('Need to create an identity cmap'); } else { - TODO('Need to support predefined CMaps see PDF 32000-1:2008 9.7.5.2 Predefined CMaps'); + TODO('Need to support predefined CMaps see PDF 32000-1:2008 ' + + '9.7.5.2 Predefined CMaps'); } } else { - TODO('Need to support encoding streams see PDF 32000-1:2008 9.7.5.3'); + TODO('Need to support encoding streams see PDF 32000-1:2008 ' + + '9.7.5.3'); } } } else if (fontDict.has('Encoding')) { @@ -3812,10 +3822,11 @@ var PartialEvaluator = (function() { var index = 0; for (var j = 0; j < differences.length; j++) { var data = differences[j]; - if (subType.name == 'TrueType') { - IsNum(data) ? index = data : encodingMap[index++] = j; + if (IsNum(data)) { + index = data; } else { - IsNum(data) ? index = data : encodingMap[index++] = GlyphsUnicode[data.name]; + encodingMap[index++] = (subType.name == 'TrueType') ? j : + GlyphsUnicode[data.name]; } } @@ -4376,7 +4387,8 @@ var CanvasGraphics = (function() { if (this.ctx.$addCurrentX) { this.ctx.$addCurrentX(-e * 0.001 * this.current.fontSize); } else { - this.current.x -= e * 0.001 * this.current.fontSize * this.current.textHScale; + this.current.x -= e * 0.001 * this.current.fontSize * + this.current.textHScale; } } else if (IsString(e)) { this.showText(e); From eebb47c07205cca852f425ad32c4e4dc982a471a Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Tue, 9 Aug 2011 23:42:50 +0300 Subject: [PATCH 31/89] Refactor the line that is longer than 80 characters in web/viewer.js. --- web/viewer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index 50d6f8e15..0307e7ea3 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -104,7 +104,8 @@ var PDFView = { var thumbnails = this.thumbnails = []; for (var i = 1; i <= pagesCount; i++) { var page = pdf.getPage(i); - pages.push(new PageView(container, page, i, page.width, page.height, page.stats)); + pages.push(new PageView(container, page, i, page.width, page.height, + page.stats)); thumbnails.push(new ThumbnailView(sidebar, pages[i - 1])); } From b2037841e531ff85b3c0b971a2a44e32d26f0648 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Thu, 11 Aug 2011 21:41:03 +0300 Subject: [PATCH 32/89] Correct the coding style according to gjslint in font.js Also refactor the lines that are over 80 characters long. --- fonts.js | 111 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/fonts.js b/fonts.js index ff2f46d7a..4f1c7ef66 100755 --- a/fonts.js +++ b/fonts.js @@ -19,46 +19,46 @@ var kMaxWaitForFontFace = 1000; * fonts and their acronyms. */ var stdFontMap = { - 'Arial': 'Helvetica', - 'Arial_Bold': 'Helvetica-Bold', - 'Arial_BoldItalic': 'Helvetica-BoldOblique', - 'Arial_Italic': 'Helvetica-Oblique', - 'Arial_BoldItalicMT': 'Helvetica-BoldOblique', - 'Arial_BoldMT': 'Helvetica-Bold', - 'Arial_ItalicMT': 'Helvetica-Oblique', - 'ArialMT': 'Helvetica', - 'Courier_Bold': 'Courier-Bold', - 'Courier_BoldItalic': 'Courier-BoldOblique', - 'Courier_Italic': 'Courier-Oblique', - 'CourierNew': 'Courier', - 'CourierNew_Bold': 'Courier-Bold', - 'CourierNew_BoldItalic': 'Courier-BoldOblique', - 'CourierNew_Italic': 'Courier-Oblique', - 'CourierNewPS_BoldItalicMT': 'Courier-BoldOblique', - 'CourierNewPS_BoldMT': 'Courier-Bold', - 'CourierNewPS_ItalicMT': 'Courier-Oblique', - 'CourierNewPSMT': 'Courier', - 'Helvetica_Bold': 'Helvetica-Bold', - 'Helvetica_BoldItalic': 'Helvetica-BoldOblique', - 'Helvetica_Italic': 'Helvetica-Oblique', - 'Symbol_Bold': 'Symbol', - 'Symbol_BoldItalic': 'Symbol', - 'Symbol_Italic': 'Symbol', - 'TimesNewRoman': 'Times-Roman', - 'TimesNewRoman_Bold': 'Times-Bold', - 'TimesNewRoman_BoldItalic': 'Times-BoldItalic', - 'TimesNewRoman_Italic': 'Times-Italic', - 'TimesNewRomanPS': 'Times-Roman', - 'TimesNewRomanPS_Bold': 'Times-Bold', - 'TimesNewRomanPS_BoldItalic': 'Times-BoldItalic', + 'Arial': 'Helvetica', + 'Arial_Bold': 'Helvetica-Bold', + 'Arial_BoldItalic': 'Helvetica-BoldOblique', + 'Arial_Italic': 'Helvetica-Oblique', + 'Arial_BoldItalicMT': 'Helvetica-BoldOblique', + 'Arial_BoldMT': 'Helvetica-Bold', + 'Arial_ItalicMT': 'Helvetica-Oblique', + 'ArialMT': 'Helvetica', + 'Courier_Bold': 'Courier-Bold', + 'Courier_BoldItalic': 'Courier-BoldOblique', + 'Courier_Italic': 'Courier-Oblique', + 'CourierNew': 'Courier', + 'CourierNew_Bold': 'Courier-Bold', + 'CourierNew_BoldItalic': 'Courier-BoldOblique', + 'CourierNew_Italic': 'Courier-Oblique', + 'CourierNewPS_BoldItalicMT': 'Courier-BoldOblique', + 'CourierNewPS_BoldMT': 'Courier-Bold', + 'CourierNewPS_ItalicMT': 'Courier-Oblique', + 'CourierNewPSMT': 'Courier', + 'Helvetica_Bold': 'Helvetica-Bold', + 'Helvetica_BoldItalic': 'Helvetica-BoldOblique', + 'Helvetica_Italic': 'Helvetica-Oblique', + 'Symbol_Bold': 'Symbol', + 'Symbol_BoldItalic': 'Symbol', + 'Symbol_Italic': 'Symbol', + 'TimesNewRoman': 'Times-Roman', + 'TimesNewRoman_Bold': 'Times-Bold', + 'TimesNewRoman_BoldItalic': 'Times-BoldItalic', + 'TimesNewRoman_Italic': 'Times-Italic', + 'TimesNewRomanPS': 'Times-Roman', + 'TimesNewRomanPS_Bold': 'Times-Bold', + 'TimesNewRomanPS_BoldItalic': 'Times-BoldItalic', 'TimesNewRomanPS_BoldItalicMT': 'Times-BoldItalic', - 'TimesNewRomanPS_BoldMT': 'Times-Bold', - 'TimesNewRomanPS_Italic': 'Times-Italic', - 'TimesNewRomanPS_ItalicMT': 'Times-Italic', - 'TimesNewRomanPSMT': 'Times-Roman', - 'TimesNewRomanPSMT_Bold': 'Times-Bold', + 'TimesNewRomanPS_BoldMT': 'Times-Bold', + 'TimesNewRomanPS_Italic': 'Times-Italic', + 'TimesNewRomanPS_ItalicMT': 'Times-Italic', + 'TimesNewRomanPSMT': 'Times-Roman', + 'TimesNewRomanPSMT_Bold': 'Times-Bold', 'TimesNewRomanPSMT_BoldItalic': 'Times-BoldItalic', - 'TimesNewRomanPSMT_Italic': 'Times-Italic' + 'TimesNewRomanPSMT_Italic': 'Times-Italic' }; var FontMeasure = (function FontMeasure() { @@ -536,7 +536,8 @@ var Font = (function Font() { // checksum var checksum = 0, n = data.length; for (var i = 0; i < n; i += 4) - checksum = (checksum + int32([data[i], data[i + 1], data[i + 2], data[i + 3]])) | 0; + checksum = (checksum + int32([data[i], data[i + 1], data[i + 2], + data[i + 3]])) | 0; var tableEntry = (tag + string32(checksum) + string32(offset) + string32(length)); @@ -803,7 +804,8 @@ var Font = (function Font() { file.pos = previousPosition; if (tag == 'head') - data[8] = data[9] = data[10] = data[11] = 0; // clearing checksum adjustment + // clearing checksum adjustment + data[8] = data[9] = data[10] = data[11] = 0; return { tag: tag, @@ -1267,10 +1269,9 @@ var Font = (function Font() { charsCache = this.charsCache = Object.create(null); if (this.compositeFont) { - // composite fonts have multi-byte strings - // convert the string from single-byte to multi-byte - // XXX assuming CIDFonts are two-byte - later need to extract the correct byte encoding - // according to the PDF spec + // composite fonts have multi-byte strings convert the string from + // single-byte to multi-byte XXX assuming CIDFonts are two-byte - later + // need to extract the correct byte encoding according to the PDF spec str = ''; var multiByteStr = ''; var length = chars.length; @@ -1558,8 +1559,8 @@ var Type1Parser = function() { }; function readNumber(str, index) { - while (str[index++] == ' ') - ; + while (str[index++] == ' '); + var start = index; var count = 0; @@ -1628,18 +1629,21 @@ var Type1Parser = function() { case '/FamilyOtherBlues': case '/StemSnapH': case '/StemSnapV': - program.properties.private[token.substring(1)] = readNumberArray(eexecStr, i + 2); + program.properties.private[token.substring(1)] = + readNumberArray(eexecStr, i + 2); break; case '/StdHW': case '/StdVW': - program.properties.private[token.substring(1)] = readNumberArray(eexecStr, i + 2)[0]; + program.properties.private[token.substring(1)] = + readNumberArray(eexecStr, i + 2)[0]; break; case '/BlueShift': case '/BlueFuzz': case '/BlueScale': case '/LanguageGroup': case '/ExpansionFactor': - program.properties.private[token.substring(1)] = readNumber(eexecStr, i + 1); + program.properties.private[token.substring(1)] = + readNumber(eexecStr, i + 1); break; } } else if (c == '/') { @@ -1810,8 +1814,10 @@ CFF.prototype = { // Add another offset after this one because we need a new offset var relativeOffset = 1; for (var i = 0; i < count + 1; i++) { - data += String.fromCharCode((relativeOffset >>> 24) & 0xFF, (relativeOffset >> 16) & 0xFF, - (relativeOffset >> 8) & 0xFF, relativeOffset & 0xFF); + data += String.fromCharCode((relativeOffset >>> 24) & 0xFF, + (relativeOffset >> 16) & 0xFF, + (relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); if (objects[i]) relativeOffset += objects[i].length; @@ -1819,7 +1825,8 @@ CFF.prototype = { for (var i = 0; i < count; i++) { for (var j = 0; j < objects[i].length; j++) - data += isByte ? String.fromCharCode(objects[i][j] & 0xFF) : objects[i][j]; + data += isByte ? String.fromCharCode(objects[i][j] & 0xFF) : + objects[i][j]; } return data; }, From 9ee841388a817e538beff5d4273f3f0ea588edae Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Thu, 11 Aug 2011 21:48:43 +0300 Subject: [PATCH 33/89] Add test js files to the lint. Specifically driver.js and user.js will now be part of lint. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a6f3ba3a4..91533761d 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ font-test: # To install gjslint, see: # # -SRC_DIRS := . utils worker web +SRC_DIRS := . utils worker web test test/resources/firefox GJSLINT_FILES = $(foreach DIR,$(SRC_DIRS),$(wildcard $(DIR)/*.js)) lint: gjslint $(GJSLINT_FILES) From a9b88d2cf871c5f02fd53ef14498a83d7d6112f9 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Thu, 11 Aug 2011 23:44:08 +0300 Subject: [PATCH 34/89] Add test/ to the lint. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 91533761d..34af3b24c 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ font-test: # To install gjslint, see: # # -SRC_DIRS := . utils worker web test test/resources/firefox +SRC_DIRS := . utils worker web test GJSLINT_FILES = $(foreach DIR,$(SRC_DIRS),$(wildcard $(DIR)/*.js)) lint: gjslint $(GJSLINT_FILES) From 56ed06e7ea768676ebb5737da166ad750332d08e Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Fri, 12 Aug 2011 01:00:32 +0300 Subject: [PATCH 35/89] Refactor the lines that are over 80 characters long in driver.js. --- test/driver.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/driver.js b/test/driver.js index 5c091a2ce..0601777a8 100644 --- a/test/driver.js +++ b/test/driver.js @@ -32,7 +32,8 @@ function load() { log('load...\n'); - log('Harness thinks this browser is "' + browser + '" with path "' + appPath + '"\n'); + log('Harness thinks this browser is "' + browser + '" with path "' + + appPath + '"\n'); log('Fetching manifest "' + manifestFile + '"... '); var r = new XMLHttpRequest(); @@ -99,7 +100,8 @@ function nextPage(task, loadError) { var page = null; if (!failure) { try { - log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages + '... '); + log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages + + '... '); ctx = canvas.getContext('2d'); page = task.pdfDoc.getPage(task.pageNum); @@ -114,8 +116,8 @@ function nextPage(task, loadError) { page.startRendering( ctx, function(e) { - snapshotCurrentPage(page, task, - (!failure && e) ? ('render : ' + e) : failure); + snapshotCurrentPage(page, task, (!failure && e) ? + ('render : ' + e) : failure); }); } catch (e) { failure = 'page setup : ' + e.toString(); From 26ce4395144875b1f34ba0eb540e1b08dc52b213 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sat, 13 Aug 2011 20:46:04 -0500 Subject: [PATCH 36/89] LZW filter --- pdf.js | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 3 deletions(-) diff --git a/pdf.js b/pdf.js index fbe9b7717..d04a6d0e1 100644 --- a/pdf.js +++ b/pdf.js @@ -644,9 +644,7 @@ var PredictorStream = (function() { this.stream = stream; this.dict = stream.dict; - if (params.has('EarlyChange')) { - error('EarlyChange predictor parameter is not supported'); - } + var colors = this.colors = params.get('Colors') || 1; var bits = this.bits = params.get('BitsPerComponent') || 8; var columns = this.columns = params.get('Columns') || 1; @@ -1985,6 +1983,134 @@ var CCITTFaxStream = (function() { return constructor; })(); +var LZWStream = (function() { + function constructor(str, earlyChange) { + this.str = str; + this.dict = str.dict; + this.cachedData = 0; + this.bitsCached = 0; + this.earlyChange = earlyChange; + this.codeLength = 9; + this.nextCode = 258; + this.dictionary = []; + this.currentSequence = null; + for (var i = 0; i < 256; ++i) { + this.dictionary[i] = { + value: i, + firstValue: i, + length: 1 + }; + } + + DecodeStream.call(this); + } + + constructor.prototype = Object.create(DecodeStream.prototype); + + constructor.prototype.readBits = function(n) { + var bitsCached = this.bitsCached; + var cachedData = this.cachedData; + while (bitsCached < n) { + var c = this.str.getByte(); + if (c == null) { + this.eof = true; + return; + } + cachedData = (cachedData << 8) | c; + bitsCached += 8; + } + this.bitsCached = (bitsCached -= n); + this.cachedData = cachedData; + this.lastCode = null; + return (cachedData >>> bitsCached) & ((1 << n) - 1); + }; + + constructor.prototype.readBlock = function() { + var blockSize = 512; + var decoded = []; + var i, j, q; + var earlyChange = this.earlyChange; + var nextCode = this.nextCode; + var dictionary = this.dictionary; + var codeLength = this.codeLength; + var prevCode = this.prevCode; + var currentSequence = this.currentSequence; + for (i = 0; i < blockSize; i++) { + var code = this.readBits(codeLength); + var hasPrev = !!currentSequence; + if (code < 256) { + currentSequence = dictionary[code]; + } else if (code >= 258) { + if (code < nextCode) { + currentSequence = dictionary[code]; + } else { + currentSequence = { + value: currentSequence.firstValue, + length: currentSequence.length + 1, + firstValue: currentSequence.firstValue, + prev: currentSequence + }; + } + } else if (code == 256) { + codeLength = 9; + nextCode = 258; + currentSequence = null; + continue; + } else { + this.eof = true; + break; + } + + if (hasPrev) { + var prevCodeSequence = dictionary[prevCode]; + dictionary[nextCode] = { + prev: prevCodeSequence, + length: prevCodeSequence.length + 1, + firstValue: prevCodeSequence.firstValue, + value: currentSequence.firstValue + }; + nextCode++; + switch(nextCode + earlyChange) { + case 512: + codeLength = 10; + break; + case 1024: + codeLength = 11; + break; + case 2048: + codeLength = 12; + break; + } + } + prevCode = code; + decoded.push(currentSequence); + } + this.nextCode = nextCode; + this.codeLength = codeLength; + this.prevCode = prevCode; + this.currentSequence = currentSequence; + + var blockLength = 0; + var length = decoded.length; + for (i = 0; i < length; i++) + blockLength += decoded[i].length; + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + blockLength); + for (i = 0; i < length; i++) { + var p = decoded[i]; + for (q = p.length - 1; q >= 0; q--) { + buffer[bufferLength + q] = p.value; + p = p.prev; + } + bufferLength += decoded[i].length; + } + this.bufferLength = bufferLength; + }; + + return constructor; +})(); + + var Name = (function() { function constructor(name) { this.name = name; @@ -2621,6 +2747,14 @@ var Parser = (function() { return new PredictorStream(new FlateStream(stream), params); } return new FlateStream(stream); + } else if (name == 'LZWDecode' || name == 'LZW') { + var earlyChange = 1; + if (params) { + if (params.has('EarlyChange')) + earlyChange = params.get('EarlyChange'); + return new PredictorStream(new LZWStream(stream, earlyChange), params); + } + return new LZWStream(stream, earlyChange); } else if (name == 'DCTDecode' || name == 'DCT') { var bytes = stream.getBytes(length); return new JpegStream(bytes, stream.dict); From aad77fcc554d93a083f0424effb0a11082d874d0 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 14 Aug 2011 08:40:22 -0500 Subject: [PATCH 37/89] BaseFont and misc fonts fixes --- fonts.js | 16 +++++++++++----- pdf.js | 15 ++++++++++++--- test/pdfs/ecma262.pdf.link | 1 + test/test_manifest.json | 6 ++++++ 4 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 test/pdfs/ecma262.pdf.link diff --git a/fonts.js b/fonts.js index 4f1c7ef66..e994526d7 100755 --- a/fonts.js +++ b/fonts.js @@ -7,7 +7,7 @@ var isWorker = (typeof window == 'undefined'); /** * Maximum file size of the font. */ -var kMaxFontFileSize = 200000; +var kMaxFontFileSize = 300000; /** * Maximum time to wait for a font to be loaded by font-face rules. @@ -83,7 +83,7 @@ var FontMeasure = (function FontMeasure() { var bold = font.bold ? 'bold' : 'normal'; var italic = font.italic ? 'italic' : 'normal'; size *= kScalePrecision; - var rule = bold + ' ' + italic + ' ' + size + 'px "' + name + '"'; + var rule = italic + ' ' + bold + ' ' + size + 'px "' + name + '"'; ctx.font = rule; }, measureText: function fonts_measureText(text) { @@ -395,17 +395,23 @@ var Font = (function Font() { // If the font is to be ignored, register it like an already loaded font // to avoid the cost of waiting for it be be loaded by the platform. if (properties.ignore) { - this.loadedName = 'Arial'; + this.loadedName = 'sans-serif'; this.loading = false; return; } if (!file) { - var fontName = stdFontMap[name]; + // The file data is not specified. Trying to mingle the font name + // to be used with the canvas.font. + var fontName = stdFontMap[name] || name.replace('_', '-'); this.bold = (fontName.indexOf('Bold') != -1); - this.italic = (fontName.indexOf('Oblique') != -1); + this.italic = (fontName.indexOf('Oblique') != -1) || + (fontName.indexOf('Italic') != -1); this.loadedName = fontName.split('-')[0]; this.loading = false; + this.charsToUnicode = function(s) { + return s; + }; return; } diff --git a/pdf.js b/pdf.js index fbe9b7717..e6a0d6713 100644 --- a/pdf.js +++ b/pdf.js @@ -3758,8 +3758,17 @@ var PartialEvaluator = (function() { fd = fontDict.get('FontDescriptor'); } - if (!fd) - return null; + if (!fd) { + var baseFontName = fontDict.get('BaseFont'); + if (!IsName(baseFontName)) + return null; + // Using base font name as a font name. + return { + name: baseFontName.name.replace(/[\+,\-]/g, '_'), + fontDict: fontDict, + properties: {} + }; + } var descriptor = xref.fetch(fd); @@ -4298,7 +4307,7 @@ var CanvasGraphics = (function() { var bold = fontObj.bold ? 'bold' : 'normal'; var italic = fontObj.italic ? 'italic' : 'normal'; - var rule = bold + ' ' + italic + ' ' + size + 'px "' + name + '"'; + var rule = italic + ' ' + bold + ' ' + size + 'px "' + name + '"'; this.ctx.font = rule; } }, diff --git a/test/pdfs/ecma262.pdf.link b/test/pdfs/ecma262.pdf.link new file mode 100644 index 000000000..9aae67530 --- /dev/null +++ b/test/pdfs/ecma262.pdf.link @@ -0,0 +1 @@ +http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 8b0e2b719..d40e53277 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -80,5 +80,11 @@ "file": "pdfs/rotation.pdf", "rounds": 1, "type": "load" + }, + { "id": "ecma262-pdf", + "file": "pdfs/ecma262.pdf", + "link": true, + "rounds": 1, + "type": "load" } ] From b141a6630984c303411759c0c77053bfcac5c14a Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 14 Aug 2011 12:11:23 -0500 Subject: [PATCH 38/89] Fixing bad comment --- fonts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index e994526d7..66d8428e2 100755 --- a/fonts.js +++ b/fonts.js @@ -401,7 +401,7 @@ var Font = (function Font() { } if (!file) { - // The file data is not specified. Trying to mingle the font name + // The file data is not specified. Trying to fix the font name // to be used with the canvas.font. var fontName = stdFontMap[name] || name.replace('_', '-'); this.bold = (fontName.indexOf('Bold') != -1); From 447ff0a059d1ff03babcb3211dd41331ade56c85 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 14 Aug 2011 12:26:48 -0500 Subject: [PATCH 39/89] Add JAI.pdf (issue #292) to the ref tests --- test/pdfs/jai.pdf.link | 1 + test/test_manifest.json | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 test/pdfs/jai.pdf.link diff --git a/test/pdfs/jai.pdf.link b/test/pdfs/jai.pdf.link new file mode 100644 index 000000000..54e17dfc2 --- /dev/null +++ b/test/pdfs/jai.pdf.link @@ -0,0 +1 @@ +http://download.oracle.com/docs/cd/E19957-01/806-5413-10/806-5413-10.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index d40e53277..c74af7729 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -86,5 +86,11 @@ "link": true, "rounds": 1, "type": "load" + }, + { "id": "jai-pdf", + "file": "pdfs/jai.pdf", + "link": true, + "rounds": 1, + "type": "load" } ] From 180747dbdc6153f3b5e268f80aaa02a00a10cfdd Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 14 Aug 2011 15:16:24 -0500 Subject: [PATCH 40/89] Optimize usage of the memory in the LZWStream; linting --- pdf.js | 117 +++++++++++++++++++++++-------------------- web/compatibility.js | 1 + 2 files changed, 63 insertions(+), 55 deletions(-) diff --git a/pdf.js b/pdf.js index ca64b796b..24d602a86 100644 --- a/pdf.js +++ b/pdf.js @@ -1989,18 +1989,23 @@ var LZWStream = (function() { this.dict = str.dict; this.cachedData = 0; this.bitsCached = 0; - this.earlyChange = earlyChange; - this.codeLength = 9; - this.nextCode = 258; - this.dictionary = []; - this.currentSequence = null; + + var maxLzwDictionarySize = 4097; + var lzwState = { + earlyChange: earlyChange, + codeLength: 9, + nextCode: 258, + dictionaryValues: new Uint8Array(maxLzwDictionarySize), + dictionaryLengths: new Uint16Array(maxLzwDictionarySize), + dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), + currentSequence: new Uint8Array(maxLzwDictionarySize), + currentSequenceLength: 0 + }; for (var i = 0; i < 256; ++i) { - this.dictionary[i] = { - value: i, - firstValue: i, - length: 1 - }; + lzwState.dictionaryValues[i] = i; + lzwState.dictionaryLengths[i] = 1; } + this.lzwState = lzwState; DecodeStream.call(this); } @@ -2027,34 +2032,44 @@ var LZWStream = (function() { constructor.prototype.readBlock = function() { var blockSize = 512; - var decoded = []; + var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize; var i, j, q; - var earlyChange = this.earlyChange; - var nextCode = this.nextCode; - var dictionary = this.dictionary; - var codeLength = this.codeLength; - var prevCode = this.prevCode; - var currentSequence = this.currentSequence; + + var lzwState = this.lzwState; + var earlyChange = lzwState.earlyChange; + var nextCode = lzwState.nextCode; + var dictionaryValues = lzwState.dictionaryValues; + var dictionaryLengths = lzwState.dictionaryLengths; + var dictionaryPrevCodes = lzwState.dictionaryPrevCodes; + var codeLength = lzwState.codeLength; + var prevCode = lzwState.prevCode; + var currentSequence = lzwState.currentSequence; + var currentSequenceLength = lzwState.currentSequenceLength; + + var decodedLength = 0; + var currentBufferLength = this.bufferLength; + var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + for (i = 0; i < blockSize; i++) { var code = this.readBits(codeLength); - var hasPrev = !!currentSequence; + var hasPrev = currentSequenceLength > 0; if (code < 256) { - currentSequence = dictionary[code]; + currentSequence[0] = code; + currentSequenceLength = 1; } else if (code >= 258) { if (code < nextCode) { - currentSequence = dictionary[code]; + currentSequenceLength = dictionaryLengths[code]; + for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { + currentSequence[j] = dictionaryValues[q]; + q = dictionaryPrevCodes[q]; + } } else { - currentSequence = { - value: currentSequence.firstValue, - length: currentSequence.length + 1, - firstValue: currentSequence.firstValue, - prev: currentSequence - }; + currentSequence[currentSequenceLength++] = currentSequence[0]; } } else if (code == 256) { codeLength = 9; nextCode = 258; - currentSequence = null; + currentSequenceLength = 0; continue; } else { this.eof = true; @@ -2062,15 +2077,11 @@ var LZWStream = (function() { } if (hasPrev) { - var prevCodeSequence = dictionary[prevCode]; - dictionary[nextCode] = { - prev: prevCodeSequence, - length: prevCodeSequence.length + 1, - firstValue: prevCodeSequence.firstValue, - value: currentSequence.firstValue - }; + dictionaryPrevCodes[nextCode] = prevCode; + dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; + dictionaryValues[nextCode] = currentSequence[0]; nextCode++; - switch(nextCode + earlyChange) { + switch (nextCode + earlyChange) { case 512: codeLength = 10; break; @@ -2083,28 +2094,23 @@ var LZWStream = (function() { } } prevCode = code; - decoded.push(currentSequence); - } - this.nextCode = nextCode; - this.codeLength = codeLength; - this.prevCode = prevCode; - this.currentSequence = currentSequence; - var blockLength = 0; - var length = decoded.length; - for (i = 0; i < length; i++) - blockLength += decoded[i].length; - var bufferLength = this.bufferLength; - var buffer = this.ensureBuffer(bufferLength + blockLength); - for (i = 0; i < length; i++) { - var p = decoded[i]; - for (q = p.length - 1; q >= 0; q--) { - buffer[bufferLength + q] = p.value; - p = p.prev; + decodedLength += currentSequenceLength; + if (estimatedDecodedSize < decodedLength) { + do { + estimatedDecodedSize += decodedSizeDelta; + } while (estimatedDecodedSize < decodedLength); + buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); } - bufferLength += decoded[i].length; + for (j = 0; j < currentSequenceLength; j++) + buffer[currentBufferLength++] = currentSequence[j]; } - this.bufferLength = bufferLength; + lzwState.nextCode = nextCode; + lzwState.codeLength = codeLength; + lzwState.prevCode = prevCode; + lzwState.currentSequenceLength = currentSequenceLength; + + this.bufferLength = currentBufferLength; }; return constructor; @@ -2752,7 +2758,8 @@ var Parser = (function() { if (params) { if (params.has('EarlyChange')) earlyChange = params.get('EarlyChange'); - return new PredictorStream(new LZWStream(stream, earlyChange), params); + return new PredictorStream( + new LZWStream(stream, earlyChange), params); } return new LZWStream(stream, earlyChange); } else if (name == 'DCTDecode' || name == 'DCT') { diff --git a/web/compatibility.js b/web/compatibility.js index 5687d30ce..d286692b1 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -40,6 +40,7 @@ // so we can use the TypedArray as well window.Uint32Array = TypedArray; window.Int32Array = TypedArray; + window.Uint16Array = TypedArray; })(); // Object.create() ? From 03c5fa3d19bac01a16245ee727b07477b8cabb2f Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sun, 14 Aug 2011 16:34:19 -0500 Subject: [PATCH 41/89] switch optimization --- pdf.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/pdf.js b/pdf.js index 24d602a86..79ae776f6 100644 --- a/pdf.js +++ b/pdf.js @@ -2081,17 +2081,9 @@ var LZWStream = (function() { dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; dictionaryValues[nextCode] = currentSequence[0]; nextCode++; - switch (nextCode + earlyChange) { - case 512: - codeLength = 10; - break; - case 1024: - codeLength = 11; - break; - case 2048: - codeLength = 12; - break; - } + codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ? + codeLength : Math.min(Math.log(nextCode + earlyChange) / + 0.6931471805599453 + 1, 12) | 0; } prevCode = code; From 23d37f98dbdf99ed0a22ba1b7ad4d83ee023931e Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 10:25:02 -0700 Subject: [PATCH 42/89] working on subroutines --- fonts.js | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/fonts.js b/fonts.js index 66d8428e2..e38edef8d 100755 --- a/fonts.js +++ b/fonts.js @@ -1598,6 +1598,17 @@ 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')) + ++i; + + var t = ''; + while(i < count && !(eexecStr[i] == ' ' || eexecStr[i] == '\n')) + t += eexecStr[i++]; + + return t; + } + var c = eexecStr[i]; if ((glyphsSection || subrsSection) && c == 'R') { @@ -1627,7 +1638,25 @@ var Type1Parser = function() { glyphsSection = true; break; case '/Subrs': - subrsSection = true; + ++i; + var num = parseInt(getToken()); + getToken(); // read in 'array' + for (var j = 0; j < num; ++j) { + var t = getToken(); // read in 'dup' + if (t == 'ND') + break; + var index = parseInt(getToken()); + if (index > j) + j = index; + var length = parseInt(getToken()); + getToken(); // read in 'RD' + var data = eexec.slice(i + 1, i + 1 + length); + var encoded = decrypt(data, kCharStringsEncryptionKey, 4); + var str = decodeCharString(encoded); + i = i + 1 + length; + getToken(); //read in 'NP' + program.subrs[index] = str.charstring; + } break; case '/BlueValues': case '/OtherBlues': @@ -1909,8 +1938,13 @@ CFF.prototype = { for (var i = 0; i < bias; i++) type2Subrs.push([0x0B]); - for (var i = 0; i < count; i++) - type2Subrs.push(this.flattenCharstring(type1Subrs[i], this.commandsMap)); + for (var i = 0; i < count; i++) { + var subr = type1Subrs[i]; + if (!subr) + subr = [0x0B]; + + type2Subrs.push(this.flattenCharstring(subr, this.commandsMap)); + } return type2Subrs; }, From 802f664baa6ed8a7ea440fa060032975ca837586 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Tue, 16 Aug 2011 22:17:46 +0300 Subject: [PATCH 43/89] Indent the driver.js correctly. --- test/driver.js | 212 +++++++++++++++++++++++++------------------------ 1 file changed, 107 insertions(+), 105 deletions(-) diff --git a/test/driver.js b/test/driver.js index 0601777a8..f12dcae23 100644 --- a/test/driver.js +++ b/test/driver.js @@ -10,137 +10,139 @@ var appPath, browser, canvas, currentTaskIdx, manifest, stdout; function queryParams() { - var qs = window.location.search.substring(1); - var kvs = qs.split('&'); - var params = { }; - for (var i = 0; i < kvs.length; ++i) { - var kv = kvs[i].split('='); - params[unescape(kv[0])] = unescape(kv[1]); - } - return params; + var qs = window.location.search.substring(1); + var kvs = qs.split('&'); + var params = { }; + for (var i = 0; i < kvs.length; ++i) { + var kv = kvs[i].split('='); + params[unescape(kv[0])] = unescape(kv[1]); + } + return params; } function load() { - var params = queryParams(); - browser = params.browser; - var manifestFile = params.manifestFile; - appPath = params.path; + var params = queryParams(); + browser = params.browser; + var manifestFile = params.manifestFile; + appPath = params.path; - canvas = document.createElement('canvas'); - canvas.mozOpaque = true; - stdout = document.getElementById('stdout'); + canvas = document.createElement('canvas'); + canvas.mozOpaque = true; + stdout = document.getElementById('stdout'); - log('load...\n'); + log('load...\n'); - log('Harness thinks this browser is "' + browser + '" with path "' + - appPath + '"\n'); - log('Fetching manifest "' + manifestFile + '"... '); + log('Harness thinks this browser is "' + browser + '" with path "' + + appPath + '"\n'); + log('Fetching manifest "' + manifestFile + '"... '); - var r = new XMLHttpRequest(); - r.open('GET', manifestFile, false); - r.onreadystatechange = function(e) { - if (r.readyState == 4) { - log('done\n'); - manifest = JSON.parse(r.responseText); - currentTaskIdx = 0, nextTask(); - } - }; - r.send(null); + var r = new XMLHttpRequest(); + r.open('GET', manifestFile, false); + r.onreadystatechange = function(e) { + if (r.readyState == 4) { + log('done\n'); + manifest = JSON.parse(r.responseText); + currentTaskIdx = 0, nextTask(); + } + }; + r.send(null); } window.onload = load; function nextTask() { - if (currentTaskIdx == manifest.length) { - return done(); + if (currentTaskIdx == manifest.length) { + return done(); + } + var task = manifest[currentTaskIdx]; + task.round = 0; + + log('Loading file "' + task.file + '"\n'); + + var r = new XMLHttpRequest(); + r.open('GET', task.file); + r.mozResponseType = r.responseType = 'arraybuffer'; + r.onreadystatechange = function() { + var failure; + if (r.readyState == 4) { + var data = r.mozResponseArrayBuffer || r.mozResponse || + r.responseArrayBuffer || r.response; + + try { + task.pdfDoc = new PDFDoc(new Stream(data)); + } catch (e) { + failure = 'load PDF doc : ' + e.toString(); + } + + task.pageNum = 1, nextPage(task, failure); } - var task = manifest[currentTaskIdx]; - task.round = 0; - - log('Loading file "' + task.file + '"\n'); - - var r = new XMLHttpRequest(); - r.open('GET', task.file); - r.mozResponseType = r.responseType = 'arraybuffer'; - r.onreadystatechange = function() { - var failure; - if (r.readyState == 4) { - var data = r.mozResponseArrayBuffer || r.mozResponse || - r.responseArrayBuffer || r.response; - - try { - task.pdfDoc = new PDFDoc(new Stream(data)); - } catch (e) { - failure = 'load PDF doc : ' + e.toString(); - } - - task.pageNum = 1, nextPage(task, failure); - } - }; - r.send(null); + }; + r.send(null); } function isLastPage(task) { - return (!task.pdfDoc || (task.pageNum > task.pdfDoc.numPages)); + return (!task.pdfDoc || (task.pageNum > task.pdfDoc.numPages)); } function nextPage(task, loadError) { - if (isLastPage(task)) { - if (++task.round < task.rounds) { - log(' Round ' + (1 + task.round) + '\n'); - task.pageNum = 1; - } else { - ++currentTaskIdx, nextTask(); - return; + if (isLastPage(task)) { + if (++task.round < task.rounds) { + log(' Round ' + (1 + task.round) + '\n'); + task.pageNum = 1; + } else { + ++currentTaskIdx, nextTask(); + return; + } + } + + var failure = loadError || ''; + + var ctx = null; + var page = null; + if (!failure) { + try { + log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages + + '... '); + ctx = canvas.getContext('2d'); + page = task.pdfDoc.getPage(task.pageNum); + + var pdfToCssUnitsCoef = 96.0 / 72.0; + // using mediaBox for the canvas size + var pageWidth = page.width; + var pageHeight = page.height; + canvas.width = pageWidth * pdfToCssUnitsCoef; + canvas.height = pageHeight * pdfToCssUnitsCoef; + clear(ctx); + + page.startRendering( + ctx, + function(e) { + snapshotCurrentPage(page, task, (!failure && e) ? + ('render : ' + e) : failure); } + ); + } catch (e) { + failure = 'page setup : ' + e.toString(); } + } - var failure = loadError || ''; - - var ctx = null; - var page = null; - if (!failure) { - try { - log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages + - '... '); - ctx = canvas.getContext('2d'); - page = task.pdfDoc.getPage(task.pageNum); - - var pdfToCssUnitsCoef = 96.0 / 72.0; - // using mediaBox for the canvas size - var pageWidth = page.width; - var pageHeight = page.height; - canvas.width = pageWidth * pdfToCssUnitsCoef; - canvas.height = pageHeight * pdfToCssUnitsCoef; - clear(ctx); - - page.startRendering( - ctx, - function(e) { - snapshotCurrentPage(page, task, (!failure && e) ? - ('render : ' + e) : failure); - }); - } catch (e) { - failure = 'page setup : ' + e.toString(); - } - } - - if (failure) { - // Skip right to snapshotting if there was a failure, since the - // fonts might be in an inconsistent state. - snapshotCurrentPage(page, task, failure); - } + if (failure) { + // Skip right to snapshotting if there was a failure, since the + // fonts might be in an inconsistent state. + snapshotCurrentPage(page, task, failure); + } } function snapshotCurrentPage(page, task, failure) { - log('done, snapshotting... '); + log('done, snapshotting... '); - sendTaskResult(canvas.toDataURL('image/png'), task, failure); - log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); + sendTaskResult(canvas.toDataURL('image/png'), task, failure); + log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); - // Set up the next request - var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; - setTimeout(function() { - ++task.pageNum, nextPage(task); + // Set up the next request + var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; + setTimeout( + function() { + ++task.pageNum, nextPage(task); }, backoff ); From 965193b38d789a389921d07ebcd924045f781fe7 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Tue, 16 Aug 2011 23:08:55 +0300 Subject: [PATCH 44/89] Keep the results visible in test_slave.html before quitting. Currently the innerHTML is replaced with text: Tests are finished. CLOSE ME! Instead of replacing the innerHTML prepend that text to it. This way the user can still check the results of the test. --- test/driver.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/driver.js b/test/driver.js index f12dcae23..92fc00af1 100644 --- a/test/driver.js +++ b/test/driver.js @@ -156,7 +156,8 @@ function sendQuitRequest() { function quitApp() { log('Done !'); - document.body.innerHTML = 'Tests are finished.

CLOSE ME!

'; + document.body.innerHTML = 'Tests are finished.

CLOSE ME!

' + + document.body.innerHTML; if (window.SpecialPowers) { SpecialPowers.quitApplication(); } else { From c592d5ed3b8a95a4392996f1222943645553d7ae Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 14:49:12 -0700 Subject: [PATCH 45/89] still mucking with subroutines --- fonts.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fonts.js b/fonts.js index e38edef8d..356d7f948 100755 --- a/fonts.js +++ b/fonts.js @@ -1469,7 +1469,7 @@ var Type1Parser = function() { var value = ''; var count = array.length; for (var i = 0; i < count; i++) { - value = parseInt(array[i]); + value = array[i]; if (value < 32) { var command = null; @@ -1479,8 +1479,8 @@ var Type1Parser = function() { // TODO Clean this code if (escape == 16) { var index = charstring.pop(); - var argc = charstring.pop(); - var data = charstring.pop(); +// var argc = charstring.pop(); +// var data = charstring.pop(); // If the flex mechanishm is not used in a font program, Adobe // state that that entries 0, 1 and 2 can simply be replace by @@ -1492,8 +1492,8 @@ var Type1Parser = function() { // This is the same things about hint replacement, if it is not used // entry 3 can be replaced by {3} if (index == 3) { - charstring.push(3); - i++; +// charstring.push(3); +// i++; continue; } } @@ -1532,11 +1532,11 @@ var Type1Parser = function() { value = command; } else if (value <= 246) { - value = parseInt(value) - 139; + value = value - 139; } else if (value <= 250) { - value = ((value - 247) * 256) + parseInt(array[++i]) + 108; + value = ((value - 247) * 256) + array[++i] + 108; } else if (value <= 254) { - value = -((value - 251) * 256) - parseInt(array[++i]) - 108; + value = -((value - 251) * 256) - array[++i] - 108; } else { value = (array[++i] & 0xff) << 24 | (array[++i] & 0xff) << 16 | (array[++i] & 0xff) << 8 | (array[++i] & 0xff) << 0; From 7cbdc982c51855f6c064a11f67ae0cf4f93c66be Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Wed, 17 Aug 2011 01:33:00 +0300 Subject: [PATCH 46/89] Report results properly to test.py from driver.js. If the PDFDoc creation failed in driver.js then that was not informed back to test.py. This lead to State.remaining being off by one. And that did not let the test to end as expected. Instead the test hung indefinitely. This change now reveals TEST-UNEXPECTED-FAIL which was hidden previously. --- test/driver.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/test/driver.js b/test/driver.js index 92fc00af1..716046c4b 100644 --- a/test/driver.js +++ b/test/driver.js @@ -80,10 +80,19 @@ function nextTask() { } function isLastPage(task) { - return (!task.pdfDoc || (task.pageNum > task.pdfDoc.numPages)); + return (task.pageNum > task.pdfDoc.numPages); } function nextPage(task, loadError) { + var failure = loadError || ''; + + if (!task.pdfDoc) { + sendTaskResult(canvas.toDataURL('image/png'), task, failure); + log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); + ++currentTaskIdx, nextTask(); + return; + } + if (isLastPage(task)) { if (++task.round < task.rounds) { log(' Round ' + (1 + task.round) + '\n'); @@ -94,15 +103,13 @@ function nextPage(task, loadError) { } } - var failure = loadError || ''; - - var ctx = null; var page = null; + if (!failure) { try { log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages + '... '); - ctx = canvas.getContext('2d'); + var ctx = canvas.getContext('2d'); page = task.pdfDoc.getPage(task.pageNum); var pdfToCssUnitsCoef = 96.0 / 72.0; @@ -179,7 +186,7 @@ var inFlightRequests = 0; function sendTaskResult(snapshot, task, failure) { var result = { browser: browser, id: task.id, - numPages: task.pdfDoc.numPages, + numPages: task.pdfDoc ? task.pdfDoc.numPages : 0, failure: failure, file: task.file, round: task.round, From 9f615036d9ff1709e348764bc799a2b8b33fb682 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 16:14:29 -0700 Subject: [PATCH 47/89] Still testing type1 charstring conversion --- fonts.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fonts.js b/fonts.js index e2f278523..77183a602 100755 --- a/fonts.js +++ b/fonts.js @@ -1488,8 +1488,9 @@ var Type1Parser = function() { // TODO Clean this code if (escape == 16) { var index = charstring.pop(); -// var argc = charstring.pop(); -// var data = charstring.pop(); + var argc = charstring.pop(); + for (var j = 0; j < argc; j++) + var data = charstring.pop(); // If the flex mechanishm is not used in a font program, Adobe // state that that entries 0, 1 and 2 can simply be replace by @@ -1501,8 +1502,8 @@ var Type1Parser = function() { // This is the same things about hint replacement, if it is not used // entry 3 can be replaced by {3} if (index == 3) { -// charstring.push(3); -// i++; + charstring.push(3); + i++; continue; } } From 2ef990059765e71ca2f35c7b6c90bc61e163d9ed Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 16:47:48 -0700 Subject: [PATCH 48/89] implemented curve2, partial fix for #325 --- pdf.js | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/pdf.js b/pdf.js index 79ae776f6..081abfd20 100644 --- a/pdf.js +++ b/pdf.js @@ -4,7 +4,7 @@ 'use strict'; var ERRORS = 0, WARNINGS = 1, TODOS = 5; -var verbosity = WARNINGS; +var verbosity = TODOS; function log(msg) { if (console && console.log) @@ -4137,6 +4137,9 @@ var CanvasExtraState = (function() { this.charSpacing = 0; this.wordSpacing = 0; this.textHScale = 1; + // Path variables + this.pathX = 0; + this.pathY = 0; // Color spaces this.fillColorSpaceObj = null; this.strokeColorSpaceObj = null; @@ -4276,18 +4279,39 @@ var CanvasGraphics = (function() { // Path moveTo: function(x, y) { this.ctx.moveTo(x, y); + + var current = this.current; + current.pathX = x; + current.pathY = y; }, lineTo: function(x, y) { this.ctx.lineTo(x, y); + + var current = this.current; + current.pathX = x; + current.pathY = y; }, curveTo: function(x1, y1, x2, y2, x3, y3) { this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + + var current = this.current; + current.pathX = x3; + current.pathY = y3; }, curveTo2: function(x2, y2, x3, y3) { - TODO("'v' operator: need current point in gfx context"); + var current = this.current; + this.ctx.bezierCurveTo(current.pathX, current.pathY, x2, y2, x3, y3); +// TODO("'v' operator: need current point in gfx context"); + + current.pathX = x3; + current.pathY = y3; }, curveTo3: function(x1, y1, x3, y3) { this.curveTo(x1, y1, x3, y3, x3, y3); + + var current = this.current; + current.pathX = x3; + current.pathY = y3; }, closePath: function() { this.ctx.closePath(); From 8351877f1670c8b28f3a45ba4f002e41d4c7dda8 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 16:49:26 -0700 Subject: [PATCH 49/89] cleanup --- pdf.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pdf.js b/pdf.js index 081abfd20..d9c1007bb 100644 --- a/pdf.js +++ b/pdf.js @@ -4,7 +4,7 @@ 'use strict'; var ERRORS = 0, WARNINGS = 1, TODOS = 5; -var verbosity = TODOS; +var verbosity = WARNINGS; function log(msg) { if (console && console.log) @@ -4301,7 +4301,6 @@ var CanvasGraphics = (function() { curveTo2: function(x2, y2, x3, y3) { var current = this.current; this.ctx.bezierCurveTo(current.pathX, current.pathY, x2, y2, x3, y3); -// TODO("'v' operator: need current point in gfx context"); current.pathX = x3; current.pathY = y3; From 7ae84533c60844aab6584608a4ea30bfc2f27513 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 18:15:20 -0700 Subject: [PATCH 50/89] added stiched functions --- pdf.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/pdf.js b/pdf.js index d9c1007bb..45f5484f6 100644 --- a/pdf.js +++ b/pdf.js @@ -5727,7 +5727,7 @@ var PDFFunction = (function() { if (!typeFn) error('Unknown type of function'); - typeFn.call(this, fn, dict); + typeFn.call(this, fn, dict, xref); }; constructor.prototype = { @@ -5872,9 +5872,58 @@ var PDFFunction = (function() { return out; } }, - constructStiched: function() { - TODO('unhandled type of function'); - this.func = function() { return [255, 105, 180]; } + constructStiched: function(fn, dict, xref) { + var domain = dict.get('Domain'); + var range = dict.get('Range'); + + if (!domain) + error('No domain'); + + var inputSize = domain.length / 2; + if (inputSize != 1) + error('Bad domain for stiched function'); + + var fnRefs = dict.get('Functions'); + var fns = []; + for (var i = 0, ii = fnRefs.length; i < ii; ++i) + fns.push(new PDFFunction(xref, xref.fetchIfRef(fnRefs[i]))); + + var bounds = dict.get('Bounds'); + var encode = dict.get('Encode'); + + this.func = function(args) { + var clip = function(v, min, max) { + if (v > max) + v = max; + else if (v < min) + v = min; + return v; + } + + // clip to domain + var v = clip(args[0], domain[0], domain[1]); + // calulate which bound the value is in + for (var i = 0, ii = bounds.length; i < ii; ++i) { + if (v < bounds[i]) + break; + } + + // encode value into domain of function + var dmin = domain[0]; + if (i > 0) + dmin = bounds[i - 1]; + var dmax = domain[1]; + if (i < bounds.length) + dmax = bounds[i]; + + var rmin = encode[2 * i]; + var rmax = encode[2 * i + 1]; + + var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); + + // call the appropropriate function + return fns[i].func([v2]); + } }, constructPostScript: function() { TODO('unhandled type of function'); From a7353ad737ad51593e1a00b7bbefffc39f8cf2fc Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 17 Aug 2011 09:22:54 -0700 Subject: [PATCH 51/89] combined pathX/Y with x/y and wrote setCurrentPoint function --- pdf.js | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/pdf.js b/pdf.js index 45f5484f6..2afed5f6b 100644 --- a/pdf.js +++ b/pdf.js @@ -4137,9 +4137,6 @@ var CanvasExtraState = (function() { this.charSpacing = 0; this.wordSpacing = 0; this.textHScale = 1; - // Path variables - this.pathX = 0; - this.pathY = 0; // Color spaces this.fillColorSpaceObj = null; this.strokeColorSpaceObj = null; @@ -4152,7 +4149,11 @@ var CanvasExtraState = (function() { constructor.prototype = { clone: function canvasextra_clone() { return Object.create(this); - } + }, + setCurrentPoint: function canvasextra_setCurrentPoint(x, y) { + this.x = x; + this.y = y; + }, }; return constructor; })(); @@ -4279,38 +4280,24 @@ var CanvasGraphics = (function() { // Path moveTo: function(x, y) { this.ctx.moveTo(x, y); - - var current = this.current; - current.pathX = x; - current.pathY = y; + this.current.setCurrentPoint(x, y); }, lineTo: function(x, y) { this.ctx.lineTo(x, y); - - var current = this.current; - current.pathX = x; - current.pathY = y; + this.current.setCurrentPoint(x, y); }, curveTo: function(x1, y1, x2, y2, x3, y3) { this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); - - var current = this.current; - current.pathX = x3; - current.pathY = y3; + this.current.setCurrentPoint(x3, y3); }, curveTo2: function(x2, y2, x3, y3) { var current = this.current; - this.ctx.bezierCurveTo(current.pathX, current.pathY, x2, y2, x3, y3); - - current.pathX = x3; - current.pathY = y3; + this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3); + current.setCurrentPoint(x3, y3); }, curveTo3: function(x1, y1, x3, y3) { this.curveTo(x1, y1, x3, y3, x3, y3); - - var current = this.current; - current.pathX = x3; - current.pathY = y3; + this.current.setCurrentPoint(x3, y3); }, closePath: function() { this.ctx.closePath(); From bd567fc322b60096659035dcd8c00c852249447a Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 17 Aug 2011 15:55:09 -0700 Subject: [PATCH 52/89] working font --- fonts.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 77183a602..a55fc63a2 100755 --- a/fonts.js +++ b/fonts.js @@ -1490,7 +1490,7 @@ var Type1Parser = function() { var index = charstring.pop(); var argc = charstring.pop(); for (var j = 0; j < argc; j++) - var data = charstring.pop(); + charstring.push('drop'); // If the flex mechanishm is not used in a font program, Adobe // state that that entries 0, 1 and 2 can simply be replace by @@ -1976,6 +1976,8 @@ CFF.prototype = { 'sub': [12, 11], 'div': [12, 12], 'pop': [1, 12, 18], +// 'pop': [], + 'drop' : [12, 18], 'endchar': 14, 'rmoveto': 21, 'hmoveto': 22, From 8ff8a92244350d6fac72954957fcaa1426cb29c6 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 17 Aug 2011 16:00:54 -0700 Subject: [PATCH 53/89] Revert "Merge branch 'writeToFile' into hmm" This reverts commit 9b91fca34702e37b7f6d7eb958e8d70f51b2602d, reversing changes made to c592d5ed3b8a95a4392996f1222943645553d7ae. --- fonts.js | 9 --------- utils/fonts_utils.js | 4 +++- web/viewer.html | 1 - 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/fonts.js b/fonts.js index a55fc63a2..a4976b0ac 100755 --- a/fonts.js +++ b/fonts.js @@ -446,15 +446,6 @@ var Font = (function Font() { break; } - var fileArr = []; - file.reset(); - file = file.getBytes(); - for (var i = 0, ii = file.length; i < ii; ++i) - fileArr.push(file[i]); - - writeToFile(data, '/tmp/' + name + '_new'); - writeToFile(fileArr, '/tmp/' + name + '_orig'); - this.data = data; this.type = properties.type; this.textMatrix = properties.textMatrix; diff --git a/utils/fonts_utils.js b/utils/fonts_utils.js index 98ea60757..edfc22186 100644 --- a/utils/fonts_utils.js +++ b/utils/fonts_utils.js @@ -1,6 +1,8 @@ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +'use strict'; + /** * The Type2 reader code below is only used for debugging purpose since Type2 * is only a CharString format and is never used directly as a Font file. @@ -389,7 +391,7 @@ function writeToFile(aBytes, aFilePath) { var stream = Cc['@mozilla.org/network/file-output-stream;1'] .createInstance(Ci.nsIFileOutputStream); - stream.init(file, 0x04 | 0x08 | 0x20, 0666, 0); + stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0); var bos = Cc['@mozilla.org/binaryoutputstream;1'] .createInstance(Ci.nsIBinaryOutputStream); diff --git a/web/viewer.html b/web/viewer.html index 5498d8a1c..285dadb01 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -10,7 +10,6 @@ - From a24ec410ee7ee81ba74eb7700395a5420a1dd28a Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 17 Aug 2011 16:04:14 -0700 Subject: [PATCH 54/89] cleanup --- fonts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/fonts.js b/fonts.js index a4976b0ac..1860df2e5 100755 --- a/fonts.js +++ b/fonts.js @@ -1967,7 +1967,6 @@ CFF.prototype = { 'sub': [12, 11], 'div': [12, 12], 'pop': [1, 12, 18], -// 'pop': [], 'drop' : [12, 18], 'endchar': 14, 'rmoveto': 21, From 5c7ecbfa28d0dad59441d3774c175ab142a3b04b Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Wed, 17 Aug 2011 20:21:54 -0500 Subject: [PATCH 55/89] Basic annotation link support --- pdf.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ web/viewer.js | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/pdf.js b/pdf.js index 79ae776f6..46eb202ff 100644 --- a/pdf.js +++ b/pdf.js @@ -3154,6 +3154,9 @@ var Page = (function() { return shadow(this, 'mediaBox', ((IsArray(obj) && obj.length == 4) ? obj : null)); }, + get annotations() { + return shadow(this, 'annotations', this.inheritPageProp('Annots')); + }, get width() { var mediaBox = this.mediaBox; var rotate = this.rotate; @@ -3266,6 +3269,56 @@ var Page = (function() { rotate: this.rotate }); gfx.execute(this.code, xref, resources); gfx.endDrawing(); + }, + rotatePoint: function (x, y) { + var rotate = this.rotate; + switch (rotate) { + default: + case 0: + return {x: x, y: this.height - y}; + case 180: + return {x: this.width - x, y: y}; + case 90: + return {x: this.width - y, y: this.height - x}; + case 270: + return {x: y, y: x}; + } + }, + getLinks: function(scale) { + var xref = this.xref; + var annotations = xref.fetchIfRef(this.annotations); + var i, n = annotations.length; + var links = []; + for (i = 0; i < n; ++i) { + var annotation = xref.fetch(annotations[i]); + if (!IsDict(annotation, 'Annot')) + continue; + var subtype = annotation.get("Subtype"); + if (!IsName(subtype) || subtype.name != 'Link') + continue; + var rect = annotation.get("Rect"); + var topLeftCorner = this.rotatePoint(rect[0], rect[1]); + var bottomRightCorner = this.rotatePoint(rect[2], rect[3]); + + var link = {}; + link.x = scale * Math.min(topLeftCorner.x, bottomRightCorner.x); + link.y = scale * Math.min(topLeftCorner.y, bottomRightCorner.y); + link.width = scale * Math.abs(topLeftCorner.x - bottomRightCorner.x); + link.height = scale * Math.abs(topLeftCorner.y - bottomRightCorner.y); + var a = annotation.get("A"); + if (a) { + switch(a.get("S").name) { + case "URI": + link.url = a.get("URI"); + break; + default: + TODO("other link types"); + break; + } + } + links.push(link); + } + return links; } }; diff --git a/web/viewer.js b/web/viewer.js index 0307e7ea3..e4db38bc8 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -165,6 +165,38 @@ var PageView = function(container, content, id, width, height, stats) { div.removeChild(div.lastChild); }; + function setupLinks(canvas, content, scale) { + var links = content.getLinks(scale); + var currentLink = null; + if (links.length > 0) + { + canvas.addEventListener('mousemove', function(e) { + var x = e.pageX; + var y = e.pageY; + for (var p = canvas; p; p = p.offsetParent) { + x -= p.offsetLeft; + y -= p.offsetTop; + } + for (var i = 0; i < links.length; i++) { + var link = links[i]; + if (!link.url) + continue; + if (link.x <= x && link.y <= y && + x < link.x + link.width && y < link.y + link.height) { + currentLink = link; + canvas.style.cursor = 'pointer'; + return; + } + } + currentLink = null; + canvas.style.cursor = 'default'; + }, false); + canvas.addEventListener('mousedown', function(e) { + window.location.href = currentLink.url; + }, false); + } + } + this.draw = function() { if (div.hasChildNodes()) { this.updateStats(); @@ -188,6 +220,8 @@ var PageView = function(container, content, id, width, height, stats) { stats.begin = Date.now(); this.content.startRendering(ctx, this.updateStats); + setupLinks(canvas, this.content, this.scale); + return true; }; From b7ac83da32110de6ea6af123a70a8a25362dec83 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 18 Aug 2011 07:43:45 -0500 Subject: [PATCH 56/89] LZW reducing memory usage --- pdf.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 2afed5f6b..eab5a35e2 100644 --- a/pdf.js +++ b/pdf.js @@ -1990,7 +1990,7 @@ var LZWStream = (function() { this.cachedData = 0; this.bitsCached = 0; - var maxLzwDictionarySize = 4097; + var maxLzwDictionarySize = 4096; var lzwState = { earlyChange: earlyChange, codeLength: 9, @@ -2036,6 +2036,9 @@ var LZWStream = (function() { var i, j, q; var lzwState = this.lzwState; + if (!lzwState) + return; // eof was found + var earlyChange = lzwState.earlyChange; var nextCode = lzwState.nextCode; var dictionaryValues = lzwState.dictionaryValues; @@ -2073,6 +2076,7 @@ var LZWStream = (function() { continue; } else { this.eof = true; + delete this.lzwState; break; } From 60127b08305ae26afb23b389b64b5820b26f4fd9 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 18 Aug 2011 11:28:37 -0700 Subject: [PATCH 57/89] increased size of loaded font --- fonts.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 1860df2e5..2c737b050 100755 --- a/fonts.js +++ b/fonts.js @@ -975,7 +975,7 @@ var Font = (function Font() { // Create a new file to hold the new version of our truetype with a new // header and new offsets - var ttf = new Uint8Array(kMaxFontFileSize); + var ttf = new Uint8Array(kMaxFontFileSize*3); // The offsets object holds at the same time a representation of where // to write the table entry information about a table and another offset @@ -1102,6 +1102,8 @@ var Font = (function Font() { for (var i = 0; i < tables.length; i++) { var table = tables[i]; var tableData = table.data; + if (tableData.length + offsets.currentOffset > ttf.length) + log('blah'); ttf.set(tableData, offsets.currentOffset); offsets.currentOffset += tableData.length; From bf9092b6609043e567cd06b8ec201a3f3934cc1b Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 10:25:02 -0700 Subject: [PATCH 58/89] working on subroutines --- fonts.js | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/fonts.js b/fonts.js index 66d8428e2..e38edef8d 100755 --- a/fonts.js +++ b/fonts.js @@ -1598,6 +1598,17 @@ 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')) + ++i; + + var t = ''; + while(i < count && !(eexecStr[i] == ' ' || eexecStr[i] == '\n')) + t += eexecStr[i++]; + + return t; + } + var c = eexecStr[i]; if ((glyphsSection || subrsSection) && c == 'R') { @@ -1627,7 +1638,25 @@ var Type1Parser = function() { glyphsSection = true; break; case '/Subrs': - subrsSection = true; + ++i; + var num = parseInt(getToken()); + getToken(); // read in 'array' + for (var j = 0; j < num; ++j) { + var t = getToken(); // read in 'dup' + if (t == 'ND') + break; + var index = parseInt(getToken()); + if (index > j) + j = index; + var length = parseInt(getToken()); + getToken(); // read in 'RD' + var data = eexec.slice(i + 1, i + 1 + length); + var encoded = decrypt(data, kCharStringsEncryptionKey, 4); + var str = decodeCharString(encoded); + i = i + 1 + length; + getToken(); //read in 'NP' + program.subrs[index] = str.charstring; + } break; case '/BlueValues': case '/OtherBlues': @@ -1909,8 +1938,13 @@ CFF.prototype = { for (var i = 0; i < bias; i++) type2Subrs.push([0x0B]); - for (var i = 0; i < count; i++) - type2Subrs.push(this.flattenCharstring(type1Subrs[i], this.commandsMap)); + for (var i = 0; i < count; i++) { + var subr = type1Subrs[i]; + if (!subr) + subr = [0x0B]; + + type2Subrs.push(this.flattenCharstring(subr, this.commandsMap)); + } return type2Subrs; }, From 5b359f1c1eef9e8a102f9c93b1f27ec046567516 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 14:49:12 -0700 Subject: [PATCH 59/89] still mucking with subroutines --- fonts.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fonts.js b/fonts.js index e38edef8d..356d7f948 100755 --- a/fonts.js +++ b/fonts.js @@ -1469,7 +1469,7 @@ var Type1Parser = function() { var value = ''; var count = array.length; for (var i = 0; i < count; i++) { - value = parseInt(array[i]); + value = array[i]; if (value < 32) { var command = null; @@ -1479,8 +1479,8 @@ var Type1Parser = function() { // TODO Clean this code if (escape == 16) { var index = charstring.pop(); - var argc = charstring.pop(); - var data = charstring.pop(); +// var argc = charstring.pop(); +// var data = charstring.pop(); // If the flex mechanishm is not used in a font program, Adobe // state that that entries 0, 1 and 2 can simply be replace by @@ -1492,8 +1492,8 @@ var Type1Parser = function() { // This is the same things about hint replacement, if it is not used // entry 3 can be replaced by {3} if (index == 3) { - charstring.push(3); - i++; +// charstring.push(3); +// i++; continue; } } @@ -1532,11 +1532,11 @@ var Type1Parser = function() { value = command; } else if (value <= 246) { - value = parseInt(value) - 139; + value = value - 139; } else if (value <= 250) { - value = ((value - 247) * 256) + parseInt(array[++i]) + 108; + value = ((value - 247) * 256) + array[++i] + 108; } else if (value <= 254) { - value = -((value - 251) * 256) - parseInt(array[++i]) - 108; + value = -((value - 251) * 256) - array[++i] - 108; } else { value = (array[++i] & 0xff) << 24 | (array[++i] & 0xff) << 16 | (array[++i] & 0xff) << 8 | (array[++i] & 0xff) << 0; From 7d5dcb5d43936f7d4144b99c3fa4e64743990f3d Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 21 Jul 2011 11:51:39 -0700 Subject: [PATCH 60/89] added ability to write data to file --- fonts.js | 8 ++++++++ utils/fonts_utils.js | 4 +--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fonts.js b/fonts.js index 356d7f948..7dfa6ead7 100755 --- a/fonts.js +++ b/fonts.js @@ -446,6 +446,14 @@ var Font = (function Font() { break; } + var fileArr = []; + file.reset(); + for (var i = 0, ii = file.length; i < ii; ++i) + fileArr.push(file[i]); + + writeToFile(data, '/tmp/' + name + '_orig'); + writeToFile(fileArr, '/tmp/' + name + '_new'); + this.data = data; this.type = properties.type; this.textMatrix = properties.textMatrix; diff --git a/utils/fonts_utils.js b/utils/fonts_utils.js index edfc22186..98ea60757 100644 --- a/utils/fonts_utils.js +++ b/utils/fonts_utils.js @@ -1,8 +1,6 @@ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ -'use strict'; - /** * The Type2 reader code below is only used for debugging purpose since Type2 * is only a CharString format and is never used directly as a Font file. @@ -391,7 +389,7 @@ function writeToFile(aBytes, aFilePath) { var stream = Cc['@mozilla.org/network/file-output-stream;1'] .createInstance(Ci.nsIFileOutputStream); - stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0); + stream.init(file, 0x04 | 0x08 | 0x20, 0666, 0); var bos = Cc['@mozilla.org/binaryoutputstream;1'] .createInstance(Ci.nsIBinaryOutputStream); From 2ad39c20cf1f9fd597fa25e95bffbf5fcab112af Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 21 Jul 2011 15:13:18 -0700 Subject: [PATCH 61/89] added include to fonts_util.js --- web/viewer.html | 1 + 1 file changed, 1 insertion(+) diff --git a/web/viewer.html b/web/viewer.html index 285dadb01..1abded240 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -10,6 +10,7 @@ + From 259f8c731771ab7fef5adfa8a1df76d95ce6d300 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 21 Jul 2011 15:13:49 -0700 Subject: [PATCH 62/89] added include to fonts_util.js --- web/viewer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/viewer.html b/web/viewer.html index 1abded240..5498d8a1c 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -10,7 +10,7 @@ - + From 04b14f7b8a51873583a3b0f305759e26ed0a1640 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 21 Jul 2011 15:18:00 -0700 Subject: [PATCH 63/89] fixed reading from sream --- fonts.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index 7dfa6ead7..e2f278523 100755 --- a/fonts.js +++ b/fonts.js @@ -448,11 +448,12 @@ var Font = (function Font() { var fileArr = []; file.reset(); + file = file.getBytes(); for (var i = 0, ii = file.length; i < ii; ++i) fileArr.push(file[i]); - writeToFile(data, '/tmp/' + name + '_orig'); - writeToFile(fileArr, '/tmp/' + name + '_new'); + writeToFile(data, '/tmp/' + name + '_new'); + writeToFile(fileArr, '/tmp/' + name + '_orig'); this.data = data; this.type = properties.type; From 8acc31ec83f424fafc54133abfa94c8867fbb02c Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 16:14:29 -0700 Subject: [PATCH 64/89] Still testing type1 charstring conversion --- fonts.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fonts.js b/fonts.js index e2f278523..77183a602 100755 --- a/fonts.js +++ b/fonts.js @@ -1488,8 +1488,9 @@ var Type1Parser = function() { // TODO Clean this code if (escape == 16) { var index = charstring.pop(); -// var argc = charstring.pop(); -// var data = charstring.pop(); + var argc = charstring.pop(); + for (var j = 0; j < argc; j++) + var data = charstring.pop(); // If the flex mechanishm is not used in a font program, Adobe // state that that entries 0, 1 and 2 can simply be replace by @@ -1501,8 +1502,8 @@ var Type1Parser = function() { // This is the same things about hint replacement, if it is not used // entry 3 can be replaced by {3} if (index == 3) { -// charstring.push(3); -// i++; + charstring.push(3); + i++; continue; } } From 6fc25241cceaea916225a6ce5ce822a62af138ea Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Wed, 17 Aug 2011 01:33:00 +0300 Subject: [PATCH 65/89] Report results properly to test.py from driver.js. If the PDFDoc creation failed in driver.js then that was not informed back to test.py. This lead to State.remaining being off by one. And that did not let the test to end as expected. Instead the test hung indefinitely. This change now reveals TEST-UNEXPECTED-FAIL which was hidden previously. --- test/driver.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/test/driver.js b/test/driver.js index 92fc00af1..716046c4b 100644 --- a/test/driver.js +++ b/test/driver.js @@ -80,10 +80,19 @@ function nextTask() { } function isLastPage(task) { - return (!task.pdfDoc || (task.pageNum > task.pdfDoc.numPages)); + return (task.pageNum > task.pdfDoc.numPages); } function nextPage(task, loadError) { + var failure = loadError || ''; + + if (!task.pdfDoc) { + sendTaskResult(canvas.toDataURL('image/png'), task, failure); + log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); + ++currentTaskIdx, nextTask(); + return; + } + if (isLastPage(task)) { if (++task.round < task.rounds) { log(' Round ' + (1 + task.round) + '\n'); @@ -94,15 +103,13 @@ function nextPage(task, loadError) { } } - var failure = loadError || ''; - - var ctx = null; var page = null; + if (!failure) { try { log(' loading page ' + task.pageNum + '/' + task.pdfDoc.numPages + '... '); - ctx = canvas.getContext('2d'); + var ctx = canvas.getContext('2d'); page = task.pdfDoc.getPage(task.pageNum); var pdfToCssUnitsCoef = 96.0 / 72.0; @@ -179,7 +186,7 @@ var inFlightRequests = 0; function sendTaskResult(snapshot, task, failure) { var result = { browser: browser, id: task.id, - numPages: task.pdfDoc.numPages, + numPages: task.pdfDoc ? task.pdfDoc.numPages : 0, failure: failure, file: task.file, round: task.round, From b18b63a9a963dd5bb36547b56007f1047ddeef09 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 16:47:48 -0700 Subject: [PATCH 66/89] implemented curve2, partial fix for #325 --- pdf.js | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/pdf.js b/pdf.js index 79ae776f6..081abfd20 100644 --- a/pdf.js +++ b/pdf.js @@ -4,7 +4,7 @@ 'use strict'; var ERRORS = 0, WARNINGS = 1, TODOS = 5; -var verbosity = WARNINGS; +var verbosity = TODOS; function log(msg) { if (console && console.log) @@ -4137,6 +4137,9 @@ var CanvasExtraState = (function() { this.charSpacing = 0; this.wordSpacing = 0; this.textHScale = 1; + // Path variables + this.pathX = 0; + this.pathY = 0; // Color spaces this.fillColorSpaceObj = null; this.strokeColorSpaceObj = null; @@ -4276,18 +4279,39 @@ var CanvasGraphics = (function() { // Path moveTo: function(x, y) { this.ctx.moveTo(x, y); + + var current = this.current; + current.pathX = x; + current.pathY = y; }, lineTo: function(x, y) { this.ctx.lineTo(x, y); + + var current = this.current; + current.pathX = x; + current.pathY = y; }, curveTo: function(x1, y1, x2, y2, x3, y3) { this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + + var current = this.current; + current.pathX = x3; + current.pathY = y3; }, curveTo2: function(x2, y2, x3, y3) { - TODO("'v' operator: need current point in gfx context"); + var current = this.current; + this.ctx.bezierCurveTo(current.pathX, current.pathY, x2, y2, x3, y3); +// TODO("'v' operator: need current point in gfx context"); + + current.pathX = x3; + current.pathY = y3; }, curveTo3: function(x1, y1, x3, y3) { this.curveTo(x1, y1, x3, y3, x3, y3); + + var current = this.current; + current.pathX = x3; + current.pathY = y3; }, closePath: function() { this.ctx.closePath(); From ac1000cc86d41e6bf0bf027e56550744c47b4bc5 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 16:49:26 -0700 Subject: [PATCH 67/89] cleanup --- pdf.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pdf.js b/pdf.js index 081abfd20..d9c1007bb 100644 --- a/pdf.js +++ b/pdf.js @@ -4,7 +4,7 @@ 'use strict'; var ERRORS = 0, WARNINGS = 1, TODOS = 5; -var verbosity = TODOS; +var verbosity = WARNINGS; function log(msg) { if (console && console.log) @@ -4301,7 +4301,6 @@ var CanvasGraphics = (function() { curveTo2: function(x2, y2, x3, y3) { var current = this.current; this.ctx.bezierCurveTo(current.pathX, current.pathY, x2, y2, x3, y3); -// TODO("'v' operator: need current point in gfx context"); current.pathX = x3; current.pathY = y3; From a48a74862ac4bc2e620bb931ca1885dab25c17b4 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 16 Aug 2011 18:15:20 -0700 Subject: [PATCH 68/89] added stiched functions --- pdf.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/pdf.js b/pdf.js index d9c1007bb..45f5484f6 100644 --- a/pdf.js +++ b/pdf.js @@ -5727,7 +5727,7 @@ var PDFFunction = (function() { if (!typeFn) error('Unknown type of function'); - typeFn.call(this, fn, dict); + typeFn.call(this, fn, dict, xref); }; constructor.prototype = { @@ -5872,9 +5872,58 @@ var PDFFunction = (function() { return out; } }, - constructStiched: function() { - TODO('unhandled type of function'); - this.func = function() { return [255, 105, 180]; } + constructStiched: function(fn, dict, xref) { + var domain = dict.get('Domain'); + var range = dict.get('Range'); + + if (!domain) + error('No domain'); + + var inputSize = domain.length / 2; + if (inputSize != 1) + error('Bad domain for stiched function'); + + var fnRefs = dict.get('Functions'); + var fns = []; + for (var i = 0, ii = fnRefs.length; i < ii; ++i) + fns.push(new PDFFunction(xref, xref.fetchIfRef(fnRefs[i]))); + + var bounds = dict.get('Bounds'); + var encode = dict.get('Encode'); + + this.func = function(args) { + var clip = function(v, min, max) { + if (v > max) + v = max; + else if (v < min) + v = min; + return v; + } + + // clip to domain + var v = clip(args[0], domain[0], domain[1]); + // calulate which bound the value is in + for (var i = 0, ii = bounds.length; i < ii; ++i) { + if (v < bounds[i]) + break; + } + + // encode value into domain of function + var dmin = domain[0]; + if (i > 0) + dmin = bounds[i - 1]; + var dmax = domain[1]; + if (i < bounds.length) + dmax = bounds[i]; + + var rmin = encode[2 * i]; + var rmax = encode[2 * i + 1]; + + var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); + + // call the appropropriate function + return fns[i].func([v2]); + } }, constructPostScript: function() { TODO('unhandled type of function'); From d24a00452ea43a33ddd8d7507d8d28b53bee5415 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 17 Aug 2011 09:22:54 -0700 Subject: [PATCH 69/89] combined pathX/Y with x/y and wrote setCurrentPoint function --- pdf.js | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/pdf.js b/pdf.js index 45f5484f6..2afed5f6b 100644 --- a/pdf.js +++ b/pdf.js @@ -4137,9 +4137,6 @@ var CanvasExtraState = (function() { this.charSpacing = 0; this.wordSpacing = 0; this.textHScale = 1; - // Path variables - this.pathX = 0; - this.pathY = 0; // Color spaces this.fillColorSpaceObj = null; this.strokeColorSpaceObj = null; @@ -4152,7 +4149,11 @@ var CanvasExtraState = (function() { constructor.prototype = { clone: function canvasextra_clone() { return Object.create(this); - } + }, + setCurrentPoint: function canvasextra_setCurrentPoint(x, y) { + this.x = x; + this.y = y; + }, }; return constructor; })(); @@ -4279,38 +4280,24 @@ var CanvasGraphics = (function() { // Path moveTo: function(x, y) { this.ctx.moveTo(x, y); - - var current = this.current; - current.pathX = x; - current.pathY = y; + this.current.setCurrentPoint(x, y); }, lineTo: function(x, y) { this.ctx.lineTo(x, y); - - var current = this.current; - current.pathX = x; - current.pathY = y; + this.current.setCurrentPoint(x, y); }, curveTo: function(x1, y1, x2, y2, x3, y3) { this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); - - var current = this.current; - current.pathX = x3; - current.pathY = y3; + this.current.setCurrentPoint(x3, y3); }, curveTo2: function(x2, y2, x3, y3) { var current = this.current; - this.ctx.bezierCurveTo(current.pathX, current.pathY, x2, y2, x3, y3); - - current.pathX = x3; - current.pathY = y3; + this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3); + current.setCurrentPoint(x3, y3); }, curveTo3: function(x1, y1, x3, y3) { this.curveTo(x1, y1, x3, y3, x3, y3); - - var current = this.current; - current.pathX = x3; - current.pathY = y3; + this.current.setCurrentPoint(x3, y3); }, closePath: function() { this.ctx.closePath(); From c9f9b8b1935128d9e159db155f4ac7361c7e5c6b Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 17 Aug 2011 15:55:09 -0700 Subject: [PATCH 70/89] working font --- fonts.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 77183a602..a55fc63a2 100755 --- a/fonts.js +++ b/fonts.js @@ -1490,7 +1490,7 @@ var Type1Parser = function() { var index = charstring.pop(); var argc = charstring.pop(); for (var j = 0; j < argc; j++) - var data = charstring.pop(); + charstring.push('drop'); // If the flex mechanishm is not used in a font program, Adobe // state that that entries 0, 1 and 2 can simply be replace by @@ -1976,6 +1976,8 @@ CFF.prototype = { 'sub': [12, 11], 'div': [12, 12], 'pop': [1, 12, 18], +// 'pop': [], + 'drop' : [12, 18], 'endchar': 14, 'rmoveto': 21, 'hmoveto': 22, From 32bde231570f9c12bcaafa82f58817ae1be1e0e6 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 17 Aug 2011 16:04:14 -0700 Subject: [PATCH 71/89] cleanup --- fonts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/fonts.js b/fonts.js index a55fc63a2..eba88c6bf 100755 --- a/fonts.js +++ b/fonts.js @@ -1976,7 +1976,6 @@ CFF.prototype = { 'sub': [12, 11], 'div': [12, 12], 'pop': [1, 12, 18], -// 'pop': [], 'drop' : [12, 18], 'endchar': 14, 'rmoveto': 21, From fd0423b5c79c359b69f72175f77651a92d18489f Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 18 Aug 2011 19:55:14 -0500 Subject: [PATCH 72/89] image load pending --- pdf.js | 92 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 19 deletions(-) diff --git a/pdf.js b/pdf.js index eab5a35e2..34af6521f 100644 --- a/pdf.js +++ b/pdf.js @@ -806,6 +806,11 @@ var JpegStream = (function() { // create DOM image var img = new Image(); + img.onload = (function() { + this.loaded = true; + if (this.onLoad) + this.onLoad(); + }).bind(this); img.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes)); this.domImage = img; } @@ -822,6 +827,44 @@ var JpegStream = (function() { return constructor; })(); +// Simple object to track the loading images +// Initialy for every that is in loading call imageLoading() +// and, when images onload is fired, call imageLoaded() +// When all images are loaded, the onLoad event is fired. +var ImagesLoader = (function() { + function constructor() { + this.loading = 0; + } + + constructor.prototype = { + imageLoading: function() { + ++this.loading; + }, + + imageLoaded: function() { + if (--this.loading == 0 && this.onLoad) { + this.onLoad(); + delete this.onLoad; + } + }, + + bind: function(jpegStream) { + if (jpegStream.loaded) + return; + this.imageLoading(); + jpegStream.onLoad = this.imageLoaded.bind(this); + }, + + notifyOnLoad: function(callback) { + if (this.loading == 0) + callback(); + this.onLoad = callback; + } + }; + + return constructor; +})(); + var DecryptStream = (function() { function constructor(str, decrypt) { this.str = str; @@ -3127,6 +3170,7 @@ var Page = (function() { create: Date.now(), compile: 0.0, fonts: 0.0, + images: 0.0, render: 0.0 }; this.xref = xref; @@ -3201,25 +3245,33 @@ var Page = (function() { var gfx = new CanvasGraphics(canvasCtx); var fonts = []; + var images = new ImagesLoader() - this.compile(gfx, fonts); + this.compile(gfx, fonts, images); stats.compile = Date.now(); + var displayContinuation = function() { + // Always defer call to display() to work around bug in + // Firefox error reporting from XHR callbacks. + setTimeout(function() { + var exc = null; + try { + self.display(gfx); + stats.render = Date.now(); + } catch (e) { + exc = e.toString(); + } + continuation(exc); + }); + }; + var fontObjs = FontLoader.bind( fonts, function() { stats.fonts = Date.now(); - // Always defer call to display() to work around bug in - // Firefox error reporting from XHR callbacks. - setTimeout(function() { - var exc = null; - try { - self.display(gfx); - stats.render = Date.now(); - } catch (e) { - exc = e.toString(); - } - continuation(exc); + images.notifyOnLoad(function() { + stats.images = Date.now(); + displayContinuation(); }); }); @@ -3228,7 +3280,7 @@ var Page = (function() { }, - compile: function(gfx, fonts) { + compile: function(gfx, fonts, images) { if (this.code) { // content was compiled return; @@ -3240,14 +3292,14 @@ var Page = (function() { if (!IsArray(this.content)) { // content is not an array, shortcut content = xref.fetchIfRef(this.content); - this.code = gfx.compile(content, xref, resources, fonts); + this.code = gfx.compile(content, xref, resources, fonts, images); return; } // the content is an array, compiling all items var i, n = this.content.length, compiledItems = []; for (i = 0; i < n; ++i) { content = xref.fetchIfRef(this.content[i]); - compiledItems.push(gfx.compile(content, xref, resources, fonts)); + compiledItems.push(gfx.compile(content, xref, resources, fonts, images)); } // creating the function that executes all compiled items this.code = function(gfx) { @@ -3787,7 +3839,7 @@ var PartialEvaluator = (function() { }; constructor.prototype = { - eval: function(stream, xref, resources, fonts) { + eval: function(stream, xref, resources, fonts, images) { resources = xref.fetchIfRef(resources) || new Dict(); var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict(); var patterns = xref.fetchIfRef(resources.get('Pattern')) || new Dict(); @@ -3832,8 +3884,10 @@ var PartialEvaluator = (function() { if ('Form' == type.name) { args[0].code = this.eval(xobj, xref, xobj.dict.get('Resources'), - fonts); + fonts, images); } + if (xobj instanceof JpegStream) + images.bind(xobj); // monitoring image load } } else if (cmd == 'Tf') { // eagerly collect all fonts var fontRes = resources.get('Font'); @@ -4209,9 +4263,9 @@ var CanvasGraphics = (function() { this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height); }, - compile: function(stream, xref, resources, fonts) { + compile: function(stream, xref, resources, fonts, images) { var pe = new PartialEvaluator(); - return pe.eval(stream, xref, resources, fonts); + return pe.eval(stream, xref, resources, fonts, images); }, execute: function(code, xref, resources) { From b1aab2f730a430e79c257250f3593b0994efd08c Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 18 Aug 2011 20:17:54 -0700 Subject: [PATCH 73/89] Fixed fonts to use strings instead of Uint8Arrays --- fonts.js | 94 +++++++++++++++++++++++--------------------------------- 1 file changed, 39 insertions(+), 55 deletions(-) diff --git a/fonts.js b/fonts.js index 2c737b050..346b547ea 100755 --- a/fonts.js +++ b/fonts.js @@ -4,11 +4,6 @@ 'use strict'; var isWorker = (typeof window == 'undefined'); -/** - * Maximum file size of the font. - */ -var kMaxFontFileSize = 300000; - /** * Maximum time to wait for a font to be loaded by font-face rules. */ @@ -466,6 +461,14 @@ var Font = (function Font() { return array; }; + + function arrayToString(arr) { + var str = ""; + for (var i = 0; i < arr.length; ++i) + str += String.fromCharCode(arr[i]); + + return str; + }; function int16(bytes) { return (bytes[0] << 8) + (bytes[1] & 0xff); @@ -502,7 +505,7 @@ var Font = (function Font() { String.fromCharCode(value & 0xff); }; - function createOpenTypeHeader(sfnt, file, offsets, numTables) { + function createOpenTypeHeader(sfnt, file, numTables) { // sfnt version (4 bytes) var header = sfnt; @@ -520,14 +523,13 @@ var Font = (function Font() { // rangeShift (2 bytes) header += string16(numTables * 16 - searchRange); - file.set(stringToArray(header), offsets.currentOffset); - offsets.currentOffset += header.length; - offsets.virtualOffset += header.length; + file.file += header; + file.virtualOffset += header.length; }; - function createTableEntry(file, offsets, tag, data) { + function createTableEntry(file, tag, data) { // offset - var offset = offsets.virtualOffset; + var offset = file.virtualOffset; // length var length = data.length; @@ -536,8 +538,8 @@ var Font = (function Font() { while (data.length & 3) data.push(0x00); - while (offsets.virtualOffset & 3) - offsets.virtualOffset++; + while (file.virtualOffset & 3) + file.virtualOffset++; // checksum var checksum = 0, n = data.length; @@ -547,11 +549,8 @@ var Font = (function Font() { var tableEntry = (tag + string32(checksum) + string32(offset) + string32(length)); - tableEntry = stringToArray(tableEntry); - file.set(tableEntry, offsets.currentOffset); - - offsets.currentOffset += tableEntry.length; - offsets.virtualOffset += data.length; + file.file += tableEntry; + file.virtualOffset += data.length; }; function getRanges(glyphs) { @@ -973,23 +972,19 @@ var Font = (function Font() { tables.push(table); } - // Create a new file to hold the new version of our truetype with a new - // header and new offsets - var ttf = new Uint8Array(kMaxFontFileSize*3); - - // The offsets object holds at the same time a representation of where - // to write the table entry information about a table and another offset - // representing the offset where to put the actual data of a particular - // table var numTables = header.numTables + requiredTables.length; - var offsets = { - currentOffset: 0, + + // header and new offsets. Table entry information is appended to the + // end of file. The virtualOffset represents where to put the actual + // data of a particular table; + var ttf = { + file: "", virtualOffset: numTables * (4 * 4) - }; + } // The new numbers of tables will be the last one plus the num // of missing tables - createOpenTypeHeader('\x00\x01\x00\x00', ttf, offsets, numTables); + createOpenTypeHeader('\x00\x01\x00\x00', ttf, numTables); if (requiredTables.indexOf('OS/2') != -1) { tables.push({ @@ -1095,28 +1090,21 @@ var Font = (function Font() { var tableData = table.data; for (var j = 0; j < tableData.length; j++) data.push(tableData[j]); - createTableEntry(ttf, offsets, table.tag, data); + createTableEntry(ttf, table.tag, data); } // Add the table datas for (var i = 0; i < tables.length; i++) { var table = tables[i]; var tableData = table.data; - if (tableData.length + offsets.currentOffset > ttf.length) - log('blah'); - ttf.set(tableData, offsets.currentOffset); - offsets.currentOffset += tableData.length; + ttf.file += arrayToString(tableData); // 4-byte aligned data - while (offsets.currentOffset & 3) - offsets.currentOffset++; + while (ttf.file.length & 3) + ttf.file += String.fromCharCode(0); } - var fontData = []; - for (var i = 0; i < offsets.currentOffset; i++) - fontData.push(ttf[i]); - - return fontData; + return stringToArray(ttf.file); }, convert: function font_convert(fontName, font, properties) { @@ -1133,13 +1121,13 @@ var Font = (function Font() { // representing the offset where to draw the actual data of a particular // table var kRequiredTablesCount = 9; - var offsets = { - currentOffset: 0, - virtualOffset: 9 * (4 * 4) - }; - var otf = new Uint8Array(kMaxFontFileSize); - createOpenTypeHeader('\x4F\x54\x54\x4F', otf, offsets, 9); + var otf = { + file: "", + virtualOffset: 9 * (4 * 4) + } + + createOpenTypeHeader('\x4F\x54\x54\x4F', otf, 9); var charstrings = font.charstrings; properties.fixedPitch = isFixedPitch(charstrings); @@ -1223,18 +1211,14 @@ var Font = (function Font() { }; for (var field in fields) - createTableEntry(otf, offsets, field, fields[field]); + createTableEntry(otf, field, fields[field]); for (var field in fields) { var table = fields[field]; - otf.set(table, offsets.currentOffset); - offsets.currentOffset += table.length; + otf.file += arrayToString(table); } - var fontData = []; - for (var i = 0; i < offsets.currentOffset; i++) - fontData.push(otf[i]); - return fontData; + return stringToArray(otf.file); }, bindWorker: function font_bindWorker(data) { From 085f8dc1c917a9489e078947c25d787870d6b418 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 18 Aug 2011 20:40:16 -0700 Subject: [PATCH 74/89] cleanup --- fonts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index 346b547ea..ce49a82b9 100755 --- a/fonts.js +++ b/fonts.js @@ -980,7 +980,7 @@ var Font = (function Font() { var ttf = { file: "", virtualOffset: numTables * (4 * 4) - } + }; // The new numbers of tables will be the last one plus the num // of missing tables @@ -1125,7 +1125,7 @@ var Font = (function Font() { var otf = { file: "", virtualOffset: 9 * (4 * 4) - } + }; createOpenTypeHeader('\x4F\x54\x54\x4F', otf, 9); From c2eaa55cd97ee64451dea80472c4d16b1aa1a390 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 18 Aug 2011 22:48:07 -0500 Subject: [PATCH 75/89] Move scale out of pdf.js --- pdf.js | 10 +++++----- web/viewer.js | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pdf.js b/pdf.js index 79a9bba77..63aefcd32 100644 --- a/pdf.js +++ b/pdf.js @@ -3340,7 +3340,7 @@ var Page = (function() { return {x: y, y: x}; } }, - getLinks: function(scale) { + getLinks: function() { var xref = this.xref; var annotations = xref.fetchIfRef(this.annotations); var i, n = annotations.length; @@ -3357,10 +3357,10 @@ var Page = (function() { var bottomRightCorner = this.rotatePoint(rect[2], rect[3]); var link = {}; - link.x = scale * Math.min(topLeftCorner.x, bottomRightCorner.x); - link.y = scale * Math.min(topLeftCorner.y, bottomRightCorner.y); - link.width = scale * Math.abs(topLeftCorner.x - bottomRightCorner.x); - link.height = scale * Math.abs(topLeftCorner.y - bottomRightCorner.y); + link.x = Math.min(topLeftCorner.x, bottomRightCorner.x); + link.y = Math.min(topLeftCorner.y, bottomRightCorner.y); + link.width = Math.abs(topLeftCorner.x - bottomRightCorner.x); + link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y); var a = annotation.get("A"); if (a) { switch(a.get("S").name) { diff --git a/web/viewer.js b/web/viewer.js index e4db38bc8..b1e28407f 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -166,7 +166,7 @@ var PageView = function(container, content, id, width, height, stats) { }; function setupLinks(canvas, content, scale) { - var links = content.getLinks(scale); + var links = content.getLinks(); var currentLink = null; if (links.length > 0) { @@ -177,6 +177,8 @@ var PageView = function(container, content, id, width, height, stats) { x -= p.offsetLeft; y -= p.offsetTop; } + x /= scale; + y /= scale; for (var i = 0; i < links.length; i++) { var link = links[i]; if (!link.url) From 1e8090c19d1f885cf7ff93ce5c6bad71f08972ff Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 18 Aug 2011 23:12:10 -0500 Subject: [PATCH 76/89] brace fix --- web/viewer.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index b1e28407f..e501a10b2 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -168,8 +168,7 @@ var PageView = function(container, content, id, width, height, stats) { function setupLinks(canvas, content, scale) { var links = content.getLinks(); var currentLink = null; - if (links.length > 0) - { + if (links.length > 0) { canvas.addEventListener('mousemove', function(e) { var x = e.pageX; var y = e.pageY; From 5f233d7cdede04ad735df9cf6c7c5c9c190ffd10 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 18 Aug 2011 22:05:08 -0700 Subject: [PATCH 77/89] cleanup --- fonts.js | 3 --- utils/fonts_utils.js | 5 ++++- web/viewer.html | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/fonts.js b/fonts.js index 1b2da707a..064459df2 100755 --- a/fonts.js +++ b/fonts.js @@ -447,9 +447,6 @@ var Font = (function Font() { for (var i = 0, ii = file.length; i < ii; ++i) fileArr.push(file[i]); - writeToFile(data, '/tmp/' + name + '_new'); - writeToFile(fileArr, '/tmp/' + name + '_orig'); - this.data = data; this.type = properties.type; this.textMatrix = properties.textMatrix; diff --git a/utils/fonts_utils.js b/utils/fonts_utils.js index 98ea60757..194bf6b55 100644 --- a/utils/fonts_utils.js +++ b/utils/fonts_utils.js @@ -1,6 +1,9 @@ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +'use strict'; + + /** * The Type2 reader code below is only used for debugging purpose since Type2 * is only a CharString format and is never used directly as a Font file. @@ -389,7 +392,7 @@ function writeToFile(aBytes, aFilePath) { var stream = Cc['@mozilla.org/network/file-output-stream;1'] .createInstance(Ci.nsIFileOutputStream); - stream.init(file, 0x04 | 0x08 | 0x20, 0666, 0); + stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0); var bos = Cc['@mozilla.org/binaryoutputstream;1'] .createInstance(Ci.nsIBinaryOutputStream); diff --git a/web/viewer.html b/web/viewer.html index 5498d8a1c..285dadb01 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -10,7 +10,6 @@ - From 0923e940d1e6838b64b532cec01bc9ed03a3e707 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 18 Aug 2011 22:05:54 -0700 Subject: [PATCH 78/89] cleanup --- utils/fonts_utils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/fonts_utils.js b/utils/fonts_utils.js index 194bf6b55..edfc22186 100644 --- a/utils/fonts_utils.js +++ b/utils/fonts_utils.js @@ -3,7 +3,6 @@ 'use strict'; - /** * The Type2 reader code below is only used for debugging purpose since Type2 * is only a CharString format and is never used directly as a Font file. From 5a528944f0e3a58d6ac0c821d31f3e1471a9a463 Mon Sep 17 00:00:00 2001 From: Adil Allawi Date: Fri, 19 Aug 2011 14:04:34 +0100 Subject: [PATCH 79/89] Change the way Type 2 CID fonts are encoded. Move the cmap glyphs above the first 255 unicode values so that fillText does not change them and create an encoding to map characters to the glyphs. --- fonts.js | 68 ++-- pdf.js | 7 +- test/pdfs/complex_ttf_font.pdf | 575 +++++++++++++++++++++++++++++++++ test/test_manifest.json | 5 + 4 files changed, 616 insertions(+), 39 deletions(-) create mode 100644 test/pdfs/complex_ttf_font.pdf diff --git a/fonts.js b/fonts.js index 1860df2e5..1aff9eb0e 100755 --- a/fonts.js +++ b/fonts.js @@ -1032,26 +1032,27 @@ var Font = (function Font() { if (properties.type == 'CIDFontType2') { // Type2 composite fonts map characters directly to glyphs so the cmap // table must be replaced. + // canvas fillText will reencode some characters even if the font has a + // glyph at that position - e.g. newline is converted to a space and U+00AD + // (soft hypen) is not drawn. + // So, offset all the glyphs by 0xFF to avoid these cases and use + // the encoding to map incoming characters to the new glyph positions var glyphs = []; - var charset = properties.charset; - if (!charset.length) { - // Type2 composite fonts map characters directly to glyphs so the cmap - for (var i = 1; i < numGlyphs; i++) { - glyphs.push({ - unicode: i - }); - } - } else { - for (var i = 1; i < charset.length; i++) { - var index = charset.indexOf(i); - if (index == -1) - break; + var encoding = properties.encoding; - glyphs.push({ - unicode: index - }); - } + for (var i = 1; i < numGlyphs; i++) { + glyphs.push({ unicode: i + 0xFF }); + } + + if ('undefined' == typeof(encoding[0])) { + // the font is directly characters to glyphs with no encoding + // so create an identity encoding + for (i = 0; i < numGlyphs; i++) + encoding[i] = i + 0xFF; + } else { + for (var i in encoding) + encoding[i] = encoding[i] + 0xFF; } if (!cmap) { @@ -1274,31 +1275,26 @@ var Font = (function Font() { if (!charsCache) charsCache = this.charsCache = Object.create(null); + // translate the string using the font's encoding + var encoding = this.encoding; + if (!encoding) + return chars; + str = ''; + if (this.compositeFont) { // composite fonts have multi-byte strings convert the string from - // single-byte to multi-byte XXX assuming CIDFonts are two-byte - later - // need to extract the correct byte encoding according to the PDF spec - str = ''; - var multiByteStr = ''; - var length = chars.length; + // single-byte to multi-byte + // XXX assuming CIDFonts are two-byte - later need to extract the + // correct byte encoding according to the PDF spec + var length = chars.length - 1; // looping over two bytes at a time so + // loop should never end on the last byte for (var i = 0; i < length; i++) { - var byte1 = chars.charCodeAt(i++) & 0xFF; - var byte2; - if (i == length) - byte2 = 0; - else - byte2 = chars.charCodeAt(i) & 0xFF; - multiByteStr += String.fromCharCode((byte1 << 8) | byte2); + var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]); + var unicode = encoding[charcode]; + str += String.fromCharCode(unicode); } - str = multiByteStr; } else { - // translate the string using the font's encoding - var encoding = this.encoding; - if (!encoding) - return chars; - - str = ''; for (var i = 0; i < chars.length; ++i) { var charcode = chars.charCodeAt(i); var unicode = encoding[charcode]; diff --git a/pdf.js b/pdf.js index 63aefcd32..f8739aade 100644 --- a/pdf.js +++ b/pdf.js @@ -4028,14 +4028,15 @@ var PartialEvaluator = (function() { if (subType.name == 'CIDFontType2') { var cidToGidMap = descendant.get('CIDToGIDMap'); if (cidToGidMap && IsRef(cidToGidMap)) { - // Extract the charset from the CIDToGIDMap + // Extract the encoding from the CIDToGIDMap var glyphsStream = xref.fetchIfRef(cidToGidMap); var glyphsData = glyphsStream.getBytes(0); - var i = 0; // Glyph ids are big-endian 2-byte values + encodingMap[0] = 0; //set this to 0 to verify the font has an encoding for (var j = 0; j < glyphsData.length; j++) { var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; - charset.push(glyphID); + if (glyphID != 0) + encodingMap[j>>1] = glyphID; } } } diff --git a/test/pdfs/complex_ttf_font.pdf b/test/pdfs/complex_ttf_font.pdf new file mode 100644 index 000000000..284caabe4 --- /dev/null +++ b/test/pdfs/complex_ttf_font.pdf @@ -0,0 +1,575 @@ +%PDF-1.3 +% +1 0 obj +<< +/Parent 2 0 R +/MediaBox [0 0 595 842] +/Resources 3 0 R +/pdftk_PageNum 1 +/Contents 4 0 R +/Type /Page +>> +endobj +2 0 obj +<< +/MediaBox [0 0 612 792] +/Kids [1 0 R] +/Count 1 +/Type /Pages +>> +endobj +4 0 obj +<< +/Length 8531 +>> +stream +q Q q 0 0 595 842 re W n 0 0 0 1 k BT 36 0 0 36 165.615 619.79 Tm /F1.1 1 +Tf [ <033d> -0.2 <0b0b> 0.4 <04a8000301e5> -0.2 <000301b9> 0.2 <033d> -0.2 +<0b61> 0.1 <02250003100e> ] TJ ET BT 36 0 0 36 253.725 619.955 Tm /F1.1 1 +Tf <0d010b61> Tj ET BT 36 0 0 36 268.38 619.79 Tm /F1.1 1 Tf [ <08e7> -0.2 +<04a80003> 0.4 <100c> -0.3 <02be> 0.2 <0003100e> 0.2 <0cb1> -0.2 <033d> -0.2 +<0ccc> 0.4 <00a2000307060225> -0.3 <00a209de> 0.2 <00a200030a2e039d> -0.1 +<0a670003> 0.4 <0a45> -0.1 <0371> -0.1 <02b8> 0.1 <00a200030362> ] TJ ET BT +36 0 0 36 474.69 619.955 Tm /F1.1 1 Tf <0e0f02a4> Tj ET BT 36 0 0 36 494.37 619.79 +Tm /F1.1 1 Tf <04a8> Tj ET BT 36 0 0 36 167.58 568.415 Tm /F1.1 1 Tf [ <033f> +-0.2 <0b0b04a8000301e5> 0.2 <000301ba> 1.2 <033f> -0.2 <0b61> 0.1 <02250003100e> +] TJ ET BT -0.0002 Tc 36 0 0 36 254.25 568.58 Tm /F1.1 1 Tf <0d140b61> Tj +0 Tc ET BT 36 0 0 36 268.02 568.415 Tm /F1.1 1 Tf [ <08ed> -0.4 <04a80003> +0.4 <100c> -0.3 <02be> 0.2 <0003100e> -0.3 <0cba> 0.3 <033f> -0.2 <0ccc00a200030706022500a209df> +0.3 <00a200030a2e039d> -0.1 <0a5e> 1 <00030a45> 0.3 <0371> -0.1 <02ba> 0.1 +<00a200030362> ] TJ ET BT 0.0004 Tc 36 0 0 36 474 568.58 Tm /F1.1 1 Tf <0e0f02a6> +Tj 0 Tc ET BT 36 0 0 36 494.37 568.415 Tm /F1.1 1 Tf <04a8> Tj ET BT 36 0 0 36 161.55 517.055 +Tm /F1.1 1 Tf [ <033d> -0.2 <0b0b04a8000301e5> 0.2 <000301b9> 0.2 <033d> -0.2 +<0b61> 0.1 <0225> -0.3 <0003> 0.4 <100e> ] TJ ET BT 36 0 0 36 249.66 517.22 +Tm /F1.1 1 Tf <0d020b61> Tj ET BT 36 0 0 36 264.315 517.055 Tm /F1.1 1 Tf +[ <08e7> -0.2 <04a80003100c02be> 0.2 <0003100e> -0.3 <0cb1> 0.3 <033d> -0.2 +<0ccc00a200030706022500a209e000a200030a2e039d> -0.1 <0a670003> 0.4 <0a45> +-0.1 <0371> -0.1 <02b8> 0.1 <00a200030362> ] TJ ET BT 36 0 0 36 474.69 517.22 +Tm /F1.1 1 Tf <0e0f02a4> Tj ET BT 36 0 0 36 494.37 517.055 Tm /F1.1 1 Tf <04a8> +Tj ET BT 36 0 0 36 98.88 463.685 Tm /F1.1 1 Tf [ <033d> 0.2 <0b17> -0.2 <04a80003> +0.4 <01e5> -0.2 <000301ba> 1.2 <033f> -0.2 <0b61> 0.1 <02250003100e> ] TJ +ET BT -0.0002 Tc 36 0 0 36 191.955 463.85 Tm /F1.1 1 Tf <0d140b61> Tj 0 Tc +ET BT 36 0 0 36 205.725 463.685 Tm /F1.1 1 Tf [ <08ed> -0.4 <04a8> 0.4 <000303cc02be> +-0.2 <0003100e> 0.2 <0cba033f> 0.2 <0ccc00a20003> ] TJ ET BT 36 0 0 36 309.6 465.695 +Tm /F1.1 1 Tf [ <071e> -0.2 <022500a209df> 0.3 <00a20003> ] TJ ET BT 36 0 0 36 361.68 463.685 +Tm /F1.1 1 Tf [ <020f> -0.2 <039d> 0.3 <0a5e> 1 <0003000300030a4c> 0.2 <0371> +-0.1 <02ba> 0.1 <00a200030362> ] TJ ET BT 0.0004 Tc 36 0 0 36 474 463.85 Tm +/F1.1 1 Tf <0e0f02a6> Tj 0 Tc ET BT 36 0 0 36 494.37 463.685 Tm /F1.1 1 Tf +<04a8> Tj ET BT 36 0 0 36 113.625 409.25 Tm /F1.1 1 Tf <100f> Tj ET BT 0.0001 +Tc 36 0 0 36 125.325 409.775 Tm /F1.1 1 Tf <0d1d0b73> Tj 0 Tc ET BT 36 0 0 36 153.405 409.25 +Tm /F1.1 1 Tf [ <08f3> 0.2 <04a8000303ce02bf0003100e> ] TJ ET BT 36 0 0 36 222.57 409.52 +Tm /F1.1 1 Tf <0d2602a7> Tj ET BT 36 0 0 36 237.69 409.25 Tm /F1.1 1 Tf <0340> +Tj ET BT 36 0 0 36 246.93 410.225 Tm /F1.1 1 Tf <0330> Tj ET BT 36 0 0 36 258.705 410.495 +Tm /F1.1 1 Tf <0dde02a7> Tj ET BT 36 0 0 36 281.07 409.235 Tm /F1.1 1 Tf <00a20003> +Tj ET BT 36 0 0 36 287.295 411.23 Tm /F1.1 1 Tf [ <071e> 0.3 <0225> -0.3 <00a209de> +0.2 <00a20003> ] TJ ET BT 36 0 0 36 339.06 409.235 Tm /F1.1 1 Tf <0a2e03d6> +Tj ET BT -0.0003 Tc 36 0 0 36 357.555 410.21 Tm /F1.1 1 Tf <030e0a71> Tj 0 +Tc ET BT 36 0 0 36 380.415 409.235 Tm /F1.1 1 Tf [ <0003000300030a45> -0.1 +<0363> ] TJ ET BT -0.0006 Tc 36 0 0 36 411.51 409.58 Tm /F1.1 1 Tf <02f7033102a7> +Tj 0 Tc ET BT 36 0 0 36 447.885 409.235 Tm /F1.1 1 Tf <00a200030363> Tj ET +BT 36 0 0 36 464.31 409.82 Tm /F1.1 1 Tf <02fe> Tj ET BT 36 0 0 36 478.74 409.55 +Tm /F1.1 1 Tf <0e0702a7> Tj ET BT 36 0 0 36 494.37 409.235 Tm /F1.1 1 Tf <04a8> +Tj ET BT 36 0 0 36 162.15 348.08 Tm /F1.1 1 Tf [ <000303e6033d> -366 <043e> +365.8 <0b0b> 0.4 <00a4> -0.3 <0003043c> -117.1 <03dc> 117.1 <01e5> 0.2 <0003043c01b9> +-0.2 <033d> 0.2 <03dc> -117.1 <03df> 117.1 <0b61> -58.2 <0439> 58.3 <0225> +-0.3 <0003> -58 <03dc> 58.3 <100e> ] TJ ET BT 36 0 0 36 252.63 348.245 Tm +/F1.1 1 Tf <0d01043d0b61> Tj ET BT 36 0 0 36 265.185 348.08 Tm /F1.1 1 Tf +[ <0410> -175.4 <03e1> 117.1 <08e7> -0.2 <00a4> 0.1 <0003> -58.4 <043e> 58.3 +<100c046c02be> -0.2 <0003> -58.4 <03dc> 58.3 <100e> 0.2 <044e0cb1> -0.2 <033d> +-116.9 <03f2> 117.1 <0ccc04aa000303dc> -117.1 <03dc> 117.1 <07060410022500a203f209de> +-0.2 <04aa0003> -58.4 <043c> 58.3 <0a2e0450> -175.4 <03dc> 175.4 <039d> 58.7 +<043c> -58.3 <0a670003> -117.1 <044f> 117.1 <0a45> -0.1 <043d> -234.2 <043e> +234.2 <0371> 58.2 <046c> -58.3 <03e102b8> 0.1 <04aa0003> -58.4 <043c> 58.3 +<0362> ] TJ ET BT 0.3513 Tc 36 0 0 36 472.05 348.245 Tm /F1.1 1 Tf [ <03e103df> +644 <0e0f> 410 <03e1> 293 <02a4> ] TJ 0 Tc ET BT 36 0 0 36 493.815 348.08 +Tm /F1.1 1 Tf <00a4> Tj ET BT 36 0 0 36 162.15 278.72 Tm /F1.1 1 Tf [ <000303e6033d> +-366 <0411> 365.8 <0b0b> 0.4 <00a4> -0.3 <0003040f> -117.1 <0495> 117.1 <01e5> +0.2 <0003040f01b9> -0.2 <033d> 0.2 <0495> -117.1 <0496> 117.1 <0b61> -58.2 +<040c> 58.3 <0225> -0.3 <0003> -58 <0495> 58.3 <100e> ] TJ ET BT 36 0 0 36 252.63 278.885 +Tm /F1.1 1 Tf <0d01043d0b61> Tj ET BT 36 0 0 36 265.185 278.72 Tm /F1.1 1 +Tf [ <03e0> -175.4 <0497> 117.1 <08e7> -0.2 <00a4> 0.1 <0003> -58.4 <0411> +58.3 <100c043d02be> -0.2 <0003> -58.4 <0495> 58.3 <100e> 0.2 <041f0cb1> -0.2 +<033d> -116.9 <03f2> 117.1 <0ccc04aa00030495> -117.1 <0495> 117.1 <07060410022500a203f209de> +-0.2 <04aa0003> -58.4 <040f> 58.3 <0a2e0421> -175.4 <0495> 175.4 <039d> 58.7 +<043c> -58.3 <0a670003> -117.1 <0420> 117.1 <0a45> -0.1 <0410> -234.2 <0411> +234.2 <0371> 58.2 <043d> -58.3 <049702b8> 0.1 <04aa0003> -58.4 <040f> 58.3 +<0362> ] TJ ET BT 0.3513 Tc 36 0 0 36 472.05 278.885 Tm /F1.1 1 Tf [ <04970496> +644 <0e0f> 410 <0497> 293 <02a4> ] TJ 0 Tc ET BT 36 0 0 36 493.815 278.72 +Tm /F1.1 1 Tf <00a4> Tj ET BT 36 0 0 36 140.535 209.345 Tm /F1.1 1 Tf [ <000303e9033d> +-365.6 <046e> 365.8 <0b0b00a4> 0.1 <0003046b> -117.1 <03dd> 117.1 <01e5> -0.2 +<0003046b01b9> 0.2 <033d> -0.2 <040c> -117.1 <040f> 117.1 <0b61> -58.2 <0468> +58.3 <02250003> -58.4 <040d> 58.3 <100e> ] TJ ET BT 36 0 0 36 231 209.51 Tm +/F1.1 1 Tf [ <0d01> -0.4 <043d0b61> ] TJ ET BT 36 0 0 36 243.57 209.345 Tm +/F1.1 1 Tf [ <0410> -175.4 <0412> 117.1 <08e7> 0.3 <00a4> -0.3 <0003> -58.4 +<046e> 58.3 <100c046c02be> 0.2 <0003> -58.4 <040d> 58.3 <100e> -0.3 <047b0cb1> +0.3 <033d> -117.3 <041f> 117.1 <0ccc04aa000303dc> -117.1 <040c> 117.1 <07060410022500a2041f09de> +0.2 <04aa0003> -58.4 <040f> 58.3 <0a2e043d041e03d6043a0316> 58.4 <046b> -58.3 +<0a5d0003> -117.1 <047c> 117.1 <0a45> -0.1 <043d> -234.2 <043f> 234.2 <0371> +58.2 <046c> -58.3 <03e202b8> 0.1 <04aa0003> -58.4 <046b> 58.3 <0362> ] TJ +ET BT 0.3513 Tc 36 0 0 36 472.05 209.51 Tm /F1.1 1 Tf [ <03e2040f> 644 <0e0f> +410 <0497> 293 <02a4> ] TJ 0 Tc ET BT 36 0 0 36 493.815 209.345 Tm /F1.1 1 +Tf <00a4> Tj ET BT 9 0 0 9 609.45 625.205 Tm /F2.1 1 Tf [ <0031> 0.5 <005200030026> +0.5 <004b> -0.5 <00440051> -0.5 <004a0048> ] TJ ET BT 9 0 0 9 609.45 573.2 +Tm /F2.1 1 Tf [ <0026> 0.5 <004b> -0.5 <00440055> 0.5 <00440046> 0.5 <0057> +-0.3 <0048> 1.5 <0055> 0.5 <00030044004f> -0.5 <0057> -0.3 <0048> 1.5 <0055> +0.5 <0051> -0.5 <00440057> -0.3 <0048> 1.5 <0056> 0.8 <00030014> ] TJ ET BT +9 0 0 9 609.45 521.195 Tm /F2.1 1 Tf [ <0026> 0.5 <004b> -0.5 <00440055> 0.5 +<00440046> 0.5 <0057> -0.3 <0048> 1.5 <0055> 0.5 <00030044004f> -0.5 <0057> +-0.3 <0048> 1.5 <0055> 0.5 <0051> -0.5 <00440057> -0.3 <0048> 1.5 <0056> 0.8 +<00030015> ] TJ ET BT 9 0 0 9 609.45 469.205 Tm /F2.1 1 Tf [ <0029> -0.8 <004c> +0.5 <0051> -0.5 <0044004f> -0.5 <0003003a004c> 0.5 <0047> -0.5 <0048> 1.5 +<00030029> -0.8 <00520055> 0.5 <0050> -0.3 <0056> ] TJ ET BT 9 0 0 9 609.45 406.805 +Tm /F2.1 1 Tf [ <0032> 0.5 <0057> -0.3 <004b> -0.5 <0048> 1.5 <0055> 0.5 <0003003a004c> +0.5 <0047> -0.5 <0048> 1.5 <00030029> -0.8 <00520055> 0.5 <0050> -0.3 <0056> +] TJ ET BT 9 0 0 9 609.45 344.405 Tm /F2.1 1 Tf [ <0031> 0.5 <00520055> 0.5 +<0050> -0.3 <0044004f> -0.5 <00030027> 0.5 <004c> 0.5 <00440046> 0.5 <0055> +0.5 <004c> 0.5 <0057> -0.3 <004c> 0.5 <0046> 0.5 <00030033> 0.2 <00520056> +0.8 <004c> 0.5 <0057> -0.3 <004c> 0.5 <00520051> -0.5 <0056> ] TJ ET BT 9 0 0 9 609.45 282.005 +Tm /F2.1 1 Tf [ <0029> -0.8 <00440055> 0.5 <0057> -0.3 <004b> -0.5 <0048> +1.5 <0055> 0.5 <00030027> 0.5 <004c> 0.5 <00440046> 0.5 <0055> 0.5 <004c> +0.5 <0057> -0.3 <004c> 0.5 <0046> 0.5 <0056> ] TJ ET BT 9 0 0 9 609.45 209.195 +Tm /F2.1 1 Tf [ <0027> 0.5 <004c> 0.5 <00440046> 0.5 <0055> 0.5 <004c> 0.5 +<0057> -0.3 <004c> 0.5 <0046> 0.5 <00030024> 0.5 <004f> -0.5 <0057> -0.3 <0048> +1.5 <0055> 0.5 <0051> -0.5 <00440057> -0.3 <0048> 1.5 <0056> ] TJ ET Q +endstream +endobj +3 0 obj +<< +/Font +<< +/F2.1 5 0 R +/F1.1 6 0 R +>> +/ProcSet [/PDF /Text] +>> +endobj +6 0 obj +<< +/DescendantFonts [7 0 R] +/BaseFont /LSUISA+font0000000013f5eeab +/Subtype /Type0 +/Encoding /Identity-H +/Type /Font +>> +endobj +5 0 obj +<< +/DescendantFonts [8 0 R] +/BaseFont /ZCCVRA+font0000000013f5eeab +/Subtype /Type0 +/Encoding /Identity-H +/Type /Font +>> +endobj +9 0 obj +<< +/Pages 2 0 R +/Type /Catalog +>> +endobj +7 0 obj +<< +/BaseFont /LSUISA+font0000000013f5eeab +/DW 1000 +/CIDSystemInfo +<< +/Supplement 0 +/Ordering (Identity) +/Registry (Adobe) +>> +/Subtype /CIDFontType2 +/FontDescriptor 10 0 R +/W 11 0 R +/CIDToGIDMap 12 0 R +/Type /Font +>> +endobj +10 0 obj +<< +/FontName /LSUISA+font0000000013f5eeab +/StemV 0 +/FontFile2 13 0 R +/Ascent 785 +/Flags 32 +/XHeight 523 +/Descent -662 +/ItalicAngle 0 +/MaxWidth 4959 +/FontBBox [-979 -662 4935 785] +/Type /FontDescriptor +/CapHeight 291 +>> +endobj +13 0 obj +<< +/Length 15672 +/Length1 15672 +>> +stream +true cvt XfpgmLglyf7Lhead6hhea4$hmtx`  %=#,:!!>%(*ys7&'67&'&'6767'"*; )*AH (7 +{8(%C9',/ 3C##)s'&'67&'&'6767h#*: (*@H )8 +{8(%C9',/ 3C##). 2547&'&676'&5&76 M<'+C& / 0/ +1 U +(;#"&#"#"5476326324#"6;'-C+% +!2K"#%%<2)/.#'nGE `7#&5&'&'&7632 +$ + 1; !j'1BP.A#"767676547&'&7676&'&7676"'&'&&632I &ed +>h1,"& / #  ," /L.O +@'1E$'-1  b@ :1dJ)1%#"'&'#"54767654'&63232654'&632&'76J!%?@%C`? f %7/%   *B,0E183\* -49G + V{? +1r1=(-%.2d+3%# '&'#"5474'&632!27654'&6326'76!T쭌O *<] +  +)U>áG&.:2 41MA$I5 -I0<%kI2g,%'GoAL- E?" +)1:%'#"'&'&563267654'&'&632327654'#"&546324#"32 +^YG%_Y +(/NK?*$470>-3I#&',`) +''}sl @WI!m2))L>*8&#f‟F T%6;Oa;d7q1%#"'&54763232654''#"'&>32q xK_m9-- 60Bx ' % *)B8hK/A3GsQ:I>&#Q4M27tzv!(PJ%#3l ,L# b7HPT=?5%#"54767676767654'&54632-3>6EpUT<0+6CmY>12 ! $,)]29(/)$_uLqZ +X4:G,Y.,B'D'(%b) +9d+19%#"'#"547676'&463232545&54632&'76+\S. *@\:1Z +W779#* \,0`Ϸ..+A#DV3)NR +e FA-%Nd +y!%#"547632767654'632tfgV[MX])V #)jD$oI@QIAg(Ea)+? p~gRae7&'67# %&'&'&'&76!27676767654'&632}"H ) +&!q<بbL80/q +:y=H 78( 3D3KV + L(87+6P-j59}72#"546327676u*R4 5.N7{%#"54632765&'&4763+8čk! Z>",7# )&59^+DR%#"''"''&547&'&'&#"#"5463276763263267676&4632&'&#"327676+);t~5)$UV'   5G94 + .##r.k3$rrbI !+'.AHA~$6=D%5   %B7(11q$$sg;Lh ow?K%!"%''&547&'&12#"54632767632367632327654&'674'&#"3276o]}V( ! +)8I( +  %)G=4<-(KGwО2[-%+'Hg_Pk*: F%!&!7"  +/'3` +N;4Zw +yr'4%#&'#"546327&54632'.46324'&#"326 5slOc)v?1DE`@ % F)I54A197P_;=4Za/?2!- >+Hr)6%# '#"546327&546327654'674'&#"326H>2үe\JU)v?1V殲B $ F)Ia,$?37P_;=%"/B75*+#7#"546327654'&74632$dO'( + +c-A7,E!+ Z" + O + 7#"5463276'&'&#"547632+%D0) 2  +@-7 %#M!d7IOT#%#"5463276'&54763NkvK'* + #$u,>7&DY *." %) + 1%'"&#"#"546327676323254'&54632:'u#6TO0(f%_ #  '(MnL(/'7 ('!)f  =%1%#"'#"546327654'&5&6323276&74632%LV)j0   +?$W 0b7, ?OZ|P%,0 c! +\>W#"'#"'#"&#"&'&#"#"546327&7632326#2576763254'&7&7462 7@ ?23EGN !)C(( ##+/u33m0-; >BD B  +):"  +&-s+-<'V-3y$*22@=7ZT- T, $(% +*& R +e+%#2&#"#"546327&'&'&54632 M< =8) 51`76>H7#"&'#"54632767637654'&'&746322'&'&'&>3^,H. 9$z ! +  +X FVe;$5("F(7/W0 > Z! + &)  @uE%'#"546327676254&#"u+8x4iC,"#-/* B(!5N976<61:( T!%2#"'&'&#"#"54632767632FA$ -56#   *K8$#8 +#%2#"'#"5463276'&'&632 htW K70+AQ ]r&H%2#"'!"54632767632R!a^ &K9b7; * %2#"'&'&#"#"5463276763" E + /MK. +(MK977+ ,d6%2#"'#"'#"7#"546327676327676326V> !;8,Ug Dzt> +D= 3+AK9`V)=-37' +8 ( (j 8L1;%2#"'''&547&'#"546327676766763274'&#"676 kP-?'ˆ\B"(,+8>qK77 <  aFBy,T-# 03[ C23+#'%2#"'#"546327&546'4'&#"326TIV)v?1AH6 F)IK8B27O_Bq!v". <,BOY%2#"'%#"54627676'7&54632676327&546'4'&326!4&#"676 w>O+7&& %l$-4@*$<|Su?1A' + @'DuL',_oz{xK3:7'1a2 +R !JƲ/+J\ NSP`Csg* 7'&:]"!/0%2#"'&'#"546327654'&'&5476%67! qc +7C\E:h@V3:p8}K=6<.k6@7HK~\?F`6?<# $P8%2#"'&547!"5463 %$%&#"# 5476732$32B&!L_{{297 YLw1FBcB<=K9,&766:7921[YNx,*4%V.iV1,5>M>&%2#"'#"'&7#"54632767632&'&#"  'Zbˆ`F06 Z K9 ++ 8?M7 DL.%# +{(%2#"'#"'&7#"546327>72'&'&#m Q &M`7fN/5%+5Z K) ! 8[J(s3-( T 3&67676!u%!'+e@49D  (#&'&''&76767&'&54632'4#"6  >!6#>0(># #7#6]  0% #!!#B9!@ + 21&>" ;`M*(4 .*0"WG  #"547>32&#"32C6 +79!& 0PD@+=`J3-'&767&#"#"'&632K799F )L P4D[ + a + 2'&767>2'&7># ;_M 0# ;^N*4 /*VA5.+!W9r &67676&67676b*0%)0% &5oB5BM, '4pA4AN 321&767>#"''&767676767676'&76) .UQ "2 !/  +- 9C1- +3 2'&7> ! 8[J(3-( T 3&67676!u%!'+e@49D2 Z(#"'&''&76767&547632'4#"6 @/2">0A!# #7 5   /&#!! #" 9"> +u 2'&67>" :`L*u5/*3 XGw? #"54767632'&#"3216 +9!& 0#>+ _( I3-l'&767&#"#"'&632K799F V P4DY  a \%#"''&763676767676'&722 !/ + C1/ +\w 22&767>#"''&763676767676'&72( .2 !/ + u.= 8C1/ +\!GO#"&'"'&76767&'&54632#"''&763676767676'&72'4#"6 =!5 5+%8 2 !/ + >0a )%<2C1/ +D +[$1#"''&763676767>'&722'&767>2 !/ +  :* . !1D 20 -> 9G 2'&7> ! 8[J(G3-( Td| 3&67676!u%|!'+e@49D +"*#0&'&''&76767&'&547632'4#"6 + ?'9"90)!# #7#5/ /%!!#"8 "<? 21&767># ;`M ?5/( YG #"547>32'&#"3206 +79!& 0%@+=_( +H1-'&767&#"#"'&632K899F Y O5Dh[   _ + 12'&767>#"''&763676767>'&76) .3 !/ +  /? 8D00 ODL#.'#"5&76767&'&54632#"''&763676767>'&76'4#"6  =!1 5+%8 3 !/ +  >0# + '$ +;4! D00   $1#"''&763676767>'&762&767>2 !/  :* .C1. -=  8 2'&7> ! 8[J(3-( T +- (&'&''&76767&'&54632'4#"6 + >%7$90(># #8#6 + 0%!""B8!!=T 2'&>" :`L)(5/*0"W@'&767&#"#&'&632K899F Y O5D\  _ +0J 12'&767>#"''&763676767>'&76) .2 !/ +  I0? 8C00 0CK#&'&'#"5&767&'&54632#"''&763676767>'&76'4#"6  ;&,  i!%8 2 !/ +  =04# )";/ +;4"C00  Q'&767676A RbP*H 5'&0'&''6767&'&54632'4#"6 7*)j!#8 2 0: - ;. <4!9  #"547>32&#"32D5 6<#&1%D@+=bJ3-" +> +stream + + #$%)*+,236789:;<=>?@BCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +endstream +endobj +8 0 obj +<< +/BaseFont /ZCCVRA+font0000000013f5eeab +/DW 1000 +/CIDSystemInfo +<< +/Supplement 0 +/Ordering (Identity) +/Registry (Adobe) +>> +/Subtype /CIDFontType2 +/FontDescriptor 14 0 R +/W 15 0 R +/CIDToGIDMap 16 0 R +/Type /Font +>> +endobj +14 0 obj +<< +/FontName /ZCCVRA+font0000000013f5eeab +/StemV 0 +/FontFile2 17 0 R +/Leading 42 +/Ascent 891 +/Flags 32 +/XHeight 242 +/Descent -216 +/ItalicAngle 0 +/MaxWidth 2000 +/FontBBox [-558 -307 2000 1026] +/Type /FontDescriptor +/CapHeight 346 +>> +endobj +17 0 obj +<< +/Length 20588 +/Length1 20588 +>> +stream +true + cvt &fpgmglyf#X,head6hhea4$hmtx"hloca# 6maxp nameP<0prepXA4444455545L5d5|5</VHI +_<5FON5 !EWT  2  2 ( A?__@x3@r3@n3@j3@T3@J32@ + 2 2@Z3@A V3S3P3@M3@G3DE2@B3@>3:3A$ @p//@3A/`  ?O +lEE2@+.2@()22'2BB2682*-2A +((.22@2@APo-12 +2A  @2@2߲042߳2PA# 2Ay)z2~ٲ2ٲ(*2A +|2sq4lk2 @ 2@2kkn/n 2A @Ҳ 2A +@ 2@3@ 2A &82A&0 00Po0/py2y$(2}|2~~ 2@|2| 2?O@س2o@2@Բ 2{z2z2@ 2AToTTTTT/T_T@P2Z@I3HHH"2G"22-2/QKONd@Q2N8:20NN#2N2F 2C +2D+2+2*2A:37 707322PAd2@2`222202P22666p661?11111`10`00P//@/`/////--0----o,, @:@5%,2@j%,2@.%,2@(%,27` p 0 @ P  :3@:3MMM7A @>>>MMM---@M:27_o/?O_o/?O` p 0 @ P   P`p/?@AC`p@P#0#@#0#p@"0$@$$ $$$$$$$A:#0#`p@P#0ײ#7A_/?o@',2&3@"3@3@3@2_A?D3@=3@:3A7_O/??pO_/?z/z@ i(((A# # # # # W# @ # # # # A +J$ $ $ j@$ $ $ $ $ " !@" " " " " " \" Q" L" A +(  ^ @ Y : A +4 4 4 54 4 4 [ [  +*> *>!M%MAMRMrMA  * **^*9*#fff4f4ffA (&M?MA >%@*r*(*$*$*f.ff(lA (&sMqM$pM/oM5k>i>A gf*af*_fA ](\5GM9F>A E>%DCB@*0>*&=f%>*)*  f +&Mr>V@(MbM@Mr>@ *f"*@*.&y(Mf)fbf&(@ fL*+&f)@@*y&uMtMs*p(^j(@i*Rh* gf)efga*`5^*S5KfVI>HfRF&?fV@ ;f42*.5-CU7/r@.~bTB/'%!  +@+JKKSB7+KR8+KP[XYKcKb S# +QZ#BKKTB8+TXCX,FYYv??>9FD>9FD>9FD>9FD>9F`D>9F`DED+++++++++++++++++++++++++KSXY2KSXYK)S \XljEDkjEDYXhlERXlhDYYK;S \X>kEDMkEDYX\>ERX>\DYYK;S \X>ED>>EDYXOERXODYYKZS \XC>ED>>EDYXCERXCDYYKS \X*lED@lEDYXl*ERX*lDYYKS \X&&EDf&EDYX2&ERX&2DYYKQS \X&&ED(&EDYX&ERX&DYYKS \X&&ED5&EDYX(&ERX&(DYY++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++eB+++++++++++++++++++++++++++++++++++++++++++++++++++=vnXEe#E`#Ee`#E`vhb nvEe#E &`bch &aev#eDn#D =XEe#E &`bch &aeX#eD=#DXETXX@eD=@=E#aDYN8qEe#E`#Ee`#E`vhb 8Ee#E &`bch &ae#eD8#D NqEe#E &`bch &aeq#eDN#DqETXq@eDN@NE#aDYKRBKPXBYC\XBY +CX`!YBp>CX;!~ +Y #B #BCX-A-A +Y#B#BCX~;! +Y#B#BtEiDEiDssssttuuuu+++ss++++++EiDssst+EDssssstttEDsttttttuuuEDsuEDssttEDsssssttttuuuuuuuuuuu++tttttts+CXMMEiDM:2+Ys++uuu+++++ss+C\X3@ 3MMMA @>>>MMM---7+tttttts++Ysststststststu+sus+++s++++u+++s+++++t+s+sst+ss++++++s+s+++t+++sssss+ss+++s++++sts+s++++u++++++++u+++++s++++stu++sss+++u++s++++++++++stust+stu+++++++++++++++++++stu++++LLJk#j$$%$]E.X9K +(#KPJ 1F%O"NAGi@'LHQP.;L +#"sZPRn\Z[In~`5br(8 n+F@h33n5C4\]|(;H{7cx!z'4RFTm?N+En!I{nc(i~?2&5@EIWl&@[{w~(8/@FM~{/h   37x{#Xby!$]ehj /7?PW\@!$0MM]fz|/=JP_f|*D!a +3%?CZk"#',?WXw ""*6J\ +#Axy22%i54BHJWdqqrvwzz"#07C[`exxxx{-AGJP[]]_c'Eg&AHk2HI_c +6PT' M)[/td_|D= +a6;Pyd_UVCFJ]e7td %/B?v:7Q)?VN/4$4Z#/DtAPOQRIn{{j"% L}4mi jj88bZDmHm@@\Y+L@ HHd%2v1x + cB,4A8HXlYCp(7BPZdsx\,cAKU_s Ad*8t,@ + ,;DVcWd6P9ND$B"`9,N8iT=qAPO5G9P+WUs\rXD@BUT@?>=<;:987543210/.-,+*)('&%$#"!  + ,E#F` &`&#HH-,E#F#a &a&#HH-,E#F` a F`&#HH-,E#F#a ` &a a&#HH-,E#F`@a f`&#HH-,E#F#a@` &a@a&#HH-, <<-, E# D# ZQX# D#Y QX# MD#Y QX# D#Y!!-, EhD ` EFvhE`D-, +C#Ce +-, + C#C -,#p>#pE: -,E#DE#D-, E%EadPQXED!!Y-,Cc#b#B+-, EC`D-,CCe +-, i@a ,b`+ d#da\XaY-,E+#Dz-,E+#D-,CXE+#DzEi #D QX+#Dz!zYY-,-,%F`F@aH-,KS \XYXY-, %E#DE#DEe#E %`j #B#hj`a Ry!@E TX#!?#YaDRy@ E TX#!?#YaD-,C#C -,C#C -, C#C -, C#Ce -,C#Ce -,C#Ce -,KRXED!!Y-, %#I@` c RX#%8#%e8c8!!!!!Y-,KdQXEi C`:!!!Y-,%# `#-,%# a#-,%-, ` <<-, a <<-,++**-,CC -,>**-,5-,v#p E PXaY:/-,!! d#d@b-,!QX d#d b@/+Y`-,!QX d#dUb/+Y`-, d#d@b`#!-,&&&&Eh:-,&&&&Ehe:-,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,CXY-,CXY-,KTC\ZX8!!Y-,C\X %% d#dadQX%% F`H F`HY +!!!!Y-,C\X %% d#dadQX%% F`H F`HY +!!!!Y-,KS#KQZX:+!!Y-,KS#KQZX;+!!Y-,KS#KQZC\ZX8!!Y-, KT&KTZ +C\ZX8!!Y-,F#F`F# F`ab# #''pE` PXaFY`h:-,B#Q@SZX TXC`BY$QX @TXC`BY$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BYYYY-,CTXKS#KQZX8!!Y!!!!Y-92Q.9P4\NsOOMsF9*9+LsFJKQ&i tF5E; +f i 8 Yd[qch5"_oA 5#5@  @Po+N]]pO jB+9%% c:)%% B-QWk$ +4 +4 +4 @Y +4  6Mkkyy  +&CA +/&hwv v7$Z@Z!jj _/p&&%n2+NCX@  + + +MM] +MMYN]]M??9910KSy2Cy@$ &%  &  +% +% % %+++++*++]q]q++++#&&#"3267#"$54$323267W',1?\ĜvrY\ /k*ĒvՙpuwkF\>$/3qL+ @\ +4# +4 +4+ +4ghg%)(gihc "" "#."5->0P},=+N]q>-,($(( $9,(%(%$-.!=++??<<<9/<<N"! ( _  }P##(Po}"=v+Nq]rLGz+:%% #O`iuR%%Zl$6"%Pk @3hh +  '''( + +4 +4 +4 +4 +4@d +4 +4 +4      +   ffxw vv V55  nX+NMCX@M@/ ?  M]N]qM]@M@/ ?  MN]qMY??10KSyQCy@<%&& %& %%%% % % +%%++<+<+++++*+++++]q]C\X9@ 99 99 9 9 9++++++++Y++++++++q]$! '&"32765&DȞ8aOzUgEXbd_ n .Lt2@  n4L$Ϲ 9 @\ 9O& "* "" "# "#..!!`/&&-  P `  }%&!=++N]r@aK59~-<--!-5- 5EJJI5Xf5 3>-1>P>c`>r:> +P>t;H;@9;23 +,(+,%+,)<3333=3M3}33333333 p33;!eu;Lz p &++,))f/;H2]//@)+4_o@4 ,,/,?,,D)C%%%/ ?       @@>>@>`>>@(P(?+7772@#%4o0@P`=8U1+N]q+Mqq+]]q]]r<]]??9+/]q+<9]qr9]qr9999<<<]+rCTX ]Y10Cy@28:# +%&!% &9& "#:7  +" 8;++++<+++++++rq]rq]q+q+++%#"&546%54&&#"#"&546632327#"&'32IPj5@(A*&I;?Urn + 2kDPZ +y;'!-2iOk^j7)+(1EL3HFqB*@!%JCK9GQ67.#N_#@m$ Y # +,*Wf gv v +r#%!& !H +2?@ 4%%%22?(+4@ 4$8+N+]++M]N]]q++Mr??q<999]q9q910]q]rq%#"547632#"&'&'&#"326@Bof{ؑE8;M 0"4TI7K1X|yƿZ9DNd?3M;+.OEL-z@# 7- #[+  _@y!&**@2?O/K5/;=4/@ 4P//p///&&@@2?0@P.8+N]q+M]N]r+++]q+M]]<?z4Ak*&O] 5@XK]ohey% +  +"@4Vfo"w"  * + ] F(& @ 2?@"4i2? 4@5/"?"_""" )22??&04@ 4!8+N]++++M]N]++q+M++<??<<]q10Cy@%++++*+]+q]q!3267#"'&54324&'&#"] ZEa) / >@?>@9>@&'4>@4>@40>>4>@@47 /@/14@ +1/E&H ?H@ + ? HHH:@2? ::2rr/@),B@ ?B@ ?/BBBBH!@ ?@ ?/@&402?4444@!&+,@2?,@()4,@#%4,o,,P,,,wM8U+]q+++<]q+]]++]]++]q<q+]++??<+<9/9+/CTX@!4+Y+]+++++CTX>%'4>4++Y99999999910]q]+!##"'"372#"&&5467&5467&&54632"32654'&"32654'&&;1oJr-=7>OqhU~ZE^jsx]J:PO6uonA053SJCF8L,߹ 9.@/K54FP..& ", ",$@"'$"#" $ ##$!@c#($,##",f"!! +  *@!A?@EG4@=5@C5@9:4@014@'(4@+-4@"$4@4@4 @.../.p..@>5.9:4.014.'(4.4.,.4.@4.*('@!A?'/''''7:4'/14'"$4'@ !4'-N+N++++]q+LQCdk5$$!et;!7E d"$$ kj4%*#l @?$" $#$#@464@  + @464   @)    *@?:5 #44@/-04{@P`/?N+]qr]]q+++++<]<]+?.Bl[@@ZZ@@[;c7$$"c"c7%+$L@?` $"$# $@# +* @? :5 -44 #4 @#4     {/?144-.4N+++]q]]q+++++<]<?.BLvc7$$"cb7%LuFN@G@ +7<F<F67$״"-$(@"A$<#"$##@'"$'ط#@;7$;@*#B$F##"-6!<2ff + +F<;(' +H@2?H@U"4HHHHH*@=5@+-4@!"*.-@=5-@+-4---@---777*BA@"4`AAAAA/AAAAGHS!N++N]qr+54&&#"!567654&'5MNZz!PPas-'>9++X-A'-/(!/5'>;'>{TCTVZPYl4$$'a}D!?? +e%$$#1R@$K +c?$$ lj4%F7+ 9 -@8K5P-%5F!+!+$@"&$!#" +$##$ @#'$+##!  +f_@V5y+ +  *@!A?@=5 @EG4@C5@9:4@564@014@+-4@'(4@"$4@4@4@--/-p--@>5-9:4-564-014-,.4-'(4-4-@4-*''&@!A?&/&&&&7:4&/14&@ $4&,N+N+++]q+'5+VJ'5';'>yNGeK9l5$$%cs> +stream + +  +endstream +endobj +18 0 obj (Mac OS X 10.6.8 Quartz PDFContext) +endobj +19 0 obj (Adil) +endobj +20 0 obj (al-Nashir al-Sahafi Version 4.5.0) +endobj +21 0 obj (D:20110812232909Z00'00') +endobj +22 0 obj +<< +/Creator (al-Nashir al-Sahafi Version 4.5.0) +/Author (Adil) +/Producer (Mac OS X 10.6.8 Quartz PDFContext) +/ModDate (D:20110812232909Z00'00') +/CreationDate (D:20110812232909Z00'00') +>> +endobj xref +0 23 +0000000000 65535 f +0000000015 00000 n +0000000138 00000 n +0000008807 00000 n +0000000221 00000 n +0000009026 00000 n +0000008889 00000 n +0000009214 00000 n +0000034643 00000 n +0000009163 00000 n +0000009448 00000 n +0000025429 00000 n +0000026363 00000 n +0000009685 00000 n +0000034877 00000 n +0000055787 00000 n +0000055953 00000 n +0000035127 00000 n +0000056184 00000 n +0000056237 00000 n +0000056261 00000 n +0000056314 00000 n +0000056357 00000 n +trailer + +<< +/Info 22 0 R +/Root 9 0 R +/Size 23 +/ID [<0c87b1b9a219e7aeea550c93d2d72c96> <0c87b1b9a219e7aeea550c93d2d72c96>] +>> +startxref +56561 +%%EOF diff --git a/test/test_manifest.json b/test/test_manifest.json index c74af7729..90a9f8a77 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -64,6 +64,11 @@ "rounds": 1, "type": "load" }, + { "id": "complexttffont-pdf", + "file": "pdfs/complex_ttf_font.pdf", + "rounds": 1, + "type": "load" + }, { "id": "i9-pdf", "file": "pdfs/i9.pdf", "link": true, From 28051220236e78e153b648f0599fe9067521487d Mon Sep 17 00:00:00 2001 From: sbarman Date: Fri, 19 Aug 2011 08:19:32 -0700 Subject: [PATCH 80/89] cleanup --- fonts.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fonts.js b/fonts.js index 064459df2..ce49a82b9 100755 --- a/fonts.js +++ b/fonts.js @@ -441,12 +441,6 @@ var Font = (function Font() { break; } - var fileArr = []; - file.reset(); - file = file.getBytes(); - for (var i = 0, ii = file.length; i < ii; ++i) - fileArr.push(file[i]); - this.data = data; this.type = properties.type; this.textMatrix = properties.textMatrix; From a67c63db131d215c78c8ecab5528d6629b6a8492 Mon Sep 17 00:00:00 2001 From: sbarman Date: Fri, 19 Aug 2011 11:24:12 -0700 Subject: [PATCH 81/89] Added default value for no annotations --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 63aefcd32..b8193a138 100644 --- a/pdf.js +++ b/pdf.js @@ -3342,7 +3342,7 @@ var Page = (function() { }, getLinks: function() { var xref = this.xref; - var annotations = xref.fetchIfRef(this.annotations); + var annotations = xref.fetchIfRef(this.annotations) || []; var i, n = annotations.length; var links = []; for (i = 0; i < n; ++i) { From 98d628ee3e8771c9a6384b91948509dbcb6e7ca6 Mon Sep 17 00:00:00 2001 From: Adil Allawi Date: Fri, 19 Aug 2011 21:51:57 +0100 Subject: [PATCH 82/89] make cmap glyph offset a symbolic constant --- fonts.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fonts.js b/fonts.js index 1aff9eb0e..8b33ca3fc 100755 --- a/fonts.js +++ b/fonts.js @@ -790,6 +790,8 @@ var Font = (function Font() { encoding: null, checkAndRepair: function font_checkAndRepair(name, font, properties) { + var kCmapGlyphOffset = 0xFF; + function readTableEntry(file) { // tag var tag = file.getBytes(4); @@ -1042,17 +1044,17 @@ var Font = (function Font() { var encoding = properties.encoding; for (var i = 1; i < numGlyphs; i++) { - glyphs.push({ unicode: i + 0xFF }); + glyphs.push({ unicode: i + kCmapGlyphOffset }); } if ('undefined' == typeof(encoding[0])) { // the font is directly characters to glyphs with no encoding // so create an identity encoding for (i = 0; i < numGlyphs; i++) - encoding[i] = i + 0xFF; + encoding[i] = i + kCmapGlyphOffset; } else { for (var i in encoding) - encoding[i] = encoding[i] + 0xFF; + encoding[i] = encoding[i] + kCmapGlyphOffset; } if (!cmap) { From 3b940c4bcd4f334c87bc937a610820040cf6fe2d Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Fri, 19 Aug 2011 22:41:56 -0500 Subject: [PATCH 83/89] 'GoTo' action/links; document outline (no UI) --- pdf.js | 78 +++++++++++++++++++++++++++++++++++++++++++++------ web/viewer.js | 31 ++++++++++++++++---- 2 files changed, 94 insertions(+), 15 deletions(-) diff --git a/pdf.js b/pdf.js index b8193a138..eb9e18086 100644 --- a/pdf.js +++ b/pdf.js @@ -3163,7 +3163,7 @@ var XRef = (function() { })(); var Page = (function() { - function constructor(xref, pageNumber, pageDict) { + function constructor(xref, pageNumber, pageDict, ref) { this.pageNumber = pageNumber; this.pageDict = pageDict; this.stats = { @@ -3174,6 +3174,7 @@ var Page = (function() { render: 0.0 }; this.xref = xref; + this.ref = ref; } constructor.prototype = { @@ -3349,10 +3350,10 @@ var Page = (function() { var annotation = xref.fetch(annotations[i]); if (!IsDict(annotation, 'Annot')) continue; - var subtype = annotation.get("Subtype"); + var subtype = annotation.get('Subtype'); if (!IsName(subtype) || subtype.name != 'Link') continue; - var rect = annotation.get("Rect"); + var rect = annotation.get('Rect'); var topLeftCorner = this.rotatePoint(rect[0], rect[1]); var bottomRightCorner = this.rotatePoint(rect[2], rect[3]); @@ -3361,14 +3362,17 @@ var Page = (function() { link.y = Math.min(topLeftCorner.y, bottomRightCorner.y); link.width = Math.abs(topLeftCorner.x - bottomRightCorner.x); link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y); - var a = annotation.get("A"); + var a = this.xref.fetchIfRef(annotation.get('A')); if (a) { - switch(a.get("S").name) { - case "URI": - link.url = a.get("URI"); + switch(a.get('S').name) { + case 'URI': + link.url = a.get('URI'); + break; + case 'GoTo': + link.dest = a.get('D'); break; default: - TODO("other link types"); + TODO('other link types'); break; } } @@ -3398,6 +3402,62 @@ var Catalog = (function() { // shadow the prototype getter return shadow(this, 'toplevelPagesDict', obj); }, + get documentOutline() { + function convertIfUnicode(str) { + if (str[0] === '\xFE' && str[1] === '\xFF') { + // UTF16BE BOM + var i, n = str.length, str2 = ""; + for (i = 2; i < n; i+=2) + str2 += String.fromCharCode((str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)); + str = str2; + } + return str; + } + + var obj = this.catDict.get('Outlines'); + var root = { items: [] }; + if (IsRef(obj)) { + obj = this.xref.fetch(obj).get('First'); + var processed = {}; + if (IsRef(obj)) { + var queue = [{obj: obj, parent: root}]; + // to avoid recursion keeping track of the items + // in the processed dictionary + processed['R' + obj.num + ',' + obj.gen] = true; + while (queue.length > 0) { + var i = queue.shift(); + var outlineDict = this.xref.fetch(i.obj); + if (!outlineDict.has('Title')) + error('Invalid outline item'); + var dest = outlineDict.get('Dest'); + if (!dest && outlineDict.get('A')) { + var a = this.xref.fetchIfRef(outlineDict.get('A')); + dest = a.get('D'); + } + var outlineItem = { + dest: dest, + title: convertIfUnicode(outlineDict.get('Title')), + color: outlineDict.get('C') || [0, 0, 0], + bold: !!(outlineDict.get('F') & 2), + italic: !!(outlineDict.get('F') & 1), + items: [] + }; + i.parent.items.push(outlineItem); + obj = outlineDict.get('First'); + if (IsRef(obj) && !processed['R' + obj.num + ',' + obj.gen]) { + queue.push({obj: obj, parent: outlineItem}); + processed['R' + obj.num + ',' + obj.gen] = true; + } + obj = outlineDict.get('Next'); + if (IsRef(obj) && !processed['R' + obj.num + ',' + obj.gen]) { + queue.push({obj: obj, parent: i.parent}); + processed['R' + obj.num + ',' + obj.gen] = true; + } + } + } + } + return shadow(this, 'documentOutline', root); + }, get numPages() { var obj = this.toplevelPagesDict.get('Count'); assertWellFormed( @@ -3418,7 +3478,7 @@ var Catalog = (function() { 'page dictionary kid is not a reference'); var obj = this.xref.fetch(kid); if (IsDict(obj, 'Page') || (IsDict(obj) && !obj.has('Kids'))) { - pageCache.push(new Page(this.xref, pageCache.length, obj)); + pageCache.push(new Page(this.xref, pageCache.length, obj, kid)); } else { // must be a child page dictionary assertWellFormed( IsDict(obj), diff --git a/web/viewer.js b/web/viewer.js index e501a10b2..24afce799 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -84,6 +84,20 @@ var PDFView = { xhr.send(null); }, + navigateTo: function (dest) { + var i, n = this.pages.length; + var destRef = dest[0]; + // TODO optimize destination page search + for (i = 0; i < n; i++) { + var pageRef = this.pages[i].content.ref; + if (destRef.num == pageRef.num && destRef.gen == pageRef.gen) { + this.page = i + 1; + // TODO scroll to specific region on the page + break; + } + } + }, + load: function(data, scale) { var sidebar = document.getElementById('sidebarView'); sidebar.parentNode.scrollTop = 0; @@ -105,7 +119,7 @@ var PDFView = { for (var i = 1; i <= pagesCount; i++) { var page = pdf.getPage(i); pages.push(new PageView(container, page, i, page.width, page.height, - page.stats)); + page.stats, this.navigateTo.bind(this))); thumbnails.push(new ThumbnailView(sidebar, pages[i - 1])); } @@ -140,7 +154,8 @@ var PDFView = { } }; -var PageView = function(container, content, id, width, height, stats) { +var PageView = function(container, content, id, width, height, + stats, navigateTo) { this.width = width; this.height = height; this.id = id; @@ -178,10 +193,9 @@ var PageView = function(container, content, id, width, height, stats) { } x /= scale; y /= scale; - for (var i = 0; i < links.length; i++) { + var i, n = links.length; + for (i = 0; i < n; i++) { var link = links[i]; - if (!link.url) - continue; if (link.x <= x && link.y <= y && x < link.x + link.width && y < link.y + link.height) { currentLink = link; @@ -193,7 +207,12 @@ var PageView = function(container, content, id, width, height, stats) { canvas.style.cursor = 'default'; }, false); canvas.addEventListener('mousedown', function(e) { - window.location.href = currentLink.url; + if (!currentLink) + return; + if (currentLink.url) + window.location.href = currentLink.url; + if (currentLink.dest) + navigateTo(currentLink.dest); }, false); } } From eefaa0153f61ab3fa111fbcf9c5109248ff7cb98 Mon Sep 17 00:00:00 2001 From: Adil Allawi Date: Sat, 20 Aug 2011 09:31:19 +0100 Subject: [PATCH 84/89] Offset glyphs to the unicode private use area --- fonts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 6afb47557..b985e48a5 100755 --- a/fonts.js +++ b/fonts.js @@ -789,7 +789,7 @@ var Font = (function Font() { encoding: null, checkAndRepair: function font_checkAndRepair(name, font, properties) { - var kCmapGlyphOffset = 0xFF; + var kCmapGlyphOffset = 0xE000; //offset glpyhs to the Unicode Private Use Area function readTableEntry(file) { // tag From 3e0c0de985f6cad680b19b1676c71270483a8d16 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sat, 20 Aug 2011 09:51:44 -0500 Subject: [PATCH 85/89] Fixing bookmarks for PDF32000 --- pdf.js | 70 +++++++++++++++++++++++++++++++++++++++++++++------ web/viewer.js | 21 +++++++++------- 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/pdf.js b/pdf.js index eb9e18086..ef2b0c612 100644 --- a/pdf.js +++ b/pdf.js @@ -2228,6 +2228,26 @@ var Ref = (function() { return constructor; })(); +// The reference is identified by number and generation, +// this structure stores only one instance of the reference. +var RefSet = (function() { + function constructor() { + this.dict = {}; + } + + constructor.prototype = { + has: function(ref) { + return !!this.dict['R' + ref.num + '.' + ref.gen]; + }, + + put: function(ref) { + this.dict['R' + ref.num + '.' + ref.gen] = ref; + } + }; + + return constructor; +})(); + function IsBool(v) { return typeof v == 'boolean'; } @@ -3408,22 +3428,22 @@ var Catalog = (function() { // UTF16BE BOM var i, n = str.length, str2 = ""; for (i = 2; i < n; i+=2) - str2 += String.fromCharCode((str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)); + str2 += String.fromCharCode( + (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)); str = str2; } return str; } - var obj = this.catDict.get('Outlines'); var root = { items: [] }; if (IsRef(obj)) { obj = this.xref.fetch(obj).get('First'); - var processed = {}; + var processed = new RefSet(); if (IsRef(obj)) { var queue = [{obj: obj, parent: root}]; // to avoid recursion keeping track of the items // in the processed dictionary - processed['R' + obj.num + ',' + obj.gen] = true; + processed.put(obj); while (queue.length > 0) { var i = queue.shift(); var outlineDict = this.xref.fetch(i.obj); @@ -3438,20 +3458,21 @@ var Catalog = (function() { dest: dest, title: convertIfUnicode(outlineDict.get('Title')), color: outlineDict.get('C') || [0, 0, 0], + count: outlineDict.get('Count'), bold: !!(outlineDict.get('F') & 2), italic: !!(outlineDict.get('F') & 1), items: [] }; i.parent.items.push(outlineItem); obj = outlineDict.get('First'); - if (IsRef(obj) && !processed['R' + obj.num + ',' + obj.gen]) { + if (IsRef(obj) && !processed.has(obj)) { queue.push({obj: obj, parent: outlineItem}); - processed['R' + obj.num + ',' + obj.gen] = true; + processed.put(obj); } obj = outlineDict.get('Next'); - if (IsRef(obj) && !processed['R' + obj.num + ',' + obj.gen]) { + if (IsRef(obj) && !processed.has(obj)) { queue.push({obj: obj, parent: i.parent}); - processed['R' + obj.num + ',' + obj.gen] = true; + processed.put(obj); } } } @@ -3488,6 +3509,39 @@ var Catalog = (function() { } } }, + get destinations() { + var xref = this.xref; + var obj = this.catDict.get('Names'); + obj = obj ? xref.fetch(obj) : this.catDict; + obj = obj.get('Dests'); + var dests = {}; + if (obj) { + // reading name tree + var processed = new RefSet(); + processed.put(obj); + var queue = [obj]; + while (queue.length > 0) { + var i, n; + obj = xref.fetch(queue.shift()); + if (obj.has('Kids')) { + var kids = obj.get('Kids'); + for (i = 0, n = kids.length; i < n; i++) { + var kid = kids[i]; + if (processed.has(kid)) + error('invalid destinations'); + queue.push(kid); + processed.put(kid); + } + continue; + } + var names = obj.get('Names'); + for (i = 0, n = names.length; i < n; i += 2) { + dests[names[i]] = xref.fetch(names[i + 1]).get('D'); + } + } + } + return shadow(this, 'destinations', dests); + }, getPage: function(n) { var pageCache = this.pageCache; if (!pageCache) { diff --git a/web/viewer.js b/web/viewer.js index 24afce799..8fe011b29 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -85,16 +85,14 @@ var PDFView = { }, navigateTo: function (dest) { - var i, n = this.pages.length; + if (typeof dest === 'string') + dest = this.destinations[dest]; + // dest array looks like that: var destRef = dest[0]; - // TODO optimize destination page search - for (i = 0; i < n; i++) { - var pageRef = this.pages[i].content.ref; - if (destRef.num == pageRef.num && destRef.gen == pageRef.gen) { - this.page = i + 1; - // TODO scroll to specific region on the page - break; - } + var pageNumber = this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R']; + if (pageNumber) { + this.page = pageNumber; + // TODO scroll to specific region on the page, the precise scaling required } }, @@ -115,16 +113,21 @@ var PDFView = { document.getElementById('numPages').innerHTML = pagesCount; var pages = this.pages = []; + var pagesRefMap = {}; var thumbnails = this.thumbnails = []; for (var i = 1; i <= pagesCount; i++) { var page = pdf.getPage(i); pages.push(new PageView(container, page, i, page.width, page.height, page.stats, this.navigateTo.bind(this))); thumbnails.push(new ThumbnailView(sidebar, pages[i - 1])); + var pageRef = page.ref; + pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i; } this.scale = (scale || kDefaultScale); this.page = parseInt(document.location.hash.substring(1)) || 1; + this.pagesRefMap = pagesRefMap; + this.destinations = pdf.catalog.destinations; }, getVisiblePages: function() { From 9bc76da676c3e74459647299995d4460ef7fe4d8 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sat, 20 Aug 2011 14:41:38 -0500 Subject: [PATCH 86/89] Implements ImageMask: using image as a stencil mask --- pdf.js | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/pdf.js b/pdf.js index 642e37d32..325aa16d8 100644 --- a/pdf.js +++ b/pdf.js @@ -4889,7 +4889,10 @@ var CanvasGraphics = (function() { var imgData = tmpCtx.getImageData(0, 0, w, h); var pixels = imgData.data; - imageObj.fillRgbaBuffer(pixels); + if (imageObj.imageMask) + imageObj.fillUsingStencilMask(pixels, this.current.fillColor); + else + imageObj.fillRgbaBuffer(pixels); tmpCtx.putImageData(imgData, 0, 0); ctx.drawImage(tmpCanvas, 0, -h); @@ -5660,14 +5663,16 @@ var PDFImage = (function() { } this.bpc = bitsPerComponent; - var colorSpace = dict.get('ColorSpace', 'CS'); - if (!colorSpace) { - TODO('JPX images (which don"t require color spaces'); - colorSpace = new Name('DeviceRGB'); + if (!this.imageMask) { + var colorSpace = dict.get('ColorSpace', 'CS'); + if (!colorSpace) { + TODO('JPX images (which don"t require color spaces'); + colorSpace = new Name('DeviceRGB'); + } + this.colorSpace = ColorSpace.parse(colorSpace, xref, res); + this.numComps = this.colorSpace.numComps; } - this.colorSpace = ColorSpace.parse(colorSpace, xref, res); - this.numComps = this.colorSpace.numComps; this.decode = dict.get('Decode', 'D'); var mask = xref.fetchIfRef(image.dict.get('Mask')); @@ -5763,6 +5768,31 @@ var PDFImage = (function() { } return buf; }, + fillUsingStencilMask: function fillUsingStencilMask(buffer, cssRgb) { + var m = /rgb\((\d+),(\d+),(\d+)\)/.exec(cssRgb); // parse CSS color + var r = m[1] | 0, g = m[2] | 0, b = m[3] | 0; + var width = this.width; + var height = this.height; + var imgArray = this.image.getBytes((height * width + 7) >> 3); + var i, j, mask; + var bufferPos = 0, imgArrayPos = 0; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + var buf = imgArray[imgArrayPos++]; + for (mask = 128; mask > 0; mask >>= 1) { + if (buf & mask) { + buffer[bufferPos++] = r; + buffer[bufferPos++] = g; + buffer[bufferPos++] = b; + buffer[bufferPos++] = 255; + } else { + buffer[bufferPos + 3] = 0; + bufferPos += 4; + } + } + } + } + }, fillRgbaBuffer: function fillRgbaBuffer(buffer) { var numComps = this.numComps; var width = this.width; From 01e2f81a490cbc3858e3df798df44bb1bf331382 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sat, 20 Aug 2011 23:03:00 -0500 Subject: [PATCH 87/89] stencil mask: height * width optimization and decode inversion --- pdf.js | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/pdf.js b/pdf.js index 325aa16d8..5d959c100 100644 --- a/pdf.js +++ b/pdf.js @@ -4889,9 +4889,13 @@ var CanvasGraphics = (function() { var imgData = tmpCtx.getImageData(0, 0, w, h); var pixels = imgData.data; - if (imageObj.imageMask) - imageObj.fillUsingStencilMask(pixels, this.current.fillColor); - else + if (imageObj.imageMask) { + var inverseDecode = imageObj.decode && imageObj.decode[0] > 0; + // TODO fillColor pattern support + var fillColor = this.current.fillColor; + imageObj.fillUsingStencilMask(pixels, fillColor, + inverseDecode); + } else imageObj.fillRgbaBuffer(pixels); tmpCtx.putImageData(imgData, 0, 0); @@ -5768,27 +5772,25 @@ var PDFImage = (function() { } return buf; }, - fillUsingStencilMask: function fillUsingStencilMask(buffer, cssRgb) { + fillUsingStencilMask: function fillUsingStencilMask(buffer, + cssRgb, inverseDecode) { var m = /rgb\((\d+),(\d+),(\d+)\)/.exec(cssRgb); // parse CSS color var r = m[1] | 0, g = m[2] | 0, b = m[3] | 0; - var width = this.width; - var height = this.height; - var imgArray = this.image.getBytes((height * width + 7) >> 3); - var i, j, mask; + var bufferLength = this.width * this.height; + var imgArray = this.image.getBytes((bufferLength + 7) >> 3); + var i, mask; var bufferPos = 0, imgArrayPos = 0; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - var buf = imgArray[imgArrayPos++]; - for (mask = 128; mask > 0; mask >>= 1) { - if (buf & mask) { - buffer[bufferPos++] = r; - buffer[bufferPos++] = g; - buffer[bufferPos++] = b; - buffer[bufferPos++] = 255; - } else { - buffer[bufferPos + 3] = 0; - bufferPos += 4; - } + for (i = 0; i < bufferLength; i++) { + var buf = imgArray[imgArrayPos++]; + for (mask = 128; mask > 0; mask >>= 1) { + if (!(buf & mask) != inverseDecode) { + buffer[bufferPos++] = r; + buffer[bufferPos++] = g; + buffer[bufferPos++] = b; + buffer[bufferPos++] = 255; + } else { + buffer[bufferPos + 3] = 0; + bufferPos += 4; } } } From d674990baaadea740302be07cbf4a1e558097e68 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Mon, 22 Aug 2011 19:22:57 +0300 Subject: [PATCH 88/89] Add kkujala to the LICENSE contributor list. --- LICENSE | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 81658476c..d96b927a3 100644 --- a/LICENSE +++ b/LICENSE @@ -7,6 +7,7 @@ Vivien Nicolas <21@vingtetun.org> Justin D'Arcangelo Yury Delendik + Kalervo Kujala Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -24,4 +25,5 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. \ No newline at end of file + DEALINGS IN THE SOFTWARE. + From 8ffbf683b8eeacb08ceec1f0da50a492152762dc Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Mon, 22 Aug 2011 22:30:22 +0300 Subject: [PATCH 89/89] Add more debug data to error-logs. Fix also a few gjslint errors. --- fonts.js | 22 ++++----- pdf.js | 123 ++++++++++++++++++++++++++------------------------ web/viewer.js | 5 +- 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/fonts.js b/fonts.js index b985e48a5..3d47ef4a2 100755 --- a/fonts.js +++ b/fonts.js @@ -461,9 +461,9 @@ var Font = (function Font() { return array; }; - + function arrayToString(arr) { - var str = ""; + var str = ''; for (var i = 0; i < arr.length; ++i) str += String.fromCharCode(arr[i]); @@ -789,10 +789,10 @@ var Font = (function Font() { encoding: null, checkAndRepair: function font_checkAndRepair(name, font, properties) { - var kCmapGlyphOffset = 0xE000; //offset glpyhs to the Unicode Private Use Area + // offset glyphs to the Unicode Private Use Area + var kCmapGlyphOffset = 0xE000; function readTableEntry(file) { - // tag var tag = file.getBytes(4); tag = String.fromCharCode(tag[0]) + String.fromCharCode(tag[1]) + @@ -975,12 +975,12 @@ var Font = (function Font() { } var numTables = header.numTables + requiredTables.length; - + // header and new offsets. Table entry information is appended to the // end of file. The virtualOffset represents where to put the actual // data of a particular table; var ttf = { - file: "", + file: '', virtualOffset: numTables * (4 * 4) }; @@ -1030,8 +1030,8 @@ var Font = (function Font() { // Type2 composite fonts map characters directly to glyphs so the cmap // table must be replaced. // canvas fillText will reencode some characters even if the font has a - // glyph at that position - e.g. newline is converted to a space and U+00AD - // (soft hypen) is not drawn. + // glyph at that position - e.g. newline is converted to a space and + // U+00AD (soft hyphen) is not drawn. // So, offset all the glyphs by 0xFF to avoid these cases and use // the encoding to map incoming characters to the new glyph positions @@ -1126,7 +1126,7 @@ var Font = (function Font() { var kRequiredTablesCount = 9; var otf = { - file: "", + file: '', virtualOffset: 9 * (4 * 4) }; @@ -1584,11 +1584,11 @@ var Type1Parser = function() { var count = eexecStr.length; for (var i = 0; i < count; i++) { var getToken = function() { - while(i < count && (eexecStr[i] == ' ' || eexecStr[i] == '\n')) + while (i < count && (eexecStr[i] == ' ' || eexecStr[i] == '\n')) ++i; var t = ''; - while(i < count && !(eexecStr[i] == ' ' || eexecStr[i] == '\n')) + while (i < count && !(eexecStr[i] == ' ' || eexecStr[i] == '\n')) t += eexecStr[i++]; return t; diff --git a/pdf.js b/pdf.js index 0ff3381f5..469eec578 100644 --- a/pdf.js +++ b/pdf.js @@ -390,13 +390,13 @@ var FlateStream = (function() { var cmf = bytes[bytesPos++]; var flg = bytes[bytesPos++]; if (cmf == -1 || flg == -1) - error('Invalid header in flate stream'); + error('Invalid header in flate stream: ' + cmf + ', ' + flg); if ((cmf & 0x0f) != 0x08) - error('Unknown compression method in flate stream'); + error('Unknown compression method in flate stream: ' + cmf + ', ' + flg); if ((((cmf << 8) + flg) % 31) != 0) - error('Bad FCHECK in flate stream'); + error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg); if (flg & 0x20) - error('FDICT bit set in flate stream'); + error('FDICT bit set in flate stream: ' + cmf + ', ' + flg); this.bytes = bytes; this.bytesPos = bytesPos; @@ -635,7 +635,7 @@ var PredictorStream = (function() { if (predictor <= 1) return stream; // no prediction if (predictor !== 2 && (predictor < 10 || predictor > 15)) - error('Unsupported predictor'); + error('Unsupported predictor: ' + predictor); if (predictor === 2) this.readBlock = this.readBlockTiff; @@ -787,7 +787,7 @@ var PredictorStream = (function() { break; } default: - error('Unsupported predictor'); + error('Unsupported predictor: ' + predictor); break; } this.bufferLength += rowBytes; @@ -2387,7 +2387,7 @@ var Lexer = (function() { } while (true); var value = parseFloat(str); if (isNaN(value)) - error('Invalid floating point number'); + error('Invalid floating point number: ' + value); return value; }, getString: function() { @@ -2486,7 +2486,7 @@ var Lexer = (function() { stream.skip(); var x2 = ToHexDigit(stream.getChar()); if (x2 == -1) - error('Illegal digit in hex char in name'); + error('Illegal digit in hex char in name: ' + x2); str += String.fromCharCode((x << 4) | x2); } else { str += '#'; @@ -2497,7 +2497,8 @@ var Lexer = (function() { } } if (str.length > 128) - error('Warning: name token is longer than allowed by the spec.'); + error('Warning: name token is longer than allowed by the spec: ' + + str.length); return new Name(str); }, getHexString: function(ch) { @@ -2515,14 +2516,14 @@ var Lexer = (function() { if (specialChars[ch.charCodeAt(0)] != 1) { var x, x2; if ((x = ToHexDigit(ch)) == -1) - error('Illegal character in hex string'); + error('Illegal character in hex string: ' + ch); ch = stream.getChar(); while (specialChars[ch.charCodeAt(0)] == 1) ch = stream.getChar(); if ((x2 = ToHexDigit(ch)) == -1) - error('Illegal character in hex string'); + error('Illegal character in hex string: ' + ch); str += String.fromCharCode((x << 4) | x2); } @@ -2582,7 +2583,7 @@ var Lexer = (function() { return new Cmd(ch); // fall through case ')': - error('Illegal character'); + error('Illegal character: ' + ch); return Error; } @@ -2591,7 +2592,7 @@ var Lexer = (function() { while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) { stream.skip(); if (str.length == 128) { - error('Command token too long'); + error('Command token too long: ' + str.length); break; } str += ch; @@ -2765,7 +2766,7 @@ var Parser = (function() { if (xref) length = xref.fetchIfRef(length); if (!IsInt(length)) { - error("Bad 'Length' attribute in stream"); + error('Bad ' + Length + ' attribute in stream'); length = 0; } @@ -2774,7 +2775,7 @@ var Parser = (function() { this.shift(); // '>>' this.shift(); // 'stream' if (!IsCmd(this.buf1, 'endstream')) - error("Missing 'endstream'"); + error('Missing endstream'); this.shift(); stream = stream.makeSubStream(pos, length, dict); @@ -2795,7 +2796,7 @@ var Parser = (function() { for (var i = 0, ii = filterArray.length; i < ii; ++i) { filter = filterArray[i]; if (!IsName(filter)) - error('Bad filter name'); + error('Bad filter name: ' + filter); else { params = null; if (IsArray(paramsArray) && (i in paramsArray)) @@ -2831,7 +2832,7 @@ var Parser = (function() { } else if (name == 'CCITTFaxDecode' || name == 'CCF') { return new CCITTFaxStream(stream, params); } else { - error("filter '" + name + "' not supported yet"); + error('filter "' + name + '" not supported yet'); } return stream; } @@ -2864,7 +2865,7 @@ var Linearization = (function() { obj > 0) { return obj; } - error("'" + name + "' field in linearization table is invalid"); + error('"' + name + '" field in linearization table is invalid'); return 0; }, getHint: function(index) { @@ -2877,7 +2878,7 @@ var Linearization = (function() { obj2 > 0) { return obj2; } - error('Hints table in linearization table is invalid'); + error('Hints table in linearization table is invalid: ' + index); return 0; }, get length() { @@ -2952,14 +2953,14 @@ var XRef = (function() { error('Invalid XRef table'); var n = obj; if (first < 0 || n < 0 || (first + n) != ((first + n) | 0)) - error('Invalid XRef table'); + error('Invalid XRef table: ' + first + ', ' + n); for (var i = first; i < first + n; ++i) { var entry = {}; if (!IsInt(obj = parser.getObj())) - error('Invalid XRef table'); + error('Invalid XRef table: ' + first + ', ' + n); entry.offset = obj; if (!IsInt(obj = parser.getObj())) - error('Invalid XRef table'); + error('Invalid XRef table: ' + first + ', ' + n); entry.gen = obj; obj = parser.getObj(); if (IsCmd(obj, 'n')) { @@ -2967,7 +2968,7 @@ var XRef = (function() { } else if (IsCmd(obj, 'f')) { entry.free = true; } else { - error('Invalid XRef table'); + error('Invalid XRef table: ' + first + ', ' + n); } if (!this.entries[i]) { // In some buggy PDF files the xref table claims to start at 1 @@ -3022,13 +3023,13 @@ var XRef = (function() { while (range.length > 0) { var first = range[0], n = range[1]; if (!IsInt(first) || !IsInt(n)) - error('Invalid XRef range fields'); + error('Invalid XRef range fields: ' + first + ', ' + n); var typeFieldWidth = byteWidths[0]; var offsetFieldWidth = byteWidths[1]; var generationFieldWidth = byteWidths[2]; if (!IsInt(typeFieldWidth) || !IsInt(offsetFieldWidth) || !IsInt(generationFieldWidth)) { - error('Invalid XRef entry fields length'); + error('Invalid XRef entry fields length: ' + first + ', ' + n); } for (i = 0; i < n; ++i) { var type = 0, offset = 0, generation = 0; @@ -3054,7 +3055,7 @@ var XRef = (function() { case 2: break; default: - error('Invalid XRef entry type'); + error('Invalid XRef entry type: ' + type); break; } if (!this.entries[first + i]) @@ -3155,12 +3156,12 @@ var XRef = (function() { for (i = 0; i < n; ++i) { var num = parser.getObj(); if (!IsInt(num)) { - error('invalid object number in the ObjStm stream'); + error('invalid object number in the ObjStm stream: ' + num); } nums.push(num); var offset = parser.getObj(); if (!IsInt(offset)) { - error('invalid object offset in the ObjStm stream'); + error('invalid object offset in the ObjStm stream: ' + offset); } } // read stream objects for cache @@ -3269,7 +3270,7 @@ var Page = (function() { var gfx = new CanvasGraphics(canvasCtx); var fonts = []; - var images = new ImagesLoader() + var images = new ImagesLoader(); this.compile(gfx, fonts, images); stats.compile = Date.now(); @@ -3323,7 +3324,8 @@ var Page = (function() { var i, n = this.content.length, compiledItems = []; for (i = 0; i < n; ++i) { content = xref.fetchIfRef(this.content[i]); - compiledItems.push(gfx.compile(content, xref, resources, fonts, images)); + compiledItems.push(gfx.compile(content, xref, resources, fonts, + images)); } // creating the function that executes all compiled items this.code = function(gfx) { @@ -3347,7 +3349,7 @@ var Page = (function() { gfx.execute(this.code, xref, resources); gfx.endDrawing(); }, - rotatePoint: function (x, y) { + rotatePoint: function(x, y) { var rotate = this.rotate; switch (rotate) { default: @@ -3384,7 +3386,7 @@ var Page = (function() { link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y); var a = this.xref.fetchIfRef(annotation.get('A')); if (a) { - switch(a.get('S').name) { + switch (a.get('S').name) { case 'URI': link.url = a.get('URI'); break; @@ -3426,8 +3428,8 @@ var Catalog = (function() { function convertIfUnicode(str) { if (str[0] === '\xFE' && str[1] === '\xFF') { // UTF16BE BOM - var i, n = str.length, str2 = ""; - for (i = 2; i < n; i+=2) + var i, n = str.length, str2 = ''; + for (i = 2; i < n; i += 2) str2 += String.fromCharCode( (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)); str = str2; @@ -4146,11 +4148,12 @@ var PartialEvaluator = (function() { var glyphsStream = xref.fetchIfRef(cidToGidMap); var glyphsData = glyphsStream.getBytes(0); // Glyph ids are big-endian 2-byte values - encodingMap[0] = 0; //set this to 0 to verify the font has an encoding + // Set this to 0 to verify the font has an encoding. + encodingMap[0] = 0; for (var j = 0; j < glyphsData.length; j++) { var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; if (glyphID != 0) - encodingMap[j>>1] = glyphID; + encodingMap[j >> 1] = glyphID; } } } @@ -4375,11 +4378,11 @@ var CanvasExtraState = (function() { constructor.prototype = { clone: function canvasextra_clone() { return Object.create(this); - }, + }, setCurrentPoint: function canvasextra_setCurrentPoint(x, y) { this.x = x; this.y = y; - }, + } }; return constructor; })(); @@ -5106,12 +5109,12 @@ var ColorSpace = (function() { // Input: array of size numComps representing color component values // Output: array of rgb values, each value ranging from [0.1] getRgb: function cs_getRgb(color) { - error('Should not call ColorSpace.getRgb'); + error('Should not call ColorSpace.getRgb: ' + color); }, // Input: Uint8Array of component values, each value scaled to [0,255] // Output: Uint8Array of rgb values, each value scaled to [0,255] getRgbBuffer: function cs_getRgbBuffer(input) { - error('Should not call ColorSpace.getRgbBuffer'); + error('Should not call ColorSpace.getRgbBuffer: ' + input); } }; @@ -5205,10 +5208,10 @@ var ColorSpace = (function() { case 'Lab': case 'DeviceN': default: - error("unimplemented color space object '" + mode + "'"); + error('unimplemented color space object "' + mode + '"'); } } else { - error('unrecognized color space object: "' + cs + "'"); + error('unrecognized color space object: "' + cs + '"'); } }; @@ -5282,7 +5285,7 @@ var IndexedCS = (function() { for (var i = 0; i < length; ++i) lookupArray[i] = lookup.charCodeAt(i); } else { - error('Unrecognized lookup table'); + error('Unrecognized lookup table: ' + lookup); } this.lookup = lookupArray; } @@ -5457,7 +5460,7 @@ var Pattern = (function() { // Input: current Canvas context // Output: the appropriate fillStyle or strokeStyle getPattern: function pattern_getStyle(ctx) { - error('Should not call Pattern.getStyle'); + error('Should not call Pattern.getStyle: ' + ctx); } }; @@ -5466,7 +5469,7 @@ var Pattern = (function() { var patternName = args[length - 1]; if (!IsName(patternName)) - error('Bad args to getPattern'); + error('Bad args to getPattern: ' + patternName); var patternRes = xref.fetchIfRef(res.get('Pattern')); if (!patternRes) @@ -5496,7 +5499,7 @@ var Pattern = (function() { var matrix = dict.get('Matrix'); return Pattern.parseShading(shading, matrix, xref, res, ctx); default: - error('Unknown type of pattern'); + error('Unknown type of pattern: ' + typeNum); } }; @@ -5701,7 +5704,7 @@ var TilingPattern = (function() { tmpCtx.strokeStyle = color; break; default: - error('Unsupported paint type'); + error('Unsupported paint type: ' + paintType); } var scale = [width / xstep, height / ystep]; @@ -5764,7 +5767,8 @@ var PDFImage = (function() { this.height = dict.get('Height', 'H'); if (this.width < 1 || this.height < 1) - error('Invalid image width or height'); + error('Invalid image width: ' + this.width + ' or height: ' + + this.height); this.interpolate = dict.get('Interpolate', 'I') || false; this.imageMask = dict.get('ImageMask', 'IM') || false; @@ -5776,7 +5780,7 @@ var PDFImage = (function() { if (this.imageMask) bitsPerComponent = 1; else - error('Bits per component missing in image'); + error('Bits per component missing in image: ' + this.imageMask); } } this.bpc = bitsPerComponent; @@ -5876,7 +5880,8 @@ var PDFImage = (function() { var sw = smask.width; var sh = smask.height; if (sw != this.width || sh != this.height) - error('smask dimensions do not match image dimensions'); + error('smask dimensions do not match image dimensions: ' + sw + + ' != ' + this.width + ', ' + sh + ' != ' + this.height); smask.fillGrayBuffer(buf); return buf; @@ -5935,7 +5940,7 @@ var PDFImage = (function() { fillGrayBuffer: function fillGrayBuffer(buffer) { var numComps = this.numComps; if (numComps != 1) - error('Reading gray scale from a color image'); + error('Reading gray scale from a color image: ' + numComps); var width = this.width; var height = this.height; @@ -5987,7 +5992,8 @@ var PDFFunction = (function() { var outputSize = range.length / 2; if (inputSize != 1) - error('No support for multi-variable inputs to functions'); + error('No support for multi-variable inputs to functions: ' + + inputSize); var size = dict.get('Size'); var bps = dict.get('BitsPerSample'); @@ -5995,7 +6001,7 @@ var PDFFunction = (function() { if (!order) order = 1; if (order !== 1) - error('No support for cubic spline interpolation'); + error('No support for cubic spline interpolation: ' + order); var encode = dict.get('Encode'); if (!encode) { @@ -6021,7 +6027,8 @@ var PDFFunction = (function() { } if (inputSize != args.length) - error('Incorrect number of arguments'); + error('Incorrect number of arguments: ' + inputSize + ' != ' + + args.length); for (var i = 0; i < inputSize; i++) { var i2 = i * 2; @@ -6132,7 +6139,7 @@ var PDFFunction = (function() { var fns = []; for (var i = 0, ii = fnRefs.length; i < ii; ++i) fns.push(new PDFFunction(xref, xref.fetchIfRef(fnRefs[i]))); - + var bounds = dict.get('Bounds'); var encode = dict.get('Encode'); @@ -6160,12 +6167,12 @@ var PDFFunction = (function() { var dmax = domain[1]; if (i < bounds.length) dmax = bounds[i]; - + var rmin = encode[2 * i]; var rmax = encode[2 * i + 1]; - var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); - + var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); + // call the appropropriate function return fns[i].func([v2]); } diff --git a/web/viewer.js b/web/viewer.js index 8fe011b29..fde57a8d0 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -84,7 +84,7 @@ var PDFView = { xhr.send(null); }, - navigateTo: function (dest) { + navigateTo: function(dest) { if (typeof dest === 'string') dest = this.destinations[dest]; // dest array looks like that: @@ -92,7 +92,8 @@ var PDFView = { var pageNumber = this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R']; if (pageNumber) { this.page = pageNumber; - // TODO scroll to specific region on the page, the precise scaling required + // TODO scroll to specific region on the page, the precise scaling + // required. } },