From d3b13e36d32a7e4f4f4df4a603a97e6f3c162213 Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Wed, 19 Oct 2016 11:39:02 +0200 Subject: [PATCH] Refactor page printing logic on the web - Move the global scratchCanvas to PDFPrintService. This is mainly to make it easier to reason about the state of scratchCanvas. In practice there is no difference because only one PDFPrintService instance can be instantiated at any given time. - Move all logic of using the rendered page to one location. This makes it easier to replace the printing logic later, when I add special handling to out-of-process frames in the Chrome extension. --- web/pdf_print_service.js | 88 +++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/web/pdf_print_service.js b/web/pdf_print_service.js index 8d0da3bd3..1f28b2596 100644 --- a/web/pdf_print_service.js +++ b/web/pdf_print_service.js @@ -35,14 +35,10 @@ var activeService = null; - // Using one canvas for all paint operations -- painting one canvas at a time. - var scratchCanvas = null; - - function renderPage(pdfDocument, pageNumber, size, wrapper) { - var activeServiceOnEntry = activeService; - if (!scratchCanvas) { - scratchCanvas = document.createElement('canvas'); - } + // Renders the page to the canvas of the given print service, and returns + // the suggested dimensions of the output page. + function renderPage(activeServiceOnEntry, pdfDocument, pageNumber, size) { + var scratchCanvas = activeService.scratchCanvas; // The size of the canvas in pixels for printing. var PRINT_RESOLUTION = 150; @@ -51,9 +47,8 @@ scratchCanvas.height = Math.floor(size.height * PRINT_UNITS); // The physical size of the img as specified by the PDF document. - var img = document.createElement('img'); - img.style.width = Math.floor(size.width * CSS_UNITS) + 'px'; - img.style.height = Math.floor(size.height * CSS_UNITS) + 'px'; + var width = Math.floor(size.width * CSS_UNITS) + 'px'; + var height = Math.floor(size.height * CSS_UNITS) + 'px'; var ctx = scratchCanvas.getContext('2d'); ctx.save(); @@ -69,21 +64,11 @@ intent: 'print' }; return pdfPage.render(renderContext).promise; - }).then(function() { - activeServiceOnEntry.throwIfInactive(); - if (('toBlob' in scratchCanvas) && - !pdfjsLib.PDFJS.disableCreateObjectURL) { - scratchCanvas.toBlob(function (blob) { - img.src = URL.createObjectURL(blob); - }); - } else { - img.src = scratchCanvas.toDataURL(); - } - wrapper.appendChild(img); - return new Promise(function(resolve, reject) { - img.onload = resolve; - img.onerror = reject; - }); + }).then(function () { + return { + width: width, + height: height, + }; }); } @@ -91,8 +76,9 @@ this.pdfDocument = pdfDocument; this.pagesOverview = pagesOverview; this.printContainer = printContainer; - this.wrappers = []; this.currentPage = -1; + // The temporary canvas where renderPage paints one page at a time. + this.scratchCanvas = document.createElement('canvas'); } PDFPrintService.prototype = { @@ -100,7 +86,6 @@ this.throwIfInactive(); var pdfDocument = this.pdfDocument; - var printContainer = this.printContainer; var body = document.querySelector('body'); body.setAttribute('data-pdfjsprinting', true); @@ -131,12 +116,6 @@ '@page { size: ' + pageSize.width + 'pt ' + pageSize.height + 'pt;}' + '}'; body.appendChild(this.pageStyleSheet); - - for (var i = 0, ii = this.pagesOverview.length; i < ii; ++i) { - var wrapper = document.createElement('div'); - printContainer.appendChild(wrapper); - this.wrappers[i] = wrapper; - } }, destroy: function () { @@ -147,16 +126,13 @@ return; } this.printContainer.textContent = ''; - this.wrappers = null; if (this.pageStyleSheet && this.pageStyleSheet.parentNode) { this.pageStyleSheet.parentNode.removeChild(this.pageStyleSheet); this.pageStyleSheet = null; } + this.scratchCanvas.width = this.scratchCanvas.height = 0; + this.scratchCanvas = null; activeService = null; - if (scratchCanvas) { - scratchCanvas.width = scratchCanvas.height = 0; - scratchCanvas = null; - } ensureOverlay().then(function () { if (OverlayManager.active !== 'printServiceOverlay') { return; // overlay was already closed @@ -176,13 +152,41 @@ } var index = this.currentPage; renderProgress(index, pageCount); - renderPage(this.pdfDocument, index + 1, - this.pagesOverview[index], this.wrappers[index]).then( - function () { renderNextPage(resolve, reject); }, reject); + renderPage(this, this.pdfDocument, index + 1, this.pagesOverview[index]) + .then(this.useRenderedPage.bind(this)) + .then(function () { + renderNextPage(resolve, reject); + }, reject); }.bind(this); return new Promise(renderNextPage); }, + useRenderedPage: function (printItem) { + this.throwIfInactive(); + var img = document.createElement('img'); + img.style.width = printItem.width; + img.style.height = printItem.height; + + var scratchCanvas = this.scratchCanvas; + if (('toBlob' in scratchCanvas) && + !pdfjsLib.PDFJS.disableCreateObjectURL) { + scratchCanvas.toBlob(function (blob) { + img.src = URL.createObjectURL(blob); + }); + } else { + img.src = scratchCanvas.toDataURL(); + } + + var wrapper = document.createElement('div'); + wrapper.appendChild(img); + this.printContainer.appendChild(wrapper); + + return new Promise(function (resolve, reject) { + img.onload = resolve; + img.onerror = reject; + }); + }, + get active() { return this === activeService; },