|
|
@ -62,11 +62,30 @@ var Dict = (function DictClosure() { |
|
|
|
return nonSerializable; // creating closure on some variable
|
|
|
|
return nonSerializable; // creating closure on some variable
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var GETALL_DICTIONARY_TYPES_WHITELIST = { |
|
|
|
|
|
|
|
'Background': true, |
|
|
|
|
|
|
|
'ExtGState': true, |
|
|
|
|
|
|
|
'Halftone': true, |
|
|
|
|
|
|
|
'Layout': true, |
|
|
|
|
|
|
|
'Mask': true, |
|
|
|
|
|
|
|
'Pagination': true, |
|
|
|
|
|
|
|
'Printing': true |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function isRecursionAllowedFor(dict) { |
|
|
|
|
|
|
|
if (!isName(dict.Type)) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var dictType = dict.Type.name; |
|
|
|
|
|
|
|
return GETALL_DICTIONARY_TYPES_WHITELIST[dictType] === true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// xref is optional
|
|
|
|
// xref is optional
|
|
|
|
function Dict(xref) { |
|
|
|
function Dict(xref) { |
|
|
|
// Map should only be used internally, use functions below to access.
|
|
|
|
// Map should only be used internally, use functions below to access.
|
|
|
|
this.map = Object.create(null); |
|
|
|
this.map = Object.create(null); |
|
|
|
this.xref = xref; |
|
|
|
this.xref = xref; |
|
|
|
|
|
|
|
this.objId = null; |
|
|
|
this.__nonSerializable__ = nonSerializable; // disable cloning of the Dict
|
|
|
|
this.__nonSerializable__ = nonSerializable; // disable cloning of the Dict
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -130,10 +149,51 @@ var Dict = (function DictClosure() { |
|
|
|
|
|
|
|
|
|
|
|
// creates new map and dereferences all Refs
|
|
|
|
// creates new map and dereferences all Refs
|
|
|
|
getAll: function Dict_getAll() { |
|
|
|
getAll: function Dict_getAll() { |
|
|
|
var all = {}; |
|
|
|
var all = Object.create(null); |
|
|
|
|
|
|
|
var queue = null; |
|
|
|
for (var key in this.map) { |
|
|
|
for (var key in this.map) { |
|
|
|
var obj = this.get(key); |
|
|
|
var obj = this.get(key); |
|
|
|
all[key] = (obj instanceof Dict ? obj.getAll() : obj); |
|
|
|
if (obj instanceof Dict) { |
|
|
|
|
|
|
|
if (isRecursionAllowedFor(obj)) { |
|
|
|
|
|
|
|
(queue || (queue = [])).push({target: all, key: key, obj: obj}); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
all[key] = this.getRaw(key); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
all[key] = obj; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!queue) { |
|
|
|
|
|
|
|
return all; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// trying to take cyclic references into the account
|
|
|
|
|
|
|
|
var processed = Object.create(null); |
|
|
|
|
|
|
|
while (queue.length > 0) { |
|
|
|
|
|
|
|
var item = queue.shift(); |
|
|
|
|
|
|
|
var itemObj = item.obj; |
|
|
|
|
|
|
|
var objId = itemObj.objId; |
|
|
|
|
|
|
|
if (objId && objId in processed) { |
|
|
|
|
|
|
|
item.target[item.key] = processed[objId]; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var dereferenced = Object.create(null); |
|
|
|
|
|
|
|
for (var key in itemObj.map) { |
|
|
|
|
|
|
|
var obj = itemObj.get(key); |
|
|
|
|
|
|
|
if (obj instanceof Dict) { |
|
|
|
|
|
|
|
if (isRecursionAllowedFor(obj)) { |
|
|
|
|
|
|
|
queue.push({target: dereferenced, key: key, obj: obj}); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
dereferenced[key] = itemObj.getRaw(key); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
dereferenced[key] = obj; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (objId) { |
|
|
|
|
|
|
|
processed[objId] = dereferenced; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
item.target[item.key] = dereferenced; |
|
|
|
} |
|
|
|
} |
|
|
|
return all; |
|
|
|
return all; |
|
|
|
}, |
|
|
|
}, |
|
|
@ -153,6 +213,8 @@ var Dict = (function DictClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dict.empty = new Dict(null); |
|
|
|
|
|
|
|
|
|
|
|
return Dict; |
|
|
|
return Dict; |
|
|
|
})(); |
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
@ -1061,10 +1123,15 @@ var XRef = (function XRefClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (xrefEntry.uncompressed) { |
|
|
|
if (xrefEntry.uncompressed) { |
|
|
|
return this.fetchUncompressed(ref, xrefEntry, suppressEncryption); |
|
|
|
xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return this.fetchCompressed(xrefEntry, suppressEncryption); |
|
|
|
xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isDict(xrefEntry)) { |
|
|
|
|
|
|
|
xrefEntry.objId = 'R' + ref.num + '.' + ref.gen; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return xrefEntry; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry, |
|
|
|
fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry, |
|
|
|