Merge worker_pull with master
This commit is contained in:
commit
3054102d3b
1
LICENSE
1
LICENSE
@ -8,6 +8,7 @@
|
|||||||
Justin D'Arcangelo <justindarc@gmail.com>
|
Justin D'Arcangelo <justindarc@gmail.com>
|
||||||
Yury Delendik
|
Yury Delendik
|
||||||
Kalervo Kujala
|
Kalervo Kujala
|
||||||
|
Adil Allawi <@ironymark>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
81
Makefile
81
Makefile
@ -12,6 +12,8 @@ PDF_JS_FILES = \
|
|||||||
pdf.js \
|
pdf.js \
|
||||||
crypto.js \
|
crypto.js \
|
||||||
fonts.js \
|
fonts.js \
|
||||||
|
metrics.js \
|
||||||
|
charsets.js \
|
||||||
glyphlist.js \
|
glyphlist.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
@ -55,30 +57,30 @@ browser-test:
|
|||||||
--browserManifestFile=$(PDF_BROWSERS) \
|
--browserManifestFile=$(PDF_BROWSERS) \
|
||||||
--manifestFile=$(PDF_TESTS)
|
--manifestFile=$(PDF_TESTS)
|
||||||
|
|
||||||
# make shell-test
|
# # make shell-test
|
||||||
#
|
# #
|
||||||
# This target runs all of the tests that can be run in a JS shell.
|
# # 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
|
# # 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
|
# # 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
|
# # of Rhino that comes with the Closure compiler used for producing the
|
||||||
# website.
|
# # website.
|
||||||
SHELL_TARGET = $(NULL)
|
# SHELL_TARGET = $(NULL)
|
||||||
ifeq ($(JS_SHELL),)
|
# ifeq ($(JS_SHELL),)
|
||||||
JS_SHELL := "java -cp $(BUILD_DIR)/compiler.jar"
|
# JS_SHELL := "java -cp $(BUILD_DIR)/compiler.jar"
|
||||||
JS_SHELL += "com.google.javascript.jscomp.mozilla.rhino.tools.shell.Main"
|
# JS_SHELL += "com.google.javascript.jscomp.mozilla.rhino.tools.shell.Main"
|
||||||
SHELL_TARGET = compiler
|
# SHELL_TARGET = compiler
|
||||||
endif
|
# endif
|
||||||
|
#
|
||||||
shell-test: shell-msg $(SHELL_TARGET) font-test
|
# shell-test: shell-msg $(SHELL_TARGET) font-test
|
||||||
shell-msg:
|
# shell-msg:
|
||||||
ifeq ($(SHELL_TARGET), compiler)
|
# ifeq ($(SHELL_TARGET), compiler)
|
||||||
@echo "No JS_SHELL env variable present."
|
# @echo "No JS_SHELL env variable present."
|
||||||
@echo "The default is to find a copy of Rhino and try that."
|
# @echo "The default is to find a copy of Rhino and try that."
|
||||||
endif
|
# endif
|
||||||
@echo "JS shell command is: $(JS_SHELL)"
|
# @echo "JS shell command is: $(JS_SHELL)"
|
||||||
|
#
|
||||||
font-test:
|
# font-test:
|
||||||
@echo "font test stub."
|
# @echo "font test stub."
|
||||||
|
|
||||||
# make lint
|
# make lint
|
||||||
#
|
#
|
||||||
@ -86,7 +88,8 @@ font-test:
|
|||||||
# To install gjslint, see:
|
# To install gjslint, see:
|
||||||
#
|
#
|
||||||
# <http://code.google.com/closure/utilities/docs/linter_howto.html>
|
# <http://code.google.com/closure/utilities/docs/linter_howto.html>
|
||||||
SRC_DIRS := . utils worker web test
|
SRC_DIRS := . utils worker web test examples/helloworld extensions/firefox \
|
||||||
|
extensions/firefox/components
|
||||||
GJSLINT_FILES = $(foreach DIR,$(SRC_DIRS),$(wildcard $(DIR)/*.js))
|
GJSLINT_FILES = $(foreach DIR,$(SRC_DIRS),$(wildcard $(DIR)/*.js))
|
||||||
lint:
|
lint:
|
||||||
gjslint $(GJSLINT_FILES)
|
gjslint $(GJSLINT_FILES)
|
||||||
@ -133,18 +136,18 @@ $(GH_PAGES)/web/%: web/%
|
|||||||
$(GH_PAGES)/web/images/%: web/images/%
|
$(GH_PAGES)/web/images/%: web/images/%
|
||||||
@cp $< $@
|
@cp $< $@
|
||||||
|
|
||||||
# make compiler
|
# # make compiler
|
||||||
#
|
# #
|
||||||
# This target downloads the Closure compiler, and places it in the
|
# # This target downloads the Closure compiler, and places it in the
|
||||||
# build directory. This target is also useful when the user doesn't
|
# # 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
|
# # have a JS shell available--we can have them use the Rhino shell that
|
||||||
# comes with Closure.
|
# # comes with Closure.
|
||||||
COMPILER_URL = http://closure-compiler.googlecode.com/files/compiler-latest.zip
|
# COMPILER_URL = http://closure-compiler.googlecode.com/files/compiler-latest.zip
|
||||||
|
#
|
||||||
compiler: $(BUILD_DIR)/compiler.zip
|
# compiler: $(BUILD_DIR)/compiler.zip
|
||||||
$(BUILD_DIR)/compiler.zip: | $(BUILD_DIR)
|
# $(BUILD_DIR)/compiler.zip: | $(BUILD_DIR)
|
||||||
curl $(COMPILER_URL) > $(BUILD_DIR)/compiler.zip;
|
# curl $(COMPILER_URL) > $(BUILD_DIR)/compiler.zip;
|
||||||
cd $(BUILD_DIR); unzip compiler.zip compiler.jar;
|
# cd $(BUILD_DIR); unzip compiler.zip compiler.jar;
|
||||||
|
|
||||||
# make firefox-extension
|
# make firefox-extension
|
||||||
#
|
#
|
||||||
@ -163,9 +166,9 @@ PDF_WEB_FILES = \
|
|||||||
extension:
|
extension:
|
||||||
# Copy a standalone version of pdf.js inside the content directory
|
# Copy a standalone version of pdf.js inside the content directory
|
||||||
@rm -Rf $(EXTENSION_SRC)/$(CONTENT_DIR)/
|
@rm -Rf $(EXTENSION_SRC)/$(CONTENT_DIR)/
|
||||||
@mkdir $(EXTENSION_SRC)/$(CONTENT_DIR)/
|
@mkdir -p $(EXTENSION_SRC)/$(CONTENT_DIR)/web
|
||||||
@cp $(PDF_JS_FILES) $(EXTENSION_SRC)/$(CONTENT_DIR)/
|
@cp $(PDF_JS_FILES) $(EXTENSION_SRC)/$(CONTENT_DIR)/
|
||||||
@cp -r $(PDF_WEB_FILES) $(EXTENSION_SRC)/$(CONTENT_DIR)/
|
@cp -r $(PDF_WEB_FILES) $(EXTENSION_SRC)/$(CONTENT_DIR)/web/
|
||||||
|
|
||||||
# Create the xpi
|
# Create the xpi
|
||||||
@cd $(EXTENSION_SRC); zip -r $(EXTENSION_NAME) *
|
@cd $(EXTENSION_SRC); zip -r $(EXTENSION_NAME) *
|
||||||
|
177
README.md
177
README.md
@ -1,32 +1,177 @@
|
|||||||
# pdf.js
|
# 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
|
## Overview
|
||||||
pdf.js is production ready. Until then we aim to publish a Firefox
|
|
||||||
PDF reader extension powered by pdf.js.
|
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.
|
||||||
|
|
||||||
|
### Getting the code
|
||||||
|
|
||||||
|
To get a local copy of the current code, clone it using git:
|
||||||
|
|
||||||
|
$ git clone git://github.com/andreasgal/pdf.js.git pdfjs
|
||||||
|
$ cd pdfjs
|
||||||
|
|
||||||
|
Next, you need to start a local web server as some browsers don't allow opening
|
||||||
|
PDF files for a file:// url:
|
||||||
|
|
||||||
|
$ make server
|
||||||
|
|
||||||
|
If everything worked out, you can now serve
|
||||||
|
|
||||||
|
+ http://localhost:8888/web/viewer.html
|
||||||
|
|
||||||
|
You can also view all the test pdf files on the right side serving
|
||||||
|
|
||||||
|
+ http://localhost:8888/test/pdfs/?frame
|
||||||
|
|
||||||
|
### Learning
|
||||||
|
|
||||||
|
Here are some initial pointers to help contributors get off the ground.
|
||||||
|
Additional resources are available in a separate section below.
|
||||||
|
|
||||||
|
#### Introductory video
|
||||||
|
|
||||||
|
Check out the presentation by our contributor Julian Viereck on the inner
|
||||||
|
workings of PDF and pdf.js:
|
||||||
|
|
||||||
|
+ http://www.youtube.com/watch?v=Iv15UY-4Fg8
|
||||||
|
|
||||||
|
#### Hello world
|
||||||
|
|
||||||
|
For a "hello world" example, take a look at:
|
||||||
|
|
||||||
|
+ [examples/helloworld/hello.js](https://github.com/andreasgal/pdf.js/blob/master/examples/helloworld/hello.js)
|
||||||
|
|
||||||
|
This example illustrates the bare minimum ingredients for integrating pdf.js
|
||||||
|
in a custom project.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
pdf.js is a community-driven project, so contributors are always welcome.
|
||||||
|
Simply fork our repo and contribute away. A great place to start is our
|
||||||
|
[open issues](https://github.com/andreasgal/pdf.js/issues). For better consistency and
|
||||||
|
long-term stability, please do look around the code and try to follow our conventions.
|
||||||
|
More information about the contributor process can be found on the
|
||||||
|
[contributor wiki page](https://github.com/andreasgal/pdf.js/wiki/Contributing).
|
||||||
|
|
||||||
|
If you don't want to hack on the project or have little spare time, __you still
|
||||||
|
can help!__ Just open PDFs in the
|
||||||
|
[online demo](http://andreasgal.github.com/pdf.js/web/viewer.html) and report
|
||||||
|
any breakage in rendering.
|
||||||
|
|
||||||
|
Our Github contributors so far:
|
||||||
|
|
||||||
|
+ https://github.com/andreasgal/pdf.js/contributors
|
||||||
|
|
||||||
|
You can add your name to it! :)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
|
||||||
|
## Running tests through our bot
|
||||||
|
|
||||||
|
If you are a reviewer, you can use our remote bot to issue comprehensive tests
|
||||||
|
against reference images before merging pull requests.
|
||||||
|
|
||||||
|
See the bot repo for details:
|
||||||
|
|
||||||
|
+ https://github.com/arturadib/pdf.js-bot
|
||||||
|
|
||||||
|
|
||||||
|
## Additional resources
|
||||||
|
|
||||||
Our demo site is here:
|
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:
|
You can read more about pdf.js here:
|
||||||
|
|
||||||
http://andreasgal.com/2011/06/15/pdf-js/
|
+ http://andreasgal.com/2011/06/15/pdf-js/
|
||||||
|
+ http://blog.mozilla.com/cjones/2011/06/15/overview-of-pdf-js-guts/
|
||||||
|
|
||||||
http://blog.mozilla.com/cjones/2011/06/15/overview-of-pdf-js-guts/
|
Talk to us on IRC:
|
||||||
|
|
||||||
follow us on twitter: @pdfjs
|
+ #pdfjs on irc.mozilla.org
|
||||||
|
|
||||||
http://twitter.com/#!/pdfjs
|
Join our mailing list:
|
||||||
|
|
||||||
join our mailing list:
|
+ dev-pdf-js@lists.mozilla.org
|
||||||
|
|
||||||
dev-pdf-js@lists.mozilla.org
|
Subscribe either using lists.mozilla.org or Google Groups:
|
||||||
|
|
||||||
|
+ https://lists.mozilla.org/listinfo/dev-pdf-js
|
||||||
|
+ https://groups.google.com/group/mozilla.dev.pdf-js/topics
|
||||||
|
|
||||||
and talk to us on IRC:
|
Follow us on twitter: @pdfjs
|
||||||
|
|
||||||
#pdfjs on irc.mozilla.org
|
+ http://twitter.com/#!/pdfjs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## PDF-related resources
|
||||||
|
|
||||||
|
A really basic overview of PDF is described here:
|
||||||
|
|
||||||
|
+ http://partners.adobe.com/public/developer/en/livecycle/lc_pdf_overview_format.pdf
|
||||||
|
|
||||||
|
A more detailed file example:
|
||||||
|
|
||||||
|
+ http://gnupdf.org/Introduction_to_PDF
|
||||||
|
|
||||||
|
The PDF specification itself is an ISO and not freely available. However, there is
|
||||||
|
a "PDF Reference" from Adobe:
|
||||||
|
|
||||||
|
+ http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/pdf_reference_1-7.pdf
|
||||||
|
|
||||||
|
Recommended chapters to read: "2. Overview", "3.4 File Structure",
|
||||||
|
"4.1 Graphics Objects" that lists the PDF commands.
|
||||||
|
101
charsets.js
Normal file
101
charsets.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
|
||||||
|
var ISOAdobeCharset = [
|
||||||
|
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
|
||||||
|
'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
|
||||||
|
'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
|
||||||
|
'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
|
||||||
|
'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
|
||||||
|
'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||||
|
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||||
|
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
|
||||||
|
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||||
|
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||||
|
'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
|
||||||
|
'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
|
||||||
|
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
|
||||||
|
'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
|
||||||
|
'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
|
||||||
|
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
|
||||||
|
'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
|
||||||
|
'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
|
||||||
|
'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
|
||||||
|
'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
|
||||||
|
'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
|
||||||
|
'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
|
||||||
|
'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
|
||||||
|
'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
|
||||||
|
'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
|
||||||
|
'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
|
||||||
|
'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
|
||||||
|
'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
|
||||||
|
'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
|
||||||
|
'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
|
||||||
|
'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
|
||||||
|
'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
|
||||||
|
'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
|
||||||
|
'ugrave', 'yacute', 'ydieresis', 'zcaron'
|
||||||
|
];
|
||||||
|
|
||||||
|
var ExpertCharset = [
|
||||||
|
'.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
|
||||||
|
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
|
||||||
|
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
|
||||||
|
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
|
||||||
|
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
|
||||||
|
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
|
||||||
|
'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
|
||||||
|
'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
|
||||||
|
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
||||||
|
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
||||||
|
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
||||||
|
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
|
||||||
|
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
|
||||||
|
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
|
||||||
|
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
|
||||||
|
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
|
||||||
|
'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
|
||||||
|
'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
|
||||||
|
'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
|
||||||
|
'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
|
||||||
|
'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
|
||||||
|
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||||
|
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
||||||
|
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
||||||
|
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
||||||
|
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
||||||
|
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
||||||
|
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
||||||
|
'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
|
||||||
|
'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall',
|
||||||
|
'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
|
||||||
|
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
|
||||||
|
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
|
||||||
|
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
|
||||||
|
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
|
||||||
|
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
|
||||||
|
'Ydieresissmall'
|
||||||
|
];
|
||||||
|
|
||||||
|
var ExpertSubsetCharset = [
|
||||||
|
'.notdef', 'space', 'dollaroldstyle', 'dollarsuperior',
|
||||||
|
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
|
||||||
|
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
|
||||||
|
'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
|
||||||
|
'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
|
||||||
|
'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
|
||||||
|
'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior',
|
||||||
|
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
||||||
|
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
||||||
|
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
||||||
|
'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted',
|
||||||
|
'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter',
|
||||||
|
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||||
|
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
||||||
|
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
||||||
|
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
||||||
|
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
||||||
|
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
||||||
|
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
||||||
|
'periodinferior', 'commainferior'
|
||||||
|
];
|
||||||
|
|
6932
cidmaps.js
Normal file
6932
cidmaps.js
Normal file
File diff suppressed because it is too large
Load Diff
55
crypto.js
55
crypto.js
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ARCFourCipher = (function() {
|
var ARCFourCipher = (function arcFourCipher() {
|
||||||
function constructor(key) {
|
function constructor(key) {
|
||||||
this.a = 0;
|
this.a = 0;
|
||||||
this.b = 0;
|
this.b = 0;
|
||||||
@ -21,7 +21,7 @@ var ARCFourCipher = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
encryptBlock: function(data) {
|
encryptBlock: function arcFourCipherEncryptBlock(data) {
|
||||||
var i, n = data.length, tmp, tmp2;
|
var i, n = data.length, tmp, tmp2;
|
||||||
var a = this.a, b = this.b, s = this.s;
|
var a = this.a, b = this.b, s = this.s;
|
||||||
var output = new Uint8Array(n);
|
var output = new Uint8Array(n);
|
||||||
@ -45,7 +45,7 @@ var ARCFourCipher = (function() {
|
|||||||
return constructor;
|
return constructor;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var md5 = (function() {
|
var calculateMD5 = (function calculateMD5() {
|
||||||
var r = new Uint8Array([
|
var r = new Uint8Array([
|
||||||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||||
@ -129,12 +129,12 @@ var md5 = (function() {
|
|||||||
return hash;
|
return hash;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var NullCipher = (function() {
|
var NullCipher = (function nullCipher() {
|
||||||
function constructor() {
|
function constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
decryptBlock: function(data) {
|
decryptBlock: function nullCipherDecryptBlock(data) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -142,7 +142,7 @@ var NullCipher = (function() {
|
|||||||
return constructor;
|
return constructor;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var AES128Cipher = (function() {
|
var AES128Cipher = (function aes128Cipher() {
|
||||||
var rcon = new Uint8Array([
|
var rcon = new Uint8Array([
|
||||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
|
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
|
||||||
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
|
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
|
||||||
@ -372,7 +372,7 @@ var AES128Cipher = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
decryptBlock: function(data) {
|
decryptBlock: function aes128CipherDecryptBlock(data) {
|
||||||
var i, sourceLength = data.length;
|
var i, sourceLength = data.length;
|
||||||
var buffer = this.buffer, bufferLength = this.bufferPosition;
|
var buffer = this.buffer, bufferLength = this.bufferPosition;
|
||||||
// waiting for IV values -- they are at the start of the stream
|
// waiting for IV values -- they are at the start of the stream
|
||||||
@ -395,19 +395,21 @@ var AES128Cipher = (function() {
|
|||||||
return constructor;
|
return constructor;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var CipherTransform = (function() {
|
var CipherTransform = (function cipherTransform() {
|
||||||
function constructor(stringCipherConstructor, streamCipherConstructor) {
|
function constructor(stringCipherConstructor, streamCipherConstructor) {
|
||||||
this.stringCipherConstructor = stringCipherConstructor;
|
this.stringCipherConstructor = stringCipherConstructor;
|
||||||
this.streamCipherConstructor = streamCipherConstructor;
|
this.streamCipherConstructor = streamCipherConstructor;
|
||||||
}
|
}
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
createStream: function(stream) {
|
createStream: function cipherTransformCreateStream(stream) {
|
||||||
var cipher = new this.streamCipherConstructor();
|
var cipher = new this.streamCipherConstructor();
|
||||||
return new DecryptStream(stream, function(data) {
|
return new DecryptStream(stream,
|
||||||
return cipher.decryptBlock(data);
|
function cipherTransformDecryptStream(data) {
|
||||||
});
|
return cipher.decryptBlock(data);
|
||||||
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
decryptString: function(s) {
|
decryptString: function cipherTransformDecryptString(s) {
|
||||||
var cipher = new this.stringCipherConstructor();
|
var cipher = new this.stringCipherConstructor();
|
||||||
var data = stringToBytes(s);
|
var data = stringToBytes(s);
|
||||||
data = cipher.decryptBlock(data);
|
data = cipher.decryptBlock(data);
|
||||||
@ -417,7 +419,7 @@ var CipherTransform = (function() {
|
|||||||
return constructor;
|
return constructor;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var CipherTransformFactory = (function() {
|
var CipherTransformFactory = (function cipherTransformFactory() {
|
||||||
function prepareKeyData(fileId, password, ownerPassword, userPassword,
|
function prepareKeyData(fileId, password, ownerPassword, userPassword,
|
||||||
flags, revision, keyLength, encryptMetadata) {
|
flags, revision, keyLength, encryptMetadata) {
|
||||||
var defaultPasswordBytes = new Uint8Array([
|
var defaultPasswordBytes = new Uint8Array([
|
||||||
@ -450,11 +452,11 @@ var CipherTransformFactory = (function() {
|
|||||||
hashData[i++] = 0xFF;
|
hashData[i++] = 0xFF;
|
||||||
hashData[i++] = 0xFF;
|
hashData[i++] = 0xFF;
|
||||||
}
|
}
|
||||||
var hash = md5(hashData, 0, i);
|
var hash = calculateMD5(hashData, 0, i);
|
||||||
var keyLengthInBytes = keyLength >> 3;
|
var keyLengthInBytes = keyLength >> 3;
|
||||||
if (revision >= 3) {
|
if (revision >= 3) {
|
||||||
for (j = 0; j < 50; ++j) {
|
for (j = 0; j < 50; ++j) {
|
||||||
hash = md5(hash, 0, keyLengthInBytes);
|
hash = calculateMD5(hash, 0, keyLengthInBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var encryptionKey = hash.subarray(0, keyLengthInBytes);
|
var encryptionKey = hash.subarray(0, keyLengthInBytes);
|
||||||
@ -467,7 +469,7 @@ var CipherTransformFactory = (function() {
|
|||||||
for (j = 0, n = fileId.length; j < n; ++j)
|
for (j = 0, n = fileId.length; j < n; ++j)
|
||||||
hashData[i++] = fileId[j];
|
hashData[i++] = fileId[j];
|
||||||
cipher = new ARCFourCipher(encryptionKey);
|
cipher = new ARCFourCipher(encryptionKey);
|
||||||
var checkData = cipher.encryptBlock(md5(hashData, 0, i));
|
var checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
|
||||||
n = encryptionKey.length;
|
n = encryptionKey.length;
|
||||||
var derrivedKey = new Uint8Array(n), k;
|
var derrivedKey = new Uint8Array(n), k;
|
||||||
for (j = 1; j <= 19; ++j) {
|
for (j = 1; j <= 19; ++j) {
|
||||||
@ -491,16 +493,16 @@ var CipherTransformFactory = (function() {
|
|||||||
|
|
||||||
function constructor(dict, fileId, password) {
|
function constructor(dict, fileId, password) {
|
||||||
var filter = dict.get('Filter');
|
var filter = dict.get('Filter');
|
||||||
if (!IsName(filter) || filter.name != 'Standard')
|
if (!isName(filter) || filter.name != 'Standard')
|
||||||
error('unknown encryption method');
|
error('unknown encryption method');
|
||||||
this.dict = dict;
|
this.dict = dict;
|
||||||
var algorithm = dict.get('V');
|
var algorithm = dict.get('V');
|
||||||
if (!IsInt(algorithm) ||
|
if (!isInt(algorithm) ||
|
||||||
(algorithm != 1 && algorithm != 2 && algorithm != 4))
|
(algorithm != 1 && algorithm != 2 && algorithm != 4))
|
||||||
error('unsupported encryption algorithm');
|
error('unsupported encryption algorithm');
|
||||||
this.algorithm = algorithm;
|
this.algorithm = algorithm;
|
||||||
var keyLength = dict.get('Length') || 40;
|
var keyLength = dict.get('Length') || 40;
|
||||||
if (!IsInt(keyLength) ||
|
if (!isInt(keyLength) ||
|
||||||
keyLength < 40 || (keyLength % 8) != 0)
|
keyLength < 40 || (keyLength % 8) != 0)
|
||||||
error('invalid key length');
|
error('invalid key length');
|
||||||
// prepare keys
|
// prepare keys
|
||||||
@ -542,7 +544,7 @@ var CipherTransformFactory = (function() {
|
|||||||
key[i++] = 0x6C;
|
key[i++] = 0x6C;
|
||||||
key[i++] = 0x54;
|
key[i++] = 0x54;
|
||||||
}
|
}
|
||||||
var hash = md5(key, 0, i);
|
var hash = calculateMD5(key, 0, i);
|
||||||
return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
|
return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,18 +554,18 @@ var CipherTransformFactory = (function() {
|
|||||||
if (cryptFilter != null)
|
if (cryptFilter != null)
|
||||||
cfm = cryptFilter.get('CFM');
|
cfm = cryptFilter.get('CFM');
|
||||||
if (!cfm || cfm.name == 'None') {
|
if (!cfm || cfm.name == 'None') {
|
||||||
return function() {
|
return function cipherTransformFactoryBuildCipherConstructorNone() {
|
||||||
return new NullCipher();
|
return new NullCipher();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if ('V2' == cfm.name) {
|
if ('V2' == cfm.name) {
|
||||||
return function() {
|
return function cipherTransformFactoryBuildCipherConstructorV2() {
|
||||||
return new ARCFourCipher(
|
return new ARCFourCipher(
|
||||||
buildObjectKey(num, gen, key, false));
|
buildObjectKey(num, gen, key, false));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if ('AESV2' == cfm.name) {
|
if ('AESV2' == cfm.name) {
|
||||||
return function() {
|
return function cipherTransformFactoryBuildCipherConstructorAESV2() {
|
||||||
return new AES128Cipher(
|
return new AES128Cipher(
|
||||||
buildObjectKey(num, gen, key, true));
|
buildObjectKey(num, gen, key, true));
|
||||||
};
|
};
|
||||||
@ -573,7 +575,8 @@ var CipherTransformFactory = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
createCipherTransform: function(num, gen) {
|
createCipherTransform: function buildCipherCreateCipherTransform(num,
|
||||||
|
gen) {
|
||||||
if (this.algorithm == 4) {
|
if (this.algorithm == 4) {
|
||||||
return new CipherTransform(
|
return new CipherTransform(
|
||||||
buildCipherConstructor(this.cf, this.stmf,
|
buildCipherConstructor(this.cf, this.stmf,
|
||||||
@ -583,7 +586,7 @@ var CipherTransformFactory = (function() {
|
|||||||
}
|
}
|
||||||
// algorithms 1 and 2
|
// algorithms 1 and 2
|
||||||
var key = buildObjectKey(num, gen, this.encryptionKey, false);
|
var key = buildObjectKey(num, gen, this.encryptionKey, false);
|
||||||
var cipherConstructor = function() {
|
var cipherConstructor = function buildCipherCipherConstructor() {
|
||||||
return new ARCFourCipher(key);
|
return new ARCFourCipher(key);
|
||||||
};
|
};
|
||||||
return new CipherTransform(cipherConstructor, cipherConstructor);
|
return new CipherTransform(cipherConstructor, cipherConstructor);
|
||||||
|
18
examples/helloworld/README.md
Normal file
18
examples/helloworld/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
## "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)
|
||||||
|
|
31
examples/helloworld/hello.js
Normal file
31
examples/helloworld/hello.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
|
||||||
|
//
|
||||||
|
// See README for overview
|
||||||
|
//
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
getPdf('helloworld.pdf', function getPdfHelloWorld(data) {
|
||||||
|
//
|
||||||
|
// Instantiate PDFDoc with PDF data
|
||||||
|
//
|
||||||
|
var pdf = new PDFDoc(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>
|
27
extensions/firefox/bootstrap.js
vendored
27
extensions/firefox/bootstrap.js
vendored
@ -1,31 +1,36 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
let Cc = Components.classes;
|
let Cc = Components.classes;
|
||||||
let Ci = Components.interfaces;
|
let Ci = Components.interfaces;
|
||||||
let Cm = Components.manager;
|
let Cm = Components.manager;
|
||||||
let Cu = Components.utils;
|
let Cu = Components.utils;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import('resource://gre/modules/Services.jsm');
|
||||||
|
|
||||||
function log(str) {
|
function log(str) {
|
||||||
dump(str + "\n");
|
dump(str + '\n');
|
||||||
};
|
}
|
||||||
|
|
||||||
function startup(aData, aReason) {
|
function startup(aData, aReason) {
|
||||||
let manifestPath = "chrome.manifest";
|
let manifestPath = 'chrome.manifest';
|
||||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
|
||||||
try {
|
try {
|
||||||
file.initWithPath(aData.installPath.path);
|
file.initWithPath(aData.installPath.path);
|
||||||
file.append(manifestPath);
|
file.append(manifestPath);
|
||||||
Cm.QueryInterface(Ci.nsIComponentRegistrar).autoRegister(file);
|
Cm.QueryInterface(Ci.nsIComponentRegistrar).autoRegister(file);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function shutdown(aData, aReason) {
|
function shutdown(aData, aReason) {
|
||||||
};
|
}
|
||||||
|
|
||||||
function install(aData, aReason) {
|
function install(aData, aReason) {
|
||||||
let url = "chrome://pdf.js/content/web/viewer.html?file=%s";
|
let url = 'chrome://pdf.js/content/web/viewer.html?file=%s';
|
||||||
Services.prefs.setCharPref("extensions.pdf.js.url", url);
|
Services.prefs.setCharPref('extensions.pdf.js.url', url);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
@ -1,55 +1,68 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
const Cr = Components.results;
|
const Cr = Components.results;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
|
|
||||||
const PDF_CONTENT_TYPE = "application/pdf";
|
const PDF_CONTENT_TYPE = 'application/pdf';
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import('resource://gre/modules/Services.jsm');
|
||||||
|
|
||||||
// TODO
|
|
||||||
// Add some download progress event
|
|
||||||
|
|
||||||
function log(aMsg) {
|
function log(aMsg) {
|
||||||
let msg = "pdfContentHandler.js: " + (aMsg.join ? aMsg.join("") : aMsg);
|
let msg = 'pdfContentHandler.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
|
||||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
|
Cc['@mozilla.org/consoleservice;1'].getService(Ci.nsIConsoleService)
|
||||||
.logStringMessage(msg);
|
.logStringMessage(msg);
|
||||||
dump(msg + "\n");
|
dump(msg + '\n');
|
||||||
};
|
}
|
||||||
|
|
||||||
|
function fireEventTo(aName, aData, aWindow) {
|
||||||
|
let window = aWindow.wrappedJSObject;
|
||||||
|
let evt = window.document.createEvent('CustomEvent');
|
||||||
|
evt.initCustomEvent('pdf' + aName, false, false, aData);
|
||||||
|
window.document.dispatchEvent(evt);
|
||||||
|
}
|
||||||
|
|
||||||
function loadDocument(aWindow, aDocumentUrl) {
|
function loadDocument(aWindow, aDocumentUrl) {
|
||||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
|
||||||
.createInstance(Ci.nsIXMLHttpRequest);
|
.createInstance(Ci.nsIXMLHttpRequest);
|
||||||
xhr.open("GET", aDocumentUrl);
|
xhr.onprogress = function updateProgress(evt) {
|
||||||
xhr.mozResponseType = xhr.responseType = "arraybuffer";
|
if (evt.lengthComputable)
|
||||||
xhr.onreadystatechange = function() {
|
fireEventTo(evt.type, evt.loaded / evt.total, aWindow);
|
||||||
if (xhr.readyState == 4 && xhr.status == 200) {
|
};
|
||||||
let data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
|
||||||
xhr.responseArrayBuffer || xhr.response);
|
|
||||||
try {
|
|
||||||
var view = new Uint8Array(data);
|
|
||||||
|
|
||||||
// I think accessing aWindow.wrappedJSObject returns a
|
xhr.onerror = function error(evt) {
|
||||||
// XPCSafeJSObjectWrapper and so it is safe but mrbkap can confirm that
|
fireEventTo(evt.type, false, aWindow);
|
||||||
let window = aWindow.wrappedJSObject;
|
};
|
||||||
var arrayBuffer = new window.ArrayBuffer(data.byteLength);
|
|
||||||
var view2 = new window.Uint8Array(arrayBuffer);
|
|
||||||
view2.set(view);
|
|
||||||
|
|
||||||
let evt = window.document.createEvent("CustomEvent");
|
xhr.onload = function load(evt) {
|
||||||
evt.initCustomEvent("pdfloaded", false, false, arrayBuffer);
|
let data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
||||||
window.document.dispatchEvent(evt);
|
xhr.responseArrayBuffer || xhr.response);
|
||||||
} catch(e) {
|
try {
|
||||||
log("Error - " + e);
|
let view = new Uint8Array(data);
|
||||||
}
|
|
||||||
|
let window = aWindow.wrappedJSObject;
|
||||||
|
let arrayBuffer = new window.ArrayBuffer(data.byteLength);
|
||||||
|
let view2 = new window.Uint8Array(arrayBuffer);
|
||||||
|
view2.set(view);
|
||||||
|
|
||||||
|
fireEventTo(evt.type, arrayBuffer, aWindow);
|
||||||
|
} catch (e) {
|
||||||
|
log('Error - ' + e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
xhr.open('GET', aDocumentUrl);
|
||||||
|
xhr.responseType = 'arraybuffer';
|
||||||
xhr.send(null);
|
xhr.send(null);
|
||||||
};
|
}
|
||||||
|
|
||||||
let WebProgressListener = {
|
let WebProgressListener = {
|
||||||
init: function(aWindow, aUrl) {
|
init: function WebProgressListenerInit(aWindow, aUrl) {
|
||||||
this._locationHasChanged = false;
|
this._locationHasChanged = false;
|
||||||
this._documentUrl = aUrl;
|
this._documentUrl = aUrl;
|
||||||
|
|
||||||
@ -64,11 +77,12 @@ let WebProgressListener = {
|
|||||||
.getInterface(Ci.nsIWebProgress);
|
.getInterface(Ci.nsIWebProgress);
|
||||||
try {
|
try {
|
||||||
webProgress.removeProgressListener(this);
|
webProgress.removeProgressListener(this);
|
||||||
} catch(e) {}
|
} catch (e) {}
|
||||||
webProgress.addProgressListener(this, flags);
|
webProgress.addProgressListener(this, flags);
|
||||||
},
|
},
|
||||||
|
|
||||||
onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
|
onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags,
|
||||||
|
aStatus) {
|
||||||
const complete = Ci.nsIWebProgressListener.STATE_IS_WINDOW +
|
const complete = Ci.nsIWebProgressListener.STATE_IS_WINDOW +
|
||||||
Ci.nsIWebProgressListener.STATE_STOP;
|
Ci.nsIWebProgressListener.STATE_STOP;
|
||||||
if ((aStateFlags & complete) == complete && this._locationHasChanged) {
|
if ((aStateFlags & complete) == complete && this._locationHasChanged) {
|
||||||
@ -77,14 +91,17 @@ let WebProgressListener = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onProgressChange: function onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
|
onProgressChange: function onProgressChange(aWebProgress, aRequest, aCurSelf,
|
||||||
|
aMaxSelf, aCurTotal, aMaxTotal) {
|
||||||
},
|
},
|
||||||
|
|
||||||
onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocationURI) {
|
onLocationChange: function onLocationChange(aWebProgress, aRequest,
|
||||||
|
aLocationURI) {
|
||||||
this._locationHasChanged = true;
|
this._locationHasChanged = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
|
onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus,
|
||||||
|
aMessage) {
|
||||||
},
|
},
|
||||||
|
|
||||||
onSecurityChange: function onSecurityChange(aWebProgress, aRequest, aState) {
|
onSecurityChange: function onSecurityChange(aWebProgress, aRequest, aState) {
|
||||||
@ -127,16 +144,16 @@ pdfContentHandler.prototype = {
|
|||||||
WebProgressListener.init(window, uri.spec);
|
WebProgressListener.init(window, uri.spec);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let url = Services.prefs.getCharPref("extensions.pdf.js.url");
|
let url = Services.prefs.getCharPref('extensions.pdf.js.url');
|
||||||
url = url.replace("%s", uri.spec);
|
url = url.replace('%s', uri.spec);
|
||||||
window.location = url;
|
window.location = url;
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
log("Error - " + e);
|
log('Error retrieving the pdf.js base url - ' + e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
classID: Components.ID("{2278dfd0-b75c-11e0-8257-1ba3d93c9f1a}"),
|
classID: Components.ID('{2278dfd0-b75c-11e0-8257-1ba3d93c9f1a}'),
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler])
|
||||||
};
|
};
|
||||||
|
|
||||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([pdfContentHandler]);
|
var NSGetFactory = XPCOMUtils.generateNSGetFactory([pdfContentHandler]);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<Description>
|
<Description>
|
||||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||||
<em:minVersion>6.0</em:minVersion>
|
<em:minVersion>6.0</em:minVersion>
|
||||||
<em:maxVersion>9.0.*</em:maxVersion>
|
<em:maxVersion>10.0.*</em:maxVersion>
|
||||||
</Description>
|
</Description>
|
||||||
</em:targetApplication>
|
</em:targetApplication>
|
||||||
<em:bootstrap>true</em:bootstrap>
|
<em:bootstrap>true</em:bootstrap>
|
||||||
|
530
fonts.js
Executable file → Normal file
530
fonts.js
Executable file → Normal file
@ -11,6 +11,11 @@ var kMaxWaitForFontFace = 1000;
|
|||||||
|
|
||||||
// Unicode Private Use Area
|
// Unicode Private Use Area
|
||||||
var kCmapGlyphOffset = 0xE000;
|
var kCmapGlyphOffset = 0xE000;
|
||||||
|
var kSizeOfGlyphArea = 0x1900;
|
||||||
|
|
||||||
|
// 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
|
// Until hinting is fully supported this constant can be used
|
||||||
var kHintingEnabled = false;
|
var kHintingEnabled = false;
|
||||||
@ -221,7 +226,7 @@ var FontLoader = {
|
|||||||
fontsToLoad[fontName] = true;
|
fontsToLoad[fontName] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkFontsLoaded() {
|
function checkFontsLoaded() {
|
||||||
for (var i = 0; i < objs.length; i++) {
|
for (var i = 0; i < objs.length; i++) {
|
||||||
var fontObj = objs[i];
|
var fontObj = objs[i];
|
||||||
@ -611,8 +616,12 @@ var Font = (function Font() {
|
|||||||
var constructor = function font_constructor(name, file, properties) {
|
var constructor = function font_constructor(name, file, properties) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.encoding = properties.encoding;
|
this.encoding = properties.encoding;
|
||||||
this.glyphs = properties.glyphs;
|
|
||||||
|
// Glyhps are no needed anymore? MERGE
|
||||||
|
// this.glyphs = properties.glyphs;
|
||||||
this.loadedName = properties.loadedName;
|
this.loadedName = properties.loadedName;
|
||||||
|
this.coded = properties.coded;
|
||||||
|
this.resources = properties.resources;
|
||||||
this.sizes = [];
|
this.sizes = [];
|
||||||
|
|
||||||
var names = name.split('+');
|
var names = name.split('+');
|
||||||
@ -627,6 +636,12 @@ var Font = (function Font() {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.fontMatrix = properties.fontMatrix;
|
||||||
|
if (properties.type == 'Type3')
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Trying to fix encoding using glyph widths and CIDSystemInfo.
|
||||||
|
this.fixWidths(properties);
|
||||||
|
|
||||||
if (!file) {
|
if (!file) {
|
||||||
// The file data is not specified. Trying to fix the font name
|
// The file data is not specified. Trying to fix the font name
|
||||||
@ -640,18 +655,23 @@ var Font = (function Font() {
|
|||||||
// name ArialBlack for example will be replaced by Helvetica.
|
// name ArialBlack for example will be replaced by Helvetica.
|
||||||
this.black = (name.search(/Black/g) != -1);
|
this.black = (name.search(/Black/g) != -1);
|
||||||
|
|
||||||
|
this.defaultWidth = properties.defaultWidth;
|
||||||
|
// MERGE
|
||||||
|
// this.loadedName = fontName.split('-')[0];
|
||||||
|
this.composite = properties.composite;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var data;
|
var data;
|
||||||
switch (properties.type) {
|
var type = properties.type;
|
||||||
|
switch (type) {
|
||||||
case 'Type1':
|
case 'Type1':
|
||||||
case 'CIDFontType0':
|
case 'CIDFontType0':
|
||||||
this.mimetype = 'font/opentype';
|
this.mimetype = 'font/opentype';
|
||||||
|
|
||||||
var subtype = properties.subtype;
|
var subtype = properties.subtype;
|
||||||
var cff = (subtype === 'Type1C') ?
|
var cff = (subtype == 'Type1C' || subtype == 'CIDFontType0C') ?
|
||||||
new Type2CFF(file, properties) : new CFF(name, file, properties);
|
new Type2CFF(file, properties) : new CFF(name, file, properties);
|
||||||
|
|
||||||
// Wrap the CFF data inside an OTF font file
|
// Wrap the CFF data inside an OTF font file
|
||||||
@ -673,8 +693,12 @@ var Font = (function Font() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.type = properties.type;
|
// MERGE
|
||||||
this.textMatrix = properties.textMatrix;
|
//this.textMatrix = properties.textMatrix;
|
||||||
|
this.type = type;
|
||||||
|
this.fontMatrix = properties.fontMatrix;
|
||||||
|
this.defaultWidth = properties.defaultWidth;
|
||||||
|
this.loadedName = properties.loadedName;
|
||||||
this.composite = properties.composite;
|
this.composite = properties.composite;
|
||||||
|
|
||||||
// TODO: Remove this once we can be sure nothing got broken to du changes
|
// TODO: Remove this once we can be sure nothing got broken to du changes
|
||||||
@ -738,6 +762,10 @@ var Font = (function Font() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function createOpenTypeHeader(sfnt, file, numTables) {
|
function createOpenTypeHeader(sfnt, file, numTables) {
|
||||||
|
// Windows hates the Mac TrueType sfnt version number
|
||||||
|
if (sfnt == 'true')
|
||||||
|
sfnt = string32(0x00010000);
|
||||||
|
|
||||||
// sfnt version (4 bytes)
|
// sfnt version (4 bytes)
|
||||||
var header = sfnt;
|
var header = sfnt;
|
||||||
|
|
||||||
@ -791,19 +819,24 @@ var Font = (function Font() {
|
|||||||
var codes = [];
|
var codes = [];
|
||||||
var length = glyphs.length;
|
var length = glyphs.length;
|
||||||
for (var n = 0; n < length; ++n)
|
for (var n = 0; n < length; ++n)
|
||||||
codes.push(String.fromCharCode(glyphs[n].unicode));
|
codes.push({ unicode: glyphs[n].unicode, code: n });
|
||||||
codes.sort();
|
codes.sort(function fontGetRangesSort(a, b) {
|
||||||
|
return a.unicode - b.unicode;
|
||||||
|
});
|
||||||
|
|
||||||
// Split the sorted codes into ranges.
|
// Split the sorted codes into ranges.
|
||||||
var ranges = [];
|
var ranges = [];
|
||||||
for (var n = 0; n < length; ) {
|
for (var n = 0; n < length; ) {
|
||||||
var start = codes[n++].charCodeAt(0);
|
var start = codes[n].unicode;
|
||||||
|
var startCode = codes[n].code;
|
||||||
|
++n;
|
||||||
var end = start;
|
var end = start;
|
||||||
while (n < length && end + 1 == codes[n].charCodeAt(0)) {
|
while (n < length && end + 1 == codes[n].unicode) {
|
||||||
++end;
|
++end;
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
ranges.push([start, end]);
|
var endCode = codes[n - 1].code;
|
||||||
|
ranges.push([start, end, startCode, endCode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ranges;
|
return ranges;
|
||||||
@ -832,22 +865,39 @@ var Font = (function Font() {
|
|||||||
var idRangeOffsets = '';
|
var idRangeOffsets = '';
|
||||||
var glyphsIds = '';
|
var glyphsIds = '';
|
||||||
var bias = 0;
|
var bias = 0;
|
||||||
for (var i = 0; i < segCount - 1; i++) {
|
|
||||||
var range = ranges[i];
|
|
||||||
var start = range[0];
|
|
||||||
var end = range[1];
|
|
||||||
var offset = (segCount - i) * 2 + bias * 2;
|
|
||||||
bias += (end - start + 1);
|
|
||||||
|
|
||||||
startCount += string16(start);
|
if (deltas) {
|
||||||
endCount += string16(end);
|
for (var i = 0; i < segCount - 1; i++) {
|
||||||
idDeltas += string16(0);
|
var range = ranges[i];
|
||||||
idRangeOffsets += string16(offset);
|
var start = range[0];
|
||||||
|
var end = range[1];
|
||||||
|
var offset = (segCount - i) * 2 + bias * 2;
|
||||||
|
bias += (end - start + 1);
|
||||||
|
|
||||||
|
startCount += string16(start);
|
||||||
|
endCount += string16(end);
|
||||||
|
idDeltas += string16(0);
|
||||||
|
idRangeOffsets += string16(offset);
|
||||||
|
|
||||||
|
var startCode = range[2];
|
||||||
|
var endCode = range[3];
|
||||||
|
for (var j = startCode; j <= endCode; ++j)
|
||||||
|
glyphsIds += string16(deltas[j]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < segCount - 1; i++) {
|
||||||
|
var range = ranges[i];
|
||||||
|
var start = range[0];
|
||||||
|
var end = range[1];
|
||||||
|
var startCode = range[2];
|
||||||
|
|
||||||
|
startCount += string16(start);
|
||||||
|
endCount += string16(end);
|
||||||
|
idDeltas += string16((startCode - start + 1) & 0xFFFF);
|
||||||
|
idRangeOffsets += string16(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < glyphs.length; i++)
|
|
||||||
glyphsIds += string16(deltas ? deltas[i] : i + 1);
|
|
||||||
|
|
||||||
endCount += '\xFF\xFF';
|
endCount += '\xFF\xFF';
|
||||||
startCount += '\xFF\xFF';
|
startCount += '\xFF\xFF';
|
||||||
idDeltas += '\x00\x01';
|
idDeltas += '\x00\x01';
|
||||||
@ -867,7 +917,9 @@ var Font = (function Font() {
|
|||||||
format314);
|
format314);
|
||||||
};
|
};
|
||||||
|
|
||||||
function createOS2Table(properties) {
|
function createOS2Table(properties, override) {
|
||||||
|
var override = override || {};
|
||||||
|
|
||||||
var ulUnicodeRange1 = 0;
|
var ulUnicodeRange1 = 0;
|
||||||
var ulUnicodeRange2 = 0;
|
var ulUnicodeRange2 = 0;
|
||||||
var ulUnicodeRange3 = 0;
|
var ulUnicodeRange3 = 0;
|
||||||
@ -898,6 +950,24 @@ 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
|
return '\x00\x03' + // version
|
||||||
'\x02\x24' + // xAvgCharWidth
|
'\x02\x24' + // xAvgCharWidth
|
||||||
'\x01\xF4' + // usWeightClass
|
'\x01\xF4' + // usWeightClass
|
||||||
@ -926,11 +996,11 @@ var Font = (function Font() {
|
|||||||
string16(firstCharIndex ||
|
string16(firstCharIndex ||
|
||||||
properties.firstChar) + // usFirstCharIndex
|
properties.firstChar) + // usFirstCharIndex
|
||||||
string16(lastCharIndex || properties.lastChar) + // usLastCharIndex
|
string16(lastCharIndex || properties.lastChar) + // usLastCharIndex
|
||||||
string16(properties.ascent) + // sTypoAscender
|
string16(typoAscent) + // sTypoAscender
|
||||||
string16(properties.descent) + // sTypoDescender
|
string16(typoDescent) + // sTypoDescender
|
||||||
'\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value)
|
'\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value)
|
||||||
string16(properties.ascent) + // usWinAscent
|
string16(winAscent) + // usWinAscent
|
||||||
string16(-properties.descent) + // usWinDescent
|
string16(winDescent) + // usWinDescent
|
||||||
'\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31)
|
'\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31)
|
||||||
'\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63)
|
'\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63)
|
||||||
string16(properties.xHeight) + // sxHeight
|
string16(properties.xHeight) + // sxHeight
|
||||||
@ -1037,9 +1107,11 @@ var Font = (function Font() {
|
|||||||
var data = file.getBytes(length);
|
var data = file.getBytes(length);
|
||||||
file.pos = previousPosition;
|
file.pos = previousPosition;
|
||||||
|
|
||||||
if (tag == 'head')
|
if (tag == 'head') {
|
||||||
// clearing checksum adjustment
|
// clearing checksum adjustment
|
||||||
data[8] = data[9] = data[10] = data[11] = 0;
|
data[8] = data[9] = data[10] = data[11] = 0;
|
||||||
|
data[17] |= 0x20; //Set font optimized for cleartype flag
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tag: tag,
|
tag: tag,
|
||||||
@ -1077,7 +1149,7 @@ var Font = (function Font() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that table are sorted by platformID then encodingID,
|
// Check that table are sorted by platformID then encodingID,
|
||||||
records.sort(function(a, b) {
|
records.sort(function fontReplaceCMapTableSort(a, b) {
|
||||||
return ((a.platformID << 16) + a.encodingID) -
|
return ((a.platformID << 16) + a.encodingID) -
|
||||||
((b.platformID << 16) + b.encodingID);
|
((b.platformID << 16) + b.encodingID);
|
||||||
});
|
});
|
||||||
@ -1205,6 +1277,49 @@ var Font = (function Font() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function sanitizeGlyphLocations(loca, glyf, numGlyphs,
|
||||||
|
isGlyphLocationsLong) {
|
||||||
|
var itemSize, itemDecode, itemEncode;
|
||||||
|
if (isGlyphLocationsLong) {
|
||||||
|
itemSize = 4;
|
||||||
|
itemDecode = function fontItemDecodeLong(data, offset) {
|
||||||
|
return (data[offset] << 24) | (data[offset + 1] << 16) |
|
||||||
|
(data[offset + 2] << 8) | data[offset + 3];
|
||||||
|
};
|
||||||
|
itemEncode = function fontItemEncodeLong(data, offset, value) {
|
||||||
|
data[offset] = (value >>> 24) & 0xFF;
|
||||||
|
data[offset + 1] = (value >> 16) & 0xFF;
|
||||||
|
data[offset + 2] = (value >> 8) & 0xFF;
|
||||||
|
data[offset + 3] = value & 0xFF;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
itemSize = 2;
|
||||||
|
itemDecode = function fontItemDecode(data, offset) {
|
||||||
|
return (data[offset] << 9) | (data[offset + 1] << 1);
|
||||||
|
};
|
||||||
|
itemEncode = function fontItemEncode(data, offset, value) {
|
||||||
|
data[offset] = (value >> 9) & 0xFF;
|
||||||
|
data[offset + 1] = (value >> 1) & 0xFF;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var locaData = loca.data;
|
||||||
|
var startOffset = itemDecode(locaData, 0);
|
||||||
|
var firstOffset = itemDecode(locaData, itemSize);
|
||||||
|
if (firstOffset - startOffset < 12 || startOffset > 0) {
|
||||||
|
// removing first glyph
|
||||||
|
glyf.data = glyf.data.subarray(firstOffset);
|
||||||
|
glyf.length -= firstOffset;
|
||||||
|
|
||||||
|
itemEncode(locaData, 0, 0);
|
||||||
|
var i, pos = itemSize;
|
||||||
|
for (i = 1; i <= numGlyphs; ++i) {
|
||||||
|
itemEncode(locaData, pos,
|
||||||
|
itemDecode(locaData, pos) - firstOffset);
|
||||||
|
pos += itemSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check that required tables are present
|
// Check that required tables are present
|
||||||
var requiredTables = ['OS/2', 'cmap', 'head', 'hhea',
|
var requiredTables = ['OS/2', 'cmap', 'head', 'hhea',
|
||||||
'hmtx', 'maxp', 'name', 'post'];
|
'hmtx', 'maxp', 'name', 'post'];
|
||||||
@ -1212,7 +1327,7 @@ var Font = (function Font() {
|
|||||||
var header = readOpenTypeHeader(font);
|
var header = readOpenTypeHeader(font);
|
||||||
var numTables = header.numTables;
|
var numTables = header.numTables;
|
||||||
|
|
||||||
var cmap, maxp, hhea, hmtx, vhea, vmtx;
|
var cmap, maxp, hhea, hmtx, vhea, vmtx, head, loca, glyf;
|
||||||
var tables = [];
|
var tables = [];
|
||||||
for (var i = 0; i < numTables; i++) {
|
for (var i = 0; i < numTables; i++) {
|
||||||
var table = readTableEntry(font);
|
var table = readTableEntry(font);
|
||||||
@ -1226,6 +1341,8 @@ var Font = (function Font() {
|
|||||||
hhea = table;
|
hhea = table;
|
||||||
else if (table.tag == 'hmtx')
|
else if (table.tag == 'hmtx')
|
||||||
hmtx = table;
|
hmtx = table;
|
||||||
|
else if (table.tag == 'head')
|
||||||
|
head = table;
|
||||||
|
|
||||||
requiredTables.splice(index, 1);
|
requiredTables.splice(index, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -1233,6 +1350,10 @@ var Font = (function Font() {
|
|||||||
vmtx = table;
|
vmtx = table;
|
||||||
else if (table.tag == 'vhea')
|
else if (table.tag == 'vhea')
|
||||||
vhea = table;
|
vhea = table;
|
||||||
|
else if (table.tag == 'loca')
|
||||||
|
loca = table;
|
||||||
|
else if (table.tag == 'glyf')
|
||||||
|
glyf = table;
|
||||||
}
|
}
|
||||||
tables.push(table);
|
tables.push(table);
|
||||||
}
|
}
|
||||||
@ -1252,9 +1373,19 @@ var Font = (function Font() {
|
|||||||
createOpenTypeHeader(header.version, ttf, numTables);
|
createOpenTypeHeader(header.version, ttf, numTables);
|
||||||
|
|
||||||
if (requiredTables.indexOf('OS/2') != -1) {
|
if (requiredTables.indexOf('OS/2') != -1) {
|
||||||
|
// extract some more font properties from the OpenType head and
|
||||||
|
// hhea tables; yMin and descent value are always negative
|
||||||
|
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,
|
||||||
|
ascent: int16([hhea.data[4], hhea.data[5]]),
|
||||||
|
descent: int16([hhea.data[6], hhea.data[7]]) - 0x10000
|
||||||
|
};
|
||||||
|
|
||||||
tables.push({
|
tables.push({
|
||||||
tag: 'OS/2',
|
tag: 'OS/2',
|
||||||
data: stringToArray(createOS2Table(properties))
|
data: stringToArray(createOS2Table(properties, override))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1267,6 +1398,11 @@ var Font = (function Font() {
|
|||||||
sanitizeMetrics(font, hhea, hmtx, numGlyphs);
|
sanitizeMetrics(font, hhea, hmtx, numGlyphs);
|
||||||
sanitizeMetrics(font, vhea, vmtx, numGlyphs);
|
sanitizeMetrics(font, vhea, vmtx, numGlyphs);
|
||||||
|
|
||||||
|
if (head && loca && glyf) {
|
||||||
|
var isGlyphLocationsLong = int16([head.data[50], head.data[51]]);
|
||||||
|
sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong);
|
||||||
|
}
|
||||||
|
|
||||||
// Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
|
// Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
|
||||||
// Sometimes it's 0. That needs to be fixed
|
// Sometimes it's 0. That needs to be fixed
|
||||||
if (hhea.data[10] == 0 && hhea.data[11] == 0) {
|
if (hhea.data[10] == 0 && hhea.data[11] == 0) {
|
||||||
@ -1291,26 +1427,25 @@ var Font = (function Font() {
|
|||||||
tables.push(cmap);
|
tables.push(cmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
var encoding = properties.encoding;
|
var encoding = properties.encoding, i;
|
||||||
if (!encoding[0]) {
|
|
||||||
// the font is directly characters to glyphs with no encoding
|
// offsetting glyphs to avoid problematic unicode ranges
|
||||||
// so create an identity encoding
|
for (i in encoding) {
|
||||||
var widths = properties.widths;
|
if (encoding.hasOwnProperty(i)) {
|
||||||
for (i = 0; i < numGlyphs; i++) {
|
var unicode = encoding[i].unicode;
|
||||||
var width = widths[i];
|
if (unicode <= 0x1f ||
|
||||||
encoding[i] = {
|
(unicode >= 127 && unicode < kSizeOfGlyphArea))
|
||||||
unicode: i + kCmapGlyphOffset,
|
encoding[i].unicode += kCmapGlyphOffset;
|
||||||
width: IsNum(width) ? width : properties.defaultWidth
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (var code in encoding)
|
|
||||||
encoding[code].unicode += kCmapGlyphOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var glyphs = [];
|
var glyphs = [];
|
||||||
for (var i = 1; i < numGlyphs; i++)
|
for (i = 1; i < numGlyphs; i++) {
|
||||||
glyphs.push({ unicode: i + kCmapGlyphOffset });
|
glyphs.push({
|
||||||
|
unicode: i <= 0x1f || (i >= 127 && i < kSizeOfGlyphArea) ?
|
||||||
|
i + kCmapGlyphOffset : i
|
||||||
|
});
|
||||||
|
}
|
||||||
cmap.data = createCMapTable(glyphs);
|
cmap.data = createCMapTable(glyphs);
|
||||||
} else {
|
} else {
|
||||||
replaceCMapTable(cmap, font, properties);
|
replaceCMapTable(cmap, font, properties);
|
||||||
@ -1398,7 +1533,7 @@ var Font = (function Font() {
|
|||||||
'cmap': createCMapTable(charstrings.slice(), font.glyphIds),
|
'cmap': createCMapTable(charstrings.slice(), font.glyphIds),
|
||||||
|
|
||||||
// Font header
|
// Font header
|
||||||
'head': (function() {
|
'head': (function fontFieldsHead() {
|
||||||
return stringToArray(
|
return stringToArray(
|
||||||
'\x00\x01\x00\x00' + // Version number
|
'\x00\x01\x00\x00' + // Version number
|
||||||
'\x00\x00\x10\x00' + // fontRevision
|
'\x00\x00\x10\x00' + // fontRevision
|
||||||
@ -1420,7 +1555,7 @@ var Font = (function Font() {
|
|||||||
})(),
|
})(),
|
||||||
|
|
||||||
// Horizontal header
|
// Horizontal header
|
||||||
'hhea': (function() {
|
'hhea': (function fontFieldsHhea() {
|
||||||
return stringToArray(
|
return stringToArray(
|
||||||
'\x00\x01\x00\x00' + // Version number
|
'\x00\x01\x00\x00' + // Version number
|
||||||
string16(properties.ascent) + // Typographic Ascent
|
string16(properties.ascent) + // Typographic Ascent
|
||||||
@ -1443,7 +1578,7 @@ var Font = (function Font() {
|
|||||||
})(),
|
})(),
|
||||||
|
|
||||||
// Horizontal metrics
|
// Horizontal metrics
|
||||||
'hmtx': (function() {
|
'hmtx': (function fontFieldsHmtx() {
|
||||||
var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
|
var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
|
||||||
for (var i = 0; i < charstrings.length; i++) {
|
for (var i = 0; i < charstrings.length; i++) {
|
||||||
hmtx += string16(charstrings[i].width) + string16(0);
|
hmtx += string16(charstrings[i].width) + string16(0);
|
||||||
@ -1452,7 +1587,7 @@ var Font = (function Font() {
|
|||||||
})(),
|
})(),
|
||||||
|
|
||||||
// Maximum profile
|
// Maximum profile
|
||||||
'maxp': (function() {
|
'maxp': (function fontFieldsMaxp() {
|
||||||
return stringToArray(
|
return stringToArray(
|
||||||
'\x00\x00\x50\x00' + // Version number
|
'\x00\x00\x50\x00' + // Version number
|
||||||
string16(charstrings.length + 1)); // Num of glyphs
|
string16(charstrings.length + 1)); // Num of glyphs
|
||||||
@ -1474,6 +1609,153 @@ var Font = (function Font() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return stringToArray(otf.file);
|
return stringToArray(otf.file);
|
||||||
|
},
|
||||||
|
|
||||||
|
fixWidths: function font_fixWidths(properties) {
|
||||||
|
if (properties.type !== 'CIDFontType0' &&
|
||||||
|
properties.type !== 'CIDFontType2')
|
||||||
|
return;
|
||||||
|
|
||||||
|
var encoding = properties.encoding;
|
||||||
|
if (encoding[0])
|
||||||
|
return;
|
||||||
|
var glyphsWidths = properties.widths;
|
||||||
|
if (!glyphsWidths)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var defaultWidth = properties.defaultWidth;
|
||||||
|
var cidSystemInfo = properties.cidSystemInfo;
|
||||||
|
var cidToUnicode;
|
||||||
|
if (cidSystemInfo) {
|
||||||
|
cidToUnicode = CIDToUnicodeMaps[
|
||||||
|
cidSystemInfo.registry + '-' + cidSystemInfo.ordering];
|
||||||
|
}
|
||||||
|
if (!cidToUnicode) {
|
||||||
|
// the font is directly characters to glyphs with no encoding
|
||||||
|
// so create an identity encoding
|
||||||
|
for (i = 0; i < 0xD800; i++) {
|
||||||
|
var width = glyphsWidths[i];
|
||||||
|
encoding[i] = {
|
||||||
|
unicode: i,
|
||||||
|
width: isNum(width) ? width : defaultWidth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// skipping surrogates + 256-user defined
|
||||||
|
for (i = 0xE100; i <= 0xFFFF; i++) {
|
||||||
|
var width = glyphsWidths[i];
|
||||||
|
encoding[i] = {
|
||||||
|
unicode: i,
|
||||||
|
width: isNum(width) ? width : defaultWidth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoding[0] = { unicode: 0, width: 0 };
|
||||||
|
var glyph = 1, i, j, k;
|
||||||
|
for (i = 0; i < cidToUnicode.length; ++i) {
|
||||||
|
var unicode = cidToUnicode[i];
|
||||||
|
var width;
|
||||||
|
if (isArray(unicode)) {
|
||||||
|
var length = unicode.length;
|
||||||
|
width = glyphsWidths[glyph];
|
||||||
|
for (j = 0; j < length; j++) {
|
||||||
|
k = unicode[j];
|
||||||
|
encoding[k] = {
|
||||||
|
unicode: k,
|
||||||
|
width: isNum(width) ? width : defaultWidth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
glyph++;
|
||||||
|
} else if (typeof unicode === 'object') {
|
||||||
|
var fillLength = unicode.f;
|
||||||
|
if (fillLength) {
|
||||||
|
k = unicode.c;
|
||||||
|
for (j = 0; j < fillLength; ++j) {
|
||||||
|
width = glyphsWidths[glyph++];
|
||||||
|
encoding[k] = {
|
||||||
|
unicode: k,
|
||||||
|
width: isNum(width) ? width : defaultWidth
|
||||||
|
};
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
glyph += unicode.s;
|
||||||
|
} else if (unicode) {
|
||||||
|
width = glyphsWidths[glyph++];
|
||||||
|
encoding[unicode] = {
|
||||||
|
unicode: unicode,
|
||||||
|
width: isNum(width) ? width : defaultWidth
|
||||||
|
};
|
||||||
|
} else
|
||||||
|
glyph++;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
charsToGlyphs: function fonts_chars2Glyphs(chars) {
|
||||||
|
var charsCache = this.charsCache;
|
||||||
|
var glyphs;
|
||||||
|
|
||||||
|
// if we translated this string before, just grab it from the cache
|
||||||
|
if (charsCache) {
|
||||||
|
glyphs = charsCache[chars];
|
||||||
|
if (glyphs)
|
||||||
|
return glyphs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lazily create the translation cache
|
||||||
|
if (!charsCache)
|
||||||
|
charsCache = this.charsCache = Object.create(null);
|
||||||
|
|
||||||
|
// translate the string using the font's encoding
|
||||||
|
var encoding = this.encoding;
|
||||||
|
if (!encoding)
|
||||||
|
return chars;
|
||||||
|
|
||||||
|
glyphs = [];
|
||||||
|
|
||||||
|
if (this.composite) {
|
||||||
|
// composite fonts have multi-byte strings convert the string from
|
||||||
|
// single-byte to multi-byte
|
||||||
|
// XXX assuming CIDFonts are two-byte - later need to extract the
|
||||||
|
// correct byte encoding according to the PDF spec
|
||||||
|
var length = chars.length - 1; // looping over two bytes at a time so
|
||||||
|
// loop should never end on the last byte
|
||||||
|
for (var i = 0; i < length; i++) {
|
||||||
|
var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]);
|
||||||
|
var glyph = encoding[charcode];
|
||||||
|
if ('undefined' == typeof(glyph)) {
|
||||||
|
warn('Unencoded charcode ' + charcode);
|
||||||
|
glyph = {
|
||||||
|
unicode: charcode,
|
||||||
|
width: this.defaultWidth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
glyphs.push(glyph);
|
||||||
|
// placing null after each word break charcode (ASCII SPACE)
|
||||||
|
if (charcode == 0x20)
|
||||||
|
glyphs.push(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (var i = 0; i < chars.length; ++i) {
|
||||||
|
var charcode = chars.charCodeAt(i);
|
||||||
|
var glyph = encoding[charcode];
|
||||||
|
if ('undefined' == typeof(glyph)) {
|
||||||
|
warn('Unencoded charcode ' + charcode);
|
||||||
|
glyph = {
|
||||||
|
unicode: charcode,
|
||||||
|
width: this.defaultWidth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
glyphs.push(glyph);
|
||||||
|
if (charcode == 0x20)
|
||||||
|
glyphs.push(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter the translated string into the cache
|
||||||
|
return (charsCache[chars] = glyphs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1485,7 +1767,7 @@ var Font = (function Font() {
|
|||||||
* program. Some of its logic depends on the Type2 charstrings
|
* program. Some of its logic depends on the Type2 charstrings
|
||||||
* structure.
|
* structure.
|
||||||
*/
|
*/
|
||||||
var Type1Parser = function() {
|
var Type1Parser = function type1Parser() {
|
||||||
/*
|
/*
|
||||||
* Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence
|
* Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence
|
||||||
* of Plaintext Bytes. The function took a key as a parameter which can be
|
* of Plaintext Bytes. The function took a key as a parameter which can be
|
||||||
@ -1908,7 +2190,7 @@ var Type1Parser = function() {
|
|||||||
// Make the angle into the right direction
|
// Make the angle into the right direction
|
||||||
matrix[2] *= -1;
|
matrix[2] *= -1;
|
||||||
|
|
||||||
properties.textMatrix = matrix;
|
properties.fontMatrix = matrix;
|
||||||
break;
|
break;
|
||||||
case '/Encoding':
|
case '/Encoding':
|
||||||
var size = parseInt(getToken(), 10);
|
var size = parseInt(getToken(), 10);
|
||||||
@ -2013,7 +2295,7 @@ var CFFStrings = [
|
|||||||
|
|
||||||
var type1Parser = new Type1Parser();
|
var type1Parser = new Type1Parser();
|
||||||
|
|
||||||
var CFF = function(name, file, properties) {
|
var CFF = function cffCFF(name, file, properties) {
|
||||||
// Get the data block containing glyphs and subrs informations
|
// Get the data block containing glyphs and subrs informations
|
||||||
var headerBlock = file.getBytes(properties.length1);
|
var headerBlock = file.getBytes(properties.length1);
|
||||||
type1Parser.extractFontHeader(headerBlock, properties);
|
type1Parser.extractFontHeader(headerBlock, properties);
|
||||||
@ -2186,7 +2468,7 @@ CFF.prototype = {
|
|||||||
var cmd = map[command];
|
var cmd = map[command];
|
||||||
assert(cmd, 'Unknow command: ' + command);
|
assert(cmd, 'Unknow command: ' + command);
|
||||||
|
|
||||||
if (IsArray(cmd))
|
if (isArray(cmd))
|
||||||
charstring.splice(i++, 1, cmd[0], cmd[1]);
|
charstring.splice(i++, 1, cmd[0], cmd[1]);
|
||||||
else
|
else
|
||||||
charstring[i] = cmd;
|
charstring[i] = cmd;
|
||||||
@ -2213,7 +2495,7 @@ CFF.prototype = {
|
|||||||
'names': this.createCFFIndexHeader([name]),
|
'names': this.createCFFIndexHeader([name]),
|
||||||
|
|
||||||
'topDict': (function topDict(self) {
|
'topDict': (function topDict(self) {
|
||||||
return function() {
|
return function cffWrapTopDict() {
|
||||||
var header = '\x00\x01\x01\x01';
|
var header = '\x00\x01\x01\x01';
|
||||||
var dict =
|
var dict =
|
||||||
'\xf8\x1b\x00' + // version
|
'\xf8\x1b\x00' + // version
|
||||||
@ -2290,7 +2572,7 @@ CFF.prototype = {
|
|||||||
'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs),
|
'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs),
|
||||||
true),
|
true),
|
||||||
|
|
||||||
'private': (function(self) {
|
'private': (function cffWrapPrivate(self) {
|
||||||
var data =
|
var data =
|
||||||
'\x8b\x14' + // defaultWidth
|
'\x8b\x14' + // defaultWidth
|
||||||
'\x8b\x15'; // nominalWidth
|
'\x8b\x15'; // nominalWidth
|
||||||
@ -2312,7 +2594,7 @@ CFF.prototype = {
|
|||||||
continue;
|
continue;
|
||||||
var value = properties.private[field];
|
var value = properties.private[field];
|
||||||
|
|
||||||
if (IsArray(value)) {
|
if (isArray(value)) {
|
||||||
data += self.encodeNumber(value[0]);
|
data += self.encodeNumber(value[0]);
|
||||||
for (var i = 1; i < value.length; i++)
|
for (var i = 1; i < value.length; i++)
|
||||||
data += self.encodeNumber(value[i] - value[i - 1]);
|
data += self.encodeNumber(value[i] - value[i - 1]);
|
||||||
@ -2343,7 +2625,7 @@ CFF.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var Type2CFF = (function() {
|
var Type2CFF = (function type2CFF() {
|
||||||
// TODO: replace parsing code with the Type2Parser in font_utils.js
|
// TODO: replace parsing code with the Type2Parser in font_utils.js
|
||||||
function constructor(file, properties) {
|
function constructor(file, properties) {
|
||||||
var bytes = file.getBytes();
|
var bytes = file.getBytes();
|
||||||
@ -2368,16 +2650,21 @@ var Type2CFF = (function() {
|
|||||||
|
|
||||||
var strings = this.getStrings(stringIndex);
|
var strings = this.getStrings(stringIndex);
|
||||||
|
|
||||||
var baseDict = this.parseDict(dictIndex.get(0));
|
var baseDict = this.parseDict(dictIndex.get(0).data);
|
||||||
var topDict = this.getTopDict(baseDict, strings);
|
var topDict = this.getTopDict(baseDict, strings);
|
||||||
|
|
||||||
var bytes = this.bytes;
|
var bytes = this.bytes;
|
||||||
|
|
||||||
|
var privateDict = {};
|
||||||
var privateInfo = topDict.Private;
|
var privateInfo = topDict.Private;
|
||||||
var privOffset = privateInfo[1], privLength = privateInfo[0];
|
if (privateInfo) {
|
||||||
var privBytes = bytes.subarray(privOffset, privOffset + privLength);
|
var privOffset = privateInfo[1], privLength = privateInfo[0];
|
||||||
baseDict = this.parseDict(privBytes);
|
var privBytes = bytes.subarray(privOffset, privOffset + privLength);
|
||||||
var privDict = this.getPrivDict(baseDict, strings);
|
baseDict = this.parseDict(privBytes);
|
||||||
|
privateDict = this.getPrivDict(baseDict, strings);
|
||||||
|
} else {
|
||||||
|
privateDict.defaultWidthX = properties.defaultWidth;
|
||||||
|
}
|
||||||
|
|
||||||
var charStrings = this.parseIndex(topDict.CharStrings);
|
var charStrings = this.parseIndex(topDict.CharStrings);
|
||||||
var charset = this.parseCharsets(topDict.charset,
|
var charset = this.parseCharsets(topDict.charset,
|
||||||
@ -2393,10 +2680,37 @@ var Type2CFF = (function() {
|
|||||||
if (hasSupplement)
|
if (hasSupplement)
|
||||||
bytes[topDict.Encoding] = 0;
|
bytes[topDict.Encoding] = 0;
|
||||||
|
|
||||||
|
// The CFF specification state that the 'dotsection' command
|
||||||
|
// (12, 0) is deprecated and treated as a no-op, but all Type2
|
||||||
|
// charstrings processors should support them. Unfortunately
|
||||||
|
// the font sanitizer don't. As a workaround the sequence (12, 0)
|
||||||
|
// is replaced by a useless (0, hmoveto).
|
||||||
|
var count = charStrings.length;
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
var charstring = charStrings.get(i);
|
||||||
|
|
||||||
|
var start = charstring.start;
|
||||||
|
var data = charstring.data;
|
||||||
|
var length = data.length;
|
||||||
|
for (var j = 0; j <= length; j) {
|
||||||
|
var value = data[j++];
|
||||||
|
if (value == 12 && data[j++] == 0) {
|
||||||
|
bytes[start + j - 2] = 139;
|
||||||
|
bytes[start + j - 1] = 22;
|
||||||
|
} else if (value === 28) {
|
||||||
|
j += 2;
|
||||||
|
} else if (value >= 247 && value <= 254) {
|
||||||
|
j++;
|
||||||
|
} else if (value == 255) {
|
||||||
|
j += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// charstrings contains info about glyphs (one element per glyph
|
// charstrings contains info about glyphs (one element per glyph
|
||||||
// containing mappings for {unicode, width})
|
// containing mappings for {unicode, width})
|
||||||
var charstrings = this.getCharStrings(charset, charStrings,
|
var charstrings = this.getCharStrings(charset, charStrings,
|
||||||
privDict, this.properties);
|
privateDict, this.properties);
|
||||||
|
|
||||||
// create the mapping between charstring and glyph id
|
// create the mapping between charstring and glyph id
|
||||||
var glyphIds = [];
|
var glyphIds = [];
|
||||||
@ -2413,13 +2727,11 @@ var Type2CFF = (function() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getCharStrings: function cff_charstrings(charsets, charStrings,
|
getCharStrings: function cff_charstrings(charsets, charStrings,
|
||||||
privDict, properties) {
|
privateDict, properties) {
|
||||||
var defaultWidth = privDict['defaultWidthX'];
|
var defaultWidth = privateDict['defaultWidthX'];
|
||||||
var nominalWidth = privDict['nominalWidthX'];
|
|
||||||
|
|
||||||
var charstrings = [];
|
var charstrings = [];
|
||||||
var differences = properties.differences;
|
var differences = properties.differences;
|
||||||
var index = 0;
|
var index = properties.firstChar || 0;
|
||||||
for (var i = 1; i < charsets.length; i++) {
|
for (var i = 1; i < charsets.length; i++) {
|
||||||
var code = -1;
|
var code = -1;
|
||||||
var glyph = charsets[i];
|
var glyph = charsets[i];
|
||||||
@ -2431,7 +2743,8 @@ var Type2CFF = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapping = properties.glyphs[glyph] || {};
|
var mapping =
|
||||||
|
properties.glyphs[glyph] || properties.glyphs[index] || {};
|
||||||
if (code == -1)
|
if (code == -1)
|
||||||
index = code = mapping.unicode || index;
|
index = code = mapping.unicode || index;
|
||||||
|
|
||||||
@ -2441,7 +2754,7 @@ var Type2CFF = (function() {
|
|||||||
var width = mapping.width;
|
var width = mapping.width;
|
||||||
properties.glyphs[glyph] = properties.encoding[index] = {
|
properties.glyphs[glyph] = properties.encoding[index] = {
|
||||||
unicode: code,
|
unicode: code,
|
||||||
width: IsNum(width) ? width : defaultWidth
|
width: isNum(width) ? width : defaultWidth
|
||||||
};
|
};
|
||||||
|
|
||||||
charstrings.push({
|
charstrings.push({
|
||||||
@ -2453,7 +2766,9 @@ var Type2CFF = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sort the array by the unicode value
|
// sort the array by the unicode value
|
||||||
charstrings.sort(function(a, b) {return a.unicode - b.unicode});
|
charstrings.sort(function type2CFFGetCharStringsSort(a, b) {
|
||||||
|
return a.unicode - b.unicode;
|
||||||
|
});
|
||||||
return charstrings;
|
return charstrings;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2473,8 +2788,8 @@ var Type2CFF = (function() {
|
|||||||
|
|
||||||
if (pos == 0 || pos == 1) {
|
if (pos == 0 || pos == 1) {
|
||||||
var gid = 1;
|
var gid = 1;
|
||||||
var baseEncoding =
|
var baseEncoding = pos ? Encodings.ExpertEncoding.slice() :
|
||||||
pos ? Encodings.ExpertEncoding : Encodings.StandardEncoding;
|
Encodings.StandardEncoding.slice();
|
||||||
for (var i = 0; i < charset.length; i++) {
|
for (var i = 0; i < charset.length; i++) {
|
||||||
var index = baseEncoding.indexOf(charset[i]);
|
var index = baseEncoding.indexOf(charset[i]);
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
@ -2519,37 +2834,42 @@ var Type2CFF = (function() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
parseCharsets: function cff_parsecharsets(pos, length, strings) {
|
parseCharsets: function cff_parsecharsets(pos, length, strings) {
|
||||||
|
if (pos == 0) {
|
||||||
|
return ISOAdobeCharset.slice();
|
||||||
|
} else if (pos == 1) {
|
||||||
|
return ExpertCharset.slice();
|
||||||
|
} else if (pos == 2) {
|
||||||
|
return ExpertSubsetCharset.slice();
|
||||||
|
}
|
||||||
|
|
||||||
var bytes = this.bytes;
|
var bytes = this.bytes;
|
||||||
var format = bytes[pos++];
|
var format = bytes[pos++];
|
||||||
var charset = ['.notdef'];
|
var charset = ['.notdef'];
|
||||||
|
|
||||||
// subtract 1 for the .notdef glyph
|
// subtract 1 for the .notdef glyph
|
||||||
length -= 1;
|
length -= 1;
|
||||||
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case 0:
|
case 0:
|
||||||
for (var i = 0; i < length; ++i) {
|
for (var i = 0; i < length; i++) {
|
||||||
var id = bytes[pos++];
|
var sid = (bytes[pos++] << 8) | bytes[pos++];
|
||||||
id = (id << 8) | bytes[pos++];
|
charset.push(strings[sid]);
|
||||||
charset.push(strings[id]);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
while (charset.length <= length) {
|
while (charset.length <= length) {
|
||||||
var first = bytes[pos++];
|
var sid = (bytes[pos++] << 8) | bytes[pos++];
|
||||||
first = (first << 8) | bytes[pos++];
|
var count = bytes[pos++];
|
||||||
var numLeft = bytes[pos++];
|
for (var i = 0; i <= count; i++)
|
||||||
for (var i = 0; i <= numLeft; ++i)
|
charset.push(strings[sid++]);
|
||||||
charset.push(strings[first++]);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
while (charset.length <= length) {
|
while (charset.length <= length) {
|
||||||
var first = bytes[pos++];
|
var sid = (bytes[pos++] << 8) | bytes[pos++];
|
||||||
first = (first << 8) | bytes[pos++];
|
var count = (bytes[pos++] << 8) | bytes[pos++];
|
||||||
var numLeft = bytes[pos++];
|
for (var i = 0; i <= count; i++)
|
||||||
numLeft = (numLeft << 8) | bytes[pos++];
|
charset.push(strings[sid++]);
|
||||||
for (var i = 0; i <= numLeft; ++i)
|
|
||||||
charset.push(strings[first++]);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2624,20 +2944,20 @@ var Type2CFF = (function() {
|
|||||||
}
|
}
|
||||||
return dict;
|
return dict;
|
||||||
},
|
},
|
||||||
getStrings: function cff_getstrings(stringIndex) {
|
getStrings: function cff_getStrings(stringIndex) {
|
||||||
function bytesToString(bytesArr) {
|
function bytesToString(bytesArray) {
|
||||||
var s = '';
|
var str = '';
|
||||||
for (var i = 0, ii = bytesArr.length; i < ii; ++i)
|
for (var i = 0, length = bytesArray.length; i < length; i++)
|
||||||
s += String.fromCharCode(bytesArr[i]);
|
str += String.fromCharCode(bytesArray[i]);
|
||||||
return s;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
var stringArray = [];
|
var stringArray = [];
|
||||||
for (var i = 0, ii = CFFStrings.length; i < ii; ++i)
|
for (var i = 0, length = CFFStrings.length; i < length; i++)
|
||||||
stringArray.push(CFFStrings[i]);
|
stringArray.push(CFFStrings[i]);
|
||||||
|
|
||||||
for (var i = 0, ii = stringIndex.length; i < ii; ++i)
|
for (var i = 0, length = stringIndex.length; i < length; i++)
|
||||||
stringArray.push(bytesToString(stringIndex.get(i)));
|
stringArray.push(bytesToString(stringIndex.get(i).data));
|
||||||
|
|
||||||
return stringArray;
|
return stringArray;
|
||||||
},
|
},
|
||||||
@ -2683,7 +3003,7 @@ var Type2CFF = (function() {
|
|||||||
} else if (value <= 254) {
|
} else if (value <= 254) {
|
||||||
return -((value - 251) * 256) - dict[pos++] - 108;
|
return -((value - 251) * 256) - dict[pos++] - 108;
|
||||||
} else {
|
} else {
|
||||||
error('Incorrect byte');
|
error('255 is not a valid DICT command');
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -2760,7 +3080,11 @@ var Type2CFF = (function() {
|
|||||||
|
|
||||||
var start = offsets[index];
|
var start = offsets[index];
|
||||||
var end = offsets[index + 1];
|
var end = offsets[index + 1];
|
||||||
return bytes.subarray(start, end);
|
return {
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
data: bytes.subarray(start, end)
|
||||||
|
};
|
||||||
},
|
},
|
||||||
length: count,
|
length: count,
|
||||||
endPos: end
|
endPos: end
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var appPath, browser, canvas, currentTaskIdx, manifest, stdout;
|
var appPath, browser, canvas, currentTaskIdx, manifest, stdout;
|
||||||
|
var inFlightRequests = 0;
|
||||||
|
|
||||||
function queryParams() {
|
function queryParams() {
|
||||||
var qs = window.location.search.substring(1);
|
var qs = window.location.search.substring(1);
|
||||||
@ -38,16 +39,28 @@ function load() {
|
|||||||
|
|
||||||
var r = new XMLHttpRequest();
|
var r = new XMLHttpRequest();
|
||||||
r.open('GET', manifestFile, false);
|
r.open('GET', manifestFile, false);
|
||||||
r.onreadystatechange = function(e) {
|
r.onreadystatechange = function loadOnreadystatechange(e) {
|
||||||
if (r.readyState == 4) {
|
if (r.readyState == 4) {
|
||||||
log('done\n');
|
log('done\n');
|
||||||
manifest = JSON.parse(r.responseText);
|
manifest = JSON.parse(r.responseText);
|
||||||
currentTaskIdx = 0, nextTask();
|
currentTaskIdx = 0;
|
||||||
|
nextTask();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
r.send(null);
|
r.send(null);
|
||||||
}
|
}
|
||||||
window.onload = load;
|
|
||||||
|
function cleanup() {
|
||||||
|
var styleSheet = document.styleSheets[0];
|
||||||
|
if (styleSheet) {
|
||||||
|
while (styleSheet.cssRules.length > 0)
|
||||||
|
styleSheet.deleteRule(0);
|
||||||
|
}
|
||||||
|
var guard = document.getElementById('content-end');
|
||||||
|
var body = document.body;
|
||||||
|
while (body.lastChild !== guard)
|
||||||
|
body.removeChild(body.lastChild);
|
||||||
|
}
|
||||||
|
|
||||||
function nextTask() {
|
function nextTask() {
|
||||||
// If there is a pdfDoc on the last task executed, destroy it to free memory.
|
// If there is a pdfDoc on the last task executed, destroy it to free memory.
|
||||||
@ -55,6 +68,8 @@ function nextTask() {
|
|||||||
task.pdfDoc.destroy();
|
task.pdfDoc.destroy();
|
||||||
delete task.pdfDoc;
|
delete task.pdfDoc;
|
||||||
}
|
}
|
||||||
|
cleanup();
|
||||||
|
|
||||||
if (currentTaskIdx == manifest.length) {
|
if (currentTaskIdx == manifest.length) {
|
||||||
return done();
|
return done();
|
||||||
}
|
}
|
||||||
@ -63,39 +78,34 @@ function nextTask() {
|
|||||||
|
|
||||||
log('Loading file "' + task.file + '"\n');
|
log('Loading file "' + task.file + '"\n');
|
||||||
|
|
||||||
var r = new XMLHttpRequest();
|
getPdf(task.file, function nextTaskGetPdf(data) {
|
||||||
r.open('GET', task.file);
|
|
||||||
r.mozResponseType = r.responseType = 'arraybuffer';
|
|
||||||
r.onreadystatechange = function() {
|
|
||||||
var failure;
|
var failure;
|
||||||
if (r.readyState == 4) {
|
try {
|
||||||
var data = r.mozResponseArrayBuffer || r.mozResponse ||
|
task.pdfDoc = new PDFDoc(data);
|
||||||
r.responseArrayBuffer || r.response;
|
} catch (e) {
|
||||||
|
failure = 'load PDF doc : ' + e.toString();
|
||||||
try {
|
|
||||||
task.pdfDoc = new WorkerPDFDoc(data);
|
|
||||||
// task.pdfDoc = new PDFDoc(new Stream(data));
|
|
||||||
} catch (e) {
|
|
||||||
failure = 'load PDF doc : ' + e.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
task.pageNum = task.firstPage || 1, nextPage(task, failure);
|
|
||||||
}
|
}
|
||||||
};
|
task.pageNum = task.firstPage || 1;
|
||||||
r.send(null);
|
nextPage(task, failure);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLastPage(task) {
|
function isLastPage(task) {
|
||||||
return (task.pageNum > task.pdfDoc.numPages);
|
return task.pageNum > task.pdfDoc.numPages || task.pageNum > task.pageLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canvasToDataURL() {
|
||||||
|
return canvas.toDataURL('image/png');
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextPage(task, loadError) {
|
function nextPage(task, loadError) {
|
||||||
var failure = loadError || '';
|
var failure = loadError || '';
|
||||||
|
|
||||||
if (!task.pdfDoc) {
|
if (!task.pdfDoc) {
|
||||||
sendTaskResult(canvas.toDataURL('image/png'), task, failure);
|
sendTaskResult(canvasToDataURL(), task, failure);
|
||||||
log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n');
|
log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n');
|
||||||
++currentTaskIdx, nextTask();
|
++currentTaskIdx;
|
||||||
|
nextTask();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,11 +114,19 @@ function nextPage(task, loadError) {
|
|||||||
log(' Round ' + (1 + task.round) + '\n');
|
log(' Round ' + (1 + task.round) + '\n');
|
||||||
task.pageNum = 1;
|
task.pageNum = 1;
|
||||||
} else {
|
} else {
|
||||||
++currentTaskIdx, nextTask();
|
++currentTaskIdx;
|
||||||
|
nextTask();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (task.skipPages && task.skipPages.indexOf(task.pageNum) >= 0) {
|
||||||
|
log(' skipping page ' + task.pageNum + '/' + task.pdfDoc.numPages +
|
||||||
|
'... ');
|
||||||
|
snapshotCurrentPage(task, '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var page = null;
|
var page = null;
|
||||||
|
|
||||||
if (!failure) {
|
if (!failure) {
|
||||||
@ -128,8 +146,8 @@ function nextPage(task, loadError) {
|
|||||||
|
|
||||||
page.startRendering(
|
page.startRendering(
|
||||||
ctx,
|
ctx,
|
||||||
function(e) {
|
function nextPageStartRendering(e) {
|
||||||
snapshotCurrentPage(page, task, (!failure && e) ?
|
snapshotCurrentPage(task, (!failure && e) ?
|
||||||
('render : ' + e) : failure);
|
('render : ' + e) : failure);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -141,21 +159,22 @@ function nextPage(task, loadError) {
|
|||||||
if (failure) {
|
if (failure) {
|
||||||
// Skip right to snapshotting if there was a failure, since the
|
// Skip right to snapshotting if there was a failure, since the
|
||||||
// fonts might be in an inconsistent state.
|
// 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... ');
|
log('done, snapshotting... ');
|
||||||
|
|
||||||
sendTaskResult(canvas.toDataURL('image/png'), task, failure);
|
sendTaskResult(canvasToDataURL(), task, failure);
|
||||||
log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n');
|
log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n');
|
||||||
|
|
||||||
// Set up the next request
|
// Set up the next request
|
||||||
var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0;
|
var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0;
|
||||||
setTimeout(
|
setTimeout(
|
||||||
function() {
|
function snapshotCurrentPageSetTimeout() {
|
||||||
++task.pageNum, nextPage(task);
|
++task.pageNum;
|
||||||
|
nextPage(task);
|
||||||
},
|
},
|
||||||
backoff
|
backoff
|
||||||
);
|
);
|
||||||
@ -188,11 +207,11 @@ function done() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var inFlightRequests = 0;
|
|
||||||
function sendTaskResult(snapshot, task, failure) {
|
function sendTaskResult(snapshot, task, failure) {
|
||||||
var result = { browser: browser,
|
var result = { browser: browser,
|
||||||
id: task.id,
|
id: task.id,
|
||||||
numPages: task.pdfDoc ? task.pdfDoc.numPages : 0,
|
numPages: task.pdfDoc ?
|
||||||
|
(task.pageLimit || task.pdfDoc.numPages) : 0,
|
||||||
failure: failure,
|
failure: failure,
|
||||||
file: task.file,
|
file: task.file,
|
||||||
round: task.round,
|
round: task.round,
|
||||||
@ -203,11 +222,11 @@ function sendTaskResult(snapshot, task, failure) {
|
|||||||
// (The POST URI is ignored atm.)
|
// (The POST URI is ignored atm.)
|
||||||
r.open('POST', '/submit_task_results', true);
|
r.open('POST', '/submit_task_results', true);
|
||||||
r.setRequestHeader('Content-Type', 'application/json');
|
r.setRequestHeader('Content-Type', 'application/json');
|
||||||
r.onreadystatechange = function(e) {
|
r.onreadystatechange = function sendTaskResultOnreadystatechange(e) {
|
||||||
if (r.readyState == 4) {
|
if (r.readyState == 4) {
|
||||||
inFlightRequests--;
|
inFlightRequests--;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
document.getElementById('inFlightCount').innerHTML = inFlightRequests++;
|
document.getElementById('inFlightCount').innerHTML = inFlightRequests++;
|
||||||
r.send(JSON.stringify(result));
|
r.send(JSON.stringify(result));
|
||||||
}
|
}
|
||||||
|
18
test/pdfs/.gitignore
vendored
18
test/pdfs/.gitignore
vendored
@ -1,3 +1,15 @@
|
|||||||
pdf.pdf
|
*.pdf
|
||||||
intelisa.pdf
|
|
||||||
openweb_tm-PRINT.pdf
|
!tracemonkey.pdf
|
||||||
|
!ArabicCIDTrueType.pdf
|
||||||
|
!ThuluthFeatures.pdf
|
||||||
|
!arial_unicode_ab_cidfont.pdf
|
||||||
|
!arial_unicode_en_cidfont.pdf
|
||||||
|
!asciihexdecode.pdf
|
||||||
|
!canvas.pdf
|
||||||
|
!complex_ttf_font.pdf
|
||||||
|
!extgstate.pdf
|
||||||
|
!rotation.pdf
|
||||||
|
!simpletype3font.pdf
|
||||||
|
!sizes.pdf
|
||||||
|
|
||||||
|
BIN
test/pdfs/ThuluthFeatures.pdf
Executable file
BIN
test/pdfs/ThuluthFeatures.pdf
Executable file
Binary file not shown.
105
test/pdfs/extgstate.pdf
Normal file
105
test/pdfs/extgstate.pdf
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
%PDF-1.4
|
||||||
|
%öäüß
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Catalog
|
||||||
|
/Version /1.4
|
||||||
|
/Pages 2 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Pages
|
||||||
|
/Kids [3 0 R]
|
||||||
|
/Count 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Page
|
||||||
|
/MediaBox [0 0 612 792]
|
||||||
|
/Resources 4 0 R
|
||||||
|
/Parent 2 0 R
|
||||||
|
/Contents 5 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/ExtGState 6 0 R
|
||||||
|
/Font 7 0 R
|
||||||
|
/XObject <<
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
5 0 obj
|
||||||
|
<<
|
||||||
|
/Length 8 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
/GS1 gs
|
||||||
|
/F0 12 Tf
|
||||||
|
BT
|
||||||
|
100 700 Td
|
||||||
|
(I should be courier!) Tj
|
||||||
|
ET
|
||||||
|
50 600 m
|
||||||
|
400 600 l
|
||||||
|
S
|
||||||
|
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
6 0 obj
|
||||||
|
<<
|
||||||
|
/GS1 9 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
7 0 obj
|
||||||
|
<<
|
||||||
|
/F0 10 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
8 0 obj
|
||||||
|
82
|
||||||
|
endobj
|
||||||
|
9 0 obj
|
||||||
|
<<
|
||||||
|
/Type /ExtGState
|
||||||
|
/LW 10
|
||||||
|
/LC 1
|
||||||
|
/LJ 2
|
||||||
|
/ML 0.3000000119
|
||||||
|
/D [[0.0917000026 183.3300018311]
|
||||||
|
0]
|
||||||
|
/Font [10 0 R 36]
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
10 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Font
|
||||||
|
/Subtype /Type1
|
||||||
|
/BaseFont /Courier
|
||||||
|
/Encoding /WinAnsiEncoding
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
xref
|
||||||
|
0 11
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000015 00000 n
|
||||||
|
0000000078 00000 n
|
||||||
|
0000000135 00000 n
|
||||||
|
0000000239 00000 n
|
||||||
|
0000000304 00000 n
|
||||||
|
0000000441 00000 n
|
||||||
|
0000000473 00000 n
|
||||||
|
0000000505 00000 n
|
||||||
|
0000000523 00000 n
|
||||||
|
0000000653 00000 n
|
||||||
|
trailer
|
||||||
|
<<
|
||||||
|
/Root 1 0 R
|
||||||
|
/ID [<BFFF29B7D1C75EC69AC080682C2AFC5B> <BFFF29B7D1C75EC69AC080682C2AFC5B>]
|
||||||
|
/Size 11
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
749
|
||||||
|
%%EOF
|
1
test/pdfs/f1040.pdf.link
Normal file
1
test/pdfs/f1040.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://www.irs.gov/pub/irs-pdf/f1040.pdf
|
1
test/pdfs/fips197.pdf.link
Normal file
1
test/pdfs/fips197.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
1
test/pdfs/hudsonsurvey.pdf.link
Normal file
1
test/pdfs/hudsonsurvey.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://issues.apache.org/jira/secure/attachment/12421789/survey.pdf
|
1
test/pdfs/ibwa-bad.pdf.link
Normal file
1
test/pdfs/ibwa-bad.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://www.bottledwater.org/public/pdf/IBWA05ModelCode_Mar2.pdf
|
141
test/pdfs/simpletype3font.pdf
Normal file
141
test/pdfs/simpletype3font.pdf
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
%PDF-1.4
|
||||||
|
%öäüß
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Catalog
|
||||||
|
/Version /1.4
|
||||||
|
/Pages 2 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Pages
|
||||||
|
/Kids [3 0 R]
|
||||||
|
/Count 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Page
|
||||||
|
/MediaBox [0 0 612 792]
|
||||||
|
/Parent 2 0 R
|
||||||
|
/Resources 4 0 R
|
||||||
|
/Contents 5 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/Font 6 0 R
|
||||||
|
/XObject <<
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
5 0 obj
|
||||||
|
<<
|
||||||
|
/Length 7 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
/F0 12 Tf
|
||||||
|
BT
|
||||||
|
100 700 Td
|
||||||
|
(ababab) Tj
|
||||||
|
ET
|
||||||
|
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
6 0 obj
|
||||||
|
<<
|
||||||
|
/F0 8 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
7 0 obj
|
||||||
|
39
|
||||||
|
endobj
|
||||||
|
8 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Font
|
||||||
|
/Subtype /Type3
|
||||||
|
/FontBBox [0 0 750 750]
|
||||||
|
/FontMatrix [0.001 0 0 0.001 0 0]
|
||||||
|
/CharProcs 9 0 R
|
||||||
|
/Encoding 10 0 R
|
||||||
|
/FirstChar 97
|
||||||
|
/LastChar 98
|
||||||
|
/Widths [1000 1000]
|
||||||
|
/FontDescriptor 11 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
9 0 obj
|
||||||
|
<<
|
||||||
|
/square 12 0 R
|
||||||
|
/triangle 13 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
10 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Encoding
|
||||||
|
/Differences [97 /square /triangle]
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
11 0 obj
|
||||||
|
<<
|
||||||
|
/Type /FontDescriptor
|
||||||
|
/FontName /SandT
|
||||||
|
/Flags 262178
|
||||||
|
/Ascent 0
|
||||||
|
/CapHeight 0
|
||||||
|
/Descent 0
|
||||||
|
/ItalicAngle 0
|
||||||
|
/StemV 0
|
||||||
|
/FontBBox [0 0 750 750]
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
12 0 obj
|
||||||
|
<<
|
||||||
|
/Length 14 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
1000 0 0 0 750 750 d1 0 0 750 750 re f
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
13 0 obj
|
||||||
|
<<
|
||||||
|
/Length 15 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
1000 0 0 0 750 750 d1 0 0 m 375 750 l 750 0 l f
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
14 0 obj
|
||||||
|
38
|
||||||
|
endobj
|
||||||
|
15 0 obj
|
||||||
|
47
|
||||||
|
endobj
|
||||||
|
xref
|
||||||
|
0 16
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000015 00000 n
|
||||||
|
0000000078 00000 n
|
||||||
|
0000000135 00000 n
|
||||||
|
0000000239 00000 n
|
||||||
|
0000000287 00000 n
|
||||||
|
0000000381 00000 n
|
||||||
|
0000000412 00000 n
|
||||||
|
0000000430 00000 n
|
||||||
|
0000000641 00000 n
|
||||||
|
0000000694 00000 n
|
||||||
|
0000000768 00000 n
|
||||||
|
0000000925 00000 n
|
||||||
|
0000001020 00000 n
|
||||||
|
0000001124 00000 n
|
||||||
|
0000001143 00000 n
|
||||||
|
trailer
|
||||||
|
<<
|
||||||
|
/Root 1 0 R
|
||||||
|
/ID [<DD02410A8B7AD4A0EE0D50E4180FABAC> <DD02410A8B7AD4A0EE0D50E4180FABAC>]
|
||||||
|
/Size 16
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
1162
|
||||||
|
%%EOF
|
1
test/pdfs/tcpdf_033.pdf.link
Normal file
1
test/pdfs/tcpdf_033.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://www.tcpdf.org/examples/example_033.pdf
|
1
test/pdfs/txt2pdf.pdf.link
Normal file
1
test/pdfs/txt2pdf.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://www.sanface.com/pdf/test.pdf
|
1
test/pdfs/unix01.pdf.link
Normal file
1
test/pdfs/unix01.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://docs.rice.edu/confluence/download/attachments/4588376/unix01.pdf?version=1
|
1
test/pdfs/usmanm-bad.pdf.link
Normal file
1
test/pdfs/usmanm-bad.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://www.mit.edu/~6.033/writing-samples/usmanm_dp1.pdf
|
1
test/pdfs/vesta.pdf.link
Normal file
1
test/pdfs/vesta.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://www-csag.ucsd.edu/~jburke/Vesta/Vesta_Overview.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
|
1
test/pdfs/wnv_chinese.pdf.link
Normal file
1
test/pdfs/wnv_chinese.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://www.cdc.gov/ncidod/dvbid/westnile/languages/chinese.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
|
||||||
|
|
26
test/test.py
26
test/test.py
@ -23,6 +23,8 @@ class TestOptions(OptionParser):
|
|||||||
OptionParser.__init__(self, **kwargs)
|
OptionParser.__init__(self, **kwargs)
|
||||||
self.add_option("-m", "--masterMode", action="store_true", dest="masterMode",
|
self.add_option("-m", "--masterMode", action="store_true", dest="masterMode",
|
||||||
help="Run the script in master mode.", default=False)
|
help="Run the script in master mode.", default=False)
|
||||||
|
self.add_option("--noPrompts", action="store_true", dest="noPrompts",
|
||||||
|
help="Uses default answers (intended for CLOUD TESTS only!).", default=False)
|
||||||
self.add_option("--manifestFile", action="store", type="string", dest="manifestFile",
|
self.add_option("--manifestFile", action="store", type="string", dest="manifestFile",
|
||||||
help="A JSON file in the form of test_manifest.json (the default).")
|
help="A JSON file in the form of test_manifest.json (the default).")
|
||||||
self.add_option("-b", "--browser", action="store", type="string", dest="browser",
|
self.add_option("-b", "--browser", action="store", type="string", dest="browser",
|
||||||
@ -321,7 +323,7 @@ def setUp(options):
|
|||||||
if options.masterMode and os.path.isdir(TMPDIR):
|
if options.masterMode and os.path.isdir(TMPDIR):
|
||||||
print 'Temporary snapshot dir tmp/ is still around.'
|
print 'Temporary snapshot dir tmp/ is still around.'
|
||||||
print 'tmp/ can be removed if it has nothing you need.'
|
print 'tmp/ can be removed if it has nothing you need.'
|
||||||
if prompt('SHOULD THIS SCRIPT REMOVE tmp/? THINK CAREFULLY'):
|
if options.noPrompts or prompt('SHOULD THIS SCRIPT REMOVE tmp/? THINK CAREFULLY'):
|
||||||
subprocess.call(( 'rm', '-rf', 'tmp' ))
|
subprocess.call(( 'rm', '-rf', 'tmp' ))
|
||||||
|
|
||||||
assert not os.path.isdir(TMPDIR)
|
assert not os.path.isdir(TMPDIR)
|
||||||
@ -414,8 +416,9 @@ def checkEq(task, results, browser, masterMode):
|
|||||||
|
|
||||||
path = os.path.join(pfx, str(page + 1))
|
path = os.path.join(pfx, str(page + 1))
|
||||||
if not os.access(path, os.R_OK):
|
if not os.access(path, os.R_OK):
|
||||||
print 'WARNING: no reference snapshot', path
|
|
||||||
State.numEqNoSnapshot += 1
|
State.numEqNoSnapshot += 1
|
||||||
|
if not masterMode:
|
||||||
|
print 'WARNING: no reference snapshot', path
|
||||||
else:
|
else:
|
||||||
f = open(path)
|
f = open(path)
|
||||||
ref = f.read()
|
ref = f.read()
|
||||||
@ -432,9 +435,9 @@ def checkEq(task, results, browser, masterMode):
|
|||||||
# NB: this follows the format of Mozilla reftest
|
# NB: this follows the format of Mozilla reftest
|
||||||
# output so that we can reuse its reftest-analyzer
|
# output so that we can reuse its reftest-analyzer
|
||||||
# script
|
# script
|
||||||
print >>eqLog, 'REFTEST TEST-UNEXPECTED-FAIL |', browser +'-'+ taskId +'-page'+ str(page + 1), '| image comparison (==)'
|
eqLog.write('REFTEST TEST-UNEXPECTED-FAIL | ' + browser +'-'+ taskId +'-page'+ str(page + 1) + ' | image comparison (==)\n')
|
||||||
print >>eqLog, 'REFTEST IMAGE 1 (TEST):', snapshot
|
eqLog.write('REFTEST IMAGE 1 (TEST): ' + snapshot + '\n')
|
||||||
print >>eqLog, 'REFTEST IMAGE 2 (REFERENCE):', ref
|
eqLog.write('REFTEST IMAGE 2 (REFERENCE): ' + ref + '\n')
|
||||||
|
|
||||||
passed = False
|
passed = False
|
||||||
State.numEqFailures += 1
|
State.numEqFailures += 1
|
||||||
@ -444,8 +447,9 @@ def checkEq(task, results, browser, masterMode):
|
|||||||
try:
|
try:
|
||||||
os.makedirs(tmpTaskDir)
|
os.makedirs(tmpTaskDir)
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
print >>sys.stderr, 'Creating', tmpTaskDir, 'failed!'
|
if e.errno != 17: # file exists
|
||||||
|
print >>sys.stderr, 'Creating', tmpTaskDir, 'failed!'
|
||||||
|
|
||||||
of = open(os.path.join(tmpTaskDir, str(page + 1)), 'w')
|
of = open(os.path.join(tmpTaskDir, str(page + 1)), 'w')
|
||||||
of.write(snapshot)
|
of.write(snapshot)
|
||||||
of.close()
|
of.close()
|
||||||
@ -453,7 +457,6 @@ def checkEq(task, results, browser, masterMode):
|
|||||||
if passed:
|
if passed:
|
||||||
print 'TEST-PASS | eq test', task['id'], '| in', browser
|
print 'TEST-PASS | eq test', task['id'], '| in', browser
|
||||||
|
|
||||||
|
|
||||||
def checkFBF(task, results, browser):
|
def checkFBF(task, results, browser):
|
||||||
round0, round1 = results[0], results[1]
|
round0, round1 = results[0], results[1]
|
||||||
assert len(round0) == len(round1)
|
assert len(round0) == len(round1)
|
||||||
@ -503,10 +506,10 @@ def maybeUpdateRefImages(options, browser):
|
|||||||
print ' Yes! The references in tmp/ can be synced with ref/.'
|
print ' Yes! The references in tmp/ can be synced with ref/.'
|
||||||
if options.reftest:
|
if options.reftest:
|
||||||
startReftest(browser, options)
|
startReftest(browser, options)
|
||||||
if not prompt('Would you like to update the master copy in ref/?'):
|
if options.noPrompts or not prompt('Would you like to update the master copy in ref/?'):
|
||||||
print ' OK, not updating.'
|
print ' OK, not updating.'
|
||||||
else:
|
else:
|
||||||
sys.stdout.write(' Updating ... ')
|
sys.stdout.write(' Updating ref/ ... ')
|
||||||
|
|
||||||
# XXX unclear what to do on errors here ...
|
# XXX unclear what to do on errors here ...
|
||||||
# NB: do *NOT* pass --delete to rsync. That breaks this
|
# NB: do *NOT* pass --delete to rsync. That breaks this
|
||||||
@ -539,7 +542,8 @@ def runTests(options, browsers):
|
|||||||
teardownBrowsers(browsers)
|
teardownBrowsers(browsers)
|
||||||
t2 = time.time()
|
t2 = time.time()
|
||||||
print "Runtime was", int(t2 - t1), "seconds"
|
print "Runtime was", int(t2 - t1), "seconds"
|
||||||
|
if State.eqLog:
|
||||||
|
State.eqLog.close();
|
||||||
if options.masterMode:
|
if options.masterMode:
|
||||||
maybeUpdateRefImages(options, browsers[0])
|
maybeUpdateRefImages(options, browsers[0])
|
||||||
elif options.reftest and State.numEqFailures > 0:
|
elif options.reftest and State.numEqFailures > 0:
|
||||||
|
@ -69,6 +69,17 @@
|
|||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "load"
|
"type": "load"
|
||||||
},
|
},
|
||||||
|
{ "id": "thuluthfont-pdf",
|
||||||
|
"file": "pdfs/ThuluthFeatures.pdf",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "wnv_chinese-pdf",
|
||||||
|
"file": "pdfs/wnv_chinese.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "i9-pdf",
|
{ "id": "i9-pdf",
|
||||||
"file": "pdfs/i9.pdf",
|
"file": "pdfs/i9.pdf",
|
||||||
"link": true,
|
"link": true,
|
||||||
@ -115,5 +126,78 @@
|
|||||||
"link": true,
|
"link": true,
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "wdsg_fitc",
|
||||||
|
"file": "pdfs/wdsg_fitc.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "unix01",
|
||||||
|
"file": "pdfs/unix01.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "fips197",
|
||||||
|
"file": "pdfs/fips197.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "load"
|
||||||
|
},
|
||||||
|
{ "id": "txt2pdf",
|
||||||
|
"file": "pdfs/txt2pdf.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "load"
|
||||||
|
},
|
||||||
|
{ "id": "f1040",
|
||||||
|
"file": "pdfs/f1040.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "load"
|
||||||
|
},
|
||||||
|
{ "id": "hudsonsurvey",
|
||||||
|
"file": "pdfs/hudsonsurvey.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "load"
|
||||||
|
},
|
||||||
|
{ "id": "extgstate",
|
||||||
|
"file": "pdfs/extgstate.pdf",
|
||||||
|
"link": false,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "load"
|
||||||
|
},
|
||||||
|
{ "id": "usmanm-bad",
|
||||||
|
"file": "pdfs/usmanm-bad.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "vesta-bad",
|
||||||
|
"file": "pdfs/vesta.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "load"
|
||||||
|
},
|
||||||
|
{ "id": "ibwa-bad",
|
||||||
|
"file": "pdfs/ibwa-bad.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"skipPages": [ 16 ],
|
||||||
|
"type": "load"
|
||||||
|
},
|
||||||
|
{ "id": "tcpdf_033",
|
||||||
|
"file": "pdfs/tcpdf_033.pdf",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "simpletype3font",
|
||||||
|
"file": "pdfs/simpletype3font.pdf",
|
||||||
|
"link": false,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
<script type="text/javascript" src="/crypto.js"></script>
|
<script type="text/javascript" src="/crypto.js"></script>
|
||||||
<script type="text/javascript" src="/glyphlist.js"></script>
|
<script type="text/javascript" src="/glyphlist.js"></script>
|
||||||
<script type="text/javascript" src="/metrics.js"></script>
|
<script type="text/javascript" src="/metrics.js"></script>
|
||||||
|
<script type="text/javascript" src="/charsets.js"></script>
|
||||||
|
<script type="text/javascript" src="/cidmaps.js"></script>
|
||||||
<script type="text/javascript" src="driver.js"></script>
|
<script type="text/javascript" src="driver.js"></script>
|
||||||
<script type="text/javascript" src="../worker.js"></script>
|
<script type="text/javascript" src="../worker.js"></script>
|
||||||
<script type="text/javascript" src="../worker/message_handler.js"></script>
|
<script type="text/javascript" src="../worker/message_handler.js"></script>
|
||||||
@ -17,6 +19,7 @@
|
|||||||
<body onload="load();">
|
<body onload="load();">
|
||||||
<pre style="width:800; height:800; overflow: scroll;"id="stdout"></pre>
|
<pre style="width:800; height:800; overflow: scroll;"id="stdout"></pre>
|
||||||
<p>Inflight requests: <span id="inFlightCount"></span></p>
|
<p>Inflight requests: <span id="inFlightCount"></span></p>
|
||||||
|
<div id="content-end"><!-- cleanup() guard --></div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -3,400 +3,6 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var CFFStrings = [
|
|
||||||
'.notdef',
|
|
||||||
'space',
|
|
||||||
'exclam',
|
|
||||||
'quotedbl',
|
|
||||||
'numbersign',
|
|
||||||
'dollar',
|
|
||||||
'percent',
|
|
||||||
'ampersand',
|
|
||||||
'quoteright',
|
|
||||||
'parenleft',
|
|
||||||
'parenright',
|
|
||||||
'asterisk',
|
|
||||||
'plus',
|
|
||||||
'comma',
|
|
||||||
'hyphen',
|
|
||||||
'period',
|
|
||||||
'slash',
|
|
||||||
'zero',
|
|
||||||
'one',
|
|
||||||
'two',
|
|
||||||
'three',
|
|
||||||
'four',
|
|
||||||
'five',
|
|
||||||
'six',
|
|
||||||
'seven',
|
|
||||||
'eight',
|
|
||||||
'nine',
|
|
||||||
'colon',
|
|
||||||
'semicolon',
|
|
||||||
'less',
|
|
||||||
'equal',
|
|
||||||
'greater',
|
|
||||||
'question',
|
|
||||||
'at',
|
|
||||||
'A',
|
|
||||||
'B',
|
|
||||||
'C',
|
|
||||||
'D',
|
|
||||||
'E',
|
|
||||||
'F',
|
|
||||||
'G',
|
|
||||||
'H',
|
|
||||||
'I',
|
|
||||||
'J',
|
|
||||||
'K',
|
|
||||||
'L',
|
|
||||||
'M',
|
|
||||||
'N',
|
|
||||||
'O',
|
|
||||||
'P',
|
|
||||||
'Q',
|
|
||||||
'R',
|
|
||||||
'S',
|
|
||||||
'T',
|
|
||||||
'U',
|
|
||||||
'V',
|
|
||||||
'W',
|
|
||||||
'X',
|
|
||||||
'Y',
|
|
||||||
'Z',
|
|
||||||
'bracketleft',
|
|
||||||
'backslash',
|
|
||||||
'bracketright',
|
|
||||||
'asciicircum',
|
|
||||||
'underscore',
|
|
||||||
'quoteleft',
|
|
||||||
'a',
|
|
||||||
'b',
|
|
||||||
'c',
|
|
||||||
'd',
|
|
||||||
'e',
|
|
||||||
'f',
|
|
||||||
'g',
|
|
||||||
'h',
|
|
||||||
'i',
|
|
||||||
'j',
|
|
||||||
'k',
|
|
||||||
'l',
|
|
||||||
'm',
|
|
||||||
'n',
|
|
||||||
'o',
|
|
||||||
'p',
|
|
||||||
'q',
|
|
||||||
'r',
|
|
||||||
's',
|
|
||||||
't',
|
|
||||||
'u',
|
|
||||||
'v',
|
|
||||||
'w',
|
|
||||||
'x',
|
|
||||||
'y',
|
|
||||||
'z',
|
|
||||||
'braceleft',
|
|
||||||
'bar',
|
|
||||||
'braceright',
|
|
||||||
'asciitilde',
|
|
||||||
'exclamdown',
|
|
||||||
'cent',
|
|
||||||
'sterling',
|
|
||||||
'fraction',
|
|
||||||
'yen',
|
|
||||||
'florin',
|
|
||||||
'section',
|
|
||||||
'currency',
|
|
||||||
'quotesingle',
|
|
||||||
'quotedblleft',
|
|
||||||
'guillemotleft',
|
|
||||||
'guilsinglleft',
|
|
||||||
'guilsinglright',
|
|
||||||
'fi',
|
|
||||||
'fl',
|
|
||||||
'endash',
|
|
||||||
'dagger',
|
|
||||||
'daggerdbl',
|
|
||||||
'periodcentered',
|
|
||||||
'paragraph',
|
|
||||||
'bullet',
|
|
||||||
'quotesinglbase',
|
|
||||||
'quotedblbase',
|
|
||||||
'quotedblright',
|
|
||||||
'guillemotright',
|
|
||||||
'ellipsis',
|
|
||||||
'perthousand',
|
|
||||||
'questiondown',
|
|
||||||
'grave',
|
|
||||||
'acute',
|
|
||||||
'circumflex',
|
|
||||||
'tilde',
|
|
||||||
'macron',
|
|
||||||
'breve',
|
|
||||||
'dotaccent',
|
|
||||||
'dieresis',
|
|
||||||
'ring',
|
|
||||||
'cedilla',
|
|
||||||
'hungarumlaut',
|
|
||||||
'ogonek',
|
|
||||||
'caron',
|
|
||||||
'emdash',
|
|
||||||
'AE',
|
|
||||||
'ordfeminine',
|
|
||||||
'Lslash',
|
|
||||||
'Oslash',
|
|
||||||
'OE',
|
|
||||||
'ordmasculine',
|
|
||||||
'ae',
|
|
||||||
'dotlessi',
|
|
||||||
'lslash',
|
|
||||||
'oslash',
|
|
||||||
'oe',
|
|
||||||
'germandbls',
|
|
||||||
'onesuperior',
|
|
||||||
'logicalnot',
|
|
||||||
'mu',
|
|
||||||
'trademark',
|
|
||||||
'Eth',
|
|
||||||
'onehalf',
|
|
||||||
'plusminus',
|
|
||||||
'Thorn',
|
|
||||||
'onequarter',
|
|
||||||
'divide',
|
|
||||||
'brokenbar',
|
|
||||||
'degree',
|
|
||||||
'thorn',
|
|
||||||
'threequarters',
|
|
||||||
'twosuperior',
|
|
||||||
'registered',
|
|
||||||
'minus',
|
|
||||||
'eth',
|
|
||||||
'multiply',
|
|
||||||
'threesuperior',
|
|
||||||
'copyright',
|
|
||||||
'Aacute',
|
|
||||||
'Acircumflex',
|
|
||||||
'Adieresis',
|
|
||||||
'Agrave',
|
|
||||||
'Aring',
|
|
||||||
'Atilde',
|
|
||||||
'Ccedilla',
|
|
||||||
'Eacute',
|
|
||||||
'Ecircumflex',
|
|
||||||
'Edieresis',
|
|
||||||
'Egrave',
|
|
||||||
'Iacute',
|
|
||||||
'Icircumflex',
|
|
||||||
'Idieresis',
|
|
||||||
'Igrave',
|
|
||||||
'Ntilde',
|
|
||||||
'Oacute',
|
|
||||||
'Ocircumflex',
|
|
||||||
'Odieresis',
|
|
||||||
'Ograve',
|
|
||||||
'Otilde',
|
|
||||||
'Scaron',
|
|
||||||
'Uacute',
|
|
||||||
'Ucircumflex',
|
|
||||||
'Udieresis',
|
|
||||||
'Ugrave',
|
|
||||||
'Yacute',
|
|
||||||
'Ydieresis',
|
|
||||||
'Zcaron',
|
|
||||||
'aacute',
|
|
||||||
'acircumflex',
|
|
||||||
'adieresis',
|
|
||||||
'agrave',
|
|
||||||
'aring',
|
|
||||||
'atilde',
|
|
||||||
'ccedilla',
|
|
||||||
'eacute',
|
|
||||||
'ecircumflex',
|
|
||||||
'edieresis',
|
|
||||||
'egrave',
|
|
||||||
'iacute',
|
|
||||||
'icircumflex',
|
|
||||||
'idieresis',
|
|
||||||
'igrave',
|
|
||||||
'ntilde',
|
|
||||||
'oacute',
|
|
||||||
'ocircumflex',
|
|
||||||
'odieresis',
|
|
||||||
'ograve',
|
|
||||||
'otilde',
|
|
||||||
'scaron',
|
|
||||||
'uacute',
|
|
||||||
'ucircumflex',
|
|
||||||
'udieresis',
|
|
||||||
'ugrave',
|
|
||||||
'yacute',
|
|
||||||
'ydieresis',
|
|
||||||
'zcaron',
|
|
||||||
'exclamsmall',
|
|
||||||
'Hungarumlautsmall',
|
|
||||||
'dollaroldstyle',
|
|
||||||
'dollarsuperior',
|
|
||||||
'ampersandsmall',
|
|
||||||
'Acutesmall',
|
|
||||||
'parenleftsuperior',
|
|
||||||
'parenrightsuperior',
|
|
||||||
'266 ff',
|
|
||||||
'onedotenleader',
|
|
||||||
'zerooldstyle',
|
|
||||||
'oneoldstyle',
|
|
||||||
'twooldstyle',
|
|
||||||
'threeoldstyle',
|
|
||||||
'fouroldstyle',
|
|
||||||
'fiveoldstyle',
|
|
||||||
'sixoldstyle',
|
|
||||||
'sevenoldstyle',
|
|
||||||
'eightoldstyle',
|
|
||||||
'nineoldstyle',
|
|
||||||
'commasuperior',
|
|
||||||
'threequartersemdash',
|
|
||||||
'periodsuperior',
|
|
||||||
'questionsmall',
|
|
||||||
'asuperior',
|
|
||||||
'bsuperior',
|
|
||||||
'centsuperior',
|
|
||||||
'dsuperior',
|
|
||||||
'esuperior',
|
|
||||||
'isuperior',
|
|
||||||
'lsuperior',
|
|
||||||
'msuperior',
|
|
||||||
'nsuperior',
|
|
||||||
'osuperior',
|
|
||||||
'rsuperior',
|
|
||||||
'ssuperior',
|
|
||||||
'tsuperior',
|
|
||||||
'ff',
|
|
||||||
'ffi',
|
|
||||||
'ffl',
|
|
||||||
'parenleftinferior',
|
|
||||||
'parenrightinferior',
|
|
||||||
'Circumflexsmall',
|
|
||||||
'hyphensuperior',
|
|
||||||
'Gravesmall',
|
|
||||||
'Asmall',
|
|
||||||
'Bsmall',
|
|
||||||
'Csmall',
|
|
||||||
'Dsmall',
|
|
||||||
'Esmall',
|
|
||||||
'Fsmall',
|
|
||||||
'Gsmall',
|
|
||||||
'Hsmall',
|
|
||||||
'Ismall',
|
|
||||||
'Jsmall',
|
|
||||||
'Ksmall',
|
|
||||||
'Lsmall',
|
|
||||||
'Msmall',
|
|
||||||
'Nsmall',
|
|
||||||
'Osmall',
|
|
||||||
'Psmall',
|
|
||||||
'Qsmall',
|
|
||||||
'Rsmall',
|
|
||||||
'Ssmall',
|
|
||||||
'Tsmall',
|
|
||||||
'Usmall',
|
|
||||||
'Vsmall',
|
|
||||||
'Wsmall',
|
|
||||||
'Xsmall',
|
|
||||||
'Ysmall',
|
|
||||||
'Zsmall',
|
|
||||||
'colonmonetary',
|
|
||||||
'onefitted',
|
|
||||||
'rupiah',
|
|
||||||
'Tildesmall',
|
|
||||||
'exclamdownsmall',
|
|
||||||
'centoldstyle',
|
|
||||||
'Lslashsmall',
|
|
||||||
'Scaronsmall',
|
|
||||||
'Zcaronsmall',
|
|
||||||
'Dieresissmall',
|
|
||||||
'Brevesmall',
|
|
||||||
'Caronsmall',
|
|
||||||
'Dotaccentsmall',
|
|
||||||
'Macronsmall',
|
|
||||||
'figuredash',
|
|
||||||
'hypheninferior',
|
|
||||||
'Ogoneksmall',
|
|
||||||
'Ringsmall',
|
|
||||||
'Cedillasmall',
|
|
||||||
'questiondownsmall',
|
|
||||||
'oneeighth',
|
|
||||||
'threeeighths',
|
|
||||||
'fiveeighths',
|
|
||||||
'seveneighths',
|
|
||||||
'onethird',
|
|
||||||
'twothirds',
|
|
||||||
'zerosuperior',
|
|
||||||
'foursuperior',
|
|
||||||
'fivesuperior',
|
|
||||||
'sixsuperior',
|
|
||||||
'sevensuperior',
|
|
||||||
'eightsuperior',
|
|
||||||
'ninesuperior',
|
|
||||||
'zeroinferior',
|
|
||||||
'oneinferior',
|
|
||||||
'twoinferior',
|
|
||||||
'threeinferior',
|
|
||||||
'fourinferior',
|
|
||||||
'fiveinferior',
|
|
||||||
'sixinferior',
|
|
||||||
'seveninferior',
|
|
||||||
'eightinferior',
|
|
||||||
'nineinferior',
|
|
||||||
'centinferior',
|
|
||||||
'dollarinferior',
|
|
||||||
'periodinferior',
|
|
||||||
'commainferior',
|
|
||||||
'Agravesmall',
|
|
||||||
'Aacutesmall',
|
|
||||||
'Acircumflexsmall',
|
|
||||||
'Atildesmall',
|
|
||||||
'Adieresissmall',
|
|
||||||
'Aringsmall',
|
|
||||||
'AEsmall',
|
|
||||||
'Ccedillasmall',
|
|
||||||
'Egravesmall',
|
|
||||||
'Eacutesmall',
|
|
||||||
'Ecircumflexsmall',
|
|
||||||
'Edieresissmall',
|
|
||||||
'Igravesmall',
|
|
||||||
'Iacutesmall',
|
|
||||||
'Icircumflexsmall',
|
|
||||||
'Idieresissmall',
|
|
||||||
'Ethsmall',
|
|
||||||
'Ntildesmall',
|
|
||||||
'Ogravesmall',
|
|
||||||
'Oacutesmall',
|
|
||||||
'Ocircumflexsmall',
|
|
||||||
'Otildesmall',
|
|
||||||
'Odieresissmall',
|
|
||||||
'OEsmall',
|
|
||||||
'Oslashsmall',
|
|
||||||
'Ugravesmall',
|
|
||||||
'Uacutesmall',
|
|
||||||
'Ucircumflexsmall',
|
|
||||||
'Udieresissmall',
|
|
||||||
'Yacutesmall',
|
|
||||||
'Thornsmall',
|
|
||||||
'Ydieresissmall',
|
|
||||||
'001.000',
|
|
||||||
'001.001',
|
|
||||||
'001.002',
|
|
||||||
'001.003',
|
|
||||||
'Black',
|
|
||||||
'Bold',
|
|
||||||
'Book',
|
|
||||||
'Light',
|
|
||||||
'Medium',
|
|
||||||
'Regular',
|
|
||||||
'Roman',
|
|
||||||
'Semibold'
|
|
||||||
];
|
|
||||||
|
|
||||||
var CFFEncodingMap = {
|
var CFFEncodingMap = {
|
||||||
'0': '-reserved-',
|
'0': '-reserved-',
|
||||||
'1': 'hstem',
|
'1': 'hstem',
|
||||||
@ -560,7 +166,7 @@ var CFFDictDataMap = {
|
|||||||
'18': {
|
'18': {
|
||||||
name: 'ExpansionFactor'
|
name: 'ExpansionFactor'
|
||||||
},
|
},
|
||||||
'9': {
|
'19': {
|
||||||
name: 'initialRandomSeed'
|
name: 'initialRandomSeed'
|
||||||
},
|
},
|
||||||
'20': {
|
'20': {
|
||||||
|
@ -20,17 +20,27 @@ function readCharset(aStream, aCharstrings) {
|
|||||||
var charset = {};
|
var charset = {};
|
||||||
|
|
||||||
var format = aStream.getByte();
|
var format = aStream.getByte();
|
||||||
|
var count = aCharstrings.length - 1;
|
||||||
if (format == 0) {
|
if (format == 0) {
|
||||||
charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);
|
charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);
|
||||||
|
|
||||||
var count = aCharstrings.length - 1;
|
|
||||||
for (var i = 1; i < count + 1; i++) {
|
for (var i = 1; i < count + 1; i++) {
|
||||||
var sid = aStream.getByte() << 8 | aStream.getByte();
|
var sid = aStream.getByte() << 8 | aStream.getByte();
|
||||||
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
|
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
|
||||||
//log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
|
//log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
|
||||||
}
|
}
|
||||||
} else if (format == 1) {
|
} else if (format == 1) {
|
||||||
error('Charset Range are not supported');
|
for (var i = 1; i < count + 1; i++) {
|
||||||
|
var first = aStream.getByte();
|
||||||
|
first = (first << 8) | aStream.getByte();
|
||||||
|
var numLeft = aStream.getByte();
|
||||||
|
for (var j = 0; j <= numLeft; j++) {
|
||||||
|
var sid = first++;
|
||||||
|
if (CFFStrings[sid] == 'three')
|
||||||
|
log(aCharstrings[j]);
|
||||||
|
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error('Invalid charset format');
|
error('Invalid charset format');
|
||||||
}
|
}
|
||||||
@ -44,6 +54,9 @@ function readCharset(aStream, aCharstrings) {
|
|||||||
* chapter 3.1.
|
* chapter 3.1.
|
||||||
*/
|
*/
|
||||||
function readCharstringEncoding(aString) {
|
function readCharstringEncoding(aString) {
|
||||||
|
if (!aString)
|
||||||
|
return '';
|
||||||
|
|
||||||
var charstringTokens = [];
|
var charstringTokens = [];
|
||||||
|
|
||||||
var count = aString.length;
|
var count = aString.length;
|
||||||
@ -69,11 +82,11 @@ function readCharstringEncoding(aString) {
|
|||||||
} else if (value <= 31) {
|
} else if (value <= 31) {
|
||||||
token = CFFEncodingMap[value];
|
token = CFFEncodingMap[value];
|
||||||
} else if (value < 247) {
|
} else if (value < 247) {
|
||||||
token = parseInt(value) - 139;
|
token = parseInt(value, 10) - 139;
|
||||||
} else if (value < 251) {
|
} else if (value < 251) {
|
||||||
token = ((value - 247) * 256) + aString[i++] + 108;
|
token = (value - 247) * 256 + aString[i++] + 108;
|
||||||
} else if (value < 255) {
|
} else if (value < 255) {
|
||||||
token = -((value - 251) * 256) - aString[i++] - 108;
|
token = -(value - 251) * 256 - aString[i++] - 108;
|
||||||
} else {// value == 255
|
} else {// value == 255
|
||||||
token = aString[i++] << 24 | aString[i++] << 16 |
|
token = aString[i++] << 24 | aString[i++] << 16 |
|
||||||
aString[i++] << 8 | aString[i];
|
aString[i++] << 8 | aString[i];
|
||||||
@ -113,7 +126,7 @@ function readFontDictData(aString, aMap) {
|
|||||||
while (!parsed) {
|
while (!parsed) {
|
||||||
var byte = aString[i++];
|
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++) {
|
for (var j = 0; j < nibbles.length; j++) {
|
||||||
var nibble = nibbles[j];
|
var nibble = nibbles[j];
|
||||||
switch (nibble) {
|
switch (nibble) {
|
||||||
@ -144,11 +157,11 @@ function readFontDictData(aString, aMap) {
|
|||||||
} else if (value <= 31) {
|
} else if (value <= 31) {
|
||||||
token = aMap[value];
|
token = aMap[value];
|
||||||
} else if (value <= 246) {
|
} else if (value <= 246) {
|
||||||
token = parseInt(value) - 139;
|
token = parseInt(value, 10) - 139;
|
||||||
} else if (value <= 250) {
|
} else if (value <= 250) {
|
||||||
token = ((value - 247) * 256) + aString[i++] + 108;
|
token = (value - 247) * 256 + aString[i++] + 108;
|
||||||
} else if (value <= 254) {
|
} else if (value <= 254) {
|
||||||
token = -((value - 251) * 256) - aString[i++] - 108;
|
token = -(value - 251) * 256 - aString[i++] - 108;
|
||||||
} else if (value == 255) {
|
} else if (value == 255) {
|
||||||
error('255 is not a valid DICT command');
|
error('255 is not a valid DICT command');
|
||||||
}
|
}
|
||||||
@ -193,13 +206,13 @@ function readFontIndexData(aStream, aIsByte) {
|
|||||||
}
|
}
|
||||||
error(offsize + ' is not a valid offset size');
|
error(offsize + ' is not a valid offset size');
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
|
|
||||||
var offsets = [];
|
var offsets = [];
|
||||||
for (var i = 0; i < count + 1; i++)
|
for (var i = 0; i < count + 1; i++)
|
||||||
offsets.push(getNextOffset());
|
offsets.push(getNextOffset());
|
||||||
|
|
||||||
log('Found ' + count + ' objects at offsets :' +
|
dump('Found ' + count + ' objects at offsets :' +
|
||||||
offsets + ' (offsize: ' + offsize + ')');
|
offsets + ' (offsize: ' + offsize + ')');
|
||||||
|
|
||||||
// Now extract the objects
|
// Now extract the objects
|
||||||
@ -219,7 +232,7 @@ function readFontIndexData(aStream, aIsByte) {
|
|||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
var Type2Parser = function(aFilePath) {
|
var Type2Parser = function type2Parser(aFilePath) {
|
||||||
var font = new Dict();
|
var font = new Dict();
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
@ -236,7 +249,7 @@ var Type2Parser = function(aFilePath) {
|
|||||||
function dump(aStr) {
|
function dump(aStr) {
|
||||||
if (debug)
|
if (debug)
|
||||||
log(aStr);
|
log(aStr);
|
||||||
};
|
}
|
||||||
|
|
||||||
function parseAsToken(aString, aMap) {
|
function parseAsToken(aString, aMap) {
|
||||||
var decoded = readFontDictData(aString, aMap);
|
var decoded = readFontDictData(aString, aMap);
|
||||||
@ -245,7 +258,7 @@ var Type2Parser = function(aFilePath) {
|
|||||||
var count = decoded.length;
|
var count = decoded.length;
|
||||||
for (var i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
var token = decoded[i];
|
var token = decoded[i];
|
||||||
if (IsNum(token)) {
|
if (isNum(token)) {
|
||||||
stack.push(token);
|
stack.push(token);
|
||||||
} else {
|
} else {
|
||||||
switch (token.operand) {
|
switch (token.operand) {
|
||||||
@ -277,31 +290,28 @@ var Type2Parser = function(aFilePath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
this.parse = function(aStream) {
|
this.parse = function type2ParserParse(aStream) {
|
||||||
font.set('major', aStream.getByte());
|
font.set('major', aStream.getByte());
|
||||||
font.set('minor', aStream.getByte());
|
font.set('minor', aStream.getByte());
|
||||||
font.set('hdrSize', aStream.getByte());
|
font.set('hdrSize', aStream.getByte());
|
||||||
font.set('offsize', aStream.getByte());
|
font.set('offsize', aStream.getByte());
|
||||||
|
|
||||||
// Move the cursor after the header
|
|
||||||
aStream.skip(font.get('hdrSize') - aStream.pos);
|
|
||||||
|
|
||||||
// Read the NAME Index
|
// Read the NAME Index
|
||||||
dump('Reading Index: Names');
|
dump('Reading Index: Names');
|
||||||
font.set('Names', readFontIndexData(aStream));
|
font.set('Names', readFontIndexData(aStream));
|
||||||
log('Names: ' + font.get('Names'));
|
dump('Names: ' + font.get('Names'));
|
||||||
|
|
||||||
// Read the Top Dict Index
|
// Read the Top Dict Index
|
||||||
dump('Reading Index: TopDict');
|
dump('Reading Index: TopDict');
|
||||||
var topDict = readFontIndexData(aStream, true);
|
var topDict = readFontIndexData(aStream, true);
|
||||||
log('TopDict: ' + topDict);
|
dump('TopDict: ' + topDict);
|
||||||
|
|
||||||
// Read the String Index
|
// Read the String Index
|
||||||
dump('Reading Index: Strings');
|
dump('Reading Index: Strings');
|
||||||
var strings = readFontIndexData(aStream);
|
var strings = readFontIndexData(aStream);
|
||||||
log('strings: ' + strings);
|
dump('strings: ' + strings);
|
||||||
|
|
||||||
// Fill up the Strings dictionary with the new unique strings
|
// Fill up the Strings dictionary with the new unique strings
|
||||||
for (var i = 0; i < strings.length; i++)
|
for (var i = 0; i < strings.length; i++)
|
||||||
@ -321,7 +331,7 @@ var Type2Parser = function(aFilePath) {
|
|||||||
|
|
||||||
// Reading Private Dict
|
// Reading Private Dict
|
||||||
var priv = font.get('Private');
|
var priv = font.get('Private');
|
||||||
log('Reading Private Dict (offset: ' + priv.offset +
|
dump('Reading Private Dict (offset: ' + priv.offset +
|
||||||
' size: ' + priv.size + ')');
|
' size: ' + priv.size + ')');
|
||||||
aStream.pos = priv.offset;
|
aStream.pos = priv.offset;
|
||||||
|
|
||||||
@ -353,7 +363,7 @@ var Type2Parser = function(aFilePath) {
|
|||||||
aStream.pos = charsetEntry;
|
aStream.pos = charsetEntry;
|
||||||
var charset = readCharset(aStream, charStrings);
|
var charset = readCharset(aStream, charStrings);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
58
web/compatibility.js
Executable file → Normal file
58
web/compatibility.js
Executable file → Normal file
@ -1,8 +1,10 @@
|
|||||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
// Checking if the typed arrays are supported
|
// Checking if the typed arrays are supported
|
||||||
(function() {
|
(function checkTypedArrayCompatibility() {
|
||||||
if (typeof Uint8Array !== 'undefined')
|
if (typeof Uint8Array !== 'undefined')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -10,8 +12,9 @@
|
|||||||
return this.slice(start, end);
|
return this.slice(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_(array, offset) {
|
function setArrayOffset(array, offset) {
|
||||||
if (arguments.length < 2) offset = 0;
|
if (arguments.length < 2)
|
||||||
|
offset = 0;
|
||||||
for (var i = 0, n = array.length; i < n; ++i, ++offset)
|
for (var i = 0, n = array.length; i < n; ++i, ++offset)
|
||||||
this[offset] = array[i] & 0xFF;
|
this[offset] = array[i] & 0xFF;
|
||||||
}
|
}
|
||||||
@ -19,15 +22,17 @@
|
|||||||
function TypedArray(arg1) {
|
function TypedArray(arg1) {
|
||||||
var result;
|
var result;
|
||||||
if (typeof arg1 === 'number') {
|
if (typeof arg1 === 'number') {
|
||||||
result = new Array(arg1);
|
result = [];
|
||||||
for (var i = 0; i < arg1; ++i)
|
for (var i = 0; i < arg1; ++i)
|
||||||
result[i] = 0;
|
result[i] = 0;
|
||||||
} else
|
} else
|
||||||
result = arg1.slice(0);
|
result = arg1.slice(0);
|
||||||
|
|
||||||
result.subarray = subarray;
|
result.subarray = subarray;
|
||||||
result.buffer = result;
|
result.buffer = result;
|
||||||
result.byteLength = result.length;
|
result.byteLength = result.length;
|
||||||
result.set = set_;
|
result.set = setArrayOffset;
|
||||||
|
|
||||||
if (typeof arg1 === 'object' && arg1.buffer)
|
if (typeof arg1 === 'object' && arg1.buffer)
|
||||||
result.buffer = arg1.buffer;
|
result.buffer = arg1.buffer;
|
||||||
|
|
||||||
@ -44,31 +49,31 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
// Object.create() ?
|
// Object.create() ?
|
||||||
(function() {
|
(function checkObjectCreateCompatibility() {
|
||||||
if (typeof Object.create !== 'undefined')
|
if (typeof Object.create !== 'undefined')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object.create = function(proto) {
|
Object.create = function objectCreate(proto) {
|
||||||
var constructor = function() {};
|
var constructor = function objectCreateConstructor() {};
|
||||||
constructor.prototype = proto;
|
constructor.prototype = proto;
|
||||||
return new constructor();
|
return new constructor();
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Object.defineProperty() ?
|
// Object.defineProperty() ?
|
||||||
(function() {
|
(function checkObjectDefinePropertyCompatibility() {
|
||||||
if (typeof Object.defineProperty !== 'undefined')
|
if (typeof Object.defineProperty !== 'undefined')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object.defineProperty = function(obj, name, def) {
|
Object.defineProperty = function objectDefineProperty(obj, name, def) {
|
||||||
delete obj[name];
|
delete obj[name];
|
||||||
if ('get' in def)
|
if ('get' in def)
|
||||||
obj.__defineGetter__(name, def['get']);
|
obj.__defineGetter__(name, def['get']);
|
||||||
if ('set' in def)
|
if ('set' in def)
|
||||||
obj.__defineSetter__(name, def['set']);
|
obj.__defineSetter__(name, def['set']);
|
||||||
if ('value' in def) {
|
if ('value' in def) {
|
||||||
obj.__defineSetter__(name, function(value) {
|
obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
|
||||||
this.__defineGetter__(name, function() {
|
this.__defineGetter__(name, function objectDefinePropertyGetter() {
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
return value;
|
return value;
|
||||||
@ -79,7 +84,7 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
// No XMLHttpRequest.response ?
|
// No XMLHttpRequest.response ?
|
||||||
(function() {
|
(function checkXMLHttpRequestResponseCompatibility() {
|
||||||
var xhrPrototype = XMLHttpRequest.prototype;
|
var xhrPrototype = XMLHttpRequest.prototype;
|
||||||
if ('response' in xhrPrototype ||
|
if ('response' in xhrPrototype ||
|
||||||
'mozResponseArrayBuffer' in xhrPrototype ||
|
'mozResponseArrayBuffer' in xhrPrototype ||
|
||||||
@ -89,7 +94,7 @@
|
|||||||
// IE ?
|
// IE ?
|
||||||
if (typeof VBArray !== 'undefined') {
|
if (typeof VBArray !== 'undefined') {
|
||||||
Object.defineProperty(xhrPrototype, 'response', {
|
Object.defineProperty(xhrPrototype, 'response', {
|
||||||
get: function() {
|
get: function xmlHttpRequestResponseGet() {
|
||||||
return new Uint8Array(new VBArray(this.responseBody).toArray());
|
return new Uint8Array(new VBArray(this.responseBody).toArray());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -117,14 +122,14 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
// window.btoa (base64 encode function) ?
|
// window.btoa (base64 encode function) ?
|
||||||
(function() {
|
(function checkWindowBtoaCompatibility() {
|
||||||
if ('btoa' in window)
|
if ('btoa' in window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var digits =
|
var digits =
|
||||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||||
|
|
||||||
window.btoa = function(chars) {
|
window.btoa = function windowBtoa(chars) {
|
||||||
var buffer = '';
|
var buffer = '';
|
||||||
var i, n;
|
var i, n;
|
||||||
for (i = 0, n = chars.length; i < n; i += 3) {
|
for (i = 0, n = chars.length; i < n; i += 3) {
|
||||||
@ -142,13 +147,13 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
// Function.prototype.bind ?
|
// Function.prototype.bind ?
|
||||||
(function() {
|
(function checkFunctionPrototypeBindCompatibility() {
|
||||||
if (typeof Function.prototype.bind !== 'undefined')
|
if (typeof Function.prototype.bind !== 'undefined')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Function.prototype.bind = function(obj) {
|
Function.prototype.bind = function functionPrototypeBind(obj) {
|
||||||
var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
|
var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
|
||||||
var bound = function() {
|
var bound = function functionPrototypeBindBound() {
|
||||||
var args = Array.prototype.concat.apply(headArgs, arguments);
|
var args = Array.prototype.concat.apply(headArgs, arguments);
|
||||||
return fn.apply(obj, args);
|
return fn.apply(obj, args);
|
||||||
};
|
};
|
||||||
@ -157,15 +162,15 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
// IE9 text/html data URI
|
// IE9 text/html data URI
|
||||||
(function() {
|
(function checkDocumentDocumentModeCompatibility() {
|
||||||
if (document.documentMode !== 9)
|
if (document.documentMode !== 9)
|
||||||
return;
|
return;
|
||||||
// overriding the src property
|
// overriding the src property
|
||||||
var originalSrcDescriptor = Object.getOwnPropertyDescriptor(
|
var originalSrcDescriptor = Object.getOwnPropertyDescriptor(
|
||||||
HTMLIFrameElement.prototype, 'src');
|
HTMLIFrameElement.prototype, 'src');
|
||||||
Object.defineProperty(HTMLIFrameElement.prototype, 'src', {
|
Object.defineProperty(HTMLIFrameElement.prototype, 'src', {
|
||||||
get: function() { return this.$src; },
|
get: function htmlIFrameElementPrototypeSrcGet() { return this.$src; },
|
||||||
set: function(src) {
|
set: function htmlIFrameElementPrototypeSrcSet(src) {
|
||||||
this.$src = src;
|
this.$src = src;
|
||||||
if (src.substr(0, 14) != 'data:text/html') {
|
if (src.substr(0, 14) != 'data:text/html') {
|
||||||
originalSrcDescriptor.set.call(this, src);
|
originalSrcDescriptor.set.call(this, src);
|
||||||
@ -174,7 +179,7 @@
|
|||||||
// for text/html, using blank document and then
|
// for text/html, using blank document and then
|
||||||
// document's open, write, and close operations
|
// document's open, write, and close operations
|
||||||
originalSrcDescriptor.set.call(this, 'about:blank');
|
originalSrcDescriptor.set.call(this, 'about:blank');
|
||||||
setTimeout((function() {
|
setTimeout((function htmlIFrameElementPrototypeSrcOpenWriteClose() {
|
||||||
var doc = this.contentDocument;
|
var doc = this.contentDocument;
|
||||||
doc.open('text/html');
|
doc.open('text/html');
|
||||||
doc.write(src.substr(src.indexOf(',') + 1));
|
doc.write(src.substr(src.indexOf(',') + 1));
|
||||||
@ -184,3 +189,4 @@
|
|||||||
enumerable: true
|
enumerable: true
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
15
web/viewer.css
Executable file → Normal file
15
web/viewer.css
Executable file → Normal file
@ -119,6 +119,7 @@ span#info {
|
|||||||
margin-right:auto;
|
margin-right:auto;
|
||||||
line-height: 134px;
|
line-height: 134px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnail:not([data-loaded]) {
|
.thumbnail:not([data-loaded]) {
|
||||||
@ -195,16 +196,17 @@ span#info {
|
|||||||
canvas {
|
canvas {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
display: block;
|
display: block;
|
||||||
box-shadow: 0px 4px 10px #000;
|
|
||||||
-moz-box-shadow: 0px 4px 10px #000;
|
|
||||||
-webkit-box-shadow: 0px 4px 10px #000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
width: 816px;
|
width: 816px;
|
||||||
height: 1056px;
|
height: 1056px;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
position:relative;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0px 4px 10px #000;
|
||||||
|
-moz-box-shadow: 0px 4px 10px #000;
|
||||||
|
-webkit-box-shadow: 0px 4px 10px #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page > a {
|
.page > a {
|
||||||
@ -271,3 +273,8 @@ canvas {
|
|||||||
page-break-after: always;
|
page-break-after: always;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#loading {
|
||||||
|
margin: 100px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
<script type="text/javascript" src="../crypto.js"></script>
|
<script type="text/javascript" src="../crypto.js"></script>
|
||||||
<script type="text/javascript" src="../glyphlist.js"></script>
|
<script type="text/javascript" src="../glyphlist.js"></script>
|
||||||
<script type="text/javascript" src="../metrics.js"></script>
|
<script type="text/javascript" src="../metrics.js"></script>
|
||||||
|
<script type="text/javascript" src="../charsets.js"></script>
|
||||||
|
<script type="text/javascript" src="../cidmaps.js"></script>
|
||||||
<script type="text/javascript" src="../worker.js"></script>
|
<script type="text/javascript" src="../worker.js"></script>
|
||||||
<script type="text/javascript" src="../worker/message_handler.js"></script>
|
<script type="text/javascript" src="../worker/message_handler.js"></script>
|
||||||
<script type="text/javascript" src="../worker/processor_handler.js"></script>
|
<script type="text/javascript" src="../worker/processor_handler.js"></script>
|
||||||
@ -30,7 +32,7 @@
|
|||||||
|
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
|
|
||||||
<input type="text" id="pageNumber" onchange="PDFView.page = this.value;" value="1" size="4"/>
|
<input type="number" id="pageNumber" onchange="PDFView.page = this.value;" value="1" size="4" min="1" />
|
||||||
|
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span id="numPages">--</span>
|
<span id="numPages">--</span>
|
||||||
@ -92,7 +94,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="loading">Loading... 0%</div>
|
||||||
<div id="viewer"></div>
|
<div id="viewer"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
271
web/viewer.js
271
web/viewer.js
@ -9,11 +9,13 @@ var kDefaultScaleDelta = 1.1;
|
|||||||
var kCacheSize = 20;
|
var kCacheSize = 20;
|
||||||
var kCssUnits = 96.0 / 72.0;
|
var kCssUnits = 96.0 / 72.0;
|
||||||
var kScrollbarPadding = 40;
|
var kScrollbarPadding = 40;
|
||||||
|
var kMinScale = 0.25;
|
||||||
|
var kMaxScale = 4.0;
|
||||||
|
|
||||||
|
|
||||||
var Cache = function(size) {
|
var Cache = function cacheCache(size) {
|
||||||
var data = [];
|
var data = [];
|
||||||
this.push = function(view) {
|
this.push = function cachePush(view) {
|
||||||
data.push(view);
|
data.push(view);
|
||||||
if (data.length > size)
|
if (data.length > size)
|
||||||
data.shift().update();
|
data.shift().update();
|
||||||
@ -21,23 +23,22 @@ var Cache = function(size) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var cache = new Cache(kCacheSize);
|
var cache = new Cache(kCacheSize);
|
||||||
|
var currentPageNumber = 1;
|
||||||
|
|
||||||
var PDFView = {
|
var PDFView = {
|
||||||
pages: [],
|
pages: [],
|
||||||
thumbnails: [],
|
thumbnails: [],
|
||||||
currentScale: kDefaultScale,
|
currentScale: kDefaultScale,
|
||||||
|
initialBookmark: document.location.hash.substring(1),
|
||||||
|
|
||||||
setScale: function(val, resetAutoSettings) {
|
setScale: function pdfViewSetScale(val, resetAutoSettings) {
|
||||||
var pages = this.pages;
|
var pages = this.pages;
|
||||||
for (var i = 0; i < pages.length; i++)
|
for (var i = 0; i < pages.length; i++)
|
||||||
pages[i].update(val * kCssUnits);
|
pages[i].update(val * kCssUnits);
|
||||||
this.currentScale = val;
|
this.currentScale = val;
|
||||||
|
|
||||||
if (document.location.hash == '#' + this.page)
|
this.pages[this.page - 1].scrollIntoView();
|
||||||
this.pages[this.page - 1].draw();
|
this.pages[this.page - 1].draw();
|
||||||
else
|
|
||||||
// Jump the scroll position to the correct page.
|
|
||||||
document.location.hash = this.page;
|
|
||||||
|
|
||||||
var event = document.createEvent('UIEvents');
|
var event = document.createEvent('UIEvents');
|
||||||
event.initUIEvent('scalechange', false, false, window, 0);
|
event.initUIEvent('scalechange', false, false, window, 0);
|
||||||
@ -46,7 +47,7 @@ var PDFView = {
|
|||||||
window.dispatchEvent(event);
|
window.dispatchEvent(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
parseScale: function(value, resetAutoSettings) {
|
parseScale: function pdfViewParseScale(value, resetAutoSettings) {
|
||||||
if ('custom' == value)
|
if ('custom' == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -58,9 +59,9 @@ var PDFView = {
|
|||||||
|
|
||||||
var currentPage = this.pages[this.page - 1];
|
var currentPage = this.pages[this.page - 1];
|
||||||
var pageWidthScale = (window.innerWidth - kScrollbarPadding) /
|
var pageWidthScale = (window.innerWidth - kScrollbarPadding) /
|
||||||
currentPage.width / kCssUnits;
|
currentPage.width / kCssUnits;
|
||||||
var pageHeightScale = (window.innerHeight - kScrollbarPadding) /
|
var pageHeightScale = (window.innerHeight - kScrollbarPadding) /
|
||||||
currentPage.height / kCssUnits;
|
currentPage.height / kCssUnits;
|
||||||
if ('page-width' == value)
|
if ('page-width' == value)
|
||||||
this.setScale(pageWidthScale, resetAutoSettings);
|
this.setScale(pageWidthScale, resetAutoSettings);
|
||||||
if ('page-height' == value)
|
if ('page-height' == value)
|
||||||
@ -71,12 +72,14 @@ var PDFView = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomIn: function() {
|
zoomIn: function pdfViewZoomIn() {
|
||||||
this.setScale(this.currentScale * kDefaultScaleDelta, true);
|
var newScale = Math.min(kMaxScale, this.currentScale * kDefaultScaleDelta);
|
||||||
|
this.setScale(newScale, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomOut: function() {
|
zoomOut: function pdfViewZoomOut() {
|
||||||
this.setScale(this.currentScale / kDefaultScaleDelta, true);
|
var newScale = Math.max(kMinScale, this.currentScale / kDefaultScaleDelta);
|
||||||
|
this.setScale(newScale, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
set page(val) {
|
set page(val) {
|
||||||
@ -87,44 +90,41 @@ var PDFView = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.location.hash = val;
|
currentPageNumber = val;
|
||||||
document.getElementById('previous').disabled = (val == 1);
|
document.getElementById('previous').disabled = (val == 1);
|
||||||
document.getElementById('next').disabled = (val == pages.length);
|
document.getElementById('next').disabled = (val == pages.length);
|
||||||
if (input.value == val)
|
if (input.value != val) {
|
||||||
return;
|
input.value = val;
|
||||||
|
}
|
||||||
|
|
||||||
input.value = val;
|
pages[val - 1].scrollIntoView();
|
||||||
pages[val - 1].draw();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
get page() {
|
get page() {
|
||||||
return parseInt(document.location.hash.substring(1)) || 1;
|
return currentPageNumber;
|
||||||
},
|
},
|
||||||
|
|
||||||
open: function(url, scale) {
|
open: function pdfViewOpen(url, scale) {
|
||||||
if (url.indexOf('http') == 0)
|
if (url.indexOf('http') == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
document.title = url;
|
document.title = url;
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
getPdf(
|
||||||
xhr.open('GET', url);
|
{
|
||||||
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
url: url,
|
||||||
xhr.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
|
progress: function getPdfProgress(evt) {
|
||||||
|
if (evt.lengthComputable)
|
||||||
xhr.onreadystatechange = function() {
|
PDFView.progress(evt.loaded / evt.total);
|
||||||
if (xhr.readyState === 4 && xhr.status === xhr.expected) {
|
},
|
||||||
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
error: PDFView.error
|
||||||
xhr.responseArrayBuffer || xhr.response);
|
},
|
||||||
|
function getPdfLoad(data) {
|
||||||
PDFView.load(data, scale);
|
PDFView.load(data, scale);
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
xhr.send(null);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
navigateTo: function(dest) {
|
navigateTo: function pdfViewNavigateTo(dest) {
|
||||||
if (typeof dest === 'string')
|
if (typeof dest === 'string')
|
||||||
dest = this.destinations[dest];
|
dest = this.destinations[dest];
|
||||||
if (!(dest instanceof Array))
|
if (!(dest instanceof Array))
|
||||||
@ -140,7 +140,36 @@ var PDFView = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
load: function(data, scale) {
|
getDestinationHash: function pdfViewGetDestinationHash(dest) {
|
||||||
|
if (typeof dest === 'string')
|
||||||
|
return '#' + escape(dest);
|
||||||
|
if (dest instanceof Array) {
|
||||||
|
var destRef = dest[0]; // see nevigateTo method for dest format
|
||||||
|
var pageNumber = destRef instanceof Object ?
|
||||||
|
this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] :
|
||||||
|
(destRef + 1);
|
||||||
|
if (pageNumber) {
|
||||||
|
return '#page=' + pageNumber + '&dest=' + dest.slice(1).join(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
|
||||||
|
error: function pdfViewError() {
|
||||||
|
var loadingIndicator = document.getElementById('loading');
|
||||||
|
loadingIndicator.innerHTML = 'Error';
|
||||||
|
},
|
||||||
|
|
||||||
|
progress: function pdfViewProgress(level) {
|
||||||
|
var percent = Math.round(level * 100);
|
||||||
|
var loadingIndicator = document.getElementById('loading');
|
||||||
|
loadingIndicator.innerHTML = 'Loading... ' + percent + '%';
|
||||||
|
},
|
||||||
|
|
||||||
|
load: function pdfViewLoad(data, scale) {
|
||||||
|
var loadingIndicator = document.getElementById('loading');
|
||||||
|
loadingIndicator.style.display = 'none';
|
||||||
|
|
||||||
var sidebar = document.getElementById('sidebarView');
|
var sidebar = document.getElementById('sidebarView');
|
||||||
sidebar.parentNode.scrollTop = 0;
|
sidebar.parentNode.scrollTop = 0;
|
||||||
|
|
||||||
@ -152,15 +181,10 @@ var PDFView = {
|
|||||||
while (container.hasChildNodes())
|
while (container.hasChildNodes())
|
||||||
container.removeChild(container.lastChild);
|
container.removeChild(container.lastChild);
|
||||||
|
|
||||||
var pdf;
|
var pdf = new WorkerPDFDoc(data);
|
||||||
if (true /* Use Worker */) {
|
|
||||||
pdf = new WorkerPDFDoc(data);
|
|
||||||
} else {
|
|
||||||
pdf = new PDFDoc(new Stream(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
var pagesCount = pdf.numPages;
|
var pagesCount = pdf.numPages;
|
||||||
document.getElementById('numPages').innerHTML = pagesCount;
|
document.getElementById('numPages').innerHTML = pagesCount;
|
||||||
|
document.getElementById('pageNumber').max = pagesCount;
|
||||||
|
|
||||||
var pages = this.pages = [];
|
var pages = this.pages = [];
|
||||||
var pagesRefMap = {};
|
var pagesRefMap = {};
|
||||||
@ -169,14 +193,14 @@ var PDFView = {
|
|||||||
var page = pdf.getPage(i);
|
var page = pdf.getPage(i);
|
||||||
pages.push(new PageView(container, page, i, page.width, page.height,
|
pages.push(new PageView(container, page, i, page.width, page.height,
|
||||||
page.stats, this.navigateTo.bind(this)));
|
page.stats, this.navigateTo.bind(this)));
|
||||||
thumbnails.push(new ThumbnailView(sidebar, pages[i - 1],
|
thumbnails.push(new ThumbnailView(sidebar, page, i,
|
||||||
page.width / page.height));
|
page.width / page.height));
|
||||||
var pageRef = page.ref;
|
var pageRef = page.ref;
|
||||||
pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i;
|
pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setScale(scale || kDefaultScale, true);
|
this.setScale(scale || kDefaultScale, true);
|
||||||
this.page = parseInt(document.location.hash.substring(1)) || 1;
|
|
||||||
this.pagesRefMap = pagesRefMap;
|
this.pagesRefMap = pagesRefMap;
|
||||||
this.destinations = pdf.catalog.destinations;
|
this.destinations = pdf.catalog.destinations;
|
||||||
if (pdf.catalog.documentOutline) {
|
if (pdf.catalog.documentOutline) {
|
||||||
@ -185,9 +209,31 @@ var PDFView = {
|
|||||||
outlineSwitchButton.removeAttribute('disabled');
|
outlineSwitchButton.removeAttribute('disabled');
|
||||||
this.switchSidebarView('outline');
|
this.switchSidebarView('outline');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.initialBookmark) {
|
||||||
|
this.setHash(this.initialBookmark);
|
||||||
|
this.initialBookmark = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this.page = 1;
|
||||||
},
|
},
|
||||||
|
|
||||||
switchSidebarView: function(view) {
|
setHash: function pdfViewSetHash(hash) {
|
||||||
|
if (!hash)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (hash.indexOf('=') >= 0) {
|
||||||
|
// TODO more complex hashes, for now catching page=XX only
|
||||||
|
var m = /\bpage=(\d+)/.exec(hash);
|
||||||
|
if (m && m[1] > 0)
|
||||||
|
this.page = m[1];
|
||||||
|
} else if (/^\d+$/.test(hash)) // page number
|
||||||
|
this.page = hash;
|
||||||
|
else // named destination
|
||||||
|
PDFView.navigateTo(unescape(hash));
|
||||||
|
},
|
||||||
|
|
||||||
|
switchSidebarView: function pdfViewSwitchSidebarView(view) {
|
||||||
var thumbsScrollView = document.getElementById('sidebarScrollView');
|
var thumbsScrollView = document.getElementById('sidebarScrollView');
|
||||||
var outlineScrollView = document.getElementById('outlineScrollView');
|
var outlineScrollView = document.getElementById('outlineScrollView');
|
||||||
var thumbsSwitchButton = document.getElementById('thumbsSwitch');
|
var thumbsSwitchButton = document.getElementById('thumbsSwitch');
|
||||||
@ -208,14 +254,14 @@ var PDFView = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getVisiblePages: function() {
|
getVisiblePages: function pdfViewGetVisiblePages() {
|
||||||
var pages = this.pages;
|
var pages = this.pages;
|
||||||
var kBottomMargin = 10;
|
var kBottomMargin = 10;
|
||||||
var visiblePages = [];
|
var visiblePages = [];
|
||||||
|
|
||||||
var currentHeight = kBottomMargin;
|
var currentHeight = kBottomMargin;
|
||||||
var windowTop = window.pageYOffset;
|
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 page = pages[i - 1];
|
||||||
var pageHeight = page.height * page.scale + kBottomMargin;
|
var pageHeight = page.height * page.scale + kBottomMargin;
|
||||||
if (currentHeight + pageHeight > windowTop)
|
if (currentHeight + pageHeight > windowTop)
|
||||||
@ -225,23 +271,28 @@ var PDFView = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var windowBottom = window.pageYOffset + window.innerHeight;
|
var windowBottom = window.pageYOffset + window.innerHeight;
|
||||||
for (; i <= pages.length && currentHeight < windowBottom; i++) {
|
for (; i <= pages.length && currentHeight < windowBottom; ++i) {
|
||||||
var page = pages[i - 1];
|
var singlePage = pages[i - 1];
|
||||||
visiblePages.push({ id: page.id, y: currentHeight, view: page });
|
visiblePages.push({ id: singlePage.id, y: currentHeight,
|
||||||
currentHeight += page.height * page.scale + kBottomMargin;
|
view: singlePage });
|
||||||
|
currentHeight += singlePage.height * singlePage.scale + kBottomMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
return visiblePages;
|
return visiblePages;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var PageView = function(container, content, id, width, height,
|
var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||||
stats, navigateTo) {
|
stats, navigateTo) {
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
|
||||||
|
var view = this.content.view;
|
||||||
|
this.x = view.x;
|
||||||
|
this.y = view.y;
|
||||||
|
this.width = view.width;
|
||||||
|
this.height = view.height;
|
||||||
|
|
||||||
var anchor = document.createElement('a');
|
var anchor = document.createElement('a');
|
||||||
anchor.name = '' + this.id;
|
anchor.name = '' + this.id;
|
||||||
|
|
||||||
@ -252,7 +303,7 @@ var PageView = function(container, content, id, width, height,
|
|||||||
container.appendChild(anchor);
|
container.appendChild(anchor);
|
||||||
container.appendChild(div);
|
container.appendChild(div);
|
||||||
|
|
||||||
this.update = function(scale) {
|
this.update = function pageViewUpdate(scale) {
|
||||||
this.scale = scale || this.scale;
|
this.scale = scale || this.scale;
|
||||||
div.style.width = (this.width * this.scale) + 'px';
|
div.style.width = (this.width * this.scale) + 'px';
|
||||||
div.style.height = (this.height * this.scale) + 'px';
|
div.style.height = (this.height * this.scale) + 'px';
|
||||||
@ -262,19 +313,21 @@ var PageView = function(container, content, id, width, height,
|
|||||||
div.removeAttribute('data-loaded');
|
div.removeAttribute('data-loaded');
|
||||||
};
|
};
|
||||||
|
|
||||||
function setupLinks(canvas, content, scale) {
|
function setupLinks(content, scale) {
|
||||||
function bindLink(link, dest) {
|
function bindLink(link, dest) {
|
||||||
link.onclick = function() {
|
link.href = PDFView.getDestinationHash(dest);
|
||||||
|
link.onclick = function pageViewSetupLinksOnclick() {
|
||||||
if (dest)
|
if (dest)
|
||||||
PDFView.navigateTo(dest);
|
PDFView.navigateTo(dest);
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var links = content.getLinks();
|
var links = content.getLinks();
|
||||||
for (var i = 0; i < links.length; i++) {
|
for (var i = 0; i < links.length; i++) {
|
||||||
var link = document.createElement('a');
|
var link = document.createElement('a');
|
||||||
link.style.left = Math.floor(links[i].x * scale) + 'px';
|
link.style.left = (Math.floor(links[i].x - view.x) * scale) + 'px';
|
||||||
link.style.top = Math.floor(links[i].y * scale) + 'px';
|
link.style.top = (Math.floor(links[i].y - view.y) * scale) + 'px';
|
||||||
link.style.width = Math.ceil(links[i].width * scale) + 'px';
|
link.style.width = Math.ceil(links[i].width * scale) + 'px';
|
||||||
link.style.height = Math.ceil(links[i].height * scale) + 'px';
|
link.style.height = Math.ceil(links[i].height * scale) + 'px';
|
||||||
link.href = links[i].url || '';
|
link.href = links[i].url || '';
|
||||||
@ -284,13 +337,16 @@ var PageView = function(container, content, id, width, height,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scrollIntoView = function(dest) {
|
this.scrollIntoView = function pageViewScrollIntoView(dest) {
|
||||||
|
if (!dest) {
|
||||||
|
div.scrollIntoView(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var x = 0, y = 0;
|
var x = 0, y = 0;
|
||||||
var width = 0, height = 0, widthScale, heightScale;
|
var width = 0, height = 0, widthScale, heightScale;
|
||||||
var scale = 0;
|
var scale = 0;
|
||||||
switch (dest[1].name) {
|
switch (dest[1].name) {
|
||||||
default:
|
|
||||||
return;
|
|
||||||
case 'XYZ':
|
case 'XYZ':
|
||||||
x = dest[2];
|
x = dest[2];
|
||||||
y = dest[3];
|
y = dest[3];
|
||||||
@ -321,6 +377,8 @@ var PageView = function(container, content, id, width, height,
|
|||||||
height / kCssUnits;
|
height / kCssUnits;
|
||||||
scale = Math.min(widthScale, heightScale);
|
scale = Math.min(widthScale, heightScale);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var boundingRect = [
|
var boundingRect = [
|
||||||
@ -331,7 +389,7 @@ var PageView = function(container, content, id, width, height,
|
|||||||
if (scale)
|
if (scale)
|
||||||
PDFView.setScale(scale, true);
|
PDFView.setScale(scale, true);
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function pageViewScrollIntoViewRelayout() {
|
||||||
// letting page to re-layout before scrolling
|
// letting page to re-layout before scrolling
|
||||||
var scale = PDFView.currentScale;
|
var scale = PDFView.currentScale;
|
||||||
var x = Math.min(boundingRect[0].x, boundingRect[1].x);
|
var x = Math.min(boundingRect[0].x, boundingRect[1].x);
|
||||||
@ -352,7 +410,7 @@ var PageView = function(container, content, id, width, height,
|
|||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.draw = function() {
|
this.draw = function pageviewDraw() {
|
||||||
if (div.hasChildNodes()) {
|
if (div.hasChildNodes()) {
|
||||||
this.updateStats();
|
this.updateStats();
|
||||||
return false;
|
return false;
|
||||||
@ -362,8 +420,9 @@ var PageView = function(container, content, id, width, height,
|
|||||||
canvas.id = 'page' + this.id;
|
canvas.id = 'page' + this.id;
|
||||||
canvas.mozOpaque = true;
|
canvas.mozOpaque = true;
|
||||||
|
|
||||||
canvas.width = this.width * this.scale;
|
var scale = this.scale;
|
||||||
canvas.height = this.height * this.scale;
|
canvas.width = pageWidth * scale;
|
||||||
|
canvas.height = pageHeight * scale;
|
||||||
div.appendChild(canvas);
|
div.appendChild(canvas);
|
||||||
|
|
||||||
var ctx = canvas.getContext('2d');
|
var ctx = canvas.getContext('2d');
|
||||||
@ -371,17 +430,18 @@ var PageView = function(container, content, id, width, height,
|
|||||||
ctx.fillStyle = 'rgb(255, 255, 255)';
|
ctx.fillStyle = 'rgb(255, 255, 255)';
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
|
ctx.translate(-this.x * scale, -this.y * scale);
|
||||||
|
|
||||||
stats.begin = Date.now();
|
stats.begin = Date.now();
|
||||||
this.content.startRendering(ctx, this.updateStats);
|
this.content.startRendering(ctx, this.updateStats);
|
||||||
|
|
||||||
setupLinks(canvas, this.content, this.scale);
|
setupLinks(this.content, this.scale);
|
||||||
div.setAttribute('data-loaded', true);
|
div.setAttribute('data-loaded', true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateStats = function() {
|
this.updateStats = function pageViewUpdateStats() {
|
||||||
var t1 = stats.compile, t2 = stats.fonts, t3 = stats.render;
|
var t1 = stats.compile, t2 = stats.fonts, t3 = stats.render;
|
||||||
var str = 'Time to compile/fonts/render: ' +
|
var str = 'Time to compile/fonts/render: ' +
|
||||||
(t1 - stats.begin) + '/' + (t2 - t1) + '/' + (t3 - t2) + ' ms';
|
(t1 - stats.begin) + '/' + (t2 - t1) + '/' + (t3 - t2) + ' ms';
|
||||||
@ -389,23 +449,27 @@ var PageView = function(container, content, id, width, height,
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
var ThumbnailView = function(container, page, pageRatio) {
|
var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
|
||||||
var anchor = document.createElement('a');
|
var anchor = document.createElement('a');
|
||||||
anchor.href = '#' + page.id;
|
anchor.href = '#' + id;
|
||||||
|
anchor.onclick = function stopNivigation() {
|
||||||
|
PDFView.page = id;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
var div = document.createElement('div');
|
var div = document.createElement('div');
|
||||||
div.id = 'thumbnailContainer' + page.id;
|
div.id = 'thumbnailContainer' + id;
|
||||||
div.className = 'thumbnail';
|
div.className = 'thumbnail';
|
||||||
|
|
||||||
anchor.appendChild(div);
|
anchor.appendChild(div);
|
||||||
container.appendChild(anchor);
|
container.appendChild(anchor);
|
||||||
|
|
||||||
this.draw = function() {
|
this.draw = function thumbnailViewDraw() {
|
||||||
if (div.hasChildNodes())
|
if (div.hasChildNodes())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var canvas = document.createElement('canvas');
|
var canvas = document.createElement('canvas');
|
||||||
canvas.id = 'thumbnail' + page.id;
|
canvas.id = 'thumbnail' + id;
|
||||||
canvas.mozOpaque = true;
|
canvas.mozOpaque = true;
|
||||||
|
|
||||||
var maxThumbSize = 134;
|
var maxThumbSize = 134;
|
||||||
@ -423,16 +487,24 @@ var ThumbnailView = function(container, page, pageRatio) {
|
|||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
|
|
||||||
page.content.startRendering(ctx, function() { });
|
var view = page.view;
|
||||||
|
var scaleX = (canvas.width / page.width);
|
||||||
|
var scaleY = (canvas.height / page.height);
|
||||||
|
ctx.translate(-view.x * scaleX, -view.y * scaleY);
|
||||||
|
div.style.width = (view.width * scaleX) + 'px';
|
||||||
|
div.style.height = (view.height * scaleY) + 'px';
|
||||||
|
div.style.lineHeight = (view.height * scaleY) + 'px';
|
||||||
|
|
||||||
|
page.startRendering(ctx, function thumbnailViewDrawStartRendering() {});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
var DocumentOutlineView = function(outline) {
|
var DocumentOutlineView = function documentOutlineView(outline) {
|
||||||
var outlineView = document.getElementById('outlineView');
|
var outlineView = document.getElementById('outlineView');
|
||||||
|
|
||||||
function bindItemLink(domObj, item) {
|
function bindItemLink(domObj, item) {
|
||||||
domObj.href = '';
|
domObj.href = PDFView.getDestinationHash(item.dest);
|
||||||
domObj.onclick = function(e) {
|
domObj.onclick = function documentOutlineViewOnclick(e) {
|
||||||
PDFView.navigateTo(item.dest);
|
PDFView.navigateTo(item.dest);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@ -463,7 +535,7 @@ var DocumentOutlineView = function(outline) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('load', function(evt) {
|
window.addEventListener('load', function webViewerLoad(evt) {
|
||||||
var params = document.location.search.substring(1).split('&');
|
var params = document.location.search.substring(1).split('&');
|
||||||
for (var i = 0; i < params.length; i++) {
|
for (var i = 0; i < params.length; i++) {
|
||||||
var param = params[i].split('=');
|
var param = params[i].split('=');
|
||||||
@ -478,10 +550,18 @@ window.addEventListener('load', function(evt) {
|
|||||||
document.getElementById('fileInput').value = null;
|
document.getElementById('fileInput').value = null;
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
window.addEventListener('pdfloaded', function(evt) {
|
window.addEventListener('pdfload', function webViewerPdfload(evt) {
|
||||||
PDFView.load(evt.detail);
|
PDFView.load(evt.detail);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
window.addEventListener('pdfprogress', function webViewerPdfProgress(evt) {
|
||||||
|
PDFView.progress(evt.detail);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
window.addEventListener('pdferror', function webViewerPdfError(evt) {
|
||||||
|
PDFView.error();
|
||||||
|
}, true);
|
||||||
|
|
||||||
function updateViewarea() {
|
function updateViewarea() {
|
||||||
var visiblePages = PDFView.getVisiblePages();
|
var visiblePages = PDFView.getVisiblePages();
|
||||||
for (var i = 0; i < visiblePages.length; i++) {
|
for (var i = 0; i < visiblePages.length; i++) {
|
||||||
@ -502,29 +582,29 @@ function updateViewarea() {
|
|||||||
PDFView.page = firstPage.id;
|
PDFView.page = firstPage.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('scroll', function onscroll(evt) {
|
window.addEventListener('scroll', function webViewerScroll(evt) {
|
||||||
updateViewarea();
|
updateViewarea();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
window.addEventListener('resize', function onscroll(evt) {
|
window.addEventListener('resize', function webViewerResize(evt) {
|
||||||
if (document.getElementById('pageWidthOption').selected ||
|
if (document.getElementById('pageWidthOption').selected ||
|
||||||
document.getElementById('pageFitOption').selected)
|
document.getElementById('pageFitOption').selected)
|
||||||
PDFView.parseScale(document.getElementById('scaleSelect').value);
|
PDFView.parseScale(document.getElementById('scaleSelect').value);
|
||||||
updateViewarea();
|
updateViewarea();
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('hashchange', function(evt) {
|
window.addEventListener('hashchange', function webViewerHashchange(evt) {
|
||||||
PDFView.page = PDFView.page;
|
PDFView.setHash(document.location.hash.substring(1));
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('change', function(evt) {
|
window.addEventListener('change', function webViewerChange(evt) {
|
||||||
var files = evt.target.files;
|
var files = evt.target.files;
|
||||||
if (!files || files.length == 0)
|
if (!files || files.length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Read the local file into a Uint8Array.
|
// Read the local file into a Uint8Array.
|
||||||
var fileReader = new FileReader();
|
var fileReader = new FileReader();
|
||||||
fileReader.onload = function(evt) {
|
fileReader.onload = function webViewerChangeFileReaderOnload(evt) {
|
||||||
var data = evt.target.result;
|
var data = evt.target.result;
|
||||||
var buffer = new ArrayBuffer(data.length);
|
var buffer = new ArrayBuffer(data.length);
|
||||||
var uint8Array = new Uint8Array(buffer);
|
var uint8Array = new Uint8Array(buffer);
|
||||||
@ -540,10 +620,9 @@ window.addEventListener('change', function(evt) {
|
|||||||
fileReader.readAsBinaryString(file);
|
fileReader.readAsBinaryString(file);
|
||||||
|
|
||||||
document.title = file.name;
|
document.title = file.name;
|
||||||
document.location.hash = 1;
|
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
window.addEventListener('transitionend', function(evt) {
|
window.addEventListener('transitionend', function webViewerTransitionend(evt) {
|
||||||
var pageIndex = 0;
|
var pageIndex = 0;
|
||||||
var pagesCount = PDFView.pages.length;
|
var pagesCount = PDFView.pages.length;
|
||||||
|
|
||||||
@ -592,13 +671,19 @@ window.addEventListener('scalechange', function scalechange(evt) {
|
|||||||
|
|
||||||
window.addEventListener('pagechange', function pagechange(evt) {
|
window.addEventListener('pagechange', function pagechange(evt) {
|
||||||
var page = evt.detail;
|
var page = evt.detail;
|
||||||
document.location.hash = page;
|
|
||||||
document.getElementById('pageNumber').value = page;
|
document.getElementById('pageNumber').value = page;
|
||||||
document.getElementById('previous').disabled = (page == 1);
|
document.getElementById('previous').disabled = (page == 1);
|
||||||
document.getElementById('next').disabled = (page == PDFView.pages.length);
|
document.getElementById('next').disabled = (page == PDFView.pages.length);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
window.addEventListener('keydown', function keydown(evt) {
|
window.addEventListener('keydown', function keydown(evt) {
|
||||||
|
var curElement = document.activeElement;
|
||||||
|
var controlsElement = document.getElementById('controls');
|
||||||
|
while (curElement) {
|
||||||
|
if (curElement === controlsElement)
|
||||||
|
return; // ignoring if the 'controls' element is focused
|
||||||
|
curElement = curElement.parentNode;
|
||||||
|
}
|
||||||
switch (evt.keyCode) {
|
switch (evt.keyCode) {
|
||||||
case 61: // FF/Mac '='
|
case 61: // FF/Mac '='
|
||||||
case 107: // FF '+' and '='
|
case 107: // FF '+' and '='
|
||||||
|
@ -9,16 +9,15 @@
|
|||||||
|
|
||||||
|
|
||||||
var pdfDoc;
|
var pdfDoc;
|
||||||
window.onload = function() {
|
window.onload = function webViewerWorkerOnload() {
|
||||||
window.canvas = document.getElementById("canvas");
|
window.canvas = document.getElementById("canvas");
|
||||||
window.ctx = canvas.getContext("2d");
|
window.ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
pdfDoc = new WorkerPDFDoc(window.canvas);
|
pdfDoc = new WorkerPDFDoc(window.canvas);
|
||||||
pdfDoc.onChangePage = function(numPage) {
|
pdfDoc.onChangePage = function webViewerWorkerOnChangePage(numPage) {
|
||||||
document.getElementById("pageNumber").value = numPage;
|
document.getElementById("pageNumber").value = numPage;
|
||||||
}
|
}
|
||||||
// pdfDoc.open("canvas.pdf", function() {
|
pdfDoc.open("compressed.tracemonkey-pldi-09.pdf", function webViewerWorkerOpen() {
|
||||||
pdfDoc.open("compressed.tracemonkey-pldi-09.pdf", function() {
|
|
||||||
document.getElementById("numPages").innerHTML = "/" + pdfDoc.numPages;
|
document.getElementById("numPages").innerHTML = "/" + pdfDoc.numPages;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,10 @@ var WorkerPage = (function() {
|
|||||||
return this.page.stats;
|
return this.page.stats;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get view() {
|
||||||
|
return this.page.view;
|
||||||
|
},
|
||||||
|
|
||||||
startRendering: function(ctx, callback, errback) {
|
startRendering: function(ctx, callback, errback) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
@ -33,3 +33,4 @@ var console = {
|
|||||||
this.log('Timer:', name, Date.now() - time);
|
this.log('Timer:', name, Date.now() - time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user