]> git.parisson.com Git - pdf.js.git/commitdiff
Almost passing gjslint.
authorRob Sayre <sayrer@gmail.com>
Wed, 6 Jul 2011 06:06:45 +0000 (23:06 -0700)
committerRob Sayre <sayrer@gmail.com>
Wed, 6 Jul 2011 06:06:45 +0000 (23:06 -0700)
13 files changed:
crypto.js
fonts.js
glyphlist.js
pdf.js
utils/cffStandardStrings.js
utils/fonts_utils.js
web/multi_page_viewer.js
web/viewer.js
worker/canvas.js
worker/client.js
worker/console.js
worker/font.js
worker/pdf.js

index d73408ad6c6e3e780128841337c1d11c4f8801a9..c60590777651ddba4763eccb7fa08c334c3c0508 100644 (file)
--- a/crypto.js
+++ b/crypto.js
@@ -1,7 +1,7 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var ARCFourCipher = (function() {
   function constructor(key) {
@@ -30,7 +30,7 @@ var ARCFourCipher = (function() {
         a = (a + 1) & 0xFF;
         tmp = s[a];
         b = (b + tmp) & 0xFF;
-        tmp2 = s[b]
+        tmp2 = s[b];
         s[a] = tmp2;
         s[b] = tmp;
         output[i] = data[i] ^ s[(tmp + tmp2) & 0xFF];
@@ -47,22 +47,23 @@ var ARCFourCipher = (function() {
 var md5 = (function() {
   var r = new Uint8Array([
     7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
-    5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
+    5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
     4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
     6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]);
+
   var k = new Int32Array([
     -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426,
     -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162,
     1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632,
-    643717713, -373897302, -701558691, 38016083, -660478335, -405537848, 568446438,
-    -1019803690, -187363961, 1163531501, -1444681467, -51403784, 1735328473,
-    -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060,
-    1272893353, -155497632, -1094730640, 681279174, -358537222, -722521979,
-    76029189, -640364487, -421815835, 530742520, -995338651, -198630844, 1126891415,
-    -1416354905, -57434055, 1700485571, -1894986606, -1051523, -2054922799,
-    1873313359, -30611744, -1560198380, 1309151649, -145523070, -1120210379,
-    718787259, -343485551]);
-  
+    643717713, -373897302, -701558691, 38016083, -660478335, -405537848,
+    568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784,
+    1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556,
+    -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222,
+    -722521979, 76029189, -640364487, -421815835, 530742520, -995338651,
+    -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606,
+    -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649,
+    -145523070, -1120210379, 718787259, -343485551]);
+
   function hash(data, offset, length) {
     var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878;
     // pre-processing
@@ -76,10 +77,10 @@ var md5 = (function() {
     for (; i < n; ++i)
       padded[i] = 0;
     padded[i++] = (length << 3) & 0xFF;
-    padded[i++] = (length >> 5)  & 0xFF;
-    padded[i++] = (length >> 13)  & 0xFF;
-    padded[i++] = (length >> 21)  & 0xFF;
-    padded[i++] = (length >>> 29)  & 0xFF;
+    padded[i++] = (length >> 5) & 0xFF;
+    padded[i++] = (length >> 13) & 0xFF;
+    padded[i++] = (length >> 21) & 0xFF;
+    padded[i++] = (length >>> 29) & 0xFF;
     padded[i++] = 0;
     padded[i++] = 0;
     padded[i++] = 0;
@@ -87,8 +88,10 @@ var md5 = (function() {
     // TODO ArrayBuffer ?
     var w = new Int32Array(16);
     for (i = 0; i < paddedLength;) {
-      for (j = 0; j < 16; ++j, i += 4)
-        w[j] = padded[i] | (padded[i + 1] << 8) | (padded[i + 2] << 16) | (padded[i + 3] << 24);
+      for (j = 0; j < 16; ++j, i += 4) {
+        w[j] = (padded[i] | (padded[i + 1] << 8) |
+                (padded[i + 2] << 16) | (padded[i + 3] << 24));
+      }
       var a = h0, b = h1, c = h2, d = h3, f, g;
       for (j = 0; j < 64; ++j) {
         if (j < 16) {
@@ -131,7 +134,7 @@ var CipherTransform = (function() {
     this.streamCipherConstructor = streamCipherConstructor;
   }
   constructor.prototype = {
-    createStream: function (stream) {
+    createStream: function(stream) {
       var cipher = new this.streamCipherConstructor();
       return new DecryptStream(stream, function(data) {
         return cipher.encryptBlock(data);
@@ -148,10 +151,13 @@ var CipherTransform = (function() {
 })();
 
 var CipherTransformFactory = (function() {
-  function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength) {
+  function prepareKeyData(fileId, password, ownerPassword, userPassword,
+                          flags, revision, keyLength) {
     var defaultPasswordBytes = new Uint8Array([
-      0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, 
-      0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
+      0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
+      0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
+      0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
+      0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
     var hashData = new Uint8Array(88), i = 0, j, n;
     if (password) {
       n = Math.min(32, password.length);
@@ -183,9 +189,10 @@ var CipherTransformFactory = (function() {
     var cipher, checkData;
 
     if (revision >= 3) {
-      // padded password in hashData, we can use this array for user password check
+      // padded password in hashData, we can use this array for user
+      // password check
       i = 32;
-      for(j = 0, n = fileId.length; j < n; ++j)
+      for (j = 0, n = fileId.length; j < n; ++j)
         hashData[i++] = fileId[j];
       cipher = new ARCFourCipher(encryptionKey);
       var checkData = cipher.encryptBlock(md5(hashData, 0, i));
@@ -203,37 +210,38 @@ var CipherTransformFactory = (function() {
     }
     for (j = 0, n = checkData.length; j < n; ++j) {
       if (userPassword[j] != checkData[j])
-        error("incorrect password");
+        error('incorrect password');
     }
     return encryptionKey;
-  } 
+  }
 
   function constructor(dict, fileId, password) {
-    var filter = dict.get("Filter");
-    if (!IsName(filter) || filter.name != "Standard")
-      error("unknown encryption method");
+    var filter = dict.get('Filter');
+    if (!IsName(filter) || filter.name != 'Standard')
+      error('unknown encryption method');
     this.dict = dict;
-    var algorithm = dict.get("V");
+    var algorithm = dict.get('V');
     if (!IsInt(algorithm) ||
       (algorithm != 1 && algorithm != 2))
-      error("unsupported encryption algorithm");
+      error('unsupported encryption algorithm');
     // TODO support algorithm 4
-    var keyLength = dict.get("Length") || 40;
+    var keyLength = dict.get('Length') || 40;
     if (!IsInt(keyLength) ||
       keyLength < 40 || (keyLength % 8) != 0)
-      error("invalid key length");
+      error('invalid key length');
     // prepare keys
-    var ownerPassword = stringToBytes(dict.get("O"));
-    var userPassword = stringToBytes(dict.get("U"));
-    var flags = dict.get("P");
-    var revision = dict.get("R");
+    var ownerPassword = stringToBytes(dict.get('O'));
+    var userPassword = stringToBytes(dict.get('U'));
+    var flags = dict.get('P');
+    var revision = dict.get('R');
     var fileIdBytes = stringToBytes(fileId);
     var passwordBytes;
     if (password)
       passwordBytes = stringToBytes(password);
 
-    this.encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, 
-                                        ownerPassword, userPassword, flags, revision, keyLength);
+    this.encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
+                                        ownerPassword, userPassword,
+                                        flags, revision, keyLength);
   }
 
   constructor.prototype = {
index 8701f8e5fea184f0fda746c88c0a98540ce8d944..d00d114dbac97d6b24bd93217f856ccfa88804b1 100644 (file)
--- a/fonts.js
+++ b/fonts.js
@@ -1,9 +1,9 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
-var isWorker = (typeof window == "undefined");
+var isWorker = (typeof window == 'undefined');
 
 /**
  * Maximum file size of the font.
@@ -11,7 +11,7 @@ var isWorker = (typeof window == "undefined");
 var kMaxFontFileSize = 40000;
 
 /**
- * Maximum time to wait for a font to be loaded by @font-face
+ * Maximum time to wait for a font to be loaded by font-face rules.
  */
 var kMaxWaitForFontFace = 1000;
 
@@ -20,7 +20,7 @@ var kMaxWaitForFontFace = 1000;
  * many fonts are loaded.
  */
 var fontCount = 0;
-var fontName  = "";
+var fontName = '';
 
 /**
  * If for some reason one want to debug without fonts activated, it just need
@@ -41,7 +41,7 @@ var Fonts = (function Fonts() {
   var fonts = Object.create(null);
 
   if (!isWorker) {
-    var ctx = document.createElement("canvas").getContext("2d");
+    var ctx = document.createElement('canvas').getContext('2d');
     ctx.scale(1 / kScalePrecision, 1);
   }
 
@@ -94,7 +94,7 @@ var Fonts = (function Fonts() {
       if (!encoding)
         return chars;
 
-      str = "";
+      str = '';
       for (var i = 0; i < chars.length; ++i) {
         var charcode = chars.charCodeAt(i);
         var unicode = encoding[charcode];
@@ -123,7 +123,7 @@ var Fonts = (function Fonts() {
         measureCache[text] = width;
       return width;
     }
-  }
+  };
 })();
 
 var FontLoader = {
@@ -139,19 +139,19 @@ var FontLoader = {
       }
 
       document.documentElement.removeEventListener(
-        "pdfjsFontLoad", checkFontsLoaded, false);
+        'pdfjsFontLoad', checkFontsLoaded, false);
 
       callback();
       return true;
     }
 
-    var rules = [ ], names = [ ];
+    var rules = [], names = [];
     for (var i = 0; i < fonts.length; i++) {
       var font = fonts[i];
       if (!Fonts.lookup(font.name)) {
         var obj = new Font(font.name, font.file, font.properties);
 
-        var str = "";
+        var str = '';
         var data = Fonts.lookup(font.name).data;
         var length = data.length;
         for (var j = 0; j < length; j++)
@@ -171,7 +171,7 @@ var FontLoader = {
 
     if (!checkFontsLoaded()) {
       document.documentElement.addEventListener(
-        "pdfjsFontLoad", checkFontsLoaded, false);
+        'pdfjsFontLoad', checkFontsLoaded, false);
     }
 
     return;
@@ -205,29 +205,29 @@ var FontLoader = {
       // The postMessage() hackery was added to work around chrome bug
       // 82402.
 
-      var div = document.createElement("div");
-      div.setAttribute("style",
-                       'visibility: hidden;'+
-                       'width: 10px; height: 10px;'+
+      var div = document.createElement('div');
+      div.setAttribute('style',
+                       'visibility: hidden;' +
+                       'width: 10px; height: 10px;' +
                        'position: absolute; top: 0px; left: 0px;');
       var html = '';
       for (var i = 0; i < names.length; ++i) {
-        html += '<span style="font-family:'+ names[i] +'">Hi</span>';
+        html += '<span style="font-family:' + names[i] + '">Hi</span>';
       }
       div.innerHTML = html;
       document.body.appendChild(div);
 
       if (!this.listeneningForFontLoad) {
         window.addEventListener(
-          "message",
+          'message',
           function(e) {
             var fontNames = JSON.parse(e.data);
             for (var i = 0; i < fontNames.length; ++i) {
               var font = Fonts.lookup(fontNames[i]);
               font.loading = false;
             }
-            var evt = document.createEvent("Events");
-            evt.initEvent("pdfjsFontLoad", true, false);
+            var evt = document.createEvent('Events');
+            evt.initEvent('pdfjsFontLoad', true, false);
             document.documentElement.dispatchEvent(evt);
           },
           false);
@@ -241,26 +241,26 @@ var FontLoader = {
       for (var i = 0; i < rules.length; ++i) {
         src += rules[i];
       }
-      src += '</style>'
-      src += '<script type="application/javascript">'
+      src += '</style>';
+      src += '<script type="application/javascript">';
       var fontNamesArray = '';
       for (var i = 0; i < names.length; ++i) {
-        fontNamesArray += '"'+ names[i] + '", ';
+        fontNamesArray += '"' + names[i] + '", ';
       }
-      src += '  var fontNames=['+ fontNamesArray +'];\n';
-      src += '  window.onload = function () {\n'
+      src += '  var fontNames=[' + fontNamesArray + '];\n';
+      src += '  window.onload = function () {\n';
       src += '    top.postMessage(JSON.stringify(fontNames), "*");\n';
       src += '  }';
       src += '</script></head><body>';
       for (var i = 0; i < names.length; ++i) {
-        src += '<p style="font-family:\''+ fontName +'\'">Hi</p>';
+        src += '<p style="font-family:\'' + fontName + '\'">Hi</p>';
       }
       src += '</body></html>';
-      var frame = document.createElement("iframe");
-      frame.src = 'data:text/html,'+ src;
-      frame.setAttribute("style",
-                         'visibility: hidden;'+
-                         'width: 10px; height: 10px;'+
+      var frame = document.createElement('iframe');
+      frame.src = 'data:text/html,' + src;
+      frame.setAttribute('style',
+                         'visibility: hidden;' +
+                         'width: 10px; height: 10px;' +
                          'position: absolute; top: 0px; left: 0px;');
       document.body.appendChild(frame);
       /** Hack end */
@@ -268,129 +268,129 @@ var FontLoader = {
 };
 
 var UnicodeRanges = [
-  { "begin": 0x0000, "end": 0x007F }, // Basic Latin
-  { "begin": 0x0080, "end": 0x00FF }, // Latin-1 Supplement
-  { "begin": 0x0100, "end": 0x017F }, // Latin Extended-A
-  { "begin": 0x0180, "end": 0x024F }, // Latin Extended-B
-  { "begin": 0x0250, "end": 0x02AF }, // IPA Extensions
-  { "begin": 0x02B0, "end": 0x02FF }, // Spacing Modifier Letters
-  { "begin": 0x0300, "end": 0x036F }, // Combining Diacritical Marks
-  { "begin": 0x0370, "end": 0x03FF }, // Greek and Coptic
-  { "begin": 0x2C80, "end": 0x2CFF }, // Coptic
-  { "begin": 0x0400, "end": 0x04FF }, // Cyrillic
-  { "begin": 0x0530, "end": 0x058F }, // Armenian
-  { "begin": 0x0590, "end": 0x05FF }, // Hebrew
-  { "begin": 0xA500, "end": 0xA63F }, // Vai
-  { "begin": 0x0600, "end": 0x06FF }, // Arabic
-  { "begin": 0x07C0, "end": 0x07FF }, // NKo
-  { "begin": 0x0900, "end": 0x097F }, // Devanagari
-  { "begin": 0x0980, "end": 0x09FF }, // Bengali
-  { "begin": 0x0A00, "end": 0x0A7F }, // Gurmukhi
-  { "begin": 0x0A80, "end": 0x0AFF }, // Gujarati
-  { "begin": 0x0B00, "end": 0x0B7F }, // Oriya
-  { "begin": 0x0B80, "end": 0x0BFF }, // Tamil
-  { "begin": 0x0C00, "end": 0x0C7F }, // Telugu
-  { "begin": 0x0C80, "end": 0x0CFF }, // Kannada
-  { "begin": 0x0D00, "end": 0x0D7F }, // Malayalam
-  { "begin": 0x0E00, "end": 0x0E7F }, // Thai
-  { "begin": 0x0E80, "end": 0x0EFF }, // Lao
-  { "begin": 0x10A0, "end": 0x10FF }, // Georgian
-  { "begin": 0x1B00, "end": 0x1B7F }, // Balinese
-  { "begin": 0x1100, "end": 0x11FF }, // Hangul Jamo
-  { "begin": 0x1E00, "end": 0x1EFF }, // Latin Extended Additional
-  { "begin": 0x1F00, "end": 0x1FFF }, // Greek Extended
-  { "begin": 0x2000, "end": 0x206F }, // General Punctuation
-  { "begin": 0x2070, "end": 0x209F }, // Superscripts And Subscripts
-  { "begin": 0x20A0, "end": 0x20CF }, // Currency Symbol
-  { "begin": 0x20D0, "end": 0x20FF }, // Combining Diacritical Marks For Symbols
-  { "begin": 0x2100, "end": 0x214F }, // Letterlike Symbols
-  { "begin": 0x2150, "end": 0x218F }, // Number Forms
-  { "begin": 0x2190, "end": 0x21FF }, // Arrows
-  { "begin": 0x2200, "end": 0x22FF }, // Mathematical Operators
-  { "begin": 0x2300, "end": 0x23FF }, // Miscellaneous Technical
-  { "begin": 0x2400, "end": 0x243F }, // Control Pictures
-  { "begin": 0x2440, "end": 0x245F }, // Optical Character Recognition
-  { "begin": 0x2460, "end": 0x24FF }, // Enclosed Alphanumerics
-  { "begin": 0x2500, "end": 0x257F }, // Box Drawing
-  { "begin": 0x2580, "end": 0x259F }, // Block Elements
-  { "begin": 0x25A0, "end": 0x25FF }, // Geometric Shapes
-  { "begin": 0x2600, "end": 0x26FF }, // Miscellaneous Symbols
-  { "begin": 0x2700, "end": 0x27BF }, // Dingbats
-  { "begin": 0x3000, "end": 0x303F }, // CJK Symbols And Punctuation
-  { "begin": 0x3040, "end": 0x309F }, // Hiragana
-  { "begin": 0x30A0, "end": 0x30FF }, // Katakana
-  { "begin": 0x3100, "end": 0x312F }, // Bopomofo
-  { "begin": 0x3130, "end": 0x318F }, // Hangul Compatibility Jamo
-  { "begin": 0xA840, "end": 0xA87F }, // Phags-pa
-  { "begin": 0x3200, "end": 0x32FF }, // Enclosed CJK Letters And Months
-  { "begin": 0x3300, "end": 0x33FF }, // CJK Compatibility
-  { "begin": 0xAC00, "end": 0xD7AF }, // Hangul Syllables
-  { "begin": 0xD800, "end": 0xDFFF }, // Non-Plane 0 *
-  { "begin": 0x10900, "end": 0x1091F }, // Phoenicia
-  { "begin": 0x4E00, "end": 0x9FFF }, // CJK Unified Ideographs
-  { "begin": 0xE000, "end": 0xF8FF }, // Private Use Area (plane 0)
-  { "begin": 0x31C0, "end": 0x31EF }, // CJK Strokes
-  { "begin": 0xFB00, "end": 0xFB4F }, // Alphabetic Presentation Forms
-  { "begin": 0xFB50, "end": 0xFDFF }, // Arabic Presentation Forms-A
-  { "begin": 0xFE20, "end": 0xFE2F }, // Combining Half Marks
-  { "begin": 0xFE10, "end": 0xFE1F }, // Vertical Forms
-  { "begin": 0xFE50, "end": 0xFE6F }, // Small Form Variants
-  { "begin": 0xFE70, "end": 0xFEFF }, // Arabic Presentation Forms-B
-  { "begin": 0xFF00, "end": 0xFFEF }, // Halfwidth And Fullwidth Forms
-  { "begin": 0xFFF0, "end": 0xFFFF }, // Specials
-  { "begin": 0x0F00, "end": 0x0FFF }, // Tibetan
-  { "begin": 0x0700, "end": 0x074F }, // Syriac
-  { "begin": 0x0780, "end": 0x07BF }, // Thaana
-  { "begin": 0x0D80, "end": 0x0DFF }, // Sinhala
-  { "begin": 0x1000, "end": 0x109F }, // Myanmar
-  { "begin": 0x1200, "end": 0x137F }, // Ethiopic
-  { "begin": 0x13A0, "end": 0x13FF }, // Cherokee
-  { "begin": 0x1400, "end": 0x167F }, // Unified Canadian Aboriginal Syllabics
-  { "begin": 0x1680, "end": 0x169F }, // Ogham
-  { "begin": 0x16A0, "end": 0x16FF }, // Runic
-  { "begin": 0x1780, "end": 0x17FF }, // Khmer
-  { "begin": 0x1800, "end": 0x18AF }, // Mongolian
-  { "begin": 0x2800, "end": 0x28FF }, // Braille Patterns
-  { "begin": 0xA000, "end": 0xA48F }, // Yi Syllables
-  { "begin": 0x1700, "end": 0x171F }, // Tagalog
-  { "begin": 0x10300, "end": 0x1032F }, // Old Italic
-  { "begin": 0x10330, "end": 0x1034F }, // Gothic
-  { "begin": 0x10400, "end": 0x1044F }, // Deseret
-  { "begin": 0x1D000, "end": 0x1D0FF }, // Byzantine Musical Symbols
-  { "begin": 0x1D400, "end": 0x1D7FF }, // Mathematical Alphanumeric Symbols
-  { "begin": 0xFF000, "end": 0xFFFFD }, // Private Use (plane 15)
-  { "begin": 0xFE00, "end": 0xFE0F }, // Variation Selectors
-  { "begin": 0xE0000, "end": 0xE007F }, // Tags
-  { "begin": 0x1900, "end": 0x194F }, // Limbu
-  { "begin": 0x1950, "end": 0x197F }, // Tai Le
-  { "begin": 0x1980, "end": 0x19DF }, // New Tai Lue
-  { "begin": 0x1A00, "end": 0x1A1F }, // Buginese
-  { "begin": 0x2C00, "end": 0x2C5F }, // Glagolitic
-  { "begin": 0x2D30, "end": 0x2D7F }, // Tifinagh
-  { "begin": 0x4DC0, "end": 0x4DFF }, // Yijing Hexagram Symbols
-  { "begin": 0xA800, "end": 0xA82F }, // Syloti Nagri
-  { "begin": 0x10000, "end": 0x1007F }, // Linear B Syllabary
-  { "begin": 0x10140, "end": 0x1018F }, // Ancient Greek Numbers
-  { "begin": 0x10380, "end": 0x1039F }, // Ugaritic
-  { "begin": 0x103A0, "end": 0x103DF }, // Old Persian
-  { "begin": 0x10450, "end": 0x1047F }, // Shavian
-  { "begin": 0x10480, "end": 0x104AF }, // Osmanya
-  { "begin": 0x10800, "end": 0x1083F }, // Cypriot Syllabary
-  { "begin": 0x10A00, "end": 0x10A5F }, // Kharoshthi
-  { "begin": 0x1D300, "end": 0x1D35F }, // Tai Xuan Jing Symbols
-  { "begin": 0x12000, "end": 0x123FF }, // Cuneiform
-  { "begin": 0x1D360, "end": 0x1D37F }, // Counting Rod Numerals
-  { "begin": 0x1B80, "end": 0x1BBF }, // Sundanese
-  { "begin": 0x1C00, "end": 0x1C4F }, // Lepcha
-  { "begin": 0x1C50, "end": 0x1C7F }, // Ol Chiki
-  { "begin": 0xA880, "end": 0xA8DF }, // Saurashtra
-  { "begin": 0xA900, "end": 0xA92F }, // Kayah Li
-  { "begin": 0xA930, "end": 0xA95F }, // Rejang
-  { "begin": 0xAA00, "end": 0xAA5F }, // Cham
-  { "begin": 0x10190, "end": 0x101CF }, // Ancient Symbols
-  { "begin": 0x101D0, "end": 0x101FF }, // Phaistos Disc
-  { "begin": 0x102A0, "end": 0x102DF }, // Carian
-  { "begin": 0x1F030, "end": 0x1F09F }  // Domino Tiles
+  { 'begin': 0x0000, 'end': 0x007F }, // Basic Latin
+  { 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement
+  { 'begin': 0x0100, 'end': 0x017F }, // Latin Extended-A
+  { 'begin': 0x0180, 'end': 0x024F }, // Latin Extended-B
+  { 'begin': 0x0250, 'end': 0x02AF }, // IPA Extensions
+  { 'begin': 0x02B0, 'end': 0x02FF }, // Spacing Modifier Letters
+  { 'begin': 0x0300, 'end': 0x036F }, // Combining Diacritical Marks
+  { 'begin': 0x0370, 'end': 0x03FF }, // Greek and Coptic
+  { 'begin': 0x2C80, 'end': 0x2CFF }, // Coptic
+  { 'begin': 0x0400, 'end': 0x04FF }, // Cyrillic
+  { 'begin': 0x0530, 'end': 0x058F }, // Armenian
+  { 'begin': 0x0590, 'end': 0x05FF }, // Hebrew
+  { 'begin': 0xA500, 'end': 0xA63F }, // Vai
+  { 'begin': 0x0600, 'end': 0x06FF }, // Arabic
+  { 'begin': 0x07C0, 'end': 0x07FF }, // NKo
+  { 'begin': 0x0900, 'end': 0x097F }, // Devanagari
+  { 'begin': 0x0980, 'end': 0x09FF }, // Bengali
+  { 'begin': 0x0A00, 'end': 0x0A7F }, // Gurmukhi
+  { 'begin': 0x0A80, 'end': 0x0AFF }, // Gujarati
+  { 'begin': 0x0B00, 'end': 0x0B7F }, // Oriya
+  { 'begin': 0x0B80, 'end': 0x0BFF }, // Tamil
+  { 'begin': 0x0C00, 'end': 0x0C7F }, // Telugu
+  { 'begin': 0x0C80, 'end': 0x0CFF }, // Kannada
+  { 'begin': 0x0D00, 'end': 0x0D7F }, // Malayalam
+  { 'begin': 0x0E00, 'end': 0x0E7F }, // Thai
+  { 'begin': 0x0E80, 'end': 0x0EFF }, // Lao
+  { 'begin': 0x10A0, 'end': 0x10FF }, // Georgian
+  { 'begin': 0x1B00, 'end': 0x1B7F }, // Balinese
+  { 'begin': 0x1100, 'end': 0x11FF }, // Hangul Jamo
+  { 'begin': 0x1E00, 'end': 0x1EFF }, // Latin Extended Additional
+  { 'begin': 0x1F00, 'end': 0x1FFF }, // Greek Extended
+  { 'begin': 0x2000, 'end': 0x206F }, // General Punctuation
+  { 'begin': 0x2070, 'end': 0x209F }, // Superscripts And Subscripts
+  { 'begin': 0x20A0, 'end': 0x20CF }, // Currency Symbol
+  { 'begin': 0x20D0, 'end': 0x20FF }, // Combining Diacritical Marks For Symbols
+  { 'begin': 0x2100, 'end': 0x214F }, // Letterlike Symbols
+  { 'begin': 0x2150, 'end': 0x218F }, // Number Forms
+  { 'begin': 0x2190, 'end': 0x21FF }, // Arrows
+  { 'begin': 0x2200, 'end': 0x22FF }, // Mathematical Operators
+  { 'begin': 0x2300, 'end': 0x23FF }, // Miscellaneous Technical
+  { 'begin': 0x2400, 'end': 0x243F }, // Control Pictures
+  { 'begin': 0x2440, 'end': 0x245F }, // Optical Character Recognition
+  { 'begin': 0x2460, 'end': 0x24FF }, // Enclosed Alphanumerics
+  { 'begin': 0x2500, 'end': 0x257F }, // Box Drawing
+  { 'begin': 0x2580, 'end': 0x259F }, // Block Elements
+  { 'begin': 0x25A0, 'end': 0x25FF }, // Geometric Shapes
+  { 'begin': 0x2600, 'end': 0x26FF }, // Miscellaneous Symbols
+  { 'begin': 0x2700, 'end': 0x27BF }, // Dingbats
+  { 'begin': 0x3000, 'end': 0x303F }, // CJK Symbols And Punctuation
+  { 'begin': 0x3040, 'end': 0x309F }, // Hiragana
+  { 'begin': 0x30A0, 'end': 0x30FF }, // Katakana
+  { 'begin': 0x3100, 'end': 0x312F }, // Bopomofo
+  { 'begin': 0x3130, 'end': 0x318F }, // Hangul Compatibility Jamo
+  { 'begin': 0xA840, 'end': 0xA87F }, // Phags-pa
+  { 'begin': 0x3200, 'end': 0x32FF }, // Enclosed CJK Letters And Months
+  { 'begin': 0x3300, 'end': 0x33FF }, // CJK Compatibility
+  { 'begin': 0xAC00, 'end': 0xD7AF }, // Hangul Syllables
+  { 'begin': 0xD800, 'end': 0xDFFF }, // Non-Plane 0 *
+  { 'begin': 0x10900, 'end': 0x1091F }, // Phoenicia
+  { 'begin': 0x4E00, 'end': 0x9FFF }, // CJK Unified Ideographs
+  { 'begin': 0xE000, 'end': 0xF8FF }, // Private Use Area (plane 0)
+  { 'begin': 0x31C0, 'end': 0x31EF }, // CJK Strokes
+  { 'begin': 0xFB00, 'end': 0xFB4F }, // Alphabetic Presentation Forms
+  { 'begin': 0xFB50, 'end': 0xFDFF }, // Arabic Presentation Forms-A
+  { 'begin': 0xFE20, 'end': 0xFE2F }, // Combining Half Marks
+  { 'begin': 0xFE10, 'end': 0xFE1F }, // Vertical Forms
+  { 'begin': 0xFE50, 'end': 0xFE6F }, // Small Form Variants
+  { 'begin': 0xFE70, 'end': 0xFEFF }, // Arabic Presentation Forms-B
+  { 'begin': 0xFF00, 'end': 0xFFEF }, // Halfwidth And Fullwidth Forms
+  { 'begin': 0xFFF0, 'end': 0xFFFF }, // Specials
+  { 'begin': 0x0F00, 'end': 0x0FFF }, // Tibetan
+  { 'begin': 0x0700, 'end': 0x074F }, // Syriac
+  { 'begin': 0x0780, 'end': 0x07BF }, // Thaana
+  { 'begin': 0x0D80, 'end': 0x0DFF }, // Sinhala
+  { 'begin': 0x1000, 'end': 0x109F }, // Myanmar
+  { 'begin': 0x1200, 'end': 0x137F }, // Ethiopic
+  { 'begin': 0x13A0, 'end': 0x13FF }, // Cherokee
+  { 'begin': 0x1400, 'end': 0x167F }, // Unified Canadian Aboriginal Syllabics
+  { 'begin': 0x1680, 'end': 0x169F }, // Ogham
+  { 'begin': 0x16A0, 'end': 0x16FF }, // Runic
+  { 'begin': 0x1780, 'end': 0x17FF }, // Khmer
+  { 'begin': 0x1800, 'end': 0x18AF }, // Mongolian
+  { 'begin': 0x2800, 'end': 0x28FF }, // Braille Patterns
+  { 'begin': 0xA000, 'end': 0xA48F }, // Yi Syllables
+  { 'begin': 0x1700, 'end': 0x171F }, // Tagalog
+  { 'begin': 0x10300, 'end': 0x1032F }, // Old Italic
+  { 'begin': 0x10330, 'end': 0x1034F }, // Gothic
+  { 'begin': 0x10400, 'end': 0x1044F }, // Deseret
+  { 'begin': 0x1D000, 'end': 0x1D0FF }, // Byzantine Musical Symbols
+  { 'begin': 0x1D400, 'end': 0x1D7FF }, // Mathematical Alphanumeric Symbols
+  { 'begin': 0xFF000, 'end': 0xFFFFD }, // Private Use (plane 15)
+  { 'begin': 0xFE00, 'end': 0xFE0F }, // Variation Selectors
+  { 'begin': 0xE0000, 'end': 0xE007F }, // Tags
+  { 'begin': 0x1900, 'end': 0x194F }, // Limbu
+  { 'begin': 0x1950, 'end': 0x197F }, // Tai Le
+  { 'begin': 0x1980, 'end': 0x19DF }, // New Tai Lue
+  { 'begin': 0x1A00, 'end': 0x1A1F }, // Buginese
+  { 'begin': 0x2C00, 'end': 0x2C5F }, // Glagolitic
+  { 'begin': 0x2D30, 'end': 0x2D7F }, // Tifinagh
+  { 'begin': 0x4DC0, 'end': 0x4DFF }, // Yijing Hexagram Symbols
+  { 'begin': 0xA800, 'end': 0xA82F }, // Syloti Nagri
+  { 'begin': 0x10000, 'end': 0x1007F }, // Linear B Syllabary
+  { 'begin': 0x10140, 'end': 0x1018F }, // Ancient Greek Numbers
+  { 'begin': 0x10380, 'end': 0x1039F }, // Ugaritic
+  { 'begin': 0x103A0, 'end': 0x103DF }, // Old Persian
+  { 'begin': 0x10450, 'end': 0x1047F }, // Shavian
+  { 'begin': 0x10480, 'end': 0x104AF }, // Osmanya
+  { 'begin': 0x10800, 'end': 0x1083F }, // Cypriot Syllabary
+  { 'begin': 0x10A00, 'end': 0x10A5F }, // Kharoshthi
+  { 'begin': 0x1D300, 'end': 0x1D35F }, // Tai Xuan Jing Symbols
+  { 'begin': 0x12000, 'end': 0x123FF }, // Cuneiform
+  { 'begin': 0x1D360, 'end': 0x1D37F }, // Counting Rod Numerals
+  { 'begin': 0x1B80, 'end': 0x1BBF }, // Sundanese
+  { 'begin': 0x1C00, 'end': 0x1C4F }, // Lepcha
+  { 'begin': 0x1C50, 'end': 0x1C7F }, // Ol Chiki
+  { 'begin': 0xA880, 'end': 0xA8DF }, // Saurashtra
+  { 'begin': 0xA900, 'end': 0xA92F }, // Kayah Li
+  { 'begin': 0xA930, 'end': 0xA95F }, // Rejang
+  { 'begin': 0xAA00, 'end': 0xAA5F }, // Cham
+  { 'begin': 0x10190, 'end': 0x101CF }, // Ancient Symbols
+  { 'begin': 0x101D0, 'end': 0x101FF }, // Phaistos Disc
+  { 'begin': 0x102A0, 'end': 0x102DF }, // Carian
+  { 'begin': 0x1F030, 'end': 0x1F09F }  // Domino Tiles
 ];
 
 function getUnicodeRangeFor(value) {
@@ -400,7 +400,7 @@ function getUnicodeRangeFor(value) {
       return i;
   }
   return -1;
-};
+}
 
 /**
  * 'Font' is the class the outside world should use, it encapsulate all the font
@@ -410,7 +410,7 @@ function getUnicodeRangeFor(value) {
  *   var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
  *   type1Font.bind();
  */
-var Font = (function () {
+var Font = (function() {
   var constructor = function font_constructor(name, file, properties) {
     this.name = name;
     this.encoding = properties.encoding;
@@ -432,16 +432,16 @@ var Font = (function () {
 
     var data;
     switch (properties.type) {
-      case "Type1":
+      case 'Type1':
         var cff = new CFF(name, file, properties);
-        this.mimetype = "font/opentype";
+        this.mimetype = 'font/opentype';
 
         // Wrap the CFF data inside an OTF font file
         data = this.convert(name, cff, properties);
         break;
 
-      case "TrueType":
-        this.mimetype = "font/opentype";
+      case 'TrueType':
+        this.mimetype = 'font/opentype';
 
         // Repair the TrueType file if it is can be damaged in the point of
         // view of the sanitizer
@@ -449,7 +449,7 @@ var Font = (function () {
         break;
 
       default:
-        warn("Font " + properties.type + " is not supported");
+        warn('Font ' + properties.type + ' is not supported');
         break;
     }
     this.data = data;
@@ -538,10 +538,11 @@ var Font = (function () {
 
     // checksum
     var checksum = 0;
-    for (var i = 0; i < length; i+=4)
-      checksum += int16([data[i], data[i+1], data[i+2], data[i+3]]);
+    for (var i = 0; i < length; i += 4)
+      checksum += int16([data[i], data[i + 1], data[i + 2], data[i + 3]]);
 
-    var tableEntry = tag + string32(checksum) + string32(offset) + string32(length);
+    var tableEntry = (tag + string32(checksum) +
+                      string32(offset) + string32(length));
     tableEntry = stringToArray(tableEntry);
     file.set(tableEntry, offsets.currentOffset);
 
@@ -555,7 +556,7 @@ var Font = (function () {
     var codes = [];
     var length = glyphs.length;
     for (var n = 0; n < length; ++n)
-      codes.push(String.fromCharCode(glyphs[n].unicode))
+      codes.push(String.fromCharCode(glyphs[n].unicode));
     codes.sort();
 
     // Split the sorted codes into ranges.
@@ -577,10 +578,10 @@ var Font = (function () {
     var ranges = getRanges(glyphs);
 
     var numTables = 1;
-    var cmap = "\x00\x00" + // version
+    var cmap = '\x00\x00' + // version
                string16(numTables) +  // numTables
-               "\x00\x03" + // platformID
-               "\x00\x01" + // encodingID
+               '\x00\x03' + // platformID
+               '\x00\x01' + // encodingID
                string32(4 + numTables * 8); // start of the table record
 
     var headerSize = (12 * 2 + (ranges.length * 5 * 2));
@@ -590,20 +591,20 @@ var Font = (function () {
     var searchEntry = Math.log(segCount) / Math.log(2);
     var rangeShift = 2 * segCount - searchRange;
 
-    var format314 = "\x00\x04" + // format
+    var format314 = '\x00\x04' + // format
                     string16(headerSize) + // length
-                    "\x00\x00" + // language
+                    '\x00\x00' + // language
                     string16(segCount2) +
                     string16(searchRange) +
                     string16(searchEntry) +
                     string16(rangeShift);
 
     // Fill up the 4 parallel arrays describing the segments.
-    var startCount = "";
-    var endCount = "";
-    var idDeltas = "";
-    var idRangeOffsets = "";
-    var glyphsIds = "";
+    var startCount = '';
+    var endCount = '';
+    var idDeltas = '';
+    var idRangeOffsets = '';
+    var glyphsIds = '';
     var bias = 0;
     for (var i = 0; i < segCount - 1; i++) {
       var range = ranges[i];
@@ -615,18 +616,18 @@ var Font = (function () {
       startCount += string16(start);
       endCount += string16(end);
       idDeltas += string16(delta);
-           idRangeOffsets += string16(0);
+      idRangeOffsets += string16(0);
 
       for (var j = start; j <= end; j++) {
         glyphsIds += string16(j);
       }
     }
 
-    endCount += "\xFF\xFF";
-    startCount += "\xFF\xFF";
-    idDeltas += "\x00\x01";
-    idRangeOffsets += "\x00\x00";
-    format314 += endCount + "\x00\x00" + startCount +
+    endCount += '\xFF\xFF';
+    startCount += '\xFF\xFF';
+    idDeltas += '\x00\x01';
+    idRangeOffsets += '\x00\x00';
+    format314 += endCount + '\x00\x00' + startCount +
                  idDeltas + idRangeOffsets + glyphsIds;
 
     return stringToArray(cmap + format314);
@@ -638,19 +639,19 @@ var Font = (function () {
     var ulUnicodeRange3 = 0;
     var ulUnicodeRange4 = 0;
 
-       var charset = properties.charset;
+    var charset = properties.charset;
     if (charset && charset.length) {
-           var firstCharIndex = null;
-           var lastCharIndex = 0;
+      var firstCharIndex = null;
+      var lastCharIndex = 0;
 
       for (var i = 1; i < charset.length; i++) {
-             var code = GlyphsUnicode[charset[i]];
-                   if (firstCharIndex > code || !firstCharIndex)
-                     firstCharIndex = code;
-                   if (lastCharIndex < code)
-                     lastCharIndex = code;
+        var code = GlyphsUnicode[charset[i]];
+        if (firstCharIndex > code || !firstCharIndex)
+          firstCharIndex = code;
+        if (lastCharIndex < code)
+          lastCharIndex = code;
 
-             var position = getUnicodeRangeFor(code);
+        var position = getUnicodeRangeFor(code);
         if (position < 32) {
           ulUnicodeRange1 |= 1 << position;
         } else if (position < 64) {
@@ -660,62 +661,64 @@ var Font = (function () {
         } else if (position < 123) {
           ulUnicodeRange4 |= 1 << position - 96;
         } else {
-          error("Unicode ranges Bits > 123 are reserved for internal usage");
+          error('Unicode ranges Bits > 123 are reserved for internal usage');
         }
       }
     }
 
-    return "\x00\x03" + // version
-           "\x02\x24" + // xAvgCharWidth
-           "\x01\xF4" + // usWeightClass
-           "\x00\x05" + // usWidthClass
-           "\x00\x00" + // fstype (0 to let the font loads via font-face on IE)
-           "\x02\x8A" + // ySubscriptXSize
-           "\x02\xBB" + // ySubscriptYSize
-           "\x00\x00" + // ySubscriptXOffset
-           "\x00\x8C" + // ySubscriptYOffset
-           "\x02\x8A" + // ySuperScriptXSize
-           "\x02\xBB" + // ySuperScriptYSize
-           "\x00\x00" + // ySuperScriptXOffset
-           "\x01\xDF" + // ySuperScriptYOffset
-           "\x00\x31" + // yStrikeOutSize
-           "\x01\x02" + // yStrikeOutPosition
-           "\x00\x00" + // sFamilyClass
-           "\x00\x00\x06" + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) +
-           "\x00\x00\x00\x00\x00\x00" + // Panose
+    return '\x00\x03' + // version
+           '\x02\x24' + // xAvgCharWidth
+           '\x01\xF4' + // usWeightClass
+           '\x00\x05' + // usWidthClass
+           '\x00\x00' + // fstype (0 to let the font loads via font-face on IE)
+           '\x02\x8A' + // ySubscriptXSize
+           '\x02\xBB' + // ySubscriptYSize
+           '\x00\x00' + // ySubscriptXOffset
+           '\x00\x8C' + // ySubscriptYOffset
+           '\x02\x8A' + // ySuperScriptXSize
+           '\x02\xBB' + // ySuperScriptYSize
+           '\x00\x00' + // ySuperScriptXOffset
+           '\x01\xDF' + // ySuperScriptYOffset
+           '\x00\x31' + // yStrikeOutSize
+           '\x01\x02' + // yStrikeOutPosition
+           '\x00\x00' + // sFamilyClass
+           '\x00\x00\x06' +
+           String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) +
+           '\x00\x00\x00\x00\x00\x00' + // Panose
            string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31)
            string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63)
            string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95)
            string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127)
-           "\x2A\x32\x31\x2A" + // achVendID
+           '\x2A\x32\x31\x2A' + // achVendID
            string16(properties.italicAngle ? 1 : 0) + // fsSelection
-           string16(firstCharIndex || properties.firstChar) + // usFirstCharIndex
+           string16(firstCharIndex ||
+                    properties.firstChar) + // usFirstCharIndex
            string16(lastCharIndex || properties.lastChar) +  // usLastCharIndex
            string16(properties.ascent) + // sTypoAscender
            string16(properties.descent) + // sTypoDescender
-           "\x00\x64" + // sTypoLineGap (7%-10% of the unitsPerEM value)
-           string16(properties.ascent)  + // usWinAscent
+           '\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value)
+           string16(properties.ascent) + // usWinAscent
            string16(-properties.descent) + // usWinDescent
-           "\x00\x00\x00\x00" + // ulCodePageRange1 (Bits 0-31)
-           "\x00\x00\x00\x00" + // ulCodePageRange2 (Bits 32-63)
-           string16(properties.xHeight)   + // sxHeight
+           '\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31)
+           '\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63)
+           string16(properties.xHeight) + // sxHeight
            string16(properties.capHeight) + // sCapHeight
            string16(0) + // usDefaultChar
            string16(firstCharIndex || properties.firstChar) + // usBreakChar
-           "\x00\x03";  // usMaxContext
+           '\x00\x03';  // usMaxContext
   };
 
   function createPostTable(properties) {
     var angle = Math.floor(properties.italicAngle * (Math.pow(2, 16)));
-    return "\x00\x03\x00\x00" + // Version number
-           string32(angle)    + // italicAngle
-           "\x00\x00"         + // underlinePosition
-           "\x00\x00"         + // underlineThickness
+    return '\x00\x03\x00\x00' + // Version number
+           string32(angle) + // italicAngle
+           '\x00\x00' + // underlinePosition
+           '\x00\x00' + // underlineThickness
            string32(properties.fixedPitch) + // isFixedPitch
-           "\x00\x00\x00\x00" + // minMemType42
-           "\x00\x00\x00\x00" + // maxMemType42
-           "\x00\x00\x00\x00" + // minMemType1
-           "\x00\x00\x00\x00";  // maxMemType1
+           '\x00\x00\x00\x00' + // minMemType42
+           '\x00\x00\x00\x00' + // maxMemType42
+           '\x00\x00\x00\x00' + // minMemType1
+           '\x00\x00\x00\x00';  // maxMemType1
   };
 
   constructor.prototype = {
@@ -750,7 +753,7 @@ var Font = (function () {
           length: offset,
           offset: length,
           data: data
-        }
+        };
       };
 
       function readOpenTypeHeader(ttf) {
@@ -760,7 +763,7 @@ var Font = (function () {
           searchRange: int16(ttf.getBytes(2)),
           entrySelector: int16(ttf.getBytes(2)),
           rangeShift: int16(ttf.getBytes(2))
-        }
+        };
       };
 
       function replaceCMapTable(cmap, font, properties) {
@@ -781,7 +784,8 @@ var Font = (function () {
               (format == 6 && numTables == 1 && !properties.encoding.empty)) {
             // Format 0 alone is not allowed by the sanitizer so let's rewrite
             // that to a 3-1-4 Unicode BMP table
-            TODO("Use an other source of informations than charset here, it is not reliable");
+            TODO('Use an other source of informations than ' +
+                 'charset here, it is not reliable');
             var charset = properties.charset;
             var glyphs = [];
             for (var j = 0; j < charset.length; j++) {
@@ -821,8 +825,9 @@ var Font = (function () {
             for (var j = 0; j < glyphs.length; j++)
               glyphs[j] = { unicode: glyphs[j] + firstCode };
 
-            var ranges= getRanges(glyphs);
-            assert(ranges.length == 1, "Got " + ranges.length + " ranges in a dense array");
+            var ranges = getRanges(glyphs);
+            assert(ranges.length == 1, 'Got ' + ranges.length +
+                   ' ranges in a dense array');
 
             var encoding = properties.encoding;
             var denseRange = ranges[0];
@@ -837,8 +842,8 @@ var Font = (function () {
       };
 
       // Check that required tables are present
-      var requiredTables = [ "OS/2", "cmap", "head", "hhea",
-                             "hmtx", "maxp", "name", "post" ];
+      var requiredTables = ['OS/2', 'cmap', 'head', 'hhea',
+                             'hmtx', 'maxp', 'name', 'post'];
 
       var header = readOpenTypeHeader(font);
       var numTables = header.numTables;
@@ -852,9 +857,9 @@ var Font = (function () {
         var table = readTableEntry(font);
         var index = requiredTables.indexOf(table.tag);
         if (index != -1) {
-          if (table.tag == "cmap")
+          if (table.tag == 'cmap')
             cmap = table;
-          else if (table.tag == "post")
+          else if (table.tag == 'post')
             post = table;
 
           requiredTables.splice(index, 1);
@@ -862,10 +867,10 @@ var Font = (function () {
         tables.push(table);
       }
 
-      // If any tables are still in the array this means some required tables are
-      // missing, which means that we need to rebuild the font in order to pass
-      // the sanitizer.
-      if (requiredTables.length && requiredTables[0] == "OS/2") {
+      // If any tables are still in the array this means some required
+      // tables are missing, which means that we need to rebuild the
+      // font in order to pass the sanitizer.
+      if (requiredTables.length && requiredTables[0] == 'OS/2') {
         // Create a new file to hold the new version of our truetype with a new
         // header and new offsets
         var ttf = new Uint8Array(kMaxFontFileSize);
@@ -880,13 +885,13 @@ var Font = (function () {
           virtualOffset: numTables * (4 * 4)
         };
 
-        // The new numbers of tables will be the last one plus the num of missing
-        // tables
-        createOpenTypeHeader("\x00\x01\x00\x00", ttf, offsets, numTables);
+        // The new numbers of tables will be the last one plus the num
+        // of missing tables
+        createOpenTypeHeader('\x00\x01\x00\x00', ttf, offsets, numTables);
 
         // Insert the missing table
         tables.push({
-          tag: "OS/2",
+          tag: 'OS/2',
           data: stringToArray(createOS2Table(properties))
         });
 
@@ -896,7 +901,7 @@ var Font = (function () {
         // Rewrite the 'post' table if needed
         if (!post) {
           tables.push({
-            tag: "post",
+            tag: 'post',
             data: stringToArray(createPostTable(properties))
           });
         }
@@ -935,7 +940,8 @@ var Font = (function () {
 
         return fontData;
       } else if (requiredTables.length) {
-        error("Table " + requiredTables[0] + " is missing from the TrueType font");
+        error('Table ' + requiredTables[0] +
+              ' is missing from the TrueType font');
       }
 
       return font.getBytes();
@@ -943,21 +949,22 @@ var Font = (function () {
 
     convert: function font_convert(fontName, font, properties) {
       function createNameTable(name) {
-           // All the strings of the name table should be an odd number of bytes
+        // All the strings of the name table should be an odd number
+        // of bytes
         if (name.length % 2)
           name = name.slice(0, name.length - 1);
 
         var strings = [
-          "Original licence",  // 0.Copyright
+          'Original licence',  // 0.Copyright
           name,                // 1.Font family
-          "Unknown",           // 2.Font subfamily (font weight)
-          "uniqueID",          // 3.Unique ID
+          'Unknown',           // 2.Font subfamily (font weight)
+          'uniqueID',          // 3.Unique ID
           name,                // 4.Full font name
-          "Version 0.11",      // 5.Version
-          "Unknown",           // 6.Postscript name
-          "Unknown",           // 7.Trademark
-          "Unknown",           // 8.Manufacturer
-          "Unknown"            // 9.Designer
+          'Version 0.11',      // 5.Version
+          'Unknown',           // 6.Postscript name
+          'Unknown',           // 7.Trademark
+          'Unknown',           // 8.Manufacturer
+          'Unknown'            // 9.Designer
         ];
 
         // Mac want 1-byte per character strings while Windows want
@@ -966,20 +973,20 @@ var Font = (function () {
         for (var i = 0; i < strings.length; i++) {
           var str = strings[i];
 
-          var strUnicode = "";
+          var strUnicode = '';
           for (var j = 0; j < str.length; j++)
             strUnicode += string16(str.charCodeAt(j));
           stringsUnicode.push(strUnicode);
         }
 
         var names = [strings, stringsUnicode];
-        var platforms = ["\x00\x01", "\x00\x03"];
-        var encodings = ["\x00\x00", "\x00\x01"];
-        var languages = ["\x00\x00", "\x04\x09"];
+        var platforms = ['\x00\x01', '\x00\x03'];
+        var encodings = ['\x00\x00', '\x00\x01'];
+        var languages = ['\x00\x00', '\x04\x09'];
 
         var namesRecordCount = strings.length * platforms.length;
         var nameTable =
-          "\x00\x00" +                           // format
+          '\x00\x00' +                           // format
           string16(namesRecordCount) +           // Number of names Record
           string16(namesRecordCount * 12 + 6);   // Storage
 
@@ -1001,16 +1008,16 @@ var Font = (function () {
           }
         }
 
-                   nameTable += strings.join("") + stringsUnicode.join("");
+        nameTable += strings.join('') + stringsUnicode.join('');
         return nameTable;
       }
 
-           function isFixedPitch(glyphs) {
-             for (var i = 0; i < glyphs.length - 1; i++) {
-                   if (glyphs[i] != glyphs[i+1])
-                     return false;
-                   }
-                   return true;
+      function isFixedPitch(glyphs) {
+        for (var i = 0; i < glyphs.length - 1; i++) {
+          if (glyphs[i] != glyphs[i + 1])
+            return false;
+        }
+        return true;
       };
 
       // The offsets object holds at the same time a representation of where
@@ -1024,67 +1031,68 @@ var Font = (function () {
       };
 
       var otf = new Uint8Array(kMaxFontFileSize);
-      createOpenTypeHeader("\x4F\x54\x54\x4F", otf, offsets, 9);
+      createOpenTypeHeader('\x4F\x54\x54\x4F', otf, offsets, 9);
 
-           var charstrings = font.charstrings;
-           properties.fixedPitch = isFixedPitch(charstrings);
+      var charstrings = font.charstrings;
+      properties.fixedPitch = isFixedPitch(charstrings);
       var fields = {
         // PostScript Font Program
-        "CFF ": font.data,
+        'CFF ': font.data,
 
         // OS/2 and Windows Specific metrics
-        "OS/2": stringToArray(createOS2Table(properties)),
+        'OS/2': stringToArray(createOS2Table(properties)),
 
         // Character to glyphs mapping
-        "cmap": createCMapTable(charstrings.slice()),
+        'cmap': createCMapTable(charstrings.slice()),
 
         // Font header
-        "head": (function() {
+        'head': (function() {
           return stringToArray(
-              "\x00\x01\x00\x00" + // Version number
-              "\x00\x00\x10\x00" + // fontRevision
-              "\x00\x00\x00\x00" + // checksumAdjustement
-              "\x5F\x0F\x3C\xF5" + // magicNumber
-              "\x00\x00" + // Flags
-              "\x03\xE8" + // unitsPerEM (defaulting to 1000)
-              "\x00\x00\x00\x00\x9e\x0b\x7e\x27" + // creation date
-              "\x00\x00\x00\x00\x9e\x0b\x7e\x27" + // modifification date
-              "\x00\x00" + // xMin
+              '\x00\x01\x00\x00' + // Version number
+              '\x00\x00\x10\x00' + // fontRevision
+              '\x00\x00\x00\x00' + // checksumAdjustement
+              '\x5F\x0F\x3C\xF5' + // magicNumber
+              '\x00\x00' + // Flags
+              '\x03\xE8' + // unitsPerEM (defaulting to 1000)
+              '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date
+              '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date
+              '\x00\x00' + // xMin
               string16(properties.descent) + // yMin
-              "\x0F\xFF" + // xMax
+              '\x0F\xFF' + // xMax
               string16(properties.ascent) + // yMax
               string16(properties.italicAngle ? 2 : 0) + // macStyle
-              "\x00\x11" + // lowestRecPPEM
-              "\x00\x00" + // fontDirectionHint
-              "\x00\x00" + // indexToLocFormat
-              "\x00\x00");  // glyphDataFormat
+              '\x00\x11' + // lowestRecPPEM
+              '\x00\x00' + // fontDirectionHint
+              '\x00\x00' + // indexToLocFormat
+              '\x00\x00');  // glyphDataFormat
         })(),
 
         // Horizontal header
-        "hhea": (function() {
+        'hhea': (function() {
           return stringToArray(
-              "\x00\x01\x00\x00" + // Version number
+              '\x00\x01\x00\x00' + // Version number
               string16(properties.ascent) + // Typographic Ascent
               string16(properties.descent) + // Typographic Descent
-              "\x00\x00" + // Line Gap
-              "\xFF\xFF" + // advanceWidthMax
-              "\x00\x00" + // minLeftSidebearing
-              "\x00\x00" + // minRightSidebearing
-              "\x00\x00" + // xMaxExtent
+              '\x00\x00' + // Line Gap
+              '\xFF\xFF' + // advanceWidthMax
+              '\x00\x00' + // minLeftSidebearing
+              '\x00\x00' + // minRightSidebearing
+              '\x00\x00' + // xMaxExtent
               string16(properties.capHeight) + // caretSlopeRise
-              string16(Math.tan(properties.italicAngle) * properties.xHeight) + // caretSlopeRun
-              "\x00\x00" + // caretOffset
-              "\x00\x00" + // -reserved-
-              "\x00\x00" + // -reserved-
-              "\x00\x00" + // -reserved-
-              "\x00\x00" + // -reserved-
-              "\x00\x00" + // metricDataFormat
+              string16(Math.tan(properties.italicAngle) *
+                       properties.xHeight) + // caretSlopeRun
+              '\x00\x00' + // caretOffset
+              '\x00\x00' + // -reserved-
+              '\x00\x00' + // -reserved-
+              '\x00\x00' + // -reserved-
+              '\x00\x00' + // -reserved-
+              '\x00\x00' + // metricDataFormat
               string16(charstrings.length + 1)); // Number of HMetrics
         })(),
 
         // Horizontal metrics
-        "hmtx": (function() {
-          var hmtx = "\x00\x00\x00\x00"; // Fake .notdef
+        'hmtx': (function() {
+          var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
           for (var i = 0; i < charstrings.length; i++) {
             hmtx += string16(charstrings[i].width) + string16(0);
           }
@@ -1092,17 +1100,17 @@ var Font = (function () {
         })(),
 
         // Maximum profile
-        "maxp": (function() {
+        'maxp': (function() {
           return stringToArray(
-              "\x00\x00\x50\x00" + // Version number
+              '\x00\x00\x50\x00' + // Version number
              string16(charstrings.length + 1)); // Num of glyphs
         })(),
 
         // Naming tables
-        "name": stringToArray(createNameTable(fontName)),
+        'name': stringToArray(createNameTable(fontName)),
 
         // PostScript informations
-        "post": stringToArray(createPostTable(properties))
+        'post': stringToArray(createPostTable(properties))
       };
 
       for (var field in fields)
@@ -1122,9 +1130,9 @@ var Font = (function () {
 
     bindWorker: function font_bindWorker(data) {
       postMessage({
-        action: "font",
+        action: 'font',
         data: {
-          raw:      data,
+          raw: data,
           fontName: this.name,
           mimetype: this.mimetype
         }
@@ -1134,9 +1142,10 @@ var Font = (function () {
     bindDOM: function font_bindDom(data) {
       var fontName = this.name;
 
-      // Add the @font-face rule to the document
-      var url = "url(data:" + this.mimetype + ";base64," + window.btoa(data) + ");";
-      var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}";
+      // Add the font-face rule to the document
+      var url = ('url(data:' + this.mimetype + ';base64,' +
+                 window.btoa(data) + ');');
+      var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}';
       var styleSheet = document.styleSheets[0];
       styleSheet.insertRule(rule, styleSheet.cssRules.length);
 
@@ -1149,8 +1158,8 @@ var Font = (function () {
 
 /**
  * Type1Parser encapsulate the needed code for parsing a Type1 font
- * program.
- * Some of its logic depends on the Type2 charstrings structure.
+ * program. Some of its logic depends on the Type2 charstrings
+ * structure.
  */
 var Type1Parser = function() {
   /*
@@ -1165,7 +1174,7 @@ var Type1Parser = function() {
     var r = key, c1 = 52845, c2 = 22719;
     var decryptedString = [];
 
-    var value = "";
+    var value = '';
     var count = stream.length;
     for (var i = 0; i < count; i++) {
       value = stream[i];
@@ -1214,65 +1223,65 @@ var Type1Parser = function() {
    * the charStrings.
    */
   var charStringDictionary = {
-    "1": "hstem",
-    "3": "vstem",
-    "4": "vmoveto",
-    "5": "rlineto",
-    "6": "hlineto",
-    "7": "vlineto",
-    "8": "rrcurveto",
+    '1': 'hstem',
+    '3': 'vstem',
+    '4': 'vmoveto',
+    '5': 'rlineto',
+    '6': 'hlineto',
+    '7': 'vlineto',
+    '8': 'rrcurveto',
 
     // closepath is a Type1 command that do not take argument and is useless
     // in Type2 and it can simply be ignored.
-    "9": null, // closepath
+    '9': null, // closepath
 
-    "10": "callsubr",
+    '10': 'callsubr',
 
     // return is normally used inside sub-routines to tells to the execution
     // flow that it can be back to normal.
     // During the translation process Type1 charstrings will be flattened and
     // sub-routines will be embedded directly into the charstring directly, so
     // this can be ignored safely.
-    "11": "return",
+    '11': 'return',
 
-    "12": {
+    '12': {
       // dotsection is a Type1 command to specify some hinting feature for dots
       // that do not take a parameter and it can safely be ignored for Type2.
-      "0": null, // dotsection
+      '0': null, // dotsection
 
       // [vh]stem3 are Type1 only and Type2 supports [vh]stem with multiple
       // parameters, so instead of returning [vh]stem3 take a shortcut and
       // return [vhstem] instead.
-      "1": "vstem",
-      "2": "hstem",
+      '1': 'vstem',
+      '2': 'hstem',
 
       // Type1 only command with command not (yet) built-in ,throw an error
-      "6": -1, // seac
-      "7": -1, //sbw
+      '6': -1, // seac
+      '7': -1, //sbw
 
-      "11": "sub",
-      "12": "div",
+      '11': 'sub',
+      '12': 'div',
 
       // callothersubr is a mechanism to make calls on the postscript
       // interpreter, this is not supported by Type2 charstring but hopefully
       // most of the default commands can be ignored safely.
-      "16": "callothersubr",
+      '16': 'callothersubr',
 
-      "17": "pop",
+      '17': 'pop',
 
       // setcurrentpoint sets the current point to x, y without performing a
       // moveto (this is a one shot positionning command). This is used only
       // with the return of an OtherSubrs call.
       // TODO Implement the OtherSubrs charstring embedding and replace this
       //      call by a no-op, like 2 'pop' commands for example.
-      "33": null, //setcurrentpoint
+      '33': null //setcurrentpoint
     },
-    "13": "hsbw",
-    "14": "endchar",
-    "21": "rmoveto",
-    "22": "hmoveto",
-    "30": "vhcurveto",
-    "31": "hvcurveto"
+    '13': 'hsbw',
+    '14': 'endchar',
+    '21': 'rmoveto',
+    '22': 'hmoveto',
+    '30': 'vhcurveto',
+    '31': 'hvcurveto'
   };
 
   var kEscapeCommand = 12;
@@ -1283,7 +1292,7 @@ var Type1Parser = function() {
     var width = 0;
     var used = false;
 
-    var value = "";
+    var value = '';
     var count = array.length;
     for (var i = 0; i < count; i++) {
       value = parseInt(array[i]);
@@ -1315,20 +1324,20 @@ var Type1Parser = function() {
             }
           }
 
-          command = charStringDictionary["12"][escape];
+          command = charStringDictionary['12'][escape];
         } else {
           // TODO Clean this code
           if (value == 13) {
             if (charstring.length == 2) {
               width = charstring[1];
-            } else if (charstring.length == 4 && charstring[3] == "div") {
+            } else if (charstring.length == 4 && charstring[3] == 'div') {
               width = charstring[1] / charstring[2];
             } else {
-              error("Unsupported hsbw format: " + charstring);
+              error('Unsupported hsbw format: ' + charstring);
             }
 
             lsb = charstring[0];
-            charstring.push(lsb, "hmoveto");
+            charstring.push(lsb, 'hmoveto');
             charstring.splice(0, 1);
             continue;
           }
@@ -1342,7 +1351,9 @@ var Type1Parser = function() {
         } else if (!command) {
           break;
         } else if (command == -1) {
-          error("Support for Type1 command " + value + " (" + escape + ") is not implemented in charstring: " + charString);
+          error('Support for Type1 command ' + value +
+                ' (' + escape + ') is not implemented in charstring: ' +
+                charString);
         }
 
         value = command;
@@ -1364,16 +1375,16 @@ var Type1Parser = function() {
   };
 
   /**
-   * Returns an object containing a Subrs array and a CharStrings array
-   * extracted from and eexec encrypted block of data
+   * Returns an object containing a Subrs array and a CharStrings
+   * array extracted from and eexec encrypted block of data
    */
   function readNumberArray(str, index) {
     var start = ++index;
     var count = 0;
-    while (str[index++] != "]")
+    while (str[index++] != ']')
       count++;
 
-    var array = str.substr(start, count).split(" ");
+    var array = str.substr(start, count).split(' ');
     for (var i = 0; i < array.length; i++)
       array[i] = parseFloat(array[i] || 0);
     return array;
@@ -1381,12 +1392,12 @@ var Type1Parser = function() {
 
   this.extractFontProgram = function t1_extractFontProgram(stream) {
     var eexec = decrypt(stream, kEexecEncryptionKey, 4);
-    var eexecString = "";
+    var eexecStr = '';
     for (var i = 0; i < eexec.length; i++)
-      eexecString += String.fromCharCode(eexec[i]);
+      eexecStr += String.fromCharCode(eexec[i]);
 
     var glyphsSection = false, subrsSection = false;
-    var extracted = {
+    var program = {
       subrs: [],
       charstrings: [],
       properties: {
@@ -1395,70 +1406,70 @@ var Type1Parser = function() {
       }
     };
 
-    var glyph = "";
-    var token = "";
+    var glyph = '';
+    var token = '';
     var length = 0;
 
-    var c = "";
-    var count = eexecString.length;
+    var c = '';
+    var count = eexecStr.length;
     for (var i = 0; i < count; i++) {
-      var c = eexecString[i];
+      var c = eexecStr[i];
 
-      if ((glyphsSection || subrsSection) && c == "R") {
+      if ((glyphsSection || subrsSection) && c == 'R') {
         var data = eexec.slice(i + 3, i + 3 + length);
         var encoded = decrypt(data, kCharStringsEncryptionKey, 4);
         var str = decodeCharString(encoded);
 
         if (glyphsSection) {
-          extracted.charstrings.push({
+          program.charstrings.push({
             glyph: glyph,
             data: str.charstring,
             lsb: str.lsb,
             width: str.width
           });
         } else {
-          extracted.subrs.push(str.charstring);
+          program.subrs.push(str.charstring);
         }
         i += length + 3;
-      } else if (c == " " || c == "\n") {
+      } else if (c == ' ' || c == '\n') {
         length = parseInt(token);
-        token = "";
+        token = '';
       } else {
         token += c;
         if (!glyphsSection) {
           switch (token) {
-            case "/CharString":
+            case '/CharString':
               glyphsSection = true;
               break;
-            case "/Subrs":
+            case '/Subrs':
               subrsSection = true;
               break;
-            case "/StdHW":
-              extracted.properties.stdHW = readNumberArray(eexecString, i + 2)[0];
+            case '/StdHW':
+              program.properties.stdHW = readNumberArray(eexecStr, i + 2)[0];
               break;
-            case "/StdVW":
-              extracted.properties.stdVW = readNumberArray(eexecString, i + 2)[0];
+            case '/StdVW':
+              program.properties.stdVW = readNumberArray(eexecStr, i + 2)[0];
               break;
-            case "/StemSnapH":
-              extracted.properties.stemSnapH = readNumberArray(eexecString, i + 2);
+            case '/StemSnapH':
+              program.properties.stemSnapH = readNumberArray(eexecStr, i + 2);
               break;
-            case "/StemSnapV":
-              extracted.properties.stemSnapV = readNumberArray(eexecString, i + 2);
+            case '/StemSnapV':
+              program.properties.stemSnapV = readNumberArray(eexecStr, i + 2);
               break;
           }
-        } else if (c == "/") {
-          token = glyph = "";
-          while ((c = eexecString[++i]) != " ")
+        } else if (c == '/') {
+          token = glyph = '';
+          while ((c = eexecStr[++i]) != ' ')
             glyph += c;
         }
       }
     }
 
-    return extracted;
+    return program;
   },
 
   this.extractFontHeader = function t1_extractFontProgram(stream) {
-    var headerString = "";
+    var headerString = '';
     for (var i = 0; i < stream.length; i++)
       headerString += String.fromCharCode(stream[i]);
 
@@ -1466,13 +1477,13 @@ var Type1Parser = function() {
       textMatrix: null
     };
 
-    var token = "";
+    var token = '';
     var count = headerString.length;
     for (var i = 0; i < count; i++) {
       var c = headerString[i];
-      if (c == " " || c == "\n") {
+      if (c == ' ' || c == '\n') {
         switch (token) {
-          case "/FontMatrix":
+          case '/FontMatrix':
             var matrix = readNumberArray(headerString, i + 1);
 
             // The FontMatrix is in unitPerEm, so make it pixels
@@ -1485,7 +1496,7 @@ var Type1Parser = function() {
             info.textMatrix = matrix;
             break;
         }
-        token = "";
+        token = '';
       } else {
         token += c;
       }
@@ -1500,69 +1511,79 @@ var Type1Parser = function() {
  * which itself embed Type2 charstrings.
  */
 var CFFStrings = [
-  ".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand",
-  "quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period",
-  "slash","zero","one","two","three","four","five","six","seven","eight","nine",
-  "colon","semicolon","less","equal","greater","question","at","A","B","C","D","E",
-  "F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y",
-  "Z","bracketleft","backslash","bracketright","asciicircum","underscore",
-  "quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q",
-  "r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde",
-  "exclamdown","cent","sterling","fraction","yen","florin","section","currency",
-  "quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright",
-  "fi","fl","endash","dagger","daggerdbl","periodcentered","paragraph","bullet",
-  "quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis",
-  "perthousand","questiondown","grave","acute","circumflex","tilde","macron",
-  "breve","dotaccent","dieresis","ring","cedilla","hungarumlaut","ogonek","caron",
-  "emdash","AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae","dotlessi",
-  "lslash","oslash","oe","germandbls","onesuperior","logicalnot","mu","trademark",
-  "Eth","onehalf","plusminus","Thorn","onequarter","divide","brokenbar","degree",
-  "thorn","threequarters","twosuperior","registered","minus","eth","multiply",
-  "threesuperior","copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring",
-  "Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave","Iacute",
-  "Icircumflex","Idieresis","Igrave","Ntilde","Oacute","Ocircumflex","Odieresis",
-  "Ograve","Otilde","Scaron","Uacute","Ucircumflex","Udieresis","Ugrave","Yacute",
-  "Ydieresis","Zcaron","aacute","acircumflex","adieresis","agrave","aring","atilde",
-  "ccedilla","eacute","ecircumflex","edieresis","egrave","iacute","icircumflex",
-  "idieresis","igrave","ntilde","oacute","ocircumflex","odieresis","ograve",
-  "otilde","scaron","uacute","ucircumflex","udieresis","ugrave","yacute",
-  "ydieresis","zcaron","exclamsmall","Hungarumlautsmall","dollaroldstyle",
-  "dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior",
-  "parenrightsuperior","266 ff","onedotenleader","zerooldstyle","oneoldstyle",
-  "twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle",
-  "sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior",
-  "threequartersemdash","periodsuperior","questionsmall","asuperior","bsuperior",
-  "centsuperior","dsuperior","esuperior","isuperior","lsuperior","msuperior",
-  "nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","ffi","ffl",
-  "parenleftinferior","parenrightinferior","Circumflexsmall","hyphensuperior",
-  "Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall",
-  "Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall",
-  "Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall",
-  "Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","exclamdownsmall",
-  "centoldstyle","Lslashsmall","Scaronsmall","Zcaronsmall","Dieresissmall",
-  "Brevesmall","Caronsmall","Dotaccentsmall","Macronsmall","figuredash",
-  "hypheninferior","Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall",
-  "oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds",
-  "zerosuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior",
-  "eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior",
-  "threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior",
-  "eightinferior","nineinferior","centinferior","dollarinferior","periodinferior",
-  "commainferior","Agravesmall","Aacutesmall","Acircumflexsmall","Atildesmall",
-  "Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall",
-  "Eacutesmall","Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall",
-  "Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall",
-  "Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall",
-  "Oslashsmall","Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall",
-  "Yacutesmall","Thornsmall","Ydieresissmall","001.000","001.001","001.002",
-  "001.003","Black","Bold","Book","Light","Medium","Regular","Roman","Semibold"
+  '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+  'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
+  'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
+  'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
+  'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+  'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+  'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum',
+  'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+  'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+  'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
+  'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
+  'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
+  'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
+  'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase',
+  'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown',
+  'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent',
+  'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash',
+  'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae',
+  'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior',
+  'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn',
+  'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters',
+  'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior',
+  'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring',
+  'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave',
+  'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute',
+  'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute',
+  'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron',
+  'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde',
+  'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute',
+  'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex',
+  'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex',
+  'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall',
+  'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall',
+  'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff',
+  'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle',
+  'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
+  'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior',
+  'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior',
+  'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior',
+  'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
+  'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior',
+  'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall',
+  'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
+  'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
+  'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
+  'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
+  'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
+  'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall',
+  'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior',
+  'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth',
+  'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds',
+  'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
+  'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior',
+  'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior',
+  'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',
+  'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior',
+  'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall',
+  'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',
+  'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall',
+  'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall',
+  'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall',
+  'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',
+  'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall',
+  'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003',
+  'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'
 ];
 
 var type1Parser = new Type1Parser();
 
 var CFF = function(name, file, properties) {
   // Get the data block containing glyphs and subrs informations
-  var length1 = file.dict.get("Length1");
-  var length2 = file.dict.get("Length2");
+  var length1 = file.dict.get('Length1');
+  var length2 = file.dict.get('Length2');
 
   var headerBlock = file.getBytes(length1);
   var header = type1Parser.extractFontHeader(headerBlock);
@@ -1580,7 +1601,8 @@ var CFF = function(name, file, properties) {
   var subrs = this.getType2Subrs(data.subrs);
 
   this.charstrings = charstrings;
-  this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties);
+  this.data = this.wrap(name, type2Charstrings, this.charstrings,
+                        subrs, properties);
 };
 
 CFF.prototype = {
@@ -1591,14 +1613,14 @@ CFF.prototype = {
     // If there is no object, just create an array saying that with another
     // offset byte.
     if (count == 0)
-      return "\x00\x00\x00";
+      return '\x00\x00\x00';
 
     var data = String.fromCharCode(count >> 8, count & 0xff);
 
     // Next byte contains the offset size use to reference object in the file
     // Actually we're using 0x04 to be sure to be able to store everything
     // without thinking of it while coding.
-    data += "\x04";
+    data += '\x04';
 
     // Add another offset after this one because we need a new offset
     var relativeOffset = 1;
@@ -1610,7 +1632,7 @@ CFF.prototype = {
         relativeOffset += objects[i].length;
     }
 
-    for (var i =0; i < count; i++) {
+    for (var i = 0; i < count; i++) {
       for (var j = 0; j < objects[i].length; j++)
         data += isByte ? String.fromCharCode(objects[i][j]) : objects[i][j];
     }
@@ -1619,17 +1641,17 @@ CFF.prototype = {
 
   encodeNumber: function cff_encodeNumber(value) {
     if (value >= -32768 && value <= 32767) {
-      return "\x1c" +
+      return '\x1c' +
              String.fromCharCode(value >> 8) +
              String.fromCharCode(value & 0xFF);
-    } else if (value >= (-2147483647-1) && value <= 2147483647) {
-      return "\xff" +
+    } else if (value >= (-2147483647 - 1) && value <= 2147483647) {
+      return '\xff' +
              String.fromCharCode(value >> 24) +
              String.fromCharCode(value >> 16) +
              String.fromCharCode(value >> 8) +
              String.fromCharCode(value & 0xFF);
     }
-    error("Value: " + value + " is not allowed");
+    error('Value: ' + value + ' is not allowed');
     return null;
   },
 
@@ -1640,8 +1662,10 @@ CFF.prototype = {
       var glyph = glyphs[i];
       var unicode = GlyphsUnicode[glyph.glyph];
       if (!unicode) {
-        if (glyph.glyph != ".notdef")
-          warn(glyph + " does not have an entry in the glyphs unicode dictionary");
+        if (glyph.glyph != '.notdef') {
+          warn(glyph +
+               ' does not have an entry in the glyphs unicode dictionary');
+        }
       } else {
         charstrings.push({
           glyph: glyph,
@@ -1651,7 +1675,7 @@ CFF.prototype = {
           lsb: glyph.lsb
         });
       }
-    };
+    }
 
     charstrings.sort(function charstrings_sort(a, b) {
       return a.unicode - b.unicode;
@@ -1661,10 +1685,11 @@ CFF.prototype = {
 
   getType2Charstrings: function cff_getType2Charstrings(type1Charstrings) {
     var type2Charstrings = [];
-         var count = type1Charstrings.length;
+    var count = type1Charstrings.length;
     for (var i = 0; i < count; i++) {
       var charstring = type1Charstrings[i].charstring;
-      type2Charstrings.push(this.flattenCharstring(charstring.slice(), this.commandsMap));
+      type2Charstrings.push(this.flattenCharstring(charstring.slice(),
+                                                   this.commandsMap));
     }
     return type2Charstrings;
   },
@@ -1695,23 +1720,23 @@ CFF.prototype = {
    * every 'callsubr', 'callothersubr' by the real commands.
    */
   commandsMap: {
-    "hstem": 1,
-    "vstem": 3,
-    "vmoveto": 4,
-    "rlineto": 5,
-    "hlineto": 6,
-    "vlineto": 7,
-    "rrcurveto": 8,
-    "callsubr": 10,
-    "return": 11,
-    "sub": [12, 11],
-    "div": [12, 12],
-    "pop": [1, 12, 18],
-    "endchar": 14,
-    "rmoveto": 21,
-    "hmoveto": 22,
-    "vhcurveto": 30,
-    "hvcurveto": 31,
+    'hstem': 1,
+    'vstem': 3,
+    'vmoveto': 4,
+    'rlineto': 5,
+    'hlineto': 6,
+    'vlineto': 7,
+    'rrcurveto': 8,
+    'callsubr': 10,
+    'return': 11,
+    'sub': [12, 11],
+    'div': [12, 12],
+    'pop': [1, 12, 18],
+    'endchar': 14,
+    'rmoveto': 21,
+    'hmoveto': 22,
+    'vhcurveto': 30,
+    'hvcurveto': 31
   },
 
   flattenCharstring: function flattenCharstring(charstring, map) {
@@ -1719,7 +1744,7 @@ CFF.prototype = {
       var command = charstring[i];
       if (command.charAt) {
         var cmd = map[command];
-        assert(cmd, "Unknow command: " + command);
+        assert(cmd, 'Unknow command: ' + command);
 
         if (IsArray(cmd)) {
           charstring.splice(i++, 1, cmd[0], cmd[1]);
@@ -1728,7 +1753,7 @@ CFF.prototype = {
         }
       } else {
         charstring.splice(i, 1, 28, command >> 8, command & 0xff);
-        i+= 2;
+        i += 2;
       }
     }
     return charstring;
@@ -1736,66 +1761,68 @@ CFF.prototype = {
 
   wrap: function wrap(name, glyphs, charstrings, subrs, properties) {
     var fields = {
-      "header": "\x01\x00\x04\x04", // major version, minor version, header size, offset size
+      // major version, minor version, header size, offset size
+      'header': '\x01\x00\x04\x04',
 
-      "names": this.createCFFIndexHeader([name]),
+      'names': this.createCFFIndexHeader([name]),
 
-      "topDict": (function topDict(self) {
+      'topDict': (function topDict(self) {
         return function() {
           var dict =
-              "\x00\x01\x01\x01\x30" +
-              "\xf8\x1b\x00" + // version
-              "\xf8\x1b\x01" + // Notice
-              "\xf8\x1b\x02" + // FullName
-              "\xf8\x1b\x03" + // FamilyName
-              "\xf8\x1b\x04" +  // Weight
-              "\x1c\x00\x00\x10"; // Encoding
+              '\x00\x01\x01\x01\x30' +
+              '\xf8\x1b\x00' + // version
+              '\xf8\x1b\x01' + // Notice
+              '\xf8\x1b\x02' + // FullName
+              '\xf8\x1b\x03' + // FamilyName
+              '\xf8\x1b\x04' +  // Weight
+              '\x1c\x00\x00\x10'; // Encoding
 
           var boundingBox = properties.bbox;
           for (var i = 0; i < boundingBox.length; i++)
             dict += self.encodeNumber(boundingBox[i]);
-          dict += "\x05"; // FontBBox;
+          dict += '\x05'; // FontBBox;
 
           var offset = fields.header.length +
                        fields.names.length +
                        (dict.length + (4 + 4 + 7)) +
                        fields.strings.length +
                        fields.globalSubrs.length;
-          dict += self.encodeNumber(offset) + "\x0f"; // Charset
+          dict += self.encodeNumber(offset) + '\x0f'; // Charset
 
           offset = offset + (glyphs.length * 2) + 1;
-          dict += self.encodeNumber(offset) + "\x11"; // Charstrings
+          dict += self.encodeNumber(offset) + '\x11'; // Charstrings
 
           dict += self.encodeNumber(fields.private.length);
           var offset = offset + fields.charstrings.length;
-          dict += self.encodeNumber(offset) + "\x12"; // Private
+          dict += self.encodeNumber(offset) + '\x12'; // Private
 
           return dict;
         };
       })(this),
 
-      "strings": (function strings(self) {
+      'strings': (function strings(self) {
         var strings = [
-          "Version 0.11",         // Version
-          "See original notice",  // Notice
+          'Version 0.11',         // Version
+          'See original notice',  // Notice
           name,                   // FullName
           name,                   // FamilyName
-          "Medium"                // Weight
+          'Medium'                // Weight
         ];
         return self.createCFFIndexHeader(strings);
       })(this),
 
-      "globalSubrs": this.createCFFIndexHeader([]),
+      'globalSubrs': this.createCFFIndexHeader([]),
 
-      "charset": (function charset(self) {
-        var charset = "\x00"; // Encoding
+      'charset': (function charset(self) {
+        var charset = '\x00'; // Encoding
 
-             var count = glyphs.length;
+        var count = glyphs.length;
         for (var i = 0; i < count; i++) {
           var index = CFFStrings.indexOf(charstrings[i].glyph.glyph);
-          // Some characters like asterikmath && circlecopyrt are missing from the
-          // original strings, for the moment let's map them to .notdef and see
-          // later if it cause any problems
+          // Some characters like asterikmath && circlecopyrt are
+          // missing from the original strings, for the moment let's
+          // map them to .notdef and see later if it cause any
+          // problems
           if (index == -1)
             index = 0;
 
@@ -1804,31 +1831,32 @@ CFF.prototype = {
         return charset;
       })(this),
 
-      "charstrings": this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs), true),
+      'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs),
+                                               true),
 
-      "private": (function(self) {
+      'private': (function(self) {
         var data =
-            "\x8b\x14" + // defaultWidth
-            "\x8b\x15" + // nominalWidth
-            self.encodeNumber(properties.stdHW || 0) + "\x0a" + // StdHW
-            self.encodeNumber(properties.stdVW || 0) + "\x0b";  // StdVW
+            '\x8b\x14' + // defaultWidth
+            '\x8b\x15' + // nominalWidth
+            self.encodeNumber(properties.stdHW || 0) + '\x0a' + // StdHW
+            self.encodeNumber(properties.stdVW || 0) + '\x0b';  // StdVW
 
         var stemH = properties.stemSnapH;
         for (var i = 0; i < stemH.length; i++)
           data += self.encodeNumber(stemH[i]);
-        data += "\x0c\x0c"; // StemSnapH
+        data += '\x0c\x0c'; // StemSnapH
 
         var stemV = properties.stemSnapV;
         for (var i = 0; i < stemV.length; i++)
           data += self.encodeNumber(stemV[i]);
-        data += "\x0c\x0d"; // StemSnapV
+        data += '\x0c\x0d'; // StemSnapV
 
-        data += self.encodeNumber(data.length + 4) + "\x13"; // Subrs offset
+        data += self.encodeNumber(data.length + 4) + '\x13'; // Subrs offset
 
         return data;
       })(this),
 
-      "localSubrs": this.createCFFIndexHeader(subrs, true)
+      'localSubrs': this.createCFFIndexHeader(subrs, true)
     };
     fields.topDict = fields.topDict();
 
index 85ab876f9a0bd3093ae8a1f0a26385dc352cab07..3551e61734e0afdaa938b67f4105f9408a352267 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var GlyphsUnicode = {
   A: 0x0041,
@@ -2474,8 +2474,8 @@ var GlyphsUnicode = {
   lameddageshhebrew: 0xFB3C,
   lamedhebrew: 0x05DC,
   lamedholam: 0x05DC05B9,
-  lamedholamdagesh: "05DC 05B9 05BC",
-  lamedholamdageshhebrew: "05DC 05B9 05BC",
+  lamedholamdagesh: '05DC 05B9 05BC',
+  lamedholamdageshhebrew: '05DC 05B9 05BC',
   lamedholamhebrew: 0x05DC05B9,
   lamfinalarabic: 0xFEDE,
   lamhahinitialarabic: 0xFCCA,
@@ -2486,8 +2486,8 @@ var GlyphsUnicode = {
   lammedialarabic: 0xFEE0,
   lammeemhahinitialarabic: 0xFD88,
   lammeeminitialarabic: 0xFCCC,
-  lammeemjeeminitialarabic: "FEDF FEE4 FEA0",
-  lammeemkhahinitialarabic: "FEDF FEE4 FEA8",
+  lammeemjeeminitialarabic: 'FEDF FEE4 FEA0',
+  lammeemkhahinitialarabic: 'FEDF FEE4 FEA8',
   largecircle: 0x25EF,
   lbar: 0x019A,
   lbelt: 0x026C,
@@ -3250,7 +3250,7 @@ var GlyphsUnicode = {
   reharmenian: 0x0580,
   rehfinalarabic: 0xFEAE,
   rehiragana: 0x308C,
-  rehyehaleflamarabic: "0631 FEF3 FE8E 0644",
+  rehyehaleflamarabic: '0631 FEF3 FE8E 0644',
   rekatakana: 0x30EC,
   rekatakanahalfwidth: 0xFF9A,
   resh: 0x05E8,
diff --git a/pdf.js b/pdf.js
index a9f0ee935bb137c42ca2f6a8c62cb99c3e766dd2..7d8e432a2adc927f0715f829fde7b737032cef53 100644 (file)
--- a/pdf.js
+++ b/pdf.js
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
-/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var ERRORS = 0, WARNINGS = 1, TODOS = 5;
 var verbosity = WARNINGS;
 
 function log(msg) {
-    if (console && console.log)
-        console.log(msg);
-    else if (print)
-        print(msg);
+  if (console && console.log)
+    console.log(msg);
+  else if (print)
+    print(msg);
 }
 
 function warn(msg) {
-    if (verbosity >= WARNINGS)
-        log("Warning: "+ msg);
+  if (verbosity >= WARNINGS)
+    log('Warning: ' + msg);
 }
 
 function error(msg) {
-    throw new Error(msg);
+  throw new Error(msg);
 }
 
 function TODO(what) {
-    if (verbosity >= TODOS)
-        log("TODO: "+ what);
+  if (verbosity >= TODOS)
+    log('TODO: ' + what);
 }
 
 function malformed(msg) {
-    error("Malformed PDF: "+ msg);
+  error('Malformed PDF: ' + msg);
 }
 
 function assert(cond, msg) {
-    if (!cond)
-        error(msg);
+  if (!cond)
+    error(msg);
 }
 
 // In a well-formed PDF, |cond| holds.  If it doesn't, subsequent
 // behavior is undefined.
 function assertWellFormed(cond, msg) {
-    if (!cond)
-        malformed(msg);
+  if (!cond)
+    malformed(msg);
 }
 
 function shadow(obj, prop, value) {
-    Object.defineProperty(obj, prop, { value: value, enumerable: true });
+  Object.defineProperty(obj, prop, { value: value, enumerable: true });
     return value;
 }
 
 function bytesToString(bytes) {
-    var str = "";
-    var length = bytes.length;
-    for (var n = 0; n < length; ++n)
-        str += String.fromCharCode(bytes[n]);
-    return str;
+  var str = '';
+  var length = bytes.length;
+  for (var n = 0; n < length; ++n)
+    str += String.fromCharCode(bytes[n]);
+  return str;
 }
 
 function stringToBytes(str) {
-    var length = str.length;
-    var bytes = new Uint8Array(length);
-    for (var n = 0; n < length; ++n)
-        bytes[n] = str.charCodeAt(n) & 0xFF;
-    return bytes;
+  var length = str.length;
+  var bytes = new Uint8Array(length);
+  for (var n = 0; n < length; ++n)
+    bytes[n] = str.charCodeAt(n) & 0xFF;
+  return bytes;
 }
 
 var Stream = (function() {
-    function constructor(arrayBuffer, start, length, dict) {
-        this.bytes = new Uint8Array(arrayBuffer);
-        this.start = start || 0;
-        this.pos = this.start;
-        this.end = (start + length) || this.bytes.length;
-        this.dict = dict;
-    }
+  function constructor(arrayBuffer, start, length, dict) {
+    this.bytes = new Uint8Array(arrayBuffer);
+    this.start = start || 0;
+    this.pos = this.start;
+    this.end = (start + length) || this.bytes.length;
+    this.dict = dict;
+  }
 
-    // required methods for a stream. if a particular stream does not
-    // implement these, an error should be thrown
-    constructor.prototype = {
-        get length() {
-            return this.end - this.start;
-        },
-        getByte: function stream_getByte() {
-            if (this.pos >= this.end)
-                return null;
-            return this.bytes[this.pos++];
-        },
-        // returns subarray of original buffer
-        // should only be read
-        getBytes: function stream_getBytes(length) {
-            var bytes = this.bytes;
-            var pos = this.pos;
-            var strEnd = this.end;
-
-            if (!length)
-                return bytes.subarray(pos, strEnd);
-
-            var end = pos + length;
-            if (end > strEnd)
-                end = strEnd;
-
-            this.pos = end;
-            return bytes.subarray(pos, end);
-        },
-        lookChar: function stream_lookChar() {
-            if (this.pos >= this.end)
-                return null;
-            return String.fromCharCode(this.bytes[this.pos]);
-        },
-        getChar: function stream_getChar() {
-            if (this.pos >= this.end)
-                return null;
-            return String.fromCharCode(this.bytes[this.pos++]);
-        },
-        skip: function stream_skip(n) {
-            if (!n)
-                n = 1;
-            this.pos += n;
-        },
-        reset: function stream_reset() {
-            this.pos = this.start;
-        },
-        moveStart: function stream_moveStart() {
-            this.start = this.pos;
-        },
-        makeSubStream: function stream_makeSubstream(start, length, dict) {
-            return new Stream(this.bytes.buffer, start, length, dict);
-        }
-    };
+  // required methods for a stream. if a particular stream does not
+  // implement these, an error should be thrown
+  constructor.prototype = {
+    get length() {
+      return this.end - this.start;
+    },
+    getByte: function stream_getByte() {
+      if (this.pos >= this.end)
+        return null;
+      return this.bytes[this.pos++];
+    },
+    // returns subarray of original buffer
+    // should only be read
+    getBytes: function stream_getBytes(length) {
+      var bytes = this.bytes;
+      var pos = this.pos;
+      var strEnd = this.end;
+
+      if (!length)
+        return bytes.subarray(pos, strEnd);
+
+      var end = pos + length;
+      if (end > strEnd)
+        end = strEnd;
+
+      this.pos = end;
+      return bytes.subarray(pos, end);
+    },
+    lookChar: function stream_lookChar() {
+      if (this.pos >= this.end)
+        return null;
+      return String.fromCharCode(this.bytes[this.pos]);
+    },
+    getChar: function stream_getChar() {
+      if (this.pos >= this.end)
+        return null;
+      return String.fromCharCode(this.bytes[this.pos++]);
+    },
+    skip: function stream_skip(n) {
+      if (!n)
+        n = 1;
+      this.pos += n;
+    },
+    reset: function stream_reset() {
+      this.pos = this.start;
+    },
+    moveStart: function stream_moveStart() {
+      this.start = this.pos;
+    },
+    makeSubStream: function stream_makeSubstream(start, length, dict) {
+      return new Stream(this.bytes.buffer, start, length, dict);
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var StringStream = (function() {
-    function constructor(str) {
-        var length = str.length;
-        var bytes = new Uint8Array(length);
-        for (var n = 0; n < length; ++n)
-            bytes[n] = str.charCodeAt(n);
-        Stream.call(this, bytes);
-    }
+  function constructor(str) {
+    var length = str.length;
+    var bytes = new Uint8Array(length);
+    for (var n = 0; n < length; ++n)
+      bytes[n] = str.charCodeAt(n);
+    Stream.call(this, bytes);
+  }
 
-    constructor.prototype = Stream.prototype;
+  constructor.prototype = Stream.prototype;
 
-    return constructor;
+  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 decodestream_ensureBuffer(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 = new Uint8Array(size);
-            for (var i = 0; i < current; ++i)
-                buffer2[i] = buffer[i];
-            return this.buffer = buffer2;
-        },
-        getByte: function decodestream_getByte() {
-            var pos = this.pos;
-            while (this.bufferLength <= pos) {
-                if (this.eof)
-                    return null;
-                this.readBlock();
-            }
-            return this.buffer[this.pos++];
-        },
-        getBytes: function decodestream_getBytes(length) {
-            var pos = this.pos;
-
-            if (length) {
-                this.ensureBuffer(pos + length);
-                var end = pos + length;
-
-                while (!this.eof && this.bufferLength < end)
-                    this.readBlock();
-
-                var bufEnd = this.bufferLength;
-                if (end > bufEnd)
-                    end = bufEnd;
-            } else {
-                while (!this.eof)
-                    this.readBlock();
+  function constructor() {
+    this.pos = 0;
+    this.bufferLength = 0;
+    this.eof = false;
+    this.buffer = null;
+  }
 
-                var end = this.bufferLength;
-            }
+  constructor.prototype = {
+    ensureBuffer: function decodestream_ensureBuffer(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 = new Uint8Array(size);
+      for (var i = 0; i < current; ++i)
+        buffer2[i] = buffer[i];
+      return this.buffer = buffer2;
+    },
+    getByte: function decodestream_getByte() {
+      var pos = this.pos;
+      while (this.bufferLength <= pos) {
+        if (this.eof)
+          return null;
+        this.readBlock();
+      }
+      return this.buffer[this.pos++];
+    },
+    getBytes: function decodestream_getBytes(length) {
+      var pos = this.pos;
+
+      if (length) {
+        this.ensureBuffer(pos + length);
+        var end = pos + length;
+
+        while (!this.eof && this.bufferLength < end)
+          this.readBlock();
+
+        var bufEnd = this.bufferLength;
+        if (end > bufEnd)
+          end = bufEnd;
+      } else {
+        while (!this.eof)
+          this.readBlock();
+
+        var end = this.bufferLength;
+      }
 
-            this.pos = end;
-            return this.buffer.subarray(pos, end)
-        },
-        lookChar: function decodestream_lookChar() {
-            var pos = this.pos;
-            while (this.bufferLength <= pos) {
-                if (this.eof)
-                    return null;
-                this.readBlock();
-            }
-            return String.fromCharCode(this.buffer[this.pos]);
-        },
-        getChar: function decodestream_getChar() {
-            var pos = this.pos;
-            while (this.bufferLength <= pos) {
-                if (this.eof)
-                    return null;
-                this.readBlock();
-            }
-            return String.fromCharCode(this.buffer[this.pos++]);
-        },
-        skip: function decodestream_skip(n) {
-            if (!n)
-                n = 1;
-            this.pos += n;
-        }
-    };
+      this.pos = end;
+      return this.buffer.subarray(pos, end);
+    },
+    lookChar: function decodestream_lookChar() {
+      var pos = this.pos;
+      while (this.bufferLength <= pos) {
+        if (this.eof)
+          return null;
+        this.readBlock();
+      }
+      return String.fromCharCode(this.buffer[this.pos]);
+    },
+    getChar: function decodestream_getChar() {
+      var pos = this.pos;
+      while (this.bufferLength <= pos) {
+        if (this.eof)
+          return null;
+        this.readBlock();
+      }
+      return String.fromCharCode(this.buffer[this.pos++]);
+    },
+    skip: function decodestream_skip(n) {
+      if (!n)
+        n = 1;
+      this.pos += n;
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
-
 var FakeStream = (function() {
-    function constructor(stream) {
-        this.dict = stream.dict;
-        DecodeStream.call(this);
-    };
-
-    constructor.prototype = Object.create(DecodeStream.prototype);
-    constructor.prototype.readBlock = function() {
-        var bufferLength = this.bufferLength;
-        bufferLength += 1024;
-        var buffer = this.ensureBuffer(bufferLength);
-        this.bufferLength = bufferLength;
-    };
-    constructor.prototype.getBytes = function(length) {
-        var pos = this.pos;
-
-        if (length) {
-            this.ensureBuffer(pos + length);
-            var end = pos + length;
-
-            while (!this.eof && this.bufferLength < end)
-                this.readBlock();
-
-            var bufEnd = this.bufferLength;
-            if (end > bufEnd)
-                end = bufEnd;
-        } else {
-            this.eof = true;
-            var end = this.bufferLength;
-        }
+  function constructor(stream) {
+    this.dict = stream.dict;
+    DecodeStream.call(this);
+  };
+
+  constructor.prototype = Object.create(DecodeStream.prototype);
+  constructor.prototype.readBlock = function() {
+    var bufferLength = this.bufferLength;
+    bufferLength += 1024;
+    var buffer = this.ensureBuffer(bufferLength);
+    this.bufferLength = bufferLength;
+  };
+
+  constructor.prototype.getBytes = function(length) {
+    var pos = this.pos;
+
+    if (length) {
+      this.ensureBuffer(pos + length);
+      var end = pos + length;
+
+      while (!this.eof && this.bufferLength < end)
+        this.readBlock();
+
+      var bufEnd = this.bufferLength;
+      if (end > bufEnd)
+        end = bufEnd;
+    } else {
+      this.eof = true;
+      var end = this.bufferLength;
+    }
 
-        this.pos = end;
-        return this.buffer.subarray(pos, end)
-    };
+    this.pos = end;
+    return this.buffer.subarray(pos, end);
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var FlateStream = (function() {
-    var codeLenCodeMap = new Uint32Array([
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-    ]);
+  var codeLenCodeMap = new Uint32Array([
+    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+  ]);
+
+  var lengthDecode = new Uint32Array([
+    0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a,
+    0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f,
+    0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073,
+    0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102
+  ]);
+
+  var distDecode = new Uint32Array([
+    0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d,
+    0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1,
+    0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01,
+    0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001
+  ]);
+
+  var fixedLitCodeTab = [new Uint32Array([
+    0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0,
+    0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0,
+    0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0,
+    0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0,
+    0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8,
+    0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8,
+    0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8,
+    0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8,
+    0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4,
+    0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4,
+    0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4,
+    0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4,
+    0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc,
+    0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec,
+    0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc,
+    0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc,
+    0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2,
+    0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2,
+    0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2,
+    0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2,
+    0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca,
+    0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea,
+    0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da,
+    0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa,
+    0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6,
+    0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6,
+    0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6,
+    0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6,
+    0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce,
+    0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee,
+    0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de,
+    0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe,
+    0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1,
+    0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1,
+    0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1,
+    0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1,
+    0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9,
+    0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9,
+    0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9,
+    0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9,
+    0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5,
+    0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5,
+    0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5,
+    0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5,
+    0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd,
+    0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed,
+    0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd,
+    0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd,
+    0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3,
+    0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3,
+    0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3,
+    0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3,
+    0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb,
+    0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb,
+    0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db,
+    0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb,
+    0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7,
+    0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7,
+    0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7,
+    0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7,
+    0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf,
+    0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef,
+    0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df,
+    0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff
+  ]), 9];
+
+  var fixedDistCodeTab = [new Uint32Array([
+    0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c,
+    0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000,
+    0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d,
+    0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
+  ]), 5];
+
+  function constructor(stream) {
+    var bytes = stream.getBytes();
+    var bytesPos = 0;
+
+    this.dict = stream.dict;
+    var cmf = bytes[bytesPos++];
+    var flg = bytes[bytesPos++];
+    if (cmf == -1 || flg == -1)
+      error('Invalid header in flate stream');
+    if ((cmf & 0x0f) != 0x08)
+      error('Unknown compression method in flate stream');
+    if ((((cmf << 8) + flg) % 31) != 0)
+      error('Bad FCHECK in flate stream');
+    if (flg & 0x20)
+      error('FDICT bit set in flate stream');
+
+    this.bytes = bytes;
+    this.bytesPos = bytesPos;
+
+    this.codeSize = 0;
+    this.codeBuf = 0;
+
+    DecodeStream.call(this);
+  }
 
-    var lengthDecode = new Uint32Array([
-        0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009,
-        0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017,
-        0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043,
-        0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3,
-        0x00102, 0x00102, 0x00102
-    ]);
+  constructor.prototype = Object.create(DecodeStream.prototype);
 
-    var distDecode = new Uint32Array([
-        0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009,
-        0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061,
-        0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401,
-        0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001,
-        0xd4001, 0xd6001
-    ]);
+  constructor.prototype.getBits = function(bits) {
+    var codeSize = this.codeSize;
+    var codeBuf = this.codeBuf;
+    var bytes = this.bytes;
+    var bytesPos = this.bytesPos;
 
-    var fixedLitCodeTab = [new Uint32Array([
-        0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030,
-        0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080,
-        0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114,
-        0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0,
-        0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014,
-        0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064,
-        0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106,
-        0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8,
-        0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c,
-        0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072,
-        0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002,
-        0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094,
-        0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a,
-        0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056,
-        0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b,
-        0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec,
-        0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e,
-        0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e,
-        0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110,
-        0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2,
-        0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019,
-        0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069,
-        0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102,
-        0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca,
-        0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045,
-        0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d,
-        0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d,
-        0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b,
-        0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023,
-        0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b,
-        0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d,
-        0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6,
-        0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037,
-        0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087,
-        0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117,
-        0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be,
-        0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010,
-        0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060,
-        0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104,
-        0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1,
-        0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048,
-        0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074,
-        0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004,
-        0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099,
-        0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c,
-        0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052,
-        0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109,
-        0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5,
-        0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a,
-        0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a,
-        0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113,
-        0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad,
-        0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e,
-        0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e,
-        0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100,
-        0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3,
-        0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041,
-        0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079,
-        0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009,
-        0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d,
-        0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025,
-        0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d,
-        0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e,
-        0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb,
-        0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033,
-        0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083,
-        0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115,
-        0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7,
-        0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017,
-        0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067,
-        0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107,
-        0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df,
-        0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f,
-        0x900ff
-    ]), 9];
-
-    var fixedDistCodeTab = [new Uint32Array([
-        0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c,
-        0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016,
-        0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005,
-        0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b,
-        0x50007, 0x50017, 0x5000f, 0x00000
-    ]), 5];
-
-    function constructor(stream) {
-        var bytes = stream.getBytes();
-        var bytesPos = 0;
-
-        this.dict = stream.dict;
-        var cmf = bytes[bytesPos++];
-        var flg = bytes[bytesPos++];
-        if (cmf == -1 || flg == -1)
-            error("Invalid header in flate stream");
-        if ((cmf & 0x0f) != 0x08)
-            error("Unknown compression method in flate stream");
-        if ((((cmf << 8) + flg) % 31) != 0)
-            error("Bad FCHECK in flate stream");
-        if (flg & 0x20)
-            error("FDICT bit set in flate stream");
-
-        this.bytes = bytes;
-        this.bytesPos = bytesPos;
-
-        this.codeSize = 0;
-        this.codeBuf = 0;
-        
-        DecodeStream.call(this);
+    var b;
+    while (codeSize < bits) {
+      if (typeof (b = bytes[bytesPos++]) == 'undefined')
+        error('Bad encoding in flate stream');
+      codeBuf |= b << codeSize;
+      codeSize += 8;
+    }
+    b = codeBuf & ((1 << bits) - 1);
+    this.codeBuf = codeBuf >> bits;
+    this.codeSize = codeSize -= bits;
+    this.bytesPos = bytesPos;
+    return b;
+  };
+
+  constructor.prototype.getCode = function(table) {
+    var codes = table[0];
+    var maxLen = table[1];
+    var codeSize = this.codeSize;
+    var codeBuf = this.codeBuf;
+    var bytes = this.bytes;
+    var bytesPos = this.bytesPos;
+
+    while (codeSize < maxLen) {
+      var b;
+      if (typeof (b = bytes[bytesPos++]) == 'undefined')
+        error('Bad encoding in flate stream');
+      codeBuf |= (b << codeSize);
+      codeSize += 8;
+    }
+    var code = codes[codeBuf & ((1 << maxLen) - 1)];
+    var codeLen = code >> 16;
+    var codeVal = code & 0xffff;
+    if (codeSize == 0 || codeSize < codeLen || codeLen == 0)
+      error('Bad encoding in flate stream');
+    this.codeBuf = (codeBuf >> codeLen);
+    this.codeSize = (codeSize - codeLen);
+    this.bytesPos = bytesPos;
+    return codeVal;
+  };
+
+  constructor.prototype.generateHuffmanTable = function(lengths) {
+    var n = lengths.length;
+
+    // find max code length
+    var maxLen = 0;
+    for (var i = 0; i < n; ++i) {
+      if (lengths[i] > maxLen)
+        maxLen = lengths[i];
     }
 
-    constructor.prototype = Object.create(DecodeStream.prototype);
-
-    constructor.prototype.getBits = function(bits) {
-        var codeSize = this.codeSize;
-        var codeBuf = this.codeBuf;
-        var bytes = this.bytes;
-        var bytesPos = this.bytesPos;
-
-        var b;
-        while (codeSize < bits) {
-            if (typeof (b = bytes[bytesPos++]) == "undefined")
-                error("Bad encoding in flate stream");
-            codeBuf |= b << codeSize;
-            codeSize += 8;
-        }
-        b = codeBuf & ((1 << bits) - 1);
-        this.codeBuf = codeBuf >> bits;
-        this.codeSize = codeSize -= bits;
-        this.bytesPos = bytesPos;
-        return b;
-    };
-    constructor.prototype.getCode = function(table) {
-        var codes = table[0];
-        var maxLen = table[1];
-        var codeSize = this.codeSize;
-        var codeBuf = this.codeBuf;
-        var bytes = this.bytes;
-        var bytesPos = this.bytesPos;
-
-        while (codeSize < maxLen) {
-            var b;
-            if (typeof (b = bytes[bytesPos++]) == "undefined")
-                error("Bad encoding in flate stream");
-            codeBuf |= (b << codeSize);
-            codeSize += 8;
-        }
-        var code = codes[codeBuf & ((1 << maxLen) - 1)];
-        var codeLen = code >> 16;
-        var codeVal = code & 0xffff;
-        if (codeSize == 0|| codeSize < codeLen || codeLen == 0)
-            error("Bad encoding in flate stream");
-        this.codeBuf = (codeBuf >> codeLen);
-        this.codeSize = (codeSize - codeLen);
-        this.bytesPos = bytesPos;
-        return codeVal;
-    };
-    constructor.prototype.generateHuffmanTable = function(lengths) {
-        var n = lengths.length;
-
-        // find max code length
-        var maxLen = 0;
-        for (var i = 0; i < n; ++i) {
-            if (lengths[i] > maxLen)
-                maxLen = lengths[i];
+    // build the table
+    var size = 1 << maxLen;
+    var codes = new Uint32Array(size);
+    for (var len = 1, code = 0, skip = 2;
+         len <= maxLen;
+         ++len, code <<= 1, skip <<= 1) {
+      for (var val = 0; val < n; ++val) {
+        if (lengths[val] == len) {
+          // bit-reverse the code
+          var code2 = 0;
+          var t = code;
+          for (var i = 0; i < len; ++i) {
+            code2 = (code2 << 1) | (t & 1);
+            t >>= 1;
+          }
+
+          // fill the table entries
+          for (var i = code2; i < size; i += skip)
+            codes[i] = (len << 16) | val;
+
+          ++code;
         }
+      }
+    }
 
-        // build the table
-        var size = 1 << maxLen;
-        var codes = new Uint32Array(size);
-        for (var len = 1, code = 0, skip = 2;
-                len <= maxLen;
-                ++len, code <<= 1, skip <<= 1) {
-            for (var val = 0; val < n; ++val) {
-                if (lengths[val] == len) {
-                    // bit-reverse the code
-                    var code2 = 0;
-                    var t = code;
-                    for (var i = 0; i < len; ++i) {
-                        code2 = (code2 << 1) | (t & 1);
-                        t >>= 1;
-                    }
-
-                    // fill the table entries
-                    for (var i = code2; i < size; i += skip)
-                        codes[i] = (len << 16) | val;
-
-                    ++code;
-                }
-            }
-        }
+    return [codes, maxLen];
+  };
 
-        return [codes, maxLen];
-    };
-    constructor.prototype.readBlock = function() {
-        function repeat(stream, array, len, offset, what) {
-            var repeat = stream.getBits(len) + offset;
-            while (repeat-- > 0)
-                array[i++] = what;
-        }
+  constructor.prototype.readBlock = function() {
+    function repeat(stream, array, len, offset, what) {
+      var repeat = stream.getBits(len) + offset;
+      while (repeat-- > 0)
+        array[i++] = what;
+    }
 
-        // read block header
-        var hdr = this.getBits(3);
-        if (hdr & 1)
-            this.eof = true;
-        hdr >>= 1;
-
-        if (hdr == 0) { // uncompressed block
-            var bytes = this.bytes;
-            var bytesPos = this.bytesPos;
-            var b;
-
-            if (typeof (b = bytes[bytesPos++]) == "undefined")
-                error("Bad block header in flate stream");
-            var blockLen = b;
-            if (typeof (b = bytes[bytesPos++]) == "undefined")
-                error("Bad block header in flate stream");
-            blockLen |= (b << 8);
-            if (typeof (b = bytes[bytesPos++]) == "undefined")
-                error("Bad block header in flate stream");
-            var check = b;
-            if (typeof (b = bytes[bytesPos++]) == "undefined")
-                error("Bad block header in flate stream");
-            check |= (b << 8);
-            if (check != (~blockLen & 0xffff))
-                error("Bad uncompressed block length in flate stream");
-
-            this.codeBuf = 0;
-            this.codeSize = 0;
-            
-            var bufferLength = this.bufferLength;
-            var buffer = this.ensureBuffer(bufferLength + blockLen);
-            var end = bufferLength + blockLen;
-            this.bufferLength = end;
-            for (var n = bufferLength; n < end; ++n) {
-                if (typeof (b = bytes[bytesPos++]) == "undefined") {
-                    this.eof = true;
-                    break;
-                }
-                buffer[n] = b;
-            }
-            this.bytesPos = bytesPos;
-            return;
-        }
+    // read block header
+    var hdr = this.getBits(3);
+    if (hdr & 1)
+      this.eof = true;
+    hdr >>= 1;
+
+    if (hdr == 0) { // uncompressed block
+      var bytes = this.bytes;
+      var bytesPos = this.bytesPos;
+      var b;
+
+      if (typeof (b = bytes[bytesPos++]) == 'undefined')
+        error('Bad block header in flate stream');
+      var blockLen = b;
+      if (typeof (b = bytes[bytesPos++]) == 'undefined')
+        error('Bad block header in flate stream');
+      blockLen |= (b << 8);
+      if (typeof (b = bytes[bytesPos++]) == 'undefined')
+        error('Bad block header in flate stream');
+      var check = b;
+      if (typeof (b = bytes[bytesPos++]) == 'undefined')
+        error('Bad block header in flate stream');
+      check |= (b << 8);
+      if (check != (~blockLen & 0xffff))
+        error('Bad uncompressed block length in flate stream');
+
+      this.codeBuf = 0;
+      this.codeSize = 0;
 
-        var litCodeTable;
-        var distCodeTable;
-        if (hdr == 1) { // compressed block, fixed codes
-            litCodeTable = fixedLitCodeTab;
-            distCodeTable = fixedDistCodeTab;
-        } else if (hdr == 2) { // compressed block, dynamic codes
-            var numLitCodes = this.getBits(5) + 257;
-            var numDistCodes = this.getBits(5) + 1;
-            var numCodeLenCodes = this.getBits(4) + 4;
-
-            // build the code lengths code table
-            var codeLenCodeLengths = Array(codeLenCodeMap.length);
-            var i = 0;
-            while (i < numCodeLenCodes)
-                codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3);
-            var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
-
-            // build the literal and distance code tables
-            var len = 0;
-            var i = 0;
-            var codes = numLitCodes + numDistCodes;
-            var codeLengths = new Array(codes);
-            while (i < codes) {
-                var code = this.getCode(codeLenCodeTab);
-                if (code == 16) {
-                    repeat(this, codeLengths, 2, 3, len);
-                } else if (code == 17) {
-                    repeat(this, codeLengths, 3, 3, len = 0);
-                } else if (code == 18) {
-                    repeat(this, codeLengths, 7, 11, len = 0);
-                } else {
-                    codeLengths[i++] = len = code;
-                }
-            }
+      var bufferLength = this.bufferLength;
+      var buffer = this.ensureBuffer(bufferLength + blockLen);
+      var end = bufferLength + blockLen;
+      this.bufferLength = end;
+      for (var n = bufferLength; n < end; ++n) {
+        if (typeof (b = bytes[bytesPos++]) == 'undefined') {
+          this.eof = true;
+          break;
+        }
+        buffer[n] = b;
+      }
+      this.bytesPos = bytesPos;
+      return;
+    }
 
-            litCodeTable =
-                this.generateHuffmanTable(codeLengths.slice(0, numLitCodes));
-            distCodeTable =
-                this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes));
+    var litCodeTable;
+    var distCodeTable;
+    if (hdr == 1) { // compressed block, fixed codes
+      litCodeTable = fixedLitCodeTab;
+      distCodeTable = fixedDistCodeTab;
+    } else if (hdr == 2) { // compressed block, dynamic codes
+      var numLitCodes = this.getBits(5) + 257;
+      var numDistCodes = this.getBits(5) + 1;
+      var numCodeLenCodes = this.getBits(4) + 4;
+
+      // build the code lengths code table
+      var codeLenCodeLengths = Array(codeLenCodeMap.length);
+      var i = 0;
+      while (i < numCodeLenCodes)
+        codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3);
+      var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
+
+      // build the literal and distance code tables
+      var len = 0;
+      var i = 0;
+      var codes = numLitCodes + numDistCodes;
+      var codeLengths = new Array(codes);
+      while (i < codes) {
+        var code = this.getCode(codeLenCodeTab);
+        if (code == 16) {
+          repeat(this, codeLengths, 2, 3, len);
+        } else if (code == 17) {
+          repeat(this, codeLengths, 3, 3, len = 0);
+        } else if (code == 18) {
+          repeat(this, codeLengths, 7, 11, len = 0);
         } else {
-            error("Unknown block type in flate stream");
+          codeLengths[i++] = len = code;
         }
+      }
 
-        var buffer = this.buffer;
-        var limit = buffer ? buffer.length : 0;
-        var pos = this.bufferLength;
-        while (true) {
-            var code1 = this.getCode(litCodeTable);
-            if (code1 < 256) {
-                if (pos + 1 >= limit) {
-                    buffer = this.ensureBuffer(pos + 1);
-                    limit = buffer.length;
-                }
-                buffer[pos++] = code1;
-                continue;
-            }
-            if (code1 == 256) {
-                this.bufferLength = pos;
-                return;
-            }
-            code1 -= 257;
-            code1 = lengthDecode[code1];
-            var code2 = code1 >> 16;
-            if (code2 > 0)
-                code2 = this.getBits(code2);
-            var len = (code1 & 0xffff) + code2;
-            code1 = this.getCode(distCodeTable);
-            code1 = distDecode[code1];
-            code2 = code1 >> 16;
-            if (code2 > 0)
-                code2 = this.getBits(code2);
-            var dist = (code1 & 0xffff) + code2;
-            if (pos + len >= limit) {
-                buffer = this.ensureBuffer(pos + len);
-                limit = buffer.length;
-            }
-            for (var k = 0; k < len; ++k, ++pos)
-                buffer[pos] = buffer[pos - dist];
+      litCodeTable =
+        this.generateHuffmanTable(codeLengths.slice(0, numLitCodes));
+      distCodeTable =
+        this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes));
+    } else {
+      error('Unknown block type in flate stream');
+    }
+
+    var buffer = this.buffer;
+    var limit = buffer ? buffer.length : 0;
+    var pos = this.bufferLength;
+    while (true) {
+      var code1 = this.getCode(litCodeTable);
+      if (code1 < 256) {
+        if (pos + 1 >= limit) {
+          buffer = this.ensureBuffer(pos + 1);
+          limit = buffer.length;
         }
-    };
+        buffer[pos++] = code1;
+        continue;
+      }
+      if (code1 == 256) {
+        this.bufferLength = pos;
+        return;
+      }
+      code1 -= 257;
+      code1 = lengthDecode[code1];
+      var code2 = code1 >> 16;
+      if (code2 > 0)
+        code2 = this.getBits(code2);
+      var len = (code1 & 0xffff) + code2;
+      code1 = this.getCode(distCodeTable);
+      code1 = distDecode[code1];
+      code2 = code1 >> 16;
+      if (code2 > 0)
+        code2 = this.getBits(code2);
+      var dist = (code1 & 0xffff) + code2;
+      if (pos + len >= limit) {
+        buffer = this.ensureBuffer(pos + len);
+        limit = buffer.length;
+      }
+      for (var k = 0; k < len; ++k, ++pos)
+        buffer[pos] = buffer[pos - dist];
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var PredictorStream = (function() {
-    function constructor(stream, params) {
-        var predictor = this.predictor = params.get("Predictor") || 1;
+  function constructor(stream, params) {
+    var predictor = this.predictor = params.get('Predictor') || 1;
 
-        if (predictor <= 1)
-            return stream; // no prediction
-        if (predictor !== 2 && (predictor < 10 || predictor > 15))
-            error("Unsupported predictor");
-
-        if (predictor === 2)
-            this.readBlock = this.readBlockTiff;
-        else
-            this.readBlock = this.readBlockPng;
-
-        this.stream = stream;
-        this.dict = stream.dict;
-        if (params.has("EarlyChange")) {
-            error("EarlyChange predictor parameter is not supported");
-        }
-        var colors = this.colors = params.get("Colors") || 1;
-        var bits = this.bits = params.get("BitsPerComponent") || 8;
-        var columns = this.columns = params.get("Columns") || 1;
+    if (predictor <= 1)
+      return stream; // no prediction
+    if (predictor !== 2 && (predictor < 10 || predictor > 15))
+      error('Unsupported predictor');
 
-        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;
+    if (predictor === 2)
+      this.readBlock = this.readBlockTiff;
+    else
+      this.readBlock = this.readBlockPng;
 
-        DecodeStream.call(this);
-        return this;
+    this.stream = stream;
+    this.dict = stream.dict;
+    if (params.has('EarlyChange')) {
+      error('EarlyChange predictor parameter is not supported');
     }
+    var colors = this.colors = params.get('Colors') || 1;
+    var bits = this.bits = params.get('BitsPerComponent') || 8;
+    var columns = this.columns = params.get('Columns') || 1;
 
-    constructor.prototype = Object.create(DecodeStream.prototype);
-
-    constructor.prototype.readBlockTiff = function() {
-        var rowBytes = this.rowBytes;
-        var pixBytes = this.pixBytes;
+    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;
 
-        var bufferLength = this.bufferLength;
-        var buffer = this.ensureBuffer(bufferLength + rowBytes);
-        var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
-
-        var bits = this.bits;
-        var colors = this.colors;
+    DecodeStream.call(this);
+    return this;
+  }
 
-        var rawBytes = this.stream.getBytes(rowBytes);
+  constructor.prototype = Object.create(DecodeStream.prototype);
 
-        if (bits === 1) {
-            var inbuf = 0;
-            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
-                currentRow[i] = (c ^ (inBuf >> colors)) & 0xFF;
-                // truncate inBuf (assumes colors < 16)
-                inBuf &= 0xFFFF;
-            }
-        } else if (bits === 8) {
-            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 = 0;
-            var columns = this.columns;
-            for (var i = 0; i < columns; ++i) {
-                for (var kk = 0; kk < colors; ++kk) {
-                    if (inbits < bits) {
-                        inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF);
-                        inbits += 8;
-                    }
-                    compArray[kk] = (compArray[kk] +
-                            (inbuf >> (inbits - bits))) & bitMask;
-                    inbits -= bits;
-                    outbuf = (outbuf << bits) | compArray[kk];
-                    outbits += bits;
-                    if (outbits >= 8) {
-                        currentRow[k++] = (outbuf >> (outbits - 8)) & 0xFF;
-                        outbits -= 8;
-                    }
-                }
-            }
-            if (outbits > 0) {
-                currentRow[k++] = (outbuf << (8 - outbits)) +
-                    (inbuf & ((1 << (8 - outbits)) - 1))
-            }
-        }
-        this.bufferLength += rowBytes;
-    };
-    constructor.prototype.readBlockPng = function() {
-        var rowBytes = this.rowBytes;
-        var pixBytes = this.pixBytes;
+  constructor.prototype.readBlockTiff = function() {
+    var rowBytes = this.rowBytes;
+    var pixBytes = this.pixBytes;
 
-        var predictor = this.stream.getByte();
-        var rawBytes = this.stream.getBytes(rowBytes);
+    var bufferLength = this.bufferLength;
+    var buffer = this.ensureBuffer(bufferLength + rowBytes);
+    var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
 
-        var bufferLength = this.bufferLength;
-        var buffer = this.ensureBuffer(bufferLength + rowBytes);
+    var bits = this.bits;
+    var colors = this.colors;
 
-        var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
-        var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
-        if (prevRow.length == 0)
-            prevRow = currentRow;
+    var rawBytes = this.stream.getBytes(rowBytes);
 
-        switch (predictor) {
-        case 0:
-            break;
-        case 1:
-            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 = 0; i < rowBytes; ++i)
-                currentRow[i] = (prevRow[i] + rawBytes[i]) & 0xFF;
-            break;
-        case 3:
-            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
-            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;
-
-                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;
-
-                var c = rawBytes[i];
-                if (pa <= pb && pa <= pc)
-                    currentRow[i] = left + c;
-                else if (pb <= pc)
-                    currentRow[i] = up + c;
-                else
-                    currentRow[i] = upLeft + c;
-                break;
-            }
-        default:
-            error("Unsupported predictor");
-            break;
+    if (bits === 1) {
+      var inbuf = 0;
+      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
+        currentRow[i] = (c ^ (inBuf >> colors)) & 0xFF;
+        // truncate inBuf (assumes colors < 16)
+        inBuf &= 0xFFFF;
+      }
+    } else if (bits === 8) {
+      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 = 0;
+      var columns = this.columns;
+      for (var i = 0; i < columns; ++i) {
+        for (var kk = 0; kk < colors; ++kk) {
+          if (inbits < bits) {
+            inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF);
+            inbits += 8;
+          }
+          compArray[kk] = (compArray[kk] +
+                           (inbuf >> (inbits - bits))) & bitMask;
+          inbits -= bits;
+          outbuf = (outbuf << bits) | compArray[kk];
+          outbits += bits;
+          if (outbits >= 8) {
+            currentRow[k++] = (outbuf >> (outbits - 8)) & 0xFF;
+            outbits -= 8;
+          }
         }
-        this.bufferLength += rowBytes;
-    };
+      }
+      if (outbits > 0) {
+        currentRow[k++] = (outbuf << (8 - outbits)) +
+        (inbuf & ((1 << (8 - outbits)) - 1));
+      }
+    }
+    this.bufferLength += rowBytes;
+  };
+
+  constructor.prototype.readBlockPng = function() {
+    var rowBytes = this.rowBytes;
+    var pixBytes = this.pixBytes;
+
+    var predictor = this.stream.getByte();
+    var rawBytes = this.stream.getBytes(rowBytes);
+
+    var bufferLength = this.bufferLength;
+    var buffer = this.ensureBuffer(bufferLength + rowBytes);
+
+    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 = 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 = 0; i < rowBytes; ++i)
+        currentRow[i] = (prevRow[i] + rawBytes[i]) & 0xFF;
+      break;
+    case 3:
+      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
+      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;
+
+        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;
+
+        var c = rawBytes[i];
+        if (pa <= pb && pa <= pc)
+          currentRow[i] = left + c;
+        else if (pb <= pc)
+          currentRow[i] = up + c;
+        else
+          currentRow[i] = upLeft + c;
+        break;
+      }
+    default:
+      error('Unsupported predictor');
+      break;
+    }
+    this.bufferLength += rowBytes;
+  };
 
-    return constructor;
+  return constructor;
 })();
 
-// A JpegStream can't be read directly. We use the platform to render the underlying
-// JPEG data for us.
+// 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;
-    }
+  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;
-        },
-        getChar: function() {
-            error("internal error: getChar is not valid on JpegStream");
-        }
-    };
+  constructor.prototype = {
+    getImage: function() {
+      return this.domImage;
+    },
+    getChar: function() {
+      error('internal error: getChar is not valid on JpegStream');
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
+
 var DecryptStream = (function() {
-    function constructor(str, decrypt) {
-        this.str = str;
-        this.dict = str.dict;
-        this.decrypt = decrypt;
+  function constructor(str, decrypt) {
+    this.str = str;
+    this.dict = str.dict;
+    this.decrypt = decrypt;
 
-        DecodeStream.call(this);
-    }
+    DecodeStream.call(this);
+  }
 
-    var chunkSize = 512;
+  var chunkSize = 512;
 
-    constructor.prototype = Object.create(DecodeStream.prototype);
-    constructor.prototype.readBlock = function() {
-      var chunk = this.str.getBytes(chunkSize);
-      if (!chunk || chunk.length == 0) {
-        this.eof = true;
-        return;
-      }
-      var decrypt = this.decrypt;
-      chunk = decrypt(chunk);
+  constructor.prototype = Object.create(DecodeStream.prototype);
 
-      var bufferLength = this.bufferLength;
-      var i, n = chunk.length;
-      var buffer = this.ensureBuffer(bufferLength + n);
-      for (i = 0; i < n; i++)
-        buffer[bufferLength++] = chunk[i];
-      this.bufferLength = bufferLength;
-      this.eof = n < chunkSize;
-    };
-
-    return constructor;
+  constructor.prototype.readBlock = function() {
+    var chunk = this.str.getBytes(chunkSize);
+    if (!chunk || chunk.length == 0) {
+      this.eof = true;
+      return;
+    }
+    var decrypt = this.decrypt;
+    chunk = decrypt(chunk);
+
+    var bufferLength = this.bufferLength;
+    var i, n = chunk.length;
+    var buffer = this.ensureBuffer(bufferLength + n);
+    for (i = 0; i < n; i++)
+      buffer[bufferLength++] = chunk[i];
+    this.bufferLength = bufferLength;
+    this.eof = n < chunkSize;
+  };
+
+  return constructor;
 })();
 
 var Ascii85Stream = (function() {
-    function constructor(str) {
-        this.str = str;
-        this.dict = str.dict;
-        this.input = new Uint8Array(5);
-        
-        DecodeStream.call(this);
-    }
+  function constructor(str) {
+    this.str = str;
+    this.dict = str.dict;
+    this.input = new Uint8Array(5);
 
-    constructor.prototype = Object.create(DecodeStream.prototype);
-    constructor.prototype.readBlock = function() {
-        var tildaCode = "~".charCodeAt(0);
-        var zCode = "z".charCodeAt(0);
-        var str = this.str;
+    DecodeStream.call(this);
+  }
 
-        var c = str.getByte();
-        while (Lexer.isSpace(String.fromCharCode(c)))
-            c = str.getByte();
+  constructor.prototype = Object.create(DecodeStream.prototype);
 
-        if (!c || c === tildaCode) {
-            this.eof = true;
-            return;
-        } 
+  constructor.prototype.readBlock = function() {
+    var tildaCode = '~'.charCodeAt(0);
+    var zCode = 'z'.charCodeAt(0);
+    var str = this.str;
 
-        var bufferLength = this.bufferLength;
+    var c = str.getByte();
+    while (Lexer.isSpace(String.fromCharCode(c)))
+      c = str.getByte();
 
-        // special code for z
-        if (c == zCode) {
-            var buffer = this.ensureBuffer(bufferLength + 4);
-            for (var i = 0; i < 4; ++i)
-                buffer[bufferLength + i] = 0;
-            this.bufferLength += 4;
-        } else {
-            var input = this.input;
-            input[0] = c;
-            for (var i = 1; i < 5; ++i){
-                c = str.getByte();
-                while (Lexer.isSpace(String.fromCharCode(c)))
-                    c = str.getByte();
+    if (!c || c === tildaCode) {
+      this.eof = true;
+      return;
+    }
 
-                input[i] = c;
+    var bufferLength = this.bufferLength;
+
+    // special code for z
+    if (c == zCode) {
+      var buffer = this.ensureBuffer(bufferLength + 4);
+      for (var i = 0; i < 4; ++i)
+        buffer[bufferLength + i] = 0;
+      this.bufferLength += 4;
+    } else {
+      var input = this.input;
+      input[0] = c;
+      for (var i = 1; i < 5; ++i) {
+        c = str.getByte();
+        while (Lexer.isSpace(String.fromCharCode(c)))
+          c = str.getByte();
 
-                if (!c || c == tildaCode)
-                    break;
-            }
-            var buffer = this.ensureBuffer(bufferLength + i - 1);
-            this.bufferLength += i - 1;
-
-            // partial ending;
-            if (i < 5) {
-                for (; i < 5; ++i)
-                    input[i] = 0x21 + 84;
-                this.eof = true;
-            }
-            var t = 0;
-            for (var i = 0; i < 5; ++i)
-                t = t * 85 + (input[i] - 0x21);
+        input[i] = c;
 
-            for (var i = 3; i >= 0; --i){
-                buffer[bufferLength + i] = t & 0xFF;
-                t >>= 8;
-            }
-        }
-    };
+        if (!c || c == tildaCode)
+          break;
+      }
+      var buffer = this.ensureBuffer(bufferLength + i - 1);
+      this.bufferLength += i - 1;
+
+      // partial ending;
+      if (i < 5) {
+        for (; i < 5; ++i)
+          input[i] = 0x21 + 84;
+        this.eof = true;
+      }
+      var t = 0;
+      for (var i = 0; i < 5; ++i)
+        t = t * 85 + (input[i] - 0x21);
+
+      for (var i = 3; i >= 0; --i) {
+        buffer[bufferLength + i] = t & 0xFF;
+        t >>= 8;
+      }
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var CCITTFaxStream = (function() {
 
-    var ccittEOL = -2;
-    var twoDimPass = 0;
-    var twoDimHoriz = 1;
-    var twoDimVert0 = 2;
-    var twoDimVertR1 = 3;
-    var twoDimVertL1 = 4;
-    var twoDimVertR2 = 5;
-    var twoDimVertL2 = 6;
-    var twoDimVertR3 = 7;
-    var twoDimVertL3 = 8;
-
-    var twoDimTable = [
+  var ccittEOL = -2;
+  var twoDimPass = 0;
+  var twoDimHoriz = 1;
+  var twoDimVert0 = 2;
+  var twoDimVertR1 = 3;
+  var twoDimVertL1 = 4;
+  var twoDimVertR2 = 5;
+  var twoDimVertL2 = 6;
+  var twoDimVertR3 = 7;
+  var twoDimVertL3 = 8;
+
+  var twoDimTable = [
     [-1, -1], [-1, -1],               // 000000x
     [7, twoDimVertL3],                // 0000010
     [7, twoDimVertR3],                // 0000011
@@ -987,3964 +983,4024 @@ var CCITTFaxStream = (function() {
     [1, twoDimVert0], [1, twoDimVert0],
     [1, twoDimVert0], [1, twoDimVert0],
     [1, twoDimVert0], [1, twoDimVert0]
-    ];
-
-    var whiteTable1 = [
-        [-1, -1],                 // 00000
-        [12, ccittEOL],               // 00001
-        [-1, -1], [-1, -1],               // 0001x
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 001xx
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 010xx
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 011xx
-        [11, 1792], [11, 1792],           // 1000x
-        [12, 1984],                   // 10010
-        [12, 2048],                   // 10011
-        [12, 2112],                   // 10100
-        [12, 2176],                   // 10101
-        [12, 2240],                   // 10110
-        [12, 2304],                   // 10111
-        [11, 1856], [11, 1856],           // 1100x
-        [11, 1920], [11, 1920],           // 1101x
-        [12, 2368],                   // 11100
-        [12, 2432],                   // 11101
-        [12, 2496],                   // 11110
-        [12, 2560]                    // 11111
-    ];
-
-    var whiteTable2 = [
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 0000000xx
-        [8, 29], [8, 29],             // 00000010x
-        [8, 30], [8, 30],             // 00000011x
-        [8, 45], [8, 45],             // 00000100x
-        [8, 46], [8, 46],             // 00000101x
-        [7, 22], [7, 22], [7, 22], [7, 22],       // 0000011xx
-        [7, 23], [7, 23], [7, 23], [7, 23],       // 0000100xx
-        [8, 47], [8, 47],             // 00001010x
-        [8, 48], [8, 48],             // 00001011x
-        [6, 13], [6, 13], [6, 13], [6, 13],       // 000011xxx
-        [6, 13], [6, 13], [6, 13], [6, 13],
-        [7, 20], [7, 20], [7, 20], [7, 20],       // 0001000xx
-        [8, 33], [8, 33],             // 00010010x
-        [8, 34], [8, 34],             // 00010011x
-        [8, 35], [8, 35],             // 00010100x
-        [8, 36], [8, 36],             // 00010101x
-        [8, 37], [8, 37],             // 00010110x
-        [8, 38], [8, 38],             // 00010111x
-        [7, 19], [7, 19], [7, 19], [7, 19],       // 0001100xx
-        [8, 31], [8, 31],             // 00011010x
-        [8, 32], [8, 32],             // 00011011x
-        [6, 1], [6, 1], [6, 1], [6, 1],       // 000111xxx
-        [6, 1], [6, 1], [6, 1], [6, 1],
-        [6, 12], [6, 12], [6, 12], [6, 12],       // 001000xxx
-        [6, 12], [6, 12], [6, 12], [6, 12],
-        [8, 53], [8, 53],             // 00100100x
-        [8, 54], [8, 54],             // 00100101x
-        [7, 26], [7, 26], [7, 26], [7, 26],       // 0010011xx
-        [8, 39], [8, 39],             // 00101000x
-        [8, 40], [8, 40],             // 00101001x
-        [8, 41], [8, 41],             // 00101010x
-        [8, 42], [8, 42],             // 00101011x
-        [8, 43], [8, 43],             // 00101100x
-        [8, 44], [8, 44],             // 00101101x
-        [7, 21], [7, 21], [7, 21], [7, 21],       // 0010111xx
-        [7, 28], [7, 28], [7, 28], [7, 28],       // 0011000xx
-        [8, 61], [8, 61],             // 00110010x
-        [8, 62], [8, 62],             // 00110011x
-        [8, 63], [8, 63],             // 00110100x
-        [8, 0], [8, 0],               // 00110101x
-        [8, 320], [8, 320],               // 00110110x
-        [8, 384], [8, 384],               // 00110111x
-        [5, 10], [5, 10], [5, 10], [5, 10],       // 00111xxxx
-        [5, 10], [5, 10], [5, 10], [5, 10],
-        [5, 10], [5, 10], [5, 10], [5, 10],
-        [5, 10], [5, 10], [5, 10], [5, 10],
-        [5, 11], [5, 11], [5, 11], [5, 11],       // 01000xxxx
-        [5, 11], [5, 11], [5, 11], [5, 11],
-        [5, 11], [5, 11], [5, 11], [5, 11],
-        [5, 11], [5, 11], [5, 11], [5, 11],
-        [7, 27], [7, 27], [7, 27], [7, 27],       // 0100100xx
-        [8, 59], [8, 59],             // 01001010x
-        [8, 60], [8, 60],             // 01001011x
-        [9, 1472],                    // 010011000
-        [9, 1536],                    // 010011001
-        [9, 1600],                    // 010011010
-        [9, 1728],                    // 010011011
-        [7, 18], [7, 18], [7, 18], [7, 18],       // 0100111xx
-        [7, 24], [7, 24], [7, 24], [7, 24],       // 0101000xx
-        [8, 49], [8, 49],             // 01010010x
-        [8, 50], [8, 50],             // 01010011x
-        [8, 51], [8, 51],             // 01010100x
-        [8, 52], [8, 52],             // 01010101x
-        [7, 25], [7, 25], [7, 25], [7, 25],       // 0101011xx
-        [8, 55], [8, 55],             // 01011000x
-        [8, 56], [8, 56],             // 01011001x
-        [8, 57], [8, 57],             // 01011010x
-        [8, 58], [8, 58],             // 01011011x
-        [6, 192], [6, 192], [6, 192], [6, 192],   // 010111xxx
-        [6, 192], [6, 192], [6, 192], [6, 192],
-        [6, 1664], [6, 1664], [6, 1664], [6, 1664],   // 011000xxx
-        [6, 1664], [6, 1664], [6, 1664], [6, 1664],
-        [8, 448], [8, 448],               // 01100100x
-        [8, 512], [8, 512],               // 01100101x
-        [9, 704],                 // 011001100
-        [9, 768],                 // 011001101
-        [8, 640], [8, 640],               // 01100111x
-        [8, 576], [8, 576],               // 01101000x
-        [9, 832],                 // 011010010
-        [9, 896],                 // 011010011
-        [9, 960],                 // 011010100
-        [9, 1024],                    // 011010101
-        [9, 1088],                    // 011010110
-        [9, 1152],                    // 011010111
-        [9, 1216],                    // 011011000
-        [9, 1280],                    // 011011001
-        [9, 1344],                    // 011011010
-        [9, 1408],                    // 011011011
-        [7, 256], [7, 256], [7, 256], [7, 256],   // 0110111xx
-        [4, 2], [4, 2], [4, 2], [4, 2],       // 0111xxxxx
-        [4, 2], [4, 2], [4, 2], [4, 2],
-        [4, 2], [4, 2], [4, 2], [4, 2],
-        [4, 2], [4, 2], [4, 2], [4, 2],
-        [4, 2], [4, 2], [4, 2], [4, 2],
-        [4, 2], [4, 2], [4, 2], [4, 2],
-        [4, 2], [4, 2], [4, 2], [4, 2],
-        [4, 2], [4, 2], [4, 2], [4, 2],
-        [4, 3], [4, 3], [4, 3], [4, 3],       // 1000xxxxx
-        [4, 3], [4, 3], [4, 3], [4, 3],
-        [4, 3], [4, 3], [4, 3], [4, 3],
-        [4, 3], [4, 3], [4, 3], [4, 3],
-        [4, 3], [4, 3], [4, 3], [4, 3],
-        [4, 3], [4, 3], [4, 3], [4, 3],
-        [4, 3], [4, 3], [4, 3], [4, 3],
-        [4, 3], [4, 3], [4, 3], [4, 3],
-        [5, 128], [5, 128], [5, 128], [5, 128],   // 10010xxxx
-        [5, 128], [5, 128], [5, 128], [5, 128],
-        [5, 128], [5, 128], [5, 128], [5, 128],
-        [5, 128], [5, 128], [5, 128], [5, 128],
-        [5, 8], [5, 8], [5, 8], [5, 8],       // 10011xxxx
-        [5, 8], [5, 8], [5, 8], [5, 8],
-        [5, 8], [5, 8], [5, 8], [5, 8],
-        [5, 8], [5, 8], [5, 8], [5, 8],
-        [5, 9], [5, 9], [5, 9], [5, 9],       // 10100xxxx
-        [5, 9], [5, 9], [5, 9], [5, 9],
-        [5, 9], [5, 9], [5, 9], [5, 9],
-        [5, 9], [5, 9], [5, 9], [5, 9],
-        [6, 16], [6, 16], [6, 16], [6, 16],       // 101010xxx
-        [6, 16], [6, 16], [6, 16], [6, 16],
-        [6, 17], [6, 17], [6, 17], [6, 17],       // 101011xxx
-        [6, 17], [6, 17], [6, 17], [6, 17],
-        [4, 4], [4, 4], [4, 4], [4, 4],       // 1011xxxxx
-        [4, 4], [4, 4], [4, 4], [4, 4],
-        [4, 4], [4, 4], [4, 4], [4, 4],
-        [4, 4], [4, 4], [4, 4], [4, 4],
-        [4, 4], [4, 4], [4, 4], [4, 4],
-        [4, 4], [4, 4], [4, 4], [4, 4],
-        [4, 4], [4, 4], [4, 4], [4, 4],
-        [4, 4], [4, 4], [4, 4], [4, 4],
-        [4, 5], [4, 5], [4, 5], [4, 5],       // 1100xxxxx
-        [4, 5], [4, 5], [4, 5], [4, 5],
-        [4, 5], [4, 5], [4, 5], [4, 5],
-        [4, 5], [4, 5], [4, 5], [4, 5],
-        [4, 5], [4, 5], [4, 5], [4, 5],
-        [4, 5], [4, 5], [4, 5], [4, 5],
-        [4, 5], [4, 5], [4, 5], [4, 5],
-        [4, 5], [4, 5], [4, 5], [4, 5],
-        [6, 14], [6, 14], [6, 14], [6, 14],       // 110100xxx
-        [6, 14], [6, 14], [6, 14], [6, 14],
-        [6, 15], [6, 15], [6, 15], [6, 15],       // 110101xxx
-        [6, 15], [6, 15], [6, 15], [6, 15],
-        [5, 64], [5, 64], [5, 64], [5, 64],       // 11011xxxx
-        [5, 64], [5, 64], [5, 64], [5, 64],
-        [5, 64], [5, 64], [5, 64], [5, 64],
-        [5, 64], [5, 64], [5, 64], [5, 64],
-        [4, 6], [4, 6], [4, 6], [4, 6],       // 1110xxxxx
-        [4, 6], [4, 6], [4, 6], [4, 6],
-        [4, 6], [4, 6], [4, 6], [4, 6],
-        [4, 6], [4, 6], [4, 6], [4, 6],
-        [4, 6], [4, 6], [4, 6], [4, 6],
-        [4, 6], [4, 6], [4, 6], [4, 6],
-        [4, 6], [4, 6], [4, 6], [4, 6],
-        [4, 6], [4, 6], [4, 6], [4, 6],
-        [4, 7], [4, 7], [4, 7], [4, 7],       // 1111xxxxx
-        [4, 7], [4, 7], [4, 7], [4, 7],
-        [4, 7], [4, 7], [4, 7], [4, 7],
-        [4, 7], [4, 7], [4, 7], [4, 7],
-        [4, 7], [4, 7], [4, 7], [4, 7],
-        [4, 7], [4, 7], [4, 7], [4, 7],
-        [4, 7], [4, 7], [4, 7], [4, 7],
-        [4, 7], [4, 7], [4, 7], [4, 7]
-    ];
-    
-    var blackTable1 = [
-        [-1, -1], [-1, -1],                   // 000000000000x
-        [12, ccittEOL], [12, ccittEOL],           // 000000000001x
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000001xx
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000010xx
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000011xx
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000100xx
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000101xx
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000110xx
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000111xx
-        [11, 1792], [11, 1792], [11, 1792], [11, 1792],   // 00000001000xx
-        [12, 1984], [12, 1984],               // 000000010010x
-        [12, 2048], [12, 2048],               // 000000010011x
-        [12, 2112], [12, 2112],               // 000000010100x
-        [12, 2176], [12, 2176],               // 000000010101x
-        [12, 2240], [12, 2240],               // 000000010110x
-        [12, 2304], [12, 2304],               // 000000010111x
-        [11, 1856], [11, 1856], [11, 1856], [11, 1856],   // 00000001100xx
-        [11, 1920], [11, 1920], [11, 1920], [11, 1920],   // 00000001101xx
-        [12, 2368], [12, 2368],               // 000000011100x
-        [12, 2432], [12, 2432],               // 000000011101x
-        [12, 2496], [12, 2496],               // 000000011110x
-        [12, 2560], [12, 2560],               // 000000011111x
-        [10, 18], [10, 18], [10, 18], [10, 18],       // 0000001000xxx
-        [10, 18], [10, 18], [10, 18], [10, 18],
-        [12, 52], [12, 52],                   // 000000100100x
-        [13, 640],                        // 0000001001010
-        [13, 704],                        // 0000001001011
-        [13, 768],                        // 0000001001100
-        [13, 832],                        // 0000001001101
-        [12, 55], [12, 55],                   // 000000100111x
-        [12, 56], [12, 56],                   // 000000101000x
-        [13, 1280],                       // 0000001010010
-        [13, 1344],                       // 0000001010011
-        [13, 1408],                       // 0000001010100
-        [13, 1472],                       // 0000001010101
-        [12, 59], [12, 59],                   // 000000101011x
-        [12, 60], [12, 60],                   // 000000101100x
-        [13, 1536],                       // 0000001011010
-        [13, 1600],                       // 0000001011011
-        [11, 24], [11, 24], [11, 24], [11, 24],       // 00000010111xx
-        [11, 25], [11, 25], [11, 25], [11, 25],       // 00000011000xx
-        [13, 1664],                       // 0000001100100
-        [13, 1728],                       // 0000001100101
-        [12, 320], [12, 320],                 // 000000110011x
-        [12, 384], [12, 384],                 // 000000110100x
-        [12, 448], [12, 448],                 // 000000110101x
-        [13, 512],                        // 0000001101100
-        [13, 576],                        // 0000001101101
-        [12, 53], [12, 53],                   // 000000110111x
-        [12, 54], [12, 54],                   // 000000111000x
-        [13, 896],                        // 0000001110010
-        [13, 960],                        // 0000001110011
-        [13, 1024],                       // 0000001110100
-        [13, 1088],                       // 0000001110101
-        [13, 1152],                       // 0000001110110
-        [13, 1216],                       // 0000001110111
-        [10, 64], [10, 64], [10, 64], [10, 64],       // 0000001111xxx
-        [10, 64], [10, 64], [10, 64], [10, 64]
-    ];
-
-    var blackTable2 = [
-        [8, 13], [8, 13], [8, 13], [8, 13],           // 00000100xxxx
-        [8, 13], [8, 13], [8, 13], [8, 13],
-        [8, 13], [8, 13], [8, 13], [8, 13],
-        [8, 13], [8, 13], [8, 13], [8, 13],
-        [11, 23], [11, 23],                   // 00000101000x
-        [12, 50],                     // 000001010010
-        [12, 51],                     // 000001010011
-        [12, 44],                     // 000001010100
-        [12, 45],                     // 000001010101
-        [12, 46],                     // 000001010110
-        [12, 47],                     // 000001010111
-        [12, 57],                     // 000001011000
-        [12, 58],                     // 000001011001
-        [12, 61],                     // 000001011010
-        [12, 256],                        // 000001011011
-        [10, 16], [10, 16], [10, 16], [10, 16],       // 0000010111xx
-        [10, 17], [10, 17], [10, 17], [10, 17],       // 0000011000xx
-        [12, 48],                     // 000001100100
-        [12, 49],                     // 000001100101
-        [12, 62],                     // 000001100110
-        [12, 63],                     // 000001100111
-        [12, 30],                     // 000001101000
-        [12, 31],                     // 000001101001
-        [12, 32],                     // 000001101010
-        [12, 33],                     // 000001101011
-        [12, 40],                     // 000001101100
-        [12, 41],                     // 000001101101
-        [11, 22], [11, 22],                   // 00000110111x
-        [8, 14], [8, 14], [8, 14], [8, 14],           // 00000111xxxx
-        [8, 14], [8, 14], [8, 14], [8, 14],
-        [8, 14], [8, 14], [8, 14], [8, 14],
-        [8, 14], [8, 14], [8, 14], [8, 14],
-        [7, 10], [7, 10], [7, 10], [7, 10],           // 0000100xxxxx
-        [7, 10], [7, 10], [7, 10], [7, 10],
-        [7, 10], [7, 10], [7, 10], [7, 10],
-        [7, 10], [7, 10], [7, 10], [7, 10],
-        [7, 10], [7, 10], [7, 10], [7, 10],
-        [7, 10], [7, 10], [7, 10], [7, 10],
-        [7, 10], [7, 10], [7, 10], [7, 10],
-        [7, 10], [7, 10], [7, 10], [7, 10],
-        [7, 11], [7, 11], [7, 11], [7, 11],           // 0000101xxxxx
-        [7, 11], [7, 11], [7, 11], [7, 11],
-        [7, 11], [7, 11], [7, 11], [7, 11],
-        [7, 11], [7, 11], [7, 11], [7, 11],
-        [7, 11], [7, 11], [7, 11], [7, 11],
-        [7, 11], [7, 11], [7, 11], [7, 11],
-        [7, 11], [7, 11], [7, 11], [7, 11],
-        [7, 11], [7, 11], [7, 11], [7, 11],
-        [9, 15], [9, 15], [9, 15], [9, 15],           // 000011000xxx
-        [9, 15], [9, 15], [9, 15], [9, 15],
-        [12, 128],                        // 000011001000
-        [12, 192],                        // 000011001001
-        [12, 26],                     // 000011001010
-        [12, 27],                     // 000011001011
-        [12, 28],                     // 000011001100
-        [12, 29],                     // 000011001101
-        [11, 19], [11, 19],                   // 00001100111x
-        [11, 20], [11, 20],                   // 00001101000x
-        [12, 34],                     // 000011010010
-        [12, 35],                     // 000011010011
-        [12, 36],                     // 000011010100
-        [12, 37],                     // 000011010101
-        [12, 38],                     // 000011010110
-        [12, 39],                     // 000011010111
-        [11, 21], [11, 21],                   // 00001101100x
-        [12, 42],                     // 000011011010
-        [12, 43],                     // 000011011011
-        [10, 0], [10, 0], [10, 0], [10, 0],           // 0000110111xx
-        [7, 12], [7, 12], [7, 12], [7, 12],           // 0000111xxxxx
-        [7, 12], [7, 12], [7, 12], [7, 12],
-        [7, 12], [7, 12], [7, 12], [7, 12],
-        [7, 12], [7, 12], [7, 12], [7, 12],
-        [7, 12], [7, 12], [7, 12], [7, 12],
-        [7, 12], [7, 12], [7, 12], [7, 12],
-        [7, 12], [7, 12], [7, 12], [7, 12],
-        [7, 12], [7, 12], [7, 12], [7, 12]    
-    ];
-
-    var blackTable3 = [
-        [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 0000xx
-        [6, 9],                       // 000100
-        [6, 8],                       // 000101
-        [5, 7], [5, 7],                   // 00011x
-        [4, 6], [4, 6], [4, 6], [4, 6],           // 0010xx
-        [4, 5], [4, 5], [4, 5], [4, 5],           // 0011xx
-        [3, 1], [3, 1], [3, 1], [3, 1],           // 010xxx
-        [3, 1], [3, 1], [3, 1], [3, 1],
-        [3, 4], [3, 4], [3, 4], [3, 4],           // 011xxx
-        [3, 4], [3, 4], [3, 4], [3, 4],
-        [2, 3], [2, 3], [2, 3], [2, 3],           // 10xxxx
-        [2, 3], [2, 3], [2, 3], [2, 3],
-        [2, 3], [2, 3], [2, 3], [2, 3],
-        [2, 3], [2, 3], [2, 3], [2, 3],
-        [2, 2], [2, 2], [2, 2], [2, 2],           // 11xxxx
-        [2, 2], [2, 2], [2, 2], [2, 2],
-        [2, 2], [2, 2], [2, 2], [2, 2],
-        [2, 2], [2, 2], [2, 2], [2, 2]
-    ];
-
-    function constructor(str, params) {
-        this.str = str;
-        this.dict = str.dict;
-
-        params = params || new Dict();
-
-        this.encoding = params.get("K") || 0;
-        this.eoline = params.get("EndOfLine") || false;
-        this.byteAlign = params.get("EncodedByteAlign") || false;
-        this.columns = params.get("Columns") || 1728;
-        this.rows = params.get("Rows") || 0;
-        var eoblock = params.get("EndOfBlock");
-        if (eoblock == null)
-            eoblock = true;
-        this.eoblock = eoblock;
-        this.black = params.get("BlackIs1") || false;
-
-        this.codingLine = new Uint32Array(this.columns + 1);
-        this.refLine = new Uint32Array(this.columns + 2);
-        
-        this.codingLine[0] = this.columns;
-        this.codingPos = 0;
+  ];
+
+  var whiteTable1 = [
+    [-1, -1],                 // 00000
+    [12, ccittEOL],               // 00001
+    [-1, -1], [-1, -1],               // 0001x
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 001xx
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 010xx
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 011xx
+    [11, 1792], [11, 1792],           // 1000x
+    [12, 1984],                   // 10010
+    [12, 2048],                   // 10011
+    [12, 2112],                   // 10100
+    [12, 2176],                   // 10101
+    [12, 2240],                   // 10110
+    [12, 2304],                   // 10111
+    [11, 1856], [11, 1856],           // 1100x
+    [11, 1920], [11, 1920],           // 1101x
+    [12, 2368],                   // 11100
+    [12, 2432],                   // 11101
+    [12, 2496],                   // 11110
+    [12, 2560]                    // 11111
+  ];
+
+  var whiteTable2 = [
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 0000000xx
+    [8, 29], [8, 29],             // 00000010x
+    [8, 30], [8, 30],             // 00000011x
+    [8, 45], [8, 45],             // 00000100x
+    [8, 46], [8, 46],             // 00000101x
+    [7, 22], [7, 22], [7, 22], [7, 22],       // 0000011xx
+    [7, 23], [7, 23], [7, 23], [7, 23],       // 0000100xx
+    [8, 47], [8, 47],             // 00001010x
+    [8, 48], [8, 48],             // 00001011x
+    [6, 13], [6, 13], [6, 13], [6, 13],       // 000011xxx
+    [6, 13], [6, 13], [6, 13], [6, 13],
+    [7, 20], [7, 20], [7, 20], [7, 20],       // 0001000xx
+    [8, 33], [8, 33],             // 00010010x
+    [8, 34], [8, 34],             // 00010011x
+    [8, 35], [8, 35],             // 00010100x
+    [8, 36], [8, 36],             // 00010101x
+    [8, 37], [8, 37],             // 00010110x
+    [8, 38], [8, 38],             // 00010111x
+    [7, 19], [7, 19], [7, 19], [7, 19],       // 0001100xx
+    [8, 31], [8, 31],             // 00011010x
+    [8, 32], [8, 32],             // 00011011x
+    [6, 1], [6, 1], [6, 1], [6, 1],       // 000111xxx
+    [6, 1], [6, 1], [6, 1], [6, 1],
+    [6, 12], [6, 12], [6, 12], [6, 12],       // 001000xxx
+    [6, 12], [6, 12], [6, 12], [6, 12],
+    [8, 53], [8, 53],             // 00100100x
+    [8, 54], [8, 54],             // 00100101x
+    [7, 26], [7, 26], [7, 26], [7, 26],       // 0010011xx
+    [8, 39], [8, 39],             // 00101000x
+    [8, 40], [8, 40],             // 00101001x
+    [8, 41], [8, 41],             // 00101010x
+    [8, 42], [8, 42],             // 00101011x
+    [8, 43], [8, 43],             // 00101100x
+    [8, 44], [8, 44],             // 00101101x
+    [7, 21], [7, 21], [7, 21], [7, 21],       // 0010111xx
+    [7, 28], [7, 28], [7, 28], [7, 28],       // 0011000xx
+    [8, 61], [8, 61],             // 00110010x
+    [8, 62], [8, 62],             // 00110011x
+    [8, 63], [8, 63],             // 00110100x
+    [8, 0], [8, 0],               // 00110101x
+    [8, 320], [8, 320],               // 00110110x
+    [8, 384], [8, 384],               // 00110111x
+    [5, 10], [5, 10], [5, 10], [5, 10],       // 00111xxxx
+    [5, 10], [5, 10], [5, 10], [5, 10],
+    [5, 10], [5, 10], [5, 10], [5, 10],
+    [5, 10], [5, 10], [5, 10], [5, 10],
+    [5, 11], [5, 11], [5, 11], [5, 11],       // 01000xxxx
+    [5, 11], [5, 11], [5, 11], [5, 11],
+    [5, 11], [5, 11], [5, 11], [5, 11],
+    [5, 11], [5, 11], [5, 11], [5, 11],
+    [7, 27], [7, 27], [7, 27], [7, 27],       // 0100100xx
+    [8, 59], [8, 59],             // 01001010x
+    [8, 60], [8, 60],             // 01001011x
+    [9, 1472],                    // 010011000
+    [9, 1536],                    // 010011001
+    [9, 1600],                    // 010011010
+    [9, 1728],                    // 010011011
+    [7, 18], [7, 18], [7, 18], [7, 18],       // 0100111xx
+    [7, 24], [7, 24], [7, 24], [7, 24],       // 0101000xx
+    [8, 49], [8, 49],             // 01010010x
+    [8, 50], [8, 50],             // 01010011x
+    [8, 51], [8, 51],             // 01010100x
+    [8, 52], [8, 52],             // 01010101x
+    [7, 25], [7, 25], [7, 25], [7, 25],       // 0101011xx
+    [8, 55], [8, 55],             // 01011000x
+    [8, 56], [8, 56],             // 01011001x
+    [8, 57], [8, 57],             // 01011010x
+    [8, 58], [8, 58],             // 01011011x
+    [6, 192], [6, 192], [6, 192], [6, 192],   // 010111xxx
+    [6, 192], [6, 192], [6, 192], [6, 192],
+    [6, 1664], [6, 1664], [6, 1664], [6, 1664],   // 011000xxx
+    [6, 1664], [6, 1664], [6, 1664], [6, 1664],
+    [8, 448], [8, 448],               // 01100100x
+    [8, 512], [8, 512],               // 01100101x
+    [9, 704],                 // 011001100
+    [9, 768],                 // 011001101
+    [8, 640], [8, 640],               // 01100111x
+    [8, 576], [8, 576],               // 01101000x
+    [9, 832],                 // 011010010
+    [9, 896],                 // 011010011
+    [9, 960],                 // 011010100
+    [9, 1024],                    // 011010101
+    [9, 1088],                    // 011010110
+    [9, 1152],                    // 011010111
+    [9, 1216],                    // 011011000
+    [9, 1280],                    // 011011001
+    [9, 1344],                    // 011011010
+    [9, 1408],                    // 011011011
+    [7, 256], [7, 256], [7, 256], [7, 256],   // 0110111xx
+    [4, 2], [4, 2], [4, 2], [4, 2],       // 0111xxxxx
+    [4, 2], [4, 2], [4, 2], [4, 2],
+    [4, 2], [4, 2], [4, 2], [4, 2],
+    [4, 2], [4, 2], [4, 2], [4, 2],
+    [4, 2], [4, 2], [4, 2], [4, 2],
+    [4, 2], [4, 2], [4, 2], [4, 2],
+    [4, 2], [4, 2], [4, 2], [4, 2],
+    [4, 2], [4, 2], [4, 2], [4, 2],
+    [4, 3], [4, 3], [4, 3], [4, 3],       // 1000xxxxx
+    [4, 3], [4, 3], [4, 3], [4, 3],
+    [4, 3], [4, 3], [4, 3], [4, 3],
+    [4, 3], [4, 3], [4, 3], [4, 3],
+    [4, 3], [4, 3], [4, 3], [4, 3],
+    [4, 3], [4, 3], [4, 3], [4, 3],
+    [4, 3], [4, 3], [4, 3], [4, 3],
+    [4, 3], [4, 3], [4, 3], [4, 3],
+    [5, 128], [5, 128], [5, 128], [5, 128],   // 10010xxxx
+    [5, 128], [5, 128], [5, 128], [5, 128],
+    [5, 128], [5, 128], [5, 128], [5, 128],
+    [5, 128], [5, 128], [5, 128], [5, 128],
+    [5, 8], [5, 8], [5, 8], [5, 8],       // 10011xxxx
+    [5, 8], [5, 8], [5, 8], [5, 8],
+    [5, 8], [5, 8], [5, 8], [5, 8],
+    [5, 8], [5, 8], [5, 8], [5, 8],
+    [5, 9], [5, 9], [5, 9], [5, 9],       // 10100xxxx
+    [5, 9], [5, 9], [5, 9], [5, 9],
+    [5, 9], [5, 9], [5, 9], [5, 9],
+    [5, 9], [5, 9], [5, 9], [5, 9],
+    [6, 16], [6, 16], [6, 16], [6, 16],       // 101010xxx
+    [6, 16], [6, 16], [6, 16], [6, 16],
+    [6, 17], [6, 17], [6, 17], [6, 17],       // 101011xxx
+    [6, 17], [6, 17], [6, 17], [6, 17],
+    [4, 4], [4, 4], [4, 4], [4, 4],       // 1011xxxxx
+    [4, 4], [4, 4], [4, 4], [4, 4],
+    [4, 4], [4, 4], [4, 4], [4, 4],
+    [4, 4], [4, 4], [4, 4], [4, 4],
+    [4, 4], [4, 4], [4, 4], [4, 4],
+    [4, 4], [4, 4], [4, 4], [4, 4],
+    [4, 4], [4, 4], [4, 4], [4, 4],
+    [4, 4], [4, 4], [4, 4], [4, 4],
+    [4, 5], [4, 5], [4, 5], [4, 5],       // 1100xxxxx
+    [4, 5], [4, 5], [4, 5], [4, 5],
+    [4, 5], [4, 5], [4, 5], [4, 5],
+    [4, 5], [4, 5], [4, 5], [4, 5],
+    [4, 5], [4, 5], [4, 5], [4, 5],
+    [4, 5], [4, 5], [4, 5], [4, 5],
+    [4, 5], [4, 5], [4, 5], [4, 5],
+    [4, 5], [4, 5], [4, 5], [4, 5],
+    [6, 14], [6, 14], [6, 14], [6, 14],       // 110100xxx
+    [6, 14], [6, 14], [6, 14], [6, 14],
+    [6, 15], [6, 15], [6, 15], [6, 15],       // 110101xxx
+    [6, 15], [6, 15], [6, 15], [6, 15],
+    [5, 64], [5, 64], [5, 64], [5, 64],       // 11011xxxx
+    [5, 64], [5, 64], [5, 64], [5, 64],
+    [5, 64], [5, 64], [5, 64], [5, 64],
+    [5, 64], [5, 64], [5, 64], [5, 64],
+    [4, 6], [4, 6], [4, 6], [4, 6],       // 1110xxxxx
+    [4, 6], [4, 6], [4, 6], [4, 6],
+    [4, 6], [4, 6], [4, 6], [4, 6],
+    [4, 6], [4, 6], [4, 6], [4, 6],
+    [4, 6], [4, 6], [4, 6], [4, 6],
+    [4, 6], [4, 6], [4, 6], [4, 6],
+    [4, 6], [4, 6], [4, 6], [4, 6],
+    [4, 6], [4, 6], [4, 6], [4, 6],
+    [4, 7], [4, 7], [4, 7], [4, 7],       // 1111xxxxx
+    [4, 7], [4, 7], [4, 7], [4, 7],
+    [4, 7], [4, 7], [4, 7], [4, 7],
+    [4, 7], [4, 7], [4, 7], [4, 7],
+    [4, 7], [4, 7], [4, 7], [4, 7],
+    [4, 7], [4, 7], [4, 7], [4, 7],
+    [4, 7], [4, 7], [4, 7], [4, 7],
+    [4, 7], [4, 7], [4, 7], [4, 7]
+  ];
+
+  var blackTable1 = [
+    [-1, -1], [-1, -1],                   // 000000000000x
+    [12, ccittEOL], [12, ccittEOL],           // 000000000001x
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000001xx
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000010xx
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000011xx
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000100xx
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000101xx
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000110xx
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000111xx
+    [11, 1792], [11, 1792], [11, 1792], [11, 1792],   // 00000001000xx
+    [12, 1984], [12, 1984],               // 000000010010x
+    [12, 2048], [12, 2048],               // 000000010011x
+    [12, 2112], [12, 2112],               // 000000010100x
+    [12, 2176], [12, 2176],               // 000000010101x
+    [12, 2240], [12, 2240],               // 000000010110x
+    [12, 2304], [12, 2304],               // 000000010111x
+    [11, 1856], [11, 1856], [11, 1856], [11, 1856],   // 00000001100xx
+    [11, 1920], [11, 1920], [11, 1920], [11, 1920],   // 00000001101xx
+    [12, 2368], [12, 2368],               // 000000011100x
+    [12, 2432], [12, 2432],               // 000000011101x
+    [12, 2496], [12, 2496],               // 000000011110x
+    [12, 2560], [12, 2560],               // 000000011111x
+    [10, 18], [10, 18], [10, 18], [10, 18],       // 0000001000xxx
+    [10, 18], [10, 18], [10, 18], [10, 18],
+    [12, 52], [12, 52],                   // 000000100100x
+    [13, 640],                        // 0000001001010
+    [13, 704],                        // 0000001001011
+    [13, 768],                        // 0000001001100
+    [13, 832],                        // 0000001001101
+    [12, 55], [12, 55],                   // 000000100111x
+    [12, 56], [12, 56],                   // 000000101000x
+    [13, 1280],                       // 0000001010010
+    [13, 1344],                       // 0000001010011
+    [13, 1408],                       // 0000001010100
+    [13, 1472],                       // 0000001010101
+    [12, 59], [12, 59],                   // 000000101011x
+    [12, 60], [12, 60],                   // 000000101100x
+    [13, 1536],                       // 0000001011010
+    [13, 1600],                       // 0000001011011
+    [11, 24], [11, 24], [11, 24], [11, 24],       // 00000010111xx
+    [11, 25], [11, 25], [11, 25], [11, 25],       // 00000011000xx
+    [13, 1664],                       // 0000001100100
+    [13, 1728],                       // 0000001100101
+    [12, 320], [12, 320],                 // 000000110011x
+    [12, 384], [12, 384],                 // 000000110100x
+    [12, 448], [12, 448],                 // 000000110101x
+    [13, 512],                        // 0000001101100
+    [13, 576],                        // 0000001101101
+    [12, 53], [12, 53],                   // 000000110111x
+    [12, 54], [12, 54],                   // 000000111000x
+    [13, 896],                        // 0000001110010
+    [13, 960],                        // 0000001110011
+    [13, 1024],                       // 0000001110100
+    [13, 1088],                       // 0000001110101
+    [13, 1152],                       // 0000001110110
+    [13, 1216],                       // 0000001110111
+    [10, 64], [10, 64], [10, 64], [10, 64],       // 0000001111xxx
+    [10, 64], [10, 64], [10, 64], [10, 64]
+  ];
+
+  var blackTable2 = [
+    [8, 13], [8, 13], [8, 13], [8, 13],           // 00000100xxxx
+    [8, 13], [8, 13], [8, 13], [8, 13],
+    [8, 13], [8, 13], [8, 13], [8, 13],
+    [8, 13], [8, 13], [8, 13], [8, 13],
+    [11, 23], [11, 23],                   // 00000101000x
+    [12, 50],                     // 000001010010
+    [12, 51],                     // 000001010011
+    [12, 44],                     // 000001010100
+    [12, 45],                     // 000001010101
+    [12, 46],                     // 000001010110
+    [12, 47],                     // 000001010111
+    [12, 57],                     // 000001011000
+    [12, 58],                     // 000001011001
+    [12, 61],                     // 000001011010
+    [12, 256],                        // 000001011011
+    [10, 16], [10, 16], [10, 16], [10, 16],       // 0000010111xx
+    [10, 17], [10, 17], [10, 17], [10, 17],       // 0000011000xx
+    [12, 48],                     // 000001100100
+    [12, 49],                     // 000001100101
+    [12, 62],                     // 000001100110
+    [12, 63],                     // 000001100111
+    [12, 30],                     // 000001101000
+    [12, 31],                     // 000001101001
+    [12, 32],                     // 000001101010
+    [12, 33],                     // 000001101011
+    [12, 40],                     // 000001101100
+    [12, 41],                     // 000001101101
+    [11, 22], [11, 22],                   // 00000110111x
+    [8, 14], [8, 14], [8, 14], [8, 14],           // 00000111xxxx
+    [8, 14], [8, 14], [8, 14], [8, 14],
+    [8, 14], [8, 14], [8, 14], [8, 14],
+    [8, 14], [8, 14], [8, 14], [8, 14],
+    [7, 10], [7, 10], [7, 10], [7, 10],           // 0000100xxxxx
+    [7, 10], [7, 10], [7, 10], [7, 10],
+    [7, 10], [7, 10], [7, 10], [7, 10],
+    [7, 10], [7, 10], [7, 10], [7, 10],
+    [7, 10], [7, 10], [7, 10], [7, 10],
+    [7, 10], [7, 10], [7, 10], [7, 10],
+    [7, 10], [7, 10], [7, 10], [7, 10],
+    [7, 10], [7, 10], [7, 10], [7, 10],
+    [7, 11], [7, 11], [7, 11], [7, 11],           // 0000101xxxxx
+    [7, 11], [7, 11], [7, 11], [7, 11],
+    [7, 11], [7, 11], [7, 11], [7, 11],
+    [7, 11], [7, 11], [7, 11], [7, 11],
+    [7, 11], [7, 11], [7, 11], [7, 11],
+    [7, 11], [7, 11], [7, 11], [7, 11],
+    [7, 11], [7, 11], [7, 11], [7, 11],
+    [7, 11], [7, 11], [7, 11], [7, 11],
+    [9, 15], [9, 15], [9, 15], [9, 15],           // 000011000xxx
+    [9, 15], [9, 15], [9, 15], [9, 15],
+    [12, 128],                        // 000011001000
+    [12, 192],                        // 000011001001
+    [12, 26],                     // 000011001010
+    [12, 27],                     // 000011001011
+    [12, 28],                     // 000011001100
+    [12, 29],                     // 000011001101
+    [11, 19], [11, 19],                   // 00001100111x
+    [11, 20], [11, 20],                   // 00001101000x
+    [12, 34],                     // 000011010010
+    [12, 35],                     // 000011010011
+    [12, 36],                     // 000011010100
+    [12, 37],                     // 000011010101
+    [12, 38],                     // 000011010110
+    [12, 39],                     // 000011010111
+    [11, 21], [11, 21],                   // 00001101100x
+    [12, 42],                     // 000011011010
+    [12, 43],                     // 000011011011
+    [10, 0], [10, 0], [10, 0], [10, 0],           // 0000110111xx
+    [7, 12], [7, 12], [7, 12], [7, 12],           // 0000111xxxxx
+    [7, 12], [7, 12], [7, 12], [7, 12],
+    [7, 12], [7, 12], [7, 12], [7, 12],
+    [7, 12], [7, 12], [7, 12], [7, 12],
+    [7, 12], [7, 12], [7, 12], [7, 12],
+    [7, 12], [7, 12], [7, 12], [7, 12],
+    [7, 12], [7, 12], [7, 12], [7, 12],
+    [7, 12], [7, 12], [7, 12], [7, 12]
+  ];
+
+  var blackTable3 = [
+    [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 0000xx
+    [6, 9],                       // 000100
+    [6, 8],                       // 000101
+    [5, 7], [5, 7],                   // 00011x
+    [4, 6], [4, 6], [4, 6], [4, 6],           // 0010xx
+    [4, 5], [4, 5], [4, 5], [4, 5],           // 0011xx
+    [3, 1], [3, 1], [3, 1], [3, 1],           // 010xxx
+    [3, 1], [3, 1], [3, 1], [3, 1],
+    [3, 4], [3, 4], [3, 4], [3, 4],           // 011xxx
+    [3, 4], [3, 4], [3, 4], [3, 4],
+    [2, 3], [2, 3], [2, 3], [2, 3],           // 10xxxx
+    [2, 3], [2, 3], [2, 3], [2, 3],
+    [2, 3], [2, 3], [2, 3], [2, 3],
+    [2, 3], [2, 3], [2, 3], [2, 3],
+    [2, 2], [2, 2], [2, 2], [2, 2],           // 11xxxx
+    [2, 2], [2, 2], [2, 2], [2, 2],
+    [2, 2], [2, 2], [2, 2], [2, 2],
+    [2, 2], [2, 2], [2, 2], [2, 2]
+  ];
+
+  function constructor(str, params) {
+    this.str = str;
+    this.dict = str.dict;
+
+    params = params || new Dict();
+
+    this.encoding = params.get('K') || 0;
+    this.eoline = params.get('EndOfLine') || false;
+    this.byteAlign = params.get('EncodedByteAlign') || false;
+    this.columns = params.get('Columns') || 1728;
+    this.rows = params.get('Rows') || 0;
+    var eoblock = params.get('EndOfBlock');
+    if (eoblock == null)
+      eoblock = true;
+    this.eoblock = eoblock;
+    this.black = params.get('BlackIs1') || false;
+
+    this.codingLine = new Uint32Array(this.columns + 1);
+    this.refLine = new Uint32Array(this.columns + 2);
+
+    this.codingLine[0] = this.columns;
+    this.codingPos = 0;
+
+    this.row = 0;
+    this.nextLine2D = this.encoding < 0;
+    this.inputBits = 0;
+    this.inputBuf;
+    this.outputBits = 0;
+    this.buf = EOF;
+
+    var code1;
+    while ((code1 = this.lookBits(12)) == 0) {
+      this.eatBits(1);
+    }
+    if (code1 == 1) {
+      this.eatBits(12);
+    }
+    if (this.encoding > 0) {
+      this.nextLine2D = !this.lookBits(1);
+      this.eatBits(1);
+    }
 
-        this.row = 0;
-        this.nextLine2D = this.encoding < 0;
-        this.inputBits = 0;
-        this.inputBuf;
-        this.outputBits = 0;
-        this.buf = EOF;
+    DecodeStream.call(this);
+  }
 
-        var code1;
-        while ((code1 = this.lookBits(12)) == 0) {
-            this.eatBits(1);
-        }
-        if (code1 == 1) {
-            this.eatBits(12);
-        }
-        if (this.encoding > 0) {
-            this.nextLine2D = !this.lookBits(1);
-            this.eatBits(1);
-        }
-        
-        DecodeStream.call(this);
+  constructor.prototype = Object.create(DecodeStream.prototype);
+
+  constructor.prototype.readBlock = function() {
+    while (!this.eof) {
+      var c = this.lookChar();
+      this.buf = EOF;
+      this.ensureBuffer(this.bufferLength + 1);
+      this.buffer[this.bufferLength++] = c;
     }
+  };
 
-    constructor.prototype = Object.create(DecodeStream.prototype);
-    constructor.prototype.readBlock = function() {
-        while (!this.eof) {
-            var c = this.lookChar();
-            this.buf = EOF;
-            this.ensureBuffer(this.bufferLength + 1);
-            this.buffer[this.bufferLength++] = c;
-        }
-    };
-    constructor.prototype.addPixels = function(a1, blackPixels) {
-        var codingLine = this.codingLine;
-        var codingPos = this.codingPos;
-
-        if (a1 > codingLine[codingPos]) {
-            if (a1 > this.columns) {
-                warn("row is wrong length");
-                this.err = true;
-                a1 = this.columns;
-            }
-            if ((codingPos & 1) ^ blackPixels) {
-                ++codingPos;
-            }
+  constructor.prototype.addPixels = function(a1, blackPixels) {
+    var codingLine = this.codingLine;
+    var codingPos = this.codingPos;
 
-            codingLine[codingPos] = a1;
-        }
-        this.codingPos = codingPos;
-    };
-    constructor.prototype.addPixelsNeg = function(a1, blackPixels) {
-        var codingLine = this.codingLine;
-        var codingPos = this.codingPos;
-
-        if (a1 > codingLine[codingPos]) {
-            if (a1 > this.columns) {
-                warn("row is wrong length");
-                this.err = true;
-                a1 = this.columns;
-            }
-            if ((codingPos & 1) ^ blackPixels)
-                ++codingPos;
-
-            codingLine[codingPos] = a1;
-        } else if (a1 < codingLine[codingPos]) {
-            if (a1 < 0) {
-                warn("invalid code");
-                this.err = true;
-                a1 = 0;
-            }
-            while (codingPos > 0 && a1 < codingLine[codingPos - 1])
-                --codingPos;
-            codingLine[codingPos] = a1;
-        }
+    if (a1 > codingLine[codingPos]) {
+      if (a1 > this.columns) {
+        warn('row is wrong length');
+        this.err = true;
+        a1 = this.columns;
+      }
+      if ((codingPos & 1) ^ blackPixels) {
+        ++codingPos;
+      }
 
-        this.codingPos = codingPos;
-    };
-    constructor.prototype.lookChar = function() {
-        var refLine = this.refLine;
-        var codingLine = this.codingLine;
-        var columns = this.columns;
-
-        var refPos, blackPixels, bits;
-
-        if (this.buf != EOF)
-            return buf;
-
-        if (this.outputBits == 0) {
-            if (this.eof)
-                return;
-
-            this.err = false;
-
-            if (this.nextLine2D) {
-                for (var i = 0; codingLine[i] < columns; ++i)
-                    refLine[i] = codingLine[i];
-
-                refLine[i++] = columns;
-                refLine[i] = columns;
-                codingLine[0] = 0;
-                this.codingPos = 0;
-                refPos = 0;
-                blackPixels = 0;
-
-                while (codingLine[this.codingPos] < columns) {
-                    var code1 = this.getTwoDimCode();
-                    switch (code1) {
-                    case twoDimPass:
-                        this.addPixels(refLine[refPos + 1], blackPixels);
-                        if (refLine[refPos + 1] < columns)
-                            refPos += 2;
-                        break;
-                    case twoDimHoriz:
-                        var code1 = 0, code2 = 0;
-                        if (blackPixels) {
-                            var code3;
-                            do {
-                                code1 += (code3 = this.getBlackCode());
-                            } while (code3 >= 64);
-                            do {
-                                code2 += (code3 = this.getWhiteCode());
-                            } while (code3 >= 64);
-                        } else {
-                            var code3;
-                            do {
-                                code1 += (code3 = this.getWhiteCode());
-                            } while (code3 >= 64);
-                            do {
-                                code2 += (code3 = this.getBlackCode());
-                            } while (code3 >= 64);
-                        }
-                        this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
-                        if (codingLine[this.codingPos] < columns) {
-                            this.addPixels(codingLine[this.codingPos] + code2,
-                                    blackPixels ^ 1);
-                        }
-                        while (refLine[refPos] <= codingLine[this.codingPos] 
-                                && refLine[refPos] < columns) {
-                            refPos += 2;
-                        }    
-                        break;
-                    case twoDimVertR3:
-                        this.addPixels(refLine[refPos] + 3, blackPixels);
-                        blackPixels ^= 1;
-                        if (codingLine[this.codingPos] < columns) {
-                            ++refPos;
-                            while (refLine[refPos] <= codingLine[this.codingPos] &&
-                                    refLine[refPos] < columns)
-                                refPos += 2;
-                        }
-                        break;
-                    case twoDimVertR2:
-                        this.addPixels(refLine[refPos] + 2, blackPixels);
-                        blackPixels ^= 1;
-                        if (codingLine[this.codingPos] < columns) {
-                            ++refPos;
-                            while (refLine[refPos] <= codingLine[this.codingPos] &&
-                                    refLine[refPos] < columns) {
-                                refPos += 2;
-                            }
-                        }
-                        break;
-                    case twoDimVertR1:
-                        this.addPixels(refLine[refPos] + 1, blackPixels);
-                        blackPixels ^= 1;
-                        if (codingLine[this.codingPos] < columns) {
-                            ++refPos;
-                            while (refLine[refPos] <= codingLine[this.codingPos] &&
-                                    refLine[refPos] < columns)
-                                refPos += 2;
-                        }
-                        break;
-                    case twoDimVert0:
-                        this.addPixels(refLine[refPos], blackPixels);
-                        blackPixels ^= 1;
-                        if (codingLine[this.codingPos] < columns) {
-                            ++refPos;
-                            while (refLine[refPos] <= codingLine[this.codingPos] &&
-                                    refLine[refPos] < columns)
-                                refPos += 2;
-                        }
-                        break;
-                    case twoDimVertL3:
-                        this.addPixelsNeg(refLine[refPos] - 3, blackPixels);
-                        blackPixels ^= 1;
-                        if (codingLine[this.codingPos] < columns) {
-                            if (refPos > 0)
-                                --refPos;
-                            else
-                                ++refPos;
-                            while (refLine[refPos] <= codingLine[this.codingPos] &&
-                                    refLine[refPos] < columns)
-                                refPos += 2;
-                        }
-                        break;
-                    case twoDimVertL2:
-                        this.addPixelsNeg(refLine[refPos] - 2, blackPixels);
-                        blackPixels ^= 1;
-                        if (codingLine[this.codingPos] < columns) {
-                            if (refPos > 0)
-                                --refPos;
-                            else
-                                ++refPos;
-                            while (refLine[refPos] <= codingLine[this.codingPos] &&
-                                    refLine[refPos] < columns)
-                                refPos += 2;
-                        }
-                        break;
-                    case twoDimVertL1:
-                        this.addPixelsNeg(refLine[refPos] - 1, blackPixels);
-                        blackPixels ^= 1;
-                        if (codingLine[this.codingPos] < columns) {
-                            if (refPos > 0)
-                                --refPos;
-                            else
-                                ++refPos;
-                            
-                            while (refLine[refPos] <= codingLine[this.codingPos] &&
-                                    refLine[refPos] < columns)
-                                refPos += 2;
-                        }
-                        break;
-                    case EOF:
-                        this.addPixels(columns, 0);
-                        this.eof = true;
-                        break;
-                    default:
-                        warn("bad 2d code");
-                        this.addPixels(columns, 0);
-                        this.err = true;
-                        break;
-                    }
-                }
-            } else {
-                codingLine[0] = 0;
-                this.codingPos = 0;
-                blackPixels = 0;
-                while(codingLine[this.codingPos] < columns) {
-                    code1 = 0;
-                    if (blackPixels) {
-                        do {
-                            code1 += (code3 = this.getBlackCode());
-                        } while (code3 >= 64);
-                    } else {
-                        do {
-                            code1 += (code3 = this.getWhiteCode());
-                        } while (code3 >= 64);
-                    }
-                    this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
-                    blackPixels ^= 1;
-                }
-            }
+      codingLine[codingPos] = a1;
+    }
+    this.codingPos = codingPos;
+  };
+
+  constructor.prototype.addPixelsNeg = function(a1, blackPixels) {
+    var codingLine = this.codingLine;
+    var codingPos = this.codingPos;
+
+    if (a1 > codingLine[codingPos]) {
+      if (a1 > this.columns) {
+        warn('row is wrong length');
+        this.err = true;
+        a1 = this.columns;
+      }
+      if ((codingPos & 1) ^ blackPixels)
+        ++codingPos;
+
+      codingLine[codingPos] = a1;
+    } else if (a1 < codingLine[codingPos]) {
+      if (a1 < 0) {
+        warn('invalid code');
+        this.err = true;
+        a1 = 0;
+      }
+      while (codingPos > 0 && a1 < codingLine[codingPos - 1])
+        --codingPos;
+      codingLine[codingPos] = a1;
+    }
 
-            if (this.byteAlign)
-                inputBits &= ~7;
-                    
-            var gotEOL = false;
+    this.codingPos = codingPos;
+  };
 
-            if (!this.eoblock && this.row == this.rows - 1) {
-                this.eof = true;
-            } else {
-                code1 = this.lookBits(12);
-                while (code1 == 0) {
-                    this.eatBits(1);
-                    code1 = this.lookBits(12);
-                }
-                if (code1 == 1) {
-                    this.eatBits(12);
-                    gotEOL = true;
-                } else if (code1 == EOF) {
-                    this.eof = true;
-                }
-            }
+  constructor.prototype.lookChar = function() {
+    var refLine = this.refLine;
+    var codingLine = this.codingLine;
+    var columns = this.columns;
 
-            if (!this.eof && this.encoding > 0) {
-                this.nextLine2D = !this.lookBits(1);
-                this.eatBits(1);
-            }
+    var refPos, blackPixels, bits;
 
-            if (this.eoblock && gotEOL) {
-                code1 = this.lookBits(12);
-                if (code1 == 1) {
-                    this.eatBits(12);
-                    if (this.encoding > 0) {
-                        this.lookBits(1);
-                        this.eatBits(1);
-                    }
-                    if (this.encoding >= 0) {
-                        for (var i = 0; i < 4; ++i) {
-                            code1 = this.lookBits(12);
-                            if (code1 != 1)
-                                warning("bad rtc code");
-                            this.eatBits(12);
-                            if (this.encoding > 0) {
-                                this.lookBits(1);
-                                this.eatBits(1);
-                            }
-                        }
-                    }
-                    this.eof = true;
-                }
-            } else if (this.err && this.eoline) {
-                var code1;
-                while (true) {
-                    code1 = this.lookBits(13);
-                    if (code1 == EOF) {
-                        this.eof = true;
-                        return;
-                    }
-                    if ((code1 >> 1) == 1) {
-                        break;
-                    }
-                    this.eatBits(1);
-                }
-                this.eatBits(12);
-                if (this.encoding > 0) {
-                    this.eatBits(1);
-                    this.nextLine2D = !(code1 & 1);
-                }
-            }
+    if (this.buf != EOF)
+      return buf;
 
-            if (codingLine[0] > 0)
-                this.outputBits = codingLine[this.codingPos = 0];
-            else
-                this.outputBits = codingLine[this.codingPos = 1];
-            this.row++;
-        }
+    if (this.outputBits == 0) {
+      if (this.eof)
+        return;
 
-        if (this.outputBits >= 8) {
-            this.buf = (this.codingPos & 1) ? 0 : 0xFF;
-            this.outputBits -= 8;
-            if (this.outputBits == 0 && codingLine[this.codingPos] < columns) {
-                this.codingPos++;
-                this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
+      this.err = false;
+
+      if (this.nextLine2D) {
+        for (var i = 0; codingLine[i] < columns; ++i)
+          refLine[i] = codingLine[i];
+
+        refLine[i++] = columns;
+        refLine[i] = columns;
+        codingLine[0] = 0;
+        this.codingPos = 0;
+        refPos = 0;
+        blackPixels = 0;
+
+        while (codingLine[this.codingPos] < columns) {
+          var code1 = this.getTwoDimCode();
+          switch (code1) {
+          case twoDimPass:
+            this.addPixels(refLine[refPos + 1], blackPixels);
+            if (refLine[refPos + 1] < columns)
+              refPos += 2;
+            break;
+          case twoDimHoriz:
+            var code1 = 0, code2 = 0;
+            if (blackPixels) {
+              var code3;
+              do {
+                code1 += (code3 = this.getBlackCode());
+              } while (code3 >= 64);
+              do {
+                code2 += (code3 = this.getWhiteCode());
+              } while (code3 >= 64);
+            } else {
+              var code3;
+              do {
+                code1 += (code3 = this.getWhiteCode());
+              } while (code3 >= 64);
+              do {
+                code2 += (code3 = this.getBlackCode());
+              } while (code3 >= 64);
             }
-        } else {
-            var bits = 8;
-            this.buf = 0;
-            do {
-                if (this.outputBits > bits) {
-                    this.buf <<= bits;
-                    if (!(this.codingPos & 1)) {
-                        this.buf |= 0xFF >> (8 - bits);
-                    }
-                    this.outputBits -= bits;
-                    bits = 0;
-                } else {
-                    this.buf <<= this.outputBits;
-                    if (!(this.codingPos & 1)) {
-                        this.buf |= 0xFF >> (8 - this.outputBits);
-                    }
-                    bits -= this.outputBits;
-                    this.outputBits = 0;
-                    if (codingLine[this.codingPos] < columns) {
-                        this.codingPos++;
-                        this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
-                    } else if (bits > 0) {
-                        this.buf <<= bits;
-                        bits = 0;
-                    }
-                }
-            } while (bits);
-        }
-        if (this.black) {
-            this.buf ^= 0xFF;
-        }
-        return this.buf;
-    };
-    constructor.prototype.getTwoDimCode = function() {
-        var code = 0;
-        var p;
-        if (this.eoblock) {
-            code = this.lookBits(7);
-            p = twoDimTable[code];
-            if (p[0] > 0) {
-                this.eatBits(p[0]);
-                return p[1];
+            this.addPixels(codingLine[this.codingPos] +
+                           code1, blackPixels);
+            if (codingLine[this.codingPos] < columns) {
+              this.addPixels(codingLine[this.codingPos] + code2,
+                             blackPixels ^ 1);
             }
-        } else {
-            for (var n = 1; n <= 7; ++n) {
-                code = this.lookBits(n);
-                if (n < 7) {
-                    code <<= 7 - n;
-                }
-                p = twoDimTable[code];
-                if (p[0] == n) {
-                    this.eatBits(n);
-                    return p[1];
-                }
+            while (refLine[refPos] <= codingLine[this.codingPos] &&
+                   refLine[refPos] < columns) {
+              refPos += 2;
             }
-        }
-        warn("Bad two dim code");
-        return EOF;
-    };
-
-    constructor.prototype.getWhiteCode = function() {
-        var code = 0;
-        var p;
-        var n;
-        if (this.eoblock) {
-            code = this.lookBits(12);
-            if (code == EOF)
-                return 1;
-            
-            if ((code >> 5) == 0)
-                p = whiteTable1[code];
-            else
-                p = whiteTable2[code >> 3];
-
-            if (p[0] > 0) {
-                this.eatBits(p[0]);
-                return p[1];
+            break;
+          case twoDimVertR3:
+            this.addPixels(refLine[refPos] + 3, blackPixels);
+            blackPixels ^= 1;
+            if (codingLine[this.codingPos] < columns) {
+              ++refPos;
+              while (refLine[refPos] <= codingLine[this.codingPos] &&
+                     refLine[refPos] < columns)
+                refPos += 2;
             }
-        } else {
-            for (var n = 1; n <= 9; ++n) {
-                code = this.lookBits(n);
-                if (code == EOF)
-                    return 1;
-
-                if (n < 9)
-                    code <<= 9 - n;
-                p = whiteTable2[code];
-                if (p[0] == n) {
-                    this.eatBits(n);    
-                    return p[0];
-                }
+            break;
+          case twoDimVertR2:
+            this.addPixels(refLine[refPos] + 2, blackPixels);
+            blackPixels ^= 1;
+            if (codingLine[this.codingPos] < columns) {
+              ++refPos;
+              while (refLine[refPos] <= codingLine[this.codingPos] &&
+                     refLine[refPos] < columns) {
+                refPos += 2;
+              }
             }
-            for (var n = 11; n <= 12; ++n) {
-                code == this.lookBits(n);
-                if (code == EOF)
-                    return 1;
-                if (n < 12) 
-                    code <<= 12 - n;
-                p = whiteTable1[code];
-                if (p[0] == n) {
-                    this.eatBits(n);
-                    return p[1];
-                }
+            break;
+          case twoDimVertR1:
+            this.addPixels(refLine[refPos] + 1, blackPixels);
+            blackPixels ^= 1;
+            if (codingLine[this.codingPos] < columns) {
+              ++refPos;
+              while (refLine[refPos] <= codingLine[this.codingPos] &&
+                     refLine[refPos] < columns)
+                refPos += 2;
             }
-        }
-        warn("bad white code");
-        this.eatBits(1);
-        return 1;
-    };
-    constructor.prototype.getBlackCode = function() {
-        var code, p, n;
-        if (this.eoblock) {
-            code = this.lookBits(13);
-            if (code == EOF)
-                return 1;
-            if ((code >> 7) == 0)
-                p = blackTable1[code];
-            else if ((code >> 9) == 0 && (code >> 7) != 0)
-                p = blackTable2[(code >> 1) - 64];
-            else 
-                p = blackTable3[code >> 7];
-
-            if (p[0] > 0) {
-                this.eatBits(p[0]);
-                return p[1];
+            break;
+          case twoDimVert0:
+            this.addPixels(refLine[refPos], blackPixels);
+            blackPixels ^= 1;
+            if (codingLine[this.codingPos] < columns) {
+              ++refPos;
+              while (refLine[refPos] <= codingLine[this.codingPos] &&
+                     refLine[refPos] < columns)
+                refPos += 2;
             }
-        } else {
-            for (var n = 2; n <= 6; ++n) {
-                code = this.lookBits(n);
-                if (code == EOF)
-                    return 1;
-                if (n < 6)
-                    code <<= 6 - n;
-
-                p = blackTable3[code];
-                if (p[0] == n) {
-                    this.eatBits(n);
-                    return p[1];
-                }
+            break;
+          case twoDimVertL3:
+            this.addPixelsNeg(refLine[refPos] - 3, blackPixels);
+            blackPixels ^= 1;
+            if (codingLine[this.codingPos] < columns) {
+              if (refPos > 0)
+                --refPos;
+              else
+                ++refPos;
+              while (refLine[refPos] <= codingLine[this.codingPos] &&
+                     refLine[refPos] < columns)
+                refPos += 2;
             }
-            for (var n = 7; n <= 12; ++n) {
-                code = this.lookBits(n);
-                if (code == EOF)
-                    return 1;
-                if (n < 12)
-                    code <<= 12 - n;
-                if (code >= 64) {
-                    p = blackTable2[code - 64];
-                    if (p[0] == n) {
-                        this.eatBits(n);
-                        return p[1];
-                    }
-                }
+            break;
+          case twoDimVertL2:
+            this.addPixelsNeg(refLine[refPos] - 2, blackPixels);
+            blackPixels ^= 1;
+            if (codingLine[this.codingPos] < columns) {
+              if (refPos > 0)
+                --refPos;
+              else
+                ++refPos;
+              while (refLine[refPos] <= codingLine[this.codingPos] &&
+                     refLine[refPos] < columns)
+                refPos += 2;
             }
-            for (n = 10; n <= 13; ++n) {
-                code = this.lookBits(n);
-                if (code == EOF)
-                    return 1;
-                if (n < 13)
-                    code << 13 - n;
-                p = blackTable1[code];
-                if (p[0] == n) {
-                    this.eatBits(n);
-                    return p[1];
-                }
+            break;
+          case twoDimVertL1:
+            this.addPixelsNeg(refLine[refPos] - 1, blackPixels);
+            blackPixels ^= 1;
+            if (codingLine[this.codingPos] < columns) {
+              if (refPos > 0)
+                --refPos;
+              else
+                ++refPos;
+
+              while (refLine[refPos] <= codingLine[this.codingPos] &&
+                     refLine[refPos] < columns)
+                refPos += 2;
             }
+            break;
+          case EOF:
+            this.addPixels(columns, 0);
+            this.eof = true;
+            break;
+          default:
+            warn('bad 2d code');
+            this.addPixels(columns, 0);
+            this.err = true;
+            break;
+          }
         }
-        warn("bad black code");
-        this.eatBits(1);
-        return 1;
-    };
-    constructor.prototype.lookBits = function(n) {
-        var c;
-        while (this.inputBits < n) {
-            if ((c = this.str.getByte()) == null) {
-                if (this.inputBits == 0)
-                    return EOF;
-                return (this.inputBuf << (n - this.inputBits)) 
-                    & (0xFFFF >> (16 - n));
-            }
-            this.inputBuf = (this.inputBuf << 8) + c;
-            this.inputBits += 8;
+      } else {
+        codingLine[0] = 0;
+        this.codingPos = 0;
+        blackPixels = 0;
+        while (codingLine[this.codingPos] < columns) {
+          code1 = 0;
+          if (blackPixels) {
+            do {
+              code1 += (code3 = this.getBlackCode());
+            } while (code3 >= 64);
+          } else {
+            do {
+              code1 += (code3 = this.getWhiteCode());
+            } while (code3 >= 64);
+          }
+          this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
+          blackPixels ^= 1;
         }
-        return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
-    };
-    constructor.prototype.eatBits = function(n) {
-        if ((this.inputBits -= n) < 0)
-            this.inputBits = 0;
-    }
-
-    return constructor;
-})();
-
-var Name = (function() {
-    function constructor(name) {
-        this.name = name;
-    }
+      }
 
-    constructor.prototype = {
-    };
+      if (this.byteAlign)
+        inputBits &= ~7;
 
-    return constructor;
-})();
+      var gotEOL = false;
 
-var Cmd = (function() {
-    function constructor(cmd) {
-        this.cmd = cmd;
-    }
+      if (!this.eoblock && this.row == this.rows - 1) {
+        this.eof = true;
+      } else {
+        code1 = this.lookBits(12);
+        while (code1 == 0) {
+          this.eatBits(1);
+          code1 = this.lookBits(12);
+        }
+        if (code1 == 1) {
+          this.eatBits(12);
+          gotEOL = true;
+        } else if (code1 == EOF) {
+          this.eof = true;
+        }
+      }
 
-    constructor.prototype = {
-    };
+      if (!this.eof && this.encoding > 0) {
+        this.nextLine2D = !this.lookBits(1);
+        this.eatBits(1);
+      }
 
-    return constructor;
-})();
+      if (this.eoblock && gotEOL) {
+        code1 = this.lookBits(12);
+        if (code1 == 1) {
+          this.eatBits(12);
+          if (this.encoding > 0) {
+            this.lookBits(1);
+            this.eatBits(1);
+          }
+          if (this.encoding >= 0) {
+            for (var i = 0; i < 4; ++i) {
+              code1 = this.lookBits(12);
+              if (code1 != 1)
+                warning('bad rtc code');
+              this.eatBits(12);
+              if (this.encoding > 0) {
+                this.lookBits(1);
+                this.eatBits(1);
+              }
+            }
+          }
+          this.eof = true;
+        }
+      } else if (this.err && this.eoline) {
+        var code1;
+        while (true) {
+          code1 = this.lookBits(13);
+          if (code1 == EOF) {
+            this.eof = true;
+            return;
+          }
+          if ((code1 >> 1) == 1) {
+            break;
+          }
+          this.eatBits(1);
+        }
+        this.eatBits(12);
+        if (this.encoding > 0) {
+          this.eatBits(1);
+          this.nextLine2D = !(code1 & 1);
+        }
+      }
 
-var Dict = (function() {
-    function constructor() {
-        this.map = Object.create(null);
+      if (codingLine[0] > 0)
+        this.outputBits = codingLine[this.codingPos = 0];
+      else
+        this.outputBits = codingLine[this.codingPos = 1];
+      this.row++;
     }
 
-    constructor.prototype = {
-        get: function(key) {
-            if (key in this.map)
-              return this.map[key];
-            return null;
-        },
-        get2: function(key1, key2) {
-            return this.get(key1) || this.get(key2);
-        },
-        get3: function(key1, key2, key3) {
-            return this.get(key1) || this.get(key2) || this.get(key3);
-        },
-        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]);
-        }
-    };
-    return constructor;
+    if (this.outputBits >= 8) {
+      this.buf = (this.codingPos & 1) ? 0 : 0xFF;
+      this.outputBits -= 8;
+      if (this.outputBits == 0 && codingLine[this.codingPos] < columns) {
+        this.codingPos++;
+        this.outputBits = (codingLine[this.codingPos] -
+                           codingLine[this.codingPos - 1]);
+      }
+    } else {
+      var bits = 8;
+      this.buf = 0;
+      do {
+        if (this.outputBits > bits) {
+          this.buf <<= bits;
+          if (!(this.codingPos & 1)) {
+            this.buf |= 0xFF >> (8 - bits);
+          }
+          this.outputBits -= bits;
+          bits = 0;
+        } else {
+          this.buf <<= this.outputBits;
+          if (!(this.codingPos & 1)) {
+            this.buf |= 0xFF >> (8 - this.outputBits);
+          }
+          bits -= this.outputBits;
+          this.outputBits = 0;
+          if (codingLine[this.codingPos] < columns) {
+            this.codingPos++;
+            this.outputBits = (codingLine[this.codingPos] -
+                               codingLine[this.codingPos - 1]);
+          } else if (bits > 0) {
+            this.buf <<= bits;
+            bits = 0;
+          }
+        }
+      } while (bits);
+    }
+    if (this.black) {
+      this.buf ^= 0xFF;
+    }
+    return this.buf;
+  };
+
+  constructor.prototype.getTwoDimCode = function() {
+    var code = 0;
+    var p;
+    if (this.eoblock) {
+      code = this.lookBits(7);
+      p = twoDimTable[code];
+      if (p[0] > 0) {
+        this.eatBits(p[0]);
+        return p[1];
+      }
+    } else {
+      for (var n = 1; n <= 7; ++n) {
+        code = this.lookBits(n);
+        if (n < 7) {
+          code <<= 7 - n;
+        }
+        p = twoDimTable[code];
+        if (p[0] == n) {
+          this.eatBits(n);
+          return p[1];
+        }
+      }
+    }
+    warn('Bad two dim code');
+    return EOF;
+  };
+
+  constructor.prototype.getWhiteCode = function() {
+    var code = 0;
+    var p;
+    var n;
+    if (this.eoblock) {
+      code = this.lookBits(12);
+      if (code == EOF)
+        return 1;
+
+      if ((code >> 5) == 0)
+        p = whiteTable1[code];
+      else
+        p = whiteTable2[code >> 3];
+
+      if (p[0] > 0) {
+        this.eatBits(p[0]);
+        return p[1];
+      }
+    } else {
+      for (var n = 1; n <= 9; ++n) {
+        code = this.lookBits(n);
+        if (code == EOF)
+          return 1;
+
+        if (n < 9)
+          code <<= 9 - n;
+        p = whiteTable2[code];
+        if (p[0] == n) {
+          this.eatBits(n);
+          return p[0];
+        }
+      }
+      for (var n = 11; n <= 12; ++n) {
+        code == this.lookBits(n);
+        if (code == EOF)
+          return 1;
+        if (n < 12)
+          code <<= 12 - n;
+        p = whiteTable1[code];
+        if (p[0] == n) {
+          this.eatBits(n);
+          return p[1];
+        }
+      }
+    }
+    warn('bad white code');
+    this.eatBits(1);
+    return 1;
+  };
+
+  constructor.prototype.getBlackCode = function() {
+    var code, p, n;
+    if (this.eoblock) {
+      code = this.lookBits(13);
+      if (code == EOF)
+        return 1;
+      if ((code >> 7) == 0)
+        p = blackTable1[code];
+      else if ((code >> 9) == 0 && (code >> 7) != 0)
+        p = blackTable2[(code >> 1) - 64];
+      else
+        p = blackTable3[code >> 7];
+
+      if (p[0] > 0) {
+        this.eatBits(p[0]);
+        return p[1];
+      }
+    } else {
+      for (var n = 2; n <= 6; ++n) {
+        code = this.lookBits(n);
+        if (code == EOF)
+          return 1;
+        if (n < 6)
+          code <<= 6 - n;
+
+        p = blackTable3[code];
+        if (p[0] == n) {
+          this.eatBits(n);
+          return p[1];
+        }
+      }
+      for (var n = 7; n <= 12; ++n) {
+        code = this.lookBits(n);
+        if (code == EOF)
+          return 1;
+        if (n < 12)
+          code <<= 12 - n;
+        if (code >= 64) {
+          p = blackTable2[code - 64];
+          if (p[0] == n) {
+            this.eatBits(n);
+            return p[1];
+          }
+        }
+      }
+      for (n = 10; n <= 13; ++n) {
+        code = this.lookBits(n);
+        if (code == EOF)
+          return 1;
+        if (n < 13)
+          code << 13 - n;
+        p = blackTable1[code];
+        if (p[0] == n) {
+          this.eatBits(n);
+          return p[1];
+        }
+      }
+    }
+    warn('bad black code');
+    this.eatBits(1);
+    return 1;
+  };
+
+  constructor.prototype.lookBits = function(n) {
+    var c;
+    while (this.inputBits < n) {
+      if ((c = this.str.getByte()) == null) {
+        if (this.inputBits == 0)
+          return EOF;
+        return ((this.inputBuf << (n - this.inputBits)) &
+                (0xFFFF >> (16 - n)));
+      }
+      this.inputBuf = (this.inputBuf << 8) + c;
+      this.inputBits += 8;
+    }
+    return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
+  };
+
+  constructor.prototype.eatBits = function(n) {
+    if ((this.inputBits -= n) < 0)
+      this.inputBits = 0;
+  }
+
+  return constructor;
 })();
 
-var Ref = (function() {
-    function constructor(num, gen) {
-        this.num = num;
-        this.gen = gen;
+var Name = (function() {
+  function constructor(name) {
+    this.name = name;
+  }
+
+  constructor.prototype = {
+  };
+
+  return constructor;
+})();
+
+var Cmd = (function() {
+  function constructor(cmd) {
+    this.cmd = cmd;
+  }
+
+  constructor.prototype = {
+  };
+
+  return constructor;
+})();
+
+var Dict = (function() {
+  function constructor() {
+    this.map = Object.create(null);
+  }
+
+  constructor.prototype = {
+    get: function(key) {
+      if (key in this.map)
+        return this.map[key];
+      return null;
+    },
+    get2: function(key1, key2) {
+      return this.get(key1) || this.get(key2);
+    },
+    get3: function(key1, key2, key3) {
+      return this.get(key1) || this.get(key2) || this.get(key3);
+    },
+    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]);
     }
+  };
+  return constructor;
+})();
+
+var Ref = (function() {
+  function constructor(num, gen) {
+    this.num = num;
+    this.gen = gen;
+  }
 
-    constructor.prototype = {
-    };
+  constructor.prototype = {
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 function IsBool(v) {
-    return typeof v == "boolean";
+  return typeof v == 'boolean';
 }
 
 function IsInt(v) {
-    return typeof v == "number" && ((v|0) == v);
+  return typeof v == 'number' && ((v | 0) == v);
 }
 
 function IsNum(v) {
-    return typeof v == "number";
+  return typeof v == 'number';
 }
 
 function IsString(v) {
-    return typeof v == "string";
+  return typeof v == 'string';
 }
 
 function IsNull(v) {
-    return v === null;
+  return v === null;
 }
 
 function IsName(v) {
-    return v instanceof Name;
+  return v instanceof Name;
 }
 
 function IsCmd(v, cmd) {
-    return v instanceof Cmd && (!cmd || v.cmd == cmd);
+  return v instanceof Cmd && (!cmd || v.cmd == cmd);
 }
 
 function IsDict(v, type) {
-    return v instanceof Dict && (!type || v.get("Type").name == type);
+  return v instanceof Dict && (!type || v.get('Type').name == type);
 }
 
 function IsArray(v) {
-    return v instanceof Array;
+  return v instanceof Array;
 }
 
 function IsStream(v) {
-    return typeof v == "object" && v != null && ("getChar" in v);
+  return typeof v == 'object' && v != null && ('getChar' in v);
 }
 
 function IsRef(v) {
-    return v instanceof Ref;
+  return v instanceof Ref;
 }
 
 function IsPDFFunction(v) {
-    var fnDict;
-    if (typeof v != "object")
-        return false;
-    else if (IsDict(v))
-        fnDict = v;
-    else if (IsStream(v))
-        fnDict = v.dict;
-    else
-        return false;
-    return fnDict.has("FunctionType");
+  var fnDict;
+  if (typeof v != 'object')
+    return false;
+  else if (IsDict(v))
+    fnDict = v;
+  else if (IsStream(v))
+    fnDict = v.dict;
+  else
+    return false;
+  return fnDict.has('FunctionType');
 }
 
 var EOF = {};
 
 function IsEOF(v) {
-    return v == EOF;
+  return v == EOF;
 }
 
 var None = {};
 
 function IsNone(v) {
-    return v == None;
+  return v == None;
 }
 
 var Lexer = (function() {
-    function constructor(stream) {
-        this.stream = stream;
-    }
+  function constructor(stream) {
+    this.stream = stream;
+  }
 
-    constructor.isSpace = function(ch) {
-        return ch == " " || ch == "\t";
-    }
+  constructor.isSpace = function(ch) {
+    return ch == ' ' || ch == '\t';
+  }
 
-    // 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
-    ];
-
-    var MIN_INT = (1<<31) | 0;
-    var MAX_INT = (MIN_INT - 1) | 0;
-    var MIN_UINT = 0;
-    var MAX_UINT = ((1<<30) * 4) - 1;
-
-    function ToHexDigit(ch) {
-        if (ch >= "0" && ch <= "9")
-            return ch.charCodeAt(0) - 48;
-        ch = ch.toUpperCase();
-        if (ch >= "A" && ch <= "F")
-            return ch.charCodeAt(0) - 55;
-        return -1;
-    }
+  // 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
+  ];
+
+  var MIN_INT = (1 << 31) | 0;
+  var MAX_INT = (MIN_INT - 1) | 0;
+  var MIN_UINT = 0;
+  var MAX_UINT = ((1 << 30) * 4) - 1;
+
+  function ToHexDigit(ch) {
+    if (ch >= '0' && ch <= '9')
+      return ch.charCodeAt(0) - 48;
+    ch = ch.toUpperCase();
+    if (ch >= 'A' && ch <= 'F')
+      return ch.charCodeAt(0) - 55;
+    return -1;
+  }
 
-    constructor.prototype = {
-        getNumber: function(ch) {
-            var floating = false;
-            var str = ch;
-            var stream = this.stream;
-            do {
-                ch = stream.lookChar();
-                if (ch == "." && !floating) {
-                    str += ch;
-                    floating = true;
-                } else if (ch == "-") {
-                    // ignore minus signs in the middle of numbers to match
-                    // Adobe's behavior
-                    warn("Badly formated number");
-                } else if (ch >= "0" && ch <= "9") {
-                    str += ch;
-                } else if (ch == "e" || ch == "E") {
-                    floating = true;
-                } else {
-                    // the last character doesn't belong to us
-                    break;
-                }
-                stream.skip();
-            } while (true);
-            var value = parseFloat(str);
-            if (isNaN(value))
-                error("Invalid floating point number");
-            return value;
-        },
-        getString: function() {
-            var n = 0;
-            var numParen = 1;
-            var done = false;
-            var str = "";
-            var stream = this.stream;
-            var ch;
-            do {
-                switch (ch = stream.getChar()) {
-                case undefined:
-                    warn("Unterminated string");
-                    done = true;
-                    break;
-                case '(':
-                    ++numParen;
-                    str += ch;
-                    break;
-                case ')':
-                    if (--numParen == 0) {
-                        done = true;
-                    } else {
-                        str += ch;
-                    }
-                    break;
-                case '\\':
-                    switch (ch = stream.getChar()) {
-                    case undefined:
-                        warn("Unterminated string");
-                        done = true;
-                        break;
-                    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 += ch;
-                        break;
-                    case '0': case '1': case '2': case '3':
-                    case '4': case '5': case '6': case '7':
-                        var x = ch - '0';
-                        ch = stream.lookChar();
-                        if (ch >= '0' && ch <= '7') {
-                            stream.skip();
-                            x = (x << 3) + (ch - '0');
-                            ch = stream.lookChar();
-                            if (ch >= '0' && ch <= '7') {
-                                stream.skip();
-                                x = (x << 3) + (ch - '0');
-                            }
-                        }
-
-                        str += String.fromCharCode(x);
-                        break;
-                    case '\r':
-                        ch = stream.lookChar();
-                        if (ch == '\n')
-                            stream.skip();
-                        break;
-                    case '\n':
-                        break;
-                    default:
-                        str += ch;
-                        break;
-                    }
-                    break;
-                default:
-                    str += ch;
-                    break;
-                }
-            } while (!done);
-            if (!str.length)
-                return EOF;
-            return str;
-        },
-        getName: function(ch) {
-            var str = "";
-            var stream = this.stream;
-            while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
+  constructor.prototype = {
+    getNumber: function(ch) {
+      var floating = false;
+      var str = ch;
+      var stream = this.stream;
+      do {
+        ch = stream.lookChar();
+        if (ch == '.' && !floating) {
+          str += ch;
+          floating = true;
+        } else if (ch == '-') {
+          // ignore minus signs in the middle of numbers to match
+          // Adobe's behavior
+          warn('Badly formated number');
+        } else if (ch >= '0' && ch <= '9') {
+          str += ch;
+        } else if (ch == 'e' || ch == 'E') {
+          floating = true;
+        } else {
+          // the last character doesn't belong to us
+          break;
+        }
+        stream.skip();
+      } while (true);
+      var value = parseFloat(str);
+      if (isNaN(value))
+        error('Invalid floating point number');
+      return value;
+    },
+    getString: function() {
+      var n = 0;
+      var numParen = 1;
+      var done = false;
+      var str = '';
+      var stream = this.stream;
+      var ch;
+      do {
+        switch (ch = stream.getChar()) {
+        case undefined:
+          warn('Unterminated string');
+          done = true;
+          break;
+        case '(':
+          ++numParen;
+          str += ch;
+          break;
+        case ')':
+          if (--numParen == 0) {
+            done = true;
+          } else {
+            str += ch;
+          }
+          break;
+        case '\\':
+          switch (ch = stream.getChar()) {
+          case undefined:
+            warn('Unterminated string');
+            done = true;
+            break;
+          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 += ch;
+            break;
+          case '0': case '1': case '2': case '3':
+          case '4': case '5': case '6': case '7':
+            var x = ch - '0';
+            ch = stream.lookChar();
+            if (ch >= '0' && ch <= '7') {
+              stream.skip();
+              x = (x << 3) + (ch - '0');
+              ch = stream.lookChar();
+              if (ch >= '0' && ch <= '7') {
                 stream.skip();
-                if (ch == "#") {
-                    ch = stream.lookChar();
-                    var x = ToHexDigit(ch);
-                    if (x != -1) {
-                        stream.skip();
-                        var x2 = ToHexDigit(stream.getChar());
-                        if (x2 == -1)
-                            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)
-                error("Warning: name token is longer than allowed by the specification");
-            return new Name(str);
-        },
-        getHexString: function(ch) {
-            var str = "";
-            var stream = this.stream;
-            while (1) {
-                ch = stream.getChar();
-                if (ch == '>') {
-                    break;
-                }
-                if (!ch) {
-                    warn("Unterminated hex string");
-                    break;
-                }
-                if (specialChars[ch.charCodeAt(0)] != 1) {
-                    var x, x2;
-                    if (((x = ToHexDigit(ch)) == -1) ||
-                        ((x2 = ToHexDigit(stream.getChar())) == -1)) {
-                        error("Illegal character in hex string");
-                        break;
-                    }
-                    str += String.fromCharCode((x << 4) | x2);
-                }
-            }
-            return str;
-        },
-        getObj: function() {
-            // skip whitespace and comments
-            var comment = false;
-            var stream = this.stream;
-            var ch;
-            while (true) {
-                if (!(ch = stream.getChar()))
-                    return EOF;
-                if (comment) {
-                    if (ch == '\r' || ch == '\n')
-                        comment = false;
-                } else if (ch == '%') {
-                    comment = true;
-                } else if (specialChars[ch.charCodeAt(0)] != 1) {
-                    break;
-                }
+                x = (x << 3) + (ch - '0');
+              }
             }
 
-            // start reading token
-            switch (ch) {
-            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();
-            case '/':
-                   return this.getName(ch);
-            // array punctuation
-            case '[':
-            case ']':
-                return new Cmd(ch);
-            // hex string or dict punctuation
-            case '<':
-                   ch = stream.lookChar();
-                if (ch == '<') {
-                    // dict punctuation
-                    stream.skip();
-                    return new Cmd("<<");
-                }
-                   return this.getHexString(ch);
-            // dict punctuation
-            case '>':
-                   ch = stream.lookChar();
-                   if (ch == '>') {
-                    stream.skip();
-                    return new Cmd(">>");
-                }
-            case "{":
-            case "}":
-              return new Cmd(ch);
-               // fall through
-            case ')':
-                error("Illegal character");
-                return Error;
-            }
+            str += String.fromCharCode(x);
+            break;
+          case '\r':
+            ch = stream.lookChar();
+            if (ch == '\n')
+              stream.skip();
+            break;
+          case '\n':
+            break;
+          default:
+            str += ch;
+            break;
+          }
+          break;
+        default:
+          str += ch;
+          break;
+        }
+      } while (!done);
+      if (!str.length)
+        return EOF;
+      return str;
+    },
+    getName: function(ch) {
+      var str = '';
+      var stream = this.stream;
+      while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
+        stream.skip();
+        if (ch == '#') {
+          ch = stream.lookChar();
+          var x = ToHexDigit(ch);
+          if (x != -1) {
+            stream.skip();
+            var x2 = ToHexDigit(stream.getChar());
+            if (x2 == -1)
+              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)
+        error('Warning: name token is longer than allowed by the spec.');
+      return new Name(str);
+    },
+    getHexString: function(ch) {
+      var str = '';
+      var stream = this.stream;
+      while (1) {
+        ch = stream.getChar();
+        if (ch == '>') {
+          break;
+        }
+        if (!ch) {
+          warn('Unterminated hex string');
+          break;
+        }
+        if (specialChars[ch.charCodeAt(0)] != 1) {
+          var x, x2;
+          if (((x = ToHexDigit(ch)) == -1) ||
+              ((x2 = ToHexDigit(stream.getChar())) == -1)) {
+            error('Illegal character in hex string');
+            break;
+          }
+          str += String.fromCharCode((x << 4) | x2);
+        }
+      }
+      return str;
+    },
+    getObj: function() {
+      // skip whitespace and comments
+      var comment = false;
+      var stream = this.stream;
+      var ch;
+      while (true) {
+        if (!(ch = stream.getChar()))
+          return EOF;
+        if (comment) {
+          if (ch == '\r' || ch == '\n')
+            comment = false;
+        } else if (ch == '%') {
+          comment = true;
+        } else if (specialChars[ch.charCodeAt(0)] != 1) {
+          break;
+        }
+      }
 
-            // command
-            var str = ch;
-            while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
-                stream.skip();
-                if (str.length == 128) {
-                    error("Command token too long");
-                    break;
-                }
-                str += ch;
-            }
-            if (str == "true")
-                return true;
-            if (str == "false")
-                return false;
-            if (str == "null")
-                return null;
-            return new Cmd(str);
-        },
-        skipToNextLine: function() {
-            var stream = this.stream;
-            while (true) {
-                var ch = stream.getChar();
-                if (!ch || ch == "\n")
-                    return;
-                if (ch == "\r") {
-                    if ((ch = stream.lookChar()) == "\n")
-                        stream.skip();
-                    return;
-                }
-            }
+      // start reading token
+      switch (ch) {
+      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();
+      case '/':
+      return this.getName(ch);
+      // array punctuation
+      case '[':
+      case ']':
+      return new Cmd(ch);
+      // hex string or dict punctuation
+      case '<':
+      ch = stream.lookChar();
+      if (ch == '<') {
+        // dict punctuation
+        stream.skip();
+        return new Cmd('<<');
+      }
+      return this.getHexString(ch);
+      // dict punctuation
+      case '>':
+      ch = stream.lookChar();
+      if (ch == '>') {
+        stream.skip();
+        return new Cmd('>>');
+      }
+      case '{':
+      case '}':
+      return new Cmd(ch);
+      // fall through
+      case ')':
+      error('Illegal character');
+      return Error;
+      }
+
+      // command
+      var str = ch;
+      while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
+        stream.skip();
+        if (str.length == 128) {
+          error('Command token too long');
+          break;
+        }
+        str += ch;
+      }
+      if (str == 'true')
+        return true;
+      if (str == 'false')
+        return false;
+      if (str == 'null')
+        return null;
+      return new Cmd(str);
+    },
+    skipToNextLine: function() {
+      var stream = this.stream;
+      while (true) {
+        var ch = stream.getChar();
+        if (!ch || ch == '\n')
+          return;
+        if (ch == '\r') {
+          if ((ch = stream.lookChar()) == '\n')
+            stream.skip();
+          return;
         }
-    };
+      }
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var Parser = (function() {
-    function constructor(lexer, allowStreams, xref) {
-        this.lexer = lexer;
-        this.allowStreams = allowStreams;
-        this.xref = xref;
-        this.inlineImg = 0;
-        this.refill();
-    }
+  function constructor(lexer, allowStreams, xref) {
+    this.lexer = lexer;
+    this.allowStreams = allowStreams;
+    this.xref = xref;
+    this.inlineImg = 0;
+    this.refill();
+  }
 
-    constructor.prototype = {
-        refill: function() {
-            this.buf1 = this.lexer.getObj();
-            this.buf2 = this.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 (IsCmd(this.buf2, "ID")) {
-                this.lexer.skip(); // skip char after 'ID' command
-                this.inlineImg = 1;
-            }
-            this.buf1 = this.buf2;
-            // don't buffer inline image data
-            this.buf2 = (this.inlineImg > 0) ? null : this.lexer.getObj();
-        },
-        getObj: function(cipherTransform) {
-            // refill buffer after inline image data
-            if (this.inlineImg == 2)
-                this.refill();
-
-            if (IsCmd(this.buf1, "[")) { // array
-                this.shift();
-                var array = [];
-                while (!IsCmd(this.buf1, "]") && !IsEOF(this.buf1))
-                    array.push(this.getObj());
-                if (IsEOF(this.buf1))
-                    error("End of file inside array");
-                this.shift();
-                return array;
-            } else if (IsCmd(this.buf1, "<<")) { // dictionary or stream
-                this.shift();
-                var dict = new Dict();
-                while (!IsCmd(this.buf1, ">>") && !IsEOF(this.buf1)) {
-                    if (!IsName(this.buf1)) {
-                        error("Dictionary key must be a name object");
-                        shift();
-                    } else {
-                        var key = this.buf1.name;
-                        this.shift();
-                        if (IsEOF(this.buf1))
-                            break;
-                        dict.set(key, this.getObj(cipherTransform));
-                    }
-                }
-                if (IsEOF(this.buf1))
-                    error("End of file inside dictionary");
-
-                // stream objects are not allowed inside content streams or
-                // object streams
-                if (this.allowStreams && IsCmd(this.buf2, "stream")) {
-                    return this.makeStream(dict, cipherTransform);
-                } else {
-                    this.shift();
-                }
-                return dict;
-
-            } else if (IsInt(this.buf1)) { // indirect reference or integer
-                var num = this.buf1;
-                this.shift();
-                if (IsInt(this.buf1) && IsCmd(this.buf2, "R")) {
-                    var ref = new Ref(num, this.buf1);
-                    this.shift();
-                    this.shift();
-                    return ref;
-                }
-                return num;
-            } else if (IsString(this.buf1)) { // string
-                var str = this.buf1;
-                this.shift();
-                if (cipherTransform)
-                    str = cipherTransform.decryptString(str);
-                return str;
-            }
+  constructor.prototype = {
+    refill: function() {
+      this.buf1 = this.lexer.getObj();
+      this.buf2 = this.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 (IsCmd(this.buf2, 'ID')) {
+        this.lexer.skip(); // skip char after 'ID' command
+        this.inlineImg = 1;
+      }
+      this.buf1 = this.buf2;
+      // don't buffer inline image data
+      this.buf2 = (this.inlineImg > 0) ? null : this.lexer.getObj();
+    },
+    getObj: function(cipherTransform) {
+      // refill buffer after inline image data
+      if (this.inlineImg == 2)
+        this.refill();
 
-            // simple object
-            var obj = this.buf1;
+      if (IsCmd(this.buf1, '[')) { // array
+        this.shift();
+        var array = [];
+        while (!IsCmd(this.buf1, ']') && !IsEOF(this.buf1))
+          array.push(this.getObj());
+        if (IsEOF(this.buf1))
+          error('End of file inside array');
+        this.shift();
+        return array;
+      } else if (IsCmd(this.buf1, '<<')) { // dictionary or stream
+        this.shift();
+        var dict = new Dict();
+        while (!IsCmd(this.buf1, '>>') && !IsEOF(this.buf1)) {
+          if (!IsName(this.buf1)) {
+            error('Dictionary key must be a name object');
+            shift();
+          } else {
+            var key = this.buf1.name;
             this.shift();
-            return obj;
-        },
-        makeStream: function(dict, cipherTransform) {
-            var lexer = this.lexer;
-            var stream = lexer.stream;
-
-            // get stream start position
-            lexer.skipToNextLine();
-            var pos = stream.pos;
-
-            // get length
-            var length = dict.get("Length");
-            var xref = this.xref;
-            if (xref)
-                length = xref.fetchIfRef(length);
-            if (!IsInt(length)) {
-                error("Bad 'Length' attribute in stream");
-                length = 0;
-            }
+            if (IsEOF(this.buf1))
+              break;
+            dict.set(key, this.getObj(cipherTransform));
+          }
+        }
+        if (IsEOF(this.buf1))
+          error('End of file inside dictionary');
 
-            // skip over the stream data
-            stream.pos = pos + length;
-            this.shift(); // '>>'
-            this.shift(); // 'stream'
-            if (!IsCmd(this.buf1, "endstream"))
-                error("Missing 'endstream'");
-            this.shift();
+        // stream objects are not allowed inside content streams or
+        // object streams
+        if (this.allowStreams && IsCmd(this.buf2, 'stream')) {
+          return this.makeStream(dict, cipherTransform);
+        } else {
+          this.shift();
+        }
+        return dict;
+
+      } else if (IsInt(this.buf1)) { // indirect reference or integer
+        var num = this.buf1;
+        this.shift();
+        if (IsInt(this.buf1) && IsCmd(this.buf2, 'R')) {
+          var ref = new Ref(num, this.buf1);
+          this.shift();
+          this.shift();
+          return ref;
+        }
+        return num;
+      } else if (IsString(this.buf1)) { // string
+        var str = this.buf1;
+        this.shift();
+        if (cipherTransform)
+          str = cipherTransform.decryptString(str);
+        return str;
+      }
 
-            stream = stream.makeSubStream(pos, length, dict);
-            if (cipherTransform)
-                stream = cipherTransform.createStream(stream);
-            stream = this.filter(stream, dict, length);
-            stream.parameters = dict;
-            return stream;
-        },
-        filter: function(stream, dict, length) {
-            var filter = dict.get2("Filter", "F");
-            var params = dict.get2("DecodeParms", "DP");
-            if (IsName(filter))
-                return this.makeFilter(stream, filter.name, length, params);
-            if (IsArray(filter)) {
-                var filterArray = filter;
-                var paramsArray = params;
-                for (var i = 0, ii = filterArray.length; i < ii; ++i) {
-                    filter = filterArray[i];
-                    if (!IsName(filter))
-                        error("Bad filter name");
-                    else {
-                        params = null;
-                        if (IsArray(paramsArray) && (i in paramsArray))
-                            params = paramsArray[i];
-                        stream = this.makeFilter(stream, filter.name, length, params);
-                    }
-                }
-            }
-            return stream;
-        },
-        makeFilter: function(stream, name, length, params) {
-            if (name == "FlateDecode" || name == "Fl") {
-                if (params) {
-                    return new PredictorStream(new FlateStream(stream), params);
-                }
-                return new FlateStream(stream);
-            } else if (name == "DCTDecode") {
-                var bytes = stream.getBytes(length);
-                return new JpegStream(bytes, stream.dict);
-            } else if (name == "ASCII85Decode") {
-                return new Ascii85Stream(stream);
-            } else if (name == "CCITTFaxDecode") {
-                TODO("implement fax stream");
-                return new CCITTFaxStream(stream, params);
-            } else {
-                error("filter '" + name + "' not supported yet");
-            }
-            return stream;
+      // simple object
+      var obj = this.buf1;
+      this.shift();
+      return obj;
+    },
+    makeStream: function(dict, cipherTransform) {
+      var lexer = this.lexer;
+      var stream = lexer.stream;
+
+      // get stream start position
+      lexer.skipToNextLine();
+      var pos = stream.pos;
+
+      // get length
+      var length = dict.get('Length');
+      var xref = this.xref;
+      if (xref)
+        length = xref.fetchIfRef(length);
+      if (!IsInt(length)) {
+        error("Bad 'Length' attribute in stream");
+        length = 0;
+      }
+
+      // skip over the stream data
+      stream.pos = pos + length;
+      this.shift(); // '>>'
+      this.shift(); // 'stream'
+      if (!IsCmd(this.buf1, 'endstream'))
+        error("Missing 'endstream'");
+      this.shift();
+
+      stream = stream.makeSubStream(pos, length, dict);
+      if (cipherTransform)
+        stream = cipherTransform.createStream(stream);
+      stream = this.filter(stream, dict, length);
+      stream.parameters = dict;
+      return stream;
+    },
+    filter: function(stream, dict, length) {
+      var filter = dict.get2('Filter', 'F');
+      var params = dict.get2('DecodeParms', 'DP');
+      if (IsName(filter))
+        return this.makeFilter(stream, filter.name, length, params);
+      if (IsArray(filter)) {
+        var filterArray = filter;
+        var paramsArray = params;
+        for (var i = 0, ii = filterArray.length; i < ii; ++i) {
+          filter = filterArray[i];
+          if (!IsName(filter))
+            error('Bad filter name');
+          else {
+            params = null;
+            if (IsArray(paramsArray) && (i in paramsArray))
+              params = paramsArray[i];
+            stream = this.makeFilter(stream, filter.name, length, params);
+          }
+        }
+      }
+      return stream;
+    },
+    makeFilter: function(stream, name, length, params) {
+      if (name == 'FlateDecode' || name == 'Fl') {
+        if (params) {
+          return new PredictorStream(new FlateStream(stream), params);
         }
-    };
+        return new FlateStream(stream);
+      } else if (name == 'DCTDecode') {
+        var bytes = stream.getBytes(length);
+        return new JpegStream(bytes, stream.dict);
+      } else if (name == 'ASCII85Decode') {
+        return new Ascii85Stream(stream);
+      } else if (name == 'CCITTFaxDecode') {
+        TODO('implement fax stream');
+        return new CCITTFaxStream(stream, params);
+      } else {
+        error("filter '" + name + "' not supported yet");
+      }
+      return stream;
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var Linearization = (function() {
-    function constructor(stream) {
-        this.parser = new Parser(new Lexer(stream), false);
-        var obj1 = this.parser.getObj();
-        var obj2 = this.parser.getObj();
-        var obj3 = this.parser.getObj();
-        this.linDict = this.parser.getObj();
-        if (IsInt(obj1) && IsInt(obj2) && IsCmd(obj3, "obj") && IsDict(this.linDict)) {
-            var obj = this.linDict.get("Linearized");
-            if (!(IsNum(obj) && obj > 0))
-                this.linDict = null;
-        }
+  function constructor(stream) {
+    this.parser = new Parser(new Lexer(stream), false);
+    var obj1 = this.parser.getObj();
+    var obj2 = this.parser.getObj();
+    var obj3 = this.parser.getObj();
+    this.linDict = this.parser.getObj();
+    if (IsInt(obj1) && IsInt(obj2) && IsCmd(obj3, 'obj') &&
+        IsDict(this.linDict)) {
+      var obj = this.linDict.get('Linearized');
+      if (!(IsNum(obj) && obj > 0))
+        this.linDict = null;
     }
+  }
 
-    constructor.prototype = {
-        getInt: function(name) {
-            var linDict = this.linDict;
-            var obj;
-            if (IsDict(linDict) &&
-                IsInt(obj = linDict.get(name)) &&
-                obj > 0) {
-                return obj;
-            }
-            error("'" + name + "' field in linearization table is invalid");
-            return 0;
-        },
-        getHint: function(index) {
-            var linDict = this.linDict;
-            var obj1, obj2;
-            if (IsDict(linDict) &&
-                IsArray(obj1 = linDict.get("H")) &&
-                obj1.length >= 2 &&
-                IsInt(obj2 = obj1[index]) &&
-                obj2 > 0) {
-                return obj2;
-            }
-            error("Hints table in linearization table is invalid");
-            return 0;
-        },
-        get length() {
-            if (!IsDict(this.linDict))
-                return 0;
-            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");
-        }
-    };
+  constructor.prototype = {
+    getInt: function(name) {
+      var linDict = this.linDict;
+      var obj;
+      if (IsDict(linDict) &&
+          IsInt(obj = linDict.get(name)) &&
+          obj > 0) {
+        return obj;
+      }
+      error("'" + name + "' field in linearization table is invalid");
+      return 0;
+    },
+    getHint: function(index) {
+      var linDict = this.linDict;
+      var obj1, obj2;
+      if (IsDict(linDict) &&
+          IsArray(obj1 = linDict.get('H')) &&
+          obj1.length >= 2 &&
+          IsInt(obj2 = obj1[index]) &&
+          obj2 > 0) {
+        return obj2;
+      }
+      error('Hints table in linearization table is invalid');
+      return 0;
+    },
+    get length() {
+      if (!IsDict(this.linDict))
+        return 0;
+      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');
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var XRef = (function() {
-    function constructor(stream, startXRef, mainXRefEntriesOffset) {
-        this.stream = stream;
-        this.entries = [];
-        this.xrefstms = {};
-        var trailerDict = this.readXRef(startXRef);
-
-        // prepare the XRef cache
-        this.cache = [];
-
-        var encrypt = trailerDict.get("Encrypt");
-        if (encrypt) {
-            var fileId = trailerDict.get("ID");
-            this.encrypt = new CipherTransformFactory(this.fetch(encrypt), fileId[0] /*, password */);
-        }
-
-        // get the root dictionary (catalog) object
-        if (!IsRef(this.root = trailerDict.get("Root")))
-            error("Invalid root reference");
+  function constructor(stream, startXRef, mainXRefEntriesOffset) {
+    this.stream = stream;
+    this.entries = [];
+    this.xrefstms = {};
+    var trailerDict = this.readXRef(startXRef);
+
+    // prepare the XRef cache
+    this.cache = [];
+
+    var encrypt = trailerDict.get('Encrypt');
+    if (encrypt) {
+      var fileId = trailerDict.get('ID');
+      this.encrypt = new CipherTransformFactory(this.fetch(encrypt),
+                                                fileId[0] /*, password */);
     }
 
-    constructor.prototype = {
-        readXRefTable: function readXRefTable(parser) {
-            var obj;
-            while (true) {
-                if (IsCmd(obj = parser.getObj(), "trailer"))
-                    break;
-                if (!IsInt(obj))
-                    error("Invalid XRef table");
-                var first = obj;
-                if (!IsInt(obj = parser.getObj()))
-                    error("Invalid XRef table");
-                var n = obj;
-                if (first < 0 || n < 0 || (first + n) != ((first + n) | 0))
-                    error("Invalid XRef table");
-                for (var i = first; i < first + n; ++i) {
-                    var entry = {};
-                    if (!IsInt(obj = parser.getObj()))
-                        error("Invalid XRef table");
-                    entry.offset = obj;
-                    if (!IsInt(obj = parser.getObj()))
-                        error("Invalid XRef table");
-                    entry.gen = obj;
-                    obj = parser.getObj();
-                    if (IsCmd(obj, "n")) {
-                        entry.uncompressed = true;
-                    } else if (IsCmd(obj, "f")) {
-                        entry.free = true;
-                    } else {
-                        error("Invalid XRef table");
-                    }
-                    if (!this.entries[i]) {
-                        // In some buggy PDF files the xref table claims to start at 1
-                        // instead of 0.
-                        if (i == 1 && first == 1 &&
-                            entry.offset == 0 && entry.gen == 65535 && entry.free) {
-                            i = first = 0;
-                        }
-                        this.entries[i] = entry;
-                    }
-                }
-            }
+    // get the root dictionary (catalog) object
+    if (!IsRef(this.root = trailerDict.get('Root')))
+      error('Invalid root reference');
+  }
 
-            // read the trailer dictionary
-            var dict;
-            if (!IsDict(dict = parser.getObj()))
-                error("Invalid XRef table");
-
-            // get the 'Prev' pointer
-            var prev;
-            obj = dict.get("Prev");
-            if (IsInt(obj)) {
-                prev = obj;
-            } else if (IsRef(obj)) {
-                // certain buggy PDF generators generate "/Prev NNN 0 R" instead
-                // of "/Prev NNN"
-                prev = obj.num;
-            }
-            if (prev) {
-                this.readXRef(prev);
+  constructor.prototype = {
+    readXRefTable: function readXRefTable(parser) {
+      var obj;
+      while (true) {
+        if (IsCmd(obj = parser.getObj(), 'trailer'))
+          break;
+        if (!IsInt(obj))
+          error('Invalid XRef table');
+        var first = obj;
+        if (!IsInt(obj = parser.getObj()))
+          error('Invalid XRef table');
+        var n = obj;
+        if (first < 0 || n < 0 || (first + n) != ((first + n) | 0))
+          error('Invalid XRef table');
+        for (var i = first; i < first + n; ++i) {
+          var entry = {};
+          if (!IsInt(obj = parser.getObj()))
+            error('Invalid XRef table');
+          entry.offset = obj;
+          if (!IsInt(obj = parser.getObj()))
+            error('Invalid XRef table');
+          entry.gen = obj;
+          obj = parser.getObj();
+          if (IsCmd(obj, 'n')) {
+            entry.uncompressed = true;
+          } else if (IsCmd(obj, 'f')) {
+            entry.free = true;
+          } else {
+            error('Invalid XRef table');
+          }
+          if (!this.entries[i]) {
+            // In some buggy PDF files the xref table claims to start at 1
+            // instead of 0.
+            if (i == 1 && first == 1 &&
+                entry.offset == 0 && entry.gen == 65535 && entry.free) {
+              i = first = 0;
             }
+            this.entries[i] = entry;
+          }
+        }
+      }
 
-            // check for 'XRefStm' key
-            if (IsInt(obj = dict.get("XRefStm"))) {
-                var pos = obj;
-                if (pos in this.xrefstms)
-                    error("Invalid XRef table");
-                this.xrefstms[pos] = 1; // avoid infinite recursion
-                this.readXRef(pos);
-            }
+      // read the trailer dictionary
+      var dict;
+      if (!IsDict(dict = parser.getObj()))
+        error('Invalid XRef table');
+
+      // get the 'Prev' pointer
+      var prev;
+      obj = dict.get('Prev');
+      if (IsInt(obj)) {
+        prev = obj;
+      } else if (IsRef(obj)) {
+        // certain buggy PDF generators generate "/Prev NNN 0 R" instead
+        // of "/Prev NNN"
+        prev = obj.num;
+      }
+      if (prev) {
+        this.readXRef(prev);
+      }
 
-            return dict;
-        },
-        readXRefStream: function readXRefStream(stream) {
-            var streamParameters = stream.parameters;
-            var length = streamParameters.get("Length");
-            var byteWidths = streamParameters.get("W");
-            var range = streamParameters.get("Index");
-            if (!range)
-                range = [0, streamParameters.get("Size")];
-            var i, j;
-            while (range.length > 0) {
-                var first = range[0], n = range[1];
-                if (!IsInt(first) || !IsInt(n))
-                    error("Invalid XRef range fields");
-                var typeFieldWidth = byteWidths[0], offsetFieldWidth = byteWidths[1], generationFieldWidth = byteWidths[2];
-                if (!IsInt(typeFieldWidth) || !IsInt(offsetFieldWidth) || !IsInt(generationFieldWidth))
-                    error("Invalid XRef entry fields length");
-                for (i = 0; i < n; ++i) {
-                    var type = 0, offset = 0, generation = 0;
-                    for (j = 0; j < typeFieldWidth; ++j)
-                        type = (type << 8) | stream.getByte();
-                    // if type field is absent, its default value = 1
-                    if (typeFieldWidth == 0)
-                        type = 1;
-                    for (j = 0; j < offsetFieldWidth; ++j)
-                        offset = (offset << 8) | stream.getByte();
-                    for (j = 0; j < generationFieldWidth; ++j)
-                        generation = (generation << 8) | stream.getByte();
-                    var entry = {}
-                    entry.offset = offset;
-                    entry.gen = generation;
-                    switch (type) {
-                    case 0:
-                        entry.free = true;
-                        break;
-                    case 1:
-                        entry.uncompressed = true;
-                        break;
-                    case 2:
-                        break;
-                    default:
-                        error("Invalid XRef entry type");
-                        break;
-                    }
-                    if (!this.entries[first + i])
-                        this.entries[first + i] = entry;
-                }
-                range.splice(0, 2);
-            }
-            var prev = streamParameters.get("Prev");
-            if (IsInt(prev))
-                this.readXRef(prev);
-            return streamParameters;
-        },
-        readXRef: function readXref(startXRef) {
-            var stream = this.stream;
-            stream.pos = startXRef;
-            var parser = new Parser(new Lexer(stream), true);
-            var obj = parser.getObj();
-            // parse an old-style xref table
-            if (IsCmd(obj, "xref"))
-                return this.readXRefTable(parser);
-            // parse an xref stream
-            if (IsInt(obj)) {
-                if (!IsInt(parser.getObj()) ||
-                    !IsCmd(parser.getObj(), "obj") ||
-                    !IsStream(obj = parser.getObj())) {
-                    error("Invalid XRef stream");
-                }
-                return this.readXRefStream(obj);
-            }
-            error("Invalid XRef");
-            return null;
-        },
-        getEntry: function(i) {
-            var e = this.entries[i];
-            if (e.free)
-                error("reading an XRef stream not implemented yet");
-            return e;
-        },
-        fetchIfRef: function(obj) {
-            if (!IsRef(obj))
-                return obj;
-            return this.fetch(obj);
-        },
-        fetch: function(ref) {
-            var num = ref.num;
-            var e = this.cache[num];
-            if (e)
-                return e;
-
-            e = this.getEntry(num);
-            var gen = ref.gen;
-            var stream, parser;
-            if (e.uncompressed) {
-                if (e.gen != gen)
-                    throw("inconsistent generation in XRef");
-                stream = this.stream.makeSubStream(e.offset);
-                parser = new Parser(new Lexer(stream), true, this);
-                var obj1 = parser.getObj();
-                var obj2 = parser.getObj();
-                var obj3 = parser.getObj();
-                if (!IsInt(obj1) || obj1 != num ||
-                    !IsInt(obj2) || obj2 != gen ||
-                    !IsCmd(obj3)) {
-                    error("bad XRef entry");
-                }
-                if (!IsCmd(obj3, "obj")) {
-                    // some bad pdfs use "obj1234" and really mean 1234
-                    if (obj3.cmd.indexOf("obj") == 0) {
-                        var num = parseInt(obj3.cmd.substring(3));
-                        if (!isNaN(num))
-                            return num;
-                    }
-                    error("bad XRef entry");
-                }
-                if (this.encrypt) {
-                    e = parser.getObj(this.encrypt.createCipherTransform(num, gen));
-                } else {
-                    e = parser.getObj();
-                }
-                // Don't cache streams since they are mutable.
-                if (!IsStream(e))
-                    this.cache[num] = e;
-                return e;
-            }
+      // check for 'XRefStm' key
+      if (IsInt(obj = dict.get('XRefStm'))) {
+        var pos = obj;
+        if (pos in this.xrefstms)
+          error('Invalid XRef table');
+        this.xrefstms[pos] = 1; // avoid infinite recursion
+        this.readXRef(pos);
+      }
 
-            // compressed entry
-            stream = this.fetch(new Ref(e.offset, 0));
-            if (!IsStream(stream))
-                error("bad ObjStm stream");
-            var first = stream.parameters.get("First");
-            var n = stream.parameters.get("N");
-            if (!IsInt(first) || !IsInt(n)) {
-                error("invalid first and n parameters for ObjStm stream");
-            }
-            parser = new Parser(new Lexer(stream), false);
-            var i, entries = [], nums = [];
-            // read the object numbers to populate cache
-            for (i = 0; i < n; ++i) {
-                var num = parser.getObj();
-                if (!IsInt(num)) {
-                    error("invalid object number in the ObjStm stream");
-                }
-                nums.push(num);
-                var offset = parser.getObj();
-                if (!IsInt(offset)) {
-                    error("invalid object offset in the ObjStm stream");
-                }
-            }
-            // read stream objects for cache
-            for (i = 0; i < n; ++i) {
-                entries.push(parser.getObj());
-                this.cache[nums[i]] = entries[i];
-            }
-            e = entries[e.gen];
-            if (!e) {
-                error("bad XRef entry for compressed object");
-            }
-            return e;
-        },
-        getCatalogObj: function() {
-            return this.fetch(this.root);
+      return dict;
+    },
+    readXRefStream: function readXRefStream(stream) {
+      var streamParameters = stream.parameters;
+      var length = streamParameters.get('Length');
+      var byteWidths = streamParameters.get('W');
+      var range = streamParameters.get('Index');
+      if (!range)
+        range = [0, streamParameters.get('Size')];
+      var i, j;
+      while (range.length > 0) {
+        var first = range[0], n = range[1];
+        if (!IsInt(first) || !IsInt(n))
+          error('Invalid XRef range fields');
+        var typeFieldWidth = byteWidths[0];
+        var offsetFieldWidth = byteWidths[1];
+        var generationFieldWidth = byteWidths[2];
+        if (!IsInt(typeFieldWidth) || !IsInt(offsetFieldWidth) ||
+            !IsInt(generationFieldWidth)) {
+          error('Invalid XRef entry fields length');
+        }
+        for (i = 0; i < n; ++i) {
+          var type = 0, offset = 0, generation = 0;
+          for (j = 0; j < typeFieldWidth; ++j)
+            type = (type << 8) | stream.getByte();
+          // if type field is absent, its default value = 1
+          if (typeFieldWidth == 0)
+            type = 1;
+          for (j = 0; j < offsetFieldWidth; ++j)
+            offset = (offset << 8) | stream.getByte();
+          for (j = 0; j < generationFieldWidth; ++j)
+            generation = (generation << 8) | stream.getByte();
+          var entry = {};
+          entry.offset = offset;
+          entry.gen = generation;
+          switch (type) {
+          case 0:
+            entry.free = true;
+            break;
+          case 1:
+            entry.uncompressed = true;
+            break;
+          case 2:
+            break;
+          default:
+            error('Invalid XRef entry type');
+            break;
+          }
+          if (!this.entries[first + i])
+            this.entries[first + i] = entry;
+        }
+        range.splice(0, 2);
+      }
+      var prev = streamParameters.get('Prev');
+      if (IsInt(prev))
+        this.readXRef(prev);
+      return streamParameters;
+    },
+    readXRef: function readXref(startXRef) {
+      var stream = this.stream;
+      stream.pos = startXRef;
+      var parser = new Parser(new Lexer(stream), true);
+      var obj = parser.getObj();
+      // parse an old-style xref table
+      if (IsCmd(obj, 'xref'))
+        return this.readXRefTable(parser);
+      // parse an xref stream
+      if (IsInt(obj)) {
+        if (!IsInt(parser.getObj()) ||
+            !IsCmd(parser.getObj(), 'obj') ||
+            !IsStream(obj = parser.getObj())) {
+          error('Invalid XRef stream');
         }
-    };
+        return this.readXRefStream(obj);
+      }
+      error('Invalid XRef');
+      return null;
+    },
+    getEntry: function(i) {
+      var e = this.entries[i];
+      if (e.free)
+        error('reading an XRef stream not implemented yet');
+      return e;
+    },
+    fetchIfRef: function(obj) {
+      if (!IsRef(obj))
+        return obj;
+      return this.fetch(obj);
+    },
+    fetch: function(ref) {
+      var num = ref.num;
+      var e = this.cache[num];
+      if (e)
+        return e;
+
+      e = this.getEntry(num);
+      var gen = ref.gen;
+      var stream, parser;
+      if (e.uncompressed) {
+        if (e.gen != gen)
+          throw ('inconsistent generation in XRef');
+        stream = this.stream.makeSubStream(e.offset);
+        parser = new Parser(new Lexer(stream), true, this);
+        var obj1 = parser.getObj();
+        var obj2 = parser.getObj();
+        var obj3 = parser.getObj();
+        if (!IsInt(obj1) || obj1 != num ||
+            !IsInt(obj2) || obj2 != gen ||
+            !IsCmd(obj3)) {
+          error('bad XRef entry');
+        }
+        if (!IsCmd(obj3, 'obj')) {
+          // some bad pdfs use "obj1234" and really mean 1234
+          if (obj3.cmd.indexOf('obj') == 0) {
+            var num = parseInt(obj3.cmd.substring(3));
+            if (!isNaN(num))
+              return num;
+          }
+          error('bad XRef entry');
+        }
+        if (this.encrypt) {
+          e = parser.getObj(this.encrypt.createCipherTransform(num, gen));
+        } else {
+          e = parser.getObj();
+        }
+        // Don't cache streams since they are mutable.
+        if (!IsStream(e))
+          this.cache[num] = e;
+        return e;
+      }
+
+      // compressed entry
+      stream = this.fetch(new Ref(e.offset, 0));
+      if (!IsStream(stream))
+        error('bad ObjStm stream');
+      var first = stream.parameters.get('First');
+      var n = stream.parameters.get('N');
+      if (!IsInt(first) || !IsInt(n)) {
+        error('invalid first and n parameters for ObjStm stream');
+      }
+      parser = new Parser(new Lexer(stream), false);
+      var i, entries = [], nums = [];
+      // read the object numbers to populate cache
+      for (i = 0; i < n; ++i) {
+        var num = parser.getObj();
+        if (!IsInt(num)) {
+          error('invalid object number in the ObjStm stream');
+        }
+        nums.push(num);
+        var offset = parser.getObj();
+        if (!IsInt(offset)) {
+          error('invalid object offset in the ObjStm stream');
+        }
+      }
+      // read stream objects for cache
+      for (i = 0; i < n; ++i) {
+        entries.push(parser.getObj());
+        this.cache[nums[i]] = entries[i];
+      }
+      e = entries[e.gen];
+      if (!e) {
+        error('bad XRef entry for compressed object');
+      }
+      return e;
+    },
+    getCatalogObj: function() {
+      return this.fetch(this.root);
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var Page = (function() {
-    function constructor(xref, pageNumber, pageDict) {
-        this.xref = xref;
-        this.pageNumber = pageNumber;
-        this.pageDict = pageDict;
-    }
+  function constructor(xref, pageNumber, pageDict) {
+    this.xref = xref;
+    this.pageNumber = pageNumber;
+    this.pageDict = pageDict;
+  }
 
-    constructor.prototype = {
-        getPageProp: function(key) {
-            return this.xref.fetchIfRef(this.pageDict.get(key));
-        },
-        inheritPageProp: function(key) {
-            var dict = this.pageDict;
-            var obj = dict.get(key);
-            while (!obj) {
-                dict = this.xref.fetchIfRef(dict.get("Parent"));
-                if (!dict)
-                    break;
-                obj = dict.get(key);
-            }
-            return obj;
-        },
-        get content() {
-            return shadow(this, "content", this.getPageProp("Contents"));
-        },
-        get resources() {
-            return shadow(this, "resources", this.inheritPageProp("Resources"));
-        },
-        get mediaBox() {
-            var obj = this.inheritPageProp("MediaBox");
-            return shadow(this, "mediaBox", ((IsArray(obj) && obj.length == 4)
-                                             ? obj
-                                             : null));
-        },
-        compile: function(gfx, fonts) {
-            if (this.code) {
-                // content was compiled
-                return;
-            }
+  constructor.prototype = {
+    getPageProp: function(key) {
+      return this.xref.fetchIfRef(this.pageDict.get(key));
+    },
+    inheritPageProp: function(key) {
+      var dict = this.pageDict;
+      var obj = dict.get(key);
+      while (!obj) {
+        dict = this.xref.fetchIfRef(dict.get('Parent'));
+        if (!dict)
+          break;
+        obj = dict.get(key);
+      }
+      return obj;
+    },
+    get content() {
+      return shadow(this, 'content', this.getPageProp('Contents'));
+    },
+    get resources() {
+      return shadow(this, 'resources', this.inheritPageProp('Resources'));
+    },
+    get mediaBox() {
+      var obj = this.inheritPageProp('MediaBox');
+      return shadow(this, 'mediaBox',
+                    ((IsArray(obj) && obj.length == 4) ? obj : null));
+    },
+    compile: function(gfx, fonts) {
+      if (this.code) {
+        // content was compiled
+        return;
+      }
 
-            var xref = this.xref;
-            var content;
-            var resources = xref.fetchIfRef(this.resources);
-            if (!IsArray(this.content)) {
-                // content is not an array, shortcut
-                content = xref.fetchIfRef(this.content);
-                this.code = gfx.compile(content, xref, resources, fonts);
-                return;
-            }
-            // the content is an array, compiling all items
-            var i, n = this.content.length, compiledItems = [];
-            for (i = 0; i < n; ++i) {
-                content = xref.fetchIfRef(this.content[i]);
-                compiledItems.push(gfx.compile(content, xref, resources, fonts));
-            }
-            // creating the function that executes all compiled items
-            this.code = function(gfx) {
-                var i, n = compiledItems.length;
-                for (i = 0; i < n; ++i) {
-                    compiledItems[i](gfx);
-                }
-            };
-        },
-        display: function(gfx) {
-            assert(this.code instanceof Function, "page content must be compiled first");
-            var xref = this.xref;
-            var resources = xref.fetchIfRef(this.resources);
-            var mediaBox = xref.fetchIfRef(this.mediaBox);
-            assertWellFormed(IsDict(resources), "invalid page resources");
-            gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
-                               width: mediaBox[2] - mediaBox[0],
-                               height: mediaBox[3] - mediaBox[1] });
-            gfx.execute(this.code, xref, resources);
-            gfx.endDrawing();
+      var xref = this.xref;
+      var content;
+      var resources = xref.fetchIfRef(this.resources);
+      if (!IsArray(this.content)) {
+        // content is not an array, shortcut
+        content = xref.fetchIfRef(this.content);
+        this.code = gfx.compile(content, xref, resources, fonts);
+        return;
+      }
+      // the content is an array, compiling all items
+      var i, n = this.content.length, compiledItems = [];
+      for (i = 0; i < n; ++i) {
+        content = xref.fetchIfRef(this.content[i]);
+        compiledItems.push(gfx.compile(content, xref, resources, fonts));
+      }
+      // creating the function that executes all compiled items
+      this.code = function(gfx) {
+        var i, n = compiledItems.length;
+        for (i = 0; i < n; ++i) {
+          compiledItems[i](gfx);
         }
-    };
+      };
+    },
+    display: function(gfx) {
+      assert(this.code instanceof Function,
+             'page content must be compiled first');
+      var xref = this.xref;
+      var resources = xref.fetchIfRef(this.resources);
+      var mediaBox = xref.fetchIfRef(this.mediaBox);
+      assertWellFormed(IsDict(resources), 'invalid page resources');
+      gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
+            width: mediaBox[2] - mediaBox[0],
+            height: mediaBox[3] - mediaBox[1] });
+      gfx.execute(this.code, xref, resources);
+      gfx.endDrawing();
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var Catalog = (function() {
-    function constructor(xref) {
-        this.xref = xref;
-        var obj = xref.getCatalogObj();
-        assertWellFormed(IsDict(obj), "catalog object is not a dictionary");
-        this.catDict = obj;
-    }
+  function constructor(xref) {
+    this.xref = xref;
+    var obj = xref.getCatalogObj();
+    assertWellFormed(IsDict(obj), 'catalog object is not a dictionary');
+    this.catDict = obj;
+  }
 
-    constructor.prototype = {
-        get toplevelPagesDict() {
-            var obj = this.catDict.get("Pages");
-            assertWellFormed(IsRef(obj), "invalid top-level pages reference");
-            var obj = this.xref.fetch(obj);
-            assertWellFormed(IsDict(obj), "invalid top-level pages dictionary");
-            // shadow the prototype getter
-            return shadow(this, "toplevelPagesDict", obj);
-        },
-        get numPages() {
-            var obj = this.toplevelPagesDict.get("Count");
-            assertWellFormed(IsInt(obj),
-                             "page count in top level pages object is not an integer");
-            // shadow the prototype getter
-            return shadow(this, "num", obj);
-        },
-        traverseKids: function(pagesDict) {
-            var pageCache = this.pageCache;
-            var kids = pagesDict.get("Kids");
-            assertWellFormed(IsArray(kids),
-                             "page dictionary kids object is not an array");
-            for (var i = 0; i < kids.length; ++i) {
-                var kid = kids[i];
-                assertWellFormed(IsRef(kid),
-                                 "page dictionary kid is not a reference");
-                var obj = this.xref.fetch(kid);
-                if (IsDict(obj, "Page") || (IsDict(obj) && !obj.has("Kids"))) {
-                    pageCache.push(new Page(this.xref, pageCache.length, obj));
-                } else { // must be a child page dictionary
-                    assertWellFormed(IsDict(obj),
-                                     "page dictionary kid reference points to wrong type of object");
-                    this.traverseKids(obj);
-                }
-            }
-        },
-        getPage: function(n) {
-            var pageCache = this.pageCache;
-            if (!pageCache) {
-                pageCache = this.pageCache = [];
-                this.traverseKids(this.toplevelPagesDict);
-            }
-            return this.pageCache[n-1];
+  constructor.prototype = {
+    get toplevelPagesDict() {
+      var obj = this.catDict.get('Pages');
+      assertWellFormed(IsRef(obj), 'invalid top-level pages reference');
+      var obj = this.xref.fetch(obj);
+      assertWellFormed(IsDict(obj), 'invalid top-level pages dictionary');
+      // shadow the prototype getter
+      return shadow(this, 'toplevelPagesDict', obj);
+    },
+    get numPages() {
+      var obj = this.toplevelPagesDict.get('Count');
+      assertWellFormed(
+        IsInt(obj),
+        'page count in top level pages object is not an integer'
+      );
+      // shadow the prototype getter
+      return shadow(this, 'num', obj);
+    },
+    traverseKids: function(pagesDict) {
+      var pageCache = this.pageCache;
+      var kids = pagesDict.get('Kids');
+      assertWellFormed(IsArray(kids),
+                       'page dictionary kids object is not an array');
+      for (var i = 0; i < kids.length; ++i) {
+        var kid = kids[i];
+        assertWellFormed(IsRef(kid),
+                         'page dictionary kid is not a reference');
+        var obj = this.xref.fetch(kid);
+        if (IsDict(obj, 'Page') || (IsDict(obj) && !obj.has('Kids'))) {
+          pageCache.push(new Page(this.xref, pageCache.length, obj));
+        } else { // must be a child page dictionary
+          assertWellFormed(
+            IsDict(obj),
+            'page dictionary kid reference points to wrong type of object'
+          );
+          this.traverseKids(obj);
         }
-    };
+      }
+    },
+    getPage: function(n) {
+      var pageCache = this.pageCache;
+      if (!pageCache) {
+        pageCache = this.pageCache = [];
+        this.traverseKids(this.toplevelPagesDict);
+      }
+      return this.pageCache[n - 1];
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var PDFDoc = (function() {
-    function constructor(stream) {
-        assertWellFormed(stream.length > 0, "stream must have data");
-        this.stream = stream;
-        this.setup();
-    }
+  function constructor(stream) {
+    assertWellFormed(stream.length > 0, 'stream must have data');
+    this.stream = stream;
+    this.setup();
+  }
 
-    function find(stream, needle, limit, backwards) {
-        var pos = stream.pos;
-        var end = stream.end;
-        var str = "";
-        if (pos + limit > end)
-            limit = end - pos;
-        for (var n = 0; n < limit; ++n)
-            str += stream.getChar();
-        stream.pos = pos;
-        var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
-        if (index == -1)
-            return false; /* not found */
-        stream.pos += index;
-        return true; /* found */
-    }
+  function find(stream, needle, limit, backwards) {
+    var pos = stream.pos;
+    var end = stream.end;
+    var str = '';
+    if (pos + limit > end)
+      limit = end - pos;
+    for (var n = 0; n < limit; ++n)
+      str += stream.getChar();
+    stream.pos = pos;
+    var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
+    if (index == -1)
+      return false; /* not found */
+    stream.pos += index;
+    return true; /* found */
+  }
 
-    constructor.prototype = {
-        get linearization() {
-            var length = this.stream.length;
-            var linearization = false;
-            if (length) {
-                linearization = new Linearization(this.stream);
-                if (linearization.length != length)
-                    linearization = false;
-            }
-            // shadow the prototype getter with a data property
-            return shadow(this, "linearization", linearization);
-        },
-        get startXRef() {
-            var stream = this.stream;
-            var startXRef = 0;
-            var linearization = this.linearization;
-            if (linearization) {
-                // Find end of first obj.
-                stream.reset();
-                if (find(stream, "endobj", 1024))
-                    startXRef = stream.pos + 6;
-            } else {
-                // Find startxref at the end of the file.
-                var start = stream.end - 1024;
-                if (start < 0)
-                    start = 0;
-                stream.pos = start;
-                if (find(stream, "startxref", 1024, true)) {
-                    stream.skip(9);
-                    var ch;
-                    while (Lexer.isSpace(ch = stream.getChar()))
-                        ;
-                    var str = "";
-                    while ((ch - "0") <= 9) {
-                        str += ch;
-                        ch = stream.getChar();
-                    }
-                    startXRef = parseInt(str);
-                    if (isNaN(startXRef))
-                        startXRef = 0;
-                }
-            }
-            // shadow the prototype getter with a data property
-            return shadow(this, "startXRef", startXRef);
-        },
-        get mainXRefEntriesOffset() {
-            var mainXRefEntriesOffset = 0;
-            var linearization = this.linearization;
-            if (linearization)
-                mainXRefEntriesOffset = linearization.mainXRefEntriesOffset;
-            // shadow the prototype getter with a data property
-            return shadow(this, "mainXRefEntriesOffset", mainXRefEntriesOffset);
-        },
-        // Find the header, remove leading garbage and setup the stream
-        // starting from the header.
-        checkHeader: function() {
-            var stream = this.stream;
-            stream.reset();
-            if (find(stream, "%PDF-", 1024)) {
-                // Found the header, trim off any garbage before it.
-                stream.moveStart();
-                return;
-            }
-            // May not be a PDF file, continue anyway.
-        },
-        setup: function(ownerPassword, userPassword) {
-            this.checkHeader();
-            this.xref = new XRef(this.stream,
-                                 this.startXRef,
-                                 this.mainXRefEntriesOffset);
-            this.catalog = new Catalog(this.xref);
-        },
-        get numPages() {
-            var linearization = this.linearization;
-            var num = linearization
-                      ? linearization.numPages
-                      : this.catalog.numPages;
-            // shadow the prototype getter
-            return shadow(this, "numPages", num);
-        },
-        getPage: function(n) {
-            var linearization = this.linearization;
-            // assert(!linearization, "linearized page access not implemented");
-            return this.catalog.getPage(n);
+  constructor.prototype = {
+    get linearization() {
+      var length = this.stream.length;
+      var linearization = false;
+      if (length) {
+        linearization = new Linearization(this.stream);
+        if (linearization.length != length)
+          linearization = false;
+      }
+      // shadow the prototype getter with a data property
+      return shadow(this, 'linearization', linearization);
+    },
+    get startXRef() {
+      var stream = this.stream;
+      var startXRef = 0;
+      var linearization = this.linearization;
+      if (linearization) {
+        // Find end of first obj.
+        stream.reset();
+        if (find(stream, 'endobj', 1024))
+          startXRef = stream.pos + 6;
+      } else {
+        // Find startxref at the end of the file.
+        var start = stream.end - 1024;
+        if (start < 0)
+          start = 0;
+        stream.pos = start;
+        if (find(stream, 'startxref', 1024, true)) {
+          stream.skip(9);
+          var ch;
+          while (Lexer.isSpace(ch = stream.getChar()))
+;
+          var str = '';
+          while ((ch - '0') <= 9) {
+            str += ch;
+            ch = stream.getChar();
+          }
+          startXRef = parseInt(str);
+          if (isNaN(startXRef))
+            startXRef = 0;
         }
-    };
+      }
+      // shadow the prototype getter with a data property
+      return shadow(this, 'startXRef', startXRef);
+    },
+    get mainXRefEntriesOffset() {
+      var mainXRefEntriesOffset = 0;
+      var linearization = this.linearization;
+      if (linearization)
+        mainXRefEntriesOffset = linearization.mainXRefEntriesOffset;
+      // shadow the prototype getter with a data property
+      return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset);
+    },
+    // Find the header, remove leading garbage and setup the stream
+    // starting from the header.
+    checkHeader: function() {
+      var stream = this.stream;
+      stream.reset();
+      if (find(stream, '%PDF-', 1024)) {
+        // Found the header, trim off any garbage before it.
+        stream.moveStart();
+        return;
+      }
+      // May not be a PDF file, continue anyway.
+    },
+    setup: function(ownerPassword, userPassword) {
+      this.checkHeader();
+      this.xref = new XRef(this.stream,
+                           this.startXRef,
+                           this.mainXRefEntriesOffset);
+      this.catalog = new Catalog(this.xref);
+    },
+    get numPages() {
+      var linearization = this.linearization;
+      var num = linearization ? linearization.numPages : this.catalog.numPages;
+      // shadow the prototype getter
+      return shadow(this, 'numPages', num);
+    },
+    getPage: function(n) {
+      var linearization = this.linearization;
+      // assert(!linearization, "linearized page access not implemented");
+      return this.catalog.getPage(n);
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var Encodings = {
   get ExpertEncoding() {
-    return shadow(this, "ExpertEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
-      "space","exclamsmall","Hungarumlautsmall",,"dollaroldstyle","dollarsuperior",
-      "ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior",
-      "twodotenleader","onedotenleader","comma","hyphen","period","fraction",
-      "zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle",
-      "fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle",
-      "colon","semicolon","commasuperior","threequartersemdash","periodsuperior",
-      "questionsmall",,"asuperior","bsuperior","centsuperior","dsuperior","esuperior",,,
-      "isuperior",,,"lsuperior","msuperior","nsuperior","osuperior",,,"rsuperior",
-      "ssuperior","tsuperior",,"ff","fi","fl","ffi","ffl","parenleftinferior",,
-      "parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall","Asmall",
-      "Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall",
-      "Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall",
-      "Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary",
-      "onefitted","rupiah","Tildesmall",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
-      "exclamdownsmall","centoldstyle","Lslashsmall",,,"Scaronsmall","Zcaronsmall",
-      "Dieresissmall","Brevesmall","Caronsmall",,"Dotaccentsmall",,,"Macronsmall",,,
-      "figuredash","hypheninferior",,,"Ogoneksmall","Ringsmall","Cedillasmall",,,,
-      "onequarter","onehalf","threequarters","questiondownsmall","oneeighth",
-      "threeeighths","fiveeighths","seveneighths","onethird","twothirds",,,
-      "zerosuperior","onesuperior","twosuperior","threesuperior","foursuperior",
-      "fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior",
-      "zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior",
-      "fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior",
-      "centinferior","dollarinferior","periodinferior","commainferior","Agravesmall",
-      "Aacutesmall","Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall",
-      "AEsmall","Ccedillasmall","Egravesmall","Eacutesmall","Ecircumflexsmall",
-      "Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall",
-      "Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall",
-      "Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall",
-      "Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall","Thornsmall",
-      "Ydieresissmall"
+    return shadow(this, 'ExpertEncoding', [,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+      'space', 'exclamsmall', 'Hungarumlautsmall',, 'dollaroldstyle',
+      'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
+      'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
+      'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
+      'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
+      'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
+      'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior',
+      'questionsmall',, 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior',
+      'esuperior',,, 'isuperior',,, 'lsuperior', 'msuperior', 'nsuperior',
+      'osuperior',,, 'rsuperior', 'ssuperior', 'tsuperior',, 'ff', 'fi', 'fl',
+      'ffi', 'ffl', 'parenleftinferior',, 'parenrightinferior',
+      'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall',
+      'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
+      'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
+      'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
+      'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
+      'Tildesmall',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 'exclamdownsmall',
+      'centoldstyle', 'Lslashsmall',,, 'Scaronsmall', 'Zcaronsmall',
+      'Dieresissmall', 'Brevesmall', 'Caronsmall',, 'Dotaccentsmall',,,
+      'Macronsmall',,, 'figuredash', 'hypheninferior',,, 'Ogoneksmall',
+      'Ringsmall', 'Cedillasmall',,,, 'onequarter', 'onehalf', 'threequarters',
+      'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
+      'seveneighths', 'onethird', 'twothirds',,, 'zerosuperior', 'onesuperior',
+      'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
+      'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
+      'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
+      'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
+      'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
+      'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
+      'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall',
+      'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
+      'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
+      'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
+      'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
+      'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
+      'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
+      'Ydieresissmall'
     ]);
   },
   get MacExpertEncoding() {
-    return shadow(this, "MacExpertEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
-      "space","exclamsmall","Hungarumlautsmall","centoldstyle","dollaroldstyle",
-      "dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior",
-      "parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period",
-      "fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle",
-      "fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle",
-      "nineoldstyle","colon","semicolon",,"threequartersemdash",,"questionsmall",,,,,
-      "Ethsmall",,,"onequarter","onehalf","threequarters","oneeighth","threeeighths",
-      "fiveeighths","seveneighths","onethird","twothirds",,,,,,,"ff","fi","fl","ffi",
-      "ffl","parenleftinferior",,"parenrightinferior","Circumflexsmall",
-      "hypheninferior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall",
-      "Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall",
-      "Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall",
-      "Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall",,,
-      "asuperior","centsuperior",,,,,"Aacutesmall","Agravesmall","Acircumflexsmall",
-      "Adieresissmall","Atildesmall","Aringsmall","Ccedillasmall","Eacutesmall",
-      "Egravesmall","Ecircumflexsmall","Edieresissmall","Iacutesmall","Igravesmall",
-      "Icircumflexsmall","Idieresissmall","Ntildesmall","Oacutesmall","Ogravesmall",
-      "Ocircumflexsmall","Odieresissmall","Otildesmall","Uacutesmall","Ugravesmall",
-      "Ucircumflexsmall","Udieresissmall",,"eightsuperior","fourinferior",
-      "threeinferior","sixinferior","eightinferior","seveninferior","Scaronsmall",,
-      "centinferior","twoinferior",,"Dieresissmall",,"Caronsmall","osuperior",
-      "fiveinferior",,"commainferior","periodinferior","Yacutesmall",,"dollarinferior",,
-      "Thornsmall",,"nineinferior","zeroinferior","Zcaronsmall","AEsmall","Oslashsmall",
-      "questiondownsmall","oneinferior","Lslashsmall",,,,,,,"Cedillasmall",,,,,,
-      "OEsmall","figuredash","hyphensuperior",,,,,"exclamdownsmall",,"Ydieresissmall",,
-      "onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior",
-      "sixsuperior","sevensuperior","ninesuperior","zerosuperior",,"esuperior",
-      "rsuperior","tsuperior",,,"isuperior","ssuperior","dsuperior",,,,,,"lsuperior",
-      "Ogoneksmall","Brevesmall","Macronsmall","bsuperior","nsuperior","msuperior",
-      "commasuperior","periodsuperior","Dotaccentsmall","Ringsmall",,,
+    return shadow(this, 'MacExpertEncoding', [,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+      'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle',
+      'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
+      'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
+      'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
+      'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
+      'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
+      'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon',,
+      'threequartersemdash',, 'questionsmall',,,,, 'Ethsmall',,, 'onequarter',
+      'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
+      'seveneighths', 'onethird', 'twothirds',,,,,,, 'ff', 'fi', 'fl', 'ffi',
+      'ffl', 'parenleftinferior',, 'parenrightinferior', 'Circumflexsmall',
+      'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall',
+      'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall',
+      'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall',
+      'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall',
+      'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall',,,
+      'asuperior', 'centsuperior',,,,, 'Aacutesmall', 'Agravesmall',
+      'Acircumflexsmall', 'Adieresissmall', 'Atildesmall', 'Aringsmall',
+      'Ccedillasmall', 'Eacutesmall', 'Egravesmall', 'Ecircumflexsmall',
+      'Edieresissmall', 'Iacutesmall', 'Igravesmall', 'Icircumflexsmall',
+      'Idieresissmall', 'Ntildesmall', 'Oacutesmall', 'Ogravesmall',
+      'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall', 'Uacutesmall',
+      'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall',, 'eightsuperior',
+      'fourinferior', 'threeinferior', 'sixinferior', 'eightinferior',
+      'seveninferior', 'Scaronsmall',, 'centinferior', 'twoinferior',,
+      'Dieresissmall',, 'Caronsmall', 'osuperior', 'fiveinferior',,
+      'commainferior', 'periodinferior', 'Yacutesmall',, 'dollarinferior',,
+      'Thornsmall',, 'nineinferior', 'zeroinferior', 'Zcaronsmall', 'AEsmall',
+      'Oslashsmall', 'questiondownsmall', 'oneinferior', 'Lslashsmall',,,,,,,
+      'Cedillasmall',,,,,, 'OEsmall', 'figuredash', 'hyphensuperior',,,,,
+      'exclamdownsmall',, 'Ydieresissmall',, 'onesuperior', 'twosuperior',
+      'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
+      'sevensuperior', 'ninesuperior', 'zerosuperior',, 'esuperior',
+      'rsuperior', 'tsuperior',,, 'isuperior', 'ssuperior', 'dsuperior',,,,,,
+      'lsuperior', 'Ogoneksmall', 'Brevesmall', 'Macronsmall', 'bsuperior',
+      'nsuperior', 'msuperior', 'commasuperior', 'periodsuperior',
+      'Dotaccentsmall', 'Ringsmall'
     ]);
   },
   get MacRomanEncoding() {
-    return shadow(this, "MacRomanEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
-      "space","exclam","quotedbl","numbersign","dollar","percent","ampersand",
-      "quotesingle","parenleft","parenright","asterisk","plus","comma","hyphen",
-      "period","slash","zero","one","two","three","four","five","six","seven","eight",
-      "nine","colon","semicolon","less","equal","greater","question","at","A","B","C",
-      "D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W",
-      "X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore",
-      "grave","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r",
-      "s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde",,
-      "Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis","aacute",
-      "agrave","acircumflex","adieresis","atilde","aring","ccedilla","eacute","egrave",
-      "ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis","ntilde",
-      "oacute","ograve","ocircumflex","odieresis","otilde","uacute","ugrave",
-      "ucircumflex","udieresis","dagger","degree","cent","sterling","section","bullet",
-      "paragraph","germandbls","registered","copyright","trademark","acute","dieresis",
-      "notequal","AE","Oslash","infinity","plusminus","lessequal","greaterequal","yen",
-      "mu","partialdiff","summation","product","pi","integral","ordfeminine",
-      "ordmasculine","Omega","ae","oslash","questiondown","exclamdown","logicalnot",
-      "radical","florin","approxequal","Delta","guillemotleft","guillemotright",
-      "ellipsis","space","Agrave","Atilde","Otilde","OE","oe","endash","emdash",
-      "quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge",
-      "ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright",
-      "fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase",
-      "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave","Iacute",
-      "Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple","Ograve",
-      "Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde","macron","breve",
-      "dotaccent","ring","cedilla","hungarumlaut","ogonek","caron"
+    return shadow(this, 'MacRomanEncoding', [,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+      'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+      'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk',
+      'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
+      'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon',
+      'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C',
+      'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
+      'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash',
+      'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd',
+      'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
+      's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
+      'asciitilde',, 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde',
+      'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis',
+      'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex',
+      'edieresis', 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde',
+      'oacute', 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute',
+      'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent',
+      'sterling', 'section', 'bullet', 'paragraph', 'germandbls', 'registered',
+      'copyright', 'trademark', 'acute', 'dieresis', 'notequal', 'AE',
+      'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen',
+      'mu', 'partialdiff', 'summation', 'product', 'pi', 'integral',
+      'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown',
+      'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta',
+      'guillemotleft', 'guillemotright', 'ellipsis', 'space', 'Agrave',
+      'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft',
+      'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge',
+      'ydieresis', 'Ydieresis', 'fraction', 'currency', 'guilsinglleft',
+      'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered',
+      'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex',
+      'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex',
+      'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve',
+      'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde',
+      'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
+      'ogonek', 'caron'
     ]);
   },
   get StandardEncoding() {
-    return shadow(this, "StandardEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
-      "space","exclam","quotedbl","numbersign","dollar","percent","ampersand",
-      "quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period",
-      "slash","zero","one","two","three","four","five","six","seven","eight","nine",
-      "colon","semicolon","less","equal","greater","question","at","A","B","C","D","E",
-      "F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y",
-      "Z","bracketleft","backslash","bracketright","asciicircum","underscore",
-      "quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q",
-      "r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde",,,
-      "exclamdown","cent","sterling","fraction","yen","florin","section","currency",
-      "quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright",
-      "fi","fl",,"endash","dagger","daggerdbl","periodcentered",,"paragraph","bullet",
-      "quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis",
-      "perthousand",,"questiondown",,"grave","acute","circumflex","tilde","macron",
-      "breve","dotaccent","dieresis",,"ring","cedilla",,"hungarumlaut","ogonek","caron",
-      "emdash",,,,,,,,,,,,,,,,,"AE",,"ordfeminine",,,,,"Lslash","Oslash","OE",
-      "ordmasculine",,,,,,"ae",,,,"dotlessi",,,"lslash","oslash","oe","germandbls",,,
+    return shadow(this, 'StandardEncoding', [,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+      'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+      'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk',
+      'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
+      'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon',
+      'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B',
+      'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+      'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft',
+      'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft',
+      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+      'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft',
+      'bar', 'braceright', 'asciitilde',,, 'exclamdown', 'cent', 'sterling',
+      'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',
+      'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi',
+      'fl',, 'endash', 'dagger', 'daggerdbl', 'periodcentered',, 'paragraph',
+      'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright',
+      'guillemotright', 'ellipsis', 'perthousand',, 'questiondown',, 'grave',
+      'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent',
+      'dieresis',, 'ring', 'cedilla',, 'hungarumlaut', 'ogonek', 'caron',
+      'emdash',,,,,,,,,,,,,,,,, 'AE',, 'ordfeminine',,,,, 'Lslash', 'Oslash',
+      'OE', 'ordmasculine',,,,,, 'ae',,,, 'dotlessi',,, 'lslash', 'oslash',
+      'oe', 'germandbls'
     ]);
   },
   get WinAnsiEncoding() {
-    return shadow(this, "WinAnsiEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
-      "space","exclam","quotedbl","numbersign","dollar","percent","ampersand",
-      "quotesingle","parenleft","parenright","asterisk","plus","comma","hyphen",
-      "period","slash","zero","one","two","three","four","five","six","seven","eight",
-      "nine","colon","semicolon","less","equal","greater","question","at","A","B","C",
-      "D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W",
-      "X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore",
-      "grave","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r",
-      "s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde",
-      "bullet","Euro","bullet","quotesinglbase","florin","quotedblbase","ellipsis",
-      "dagger","daggerdbl","circumflex","perthousand","Scaron","guilsinglleft","OE",
-      "bullet","Zcaron","bullet","bullet","quoteleft","quoteright","quotedblleft",
-      "quotedblright","bullet","endash","emdash","tilde","trademark","scaron",
-      "guilsinglright","oe","bullet","zcaron","Ydieresis","space","exclamdown","cent",
-      "sterling","currency","yen","brokenbar","section","dieresis","copyright",
-      "ordfeminine","guillemotleft","logicalnot","hyphen","registered","macron",
-      "degree","plusminus","twosuperior","threesuperior","acute","mu","paragraph",
-      "periodcentered","cedilla","onesuperior","ordmasculine","guillemotright",
-      "onequarter","onehalf","threequarters","questiondown","Agrave","Aacute",
-      "Acircumflex","Atilde","Adieresis","Aring","AE","Ccedilla","Egrave","Eacute",
-      "Ecircumflex","Edieresis","Igrave","Iacute","Icircumflex","Idieresis","Eth",
-      "Ntilde","Ograve","Oacute","Ocircumflex","Otilde","Odieresis","multiply","Oslash",
-      "Ugrave","Uacute","Ucircumflex","Udieresis","Yacute","Thorn","germandbls",
-      "agrave","aacute","acircumflex","atilde","adieresis","aring","ae","ccedilla",
-      "egrave","eacute","ecircumflex","edieresis","igrave","iacute","icircumflex",
-      "idieresis","eth","ntilde","ograve","oacute","ocircumflex","otilde","odieresis",
-      "divide","oslash","ugrave","uacute","ucircumflex","udieresis","yacute","thorn",
-      "ydieresis"
+    return shadow(this, 'WinAnsiEncoding',
+     [,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+      'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+      'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk',
+      'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
+      'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon',
+      'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C',
+      'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
+      'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash',
+      'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd',
+      'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
+      's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
+      'asciitilde', 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin',
+      'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'circumflex',
+      'perthousand', 'Scaron', 'guilsinglleft', 'OE', 'bullet', 'Zcaron',
+      'bullet', 'bullet', 'quoteleft', 'quoteright', 'quotedblleft',
+      'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark',
+      'scaron', 'guilsinglright', 'oe', 'bullet', 'zcaron', 'Ydieresis',
+      'space', 'exclamdown', 'cent', 'sterling', 'currency', 'yen', 'brokenbar',
+      'section', 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft',
+      'logicalnot', 'hyphen', 'registered', 'macron', 'degree', 'plusminus',
+      'twosuperior', 'threesuperior', 'acute', 'mu', 'paragraph',
+      'periodcentered', 'cedilla', 'onesuperior', 'ordmasculine',
+      'guillemotright', 'onequarter', 'onehalf', 'threequarters',
+      'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis',
+      'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex',
+      'Edieresis', 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth',
+      'Ntilde', 'Ograve', 'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis',
+      'multiply', 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis',
+      'Yacute', 'Thorn', 'germandbls', 'agrave', 'aacute', 'acircumflex',
+      'atilde', 'adieresis', 'aring', 'ae', 'ccedilla', 'egrave', 'eacute',
+      'ecircumflex', 'edieresis', 'igrave', 'iacute', 'icircumflex',
+      'idieresis', 'eth', 'ntilde', 'ograve', 'oacute', 'ocircumflex',
+      'otilde', 'odieresis', 'divide', 'oslash', 'ugrave', 'uacute',
+      'ucircumflex', 'udieresis', 'yacute', 'thorn', 'ydieresis'
     ]);
   },
   get zapfDingbatsEncoding() {
-    return shadow(this, "zapfDingbatsEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
-      "space","a1","a2","a202","a3","a4","a5","a119","a118","a117","a11","a12","a13",
-      "a14","a15","a16","a105","a17","a18","a19","a20","a21","a22","a23","a24","a25",
-      "a26","a27","a28","a6","a7","a8","a9","a10","a29","a30","a31","a32","a33","a34",
-      "a35","a36","a37","a38","a39","a40","a41","a42","a43","a44","a45","a46","a47",
-      "a48","a49","a50","a51","a52","a53","a54","a55","a56","a57","a58","a59","a60",
-      "a61","a62","a63","a64","a65","a66","a67","a68","a69","a70","a71","a72","a73",
-      "a74","a203","a75","a204","a76","a77","a78","a79","a81","a82","a83","a84","a97",
-      "a98","a99","a100",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"a101","a102","a103","a104",
-      "a106","a107","a108","a112","a111","a110","a109","a120","a121","a122","a123",
-      "a124","a125","a126","a127","a128","a129","a130","a131","a132","a133","a134",
-      "a135","a136","a137","a138","a139","a140","a141","a142","a143","a144","a145",
-      "a146","a147","a148","a149","a150","a151","a152","a153","a154","a155","a156",
-      "a157","a158","a159","a160","a161","a163","a164","a196","a165","a192","a166",
-      "a167","a168","a169","a170","a171","a172","a173","a162","a174","a175","a176",
-      "a177","a178","a179","a193","a180","a199","a181","a200","a182",,"a201","a183",
-      "a184","a197","a185","a194","a198","a186","a195","a187","a188","a189","a190",
-      "a191"
+    return shadow(this, 'zapfDingbatsEncoding',
+      [,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+      'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117',
+      'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19',
+      'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6',
+      'a7', 'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35',
+      'a36', 'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45',
+      'a46', 'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55',
+      'a56', 'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65',
+      'a66', 'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203',
+      'a75', 'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84',
+      'a97', 'a98', 'a99', 'a100',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 'a101',
+      'a102', 'a103', 'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110',
+      'a109', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127',
+      'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136',
+      'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145',
+      'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154',
+      'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164',
+      'a196', 'a165', 'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171',
+      'a172', 'a173', 'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179',
+      'a193', 'a180', 'a199', 'a181', 'a200', 'a182',, 'a201', 'a183', 'a184',
+      'a197', 'a185', 'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189',
+      'a190', 'a191'
     ]);
   }
 };
 
-var IDENTITY_MATRIX = [ 1, 0, 0, 1, 0, 0 ];
+var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
 
 // <canvas> contexts store most of the state we need natively.
 // However, PDF needs a bit more state, which we store here.
 var CanvasExtraState = (function() {
-    function constructor() {
-        // Are soft masks and alpha values shapes or opacities?
-        this.alphaIsShape = false;
-        this.fontSize = 0;
-        this.textMatrix = IDENTITY_MATRIX;
-        this.leading = 0;
-        // Current point (in user coordinates)
-        this.x = 0;
-        this.y = 0;
-        // Start of text line (in text coordinates)
-        this.lineX = 0;
-        this.lineY = 0;
-        // Character and word spacing
-        this.charSpace = 0;
-        this.wordSpace = 0;
-        this.textHScale = 100;
-        // Color spaces
-        this.fillColorSpace = null;
-        this.strokeColorSpace = null;
-    }
-    constructor.prototype = {
-    };
-    return constructor;
+  function constructor() {
+    // Are soft masks and alpha values shapes or opacities?
+    this.alphaIsShape = false;
+    this.fontSize = 0;
+    this.textMatrix = IDENTITY_MATRIX;
+    this.leading = 0;
+    // Current point (in user coordinates)
+    this.x = 0;
+    this.y = 0;
+    // Start of text line (in text coordinates)
+    this.lineX = 0;
+    this.lineY = 0;
+    // Character and word spacing
+    this.charSpace = 0;
+    this.wordSpace = 0;
+    this.textHScale = 100;
+    // Color spaces
+    this.fillColorSpace = null;
+    this.strokeColorSpace = null;
+  }
+  constructor.prototype = {
+  };
+  return constructor;
 })();
 
 function ScratchCanvas(width, height) {
-    var canvas = document.createElement("canvas");
-    canvas.width = width;
-    canvas.height = height;
-    return canvas;
+  var canvas = document.createElement('canvas');
+  canvas.width = width;
+  canvas.height = height;
+  return canvas;
 }
 
 var CanvasGraphics = (function() {
-    function constructor(canvasCtx, imageCanvas) {
-        this.ctx = canvasCtx;
-        this.current = new CanvasExtraState();
-        this.stateStack = [ ];
-        this.pendingClip = null;
-        this.res = null;
-        this.xobjs = null;
-        this.ScratchCanvas = imageCanvas || ScratchCanvas;
-    }
+  function constructor(canvasCtx, imageCanvas) {
+    this.ctx = canvasCtx;
+    this.current = new CanvasExtraState();
+    this.stateStack = [];
+    this.pendingClip = null;
+    this.res = null;
+    this.xobjs = null;
+    this.ScratchCanvas = imageCanvas || ScratchCanvas;
+  }
 
-    var LINE_CAP_STYLES = [ "butt", "round", "square" ];
-    var LINE_JOIN_STYLES = [ "miter", "round", "bevel" ];
-    var NORMAL_CLIP = {};
-    var EO_CLIP = {};
-
-    // Used for tiling patterns
-    var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
-
-    constructor.prototype = {
-        map: {
-            // Graphics state
-            w: "setLineWidth",
-            J: "setLineCap",
-            j: "setLineJoin",
-            M: "setMiterLimit",
-            d: "setDash",
-            ri: "setRenderingIntent",
-            i: "setFlatness",
-            gs: "setGState",
-            q: "save",
-            Q: "restore",
-            cm: "transform",
-
-            // Path
-            m: "moveTo",
-            l: "lineTo",
-            c: "curveTo",
-            v: "curveTo2",
-            y: "curveTo3",
-            h: "closePath",
-            re: "rectangle",
-            S: "stroke",
-            s: "closeStroke",
-            f: "fill",
-            F: "fill",
-            "f*": "eoFill",
-            B: "fillStroke",
-            "B*": "eoFillStroke",
-            b: "closeFillStroke",
-            "b*": "closeEOFillStroke",
-            n: "endPath",
-
-            // Clipping
-            W: "clip",
-            "W*": "eoClip",
-
-            // Text
-            BT: "beginText",
-            ET: "endText",
-            Tc: "setCharSpacing",
-            Tw: "setWordSpacing",
-            Tz: "setHScale",
-            TL: "setLeading",
-            Tf: "setFont",
-            Tr: "setTextRenderingMode",
-            Ts: "setTextRise",
-            Td: "moveText",
-            TD: "setLeadingMoveText",
-            Tm: "setTextMatrix",
-            "T*": "nextLine",
-            Tj: "showText",
-            TJ: "showSpacedText",
-            "'": "nextLineShowText",
-            '"': "nextLineSetSpacingShowText",
-
-            // Type3 fonts
-            d0: "setCharWidth",
-            d1: "setCharWidthAndBounds",
-
-            // Color
-            CS: "setStrokeColorSpace",
-            cs: "setFillColorSpace",
-            SC: "setStrokeColor",
-            SCN: "setStrokeColorN",
-            sc: "setFillColor",
-            scn: "setFillColorN",
-            G: "setStrokeGray",
-            g: "setFillGray",
-            RG: "setStrokeRGBColor",
-            rg: "setFillRGBColor",
-            K: "setStrokeCMYKColor",
-            k: "setFillCMYKColor",
-
-            // Shading
-            sh: "shadingFill",
-
-            // Images
-            BI: "beginInlineImage",
-
-            // XObjects
-            Do: "paintXObject",
-
-            // Marked content
-            MP: "markPoint",
-            DP: "markPointProps",
-            BMC: "beginMarkedContent",
-            BDC: "beginMarkedContentProps",
-            EMC: "endMarkedContent",
-
-            // Compatibility
-            BX: "beginCompat",
-            EX: "endCompat",
-        },
-
-        translateFont: function(fontDict, xref, resources) {
-            var fd = fontDict.get("FontDescriptor");
-            if (!fd)
-                // XXX deprecated "special treatment" for standard
-                // fonts?  What do we need to do here?
-                return null;
-            var descriptor = xref.fetch(fd);
-
-            var fontName = descriptor.get("FontName");
-            assertWellFormed(IsName(fontName), "invalid font name");
-            fontName = fontName.name.replace("+", "_");
-
-            var fontFile = descriptor.get3("FontFile", "FontFile2", "FontFile3");
-            if (!fontFile)
-                error("FontFile not found for font: " + fontName);
-            fontFile = xref.fetchIfRef(fontFile);
-
-            var encodingMap = {};
-            var charset = [];
-            if (fontDict.has("Encoding")) {
-                var encoding = xref.fetchIfRef(fontDict.get("Encoding"));
-                if (IsDict(encoding)) {
-                    // Build a map between codes and glyphs
-                    var differences = encoding.get("Differences");
-                    var index = 0;
-                    for (var j = 0; j < differences.length; j++) {
-                        var data = differences[j];
-                        IsNum(data) ? index = data : encodingMap[index++] = data;
-                    }
-
-                    // Get the font charset if any
-                    var charset = descriptor.get("CharSet");
-                    if (charset) {
-                        assertWellFormed(IsString(charset), "invalid charset");
-                        charset = charset.split("/");
-                        charset.shift();
-                    }
-                } else if (IsName(encoding)) {
-                    var encoding = Encodings[encoding.name];
-                    if (!encoding)
-                        error("Unknown font encoding");
-
-                    var index = 0;
-                    for (var j = 0; j < encoding.length; j++)
-                        encodingMap[index++] = GlyphsUnicode[encoding[j]];
-
-                    var firstChar = xref.fetchIfRef(fontDict.get("FirstChar"));
-                    var widths = xref.fetchIfRef(fontDict.get("Widths"));
-                    assertWellFormed(IsArray(widths) && IsInt(firstChar),
-                                     "invalid font Widths or FirstChar");
-
-                    for (var j = 0; j < widths.length; j++) {
-                        if (widths[j])
-                            charset.push(encoding[j + firstChar]);
-                    }
-                }
-            } else if (fontDict.has("ToUnicode")) {
-                encodingMap = {empty: true};
-                var cmapObj = xref.fetchIfRef(fontDict.get("ToUnicode"));
-                if (IsName(cmapObj)) {
-                    error("ToUnicode file cmap translation not implemented");
-                } else if (IsStream(cmapObj)) {
-                    var encoding = Encodings["WinAnsiEncoding"];
-                    var firstChar = xref.fetchIfRef(fontDict.get("FirstChar"));
-
-                    var tokens = [];
-                    var token = "";
-
-                    var cmap = cmapObj.getBytes(cmapObj.length);
-                    for (var i =0; i < cmap.length; i++) {
-                      var byte = cmap[i];
-                      if (byte == 0x20 || byte == 0x0A || byte == 0x3C || byte == 0x3E) {
-                        switch (token) {
-                          case "useCMap":
-                            error("useCMap is not implemented");
-                            break;
-
-                          case "beginbfrange":
-                          case "begincodespacerange":
-                            token = "";
-                            tokens = [];
-                            break;
-
-                          case "endcodespacerange":
-                            TODO("Support CMap ranges");
-                            break;
-
-                          case "endbfrange":
-                            for (var j = 0; j < tokens.length; j+=3) {
-                              var startRange = parseInt("0x" + tokens[j]);
-                              var endRange = parseInt("0x" + tokens[j+1]);
-                              var code = parseInt("0x" + tokens[j+2]);
-
-                              for (var k = startRange; k <= endRange; k++) {
-                                // The encoding mapping table will be filled
-                                // later during the building phase
-                                //encodingMap[k] = GlyphsUnicode[encoding[code]];
-                                charset.push(encoding[code++] || ".notdef");
-                              }
-                            }
-                            break;
-
-                          case "beginfbchar":
-                          case "endfbchar":
-                            error("fbchar parsing is not implemented");
-                            break;
-
-                          default:
-                            if (token.length) {
-                              tokens.push(token);
-                              token = "";
-                            }
-                            break;
-                        }
-                    } else if (byte == 0x5B || byte == 0x5D) {
-                        error("CMAP list parsing is not implemented");
-                    } else {
-                        token += String.fromCharCode(byte);
-                    }
-                  }
-               }
-            }
+  var LINE_CAP_STYLES = ['butt', 'round', 'square'];
+  var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
+  var NORMAL_CLIP = {};
+  var EO_CLIP = {};
+
+  // Used for tiling patterns
+  var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
+
+  constructor.prototype = {
+    map: {
+      // Graphics state
+      w: 'setLineWidth',
+      J: 'setLineCap',
+      j: 'setLineJoin',
+      M: 'setMiterLimit',
+      d: 'setDash',
+      ri: 'setRenderingIntent',
+      i: 'setFlatness',
+      gs: 'setGState',
+      q: 'save',
+      Q: 'restore',
+      cm: 'transform',
+
+      // Path
+      m: 'moveTo',
+      l: 'lineTo',
+      c: 'curveTo',
+      v: 'curveTo2',
+      y: 'curveTo3',
+      h: 'closePath',
+      re: 'rectangle',
+      S: 'stroke',
+      s: 'closeStroke',
+      f: 'fill',
+      F: 'fill',
+      'f*': 'eoFill',
+      B: 'fillStroke',
+      'B*': 'eoFillStroke',
+      b: 'closeFillStroke',
+      'b*': 'closeEOFillStroke',
+      n: 'endPath',
+
+      // Clipping
+      W: 'clip',
+      'W*': 'eoClip',
+
+      // Text
+      BT: 'beginText',
+      ET: 'endText',
+      Tc: 'setCharSpacing',
+      Tw: 'setWordSpacing',
+      Tz: 'setHScale',
+      TL: 'setLeading',
+      Tf: 'setFont',
+      Tr: 'setTextRenderingMode',
+      Ts: 'setTextRise',
+      Td: 'moveText',
+      TD: 'setLeadingMoveText',
+      Tm: 'setTextMatrix',
+      'T*': 'nextLine',
+      Tj: 'showText',
+      TJ: 'showSpacedText',
+      "'": 'nextLineShowText',
+      '"': 'nextLineSetSpacingShowText',
+
+      // Type3 fonts
+      d0: 'setCharWidth',
+      d1: 'setCharWidthAndBounds',
+
+      // Color
+      CS: 'setStrokeColorSpace',
+      cs: 'setFillColorSpace',
+      SC: 'setStrokeColor',
+      SCN: 'setStrokeColorN',
+      sc: 'setFillColor',
+      scn: 'setFillColorN',
+      G: 'setStrokeGray',
+      g: 'setFillGray',
+      RG: 'setStrokeRGBColor',
+      rg: 'setFillRGBColor',
+      K: 'setStrokeCMYKColor',
+      k: 'setFillCMYKColor',
+
+      // Shading
+      sh: 'shadingFill',
+
+      // Images
+      BI: 'beginInlineImage',
+
+      // XObjects
+      Do: 'paintXObject',
+
+      // Marked content
+      MP: 'markPoint',
+      DP: 'markPointProps',
+      BMC: 'beginMarkedContent',
+      BDC: 'beginMarkedContentProps',
+      EMC: 'endMarkedContent',
+
+      // Compatibility
+      BX: 'beginCompat',
+      EX: 'endCompat'
+    },
+
+    translateFont: function(fontDict, xref, resources) {
+      var fd = fontDict.get('FontDescriptor');
+      if (!fd)
+        // XXX deprecated "special treatment" for standard
+        // fonts?  What do we need to do here?
+        return null;
+      var descriptor = xref.fetch(fd);
+
+      var fontName = descriptor.get('FontName');
+      assertWellFormed(IsName(fontName), 'invalid font name');
+      fontName = fontName.name.replace('+', '_');
+
+      var fontFile = descriptor.get3('FontFile', 'FontFile2', 'FontFile3');
+      if (!fontFile)
+        error('FontFile not found for font: ' + fontName);
+      fontFile = xref.fetchIfRef(fontFile);
+
+      var encodingMap = {};
+      var charset = [];
+      if (fontDict.has('Encoding')) {
+        var encoding = xref.fetchIfRef(fontDict.get('Encoding'));
+        if (IsDict(encoding)) {
+          // Build a map between codes and glyphs
+          var differences = encoding.get('Differences');
+          var index = 0;
+          for (var j = 0; j < differences.length; j++) {
+            var data = differences[j];
+            IsNum(data) ? index = data : encodingMap[index++] = data;
+          }
+
+          // Get the font charset if any
+          var charset = descriptor.get('CharSet');
+          if (charset) {
+            assertWellFormed(IsString(charset), 'invalid charset');
+            charset = charset.split('/');
+            charset.shift();
+          }
+        } else if (IsName(encoding)) {
+          var encoding = Encodings[encoding.name];
+          if (!encoding)
+            error('Unknown font encoding');
+
+          var index = 0;
+          for (var j = 0; j < encoding.length; j++)
+            encodingMap[index++] = GlyphsUnicode[encoding[j]];
+
+          var firstChar = xref.fetchIfRef(fontDict.get('FirstChar'));
+          var widths = xref.fetchIfRef(fontDict.get('Widths'));
+          assertWellFormed(IsArray(widths) && IsInt(firstChar),
+                           'invalid font Widths or FirstChar');
+
+          for (var j = 0; j < widths.length; j++) {
+            if (widths[j])
+              charset.push(encoding[j + firstChar]);
+          }
+        }
+      } else if (fontDict.has('ToUnicode')) {
+        encodingMap = {empty: true};
+        var cmapObj = xref.fetchIfRef(fontDict.get('ToUnicode'));
+        if (IsName(cmapObj)) {
+          error('ToUnicode file cmap translation not implemented');
+        } else if (IsStream(cmapObj)) {
+          var encoding = Encodings['WinAnsiEncoding'];
+          var firstChar = xref.fetchIfRef(fontDict.get('FirstChar'));
+
+          var tokens = [];
+          var token = '';
+
+          var cmap = cmapObj.getBytes(cmapObj.length);
+          for (var i = 0; i < cmap.length; i++) {
+            var byte = cmap[i];
+            if (byte == 0x20 || byte == 0x0A || byte == 0x3C || byte == 0x3E) {
+              switch (token) {
+              case 'useCMap':
+                error('useCMap is not implemented');
+                break;
 
-            var subType = fontDict.get("Subtype");
-            assertWellFormed(IsName(subType), "invalid font Subtype");
-
-            var properties = {
-                type: subType.name,
-                encoding: encodingMap,
-                charset: charset,
-                firstChar: fontDict.get("FirstChar"),
-                lastChar: fontDict.get("LastChar"),
-                bbox: descriptor.get("FontBBox"),
-                ascent: descriptor.get("Ascent"),
-                descent: descriptor.get("Descent"),
-                xHeight: descriptor.get("XHeight"),
-                capHeight: descriptor.get("CapHeight"),
-                flags: descriptor.get("Flags"),
-                italicAngle: descriptor.get("ItalicAngle"),
-                fixedPitch: false,
-                textMatrix: IDENTITY_MATRIX
-            };
-
-            return {
-                name: fontName,
-                file: fontFile,
-                properties: properties
-            }
-        },
-
-        beginDrawing: function(mediaBox) {
-            var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
-            this.ctx.save();
-            this.ctx.scale(cw / mediaBox.width, -ch / mediaBox.height);
-            this.ctx.translate(0, -mediaBox.height);
-        },
-
-        execute: function(code, xref, resources) {
-            resources = xref.fetchIfRef(resources) || new Dict();
-            var savedXref = this.xref, savedRes = this.res, savedXobjs = this.xobjs;
-            this.xref = xref;
-            this.res = resources || new Dict();
-            this.xobjs = xref.fetchIfRef(this.res.get("XObject")) || new Dict();
-
-            code(this);
-
-            this.xobjs = savedXobjs;
-            this.res = savedRes;
-            this.xref = savedXref;
-        },
-
-        compile: function(stream, xref, resources, fonts) {
-            resources = xref.fetchIfRef(resources) || new Dict();
-            var xobjs = xref.fetchIfRef(resources.get("XObject")) || new Dict();
-
-            var parser = new Parser(new Lexer(stream), false);
-            var objpool = [];
-
-            function emitArg(arg) {
-                if (typeof arg == "object" || typeof arg == "string") {
-                    var index = objpool.length;
-                    objpool[index] = arg;
-                    return "objpool[" + index + "]";
+              case 'beginbfrange':
+              case 'begincodespacerange':
+                token = '';
+                tokens = [];
+                break;
+
+              case 'endcodespacerange':
+                TODO('Support CMap ranges');
+                break;
+
+              case 'endbfrange':
+                for (var j = 0; j < tokens.length; j += 3) {
+                  var startRange = parseInt('0x' + tokens[j]);
+                  var endRange = parseInt('0x' + tokens[j + 1]);
+                  var code = parseInt('0x' + tokens[j + 2]);
+
+                  for (var k = startRange; k <= endRange; k++) {
+                    // The encoding mapping table will be filled
+                    // later during the building phase
+                    //encodingMap[k] = GlyphsUnicode[encoding[code]];
+                    charset.push(encoding[code++] || '.notdef');
+                  }
                 }
-                return arg;
-            }
+                break;
+
+              case 'beginfbchar':
+              case 'endfbchar':
+                error('fbchar parsing is not implemented');
+                break;
 
-            var src = "";
-
-            var args = [];
-            var map = this.map;
-            var obj;
-            while (!IsEOF(obj = parser.getObj())) {
-                if (IsCmd(obj)) {
-                    var cmd = obj.cmd;
-                    var fn = map[cmd];
-                    assertWellFormed(fn, "Unknown command '" + cmd + "'");
-                    // TODO figure out how to type-check vararg functions
-
-                    if (cmd == "Do" && !args[0].code) { // eagerly compile XForm objects
-                        var name = args[0].name;
-                        var xobj = xobjs.get(name);
-                        if (xobj) {
-                            xobj = xref.fetchIfRef(xobj);
-                            assertWellFormed(IsStream(xobj), "XObject should be a stream");
-
-                            var type = xobj.dict.get("Subtype");
-                            assertWellFormed(IsName(type), "XObject should have a Name subtype");
-
-                            if ("Form" == type.name) {
-                                args[0].code = this.compile(xobj,
-                                                            xref,
-                                                            xobj.dict.get("Resources"),
-                                                            fonts);
-                            }
-                        }
-                    } else if (cmd == "Tf") { // eagerly collect all fonts
-                        var fontRes = resources.get("Font");
-                        if (fontRes) {
-                            fontRes = xref.fetchIfRef(fontRes);
-                            var font = xref.fetchIfRef(fontRes.get(args[0].name));
-                            assertWellFormed(IsDict(font));
-                            if (!font.translated) {
-                                font.translated = this.translateFont(font, xref, resources);
-                                if (fonts && font.translated) {
-                                    // keep track of each font we translated so the caller can
-                                    // load them asynchronously before calling display on a page
-                                    fonts.push(font.translated);
-                                }
-                            }
-                        }
-                    }
-
-                    src += "this.";
-                    src += fn;
-                    src += "(";
-                    src += args.map(emitArg).join(",");
-                    src += ");\n";
-
-                    args.length = 0;
-                } else {
-                    assertWellFormed(args.length <= 33, "Too many arguments");
-                    args.push(obj);
+              default:
+                if (token.length) {
+                  tokens.push(token);
+                  token = '';
                 }
+                break;
+              }
+            } else if (byte == 0x5B || byte == 0x5D) {
+              error('CMAP list parsing is not implemented');
+            } else {
+              token += String.fromCharCode(byte);
             }
+          }
+        }
+      }
 
-            var fn = Function("objpool", src);
-            return function (gfx) { fn.call(gfx, objpool); };
-        },
-
-        endDrawing: function() {
-            this.ctx.restore();
-        },
-
-        // Graphics state
-        setLineWidth: function(width) {
-            this.ctx.lineWidth = width;
-        },
-        setLineCap: function(style) {
-            this.ctx.lineCap = LINE_CAP_STYLES[style];
-        },
-        setLineJoin: function(style) {
-            this.ctx.lineJoin = LINE_JOIN_STYLES[style];
-        },
-        setMiterLimit: function(limit) {
-            this.ctx.miterLimit = limit;
-        },
-        setDash: function(dashArray, dashPhase) {
-            this.ctx.mozDash = dashArray;
-            this.ctx.mozDashOffset = dashPhase;
-        },
-        setRenderingIntent: function(intent) {
-            TODO("set rendering intent");
-        },
-        setFlatness: function(flatness) {
-            TODO("set flatness");
-        },
-        setGState: function(dictName) {
-            TODO("set graphics state from dict");
-        },
-        save: function() {
-            this.ctx.save();
-            if (this.ctx.$saveCurrentX) {
-                this.ctx.$saveCurrentX();
+      var subType = fontDict.get('Subtype');
+      assertWellFormed(IsName(subType), 'invalid font Subtype');
+
+      var properties = {
+        type: subType.name,
+        encoding: encodingMap,
+        charset: charset,
+        firstChar: fontDict.get('FirstChar'),
+        lastChar: fontDict.get('LastChar'),
+        bbox: descriptor.get('FontBBox'),
+        ascent: descriptor.get('Ascent'),
+        descent: descriptor.get('Descent'),
+        xHeight: descriptor.get('XHeight'),
+        capHeight: descriptor.get('CapHeight'),
+        flags: descriptor.get('Flags'),
+        italicAngle: descriptor.get('ItalicAngle'),
+        fixedPitch: false,
+        textMatrix: IDENTITY_MATRIX
+      };
+
+      return {
+        name: fontName,
+          file: fontFile,
+          properties: properties
+          };
+    },
+
+    beginDrawing: function(mediaBox) {
+      var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
+      this.ctx.save();
+      this.ctx.scale(cw / mediaBox.width, -ch / mediaBox.height);
+      this.ctx.translate(0, -mediaBox.height);
+    },
+
+    execute: function(code, xref, resources) {
+      resources = xref.fetchIfRef(resources) || new Dict();
+      var savedXref = this.xref, savedRes = this.res, savedXobjs = this.xobjs;
+      this.xref = xref;
+      this.res = resources || new Dict();
+      this.xobjs = xref.fetchIfRef(this.res.get('XObject')) || new Dict();
+
+      code(this);
+
+      this.xobjs = savedXobjs;
+      this.res = savedRes;
+      this.xref = savedXref;
+    },
+
+    compile: function(stream, xref, resources, fonts) {
+      resources = xref.fetchIfRef(resources) || new Dict();
+      var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict();
+
+      var parser = new Parser(new Lexer(stream), false);
+      var objpool = [];
+
+      function emitArg(arg) {
+        if (typeof arg == 'object' || typeof arg == 'string') {
+          var index = objpool.length;
+          objpool[index] = arg;
+          return 'objpool[' + index + ']';
+        }
+        return arg;
+      }
+
+      var src = '';
+
+      var args = [];
+      var map = this.map;
+      var obj;
+      while (!IsEOF(obj = parser.getObj())) {
+        if (IsCmd(obj)) {
+          var cmd = obj.cmd;
+          var fn = map[cmd];
+          assertWellFormed(fn, "Unknown command '" + cmd + "'");
+          // TODO figure out how to type-check vararg functions
+
+          if (cmd == 'Do' && !args[0].code) { // eagerly compile XForm objects
+            var name = args[0].name;
+            var xobj = xobjs.get(name);
+            if (xobj) {
+              xobj = xref.fetchIfRef(xobj);
+              assertWellFormed(IsStream(xobj), 'XObject should be a stream');
+
+              var type = xobj.dict.get('Subtype');
+              assertWellFormed(
+                IsName(type),
+                'XObject should have a Name subtype'
+              );
+
+              if ('Form' == type.name) {
+                args[0].code = this.compile(xobj,
+                                            xref,
+                                            xobj.dict.get('Resources'),
+                                            fonts);
+              }
             }
-            this.stateStack.push(this.current);
-            this.current = new CanvasExtraState();
-        },
-        restore: function() {
-            var prev = this.stateStack.pop();
-            if (prev) {
-                if (this.ctx.$restoreCurrentX) {
-                    this.ctx.$restoreCurrentX();
+          } else if (cmd == 'Tf') { // eagerly collect all fonts
+            var fontRes = resources.get('Font');
+            if (fontRes) {
+              fontRes = xref.fetchIfRef(fontRes);
+              var font = xref.fetchIfRef(fontRes.get(args[0].name));
+              assertWellFormed(IsDict(font));
+              if (!font.translated) {
+                font.translated = this.translateFont(font, xref, resources);
+                if (fonts && font.translated) {
+                  // keep track of each font we translated so the caller can
+                  // load them asynchronously before calling display on a page
+                  fonts.push(font.translated);
                 }
-                this.current = prev;
-                this.ctx.restore();
-            }
-        },
-        transform: function(a, b, c, d, e, f) {
-            this.ctx.transform(a, b, c, d, e, f);
-        },
-
-        // Path
-        moveTo: function(x, y) {
-            this.ctx.moveTo(x, y);
-        },
-        lineTo: function(x, y) {
-            this.ctx.lineTo(x, y);
-        },
-        curveTo: function(x1, y1, x2, y2, x3, y3) {
-            this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
-        },
-        curveTo2: function(x2, y2, x3, y3) {
-            TODO("'v' operator: need current point in gfx context");
-        },
-        curveTo3: function(x1, y1, x3, y3) {
-            this.curveTo(x1, y1, x3, y3, x3, y3);
-        },
-        closePath: function() {
-            this.ctx.closePath();
-        },
-        rectangle: function(x, y, width, height) {
-            this.ctx.rect(x, y, width, height);
-        },
-        stroke: function() {
-            this.ctx.stroke();
-            this.consumePath();
-        },
-        closeStroke: function() {
-            this.closePath();
-            this.stroke();
-        },
-        fill: function() {
-            this.ctx.fill();
-            this.consumePath();
-        },
-        eoFill: function() {
-            var savedFillRule = this.setEOFillRule();
-            this.fill();
-            this.restoreFillRule(savedFillRule);
-        },
-        fillStroke: function() {
-            this.ctx.fill();
-            this.ctx.stroke();
-            this.consumePath();
-        },
-        eoFillStroke: function() {
-            var savedFillRule = this.setEOFillRule();
-            this.fillStroke();
-            this.restoreFillRule(savedFillRule);
-        },
-        closeFillStroke: function() {
-            return this.fillStroke();
-        },
-        closeEOFillStroke: function() {
-            var savedFillRule = this.setEOFillRule();
-            this.fillStroke();
-            this.restoreFillRule(savedFillRule);
-        },
-        endPath: function() {
-            this.consumePath();
-        },
-
-        // Clipping
-        clip: function() {
-            this.pendingClip = NORMAL_CLIP;
-        },
-        eoClip: function() {
-            this.pendingClip = EO_CLIP;
-        },
-
-        // Text
-        beginText: function() {
-            this.current.textMatrix = IDENTITY_MATRIX;
-            if (this.ctx.$setCurrentX) {
-                this.ctx.$setCurrentX(0)
-            }
-            this.current.x = this.current.lineX = 0;
-            this.current.y = this.current.lineY = 0;
-        },
-        endText: function() {
-        },
-        setCharSpacing: function(spacing) {
-            this.ctx.charSpacing = spacing;
-        },
-        setWordSpacing: function(spacing) {
-            this.ctx.wordSpacing = spacing;
-        },
-        setHScale: function(scale) {
-            this.ctx.textHScale = (scale % 100) * 0.01;
-        },
-        setLeading: function(leading) {
-            this.current.leading = leading;
-        },
-        setFont: function(fontRef, size) {
-            var font = this.res.get("Font");
-            if (!IsDict(font))
-              return;
-
-            font = font.get(fontRef.name);
-            font = this.xref.fetchIfRef(font);
-            if (!font)
-                return;
-
-            var fontName = "";
-            var fontDescriptor = font.get("FontDescriptor");
-            if (fontDescriptor && fontDescriptor.num) {
-                var fontDescriptor = this.xref.fetchIfRef(fontDescriptor);
-                fontName = fontDescriptor.get("FontName").name.replace("+", "_");
+              }
             }
+          }
 
-            if (!fontName) {
-                // TODO: fontDescriptor is not available, fallback to default font
-                fontName = "sans-serif";
-            }
+          src += 'this.';
+          src += fn;
+          src += '(';
+          src += args.map(emitArg).join(',');
+          src += ');\n';
 
-            this.current.fontName = fontName;
-            this.current.fontSize = size;
+          args.length = 0;
+        } else {
+          assertWellFormed(args.length <= 33, 'Too many arguments');
+          args.push(obj);
+        }
+      }
 
-            if (this.ctx.$setFont) {
-              this.ctx.$setFont(fontName, size);
-            } else {
-              this.ctx.font = size + 'px "' + fontName + '"';
-              Fonts.setActive(fontName, size);
-            }
-        },
-        setTextRenderingMode: function(mode) {
-            TODO("text rendering mode");
-        },
-        setTextRise: function(rise) {
-            TODO("text rise");
-        },
-        moveText: function (x, y) {
-            this.current.x = this.current.lineX += x;
-            this.current.y = this.current.lineY += y;
-            if (this.ctx.$setCurrentX) {
-                this.ctx.$setCurrentX(this.current.x)
-            }
-        },
-        setLeadingMoveText: function(x, y) {
-            this.setLeading(-y);
-            this.moveText(x, y);
-        },
-        setTextMatrix: function(a, b, c, d, e, f) {
-            this.current.textMatrix = [ a, b, c, d, e, f ];
-
-            if (this.ctx.$setCurrentX) {
-                this.ctx.$setCurrentX(0)
-            }
-            this.current.x = this.current.lineX = 0;
-            this.current.y = this.current.lineY = 0;
-        },
-        nextLine: function() {
-            this.moveText(0, this.current.leading);
-        },
-        showText: function(text) {
-            // TODO: apply charSpacing, wordSpacing, textHScale
-
-            this.ctx.save();
-            this.ctx.transform.apply(this.ctx, this.current.textMatrix);
-            this.ctx.scale(1, -1);
-
-            if (this.ctx.$showText) {
-                this.ctx.$showText(this.current.y, Fonts.charsToUnicode(text));
-            } else {
-                text = Fonts.charsToUnicode(text);
-                this.ctx.translate(this.current.x, -1 * this.current.y);
+      var fn = Function('objpool', src);
+      return function(gfx) { fn.call(gfx, objpool); };
+    },
+
+    endDrawing: function() {
+      this.ctx.restore();
+    },
+
+    // Graphics state
+    setLineWidth: function(width) {
+      this.ctx.lineWidth = width;
+    },
+    setLineCap: function(style) {
+      this.ctx.lineCap = LINE_CAP_STYLES[style];
+    },
+    setLineJoin: function(style) {
+      this.ctx.lineJoin = LINE_JOIN_STYLES[style];
+    },
+    setMiterLimit: function(limit) {
+      this.ctx.miterLimit = limit;
+    },
+    setDash: function(dashArray, dashPhase) {
+      this.ctx.mozDash = dashArray;
+      this.ctx.mozDashOffset = dashPhase;
+    },
+    setRenderingIntent: function(intent) {
+      TODO('set rendering intent');
+    },
+    setFlatness: function(flatness) {
+      TODO('set flatness');
+    },
+    setGState: function(dictName) {
+      TODO('set graphics state from dict');
+    },
+    save: function() {
+      this.ctx.save();
+      if (this.ctx.$saveCurrentX) {
+        this.ctx.$saveCurrentX();
+      }
+      this.stateStack.push(this.current);
+      this.current = new CanvasExtraState();
+    },
+    restore: function() {
+      var prev = this.stateStack.pop();
+      if (prev) {
+        if (this.ctx.$restoreCurrentX) {
+          this.ctx.$restoreCurrentX();
+        }
+        this.current = prev;
+        this.ctx.restore();
+      }
+    },
+    transform: function(a, b, c, d, e, f) {
+      this.ctx.transform(a, b, c, d, e, f);
+    },
+
+    // Path
+    moveTo: function(x, y) {
+      this.ctx.moveTo(x, y);
+    },
+    lineTo: function(x, y) {
+      this.ctx.lineTo(x, y);
+    },
+    curveTo: function(x1, y1, x2, y2, x3, y3) {
+      this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
+    },
+    curveTo2: function(x2, y2, x3, y3) {
+      TODO("'v' operator: need current point in gfx context");
+    },
+    curveTo3: function(x1, y1, x3, y3) {
+      this.curveTo(x1, y1, x3, y3, x3, y3);
+    },
+    closePath: function() {
+      this.ctx.closePath();
+    },
+    rectangle: function(x, y, width, height) {
+      this.ctx.rect(x, y, width, height);
+    },
+    stroke: function() {
+      this.ctx.stroke();
+      this.consumePath();
+    },
+    closeStroke: function() {
+      this.closePath();
+      this.stroke();
+    },
+    fill: function() {
+      this.ctx.fill();
+      this.consumePath();
+    },
+    eoFill: function() {
+      var savedFillRule = this.setEOFillRule();
+      this.fill();
+      this.restoreFillRule(savedFillRule);
+    },
+    fillStroke: function() {
+      this.ctx.fill();
+      this.ctx.stroke();
+      this.consumePath();
+    },
+    eoFillStroke: function() {
+      var savedFillRule = this.setEOFillRule();
+      this.fillStroke();
+      this.restoreFillRule(savedFillRule);
+    },
+    closeFillStroke: function() {
+      return this.fillStroke();
+    },
+    closeEOFillStroke: function() {
+      var savedFillRule = this.setEOFillRule();
+      this.fillStroke();
+      this.restoreFillRule(savedFillRule);
+    },
+    endPath: function() {
+      this.consumePath();
+    },
+
+    // Clipping
+    clip: function() {
+      this.pendingClip = NORMAL_CLIP;
+    },
+    eoClip: function() {
+      this.pendingClip = EO_CLIP;
+    },
+
+    // Text
+    beginText: function() {
+      this.current.textMatrix = IDENTITY_MATRIX;
+      if (this.ctx.$setCurrentX) {
+        this.ctx.$setCurrentX(0);
+      }
+      this.current.x = this.current.lineX = 0;
+      this.current.y = this.current.lineY = 0;
+    },
+    endText: function() {
+    },
+    setCharSpacing: function(spacing) {
+      this.ctx.charSpacing = spacing;
+    },
+    setWordSpacing: function(spacing) {
+      this.ctx.wordSpacing = spacing;
+    },
+    setHScale: function(scale) {
+      this.ctx.textHScale = (scale % 100) * 0.01;
+    },
+    setLeading: function(leading) {
+      this.current.leading = leading;
+    },
+    setFont: function(fontRef, size) {
+      var font = this.res.get('Font');
+      if (!IsDict(font))
+        return;
 
-                var font = Fonts.lookup(this.current.fontName);
-                if (font && font.properties.textMatrix)
-                  this.ctx.transform.apply(this.ctx, font.properties.textMatrix);
+      font = font.get(fontRef.name);
+      font = this.xref.fetchIfRef(font);
+      if (!font)
+        return;
 
-                this.ctx.fillText(text, 0, 0);
-                this.current.x += Fonts.measureText(text);
-            }
+      var fontName = '';
+      var fontDescriptor = font.get('FontDescriptor');
+      if (fontDescriptor && fontDescriptor.num) {
+        var fontDescriptor = this.xref.fetchIfRef(fontDescriptor);
+        fontName = fontDescriptor.get('FontName').name.replace('+', '_');
+      }
 
-            this.ctx.restore();
-        },
-        showSpacedText: function(arr) {
-            for (var i = 0; i < arr.length; ++i) {
-                var e = arr[i];
-                if (IsNum(e)) {
-                    if (this.ctx.$addCurrentX) {
-                        this.ctx.$addCurrentX(-e * 0.001 * this.current.fontSize)
-                    } else {
-                        this.current.x -= e * 0.001 * this.current.fontSize;
-                    }
-                } else if (IsString(e)) {
-                    this.showText(e);
-                } else {
-                    malformed("TJ array element "+ e +" isn't string or num");
-                }
-            }
-        },
-        nextLineShowText: function(text) {
-            this.nextLine();
-            this.showText(text);
-        },
-        nextLineSetSpacingShowText: function(wordSpacing, charSpacing, text) {
-            this.setWordSpacing(wordSpacing);
-            this.setCharSpacing(charSpacing);
-            this.nextLineShowText(text);
-        },
-
-        // Type3 fonts
-        setCharWidth: function(xWidth, yWidth) {
-            TODO("type 3 fonts ('d0' operator)");
-        },
-        setCharWidthAndBounds: function(xWidth, yWidth, llx, lly, urx, ury) {
-            TODO("type 3 fonts ('d1' operator)");
-        },
-
-        // Color
-        setStrokeColorSpace: function(space) {
-            this.current.strokeColorSpace = 
-                ColorSpace.parse(space, this.xref, this.res);
-        },
-        setFillColorSpace: function(space) {
-            this.current.fillColorSpace = 
-                ColorSpace.parse(space, this.xref, this.res);
-        },
-        setStrokeColor: function(/*...*/) {
-            var cs = this.getStrokeColorSpace();
-            var color = cs.getRgb(arguments);
-            this.setStrokeRGBColor.apply(this, color);
-        },
-        setStrokeColorN: function(/*...*/) {
-            // TODO real impl
-            TODO("check for special color spaces");
-            this.setStrokeColor.apply(this, arguments);
-        },
-        setFillColor: function(/*...*/) {
-            var cs = this.getFillColorSpace();
-            if (cs.name == "Pattern") {
-                TODO("implement Pattern fill");
-                return;
-            }
-            var color = cs.getRgb(arguments);
-            this.setFillRGBColor.apply(this, color);
-        },
-        setFillColorN: function(/*...*/) {
-            var cs = this.getFillColorSpace();
-
-            if (cs.name == "Pattern") {
-                var patternName = arguments[0];
-                if (IsName(patternName)) {
-                    var xref = this.xref;
-                    var patternRes = xref.fetchIfRef(this.res.get("Pattern"));
-                    if (!patternRes)
-                        error("Unable to find pattern resource");
-
-                    var pattern = xref.fetchIfRef(patternRes.get(patternName.name));
-                    var patternDict = IsStream(pattern) ? pattern.dict : pattern;
-                    var types = [null, this.tilingFill,
-                                   function() { TODO("Shading Patterns"); }];
-                    var typeNum = patternDict.get("PatternType");
-                    var patternFn = types[typeNum];
-                    if (!patternFn)
-                        error("Unhandled pattern type");
-                    patternFn.call(this, pattern, patternDict);
-                }
-            } else {
-                // TODO real impl
-                this.setFillColor.apply(this, arguments);
-            }
-        },
-        tilingFill: function(pattern) {
-            function applyMatrix(point, m) {
-                var x = point[0] * m[0] + point[1] * m[2] + m[4];
-                var y = point[0] * m[1] + point[1] * m[3] + m[5];
-                return [x,y];
-            };
-
-            function multiply(m, tm) {
-                var a = m[0] * tm[0] + m[1] * tm[2];
-                var b = m[0] * tm[1] + m[1] * tm[3];
-                var c = m[2] * tm[0] + m[3] * tm[2];
-                var d = m[2] * tm[1] + m[3] * tm[3];
-                var e = m[4] * tm[0] + m[5] * tm[2] + tm[4];
-                var f = m[4] * tm[1] + m[5] * tm[3] + tm[5];
-                return [a, b, c, d, e, f]
-            };
-
-            this.save();
-            var dict = pattern.dict;
-            var ctx = this.ctx;
-
-            var paintType = dict.get("PaintType");
-            switch (paintType) {
-            case PAINT_TYPE_COLORED:
-                // should go to default for color space
-                ctx.fillStyle = this.makeCssRgb(1, 1, 1);
-                ctx.strokeStyle = this.makeCssRgb(0, 0, 0);
-                break;
-            case PAINT_TYPE_UNCOLORED:
-            default:
-                error("Unsupported paint type");
-            }
+      if (!fontName) {
+        // TODO: fontDescriptor is not available, fallback to default font
+        fontName = 'sans-serif';
+      }
 
-            TODO("TilingType");
+      this.current.fontName = fontName;
+      this.current.fontSize = size;
 
-            var matrix = dict.get("Matrix") || IDENTITY_MATRIX;
+      if (this.ctx.$setFont) {
+        this.ctx.$setFont(fontName, size);
+      } else {
+        this.ctx.font = size + 'px "' + fontName + '"';
+        Fonts.setActive(fontName, size);
+      }
+    },
+    setTextRenderingMode: function(mode) {
+      TODO('text rendering mode');
+    },
+    setTextRise: function(rise) {
+      TODO('text rise');
+    },
+    moveText: function(x, y) {
+      this.current.x = this.current.lineX += x;
+      this.current.y = this.current.lineY += y;
+      if (this.ctx.$setCurrentX) {
+        this.ctx.$setCurrentX(this.current.x);
+      }
+    },
+    setLeadingMoveText: function(x, y) {
+      this.setLeading(-y);
+      this.moveText(x, y);
+    },
+    setTextMatrix: function(a, b, c, d, e, f) {
+      this.current.textMatrix = [a, b, c, d, e, f];
+
+      if (this.ctx.$setCurrentX) {
+        this.ctx.$setCurrentX(0);
+      }
+      this.current.x = this.current.lineX = 0;
+      this.current.y = this.current.lineY = 0;
+    },
+    nextLine: function() {
+      this.moveText(0, this.current.leading);
+    },
+    showText: function(text) {
+      // TODO: apply charSpacing, wordSpacing, textHScale
+
+      this.ctx.save();
+      this.ctx.transform.apply(this.ctx, this.current.textMatrix);
+      this.ctx.scale(1, -1);
+
+      if (this.ctx.$showText) {
+        this.ctx.$showText(this.current.y, Fonts.charsToUnicode(text));
+      } else {
+        text = Fonts.charsToUnicode(text);
+        this.ctx.translate(this.current.x, -1 * this.current.y);
+
+        var font = Fonts.lookup(this.current.fontName);
+        if (font && font.properties.textMatrix)
+          this.ctx.transform.apply(this.ctx, font.properties.textMatrix);
+
+        this.ctx.fillText(text, 0, 0);
+        this.current.x += Fonts.measureText(text);
+      }
 
-            var bbox = dict.get("BBox");
-            var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
+      this.ctx.restore();
+    },
+    showSpacedText: function(arr) {
+      for (var i = 0; i < arr.length; ++i) {
+        var e = arr[i];
+        if (IsNum(e)) {
+          if (this.ctx.$addCurrentX) {
+            this.ctx.$addCurrentX(-e * 0.001 * this.current.fontSize);
+          } else {
+            this.current.x -= e * 0.001 * this.current.fontSize;
+          }
+        } else if (IsString(e)) {
+          this.showText(e);
+        } else {
+          malformed('TJ array element ' + e + " isn't string or num");
+        }
+      }
+    },
+    nextLineShowText: function(text) {
+      this.nextLine();
+      this.showText(text);
+    },
+    nextLineSetSpacingShowText: function(wordSpacing, charSpacing, text) {
+      this.setWordSpacing(wordSpacing);
+      this.setCharSpacing(charSpacing);
+      this.nextLineShowText(text);
+    },
+
+    // Type3 fonts
+    setCharWidth: function(xWidth, yWidth) {
+      TODO("type 3 fonts ('d0' operator)");
+    },
+    setCharWidthAndBounds: function(xWidth, yWidth, llx, lly, urx, ury) {
+      TODO("type 3 fonts ('d1' operator)");
+    },
+
+    // Color
+    setStrokeColorSpace: function(space) {
+      this.current.strokeColorSpace =
+      ColorSpace.parse(space, this.xref, this.res);
+    },
+    setFillColorSpace: function(space) {
+      this.current.fillColorSpace =
+      ColorSpace.parse(space, this.xref, this.res);
+    },
+    setStrokeColor: function(/*...*/) {
+      var cs = this.getStrokeColorSpace();
+      var color = cs.getRgb(arguments);
+      this.setStrokeRGBColor.apply(this, color);
+    },
+    setStrokeColorN: function(/*...*/) {
+      // TODO real impl
+      TODO('check for special color spaces');
+      this.setStrokeColor.apply(this, arguments);
+    },
+    setFillColor: function(/*...*/) {
+      var cs = this.getFillColorSpace();
+      if (cs.name == 'Pattern') {
+        TODO('implement Pattern fill');
+        return;
+      }
+      var color = cs.getRgb(arguments);
+      this.setFillRGBColor.apply(this, color);
+    },
+    setFillColorN: function(/*...*/) {
+      var cs = this.getFillColorSpace();
+
+      if (cs.name == 'Pattern') {
+        var patternName = arguments[0];
+        if (IsName(patternName)) {
+          var xref = this.xref;
+          var patternRes = xref.fetchIfRef(this.res.get('Pattern'));
+          if (!patternRes)
+            error('Unable to find pattern resource');
+
+          var pattern = xref.fetchIfRef(patternRes.get(patternName.name));
+          var patternDict = IsStream(pattern) ? pattern.dict : pattern;
+          var types = [null, this.tilingFill,
+                       function() { TODO('Shading Patterns'); }];
+          var typeNum = patternDict.get('PatternType');
+          var patternFn = types[typeNum];
+          if (!patternFn)
+            error('Unhandled pattern type');
+          patternFn.call(this, pattern, patternDict);
+        }
+      } else {
+        // TODO real impl
+        this.setFillColor.apply(this, arguments);
+      }
+    },
+    tilingFill: function(pattern) {
+      function applyMatrix(point, m) {
+        var x = point[0] * m[0] + point[1] * m[2] + m[4];
+        var y = point[0] * m[1] + point[1] * m[3] + m[5];
+        return [x, y];
+      };
+
+      function multiply(m, tm) {
+        var a = m[0] * tm[0] + m[1] * tm[2];
+        var b = m[0] * tm[1] + m[1] * tm[3];
+        var c = m[2] * tm[0] + m[3] * tm[2];
+        var d = m[2] * tm[1] + m[3] * tm[3];
+        var e = m[4] * tm[0] + m[5] * tm[2] + tm[4];
+        var f = m[4] * tm[1] + m[5] * tm[3] + tm[5];
+        return [a, b, c, d, e, f];
+      };
+
+      this.save();
+      var dict = pattern.dict;
+      var ctx = this.ctx;
+
+      var paintType = dict.get('PaintType');
+      switch (paintType) {
+      case PAINT_TYPE_COLORED:
+        // should go to default for color space
+        ctx.fillStyle = this.makeCssRgb(1, 1, 1);
+        ctx.strokeStyle = this.makeCssRgb(0, 0, 0);
+        break;
+      case PAINT_TYPE_UNCOLORED:
+      default:
+        error('Unsupported paint type');
+      }
 
-            var xstep = dict.get("XStep");
-            var ystep = dict.get("YStep");
+      TODO('TilingType');
 
-            // top left corner should correspond to the top left of the bbox
-            var topLeft = applyMatrix([x0,y0], matrix);
-            // we want the canvas to be as large as the step size
-            var botRight = applyMatrix([x0 + xstep, y0 + ystep], matrix);
+      var matrix = dict.get('Matrix') || IDENTITY_MATRIX;
 
-            var width = botRight[0] - topLeft[0];
-            var height = botRight[1] - topLeft[1];
+      var bbox = dict.get('BBox');
+      var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
 
-            // TODO: hack to avoid OOM, remove then pattern code is fixed
-            if (Math.abs(width) > 8192 || Math.abs(height) > 8192)
-                return false;
+      var xstep = dict.get('XStep');
+      var ystep = dict.get('YStep');
 
-            var tmpCanvas = new this.ScratchCanvas(width, height);
+      // top left corner should correspond to the top left of the bbox
+      var topLeft = applyMatrix([x0, y0], matrix);
+      // we want the canvas to be as large as the step size
+      var botRight = applyMatrix([x0 + xstep, y0 + ystep], matrix);
 
-            // set the new canvas element context as the graphics context
-            var tmpCtx = tmpCanvas.getContext("2d");
-            var savedCtx = ctx;
-            this.ctx = tmpCtx;
+      var width = botRight[0] - topLeft[0];
+      var height = botRight[1] - topLeft[1];
 
-            // normalize transform matrix so each step
-            // takes up the entire tmpCanvas (need to remove white borders)
-            if (matrix[1] === 0 && matrix[2] === 0) {
-                matrix[0] = tmpCanvas.width / xstep;
-                matrix[3] = tmpCanvas.height / ystep;
-                topLeft = applyMatrix([x0,y0], matrix);
-            }
+      // TODO: hack to avoid OOM, remove then pattern code is fixed
+      if (Math.abs(width) > 8192 || Math.abs(height) > 8192)
+        return false;
 
-            // move the top left corner of bounding box to [0,0]
-            matrix = multiply(matrix, [1, 0, 0, 1, -topLeft[0], -topLeft[1]]);
+      var tmpCanvas = new this.ScratchCanvas(width, height);
 
-            this.transform.apply(this, matrix);
+      // set the new canvas element context as the graphics context
+      var tmpCtx = tmpCanvas.getContext('2d');
+      var savedCtx = ctx;
+      this.ctx = tmpCtx;
 
-            if (bbox && IsArray(bbox) && 4 == bbox.length) {
-                this.rectangle.apply(this, bbox);
-                this.clip();
-                this.endPath();
-            }
+      // normalize transform matrix so each step
+      // takes up the entire tmpCanvas (need to remove white borders)
+      if (matrix[1] === 0 && matrix[2] === 0) {
+        matrix[0] = tmpCanvas.width / xstep;
+        matrix[3] = tmpCanvas.height / ystep;
+        topLeft = applyMatrix([x0, y0], matrix);
+      }
 
-            var xref = this.xref;
-            var res = xref.fetchIfRef(dict.get("Resources"));
-            if (!pattern.code)
-                pattern.code = this.compile(pattern, xref, res, []);
-            this.execute(pattern.code, xref, res);
-
-            this.ctx = savedCtx;
-            this.restore();
-
-            TODO("Inverse pattern is painted");
-            pattern = this.ctx.createPattern(tmpCanvas, "repeat");
-            this.ctx.fillStyle = pattern;
-        },
-        setStrokeGray: function(gray) {
-            this.setStrokeRGBColor(gray, gray, gray);
-        },
-        setFillGray: function(gray) {
-            this.setFillRGBColor(gray, gray, gray);
-        },
-        setStrokeRGBColor: function(r, g, b) {
-            this.ctx.strokeStyle = this.makeCssRgb(r, g, b);
-        },
-        setFillRGBColor: function(r, g, b) {
-            this.ctx.fillStyle = this.makeCssRgb(r, g, b);
-        },
-        setStrokeCMYKColor: function(c, m, y, k) {
-            this.ctx.strokeStyle = this.makeCssCmyk(c, m, y, k);
-        },
-        setFillCMYKColor: function(c, m, y, k) {
-            this.ctx.fillStyle = this.makeCssCmyk(c, m, y, k);
-        },
-
-        // Shading
-        shadingFill: function(entryRef) {
-            var xref = this.xref;
-            var res = this.res;
-
-            var shadingRes = xref.fetchIfRef(res.get("Shading"));
-            if (!shadingRes)
-                error("No shading resource found");
-
-            var shading = xref.fetchIfRef(shadingRes.get(entryRef.name));
-            if (!shading)
-                error("No shading object found");
-
-            this.save();
-
-            var bbox = shading.get("BBox");
-            if (bbox && IsArray(bbox) && 4 == bbox.length) {
-                this.rectangle.apply(this, bbox);
-                this.clip();
-                this.endPath();
-            }
+      // move the top left corner of bounding box to [0,0]
+      matrix = multiply(matrix, [1, 0, 0, 1, -topLeft[0], -topLeft[1]]);
 
-            var cs = shading.get2("ColorSpace", "CS");
-            TODO("shading-fill color space");
+      this.transform.apply(this, matrix);
 
-            var background = shading.get("Background");
-            if (background)
-                TODO("handle background colors");
+      if (bbox && IsArray(bbox) && 4 == bbox.length) {
+        this.rectangle.apply(this, bbox);
+        this.clip();
+        this.endPath();
+      }
 
-            var types = [null,
-                           this.fillFunctionShading,
-                           this.fillAxialShading,
-                           this.fillRadialShading];
+      var xref = this.xref;
+      var res = xref.fetchIfRef(dict.get('Resources'));
+      if (!pattern.code)
+        pattern.code = this.compile(pattern, xref, res, []);
+      this.execute(pattern.code, xref, res);
+
+      this.ctx = savedCtx;
+      this.restore();
+
+      TODO('Inverse pattern is painted');
+      pattern = this.ctx.createPattern(tmpCanvas, 'repeat');
+      this.ctx.fillStyle = pattern;
+    },
+    setStrokeGray: function(gray) {
+      this.setStrokeRGBColor(gray, gray, gray);
+    },
+    setFillGray: function(gray) {
+      this.setFillRGBColor(gray, gray, gray);
+    },
+    setStrokeRGBColor: function(r, g, b) {
+      this.ctx.strokeStyle = this.makeCssRgb(r, g, b);
+    },
+    setFillRGBColor: function(r, g, b) {
+      this.ctx.fillStyle = this.makeCssRgb(r, g, b);
+    },
+    setStrokeCMYKColor: function(c, m, y, k) {
+      this.ctx.strokeStyle = this.makeCssCmyk(c, m, y, k);
+    },
+    setFillCMYKColor: function(c, m, y, k) {
+      this.ctx.fillStyle = this.makeCssCmyk(c, m, y, k);
+    },
+
+    // Shading
+    shadingFill: function(entryRef) {
+      var xref = this.xref;
+      var res = this.res;
+
+      var shadingRes = xref.fetchIfRef(res.get('Shading'));
+      if (!shadingRes)
+        error('No shading resource found');
+
+      var shading = xref.fetchIfRef(shadingRes.get(entryRef.name));
+      if (!shading)
+        error('No shading object found');
+
+      this.save();
+
+      var bbox = shading.get('BBox');
+      if (bbox && IsArray(bbox) && 4 == bbox.length) {
+        this.rectangle.apply(this, bbox);
+        this.clip();
+        this.endPath();
+      }
 
-            var typeNum = shading.get("ShadingType");
-            var fillFn = types[typeNum];
-            if (!fillFn)
-                error("Unknown or NYI type of shading '"+ typeNum +"'");
-            fillFn.apply(this, [shading]);
+      var cs = shading.get2('ColorSpace', 'CS');
+      TODO('shading-fill color space');
 
-            this.restore();
-        },
+      var background = shading.get('Background');
+      if (background)
+        TODO('handle background colors');
 
-        fillAxialShading: function(sh) {
-            var coordsArr = sh.get("Coords");
-            var x0 = coordsArr[0], y0 = coordsArr[1],
-                x1 = coordsArr[2], y1 = coordsArr[3];
+      var types = [null,
+                   this.fillFunctionShading,
+                   this.fillAxialShading,
+                   this.fillRadialShading];
 
-            var t0 = 0.0, t1 = 1.0;
-            if (sh.has("Domain")) {
-                var domainArr = sh.get("Domain");
-                t0 = domainArr[0], t1 = domainArr[1];
-            }
+      var typeNum = shading.get('ShadingType');
+      var fillFn = types[typeNum];
+      if (!fillFn)
+        error("Unknown or NYI type of shading '" + typeNum + "'");
+      fillFn.apply(this, [shading]);
 
-            var extendStart = false, extendEnd = false;
-            if (sh.has("Extend")) {
-                var extendArr = sh.get("Extend");
-                extendStart = extendArr[0], extendEnd = extendArr[1];
-                TODO("Support extend");
-            }
-            var fnObj = sh.get("Function");
-            fnObj = this.xref.fetchIfRef(fnObj);
-            if (IsArray(fnObj))
-                error("No support for array of functions");
-            else if (!IsPDFFunction(fnObj))
-                error("Invalid function");
-            var fn = new PDFFunction(this.xref, fnObj);
-
-            var gradient = this.ctx.createLinearGradient(x0, y0, x1, y1);
-
-            // 10 samples seems good enough for now, but probably won't work
-            // if there are sharp color changes. Ideally, we would implement
-            // the spec faithfully and add lossless optimizations.
-            var step = (t1 - t0) / 10;
-
-            for (var i = t0; i <= t1; i += step) {
-                var c = fn.func([i]);
-                gradient.addColorStop(i, this.makeCssRgb.apply(this, c));
-            }
+      this.restore();
+    },
 
-            this.ctx.fillStyle = gradient;
-
-            // HACK to draw the gradient onto an infinite rectangle.
-            // PDF gradients are drawn across the entire image while
-            // Canvas only allows gradients to be drawn in a rectangle
-            // The following bug should allow us to remove this.
-            // https://bugzilla.mozilla.org/show_bug.cgi?id=664884
-            this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
-        },
-
-        fillRadialShading: function(sh) {
-            TODO("radial shading");
-        },
-
-        // Images
-        beginInlineImage: function() {
-            TODO("inline images");
-            error("(Stream will not be parsed properly, bailing now)");
-            // Like an inline stream:
-            //  - key/value pairs up to Cmd(ID)
-            //  - then image data up to Cmd(EI)
-        },
-
-        // XObjects
-        paintXObject: function(obj) {
-            var xobj = this.xobjs.get(obj.name);
-            if (!xobj)
-                return;
-            xobj = this.xref.fetchIfRef(xobj);
-            assertWellFormed(IsStream(xobj), "XObject should be a stream");
-
-            var oc = xobj.dict.get("OC");
-            if (oc) {
-                TODO("oc for xobject");
-            }
+    fillAxialShading: function(sh) {
+      var coordsArr = sh.get('Coords');
+      var x0 = coordsArr[0], y0 = coordsArr[1],
+      x1 = coordsArr[2], y1 = coordsArr[3];
 
-            var opi = xobj.dict.get("OPI");
-            if (opi) {
-                TODO("opi for xobject");
-            }
+      var t0 = 0.0, t1 = 1.0;
+      if (sh.has('Domain')) {
+        var domainArr = sh.get('Domain');
+        t0 = domainArr[0], t1 = domainArr[1];
+      }
 
-            var type = xobj.dict.get("Subtype");
-            assertWellFormed(IsName(type), "XObject should have a Name subtype");
-            if ("Image" == type.name) {
-                this.paintImageXObject(obj, xobj, false);
-            } else if ("Form" == type.name) {
-                this.paintFormXObject(obj, xobj);
-            } else if ("PS" == type.name) {
-                warn("(deprecated) PostScript XObjects are not supported");
-            } else {
-                malformed("Unknown XObject subtype "+ type.name);
-            }
-        },
+      var extendStart = false, extendEnd = false;
+      if (sh.has('Extend')) {
+        var extendArr = sh.get('Extend');
+        extendStart = extendArr[0], extendEnd = extendArr[1];
+        TODO('Support extend');
+      }
+      var fnObj = sh.get('Function');
+      fnObj = this.xref.fetchIfRef(fnObj);
+      if (IsArray(fnObj))
+        error('No support for array of functions');
+      else if (!IsPDFFunction(fnObj))
+        error('Invalid function');
+      var fn = new PDFFunction(this.xref, fnObj);
+
+      var gradient = this.ctx.createLinearGradient(x0, y0, x1, y1);
+
+      // 10 samples seems good enough for now, but probably won't work
+      // if there are sharp color changes. Ideally, we would implement
+      // the spec faithfully and add lossless optimizations.
+      var step = (t1 - t0) / 10;
+
+      for (var i = t0; i <= t1; i += step) {
+        var c = fn.func([i]);
+        gradient.addColorStop(i, this.makeCssRgb.apply(this, c));
+      }
 
-        paintFormXObject: function(ref, stream) {
-            this.save();
+      this.ctx.fillStyle = gradient;
+
+      // HACK to draw the gradient onto an infinite rectangle.
+      // PDF gradients are drawn across the entire image while
+      // Canvas only allows gradients to be drawn in a rectangle
+      // The following bug should allow us to remove this.
+      // https://bugzilla.mozilla.org/show_bug.cgi?id=664884
+      this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
+    },
+
+    fillRadialShading: function(sh) {
+      TODO('radial shading');
+    },
+
+    // Images
+    beginInlineImage: function() {
+      TODO('inline images');
+      error('(Stream will not be parsed properly, bailing now)');
+      // Like an inline stream:
+      //  - key/value pairs up to Cmd(ID)
+      //  - then image data up to Cmd(EI)
+    },
+
+    // XObjects
+    paintXObject: function(obj) {
+      var xobj = this.xobjs.get(obj.name);
+      if (!xobj)
+        return;
+      xobj = this.xref.fetchIfRef(xobj);
+      assertWellFormed(IsStream(xobj), 'XObject should be a stream');
 
-            var matrix = stream.dict.get("Matrix");
-            if (matrix && IsArray(matrix) && 6 == matrix.length)
-                this.transform.apply(this, matrix);
+      var oc = xobj.dict.get('OC');
+      if (oc) {
+        TODO('oc for xobject');
+      }
 
-            var bbox = stream.dict.get("BBox");
-            if (bbox && IsArray(bbox) && 4 == bbox.length) {
-                this.rectangle.apply(this, bbox);
-                this.clip();
-                this.endPath();
-            }
+      var opi = xobj.dict.get('OPI');
+      if (opi) {
+        TODO('opi for xobject');
+      }
 
-            this.execute(ref.code, this.xref, stream.dict.get("Resources"));
-
-            this.restore();
-        },
-
-        paintImageXObject: function(ref, image, inline) {
-            this.save();
-
-            var ctx = this.ctx;
-            var dict = image.dict;
-            var w = dict.get2("Width", "W");
-            var h = dict.get2("Height", "H");
-            // scale the image to the unit square
-            ctx.scale(1/w, -1/h);
-
-            // If the platform can render the image format directly, the
-            // stream has a getImage property which directly returns a
-            // suitable DOM Image object.
-            if (image.getImage) {
-                var domImage = image.getImage();
-                ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
-                              0, -h, w, h);
-                this.restore();
-                return;
-            }
+      var type = xobj.dict.get('Subtype');
+      assertWellFormed(IsName(type), 'XObject should have a Name subtype');
+      if ('Image' == type.name) {
+        this.paintImageXObject(obj, xobj, false);
+      } else if ('Form' == type.name) {
+        this.paintFormXObject(obj, xobj);
+      } else if ('PS' == type.name) {
+        warn('(deprecated) PostScript XObjects are not supported');
+      } else {
+        malformed('Unknown XObject subtype ' + type.name);
+      }
+    },
 
-            var imageObj = new PDFImage(this.xref, this.res, image, inline); 
-
-            var tmpCanvas = new this.ScratchCanvas(w, h);
-            var tmpCtx = tmpCanvas.getContext("2d");
-            var imgData = tmpCtx.getImageData(0, 0, w, h);
-            var pixels = imgData.data;
-
-            imageObj.fillRgbaBuffer(pixels);
-            
-            tmpCtx.putImageData(imgData, 0, 0);
-            ctx.drawImage(tmpCanvas, 0, -h);
-            this.restore();
-        },
-
-        // Marked content
-
-        markPoint: function(tag) {
-            TODO("Marked content");
-        },
-        markPointProps: function(tag, properties) {
-            TODO("Marked content");
-        },
-        beginMarkedContent: function(tag) {
-            TODO("Marked content");
-        },
-        beginMarkedContentProps: function(tag, properties) {
-            TODO("Marked content");
-        },
-        endMarkedContent: function() {
-            TODO("Marked content");
-        },
-
-        // Compatibility
-
-        beginCompat: function() {
-            TODO("ignore undefined operators (should we do that anyway?)");
-        },
-        endCompat: function() {
-            TODO("stop ignoring undefined operators");
-        },
-
-        // Helper functions
-
-        consumePath: function() {
-            if (this.pendingClip) {
-                var savedFillRule = null;
-                if (this.pendingClip == EO_CLIP)
-                    savedFillRule = this.setEOFillRule();
-
-                this.ctx.clip();
-
-                this.pendingClip = null;
-                if (savedFillRule !== null)
-                    this.restoreFillRule(savedFillRule);
-            }
-            this.ctx.beginPath();
-        },
-        makeCssRgb: function(r, g, b) {
-            var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
-            return "rgb("+ ri +","+ gi +","+ bi +")";
-        },
-        makeCssCmyk: function(c, m, y, k) {
-            // while waiting on CSS's cmyk()... http://www.ilkeratalay.com/colorspacesfaq.php#rgb
-            var ri = (255 * (1 - Math.min(1, c * (1 - k) + k))) | 0;
-            var gi = (255 * (1 - Math.min(1, m * (1 - k) + k))) | 0;
-            var bi = (255 * (1 - Math.min(1, y * (1 - k) + k))) | 0;
-            return "rgb("+ ri +","+ gi +","+ bi +")";
-        },
-        getFillColorSpace: function() {
-            var cs = this.current.fillColorSpace;
-            if (cs)
-                return cs;
-
-            var states = this.stateStack;
-            var i = states.length - 1;
-            while (i >= 0 && !(cs = states[i].fillColorSpace))
-                --i;
-
-            if (cs)
-                return cs;
-            else
-                return new DeviceRgbCS();
-        },
-        getStrokeColorSpace: function() {
-            var cs = this.current.strokeColorSpace;
-            if (cs)
-                return cs;
-            
-            var states = this.stateStack;
-            var i = states.length - 1;
-            while (i >= 0 && !(cs = states[i].strokeColorSpace))
-                --i;
-
-            if (cs)
-                return cs;
-            else
-                return new DeviceRgbCS();
-        },
-        // We generally keep the canvas context set for
-        // nonzero-winding, and just set evenodd for the operations
-        // that need them.
-        setEOFillRule: function() {
-            var savedFillRule = this.ctx.mozFillRule;
-            this.ctx.mozFillRule = "evenodd";
-            return savedFillRule;
-        },
-        restoreFillRule: function(rule) {
-            this.ctx.mozFillRule = rule;
-        }
-    };
+    paintFormXObject: function(ref, stream) {
+      this.save();
+
+      var matrix = stream.dict.get('Matrix');
+      if (matrix && IsArray(matrix) && 6 == matrix.length)
+        this.transform.apply(this, matrix);
+
+      var bbox = stream.dict.get('BBox');
+      if (bbox && IsArray(bbox) && 4 == bbox.length) {
+        this.rectangle.apply(this, bbox);
+        this.clip();
+        this.endPath();
+      }
+
+      this.execute(ref.code, this.xref, stream.dict.get('Resources'));
+
+      this.restore();
+    },
+
+    paintImageXObject: function(ref, image, inline) {
+      this.save();
+
+      var ctx = this.ctx;
+      var dict = image.dict;
+      var w = dict.get2('Width', 'W');
+      var h = dict.get2('Height', 'H');
+      // scale the image to the unit square
+      ctx.scale(1 / w, -1 / h);
+
+      // If the platform can render the image format directly, the
+      // stream has a getImage property which directly returns a
+      // suitable DOM Image object.
+      if (image.getImage) {
+        var domImage = image.getImage();
+        ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
+                      0, -h, w, h);
+        this.restore();
+        return;
+      }
 
-    return constructor;
+      var imageObj = new PDFImage(this.xref, this.res, image, inline);
+
+      var tmpCanvas = new this.ScratchCanvas(w, h);
+      var tmpCtx = tmpCanvas.getContext('2d');
+      var imgData = tmpCtx.getImageData(0, 0, w, h);
+      var pixels = imgData.data;
+
+      imageObj.fillRgbaBuffer(pixels);
+
+      tmpCtx.putImageData(imgData, 0, 0);
+      ctx.drawImage(tmpCanvas, 0, -h);
+      this.restore();
+    },
+
+    // Marked content
+
+    markPoint: function(tag) {
+      TODO('Marked content');
+    },
+    markPointProps: function(tag, properties) {
+      TODO('Marked content');
+    },
+    beginMarkedContent: function(tag) {
+      TODO('Marked content');
+    },
+    beginMarkedContentProps: function(tag, properties) {
+      TODO('Marked content');
+    },
+    endMarkedContent: function() {
+      TODO('Marked content');
+    },
+
+    // Compatibility
+
+    beginCompat: function() {
+      TODO('ignore undefined operators (should we do that anyway?)');
+    },
+    endCompat: function() {
+      TODO('stop ignoring undefined operators');
+    },
+
+    // Helper functions
+
+    consumePath: function() {
+      if (this.pendingClip) {
+        var savedFillRule = null;
+        if (this.pendingClip == EO_CLIP)
+          savedFillRule = this.setEOFillRule();
+
+        this.ctx.clip();
+
+        this.pendingClip = null;
+        if (savedFillRule !== null)
+          this.restoreFillRule(savedFillRule);
+      }
+      this.ctx.beginPath();
+    },
+    makeCssRgb: function(r, g, b) {
+      var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
+      return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
+    },
+    makeCssCmyk: function(c, m, y, k) {
+      // while waiting on CSS's cmyk()...
+      // http://www.ilkeratalay.com/colorspacesfaq.php#rgb
+      var ri = (255 * (1 - Math.min(1, c * (1 - k) + k))) | 0;
+      var gi = (255 * (1 - Math.min(1, m * (1 - k) + k))) | 0;
+      var bi = (255 * (1 - Math.min(1, y * (1 - k) + k))) | 0;
+      return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
+    },
+    getFillColorSpace: function() {
+      var cs = this.current.fillColorSpace;
+      if (cs)
+        return cs;
+
+      var states = this.stateStack;
+      var i = states.length - 1;
+      while (i >= 0 && !(cs = states[i].fillColorSpace))
+        --i;
+
+      if (cs)
+        return cs;
+      else
+        return new DeviceRgbCS();
+    },
+    getStrokeColorSpace: function() {
+      var cs = this.current.strokeColorSpace;
+      if (cs)
+        return cs;
+
+      var states = this.stateStack;
+      var i = states.length - 1;
+      while (i >= 0 && !(cs = states[i].strokeColorSpace))
+        --i;
+
+      if (cs)
+        return cs;
+      else
+        return new DeviceRgbCS();
+    },
+    // We generally keep the canvas context set for
+    // nonzero-winding, and just set evenodd for the operations
+    // that need them.
+    setEOFillRule: function() {
+      var savedFillRule = this.ctx.mozFillRule;
+      this.ctx.mozFillRule = 'evenodd';
+      return savedFillRule;
+    },
+    restoreFillRule: function(rule) {
+      this.ctx.mozFillRule = rule;
+    }
+  };
+
+  return constructor;
 })();
 
 var ColorSpace = (function() {
-    function constructor() {
-        error("should not call ColorSpace constructor");
-    };
-
-    constructor.parse = function colorspace_parse(cs, xref, res) {
-        if (IsName(cs)) {
-            var colorSpaces = res.get("ColorSpace");
-            if (colorSpaces) {
-                var refcs = colorSpaces.get(cs.name);
-                if (refcs)
-                    cs = refcs;
-            }
-        }
-            
-        cs = xref.fetchIfRef(cs);
-
-        if (IsName(cs)) {
-            var mode = cs.name;
-            this.mode = mode;
+  function constructor() {
+    error('should not call ColorSpace constructor');
+  };
+
+  constructor.parse = function colorspace_parse(cs, xref, res) {
+    if (IsName(cs)) {
+      var colorSpaces = res.get('ColorSpace');
+      if (colorSpaces) {
+        var refcs = colorSpaces.get(cs.name);
+        if (refcs)
+          cs = refcs;
+      }
+    }
 
-            switch(mode) {
-            case "DeviceGray":
-            case "G":
-                return new DeviceGrayCS();
-                break;
-            case "DeviceRGB":
-            case "RGB":
-                return new DeviceRgbCS();
-                break;
-            case "DeviceCMYK":
-            case "CMYK":
-                return new DeviceCmykCS();
-                break;
-            case "Pattern":
-                return new PatternCS(null);
-                break;
-            default:
-                error("unrecognized colorspace " + mode);
-            }
-        } else if (IsArray(cs)) {
-            var mode = cs[0].name;
-            this.mode = mode;
-
-            switch (mode) {
-            case "DeviceGray":
-            case "G":
-                return new DeviceGrayCS();
-                break;
-            case "DeviceRGB":
-            case "RGB":
-                return new DeviceRgbCS();
-                break;
-            case "DeviceCMYK":
-            case "CMYK":
-                return new DeviceCmykCS();
-                break;
-            case "CalGray":
-                return new DeviceGrayCS();
-                break;
-            case "CalRGB":
-                return new DeviceRgbCS();
-                break;
-            case "ICCBased":
-                var stream = xref.fetchIfRef(cs[1]);
-                var dict = stream.dict;
-                var numComps = dict.get("N");
-                if (numComps == 1)
-                    return new DeviceGrayCS();
-                else if (numComps == 3)
-                    return new DeviceRgbCS();
-                else if (numComps == 4)
-                    return new DeviceCmykCS();
-                break;
-            case "Pattern":
-                return new PatternCS();
-                break;
-            case "Indexed":
-                var base = ColorSpace.parse(cs[1], xref, res);
-                var hiVal = cs[2] + 1;
-                var lookup = xref.fetchIfRef(cs[3]);
-                return new IndexedCS(base, hiVal, lookup);
-            case "Lab":
-            case "Seperation":
-            case "DeviceN":
-            default:
-                error("unrecognized color space object '"+ mode +"'");
-            }
-        } else {
-            error("unrecognized color space object");
-        }
-    };
+    cs = xref.fetchIfRef(cs);
+
+    if (IsName(cs)) {
+      var mode = cs.name;
+      this.mode = mode;
+
+      switch (mode) {
+      case 'DeviceGray':
+      case 'G':
+        return new DeviceGrayCS();
+        break;
+      case 'DeviceRGB':
+      case 'RGB':
+        return new DeviceRgbCS();
+        break;
+      case 'DeviceCMYK':
+      case 'CMYK':
+        return new DeviceCmykCS();
+        break;
+      case 'Pattern':
+        return new PatternCS(null);
+        break;
+      default:
+        error('unrecognized colorspace ' + mode);
+      }
+    } else if (IsArray(cs)) {
+      var mode = cs[0].name;
+      this.mode = mode;
+
+      switch (mode) {
+      case 'DeviceGray':
+      case 'G':
+        return new DeviceGrayCS();
+        break;
+      case 'DeviceRGB':
+      case 'RGB':
+        return new DeviceRgbCS();
+        break;
+      case 'DeviceCMYK':
+      case 'CMYK':
+        return new DeviceCmykCS();
+        break;
+      case 'CalGray':
+        return new DeviceGrayCS();
+        break;
+      case 'CalRGB':
+        return new DeviceRgbCS();
+        break;
+      case 'ICCBased':
+        var stream = xref.fetchIfRef(cs[1]);
+        var dict = stream.dict;
+        var numComps = dict.get('N');
+        if (numComps == 1)
+          return new DeviceGrayCS();
+        else if (numComps == 3)
+          return new DeviceRgbCS();
+        else if (numComps == 4)
+          return new DeviceCmykCS();
+        break;
+      case 'Pattern':
+        return new PatternCS();
+        break;
+      case 'Indexed':
+        var base = ColorSpace.parse(cs[1], xref, res);
+        var hiVal = cs[2] + 1;
+        var lookup = xref.fetchIfRef(cs[3]);
+        return new IndexedCS(base, hiVal, lookup);
+      case 'Lab':
+      case 'Seperation':
+      case 'DeviceN':
+      default:
+        error("unrecognized color space object '" + mode + "'");
+      }
+    } else {
+      error('unrecognized color space object');
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
 
 var PatternCS = (function() {
-    function constructor() {
-        this.name = "Pattern";
-    }
-    constructor.prototype = {};
-  
-    return constructor;
+  function constructor() {
+    this.name = 'Pattern';
+  }
+  constructor.prototype = {};
+
+  return constructor;
 })();
 
 var IndexedCS = (function() {
-    function constructor(base, highVal, lookup) {
-        this.name = "Indexed";
-        this.numComps = 1;
-        this.defaultColor = [0];
-
-        this.base = base;
-        var baseNumComps = base.numComps;
-        this.highVal = highVal;
-
-        var length = baseNumComps * highVal;
-        var lookupArray = new Uint8Array(length);
-        if (IsStream(lookup)) {
-            var bytes = lookup.getBytes(length);
-            lookupArray.set(bytes);
-        } else if (IsString(lookup)) {
-            for (var i = 0; i < length; ++i)
-                lookupArray[i] = lookup.charCodeAt(i);
-        } else {
-            error("Unrecognized lookup table");
-        }
-        this.lookup = lookupArray;
+  function constructor(base, highVal, lookup) {
+    this.name = 'Indexed';
+    this.numComps = 1;
+    this.defaultColor = [0];
+
+    this.base = base;
+    var baseNumComps = base.numComps;
+    this.highVal = highVal;
+
+    var length = baseNumComps * highVal;
+    var lookupArray = new Uint8Array(length);
+    if (IsStream(lookup)) {
+      var bytes = lookup.getBytes(length);
+      lookupArray.set(bytes);
+    } else if (IsString(lookup)) {
+      for (var i = 0; i < length; ++i)
+        lookupArray[i] = lookup.charCodeAt(i);
+    } else {
+      error('Unrecognized lookup table');
     }
+    this.lookup = lookupArray;
+  }
 
-    constructor.prototype = {
-        getRgb: function graycs_getRgb(color) {
-            var lookup = this.lookup;
-            var base = this.base;
-            var numComps = base.numComps;
-            
-            var c = [];
-            for (var i = 0; i < numComps; ++i)
-                c.push(lookup[i])
-            return this.base.getRgb(c);
-        },
-        getRgbBuffer: function graycs_getRgbBuffer(input) {
-            var base = this.base;
-            var numComps = base.numComps;
-            var lookup = this.lookup;
-            var length = input.length;
-
-            var baseBuf = new Uint8Array(length * numComps);
-            var baseBufPos = 0;
-            for (var i = 0; i < length; ++i) {
-                var lookupPos = input[i];
-                for (var j = 0; j < numComps ; ++j) {
-                    baseBuf[baseBufPos++] = lookup[lookupPos + j];
-                }
-            }
-            
-            return base.getRgbBuffer(baseBuf);
+  constructor.prototype = {
+    getRgb: function graycs_getRgb(color) {
+      var lookup = this.lookup;
+      var base = this.base;
+      var numComps = base.numComps;
+
+      var c = [];
+      for (var i = 0; i < numComps; ++i)
+        c.push(lookup[i]);
+      return this.base.getRgb(c);
+    },
+    getRgbBuffer: function graycs_getRgbBuffer(input) {
+      var base = this.base;
+      var numComps = base.numComps;
+      var lookup = this.lookup;
+      var length = input.length;
+
+      var baseBuf = new Uint8Array(length * numComps);
+      var baseBufPos = 0;
+      for (var i = 0; i < length; ++i) {
+        var lookupPos = input[i];
+        for (var j = 0; j < numComps; ++j) {
+          baseBuf[baseBufPos++] = lookup[lookupPos + j];
         }
-    };
-    return constructor;
+      }
+
+      return base.getRgbBuffer(baseBuf);
+    }
+  };
+  return constructor;
 })();
 
 var DeviceGrayCS = (function() {
-    function constructor() {
-        this.name = "DeviceGray";
-        this.numComps = 1;
-        this.defaultColor = [0];
-    };
-
-    constructor.prototype = {
-        getRgb: function graycs_getRgb(color) {
-            var c = color[0];
-            return [c, c, c];
-        },
-        getRgbBuffer: function graycs_getRgbBuffer(input) {
-            var length = input.length;
-            var rgbBuf = new Uint8Array(length);
-            for (var i = 0, j = 0; i < length; ++i) {
-                var c = input[i];
-                rgbBuf[j++] = c;
-                rgbBuf[j++] = c;
-                rgbBuf[j++] = c;
-            }
-            return rgbBuf;
-        }
-    };
-    return constructor;
+  function constructor() {
+    this.name = 'DeviceGray';
+    this.numComps = 1;
+    this.defaultColor = [0];
+  };
+
+  constructor.prototype = {
+    getRgb: function graycs_getRgb(color) {
+      var c = color[0];
+      return [c, c, c];
+    },
+    getRgbBuffer: function graycs_getRgbBuffer(input) {
+      var length = input.length;
+      var rgbBuf = new Uint8Array(length);
+      for (var i = 0, j = 0; i < length; ++i) {
+        var c = input[i];
+        rgbBuf[j++] = c;
+        rgbBuf[j++] = c;
+        rgbBuf[j++] = c;
+      }
+      return rgbBuf;
+    }
+  };
+  return constructor;
 })();
 
 var DeviceRgbCS = (function() {
-    function constructor() {
-        this.name = "DeviceRGB";
-        this.numComps = 3;
-        this.defaultColor = [0, 0, 0];
+  function constructor() {
+    this.name = 'DeviceRGB';
+    this.numComps = 3;
+    this.defaultColor = [0, 0, 0];
+  }
+  constructor.prototype = {
+    getRgb: function graycs_getRgb(color) {
+      return color;
+    },
+    getRgbBuffer: function graycs_getRgbBuffer(input) {
+      return input;
     }
-    constructor.prototype = {
-        getRgb: function graycs_getRgb(color) {
-            return color;
-        },
-        getRgbBuffer: function graycs_getRgbBuffer(input) {
-            return input;
-        }
-    };
-    return constructor;
+  };
+  return constructor;
 })();
 
 var DeviceCmykCS = (function() {
-    function constructor() {
-        this.name = "DeviceCMYK";
-        this.numComps = 4;
-        this.defaultColor = [0, 0, 0, 1];
+  function constructor() {
+    this.name = 'DeviceCMYK';
+    this.numComps = 4;
+    this.defaultColor = [0, 0, 0, 1];
+  }
+  constructor.prototype = {
+    getRgb: function graycs_getRgb(color) {
+      var c = color[0], y = color[1], m = color[2], k = color[3];
+      var ri = (1 - Math.min(1, c * (1 - k) + k)) | 0;
+      var gi = (1 - Math.min(1, m * (1 - k) + k)) | 0;
+      var bi = (1 - Math.min(1, y * (1 - k) + k)) | 0;
+      return [ri, gi, bi];
+    },
+    getRgbBuffer: function graycs_getRgbBuffer(colorBuf) {
+      error('conversion from rgb to cmyk not implemented for images');
+      return colorBuf;
     }
-    constructor.prototype = {
-        getRgb: function graycs_getRgb(color) {
-            var c = color[0], y = color[1], m = color[2], k = color[3];
-            var ri = (1 - Math.min(1, c * (1 - k) + k)) | 0;
-            var gi = (1 - Math.min(1, m * (1 - k) + k)) | 0;
-            var bi = (1 - Math.min(1, y * (1 - k) + k)) | 0;
-            return [ri, gi, bi];
-        },
-        getRgbBuffer: function graycs_getRgbBuffer(colorBuf) {
-            error("conversion from rgb to cmyk not implemented for images");
-            return colorBuf;
-        }
-    };
-    return constructor;
+  };
+  return constructor;
 })();
 
 var PDFImage = (function() {
-    function constructor(xref, res, image, inline) {
-        this.image = image;
-        if (image.getParams) {
-            // JPX/JPEG2000 streams directly contain bits per component
-            // and color space mode information.
-            TODO("get params from actual stream");
-            // var bits = ...
-            // var colorspace = ...
+  function constructor(xref, res, image, inline) {
+    this.image = image;
+    if (image.getParams) {
+      // JPX/JPEG2000 streams directly contain bits per component
+      // and color space mode information.
+      TODO('get params from actual stream');
+      // var bits = ...
+      // var colorspace = ...
+    }
+    // TODO cache rendered images?
+
+    var dict = image.dict;
+    this.width = dict.get2('Width', 'W');
+    this.height = dict.get2('Height', 'H');
+
+    if (this.width < 1 || this.height < 1)
+      error('Invalid image width or height');
+
+    this.interpolate = dict.get2('Interpolate', 'I') || false;
+    this.imageMask = dict.get2('ImageMask', 'IM') || false;
+
+    var bitsPerComponent = image.bitsPerComponent;
+    if (!bitsPerComponent) {
+      bitsPerComponent = dict.get2('BitsPerComponent', 'BPC');
+      if (!bitsPerComponent) {
+        if (this.imageMask)
+          bitsPerComponent = 1;
+        else
+          error('Bits per component missing in image');
+      }
+    }
+    this.bpc = bitsPerComponent;
+
+    var colorSpace = dict.get2('ColorSpace', 'CS');
+    this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
+
+    this.numComps = this.colorSpace.numComps;
+    this.decode = dict.get2('Decode', 'D');
+
+    var mask = xref.fetchIfRef(image.dict.get('Mask'));
+    var smask = xref.fetchIfRef(image.dict.get('SMask'));
+
+    if (mask) {
+      TODO('masked images');
+    } else if (smask) {
+      this.smask = new PDFImage(xref, res, smask);
+    }
+  };
+
+  constructor.prototype = {
+    getComponents: function getComponents(buffer) {
+      var bpc = this.bpc;
+      if (bpc == 8)
+        return buffer;
+
+      var width = this.width;
+      var height = this.height;
+      var numComps = this.numComps;
+
+      var length = width * height;
+      var bufferPos = 0;
+      var output = new Uint8Array(length);
+
+      if (bpc == 1) {
+        var rowComps = width * numComps;
+        var mask = 0;
+        var buf = 0;
+
+        for (var i = 0, ii = length; i < ii; ++i) {
+          if (i % rowComps == 0) {
+            mask = 0;
+            buf = 0;
+          } else {
+            mask >>= 1;
+          }
+
+          if (mask <= 0) {
+            buf = buffer[bufferPos++];
+            mask = 128;
+          }
+
+          var t = buf & mask;
+          if (t == 0)
+            output[i] = 0;
+          else
+            output[i] = 255;
         }
-        // TODO cache rendered images?
-
-        var dict = image.dict;
-        this.width = dict.get2("Width", "W");
-        this.height = dict.get2("Height", "H");
-
-        if (this.width < 1 || this.height < 1)
-            error("Invalid image width or height");
-
-        this.interpolate = dict.get2("Interpolate", "I") || false;
-        this.imageMask = dict.get2("ImageMask", "IM") || false;
-
-        var bitsPerComponent = image.bitsPerComponent;
-        if (!bitsPerComponent) {
-            bitsPerComponent = dict.get2("BitsPerComponent", "BPC");
-            if (!bitsPerComponent) {
-                if (this.imageMask)
-                    bitsPerComponent = 1;
-                else
-                    error("Bits per component missing in image");
-            }
+      } else {
+        var rowComps = width * numComps;
+        var bits = 0;
+        var buf = 0;
+
+        for (var i = 0, ii = length; i < ii; ++i) {
+          while (bits < bpc) {
+            buf = (buf << 8) | buffer[bufferPos++];
+            bits += 8;
+          }
+          var remainingBits = bits - bpc;
+          var ret = buf >> remainingBits;
+
+          if (i % rowComps == 0) {
+            buf = 0;
+            bits = 0;
+          } else {
+            buf = buf & ((1 << remainingBits) - 1);
+            bits = remainingBits;
+          }
+          output[i] = Math.round(255 * ret / ((1 << bpc) - 1));
         }
-        this.bpc = bitsPerComponent;
+      }
+      return this.colorSpace.getRbaBuffer(output);
+    },
+    getOpacity: function getOpacity() {
+      var smask = this.smask;
+      var width = this.width;
+      var height = this.height;
+      var buf = new Uint8Array(width * height);
+
+      if (smask) {
+        var sw = smask.width;
+        var sh = smask.height;
+        if (sw != this.width || sh != this.height)
+          error('smask dimensions do not match image dimensions');
+
+        smask.fillGrayBuffer(buf);
+        return buf;
+      } else {
+        for (var i = 0, ii = width * height; i < ii; ++i)
+          buf[i] = 255;
+      }
+      return buf;
+    },
+    fillRgbaBuffer: function fillRgbaBuffer(buffer) {
+      var numComps = this.numComps;
+      var width = this.width;
+      var height = this.height;
+      var bpc = this.bpc;
+
+      // rows start at byte boundary;
+      var rowBytes = (width * numComps * bpc + 7) >> 3;
+      var imgArray = this.image.getBytes(height * rowBytes);
+
+      var comps = this.getComponents(imgArray);
+      var compsPos = 0;
+      var opacity = this.getOpacity();
+      var opacityPos = 0;
+      var length = width * height * 4;
+
+      switch (numComps) {
+      case 1:
+        for (var i = 0; i < length; i += 4) {
+          var p = comps[compsPos++];
+          buffer[i] = p;
+          buffer[i + 1] = p;
+          buffer[i + 2] = p;
+          buffer[i + 3] = opacity[opacityPos++];
+        }
+        break;
+      case 3:
+        for (var i = 0; i < length; i += 4) {
+          buffer[i] = comps[compsPos++];
+          buffer[i + 1] = comps[compsPos++];
+          buffer[i + 2] = comps[compsPos++];
+          buffer[i + 3] = opacity[opacityPos++];
+        }
+        break;
+      default:
+        TODO('Images with ' + numComps + ' components per pixel');
+      }
+    },
+    fillGrayBuffer: function fillGrayBuffer(buffer) {
+      var numComps = this.numComps;
+      if (numComps != 1)
+        error('Reading gray scale from a color image');
 
-        var colorSpace = dict.get2("ColorSpace", "CS");
-        this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
+      var width = this.width;
+      var height = this.height;
+      var bpc = this.bpc;
 
-        this.numComps = this.colorSpace.numComps;
-        this.decode = dict.get2("Decode", "D");
+      // rows start at byte boundary;
+      var rowBytes = (width * numComps * bpc + 7) >> 3;
+      var imgArray = this.image.getBytes(height * rowBytes);
 
-        var mask = xref.fetchIfRef(image.dict.get("Mask"));
-        var smask = xref.fetchIfRef(image.dict.get("SMask"));
+      var comps = this.getComponents(imgArray);
+      var length = width * height;
 
-        if (mask) {
-            TODO("masked images");
-        } else if (smask) {
-            this.smask = new PDFImage(xref, res, smask);
-        }
-    };
-    
-    constructor.prototype = {
-        getComponents: function getComponents(buffer) {
-            var bpc = this.bpc;
-            if (bpc == 8)
-                return buffer;
-
-            var width = this.width;
-            var height = this.height;
-            var numComps = this.numComps;
-        
-            var length = width * height;
-            var bufferPos = 0;
-            var output = new Uint8Array(length);
-
-            if (bpc == 1) {
-                var rowComps = width * numComps;
-                var mask = 0;
-                var buf = 0;
-                
-                for (var i = 0, ii = length; i < ii; ++i) {
-                    if (i % rowComps == 0) {
-                        mask = 0;
-                        buf = 0;
-                    } else {
-                        mask >>= 1;
-                    }
-
-                    if (mask <= 0) {
-                        buf = buffer[bufferPos++];
-                        mask = 128;
-                    }
-
-                    var t = buf & mask;
-                    if (t == 0)
-                        output[i] = 0;
-                    else
-                        output[i] = 255;
-                }
-            } else {
-                var rowComps = width * numComps;
-                var bits = 0;
-                var buf = 0;
-
-                for (var i = 0, ii = length; i < ii; ++i) {
-                    while (bits < bpc) {
-                        buf = (buf << 8) | buffer[bufferPos++];
-                        bits += 8;
-                    }
-                    var remainingBits = bits - bpc;
-                    var ret = buf >> remainingBits;
-                    
-                    if (i % rowComps == 0) {
-                        buf = 0;
-                        bits = 0;
-                    } else {
-                        buf = buf & ((1 << remainingBits) - 1);
-                        bits = remainingBits;
-                    }
-                    output[i] = Math.round(255 * ret / ((1 << bpc) - 1));
-                }
-            }
-            return this.colorSpace.getRbaBuffer(output);
-        },
-        getOpacity: function getOpacity() {
-            var smask = this.smask;
-            var width = this.width;
-            var height = this.height;
-            var buf = new Uint8Array(width * height);
-            
-            if (smask) {
-                var sw = smask.width;
-                var sh = smask.height;
-                if (sw != this.width || sh != this.height)
-                    error("smask dimensions do not match image dimensions");
-                
-                smask.fillGrayBuffer(buf);
-                return buf;
-            } else {
-                for (var i = 0, ii = width * height; i < ii; ++i)
-                    buf[i] = 255;
-            }
-            return buf;
-        },
-        fillRgbaBuffer: function fillRgbaBuffer(buffer) {
-            var numComps = this.numComps;
-            var width = this.width;
-            var height = this.height;
-            var bpc = this.bpc;
-
-            // rows start at byte boundary;
-            var rowBytes = (width * numComps * bpc + 7) >> 3;
-            var imgArray = this.image.getBytes(height * rowBytes);
-            
-            var comps = this.getComponents(imgArray);
-            var compsPos = 0;
-            var opacity = this.getOpacity();
-            var opacityPos = 0;
-            var length = width * height * 4;
-
-            switch (numComps) {
-                case 1:
-                    for (var i = 0; i < length; i += 4) {
-                        var p = comps[compsPos++];
-                        buffer[i] = p;
-                        buffer[i+1] = p;
-                        buffer[i+2] = p;
-                        buffer[i+3] = opacity[opacityPos++];
-                    }
-                    break;
-                case 3:
-                    for (var i = 0; i < length; i += 4) {
-                        buffer[i] = comps[compsPos++];
-                        buffer[i+1] = comps[compsPos++];
-                        buffer[i+2] = comps[compsPos++];
-                        buffer[i+3] = opacity[opacityPos++];
-                    }
-                    break;
-                default:
-                    TODO("Images with "+ numComps + " components per pixel");
-            }
-        },
-        fillGrayBuffer: function fillGrayBuffer(buffer) {
-            var numComps = this.numComps;
-            if (numComps != 1)
-                error("Reading gray scale from a color image");
-
-            var width = this.width;
-            var height = this.height;
-            var bpc = this.bpc;
-
-            // rows start at byte boundary;
-            var rowBytes = (width * numComps * bpc + 7) >> 3;
-            var imgArray = this.image.getBytes(height * rowBytes);
-            
-            var comps = this.getComponents(imgArray);
-            var length = width * height;
-
-            for (var i = 0; i < length; ++i)
-                buffer[i] = comps[i];
-        },
-    };
-    return constructor;
+      for (var i = 0; i < length; ++i)
+        buffer[i] = comps[i];
+    }
+  };
+  return constructor;
 })();
 
 var PDFFunction = (function() {
-    function constructor(xref, fn) {
-        var dict = fn.dict;
-        if (!dict)
-           dict = fn;
-
-        var types = [this.constructSampled,
-                       null,
-                       this.constructInterpolated,
-                       this.constructStiched,
-                       this.constructPostScript];
-
-        var typeNum = dict.get("FunctionType");
-        var typeFn = types[typeNum];
-        if (!typeFn)
-            error("Unknown type of function");
-
-        typeFn.apply(this, [fn, dict]);
-    };
-
-    constructor.prototype = {
-        constructSampled: function(str, dict) {
-            var domain = dict.get("Domain");
-            var range = dict.get("Range");
-
-            if (!domain || !range)
-                error("No domain or range");
-
-            var inputSize = domain.length / 2;
-            var outputSize = range.length / 2;
-
-            if (inputSize != 1)
-                error("No support for multi-variable inputs to functions");
-
-            var size = dict.get("Size");
-            var bps = dict.get("BitsPerSample");
-            var order = dict.get("Order");
-            if (!order)
-                order = 1;
-            if (order !== 1)
-                error ("No support for cubic spline interpolation");
-
-            var encode = dict.get("Encode");
-            if (!encode) {
-                encode = [];
-                for (var i = 0; i < inputSize; ++i) {
-                    encode.push(0);
-                    encode.push(size[i] - 1);
-                }
-            }
-            var decode = dict.get("Decode");
-            if (!decode)
-                decode = range;
-
-            var samples = this.getSampleArray(size, outputSize, bps, str);
-
-            this.func = function(args) {
-                var clip = function(v, min, max) {
-                    if (v > max)
-                        v = max;
-                    else if (v < min)
-                        v = min
-                    return v;
-                }
+  function constructor(xref, fn) {
+    var dict = fn.dict;
+    if (!dict)
+      dict = fn;
+
+    var types = [this.constructSampled,
+                 null,
+                 this.constructInterpolated,
+                 this.constructStiched,
+                 this.constructPostScript];
+
+    var typeNum = dict.get('FunctionType');
+    var typeFn = types[typeNum];
+    if (!typeFn)
+      error('Unknown type of function');
+
+    typeFn.apply(this, [fn, dict]);
+  };
+
+  constructor.prototype = {
+    constructSampled: function(str, dict) {
+      var domain = dict.get('Domain');
+      var range = dict.get('Range');
+
+      if (!domain || !range)
+        error('No domain or range');
+
+      var inputSize = domain.length / 2;
+      var outputSize = range.length / 2;
+
+      if (inputSize != 1)
+        error('No support for multi-variable inputs to functions');
+
+      var size = dict.get('Size');
+      var bps = dict.get('BitsPerSample');
+      var order = dict.get('Order');
+      if (!order)
+        order = 1;
+      if (order !== 1)
+        error('No support for cubic spline interpolation');
+
+      var encode = dict.get('Encode');
+      if (!encode) {
+        encode = [];
+        for (var i = 0; i < inputSize; ++i) {
+          encode.push(0);
+          encode.push(size[i] - 1);
+        }
+      }
+      var decode = dict.get('Decode');
+      if (!decode)
+        decode = range;
+
+      var samples = this.getSampleArray(size, outputSize, bps, str);
+
+      this.func = function(args) {
+        var clip = function(v, min, max) {
+          if (v > max)
+            v = max;
+          else if (v < min)
+            v = min;
+          return v;
+        }
 
-                if (inputSize != args.length)
-                    error("Incorrect number of arguments");
+        if (inputSize != args.length)
+          error('Incorrect number of arguments');
 
-                for (var i = 0; i < inputSize; i++) {
-                    var i2 = i * 2;
+        for (var i = 0; i < inputSize; i++) {
+          var i2 = i * 2;
 
-                    // clip to the domain
-                    var v = clip(args[i], domain[i2], domain[i2 + 1]);
+          // clip to the domain
+          var v = clip(args[i], domain[i2], domain[i2 + 1]);
 
-                    // encode
-                    v = encode[i2] + ((v - domain[i2]) *
-                                      (encode[i2 + 1] - encode[i2]) /
-                                      (domain[i2 + 1] - domain[i2]));
+          // encode
+          v = encode[i2] + ((v - domain[i2]) *
+                            (encode[i2 + 1] - encode[i2]) /
+                            (domain[i2 + 1] - domain[i2]));
 
-                    // clip to the size
-                    args[i] = clip(v, 0, size[i] - 1);
-                }
+          // clip to the size
+          args[i] = clip(v, 0, size[i] - 1);
+        }
 
-                // interpolate to table
-                TODO("Multi-dimensional interpolation");
-                var floor = Math.floor(args[0]);
-                var ceil = Math.ceil(args[0]);
-                var scale = args[0] - floor;
-
-                floor *= outputSize;
-                ceil *= outputSize;
-
-                var output = [];
-                for (var i = 0; i < outputSize; ++i) {
-                    if (ceil == floor) {
-                        var v = samples[ceil + i];
-                    } else {
-                        var low = samples[floor + i];
-                        var high = samples[ceil + i];
-                        var v = low * scale + high * (1 - scale);
-                    }
-
-                    var i2 = i * 2;
-                    // decode
-                    v = decode[i2] + (v * (decode[i2 + 1] - decode[i2]) /
-                                      ((1 << bps) - 1));
-
-                    // clip to the domain
-                    output.push(clip(v, range[i2], range[i2 + 1]));
-                }
+        // interpolate to table
+        TODO('Multi-dimensional interpolation');
+        var floor = Math.floor(args[0]);
+        var ceil = Math.ceil(args[0]);
+        var scale = args[0] - floor;
+
+        floor *= outputSize;
+        ceil *= outputSize;
+
+        var output = [];
+        for (var i = 0; i < outputSize; ++i) {
+          if (ceil == floor) {
+            var v = samples[ceil + i];
+          } else {
+            var low = samples[floor + i];
+            var high = samples[ceil + i];
+            var v = low * scale + high * (1 - scale);
+          }
+
+          var i2 = i * 2;
+          // decode
+          v = decode[i2] + (v * (decode[i2 + 1] - decode[i2]) /
+                            ((1 << bps) - 1));
+
+          // clip to the domain
+          output.push(clip(v, range[i2], range[i2 + 1]));
+        }
 
-                return output;
-            }
-        },
-        getSampleArray: function(size, outputSize, bps, str) {
-            var length = 1;
-            for (var i = 0; i < size.length; i++)
-                length *= size[i];
-            length *= outputSize;
-
-            var array = [];
-            var codeSize = 0;
-            var codeBuf = 0;
-
-            var strBytes = str.getBytes((length * bps + 7) / 8);
-            var strIdx = 0;
-            for (var i = 0; i < length; i++) {
-                var b;
-                while (codeSize < bps) {
-                    codeBuf <<= 8;
-                    codeBuf |= strBytes[strIdx++];
-                    codeSize += 8;
-                }
-                codeSize -= bps
-                array.push(codeBuf >> codeSize);
-                codeBuf &= (1 << codeSize) - 1;
-            }
-            return array;
-        },
-        constructInterpolated: function() {
-            error("unhandled type of function");
-        },
-        constructStiched: function() {
-            error("unhandled type of function");
-        },
-        constructPostScript: function() {
-            error("unhandled type of function");
+        return output;
+      }
+    },
+    getSampleArray: function(size, outputSize, bps, str) {
+      var length = 1;
+      for (var i = 0; i < size.length; i++)
+        length *= size[i];
+      length *= outputSize;
+
+      var array = [];
+      var codeSize = 0;
+      var codeBuf = 0;
+
+      var strBytes = str.getBytes((length * bps + 7) / 8);
+      var strIdx = 0;
+      for (var i = 0; i < length; i++) {
+        var b;
+        while (codeSize < bps) {
+          codeBuf <<= 8;
+          codeBuf |= strBytes[strIdx++];
+          codeSize += 8;
         }
-    };
+        codeSize -= bps;
+        array.push(codeBuf >> codeSize);
+        codeBuf &= (1 << codeSize) - 1;
+      }
+      return array;
+    },
+    constructInterpolated: function() {
+      error('unhandled type of function');
+    },
+    constructStiched: function() {
+      error('unhandled type of function');
+    },
+    constructPostScript: function() {
+      error('unhandled type of function');
+    }
+  };
 
-    return constructor;
+  return constructor;
 })();
index 1b328a2da55c78bd4fdcb11bf577baadeee5abb6..09c408ee7b0019288899d8881a6cae34249af2ab 100644 (file)
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var CFFStrings = [
-  ".notdef",
-  "space",
-  "exclam",
-  "quotedbl",
-  "numbersign",
-  "dollar",
-  "percent",
-  "ampersand",
-  "quoteright",
-  "parenleft",
-  "parenright",
-  "asterisk",
-  "plus",
-  "comma",
-  "hyphen",
-  "period",
-  "slash",
-  "zero",
-  "one",
-  "two",
-  "three",
-  "four",
-  "five",
-  "six",
-  "seven",
-  "eight",
-  "nine",
-  "colon",
-  "semicolon",
-  "less",
-  "equal",
-  "greater",
-  "question",
-  "at",
-  "A",
-  "B",
-  "C",
-  "D",
-  "E",
-  "F",
-  "G",
-  "H",
-  "I",
-  "J",
-  "K",
-  "L",
-  "M",
-  "N",
-  "O",
-  "P",
-  "Q",
-  "R",
-  "S",
-  "T",
-  "U",
-  "V",
-  "W",
-  "X",
-  "Y",
-  "Z",
-  "bracketleft",
-  "backslash",
-  "bracketright",
-  "asciicircum",
-  "underscore",
-  "quoteleft",
-  "a",
-  "b",
-  "c",
-  "d",
-  "e",
-  "f",
-  "g",
-  "h",
-  "i",
-  "j",
-  "k",
-  "l",
-  "m",
-  "n",
-  "o",
-  "p",
-  "q",
-  "r",
-  "s",
-  "t",
-  "u",
-  "v",
-  "w",
-  "x",
-  "y",
-  "z",
-  "braceleft",
-  "bar",
-  "braceright",
-  "asciitilde",
-  "exclamdown",
-  "cent",
-  "sterling",
-  "fraction",
-  "yen",
-  "florin",
-  "section",
-  "currency",
-  "quotesingle",
-  "quotedblleft",
-  "guillemotleft",
-  "guilsinglleft",
-  "guilsinglright",
-  "fi",
-  "fl",
-  "endash",
-  "dagger",
-  "daggerdbl",
-  "periodcentered",
-  "paragraph",
-  "bullet",
-  "quotesinglbase",
-  "quotedblbase",
-  "quotedblright",
-  "guillemotright",
-  "ellipsis",
-  "perthousand",
-  "questiondown",
-  "grave",
-  "acute",
-  "circumflex",
-  "tilde",
-  "macron",
-  "breve",
-  "dotaccent",
-  "dieresis",
-  "ring",
-  "cedilla",
-  "hungarumlaut",
-  "ogonek",
-  "caron",
-  "emdash",
-  "AE",
-  "ordfeminine",
-  "Lslash",
-  "Oslash",
-  "OE",
-  "ordmasculine",
-  "ae",
-  "dotlessi",
-  "lslash",
-  "oslash",
-  "oe",
-  "germandbls",
-  "onesuperior",
-  "logicalnot",
-  "mu",
-  "trademark",
-  "Eth",
-  "onehalf",
-  "plusminus",
-  "Thorn",
-  "onequarter",
-  "divide",
-  "brokenbar",
-  "degree",
-  "thorn",
-  "threequarters",
-  "twosuperior",
-  "registered",
-  "minus",
-  "eth",
-  "multiply",
-  "threesuperior",
-  "copyright",
-  "Aacute",
-  "Acircumflex",
-  "Adieresis",
-  "Agrave",
-  "Aring",
-  "Atilde",
-  "Ccedilla",
-  "Eacute",
-  "Ecircumflex",
-  "Edieresis",
-  "Egrave",
-  "Iacute",
-  "Icircumflex",
-  "Idieresis",
-  "Igrave",
-  "Ntilde",
-  "Oacute",
-  "Ocircumflex",
-  "Odieresis",
-  "Ograve",
-  "Otilde",
-  "Scaron",
-  "Uacute",
-  "Ucircumflex",
-  "Udieresis",
-  "Ugrave",
-  "Yacute",
-  "Ydieresis",
-  "Zcaron",
-  "aacute",
-  "acircumflex",
-  "adieresis",
-  "agrave",
-  "aring",
-  "atilde",
-  "ccedilla",
-  "eacute",
-  "ecircumflex",
-  "edieresis",
-  "egrave",
-  "iacute",
-  "icircumflex",
-  "idieresis",
-  "igrave",
-  "ntilde",
-  "oacute",
-  "ocircumflex",
-  "odieresis",
-  "ograve",
-  "otilde",
-  "scaron",
-  "uacute",
-  "ucircumflex",
-  "udieresis",
-  "ugrave",
-  "yacute",
-  "ydieresis",
-  "zcaron",
-  "exclamsmall",
-  "Hungarumlautsmall",
-  "dollaroldstyle",
-  "dollarsuperior",
-  "ampersandsmall",
-  "Acutesmall",
-  "parenleftsuperior",
-  "parenrightsuperior",
-  "266 ff",
-  "onedotenleader",
-  "zerooldstyle",
-  "oneoldstyle",
-  "twooldstyle",
-  "threeoldstyle",
-  "fouroldstyle",
-  "fiveoldstyle",
-  "sixoldstyle",
-  "sevenoldstyle",
-  "eightoldstyle",
-  "nineoldstyle",
-  "commasuperior",
-  "threequartersemdash",
-  "periodsuperior",
-  "questionsmall",
-  "asuperior",
-  "bsuperior",
-  "centsuperior",
-  "dsuperior",
-  "esuperior",
-  "isuperior",
-  "lsuperior",
-  "msuperior",
-  "nsuperior",
-  "osuperior",
-  "rsuperior",
-  "ssuperior",
-  "tsuperior",
-  "ff",
-  "ffi",
-  "ffl",
-  "parenleftinferior",
-  "parenrightinferior",
-  "Circumflexsmall",
-  "hyphensuperior",
-  "Gravesmall",
-  "Asmall",
-  "Bsmall",
-  "Csmall",
-  "Dsmall",
-  "Esmall",
-  "Fsmall",
-  "Gsmall",
-  "Hsmall",
-  "Ismall",
-  "Jsmall",
-  "Ksmall",
-  "Lsmall",
-  "Msmall",
-  "Nsmall",
-  "Osmall",
-  "Psmall",
-  "Qsmall",
-  "Rsmall",
-  "Ssmall",
-  "Tsmall",
-  "Usmall",
-  "Vsmall",
-  "Wsmall",
-  "Xsmall",
-  "Ysmall",
-  "Zsmall",
-  "colonmonetary",
-  "onefitted",
-  "rupiah",
-  "Tildesmall",
-  "exclamdownsmall",
-  "centoldstyle",
-  "Lslashsmall",
-  "Scaronsmall",
-  "Zcaronsmall",
-  "Dieresissmall",
-  "Brevesmall",
-  "Caronsmall",
-  "Dotaccentsmall",
-  "Macronsmall",
-  "figuredash",
-  "hypheninferior",
-  "Ogoneksmall",
-  "Ringsmall",
-  "Cedillasmall",
-  "questiondownsmall",
-  "oneeighth",
-  "threeeighths",
-  "fiveeighths",
-  "seveneighths",
-  "onethird",
-  "twothirds",
-  "zerosuperior",
-  "foursuperior",
-  "fivesuperior",
-  "sixsuperior",
-  "sevensuperior",
-  "eightsuperior",
-  "ninesuperior",
-  "zeroinferior",
-  "oneinferior",
-  "twoinferior",
-  "threeinferior",
-  "fourinferior",
-  "fiveinferior",
-  "sixinferior",
-  "seveninferior",
-  "eightinferior",
-  "nineinferior",
-  "centinferior",
-  "dollarinferior",
-  "periodinferior",
-  "commainferior",
-  "Agravesmall",
-  "Aacutesmall",
-  "Acircumflexsmall",
-  "Atildesmall",
-  "Adieresissmall",
-  "Aringsmall",
-  "AEsmall",
-  "Ccedillasmall",
-  "Egravesmall",
-  "Eacutesmall",
-  "Ecircumflexsmall",
-  "Edieresissmall",
-  "Igravesmall",
-  "Iacutesmall",
-  "Icircumflexsmall",
-  "Idieresissmall",
-  "Ethsmall",
-  "Ntildesmall",
-  "Ogravesmall",
-  "Oacutesmall",
-  "Ocircumflexsmall",
-  "Otildesmall",
-  "Odieresissmall",
-  "OEsmall",
-  "Oslashsmall",
-  "Ugravesmall",
-  "Uacutesmall",
-  "Ucircumflexsmall",
-  "Udieresissmall",
-  "Yacutesmall",
-  "Thornsmall",
-  "Ydieresissmall",
-  "001.000",
-  "001.001",
-  "001.002",
-  "001.003",
-  "Black",
-  "Bold",
-  "Book",
-  "Light",
-  "Medium",
-  "Regular",
-  "Roman",
-  "Semibold"
+  '.notdef',
+  'space',
+  'exclam',
+  'quotedbl',
+  'numbersign',
+  'dollar',
+  'percent',
+  'ampersand',
+  'quoteright',
+  'parenleft',
+  'parenright',
+  'asterisk',
+  'plus',
+  'comma',
+  'hyphen',
+  'period',
+  'slash',
+  'zero',
+  'one',
+  'two',
+  'three',
+  'four',
+  'five',
+  'six',
+  'seven',
+  'eight',
+  'nine',
+  'colon',
+  'semicolon',
+  'less',
+  'equal',
+  'greater',
+  'question',
+  'at',
+  'A',
+  'B',
+  'C',
+  'D',
+  'E',
+  'F',
+  'G',
+  'H',
+  'I',
+  'J',
+  'K',
+  'L',
+  'M',
+  'N',
+  'O',
+  'P',
+  'Q',
+  'R',
+  'S',
+  'T',
+  'U',
+  'V',
+  'W',
+  'X',
+  'Y',
+  'Z',
+  'bracketleft',
+  'backslash',
+  'bracketright',
+  'asciicircum',
+  'underscore',
+  'quoteleft',
+  'a',
+  'b',
+  'c',
+  'd',
+  'e',
+  'f',
+  'g',
+  'h',
+  'i',
+  'j',
+  'k',
+  'l',
+  'm',
+  'n',
+  'o',
+  'p',
+  'q',
+  'r',
+  's',
+  't',
+  'u',
+  'v',
+  'w',
+  'x',
+  'y',
+  'z',
+  'braceleft',
+  'bar',
+  'braceright',
+  'asciitilde',
+  'exclamdown',
+  'cent',
+  'sterling',
+  'fraction',
+  'yen',
+  'florin',
+  'section',
+  'currency',
+  'quotesingle',
+  'quotedblleft',
+  'guillemotleft',
+  'guilsinglleft',
+  'guilsinglright',
+  'fi',
+  'fl',
+  'endash',
+  'dagger',
+  'daggerdbl',
+  'periodcentered',
+  'paragraph',
+  'bullet',
+  'quotesinglbase',
+  'quotedblbase',
+  'quotedblright',
+  'guillemotright',
+  'ellipsis',
+  'perthousand',
+  'questiondown',
+  'grave',
+  'acute',
+  'circumflex',
+  'tilde',
+  'macron',
+  'breve',
+  'dotaccent',
+  'dieresis',
+  'ring',
+  'cedilla',
+  'hungarumlaut',
+  'ogonek',
+  'caron',
+  'emdash',
+  'AE',
+  'ordfeminine',
+  'Lslash',
+  'Oslash',
+  'OE',
+  'ordmasculine',
+  'ae',
+  'dotlessi',
+  'lslash',
+  'oslash',
+  'oe',
+  'germandbls',
+  'onesuperior',
+  'logicalnot',
+  'mu',
+  'trademark',
+  'Eth',
+  'onehalf',
+  'plusminus',
+  'Thorn',
+  'onequarter',
+  'divide',
+  'brokenbar',
+  'degree',
+  'thorn',
+  'threequarters',
+  'twosuperior',
+  'registered',
+  'minus',
+  'eth',
+  'multiply',
+  'threesuperior',
+  'copyright',
+  'Aacute',
+  'Acircumflex',
+  'Adieresis',
+  'Agrave',
+  'Aring',
+  'Atilde',
+  'Ccedilla',
+  'Eacute',
+  'Ecircumflex',
+  'Edieresis',
+  'Egrave',
+  'Iacute',
+  'Icircumflex',
+  'Idieresis',
+  'Igrave',
+  'Ntilde',
+  'Oacute',
+  'Ocircumflex',
+  'Odieresis',
+  'Ograve',
+  'Otilde',
+  'Scaron',
+  'Uacute',
+  'Ucircumflex',
+  'Udieresis',
+  'Ugrave',
+  'Yacute',
+  'Ydieresis',
+  'Zcaron',
+  'aacute',
+  'acircumflex',
+  'adieresis',
+  'agrave',
+  'aring',
+  'atilde',
+  'ccedilla',
+  'eacute',
+  'ecircumflex',
+  'edieresis',
+  'egrave',
+  'iacute',
+  'icircumflex',
+  'idieresis',
+  'igrave',
+  'ntilde',
+  'oacute',
+  'ocircumflex',
+  'odieresis',
+  'ograve',
+  'otilde',
+  'scaron',
+  'uacute',
+  'ucircumflex',
+  'udieresis',
+  'ugrave',
+  'yacute',
+  'ydieresis',
+  'zcaron',
+  'exclamsmall',
+  'Hungarumlautsmall',
+  'dollaroldstyle',
+  'dollarsuperior',
+  'ampersandsmall',
+  'Acutesmall',
+  'parenleftsuperior',
+  'parenrightsuperior',
+  '266 ff',
+  'onedotenleader',
+  'zerooldstyle',
+  'oneoldstyle',
+  'twooldstyle',
+  'threeoldstyle',
+  'fouroldstyle',
+  'fiveoldstyle',
+  'sixoldstyle',
+  'sevenoldstyle',
+  'eightoldstyle',
+  'nineoldstyle',
+  'commasuperior',
+  'threequartersemdash',
+  'periodsuperior',
+  'questionsmall',
+  'asuperior',
+  'bsuperior',
+  'centsuperior',
+  'dsuperior',
+  'esuperior',
+  'isuperior',
+  'lsuperior',
+  'msuperior',
+  'nsuperior',
+  'osuperior',
+  'rsuperior',
+  'ssuperior',
+  'tsuperior',
+  'ff',
+  'ffi',
+  'ffl',
+  'parenleftinferior',
+  'parenrightinferior',
+  'Circumflexsmall',
+  'hyphensuperior',
+  'Gravesmall',
+  'Asmall',
+  'Bsmall',
+  'Csmall',
+  'Dsmall',
+  'Esmall',
+  'Fsmall',
+  'Gsmall',
+  'Hsmall',
+  'Ismall',
+  'Jsmall',
+  'Ksmall',
+  'Lsmall',
+  'Msmall',
+  'Nsmall',
+  'Osmall',
+  'Psmall',
+  'Qsmall',
+  'Rsmall',
+  'Ssmall',
+  'Tsmall',
+  'Usmall',
+  'Vsmall',
+  'Wsmall',
+  'Xsmall',
+  'Ysmall',
+  'Zsmall',
+  'colonmonetary',
+  'onefitted',
+  'rupiah',
+  'Tildesmall',
+  'exclamdownsmall',
+  'centoldstyle',
+  'Lslashsmall',
+  'Scaronsmall',
+  'Zcaronsmall',
+  'Dieresissmall',
+  'Brevesmall',
+  'Caronsmall',
+  'Dotaccentsmall',
+  'Macronsmall',
+  'figuredash',
+  'hypheninferior',
+  'Ogoneksmall',
+  'Ringsmall',
+  'Cedillasmall',
+  'questiondownsmall',
+  'oneeighth',
+  'threeeighths',
+  'fiveeighths',
+  'seveneighths',
+  'onethird',
+  'twothirds',
+  'zerosuperior',
+  'foursuperior',
+  'fivesuperior',
+  'sixsuperior',
+  'sevensuperior',
+  'eightsuperior',
+  'ninesuperior',
+  'zeroinferior',
+  'oneinferior',
+  'twoinferior',
+  'threeinferior',
+  'fourinferior',
+  'fiveinferior',
+  'sixinferior',
+  'seveninferior',
+  'eightinferior',
+  'nineinferior',
+  'centinferior',
+  'dollarinferior',
+  'periodinferior',
+  'commainferior',
+  'Agravesmall',
+  'Aacutesmall',
+  'Acircumflexsmall',
+  'Atildesmall',
+  'Adieresissmall',
+  'Aringsmall',
+  'AEsmall',
+  'Ccedillasmall',
+  'Egravesmall',
+  'Eacutesmall',
+  'Ecircumflexsmall',
+  'Edieresissmall',
+  'Igravesmall',
+  'Iacutesmall',
+  'Icircumflexsmall',
+  'Idieresissmall',
+  'Ethsmall',
+  'Ntildesmall',
+  'Ogravesmall',
+  'Oacutesmall',
+  'Ocircumflexsmall',
+  'Otildesmall',
+  'Odieresissmall',
+  'OEsmall',
+  'Oslashsmall',
+  'Ugravesmall',
+  'Uacutesmall',
+  'Ucircumflexsmall',
+  'Udieresissmall',
+  'Yacutesmall',
+  'Thornsmall',
+  'Ydieresissmall',
+  '001.000',
+  '001.001',
+  '001.002',
+  '001.003',
+  'Black',
+  'Bold',
+  'Book',
+  'Light',
+  'Medium',
+  'Regular',
+  'Roman',
+  'Semibold'
 ];
 
 var CFFEncodingMap = {
-  "0": "-reserved-",
-  "1": "hstem",
-  "2": "-reserved-",
-  "3": "vstem",
-  "4": "vmoveto",
-  "5": "rlineto",
-  "6": "hlineto",
-  "7": "vlineto",
-  "8": "rrcurveto",
-  "9": "-reserved-",
-  "10": "callsubr",
-  "11": "return",
-  "12": {
-    "3": "and",
-    "4": "or",
-    "5": "not",
-    "9": "abs",
-    "10": "add",
-    "11": "div",
-    "12": "sub",
-    "14": "neg",
-    "15": "eq",
-    "18": "drop",
-    "20": "put",
-    "21": "get",
-    "22": "ifelse",
-    "23": "random",
-    "24": "mul",
-    "26": "sqrt",
-    "27": "dup",
-    "28": "exch",
-    "29": "index",
-    "30": "roll",
-    "34": "hflex",
-    "35": "flex",
-    "36": "hflex1",
-    "37": "flex1"
+  '0': '-reserved-',
+  '1': 'hstem',
+  '2': '-reserved-',
+  '3': 'vstem',
+  '4': 'vmoveto',
+  '5': 'rlineto',
+  '6': 'hlineto',
+  '7': 'vlineto',
+  '8': 'rrcurveto',
+  '9': '-reserved-',
+  '10': 'callsubr',
+  '11': 'return',
+  '12': {
+    '3': 'and',
+    '4': 'or',
+    '5': 'not',
+    '9': 'abs',
+    '10': 'add',
+    '11': 'div',
+    '12': 'sub',
+    '14': 'neg',
+    '15': 'eq',
+    '18': 'drop',
+    '20': 'put',
+    '21': 'get',
+    '22': 'ifelse',
+    '23': 'random',
+    '24': 'mul',
+    '26': 'sqrt',
+    '27': 'dup',
+    '28': 'exch',
+    '29': 'index',
+    '30': 'roll',
+    '34': 'hflex',
+    '35': 'flex',
+    '36': 'hflex1',
+    '37': 'flex1'
   },
-  "13": "-reserved-",
-  "14": "endchar",
-  "15": "-reserved-",
-  "16": "-reserved-",
-  "17": "-reserved-",
-  "18": "hstemhm",
-  "19": "hintmask",
-  "20": "cntrmask",
-  "21": "rmoveto",
-  "22": "hmoveto",
-  "23": "vstemhm",
-  "24": "rcurveline",
-  "25": "rlivecurve",
-  "26": "vvcurveto",
-  "27": "hhcurveto",
-  "29": "callgsubr",
-  "30": "vhcurveto",
-  "31": "hvcurveto"
+  '13': '-reserved-',
+  '14': 'endchar',
+  '15': '-reserved-',
+  '16': '-reserved-',
+  '17': '-reserved-',
+  '18': 'hstemhm',
+  '19': 'hintmask',
+  '20': 'cntrmask',
+  '21': 'rmoveto',
+  '22': 'hmoveto',
+  '23': 'vstemhm',
+  '24': 'rcurveline',
+  '25': 'rlivecurve',
+  '26': 'vvcurveto',
+  '27': 'hhcurveto',
+  '29': 'callgsubr',
+  '30': 'vhcurveto',
+  '31': 'hvcurveto'
 };
 
 var CFFDictDataMap = {
-  "0": {
-    name: "version",
-    operand: "SID"
+  '0': {
+    name: 'version',
+    operand: 'SID'
   },
-  "1": {
-    name: "Notice",
-    operand: "SID"
+  '1': {
+    name: 'Notice',
+    operand: 'SID'
   },
-  "2": {
-    name: "FullName",
-    operand: "SID"
+  '2': {
+    name: 'FullName',
+    operand: 'SID'
   },
-  "3": {
-    name: "FamilyName",
-    operand: "SID"
+  '3': {
+    name: 'FamilyName',
+    operand: 'SID'
   },
-  "4": {
-    name: "Weight",
-    operand: "SID"
+  '4': {
+    name: 'Weight',
+    operand: 'SID'
   },
-  "5": {
-    name: "FontBBox",
+  '5': {
+    name: 'FontBBox',
     operand: [0, 0, 0, 0]
   },
-  "6": {
-    name: "BlueValues"
+  '6': {
+    name: 'BlueValues'
   },
-  "7": {
-    name: "OtherBlues"
+  '7': {
+    name: 'OtherBlues'
   },
-  "8": {
-    name: "FamilyBlues"
+  '8': {
+    name: 'FamilyBlues'
   },
-  "9": {
-    name: "FamilyOtherBlues"
+  '9': {
+    name: 'FamilyOtherBlues'
   },
-  "10": {
-    name: "StdHW"
+  '10': {
+    name: 'StdHW'
   },
-  "11": {
-    name: "StdVW"
+  '11': {
+    name: 'StdVW'
   },
-  "12": {
-    "0": {
-      name: "Copyright",
-      operand: "SID"
+  '12': {
+    '0': {
+      name: 'Copyright',
+      operand: 'SID'
     },
-    "1": {
-      name: "IsFixedPitch",
+    '1': {
+      name: 'IsFixedPitch',
       operand: false
     },
-    "2": {
-      name: "ItalicAngle",
+    '2': {
+      name: 'ItalicAngle',
       operand: 0
     },
-    "3": {
-      name: "UnderlinePosition",
+    '3': {
+      name: 'UnderlinePosition',
       operand: -100
     },
-    "4": {
-      name: "UnderlineThickness",
+    '4': {
+      name: 'UnderlineThickness',
       operand: 50
     },
-    "5": {
-      name: "PaintType",
+    '5': {
+      name: 'PaintType',
       operand: 0
     },
-    "6": {
-      name: "CharstringType",
+    '6': {
+      name: 'CharstringType',
       operand: 2
     },
-    "7": {
-      name: "FontMatrix",
-      operand: [0.001, 0, 0, 0.001, 0 ,0]
+    '7': {
+      name: 'FontMatrix',
+      operand: [0.001, 0, 0, 0.001, 0 , 0]
     },
-    "8": {
-      name: "StrokeWidth",
+    '8': {
+      name: 'StrokeWidth',
       operand: 0
     },
-    "9": {
-      name: "BlueScale"
+    '9': {
+      name: 'BlueScale'
     },
-    "10": {
-      name: "BlueShift"
+    '10': {
+      name: 'BlueShift'
     },
-    "11": {
-      name: "BlueFuzz"
+    '11': {
+      name: 'BlueFuzz'
     },
-    "12": {
-      name: "StemSnapH"
+    '12': {
+      name: 'StemSnapH'
     },
-    "13": {
-      name: "StemSnapV"
+    '13': {
+      name: 'StemSnapV'
     },
-    "14": {
-      name: "ForceBold"
+    '14': {
+      name: 'ForceBold'
     },
-    "17": {
-      name: "LanguageGroup"
+    '17': {
+      name: 'LanguageGroup'
     },
-    "18": {
-      name: "ExpansionFactor"
+    '18': {
+      name: 'ExpansionFactor'
     },
-    "9": {
-      name: "initialRandomSeed"
+    '9': {
+      name: 'initialRandomSeed'
     },
-    "20": {
-      name: "SyntheticBase",
+    '20': {
+      name: 'SyntheticBase',
       operand: null
     },
-    "21": {
-      name: "PostScript",
-      operand: "SID"
+    '21': {
+      name: 'PostScript',
+      operand: 'SID'
     },
-    "22": {
-      name: "BaseFontName",
-      operand: "SID"
+    '22': {
+      name: 'BaseFontName',
+      operand: 'SID'
     },
-    "23": {
-      name: "BaseFontBlend",
-      operand: "delta"
+    '23': {
+      name: 'BaseFontBlend',
+      operand: 'delta'
     }
   },
-  "13": {
-    name: "UniqueID",
+  '13': {
+    name: 'UniqueID',
     operand: null
   },
-  "14": {
-    name: "XUID",
+  '14': {
+    name: 'XUID',
     operand: []
   },
-  "15": {
-    name: "charset",
+  '15': {
+    name: 'charset',
     operand: 0
   },
-  "16": {
-    name: "Encoding",
+  '16': {
+    name: 'Encoding',
     operand: 0
   },
-  "17": {
-    name: "CharStrings",
+  '17': {
+    name: 'CharStrings',
     operand: null
   },
-  "18": {
-    name: "Private",
-    operand: "number number"
+  '18': {
+    name: 'Private',
+    operand: 'number number'
   },
-  "19": {
-    name: "Subrs"
+  '19': {
+    name: 'Subrs'
   },
-  "20": {
-    name: "defaultWidthX"
+  '20': {
+    name: 'defaultWidthX'
   },
-  "21": {
-    name: "nominalWidthX"
+  '21': {
+    name: 'nominalWidthX'
   }
 };
 
 var CFFDictPrivateDataMap = {
-  "6": {
-    name: "BluesValues",
-    operand: "delta"
+  '6': {
+    name: 'BluesValues',
+    operand: 'delta'
   },
-  "7": {
-    name: "OtherBlues",
-    operand: "delta"
+  '7': {
+    name: 'OtherBlues',
+    operand: 'delta'
   },
-  "8": {
-    name: "FamilyBlues",
-    operand: "delta"
+  '8': {
+    name: 'FamilyBlues',
+    operand: 'delta'
   },
-  "9": {
-    name: "FamilyOtherBlues",
-    operand: "delta"
+  '9': {
+    name: 'FamilyOtherBlues',
+    operand: 'delta'
   },
-  "10": {
-    name: "StdHW",
+  '10': {
+    name: 'StdHW',
     operand: null
   },
-  "11": {
-    name: "StdVW",
+  '11': {
+    name: 'StdVW',
     operand: null
   },
-  "12": {
-    "9": {
-      name: "BlueScale",
+  '12': {
+    '9': {
+      name: 'BlueScale',
       operand: 0.039625
     },
-    "10": {
-      name: "BlueShift",
+    '10': {
+      name: 'BlueShift',
       operand: 7
     },
-    "11": {
-      name: "BlueFuzz",
+    '11': {
+      name: 'BlueFuzz',
       operand: 1
     },
-    "12": {
-      name: "StemSnapH",
-      operand: "delta"
+    '12': {
+      name: 'StemSnapH',
+      operand: 'delta'
     },
-    "13": {
-      name: "StemSnapV",
-      operand: "delta"
+    '13': {
+      name: 'StemSnapV',
+      operand: 'delta'
     },
-    "14": {
-      name: "ForceBold",
-      operand: "boolean"
+    '14': {
+      name: 'ForceBold',
+      operand: 'boolean'
     },
-    "17": {
-      name: "LanguageGroup",
+    '17': {
+      name: 'LanguageGroup',
       operand: 0
     },
-    "18": {
-      name: "ExpansionFactor",
+    '18': {
+      name: 'ExpansionFactor',
       operand: 0.06
     },
-    "19": {
-      name: "initialRandomSeed",
+    '19': {
+      name: 'initialRandomSeed',
       operand: 0
     }
   },
-  "19": {
-    name: "Subrs",
+  '19': {
+    name: 'Subrs',
     operand: null
   },
-  "20": {
-    name: "defaultWidthX",
+  '20': {
+    name: 'defaultWidthX',
     operand: 0
   },
-  "21": {
-    name: "nominalWidthX",
+  '21': {
+    name: 'nominalWidthX',
     operand: 0
   }
 };
index bc0a8544cdb1d74e7b8e632fc4d368018992dfaf..edfc221863187ec17ca91dfbc04f40dee3ddb3b9 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 /**
  * The Type2 reader code below is only used for debugging purpose since Type2
@@ -21,7 +21,7 @@ function readCharset(aStream, aCharstrings) {
 
   var format = aStream.getByte();
   if (format == 0) {
-    charset[".notdef"] = readCharstringEncoding(aCharstrings[0]);
+    charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);
 
     var count = aCharstrings.length - 1;
     for (var i = 1; i < count + 1; i++) {
@@ -30,13 +30,13 @@ function readCharset(aStream, aCharstrings) {
       //log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
     }
   } else if (format == 1) {
-    error("Charset Range are not supported");
+    error('Charset Range are not supported');
   } else {
-    error("Invalid charset format");
+    error('Invalid charset format');
   }
 
   return charset;
-};
+}
 
 /**
  * Take a Type2 binary charstring as input and transform it to a human
@@ -83,7 +83,7 @@ function readCharstringEncoding(aString) {
   }
 
   return charstringTokens;
-};
+}
 
 
 /**
@@ -105,10 +105,10 @@ function readFontDictData(aString, aMap) {
     } else if (value == 29) {
       token = aString[i++] << 24 |
               aString[i++] << 16 |
-              aString[i++] << 8  |
+              aString[i++] << 8 |
               aString[i++];
     } else if (value == 30) {
-      token = "";
+      token = '';
       var parsed = false;
       while (!parsed) {
         var byte = aString[i++];
@@ -118,18 +118,18 @@ function readFontDictData(aString, aMap) {
           var nibble = nibbles[j];
           switch (nibble) {
             case 0xA:
-              token += ".";
+              token += '.';
               break;
             case 0xB:
-              token += "E";
+              token += 'E';
               break;
             case 0xC:
-              token += "E-";
+              token += 'E-';
               break;
             case 0xD:
               break;
             case 0xE:
-              token += "-";
+              token += '-';
               break;
             case 0xF:
               parsed = true;
@@ -139,7 +139,7 @@ function readFontDictData(aString, aMap) {
               break;
           }
         }
-      };
+      }
       token = parseFloat(token);
     } else if (value <= 31) {
       token = aMap[value];
@@ -150,14 +150,14 @@ function readFontDictData(aString, aMap) {
     } else if (value <= 254) {
       token = -((value - 251) * 256) - aString[i++] - 108;
     } else if (value == 255) {
-      error("255 is not a valid DICT command");
+      error('255 is not a valid DICT command');
     }
 
     fontDictDataTokens.push(token);
   }
 
   return fontDictDataTokens;
-};
+}
 
 
 /**
@@ -192,7 +192,7 @@ function readFontIndexData(aStream, aIsByte) {
       return aStream.getByte() << 24 | aStream.getByte() << 16 |
              aStream.getByte() << 8 | aStream.getByte();
     }
-    error(offsize + " is not a valid offset size");
+    error(offsize + ' is not a valid offset size');
     return null;
   };
 
@@ -200,7 +200,8 @@ function readFontIndexData(aStream, aIsByte) {
   for (var i = 0; i < count + 1; i++)
     offsets.push(getNextOffset());
 
-  log("Found " + count + " objects at offsets :" + offsets + " (offsize: " + offsize + ")");
+  log('Found ' + count + ' objects at offsets :' +
+      offsets + ' (offsize: ' + offsize + ')');
 
   // Now extract the objects
   var relativeOffset = aStream.pos;
@@ -217,15 +218,15 @@ function readFontIndexData(aStream, aIsByte) {
   }
 
   return objects;
-};
+}
 
 var Type2Parser = function(aFilePath) {
   var font = new Dict();
 
   var xhr = new XMLHttpRequest();
-  xhr.open("GET", aFilePath, false);
-  xhr.mozResponseType = xhr.responseType = "arraybuffer";
-  xhr.expected = (document.URL.indexOf("file:") == 0) ? 0 : 200;
+  xhr.open('GET', aFilePath, false);
+  xhr.mozResponseType = xhr.responseType = 'arraybuffer';
+  xhr.expected = (document.URL.indexOf('file:') == 0) ? 0 : 200;
   xhr.send(null);
   this.data = new Stream(xhr.mozResponseArrayBuffer || xhr.mozResponse ||
                          xhr.responseArrayBuffer || xhr.response);
@@ -249,19 +250,19 @@ var Type2Parser = function(aFilePath) {
         stack.push(token);
       } else {
         switch (token.operand) {
-          case "SID":
+          case 'SID':
             font.set(token.name, CFFStrings[stack.pop()]);
             break;
-          case "number number":
+          case 'number number':
             font.set(token.name, {
               offset: stack.pop(),
               size: stack.pop()
             });
             break;
-          case "boolean":
+          case 'boolean':
             font.set(token.name, stack.pop());
             break;
-          case "delta":
+          case 'delta':
             font.set(token.name, stack.pop());
             break;
           default:
@@ -280,32 +281,32 @@ var Type2Parser = function(aFilePath) {
   };
 
   this.parse = function(aStream) {
-    font.set("major", aStream.getByte());
-    font.set("minor", aStream.getByte());
-    font.set("hdrSize", aStream.getByte());
-    font.set("offsize", aStream.getByte());
+    font.set('major', aStream.getByte());
+    font.set('minor', aStream.getByte());
+    font.set('hdrSize', aStream.getByte());
+    font.set('offsize', aStream.getByte());
 
     // Move the cursor after the header
-    aStream.skip(font.get("hdrSize") - aStream.pos);
+    aStream.skip(font.get('hdrSize') - aStream.pos);
 
     // Read the NAME Index
-    dump("Reading Index: Names");
-    font.set("Names", readFontIndexData(aStream));
-    log("Names: " + font.get("Names"));
+    dump('Reading Index: Names');
+    font.set('Names', readFontIndexData(aStream));
+    log('Names: ' + font.get('Names'));
 
     // Read the Top Dict Index
-    dump("Reading Index: TopDict");
+    dump('Reading Index: TopDict');
     var topDict = readFontIndexData(aStream, true);
-    log("TopDict: " + topDict);
+    log('TopDict: ' + topDict);
 
     // Read the String Index
-    dump("Reading Index: Strings");
+    dump('Reading Index: Strings');
     var strings = readFontIndexData(aStream);
-    log("strings: " + strings);
+    log('strings: ' + strings);
 
     // Fill up the Strings dictionary with the new unique strings
     for (var i = 0; i < strings.length; i++)
-      CFFStrings.push(strings[i].join(""));
+      CFFStrings.push(strings[i].join(''));
 
     // Parse the TopDict operator
     var objects = [];
@@ -315,39 +316,40 @@ var Type2Parser = function(aFilePath) {
 
     // Read the Global Subr Index that comes just after the Strings Index
     // (cf. "The Compact Font Format Specification" Chapter 16)
-    dump("Reading Global Subr Index");
+    dump('Reading Global Subr Index');
     var subrs = readFontIndexData(aStream, true);
     dump(subrs);
 
     // Reading Private Dict
-    var priv = font.get("Private");
-    log("Reading Private Dict (offset: " + priv.offset + " size: " + priv.size + ")");
+    var priv = font.get('Private');
+    log('Reading Private Dict (offset: ' + priv.offset +
+        ' size: ' + priv.size + ')');
     aStream.pos = priv.offset;
 
     var privateDict = [];
     for (var i = 0; i < priv.size; i++)
       privateDict.push(aStream.getByte());
-    dump("private:" + privateDict);
+    dump('private:' + privateDict);
     parseAsToken(privateDict, CFFDictPrivateDataMap);
 
     for (var p in font.map)
-      dump(p + "::" + font.get(p));
+      dump(p + '::' + font.get(p));
 
     // Read CharStrings Index
-    var charStringsOffset = font.get("CharStrings");
-    dump("Read CharStrings Index (offset: " + charStringsOffset + ")");
+    var charStringsOffset = font.get('CharStrings');
+    dump('Read CharStrings Index (offset: ' + charStringsOffset + ')');
     aStream.pos = charStringsOffset;
     var charStrings = readFontIndexData(aStream, true);
 
     // Read Charset
-    dump("Read Charset for " + charStrings.length + " glyphs");
-    var charsetEntry = font.get("charset");
+    dump('Read Charset for ' + charStrings.length + ' glyphs');
+    var charsetEntry = font.get('charset');
     if (charsetEntry == 0) {
-      error("Need to support CFFISOAdobeCharset");
+      error('Need to support CFFISOAdobeCharset');
     } else if (charsetEntry == 1) {
-      error("Need to support CFFExpert");
+      error('Need to support CFFExpert');
     } else if (charsetEntry == 2) {
-      error("Need to support CFFExpertSubsetCharset");
+      error('Need to support CFFExpertSubsetCharset');
     } else {
       aStream.pos = charsetEntry;
       var charset = readCharset(aStream, charStrings);
@@ -378,23 +380,23 @@ var Type2Parser = function(aFilePath) {
  * writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".cff");
  */
 function writeToFile(aBytes, aFilePath) {
-  if (!("netscape" in window))
+  if (!('netscape' in window))
     return;
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
   var Cc = Components.classes,
       Ci = Components.interfaces;
-  var file  = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
+  var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
   file.initWithPath(aFilePath);
 
-  var stream = Cc["@mozilla.org/network/file-output-stream;1"]
+  var stream = Cc['@mozilla.org/network/file-output-stream;1']
                  .createInstance(Ci.nsIFileOutputStream);
   stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0);
 
-  var bos = Cc["@mozilla.org/binaryoutputstream;1"]
+  var bos = Cc['@mozilla.org/binaryoutputstream;1']
               .createInstance(Ci.nsIBinaryOutputStream);
   bos.setOutputStream(stream);
   bos.writeByteArray(aBytes, aBytes.length);
   stream.close();
-};
+}
 
index 01d7b4f6e9297e05dd194f9ec940106664ec4a05..04e4d176695f3545c35974bc87bddc2babc5cf0e 100644 (file)
@@ -1,47 +1,47 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var pageTimeout;
 
 var PDFViewer = {
   queryParams: {},
-  
+
   element: null,
-  
+
   sidebarContentView: null,
-  
+
   previousPageButton: null,
   nextPageButton: null,
   pageNumberInput: null,
   scaleSelect: null,
   fileInput: null,
-  
+
   willJumpToPage: false,
-  
+
   pdf: null,
-  
+
   url: 'compressed.tracemonkey-pldi-09.pdf',
   pageNumber: 1,
   numberOfPages: 1,
-  
+
   scale: 1.0,
-  
+
   pageWidth: function(page) {
     var pdfToCssUnitsCoef = 96.0 / 72.0;
     var width = (page.mediaBox[2] - page.mediaBox[0]);
     return width * PDFViewer.scale * pdfToCssUnitsCoef;
   },
-  
+
   pageHeight: function(page) {
     var pdfToCssUnitsCoef = 96.0 / 72.0;
     var height = (page.mediaBox[3] - page.mediaBox[1]);
     return height * PDFViewer.scale * pdfToCssUnitsCoef;
   },
-  
+
   lastPagesDrawn: [],
-  
+
   visiblePages: function() {
     const pageBottomMargin = 10;
     var windowTop = window.pageYOffset;
@@ -56,57 +56,57 @@ var PDFViewer = {
         break;
       currentHeight += pageHeight;
     }
-    
-    var pages = [];  
+
+    var pages = [];
     for (; i <= n && currentHeight < windowBottom; i++) {
       var page = PDFViewer.pdf.getPage(i);
       pageHeight = PDFViewer.pageHeight(page) + pageBottomMargin;
       currentHeight += pageHeight;
       pages.push(i);
     }
-    
+
     return pages;
   },
-  
+
   createThumbnail: function(num) {
     if (PDFViewer.sidebarContentView) {
       var anchor = document.createElement('a');
       anchor.href = '#' + num;
-    
+
       var containerDiv = document.createElement('div');
       containerDiv.id = 'thumbnailContainer' + num;
       containerDiv.className = 'thumbnail';
-    
+
       var pageNumberDiv = document.createElement('div');
       pageNumberDiv.className = 'thumbnailPageNumber';
       pageNumberDiv.innerHTML = '' + num;
-    
+
       anchor.appendChild(containerDiv);
       PDFViewer.sidebarContentView.appendChild(anchor);
       PDFViewer.sidebarContentView.appendChild(pageNumberDiv);
     }
   },
-  
+
   removeThumbnail: function(num) {
     var div = document.getElementById('thumbnailContainer' + num);
-    
+
     if (div) {
       while (div.hasChildNodes()) {
         div.removeChild(div.firstChild);
       }
     }
   },
-  
+
   drawThumbnail: function(num) {
     if (!PDFViewer.pdf)
       return;
 
     var div = document.getElementById('thumbnailContainer' + num);
-    
+
     if (div && !div.hasChildNodes()) {
       var page = PDFViewer.pdf.getPage(num);
       var canvas = document.createElement('canvas');
-      
+
       canvas.id = 'thumbnail' + num;
       canvas.mozOpaque = true;
 
@@ -133,43 +133,43 @@ var PDFViewer = {
       FontLoader.bind(fonts, function() { page.display(gfx); });
     }
   },
-  
+
   createPage: function(num) {
     var page = PDFViewer.pdf.getPage(num);
 
     var anchor = document.createElement('a');
     anchor.name = '' + num;
-    
+
     var div = document.createElement('div');
     div.id = 'pageContainer' + num;
     div.className = 'page';
     div.style.width = PDFViewer.pageWidth(page) + 'px';
     div.style.height = PDFViewer.pageHeight(page) + 'px';
-    
+
     PDFViewer.element.appendChild(anchor);
     PDFViewer.element.appendChild(div);
   },
-  
+
   removePage: function(num) {
     var div = document.getElementById('pageContainer' + num);
-    
+
     if (div) {
       while (div.hasChildNodes()) {
         div.removeChild(div.firstChild);
       }
     }
   },
-  
+
   drawPage: function(num) {
     if (!PDFViewer.pdf)
       return;
 
     var div = document.getElementById('pageContainer' + num);
-    
+
     if (div && !div.hasChildNodes()) {
       var page = PDFViewer.pdf.getPage(num);
       var canvas = document.createElement('canvas');
-      
+
       canvas.id = 'page' + num;
       canvas.mozOpaque = true;
 
@@ -198,20 +198,20 @@ var PDFViewer = {
     while (PDFViewer.element.hasChildNodes()) {
       PDFViewer.element.removeChild(PDFViewer.element.firstChild);
     }
-    
+
     PDFViewer.scale = num / 100;
-    
+
     var i;
-    
+
     if (PDFViewer.pdf) {
       for (i = 1; i <= PDFViewer.numberOfPages; i++) {
         PDFViewer.createPage(i);
       }
     }
-    
+
     for (i = 0; i < PDFViewer.scaleSelect.childNodes; i++) {
       var option = PDFViewer.scaleSelect.childNodes[i];
-      
+
       if (option.value == num) {
         if (!option.selected) {
           option.selected = 'selected';
@@ -222,16 +222,16 @@ var PDFViewer = {
         }
       }
     }
-    
+
     PDFViewer.scaleSelect.value = Math.floor(PDFViewer.scale * 100) + '%';
-    
+
     // Clear the array of the last pages drawn to force a redraw.
     PDFViewer.lastPagesDrawn = [];
-    
+
     // Jump the scroll position to the correct page.
     PDFViewer.goToPage(PDFViewer.pageNumber);
   },
-  
+
   goToPage: function(num) {
     if (1 <= num && num <= PDFViewer.numberOfPages) {
       PDFViewer.pageNumber = num;
@@ -242,24 +242,26 @@ var PDFViewer = {
         // Force a "scroll event" to redraw
         setTimeout(window.onscroll, 0);
       document.location.hash = PDFViewer.pageNumber;
-      
-      PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';
-      PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
+
+      PDFViewer.previousPageButton.className =
+        (PDFViewer.pageNumber === 1) ? 'disabled' : '';
+      PDFViewer.nextPageButton.className =
+        (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
     }
   },
-  
+
   goToPreviousPage: function() {
     if (PDFViewer.pageNumber > 1) {
       PDFViewer.goToPage(--PDFViewer.pageNumber);
     }
   },
-  
+
   goToNextPage: function() {
     if (PDFViewer.pageNumber < PDFViewer.numberOfPages) {
       PDFViewer.goToPage(++PDFViewer.pageNumber);
     }
   },
-  
+
   openURL: function(url) {
     PDFViewer.url = url;
     document.title = url;
@@ -269,20 +271,21 @@ var PDFViewer = {
       clearInterval(this.thumbsLoadingInterval);
       this.thumbsLoadingInterval = null;
     }
-    
+
     var req = new XMLHttpRequest();
     req.open('GET', url);
     req.mozResponseType = req.responseType = 'arraybuffer';
     req.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
-    
+
     req.onreadystatechange = function() {
       if (req.readyState === 4 && req.status === req.expected) {
-        var data = req.mozResponseArrayBuffer || req.mozResponse || req.responseArrayBuffer || req.response;
-        
+        var data = (req.mozResponseArrayBuffer || req.mozResponse ||
+                    req.responseArrayBuffer || req.response);
+
         PDFViewer.readPDF(data);
       }
     };
-    
+
     req.send(null);
   },
 
@@ -292,23 +295,26 @@ var PDFViewer = {
     while (PDFViewer.element.hasChildNodes()) {
       PDFViewer.element.removeChild(PDFViewer.element.firstChild);
     }
-    
+
     while (PDFViewer.sidebarContentView.hasChildNodes()) {
-      PDFViewer.sidebarContentView.removeChild(PDFViewer.sidebarContentView.firstChild);
+      PDFViewer.sidebarContentView.removeChild(
+        PDFViewer.sidebarContentView.firstChild
+      );
     }
-    
+
     PDFViewer.pdf = new PDFDoc(new Stream(data));
     PDFViewer.numberOfPages = PDFViewer.pdf.numPages;
-    document.getElementById('numPages').innerHTML = PDFViewer.numberOfPages.toString();
-    
+    document.getElementById('numPages').innerHTML =
+      PDFViewer.numberOfPages.toString();
+
     for (var i = 1; i <= PDFViewer.numberOfPages; i++) {
       PDFViewer.createPage(i);
     }
-    
+
     if (PDFViewer.numberOfPages > 0) {
       PDFViewer.drawPage(1);
       document.location.hash = 1;
-      
+
       // slowly loading the thumbs (few per second)
       // first time we are loading more images than subsequent
       var currentPageIndex = 1, imagesToLoad = 15;
@@ -326,9 +332,11 @@ var PDFViewer = {
         imagesToLoad = 3; // next time loading less images
       }).bind(this), 500);
     }
-    
-    PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';
-    PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
+
+    PDFViewer.previousPageButton.className =
+      (PDFViewer.pageNumber === 1) ? 'disabled' : '';
+    PDFViewer.nextPageButton.className =
+      (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
   }
 };
 
@@ -338,35 +346,35 @@ window.onload = function() {
     var qs = window.location.search.substring(1);
     var kvs = qs.split('&');
     var params = {};
-    
+
     for (var i = 0; i < kvs.length; ++i) {
       var kv = kvs[i].split('=');
       params[unescape(kv[0])] = unescape(kv[1]);
     }
-    
+
     return params;
   }();
 
   PDFViewer.element = document.getElementById('viewer');
-  
+
   PDFViewer.sidebarContentView = document.getElementById('sidebarContentView');
-  
+
   PDFViewer.pageNumberInput = document.getElementById('pageNumber');
   PDFViewer.pageNumberInput.onkeydown = function(evt) {
     var charCode = evt.charCode || evt.keyCode;
-    
+
     // Up arrow key.
     if (charCode === 38) {
       PDFViewer.goToNextPage();
       this.select();
     }
-    
+
     // Down arrow key.
     else if (charCode === 40) {
       PDFViewer.goToPreviousPage();
       this.select();
     }
-    
+
     // All other non-numeric keys (excluding Left arrow, Right arrow,
     // Backspace, and Delete keys).
     else if ((charCode < 48 || charCode > 57) &&
@@ -377,12 +385,12 @@ window.onload = function() {
     ) {
       return false;
     }
-    
+
     return true;
   };
   PDFViewer.pageNumberInput.onkeyup = function(evt) {
     var charCode = evt.charCode || evt.keyCode;
-    
+
     // All numeric keys, Backspace, and Delete.
     if ((charCode >= 48 && charCode <= 57) ||
       charCode === 8 ||   // Backspace
@@ -390,10 +398,10 @@ window.onload = function() {
     ) {
       PDFViewer.goToPage(this.value);
     }
-    
+
     this.focus();
   };
-  
+
   PDFViewer.previousPageButton = document.getElementById('previousPageButton');
   PDFViewer.previousPageButton.onclick = function(evt) {
     if (this.className.indexOf('disabled') === -1) {
@@ -406,12 +414,14 @@ window.onload = function() {
     }
   };
   PDFViewer.previousPageButton.onmouseup = function(evt) {
-    this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+    this.className =
+      (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
   };
   PDFViewer.previousPageButton.onmouseout = function(evt) {
-    this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+    this.className =
+      (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
   };
-  
+
   PDFViewer.nextPageButton = document.getElementById('nextPageButton');
   PDFViewer.nextPageButton.onclick = function(evt) {
     if (this.className.indexOf('disabled') === -1) {
@@ -424,17 +434,19 @@ window.onload = function() {
     }
   };
   PDFViewer.nextPageButton.onmouseup = function(evt) {
-    this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+    this.className =
+      (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
   };
   PDFViewer.nextPageButton.onmouseout = function(evt) {
-    this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+    this.className =
+      (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
   };
-  
+
   PDFViewer.scaleSelect = document.getElementById('scaleSelect');
   PDFViewer.scaleSelect.onchange = function(evt) {
     PDFViewer.changeScale(parseInt(this.value));
   };
-  
+
   if (window.File && window.FileReader && window.FileList && window.Blob) {
     var openFileButton = document.getElementById('openFileButton');
     openFileButton.onclick = function(evt) {
@@ -448,35 +460,37 @@ window.onload = function() {
       }
     };
     openFileButton.onmouseup = function(evt) {
-      this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+      this.className =
+        (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
     };
     openFileButton.onmouseout = function(evt) {
-      this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+      this.className =
+        (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
     };
-    
+
     PDFViewer.fileInput = document.getElementById('fileInput');
     PDFViewer.fileInput.onchange = function(evt) {
       var files = evt.target.files;
-      
+
       if (files.length > 0) {
         var file = files[0];
         var fileReader = new FileReader();
-        
+
         document.title = file.name;
-        
+
         // Read the local file into a Uint8Array.
         fileReader.onload = function(evt) {
           var data = evt.target.result;
           var buffer = new ArrayBuffer(data.length);
           var uint8Array = new Uint8Array(buffer);
-          
+
           for (var i = 0; i < data.length; i++) {
             uint8Array[i] = data.charCodeAt(i);
           }
-          
+
           PDFViewer.readPDF(uint8Array);
         };
-        
+
         // Read as a binary string since "readAsArrayBuffer" is not yet
         // implemented in Firefox.
         fileReader.readAsBinaryString(file);
@@ -486,22 +500,23 @@ window.onload = function() {
   } else {
     document.getElementById('fileWrapper').style.display = 'none';
   }
-  
-  PDFViewer.pageNumber = parseInt(PDFViewer.queryParams.page) || PDFViewer.pageNumber;
+
+  PDFViewer.pageNumber =
+    parseInt(PDFViewer.queryParams.page) || PDFViewer.pageNumber;
   PDFViewer.scale = parseInt(PDFViewer.scaleSelect.value) / 100 || 1.0;
-  
+
   PDFViewer.openURL(PDFViewer.queryParams.file || PDFViewer.url);
-  
-  window.onscroll = function(evt) {        
+
+  window.onscroll = function(evt) {
     var lastPagesDrawn = PDFViewer.lastPagesDrawn;
     var visiblePages = PDFViewer.visiblePages();
-    
+
     var pagesToDraw = [];
     var pagesToKeep = [];
     var pagesToRemove = [];
-    
+
     var i;
-    
+
     // Determine which visible pages were not previously drawn.
     for (i = 0; i < visiblePages.length; i++) {
       if (lastPagesDrawn.indexOf(visiblePages[i]) === -1) {
@@ -511,7 +526,7 @@ window.onload = function() {
         pagesToKeep.push(visiblePages[i]);
       }
     }
-    
+
     // Determine which previously drawn pages are no longer visible.
     for (i = 0; i < lastPagesDrawn.length; i++) {
       if (visiblePages.indexOf(lastPagesDrawn[i]) === -1) {
@@ -519,14 +534,16 @@ window.onload = function() {
         PDFViewer.removePage(lastPagesDrawn[i]);
       }
     }
-    
+
     PDFViewer.lastPagesDrawn = pagesToDraw.concat(pagesToKeep);
-    
+
     // Update the page number input with the current page number.
     if (!PDFViewer.willJumpToPage && visiblePages.length > 0) {
       PDFViewer.pageNumber = PDFViewer.pageNumberInput.value = visiblePages[0];
-      PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';
-      PDFViewer.nextPageButton.className = (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
+      PDFViewer.previousPageButton.className =
+        (PDFViewer.pageNumber === 1) ? 'disabled' : '';
+      PDFViewer.nextPageButton.className =
+        (PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
     } else {
       PDFViewer.willJumpToPage = false;
     }
index 6702a67359bb598dcddfa594173b363d6398d8f3..770ddb039bcc3d466441bf04063d9033b450ab08 100644 (file)
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
-/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var pdfDocument, canvas, pageScale, pageDisplay, pageNum, numPages;
 function load(userInput) {
-    canvas = document.getElementById("canvas");
-    canvas.mozOpaque = true;
-    pageNum = ("page" in queryParams()) ? parseInt(queryParams().page) : 1;
-    pageScale = ("scale" in queryParams()) ? parseInt(queryParams().scale) : 1.5;
-    var fileName = userInput;
-    if (!userInput) {
-      fileName = queryParams().file || "compressed.tracemonkey-pldi-09.pdf";
-    }
-    open(fileName);
+  canvas = document.getElementById('canvas');
+  canvas.mozOpaque = true;
+  pageNum = ('page' in queryParams()) ? parseInt(queryParams().page) : 1;
+  pageScale = ('scale' in queryParams()) ? parseInt(queryParams().scale) : 1.5;
+  var fileName = userInput;
+  if (!userInput) {
+    fileName = queryParams().file || 'compressed.tracemonkey-pldi-09.pdf';
+  }
+  open(fileName);
 }
 
 function queryParams() {
-    var qs = window.location.search.substring(1);
-    var kvs = qs.split("&");
-    var params = { };
-    for (var i = 0; i < kvs.length; ++i) {
-        var kv = kvs[i].split("=");
-        params[unescape(kv[0])] = unescape(kv[1]);
-    }
-    return params;
+  var qs = window.location.search.substring(1);
+  var kvs = qs.split('&');
+  var params = { };
+  for (var i = 0; i < kvs.length; ++i) {
+    var kv = kvs[i].split('=');
+    params[unescape(kv[0])] = unescape(kv[1]);
+  }
+  return params;
 }
 
 function open(url) {
-    document.title = url;
-    var req = new XMLHttpRequest();
-    req.open("GET", url);
-    req.mozResponseType = req.responseType = "arraybuffer";
-    req.expected = (document.URL.indexOf("file:") == 0) ? 0 : 200;
-    req.onreadystatechange = function() {
-      if (req.readyState == 4 && req.status == req.expected) {
-        var data = req.mozResponseArrayBuffer || req.mozResponse ||
-                   req.responseArrayBuffer || req.response;
-        pdfDocument = new PDFDoc(new Stream(data));
-        numPages = pdfDocument.numPages;
-        document.getElementById("numPages").innerHTML = numPages.toString();
-        goToPage(pageNum);
-      }
-    };
-    req.send(null);
+  document.title = url;
+  var req = new XMLHttpRequest();
+  req.open('GET', url);
+  req.mozResponseType = req.responseType = 'arraybuffer';
+  req.expected = (document.URL.indexOf('file:') == 0) ? 0 : 200;
+  req.onreadystatechange = function() {
+    if (req.readyState == 4 && req.status == req.expected) {
+      var data = (req.mozResponseArrayBuffer || req.mozResponse ||
+                  req.responseArrayBuffer || req.response);
+      pdfDocument = new PDFDoc(new Stream(data));
+      numPages = pdfDocument.numPages;
+      document.getElementById('numPages').innerHTML = numPages.toString();
+      goToPage(pageNum);
+    }
+  };
+  req.send(null);
 }
 
 function gotoPage(num) {
-    if (0 <= num && num <= numPages)
-        pageNum = num;
-    displayPage(pageNum);
+  if (0 <= num && num <= numPages)
+    pageNum = num;
+  displayPage(pageNum);
 }
 
 function displayPage(num) {
-    document.getElementById("pageNumber").value = num;
+  document.getElementById('pageNumber').value = num;
 
-    var t0 = Date.now();
+  var t0 = Date.now();
 
-    var page = pdfDocument.getPage(pageNum = num);
+  var page = pdfDocument.getPage(pageNum = num);
 
-    var pdfToCssUnitsCoef = 96.0 / 72.0;
-    var pageWidth = (page.mediaBox[2] - page.mediaBox[0]);
-    var pageHeight = (page.mediaBox[3] - page.mediaBox[1]);
-    canvas.width = pageScale * pageWidth * pdfToCssUnitsCoef;
-    canvas.height = pageScale * pageHeight * pdfToCssUnitsCoef;
+  var pdfToCssUnitsCoef = 96.0 / 72.0;
+  var pageWidth = (page.mediaBox[2] - page.mediaBox[0]);
+  var pageHeight = (page.mediaBox[3] - page.mediaBox[1]);
+  canvas.width = pageScale * pageWidth * pdfToCssUnitsCoef;
+  canvas.height = pageScale * pageHeight * pdfToCssUnitsCoef;
 
-    var t1 = Date.now();
-    var ctx = canvas.getContext("2d");
-    ctx.save();
-    ctx.fillStyle = "rgb(255, 255, 255)";
-    ctx.fillRect(0, 0, canvas.width, canvas.height);
-    ctx.restore();
+  var t1 = Date.now();
+  var ctx = canvas.getContext('2d');
+  ctx.save();
+  ctx.fillStyle = 'rgb(255, 255, 255)';
+  ctx.fillRect(0, 0, canvas.width, canvas.height);
+  ctx.restore();
 
-    var gfx = new CanvasGraphics(ctx);
+  var gfx = new CanvasGraphics(ctx);
 
-    // page.compile will collect all fonts for us, once we have loaded them
-    // we can trigger the actual page rendering with page.display
-    var fonts = [];
-    page.compile(gfx, fonts);
-    var t2 = Date.now();
+  // page.compile will collect all fonts for us, once we have loaded them
+  // we can trigger the actual page rendering with page.display
+  var fonts = [];
+  page.compile(gfx, fonts);
+  var t2 = Date.now();
 
-    function displayPage() {
-        var t3 = Date.now();
+  function displayPage() {
+    var t3 = Date.now();
 
-        page.display(gfx);
+    page.display(gfx);
 
-        var t4 = Date.now();
+    var t4 = Date.now();
 
-        var infoDisplay = document.getElementById("info");
-        infoDisplay.innerHTML = "Time to load/compile/fonts/render: "+ (t1 - t0) + "/" + (t2 - t1) + "/" + (t3 - t2) + "/" + (t4 - t3) + " ms";
-    }
+    var infoDisplay = document.getElementById('info');
+    infoDisplay.innerHTML = 'Time to load/compile/fonts/render: ' +
+      (t1 - t0) + '/' + (t2 - t1) + '/' + (t3 - t2) + '/' + (t4 - t3) + ' ms';
+  }
 
-    // Always defer call to displayPage() to work around bug in
-    // Firefox error reporting from XHR callbacks.
-    FontLoader.bind(fonts, function () { setTimeout(displayPage, 0); });
+  // Always defer call to displayPage() to work around bug in
+  // Firefox error reporting from XHR callbacks.
+  FontLoader.bind(fonts, function() { setTimeout(displayPage, 0); });
 }
 
 function nextPage() {
-    if (pageNum < pdfDocument.numPages)
-      displayPage(++pageNum);
+  if (pageNum < pdfDocument.numPages)
+    displayPage(++pageNum);
 }
 
 function prevPage() {
-    if (pageNum > 1)
-      displayPage(--pageNum);
+  if (pageNum > 1)
+    displayPage(--pageNum);
 }
 
 function goToPage(num) {
   if (0 <= num && num <= numPages)
     displayPage(pageNum = num);
 }
-
index bc96d8453d8c9ecbb2ff902c830b46817bc2987d..c2a9f476388627b5e8f5046d404e6014d0de4775 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var JpegStreamProxyCounter = 0;
 // WebWorker Proxy for JpegStream.
@@ -12,7 +12,7 @@ var JpegStreamProxy = (function() {
 
     // Tell the main thread to create an image.
     postMessage({
-      action: "jpeg_stream",
+      action: 'jpeg_stream',
       data: {
         id: this.id,
         raw: bytesToString(bytes)
@@ -25,7 +25,7 @@ var JpegStreamProxy = (function() {
       return this;
     },
     getChar: function() {
-      error("internal error: getChar is not valid on JpegStream");
+      error('internal error: getChar is not valid on JpegStream');
     }
   };
 
@@ -36,9 +36,9 @@ var JpegStreamProxy = (function() {
 // the time, meaning you can't create a gradient, create a second one and then
 // use the first one again. As this isn't used in pdf.js right now, it's okay.
 function GradientProxy(cmdQueue, x0, y0, x1, y1) {
-  cmdQueue.push(["$createLinearGradient", [x0, y0, x1, y1]]);
+  cmdQueue.push(['$createLinearGradient', [x0, y0, x1, y1]]);
   this.addColorStop = function(i, rgba) {
-    cmdQueue.push(["$addColorStop", [i, rgba]]);
+    cmdQueue.push(['$addColorStop', [i, rgba]]);
   }
 }
 
@@ -47,15 +47,15 @@ var patternProxyCounter = 0;
 function PatternProxy(cmdQueue, object, kind) {
   this.id = patternProxyCounter++;
 
-  if (!(object instanceof CanvasProxy) ) {
-    throw "unkown type to createPattern";
+  if (!(object instanceof CanvasProxy)) {
+    throw 'unkown type to createPattern';
   }
 
   // Flush the object here to ensure it's available on the main thread.
   // TODO: Make some kind of dependency management, such that the object
   // gets flushed only if needed.
   object.flush();
-  cmdQueue.push(["$createPatternFromCanvas", [this.id, object.id, kind]]);
+  cmdQueue.push(['$createPatternFromCanvas', [this.id, object.id, kind]]);
 }
 
 var canvasProxyCounter = 0;
@@ -68,8 +68,8 @@ function CanvasProxy(width, height) {
   // Dummy context that gets exposed.
   var ctx = {};
   this.getContext = function(type) {
-    if (type != "2d") {
-      throw "CanvasProxy can only provide a 2d context.";
+    if (type != '2d') {
+      throw 'CanvasProxy can only provide a 2d context.';
     }
     return ctx;
   }
@@ -82,45 +82,45 @@ function CanvasProxy(width, height) {
 
   // Setup function calls to `ctx`.
   var ctxFunc = [
-  "createRadialGradient",
-  "arcTo",
-  "arc",
-  "fillText",
-  "strokeText",
-  "createImageData",
-  "drawWindow",
-  "save",
-  "restore",
-  "scale",
-  "rotate",
-  "translate",
-  "transform",
-  "setTransform",
-  "clearRect",
-  "fillRect",
-  "strokeRect",
-  "beginPath",
-  "closePath",
-  "moveTo",
-  "lineTo",
-  "quadraticCurveTo",
-  "bezierCurveTo",
-  "rect",
-  "fill",
-  "stroke",
-  "clip",
-  "measureText",
-  "isPointInPath",
+  'createRadialGradient',
+  'arcTo',
+  'arc',
+  'fillText',
+  'strokeText',
+  'createImageData',
+  'drawWindow',
+  'save',
+  'restore',
+  'scale',
+  'rotate',
+  'translate',
+  'transform',
+  'setTransform',
+  'clearRect',
+  'fillRect',
+  'strokeRect',
+  'beginPath',
+  'closePath',
+  'moveTo',
+  'lineTo',
+  'quadraticCurveTo',
+  'bezierCurveTo',
+  'rect',
+  'fill',
+  'stroke',
+  'clip',
+  'measureText',
+  'isPointInPath',
 
   // These functions are necessary to track the rendering currentX state.
   // The exact values can be computed on the main thread only, as the
   // worker has no idea about text width.
-  "$setCurrentX",
-  "$addCurrentX",
-  "$saveCurrentX",
-  "$restoreCurrentX",
-  "$showText",
-  "$setFont"
+  '$setCurrentX',
+  '$addCurrentX',
+  '$saveCurrentX',
+  '$restoreCurrentX',
+  '$showText',
+  '$setFont'
   ];
 
   function buildFuncCall(name) {
@@ -154,53 +154,54 @@ function CanvasProxy(width, height) {
   }
 
   ctx.putImageData = function(data, x, y, width, height) {
-    cmdQueue.push(["$putImageData", [data, x, y, width, height]]);
+    cmdQueue.push(['$putImageData', [data, x, y, width, height]]);
   }
 
-  ctx.drawImage = function(image, x, y, width, height, sx, sy, swidth, sheight) {
+  ctx.drawImage = function(image, x, y, width, height,
+                           sx, sy, swidth, sheight) {
     if (image instanceof CanvasProxy) {
       // Send the image/CanvasProxy to the main thread.
       image.flush();
-      cmdQueue.push(["$drawCanvas", [image.id, x, y, sx, sy, swidth, sheight]]);
-    } else if(image instanceof JpegStreamProxy) {
-      cmdQueue.push(["$drawImage", [image.id, x, y, sx, sy, swidth, sheight]])
+      cmdQueue.push(['$drawCanvas', [image.id, x, y, sx, sy, swidth, sheight]]);
+    } else if (image instanceof JpegStreamProxy) {
+      cmdQueue.push(['$drawImage', [image.id, x, y, sx, sy, swidth, sheight]]);
     } else {
-      throw "unkown type to drawImage";
+      throw 'unkown type to drawImage';
     }
   }
 
   // Setup property access to `ctx`.
   var ctxProp = {
     // "canvas"
-    "globalAlpha": "1",
-    "globalCompositeOperation": "source-over",
-    "strokeStyle": "#000000",
-    "fillStyle": "#000000",
-    "lineWidth": "1",
-    "lineCap": "butt",
-    "lineJoin": "miter",
-    "miterLimit": "10",
-    "shadowOffsetX": "0",
-    "shadowOffsetY": "0",
-    "shadowBlur": "0",
-    "shadowColor": "rgba(0, 0, 0, 0)",
-    "font": "10px sans-serif",
-    "textAlign": "start",
-    "textBaseline": "alphabetic",
-    "mozTextStyle": "10px sans-serif",
-    "mozImageSmoothingEnabled": "true"
-  }
+    'globalAlpha': '1',
+    'globalCompositeOperation': 'source-over',
+    'strokeStyle': '#000000',
+    'fillStyle': '#000000',
+    'lineWidth': '1',
+    'lineCap': 'butt',
+    'lineJoin': 'miter',
+    'miterLimit': '10',
+    'shadowOffsetX': '0',
+    'shadowOffsetY': '0',
+    'shadowBlur': '0',
+    'shadowColor': 'rgba(0, 0, 0, 0)',
+    'font': '10px sans-serif',
+    'textAlign': 'start',
+    'textBaseline': 'alphabetic',
+    'mozTextStyle': '10px sans-serif',
+    'mozImageSmoothingEnabled': 'true'
+  };
 
   function buildGetter(name) {
     return function() {
-      return ctx["$" + name];
+      return ctx['$' + name];
     }
   }
 
   function buildSetter(name) {
     return function(value) {
-      cmdQueue.push(["$", name, value]);
-      return ctx["$" + name] = value;
+      cmdQueue.push(['$', name, value]);
+      return ctx['$' + name] = value;
     }
   }
 
@@ -209,23 +210,23 @@ function CanvasProxy(width, height) {
   function buildSetterStyle(name) {
     return function(value) {
       if (value instanceof GradientProxy) {
-        cmdQueue.push(["$" + name + "Gradient"]);
+        cmdQueue.push(['$' + name + 'Gradient']);
       } else if (value instanceof PatternProxy) {
-        cmdQueue.push(["$" + name + "Pattern", [value.id]]);
+        cmdQueue.push(['$' + name + 'Pattern', [value.id]]);
       } else {
-        cmdQueue.push(["$", name, value]);
-        return ctx["$" + name] = value;
+        cmdQueue.push(['$', name, value]);
+        return ctx['$' + name] = value;
       }
     }
   }
 
   for (var name in ctxProp) {
-    ctx["$" + name] = ctxProp[name];
+    ctx['$' + name] = ctxProp[name];
     ctx.__defineGetter__(name, buildGetter(name));
 
     // Special treatment for `fillStyle` and `strokeStyle`: The passed style
     // might be a gradient. Need to check for that.
-    if (name == "fillStyle" || name == "strokeStyle") {
+    if (name == 'fillStyle' || name == 'strokeStyle') {
       ctx.__defineSetter__(name, buildSetterStyle(name));
     } else {
       ctx.__defineSetter__(name, buildSetter(name));
@@ -239,13 +240,13 @@ function CanvasProxy(width, height) {
 */
 CanvasProxy.prototype.flush = function() {
   postMessage({
-    action: "canvas_proxy_cmd_queue",
+    action: 'canvas_proxy_cmd_queue',
     data: {
-      id:         this.id,
-      cmdQueue:   this.cmdQueue,
-      width:      this.width,
-      height:     this.height
+      id: this.id,
+      cmdQueue: this.cmdQueue,
+      width: this.width,
+      height: this.height
     }
   });
   this.cmdQueue.length = 0;
-}
+};
index fd98b857e25837187dbf52c73fd1343d18095994..7e8140590ba6098762e8cdd82927395c31f4f9a0 100644 (file)
@@ -1,39 +1,39 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
-if (typeof console.time == "undefined") {
+if (typeof console.time == 'undefined') {
   var consoleTimer = {};
   console.time = function(name) {
     consoleTimer[name] = Date.now();
   };
-  
+
   console.timeEnd = function(name) {
     var time = consoleTimer[name];
     if (time == null) {
-      throw "Unkown timer name " + name;
+      throw 'Unkown timer name ' + name;
     }
-    this.log("Timer:", name, Date.now() - time);
+    this.log('Timer:', name, Date.now() - time);
   };
 }
 
 function FontWorker() {
-  this.worker = new Worker("worker/font.js");
+  this.worker = new Worker('worker/font.js');
   this.fontsWaiting = 0;
   this.fontsWaitingCallbacks = [];
 
   // Listen to the WebWorker for data and call actionHandler on it.
   this.worker.onmessage = function(event) {
     var data = event.data;
-    var actionHandler = this.actionHandler
+    var actionHandler = this.actionHandler;
     if (data.action in actionHandler) {
       actionHandler[data.action].call(this, data.data);
     } else {
-      throw "Unkown action from worker: " + data.action;
+      throw 'Unkown action from worker: ' + data.action;
     }
   }.bind(this);
-  
+
   this.$handleFontLoadedCallback = this.handleFontLoadedCallback.bind(this);
 }
 
@@ -50,22 +50,23 @@ FontWorker.prototype = {
       this.fontsWaitingCallbacks.length = 0;
     }
   },
-  
+
   actionHandler: {
-    "log": function(data) {
+    'log': function(data) {
       console.log.apply(console, data);
     },
-    
-    "fonts": function(data) {
+
+    'fonts': function(data) {
       // console.log("got processed fonts from worker", Object.keys(data));
       for (name in data) {
         // Update the encoding property.
         var font = Fonts.lookup(name);
         font.properties = {
           encoding: data[name].encoding
-        }
+        };
 
-        // Call `Font.prototype.bindDOM` to make the font get loaded on the page.
+        // Call `Font.prototype.bindDOM` to make the font get loaded
+        // on the page.
         Font.prototype.bindDOM.call(
           font,
           data[name].str,
@@ -84,7 +85,7 @@ FontWorker.prototype = {
       if (Fonts[font.name]) {
         continue;
       }
-    
+
       // Register the font but don't pass in any real data. The idea is to
       // store as less data as possible to reduce memory usage.
       Fonts.registerFont(font.name, Object.create(null), Object.create(null));
@@ -94,16 +95,16 @@ FontWorker.prototype = {
       // Increate the number of fonts to wait for.
       this.fontsWaiting++;
     }
-    
-    console.time("ensureFonts");
+
+    console.time('ensureFonts');
     // If there are fonts, that need to get loaded, tell the FontWorker to get
     // started and push the callback on the waiting-callback-stack.
     if (notLoaded.length != 0) {
-      console.log("fonts -> FontWorker");
+      console.log('fonts -> FontWorker');
       // Send the worker the fonts to work on.
       this.worker.postMessage({
-        action: "fonts",
-        data:   notLoaded
+        action: 'fonts',
+        data: notLoaded
       });
       if (callback) {
         this.fontsWaitingCallbacks.push(callback);
@@ -115,13 +116,13 @@ FontWorker.prototype = {
         callback();
       }
     }
-  },
-}
+  }
+};
 
 function WorkerPDFDoc(canvas) {
-  var timer = null
+  var timer = null;
 
-  this.ctx = canvas.getContext("2d");
+  this.ctx = canvas.getContext('2d');
   this.canvas = canvas;
   this.worker = new Worker('worker/pdf.js');
   this.fontWorker = new FontWorker();
@@ -142,30 +143,30 @@ function WorkerPDFDoc(canvas) {
   var currentXStack = [];
 
   var ctxSpecial = {
-    "$setCurrentX": function(value) {
+    '$setCurrentX': function(value) {
       currentX = value;
     },
 
-    "$addCurrentX": function(value) {
+    '$addCurrentX': function(value) {
       currentX += value;
     },
 
-    "$saveCurrentX": function() {
+    '$saveCurrentX': function() {
       currentXStack.push(currentX);
     },
 
-    "$restoreCurrentX": function() {
+    '$restoreCurrentX': function() {
       currentX = currentXStack.pop();
     },
 
-    "$showText": function(y, text) {
+    '$showText': function(y, text) {
       text = Fonts.charsToUnicode(text);
       this.translate(currentX, -1 * y);
       this.fillText(text, 0, 0);
       currentX += this.measureText(text).width;
     },
 
-    "$putImageData": function(imageData, x, y) {
+    '$putImageData': function(imageData, x, y) {
       var imgData = this.getImageData(0, 0, imageData.width, imageData.height);
 
       // Store the .data property to avaid property lookups.
@@ -175,24 +176,24 @@ function WorkerPDFDoc(canvas) {
       // Copy over the imageData.
       var len = imageRealData.length;
       while (len--)
-      imgRealData[len] = imageRealData[len]
+      imgRealData[len] = imageRealData[len];
 
       this.putImageData(imgData, x, y);
     },
 
-    "$drawImage": function(id, x, y, sx, sy, swidth, sheight) {
+    '$drawImage': function(id, x, y, sx, sy, swidth, sheight) {
       var image = imagesList[id];
       if (!image) {
-        throw "Image not found: " + id;
+        throw 'Image not found: ' + id;
       }
       this.drawImage(image, x, y, image.width, image.height,
         sx, sy, swidth, sheight);
     },
 
-    "$drawCanvas": function(id, x, y, sx, sy, swidth, sheight) {
+    '$drawCanvas': function(id, x, y, sx, sy, swidth, sheight) {
       var canvas = canvasList[id];
       if (!canvas) {
-        throw "Canvas not found";
+        throw 'Canvas not found';
       }
       if (sheight != null) {
         this.drawImage(canvas, x, y, canvas.width, canvas.height,
@@ -202,58 +203,58 @@ function WorkerPDFDoc(canvas) {
       }
     },
 
-    "$createLinearGradient": function(x0, y0, x1, y1) {
+    '$createLinearGradient': function(x0, y0, x1, y1) {
       gradient = this.createLinearGradient(x0, y0, x1, y1);
     },
 
-    "$createPatternFromCanvas": function(patternId, canvasId, kind) {
+    '$createPatternFromCanvas': function(patternId, canvasId, kind) {
       var canvas = canvasList[canvasId];
       if (!canvas) {
-        throw "Canvas not found";
+        throw 'Canvas not found';
       }
       patternList[patternId] = this.createPattern(canvas, kind);
     },
 
-    "$addColorStop": function(i, rgba) {
+    '$addColorStop': function(i, rgba) {
       gradient.addColorStop(i, rgba);
     },
 
-    "$fillStyleGradient": function() {
+    '$fillStyleGradient': function() {
       this.fillStyle = gradient;
     },
 
-    "$fillStylePattern": function(id) {
+    '$fillStylePattern': function(id) {
       var pattern = patternList[id];
       if (!pattern) {
-        throw "Pattern not found";
+        throw 'Pattern not found';
       }
       this.fillStyle = pattern;
     },
 
-    "$strokeStyleGradient": function() {
+    '$strokeStyleGradient': function() {
       this.strokeStyle = gradient;
     },
 
-    "$strokeStylePattern": function(id) {
+    '$strokeStylePattern': function(id) {
       var pattern = patternList[id];
       if (!pattern) {
-        throw "Pattern not found";
+        throw 'Pattern not found';
       }
       this.strokeStyle = pattern;
     },
 
-    "$setFont": function(name, size) {
+    '$setFont': function(name, size) {
       this.font = size + 'px "' + name + '"';
       Fonts.setActive(name, size);
     }
-  }
+  };
 
   function renderProxyCanvas(canvas, cmdQueue) {
-    var ctx = canvas.getContext("2d");
+    var ctx = canvas.getContext('2d');
     var cmdQueueLength = cmdQueue.length;
     for (var i = 0; i < cmdQueueLength; i++) {
       var opp = cmdQueue[i];
-      if (opp[0] == "$") {
+      if (opp[0] == '$') {
         ctx[opp[1]] = opp[2];
       } else if (opp[0] in ctxSpecial) {
         ctxSpecial[opp[0]].apply(ctx, opp[1]);
@@ -267,44 +268,45 @@ function WorkerPDFDoc(canvas) {
   * Functions to handle data sent by the WebWorker.
   */
   var actionHandler = {
-    "log": function(data) {
+    'log': function(data) {
       console.log.apply(console, data);
     },
-    
-    "pdf_num_pages": function(data) {
+
+    'pdf_num_pages': function(data) {
       this.numPages = parseInt(data);
       if (this.loadCallback) {
         this.loadCallback();
       }
     },
-    
-    "font": function(data) {
+
+    'font': function(data) {
       var base64 = window.btoa(data.raw);
 
       // Add the @font-face rule to the document
-      var url = "url(data:" + data.mimetype + ";base64," + base64 + ");";
-      var rule = "@font-face { font-family:'" + data.fontName + "';src:" + url + "}";
+      var url = 'url(data:' + data.mimetype + ';base64,' + base64 + ');';
+      var rule = ("@font-face { font-family:'" + data.fontName +
+                  "';src:" + url + '}');
       var styleSheet = document.styleSheets[0];
       styleSheet.insertRule(rule, styleSheet.length);
 
       // Just adding the font-face to the DOM doesn't make it load. It
       // seems it's loaded once Gecko notices it's used. Therefore,
       // add a div on the page using the loaded font.
-      var div = document.createElement("div");
-      var style = 'font-family:"' + data.fontName + 
+      var div = document.createElement('div');
+      var style = 'font-family:"' + data.fontName +
         '";position: absolute;top:-99999;left:-99999;z-index:-99999';
-      div.setAttribute("style", style);
+      div.setAttribute('style', style);
       document.body.appendChild(div);
     },
-    
-    "setup_page": function(data) {
-      var size = data.split(",");
+
+    'setup_page': function(data) {
+      var size = data.split(',');
       var canvas = this.canvas, ctx = this.ctx;
       canvas.width = parseInt(size[0]);
       canvas.height = parseInt(size[1]);
     },
 
-    "fonts": function(data) {
+    'fonts': function(data) {
       this.waitingForFonts = true;
       this.fontWorker.ensureFonts(data, function() {
         this.waitingForFonts = false;
@@ -316,20 +318,20 @@ function WorkerPDFDoc(canvas) {
       }.bind(this));
     },
 
-    "jpeg_stream": function(data) {
+    'jpeg_stream': function(data) {
       var img = new Image();
-      img.src = "data:image/jpeg;base64," + window.btoa(data.raw);
+      img.src = 'data:image/jpeg;base64,' + window.btoa(data.raw);
       imagesList[data.id] = img;
     },
-    
-    "canvas_proxy_cmd_queue": function(data) {
+
+    'canvas_proxy_cmd_queue': function(data) {
         var id = data.id;
         var cmdQueue = data.cmdQueue;
 
         // Check if there is already a canvas with the given id. If not,
         // create a new canvas.
         if (!canvasList[id]) {
-          var newCanvas = document.createElement("canvas");
+          var newCanvas = document.createElement('canvas');
           newCanvas.width = data.width;
           newCanvas.height = data.height;
           canvasList[id] = newCanvas;
@@ -337,23 +339,23 @@ function WorkerPDFDoc(canvas) {
 
         var renderData = function() {
           if (id == 0) {
-            console.time("main canvas rendering");
+            console.time('main canvas rendering');
             var ctx = this.ctx;
             ctx.save();
-            ctx.fillStyle = "rgb(255, 255, 255)";
+            ctx.fillStyle = 'rgb(255, 255, 255)';
             ctx.fillRect(0, 0, canvas.width, canvas.height);
             ctx.restore();
           }
           renderProxyCanvas(canvasList[id], cmdQueue);
           if (id == 0) {
-            console.timeEnd("main canvas rendering");
-            console.timeEnd(">>> total page display time:");
+            console.timeEnd('main canvas rendering');
+            console.timeEnd('>>> total page display time:');
           }
         }.bind(this);
 
         if (this.waitingForFonts) {
           if (id == 0) {
-            console.log("want to render, but not all fonts are there", id);
+            console.log('want to render, but not all fonts are there', id);
             this.waitingForFontsCallback.push(renderData);
           } else {
             // console.log("assume canvas doesn't have fonts", id);
@@ -363,7 +365,7 @@ function WorkerPDFDoc(canvas) {
           renderData();
         }
     }
-  }
+  };
 
   // Listen to the WebWorker for data and call actionHandler on it.
   this.worker.onmessage = function(event) {
@@ -371,16 +373,16 @@ function WorkerPDFDoc(canvas) {
     if (data.action in actionHandler) {
       actionHandler[data.action].call(this, data.data);
     } else {
-      throw "Unkown action from worker: " + data.action;
+      throw 'Unkown action from worker: ' + data.action;
     }
-  }.bind(this)
+  }.bind(this);
 }
 
 WorkerPDFDoc.prototype.open = function(url, callback) {
   var req = new XMLHttpRequest();
-  req.open("GET", url);
-  req.mozResponseType = req.responseType = "arraybuffer";
-  req.expected = (document.URL.indexOf("file:") == 0) ? 0 : 200;
+  req.open('GET', url);
+  req.mozResponseType = req.responseType = 'arraybuffer';
+  req.expected = (document.URL.indexOf('file:') == 0) ? 0 : 200;
   req.onreadystatechange = function() {
     if (req.readyState == 4 && req.status == req.expected) {
       var data = req.mozResponseArrayBuffer || req.mozResponse ||
@@ -392,24 +394,24 @@ WorkerPDFDoc.prototype.open = function(url, callback) {
     }
   }.bind(this);
   req.send(null);
-}
+};
 
 WorkerPDFDoc.prototype.showPage = function(numPage) {
   this.numPage = parseInt(numPage);
-  console.log("=== start rendering page " + numPage + " ===");
-  console.time(">>> total page display time:");
+  console.log('=== start rendering page ' + numPage + ' ===');
+  console.time('>>> total page display time:');
   this.worker.postMessage(numPage);
   if (this.onChangePage) {
     this.onChangePage(numPage);
   }
-}
+};
 
 WorkerPDFDoc.prototype.nextPage = function() {
   if (this.numPage == this.numPages) return;
   this.showPage(++this.numPage);
-}
+};
 
 WorkerPDFDoc.prototype.prevPage = function() {
   if (this.numPage == 1) return;
   this.showPage(--this.numPage);
-}
+};
index e544db7a2e91f7e41d1ba70089a2d45eb51bd748..29f511407d9d10fffa17adbafd7adeb6406c7fd0 100644 (file)
@@ -1,27 +1,27 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var consoleTimer = {};
 var console = {
   log: function log() {
     var args = Array.prototype.slice.call(arguments);
     postMessage({
-      action: "log",
+      action: 'log',
       data: args
     });
   },
-  
+
   time: function(name) {
     consoleTimer[name] = Date.now();
   },
-  
+
   timeEnd: function(name) {
     var time = consoleTimer[name];
     if (time == null) {
-      throw "Unkown timer name " + name;
+      throw 'Unkown timer name ' + name;
     }
-    this.log("Timer:", name, Date.now() - time);
+    this.log('Timer:', name, Date.now() - time);
   }
-}
+};
index a8ec5ebd4efa117d8f775105b8c5a9eb41f4eccf..32e22198cd888183c0b2e00e0f52e37614f4e0c8 100644 (file)
@@ -1,13 +1,13 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
-importScripts("console.js");
+importScripts('console.js');
 
-importScripts("../pdf.js");
-importScripts("../fonts.js");
-importScripts("../glyphlist.js")
+importScripts('../pdf.js');
+importScripts('../fonts.js');
+importScripts('../glyphlist.js');
 
 function fontDataToString(font) {
   // Doing postMessage on objects make them lose their "shape". This adds the
@@ -16,43 +16,44 @@ function fontDataToString(font) {
   var fontFileDict = new Dict();
   fontFileDict.map = font.file.dict.map;
 
-  var fontFile = new Stream(font.file.bytes, font.file.start, font.file.end - font.file.start, fontFileDict);
+  var fontFile = new Stream(font.file.bytes, font.file.start,
+                            font.file.end - font.file.start, fontFileDict);
   font.file = new FlateStream(fontFile);
-  
+
   // This will encode the font.
   var fontObj = new Font(font.name, font.file, font.properties);
 
   // Create string that is used for css later.
-  var str = "";
+  var str = '';
   var data = fontObj.data;
   var length = data.length;
   for (var j = 0; j < length; j++)
     str += String.fromCharCode(data[j]);
-  
+
   return {
-    str:      str,
+    str: str,
     encoding: font.properties.encoding
-  }
+  };
 }
 
 /**
 * Functions to handle data sent by the MainThread.
 */
 var actionHandler = {
-  "fonts": function(data) {
+  'fonts': function(data) {
     var fontData;
     var result = {};
     for (var i = 0; i < data.length; i++) {
       fontData = data[i];
       result[fontData.name] = fontDataToString(fontData);
     }
-    
+
     postMessage({
-      action: "fonts",
-      data:   result
-    })
-  },
-}
+      action: 'fonts',
+      data: result
+    });
+  }
+};
 
 // Listen to the MainThread for data and call actionHandler on it.
 this.onmessage = function(event) {
@@ -60,6 +61,6 @@ this.onmessage = function(event) {
   if (data.action in actionHandler) {
     actionHandler[data.action].call(this, data.data);
   } else {
-    throw "Unkown action from worker: " + data.action;
+    throw 'Unkown action from worker: ' + data.action;
   }
-}
\ No newline at end of file
+};
index a1f18f69437e5b043a389c62b3f7140b3b150dd9..0d5008d80fc393a6e692d89004666e602b58b18f 100644 (file)
@@ -1,38 +1,38 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-"use strict";
+'use strict';
 
 var consoleTimer = {};
 var console = {
   log: function log() {
     var args = Array.prototype.slice.call(arguments);
     postMessage({
-      action: "log",
+      action: 'log',
       data: args
     });
   },
-  
+
   time: function(name) {
     consoleTimer[name] = Date.now();
   },
-  
+
   timeEnd: function(name) {
     var time = consoleTimer[name];
     if (time == null) {
-      throw "Unkown timer name " + name;
+      throw 'Unkown timer name ' + name;
     }
-    this.log("Timer:", name, Date.now() - time);
+    this.log('Timer:', name, Date.now() - time);
   }
-}
+};
 
 //
-importScripts("console.js")
-importScripts("canvas.js");
-importScripts("../pdf.js");
-importScripts("../fonts.js");
-importScripts("../crypto.js");
-importScripts("../glyphlist.js")
+importScripts('console.js');
+importScripts('canvas.js');
+importScripts('../pdf.js');
+importScripts('../fonts.js');
+importScripts('../crypto.js');
+importScripts('../glyphlist.js');
 
 // Use the JpegStreamProxy proxy.
 JpegStream = JpegStreamProxy;
@@ -48,14 +48,14 @@ onmessage = function(event) {
   if (!pdfDocument) {
     pdfDocument = new PDFDoc(new Stream(data));
     postMessage({
-      action: "pdf_num_pages",
+      action: 'pdf_num_pages',
       data: pdfDocument.numPages
     });
     return;
   }
   // User requested to render a certain page.
   else {
-    console.time("compile");
+    console.time('compile');
 
     // Let's try to render the first page...
     var page = pdfDocument.getPage(parseInt(data));
@@ -64,8 +64,8 @@ onmessage = function(event) {
     var pageWidth = (page.mediaBox[2] - page.mediaBox[0]) * pdfToCssUnitsCoef;
     var pageHeight = (page.mediaBox[3] - page.mediaBox[1]) * pdfToCssUnitsCoef;
     postMessage({
-      action: "setup_page",
-      data: pageWidth + "," + pageHeight
+      action: 'setup_page',
+      data: pageWidth + ',' + pageHeight
     });
 
     // Set canvas size.
@@ -75,21 +75,21 @@ onmessage = function(event) {
     // page.compile will collect all fonts for us, once we have loaded them
     // we can trigger the actual page rendering with page.display
     var fonts = [];
-    var gfx = new CanvasGraphics(canvas.getContext("2d"), CanvasProxy);
+    var gfx = new CanvasGraphics(canvas.getContext('2d'), CanvasProxy);
     page.compile(gfx, fonts);
-    console.timeEnd("compile");
+    console.timeEnd('compile');
 
     // Send fonts to the main thread.
-    console.time("fonts");
+    console.time('fonts');
     postMessage({
-      action: "fonts",
-      data:   fonts
+      action: 'fonts',
+      data: fonts
     });
-    console.timeEnd("fonts");
-    
-    console.time("display");
+    console.timeEnd('fonts');
+
+    console.time('display');
     page.display(gfx);
     canvas.flush();
-    console.timeEnd("display");
+    console.timeEnd('display');
   }
-}
+};