Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring of printing code and mozPrintCallback polyfill #7697

Merged
merged 3 commits into from
Oct 11, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ function createWebBundle(defines) {
amdName = 'pdfjs-dist/web/viewer';
outputName = 'viewer.js';
template = 'web/viewer.js';
files = ['app.js'];
files = ['app.js', 'firefox_print_service.js'];
if (defines.FIREFOX || defines.MOZCENTRAL) {
files.push('firefoxcom.js');
} else if (defines.CHROME) {
Expand Down
89 changes: 29 additions & 60 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ var PDFViewerApplication = {
appConfig: null,
pdfDocument: null,
pdfLoadingTask: null,
printing: false,
printService: null,
/** @type {PDFViewer} */
pdfViewer: null,
/** @type {PDFThumbnailViewer} */
Expand Down Expand Up @@ -428,11 +428,12 @@ var PDFViewerApplication = {
return this.pdfViewer.currentPageNumber;
},

get supportsPrinting() {
var canvas = document.createElement('canvas');
var value = 'mozPrintCallback' in canvas;
get printing() {
return !!this.printService;
},

return pdfjsLib.shadow(this, 'supportsPrinting', value);
get supportsPrinting() {
return PDFPrintServiceFactory.instance.supportsPrinting;
},

get supportsFullscreen() {
Expand Down Expand Up @@ -1106,59 +1107,23 @@ var PDFViewerApplication = {
return;
}

var alertNotReady = false;
var i, ii;
if (!this.pdfDocument || !this.pagesCount) {
alertNotReady = true;
} else {
for (i = 0, ii = this.pagesCount; i < ii; ++i) {
if (!this.pdfViewer.getPageView(i).pdfPage) {
alertNotReady = true;
break;
}
}
}
if (alertNotReady) {
// The beforePrint is a sync method and we need to know layout before
// returning from this method. Ensure that we can get sizes of the pages.
if (!this.pdfViewer.pageViewsReady) {
var notReadyMessage = mozL10n.get('printing_not_ready', null,
'Warning: The PDF is not fully loaded for printing.');
window.alert(notReadyMessage);
return;
}

this.printing = true;
var pagesOverview = this.pdfViewer.getPagesOverview();
var printContainer = this.appConfig.printContainer;
var printService = PDFPrintServiceFactory.instance.createPrintService(
this.pdfDocument, pagesOverview, printContainer);
this.printService = printService;
this.forceRendering();

var printContainer = this.appConfig.printContainer;
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:<width> <height>" 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;}' +
'}';
body.appendChild(this.pageStyleSheet);

for (i = 0, ii = this.pagesCount; i < ii; ++i) {
this.pdfViewer.getPageView(i).beforePrint(printContainer);
}
printService.layout();

//#if !PRODUCTION
if (true) {
Expand Down Expand Up @@ -1186,17 +1151,10 @@ var PDFViewerApplication = {
},

afterPrint: function pdfViewSetupAfterPrint() {
var div = this.appConfig.printContainer;
while (div.hasChildNodes()) {
div.removeChild(div.lastChild);
if (this.printService) {
this.printService.destroy();
this.printService = null;
}

if (this.pageStyleSheet && this.pageStyleSheet.parentNode) {
this.pageStyleSheet.parentNode.removeChild(this.pageStyleSheet);
this.pageStyleSheet = null;
}

this.printing = false;
this.forceRendering();
},

Expand Down Expand Up @@ -2330,6 +2288,17 @@ window.addEventListener('afterprint', function afterPrint(evt) {
});
})();

/* Abstract factory for the print service. */
var PDFPrintServiceFactory = {
instance: {
supportsPrinting: false,
createPrintService: function () {
throw new Error('Not implemented: createPrintService');
}
}
};

exports.PDFViewerApplication = PDFViewerApplication;
exports.DefaultExernalServices = DefaultExernalServices;
exports.PDFPrintServiceFactory = PDFPrintServiceFactory;
}));
155 changes: 155 additions & 0 deletions web/firefox_print_service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/* Copyright 2016 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define('pdfjs-web/firefox_print_service', ['exports', 'pdfjs-web/ui_utils',
'pdfjs-web/app', 'pdfjs-web/pdfjs'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports, require('./ui_utils.js'), require('./app.js'),
require('./pdfjs.js'));
} else {
factory((root.pdfjsWebFirefoxPrintService = {}), root.pdfjsWebUIUtils,
root.pdfjsWebApp, root.pdfjsWebPDFJS);
}
}(this, function (exports, uiUtils, app, pdfjsLib) {
var CSS_UNITS = uiUtils.CSS_UNITS;
var PDFPrintServiceFactory = app.PDFPrintServiceFactory;

// Creates a placeholder with div and canvas with right size for the page.
function composePage(pdfDocument, pageNumber, size, printContainer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is called renderPage in pdf_print_service.js. Can we name it renderPage here too for consistency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, I added a comments to pdf_print_service

var canvas = document.createElement('canvas');

// The size of the canvas in pixels for printing.
var PRINT_RESOLUTION = 150;
var PRINT_UNITS = PRINT_RESOLUTION / 72.0;
canvas.width = Math.floor(size.width * PRINT_UNITS);
canvas.height = Math.floor(size.height * PRINT_UNITS);

// The physical size of the canvas as specified by the PDF document.
canvas.style.width = Math.floor(size.width * CSS_UNITS) + 'px';
canvas.style.height = Math.floor(size.height * CSS_UNITS) + 'px';

var canvasWrapper = document.createElement('div');
canvasWrapper.appendChild(canvas);
printContainer.appendChild(canvasWrapper);

canvas.mozPrintCallback = function(obj) {
// Printing/rendering the page.
var ctx = obj.context;

ctx.save();
ctx.fillStyle = 'rgb(255, 255, 255)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();

pdfDocument.getPage(pageNumber).then(function (pdfPage) {
var renderContext = {
canvasContext: ctx,
transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
viewport: pdfPage.getViewport(1),
intent: 'print'
};
return pdfPage.render(renderContext).promise;
}).then(function() {
// Tell the printEngine that rendering this canvas/page has finished.
obj.done();
}, function(error) {
console.error(error);
// Tell the printEngine that rendering this canvas/page has failed.
// This will make the print process stop.
if ('abort' in obj) {
obj.abort();
} else {
obj.done();
}
});
};
}

function FirefoxPrintService(pdfDocument, pagesOverview, printContainer) {
this.pdfDocument = pdfDocument;
this.pagesOverview = pagesOverview;
this.printContainer = printContainer;
this.pageStyleSheet = null;
}

FirefoxPrintService.prototype = {
layout: function () {
var pdfDocument = this.pdfDocument;
var printContainer = this.printContainer;
var body = document.querySelector('body');
body.setAttribute('data-pdfjsprinting', true);

var hasEqualPageSizes = this.pagesOverview.every(function (size) {
return size.width === this.pagesOverview[0].width &&
size.height === this.pagesOverview[0].height;
}, this);
if (!hasEqualPageSizes) {
console.warn('Not all pages have the same size. The printed ' +
'result may be incorrect!');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: remove one space

}

// 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 (e.g. 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.pagesOverview[0];
this.pageStyleSheet.textContent =
// "size:<width> <height>" 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;}' +
'}';
body.appendChild(this.pageStyleSheet);

for (var i = 0, ii = this.pagesOverview.length; i < ii; ++i) {
composePage(pdfDocument, i + 1, this.pagesOverview[i], printContainer);
}
},

destroy: function () {
this.printContainer.textContent = '';
if (this.pageStyleSheet && this.pageStyleSheet.parentNode) {
this.pageStyleSheet.parentNode.removeChild(this.pageStyleSheet);
this.pageStyleSheet = null;
}
}
};

PDFPrintServiceFactory.instance = {
get supportsPrinting() {
var canvas = document.createElement('canvas');
var value = 'mozPrintCallback' in canvas;

return pdfjsLib.shadow(this, 'supportsPrinting', value);
},

createPrintService: function (pdfDocument, pagesOverview, printContainer) {
return new FirefoxPrintService(pdfDocument, pagesOverview,
printContainer);
}
};

exports.FirefoxPrintService = FirefoxPrintService;
}));
3 changes: 3 additions & 0 deletions web/mozPrintCallback_polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@

function renderProgress() {
var progressContainer = document.getElementById('mozPrintCallback-shim');
if (!progressContainer) {
return;
}
if (canvases && canvases.length) {
var progress = Math.round(100 * index / canvases.length);
var progressBar = progressContainer.querySelector('progress');
Expand Down
53 changes: 0 additions & 53 deletions web/pdf_page_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,59 +540,6 @@ var PDFPageView = (function PDFPageViewClosure() {
}
return promise;
},

beforePrint: function PDFPageView_beforePrint(printContainer) {
var CustomStyle = pdfjsLib.CustomStyle;
var pdfPage = this.pdfPage;

var viewport = pdfPage.getViewport(1);

var canvas = document.createElement('canvas');

// The size of the canvas in pixels for printing.
var PRINT_RESOLUTION = 150;
var PRINT_UNITS = PRINT_RESOLUTION / 72.0;
canvas.width = Math.floor(viewport.width * PRINT_UNITS);
canvas.height = Math.floor(viewport.height * PRINT_UNITS);

// The physical size of the canvas as specified by the PDF document.
canvas.style.width = Math.floor(viewport.width * CSS_UNITS) + 'px';
canvas.style.height = Math.floor(viewport.height * CSS_UNITS) + 'px';

var canvasWrapper = document.createElement('div');
canvasWrapper.appendChild(canvas);
printContainer.appendChild(canvasWrapper);

canvas.mozPrintCallback = function(obj) {
var ctx = obj.context;

ctx.save();
ctx.fillStyle = 'rgb(255, 255, 255)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();

var renderContext = {
canvasContext: ctx,
transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
viewport: viewport,
intent: 'print'
};

pdfPage.render(renderContext).promise.then(function() {
// Tell the printEngine that rendering this canvas/page has finished.
obj.done();
}, function(error) {
console.error(error);
// Tell the printEngine that rendering this canvas/page has failed.
// This will make the print process stop.
if ('abort' in obj) {
obj.abort();
} else {
obj.done();
}
});
};
},
};

return PDFPageView;
Expand Down
Loading