]> git.parisson.com Git - pdf.js.git/commitdiff
Optimize usage of the memory in the LZWStream; linting
authornotmasteryet <async.processingjs@yahoo.com>
Sun, 14 Aug 2011 20:16:24 +0000 (15:16 -0500)
committernotmasteryet <async.processingjs@yahoo.com>
Sun, 14 Aug 2011 20:16:24 +0000 (15:16 -0500)
pdf.js
web/compatibility.js

diff --git a/pdf.js b/pdf.js
index ca64b796b3f826713dd4c4770415cc1ee18b7d05..24d602a861300dbc429ebf5e48be0961539ee91a 100644 (file)
--- a/pdf.js
+++ b/pdf.js
@@ -1989,18 +1989,23 @@ var LZWStream = (function() {
     this.dict = str.dict;
     this.cachedData = 0;
     this.bitsCached = 0;
-    this.earlyChange = earlyChange;
-    this.codeLength = 9;
-    this.nextCode = 258;
-    this.dictionary = [];
-    this.currentSequence = null;
+
+    var maxLzwDictionarySize = 4097;
+    var lzwState = {
+      earlyChange: earlyChange,
+      codeLength: 9,
+      nextCode: 258,
+      dictionaryValues: new Uint8Array(maxLzwDictionarySize),
+      dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
+      dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
+      currentSequence: new Uint8Array(maxLzwDictionarySize),
+      currentSequenceLength: 0
+    };
     for (var i = 0; i < 256; ++i) {
-      this.dictionary[i] = {
-        value: i,
-        firstValue: i,
-        length: 1
-      };
+      lzwState.dictionaryValues[i] = i;
+      lzwState.dictionaryLengths[i] = 1;
     }
+    this.lzwState = lzwState;
 
     DecodeStream.call(this);
   }
@@ -2027,34 +2032,44 @@ var LZWStream = (function() {
 
   constructor.prototype.readBlock = function() {
     var blockSize = 512;
-    var decoded = [];
+    var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
     var i, j, q;
-    var earlyChange = this.earlyChange;
-    var nextCode = this.nextCode;
-    var dictionary = this.dictionary;
-    var codeLength = this.codeLength;
-    var prevCode = this.prevCode;
-    var currentSequence = this.currentSequence;
+
+    var lzwState = this.lzwState;
+    var earlyChange = lzwState.earlyChange;
+    var nextCode = lzwState.nextCode;
+    var dictionaryValues = lzwState.dictionaryValues;
+    var dictionaryLengths = lzwState.dictionaryLengths;
+    var dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
+    var codeLength = lzwState.codeLength;
+    var prevCode = lzwState.prevCode;
+    var currentSequence = lzwState.currentSequence;
+    var currentSequenceLength = lzwState.currentSequenceLength;
+
+    var decodedLength = 0;
+    var currentBufferLength = this.bufferLength;
+    var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+
     for (i = 0; i < blockSize; i++) {
       var code = this.readBits(codeLength);
-      var hasPrev = !!currentSequence;
+      var hasPrev = currentSequenceLength > 0;
       if (code < 256) {
-        currentSequence = dictionary[code];
+        currentSequence[0] = code;
+        currentSequenceLength = 1;
       } else if (code >= 258) {
         if (code < nextCode) {
-          currentSequence = dictionary[code];
+          currentSequenceLength = dictionaryLengths[code];
+          for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
+            currentSequence[j] = dictionaryValues[q];
+            q = dictionaryPrevCodes[q];
+          }
         } else {
-          currentSequence = {
-            value: currentSequence.firstValue,
-            length: currentSequence.length + 1,
-            firstValue: currentSequence.firstValue,
-            prev: currentSequence
-          };
+          currentSequence[currentSequenceLength++] = currentSequence[0];
         }
       } else if (code == 256) {
         codeLength = 9;
         nextCode = 258;
-        currentSequence = null;
+        currentSequenceLength = 0;
         continue;
       } else {
         this.eof = true;
@@ -2062,15 +2077,11 @@ var LZWStream = (function() {
       }
 
       if (hasPrev) {
-        var prevCodeSequence = dictionary[prevCode];
-        dictionary[nextCode] = {
-          prev: prevCodeSequence,
-          length: prevCodeSequence.length + 1,
-          firstValue: prevCodeSequence.firstValue,
-          value: currentSequence.firstValue
-        };
+        dictionaryPrevCodes[nextCode] = prevCode;
+        dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
+        dictionaryValues[nextCode] = currentSequence[0];
         nextCode++;
-        switch(nextCode + earlyChange) {
+        switch (nextCode + earlyChange) {
           case 512:
             codeLength = 10;
             break;
@@ -2083,28 +2094,23 @@ var LZWStream = (function() {
         }
       }
       prevCode = code;
-      decoded.push(currentSequence);
-    }
-    this.nextCode = nextCode;
-    this.codeLength = codeLength;
-    this.prevCode = prevCode;
-    this.currentSequence = currentSequence;
-
-    var blockLength = 0;
-    var length = decoded.length;
-    for (i = 0; i < length; i++)
-      blockLength += decoded[i].length;
-    var bufferLength = this.bufferLength;
-    var buffer = this.ensureBuffer(bufferLength + blockLength);
-    for (i = 0; i < length; i++) {
-      var p = decoded[i];
-      for (q = p.length - 1; q >= 0; q--) {
-        buffer[bufferLength + q] = p.value;
-        p = p.prev;
-      }
-      bufferLength += decoded[i].length;
+
+      decodedLength += currentSequenceLength;
+      if (estimatedDecodedSize < decodedLength) {
+        do {
+          estimatedDecodedSize += decodedSizeDelta;
+        } while (estimatedDecodedSize < decodedLength);
+        buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+      }
+      for (j = 0; j < currentSequenceLength; j++)
+        buffer[currentBufferLength++] = currentSequence[j];
     }
-    this.bufferLength = bufferLength;
+    lzwState.nextCode = nextCode;
+    lzwState.codeLength = codeLength;
+    lzwState.prevCode = prevCode;
+    lzwState.currentSequenceLength = currentSequenceLength;
+
+    this.bufferLength = currentBufferLength;
   };
 
   return constructor;
@@ -2752,7 +2758,8 @@ var Parser = (function() {
         if (params) {
           if (params.has('EarlyChange'))
             earlyChange = params.get('EarlyChange');
-          return new PredictorStream(new LZWStream(stream, earlyChange), params);
+          return new PredictorStream(
+            new LZWStream(stream, earlyChange), params);
         }
         return new LZWStream(stream, earlyChange);
       } else if (name == 'DCTDecode' || name == 'DCT') {
index 5687d30ce989f66e56554ab111b4df7671a877d2..d286692b16e9e400f889961b02d68cf83bd09176 100644 (file)
@@ -40,6 +40,7 @@
   // so we can use the TypedArray as well
   window.Uint32Array = TypedArray;
   window.Int32Array = TypedArray;
+  window.Uint16Array = TypedArray;
 })();
 
 // Object.create() ?