From e316d787556d2e6e8c04a314904e6e60e67a8218 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Wed, 30 Nov 2011 14:19:07 -0500 Subject: [PATCH 01/14] Smoother thumbnail scrolling via lazy rendering --- web/viewer.html | 4 +- web/viewer.js | 113 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 78 insertions(+), 39 deletions(-) diff --git a/web/viewer.html b/web/viewer.html index a72503eee..ebc0bcb06 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -28,7 +28,6 @@ - @@ -119,6 +118,7 @@
Loading... 0%
+ + - diff --git a/web/viewer.js b/web/viewer.js index bfb3a4303..e945dc434 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -13,19 +13,6 @@ var kMinScale = 0.25; var kMaxScale = 4.0; -var Cache = function cacheCache(size) { - var data = []; - this.push = function cachePush(view) { - var i = data.indexOf(view); - if (i >= 0) - data.splice(i); - data.push(view); - if (data.length > size) - data.shift().update(); - }; -}; - -var cache = new Cache(kCacheSize); var currentPageNumber = 1; var PDFView = { @@ -294,6 +281,7 @@ var PDFView = { outlineScrollView.setAttribute('hidden', 'true'); thumbsSwitchButton.setAttribute('data-selected', true); outlineSwitchButton.removeAttribute('data-selected'); + updateThumbViewArea(); break; case 'outline': thumbsScrollView.setAttribute('hidden', 'true'); @@ -328,6 +316,34 @@ var PDFView = { currentHeight += singlePage.height * singlePage.scale + kBottomMargin; } return visiblePages; + }, + + getVisibleThumbs: function pdfViewGetVisibleThumbs() { + var thumbs = this.thumbnails; + var kBottomMargin = 5; + var visibleThumbs = []; + + var view = document.getElementById('sidebarScrollView'); + var currentHeight = kBottomMargin; + var top = view.scrollTop; + for (var i = 1; i <= thumbs.length; ++i) { + var thumb = thumbs[i - 1]; + var thumbHeight = thumb.height * thumb.scaleY + kBottomMargin; + if (currentHeight + thumbHeight > top) + break; + + currentHeight += thumbHeight; + } + + var bottom = top + view.clientHeight; + for (; i <= thumbs.length && currentHeight < bottom; ++i) { + var singleThumb = thumbs[i - 1]; + visibleThumbs.push({ id: singleThumb.id, y: currentHeight, + view: singleThumb }); + currentHeight += singleThumb.height * singleThumb.scaleY + kBottomMargin; + } + + return visibleThumbs; } }; @@ -510,6 +526,19 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { PDFView.page = id; return false; }; + + var view = page.view; + this.width = view.width; + this.height = view.height; + this.id = id; + + var maxThumbSize = 134; + var canvasWidth = pageRatio >= 1 ? maxThumbSize : + maxThumbSize * pageRatio; + var canvasHeight = pageRatio <= 1 ? maxThumbSize : + maxThumbSize / pageRatio; + this.scaleX = (canvasWidth / this.width); + this.scaleY = (canvasHeight / this.height); var div = document.createElement('div'); div.id = 'thumbnailContainer' + id; @@ -526,11 +555,8 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { canvas.id = 'thumbnail' + id; canvas.mozOpaque = true; - var maxThumbSize = 134; - canvas.width = pageRatio >= 1 ? maxThumbSize : - maxThumbSize * pageRatio; - canvas.height = pageRatio <= 1 ? maxThumbSize : - maxThumbSize / pageRatio; + canvas.width = canvasWidth; + canvas.height = canvasHeight; div.setAttribute('data-loaded', true); div.appendChild(canvas); @@ -542,8 +568,8 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { ctx.restore(); var view = page.view; - var scaleX = (canvas.width / page.width); - var scaleY = (canvas.height / page.height); + var scaleX = this.scaleX; + var scaleY = this.scaleY; ctx.translate(-view.x * scaleX, -view.y * scaleY); div.style.width = (view.width * scaleX) + 'px'; div.style.height = (view.height * scaleY) + 'px'; @@ -613,8 +639,7 @@ function updateViewarea() { var visiblePages = PDFView.getVisiblePages(); for (var i = 0; i < visiblePages.length; i++) { var page = visiblePages[i]; - if (PDFView.pages[page.id - 1].draw()) - cache.push(page.view); + PDFView.pages[page.id - 1].draw(); } if (!visiblePages.length) @@ -641,6 +666,35 @@ window.addEventListener('scroll', function webViewerScroll(evt) { updateViewarea(); }, true); + +var sidebarScrollView = document.getElementById('sidebarScrollView'); +var thumbnailTimer; + +function updateThumbViewArea() { + // Only render thumbs after pausing scrolling for this amount of time + // (makes UI more responsive) + var delay = 50; // in ms + + if (thumbnailTimer) + clearTimeout(thumbnailTimer); + + thumbnailTimer = setTimeout(function(){ + var visibleThumbs = PDFView.getVisibleThumbs(); + for (var i = 0; i < visibleThumbs.length; i++) { + var thumb = visibleThumbs[i]; + PDFView.thumbnails[thumb.id - 1].draw(); + } + }, delay); +} + +sidebarScrollView.addEventListener('scroll', function thumbViewScroll(evt) { + updateThumbViewArea(); +}, true); + +window.addEventListener('transitionend', function webViewerTransitionend(evt) { + updateThumbViewArea(); +}, true); + window.addEventListener('resize', function webViewerResize(evt) { if (document.getElementById('pageWidthOption').selected || document.getElementById('pageFitOption').selected) @@ -681,21 +735,6 @@ window.addEventListener('change', function webViewerChange(evt) { document.getElementById('download').setAttribute('hidden', 'true'); }, true); -window.addEventListener('transitionend', function webViewerTransitionend(evt) { - var pageIndex = 0; - var pagesCount = PDFView.pages.length; - - var container = document.getElementById('sidebarView'); - container._interval = window.setInterval(function interval() { - if (pageIndex >= pagesCount) { - window.clearInterval(container._interval); - return; - } - - PDFView.thumbnails[pageIndex++].draw(); - }, 500); -}, true); - window.addEventListener('scalechange', function scalechange(evt) { var customScaleOption = document.getElementById('customScaleOption'); customScaleOption.selected = false; From a523d807534e0493147963b453c837345fa58e9e Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Wed, 30 Nov 2011 15:10:27 -0500 Subject: [PATCH 02/14] bringing Cache() back --- web/viewer.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index e945dc434..dd49d75b7 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -13,6 +13,19 @@ var kMinScale = 0.25; var kMaxScale = 4.0; +var Cache = function cacheCache(size) { + var data = []; + this.push = function cachePush(view) { + var i = data.indexOf(view); + if (i >= 0) + data.splice(i); + data.push(view); + if (data.length > size) + data.shift().update(); + }; +}; + +var cache = new Cache(kCacheSize); var currentPageNumber = 1; var PDFView = { @@ -639,7 +652,8 @@ function updateViewarea() { var visiblePages = PDFView.getVisiblePages(); for (var i = 0; i < visiblePages.length; i++) { var page = visiblePages[i]; - PDFView.pages[page.id - 1].draw(); + if (PDFView.pages[page.id - 1].draw()) + cache.push(page.view); } if (!visiblePages.length) From 4369a1a84a8a18bbbcea4e180f8b9eb7fdb99b98 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Wed, 30 Nov 2011 15:20:14 -0500 Subject: [PATCH 03/14] make it work in WebKit --- web/viewer.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index dd49d75b7..2114ad3af 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -701,13 +701,9 @@ function updateThumbViewArea() { }, delay); } -sidebarScrollView.addEventListener('scroll', function thumbViewScroll(evt) { - updateThumbViewArea(); -}, true); - -window.addEventListener('transitionend', function webViewerTransitionend(evt) { - updateThumbViewArea(); -}, true); +sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true); +window.addEventListener('transitionend', updateThumbViewArea, true); +window.addEventListener('webkitTransitionEnd', updateThumbViewArea, true); window.addEventListener('resize', function webViewerResize(evt) { if (document.getElementById('pageWidthOption').selected || From 8dc467709d834fcf1674c47eb9a84835feb76d51 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Wed, 30 Nov 2011 16:14:22 -0500 Subject: [PATCH 04/14] bug fix --- web/viewer.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index b7c654ebf..6b82be6a1 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -568,8 +568,8 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { maxThumbSize * pageRatio; var canvasHeight = pageRatio <= 1 ? maxThumbSize : maxThumbSize / pageRatio; - this.scaleX = (canvasWidth / this.width); - this.scaleY = (canvasHeight / this.height); + var scaleX = this.scaleX = (canvasWidth / this.width); + var scaleY = this.scaleY = (canvasHeight / this.height); var div = document.createElement('div'); div.id = 'thumbnailContainer' + id; @@ -598,8 +598,6 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { ctx.restore(); var view = page.view; - var scaleX = this.scaleX; - var scaleY = this.scaleY; ctx.translate(-view.x * scaleX, -view.y * scaleY); div.style.width = (view.width * scaleX) + 'px'; div.style.height = (view.height * scaleY) + 'px'; From b1ed459443f05169b54bbdc631a7e2e21545a1e1 Mon Sep 17 00:00:00 2001 From: fixplz Date: Sat, 3 Dec 2011 00:33:00 +0200 Subject: [PATCH 05/14] Scan for startxref more than 1024 chars from end #828 --- src/core.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/core.js b/src/core.js index 6b7845efd..9c9be9218 100644 --- a/src/core.js +++ b/src/core.js @@ -382,11 +382,15 @@ var PDFDocModel = (function pdfDoc() { startXRef = stream.pos + 6; } else { // Find startxref at the end of the file. - var start = stream.end - 1024; - if (start < 0) - start = 0; - stream.pos = start; - if (find(stream, 'startxref', 1024, true)) { + var found = false, pos = stream.end; + while(!found && pos > 0) { + pos -= 1024; + if (pos < 0) + pos = 0; + stream.pos = pos; + found = find(stream, 'startxref', 1024, true); + } + if (found) { stream.skip(9); var ch; do { From 7fa9b5827a82eafd3b03b9fed5332c287f2ab3d3 Mon Sep 17 00:00:00 2001 From: fixplz Date: Sat, 3 Dec 2011 01:55:59 +0200 Subject: [PATCH 06/14] Avoid skipping over tag in startxref search --- src/core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.js b/src/core.js index 9c9be9218..3c0981954 100644 --- a/src/core.js +++ b/src/core.js @@ -384,7 +384,7 @@ var PDFDocModel = (function pdfDoc() { // Find startxref at the end of the file. var found = false, pos = stream.end; while(!found && pos > 0) { - pos -= 1024; + pos -= 1024 - 9; if (pos < 0) pos = 0; stream.pos = pos; From 5fd3647c576715f4c729fa5c99aa0098539be30c Mon Sep 17 00:00:00 2001 From: fixplz Date: Mon, 5 Dec 2011 00:00:22 +0200 Subject: [PATCH 07/14] Style fixes --- src/core.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core.js b/src/core.js index 3c0981954..32c13d8cf 100644 --- a/src/core.js +++ b/src/core.js @@ -381,14 +381,15 @@ var PDFDocModel = (function pdfDoc() { if (find(stream, 'endobj', 1024)) startXRef = stream.pos + 6; } else { - // Find startxref at the end of the file. + // Find startxref by jumping backward from the end of the file. + var step = 1024; var found = false, pos = stream.end; - while(!found && pos > 0) { - pos -= 1024 - 9; + while (!found && pos > 0) { + pos -= step - 'startxref'.length; if (pos < 0) pos = 0; stream.pos = pos; - found = find(stream, 'startxref', 1024, true); + found = find(stream, 'startxref', step, true); } if (found) { stream.skip(9); From 7d8240f15cb0315f5df1876197d5a5ce946d8f68 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Tue, 6 Dec 2011 16:52:29 -0500 Subject: [PATCH 08/14] Addressing comments, linting --- web/viewer.html | 51 ++++++++++++++++++++++++------------------------- web/viewer.js | 4 ++-- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/web/viewer.html b/web/viewer.html index 5164d0b19..08b75468f 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -3,32 +3,7 @@ Simple pdf.js page viewer - - - - - - - - - - - - - - - - - - - - - - - - - - +
@@ -119,6 +94,30 @@
Loading... 0%
+ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/viewer.js b/web/viewer.js index 6b82be6a1..f4088ec40 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -557,7 +557,7 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { PDFView.page = id; return false; }; - + var view = page.view; this.width = view.width; this.height = view.height; @@ -728,7 +728,7 @@ function updateThumbViewArea() { if (thumbnailTimer) clearTimeout(thumbnailTimer); - thumbnailTimer = setTimeout(function(){ + thumbnailTimer = setTimeout(function() { var visibleThumbs = PDFView.getVisibleThumbs(); for (var i = 0; i < visibleThumbs.length; i++) { var thumb = visibleThumbs[i]; From f239d01bde22a2b5c16e2d0be95b573b5e10668d Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Wed, 7 Dec 2011 00:18:40 +0200 Subject: [PATCH 09/14] Name constructors in obj.js. --- src/obj.js | 58 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/obj.js b/src/obj.js index 474b54336..b78964a63 100644 --- a/src/obj.js +++ b/src/obj.js @@ -3,34 +3,34 @@ 'use strict'; -var Name = (function nameName() { - function constructor(name) { +var Name = (function NameClosure() { + function Name(name) { this.name = name; } - constructor.prototype = { + Name.prototype = { }; - return constructor; + return Name; })(); -var Cmd = (function cmdCmd() { - function constructor(cmd) { +var Cmd = (function CmdClosure() { + function Cmd(cmd) { this.cmd = cmd; } - constructor.prototype = { + Cmd.prototype = { }; - return constructor; + return Cmd; })(); -var Dict = (function dictDict() { - function constructor() { +var Dict = (function DictClosure() { + function Dict() { this.map = Object.create(null); } - constructor.prototype = { + Dict.prototype = { get: function dictGet(key1, key2, key3) { var value; if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map || @@ -60,29 +60,29 @@ var Dict = (function dictDict() { } }; - return constructor; + return Dict; })(); -var Ref = (function refRef() { - function constructor(num, gen) { +var Ref = (function RefClosure() { + function Ref(num, gen) { this.num = num; this.gen = gen; } - constructor.prototype = { + Ref.prototype = { }; - return constructor; + return Ref; })(); // The reference is identified by number and generation, // this structure stores only one instance of the reference. -var RefSet = (function refSet() { - function constructor() { +var RefSet = (function RefSetClosure() { + function RefSet() { this.dict = {}; } - constructor.prototype = { + RefSet.prototype = { has: function refSetHas(ref) { return !!this.dict['R' + ref.num + '.' + ref.gen]; }, @@ -92,18 +92,18 @@ var RefSet = (function refSet() { } }; - return constructor; + return RefSet; })(); -var Catalog = (function catalogCatalog() { - function constructor(xref) { +var Catalog = (function CatalogClosure() { + function Catalog(xref) { this.xref = xref; var obj = xref.getCatalogObj(); assertWellFormed(isDict(obj), 'catalog object is not a dictionary'); this.catDict = obj; } - constructor.prototype = { + Catalog.prototype = { get toplevelPagesDict() { var pagesObj = this.catDict.get('Pages'); assertWellFormed(isRef(pagesObj), 'invalid top-level pages reference'); @@ -253,11 +253,11 @@ var Catalog = (function catalogCatalog() { } }; - return constructor; + return Catalog; })(); -var XRef = (function xRefXRef() { - function constructor(stream, startXRef, mainXRefEntriesOffset) { +var XRef = (function XRefClosure() { + function XRef(stream, startXRef, mainXRefEntriesOffset) { this.stream = stream; this.entries = []; this.xrefstms = {}; @@ -278,7 +278,7 @@ var XRef = (function xRefXRef() { error('Invalid root reference'); } - constructor.prototype = { + XRef.prototype = { readXRefTable: function readXRefTable(parser) { var obj; while (true) { @@ -642,7 +642,7 @@ var XRef = (function xRefXRef() { } }; - return constructor; + return XRef; })(); /** @@ -651,7 +651,7 @@ var XRef = (function xRefXRef() { * inside of a worker. The `PDFObjects` implements some basic functions to * manage these objects. */ -var PDFObjects = (function pdfObjects() { +var PDFObjects = (function PDFObjectsClosure() { function PDFObjects() { this.objs = {}; } From 2040c35001591a049aea53eb6fb14289eb26fac2 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Wed, 7 Dec 2011 08:52:13 -0500 Subject: [PATCH 10/14] Moved event binding to 'load' event --- web/viewer.html | 52 ++++++++++++++++++++++++------------------------- web/viewer.js | 5 +++-- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/web/viewer.html b/web/viewer.html index 08b75468f..be758dbb9 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -3,6 +3,32 @@ Simple pdf.js page viewer + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -93,31 +119,5 @@
Loading... 0%
- - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/web/viewer.js b/web/viewer.js index f4088ec40..7408182d8 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -678,6 +678,9 @@ window.addEventListener('load', function webViewerLoad(evt) { document.getElementById('fileInput').setAttribute('hidden', 'true'); else document.getElementById('fileInput').value = null; + + var sidebarScrollView = document.getElementById('sidebarScrollView'); + sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true); }, true); window.addEventListener('unload', function webViewerUnload(evt) { @@ -717,7 +720,6 @@ window.addEventListener('scroll', function webViewerScroll(evt) { }, true); -var sidebarScrollView = document.getElementById('sidebarScrollView'); var thumbnailTimer; function updateThumbViewArea() { @@ -737,7 +739,6 @@ function updateThumbViewArea() { }, delay); } -sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true); window.addEventListener('transitionend', updateThumbViewArea, true); window.addEventListener('webkitTransitionEnd', updateThumbViewArea, true); From 1ef4c94de20eaae4a1f010eb0660b693e1c71f51 Mon Sep 17 00:00:00 2001 From: Kalervo Kujala Date: Fri, 9 Dec 2011 00:18:43 +0200 Subject: [PATCH 11/14] Name all constructors. --- src/canvas.js | 16 ++--- src/colorspace.js | 66 +++++++++--------- src/core.js | 24 +++---- src/crypto.js | 44 ++++++------ src/evaluator.js | 16 ++--- src/fonts.js | 16 ++--- src/function.js | 2 +- src/image.js | 12 ++-- src/parser.js | 26 ++++---- src/pattern.js | 34 +++++----- src/stream.js | 166 ++++++++++++++++++++++++---------------------- src/util.js | 14 ++-- 12 files changed, 223 insertions(+), 213 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index 8fe497dd4..995899cf0 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -17,8 +17,8 @@ var TextRenderingMode = { ADD_TO_PATH: 7 }; -var CanvasExtraState = (function canvasExtraState() { - function constructor(old) { +var CanvasExtraState = (function CanvasExtraStateClosure() { + function CanvasExtraState(old) { // Are soft masks and alpha values shapes or opacities? this.alphaIsShape = false; this.fontSize = 0; @@ -52,7 +52,7 @@ var CanvasExtraState = (function canvasExtraState() { this.old = old; } - constructor.prototype = { + CanvasExtraState.prototype = { clone: function canvasextra_clone() { return Object.create(this); }, @@ -61,7 +61,7 @@ var CanvasExtraState = (function canvasExtraState() { this.y = y; } }; - return constructor; + return CanvasExtraState; })(); function ScratchCanvas(width, height) { @@ -181,12 +181,12 @@ function addContextCurrentTransform(ctx) { } } -var CanvasGraphics = (function canvasGraphics() { +var CanvasGraphics = (function CanvasGraphicsClosure() { // Defines the time the executeIRQueue is going to be executing // before it stops and shedules a continue of execution. var kExecutionTime = 50; - function constructor(canvasCtx, objs, textLayer) { + function CanvasGraphics(canvasCtx, objs, textLayer) { this.ctx = canvasCtx; this.current = new CanvasExtraState(); this.stateStack = []; @@ -206,7 +206,7 @@ var CanvasGraphics = (function canvasGraphics() { var NORMAL_CLIP = {}; var EO_CLIP = {}; - constructor.prototype = { + CanvasGraphics.prototype = { slowCommands: { 'stroke': true, 'closeStroke': true, @@ -1181,7 +1181,7 @@ var CanvasGraphics = (function canvasGraphics() { } }; - return constructor; + return CanvasGraphics; })(); if (!isWorker) { diff --git a/src/colorspace.js b/src/colorspace.js index b369d0f88..231ff6923 100644 --- a/src/colorspace.js +++ b/src/colorspace.js @@ -3,13 +3,13 @@ 'use strict'; -var ColorSpace = (function colorSpaceColorSpace() { +var ColorSpace = (function ColorSpaceClosure() { // Constructor should define this.numComps, this.defaultColor, this.name - function constructor() { + function ColorSpace() { error('should not call ColorSpace constructor'); } - constructor.prototype = { + ColorSpace.prototype = { // Input: array of size numComps representing color component values // Output: array of rgb values, each value ranging from [0.1] getRgb: function colorSpaceGetRgb(color) { @@ -22,15 +22,15 @@ var ColorSpace = (function colorSpaceColorSpace() { } }; - constructor.parse = function colorSpaceParse(cs, xref, res) { - var IR = constructor.parseToIR(cs, xref, res); + ColorSpace.parse = function colorSpaceParse(cs, xref, res) { + var IR = ColorSpace.parseToIR(cs, xref, res); if (IR instanceof AlternateCS) return IR; - return constructor.fromIR(IR); + return ColorSpace.fromIR(IR); }; - constructor.fromIR = function colorSpaceFromIR(IR) { + ColorSpace.fromIR = function colorSpaceFromIR(IR) { var name = isArray(IR) ? IR[0] : IR; switch (name) { @@ -63,7 +63,7 @@ var ColorSpace = (function colorSpaceColorSpace() { return null; }; - constructor.parseToIR = function colorSpaceParseToIR(cs, xref, res) { + ColorSpace.parseToIR = function colorSpaceParseToIR(cs, xref, res) { if (isName(cs)) { var colorSpaces = xref.fetchIfRef(res.get('ColorSpace')); if (isDict(colorSpaces)) { @@ -155,7 +155,7 @@ var ColorSpace = (function colorSpaceColorSpace() { return null; }; - return constructor; + return ColorSpace; })(); /** @@ -164,8 +164,8 @@ var ColorSpace = (function colorSpaceColorSpace() { * Both color spaces use a tinting function to convert colors to a base color * space. */ -var AlternateCS = (function alternateCS() { - function constructor(numComps, base, tintFn) { +var AlternateCS = (function AlternateCSClosure() { + function AlternateCS(numComps, base, tintFn) { this.name = 'Alternate'; this.numComps = numComps; this.defaultColor = []; @@ -175,7 +175,7 @@ var AlternateCS = (function alternateCS() { this.tintFn = tintFn; } - constructor.prototype = { + AlternateCS.prototype = { getRgb: function altcs_getRgb(color) { var tinted = this.tintFn(color); return this.base.getRgb(tinted); @@ -203,21 +203,21 @@ var AlternateCS = (function alternateCS() { } }; - return constructor; + return AlternateCS; })(); -var PatternCS = (function patternCS() { - function constructor(baseCS) { +var PatternCS = (function PatternCSClosure() { + function PatternCS(baseCS) { this.name = 'Pattern'; this.base = baseCS; } - constructor.prototype = {}; + PatternCS.prototype = {}; - return constructor; + return PatternCS; })(); -var IndexedCS = (function indexedCS() { - function constructor(base, highVal, lookup) { +var IndexedCS = (function IndexedCSClosure() { + function IndexedCS(base, highVal, lookup) { this.name = 'Indexed'; this.numComps = 1; this.defaultColor = [0]; @@ -240,7 +240,7 @@ var IndexedCS = (function indexedCS() { this.lookup = lookupArray; } - constructor.prototype = { + IndexedCS.prototype = { getRgb: function indexcs_getRgb(color) { var numComps = this.base.numComps; var start = color[0] * numComps; @@ -269,17 +269,17 @@ var IndexedCS = (function indexedCS() { return base.getRgbBuffer(baseBuf, 8); } }; - return constructor; + return IndexedCS; })(); -var DeviceGrayCS = (function deviceGrayCS() { - function constructor() { +var DeviceGrayCS = (function DeviceGrayCSClosure() { + function DeviceGrayCS() { this.name = 'DeviceGray'; this.numComps = 1; this.defaultColor = [0]; } - constructor.prototype = { + DeviceGrayCS.prototype = { getRgb: function graycs_getRgb(color) { var c = color[0]; return [c, c, c]; @@ -297,16 +297,16 @@ var DeviceGrayCS = (function deviceGrayCS() { return rgbBuf; } }; - return constructor; + return DeviceGrayCS; })(); -var DeviceRgbCS = (function deviceRgbCS() { - function constructor() { +var DeviceRgbCS = (function DeviceRgbCSClosure() { + function DeviceRgbCS() { this.name = 'DeviceRGB'; this.numComps = 3; this.defaultColor = [0, 0, 0]; } - constructor.prototype = { + DeviceRgbCS.prototype = { getRgb: function rgbcs_getRgb(color) { return color; }, @@ -321,16 +321,16 @@ var DeviceRgbCS = (function deviceRgbCS() { return rgbBuf; } }; - return constructor; + return DeviceRgbCS; })(); -var DeviceCmykCS = (function deviceCmykCS() { - function constructor() { +var DeviceCmykCS = (function DeviceCmykCSClosure() { + function DeviceCmykCS() { this.name = 'DeviceCMYK'; this.numComps = 4; this.defaultColor = [0, 0, 0, 1]; } - constructor.prototype = { + DeviceCmykCS.prototype = { getRgb: function cmykcs_getRgb(color) { var c = color[0], m = color[1], y = color[2], k = color[3]; var c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k; @@ -406,6 +406,6 @@ var DeviceCmykCS = (function deviceCmykCS() { } }; - return constructor; + return DeviceCmykCS; })(); diff --git a/src/core.js b/src/core.js index 55c68352d..5cefaac68 100644 --- a/src/core.js +++ b/src/core.js @@ -56,8 +56,8 @@ function getPdf(arg, callback) { } globalScope.PDFJS.getPdf = getPdf; -var Page = (function pagePage() { - function constructor(xref, pageNumber, pageDict, ref) { +var Page = (function PageClosure() { + function Page(xref, pageNumber, pageDict, ref) { this.pageNumber = pageNumber; this.pageDict = pageDict; this.stats = { @@ -74,7 +74,7 @@ var Page = (function pagePage() { this.callback = null; } - constructor.prototype = { + Page.prototype = { getPageProp: function pageGetPageProp(key) { return this.xref.fetchIfRef(this.pageDict.get(key)); }, @@ -325,7 +325,7 @@ var Page = (function pagePage() { } }; - return constructor; + return Page; })(); /** @@ -338,8 +338,8 @@ var Page = (function pagePage() { * need for the `PDFDocModel` anymore and there is only one object on the * main thread and not one entire copy on each worker instance. */ -var PDFDocModel = (function pdfDoc() { - function constructor(arg, callback) { +var PDFDocModel = (function PDFDocModelClosure() { + function PDFDocModel(arg, callback) { if (isStream(arg)) init.call(this, arg); else if (isArrayBuffer(arg)) @@ -370,7 +370,7 @@ var PDFDocModel = (function pdfDoc() { return true; /* found */ } - constructor.prototype = { + PDFDocModel.prototype = { get linearization() { var length = this.stream.length; var linearization = false; @@ -454,11 +454,11 @@ var PDFDocModel = (function pdfDoc() { } }; - return constructor; + return PDFDocModel; })(); -var PDFDoc = (function pdfDoc() { - function constructor(arg, callback) { +var PDFDoc = (function PDFDocClosure() { + function PDFDoc(arg, callback) { var stream = null; var data = null; @@ -526,7 +526,7 @@ var PDFDoc = (function pdfDoc() { } } - constructor.prototype = { + PDFDoc.prototype = { setupFakeWorker: function() { // If we don't use a worker, just post/sendMessage to the main thread. var fakeWorker = { @@ -655,7 +655,7 @@ var PDFDoc = (function pdfDoc() { } }; - return constructor; + return PDFDoc; })(); globalScope.PDFJS.PDFDoc = PDFDoc; diff --git a/src/crypto.js b/src/crypto.js index 955598644..7c34a8506 100644 --- a/src/crypto.js +++ b/src/crypto.js @@ -3,8 +3,8 @@ 'use strict'; -var ARCFourCipher = (function arcFourCipher() { - function constructor(key) { +var ARCFourCipher = (function ARCFourCipherClosure() { + function ARCFourCipher(key) { this.a = 0; this.b = 0; var s = new Uint8Array(256); @@ -20,7 +20,7 @@ var ARCFourCipher = (function arcFourCipher() { this.s = s; } - constructor.prototype = { + ARCFourCipher.prototype = { encryptBlock: function arcFourCipherEncryptBlock(data) { var i, n = data.length, tmp, tmp2; var a = this.a, b = this.b, s = this.s; @@ -39,12 +39,12 @@ var ARCFourCipher = (function arcFourCipher() { return output; } }; - constructor.prototype.decryptBlock = constructor.prototype.encryptBlock; + ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock; - return constructor; + return ARCFourCipher; })(); -var calculateMD5 = (function calculateMD5() { +var calculateMD5 = (function calculateMD5Closure() { 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, @@ -128,20 +128,20 @@ var calculateMD5 = (function calculateMD5() { return hash; })(); -var NullCipher = (function nullCipher() { - function constructor() { +var NullCipher = (function NullCipherClosure() { + function NullCipher() { } - constructor.prototype = { + NullCipher.prototype = { decryptBlock: function nullCipherDecryptBlock(data) { return data; } }; - return constructor; + return NullCipher; })(); -var AES128Cipher = (function aes128Cipher() { +var AES128Cipher = (function AES128CipherClosure() { 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, @@ -330,7 +330,7 @@ var AES128Cipher = (function aes128Cipher() { return state; } - function constructor(key) { + function AES128Cipher(key) { this.key = expandKey128(key); this.buffer = new Uint8Array(16); this.bufferPosition = 0; @@ -370,7 +370,7 @@ var AES128Cipher = (function aes128Cipher() { return output; } - constructor.prototype = { + AES128Cipher.prototype = { decryptBlock: function aes128CipherDecryptBlock(data) { var i, sourceLength = data.length; var buffer = this.buffer, bufferLength = this.bufferPosition; @@ -391,15 +391,15 @@ var AES128Cipher = (function aes128Cipher() { } }; - return constructor; + return AES128Cipher; })(); -var CipherTransform = (function cipherTransform() { - function constructor(stringCipherConstructor, streamCipherConstructor) { +var CipherTransform = (function CipherTransformClosure() { + function CipherTransform(stringCipherConstructor, streamCipherConstructor) { this.stringCipherConstructor = stringCipherConstructor; this.streamCipherConstructor = streamCipherConstructor; } - constructor.prototype = { + CipherTransform.prototype = { createStream: function cipherTransformCreateStream(stream) { var cipher = new this.streamCipherConstructor(); return new DecryptStream(stream, @@ -415,10 +415,10 @@ var CipherTransform = (function cipherTransform() { return bytesToString(data); } }; - return constructor; + return CipherTransform; })(); -var CipherTransformFactory = (function cipherTransformFactory() { +var CipherTransformFactory = (function CipherTransformFactoryClosure() { function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) { var defaultPasswordBytes = new Uint8Array([ @@ -490,7 +490,7 @@ var CipherTransformFactory = (function cipherTransformFactory() { var identityName = new Name('Identity'); - function constructor(dict, fileId, password) { + function CipherTransformFactory(dict, fileId, password) { var filter = dict.get('Filter'); if (!isName(filter) || filter.name != 'Standard') error('unknown encryption method'); @@ -573,7 +573,7 @@ var CipherTransformFactory = (function cipherTransformFactory() { return null; } - constructor.prototype = { + CipherTransformFactory.prototype = { createCipherTransform: function buildCipherCreateCipherTransform(num, gen) { if (this.algorithm == 4) { @@ -592,6 +592,6 @@ var CipherTransformFactory = (function cipherTransformFactory() { } }; - return constructor; + return CipherTransformFactory; })(); diff --git a/src/evaluator.js b/src/evaluator.js index 954c3bec3..a5ca627c5 100644 --- a/src/evaluator.js +++ b/src/evaluator.js @@ -3,8 +3,8 @@ 'use strict'; -var PartialEvaluator = (function partialEvaluator() { - function constructor(xref, handler, uniquePrefix) { +var PartialEvaluator = (function PartialEvaluatorClosure() { + function PartialEvaluator(xref, handler, uniquePrefix) { this.state = new EvalState(); this.stateStack = []; @@ -111,7 +111,7 @@ var PartialEvaluator = (function partialEvaluator() { EX: 'endCompat' }; - constructor.prototype = { + PartialEvaluator.prototype = { getIRQueue: function partialEvaluatorGetIRQueue(stream, resources, queue, dependency) { @@ -858,11 +858,11 @@ var PartialEvaluator = (function partialEvaluator() { } }; - return constructor; + return PartialEvaluator; })(); -var EvalState = (function evalState() { - function constructor() { +var EvalState = (function EvalStateClosure() { + function EvalState() { // Are soft masks and alpha values shapes or opacities? this.alphaIsShape = false; this.fontSize = 0; @@ -879,8 +879,8 @@ var EvalState = (function evalState() { this.fillColorSpace = null; this.strokeColorSpace = null; } - constructor.prototype = { + EvalState.prototype = { }; - return constructor; + return EvalState; })(); diff --git a/src/fonts.js b/src/fonts.js index fd461bce5..a80cd15f7 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -731,8 +731,8 @@ function isSpecialUnicode(unicode) { * var type1Font = new Font("MyFontName", binaryFile, propertiesObject); * type1Font.bind(); */ -var Font = (function Font() { - var constructor = function font_constructor(name, file, properties) { +var Font = (function FontClosure() { + function Font(name, file, properties) { this.name = name; this.coded = properties.coded; this.charProcIRQueues = properties.charProcIRQueues; @@ -1222,7 +1222,7 @@ var Font = (function Font() { return nameTable; } - constructor.prototype = { + Font.prototype = { name: null, font: null, mimetype: null, @@ -2204,7 +2204,7 @@ var Font = (function Font() { } }; - return constructor; + return Font; })(); /* @@ -3114,9 +3114,9 @@ CFF.prototype = { } }; -var Type2CFF = (function type2CFF() { +var Type2CFF = (function Type2CFFClosure() { // TODO: replace parsing code with the Type2Parser in font_utils.js - function constructor(file, properties) { + function Type2CFF(file, properties) { var bytes = file.getBytes(); this.bytes = bytes; this.properties = properties; @@ -3124,7 +3124,7 @@ var Type2CFF = (function type2CFF() { this.data = this.parse(); } - constructor.prototype = { + Type2CFF.prototype = { parse: function cff_parse() { var header = this.parseHeader(); var properties = this.properties; @@ -3668,6 +3668,6 @@ var Type2CFF = (function type2CFF() { } }; - return constructor; + return Type2CFF; })(); diff --git a/src/function.js b/src/function.js index ef24736c1..6b0063218 100644 --- a/src/function.js +++ b/src/function.js @@ -3,7 +3,7 @@ 'use strict'; -var PDFFunction = (function pdfFunction() { +var PDFFunction = (function PDFFunctionClosure() { var CONSTRUCT_SAMPLED = 0; var CONSTRUCT_INTERPOLATED = 2; var CONSTRUCT_STICHED = 3; diff --git a/src/image.js b/src/image.js index 17ef7b06d..0688d07ef 100644 --- a/src/image.js +++ b/src/image.js @@ -3,8 +3,8 @@ 'use strict'; -var PDFImage = (function pdfImage() { - function constructor(xref, res, image, inline) { +var PDFImage = (function PDFImageClosure() { + function PDFImage(xref, res, image, inline) { this.image = image; if (image.getParams) { // JPX/JPEG2000 streams directly contain bits per component @@ -60,7 +60,7 @@ var PDFImage = (function pdfImage() { } } - constructor.prototype = { + PDFImage.prototype = { getComponents: function getComponents(buffer, decodeMap) { var bpc = this.bpc; if (bpc == 8) @@ -226,15 +226,15 @@ var PDFImage = (function pdfImage() { buffer[i] = comps[i]; } }; - return constructor; + return PDFImage; })(); -var JpegImageLoader = (function jpegImage() { +var JpegImageLoader = (function JpegImageLoaderClosure() { function JpegImageLoader(objId, imageData, objs) { var src = 'data:image/jpeg;base64,' + window.btoa(imageData); var img = new Image(); - img.onload = (function jpegImageLoaderOnload() { + img.onload = (function onloadClosure() { this.loaded = true; objs.resolve(objId, this); diff --git a/src/parser.js b/src/parser.js index 036191677..6ffae0b1c 100644 --- a/src/parser.js +++ b/src/parser.js @@ -9,8 +9,8 @@ function isEOF(v) { return v == EOF; } -var Parser = (function parserParser() { - function constructor(lexer, allowStreams, xref) { +var Parser = (function ParserClosure() { + function Parser(lexer, allowStreams, xref) { this.lexer = lexer; this.allowStreams = allowStreams; this.xref = xref; @@ -18,7 +18,7 @@ var Parser = (function parserParser() { this.refill(); } - constructor.prototype = { + Parser.prototype = { refill: function parserRefill() { this.buf1 = this.lexer.getObj(); this.buf2 = this.lexer.getObj(); @@ -254,15 +254,15 @@ var Parser = (function parserParser() { } }; - return constructor; + return Parser; })(); -var Lexer = (function lexer() { - function constructor(stream) { +var Lexer = (function LexerClosure() { + function Lexer(stream) { this.stream = stream; } - constructor.isSpace = function lexerIsSpace(ch) { + Lexer.isSpace = function lexerIsSpace(ch) { return ch == ' ' || ch == '\t' || ch == '\x0d' || ch == '\x0a'; }; @@ -296,7 +296,7 @@ var Lexer = (function lexer() { return -1; } - constructor.prototype = { + Lexer.prototype = { getNumber: function lexerGetNumber(ch) { var floating = false; var str = ch; @@ -558,11 +558,11 @@ var Lexer = (function lexer() { } }; - return constructor; + return Lexer; })(); -var Linearization = (function linearizationLinearization() { - function constructor(stream) { +var Linearization = (function LinearizationClosure() { + function Linearization(stream) { this.parser = new Parser(new Lexer(stream), false); var obj1 = this.parser.getObj(); var obj2 = this.parser.getObj(); @@ -576,7 +576,7 @@ var Linearization = (function linearizationLinearization() { } } - constructor.prototype = { + Linearization.prototype = { getInt: function linearizationGetInt(name) { var linDict = this.linDict; var obj; @@ -635,6 +635,6 @@ var Linearization = (function linearizationLinearization() { } }; - return constructor; + return Linearization; })(); diff --git a/src/pattern.js b/src/pattern.js index 9e2dca17a..bf68253b3 100644 --- a/src/pattern.js +++ b/src/pattern.js @@ -8,13 +8,13 @@ var PatternType = { RADIAL: 3 }; -var Pattern = (function patternPattern() { +var Pattern = (function PatternClosure() { // Constructor should define this.getPattern - function constructor() { + function Pattern() { error('should not call Pattern constructor'); } - constructor.prototype = { + Pattern.prototype = { // Input: current Canvas context // Output: the appropriate fillStyle or strokeStyle getPattern: function pattern_getStyle(ctx) { @@ -22,11 +22,11 @@ var Pattern = (function patternPattern() { } }; - constructor.shadingFromIR = function pattern_shadingFromIR(ctx, raw) { + Pattern.shadingFromIR = function pattern_shadingFromIR(ctx, raw) { return Shadings[raw[0]].fromIR(ctx, raw); }; - constructor.parseShading = function pattern_shading(shading, matrix, xref, + Pattern.parseShading = function pattern_shading(shading, matrix, xref, res, ctx) { var dict = isStream(shading) ? shading.dict : shading; @@ -41,15 +41,15 @@ var Pattern = (function patternPattern() { return new Shadings.Dummy(); } }; - return constructor; + return Pattern; })(); var Shadings = {}; // Radial and axial shading have very similar implementations // If needed, the implementations can be broken into two classes -Shadings.RadialAxial = (function radialAxialShading() { - function constructor(dict, matrix, xref, res, ctx) { +Shadings.RadialAxial = (function RadialAxialClosure() { + function RadialAxial(dict, matrix, xref, res, ctx) { this.matrix = matrix; this.coordsArr = dict.get('Coords'); this.shadingType = dict.get('ShadingType'); @@ -102,7 +102,7 @@ Shadings.RadialAxial = (function radialAxialShading() { this.colorStops = colorStops; } - constructor.fromIR = function radialAxialShadingGetIR(ctx, raw) { + RadialAxial.fromIR = function radialAxialShadingGetIR(ctx, raw) { var type = raw[1]; var colorStops = raw[2]; var p0 = raw[3]; @@ -134,7 +134,7 @@ Shadings.RadialAxial = (function radialAxialShading() { return grad; }; - constructor.prototype = { + RadialAxial.prototype = { getIR: function radialAxialShadingGetIR() { var coordsArr = this.coordsArr; var type = this.shadingType; @@ -162,27 +162,27 @@ Shadings.RadialAxial = (function radialAxialShading() { } }; - return constructor; + return RadialAxial; })(); -Shadings.Dummy = (function dummyShading() { - function constructor() { +Shadings.Dummy = (function DummyClosure() { + function Dummy() { this.type = 'Pattern'; } - constructor.fromIR = function dummyShadingFromIR() { + Dummy.fromIR = function dummyShadingFromIR() { return 'hotpink'; }; - constructor.prototype = { + Dummy.prototype = { getIR: function dummyShadingGetIR() { return ['Dummy']; } }; - return constructor; + return Dummy; })(); -var TilingPattern = (function tilingPattern() { +var TilingPattern = (function TilingPatternClosure() { var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; function TilingPattern(IR, color, ctx, objs) { diff --git a/src/stream.js b/src/stream.js index 559fb2ca2..d996f5c91 100644 --- a/src/stream.js +++ b/src/stream.js @@ -3,8 +3,8 @@ 'use strict'; -var Stream = (function streamStream() { - function constructor(arrayBuffer, start, length, dict) { +var Stream = (function StreamClosure() { + function Stream(arrayBuffer, start, length, dict) { this.bytes = new Uint8Array(arrayBuffer); this.start = start || 0; this.pos = this.start; @@ -14,7 +14,7 @@ var Stream = (function streamStream() { // required methods for a stream. if a particular stream does not // implement these, an error should be thrown - constructor.prototype = { + Stream.prototype = { get length() { return this.end - this.start; }, @@ -67,11 +67,11 @@ var Stream = (function streamStream() { isStream: true }; - return constructor; + return Stream; })(); -var StringStream = (function stringStream() { - function constructor(str) { +var StringStream = (function StringStreamClosure() { + function StringStream(str) { var length = str.length; var bytes = new Uint8Array(length); for (var n = 0; n < length; ++n) @@ -79,21 +79,21 @@ var StringStream = (function stringStream() { Stream.call(this, bytes); } - constructor.prototype = Stream.prototype; + StringStream.prototype = Stream.prototype; - return constructor; + return StringStream; })(); // super class for the decoding streams -var DecodeStream = (function decodeStream() { - function constructor() { +var DecodeStream = (function DecodeStreamClosure() { + function DecodeStream() { this.pos = 0; this.bufferLength = 0; this.eof = false; this.buffer = null; } - constructor.prototype = { + DecodeStream.prototype = { ensureBuffer: function decodestream_ensureBuffer(requested) { var buffer = this.buffer; var current = buffer ? buffer.byteLength : 0; @@ -178,24 +178,24 @@ var DecodeStream = (function decodeStream() { } }; - return constructor; + return DecodeStream; })(); -var FakeStream = (function fakeStream() { - function constructor(stream) { +var FakeStream = (function FakeStreamClosure() { + function FakeStream(stream) { this.dict = stream.dict; DecodeStream.call(this); } - constructor.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.readBlock = function fakeStreamReadBlock() { + FakeStream.prototype = Object.create(DecodeStream.prototype); + FakeStream.prototype.readBlock = function fakeStreamReadBlock() { var bufferLength = this.bufferLength; bufferLength += 1024; var buffer = this.ensureBuffer(bufferLength); this.bufferLength = bufferLength; }; - constructor.prototype.getBytes = function fakeStreamGetBytes(length) { + FakeStream.prototype.getBytes = function fakeStreamGetBytes(length) { var end, pos = this.pos; if (length) { @@ -217,18 +217,20 @@ var FakeStream = (function fakeStream() { return this.buffer.subarray(pos, end); }; - return constructor; + return FakeStream; })(); -var StreamsSequenceStream = (function streamSequenceStream() { - function constructor(streams) { +var StreamsSequenceStream = (function StreamsSequenceStreamClosure() { + function StreamsSequenceStream(streams) { this.streams = streams; DecodeStream.call(this); } - constructor.prototype = Object.create(DecodeStream.prototype); + StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype); + + StreamsSequenceStream.prototype.readBlock = + function streamSequenceStreamReadBlock() { - constructor.prototype.readBlock = function streamSequenceStreamReadBlock() { var streams = this.streams; if (streams.length == 0) { this.eof = true; @@ -243,10 +245,10 @@ var StreamsSequenceStream = (function streamSequenceStream() { this.bufferLength = newLength; }; - return constructor; + return StreamsSequenceStream; })(); -var FlateStream = (function flateStream() { +var FlateStream = (function FlateStreamClosure() { var codeLenCodeMap = new Uint32Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]); @@ -339,7 +341,7 @@ var FlateStream = (function flateStream() { 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 ]), 5]; - function constructor(stream) { + function FlateStream(stream) { var bytes = stream.getBytes(); var bytesPos = 0; @@ -364,9 +366,9 @@ var FlateStream = (function flateStream() { DecodeStream.call(this); } - constructor.prototype = Object.create(DecodeStream.prototype); + FlateStream.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.getBits = function flateStreamGetBits(bits) { + FlateStream.prototype.getBits = function flateStreamGetBits(bits) { var codeSize = this.codeSize; var codeBuf = this.codeBuf; var bytes = this.bytes; @@ -386,7 +388,7 @@ var FlateStream = (function flateStream() { return b; }; - constructor.prototype.getCode = function flateStreamGetCode(table) { + FlateStream.prototype.getCode = function flateStreamGetCode(table) { var codes = table[0]; var maxLen = table[1]; var codeSize = this.codeSize; @@ -412,7 +414,7 @@ var FlateStream = (function flateStream() { return codeVal; }; - constructor.prototype.generateHuffmanTable = + FlateStream.prototype.generateHuffmanTable = function flateStreamGenerateHuffmanTable(lengths) { var n = lengths.length; @@ -451,7 +453,7 @@ var FlateStream = (function flateStream() { return [codes, maxLen]; }; - constructor.prototype.readBlock = function flateStreamReadBlock() { + FlateStream.prototype.readBlock = function flateStreamReadBlock() { // read block header var hdr = this.getBits(3); if (hdr & 1) @@ -582,11 +584,11 @@ var FlateStream = (function flateStream() { } }; - return constructor; + return FlateStream; })(); -var PredictorStream = (function predictorStream() { - function constructor(stream, params) { +var PredictorStream = (function PredictorStreamClosure() { + function PredictorStream(stream, params) { var predictor = this.predictor = params.get('Predictor') || 1; if (predictor <= 1) @@ -613,9 +615,9 @@ var PredictorStream = (function predictorStream() { return this; } - constructor.prototype = Object.create(DecodeStream.prototype); + PredictorStream.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.readBlockTiff = + PredictorStream.prototype.readBlockTiff = function predictorStreamReadBlockTiff() { var rowBytes = this.rowBytes; @@ -676,7 +678,9 @@ var PredictorStream = (function predictorStream() { this.bufferLength += rowBytes; }; - constructor.prototype.readBlockPng = function predictorStreamReadBlockPng() { + PredictorStream.prototype.readBlockPng = + function predictorStreamReadBlockPng() { + var rowBytes = this.rowBytes; var pixBytes = this.pixBytes; @@ -753,7 +757,7 @@ var PredictorStream = (function predictorStream() { this.bufferLength += rowBytes; }; - return constructor; + return PredictorStream; })(); /** @@ -763,7 +767,7 @@ var PredictorStream = (function predictorStream() { * a library to decode these images and the stream behaves like all the other * DecodeStreams. */ -var JpegStream = (function jpegStream() { +var JpegStream = (function JpegStreamClosure() { function isAdobeImage(bytes) { var maxBytesScanned = Math.max(bytes.length - 16, 1024); // Looking for APP14, 'Adobe' @@ -794,7 +798,7 @@ var JpegStream = (function jpegStream() { return newBytes; } - function constructor(bytes, dict, xref) { + function JpegStream(bytes, dict, xref) { // TODO: per poppler, some images may have 'junk' before that // need to be removed this.dict = dict; @@ -825,9 +829,9 @@ var JpegStream = (function jpegStream() { DecodeStream.call(this); } - constructor.prototype = Object.create(DecodeStream.prototype); + JpegStream.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) { + JpegStream.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) { if (this.bufferLength) return; var jpegImage = new JpegImage(); @@ -839,18 +843,18 @@ var JpegStream = (function jpegStream() { this.buffer = data; this.bufferLength = data.length; }; - constructor.prototype.getIR = function jpegStreamGetIR() { + JpegStream.prototype.getIR = function jpegStreamGetIR() { return this.src; }; - constructor.prototype.getChar = function jpegStreamGetChar() { + JpegStream.prototype.getChar = function jpegStreamGetChar() { error('internal error: getChar is not valid on JpegStream'); }; - return constructor; + return JpegStream; })(); -var DecryptStream = (function decryptStream() { - function constructor(str, decrypt) { +var DecryptStream = (function DecryptStreamClosure() { + function DecryptStream(str, decrypt) { this.str = str; this.dict = str.dict; this.decrypt = decrypt; @@ -860,9 +864,9 @@ var DecryptStream = (function decryptStream() { var chunkSize = 512; - constructor.prototype = Object.create(DecodeStream.prototype); + DecryptStream.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.readBlock = function decryptStreamReadBlock() { + DecryptStream.prototype.readBlock = function decryptStreamReadBlock() { var chunk = this.str.getBytes(chunkSize); if (!chunk || chunk.length == 0) { this.eof = true; @@ -879,11 +883,11 @@ var DecryptStream = (function decryptStream() { this.bufferLength = bufferLength; }; - return constructor; + return DecryptStream; })(); -var Ascii85Stream = (function ascii85Stream() { - function constructor(str) { +var Ascii85Stream = (function Ascii85StreamClosure() { + function Ascii85Stream(str) { this.str = str; this.dict = str.dict; this.input = new Uint8Array(5); @@ -891,9 +895,9 @@ var Ascii85Stream = (function ascii85Stream() { DecodeStream.call(this); } - constructor.prototype = Object.create(DecodeStream.prototype); + Ascii85Stream.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.readBlock = function ascii85StreamReadBlock() { + Ascii85Stream.prototype.readBlock = function ascii85StreamReadBlock() { var tildaCode = '~'.charCodeAt(0); var zCode = 'z'.charCodeAt(0); var str = this.str; @@ -948,11 +952,11 @@ var Ascii85Stream = (function ascii85Stream() { } }; - return constructor; + return Ascii85Stream; })(); -var AsciiHexStream = (function asciiHexStream() { - function constructor(str) { +var AsciiHexStream = (function AsciiHexStreamClosure() { + function AsciiHexStream(str) { this.str = str; this.dict = str.dict; @@ -986,9 +990,9 @@ var AsciiHexStream = (function asciiHexStream() { 102: 15 }; - constructor.prototype = Object.create(DecodeStream.prototype); + AsciiHexStream.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.readBlock = function asciiHexStreamReadBlock() { + AsciiHexStream.prototype.readBlock = function asciiHexStreamReadBlock() { var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, decodeLength, buffer, bufferLength, i, length; @@ -1018,10 +1022,10 @@ var AsciiHexStream = (function asciiHexStream() { this.eof = true; }; - return constructor; + return AsciiHexStream; })(); -var CCITTFaxStream = (function ccittFaxStream() { +var CCITTFaxStream = (function CCITTFaxStreamClosure() { var ccittEOL = -2; var twoDimPass = 0; @@ -1449,7 +1453,7 @@ var CCITTFaxStream = (function ccittFaxStream() { [2, 2], [2, 2], [2, 2], [2, 2] ]; - function constructor(str, params) { + function CCITTFaxStream(str, params) { this.str = str; this.dict = str.dict; @@ -1494,9 +1498,9 @@ var CCITTFaxStream = (function ccittFaxStream() { DecodeStream.call(this); } - constructor.prototype = Object.create(DecodeStream.prototype); + CCITTFaxStream.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.readBlock = function ccittFaxStreamReadBlock() { + CCITTFaxStream.prototype.readBlock = function ccittFaxStreamReadBlock() { while (!this.eof) { var c = this.lookChar(); this.buf = EOF; @@ -1505,7 +1509,7 @@ var CCITTFaxStream = (function ccittFaxStream() { } }; - constructor.prototype.addPixels = + CCITTFaxStream.prototype.addPixels = function ccittFaxStreamAddPixels(a1, blackPixels) { var codingLine = this.codingLine; var codingPos = this.codingPos; @@ -1525,7 +1529,7 @@ var CCITTFaxStream = (function ccittFaxStream() { this.codingPos = codingPos; }; - constructor.prototype.addPixelsNeg = + CCITTFaxStream.prototype.addPixelsNeg = function ccittFaxStreamAddPixelsNeg(a1, blackPixels) { var codingLine = this.codingLine; var codingPos = this.codingPos; @@ -1554,7 +1558,7 @@ var CCITTFaxStream = (function ccittFaxStream() { this.codingPos = codingPos; }; - constructor.prototype.lookChar = function ccittFaxStreamLookChar() { + CCITTFaxStream.prototype.lookChar = function ccittFaxStreamLookChar() { if (this.buf != EOF) return this.buf; @@ -1873,7 +1877,9 @@ var CCITTFaxStream = (function ccittFaxStream() { return [false, 0, false]; }; - constructor.prototype.getTwoDimCode = function ccittFaxStreamGetTwoDimCode() { + CCITTFaxStream.prototype.getTwoDimCode = + function ccittFaxStreamGetTwoDimCode() { + var code = 0; var p; if (this.eoblock) { @@ -1892,7 +1898,9 @@ var CCITTFaxStream = (function ccittFaxStream() { return EOF; }; - constructor.prototype.getWhiteCode = function ccittFaxStreamGetWhiteCode() { + CCITTFaxStream.prototype.getWhiteCode = + function ccittFaxStreamGetWhiteCode() { + var code = 0; var p; var n; @@ -1924,7 +1932,9 @@ var CCITTFaxStream = (function ccittFaxStream() { return 1; }; - constructor.prototype.getBlackCode = function ccittFaxStreamGetBlackCode() { + CCITTFaxStream.prototype.getBlackCode = + function ccittFaxStreamGetBlackCode() { + var code, p; if (this.eoblock) { code = this.lookBits(13); @@ -1959,7 +1969,7 @@ var CCITTFaxStream = (function ccittFaxStream() { return 1; }; - constructor.prototype.lookBits = function ccittFaxStreamLookBits(n) { + CCITTFaxStream.prototype.lookBits = function ccittFaxStreamLookBits(n) { var c; while (this.inputBits < n) { if ((c = this.str.getByte()) == null) { @@ -1974,16 +1984,16 @@ var CCITTFaxStream = (function ccittFaxStream() { return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n)); }; - constructor.prototype.eatBits = function ccittFaxStreamEatBits(n) { + CCITTFaxStream.prototype.eatBits = function ccittFaxStreamEatBits(n) { if ((this.inputBits -= n) < 0) this.inputBits = 0; }; - return constructor; + return CCITTFaxStream; })(); -var LZWStream = (function lzwStream() { - function constructor(str, earlyChange) { +var LZWStream = (function LZWStreamClosure() { + function LZWStream(str, earlyChange) { this.str = str; this.dict = str.dict; this.cachedData = 0; @@ -2009,9 +2019,9 @@ var LZWStream = (function lzwStream() { DecodeStream.call(this); } - constructor.prototype = Object.create(DecodeStream.prototype); + LZWStream.prototype = Object.create(DecodeStream.prototype); - constructor.prototype.readBits = function lzwStreamReadBits(n) { + LZWStream.prototype.readBits = function lzwStreamReadBits(n) { var bitsCached = this.bitsCached; var cachedData = this.cachedData; while (bitsCached < n) { @@ -2029,7 +2039,7 @@ var LZWStream = (function lzwStream() { return (cachedData >>> bitsCached) & ((1 << n) - 1); }; - constructor.prototype.readBlock = function lzwStreamReadBlock() { + LZWStream.prototype.readBlock = function lzwStreamReadBlock() { var blockSize = 512; var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize; var i, j, q; @@ -2108,6 +2118,6 @@ var LZWStream = (function lzwStream() { this.bufferLength = currentBufferLength; }; - return constructor; + return LZWStream; })(); diff --git a/src/util.js b/src/util.js index 4fb96f062..88b9f0b45 100644 --- a/src/util.js +++ b/src/util.js @@ -76,24 +76,24 @@ function stringToBytes(str) { var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; -var Util = (function utilUtil() { - function constructor() {} - constructor.makeCssRgb = function makergb(r, g, b) { +var Util = (function UtilClosure() { + function Util() {} + Util.makeCssRgb = function makergb(r, g, b) { var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; }; - constructor.makeCssCmyk = function makecmyk(c, m, y, k) { + Util.makeCssCmyk = function makecmyk(c, m, y, k) { c = (new DeviceCmykCS()).getRgb([c, m, y, k]); var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0; return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; }; - constructor.applyTransform = function apply(p, m) { + Util.applyTransform = function apply(p, m) { var xt = p[0] * m[0] + p[1] * m[2] + m[4]; var yt = p[0] * m[1] + p[1] * m[3] + m[5]; return [xt, yt]; }; - return constructor; + return Util; })(); var PDFStringTranslateTable = [ @@ -197,7 +197,7 @@ function isPDFFunction(v) { * can be set. If any of these happens twice or the data is required before * it was set, an exception is throw. */ -var Promise = (function promise() { +var Promise = (function PromiseClosure() { var EMPTY_PROMISE = {}; /** From 303f5cd07b28709ea4e441a5a3ff781e6e11eacd Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 8 Dec 2011 19:17:24 -0600 Subject: [PATCH 12/14] Add bad PDF with lots of extra bytes at the end --- test/pdfs/.gitignore | 1 + test/pdfs/scan-bad.pdf | Bin 0 -> 29832 bytes test/test_manifest.json | 6 ++++++ 3 files changed, 7 insertions(+) create mode 100755 test/pdfs/scan-bad.pdf diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 325987de6..dd0dceced 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -17,3 +17,4 @@ !devicen.pdf !cmykjpeg.pdf !issue840.pdf +!scan-bad.pdf diff --git a/test/pdfs/scan-bad.pdf b/test/pdfs/scan-bad.pdf new file mode 100755 index 0000000000000000000000000000000000000000..ca09315f907b7bb51cae52acf6d43107fa04f5e1 GIT binary patch literal 29832 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 Date: Thu, 8 Dec 2011 20:09:19 -0600 Subject: [PATCH 13/14] Fix error object wrapper (#914) --- src/worker.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/worker.js b/src/worker.js index 8e4c14fbc..52e631c92 100644 --- a/src/worker.js +++ b/src/worker.js @@ -83,8 +83,8 @@ var WorkerMessageHandler = { } catch (e) { // Turn the error into an obj that can be serialized e = { - message: e.message, - stack: e.stack + message: typeof e === 'object' ? e.message : e, + stack: typeof e === 'object' ? e.stack : null }; handler.send('page_error', { pageNum: pageNum, From ade44385379127df5a4b75fa5c38a202fd819669 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 8 Dec 2011 20:51:12 -0600 Subject: [PATCH 14/14] Suppress messages from the browser --- test/test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test.py b/test/test.py index 256200587..888bd9ce8 100644 --- a/test/test.py +++ b/test/test.py @@ -12,6 +12,7 @@ DOC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),"..")) ANAL = True DEFAULT_MANIFEST_FILE = 'test_manifest.json' EQLOG_FILE = 'eq.log' +BROWSERLOG_FILE = 'browser.log' REFDIR = 'ref' TMPDIR = 'tmp' VERBOSE = False @@ -229,6 +230,7 @@ class BaseBrowserCommand(object): def setup(self): self.tempDir = tempfile.mkdtemp() self.profileDir = os.path.join(self.tempDir, "profile") + self.browserLog = open(BROWSERLOG_FILE, "w") def teardown(self): # If the browser is still running, wait up to ten seconds for it to quit @@ -245,6 +247,8 @@ class BaseBrowserCommand(object): if self.tempDir is not None and os.path.exists(self.tempDir): shutil.rmtree(self.tempDir) + self.browserLog.close() + def start(self, url): raise Exception("Can't start BaseBrowserCommand") @@ -262,7 +266,7 @@ class FirefoxBrowserCommand(BaseBrowserCommand): if platform.system() == "Darwin": cmds.append("-foreground") cmds.extend(["-no-remote", "-profile", self.profileDir, url]) - self.process = subprocess.Popen(cmds) + self.process = subprocess.Popen(cmds, stdout = self.browserLog, stderr = self.browserLog) class ChromeBrowserCommand(BaseBrowserCommand): def _fixupMacPath(self): @@ -272,7 +276,7 @@ class ChromeBrowserCommand(BaseBrowserCommand): cmds = [self.path] cmds.extend(["--user-data-dir=%s" % self.profileDir, "--no-first-run", "--disable-sync", url]) - self.process = subprocess.Popen(cmds) + self.process = subprocess.Popen(cmds, stdout = self.browserLog, stderr = self.browserLog) def makeBrowserCommand(browser): path = browser["path"].lower()