Merge branch 'master' of https://github.com/andreasgal/pdf.js.git into charstoglyphs
Conflicts: test/test_manifest.json
This commit is contained in:
		
						commit
						0b1b8da982
					
				
							
								
								
									
										1
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								LICENSE
									
									
									
									
									
								
							| @ -8,6 +8,7 @@ | ||||
|                   Justin D'Arcangelo <justindarc@gmail.com> | ||||
|                   Yury Delendik | ||||
|                   Kalervo Kujala | ||||
|                   Adil Allawi <@ironymark> | ||||
| 
 | ||||
|     Permission is hereby granted, free of charge, to any person obtaining a | ||||
|     copy of this software and associated documentation files (the "Software"), | ||||
|  | ||||
							
								
								
									
										72
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								Makefile
									
									
									
									
									
								
							| @ -55,30 +55,30 @@ browser-test: | ||||
| 	--browserManifestFile=$(PDF_BROWSERS) \
 | ||||
| 	--manifestFile=$(PDF_TESTS) | ||||
| 
 | ||||
| # make shell-test
 | ||||
| #
 | ||||
| # This target runs all of the tests that can be run in a JS shell.
 | ||||
| # The shell used is taken from the JS_SHELL environment variable. If
 | ||||
| # that variable is not defined, the script will attempt to use the copy
 | ||||
| # of Rhino that comes with the Closure compiler used for producing the
 | ||||
| # website.
 | ||||
| SHELL_TARGET = $(NULL) | ||||
| ifeq ($(JS_SHELL),) | ||||
| JS_SHELL := "java -cp $(BUILD_DIR)/compiler.jar" | ||||
| JS_SHELL += "com.google.javascript.jscomp.mozilla.rhino.tools.shell.Main" | ||||
| SHELL_TARGET = compiler | ||||
| endif | ||||
| 
 | ||||
| shell-test: shell-msg $(SHELL_TARGET) font-test | ||||
| shell-msg: | ||||
| ifeq ($(SHELL_TARGET), compiler) | ||||
| 	@echo "No JS_SHELL env variable present." | ||||
| 	@echo "The default is to find a copy of Rhino and try that." | ||||
| endif | ||||
| 	@echo "JS shell command is: $(JS_SHELL)" | ||||
| 
 | ||||
| font-test: | ||||
| 	@echo "font test stub." | ||||
| # # make shell-test
 | ||||
| # #
 | ||||
| # # This target runs all of the tests that can be run in a JS shell.
 | ||||
| # # The shell used is taken from the JS_SHELL environment variable. If
 | ||||
| # # that variable is not defined, the script will attempt to use the copy
 | ||||
| # # of Rhino that comes with the Closure compiler used for producing the
 | ||||
| # # website.
 | ||||
| # SHELL_TARGET = $(NULL)
 | ||||
| # ifeq ($(JS_SHELL),)
 | ||||
| # JS_SHELL := "java -cp $(BUILD_DIR)/compiler.jar"
 | ||||
| # JS_SHELL += "com.google.javascript.jscomp.mozilla.rhino.tools.shell.Main"
 | ||||
| # SHELL_TARGET = compiler
 | ||||
| # endif
 | ||||
| # 
 | ||||
| # shell-test: shell-msg $(SHELL_TARGET) font-test
 | ||||
| # shell-msg:
 | ||||
| # ifeq ($(SHELL_TARGET), compiler)
 | ||||
| #   @echo "No JS_SHELL env variable present."
 | ||||
| #   @echo "The default is to find a copy of Rhino and try that."
 | ||||
| # endif
 | ||||
| #   @echo "JS shell command is: $(JS_SHELL)"
 | ||||
| # 
 | ||||
| # font-test:
 | ||||
| #   @echo "font test stub."
 | ||||
| 
 | ||||
| # make lint
 | ||||
| #
 | ||||
| @ -133,18 +133,18 @@ $(GH_PAGES)/web/%: web/% | ||||
| $(GH_PAGES)/web/images/%: web/images/% | ||||
| 	@cp $< $@ | ||||
| 
 | ||||
| # make compiler
 | ||||
| #
 | ||||
| # This target downloads the Closure compiler, and places it in the
 | ||||
| # build directory. This target is also useful when the user doesn't
 | ||||
| # have a JS shell available--we can have them use the Rhino shell that
 | ||||
| # comes with Closure.
 | ||||
| COMPILER_URL = http://closure-compiler.googlecode.com/files/compiler-latest.zip | ||||
| 
 | ||||
| compiler: $(BUILD_DIR)/compiler.zip | ||||
| $(BUILD_DIR)/compiler.zip: | $(BUILD_DIR) | ||||
| 	curl $(COMPILER_URL) > $(BUILD_DIR)/compiler.zip; | ||||
| 	cd $(BUILD_DIR); unzip compiler.zip compiler.jar; | ||||
| # # make compiler
 | ||||
| # #
 | ||||
| # # This target downloads the Closure compiler, and places it in the
 | ||||
| # # build directory. This target is also useful when the user doesn't
 | ||||
| # # have a JS shell available--we can have them use the Rhino shell that
 | ||||
| # # comes with Closure.
 | ||||
| # COMPILER_URL = http://closure-compiler.googlecode.com/files/compiler-latest.zip
 | ||||
| # 
 | ||||
| # compiler: $(BUILD_DIR)/compiler.zip
 | ||||
| # $(BUILD_DIR)/compiler.zip: | $(BUILD_DIR)
 | ||||
| #   curl $(COMPILER_URL) > $(BUILD_DIR)/compiler.zip;
 | ||||
| #   cd $(BUILD_DIR); unzip compiler.zip compiler.jar;
 | ||||
| 
 | ||||
| # make firefox-extension
 | ||||
| #
 | ||||
|  | ||||
							
								
								
									
										89
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								README.md
									
									
									
									
									
								
							| @ -1,17 +1,84 @@ | ||||
| # 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. | ||||
| 
 | ||||
| ## Overview | ||||
| 
 | ||||
| pdf.js is an HTML5 technology experiment that explores building a faithful | ||||
| and efficient Portable Document Format (PDF) renderer without native code  | ||||
| assistance. | ||||
| 
 | ||||
| pdf.js is community-driven and supported by Mozilla Labs. Our goal is to  | ||||
| create a general-purpose, web standards-based platform for parsing and  | ||||
| rendering PDFs, and eventually release a PDF reader extension powered by  | ||||
| pdf.js. Integration with Firefox is a possibility if the experiment proves  | ||||
| successful. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ## Getting started | ||||
| 
 | ||||
| **Online demo** | ||||
| 
 | ||||
| For an online demo, visit: | ||||
| 
 | ||||
|   http://andreasgal.github.com/pdf.js/web/viewer.html | ||||
| 
 | ||||
| This demo provides an interactive interface for displaying and browsing PDFs | ||||
| using the pdf.js API. | ||||
| 
 | ||||
| **Hello world** | ||||
| 
 | ||||
| For a "hello world" example, take a look at: | ||||
| 
 | ||||
|     examples/helloworld/ | ||||
| 
 | ||||
| This example illustrates the bare minimum ingredients for integrating pdf.js | ||||
| in a custom project. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ## Running the Tests | ||||
| 
 | ||||
| pdf.js comes with browser-level regression tests that allow one to probe  | ||||
| whether it's able to successfully parse PDFs, as well as compare its output | ||||
| against reference images, pixel-by-pixel. | ||||
| 
 | ||||
| To run the tests, first configure the browser manifest file at: | ||||
| 
 | ||||
|     test/resources/browser_manifests/browser_manifest.json | ||||
| 
 | ||||
| Sample manifests for different platforms are provided in that directory. | ||||
| 
 | ||||
| To run all the bundled tests, type: | ||||
| 
 | ||||
|     $ make test | ||||
| 
 | ||||
| and cross your fingers. Different types of tests are available, see the test | ||||
| manifest file at: | ||||
| 
 | ||||
|     test/test_manifest.json | ||||
| 
 | ||||
| The test type `eq` tests whether the output images are identical to reference  | ||||
| images. The test type `load` simply tests whether the file loads without  | ||||
| raising any errors. | ||||
| 
 | ||||
| 
 | ||||
| ## Contributing | ||||
| 
 | ||||
| pdf.js is a community-driver project, so contributors are always welcome.  | ||||
| Simply fork our repo and contribute away. A great place to start is our | ||||
| open issues.  | ||||
| 
 | ||||
| For better consistency and long-term stability, please do look around the  | ||||
| code and try to follow our conventions. | ||||
| 
 | ||||
| 
 | ||||
| ## Additional resources | ||||
| 
 | ||||
| Our demo site is here: | ||||
| 
 | ||||
|   http://andreasgal.github.com/pdf.js/ | ||||
|   http://andreasgal.github.com/pdf.js/web/viewer.html | ||||
| 
 | ||||
| You can read more about pdf.js here: | ||||
| 
 | ||||
| @ -19,14 +86,14 @@ You can read more about pdf.js here: | ||||
| 
 | ||||
|   http://blog.mozilla.com/cjones/2011/06/15/overview-of-pdf-js-guts/ | ||||
| 
 | ||||
| follow us on twitter: @pdfjs | ||||
| Follow us on twitter: @pdfjs | ||||
| 
 | ||||
|   http://twitter.com/#!/pdfjs | ||||
| 
 | ||||
| join our mailing list: | ||||
| Join our mailing list: | ||||
| 
 | ||||
|   dev-pdf-js@lists.mozilla.org | ||||
| 
 | ||||
| and talk to us on IRC: | ||||
| Talk to us on IRC: | ||||
| 
 | ||||
|   #pdfjs on irc.mozilla.org | ||||
|  | ||||
							
								
								
									
										16
									
								
								examples/helloworld/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								examples/helloworld/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| ## "Hello World" overview | ||||
| 
 | ||||
| This example is a minimalistic application of the pdf.js project. The file  | ||||
| `helloworld.pdf` is from the GNUpdf project (see [Introduction to PDF at GNUpdf](http://gnupdf.org/Introduction_to_PDF), and contains a simple and  | ||||
| human-readable PDF. | ||||
| 
 | ||||
| 
 | ||||
| ## Getting started | ||||
| 
 | ||||
| Point your browser to `index.html`. Voila. Take a peek at `hello.js` to see  | ||||
| how to make basic calls to `pdf.js`. | ||||
| 
 | ||||
| 
 | ||||
| ## Additional resources | ||||
| 
 | ||||
| + [GNUpdf - Introduction to PDF](http://gnupdf.org/Introduction_to_PDF) | ||||
							
								
								
									
										49
									
								
								examples/helloworld/hello.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								examples/helloworld/hello.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| //
 | ||||
| // See README for overview
 | ||||
| //
 | ||||
| 
 | ||||
| 
 | ||||
| //
 | ||||
| // Ajax GET request, for binary files
 | ||||
| // (like jQuery's $.get(), but supports the binary type ArrayBuffer)
 | ||||
| //
 | ||||
| var ajaxGet = function(url, callback){ | ||||
|   var xhr = new XMLHttpRequest(); | ||||
|   xhr.open('GET', url); | ||||
|   xhr.mozResponseType = xhr.responseType = 'arraybuffer'; | ||||
|   xhr.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200; | ||||
|   xhr.onreadystatechange = function() { | ||||
|     if (xhr.readyState === 4 && xhr.status === xhr.expected) { | ||||
|       var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse || | ||||
|                   xhr.responseArrayBuffer || xhr.response); | ||||
| 
 | ||||
|       callback(data); | ||||
|     } | ||||
|   }; | ||||
|   xhr.send(null);   | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // This is where the fun happens
 | ||||
| //
 | ||||
| ajaxGet('helloworld.pdf', function(data){ | ||||
|   //
 | ||||
|   // Instantiate PDFDoc with PDF data
 | ||||
|   //
 | ||||
|   var pdf = new PDFDoc(new Stream(data)); | ||||
|   var page = pdf.getPage(1); | ||||
|   var scale = 1.5; | ||||
| 
 | ||||
|   //
 | ||||
|   // Prepare canvas using PDF page dimensions
 | ||||
|   //
 | ||||
|   var canvas = document.getElementById('the-canvas'); | ||||
|   var context = canvas.getContext('2d'); | ||||
|   canvas.height = page.height * scale; | ||||
|   canvas.width = page.width * scale;   | ||||
| 
 | ||||
|   //
 | ||||
|   // Render PDF page into canvas context
 | ||||
|   //
 | ||||
|   page.startRendering(context); | ||||
| }); | ||||
							
								
								
									
										68
									
								
								examples/helloworld/helloworld.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								examples/helloworld/helloworld.pdf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| %PDF-1.7 | ||||
| 
 | ||||
| 1 0 obj  % entry point | ||||
| << | ||||
|   /Type /Catalog | ||||
|   /Pages 2 0 R | ||||
| >> | ||||
| endobj | ||||
| 
 | ||||
| 2 0 obj | ||||
| << | ||||
|   /Type /Pages | ||||
|   /MediaBox [ 0 0 200 200 ] | ||||
|   /Count 1 | ||||
|   /Kids [ 3 0 R ] | ||||
| >> | ||||
| endobj | ||||
| 
 | ||||
| 3 0 obj | ||||
| << | ||||
|   /Type /Page | ||||
|   /Parent 2 0 R | ||||
|   /Resources << | ||||
|     /Font << | ||||
|       /F1 4 0 R  | ||||
|     >> | ||||
|   >> | ||||
|   /Contents 5 0 R | ||||
| >> | ||||
| endobj | ||||
| 
 | ||||
| 4 0 obj | ||||
| << | ||||
|   /Type /Font | ||||
|   /Subtype /Type1 | ||||
|   /BaseFont /Times-Roman | ||||
| >> | ||||
| endobj | ||||
| 
 | ||||
| 5 0 obj  % page content | ||||
| << | ||||
|   /Length 44 | ||||
| >> | ||||
| stream | ||||
| BT | ||||
| 70 50 TD | ||||
| /F1 12 Tf | ||||
| (Hello, world!) Tj | ||||
| ET | ||||
| endstream | ||||
| endobj | ||||
| 
 | ||||
| xref | ||||
| 0 6 | ||||
| 0000000000 65535 f  | ||||
| 0000000010 00000 n  | ||||
| 0000000079 00000 n  | ||||
| 0000000173 00000 n  | ||||
| 0000000301 00000 n  | ||||
| 0000000380 00000 n  | ||||
| trailer | ||||
| << | ||||
|   /Size 6 | ||||
|   /Root 1 0 R | ||||
| >> | ||||
| startxref | ||||
| 492 | ||||
| %%EOF | ||||
							
								
								
									
										18
									
								
								examples/helloworld/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								examples/helloworld/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| <!doctype html> | ||||
| <html> | ||||
| 
 | ||||
| <head> | ||||
|   <!-- PDF.js-specific --> | ||||
|   <script type="text/javascript" src="../../pdf.js"></script> | ||||
|   <script type="text/javascript" src="../../metrics.js"></script> | ||||
|   <script type="text/javascript" src="../../fonts.js"></script> | ||||
|   <script type="text/javascript" src="../../glyphlist.js"></script> | ||||
| 
 | ||||
|   <script type="text/javascript" src="hello.js"></script> | ||||
| </head>   | ||||
| 
 | ||||
| <body> | ||||
|   <canvas id="the-canvas" style="border:1px solid black;"/> | ||||
| </body> | ||||
| 
 | ||||
| </html> | ||||
							
								
								
									
										53
									
								
								fonts.js
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								fonts.js
									
									
									
									
									
								
							| @ -12,6 +12,9 @@ var kMaxWaitForFontFace = 1000; | ||||
| // Unicode Private Use Area
 | ||||
| var kCmapGlyphOffset = 0xE000; | ||||
| 
 | ||||
| // PDF Glyph Space Units are one Thousandth of a TextSpace Unit except for Type 3 fonts
 | ||||
| var kPDFGlyphSpaceUnits = 1000; | ||||
| 
 | ||||
| // Until hinting is fully supported this constant can be used
 | ||||
| var kHintingEnabled = false; | ||||
| 
 | ||||
| @ -536,6 +539,10 @@ var Font = (function Font() { | ||||
|   }; | ||||
| 
 | ||||
|   function createOpenTypeHeader(sfnt, file, numTables) { | ||||
|     // Windows hates the Mac TrueType sfnt version number
 | ||||
|     if (sfnt == 'true') | ||||
|       sfnt = string32(0x00010000); | ||||
| 
 | ||||
|     // sfnt version (4 bytes)
 | ||||
|     var header = sfnt; | ||||
| 
 | ||||
| @ -665,7 +672,9 @@ var Font = (function Font() { | ||||
|                          format314); | ||||
|   }; | ||||
| 
 | ||||
|   function createOS2Table(properties) { | ||||
|   function createOS2Table(properties, override) { | ||||
|     var override = override || {}; | ||||
| 
 | ||||
|     var ulUnicodeRange1 = 0; | ||||
|     var ulUnicodeRange2 = 0; | ||||
|     var ulUnicodeRange3 = 0; | ||||
| @ -696,6 +705,21 @@ var Font = (function Font() { | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     var unitsPerEm = override.unitsPerEm || kPDFGlyphSpaceUnits; | ||||
|     var typoAscent = override.ascent || properties.ascent; | ||||
|     var typoDescent = override.descent || properties.descent; | ||||
|     var winAscent = override.yMax || typoAscent; | ||||
|     var winDescent = -override.yMin || -typoDescent; | ||||
| 
 | ||||
|     // if there is a units per em value but no other override then scale the calculated ascent
 | ||||
|     if (unitsPerEm != kPDFGlyphSpaceUnits && 'undefined' == typeof(override.ascent)) { | ||||
|       // if the font units differ to the PDF glyph space units then scale up the values
 | ||||
|       typoAscent = Math.round(typoAscent * unitsPerEm / kPDFGlyphSpaceUnits); | ||||
|       typoDescent = Math.round(typoDescent * unitsPerEm / kPDFGlyphSpaceUnits); | ||||
|       winAscent = typoAscent; | ||||
|       winDescent = -typoDescent; | ||||
|     } | ||||
| 
 | ||||
|     return '\x00\x03' + // version
 | ||||
|            '\x02\x24' + // xAvgCharWidth
 | ||||
|            '\x01\xF4' + // usWeightClass
 | ||||
| @ -724,11 +748,11 @@ var Font = (function Font() { | ||||
|            string16(firstCharIndex || | ||||
|                     properties.firstChar) + // usFirstCharIndex
 | ||||
|            string16(lastCharIndex || properties.lastChar) +  // usLastCharIndex
 | ||||
|            string16(properties.ascent) + // sTypoAscender
 | ||||
|            string16(properties.descent) + // sTypoDescender
 | ||||
|            string16(typoAscent) + // sTypoAscender
 | ||||
|            string16(typoDescent) + // sTypoDescender
 | ||||
|            '\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value)
 | ||||
|            string16(properties.ascent) + // usWinAscent
 | ||||
|            string16(-properties.descent) + // usWinDescent
 | ||||
|            string16(winAscent) + // usWinAscent
 | ||||
|            string16(winDescent) + // usWinDescent
 | ||||
|            '\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31)
 | ||||
|            '\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63)
 | ||||
|            string16(properties.xHeight) + // sxHeight
 | ||||
| @ -835,9 +859,11 @@ var Font = (function Font() { | ||||
|         var data = file.getBytes(length); | ||||
|         file.pos = previousPosition; | ||||
| 
 | ||||
|         if (tag == 'head') | ||||
|         if (tag == 'head') { | ||||
|           // clearing checksum adjustment
 | ||||
|           data[8] = data[9] = data[10] = data[11] = 0; | ||||
|           data[17] |= 0x20; //Set font optimized for cleartype flag
 | ||||
|         } | ||||
| 
 | ||||
|         return { | ||||
|           tag: tag, | ||||
| @ -1010,7 +1036,7 @@ var Font = (function Font() { | ||||
|       var header = readOpenTypeHeader(font); | ||||
|       var numTables = header.numTables; | ||||
| 
 | ||||
|       var cmap, maxp, hhea, hmtx, vhea, vmtx; | ||||
|       var cmap, maxp, hhea, hmtx, vhea, vmtx, head; | ||||
|       var tables = []; | ||||
|       for (var i = 0; i < numTables; i++) { | ||||
|         var table = readTableEntry(font); | ||||
| @ -1024,6 +1050,8 @@ var Font = (function Font() { | ||||
|             hhea = table; | ||||
|           else if (table.tag == 'hmtx') | ||||
|             hmtx = table; | ||||
|           else if (table.tag == 'head') | ||||
|             head = table; | ||||
| 
 | ||||
|           requiredTables.splice(index, 1); | ||||
|         } else { | ||||
| @ -1050,9 +1078,18 @@ var Font = (function Font() { | ||||
|       createOpenTypeHeader(header.version, ttf, numTables); | ||||
| 
 | ||||
|       if (requiredTables.indexOf('OS/2') != -1) { | ||||
|         //extract some more font properties from the OpenType head and hhea tables
 | ||||
|         var override = { | ||||
|           unitsPerEm: int16([head.data[18], head.data[19]]), | ||||
|           yMax: int16([head.data[42], head.data[43]]), | ||||
|           yMin: int16([head.data[38], head.data[39]]) - 0x10000, //always negative
 | ||||
|           ascent: int16([hhea.data[4], hhea.data[5]]), | ||||
|           descent: int16([hhea.data[6], hhea.data[7]]) - 0x10000 //always negative
 | ||||
|         } | ||||
| 
 | ||||
|         tables.push({ | ||||
|           tag: 'OS/2', | ||||
|           data: stringToArray(createOS2Table(properties)) | ||||
|           data: stringToArray(createOS2Table(properties, override)) | ||||
|         }); | ||||
|       } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										15
									
								
								pdf.js
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								pdf.js
									
									
									
									
									
								
							| @ -3224,7 +3224,14 @@ var XRef = (function() { | ||||
|           error('bad XRef entry'); | ||||
|         } | ||||
|         if (this.encrypt && !suppressEncryption) { | ||||
|           e = parser.getObj(this.encrypt.createCipherTransform(num, gen)); | ||||
|           try { | ||||
|             e = parser.getObj(this.encrypt.createCipherTransform(num, gen)); | ||||
|           } catch(ex) { | ||||
|             // almost all streams must to encrypted, but sometimes
 | ||||
|             // they are not probably due to some broken generators
 | ||||
|             // re-trying without encryption
 | ||||
|             return this.fetch(ref, true); | ||||
|           } | ||||
|         } else { | ||||
|           e = parser.getObj(); | ||||
|         } | ||||
| @ -4381,7 +4388,7 @@ var PartialEvaluator = (function() { | ||||
|       if (type == 'TrueType' && dict.has('ToUnicode') && differences) { | ||||
|         var cmapObj = dict.get('ToUnicode'); | ||||
|         if (IsRef(cmapObj)) { | ||||
|           cmapObj = xref.fetch(cmapObj, true); | ||||
|           cmapObj = xref.fetch(cmapObj); | ||||
|         } | ||||
|         if (IsName(cmapObj)) { | ||||
|           error('ToUnicode file cmap translation not implemented'); | ||||
| @ -6056,8 +6063,8 @@ var PDFImage = (function() { | ||||
| 
 | ||||
|     this.decode = dict.get('Decode', 'D'); | ||||
| 
 | ||||
|     var mask = xref.fetchIfRef(image.dict.get('Mask')); | ||||
|     var smask = xref.fetchIfRef(image.dict.get('SMask')); | ||||
|     var mask = xref.fetchIfRef(dict.get('Mask')); | ||||
|     var smask = xref.fetchIfRef(dict.get('SMask')); | ||||
| 
 | ||||
|     if (mask) { | ||||
|       TODO('masked images'); | ||||
|  | ||||
| @ -8,6 +8,7 @@ | ||||
| 'use strict'; | ||||
| 
 | ||||
| var appPath, browser, canvas, currentTaskIdx, manifest, stdout; | ||||
| var inFlightRequests = 0; | ||||
| 
 | ||||
| function queryParams() { | ||||
|   var qs = window.location.search.substring(1); | ||||
| @ -42,7 +43,8 @@ function load() { | ||||
|     if (r.readyState == 4) { | ||||
|       log('done\n'); | ||||
|       manifest = JSON.parse(r.responseText); | ||||
|       currentTaskIdx = 0, nextTask(); | ||||
|       currentTaskIdx = 0; | ||||
|       nextTask(); | ||||
|     } | ||||
|   }; | ||||
|   r.send(null); | ||||
| @ -73,7 +75,8 @@ function nextTask() { | ||||
|         failure = 'load PDF doc : ' + e.toString(); | ||||
|       } | ||||
| 
 | ||||
|       task.pageNum = 1, nextPage(task, failure); | ||||
|       task.pageNum = 1; | ||||
|       nextPage(task, failure); | ||||
|     } | ||||
|   }; | ||||
|   r.send(null); | ||||
| @ -89,7 +92,8 @@ function nextPage(task, loadError) { | ||||
|   if (!task.pdfDoc) { | ||||
|     sendTaskResult(canvas.toDataURL('image/png'), task, failure); | ||||
|     log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); | ||||
|     ++currentTaskIdx, nextTask(); | ||||
|     ++currentTaskIdx; | ||||
|     nextTask(); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
| @ -98,7 +102,8 @@ function nextPage(task, loadError) { | ||||
|       log(' Round ' + (1 + task.round) + '\n'); | ||||
|       task.pageNum = 1; | ||||
|     } else { | ||||
|       ++currentTaskIdx, nextTask(); | ||||
|       ++currentTaskIdx; | ||||
|       nextTask(); | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
| @ -123,7 +128,7 @@ function nextPage(task, loadError) { | ||||
|       page.startRendering( | ||||
|         ctx, | ||||
|         function(e) { | ||||
|           snapshotCurrentPage(page, task, (!failure && e) ? | ||||
|           snapshotCurrentPage(task, (!failure && e) ? | ||||
|             ('render : ' + e) : failure); | ||||
|         } | ||||
|       ); | ||||
| @ -135,11 +140,11 @@ function nextPage(task, loadError) { | ||||
|   if (failure) { | ||||
|     // Skip right to snapshotting if there was a failure, since the
 | ||||
|     // fonts might be in an inconsistent state.
 | ||||
|     snapshotCurrentPage(page, task, failure); | ||||
|     snapshotCurrentPage(task, failure); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function snapshotCurrentPage(page, task, failure) { | ||||
| function snapshotCurrentPage(task, failure) { | ||||
|   log('done, snapshotting... '); | ||||
| 
 | ||||
|   sendTaskResult(canvas.toDataURL('image/png'), task, failure); | ||||
| @ -149,7 +154,8 @@ function snapshotCurrentPage(page, task, failure) { | ||||
|   var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; | ||||
|   setTimeout( | ||||
|     function() { | ||||
|       ++task.pageNum, nextPage(task); | ||||
|       ++task.pageNum; | ||||
|       nextPage(task); | ||||
|     }, | ||||
|     backoff | ||||
|   ); | ||||
| @ -182,7 +188,6 @@ function done() { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| var inFlightRequests = 0; | ||||
| function sendTaskResult(snapshot, task, failure) { | ||||
|   var result = { browser: browser, | ||||
|                  id: task.id, | ||||
| @ -201,7 +206,7 @@ function sendTaskResult(snapshot, task, failure) { | ||||
|     if (r.readyState == 4) { | ||||
|       inFlightRequests--; | ||||
|     } | ||||
|   } | ||||
|   }; | ||||
|   document.getElementById('inFlightCount').innerHTML = inFlightRequests++; | ||||
|   r.send(JSON.stringify(result)); | ||||
| } | ||||
|  | ||||
							
								
								
									
										12
									
								
								test/pdfs/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								test/pdfs/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +1,13 @@ | ||||
| pdf.pdf | ||||
| DiwanProfile.pdf | ||||
| artofwar.pdf | ||||
| cable.pdf | ||||
| ecma262.pdf | ||||
| hmm.pdf | ||||
| i9.pdf | ||||
| intelisa.pdf | ||||
| openweb_tm-PRINT.pdf | ||||
| pdf.pdf | ||||
| pdkids.pdf | ||||
| shavian.pdf | ||||
| jai.pdf | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										1
									
								
								test/pdfs/wdsg_fitc.pdf.link
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/pdfs/wdsg_fitc.pdf.link
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| http://www.airgid.com/book/wdsg_fitc.pdf | ||||
							
								
								
									
										2
									
								
								test/resources/browser_manifests/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								test/resources/browser_manifests/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| browser_manifest.json | ||||
| 
 | ||||
| @ -116,6 +116,12 @@ | ||||
|        "rounds": 1, | ||||
|        "type": "eq" | ||||
|     }, | ||||
|     {  "id": "wdsg_fitc", | ||||
|        "file": "pdfs/wdsg_fitc.pdf", | ||||
|        "link": true, | ||||
|        "rounds": 1, | ||||
|        "type": "eq" | ||||
|     }, | ||||
|     {  "id": "fips197", | ||||
|        "file": "pdfs/fips197.pdf", | ||||
|        "link": true, | ||||
|  | ||||
| @ -560,7 +560,7 @@ var CFFDictDataMap = { | ||||
|     '18': { | ||||
|       name: 'ExpansionFactor' | ||||
|     }, | ||||
|     '9': { | ||||
|     '19': { | ||||
|       name: 'initialRandomSeed' | ||||
|     }, | ||||
|     '20': { | ||||
|  | ||||
| @ -69,7 +69,7 @@ function readCharstringEncoding(aString) { | ||||
|     } else if (value <= 31) { | ||||
|       token = CFFEncodingMap[value]; | ||||
|     } else if (value < 247) { | ||||
|       token = parseInt(value) - 139; | ||||
|       token = parseInt(value, 10) - 139; | ||||
|     } else if (value < 251) { | ||||
|       token = ((value - 247) * 256) + aString[i++] + 108; | ||||
|     } else if (value < 255) { | ||||
| @ -113,7 +113,7 @@ function readFontDictData(aString, aMap) { | ||||
|       while (!parsed) { | ||||
|         var byte = aString[i++]; | ||||
| 
 | ||||
|         var nibbles = [parseInt(byte / 16), parseInt(byte % 16)]; | ||||
|         var nibbles = [parseInt(byte / 16, 10), parseInt(byte % 16, 10)]; | ||||
|         for (var j = 0; j < nibbles.length; j++) { | ||||
|           var nibble = nibbles[j]; | ||||
|           switch (nibble) { | ||||
| @ -144,7 +144,7 @@ function readFontDictData(aString, aMap) { | ||||
|     } else if (value <= 31) { | ||||
|       token = aMap[value]; | ||||
|     } else if (value <= 246) { | ||||
|       token = parseInt(value) - 139; | ||||
|       token = parseInt(value, 10) - 139; | ||||
|     } else if (value <= 250) { | ||||
|       token = ((value - 247) * 256) + aString[i++] + 108; | ||||
|     } else if (value <= 254) { | ||||
| @ -193,7 +193,7 @@ function readFontIndexData(aStream, aIsByte) { | ||||
|     } | ||||
|     error(offsize + ' is not a valid offset size'); | ||||
|     return null; | ||||
|   }; | ||||
|   } | ||||
| 
 | ||||
|   var offsets = []; | ||||
|   for (var i = 0; i < count + 1; i++) | ||||
| @ -236,7 +236,7 @@ var Type2Parser = function(aFilePath) { | ||||
|   function dump(aStr) { | ||||
|     if (debug) | ||||
|       log(aStr); | ||||
|   }; | ||||
|   } | ||||
| 
 | ||||
|   function parseAsToken(aString, aMap) { | ||||
|     var decoded = readFontDictData(aString, aMap); | ||||
| @ -277,7 +277,7 @@ var Type2Parser = function(aFilePath) { | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|   } | ||||
| 
 | ||||
|   this.parse = function(aStream) { | ||||
|     font.set('major', aStream.getByte()); | ||||
| @ -353,7 +353,7 @@ var Type2Parser = function(aFilePath) { | ||||
|       aStream.pos = charsetEntry; | ||||
|       var charset = readCharset(aStream, charStrings); | ||||
|     } | ||||
|   } | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| /* | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | ||||
| /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ | ||||
| 
 | ||||
| 'use strict'; | ||||
| 
 | ||||
| // Checking if the typed arrays are supported
 | ||||
| (function() { | ||||
|   if (typeof Uint8Array !== 'undefined') | ||||
| @ -10,8 +12,9 @@ | ||||
|     return this.slice(start, end); | ||||
|   } | ||||
| 
 | ||||
|   function set_(array, offset) { | ||||
|     if (arguments.length < 2) offset = 0; | ||||
|   function set_function(array, offset) { | ||||
|     if (arguments.length < 2) | ||||
|       offset = 0; | ||||
|     for (var i = 0, n = array.length; i < n; ++i, ++offset) | ||||
|       this[offset] = array[i] & 0xFF; | ||||
|   } | ||||
| @ -19,15 +22,17 @@ | ||||
|   function TypedArray(arg1) { | ||||
|     var result; | ||||
|     if (typeof arg1 === 'number') { | ||||
|        result = new Array(arg1); | ||||
|        for (var i = 0; i < arg1; ++i) | ||||
|          result[i] = 0; | ||||
|       result = []; | ||||
|       for (var i = 0; i < arg1; ++i) | ||||
|         result[i] = 0; | ||||
|     } else | ||||
|        result = arg1.slice(0); | ||||
|       result = arg1.slice(0); | ||||
| 
 | ||||
|     result.subarray = subarray; | ||||
|     result.buffer = result; | ||||
|     result.byteLength = result.length; | ||||
|     result.set = set_; | ||||
|     result.set = set_function; | ||||
| 
 | ||||
|     if (typeof arg1 === 'object' && arg1.buffer) | ||||
|       result.buffer = arg1.buffer; | ||||
| 
 | ||||
|  | ||||
| @ -98,7 +98,7 @@ var PDFView = { | ||||
|   }, | ||||
| 
 | ||||
|   get page() { | ||||
|     return parseInt(document.location.hash.substring(1)) || 1; | ||||
|     return parseInt(document.location.hash.substring(1), 10) || 1; | ||||
|   }, | ||||
| 
 | ||||
|   open: function(url, scale) { | ||||
| @ -170,7 +170,7 @@ var PDFView = { | ||||
|     } | ||||
| 
 | ||||
|     this.setScale(scale || kDefaultScale, true); | ||||
|     this.page = parseInt(document.location.hash.substring(1)) || 1; | ||||
|     this.page = parseInt(document.location.hash.substring(1), 10) || 1; | ||||
|     this.pagesRefMap = pagesRefMap; | ||||
|     this.destinations = pdf.catalog.destinations; | ||||
|     if (pdf.catalog.documentOutline) { | ||||
| @ -209,7 +209,7 @@ var PDFView = { | ||||
| 
 | ||||
|     var currentHeight = kBottomMargin; | ||||
|     var windowTop = window.pageYOffset; | ||||
|     for (var i = 1; i <= pages.length; i++) { | ||||
|     for (var i = 1; i <= pages.length; ++i) { | ||||
|       var page = pages[i - 1]; | ||||
|       var pageHeight = page.height * page.scale + kBottomMargin; | ||||
|       if (currentHeight + pageHeight > windowTop) | ||||
| @ -219,10 +219,11 @@ var PDFView = { | ||||
|     } | ||||
| 
 | ||||
|     var windowBottom = window.pageYOffset + window.innerHeight; | ||||
|     for (; i <= pages.length && currentHeight < windowBottom; i++) { | ||||
|       var page = pages[i - 1]; | ||||
|       visiblePages.push({ id: page.id, y: currentHeight, view: page }); | ||||
|       currentHeight += page.height * page.scale + kBottomMargin; | ||||
|     for (; i <= pages.length && currentHeight < windowBottom; ++i) { | ||||
|       var singlePage = pages[i - 1]; | ||||
|       visiblePages.push({ id: singlePage.id, y: currentHeight, | ||||
|                           view: singlePage }); | ||||
|       currentHeight += singlePage.height * singlePage.scale + kBottomMargin; | ||||
|     } | ||||
| 
 | ||||
|     return visiblePages; | ||||
| @ -256,13 +257,13 @@ var PageView = function(container, content, id, width, height, | ||||
|     div.removeAttribute('data-loaded'); | ||||
|   }; | ||||
| 
 | ||||
|   function setupLinks(canvas, content, scale) { | ||||
|   function setupLinks(content, scale) { | ||||
|     function bindLink(link, dest) { | ||||
|       link.onclick = function() { | ||||
|         if (dest) | ||||
|           PDFView.navigateTo(dest); | ||||
|         return false; | ||||
|       } | ||||
|       }; | ||||
|     } | ||||
|     var links = content.getLinks(); | ||||
|     for (var i = 0; i < links.length; i++) { | ||||
| @ -283,8 +284,6 @@ var PageView = function(container, content, id, width, height, | ||||
|       var width = 0, height = 0, widthScale, heightScale; | ||||
|       var scale = 0; | ||||
|       switch (dest[1].name) { | ||||
|         default: | ||||
|           return; | ||||
|         case 'XYZ': | ||||
|           x = dest[2]; | ||||
|           y = dest[3]; | ||||
| @ -315,6 +314,8 @@ var PageView = function(container, content, id, width, height, | ||||
|             height / kCssUnits; | ||||
|           scale = Math.min(widthScale, heightScale); | ||||
|           break; | ||||
|         default: | ||||
|           return; | ||||
|       } | ||||
| 
 | ||||
|       var boundingRect = [ | ||||
| @ -369,7 +370,7 @@ var PageView = function(container, content, id, width, height, | ||||
|     stats.begin = Date.now(); | ||||
|     this.content.startRendering(ctx, this.updateStats); | ||||
| 
 | ||||
|     setupLinks(canvas, this.content, this.scale); | ||||
|     setupLinks(this.content, this.scale); | ||||
|     div.setAttribute('data-loaded', true); | ||||
| 
 | ||||
|     return true; | ||||
|  | ||||
| @ -39,7 +39,7 @@ function GradientProxy(cmdQueue, x0, y0, x1, y1) { | ||||
|   cmdQueue.push(['$createLinearGradient', [x0, y0, x1, y1]]); | ||||
|   this.addColorStop = function(i, rgba) { | ||||
|     cmdQueue.push(['$addColorStop', [i, rgba]]); | ||||
|   } | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| // Really simple PatternProxy.
 | ||||
| @ -72,7 +72,7 @@ function CanvasProxy(width, height) { | ||||
|       throw 'CanvasProxy can only provide a 2d context.'; | ||||
|     } | ||||
|     return ctx; | ||||
|   } | ||||
|   }; | ||||
| 
 | ||||
|   // Expose only the minimum of the canvas object - there is no dom to do
 | ||||
|   // more here.
 | ||||
| @ -127,7 +127,7 @@ function CanvasProxy(width, height) { | ||||
|     return function() { | ||||
|       // console.log("funcCall", name)
 | ||||
|       cmdQueue.push([name, Array.prototype.slice.call(arguments)]); | ||||
|     } | ||||
|     }; | ||||
|   } | ||||
|   var name; | ||||
|   for (var i = 0; i < ctxFunc.length; i++) { | ||||
| @ -139,11 +139,11 @@ function CanvasProxy(width, height) { | ||||
| 
 | ||||
|   ctx.createPattern = function(object, kind) { | ||||
|     return new PatternProxy(cmdQueue, object, kind); | ||||
|   } | ||||
|   }; | ||||
| 
 | ||||
|   ctx.createLinearGradient = function(x0, y0, x1, y1) { | ||||
|     return new GradientProxy(cmdQueue, x0, y0, x1, y1); | ||||
|   } | ||||
|   }; | ||||
| 
 | ||||
|   ctx.getImageData = function(x, y, w, h) { | ||||
|     return { | ||||
| @ -151,11 +151,11 @@ function CanvasProxy(width, height) { | ||||
|       height: h, | ||||
|       data: Uint8ClampedArray(w * h * 4) | ||||
|     }; | ||||
|   } | ||||
|   }; | ||||
| 
 | ||||
|   ctx.putImageData = function(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) { | ||||
| @ -168,7 +168,7 @@ function CanvasProxy(width, height) { | ||||
|     } else { | ||||
|       throw 'unkown type to drawImage'; | ||||
|     } | ||||
|   } | ||||
|   }; | ||||
| 
 | ||||
|   // Setup property access to `ctx`.
 | ||||
|   var ctxProp = { | ||||
| @ -195,14 +195,14 @@ function CanvasProxy(width, height) { | ||||
|   function buildGetter(name) { | ||||
|     return function() { | ||||
|       return ctx['$' + name]; | ||||
|     } | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   function buildSetter(name) { | ||||
|     return function(value) { | ||||
|       cmdQueue.push(['$', name, value]); | ||||
|       return ctx['$' + name] = value; | ||||
|     } | ||||
|       return (ctx['$' + name] = value); | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   // Setting the value to `stroke|fillStyle` needs special handling, as it
 | ||||
| @ -215,9 +215,9 @@ function CanvasProxy(width, height) { | ||||
|         cmdQueue.push(['$' + name + 'Pattern', [value.id]]); | ||||
|       } else { | ||||
|         cmdQueue.push(['$', name, value]); | ||||
|         return ctx['$' + name] = value; | ||||
|         return (ctx['$' + name] = value); | ||||
|       } | ||||
|     } | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   for (var name in ctxProp) { | ||||
|  | ||||
| @ -58,7 +58,7 @@ FontWorker.prototype = { | ||||
| 
 | ||||
|     'fonts': function(data) { | ||||
|       // console.log("got processed fonts from worker", Object.keys(data));
 | ||||
|       for (name in data) { | ||||
|       for (var name in data) { | ||||
|         // Update the encoding property.
 | ||||
|         var font = Fonts.lookup(name); | ||||
|         font.properties = { | ||||
| @ -176,7 +176,7 @@ 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); | ||||
|     }, | ||||
| @ -273,7 +273,7 @@ function WorkerPDFDoc(canvas) { | ||||
|     }, | ||||
| 
 | ||||
|     'pdf_num_pages': function(data) { | ||||
|       this.numPages = parseInt(data); | ||||
|       this.numPages = parseInt(data, 10); | ||||
|       if (this.loadCallback) { | ||||
|         this.loadCallback(); | ||||
|       } | ||||
| @ -302,8 +302,8 @@ function WorkerPDFDoc(canvas) { | ||||
|     '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]); | ||||
|       canvas.width = parseInt(size[0], 10); | ||||
|       canvas.height = parseInt(size[1], 10); | ||||
|     }, | ||||
| 
 | ||||
|     'fonts': function(data) { | ||||
| @ -397,7 +397,7 @@ WorkerPDFDoc.prototype.open = function(url, callback) { | ||||
| }; | ||||
| 
 | ||||
| WorkerPDFDoc.prototype.showPage = function(numPage) { | ||||
|   this.numPage = parseInt(numPage); | ||||
|   this.numPage = parseInt(numPage, 10); | ||||
|   console.log('=== start rendering page ' + numPage + ' ==='); | ||||
|   console.time('>>> total page display time:'); | ||||
|   this.worker.postMessage(numPage); | ||||
| @ -407,11 +407,12 @@ WorkerPDFDoc.prototype.showPage = function(numPage) { | ||||
| }; | ||||
| 
 | ||||
| WorkerPDFDoc.prototype.nextPage = function() { | ||||
|   if (this.numPage == this.numPages) return; | ||||
|   this.showPage(++this.numPage); | ||||
|   if (this.numPage != this.numPages) | ||||
|     this.showPage(++this.numPage); | ||||
| }; | ||||
| 
 | ||||
| WorkerPDFDoc.prototype.prevPage = function() { | ||||
|   if (this.numPage == 1) return; | ||||
|   this.showPage(--this.numPage); | ||||
|   if (this.numPage != 1) | ||||
|     this.showPage(--this.numPage); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -25,3 +25,4 @@ var console = { | ||||
|     this.log('Timer:', name, Date.now() - time); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -64,3 +64,4 @@ this.onmessage = function(event) { | ||||
|     throw 'Unkown action from worker: ' + data.action; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -58,7 +58,7 @@ onmessage = function(event) { | ||||
|     console.time('compile'); | ||||
| 
 | ||||
|     // Let's try to render the first page...
 | ||||
|     var page = pdfDocument.getPage(parseInt(data)); | ||||
|     var page = pdfDocument.getPage(parseInt(data, 10)); | ||||
| 
 | ||||
|     var pdfToCssUnitsCoef = 96.0 / 72.0; | ||||
|     var pageWidth = (page.mediaBox[2] - page.mediaBox[0]) * pdfToCssUnitsCoef; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user