Browse Source

Merge pull request #4405 from nnethercote/avoid-re-reading-streams

Avoid unnecessary re-reading of streams
Brendan Dahl 11 years ago
parent
commit
c3ed71c9c5
  1. 2
      src/core/chunked_stream.js
  2. 9
      src/core/parser.js
  3. 89
      src/core/stream.js

2
src/core/chunked_stream.js

@ -187,6 +187,8 @@ var ChunkedStream = (function ChunkedStreamClosure() {
}, },
makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) { makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) {
this.ensureRange(start, start + length);
function ChunkedStreamSubstream() {} function ChunkedStreamSubstream() {}
ChunkedStreamSubstream.prototype = Object.create(this); ChunkedStreamSubstream.prototype = Object.create(this);
ChunkedStreamSubstream.prototype.getMissingChunks = function() { ChunkedStreamSubstream.prototype.getMissingChunks = function() {

9
src/core/parser.js

@ -300,12 +300,10 @@ var Parser = (function ParserClosure() {
return new LZWStream(stream, earlyChange); return new LZWStream(stream, earlyChange);
} }
if (name == 'DCTDecode' || name == 'DCT') { if (name == 'DCTDecode' || name == 'DCT') {
var bytes = stream.getBytes(length); return new JpegStream(stream, length, stream.dict, this.xref);
return new JpegStream(bytes, stream.dict, this.xref);
} }
if (name == 'JPXDecode' || name == 'JPX') { if (name == 'JPXDecode' || name == 'JPX') {
var bytes = stream.getBytes(length); return new JpxStream(stream, length, stream.dict);
return new JpxStream(bytes, stream.dict);
} }
if (name == 'ASCII85Decode' || name == 'A85') { if (name == 'ASCII85Decode' || name == 'A85') {
return new Ascii85Stream(stream); return new Ascii85Stream(stream);
@ -320,8 +318,7 @@ var Parser = (function ParserClosure() {
return new RunLengthStream(stream); return new RunLengthStream(stream);
} }
if (name == 'JBIG2Decode') { if (name == 'JBIG2Decode') {
var bytes = stream.getBytes(length); return new Jbig2Stream(stream, length, stream.dict);
return new Jbig2Stream(bytes, stream.dict);
} }
warn('filter "' + name + '" not supported yet'); warn('filter "' + name + '" not supported yet');
return stream; return stream;

89
src/core/stream.js

@ -14,8 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* globals bytesToString, ColorSpace, Dict, EOF, error, info, Jbig2Image, /* globals bytesToString, ColorSpace, Dict, EOF, error, info, isArray,
JpegImage, JpxImage, Lexer, Util, PDFJS, isArray, warn */ Jbig2Image, JpegImage, JpxImage, Lexer, PDFJS, shadow, Util, warn */
'use strict'; 'use strict';
@ -328,13 +328,12 @@ var FlateStream = (function FlateStreamClosure() {
0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
]), 5]; ]), 5];
function FlateStream(stream) { function FlateStream(str) {
var bytes = stream.getBytes(); this.str = str;
var bytesPos = 0; this.dict = str.dict;
this.dict = stream.dict; var cmf = str.getByte();
var cmf = bytes[bytesPos++]; var flg = str.getByte();
var flg = bytes[bytesPos++];
if (cmf == -1 || flg == -1) if (cmf == -1 || flg == -1)
error('Invalid header in flate stream: ' + cmf + ', ' + flg); error('Invalid header in flate stream: ' + cmf + ', ' + flg);
if ((cmf & 0x0f) != 0x08) if ((cmf & 0x0f) != 0x08)
@ -344,9 +343,6 @@ var FlateStream = (function FlateStreamClosure() {
if (flg & 0x20) if (flg & 0x20)
error('FDICT bit set in flate stream: ' + cmf + ', ' + flg); error('FDICT bit set in flate stream: ' + cmf + ', ' + flg);
this.bytes = bytes;
this.bytesPos = bytesPos;
this.codeSize = 0; this.codeSize = 0;
this.codeBuf = 0; this.codeBuf = 0;
@ -356,37 +352,37 @@ var FlateStream = (function FlateStreamClosure() {
FlateStream.prototype = Object.create(DecodeStream.prototype); FlateStream.prototype = Object.create(DecodeStream.prototype);
FlateStream.prototype.getBits = function FlateStream_getBits(bits) { FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
var str = this.str;
var codeSize = this.codeSize; var codeSize = this.codeSize;
var codeBuf = this.codeBuf; var codeBuf = this.codeBuf;
var bytes = this.bytes;
var bytesPos = this.bytesPos;
var b; var b;
while (codeSize < bits) { while (codeSize < bits) {
if (typeof (b = bytes[bytesPos++]) == 'undefined') if ((b = str.getByte()) === -1) {
error('Bad encoding in flate stream'); error('Bad encoding in flate stream');
}
codeBuf |= b << codeSize; codeBuf |= b << codeSize;
codeSize += 8; codeSize += 8;
} }
b = codeBuf & ((1 << bits) - 1); b = codeBuf & ((1 << bits) - 1);
this.codeBuf = codeBuf >> bits; this.codeBuf = codeBuf >> bits;
this.codeSize = codeSize -= bits; this.codeSize = codeSize -= bits;
this.bytesPos = bytesPos;
return b; return b;
}; };
FlateStream.prototype.getCode = function FlateStream_getCode(table) { FlateStream.prototype.getCode = function FlateStream_getCode(table) {
var str = this.str;
var codes = table[0]; var codes = table[0];
var maxLen = table[1]; var maxLen = table[1];
var codeSize = this.codeSize; var codeSize = this.codeSize;
var codeBuf = this.codeBuf; var codeBuf = this.codeBuf;
var bytes = this.bytes;
var bytesPos = this.bytesPos;
while (codeSize < maxLen) { while (codeSize < maxLen) {
var b; var b;
if (typeof (b = bytes[bytesPos++]) == 'undefined') if ((b = str.getByte()) === -1) {
error('Bad encoding in flate stream'); error('Bad encoding in flate stream');
}
codeBuf |= (b << codeSize); codeBuf |= (b << codeSize);
codeSize += 8; codeSize += 8;
} }
@ -397,7 +393,6 @@ var FlateStream = (function FlateStreamClosure() {
error('Bad encoding in flate stream'); error('Bad encoding in flate stream');
this.codeBuf = (codeBuf >> codeLen); this.codeBuf = (codeBuf >> codeLen);
this.codeSize = (codeSize - codeLen); this.codeSize = (codeSize - codeLen);
this.bytesPos = bytesPos;
return codeVal; return codeVal;
}; };
@ -441,6 +436,7 @@ var FlateStream = (function FlateStreamClosure() {
}; };
FlateStream.prototype.readBlock = function FlateStream_readBlock() { FlateStream.prototype.readBlock = function FlateStream_readBlock() {
var str = this.str;
// read block header // read block header
var hdr = this.getBits(3); var hdr = this.getBits(3);
if (hdr & 1) if (hdr & 1)
@ -448,21 +444,23 @@ var FlateStream = (function FlateStreamClosure() {
hdr >>= 1; hdr >>= 1;
if (hdr === 0) { // uncompressed block if (hdr === 0) { // uncompressed block
var bytes = this.bytes;
var bytesPos = this.bytesPos;
var b; var b;
if (typeof (b = bytes[bytesPos++]) == 'undefined') if ((b = str.getByte()) === -1) {
error('Bad block header in flate stream'); error('Bad block header in flate stream');
}
var blockLen = b; var blockLen = b;
if (typeof (b = bytes[bytesPos++]) == 'undefined') if ((b = str.getByte()) === -1) {
error('Bad block header in flate stream'); error('Bad block header in flate stream');
}
blockLen |= (b << 8); blockLen |= (b << 8);
if (typeof (b = bytes[bytesPos++]) == 'undefined') if ((b = str.getByte()) === -1) {
error('Bad block header in flate stream'); error('Bad block header in flate stream');
}
var check = b; var check = b;
if (typeof (b = bytes[bytesPos++]) == 'undefined') if ((b = str.getByte()) === -1) {
error('Bad block header in flate stream'); error('Bad block header in flate stream');
}
check |= (b << 8); check |= (b << 8);
if (check != (~blockLen & 0xffff) && if (check != (~blockLen & 0xffff) &&
(blockLen !== 0 || check !== 0)) { (blockLen !== 0 || check !== 0)) {
@ -478,19 +476,18 @@ var FlateStream = (function FlateStreamClosure() {
var end = bufferLength + blockLen; var end = bufferLength + blockLen;
this.bufferLength = end; this.bufferLength = end;
if (blockLen === 0) { if (blockLen === 0) {
if (typeof bytes[bytesPos] == 'undefined') { if (str.peekBytes(1).length === 0) {
this.eof = true; this.eof = true;
} }
} else { } else {
for (var n = bufferLength; n < end; ++n) { for (var n = bufferLength; n < end; ++n) {
if (typeof (b = bytes[bytesPos++]) == 'undefined') { if ((b = str.getByte()) === -1) {
this.eof = true; this.eof = true;
break; break;
} }
buffer[n] = b; buffer[n] = b;
} }
} }
this.bytesPos = bytesPos;
return; return;
} }
@ -777,17 +774,25 @@ var PredictorStream = (function PredictorStreamClosure() {
* DecodeStreams. * DecodeStreams.
*/ */
var JpegStream = (function JpegStreamClosure() { var JpegStream = (function JpegStreamClosure() {
function JpegStream(bytes, dict, xref) { function JpegStream(stream, length, dict, xref) {
// TODO: per poppler, some images may have 'junk' before that // TODO: per poppler, some images may have 'junk' before that
// need to be removed // need to be removed
this.stream = stream;
this.length = length;
this.dict = dict; this.dict = dict;
this.bytes = bytes;
DecodeStream.call(this); DecodeStream.call(this);
} }
JpegStream.prototype = Object.create(DecodeStream.prototype); JpegStream.prototype = Object.create(DecodeStream.prototype);
Object.defineProperty(JpegStream.prototype, 'bytes', {
get: function JpegStream_bytes() {
return shadow(this, 'bytes', this.stream.getBytes(this.length));
},
configurable: true
});
JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) { JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) {
if (this.bufferLength) if (this.bufferLength)
return; return;
@ -836,15 +841,23 @@ var JpegStream = (function JpegStreamClosure() {
* the stream behaves like all the other DecodeStreams. * the stream behaves like all the other DecodeStreams.
*/ */
var JpxStream = (function JpxStreamClosure() { var JpxStream = (function JpxStreamClosure() {
function JpxStream(bytes, dict) { function JpxStream(stream, length, dict) {
this.stream = stream;
this.length = length;
this.dict = dict; this.dict = dict;
this.bytes = bytes;
DecodeStream.call(this); DecodeStream.call(this);
} }
JpxStream.prototype = Object.create(DecodeStream.prototype); JpxStream.prototype = Object.create(DecodeStream.prototype);
Object.defineProperty(JpxStream.prototype, 'bytes', {
get: function JpxStream_bytes() {
return shadow(this, 'bytes', this.stream.getBytes(this.length));
},
configurable: true
});
JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) { JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) {
if (this.bufferLength) if (this.bufferLength)
return; return;
@ -935,15 +948,23 @@ var JpxStream = (function JpxStreamClosure() {
* the stream behaves like all the other DecodeStreams. * the stream behaves like all the other DecodeStreams.
*/ */
var Jbig2Stream = (function Jbig2StreamClosure() { var Jbig2Stream = (function Jbig2StreamClosure() {
function Jbig2Stream(bytes, dict) { function Jbig2Stream(stream, length, dict) {
this.stream = stream;
this.length = length;
this.dict = dict; this.dict = dict;
this.bytes = bytes;
DecodeStream.call(this); DecodeStream.call(this);
} }
Jbig2Stream.prototype = Object.create(DecodeStream.prototype); Jbig2Stream.prototype = Object.create(DecodeStream.prototype);
Object.defineProperty(Jbig2Stream.prototype, 'bytes', {
get: function Jbig2Stream_bytes() {
return shadow(this, 'bytes', this.stream.getBytes(this.length));
},
configurable: true
});
Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) { Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) {
if (this.bufferLength) if (this.bufferLength)
return; return;

Loading…
Cancel
Save