Merge branch 'master' into colorspace
This commit is contained in:
		
						commit
						03a1a0369b
					
				
							
								
								
									
										12
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README
									
									
									
									
									
								
							| @ -1,12 +0,0 @@ | ||||
| pdf.js is a technology demonstrator prototype to explore whether the HTML5 | ||||
| platform is complete enough to faithfully and efficiently render the ISO | ||||
| 32000-1:2008 Portable Document Format (PDF) without native code assistance. | ||||
| 
 | ||||
| You can read more about pdf.js here: | ||||
| 
 | ||||
| http://andreasgal.com/2011/06/15/pdf-js/ | ||||
| http://blog.mozilla.com/cjones/2011/06/15/overview-of-pdf-js-guts/ | ||||
| 
 | ||||
| Or follow us on twitter: @pdfjs | ||||
| 
 | ||||
| http://twitter.com/#!/pdfjs | ||||
							
								
								
									
										27
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| # pdf.js | ||||
| 
 | ||||
| pdf.js is a technology demonstrator prototype to explore whether the HTML5 | ||||
| platform is complete enough to faithfully and efficiently render the ISO | ||||
| 32000-1:2008 Portable Document Format (PDF) without native code assistance. | ||||
| 
 | ||||
| pdf.js is not currently part of the Mozilla project, and there is no plan | ||||
| yet to integrate it into Firefox. We will explore that possibility once | ||||
| pdf.js is production ready. Until then we aim to publish a Firefox | ||||
| PDF reader extension powered by pdf.js. | ||||
| 
 | ||||
| You can read more about pdf.js here: | ||||
| 
 | ||||
|   http://andreasgal.com/2011/06/15/pdf-js/ | ||||
|   http://blog.mozilla.com/cjones/2011/06/15/overview-of-pdf-js-guts/ | ||||
| 
 | ||||
| follow us on twitter: @pdfjs | ||||
| 
 | ||||
|   http://twitter.com/#!/pdfjs | ||||
| 
 | ||||
| join our mailing list: | ||||
| 
 | ||||
|   dev-pdf-js@lists.mozilla.org | ||||
| 
 | ||||
| and talk to us on IRC: | ||||
| 
 | ||||
|   #pdfjs on irc.mozilla.org | ||||
							
								
								
									
										10
									
								
								crypto.js
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								crypto.js
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| /* -*- Mode: Java; tab-width: s; indent-tabs-mode: nil; c-basic-offset: 2 -*- / | ||||
| /* vim: set shiftwidth=s tabstop=2 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"; | ||||
| 
 | ||||
| @ -45,12 +45,12 @@ var ARCFourCipher = (function() { | ||||
| })(); | ||||
| 
 | ||||
| var md5 = (function() { | ||||
|   const r = new Uint8Array([ | ||||
|   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, | ||||
|     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]); | ||||
|   const k = new Int32Array([ | ||||
|   var k = new Int32Array([ | ||||
|     -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, | ||||
|     -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, | ||||
|     1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, | ||||
| @ -149,7 +149,7 @@ var CipherTransform = (function() { | ||||
| 
 | ||||
| var CipherTransformFactory = (function() { | ||||
|   function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength) { | ||||
|     const defaultPasswordBytes = new Uint8Array([ | ||||
|     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]); | ||||
|     var hashData = new Uint8Array(88), i = 0, j, n; | ||||
|  | ||||
							
								
								
									
										198
									
								
								fonts.js
									
									
									
									
									
								
							
							
						
						
									
										198
									
								
								fonts.js
									
									
									
									
									
								
							| @ -26,12 +26,15 @@ var fontName  = ""; | ||||
|  */ | ||||
| var kDisableFonts = false; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Hold a map of decoded fonts and of the standard fourteen Type1 fonts and | ||||
|  * their acronyms. | ||||
|  * TODO Add the standard fourteen Type1 fonts list by default | ||||
|  *      http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65
 | ||||
|  */ | ||||
| 
 | ||||
| var kScalePrecision = 40; | ||||
| var Fonts = { | ||||
|   _active: null, | ||||
| 
 | ||||
| @ -39,8 +42,9 @@ var Fonts = { | ||||
|     return this._active; | ||||
|   }, | ||||
| 
 | ||||
|   set active(name) { | ||||
|   setActive: function fonts_setActive(name, size) { | ||||
|     this._active = this[name]; | ||||
|     this.ctx.font = (size * kScalePrecision) + 'px "' + name + '"'; | ||||
|   }, | ||||
| 
 | ||||
|   charsToUnicode: function fonts_chars2Unicode(chars) { | ||||
| @ -64,8 +68,8 @@ var Fonts = { | ||||
|       var unicode = encoding[charcode]; | ||||
| 
 | ||||
|       // Check if the glyph has already been converted
 | ||||
|       if (unicode instanceof Name) | ||||
|         unicode = encoding[unicode] = GlyphsUnicode[unicode.name]; | ||||
|       if (!IsNum(unicode)) | ||||
|           unicode = encoding[unicode] = GlyphsUnicode[unicode.name]; | ||||
| 
 | ||||
|       // Handle surrogate pairs
 | ||||
|       if (unicode > 0xFFFF) { | ||||
| @ -77,6 +81,16 @@ var Fonts = { | ||||
| 
 | ||||
|     // Enter the translated string into the cache
 | ||||
|     return active.cache[chars] = str; | ||||
|   }, | ||||
| 
 | ||||
|   get ctx() { | ||||
|     var ctx = document.createElement("canvas").getContext("2d"); | ||||
|     ctx.scale(1 / kScalePrecision, 1); | ||||
|     return shadow(this, "ctx", ctx); | ||||
|   }, | ||||
| 
 | ||||
|   measureText: function fonts_measureText(text) { | ||||
|     return this.ctx.measureText(text).width / kScalePrecision; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| @ -165,6 +179,7 @@ var Font = (function () { | ||||
|         warn("Font " + properties.type + " is not supported"); | ||||
|         break; | ||||
|     } | ||||
|     this.data = data; | ||||
| 
 | ||||
|     Fonts[name] = { | ||||
|       data: data, | ||||
| @ -720,7 +735,7 @@ var Font = (function () { | ||||
|                  "\x00\x00" + // -reserved-
 | ||||
|                  "\x00\x00" + // -reserved-
 | ||||
|                  "\x00\x00" + // metricDataFormat
 | ||||
|                  string16(charstrings.length) | ||||
|                  string16(charstrings.length + 1) // Number of HMetrics
 | ||||
|       ); | ||||
|       createTableEntry(otf, offsets, "hhea", hhea); | ||||
| 
 | ||||
| @ -730,18 +745,18 @@ var Font = (function () { | ||||
|       * while Windows use this data. So be careful if you hack on Linux and | ||||
|       * have to touch the 'hmtx' table | ||||
|       */ | ||||
|       hmtx = "\x01\xF4\x00\x00"; // Fake .notdef
 | ||||
|       hmtx = "\x00\x00\x00\x00"; // Fake .notdef
 | ||||
|       var width = 0, lsb = 0; | ||||
|       for (var i = 0; i < charstrings.length; i++) { | ||||
|         width = charstrings[i].charstring[1]; | ||||
|         hmtx += string16(width) + string16(lsb); | ||||
|         var charstring = charstrings[i]; | ||||
|         hmtx += string16(charstring.width) + string16(0); | ||||
|       } | ||||
|       hmtx = stringToArray(hmtx); | ||||
|       createTableEntry(otf, offsets, "hmtx", hmtx); | ||||
| 
 | ||||
|       /** MAXP */ | ||||
|       maxp = "\x00\x00\x50\x00" + // Version number
 | ||||
|              string16(charstrings.length + 1); // Num of glyphs (+1 to pass the sanitizer...)
 | ||||
|              string16(charstrings.length + 1); // Num of glyphs
 | ||||
|       maxp = stringToArray(maxp); | ||||
|       createTableEntry(otf, offsets, "maxp", maxp); | ||||
| 
 | ||||
| @ -778,9 +793,18 @@ var Font = (function () { | ||||
|       }); | ||||
|     }, | ||||
| 
 | ||||
|     bindDOM: function font_bindDom(data) { | ||||
|     bindDOM: function font_bindDom(data, callback) { | ||||
|       var fontName = this.name; | ||||
| 
 | ||||
|       // 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:"' + name +  | ||||
|         '";position: absolute;top:-99999;left:-99999;z-index:-99999'; | ||||
|       div.setAttribute("style", style); | ||||
|       document.body.appendChild(div); | ||||
| 
 | ||||
|       /** Hack begin */ | ||||
|       // Actually there is not event when a font has finished downloading so
 | ||||
|       // the following code are a dirty hack to 'guess' when a font is ready
 | ||||
| @ -800,15 +824,19 @@ var Font = (function () { | ||||
| 
 | ||||
|         // For some reasons the font has not loaded, so mark it loaded for the
 | ||||
|         // page to proceed but cry
 | ||||
|         if ((Date.now() - this.start) >= kMaxWaitForFontFace) { | ||||
|           window.clearInterval(interval); | ||||
|           Fonts[fontName].loading = false; | ||||
|           warn("Is " + fontName + " loaded?"); | ||||
|           this.start = 0; | ||||
|         } else if (textWidth != ctx.measureText(testString).width) { | ||||
|           window.clearInterval(interval); | ||||
|           Fonts[fontName].loading = false; | ||||
|           this.start = 0; | ||||
|         if (textWidth == ctx.measureText(testString).width) { | ||||
|           if ((Date.now() - this.start) < kMaxWaitForFontFace) { | ||||
|             return; | ||||
|           } else { | ||||
|             warn("Is " + fontName + " loaded?"); | ||||
|           } | ||||
|         } | ||||
|          | ||||
|         window.clearInterval(interval); | ||||
|         Fonts[fontName].loading = false; | ||||
|         this.start = 0; | ||||
|         if (callback) { | ||||
|           callback(); | ||||
|         } | ||||
|       }, 30, this); | ||||
| 
 | ||||
| @ -839,7 +867,7 @@ var FontsUtils = { | ||||
|       bytes.set([value]); | ||||
|       return bytes[0]; | ||||
|     } else if (bytesCount == 2) { | ||||
|       bytes.set([value >> 8, value]); | ||||
|       bytes.set([value >> 8, value & 0xff]); | ||||
|       return [bytes[0], bytes[1]]; | ||||
|     } else if (bytesCount == 4) { | ||||
|       bytes.set([value >> 24, value >> 16, value >> 8, value]); | ||||
| @ -980,16 +1008,8 @@ var Type1Parser = function() { | ||||
|       "12": "div", | ||||
| 
 | ||||
|       // callothersubr is a mechanism to make calls on the postscript
 | ||||
|       // interpreter.
 | ||||
|       // TODO When decodeCharstring encounter such a command it should
 | ||||
|       //      directly do:
 | ||||
|       //        - pop the previous charstring[] command into 'index'
 | ||||
|       //        - pop the previous charstring[] command and ignore it, it is
 | ||||
|       //          normally the number of element to push on the stack before
 | ||||
|       //          the command but since everything will be pushed on the stack
 | ||||
|       //          by the PS interpreter when it will read them that is safe to
 | ||||
|       //          ignore this command
 | ||||
|       //        - push the content of the OtherSubrs[index] inside charstring[]
 | ||||
|       // interpreter, this is not supported by Type2 charstring but hopefully
 | ||||
|       // most of the default commands can be ignored safely.
 | ||||
|       "16": "callothersubr", | ||||
| 
 | ||||
|       "17": "pop", | ||||
| @ -1009,8 +1029,13 @@ var Type1Parser = function() { | ||||
|     "31": "hvcurveto" | ||||
|   }; | ||||
| 
 | ||||
|   var kEscapeCommand = 12; | ||||
| 
 | ||||
|   function decodeCharString(array) { | ||||
|     var charString = []; | ||||
|     var charstring = []; | ||||
|     var lsb = 0; | ||||
|     var width = 0; | ||||
|     var used = false; | ||||
| 
 | ||||
|     var value = ""; | ||||
|     var count = array.length; | ||||
| @ -1019,10 +1044,48 @@ var Type1Parser = function() { | ||||
| 
 | ||||
|       if (value < 32) { | ||||
|         var command = null; | ||||
|         if (value == 12) { | ||||
|         if (value == kEscapeCommand) { | ||||
|           var escape = array[++i]; | ||||
| 
 | ||||
|           // TODO Clean this code
 | ||||
|           if (escape == 16) { | ||||
|             var index = charstring.pop(); | ||||
|             var argc = charstring.pop(); | ||||
|             var data = charstring.pop(); | ||||
| 
 | ||||
|             // If the flex mechanishm is not used in a font program, Adobe
 | ||||
|             // state that that entries 0, 1 and 2 can simply be replace by
 | ||||
|             // {}, which means that we can simply ignore them.
 | ||||
|             if (index < 3) { | ||||
|               continue; | ||||
|             } | ||||
| 
 | ||||
|             // This is the same things about hint replacement, if it is not used
 | ||||
|             // entry 3 can be replaced by {3}
 | ||||
|             if (index == 3) { | ||||
|               charstring.push(3); | ||||
|               i++; | ||||
|               continue; | ||||
|             } | ||||
|           } | ||||
| 
 | ||||
|           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") { | ||||
|               width = charstring[1] / charstring[2]; | ||||
|             } else { | ||||
|               error("Unsupported hsbw format: " + charstring); | ||||
|             } | ||||
| 
 | ||||
|             lsb = charstring[0]; | ||||
|             charstring.push(lsb, "hmoveto"); | ||||
|             charstring.splice(0, 1); | ||||
|             continue; | ||||
|           } | ||||
|           command = charStringDictionary[value]; | ||||
|         } | ||||
| 
 | ||||
| @ -1044,16 +1107,14 @@ var Type1Parser = function() { | ||||
|       } else if (value <= 254) { | ||||
|         value = -((value - 251) * 256) - parseInt(array[++i]) - 108; | ||||
|       } else { | ||||
|         var byte = array[++i]; | ||||
|         var high = (byte >> 1); | ||||
|         value = (byte - high) << 24 | array[++i] << 16 | | ||||
|                 array[++i] << 8 | array[++i]; | ||||
|         value = (array[++i] & 0xff) << 24 | (array[++i] & 0xff) << 16 | | ||||
|                 (array[++i] & 0xff) << 8 | (array[++i] & 0xff) << 0; | ||||
|       } | ||||
| 
 | ||||
|       charString.push(value); | ||||
|       charstring.push(value); | ||||
|     } | ||||
| 
 | ||||
|     return charString; | ||||
|     return { charstring: charstring, width: width, lsb: lsb }; | ||||
|   }; | ||||
| 
 | ||||
|   /** | ||||
| @ -1080,19 +1141,21 @@ var Type1Parser = function() { | ||||
|         length = parseInt(length); | ||||
|         var data = eexecString.slice(i + 3, i + 3 + length); | ||||
|         var encodedSubr = decrypt(data, kCharStringsEncryptionKey, 4); | ||||
|         var subr = decodeCharString(encodedSubr); | ||||
|         var str = decodeCharString(encodedSubr); | ||||
| 
 | ||||
|         subrs.push(subr); | ||||
|         subrs.push(str.charstring); | ||||
|         i += 3 + length; | ||||
|       } else if (inGlyphs && c == 0x52) { | ||||
|         length = parseInt(length); | ||||
|         var data = eexecString.slice(i + 3, i + 3 + length); | ||||
|         var encodedCharstring = decrypt(data, kCharStringsEncryptionKey, 4); | ||||
|         var subr = decodeCharString(encodedCharstring); | ||||
|         var str = decodeCharString(encodedCharstring); | ||||
| 
 | ||||
|         glyphs.push({ | ||||
|             glyph: glyph, | ||||
|             data: subr | ||||
|             data: str.charstring, | ||||
|             lsb: str.lsb, | ||||
|             width: str.width | ||||
|         }); | ||||
|         i += 3 + length; | ||||
|       } else if (inGlyphs && c == 0x2F) { | ||||
| @ -1254,16 +1317,18 @@ CFF.prototype = { | ||||
|     var charstrings = []; | ||||
| 
 | ||||
|     for (var i = 0; i < glyphs.length; i++) { | ||||
|       var glyph = glyphs[i].glyph; | ||||
|       var unicode = GlyphsUnicode[glyph]; | ||||
|       var glyph = glyphs[i]; | ||||
|       var unicode = GlyphsUnicode[glyph.glyph]; | ||||
|       if (!unicode) { | ||||
|         if (glyph != ".notdef") | ||||
|         if (glyph.glyph != ".notdef") | ||||
|           warn(glyph + " does not have an entry in the glyphs unicode dictionary"); | ||||
|       } else { | ||||
|         charstrings.push({ | ||||
|           glyph: glyph, | ||||
|           unicode: unicode, | ||||
|           charstring: glyphs[i].data | ||||
|           charstring: glyph.data, | ||||
|           width: glyph.width, | ||||
|           lsb: glyph.lsb | ||||
|         }); | ||||
|       } | ||||
|     }; | ||||
| @ -1305,46 +1370,11 @@ CFF.prototype = { | ||||
|     var i = 0; | ||||
|     while (true) { | ||||
|       var obj = charstring[i]; | ||||
|       if (obj == null) | ||||
|         return []; | ||||
| 
 | ||||
|       if (obj == undefined) { | ||||
|         error("unknow charstring command for " + i + " in " + charstring); | ||||
|       } | ||||
|       if (obj.charAt) { | ||||
|         switch (obj) { | ||||
|           case "callothersubr": | ||||
|             var index = charstring[i - 1]; | ||||
|             var count = charstring[i - 2]; | ||||
|             var data = charstring[i - 3]; | ||||
| 
 | ||||
|             // If the flex mechanishm is not used in a font program, Adobe
 | ||||
|             // state that that entries 0, 1 and 2 can simply be replace by
 | ||||
|             // {}, which means that we can simply ignore them.
 | ||||
|             if (index < 3) { | ||||
|               i -= 3; | ||||
|               continue; | ||||
|             } | ||||
| 
 | ||||
|             // This is the same things about hint replacment, if it is not used
 | ||||
|             // entry 3 can be replaced by {}
 | ||||
|             if (index == 3) { | ||||
|               if (!data) { | ||||
|                 charstring.splice(i - 2, 4, 3); | ||||
|                 i -= 3; | ||||
|               } else { | ||||
|                 // 5 to remove the arguments, the callothersubr call and the pop command
 | ||||
|                 charstring.splice(i - 3, 5, 3); | ||||
|                 i -= 3; | ||||
|               } | ||||
|             } | ||||
|             break; | ||||
| 
 | ||||
|           case "hsbw": | ||||
|             var charWidthVector = charstring[1]; | ||||
|             var leftSidebearing = charstring[0]; | ||||
| 
 | ||||
|             charstring.splice(i, 1, leftSidebearing, "hmoveto"); | ||||
|             charstring.splice(0, 1); | ||||
|             break; | ||||
| 
 | ||||
|           case "endchar": | ||||
|           case "return": | ||||
|             // CharString is ready to be re-encode to commands number at this point
 | ||||
| @ -1356,7 +1386,7 @@ CFF.prototype = { | ||||
|               } else if (command.charAt) { | ||||
|                 var cmd = this.commandsMap[command]; | ||||
|                 if (!cmd) | ||||
|                   error(command); | ||||
|                   error("Unknow command: " + command); | ||||
| 
 | ||||
|                 if (IsArray(cmd)) { | ||||
|                   charstring.splice(j, 1, cmd[0], cmd[1]); | ||||
|  | ||||
							
								
								
									
										48
									
								
								pdf.js
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								pdf.js
									
									
									
									
									
								
							| @ -641,7 +641,7 @@ var PredictorStream = (function() { | ||||
|         var pixBytes = this.pixBytes = (colors * bits + 7) >> 3; | ||||
|         // add an extra pixByte to represent the pixel left of column 0
 | ||||
|         var rowBytes = this.rowBytes = (columns * colors * bits + 7) >> 3; | ||||
|          | ||||
| 
 | ||||
|         DecodeStream.call(this); | ||||
|         return this; | ||||
|     } | ||||
| @ -816,7 +816,7 @@ var DecryptStream = (function() { | ||||
|         DecodeStream.call(this); | ||||
|     } | ||||
| 
 | ||||
|     const chunkSize = 512; | ||||
|     var chunkSize = 512; | ||||
| 
 | ||||
|     constructor.prototype = Object.create(DecodeStream.prototype); | ||||
|     constructor.prototype.readBlock = function() { | ||||
| @ -910,18 +910,18 @@ var Ascii85Stream = (function() { | ||||
| 
 | ||||
| var CCITTFaxStream = (function() { | ||||
| 
 | ||||
|     const ccittEOL = -2; | ||||
|     const twoDimPass = 0; | ||||
|     const twoDimHoriz = 1; | ||||
|     const twoDimVert0 = 2; | ||||
|     const twoDimVertR1 = 3; | ||||
|     const twoDimVertL1 = 4; | ||||
|     const twoDimVertR2 = 5; | ||||
|     const twoDimVertL2 = 6; | ||||
|     const twoDimVertR3 = 7; | ||||
|     const twoDimVertL3 = 8; | ||||
|     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; | ||||
| 
 | ||||
|     const twoDimTable = [ | ||||
|     var twoDimTable = [ | ||||
|     [-1, -1], [-1, -1],               // 000000x
 | ||||
|     [7, twoDimVertL3],                // 0000010
 | ||||
|     [7, twoDimVertR3],                // 0000011
 | ||||
| @ -989,7 +989,7 @@ var CCITTFaxStream = (function() { | ||||
|     [1, twoDimVert0], [1, twoDimVert0] | ||||
|     ]; | ||||
| 
 | ||||
|     const whiteTable1 = [ | ||||
|     var whiteTable1 = [ | ||||
|         [-1, -1],                 // 00000
 | ||||
|         [12, ccittEOL],               // 00001
 | ||||
|         [-1, -1], [-1, -1],               // 0001x
 | ||||
| @ -1011,7 +1011,7 @@ var CCITTFaxStream = (function() { | ||||
|         [12, 2560]                    // 11111
 | ||||
|     ]; | ||||
| 
 | ||||
|     const whiteTable2 = [ | ||||
|     var whiteTable2 = [ | ||||
|         [-1, -1], [-1, -1], [-1, -1], [-1, -1],   // 0000000xx
 | ||||
|         [8, 29], [8, 29],             // 00000010x
 | ||||
|         [8, 30], [8, 30],             // 00000011x
 | ||||
| @ -1175,7 +1175,7 @@ var CCITTFaxStream = (function() { | ||||
|         [4, 7], [4, 7], [4, 7], [4, 7] | ||||
|     ]; | ||||
|      | ||||
|     const blackTable1 = [ | ||||
|     var blackTable1 = [ | ||||
|         [-1, -1], [-1, -1],                   // 000000000000x
 | ||||
|         [12, ccittEOL], [12, ccittEOL],           // 000000000001x
 | ||||
|         [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 00000000001xx
 | ||||
| @ -1236,7 +1236,7 @@ var CCITTFaxStream = (function() { | ||||
|         [10, 64], [10, 64], [10, 64], [10, 64] | ||||
|     ]; | ||||
| 
 | ||||
|     const blackTable2 = [ | ||||
|     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], | ||||
| @ -1315,7 +1315,7 @@ var CCITTFaxStream = (function() { | ||||
|         [7, 12], [7, 12], [7, 12], [7, 12]     | ||||
|     ]; | ||||
| 
 | ||||
|     const blackTable3 = [ | ||||
|     var blackTable3 = [ | ||||
|         [-1, -1], [-1, -1], [-1, -1], [-1, -1],       // 0000xx
 | ||||
|         [6, 9],                       // 000100
 | ||||
|         [6, 8],                       // 000101
 | ||||
| @ -3809,18 +3809,24 @@ var CanvasGraphics = (function() { | ||||
|             if (fontDescriptor && fontDescriptor.num) { | ||||
|                 var fontDescriptor = this.xref.fetchIfRef(fontDescriptor); | ||||
|                 fontName = fontDescriptor.get("FontName").name.replace("+", "_"); | ||||
|                 Fonts.active = fontName; | ||||
|                 Fonts.setActive(fontName, size); | ||||
|             } | ||||
| 
 | ||||
|             if (!fontName) { | ||||
|                 // TODO: fontDescriptor is not available, fallback to default font
 | ||||
|                 this.current.fontSize = size; | ||||
|                 this.ctx.font = this.current.fontSize + 'px sans-serif'; | ||||
|                 Fonts.setActive("sans-serif", this.current.fontSize); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             this.current.fontName = fontName; | ||||
|             this.current.fontSize = size; | ||||
|             this.ctx.font = this.current.fontSize +'px "' + fontName + '", Symbol'; | ||||
| 
 | ||||
|             this.ctx.font = this.current.fontSize + 'px "' + fontName + '"'; | ||||
|             if (this.ctx.$setFont) { | ||||
|               this.ctx.$setFont(fontName); | ||||
|             } | ||||
|         }, | ||||
|         setTextRenderingMode: function(mode) { | ||||
|             TODO("text rendering mode"); | ||||
| @ -3864,7 +3870,7 @@ var CanvasGraphics = (function() { | ||||
|                 text = Fonts.charsToUnicode(text); | ||||
|                 this.ctx.translate(this.current.x, -1 * this.current.y); | ||||
|                 this.ctx.fillText(text, 0, 0); | ||||
|                 this.current.x += this.ctx.measureText(text).width; | ||||
|                 this.current.x += Fonts.measureText(text); | ||||
|             } | ||||
| 
 | ||||
|             this.ctx.restore(); | ||||
|  | ||||
							
								
								
									
										10
									
								
								test/resources/browser_manifests/browser_manifest.json.linux
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								test/resources/browser_manifests/browser_manifest.json.linux
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| [ | ||||
|    { | ||||
|     "name":"firefox7", | ||||
|     "path":"/home/sayrer/firefoxen/nightly/firefox" | ||||
|    }, | ||||
|    { | ||||
|     "name":"chrome14", | ||||
|     "path":"/opt/google/chrome/chrome" | ||||
|    } | ||||
| ] | ||||
| @ -6,5 +6,9 @@ | ||||
|    { | ||||
|     "name":"firefox6", | ||||
|     "path":"/Users/sayrer/firefoxen/Aurora.app" | ||||
|    }, | ||||
|    { | ||||
|     "name":"chrome14", | ||||
|     "path":"/Applications/Google Chrome.app" | ||||
|    } | ||||
| ] | ||||
|  | ||||
							
								
								
									
										63
									
								
								test/test.py
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								test/test.py
									
									
									
									
									
								
							| @ -2,7 +2,7 @@ import json, platform, os, shutil, sys, subprocess, tempfile, threading, time, u | ||||
| from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer | ||||
| import SocketServer | ||||
| from optparse import OptionParser | ||||
| from urlparse import urlparse | ||||
| from urlparse import urlparse, parse_qs | ||||
| 
 | ||||
| USAGE_EXAMPLE = "%prog" | ||||
| 
 | ||||
| @ -132,6 +132,11 @@ class PDFTestHandler(BaseHTTPRequestHandler): | ||||
|         self.send_header('Content-Type', 'text/plain') | ||||
|         self.end_headers() | ||||
| 
 | ||||
|         url = urlparse(self.path) | ||||
|         if url.path == "/tellMeToQuit": | ||||
|             tellAppToQuit(url.path, url.query) | ||||
|             return | ||||
| 
 | ||||
|         result = json.loads(self.rfile.read(numBytes)) | ||||
|         browser, id, failure, round, page, snapshot = result['browser'], result['id'], result['failure'], result['round'], result['page'], result['snapshot'] | ||||
|         taskResults = State.taskResults[browser][id] | ||||
| @ -156,8 +161,20 @@ class PDFTestHandler(BaseHTTPRequestHandler): | ||||
| 
 | ||||
|         State.done = (0 == State.remaining) | ||||
| 
 | ||||
| # this just does Firefox for now | ||||
| class BrowserCommand(): | ||||
| # Applescript hack to quit Chrome on Mac | ||||
| def tellAppToQuit(path, query): | ||||
|     if platform.system() != "Darwin": | ||||
|         return | ||||
|     d = parse_qs(query) | ||||
|     path = d['path'][0] | ||||
|     cmd = """osascript<<END | ||||
| tell application "%s" | ||||
| quit | ||||
| end tell | ||||
| END""" % path | ||||
|     os.system(cmd) | ||||
| 
 | ||||
| class BaseBrowserCommand(object): | ||||
|     def __init__(self, browserRecord): | ||||
|         self.name = browserRecord["name"] | ||||
|         self.path = browserRecord["path"] | ||||
| @ -170,14 +187,9 @@ class BrowserCommand(): | ||||
|         if not os.path.exists(self.path): | ||||
|             throw("Path to browser '%s' does not exist." % self.path) | ||||
| 
 | ||||
|     def _fixupMacPath(self): | ||||
|         self.path = os.path.join(self.path, "Contents", "MacOS", "firefox-bin") | ||||
| 
 | ||||
|     def setup(self): | ||||
|         self.tempDir = tempfile.mkdtemp() | ||||
|         self.profileDir = os.path.join(self.tempDir, "profile") | ||||
|         shutil.copytree(os.path.join(DOC_ROOT, "test", "resources", "firefox"), | ||||
|                         self.profileDir) | ||||
| 
 | ||||
|     def teardown(self): | ||||
|         # If the browser is still running, wait up to ten seconds for it to quit | ||||
| @ -194,6 +206,18 @@ class BrowserCommand(): | ||||
|         if self.tempDir is not None and os.path.exists(self.tempDir): | ||||
|             shutil.rmtree(self.tempDir) | ||||
| 
 | ||||
|     def start(self, url): | ||||
|         raise Exception("Can't start BaseBrowserCommand") | ||||
| 
 | ||||
| class FirefoxBrowserCommand(BaseBrowserCommand): | ||||
|     def _fixupMacPath(self): | ||||
|         self.path = os.path.join(self.path, "Contents", "MacOS", "firefox-bin") | ||||
| 
 | ||||
|     def setup(self): | ||||
|         super(FirefoxBrowserCommand, self).setup() | ||||
|         shutil.copytree(os.path.join(DOC_ROOT, "test", "resources", "firefox"), | ||||
|                         self.profileDir) | ||||
| 
 | ||||
|     def start(self, url): | ||||
|         cmds = [self.path] | ||||
|         if platform.system() == "Darwin": | ||||
| @ -201,9 +225,29 @@ class BrowserCommand(): | ||||
|         cmds.extend(["-no-remote", "-profile", self.profileDir, url]) | ||||
|         self.process = subprocess.Popen(cmds) | ||||
| 
 | ||||
| class ChromeBrowserCommand(BaseBrowserCommand): | ||||
|     def _fixupMacPath(self): | ||||
|         self.path = os.path.join(self.path, "Contents", "MacOS", "Google Chrome") | ||||
| 
 | ||||
|     def start(self, url): | ||||
|         cmds = [self.path] | ||||
|         cmds.extend(["--user-data-dir=%s" % self.profileDir, | ||||
|                      "--no-first-run", "--disable-sync", url]) | ||||
|         self.process = subprocess.Popen(cmds) | ||||
| 
 | ||||
| def makeBrowserCommand(browser): | ||||
|     path = browser["path"].lower() | ||||
|     name = browser["name"].lower() | ||||
|     if name.find("firefox") > -1 or path.find("firefox") > -1: | ||||
|         return FirefoxBrowserCommand(browser) | ||||
|     elif name.find("chrom") > -1 or path.find("chrom") > -1: | ||||
|         return ChromeBrowserCommand(browser) | ||||
|     else: | ||||
|         raise Exception("Unrecognized browser: %s" % browser) | ||||
| 
 | ||||
| def makeBrowserCommands(browserManifestFile): | ||||
|     with open(browserManifestFile) as bmf: | ||||
|         browsers = [BrowserCommand(browser) for browser in json.load(bmf)] | ||||
|         browsers = [makeBrowserCommand(browser) for browser in json.load(bmf)] | ||||
|     return browsers | ||||
| 
 | ||||
| def downloadLinkedPDFs(manifestList): | ||||
| @ -267,6 +311,7 @@ def startBrowsers(browsers, options): | ||||
|         b.setup() | ||||
|         print 'Launching', b.name | ||||
|         qs = 'browser='+ urllib.quote(b.name) +'&manifestFile='+ urllib.quote(options.manifestFile) | ||||
|         qs += '&path=' + b.path | ||||
|         b.start('http://localhost:8080/test/test_slave.html?'+ qs) | ||||
| 
 | ||||
| def teardownBrowsers(browsers): | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|   <script type="text/javascript" src="/fonts.js"></script> | ||||
|   <script type="text/javascript" src="/glyphlist.js"></script> | ||||
|   <script type="application/javascript"> | ||||
| var browser, canvas, currentTask, currentTaskIdx, failure, manifest, numPages, pdfDoc, stdout; | ||||
| var appPath, browser, canvas, currentTask, currentTaskIdx, failure, manifest, numPages, pdfDoc, stdout; | ||||
| 
 | ||||
| function queryParams() { | ||||
|     var qs = window.location.search.substring(1); | ||||
| @ -23,12 +23,13 @@ function load() { | ||||
|   var params = queryParams(); | ||||
|   browser = params.browser; | ||||
|   manifestFile = params.manifestFile; | ||||
|   appPath = params.path; | ||||
| 
 | ||||
|   canvas = document.createElement("canvas"); | ||||
|   canvas.mozOpaque = true; | ||||
|   stdout = document.getElementById("stdout"); | ||||
| 
 | ||||
|   log("Harness thinks this browser is '"+ browser +"'\n"); | ||||
|   log("Harness thinks this browser is '"+ browser + "' with path " + appPath + "\n"); | ||||
|   log("Fetching manifest "+ manifestFile +"..."); | ||||
| 
 | ||||
|   var r = new XMLHttpRequest(); | ||||
| @ -157,13 +158,21 @@ function snapshotCurrentPage(gfx) { | ||||
|   ); | ||||
| } | ||||
| 
 | ||||
| function sendQuitRequest() { | ||||
|   var r = new XMLHttpRequest(); | ||||
|   r.open("POST", "/tellMeToQuit?path=" + escape(appPath), false); | ||||
|   r.send(""); | ||||
| } | ||||
| 
 | ||||
| function quitApp() { | ||||
|   log("Done!"); | ||||
|   document.body.innerHTML = "Tests are finished.  <h1>CLOSE ME!</h1>"; | ||||
|   if (window.SpecialPowers) | ||||
|   if (window.SpecialPowers) { | ||||
|     SpecialPowers.quitApplication(); | ||||
|   else | ||||
|   } else { | ||||
|     sendQuitRequest(); | ||||
|     window.close(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function done() { | ||||
|  | ||||
| @ -1,7 +1,10 @@ | ||||
| <html> | ||||
|     <head> | ||||
|         <title>Simple pdf.js page worker viewer</title> | ||||
|         <script type="text/javascript" src="worker_client.js"></script> | ||||
|         <script type="text/javascript" src="fonts.js"></script> | ||||
|         <script type="text/javascript" src="glyphlist.js"></script> | ||||
|         <script type="text/javascript" src="pdf.js"></script> | ||||
|         <script type="text/javascript" src="worker/client.js"></script> | ||||
| <script> | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -119,7 +119,8 @@ function CanvasProxy(width, height) { | ||||
|   "$addCurrentX", | ||||
|   "$saveCurrentX", | ||||
|   "$restoreCurrentX", | ||||
|   "$showText" | ||||
|   "$showText", | ||||
|   "$setFont" | ||||
|   ]; | ||||
| 
 | ||||
|   function buildFuncCall(name) { | ||||
| @ -18,12 +18,124 @@ if (typeof console.time == "undefined") { | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| function FontWorker() { | ||||
|   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 | ||||
|     if (data.action in actionHandler) { | ||||
|       actionHandler[data.action].call(this, data.data); | ||||
|     } else { | ||||
|       throw "Unkown action from worker: " + data.action; | ||||
|     } | ||||
|   }.bind(this); | ||||
|    | ||||
|   this.$handleFontLoadedCallback = this.handleFontLoadedCallback.bind(this); | ||||
| } | ||||
| 
 | ||||
| FontWorker.prototype = { | ||||
|   handleFontLoadedCallback: function() { | ||||
|     // Decrease the number of fonts wainting to be loaded.
 | ||||
|     this.fontsWaiting--; | ||||
|     // If all fonts are available now, then call all the callbacks.
 | ||||
|     if (this.fontsWaiting == 0) { | ||||
|       var callbacks = this.fontsWaitingCallbacks; | ||||
|       for (var i = 0; i < callbacks.length; i++) { | ||||
|         callbacks[i](); | ||||
|       } | ||||
|       this.fontsWaitingCallbacks.length = 0; | ||||
|     } | ||||
|   }, | ||||
|    | ||||
|   actionHandler: { | ||||
|     "log": function(data) { | ||||
|       console.log.apply(console, data); | ||||
|     }, | ||||
|      | ||||
|     "fonts": function(data) { | ||||
|       // console.log("got processed fonts from worker", Object.keys(data));
 | ||||
|       for (name in data) { | ||||
|         // Update the 
 | ||||
|         Fonts[name].properties = { | ||||
|           encoding: data[name].encoding | ||||
|         } | ||||
|          | ||||
|         // Call `Font.prototype.bindDOM` to make the font get loaded on the page.
 | ||||
|         Font.prototype.bindDOM.call( | ||||
|           Fonts[name], | ||||
|           data[name].str, | ||||
|           // IsLoadedCallback.
 | ||||
|           this.$handleFontLoadedCallback | ||||
|         ); | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   ensureFonts: function(data, callback) { | ||||
|     var font; | ||||
|     var notLoaded = []; | ||||
|     for (var i = 0; i < data.length; i++) { | ||||
|       font = data[i]; | ||||
|       if (Fonts[font.name]) { | ||||
|         continue; | ||||
|       } | ||||
|      | ||||
|       // Store only the data on Fonts that is needed later on, such that we
 | ||||
|       // hold track on as lease memory as possible.
 | ||||
|       Fonts[font.name] = { | ||||
|         name:       font.name, | ||||
|         mimetype:   font.mimetype, | ||||
|         // This is set later on the worker replay. For some fonts, the encoding
 | ||||
|         // is calculated during the conversion process happening on the worker
 | ||||
|         // and therefore is not available right now.
 | ||||
|         // properties: {
 | ||||
|         //   encoding:  font.properties.encoding
 | ||||
|         // },
 | ||||
|         cache:      Object.create(null) | ||||
|       }; | ||||
| 
 | ||||
|       // Mark this font to be handled later.
 | ||||
|       notLoaded.push(font); | ||||
|       // Increate the number of fonts to wait for.
 | ||||
|       this.fontsWaiting++; | ||||
|     } | ||||
|      | ||||
|     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"); | ||||
|       // Send the worker the fonts to work on.
 | ||||
|       this.worker.postMessage({ | ||||
|         action: "fonts", | ||||
|         data:   notLoaded | ||||
|       }); | ||||
|       if (callback) { | ||||
|         this.fontsWaitingCallbacks.push(callback); | ||||
|       } | ||||
|     } | ||||
|     // All fonts are present? Well, then just call the callback if there is one.
 | ||||
|     else { | ||||
|       if (callback) { | ||||
|         callback(); | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
| } | ||||
| 
 | ||||
| function WorkerPDFDoc(canvas) { | ||||
|   var timer = null | ||||
| 
 | ||||
|   this.ctx = canvas.getContext("2d"); | ||||
|   this.canvas = canvas; | ||||
|   this.worker = new Worker('pdf_worker.js'); | ||||
|   this.worker = new Worker('worker/pdf.js'); | ||||
|   this.fontWorker = new FontWorker(); | ||||
|   this.waitingForFonts = false; | ||||
|   this.waitingForFontsCallback = []; | ||||
| 
 | ||||
|   this.numPage = 1; | ||||
|   this.numPages = null; | ||||
| @ -56,6 +168,7 @@ function WorkerPDFDoc(canvas) { | ||||
|     }, | ||||
| 
 | ||||
|     "$showText": function(y, text) { | ||||
|       text = Fonts.charsToUnicode(text); | ||||
|       this.translate(currentX, -1 * y); | ||||
|       this.fillText(text, 0, 0); | ||||
|       currentX += this.measureText(text).width; | ||||
| @ -136,6 +249,10 @@ function WorkerPDFDoc(canvas) { | ||||
|         throw "Pattern not found"; | ||||
|       } | ||||
|       this.strokeStyle = pattern; | ||||
|     }, | ||||
|      | ||||
|     "$setFont": function(name) { | ||||
|       Fonts.active = name; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| @ -187,6 +304,18 @@ function WorkerPDFDoc(canvas) { | ||||
|       div.setAttribute("style", style); | ||||
|       document.body.appendChild(div); | ||||
|     }, | ||||
|      | ||||
|     "fonts": function(data) { | ||||
|       this.waitingForFonts = true; | ||||
|       this.fontWorker.ensureFonts(data, function() { | ||||
|         this.waitingForFonts = false; | ||||
|         var callbacks = this.waitingForFontsCallback; | ||||
|         for (var i = 0; i < callbacks.length; i++) { | ||||
|           callbacks[i](); | ||||
|         } | ||||
|         this.waitingForFontsCallback.length = 0; | ||||
|       }.bind(this)); | ||||
|     }, | ||||
| 
 | ||||
|     "jpeg_stream": function(data) { | ||||
|       var img = new Image(); | ||||
| @ -207,11 +336,9 @@ function WorkerPDFDoc(canvas) { | ||||
|           canvasList[id] = newCanvas; | ||||
|         } | ||||
| 
 | ||||
|         // There might be fonts that need to get loaded. Shedule the
 | ||||
|         // rendering at the end of the event queue ensures this.
 | ||||
|         setTimeout(function() { | ||||
|         var renderData = function() { | ||||
|           if (id == 0) { | ||||
|             console.time("canvas rendering"); | ||||
|             console.time("main canvas rendering"); | ||||
|             var ctx = this.ctx; | ||||
|             ctx.save(); | ||||
|             ctx.fillStyle = "rgb(255, 255, 255)"; | ||||
| @ -219,12 +346,27 @@ function WorkerPDFDoc(canvas) { | ||||
|             ctx.restore(); | ||||
|           } | ||||
|           renderProxyCanvas(canvasList[id], cmdQueue); | ||||
|           if (id == 0) console.timeEnd("canvas rendering") | ||||
|         }, 0, this); | ||||
|           if (id == 0) { | ||||
|             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); | ||||
|             this.waitingForFontsCallback.push(renderData); | ||||
|           } else { | ||||
|             // console.log("assume canvas doesn't have fonts", id);
 | ||||
|             renderData(); | ||||
|           } | ||||
|         } else { | ||||
|           renderData(); | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // List to the WebWorker for data and call actionHandler on it.
 | ||||
|   // Listen to the WebWorker for data and call actionHandler on it.
 | ||||
|   this.worker.onmessage = function(event) { | ||||
|     var data = event.data; | ||||
|     if (data.action in actionHandler) { | ||||
| @ -232,7 +374,7 @@ function WorkerPDFDoc(canvas) { | ||||
|     } else { | ||||
|       throw "Unkown action from worker: " + data.action; | ||||
|     } | ||||
|   } | ||||
|   }.bind(this) | ||||
| } | ||||
| 
 | ||||
| WorkerPDFDoc.prototype.open = function(url, callback) { | ||||
| @ -255,6 +397,8 @@ WorkerPDFDoc.prototype.open = function(url, callback) { | ||||
| 
 | ||||
| WorkerPDFDoc.prototype.showPage = function(numPage) { | ||||
|   this.numPage = parseInt(numPage); | ||||
|   console.log("=== start rendering page " + numPage + " ==="); | ||||
|   console.time(">>> total page display time:"); | ||||
|   this.worker.postMessage(numPage); | ||||
|   if (this.onChangePage) { | ||||
|     this.onChangePage(numPage); | ||||
							
								
								
									
										27
									
								
								worker/console.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								worker/console.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +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"; | ||||
| 
 | ||||
| var consoleTimer = {}; | ||||
| var console = { | ||||
|   log: function log() { | ||||
|     var args = Array.prototype.slice.call(arguments); | ||||
|     postMessage({ | ||||
|       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; | ||||
|     } | ||||
|     this.log("Timer:", name, Date.now() - time); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										65
									
								
								worker/font.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								worker/font.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / | ||||
| /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| importScripts("console.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
 | ||||
|   // "shape" for all required objects agains, such that the encoding works as
 | ||||
|   // expected.
 | ||||
|   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); | ||||
|   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 data = fontObj.data; | ||||
|   var length = data.length; | ||||
|   for (var j = 0; j < length; j++) | ||||
|     str += String.fromCharCode(data[j]); | ||||
|    | ||||
|   return { | ||||
|     str:      str, | ||||
|     encoding: font.properties.encoding | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| * Functions to handle data sent by the MainThread. | ||||
| */ | ||||
| var actionHandler = { | ||||
|   "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 | ||||
|     }) | ||||
|   }, | ||||
| } | ||||
| 
 | ||||
| // Listen to the MainThread for data and call actionHandler on it.
 | ||||
| this.onmessage = function(event) { | ||||
|   var data = event.data; | ||||
|   if (data.action in actionHandler) { | ||||
|     actionHandler[data.action].call(this, data.data); | ||||
|   } else { | ||||
|     throw "Unkown action from worker: " + data.action; | ||||
|   } | ||||
| } | ||||
| @ -27,10 +27,11 @@ var console = { | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| importScripts("canvas_proxy.js"); | ||||
| importScripts("pdf.js"); | ||||
| importScripts("fonts.js"); | ||||
| importScripts("glyphlist.js") | ||||
| importScripts("console.js") | ||||
| importScripts("canvas.js"); | ||||
| importScripts("../pdf.js"); | ||||
| importScripts("../fonts.js"); | ||||
| importScripts("../glyphlist.js") | ||||
| 
 | ||||
| // Use the JpegStreamProxy proxy.
 | ||||
| JpegStream = JpegStreamProxy; | ||||
| @ -65,21 +66,14 @@ onmessage = function(event) { | ||||
|     page.compile(gfx, fonts); | ||||
|     console.timeEnd("compile"); | ||||
| 
 | ||||
|     // Send fonts to the main thread.
 | ||||
|     console.time("fonts"); | ||||
|     // Inspect fonts and translate the missing one.
 | ||||
|     var count = fonts.length; | ||||
|     for (var i = 0; i < count; i++) { | ||||
|       var font = fonts[i]; | ||||
|       if (Fonts[font.name]) { | ||||
|         fontsReady = fontsReady && !Fonts[font.name].loading; | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       // This "builds" the font and sents it over to the main thread.
 | ||||
|       new Font(font.name, font.file, font.properties); | ||||
|     } | ||||
|     postMessage({ | ||||
|       action: "fonts", | ||||
|       data:   fonts | ||||
|     }); | ||||
|     console.timeEnd("fonts"); | ||||
| 
 | ||||
|      | ||||
|     console.time("display"); | ||||
|     page.display(gfx); | ||||
|     canvas.flush(); | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user