]> git.parisson.com Git - pdf.js.git/commitdiff
Merge branch 'master' into predictor
authorsbarman <sbarman@L3CWZ5T.(none)>
Mon, 20 Jun 2011 21:56:34 +0000 (14:56 -0700)
committersbarman <sbarman@L3CWZ5T.(none)>
Mon, 20 Jun 2011 21:56:34 +0000 (14:56 -0700)
Conflicts:
pdf.js

1  2 
pdf.js

diff --cc pdf.js
index 6a1589ddeae541271d2536022e75a0015aacb425,0101f71f450299018641f1f147a724f2cf054c16..8133fa1729a0211225d031cb773c70ee165313cc
--- 1/pdf.js
--- 2/pdf.js
+++ b/pdf.js
@@@ -508,168 -509,90 +510,254 @@@ var FlateStream = (function() 
      return constructor;
  })();
  
 +var FilterPredictor = (function() {
 +    function constructor(str, type, width, colors, bits) {
 +        this.str = str;
 +        this.dict = str.dict;
 +
 +        this.type = type;
 +        this.width = width;
 +        this.colors = colors;
 +        this.bits = bits;
 +        
 +        this.nVals = width * colors;
 +        var pixBytes = (colors * bits + 7) >> 3;
 +        this.pixBytes = pixBytes;
 +        var rowBytes = ((width * colors * bits + 7) >> 3) + pixBytes;
 +        this.rowBytes = rowBytes;
 +
 +        if (width < 0 || colors < 0 || bits < 0 ||bits > 16)
 +            error("Invalid predictor");
 +        
 +        var prevLine = [];
 +        for (var i = 0; i < rowBytes; ++i)
 +            prevLine.push(0);
 +        this.prevLine = prevLine;
 +        this.prevIdx = rowBytes;
 +    }
 +
 +    constructor.prototype = {
 +        getByte: function() {
 +            if (this.prevIdx >= this.rowBytes) {
 +                if(!this.getNextLine())
 +                    return;
 +            }
 +            return this.prevLine[this.prevIdx++];
 +        },
 +        getBytes: function(length) {
 +            var buf = new Uint8Array(length);
 +            for (var i = 0; i < length; ++i)
 +                buf[i] = this.getByte();
 +            return buf;
 +        },
 +        getNextLine: function() {
 +            if (this.type >= 10) {
 +                var curType = this.str.getByte();
 +                if (!curType)
 +                    return;
 +                curType += 10;
 +            } else {
 +                var curType = this.type;
 +            }
 +
 +            var line = [];
 +            for (var i = 0; i < this.rowBytes - this.pixBytes; i++)
 +                line.push(this.str.getByte());
 +
 +            var pixBytes = this.pixBytes;
 +            var rowBytes = this.rowBytes;
 +            var prevLine = this.prevLine;
 +
 +            var upLeftBuf = [];
 +            for (var i = 0, ii = pixBytes + 1; i < ii; ++i)
 +                upLeftBuf.push(0);
 +            
 +            for (var i = pixBytes, ii = rowBytes + pixBytes + 1; i < ii; ++i) {
 +                for (var j = pixBytes; j > 0; --j) {
 +                    upLeftBuf[j] = upLeftBuf[j - 1];
 +                }
 +                upLeftBuf[0] = prevLine[i];
 +
 +                var c = line[i - pixBytes];
 +                if (c == undefined) {
 +                    if (i > pixBytes)
 +                        break;
 +                    return;
 +                }
 +                switch (curType) {
 +                case 11:
 +                    prevLine[i] = prevLine[i - pixBytes] + c;
 +                    break;
 +                case 12:
 +                    prevLine[i] = prevLine[i] + c;
 +                    break;
 +                case 13:
 +                    prevLine[i] = ((prevLine[i - pixBytes] 
 +                                + prevLine[i]) >> 1) + c;
 +                    break;
 +                case 14:
 +                    var left = prevLine[i - pixBytes];
 +                    var up = prevLine[i];
 +                    var upLeft = upLeftBuf[pixBytes];
 +                    var p = left + up - upLeft;
 +
 +                    var pa = p - left;
 +                    if (pa < 0)
 +                        pa = -pa;
 +                    var pb = p - up;
 +                    if (pb < 0)
 +                        pb = -pb;
 +                    var pc = p - upLeft;
 +                    if (pc < 0)
 +                        pc = -pc;
 +
 +                    if (pa <= pb && pa <= pc)
 +                        prevLine[i] = left + c;
 +                    else if (pb <= pc)
 +                        prevLine[i] = up + c;
 +                    else
 +                        prevLine[i] = upLeft + c;
 +                    break;
 +                case 10:
 +                default:
 +                    prevLine[i] = c;
 +                    break;
 +                }
 +            }
 +            var bits = this.bits;
 +            var colors = this.colors;
 +
 +            if (curType === 2) {
 +                if (bits === 1) {
 +                    var inbuf = prevLine[pixBytes - 1];
 +                    for (var i = pixBytes; i < rowBytes; i+= 8) {
 +                        inBuf = (inBuf << 8) | prevLine[i];
 +                        prevLine[i] ^= inBuf >> colors; 
 +                    }
 +                } else if (bits === 8) {
 +                    for (var i = pixBytes; i < rowBytes; ++i)
 +                        prevLine[i] += prevLine[i - colors];
 +                } else {
 +                    for (var i = 0, ii = colors + 1; i < ii; ++i)
 +                        upLeftBuf[i] = 0;
 +                    var bitMask = (1 << bits) - 1;
 +                    var inbuf = 0, outbut = 0;
 +                    var inbits = 0, outbits = 0;
 +                    var j = pixBytes, k = pixBytes;
 +                    var width = this.width;
 +                    for (var i = 0; i < width; ++i) {
 +                        for (var kk = 0; kk < colors; ++kk) {
 +                            if (inbits < bits) {
 +                                inbuf = (inbuf << 8) | (prevLine[j++] & 255);
 +                                inbits += 8;
 +                            }
 +                            upLeftBuf[kk] = (upLeftBuf[kk] + (inbuf >> 
 +                                        (inbits - bits))) & bitMask;
 +                            inbits -= bits;
 +                            outbuf = (outbuf << bits) | upLeftBuf[kk];
 +                            outbits += bits;
 +                            if (outbits >= 8) {
 +                                prevLine[k++] = (outbuf >> (outbits - 8));
 +                                outbits -= 8;
 +                            }
 +                        }
 +                    }
 +                    if (outbits > 0) {
 +                        prevLine[k++] = (outbuf << (8 - outbits)) +
 +                            (inbuf & ((1 << (8 - outbits)) - 1))
 +                    }
 +                }
 +            }
 +            this.prevIdx = pixBytes;
 +            return true;
 +        }
 +    };
++    return constructor;
++})();
+ var PredictorStream = (function() {
+     function constructor(stream, params) {
+         this.stream = stream;
+         this.predictor = params.get("Predictor") || 1;
+         if (this.predictor <= 1) {
+             return stream; // no prediction
+         }
+         if (params.has("EarlyChange")) {
+             error("EarlyChange predictor parameter is not supported");
+         }
+         this.colors = params.get("Colors") || 1;
+         this.bitsPerComponent = params.get("BitsPerComponent") || 8;
+         this.columns = params.get("Columns") || 1;
+         if (this.colors !== 1 || this.bitsPerComponent !== 8) {
+             error("Multi-color and multi-byte predictors are not supported");
+         }
+         if (this.predictor < 10 || this.predictor > 15) {
+             error("Unsupported predictor");
+         }
+         this.currentRow = new Uint8Array(this.columns);
+         this.pos = 0;
+         this.bufferLength = 0;
+     }
+     constructor.prototype = {
+         readRow : function() {
+             var lastRow = this.currentRow;
+             var predictor = this.stream.getByte();
+             var currentRow = this.stream.getBytes(this.columns), i;
+             switch (predictor) {
+             default:
+                 error("Unsupported predictor");
+                 break;
+             case 0:
+                 break;
+             case 2:
+                 for (i = 0; i < currentRow.length; ++i) {
+                   currentRow[i] = (lastRow[i] + currentRow[i]) & 0xFF;
+                 }
+                 break;
+             }
+             this.pos = 0;
+             this.bufferLength = currentRow.length;
+             this.currentRow = currentRow;
+         },
+         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());
+         },
+         lookChar : function() {
+             if (this.pos >= this.bufferLength) {
+                this.readRow();
+             }
+             return String.formCharCode(this.currentRow[this.pos]);
+         },
+         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;
+         }
+     };
  
      return constructor;
  })();
@@@ -719,26 -636,20 +807,20 @@@ var Dict = (function() 
  
      constructor.prototype = {
          get: function(key) {
 -            return this.map[key];
 -        },
 -        get2: function(key1, key2) {
 -            return this.get(key1) || this.get(key2);
 -        },
 -        has: function(key) {
 -            return key in this.map;
 -        },
 -        set: function(key, value) {
 -            this.map[key] = value;
 -        },
 -        forEach: function(aCallback) {
 +                 return this.map[key];
 +             },
 +    get2: function(key1, key2) {
 +              return this.get(key1) || this.get(key2);
 +          },
 +    has: function(key) {
 +             return key in this.map;
 +         },
 +    set: function(key, value) {
 +             this.map[key] = value;
 +         },
 +    forEach: function(aCallback) {
            for (var key in this.map)
              aCallback(key, this.map[key]);
-         },
-         toString: function() {
-           var keys = [];
-           for (var key in this.map)
-             keys.push(key);
-           return "Dict with " + keys.length + " keys: " + keys;
          }
      };
  
@@@ -1290,26 -1204,10 +1375,32 @@@ var Parser = (function() 
          },
          makeFilter: function(stream, name, params) {
              if (name == "FlateDecode" || name == "Fl") {
 +                var flateStr = new FlateStream(stream);
 +                if (IsDict(params)) {
 +                    var predType = params.get("Predictor");
 +                    if (predType && predType > 1) {
 +                        var colors = params.get("Colors");
 +                        if (!colors)
 +                            colors = 1;
 +                        var bpc = params.get("BitsPerComponent");
 +                        if (!bpc)
 +                            bpc = 8;
 +                        var cols = params.get("Columns");
 +                        if (!cols)
 +                            cols = 1;
 +
 +                        log("Predictor being used");
 +                        flateStr = new FilterPredictor(flateStr, predType, cols,      
 +                                colors, bpc);
 +                    }
 +                }
 +                return flateStr;
++                /*
+                 if (params) {
+                     return new PredictorStream(new FlateStream(stream), params);
+                 }
+                 return new FlateStream(stream);
++            */
              } else {
                  error("filter '" + name + "' not supported yet");
              }