]> git.parisson.com Git - pdf.js.git/commitdiff
rewrote streams to be object oriented
authorsbarman <sbarman@L3CWZ5T.(none)>
Wed, 22 Jun 2011 00:02:50 +0000 (17:02 -0700)
committersbarman <sbarman@L3CWZ5T.(none)>
Wed, 22 Jun 2011 00:02:50 +0000 (17:02 -0700)
pdf.js

diff --git a/pdf.js b/pdf.js
index 8ea56ae22b5b2b447f6007510dc9486c269503db..3331d5d4d5a089d59d26c3d6e1e59daef08443d8 100644 (file)
--- a/pdf.js
+++ b/pdf.js
@@ -71,11 +71,6 @@ var Stream = (function() {
         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;
@@ -99,10 +94,14 @@ var Stream = (function() {
             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)
@@ -137,6 +136,84 @@ var StringStream = (function() {
     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
@@ -261,12 +338,11 @@ var FlateStream = (function() {
 
         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 = {
@@ -314,64 +390,6 @@ var FlateStream = (function() {
             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;
 
@@ -489,8 +507,10 @@ var FlateStream = (function() {
                     }
                 }
 
-                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");
             }
@@ -526,30 +546,13 @@ var FlateStream = (function() {
         }
     };
 
-    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;
 })();
 
@@ -563,9 +566,9 @@ var PredictorStream = (function() {
             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;
@@ -578,27 +581,34 @@ var PredictorStream = (function() {
 
         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
@@ -607,14 +617,16 @@ var PredictorStream = (function() {
                     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) {
@@ -638,40 +650,54 @@ var PredictorStream = (function() {
                                       (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;
@@ -686,7 +712,7 @@ var PredictorStream = (function() {
                     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)
@@ -694,54 +720,49 @@ var PredictorStream = (function() {
                     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");