]> git.parisson.com Git - pdf.js.git/commitdiff
cleanup code a bit, avoid tabs, use java mode
authorAndreas Gal <andreas.gal@gmail.com>
Mon, 2 May 2011 22:06:11 +0000 (15:06 -0700)
committerAndreas Gal <andreas.gal@gmail.com>
Mon, 2 May 2011 22:06:11 +0000 (15:06 -0700)
pdf.js

diff --git a/pdf.js b/pdf.js
index 943c4cea23258f71c0753411b9c45128da28cc30..bfcaa48a3be6220572f5e59e10ce0dc5a37e81fc 100644 (file)
--- a/pdf.js
+++ b/pdf.js
@@ -1,36 +1,56 @@
-var EOF = -1;
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
+/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
+
+var HashMap = (function() {
+    function constructor() {
+    }
+
+    constructor.prototype = {
+        get: function(key) {
+            return this["$" + key];
+        },
+        set: function(key, value) {
+            this["$" + key] = value;
+        },
+        contains: function(key) {
+            return ("$" + key) in this;
+        }
+    };
+
+    return constructor;
+})();
 
 var Obj = (function() {
     function constructor(type, value) {
-       this.type = type;
-       this.value = value;
+        this.type = type;
+        this.value = value;
     }
 
     constructor.prototype = {
     };
 
     var types = [
-       "Bool", "Int", "Real", "String", "Name", "Null",
-       "Array", "Dict", "Stream", "Ref",
-       "Cmd", "Error", "EOF", "None"
-    ];
+                 "Bool", "Int", "Real", "String", "Name", "Null",
+                 "Array", "Dict", "Stream", "Ref",
+                 "Cmd", "Error", "EOF", "None"
+                ];
 
     for (var i = 0; i < types.length; ++i) {
-       var typeName = types[i];
-       constructor[typeName] = i;
-       constructor.prototype["is" + typeName] =
-           (function (value) {
-               return this.type == i &&
-                      (typeof value == "undefined" || value == this.value);
-           });
+        var typeName = types[i];
+        constructor[typeName] = i;
+        constructor.prototype["is" + typeName] =
+            (function (value) {
+                return this.type == i &&
+                       (typeof value == "undefined" || value == this.value);
+            });
     }
 
     constructor.prototype.lookup = function(key) {
-       function lookup(key) {
-           if (!(this.value.contains(key)))
-               return Obj.nullObj;
-           return this.value.get(key);
-       }
+        function lookup(key) {
+            if (!(this.value.contains(key)))
+                return Obj.nullObj;
+            return this.value.get(key);
+        }
     }
 
     Object.freeze(constructor.trueObj = new constructor(constructor.Bool, true));
@@ -43,50 +63,33 @@ var Obj = (function() {
     return constructor;
 })();
 
-var HashMap = (function() {
-    function constructor() {
-    }
-
-    constructor.prototype = {
-       get: function(key) {
-           return this["$" + key];
-       },
-       set: function(key, value) {
-           this["$" + key] = value;
-       },
-       contains: function(key) {
-           return ("$" + key) in this;
-       }
-    };
-
-    return constructor;
-})();
-
 var Lexer = (function() {
+    const EOF = -1;
+
     function constructor(bytes) {
-       this.bytes = bytes;
-       this.pos = 0;
+        this.bytes = bytes;
+        this.pos = 0;
     }
 
     // A '1' in this array means the character is white space.  A '1' or
     // '2' means the character ends a name or command.
     var specialChars = [
         1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,   // 0x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 1x
-       1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2,   // 2x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,   // 3x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 4x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0,   // 5x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 6x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0,   // 7x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 8x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 9x
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // ax
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // bx
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // cx
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // dx
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // ex
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0    // fx
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 1x
+        1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2,   // 2x
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,   // 3x
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 4x
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0,   // 5x
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 6x
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0,   // 7x
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 8x
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 9x
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // ax
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // bx
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // cx
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // dx
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // ex
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0    // fx
     ];
 
     const MIN_INT = (1<<31) | 0;
@@ -95,276 +98,275 @@ var Lexer = (function() {
     const MAX_UINT = ((1<<30) * 4) - 1;
 
     function ToHexDigit(ch) {
-       if (ch >= "0" && ch <= "9")
-           return ch - "0";
-       ch = ch.toLowerCase();
-       if (ch >= "a" && ch <= "f")
-           return ch - "a";
-       return -1;
+        if (ch >= "0" && ch <= "9")
+            return ch - "0";
+        ch = ch.toLowerCase();
+        if (ch >= "a" && ch <= "f")
+            return ch - "a";
+        return -1;
     }
 
     constructor.prototype = {
-       error: function(msg) {
-       },
-       lookChar: function() {
-           var bytes = this.bytes;
-           if (this.pos >= bytes.length)
-               return EOF;
-           return String.fromCharCode(bytes[this.pos]);
-       },
-       getChar: function() {
-           var ch = this.lookChar();
-           this.pos++:
-           return ch;
-       },
-       putBack(): function() {
-           this.pos--;
-       },
-       skipChar(): function() {
-           this.pos++;
-       },
-       getNumber: function(ch) {
+        error: function(msg) {
+        },
+        lookChar: function() {
+            var bytes = this.bytes;
+            if (this.pos >= bytes.length)
+                return EOF;
+            return String.fromCharCode(bytes[this.pos]);
+        },
+        getChar: function() {
+            var ch = this.lookChar();
+            this.pos++:
+            return ch;
+        },
+        putBack(): function() {
+            this.pos--;
+        },
+        skipChar(): function() {
+            this.pos++;
+        },
+        getNumber: function(ch) {
             var floating = false;
-           var str = ch;
-           do {
-               ch = this.getChar();
-               if (ch == "." && !floating) {
-                   str += ch;
-                   floating = true;
-               } else if (ch == "-") {
-                   // ignore minus signs in the middle of numbers to match
-                   // Adobe's behavior
-                   this.error("Badly formated number");
-               } else if (ch >= "0" && ch <= "9") {
-                   str += ch;
-               } else if (ch == "e" || ch == "E") {
-                   floating = true;
-               } else {
-                   // put back the last character, it doesn't belong to us
-                   this.putBack();
-                   break;
-               }
-           } while (true);
-           var value = parseNumber(str);
-           if (isNaN(value))
-               return Obj.errorObj;
-           if (floating) {
-               type = Obj.Floating;
-           } else {
-               if (value >= MIN_INT && value <= MAX_INT)
-                   type = Obj.Int;
-               else if (value >= MAX_UINT && value <= MAX_UINT)
-                   type = Obj.Uint;
-               else
-                   return Obj.errorObj;
-           }
-           return new Obj(type, value);
+            var str = ch;
+            do {
+                ch = this.getChar();
+                if (ch == "." && !floating) {
+                    str += ch;
+                    floating = true;
+                } else if (ch == "-") {
+                    // ignore minus signs in the middle of numbers to match
+                    // Adobe's behavior
+                    this.error("Badly formated number");
+                } else if (ch >= "0" && ch <= "9") {
+                    str += ch;
+                } else if (ch == "e" || ch == "E") {
+                    floating = true;
+                } else {
+                    // put back the last character, it doesn't belong to us
+                    this.putBack();
+                    break;
+                }
+            } while (true);
+            var value = parseNumber(str);
+            if (isNaN(value))
+                return Obj.errorObj;
+            if (floating) {
+                type = Obj.Floating;
+            } else {
+                if (value >= MIN_INT && value <= MAX_INT)
+                    type = Obj.Int;
+                else if (value >= MAX_UINT && value <= MAX_UINT)
+                    type = Obj.Uint;
+                else
+                    return Obj.errorObj;
+            }
+            return new Obj(type, value);
+        },
+        getString: function(ch) {
+            var n = 0;
+            var numParent = 1;
+            var done = false;
+            var str = ch;
+            do {
+                switch (ch = this.getChar()) {
+                case EOF:
+                    this.error("Unterminated string");
+                    done = true;
+                    break;
+                case '(':
+                    ++numParen;
+                    str += ch;
+                    break;
+                case ')':
+                    if (--numParen == 0) {
+                        done = true;
+                    } else {
+                        str += ch;
+                    }
+                    break;
+                case '\\':
+                    switch (ch = this.getChar()) {
+                    case 'n':
+                        str += '\n';
+                        break;
+                    case 'r':
+                        str += '\r';
+                        break;
+                    case 't':
+                        str += '\t';
+                        break;
+                    case 'b':
+                        str += '\b';
+                        break;
+                    case 'f':
+                        str += '\f';
+                        break;
+                    case '\\':
+                    case '(':
+                    case ')':
+                        str += c;
+                        break;
+                    case '0': case '1': case '2': case '3':
+                    case '4': case '5': case '6': case '7':
+                        var x = ch - '0';
+                        ch = this.lookChar();
+                        if (ch >= '0' && ch <= '7') {
+                            this.getChar();
+                            x = (x << 3) + (x - '0');
+                            ch = this.lookChar();
+                            if (ch >= '0' && ch <= '7') {
+                                getChar();
+                                x = (x << 3) + (x - '0');
+                            }
+                        }
+                        str += String.fromCharCode(x);
+                        break;
+                    case '\r':
+                        ch = this.lookChar();
+                        if (ch == '\n') {
+                            this.getChar();
+                        }
+                        break;
+                    case '\n':
+                        break;
+                    case EOF:
+                        this.error("Unterminated string");
+                        done = true;
+                        break;
+                    default:
+                        str += ch;
+                        break;
+                    }
+                    break;
+                default:
+                    str += ch;
+                    break;
+                }
+            } while (!done);
+            if (!str.length)
+                return new Obj(Obj.EOF);
+            return new Obj(Obj.String, str);
         },
-       getString: function(ch) {
-           var n = 0;
-           var numParent = 1;
-           var done = false;
-           var str = ch;
-           do {
-               switch (ch = this.getChar()) {
-               case EOF:
-                   this.error("Unterminated string");
-                   done = true;
-                   break;
-               case '(':
-                   ++numParen;
-                   str += ch;
-                   break;
-               case ')':
-                   if (--numParen == 0) {
-                       done = true;
-                   } else {
-                       str += ch;
-                   }
-                   break;
-               case '\\':
-                   switch (ch = this.getChar()) {
-                   case 'n':
-                       str += '\n';
-                       break;
-                   case 'r':
-                       str += '\r';
-                       break;
-                   case 't':
-                       str += '\t';
-                       break;
-                   case 'b':
-                       str += '\b';
-                       break;
-                   case 'f':
-                       str += '\f';
-                       break;
-                   case '\\':
-                   case '(':
-                   case ')':
-                       str += c;
-                       break;
-                   case '0': case '1': case '2': case '3':
-                   case '4': case '5': case '6': case '7':
-                       var x = ch - '0';
-                       ch = this.lookChar();
-                       if (ch >= '0' && ch <= '7') {
-                           this.getChar();
-                           x = (x << 3) + (x - '0');
-                           ch = this.lookChar();
-                           if (ch >= '0' && ch <= '7') {
-                               getChar();
-                               x = (x << 3) + (x - '0');
-                           }
-                       }
-                       str += String.fromCharCode(x);
-                       break;
-                   case '\r':
-                       ch = this.lookChar();
-                       if (ch == '\n') {
-                           this.getChar();
-                       }
-                       break;
-                   case '\n':
-                       break;
-                   case EOF:
-                       this.error("Unterminated string");
-                       done = true;
-                       break;
-                   default:
-                       str += ch;
-                       break;
-                   }
-                   break;
-                   
-               default:
-                   str += ch;
-                   break;
-               }
-           } while (!done);
-           if (!str.length)
-               return new Obj(Obj.EOF);
-           return new Obj(Obj.String, str);
-       },
-       getName: function(ch) {
-           var str = "";
-           while ((ch = this.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
-               this.getChar();
-               if (ch == "#") {
-                   ch = this.lookChar();
-                   var x = ToHexDigit(ch);
-                   if (x != -1) {
-                       this.getChar();
-                       var x2 = ToHexDigit(this.getChar());
-                       if (x2 == -1)
-                           this.error("Illegal digit in hex char in name");
-                       str += String.fromCharCode((x << 4) | x2);
-                   } else {
-                       str += "#";
-                       str += ch;
-                   }
-               } else {
-                   str += ch;
-               }
-           }
-           if (str.length > 128)
-               this.error("Warning: name token is longer than allowed by the specification");
-           return new Obj(Obj.Name, str);
-       },
-       getHexString: function(ch) {
-           var str = "";
-           while (1) {
-               ch = this.getChar();
-               if (ch == '>') {
-                   break;
-               } else if (ch == EOF) {
-                   this.error("Unterminated hex string");
-                   break;
-               } else if (specialChars[ch.toCharCode()] != 1) {
-                   var x, x2;
-                   if (((x = ToHexDigit(ch)) == -1) ||
-                       ((x2 = ToHexDigit(this.getChar())) == -1)) {
-                       error("Illegal character in hex string");
-                       break;
-                   }
-                   str += String.fromCharCode((x << 4) | x2);
-               }
-           }
-           return new Obj(Obj.String, str);
-       },
-       getObj: function() {
-           // skip whitespace and comments
-           var comment = false;
-           while (true) {
-               var ch;
-               if ((ch = this.getChar()) == EOF)
-                   return new Obj(Object.EOF);
-               if (comment) {
-                   if (ch == '\r' || ch == '\n')
-                       comment = false;
-               } else if (ch == '%') {
-                   comment = true;
-               } else if (specialChars[ch.chatCodeAt(0)] != 1) {
-                   break;
-               }
-           }
-
-           // start reading token
-           switch (c) {
-           case '0': case '1': case '2': case '3': case '4':
-           case '5': case '6': case '7': case '8': case '9':
-           case '+': case '-': case '.':
-               return this.getNumber(ch);
-           case '(':
-               return this.getString(ch);
-           case '/':
-               return this.getName(ch);
-           // array punctuation
-           case '[':
-           case ']':
-               return new Obj(Obj.Cmd, ch);
-           // hex string or dict punctuation
-           case '<':
-               ch = this.lookChar();
-               if (ch == '<') {
-                   // dict punctuation
-                   this.getChar();
-                   return new Obj(Obj.Cmd, ch);
-               }
-               return this.getHexString(ch);
-           // dict punctuation
-           case '>':
-               ch = this.lookChar();
-               if (ch == '>') {
-                   this.getChar();
-                   return new Obj(Obj.Cmd, ch);
-               }
+        getName: function(ch) {
+            var str = "";
+            while ((ch = this.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
+                this.getChar();
+                if (ch == "#") {
+                    ch = this.lookChar();
+                    var x = ToHexDigit(ch);
+                    if (x != -1) {
+                        this.getChar();
+                        var x2 = ToHexDigit(this.getChar());
+                        if (x2 == -1)
+                            this.error("Illegal digit in hex char in name");
+                        str += String.fromCharCode((x << 4) | x2);
+                    } else {
+                        str += "#";
+                        str += ch;
+                    }
+                } else {
+                    str += ch;
+                }
+            }
+            if (str.length > 128)
+                this.error("Warning: name token is longer than allowed by the specification");
+            return new Obj(Obj.Name, str);
+        },
+        getHexString: function(ch) {
+            var str = "";
+            while (1) {
+                ch = this.getChar();
+                if (ch == '>') {
+                    break;
+                } else if (ch == EOF) {
+                    this.error("Unterminated hex string");
+                    break;
+                } else if (specialChars[ch.toCharCode()] != 1) {
+                    var x, x2;
+                    if (((x = ToHexDigit(ch)) == -1) ||
+                        ((x2 = ToHexDigit(this.getChar())) == -1)) {
+                        error("Illegal character in hex string");
+                        break;
+                    }
+                    str += String.fromCharCode((x << 4) | x2);
+                }
+            }
+            return new Obj(Obj.String, str);
+        },
+        getObj: function() {
+            // skip whitespace and comments
+            var comment = false;
+            while (true) {
+                var ch;
+                if ((ch = this.getChar()) == EOF)
+                    return new Obj(Object.EOF);
+                if (comment) {
+                    if (ch == '\r' || ch == '\n')
+                        comment = false;
+                } else if (ch == '%') {
+                    comment = true;
+                } else if (specialChars[ch.chatCodeAt(0)] != 1) {
+                    break;
+                }
+            }
+            
+            // start reading token
+            switch (c) {
+            case '0': case '1': case '2': case '3': case '4':
+            case '5': case '6': case '7': case '8': case '9':
+            case '+': case '-': case '.':
+                return this.getNumber(ch);
+            case '(':
+                return this.getString(ch);
+            case '/':
+                   return this.getName(ch);
+            // array punctuation
+            case '[':
+            case ']':
+                   return new Obj(Obj.Cmd, ch);
+            // hex string or dict punctuation
+            case '<':
+                   ch = this.lookChar();
+                if (ch == '<') {
+                    // dict punctuation
+                    this.getChar();
+                    return new Obj(Obj.Cmd, ch);
+                }
+                   return this.getHexString(ch);
+            // dict punctuation
+            case '>':
+                   ch = this.lookChar();
+                   if (ch == '>') {
+                    this.getChar();
+                    return new Obj(Obj.Cmd, ch);
+                }
                // fall through
-           case ')':
-           case '{':
-           case '}':
-               this.error("Illegal character");
-               return Obj.errorObj;
-           }
-
-           // command
-           var str = ch;
-           while ((ch = this.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
-               getChar();
-               if (str.length == 128) {
-                   error("Command token too long");
-                   break;
-               }
-               str += ch;
-           }
-           if (str == "true")
-               return Obj.trueObj;
-           if (str == "false")
-               return Obj.falseObj;
-           if (str == "null")
-               return Obj.nullObj;
-           return new Obj(Obj.Cmd, str);
-       }
+            case ')':
+            case '{':
+            case '}':
+                this.error("Illegal character");
+                   return Obj.errorObj;
+            }
+
+            // command
+            var str = ch;
+            while ((ch = this.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
+                getChar();
+                if (str.length == 128) {
+                    error("Command token too long");
+                    break;
+                }
+                str += ch;
+            }
+            if (str == "true")
+                return Obj.trueObj;
+            if (str == "false")
+                return Obj.falseObj;
+            if (str == "null")
+                return Obj.nullObj;
+            return new Obj(Obj.Cmd, str);
+        }
     };
 
     Object.freeze(constructor.prototype);
@@ -374,108 +376,103 @@ var Lexer = (function() {
 
 var Parser = (function() {
     function constructor(lexer, allowStreams) {
-       this.lexer = lexer;
-       this.allowStreams = allowStreams;
-       this.inlineImg = 0;
-       this.refill();
+        this.lexer = lexer;
+        this.allowStreams = allowStreams;
+        this.inlineImg = 0;
+        this.refill();
     }
 
     constructor.prototype = {
-       refill: function() {
-           this.buf1 = lexer.getObj();
-           this.buf2 = lexer.getObj();
-       }
-       shift: function() {
-           if (this.inlineImg > 0) {
-               if (this.inlineImg < 2) {
-                   this.inlineImg++;
-               } else {
-                   // in a damaged content stream, if 'ID' shows up in the middle
-                   // of a dictionary, we need to reset
-                   this.inlineImg = 0;
-               }
-           } else if (this.buf2.isCmd("ID")) {
-               this.lexer.skipChar();          // skip char after 'ID' command
-               this.inlineImg = 1;
-           }
-           this.buf1 = this.buf2;
-           // don't buffer inline image data
-           this.buf2 = (this.inlineImg > 0) ? Obj.nullObj : this.lexer.getObj();
-       },
-       getObj: function() {
-           // refill buffer after inline image data
-           if (this.inlineImg == 2)
-               this.refill();
-
-           // array
-           if (this.buf1.isCmd("[")) {
-               var obj = new Obj(Obj.Array, []);
-               while (!this.buf1.isCmd("]") && !this.buf1.isEOF())
-                   obj.value.push(this.getObj());
-               if (this.buf1.isEOF())
-                   this.error("End of file inside array");
-               this.shift();
-               return obj;
-
-           // dictionary or stream
-           } else if (this.buf1.isCmd("<<")) {
-               this.shift();
-               var obj = new Obj(Obj.Dict, new HashMap());
-               while (!this.buf1.isCmd(">>") && !this.buf1.isEOF()) {
-                   if (!this.buf1.isName()) {
-                       error("Dictionary key must be a name object");
-                       shift();
-                   } else {
-                       var key = buf1.value;
-                       this.shift();
-                       if (this.buf1.isEOF() || this.buf1.isError())
-                           break;
-                       obj.value.set(key, this.getObj());
-                   }
-               }
-               if (this.buf1.isEOF())
-                   error("End of file inside dictionary");
-               // stream objects are not allowed inside content streams or
-               // object streams
-               if (this.allowStreams && this.buf2.isCmd("stream")) {
-                   return this.makeStream();
-               } else {
-                   this.shift();
-               }
-               return obj;
-
-           // indirect reference or integer
-           } else if (this.buf1.isInt()) {
-               var num = this.buf1.value;
-               this.shift();
-               if (this.buf1.isInt() && this.buf2.isCmd("R")) {
-                   var obj = new Obj(Obj.Ref, [num, this.buf1.value]);
-                   this.shift();
-                   this.shift();
-                   return obj;
-               }
-               return new Obj(Obj.Int, num);
-
-           // string
-           } else if (this.buf1.isString()) {
-               var obj = this.decrypt(this.buf1);
-               this.shift();
-               return obj;
-           }
+        refill: function() {
+            this.buf1 = lexer.getObj();
+            this.buf2 = lexer.getObj();
+        }
+        shift: function() {
+            if (this.inlineImg > 0) {
+                if (this.inlineImg < 2) {
+                    this.inlineImg++;
+                } else {
+                    // in a damaged content stream, if 'ID' shows up in the middle
+                    // of a dictionary, we need to reset
+                    this.inlineImg = 0;
+                }
+            } else if (this.buf2.isCmd("ID")) {
+                this.lexer.skipChar();         // skip char after 'ID' command
+                this.inlineImg = 1;
+            }
+            this.buf1 = this.buf2;
+            // don't buffer inline image data
+            this.buf2 = (this.inlineImg > 0) ? Obj.nullObj : this.lexer.getObj();
+        },
+        getObj: function() {
+            // refill buffer after inline image data
+            if (this.inlineImg == 2)
+                this.refill();
+
+            if (this.buf1.isCmd("[")) { // array
+                var obj = new Obj(Obj.Array, []);
+                while (!this.buf1.isCmd("]") && !this.buf1.isEOF())
+                    obj.value.push(this.getObj());
+                if (this.buf1.isEOF())
+                    this.error("End of file inside array");
+                this.shift();
+                return obj;
+            } else if (this.buf1.isCmd("<<")) { // dictionary or stream
+                this.shift();
+                var obj = new Obj(Obj.Dict, new HashMap());
+                while (!this.buf1.isCmd(">>") && !this.buf1.isEOF()) {
+                    if (!this.buf1.isName()) {
+                        error("Dictionary key must be a name object");
+                        shift();
+                    } else {
+                        var key = buf1.value;
+                        this.shift();
+                        if (this.buf1.isEOF() || this.buf1.isError())
+                            break;
+                        obj.value.set(key, this.getObj());
+                    }
+                }
+                if (this.buf1.isEOF())
+                    error("End of file inside dictionary");
+
+                // stream objects are not allowed inside content streams or
+                // object streams
+                if (this.allowStreams && this.buf2.isCmd("stream")) {
+                    return this.makeStream();
+                } else {
+                    this.shift();
+                }
+                return obj;
+
+            } else if (this.buf1.isInt()) { // indirect reference or integer
+                var num = this.buf1.value;
+                this.shift();
+                if (this.buf1.isInt() && this.buf2.isCmd("R")) {
+                    var obj = new Obj(Obj.Ref, [num, this.buf1.value]);
+                    this.shift();
+                    this.shift();
+                    return obj;
+                }
+                return new Obj(Obj.Int, num);
+            } else if (this.buf1.isString()) { // string
+                var obj = this.decrypt(this.buf1);
+                this.shift();
+                return obj;
+            }
        
-           // simple object
-           var obj = this.buf1;
-           this.shift();
-           return obj;
-       },
-       decrypt: function(obj) {
-           // TODO
-           return obj;
-       },
-       makeStream: function() {
-           // TODO
-           return new Obj(Obj.Error);
-       }
+            // simple object
+            var obj = this.buf1;
+            this.shift();
+            return obj;
+        },
+        decrypt: function(obj) {
+            // TODO
+            return obj;
+        },
+        makeStream: function() {
+            // TODO
+            return new Obj(Obj.Error);
+        }
     };
 
     Object.freeze(constructor.prototype);
@@ -486,74 +483,74 @@ var Parser = (function() {
     
 var Linearization = (function () {
     function constructor(bytes) {
-       this.parser = new Parser(new Lexer(bytes), false);
-       var obj1 = this.parser.getObj();
-       var obj2 = this.parser.getObj();
-       var obj3 = this.parser.getObj();
-       this.linDict = this.parser.getObj();
-       if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && linDict.isDict()) {
-           var obj = linDict.lookup("Linearized");
-           if (!(obj.isNum() && obj.value > 0))
-               this.linDict = Obj.nullObj;
-       }
+        this.parser = new Parser(new Lexer(bytes), false);
+        var obj1 = this.parser.getObj();
+        var obj2 = this.parser.getObj();
+        var obj3 = this.parser.getObj();
+        this.linDict = this.parser.getObj();
+        if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && linDict.isDict()) {
+            var obj = linDict.lookup("Linearized");
+            if (!(obj.isNum() && obj.value > 0))
+                this.linDict = Obj.nullObj;
+        }
     }
 
     constructor.prototype = {
-       function getInt(name) {
-           var linDict = this.linDict;
-           var obj;
-           if (!linDict.isDict() &&
-               (obj = linDict.lookup(name)).isInt() &&
-               obj.value > 0) {
-               return length;
-           }
-           error("'" + name + "' field in linearization table is invalid");
-           return 0;
-       },
-       function getHint(index) {
-           var linDict = this.linDict;
-           var obj1, obj2;
-           if (linDict.isDict() &&
-               (obj1 = linDict.lookup("H")).isArray() &&
-               obj1.value.length >= 2 &&
-               (obj2 = obj1.value[index]).isInt() &&
-               obj2.value > 0) {
-               return obj2.value;
-           }
-           this.error("Hints table in linearization table is invalid");
-           return 0;
-       },
-       get length() {
-           return this.getInt("L");
-       },
-       get hintsOffset() {
-           return this.getHint(0);
-       },
-       get hintsLength() {
-           return this.getHint(1);
-       },
-       get hintsOffset2() {
-           return this.getHint(2);
-       },
-       get hintsLenth2() {
-           return this.getHint(3);
-       },
-       get objectNumberFirst() {
-           return this.getInt("O");
-       },
-       get endFirst() {
-           return this.getInt("E");
-       },
-       get numPages() {
-           return this.getInt("N");
-       },
-       get mainXRefEntriesOffset() {
-           return this.getInt("T");
-       },
-       get pageFirst() {
-           return this.getInt("P");
-       }
-    }; 
+        function getInt(name) {
+            var linDict = this.linDict;
+            var obj;
+            if (!linDict.isDict() &&
+                (obj = linDict.lookup(name)).isInt() &&
+                obj.value > 0) {
+                return length;
+            }
+            error("'" + name + "' field in linearization table is invalid");
+            return 0;
+        },
+        function getHint(index) {
+            var linDict = this.linDict;
+            var obj1, obj2;
+            if (linDict.isDict() &&
+                (obj1 = linDict.lookup("H")).isArray() &&
+                obj1.value.length >= 2 &&
+                (obj2 = obj1.value[index]).isInt() &&
+                obj2.value > 0) {
+                return obj2.value;
+            }
+            this.error("Hints table in linearization table is invalid");
+            return 0;
+        },
+        get length() {
+            return this.getInt("L");
+        },
+        get hintsOffset() {
+            return this.getHint(0);
+        },
+        get hintsLength() {
+            return this.getHint(1);
+        },
+        get hintsOffset2() {
+            return this.getHint(2);
+        },
+        get hintsLenth2() {
+            return this.getHint(3);
+        },
+        get objectNumberFirst() {
+            return this.getInt("O");
+        },
+        get endFirst() {
+            return this.getInt("E");
+        },
+        get numPages() {
+            return this.getInt("N");
+        },
+        get mainXRefEntriesOffset() {
+            return this.getInt("T");
+        },
+        get pageFirst() {
+            return this.getInt("P");
+        }
+    };
 })();
 
 var linearization;
@@ -578,15 +575,15 @@ function checkHeader(arrayBuffer) {
     var skip = 0;
     var header = "%PDF-";
     while (skip < headerSearchSize) {
-       for (var i = 0; i < header.length; ++i)
-           if (stream[skip+i] != header.charCodeAt(i))
-               break;
-
-       // Found the header, trim off any garbage before it.
-       if (i == header.length) {
-           stream = new Uint8Array(arrayBuffer, skip);
-           return;
-       }
+        for (var i = 0; i < header.length; ++i)
+            if (stream[skip+i] != header.charCodeAt(i))
+                break;
+
+        // Found the header, trim off any garbage before it.
+        if (i == header.length) {
+            stream = new Uint8Array(arrayBuffer, skip);
+            return;
+        }
     }
 
     // May not be a PDF file, continue anyway.
@@ -595,5 +592,3 @@ function checkHeader(arrayBuffer) {
 function setup(arrayBuffer, ownerPassword, userPassword) {
     var ub = checkHeader(arrayBuffer);
 }
-
-})
\ No newline at end of file