From 5830474ef7796c8c16d565a609e7a490d44cf63d Mon Sep 17 00:00:00 2001 From: Julian Viereck <julian.viereck@gmail.com> Date: Sun, 18 Dec 2011 22:36:36 +0100 Subject: [PATCH 1/5] Add preDraw() functionality to render the next page in the background --- web/viewer.js | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 6065a2f68..9646ccd0c 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -33,6 +33,9 @@ var RenderingQueue = (function RenderingQueueClosure() { RenderingQueue.prototype = { enqueueDraw: function RenderingQueueEnqueueDraw(item) { + if (!item.drawingRequired()) + return; // as no redraw required, no need for queueing. + if ('rendering' in item) return; // is already in the queue @@ -366,6 +369,7 @@ var PDFView = { // when page is painted, using the image as thumbnail base pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() { thumbnailView.setImage(pageView.canvas); + preDraw(); }; } @@ -759,8 +763,12 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, }, 0); }; + this.drawingRequired = function() { + return !div.hasChildNodes(); + }; + this.draw = function pageviewDraw(callback) { - if (div.hasChildNodes()) { + if (!this.drawingRequired()) { this.updateStats(); callback(); return; @@ -1004,16 +1012,49 @@ window.addEventListener('unload', function webViewerUnload(evt) { window.scrollTo(0, 0); }, true); +/** + * Render the next not yet visible page already such that it is + * hopefully ready once the user scrolls to it. + */ +function preDraw() { + var pages = PDFView.pages; + var visible = PDFView.getVisiblePages(); + var last = visible[visible.length - 1]; + // PageView.id is the actual page number, which is + 1 compared + // to the index in `pages`. That means, pages[last.id] is the next + // PageView instance. + if (pages[last.id] && pages[last.id].drawingRequired()) { + renderingQueue.enqueueDraw(pages[last.id]); + return; + } + // If there is nothing to draw on the next page, maybe the user + // is scrolling up, so, let's try to render the next page *before* + // the first visible page + if (pages[visible[0].id - 2]) { + renderingQueue.enqueueDraw(pages[visible[0].id - 2]); + } +} + function updateViewarea() { var visiblePages = PDFView.getVisiblePages(); + var pageToDraw; for (var i = 0; i < visiblePages.length; i++) { var page = visiblePages[i]; - renderingQueue.enqueueDraw(PDFView.pages[page.id - 1]); + var pageObj = PDFView.pages[page.id - 1]; + + pageToDraw |= pageObj.drawingRequired(); + renderingQueue.enqueueDraw(pageObj); } if (!visiblePages.length) return; + // If there is no need to draw a page that is currenlty visible, preDraw the + // next page the user might scroll to. + if (!pageToDraw) { + preDraw(); + } + updateViewarea.inProgress = true; // used in "set page" var currentId = PDFView.page; var firstPage = visiblePages[0]; From 5bd4d1987a99266fc9c1ef668da91e78f3ef608c Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Wed, 4 Jan 2012 14:43:17 -0800 Subject: [PATCH 2/5] Easier copy/paste error message. --- web/viewer.css | 2 +- web/viewer.html | 2 +- web/viewer.js | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/web/viewer.css b/web/viewer.css index 072b2c033..e355f7fc2 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -330,7 +330,7 @@ canvas { color: black; padding: 3px; margin: 3px; - white-space: pre; + width: 98%; } .clearBoth { diff --git a/web/viewer.html b/web/viewer.html index 869bf0f2e..40e99004f 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -114,7 +114,7 @@ </button> </div> <div class="clearBoth"></div> - <div id="errorMoreInfo" hidden='true'></div> + <textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea> </div> <div id="sidebar"> diff --git a/web/viewer.js b/web/viewer.js index 6065a2f68..f089d8c24 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -346,13 +346,14 @@ var PDFView = { }; moreInfoButton.removeAttribute('hidden'); lessInfoButton.setAttribute('hidden', 'true'); - errorMoreInfo.innerHTML = 'PDF.JS Build: ' + PDFJS.build + '\n'; + errorMoreInfo.value = 'PDF.JS Build: ' + PDFJS.build + '\n'; if (moreInfo) { - errorMoreInfo.innerHTML += 'Message: ' + moreInfo.message; + errorMoreInfo.value += 'Message: ' + moreInfo.message; if (moreInfo.stack) - errorMoreInfo.innerHTML += '\n' + 'Stack: ' + moreInfo.stack; + errorMoreInfo.value += '\n' + 'Stack: ' + moreInfo.stack; } + errorMoreInfo.rows = errorMoreInfo.value.split('\n').length - 1; }, progress: function pdfViewProgress(level) { From 567dd330e1dea440e0bb5f57706578278609a351 Mon Sep 17 00:00:00 2001 From: Jeff Wagner <jwagner@gmail.com> Date: Wed, 4 Jan 2012 15:10:25 -0800 Subject: [PATCH 3/5] Fix subarray error for IE9 --- web/compatibility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/compatibility.js b/web/compatibility.js index 66e46b51b..26405ad8f 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -14,7 +14,7 @@ } function subarray(start, end) { - return this.slice(start, end); + return new TypedArray(this.slice(start, end)); } function setArrayOffset(array, offset) { From dddcb9c91bf00f4ce94a6be281f0de7470e7fe51 Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Wed, 4 Jan 2012 16:13:53 -0800 Subject: [PATCH 4/5] Add error backs for promises. --- src/core.js | 30 +++++++++++++++++++----------- src/util.js | 30 +++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/core.js b/src/core.js index 8b5fbea75..f262cde45 100644 --- a/src/core.js +++ b/src/core.js @@ -398,17 +398,25 @@ var Page = (function PageClosure() { } // Once the IRQueue and fonts are loaded, perform the actual rendering. - this.displayReadyPromise.then(function pageDisplayReadyPromise() { - var gfx = new CanvasGraphics(ctx, this.objs, textLayer); - try { - this.display(gfx, callback); - } catch (e) { - if (self.callback) - self.callback(e); + this.displayReadyPromise.then( + function pageDisplayReadyPromise() { + var gfx = new CanvasGraphics(ctx, this.objs, textLayer); + try { + this.display(gfx, callback); + } catch (e) { + if (callback) + callback(e); + else + throw e; + } + }.bind(this), + function pageDisplayReadPromiseError(reason) { + if (callback) + callback(reason); else - throw e; + throw reason; } - }.bind(this)); + ); } }; @@ -722,8 +730,8 @@ var PDFDoc = (function PDFDocClosure() { messageHandler.on('page_error', function pdfDocError(data) { var page = this.pageCache[data.pageNum]; - if (page.callback) - page.callback(data.error); + if (page.displayReadyPromise) { + page.displayReadyPromise.reject(data.error);} else throw data.error; }, this); diff --git a/src/util.js b/src/util.js index 4d8918e48..99b422296 100644 --- a/src/util.js +++ b/src/util.js @@ -206,6 +206,8 @@ var Promise = (function PromiseClosure() { */ function Promise(name, data) { this.name = name; + this.isRejected = false; + this.error = null; // If you build a promise and pass in some data it's already resolved. if (data != null) { this.isResolved = true; @@ -216,6 +218,7 @@ var Promise = (function PromiseClosure() { this._data = EMPTY_PROMISE; } this.callbacks = []; + this.errbacks = []; }; /** * Builds a promise that is resolved when all the passed in promises are @@ -282,6 +285,9 @@ var Promise = (function PromiseClosure() { if (this.isResolved) { throw 'A Promise can be resolved only once ' + this.name; } + if (this.isRejected) { + throw 'The Promise was already rejected ' + this.name; + } this.isResolved = true; this.data = data || null; @@ -292,7 +298,24 @@ var Promise = (function PromiseClosure() { } }, - then: function promiseThen(callback) { + reject: function proimseReject(reason) { + if (this.isRejected) { + throw 'A Promise can be rejected only once ' + this.name; + } + if (this.isResolved) { + throw 'The Promise was already resolved ' + this.name; + } + + this.isRejected = true; + this.error = reason || null; + var errbacks = this.errbacks; + + for (var i = 0, ii = errbacks.length; i < ii; i++) { + errbacks[i].call(null, reason); + } + }, + + then: function promiseThen(callback, errback) { if (!callback) { throw 'Requiring callback' + this.name; } @@ -301,8 +324,13 @@ var Promise = (function PromiseClosure() { if (this.isResolved) { var data = this.data; callback.call(null, data); + } else if (this.isRejected && errorback) { + var error = this.error; + errback.call(null, error); } else { this.callbacks.push(callback); + if (errback) + this.errbacks.push(errback); } } }; From 3154ec4e38796c38fd27848dbd13447b463f508c Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Wed, 4 Jan 2012 17:22:07 -0800 Subject: [PATCH 5/5] Fix bracket nit. --- src/core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core.js b/src/core.js index f262cde45..4cc5984e2 100644 --- a/src/core.js +++ b/src/core.js @@ -730,8 +730,8 @@ var PDFDoc = (function PDFDocClosure() { messageHandler.on('page_error', function pdfDocError(data) { var page = this.pageCache[data.pageNum]; - if (page.displayReadyPromise) { - page.displayReadyPromise.reject(data.error);} + if (page.displayReadyPromise) + page.displayReadyPromise.reject(data.error); else throw data.error; }, this);