Hack to support automatic printing from pdf javascript.
This commit is contained in:
parent
e20a9846ca
commit
5c43565404
10
src/api.js
10
src/api.js
@ -119,6 +119,16 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
|
|||||||
promise.resolve(destinations);
|
promise.resolve(destinations);
|
||||||
return promise;
|
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
|
* @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:
|
* tree outline (if it has one) of the PDF. The tree is in the format of:
|
||||||
|
112
src/obj.js
112
src/obj.js
@ -17,7 +17,7 @@
|
|||||||
/* globals assertWellFormed, bytesToString, CipherTransformFactory, error, info,
|
/* globals assertWellFormed, bytesToString, CipherTransformFactory, error, info,
|
||||||
InvalidPDFException, isArray, isCmd, isDict, isInt, isName, isRef,
|
InvalidPDFException, isArray, isCmd, isDict, isInt, isName, isRef,
|
||||||
isStream, JpegStream, Lexer, log, Page, Parser, Promise, shadow,
|
isStream, JpegStream, Lexer, log, Page, Parser, Promise, shadow,
|
||||||
stringToPDFString, stringToUTF8String, warn */
|
stringToPDFString, stringToUTF8String, warn, isString */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@ -292,34 +292,51 @@ var Catalog = (function CatalogClosure() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (nameTreeRef) {
|
if (nameTreeRef) {
|
||||||
// reading name tree
|
var nameTree = new NameTree(nameTreeRef, xref);
|
||||||
var processed = new RefSet();
|
var names = nameTree.getAll();
|
||||||
processed.put(nameTreeRef);
|
for (var name in names) {
|
||||||
var queue = [nameTreeRef];
|
if (!names.hasOwnProperty(name)) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var names = obj.get('Names');
|
dests[name] = fetchDestination(names[name]);
|
||||||
if (names) {
|
|
||||||
for (i = 0, n = names.length; i < n; i += 2) {
|
|
||||||
dests[names[i]] = fetchDestination(xref.fetchIfRef(names[i + 1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shadow(this, 'destinations', dests);
|
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) {
|
getPage: function Catalog_getPage(n) {
|
||||||
var pageCache = this.pageCache;
|
var pageCache = this.pageCache;
|
||||||
if (!pageCache) {
|
if (!pageCache) {
|
||||||
@ -755,6 +772,55 @@ var XRef = (function XRefClosure() {
|
|||||||
return XRef;
|
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
|
* 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
|
* for fonts, images, rendering code and such. These objects might get processed
|
||||||
|
@ -152,6 +152,7 @@ var WorkerMessageHandler = {
|
|||||||
numPages: pdfModel.numPages,
|
numPages: pdfModel.numPages,
|
||||||
fingerprint: pdfModel.getFingerprint(),
|
fingerprint: pdfModel.getFingerprint(),
|
||||||
destinations: pdfModel.catalog.destinations,
|
destinations: pdfModel.catalog.destinations,
|
||||||
|
javaScript: pdfModel.catalog.javaScript,
|
||||||
outline: pdfModel.catalog.documentOutline,
|
outline: pdfModel.catalog.documentOutline,
|
||||||
info: pdfModel.getDocumentInfo(),
|
info: pdfModel.getDocumentInfo(),
|
||||||
metadata: pdfModel.catalog.metadata,
|
metadata: pdfModel.catalog.metadata,
|
||||||
|
@ -1310,6 +1310,26 @@ var PDFView = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.pagesRefMap = pagesRefMap;
|
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();
|
var destinationsPromise = pdfDocument.getDestinations();
|
||||||
|
Loading…
Reference in New Issue
Block a user