Hack to support automatic printing from pdf javascript.

This commit is contained in:
Brendan Dahl 2013-02-28 15:29:07 -08:00
parent e20a9846ca
commit 5c43565404
4 changed files with 120 additions and 23 deletions

View File

@ -119,6 +119,16 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
promise.resolve(destinations);
return promise;
},
/**
* @return {Promise} A promise that is resolved with an array of all the
* JavaScript strings in the name tree.
*/
getJavaScript: function PDFDocumentProxy_getDestinations() {
var promise = new PDFJS.Promise();
var js = this.pdfInfo.javaScript;
promise.resolve(js);
return promise;
},
/**
* @return {Promise} A promise that is resolved with an {array} that is a
* tree outline (if it has one) of the PDF. The tree is in the format of:

View File

@ -17,7 +17,7 @@
/* globals assertWellFormed, bytesToString, CipherTransformFactory, error, info,
InvalidPDFException, isArray, isCmd, isDict, isInt, isName, isRef,
isStream, JpegStream, Lexer, log, Page, Parser, Promise, shadow,
stringToPDFString, stringToUTF8String, warn */
stringToPDFString, stringToUTF8String, warn, isString */
'use strict';
@ -292,34 +292,51 @@ var Catalog = (function CatalogClosure() {
});
}
if (nameTreeRef) {
// reading name tree
var processed = new RefSet();
processed.put(nameTreeRef);
var queue = [nameTreeRef];
while (queue.length > 0) {
var i, n;
obj = xref.fetch(queue.shift());
if (obj.has('Kids')) {
var kids = obj.get('Kids');
for (i = 0, n = kids.length; i < n; i++) {
var kid = kids[i];
if (processed.has(kid))
error('invalid destinations');
queue.push(kid);
processed.put(kid);
}
var nameTree = new NameTree(nameTreeRef, xref);
var names = nameTree.getAll();
for (var name in names) {
if (!names.hasOwnProperty(name)) {
continue;
}
var names = obj.get('Names');
if (names) {
for (i = 0, n = names.length; i < n; i += 2) {
dests[names[i]] = fetchDestination(xref.fetchIfRef(names[i + 1]));
}
}
dests[name] = fetchDestination(names[name]);
}
}
return shadow(this, 'destinations', dests);
},
get javaScript() {
var xref = this.xref;
var obj = this.catDict.get('Names');
var javaScript = [];
if (obj && obj.has('JavaScript')) {
var nameTree = new NameTree(obj.getRaw('JavaScript'), xref);
var names = nameTree.getAll();
for (var name in names) {
if (!names.hasOwnProperty(name)) {
continue;
}
// We don't really use the JavaScript right now so this code is
// defensive so we don't cause errors on document load.
var jsDict = names[name];
if (!isDict(jsDict)) {
continue;
}
var type = jsDict.get('S');
if (!isName(type) || type.name !== 'JavaScript') {
continue;
}
var js = jsDict.get('JS');
if (!isString(js) && !isStream(js)) {
continue;
}
if (isStream(js)) {
js = bytesToString(js.getBytes());
}
javaScript.push(js);
}
}
return shadow(this, 'javaScript', javaScript);
},
getPage: function Catalog_getPage(n) {
var pageCache = this.pageCache;
if (!pageCache) {
@ -755,6 +772,55 @@ var XRef = (function XRefClosure() {
return XRef;
})();
/**
* A NameTree is like a Dict but has some adventagous properties, see the spec
* (7.9.6) for more details.
* TODO: implement all the Dict functions and make this more efficent.
*/
var NameTree = (function NameTreeClosure() {
function NameTree(root, xref) {
this.root = root;
this.xref = xref;
}
NameTree.prototype = {
getAll: function NameTree_getAll() {
var dict = {};
if (!this.root) {
return dict;
}
var xref = this.xref;
// reading name tree
var processed = new RefSet();
processed.put(this.root);
var queue = [this.root];
while (queue.length > 0) {
var i, n;
var obj = xref.fetch(queue.shift());
if (obj.has('Kids')) {
var kids = obj.get('Kids');
for (i = 0, n = kids.length; i < n; i++) {
var kid = kids[i];
if (processed.has(kid))
error('invalid destinations');
queue.push(kid);
processed.put(kid);
}
continue;
}
var names = obj.get('Names');
if (names) {
for (i = 0, n = names.length; i < n; i += 2) {
dict[names[i]] = xref.fetchIfRef(names[i + 1]);
}
}
}
return dict;
}
};
return NameTree;
})();
/**
* A PDF document and page is built of many objects. E.g. there are objects
* for fonts, images, rendering code and such. These objects might get processed

View File

@ -152,6 +152,7 @@ var WorkerMessageHandler = {
numPages: pdfModel.numPages,
fingerprint: pdfModel.getFingerprint(),
destinations: pdfModel.catalog.destinations,
javaScript: pdfModel.catalog.javaScript,
outline: pdfModel.catalog.documentOutline,
info: pdfModel.getDocumentInfo(),
metadata: pdfModel.catalog.metadata,

View File

@ -1310,6 +1310,26 @@ var PDFView = {
}
self.pagesRefMap = pagesRefMap;
// Wait to do this here so all the canvases are setup.
if (PDFView.supportsPrinting) {
pdfDocument.getJavaScript().then(function(javaScript) {
if (javaScript.length) {
PDFView.fallback();
}
// Hack to support auto printing.
var regex = /\bprint\s*\(/g;
for (var i = 0, ii = javaScript.length; i < ii; i++) {
var js = javaScript[i];
if (js && regex.test(js)) {
setTimeout(function() {
window.print();
});
return;
}
}
});
}
});
var destinationsPromise = pdfDocument.getDestinations();