From d34e6ddd60e9ee6b6508fb82ffc514ea402611da Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Wed, 18 Mar 2015 23:15:43 +0100 Subject: [PATCH] Set page size via @page + size In Blink-based browsers, there is a mismatch between document size and paper size. Even if exactly the same values and unit are used, it is possible that the printed results takes more pages than expected. To solve the issue, the page size is set via @page size, and the canvas and ancestor nodes are assigned a width+height of 100% (=relative to the page). This change resolves bugs such as blank pages and split pages. --- web/pdf_page_view.js | 9 +++++++-- web/viewer.css | 6 +++++- web/viewer.js | 47 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index 8e49cbaf6..35bd51520 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -493,10 +493,15 @@ var PDFPageView = (function PDFPageViewClosure() { // better output until bug 811002 is fixed in FF. var PRINT_OUTPUT_SCALE = 2; var canvas = document.createElement('canvas'); + + // The logical size of the canvas. canvas.width = Math.floor(viewport.width) * PRINT_OUTPUT_SCALE; canvas.height = Math.floor(viewport.height) * PRINT_OUTPUT_SCALE; - canvas.style.width = (PRINT_OUTPUT_SCALE * viewport.width) + 'pt'; - canvas.style.height = (PRINT_OUTPUT_SCALE * viewport.height) + 'pt'; + + // The rendered size of the canvas, relative to the size of canvasWrapper. + canvas.style.width = (PRINT_OUTPUT_SCALE * 100) + '%'; + canvas.style.height = (PRINT_OUTPUT_SCALE * 100) + '%'; + var cssScale = 'scale(' + (1 / PRINT_OUTPUT_SCALE) + ', ' + (1 / PRINT_OUTPUT_SCALE) + ')'; CustomStyle.setProp('transform' , canvas, cssScale); diff --git a/web/viewer.css b/web/viewer.css index 4432b302b..35bd2d5bd 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -1711,10 +1711,14 @@ html[dir='rtl'] #documentPropertiesOverlay .row > * { body[data-mozPrintCallback] #printContainer { display: block; } - #printContainer canvas { + /* wrapper around (scaled) print canvas elements */ + #printContainer > div { position: relative; top: 0; left: 0; + overflow: hidden; + } + #printContainer canvas { display: block; } } diff --git a/web/viewer.js b/web/viewer.js index 20717735a..0b31999ba 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1300,6 +1300,35 @@ var PDFViewerApplication = { var body = document.querySelector('body'); body.setAttribute('data-mozPrintCallback', true); + + if (!this.hasEqualPageSizes) { + console.warn('Not all pages have the same size. The printed result ' + + 'may be incorrect!'); + } + + // Insert a @page + size rule to make sure that the page size is correctly + // set. Note that we assume that all pages have the same size, because + // variable-size pages are not supported yet (at least in Chrome & Firefox). + // TODO(robwu): Use named pages when size calculation bugs get resolved + // (e.g. https://crbug.com/355116) AND when support for named pages is + // added (http://www.w3.org/TR/css3-page/#using-named-pages). + // In browsers where @page + size is not supported (such as Firefox, + // https://bugzil.la/851441), the next stylesheet will be ignored and the + // user has to select the correct paper size in the UI if wanted. + this.pageStyleSheet = document.createElement('style'); + var pageSize = this.pdfViewer.getPageView(0).pdfPage.getViewport(1); + this.pageStyleSheet.textContent = + // "size: " is what we need. But also add "A4" because + // Firefox incorrectly reports support for the other value. + '@supports ((size:A4) and (size:1pt 1pt)) {' + + '@page { size: ' + pageSize.width + 'pt ' + pageSize.height + 'pt;}' + + // The canvas and each ancestor node must have a height of 100% to make + // sure that each canvas is printed on exactly one page. + '#printContainer {height:100%}' + + '#printContainer > div {width:100% !important;height:100% !important;}' + + '}'; + body.appendChild(this.pageStyleSheet); + for (i = 0, ii = this.pagesCount; i < ii; ++i) { this.pdfViewer.getPageView(i).beforePrint(); } @@ -1311,12 +1340,30 @@ var PDFViewerApplication = { //#endif }, + // Whether all pages of the PDF have the same width and height. + get hasEqualPageSizes() { + var firstPage = this.pdfViewer.getPageView(0); + for (var i = 1, ii = this.pagesCount; i < ii; ++i) { + var pageView = this.pdfViewer.getPageView(i); + if (pageView.width !== firstPage.width || + pageView.height !== firstPage.height) { + return false; + } + } + return true; + }, + afterPrint: function pdfViewSetupAfterPrint() { var div = document.getElementById('printContainer'); while (div.hasChildNodes()) { div.removeChild(div.lastChild); } + if (this.pageStyleSheet && this.pageStyleSheet.parentNode) { + this.pageStyleSheet.parentNode.removeChild(this.pageStyleSheet); + this.pageStyleSheet = null; + } + this.printing = false; this.forceRendering(); },