|
|
@ -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,33 +292,50 @@ 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) { |
|
|
|
continue; |
|
|
|
var i, n; |
|
|
|
} |
|
|
|
obj = xref.fetch(queue.shift()); |
|
|
|
dests[name] = fetchDestination(names[name]); |
|
|
|
if (obj.has('Kids')) { |
|
|
|
} |
|
|
|
var kids = obj.get('Kids'); |
|
|
|
} |
|
|
|
for (i = 0, n = kids.length; i < n; i++) { |
|
|
|
return shadow(this, 'destinations', dests); |
|
|
|
var kid = kids[i]; |
|
|
|
}, |
|
|
|
if (processed.has(kid)) |
|
|
|
get javaScript() { |
|
|
|
error('invalid destinations'); |
|
|
|
var xref = this.xref; |
|
|
|
queue.push(kid); |
|
|
|
var obj = this.catDict.get('Names'); |
|
|
|
processed.put(kid); |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
var names = obj.get('Names'); |
|
|
|
var type = jsDict.get('S'); |
|
|
|
if (names) { |
|
|
|
if (!isName(type) || type.name !== 'JavaScript') { |
|
|
|
for (i = 0, n = names.length; i < n; i += 2) { |
|
|
|
continue; |
|
|
|
dests[names[i]] = fetchDestination(xref.fetchIfRef(names[i + 1])); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var js = jsDict.get('JS'); |
|
|
|
|
|
|
|
if (!isString(js) && !isStream(js)) { |
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (isStream(js)) { |
|
|
|
|
|
|
|
js = bytesToString(js.getBytes()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
javaScript.push(js); |
|
|
|
} |
|
|
|
} |
|
|
|
return shadow(this, 'destinations', dests); |
|
|
|
} |
|
|
|
|
|
|
|
return shadow(this, 'javaScript', javaScript); |
|
|
|
}, |
|
|
|
}, |
|
|
|
getPage: function Catalog_getPage(n) { |
|
|
|
getPage: function Catalog_getPage(n) { |
|
|
|
var pageCache = this.pageCache; |
|
|
|
var pageCache = this.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 |
|
|
|