From 71d0f0d55c4584e2731a9f0e573c183a87f39ea9 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Thu, 8 Sep 2011 13:03:30 +0200 Subject: [PATCH 01/16] Remove a useless check in charsToUnicode --- fonts.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fonts.js b/fonts.js index bfdbb0b4a..5622e84e4 100755 --- a/fonts.js +++ b/fonts.js @@ -444,7 +444,6 @@ var Font = (function Font() { var constructor = function font_constructor(name, file, properties) { this.name = name; this.encoding = properties.encoding; - this.glyphs = properties.glyphs; this.sizes = []; var names = name.split("+"); @@ -1368,10 +1367,6 @@ var Font = (function Font() { unicode = charcode; } - // Check if the glyph has already been converted - if (!IsNum(unicode)) - unicode = encoding[charcode].unicode = this.glyphs[unicode].unicode; - // Handle surrogate pairs if (unicode > 0xFFFF) { str += String.fromCharCode(unicode & 0xFFFF); From 81d7d1a72515450b25b07eaf482a3591820db46f Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Thu, 8 Sep 2011 17:57:37 +0200 Subject: [PATCH 02/16] Add widths information for the most common fonts cases --- fonts.js | 28 +++++++++++++++++-------- pdf.js | 64 ++++++++++++++++++++++++++------------------------------ 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/fonts.js b/fonts.js index 5622e84e4..cca1d816c 100755 --- a/fonts.js +++ b/fonts.js @@ -140,11 +140,21 @@ var FontMeasure = (function FontMeasure() { ctx.font = rule; current = font; }, - measureText: function fonts_measureText(text) { + measureText: function fonts_measureText(text, encoding, size) { var width; if (measureCache && (width = measureCache[text])) return width; - width = ctx.measureText(text).width / kScalePrecision; + + try { + width = 0.0; + for (var i = 0; i < text.length; i++) { + var charWidth = encoding[text.charCodeAt(i)].width; + width += parseFloat(charWidth); + } + width = width * size / 1000; + } catch(e) { + width = ctx.measureText(text).width / kScalePrecision; + } if (measureCache) measureCache[text] = width; return width; @@ -468,8 +478,7 @@ var Font = (function Font() { (fontName.indexOf('Italic') != -1); // Use 'name' instead of 'fontName' here because the original - // name ArialNarrow for example will be replaced by Helvetica. - this.narrow = (name.indexOf("Narrow") != -1) + // name ArialBlack for example will be replaced by Helvetica. this.black = (name.indexOf("Black") != -1) this.loadedName = fontName.split('-')[0]; @@ -1018,7 +1027,9 @@ var Font = (function Font() { var index = firstCode; for (var j = start; j <= end; j++) { var code = j - firstCode - 1; - encoding[index++] = { unicode: glyphs[code].unicode }; + var mapping = encoding[index + 1] || {}; + mapping.unicode = glyphs[code].unicode; + encoding[index++] = mapping; } return cmap.data = createCMapTable(glyphs); } @@ -2329,12 +2340,11 @@ var Type2CFF = (function() { } } - if (code == -1) { - var mapping = properties.glyphs[glyph] || {}; + var mapping = properties.glyphs[glyph] || {}; + if (code == -1) index = code = mapping.unicode || index; - } - var width = widths[code] || defaultWidth; + var width = mapping.width || defaultWidth; if (code <= 0x1f || (code >= 127 && code <= 255)) code += kCmapGlyphOffset; diff --git a/pdf.js b/pdf.js index 40ffde688..7fff8ae62 100644 --- a/pdf.js +++ b/pdf.js @@ -4273,22 +4273,23 @@ var PartialEvaluator = (function() { var glyphs = {}; for (var i = firstChar; i <= lastChar; i++) { var glyph = differences[i] || baseEncoding[i]; - if (glyph) { - var index = GlyphsUnicode[glyph] || i; - glyphs[glyph] = map[i] = { - unicode: index, - width: properties.widths[i - firstChar] || properties.defaultWidth - }; + var index = GlyphsUnicode[glyph] || i; + map[i] = { + unicode: index, + width: properties.widths[i] || properties.defaultWidth + }; - // If there is no file, the character mapping can't be modified - // but this is unlikely that there is any standard encoding with - // chars below 0x1f, so that's fine. - if (!properties.file) - continue; + if (glyph) + glyphs[glyph] = map[i]; - if (index <= 0x1f || (index >= 127 && index <= 255)) - map[i].unicode += kCmapGlyphOffset; - } + // If there is no file, the character mapping can't be modified + // but this is unlikely that there is any standard encoding with + // chars below 0x1f, so that's fine. + if (!properties.file) + continue; + + if (index <= 0x1f || (index >= 127 && index <= 255)) + map[i].unicode += kCmapGlyphOffset; } if (type == 'TrueType' && dict.has('ToUnicode') && differences) { @@ -4325,10 +4326,9 @@ var PartialEvaluator = (function() { var endRange = tokens[j + 1]; var code = tokens[j + 2]; while (startRange < endRange) { - map[startRange] = { - unicode: code++, - width: 0 - } + var mapping = map[startRange] || {}; + mapping.unicode = code++; + map[startRange] = mapping; ++startRange; } } @@ -4339,10 +4339,9 @@ var PartialEvaluator = (function() { for (var j = 0; j < tokens.length; j += 2) { var index = tokens[j]; var code = tokens[j + 1]; - map[index] = { - unicode: code, - width: 0 - }; + var mapping = map[index] || {}; + mapping.unicode = code; + map[index] = mapping; } break; @@ -4494,13 +4493,13 @@ var PartialEvaluator = (function() { descent: descriptor.get('Descent'), xHeight: descriptor.get('XHeight'), capHeight: descriptor.get('CapHeight'), - defaultWidth: descriptor.get('MissingWidth') || 0, + defaultWidth: parseFloat(descriptor.get('MissingWidth')) || 0, flags: descriptor.get('Flags'), italicAngle: descriptor.get('ItalicAngle'), differences: [], widths: (function() { var glyphWidths = {}; - for (var i = 0; i <= widths.length; i++) + for (var i = 0; i < widths.length; i++) glyphWidths[firstChar++] = widths[i]; return glyphWidths; })(), @@ -4898,6 +4897,7 @@ var CanvasGraphics = (function() { var scaleFactorX = 1, scaleFactorY = 1; var font = current.font; + var baseText= text; if (font) { if (current.fontSize <= kRasterizerMin) { scaleFactorX = scaleFactorY = kScalePrecision; @@ -4907,26 +4907,22 @@ var CanvasGraphics = (function() { text = font.charsToUnicode(text); } + var encoding = current.font.encoding; + var size = current.fontSize; var charSpacing = current.charSpacing; var wordSpacing = current.wordSpacing; var textHScale = current.textHScale; - // This is a poor simulation for Arial Narrow while font-stretch - // is not implemented (bug 3512) - if (current.font.narrow) { - textHScale += 0.2; - charSpacing -= (0.09 * current.fontSize); - } - if (charSpacing != 0 || wordSpacing != 0 || textHScale != 1) { scaleFactorX *= textHScale; ctx.scale(1 / textHScale, 1); var width = 0; for (var i = 0, ii = text.length; i < ii; ++i) { - var c = text.charAt(i); + var c = baseText.charAt(i); ctx.fillText(c, 0, 0); - var charWidth = FontMeasure.measureText(c) + charSpacing; + var charWidth = FontMeasure.measureText(c, encoding, size); + charWidth += charSpacing; if (c.charCodeAt(0) == 32) charWidth += wordSpacing; ctx.translate(charWidth * scaleFactorX, 0); @@ -4935,7 +4931,7 @@ var CanvasGraphics = (function() { current.x += width; } else { ctx.fillText(text, 0, 0); - current.x += FontMeasure.measureText(text); + current.x += FontMeasure.measureText(baseText, encoding, size); } this.ctx.restore(); From b7796f123afef8f72fa68443640c4b6fadf98e34 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Thu, 22 Sep 2011 00:32:36 +0200 Subject: [PATCH 03/16] Support CropBox attribute --- pdf.js | 25 +++++++++++++++++++++++++ web/viewer.css | 10 ++++++---- web/viewer.js | 45 ++++++++++++++++++++++++++++++--------------- 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/pdf.js b/pdf.js index 224becdf1..001257af0 100644 --- a/pdf.js +++ b/pdf.js @@ -3319,6 +3319,31 @@ var Page = (function() { return shadow(this, 'mediaBox', ((IsArray(obj) && obj.length == 4) ? obj : null)); }, + get view() { + var obj = this.inheritPageProp('CropBox'); + var view = { + x: 0, + y: 0, + width: this.width, + height: this.height + }; + if (IsArray(obj) && obj.length == 4) { + var rotate = this.rotate; + if (rotate == 0 || rotate == 180) { + view.x = obj[0]; + view.y = obj[1]; + view.width = obj[2] - view.x; + view.height = obj[3] - view.y; + } else { + view.x = obj[1]; + view.y = obj[0]; + view.width = obj[3] - view.x; + view.height = obj[2] - view.y; + } + } + + return shadow(this, 'cropBox', view); + }, get annotations() { return shadow(this, 'annotations', this.inheritPageProp('Annots')); }, diff --git a/web/viewer.css b/web/viewer.css index cda191a76..e72bdc286 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -119,6 +119,7 @@ span#info { margin-right:auto; line-height: 134px; text-align: center; + overflow: hidden; } .thumbnail:not([data-loaded]) { @@ -195,16 +196,17 @@ span#info { canvas { margin: auto; display: block; - box-shadow: 0px 4px 10px #000; - -moz-box-shadow: 0px 4px 10px #000; - -webkit-box-shadow: 0px 4px 10px #000; } .page { width: 816px; height: 1056px; margin: 10px auto; - position:relative; + position: relative; + overflow: hidden; + box-shadow: 0px 4px 10px #000; + -moz-box-shadow: 0px 4px 10px #000; + -webkit-box-shadow: 0px 4px 10px #000; } .page > a { diff --git a/web/viewer.js b/web/viewer.js index 72b540664..f4f28b8ab 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -58,9 +58,9 @@ var PDFView = { var currentPage = this.pages[this.page - 1]; var pageWidthScale = (window.innerWidth - kScrollbarPadding) / - currentPage.width / kCssUnits; + currentPage.width / kCssUnits; var pageHeightScale = (window.innerHeight - kScrollbarPadding) / - currentPage.height / kCssUnits; + currentPage.height / kCssUnits; if ('page-width' == value) this.setScale(pageWidthScale, resetAutoSettings); if ('page-height' == value) @@ -170,7 +170,7 @@ var PDFView = { 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], + thumbnails.push(new ThumbnailView(sidebar, page, i, page.width / page.height)); var pageRef = page.ref; pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i; @@ -237,13 +237,17 @@ var PDFView = { } }; -var PageView = function(container, content, id, width, height, +var PageView = function(container, content, id, pageWidth, pageHeight, stats, navigateTo) { - this.width = width; - this.height = height; this.id = id; this.content = content; + var view = this.content.view; + this.x = view.x; + this.y = view.y; + this.width = view.width; + this.height = view.height; + var anchor = document.createElement('a'); anchor.name = '' + this.id; @@ -272,11 +276,12 @@ var PageView = function(container, content, id, width, height, return false; }; } + var links = content.getLinks(); for (var i = 0; i < links.length; i++) { var link = document.createElement('a'); - link.style.left = Math.floor(links[i].x * scale) + 'px'; - link.style.top = Math.floor(links[i].y * scale) + 'px'; + link.style.left = (Math.floor(links[i].x - this.x) * scale) + 'px'; + link.style.top = (Math.floor(links[i].y - this.y) * scale) + 'px'; link.style.width = Math.ceil(links[i].width * scale) + 'px'; link.style.height = Math.ceil(links[i].height * scale) + 'px'; link.href = links[i].url || ''; @@ -364,8 +369,9 @@ var PageView = function(container, content, id, width, height, canvas.id = 'page' + this.id; canvas.mozOpaque = true; - canvas.width = this.width * this.scale; - canvas.height = this.height * this.scale; + var scale = this.scale; + canvas.width = pageWidth * scale; + canvas.height = pageHeight * scale; div.appendChild(canvas); var ctx = canvas.getContext('2d'); @@ -373,6 +379,7 @@ var PageView = function(container, content, id, width, height, ctx.fillStyle = 'rgb(255, 255, 255)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.restore(); + ctx.translate(-this.x * scale, -this.y * scale); stats.begin = Date.now(); this.content.startRendering(ctx, this.updateStats); @@ -391,12 +398,12 @@ var PageView = function(container, content, id, width, height, }; }; -var ThumbnailView = function(container, page, pageRatio) { +var ThumbnailView = function(container, page, id, pageRatio) { var anchor = document.createElement('a'); - anchor.href = '#' + page.id; + anchor.href = '#' + id; var div = document.createElement('div'); - div.id = 'thumbnailContainer' + page.id; + div.id = 'thumbnailContainer' + id; div.className = 'thumbnail'; anchor.appendChild(div); @@ -407,7 +414,7 @@ var ThumbnailView = function(container, page, pageRatio) { return; var canvas = document.createElement('canvas'); - canvas.id = 'thumbnail' + page.id; + canvas.id = 'thumbnail' + id; canvas.mozOpaque = true; var maxThumbSize = 134; @@ -425,7 +432,15 @@ var ThumbnailView = function(container, page, pageRatio) { ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.restore(); - page.content.startRendering(ctx, function() { }); + var view = page.view; + var scaleX = (canvas.width / page.width); + var scaleY = (canvas.height / page.height); + ctx.translate(-view.x * scaleX, -view.y * scaleY); + div.style.width = (view.width * scaleX) + 'px'; + div.style.height = (view.height * scaleY) + 'px'; + div.style.lineHeight = (view.height * scaleY) + 'px'; + + page.startRendering(ctx, function() { }); }; }; From d8905b524d2ff3d7590b56ed990e6602de526793 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Thu, 22 Sep 2011 00:44:51 +0200 Subject: [PATCH 04/16] Fix a lint error --- web/viewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index f4f28b8ab..fb3af2ad4 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -281,7 +281,7 @@ var PageView = function(container, content, id, pageWidth, pageHeight, for (var i = 0; i < links.length; i++) { var link = document.createElement('a'); link.style.left = (Math.floor(links[i].x - this.x) * scale) + 'px'; - link.style.top = (Math.floor(links[i].y - this.y) * scale) + 'px'; + link.style.top = (Math.floor(links[i].y - this.y) * scale) + 'px'; link.style.width = Math.ceil(links[i].width * scale) + 'px'; link.style.height = Math.ceil(links[i].height * scale) + 'px'; link.href = links[i].url || ''; From 5c772329d8e5f558f1af9a8bca5f3f0945b8edca Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Thu, 22 Sep 2011 23:01:16 +0300 Subject: [PATCH 05/16] Make showText and showSpacedText slightly faster. --- pdf.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/pdf.js b/pdf.js index 1b80424d6..67b21b01f 100644 --- a/pdf.js +++ b/pdf.js @@ -5033,7 +5033,8 @@ var CanvasGraphics = (function canvasGraphics() { ctx.scale(1 / textHScale, 1); var width = 0; - for (var i = 0; i < glyphs.length; i++) { + var glyphsLength = glyphs.length; + for (var i = 0; i < glyphsLength; ++i) { var glyph = glyphs[i]; if (glyph === null) { // word break @@ -5042,34 +5043,35 @@ var CanvasGraphics = (function canvasGraphics() { } var unicode = glyph.unicode; - var char = unicode >= 0x10000 ? + var char = (unicode >= 0x10000) ? String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10), 0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode); - var charWidth = glyph.width * fontSize * 0.001; - charWidth += charSpacing; - ctx.fillText(char, width, 0); - width += charWidth; + width += glyph.width * fontSize * 0.001 + charSpacing; } current.x += width; this.ctx.restore(); }, showSpacedText: function canvasGraphicsShowSpacedText(arr) { - for (var i = 0; i < arr.length; ++i) { + var ctx = this.ctx; + var current = this.current; + var fontSize = current.fontSize; + var textHScale = current.textHScale; + var arrLength = arr.length; + for (var i = 0; i < arrLength; ++i) { var e = arr[i]; if (IsNum(e)) { - if (this.ctx.$addCurrentX) { - this.ctx.$addCurrentX(-e * 0.001 * this.current.fontSize); + if (ctx.$addCurrentX) { + ctx.$addCurrentX(-e * 0.001 * fontSize); } else { - this.current.x -= e * 0.001 * this.current.fontSize * - this.current.textHScale; + current.x -= e * 0.001 * fontSize * textHScale; } } else if (IsString(e)) { this.showText(e); } else { - malformed('TJ array element ' + e + " isn't string or num"); + malformed('TJ array element ' + e + ' is not string or num'); } } }, From 8072052fb19d0190e8ba149fc6749e8dc3a463ea Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 22 Sep 2011 13:17:28 -0700 Subject: [PATCH 06/16] Handle references for color space names that are defined in a dictionary --- pdf.js | 2 +- test/pdfs/hudsonsurvey.pdf.link | 1 + test/test_manifest.json | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 test/pdfs/hudsonsurvey.pdf.link diff --git a/pdf.js b/pdf.js index 1b80424d6..8a7c645ce 100644 --- a/pdf.js +++ b/pdf.js @@ -5431,7 +5431,7 @@ var ColorSpace = (function colorSpaceColorSpace() { constructor.parse = function colorspace_parse(cs, xref, res) { if (IsName(cs)) { - var colorSpaces = res.get('ColorSpace'); + var colorSpaces = xref.fetchIfRef(res.get('ColorSpace')); if (IsDict(colorSpaces)) { var refcs = colorSpaces.get(cs.name); if (refcs) diff --git a/test/pdfs/hudsonsurvey.pdf.link b/test/pdfs/hudsonsurvey.pdf.link new file mode 100644 index 000000000..ab3b730db --- /dev/null +++ b/test/pdfs/hudsonsurvey.pdf.link @@ -0,0 +1 @@ +https://issues.apache.org/jira/secure/attachment/12421789/survey.pdf \ No newline at end of file diff --git a/test/test_manifest.json b/test/test_manifest.json index edf13b7c5..231857fa8 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -145,5 +145,11 @@ "link": true, "rounds": 1, "type": "load" + }, + { "id": "hudsonsurvey", + "file": "pdfs/hudsonsurvey.pdf", + "link": true, + "rounds": 1, + "type": "load" } ] From 107576d634ae39d8ee60ce9dd25e28a9c6112bc0 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 22 Sep 2011 18:04:50 -0500 Subject: [PATCH 07/16] Removing introduced by the test run DOM elements --- test/driver.js | 13 +++++++++++++ test/test_slave.html | 1 + 2 files changed, 14 insertions(+) diff --git a/test/driver.js b/test/driver.js index 7d6c54509..db6c9b501 100644 --- a/test/driver.js +++ b/test/driver.js @@ -50,7 +50,20 @@ function load() { r.send(null); } +function cleanup() { + var styleSheet = document.styleSheets[0]; + if (styleSheet) { + while (styleSheet.cssRules.length > 0) + styleSheet.deleteRule(0); + } + var guard = document.getElementById('content-end'); + while (document.body.lastChild != guard) + document.body.removeChild(document.body.lastChild); +} + function nextTask() { + cleanup(); + if (currentTaskIdx == manifest.length) { return done(); } diff --git a/test/test_slave.html b/test/test_slave.html index b46e29d6b..57d8d7a83 100644 --- a/test/test_slave.html +++ b/test/test_slave.html @@ -14,6 +14,7 @@

   

Inflight requests:

+
From 7fd6283d6f2648e45363a50215853ec357466243 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 22 Sep 2011 18:29:43 -0500 Subject: [PATCH 08/16] Fixing hyperlinks (regr. #509) --- web/viewer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 9d89c8801..89d83fe6b 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -280,8 +280,8 @@ var PageView = function(container, content, id, pageWidth, pageHeight, var links = content.getLinks(); for (var i = 0; i < links.length; i++) { var link = document.createElement('a'); - link.style.left = (Math.floor(links[i].x - this.x) * scale) + 'px'; - link.style.top = (Math.floor(links[i].y - this.y) * scale) + 'px'; + link.style.left = (Math.floor(links[i].x - view.x) * scale) + 'px'; + link.style.top = (Math.floor(links[i].y - view.y) * scale) + 'px'; link.style.width = Math.ceil(links[i].width * scale) + 'px'; link.style.height = Math.ceil(links[i].height * scale) + 'px'; link.href = links[i].url || ''; From f3e4cf20cc6d4173ec45669d26f05cf929da10a7 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 22 Sep 2011 20:18:43 -0500 Subject: [PATCH 09/16] intermediate variable for document.body --- test/driver.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/driver.js b/test/driver.js index db6c9b501..3e3097107 100644 --- a/test/driver.js +++ b/test/driver.js @@ -57,8 +57,9 @@ function cleanup() { styleSheet.deleteRule(0); } var guard = document.getElementById('content-end'); - while (document.body.lastChild != guard) - document.body.removeChild(document.body.lastChild); + var body = document.body; + while (body.lastChild != guard) + body.removeChild(body.lastChild); } function nextTask() { From ba74e56c35b7c74d7e65405dfcae082664962c1b Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Fri, 23 Sep 2011 06:58:54 -0500 Subject: [PATCH 10/16] Using !== for objects comparison --- test/driver.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/driver.js b/test/driver.js index 3e3097107..e7c125347 100644 --- a/test/driver.js +++ b/test/driver.js @@ -58,7 +58,7 @@ function cleanup() { } var guard = document.getElementById('content-end'); var body = document.body; - while (body.lastChild != guard) + while (body.lastChild !== guard) body.removeChild(body.lastChild); } From 2d03f93fedd5c1a6ea98954d2451375b3683c933 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Fri, 23 Sep 2011 20:25:24 +0300 Subject: [PATCH 11/16] Name anonymous functions for debugging purposes. It also makes profiling more convenient. --- test/driver.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test/driver.js b/test/driver.js index 7d6c54509..4751910b2 100644 --- a/test/driver.js +++ b/test/driver.js @@ -39,7 +39,7 @@ function load() { var r = new XMLHttpRequest(); r.open('GET', manifestFile, false); - r.onreadystatechange = function(e) { + r.onreadystatechange = function loadOnreadystatechange(e) { if (r.readyState == 4) { log('done\n'); manifest = JSON.parse(r.responseText); @@ -62,7 +62,7 @@ function nextTask() { var r = new XMLHttpRequest(); r.open('GET', task.file); r.mozResponseType = r.responseType = 'arraybuffer'; - r.onreadystatechange = function() { + r.onreadystatechange = function nextTaskOnreadystatechange() { var failure; if (r.readyState == 4) { var data = r.mozResponseArrayBuffer || r.mozResponse || @@ -85,11 +85,15 @@ function isLastPage(task) { return (task.pageNum > task.pdfDoc.numPages); } +function canvasToDataURL() { + return canvas.toDataURL('image/png'); +} + function nextPage(task, loadError) { var failure = loadError || ''; if (!task.pdfDoc) { - sendTaskResult(canvas.toDataURL('image/png'), task, failure); + sendTaskResult(canvasToDataURL(), task, failure); log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); ++currentTaskIdx; nextTask(); @@ -126,7 +130,7 @@ function nextPage(task, loadError) { page.startRendering( ctx, - function(e) { + function nextPageStartRendering(e) { snapshotCurrentPage(task, (!failure && e) ? ('render : ' + e) : failure); } @@ -146,13 +150,13 @@ function nextPage(task, loadError) { function snapshotCurrentPage(task, failure) { log('done, snapshotting... '); - sendTaskResult(canvas.toDataURL('image/png'), task, failure); + sendTaskResult(canvasToDataURL(), task, failure); log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); // Set up the next request var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; setTimeout( - function() { + function snapshotCurrentPageSetTimeout() { ++task.pageNum; nextPage(task); }, @@ -201,7 +205,7 @@ function sendTaskResult(snapshot, task, failure) { // (The POST URI is ignored atm.) r.open('POST', '/submit_task_results', true); r.setRequestHeader('Content-Type', 'application/json'); - r.onreadystatechange = function(e) { + r.onreadystatechange = function sendTaskResultOnreadystatechange(e) { if (r.readyState == 4) { inFlightRequests--; } From 0d5efbe9fec1a81b1b08ecf1308b4e20299d1c66 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Fri, 23 Sep 2011 20:44:48 +0300 Subject: [PATCH 12/16] Name anonymous functions for debugging purposes. It also makes profiling more convenient. --- fonts.js | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/fonts.js b/fonts.js index e5cce0b4f..653751083 100644 --- a/fonts.js +++ b/fonts.js @@ -124,7 +124,7 @@ var serifFonts = { var FontLoader = { listeningForFontLoad: false, - bind: function(fonts, callback) { + bind: function fontLoaderBind(fonts, callback) { function checkFontsLoaded() { for (var i = 0; i < objs.length; i++) { var fontObj = objs[i]; @@ -180,7 +180,7 @@ var FontLoader = { // loaded in a subdocument. It's expected that the load of |rules| // has already started in this (outer) document, so that they should // be ordered before the load in the subdocument. - prepareFontLoadEvent: function(rules, names, objs) { + prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names, objs) { /** Hack begin */ // There's no event when a font has finished downloading so the // following code is a dirty hack to 'guess' when a font is @@ -219,7 +219,7 @@ var FontLoader = { if (!this.listeningForFontLoad) { window.addEventListener( 'message', - function(e) { + function fontLoaderMessage(e) { var fontNames = JSON.parse(e.data); for (var i = 0; i < objs.length; ++i) { var font = objs[i]; @@ -247,7 +247,7 @@ var FontLoader = { fontNamesArray += '"' + names[i] + '", '; } src += ' var fontNames=[' + fontNamesArray + '];\n'; - src += ' window.onload = function () {\n'; + src += ' window.onload = function fontLoaderOnload() {\n'; src += ' parent.postMessage(JSON.stringify(fontNames), "*");\n'; src += ' }'; src += ''; @@ -599,7 +599,7 @@ var Font = (function Font() { var length = glyphs.length; for (var n = 0; n < length; ++n) codes.push({ unicode: glyphs[n].unicode, code: n }); - codes.sort(function(a, b) { + codes.sort(function fontGetRangesSort(a, b) { return a.unicode - b.unicode; }); @@ -928,7 +928,7 @@ var Font = (function Font() { } // Check that table are sorted by platformID then encodingID, - records.sort(function(a, b) { + records.sort(function fontReplaceCMapTableSort(a, b) { return ((a.platformID << 16) + a.encodingID) - ((b.platformID << 16) + b.encodingID); }); @@ -1061,11 +1061,11 @@ var Font = (function Font() { var itemSize, itemDecode, itemEncode; if (isGlyphLocationsLong) { itemSize = 4; - itemDecode = function(data, offset) { + itemDecode = function fontItemDecodeLong(data, offset) { return (data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]; }; - itemEncode = function(data, offset, value) { + itemEncode = function fontItemEncodeLong(data, offset, value) { data[offset] = (value >>> 24) & 0xFF; data[offset + 1] = (value >> 16) & 0xFF; data[offset + 2] = (value >> 8) & 0xFF; @@ -1073,10 +1073,10 @@ var Font = (function Font() { }; } else { itemSize = 2; - itemDecode = function(data, offset) { + itemDecode = function fontItemDecode(data, offset) { return (data[offset] << 9) | (data[offset + 1] << 1); }; - itemEncode = function(data, offset, value) { + itemEncode = function fontItemEncode(data, offset, value) { data[offset] = (value >> 9) & 0xFF; data[offset + 1] = (value >> 1) & 0xFF; }; @@ -1323,7 +1323,7 @@ var Font = (function Font() { 'cmap': createCMapTable(charstrings.slice(), font.glyphIds), // Font header - 'head': (function() { + 'head': (function fontFieldsHead() { return stringToArray( '\x00\x01\x00\x00' + // Version number '\x00\x00\x10\x00' + // fontRevision @@ -1345,7 +1345,7 @@ var Font = (function Font() { })(), // Horizontal header - 'hhea': (function() { + 'hhea': (function fontFieldsHhea() { return stringToArray( '\x00\x01\x00\x00' + // Version number string16(properties.ascent) + // Typographic Ascent @@ -1368,7 +1368,7 @@ var Font = (function Font() { })(), // Horizontal metrics - 'hmtx': (function() { + 'hmtx': (function fontFieldsHmtx() { var hmtx = '\x00\x00\x00\x00'; // Fake .notdef for (var i = 0; i < charstrings.length; i++) { hmtx += string16(charstrings[i].width) + string16(0); @@ -1377,7 +1377,7 @@ var Font = (function Font() { })(), // Maximum profile - 'maxp': (function() { + 'maxp': (function fontFieldsMaxp() { return stringToArray( '\x00\x00\x50\x00' + // Version number string16(charstrings.length + 1)); // Num of glyphs @@ -1505,7 +1505,7 @@ var Font = (function Font() { * program. Some of its logic depends on the Type2 charstrings * structure. */ -var Type1Parser = function() { +var Type1Parser = function type1Parser() { /* * Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence * of Plaintext Bytes. The function took a key as a parameter which can be @@ -2033,7 +2033,7 @@ var CFFStrings = [ var type1Parser = new Type1Parser(); -var CFF = function(name, file, properties) { +var CFF = function cFF(name, file, properties) { // Get the data block containing glyphs and subrs informations var headerBlock = file.getBytes(properties.length1); type1Parser.extractFontHeader(headerBlock, properties); @@ -2233,7 +2233,7 @@ CFF.prototype = { 'names': this.createCFFIndexHeader([name]), 'topDict': (function topDict(self) { - return function() { + return function cFFWrapTopDict() { var header = '\x00\x01\x01\x01'; var dict = '\xf8\x1b\x00' + // version @@ -2310,7 +2310,7 @@ CFF.prototype = { 'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs), true), - 'private': (function(self) { + 'private': (function cFFWrapPrivate(self) { var data = '\x8b\x14' + // defaultWidth '\x8b\x15'; // nominalWidth @@ -2363,7 +2363,7 @@ CFF.prototype = { } }; -var Type2CFF = (function() { +var Type2CFF = (function type2CFF() { // TODO: replace parsing code with the Type2Parser in font_utils.js function constructor(file, properties) { var bytes = file.getBytes(); @@ -2503,7 +2503,9 @@ var Type2CFF = (function() { } // sort the array by the unicode value - charstrings.sort(function(a, b) {return a.unicode - b.unicode}); + charstrings.sort(function type2CFFGetCharStringsSort(a, b) { + return a.unicode - b.unicode + }); return charstrings; }, From 5ce5ca03d32272321d07b0a624fb942b90b04d78 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Fri, 23 Sep 2011 20:54:18 +0300 Subject: [PATCH 13/16] Name anonymous functions for debugging purposes. It also makes profiling more convenient. --- crypto.js | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/crypto.js b/crypto.js index a91f9e41d..42eeeda51 100644 --- a/crypto.js +++ b/crypto.js @@ -3,7 +3,7 @@ 'use strict'; -var ARCFourCipher = (function() { +var ARCFourCipher = (function aRCFourCipher() { function constructor(key) { this.a = 0; this.b = 0; @@ -21,7 +21,7 @@ var ARCFourCipher = (function() { } constructor.prototype = { - encryptBlock: function(data) { + encryptBlock: function aRCFourCipherEncryptBlock(data) { var i, n = data.length, tmp, tmp2; var a = this.a, b = this.b, s = this.s; var output = new Uint8Array(n); @@ -45,7 +45,7 @@ var ARCFourCipher = (function() { return constructor; })(); -var md5 = (function() { +var md5 = (function md5Md5() { var r = new Uint8Array([ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, @@ -129,12 +129,12 @@ var md5 = (function() { return hash; })(); -var NullCipher = (function() { +var NullCipher = (function nullCipher() { function constructor() { } constructor.prototype = { - decryptBlock: function(data) { + decryptBlock: function nullCipherDecryptBlock(data) { return data; } }; @@ -142,7 +142,7 @@ var NullCipher = (function() { return constructor; })(); -var AES128Cipher = (function() { +var AES128Cipher = (function aES128Cipher() { var rcon = new Uint8Array([ 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, @@ -372,7 +372,7 @@ var AES128Cipher = (function() { } constructor.prototype = { - decryptBlock: function(data) { + decryptBlock: function aES128CipherDecryptBlock(data) { var i, sourceLength = data.length; var buffer = this.buffer, bufferLength = this.bufferPosition; // waiting for IV values -- they are at the start of the stream @@ -395,19 +395,21 @@ var AES128Cipher = (function() { return constructor; })(); -var CipherTransform = (function() { +var CipherTransform = (function cipherTransform() { function constructor(stringCipherConstructor, streamCipherConstructor) { this.stringCipherConstructor = stringCipherConstructor; this.streamCipherConstructor = streamCipherConstructor; } constructor.prototype = { - createStream: function(stream) { + createStream: function cipherTransformCreateStream(stream) { var cipher = new this.streamCipherConstructor(); - return new DecryptStream(stream, function(data) { - return cipher.decryptBlock(data); - }); + return new DecryptStream(stream, + function cipherTransformDecryptStream(data) { + return cipher.decryptBlock(data); + } + ); }, - decryptString: function(s) { + decryptString: function cipherTransformDecryptString(s) { var cipher = new this.stringCipherConstructor(); var data = stringToBytes(s); data = cipher.decryptBlock(data); @@ -417,7 +419,7 @@ var CipherTransform = (function() { return constructor; })(); -var CipherTransformFactory = (function() { +var CipherTransformFactory = (function cipherTransformFactory() { function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) { var defaultPasswordBytes = new Uint8Array([ @@ -552,18 +554,18 @@ var CipherTransformFactory = (function() { if (cryptFilter != null) cfm = cryptFilter.get('CFM'); if (!cfm || cfm.name == 'None') { - return function() { + return function cipherTransformFactoryBuildCipherConstructorNone() { return new NullCipher(); }; } if ('V2' == cfm.name) { - return function() { + return function cipherTransformFactoryBuildCipherConstructorV2() { return new ARCFourCipher( buildObjectKey(num, gen, key, false)); }; } if ('AESV2' == cfm.name) { - return function() { + return function cipherTransformFactoryBuildCipherConstructorAESV2() { return new AES128Cipher( buildObjectKey(num, gen, key, true)); }; @@ -573,7 +575,8 @@ var CipherTransformFactory = (function() { } constructor.prototype = { - createCipherTransform: function(num, gen) { + createCipherTransform: function buildCipherCreateCipherTransform(num, + gen) { if (this.algorithm == 4) { return new CipherTransform( buildCipherConstructor(this.cf, this.stmf, @@ -583,7 +586,7 @@ var CipherTransformFactory = (function() { } // algorithms 1 and 2 var key = buildObjectKey(num, gen, this.encryptionKey, false); - var cipherConstructor = function() { + var cipherConstructor = function buildCipherCipherConstructor() { return new ARCFourCipher(key); }; return new CipherTransform(cipherConstructor, cipherConstructor); From 481f242b5a3acfb0ac0935a12600839bab3e2d4c Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Fri, 23 Sep 2011 20:56:21 +0300 Subject: [PATCH 14/16] Fix lint warnings. --- fonts.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index 653751083..bc1ad5569 100644 --- a/fonts.js +++ b/fonts.js @@ -180,7 +180,8 @@ var FontLoader = { // loaded in a subdocument. It's expected that the load of |rules| // has already started in this (outer) document, so that they should // be ordered before the load in the subdocument. - prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names, objs) { + prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names, + objs) { /** Hack begin */ // There's no event when a font has finished downloading so the // following code is a dirty hack to 'guess' when a font is @@ -2504,7 +2505,7 @@ var Type2CFF = (function type2CFF() { // sort the array by the unicode value charstrings.sort(function type2CFFGetCharStringsSort(a, b) { - return a.unicode - b.unicode + return a.unicode - b.unicode; }); return charstrings; }, From 335e86359dbb37cc309abeef2409490636628400 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Fri, 23 Sep 2011 20:58:56 +0300 Subject: [PATCH 15/16] Name anonymous functions for debugging purposes. It also makes profiling more convenient. --- pdf.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pdf.js b/pdf.js index 6c66b84c4..3709afa17 100644 --- a/pdf.js +++ b/pdf.js @@ -6466,7 +6466,7 @@ var PDFFunction = (function pDFFunction() { return out; }; }, - constructStiched: function(fn, dict, xref) { + constructStiched: function pDFFunctionConstructStiched(fn, dict, xref) { var domain = dict.get('Domain'); var range = dict.get('Range'); @@ -6485,8 +6485,8 @@ var PDFFunction = (function pDFFunction() { var bounds = dict.get('Bounds'); var encode = dict.get('Encode'); - this.func = function(args) { - var clip = function(v, min, max) { + this.func = function pDFFunctionConstructStichedFunc(args) { + var clip = function pDFFunctionConstructStichedFuncClip(v, min, max) { if (v > max) v = max; else if (v < min) @@ -6519,9 +6519,9 @@ var PDFFunction = (function pDFFunction() { return fns[i].func([v2]); }; }, - constructPostScript: function() { + constructPostScript: function pDFFunctionConstructPostScript() { TODO('unhandled type of function'); - this.func = function() { + this.func = function pDFFunctionConstructPostScriptFunc() { return [255, 105, 180]; }; } From ced260c2ff6cf7bd54aee14d7c54b98b7dee5ace Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Fri, 23 Sep 2011 18:08:23 -0500 Subject: [PATCH 16/16] Reset invalid media box to letter size. --- pdf.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pdf.js b/pdf.js index 6c66b84c4..77ac4a29b 100644 --- a/pdf.js +++ b/pdf.js @@ -3321,8 +3321,10 @@ var Page = (function pagePage() { }, get mediaBox() { var obj = this.inheritPageProp('MediaBox'); - return shadow(this, 'mediaBox', - ((IsArray(obj) && obj.length == 4) ? obj : null)); + // Reset invalid media box to letter size. + if (!IsArray(obj) || obj.length === 4) + obj = [0, 0, 612, 792]; + return shadow(this, 'mediaBox', obj); }, get view() { var obj = this.inheritPageProp('CropBox');