mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-21 23:58:07 +02:00
merge upstream
This commit is contained in:
commit
9597efb3f4
48 changed files with 1194 additions and 230 deletions
65
src/api.js
65
src/api.js
|
@ -7,20 +7,46 @@
|
|||
* is used, which means it must follow the same origin rules that any XHR does
|
||||
* e.g. No cross domain requests without CORS.
|
||||
*
|
||||
* @param {string|TypedAray} source Either a url to a PDF is located or a
|
||||
* typed array (Uint8Array) already populated with data.
|
||||
* @param {Object} headers An object containing the http headers like this:
|
||||
* { Authorization: "BASIC XXX" }.
|
||||
* @param {string|TypedAray|object} source Can be an url to where a PDF is
|
||||
* located, a typed array (Uint8Array) already populated with data or
|
||||
* and parameter object with the following possible fields:
|
||||
* - url - The URL of the PDF.
|
||||
* - data - A typed array with PDF data.
|
||||
* - httpHeaders - Basic authentication headers.
|
||||
* - password - For decrypting password-protected PDFs.
|
||||
*
|
||||
* @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
|
||||
*/
|
||||
PDFJS.getDocument = function getDocument(source, headers) {
|
||||
PDFJS.getDocument = function getDocument(source) {
|
||||
var url, data, headers, password, parameters = {};
|
||||
if (typeof source === 'string') {
|
||||
url = source;
|
||||
} else if (isArrayBuffer(source)) {
|
||||
data = source;
|
||||
} else if (typeof source === 'object') {
|
||||
url = source.url;
|
||||
data = source.data;
|
||||
headers = source.httpHeaders;
|
||||
password = source.password;
|
||||
parameters.password = password || null;
|
||||
|
||||
if (!url && !data)
|
||||
error('Invalid parameter array, need either .data or .url');
|
||||
} else {
|
||||
error('Invalid parameter in getDocument, need either Uint8Array, ' +
|
||||
'string or a parameter object');
|
||||
}
|
||||
|
||||
var promise = new PDFJS.Promise();
|
||||
var transport = new WorkerTransport(promise);
|
||||
if (typeof source === 'string') {
|
||||
if (data) {
|
||||
// assuming the data is array, instantiating directly from it
|
||||
transport.sendData(data, parameters);
|
||||
} else if (url) {
|
||||
// fetch url
|
||||
PDFJS.getPdf(
|
||||
{
|
||||
url: source,
|
||||
url: url,
|
||||
progress: function getPDFProgress(evt) {
|
||||
if (evt.lengthComputable)
|
||||
promise.progress({
|
||||
|
@ -35,12 +61,10 @@ PDFJS.getDocument = function getDocument(source, headers) {
|
|||
headers: headers
|
||||
},
|
||||
function getPDFLoad(data) {
|
||||
transport.sendData(data);
|
||||
transport.sendData(data, parameters);
|
||||
});
|
||||
} else {
|
||||
// assuming the source is array, instantiating directly from it
|
||||
transport.sendData(source);
|
||||
}
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
|
@ -122,6 +146,11 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
|
|||
});
|
||||
return promise;
|
||||
},
|
||||
isEncrypted: function PDFDocumentProxy_isEncrypted() {
|
||||
var promise = new PDFJS.Promise();
|
||||
promise.resolve(this.pdfInfo.encrypted);
|
||||
return promise;
|
||||
},
|
||||
destroy: function PDFDocumentProxy_destroy() {
|
||||
this.transport.destroy();
|
||||
}
|
||||
|
@ -429,7 +458,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
messageHandler.send('test', testObj);
|
||||
return;
|
||||
} catch (e) {
|
||||
warn('The worker has been disabled.');
|
||||
info('The worker has been disabled.');
|
||||
}
|
||||
}
|
||||
// Either workers are disabled, not supported or have thrown an exception.
|
||||
|
@ -473,6 +502,14 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
this.workerReadyPromise.resolve(pdfDocument);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('NeedPassword', function transportPassword(data) {
|
||||
this.workerReadyPromise.reject(data.exception.message, data.exception);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('IncorrectPassword', function transportBadPass(data) {
|
||||
this.workerReadyPromise.reject(data.exception.message, data.exception);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('GetPage', function transportPage(data) {
|
||||
var pageInfo = data.pageInfo;
|
||||
var page = new PDFPageProxy(pageInfo, this);
|
||||
|
@ -575,8 +612,8 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
});
|
||||
},
|
||||
|
||||
sendData: function WorkerTransport_sendData(data) {
|
||||
this.messageHandler.send('GetDocRequest', data);
|
||||
sendData: function WorkerTransport_sendData(data, params) {
|
||||
this.messageHandler.send('GetDocRequest', {data: data, params: params});
|
||||
},
|
||||
|
||||
getPage: function WorkerTransport_getPage(pageNumber, promise) {
|
||||
|
|
|
@ -343,10 +343,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
this.ctx.webkitLineDashOffset = dashPhase;
|
||||
},
|
||||
setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
|
||||
TODO('set rendering intent: ' + intent);
|
||||
// Maybe if we one day fully support color spaces this will be important
|
||||
// for now we can ignore.
|
||||
// TODO set rendering intent?
|
||||
},
|
||||
setFlatness: function CanvasGraphics_setFlatness(flatness) {
|
||||
TODO('set flatness: ' + flatness);
|
||||
// There's no way to control this with canvas, but we can safely ignore.
|
||||
// TODO set flatness?
|
||||
},
|
||||
setGState: function CanvasGraphics_setGState(states) {
|
||||
for (var i = 0, ii = states.length; i < ii; i++) {
|
||||
|
@ -841,7 +844,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
text.length += shownText.length;
|
||||
}
|
||||
} else {
|
||||
malformed('TJ array element ' + e + ' is not string or num');
|
||||
error('TJ array element ' + e + ' is not string or num');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -451,12 +451,12 @@ var LabCS = (function LabCSClosure() {
|
|||
error('Invalid WhitePoint components, no fallback available');
|
||||
|
||||
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
|
||||
warn('Invalid BlackPoint, falling back to default');
|
||||
info('Invalid BlackPoint, falling back to default');
|
||||
this.XB = this.YB = this.ZB = 0;
|
||||
}
|
||||
|
||||
if (this.amin > this.amax || this.bmin > this.bmax) {
|
||||
warn('Invalid Range, falling back to defaults');
|
||||
info('Invalid Range, falling back to defaults');
|
||||
this.amin = -100;
|
||||
this.amax = 100;
|
||||
this.bmin = -100;
|
||||
|
|
17
src/core.js
17
src/core.js
|
@ -7,7 +7,7 @@ var globalScope = (typeof window === 'undefined') ? this : window;
|
|||
|
||||
var isWorker = (typeof window == 'undefined');
|
||||
|
||||
var ERRORS = 0, WARNINGS = 1, TODOS = 5;
|
||||
var ERRORS = 0, WARNINGS = 1, INFOS = 5;
|
||||
var verbosity = WARNINGS;
|
||||
|
||||
// The global PDFJS object exposes the API
|
||||
|
@ -362,19 +362,19 @@ var Page = (function PageClosure() {
|
|||
* `PDFDocument` objects on the main thread created.
|
||||
*/
|
||||
var PDFDocument = (function PDFDocumentClosure() {
|
||||
function PDFDocument(arg, callback) {
|
||||
function PDFDocument(arg, password) {
|
||||
if (isStream(arg))
|
||||
init.call(this, arg);
|
||||
init.call(this, arg, password);
|
||||
else if (isArrayBuffer(arg))
|
||||
init.call(this, new Stream(arg));
|
||||
init.call(this, new Stream(arg), password);
|
||||
else
|
||||
error('PDFDocument: Unknown argument type');
|
||||
}
|
||||
|
||||
function init(stream) {
|
||||
function init(stream, password) {
|
||||
assertWellFormed(stream.length > 0, 'stream must have data');
|
||||
this.stream = stream;
|
||||
this.setup();
|
||||
this.setup(password);
|
||||
this.acroForm = this.catalog.catDict.get('AcroForm');
|
||||
}
|
||||
|
||||
|
@ -465,11 +465,12 @@ var PDFDocument = (function PDFDocumentClosure() {
|
|||
}
|
||||
// May not be a PDF file, continue anyway.
|
||||
},
|
||||
setup: function PDFDocument_setup(ownerPassword, userPassword) {
|
||||
setup: function PDFDocument_setup(password) {
|
||||
this.checkHeader();
|
||||
var xref = new XRef(this.stream,
|
||||
this.startXRef,
|
||||
this.mainXRefEntriesOffset);
|
||||
this.mainXRefEntriesOffset,
|
||||
password);
|
||||
this.xref = xref;
|
||||
this.catalog = new Catalog(xref);
|
||||
},
|
||||
|
|
|
@ -556,7 +556,9 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||
var encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
|
||||
ownerPassword, userPassword, flags,
|
||||
revision, keyLength, encryptMetadata);
|
||||
if (!encryptionKey && password) {
|
||||
if (!encryptionKey && !password) {
|
||||
throw new PasswordException('No password given', 'needpassword');
|
||||
} else if (!encryptionKey && password) {
|
||||
// Attempting use the password as an owner password
|
||||
var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword,
|
||||
revision, keyLength);
|
||||
|
@ -566,7 +568,7 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||
}
|
||||
|
||||
if (!encryptionKey)
|
||||
error('incorrect password or encryption data');
|
||||
throw new PasswordException('Incorrect Password', 'incorrectpassword');
|
||||
|
||||
this.encryptionKey = encryptionKey;
|
||||
|
||||
|
|
|
@ -108,39 +108,21 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
|
||||
// Compatibility
|
||||
BX: 'beginCompat',
|
||||
EX: 'endCompat'
|
||||
EX: 'endCompat',
|
||||
|
||||
// (reserved partial commands for the lexer)
|
||||
BM: null,
|
||||
BD: null,
|
||||
'true': null,
|
||||
fa: null,
|
||||
fal: null,
|
||||
fals: null,
|
||||
'false': null,
|
||||
nu: null,
|
||||
nul: null,
|
||||
'null': null
|
||||
};
|
||||
|
||||
function splitCombinedOperations(operations) {
|
||||
// Two or more operations can be combined together, trying to find which
|
||||
// operations were concatenated.
|
||||
var result = [];
|
||||
var opIndex = 0;
|
||||
|
||||
if (!operations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while (opIndex < operations.length) {
|
||||
var currentOp = '';
|
||||
for (var op in OP_MAP) {
|
||||
if (op == operations.substr(opIndex, op.length) &&
|
||||
op.length > currentOp.length) {
|
||||
currentOp = op;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentOp.length > 0) {
|
||||
result.push(operations.substr(opIndex, currentOp.length));
|
||||
opIndex += currentOp.length;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PartialEvaluator.prototype = {
|
||||
getOperatorList: function PartialEvaluator_getOperatorList(stream,
|
||||
resources,
|
||||
|
@ -285,39 +267,19 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
resources = resources || new Dict();
|
||||
var xobjs = resources.get('XObject') || new Dict();
|
||||
var patterns = resources.get('Pattern') || new Dict();
|
||||
var parser = new Parser(new Lexer(stream), false, xref);
|
||||
var parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
|
||||
var res = resources;
|
||||
var hasNextObj = false, nextObjs;
|
||||
var args = [], obj;
|
||||
var TILING_PATTERN = 1, SHADING_PATTERN = 2;
|
||||
|
||||
while (true) {
|
||||
if (hasNextObj) {
|
||||
obj = nextObjs.pop();
|
||||
hasNextObj = (nextObjs.length > 0);
|
||||
} else {
|
||||
obj = parser.getObj();
|
||||
if (isEOF(obj))
|
||||
break;
|
||||
}
|
||||
obj = parser.getObj();
|
||||
if (isEOF(obj))
|
||||
break;
|
||||
|
||||
if (isCmd(obj)) {
|
||||
var cmd = obj.cmd;
|
||||
var fn = OP_MAP[cmd];
|
||||
if (!fn) {
|
||||
// invalid content command, trying to recover
|
||||
var cmds = splitCombinedOperations(cmd);
|
||||
if (cmds) {
|
||||
cmd = cmds[0];
|
||||
fn = OP_MAP[cmd];
|
||||
// feeding other command on the next iteration
|
||||
hasNextObj = true;
|
||||
nextObjs = [];
|
||||
for (var idx = 1; idx < cmds.length; idx++) {
|
||||
nextObjs.push(Cmd.get(cmds[idx]));
|
||||
}
|
||||
}
|
||||
}
|
||||
assertWellFormed(fn, 'Unknown command "' + cmd + '"');
|
||||
// TODO figure out how to type-check vararg functions
|
||||
|
||||
|
@ -457,6 +419,18 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
value[1]
|
||||
]);
|
||||
break;
|
||||
case 'BM':
|
||||
// We support the default so don't trigger the TODO.
|
||||
if (!isName(value) || value.name != 'Normal')
|
||||
TODO('graphic state operator ' + key);
|
||||
break;
|
||||
case 'SMask':
|
||||
// We support the default so don't trigger the TODO.
|
||||
if (!isName(value) || value.name != 'None')
|
||||
TODO('graphic state operator ' + key);
|
||||
break;
|
||||
// Only generate info log messages for the following since
|
||||
// they are unlikey to have a big impact on the rendering.
|
||||
case 'OP':
|
||||
case 'op':
|
||||
case 'OPM':
|
||||
|
@ -469,14 +443,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
case 'HT':
|
||||
case 'SM':
|
||||
case 'SA':
|
||||
case 'BM':
|
||||
case 'SMask':
|
||||
case 'AIS':
|
||||
case 'TK':
|
||||
TODO('graphic state operator ' + key);
|
||||
// TODO implement these operators.
|
||||
info('graphic state operator ' + key);
|
||||
break;
|
||||
default:
|
||||
warn('Unknown graphic state operator ' + key);
|
||||
info('Unknown graphic state operator ' + key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -725,8 +698,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
}
|
||||
} else if (octet == 0x3E) {
|
||||
if (token.length) {
|
||||
// XXX guessing chars size by checking number size in the CMap
|
||||
if (token.length <= 2 && properties.composite)
|
||||
// Heuristic: guessing chars size by checking numbers sizes
|
||||
// in the CMap entries.
|
||||
if (token.length == 2 && properties.composite)
|
||||
properties.wideChars = false;
|
||||
|
||||
if (token.length <= 4) {
|
||||
|
|
31
src/fonts.js
31
src/fonts.js
|
@ -2706,9 +2706,9 @@ var Font = (function FontClosure() {
|
|||
this.isSymbolicFont = false;
|
||||
}
|
||||
|
||||
// heuristics: if removed more than 2 glyphs encoding WinAnsiEncoding
|
||||
// does not set properly
|
||||
if (glyphsRemoved > 2) {
|
||||
// heuristics: if removed more than 10 glyphs encoding WinAnsiEncoding
|
||||
// does not set properly (broken PDFs have about 100 removed glyphs)
|
||||
if (glyphsRemoved > 10) {
|
||||
warn('Switching TrueType encoding to MacRomanEncoding for ' +
|
||||
this.name + ' font');
|
||||
encoding = Encodings.MacRomanEncoding;
|
||||
|
@ -4208,7 +4208,7 @@ var CFFFont = (function CFFFontClosure() {
|
|||
this.properties = properties;
|
||||
|
||||
var parser = new CFFParser(file, properties);
|
||||
var cff = parser.parse();
|
||||
var cff = parser.parse(true);
|
||||
var compiler = new CFFCompiler(cff);
|
||||
this.readExtra(cff);
|
||||
try {
|
||||
|
@ -4299,7 +4299,7 @@ var CFFParser = (function CFFParserClosure() {
|
|||
this.properties = properties;
|
||||
}
|
||||
CFFParser.prototype = {
|
||||
parse: function CFFParser_parse() {
|
||||
parse: function CFFParser_parse(normalizeCIDData) {
|
||||
var properties = this.properties;
|
||||
var cff = new CFF();
|
||||
this.cff = cff;
|
||||
|
@ -4354,6 +4354,21 @@ var CFFParser = (function CFFParserClosure() {
|
|||
cff.charset = charset;
|
||||
cff.encoding = encoding;
|
||||
|
||||
if (!cff.isCIDFont || !normalizeCIDData)
|
||||
return cff;
|
||||
|
||||
// DirectWrite does not like CID fonts data. Trying to convert/flatten
|
||||
// the font data and remove CID properties.
|
||||
if (cff.fdArray.length !== 1)
|
||||
error('Unable to normalize CID font in CFF data');
|
||||
|
||||
var fontDict = cff.fdArray[0];
|
||||
fontDict.setByKey(17, topDict.getByName('CharStrings'));
|
||||
cff.topDict = fontDict;
|
||||
cff.isCIDFont = false;
|
||||
delete cff.fdArray;
|
||||
delete cff.fdSelect;
|
||||
|
||||
return cff;
|
||||
},
|
||||
parseHeader: function CFFParser_parseHeader() {
|
||||
|
@ -4364,7 +4379,7 @@ var CFFParser = (function CFFParserClosure() {
|
|||
++offset;
|
||||
|
||||
if (offset != 0) {
|
||||
warn('cff data is shifted');
|
||||
info('cff data is shifted');
|
||||
bytes = bytes.subarray(offset);
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
@ -4952,9 +4967,9 @@ var CFFPrivateDict = (function CFFPrivateDictClosure() {
|
|||
[[12, 17], 'LanguageGroup', 'num', 0],
|
||||
[[12, 18], 'ExpansionFactor', 'num', 0.06],
|
||||
[[12, 19], 'initialRandomSeed', 'num', 0],
|
||||
[19, 'Subrs', 'offset', null],
|
||||
[20, 'defaultWidthX', 'num', 0],
|
||||
[21, 'nominalWidthX', 'num', 0]
|
||||
[21, 'nominalWidthX', 'num', 0],
|
||||
[19, 'Subrs', 'offset', null]
|
||||
];
|
||||
var tables = null;
|
||||
function CFFPrivateDict(strings) {
|
||||
|
|
|
@ -298,7 +298,7 @@ var Catalog = (function CatalogClosure() {
|
|||
})();
|
||||
|
||||
var XRef = (function XRefClosure() {
|
||||
function XRef(stream, startXRef, mainXRefEntriesOffset) {
|
||||
function XRef(stream, startXRef, mainXRefEntriesOffset, password) {
|
||||
this.stream = stream;
|
||||
this.entries = [];
|
||||
this.xrefstms = {};
|
||||
|
@ -311,8 +311,7 @@ var XRef = (function XRefClosure() {
|
|||
var encrypt = trailerDict.get('Encrypt');
|
||||
if (encrypt) {
|
||||
var fileId = trailerDict.get('ID');
|
||||
this.encrypt = new CipherTransformFactory(encrypt,
|
||||
fileId[0] /*, password */);
|
||||
this.encrypt = new CipherTransformFactory(encrypt, fileId[0], password);
|
||||
}
|
||||
|
||||
// get the root dictionary (catalog) object
|
||||
|
|
|
@ -264,8 +264,16 @@ var Parser = (function ParserClosure() {
|
|||
})();
|
||||
|
||||
var Lexer = (function LexerClosure() {
|
||||
function Lexer(stream) {
|
||||
function Lexer(stream, knownCommands) {
|
||||
this.stream = stream;
|
||||
// The PDFs might have "glued" commands with other commands, operands or
|
||||
// literals, e.g. "q1". The knownCommands is a dictionary of the valid
|
||||
// commands and their prefixes. The prefixes are built the following way:
|
||||
// if there a command that is a prefix of the other valid command or
|
||||
// literal (e.g. 'f' and 'false') the following prefixes must be included,
|
||||
// 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no
|
||||
// other commands or literals as a prefix. The knowCommands is optional.
|
||||
this.knownCommands = knownCommands;
|
||||
}
|
||||
|
||||
Lexer.isSpace = function Lexer_isSpace(ch) {
|
||||
|
@ -529,12 +537,18 @@ var Lexer = (function LexerClosure() {
|
|||
|
||||
// command
|
||||
var str = ch;
|
||||
var knownCommands = this.knownCommands;
|
||||
var knownCommandFound = knownCommands && (str in knownCommands);
|
||||
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
|
||||
// stop if known command is found and next character does not make
|
||||
// the str a command
|
||||
if (knownCommandFound && !((str + ch) in knownCommands))
|
||||
break;
|
||||
stream.skip();
|
||||
if (str.length == 128)
|
||||
error('Command token too long: ' + str.length);
|
||||
|
||||
str += ch;
|
||||
knownCommandFound = knownCommands && (str in knownCommands);
|
||||
}
|
||||
if (str == 'true')
|
||||
return true;
|
||||
|
|
|
@ -1687,7 +1687,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||
|
||||
if (a1 > codingLine[codingPos]) {
|
||||
if (a1 > this.columns) {
|
||||
warn('row is wrong length');
|
||||
info('row is wrong length');
|
||||
this.err = true;
|
||||
a1 = this.columns;
|
||||
}
|
||||
|
@ -1707,7 +1707,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||
|
||||
if (a1 > codingLine[codingPos]) {
|
||||
if (a1 > this.columns) {
|
||||
warn('row is wrong length');
|
||||
info('row is wrong length');
|
||||
this.err = true;
|
||||
a1 = this.columns;
|
||||
}
|
||||
|
@ -1717,7 +1717,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||
codingLine[codingPos] = a1;
|
||||
} else if (a1 < codingLine[codingPos]) {
|
||||
if (a1 < 0) {
|
||||
warn('invalid code');
|
||||
info('invalid code');
|
||||
this.err = true;
|
||||
a1 = 0;
|
||||
}
|
||||
|
@ -1879,7 +1879,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||
this.eof = true;
|
||||
break;
|
||||
default:
|
||||
warn('bad 2d code');
|
||||
info('bad 2d code');
|
||||
this.addPixels(columns, 0);
|
||||
this.err = true;
|
||||
}
|
||||
|
@ -1942,7 +1942,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||
for (var i = 0; i < 4; ++i) {
|
||||
code1 = this.lookBits(12);
|
||||
if (code1 != 1)
|
||||
warn('bad rtc code: ' + code1);
|
||||
info('bad rtc code: ' + code1);
|
||||
this.eatBits(12);
|
||||
if (this.encoding > 0) {
|
||||
this.lookBits(1);
|
||||
|
@ -2065,7 +2065,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||
if (result[0] && result[2])
|
||||
return result[1];
|
||||
}
|
||||
warn('Bad two dim code');
|
||||
info('Bad two dim code');
|
||||
return EOF;
|
||||
};
|
||||
|
||||
|
@ -2098,7 +2098,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||
if (result[0])
|
||||
return result[1];
|
||||
}
|
||||
warn('bad white code');
|
||||
info('bad white code');
|
||||
this.eatBits(1);
|
||||
return 1;
|
||||
};
|
||||
|
@ -2135,7 +2135,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||
if (result[0])
|
||||
return result[1];
|
||||
}
|
||||
warn('bad black code');
|
||||
info('bad black code');
|
||||
this.eatBits(1);
|
||||
return 1;
|
||||
};
|
||||
|
|
83
src/util.js
83
src/util.js
|
@ -3,6 +3,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
// Use only for debugging purposes. This should not be used in any code that is
|
||||
// in mozilla master.
|
||||
function log(msg) {
|
||||
if (console && console.log)
|
||||
console.log(msg);
|
||||
|
@ -10,9 +12,36 @@ function log(msg) {
|
|||
print(msg);
|
||||
}
|
||||
|
||||
// A notice for devs that will not trigger the fallback UI. These are good
|
||||
// for things that are helpful to devs, such as warning that Workers were
|
||||
// disabled, which is important to devs but not end users.
|
||||
function info(msg) {
|
||||
if (verbosity >= INFOS) {
|
||||
log('Info: ' + msg);
|
||||
PDFJS.LogManager.notify('info', msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Non-fatal warnings that should trigger the fallback UI.
|
||||
function warn(msg) {
|
||||
if (verbosity >= WARNINGS)
|
||||
if (verbosity >= WARNINGS) {
|
||||
log('Warning: ' + msg);
|
||||
PDFJS.LogManager.notify('warn', msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Fatal errors that should trigger the fallback UI and halt execution by
|
||||
// throwing an exception.
|
||||
function error(msg) {
|
||||
log('Error: ' + msg);
|
||||
log(backtrace());
|
||||
PDFJS.LogManager.notify('error', msg);
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
// Missing features that should trigger the fallback UI.
|
||||
function TODO(what) {
|
||||
warn('TODO: ' + what);
|
||||
}
|
||||
|
||||
function backtrace() {
|
||||
|
@ -23,21 +52,6 @@ function backtrace() {
|
|||
}
|
||||
}
|
||||
|
||||
function error(msg) {
|
||||
log('Error: ' + msg);
|
||||
log(backtrace());
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
function TODO(what) {
|
||||
if (verbosity >= TODOS)
|
||||
log('TODO: ' + what);
|
||||
}
|
||||
|
||||
function malformed(msg) {
|
||||
error('Malformed PDF: ' + msg);
|
||||
}
|
||||
|
||||
function assert(cond, msg) {
|
||||
if (!cond)
|
||||
error(msg);
|
||||
|
@ -47,9 +61,25 @@ function assert(cond, msg) {
|
|||
// behavior is undefined.
|
||||
function assertWellFormed(cond, msg) {
|
||||
if (!cond)
|
||||
malformed(msg);
|
||||
error(msg);
|
||||
}
|
||||
|
||||
var LogManager = PDFJS.LogManager = (function LogManagerClosure() {
|
||||
var loggers = [];
|
||||
return {
|
||||
addLogger: function logManager_addLogger(logger) {
|
||||
loggers.push(logger);
|
||||
},
|
||||
notify: function(type, message) {
|
||||
for (var i = 0, ii = loggers.length; i < ii; i++) {
|
||||
var logger = loggers[i];
|
||||
if (logger[type])
|
||||
logger[type](message);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
function shadow(obj, prop, value) {
|
||||
Object.defineProperty(obj, prop, { value: value,
|
||||
enumerable: true,
|
||||
|
@ -58,6 +88,19 @@ function shadow(obj, prop, value) {
|
|||
return value;
|
||||
}
|
||||
|
||||
var PasswordException = (function PasswordExceptionClosure() {
|
||||
function PasswordException(msg, code) {
|
||||
this.name = 'PasswordException';
|
||||
this.message = msg;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
PasswordException.prototype = new Error();
|
||||
PasswordException.constructor = PasswordException;
|
||||
|
||||
return PasswordException;
|
||||
})();
|
||||
|
||||
function bytesToString(bytes) {
|
||||
var str = '';
|
||||
var length = bytes.length;
|
||||
|
@ -456,7 +499,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
|
|||
}
|
||||
|
||||
this.isResolved = true;
|
||||
this.data = data || null;
|
||||
this.data = (typeof data !== 'undefined') ? data : null;
|
||||
var callbacks = this.callbacks;
|
||||
|
||||
for (var i = 0, ii = callbacks.length; i < ii; i++) {
|
||||
|
@ -471,7 +514,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
|
|||
}
|
||||
},
|
||||
|
||||
reject: function Promise_reject(reason) {
|
||||
reject: function Promise_reject(reason, exception) {
|
||||
if (this.isRejected) {
|
||||
error('A Promise can be rejected only once ' + this.name);
|
||||
}
|
||||
|
@ -484,7 +527,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
|
|||
var errbacks = this.errbacks;
|
||||
|
||||
for (var i = 0, ii = errbacks.length; i < ii; i++) {
|
||||
errbacks[i].call(null, reason);
|
||||
errbacks[i].call(null, reason, exception);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -11,10 +11,13 @@ function MessageHandler(name, comObj) {
|
|||
var ah = this.actionHandler = {};
|
||||
|
||||
ah['console_log'] = [function ahConsoleLog(data) {
|
||||
console.log.apply(console, data);
|
||||
console.log.apply(console, data);
|
||||
}];
|
||||
ah['console_error'] = [function ahConsoleError(data) {
|
||||
console.error.apply(console, data);
|
||||
console.error.apply(console, data);
|
||||
}];
|
||||
ah['_warn'] = [function ah_Warn(data) {
|
||||
warn(data);
|
||||
}];
|
||||
|
||||
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
|
||||
|
@ -88,14 +91,35 @@ var WorkerMessageHandler = {
|
|||
handler.on('GetDocRequest', function wphSetupDoc(data) {
|
||||
// Create only the model of the PDFDoc, which is enough for
|
||||
// processing the content of the pdf.
|
||||
pdfModel = new PDFDocument(new Stream(data));
|
||||
var pdfData = data.data;
|
||||
var pdfPassword = data.params.password;
|
||||
try {
|
||||
pdfModel = new PDFDocument(new Stream(pdfData), pdfPassword);
|
||||
} catch (e) {
|
||||
if (e instanceof PasswordException) {
|
||||
if (e.code === 'needpassword') {
|
||||
handler.send('NeedPassword', {
|
||||
exception: e
|
||||
});
|
||||
} else if (e.code === 'incorrectpassword') {
|
||||
handler.send('IncorrectPassword', {
|
||||
exception: e
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
var doc = {
|
||||
numPages: pdfModel.numPages,
|
||||
fingerprint: pdfModel.getFingerprint(),
|
||||
destinations: pdfModel.catalog.destinations,
|
||||
outline: pdfModel.catalog.documentOutline,
|
||||
info: pdfModel.getDocumentInfo(),
|
||||
metadata: pdfModel.catalog.metadata
|
||||
metadata: pdfModel.catalog.metadata,
|
||||
encrypted: !!pdfModel.xref.encrypt
|
||||
};
|
||||
handler.send('GetDoc', {pdfInfo: doc});
|
||||
});
|
||||
|
@ -240,6 +264,17 @@ var workerConsole = {
|
|||
if (typeof window === 'undefined') {
|
||||
globalScope.console = workerConsole;
|
||||
|
||||
// Add a logger so we can pass warnings on to the main thread, errors will
|
||||
// throw an exception which will be forwarded on automatically.
|
||||
PDFJS.LogManager.addLogger({
|
||||
warn: function(msg) {
|
||||
postMessage({
|
||||
action: '_warn',
|
||||
data: msg
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var handler = new MessageHandler('worker_processor', this);
|
||||
WorkerMessageHandler.setup(handler);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue