get length() {
return this.end - this.start;
},
- lookByte: function() {
- if (this.pos >= this.end)
- return;
- return this.bytes[this.pos];
- },
getByte: function() {
if (this.pos >= this.end)
return;
return bytes.subarray(pos, end);
},
lookChar: function() {
- return String.fromCharCode(this.lookByte());
+ if (this.pos >= this.end)
+ return;
+ return String.fromCharCode(this.bytes[this.pos]);
},
getChar: function() {
- return String.fromCharCode(this.getByte());
+ if (this.pos >= this.end)
+ return;
+ return String.fromCharCode(this.bytes[this.pos++]);
},
skip: function(n) {
if (!n)
return constructor;
})();
+// super class for the decoding streams
+var DecodeStream = (function() {
+ function constructor() {
+ this.pos = 0;
+ this.bufferLength = 0;
+ this.eof = false;
+ this.buffer = null;
+ }
+
+ constructor.prototype = {
+ ensureBuffer: function(requested) {
+ var buffer = this.buffer;
+ var current = buffer ? buffer.byteLength : 0;
+ if (requested < current)
+ return buffer;
+ var size = 512;
+ while (size < requested)
+ size <<= 1;
+ var buffer2 = Uint8Array(size);
+ for (var i = 0; i < current; ++i)
+ buffer2[i] = buffer[i];
+ return this.buffer = buffer2;
+ },
+ getByte: function() {
+ var pos = this.pos;
+ while (this.bufferLength <= pos) {
+ if (this.eof)
+ return;
+ this.readBlock();
+ }
+ return this.buffer[this.pos++];
+ },
+ getBytes: function(length) {
+ var pos = this.pos;
+
+ this.ensureBuffer(pos + length);
+ while (!this.eof && this.bufferLength < pos + length)
+ this.readBlock();
+
+ var end = pos + length;
+ var bufEnd = this.bufferLength;
+
+ if (end > bufEnd)
+ end = bufEnd;
+
+ this.pos = end;
+ return this.buffer.subarray(pos, end)
+ },
+ lookChar: function() {
+ var pos = this.pos;
+ while (this.bufferLength <= pos) {
+ if (this.eof)
+ return;
+ this.readBlock();
+ }
+ return String.fromCharCode(this.buffer[this.pos]);
+ },
+ getChar: function() {
+ var pos = this.pos;
+ while (this.bufferLength <= pos) {
+ if (this.eof)
+ return;
+ this.readBlock();
+ }
+ return String.fromCharCode(this.buffer[this.pos++]);
+ },
+ skip: function(n) {
+ if (!n)
+ n = 1;
+ this.pos += n;
+ }
+ };
+
+ return constructor;
+})();
+
+
+
var FlateStream = (function() {
const codeLenCodeMap = Uint32Array([
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
this.bytes = bytes;
this.bytesPos = bytesPos;
- this.eof = false;
+
this.codeSize = 0;
this.codeBuf = 0;
-
- this.pos = 0;
- this.bufferLength = 0;
+
+ DecodeStream.call(this);
}
constructor.prototype = {
this.bytesPos = bytesPos;
return codeVal;
},
- ensureBuffer: function(requested) {
- var buffer = this.buffer;
- var current = buffer ? buffer.byteLength : 0;
- if (requested < current)
- return buffer;
- var size = 512;
- while (size < requested)
- size <<= 1;
- var buffer2 = Uint8Array(size);
- for (var i = 0; i < current; ++i)
- buffer2[i] = buffer[i];
- return this.buffer = buffer2;
- },
- getByte: function() {
- var pos = this.pos;
- while (this.bufferLength <= pos) {
- if (this.eof)
- return;
- this.readBlock();
- }
- return this.buffer[this.pos++];
- },
- getBytes: function(length) {
- var pos = this.pos;
-
- while (!this.eof && this.bufferLength < pos + length)
- this.readBlock();
-
- var end = pos + length;
- var bufEnd = this.bufferLength;
-
- if (end > bufEnd)
- end = bufEnd;
-
- this.pos = end;
- return this.buffer.subarray(pos, end)
- },
- lookChar: function() {
- var pos = this.pos;
- while (this.bufferLength <= pos) {
- if (this.eof)
- return;
- this.readBlock();
- }
- return String.fromCharCode(this.buffer[pos]);
- },
- getChar: function() {
- var ch = this.lookChar();
- // shouldnt matter what the position is if we get past the eof
- // so no need to check if ch is undefined
- this.pos++;
- return ch;
- },
- skip: function(n) {
- if (!n)
- n = 1;
- this.pos += n;
- },
generateHuffmanTable: function(lengths) {
var n = lengths.length;
}
}
- litCodeTable = this.generateHuffmanTable(codeLengths.slice(0, numLitCodes));
- distCodeTable = this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes));
+ litCodeTable = this.generateHuffmanTable(
+ codeLengths.slice(0, numLitCodes));
+ distCodeTable = this.generateHuffmanTable(
+ codeLengths.slice(numLitCodes, codes));
} else {
error("Unknown block type in flate stream");
}
}
};
- return constructor;
-})();
-// A JpegStream can't be read directly. We use the platform to render the underlying
-// JPEG data for us.
-var JpegStream = (function() {
- function constructor(bytes, dict) {
- // TODO: per poppler, some images may have "junk" before that need to be removed
- this.dict = dict;
-
- // create DOM image
- var img = new Image();
- img.src = "data:image/jpeg;base64," + window.btoa(bytesToString(bytes));
- this.domImage = img;
+ var thisPrototype = constructor.prototype;
+ var superPrototype = DecodeStream.prototype;
+ for (var i in superPrototype) {
+ if (!thisPrototype[i])
+ thisPrototype[i] = superPrototype[i];
}
- constructor.prototype = {
- getImage: function() {
- return this.domImage;
- },
- getChar: function() {
- error("internal error: getChar is not valid on JpegStream");
- }
- };
-
return constructor;
})();
error("Unsupported predictor");
if (predictor === 2)
- this.readRow = this.readRowTiff;
+ this.readBlock = this.readBlockTiff;
else
- this.readRow = this.readRowPng;
+ this.readBlock = this.readBlockPng;
this.stream = stream;
this.dict = stream.dict;
var pixBytes = this.pixBytes = (colors * bits + 7) >> 3;
// add an extra pixByte to represent the pixel left of column 0
- var rowBytes = this.rowBytes = ((columns * colors * bits + 7) >> 3) + pixBytes;
-
- this.currentRow = new Uint8Array(rowBytes);
- this.bufferLength = rowBytes;
- this.pos = rowBytes;
+ var rowBytes = this.rowBytes = (columns * colors * bits + 7) >> 3;
+
+ DecodeStream.call(this);
}
constructor.prototype = {
- readRowTiff : function() {
- var currentRow = this.currentRow;
+ readBlockTiff : function() {
+ var buffer = this.buffer;
+ var pos = this.pos;
+
var rowBytes = this.rowBytes;
var pixBytes = this.pixBytes;
+
+
+ var buffer = this.buffer;
+ var bufferLength = this.bufferLength;
+ this.ensureBuffer(bufferLength + rowBytes);
+ var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
+
var bits = this.bits;
var colors = this.colors;
- var rawBytes = this.stream.getBytes(rowBytes - pixBytes);
-
+ var rawBytes = this.stream.getBytes(rowBytes);
+
if (bits === 1) {
var inbuf = 0;
- for (var i = pixBytes, j = 0; i < rowBytes; ++i, ++j) {
- var c = rawBytes[j];
+ for (var i = 0; i < rowBytes; ++i) {
+ var c = rawBytes[i];
inBuf = (inBuf << 8) | c;
// bitwise addition is exclusive or
// first shift inBuf and then add
inBuf &= 0xFFFF;
}
} else if (bits === 8) {
- for (var i = pixBytes, j = 0; i < rowBytes; ++i, ++j)
- currentRow[i] = currentRow[i - colors] + rawBytes[j];
+ for (var i = 0; i < colors; ++i)
+ currentRow[i] = rawBytes[i];
+ for (; i < rowBytes; ++i)
+ currentRow[i] = currentRow[i - colors] + rawBytes[i];
} else {
var compArray = new Uint8Array(colors + 1);
var bitMask = (1 << bits) - 1;
var inbuf = 0, outbut = 0;
var inbits = 0, outbits = 0;
- var j = 0, k = pixBytes;
+ var j = 0, k = 0;
var columns = this.columns;
for (var i = 0; i < columns; ++i) {
for (var kk = 0; kk < colors; ++kk) {
(inbuf & ((1 << (8 - outbits)) - 1))
}
}
- this.pos = pixBytes;
+ this.bufferLength += rowBytes;
},
- readRowPng : function() {
- var currentRow = this.currentRow;
+ readBlockPng : function() {
+ var buffer = this.buffer;
+ var pos = this.pos;
var rowBytes = this.rowBytes;
var pixBytes = this.pixBytes;
var predictor = this.stream.getByte();
- var rawBytes = this.stream.getBytes(rowBytes - pixBytes);
+ var rawBytes = this.stream.getBytes(rowBytes);
+
+ var buffer = this.buffer;
+ var bufferLength = this.bufferLength;
+ this.ensureBuffer(bufferLength + pixBytes);
+
+ var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
+ var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
+ if (prevRow.length == 0)
+ prevRow = currentRow;
switch (predictor) {
case 0:
break;
case 1:
- for (var i = pixBytes, j = 0; i < rowBytes; ++i, ++j)
- currentRow[i] = (currentRow[i - pixBytes] + rawBytes[j]) & 0xFF;
+ for (var i = 0; i < pixBytes; ++i)
+ currentRow[i] = rawBytes[i];
+ for (; i < rowBytes; ++i)
+ currentRow[i] = (currentRow[i - pixBytes] + rawBytes[i]) & 0xFF;
break;
case 2:
- for (var i = pixBytes, j = 0; i < rowBytes; ++i, ++j)
- currentRow[i] = (currentRow[i] + rawBytes[j]) & 0xFF;
+ for (var i = 0; i < rowBytes; ++i)
+ currentRow[i] = (prevRow[i] + rawBytes[i]) & 0xFF;
break;
case 3:
- for (var i = pixBytes, j = 0; i < rowBytes; ++i, ++j)
- currentRow[i] = (((currentRow[i] + currentRow[i - pixBytes])
- >> 1) + rawBytes[j]) & 0xFF;
+ for (var i = 0; i < pixBytes; ++i)
+ currentRow[i] = (prevRow[i] >> 1) + rawBytes[i];
+ for (; i < rowBytes; ++i)
+ currentRow[i] = (((prevRow[i] + currentRow[i - pixBytes])
+ >> 1) + rawBytes[i]) & 0xFF;
break;
case 4:
// we need to save the up left pixels values. the simplest way
// is to create a new buffer
- var lastRow = currentRow;
- var currentRow = new Uint8Array(rowBytes);
- for (var i = pixBytes, j = 0; i < rowBytes; ++i, ++j) {
- var up = lastRow[i];
+ for (var i = 0; i < pixBytes; ++i)
+ currentRow[i] = rawBytes[i];
+ for (; i < rowBytes; ++i) {
+ var up = prevRow[i];
var upLeft = lastRow[i - pixBytes];
var left = currentRow[i - pixBytes];
var p = left + up - upLeft;
if (pc < 0)
pc = -pc;
- var c = rawBytes[j];
+ var c = rawBytes[i];
if (pa <= pb && pa <= pc)
currentRow[i] = left + c;
else if (pb <= pc)
else
currentRow[i] = upLeft + c;
break;
- this.currentRow = currentRow;
}
default:
error("Unsupported predictor");
break;
}
- this.pos = pixBytes;
- },
- getByte : function() {
- if (this.pos >= this.bufferLength)
- this.readRow();
- return this.currentRow[this.pos++];
- },
- getBytes : function(n) {
- var i, bytes;
- bytes = new Uint8Array(n);
- for (i = 0; i < n; ++i) {
- if (this.pos >= this.bufferLength)
- this.readRow();
- bytes[i] = this.currentRow[this.pos++];
- }
- return bytes;
- },
- getChar : function() {
- return String.formCharCode(this.getByte());
+ this.bufferLength += rowBytes;
},
- lookChar : function() {
- if (this.pos >= this.bufferLength)
- this.readRow();
- return String.formCharCode(this.currentRow[this.pos]);
+ };
+
+ var thisPrototype = constructor.prototype;
+ var superPrototype = DecodeStream.prototype;
+ for (var i in superPrototype) {
+ if (!thisPrototype[i])
+ thisPrototype[i] = superPrototype[i];
+ }
+
+ return constructor;
+})();
+
+// A JpegStream can't be read directly. We use the platform to render the underlying
+// JPEG data for us.
+var JpegStream = (function() {
+ function constructor(bytes, dict) {
+ // TODO: per poppler, some images may have "junk" before that need to be removed
+ this.dict = dict;
+
+ // create DOM image
+ var img = new Image();
+ img.src = "data:image/jpeg;base64," + window.btoa(bytesToString(bytes));
+ this.domImage = img;
+ }
+
+ constructor.prototype = {
+ getImage: function() {
+ return this.domImage;
},
- skip : function(n) {
- var i;
- if (!n) {
- n = 1;
- }
- while (n > this.bufferLength - this.pos) {
- n -= this.bufferLength - this.pos;
- this.readRow();
- if (this.bufferLength === 0) break;
- }
- this.pos += n;
+ getChar: function() {
+ error("internal error: getChar is not valid on JpegStream");
}
};
return constructor;
})();
-
var DecryptStream = (function() {
function constructor(str, fileKey, encAlgorithm, keyLength) {
TODO("decrypt stream is not implemented");