inline images working

This commit is contained in:
sbarman 2011-08-03 21:11:57 -07:00
parent 476c633a88
commit a32b56ae85

106
pdf.js
View File

@ -228,6 +228,13 @@ var DecodeStream = (function() {
} }
return String.fromCharCode(this.buffer[this.pos++]); return String.fromCharCode(this.buffer[this.pos++]);
}, },
makeSubStream: function decodestream_makeSubstream(start, length, dict) {
var end = start + length;
while (this.bufferLength <= end && !this.eof) {
this.readBlock();
}
return new Stream(this.buffer, start, length, dict);
},
skip: function decodestream_skip(n) { skip: function decodestream_skip(n) {
if (!n) if (!n)
n = 1; n = 1;
@ -2436,28 +2443,21 @@ var Parser = (function() {
this.buf2 = this.lexer.getObj(); this.buf2 = this.lexer.getObj();
}, },
shift: function() { shift: function() {
if (this.inlineImg > 0) { if (IsCmd(this.buf2, 'ID')) {
if (this.inlineImg < 2) {
this.inlineImg++;
} else {
// in a damaged content stream, if 'ID' shows up in the middle
// of a dictionary, we need to reset
this.inlineImg = 0;
}
} else if (IsCmd(this.buf2, 'ID')) {
this.lexer.skip(); // skip char after 'ID' command
this.inlineImg = 1;
}
this.buf1 = this.buf2; this.buf1 = this.buf2;
// don't buffer inline image data this.buf2 = null;
this.buf2 = (this.inlineImg > 0) ? null : this.lexer.getObj(); // skip byte after ID
this.lexer.skip();
} else {
this.buf1 = this.buf2;
this.buf2 = this.lexer.getObj();
}
}, },
getObj: function(cipherTransform) { getObj: function(cipherTransform) {
// refill buffer after inline image data if (IsCmd(this.buf1, 'BI')) { // inline image
if (this.inlineImg == 2) this.shift();
this.refill(); return this.makeInlineImage(cipherTransform);
} else if (IsCmd(this.buf1, '[')) { // array
if (IsCmd(this.buf1, '[')) { // array
this.shift(); this.shift();
var array = []; var array = [];
while (!IsCmd(this.buf1, ']') && !IsEOF(this.buf1)) while (!IsCmd(this.buf1, ']') && !IsEOF(this.buf1))
@ -2472,7 +2472,6 @@ var Parser = (function() {
while (!IsCmd(this.buf1, '>>') && !IsEOF(this.buf1)) { while (!IsCmd(this.buf1, '>>') && !IsEOF(this.buf1)) {
if (!IsName(this.buf1)) { if (!IsName(this.buf1)) {
error('Dictionary key must be a name object'); error('Dictionary key must be a name object');
shift();
} else { } else {
var key = this.buf1.name; var key = this.buf1.name;
this.shift(); this.shift();
@ -2492,7 +2491,6 @@ var Parser = (function() {
this.shift(); this.shift();
} }
return dict; return dict;
} else if (IsInt(this.buf1)) { // indirect reference or integer } else if (IsInt(this.buf1)) { // indirect reference or integer
var num = this.buf1; var num = this.buf1;
this.shift(); this.shift();
@ -2516,6 +2514,46 @@ var Parser = (function() {
this.shift(); this.shift();
return obj; return obj;
}, },
makeInlineImage: function(cipherTransform) {
var lexer = this.lexer;
var stream = lexer.stream;
// parse dictionary
var dict = new Dict();
while (!IsCmd(this.buf1, 'ID') && !IsEOF(this.buf1)) {
if (!IsName(this.buf1)) {
error('Dictionary key must be a name object');
} else {
var key = this.buf1.name;
this.shift();
if (IsEOF(this.buf1))
break;
dict.set(key, this.getObj(cipherTransform));
}
}
// parse image stream
var startPos = stream.pos;
var c1 = stream.getChar();
var c2 = stream.getChar();
while (!(c1 == 'E' && c2 == 'I') && c2 != null) {
c1 = c2;
c2 = stream.getChar();
}
var length = (stream.pos - 2) - startPos;
var imageStream = stream.makeSubStream(startPos, length, dict);
if (cipherTransform)
imageStream = cipherTransform.createStream(imageStream);
imageStream = this.filter(imageStream, dict, length);
imageStream.parameters = dict;
this.buf2 = new Cmd('EI');
this.shift();
return imageStream;
},
makeStream: function(dict, cipherTransform) { makeStream: function(dict, cipherTransform) {
var lexer = this.lexer; var lexer = this.lexer;
var stream = lexer.stream; var stream = lexer.stream;
@ -2577,15 +2615,14 @@ var Parser = (function() {
return new PredictorStream(new FlateStream(stream), params); return new PredictorStream(new FlateStream(stream), params);
} }
return new FlateStream(stream); return new FlateStream(stream);
} else if (name == 'DCTDecode') { } else if (name == 'DCTDecode' || name == 'DCT') {
var bytes = stream.getBytes(length); var bytes = stream.getBytes(length);
return new JpegStream(bytes, stream.dict); return new JpegStream(bytes, stream.dict);
} else if (name == 'ASCII85Decode') { } else if (name == 'ASCII85Decode' || name == 'A85') {
return new Ascii85Stream(stream); return new Ascii85Stream(stream);
} else if (name == 'ASCIIHexDecode') { } else if (name == 'ASCIIHexDecode' || name == 'AHx') {
return new AsciiHexStream(stream); return new AsciiHexStream(stream);
} else if (name == 'CCITTFaxDecode') { } else if (name == 'CCITTFaxDecode' || name == 'CCF') {
TODO('implement fax stream');
return new CCITTFaxStream(stream, params); return new CCITTFaxStream(stream, params);
} else { } else {
error("filter '" + name + "' not supported yet"); error("filter '" + name + "' not supported yet");
@ -3551,6 +3588,8 @@ var PartialEvaluator = (function() {
// Images // Images
BI: 'beginInlineImage', BI: 'beginInlineImage',
ID: 'beginImageData',
EI: 'endInlineImage',
// XObjects // XObjects
Do: 'paintXObject', Do: 'paintXObject',
@ -3579,6 +3618,9 @@ var PartialEvaluator = (function() {
if (IsCmd(obj)) { if (IsCmd(obj)) {
var cmd = obj.cmd; var cmd = obj.cmd;
var fn = OP_MAP[cmd]; var fn = OP_MAP[cmd];
if (!fn) {
log('blah');
}
assertWellFormed(fn, "Unknown command '" + cmd + "'"); assertWellFormed(fn, "Unknown command '" + cmd + "'");
// TODO figure out how to type-check vararg functions // TODO figure out how to type-check vararg functions
@ -4438,11 +4480,13 @@ var CanvasGraphics = (function() {
// Images // Images
beginInlineImage: function() { beginInlineImage: function() {
TODO('inline images'); error('Should not call beginInlineImage');
error('(Stream will not be parsed properly, bailing now)'); },
// Like an inline stream: beginImageData: function() {
// - key/value pairs up to Cmd(ID) error('Should not call beginImageData');
// - then image data up to Cmd(EI) },
endInlineImage: function(image) {
this.paintImageXObject(null, image, true);
}, },
// XObjects // XObjects