Merge upstream.
This commit is contained in:
commit
2d7e1d6346
28
Makefile
28
Makefile
@ -210,6 +210,7 @@ pages-repo: | $(BUILD_DIR)
|
||||
# copy of the pdf.js source.
|
||||
CONTENT_DIR := content
|
||||
BUILD_NUMBER := `git log --format=oneline $(EXTENSION_BASE_VERSION).. | wc -l | awk '{print $$1}'`
|
||||
PDFJSSCRIPT_VERSION := 0.2.$(BUILD_NUMBER)
|
||||
EXTENSION_WEB_FILES = \
|
||||
web/images \
|
||||
web/viewer.css \
|
||||
@ -225,14 +226,28 @@ FIREFOX_CONTENT_DIR := $(EXTENSION_SRC)/firefox/$(CONTENT_DIR)/
|
||||
FIREFOX_EXTENSION_FILES_TO_COPY = \
|
||||
*.js \
|
||||
*.rdf \
|
||||
*.png \
|
||||
install.rdf.in \
|
||||
README.mozilla \
|
||||
components \
|
||||
../../LICENSE \
|
||||
$(NULL)
|
||||
FIREFOX_EXTENSION_FILES = \
|
||||
content \
|
||||
*.js \
|
||||
bootstrap.js \
|
||||
install.rdf \
|
||||
icon.png \
|
||||
icon64.png \
|
||||
components \
|
||||
content \
|
||||
LICENSE \
|
||||
$(NULL)
|
||||
FIREFOX_MC_EXTENSION_FILES = \
|
||||
bootstrap.js \
|
||||
icon.png \
|
||||
icon64.png \
|
||||
components \
|
||||
content \
|
||||
LICENSE \
|
||||
$(NULL)
|
||||
|
||||
CHROME_BUILD_DIR := $(BUILD_DIR)/chrome
|
||||
@ -265,9 +280,12 @@ extension: | production
|
||||
# We don't need pdf.js anymore since its inlined
|
||||
@rm -Rf $(FIREFOX_BUILD_CONTENT)/$(BUILD_DIR)/;
|
||||
# Update the build version number
|
||||
@sed -i.bak "s/PDFJSSCRIPT_BUILD/$(BUILD_NUMBER)/" $(FIREFOX_BUILD_DIR)/install.rdf
|
||||
@sed -i.bak "s/PDFJSSCRIPT_BUILD/$(BUILD_NUMBER)/" $(FIREFOX_BUILD_DIR)/update.rdf
|
||||
@sed -i.bak "s/PDFJSSCRIPT_VERSION/$(PDFJSSCRIPT_VERSION)/" $(FIREFOX_BUILD_DIR)/install.rdf
|
||||
@sed -i.bak "s/PDFJSSCRIPT_VERSION/$(PDFJSSCRIPT_VERSION)/" $(FIREFOX_BUILD_DIR)/install.rdf.in
|
||||
@sed -i.bak "s/PDFJSSCRIPT_VERSION/$(PDFJSSCRIPT_VERSION)/" $(FIREFOX_BUILD_DIR)/update.rdf
|
||||
@sed -i.bak "s/PDFJSSCRIPT_VERSION/$(PDFJSSCRIPT_VERSION)/" $(FIREFOX_BUILD_DIR)/README.mozilla
|
||||
@rm -f $(FIREFOX_BUILD_DIR)/*.bak
|
||||
@find $(FIREFOX_BUILD_DIR) -name ".*" -delete
|
||||
# Create the xpi
|
||||
@cd $(FIREFOX_BUILD_DIR); zip -r $(FIREFOX_EXTENSION_NAME) $(FIREFOX_EXTENSION_FILES)
|
||||
@echo "extension created: " $(FIREFOX_EXTENSION_NAME)
|
||||
@ -276,6 +294,8 @@ extension: | production
|
||||
@rm -f $(FIREFOX_BUILD_DIR)/*.bak
|
||||
@cd $(FIREFOX_BUILD_DIR); zip -r $(FIREFOX_AMO_EXTENSION_NAME) $(FIREFOX_EXTENSION_FILES)
|
||||
@echo "AMO extension created: " $(FIREFOX_AMO_EXTENSION_NAME)
|
||||
# List all files for mozilla-central
|
||||
@cd $(FIREFOX_BUILD_DIR); find $(FIREFOX_MC_EXTENSION_FILES) -type f > extension-files
|
||||
|
||||
# Clear out everything in the chrome extension build directory
|
||||
@rm -Rf $(CHROME_BUILD_DIR)
|
||||
|
@ -1,18 +1,28 @@
|
||||
<!doctype html>
|
||||
<script>
|
||||
|
||||
function isPdfDownloadable(details) {
|
||||
return details.url.indexOf('pdfjs.action=download') >= 0;
|
||||
}
|
||||
|
||||
chrome.webRequest.onBeforeRequest.addListener(
|
||||
function(details) {
|
||||
if (isPdfDownloadable(details))
|
||||
return;
|
||||
|
||||
var viewerPage = 'content/web/viewer.html';
|
||||
var url = chrome.extension.getURL(viewerPage) + '?file=' + details.url;
|
||||
var url = chrome.extension.getURL(viewerPage) +
|
||||
'?file=' + encodeURIComponent(details.url);
|
||||
return { redirectUrl: url };
|
||||
},
|
||||
{
|
||||
urls: [
|
||||
"http://*/*.pdf",
|
||||
"file://*/*.pdf",
|
||||
"file://*/*.pdf"
|
||||
],
|
||||
types: [ "main_frame" ]
|
||||
},
|
||||
["blocking"]);
|
||||
|
||||
</script>
|
||||
|
||||
|
4
extensions/firefox/README.mozilla
Normal file
4
extensions/firefox/README.mozilla
Normal file
@ -0,0 +1,4 @@
|
||||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: PDFJSSCRIPT_VERSION
|
||||
|
20
extensions/firefox/bootstrap.js
vendored
20
extensions/firefox/bootstrap.js
vendored
@ -10,10 +10,14 @@ let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cm = Components.manager;
|
||||
let Cu = Components.utils;
|
||||
let application = Cc['@mozilla.org/fuel/application;1']
|
||||
.getService(Ci.fuelIApplication);
|
||||
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
function log(str) {
|
||||
if (!application.prefs.getValue(EXT_PREFIX + '.pdfBugEnabled', false))
|
||||
return;
|
||||
dump(str + '\n');
|
||||
}
|
||||
|
||||
@ -60,12 +64,7 @@ function startup(aData, aReason) {
|
||||
var ioService = Services.io;
|
||||
var resProt = ioService.getProtocolHandler('resource')
|
||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||
var aliasFile = Cc['@mozilla.org/file/local;1']
|
||||
.createInstance(Ci.nsILocalFile);
|
||||
var componentPath = aData.installPath.clone();
|
||||
componentPath.append('content');
|
||||
aliasFile.initWithPath(componentPath.path);
|
||||
var aliasURI = ioService.newFileURI(aliasFile);
|
||||
var aliasURI = ioService.newURI('content/', 'UTF-8', aData.resourceURI);
|
||||
resProt.setSubstitution(RESOURCE_NAME, aliasURI);
|
||||
|
||||
// Load the component and register it.
|
||||
@ -73,12 +72,11 @@ function startup(aData, aReason) {
|
||||
'components/PdfStreamConverter.js';
|
||||
Cu.import(pdfStreamConverterUrl);
|
||||
Factory.register(PdfStreamConverter);
|
||||
Services.prefs.setBoolPref('extensions.pdf.js.active', true);
|
||||
}
|
||||
|
||||
function shutdown(aData, aReason) {
|
||||
if (Services.prefs.getBoolPref('extensions.pdf.js.active'))
|
||||
Services.prefs.setBoolPref('extensions.pdf.js.active', false);
|
||||
if (aReason == APP_SHUTDOWN)
|
||||
return;
|
||||
var ioService = Services.io;
|
||||
var resProt = ioService.getProtocolHandler('resource')
|
||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||
@ -87,18 +85,14 @@ function shutdown(aData, aReason) {
|
||||
// Remove the contract/component.
|
||||
Factory.unregister();
|
||||
// Unload the converter
|
||||
if (pdfStreamConverterUrl) {
|
||||
Cu.unload(pdfStreamConverterUrl);
|
||||
pdfStreamConverterUrl = null;
|
||||
}
|
||||
}
|
||||
|
||||
function install(aData, aReason) {
|
||||
Services.prefs.setBoolPref('extensions.pdf.js.active', false);
|
||||
}
|
||||
|
||||
function uninstall(aData, aReason) {
|
||||
Services.prefs.clearUserPref('extensions.pdf.js.active');
|
||||
application.prefs.setValue(EXT_PREFIX + '.database', '{}');
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,15 @@ const MAX_DATABASE_LENGTH = 4096;
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
let application = Cc['@mozilla.org/fuel/application;1']
|
||||
.getService(Ci.fuelIApplication);
|
||||
let privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
|
||||
.getService(Ci.nsIPrivateBrowsingService);
|
||||
let inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
|
||||
|
||||
function log(aMsg) {
|
||||
if (!application.prefs.getValue(EXT_PREFIX + '.pdfBugEnabled', false))
|
||||
return;
|
||||
let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
|
||||
Services.console.logStringMessage(msg);
|
||||
dump(msg + '\n');
|
||||
@ -40,11 +48,6 @@ function topWindow(win) {
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
}
|
||||
let application = Cc['@mozilla.org/fuel/application;1']
|
||||
.getService(Ci.fuelIApplication);
|
||||
let privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
|
||||
.getService(Ci.nsIPrivateBrowsingService);
|
||||
let inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
|
||||
|
||||
// All the priviledged actions.
|
||||
function ChromeActions() {
|
||||
@ -66,6 +69,9 @@ ChromeActions.prototype = {
|
||||
if (this.inPrivateBrowswing)
|
||||
return '{}';
|
||||
return application.prefs.getValue(EXT_PREFIX + '.database', '{}');
|
||||
},
|
||||
pdfBugEnabled: function() {
|
||||
return application.prefs.getValue(EXT_PREFIX + '.pdfBugEnabled', false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -122,15 +128,12 @@ PdfStreamConverter.prototype = {
|
||||
|
||||
// nsIStreamConverter::asyncConvertData
|
||||
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
||||
if (!Services.prefs.getBoolPref('extensions.pdf.js.active'))
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Ignoring HTTP POST requests -- pdf.js has to repeat the request.
|
||||
var skipConversion = false;
|
||||
try {
|
||||
var request = aCtxt;
|
||||
request.QueryInterface(Ci.nsIHttpChannel);
|
||||
skipConversion = (request.requestMethod === 'POST');
|
||||
skipConversion = (request.requestMethod !== 'GET');
|
||||
} catch (e) {
|
||||
// Non-HTTP request... continue normally.
|
||||
}
|
||||
|
BIN
extensions/firefox/icon.png
Normal file
BIN
extensions/firefox/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
BIN
extensions/firefox/icon64.png
Normal file
BIN
extensions/firefox/icon64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
@ -5,20 +5,18 @@
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>uriloader@pdf.js</em:id>
|
||||
<em:name>pdf.js</em:name>
|
||||
<em:version>0.2.PDFJSSCRIPT_BUILD</em:version>
|
||||
<em:iconURL>chrome://pdf.js/skin/logo.png</em:iconURL>
|
||||
<em:name>PDF Viewer</em:name>
|
||||
<em:version>PDFJSSCRIPT_VERSION</em:version>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>6.0</em:minVersion>
|
||||
<em:maxVersion>13.0a1</em:maxVersion>
|
||||
<em:maxVersion>14.0a1</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:unpack>true</em:unpack>
|
||||
<em:creator>Mozilla Labs</em:creator>
|
||||
<em:description>pdf.js uri loader</em:description>
|
||||
<em:creator>Mozilla</em:creator>
|
||||
<em:description>Uses HTML5 to display PDF files directly in Firefox.</em:description>
|
||||
<em:homepageURL>https://github.com/mozilla/pdf.js/</em:homepageURL>
|
||||
<em:type>2</em:type>
|
||||
<!-- Use the raw link for updates so we we can use SSL. -->
|
||||
|
26
extensions/firefox/install.rdf.in
Normal file
26
extensions/firefox/install.rdf.in
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
#filter substitution
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>uriloader@pdf.js</em:id>
|
||||
<em:name>PDF Viewer</em:name>
|
||||
<em:version>PDFJSSCRIPT_VERSION</em:version>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>@FIREFOX_VERSION@</em:minVersion>
|
||||
<em:maxVersion>@FIREFOX_VERSION@</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:strictCompatibility>true</em:strictCompatibility>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:creator>Mozilla</em:creator>
|
||||
<em:description>Uses HTML5 to display PDF files directly in Firefox.</em:description>
|
||||
<em:homepageURL>http://support.mozilla.org/kb/using-mozilla-pdf-viewer</em:homepageURL>
|
||||
<em:type>2</em:type>
|
||||
</Description>
|
||||
</RDF>
|
@ -8,7 +8,7 @@
|
||||
<RDF:Seq>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<em:version>0.2.PDFJSSCRIPT_BUILD</em:version>
|
||||
<em:version>PDFJSSCRIPT_VERSION</em:version>
|
||||
<em:targetApplication>
|
||||
<RDF:Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
|
42
external/shelljs/README.md
vendored
42
external/shelljs/README.md
vendored
@ -1,8 +1,10 @@
|
||||
# ShellJS - Unix shell commands for Node.js [](http://travis-ci.org/arturadib/shelljs)
|
||||
|
||||
_This project is young and experimental. Use at your own risk._
|
||||
|
||||
ShellJS is a **portable** (Windows included) implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands.
|
||||
|
||||
The project is both [unit-tested](http://travis-ci.org/arturadib/shelljs) and battle-tested at Mozilla's [pdf.js](http://github.com/mozilla/pdf.js).
|
||||
The project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and is being used at Mozilla's [pdf.js](http://github.com/mozilla/pdf.js).
|
||||
|
||||
|
||||
### Example
|
||||
@ -12,7 +14,7 @@ require('shelljs/global');
|
||||
|
||||
// Copy files to release dir
|
||||
mkdir('-p', 'out/Release');
|
||||
cp('-R', 'lib/*.js', 'out/Release');
|
||||
cp('-R', 'stuff/*', 'out/Release');
|
||||
|
||||
// Replace macros in each .js file
|
||||
cd('lib');
|
||||
@ -130,6 +132,27 @@ Returns list of files in the given path, or in current directory if no path prov
|
||||
For convenient iteration via `for (file in ls())`, the format returned is a hash object:
|
||||
`{ 'file1':null, 'dir1/file2':null, ...}`.
|
||||
|
||||
#### find(path [,path ...])
|
||||
#### find(path_array)
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
find('src', 'lib');
|
||||
find(['src', 'lib']); // same as above
|
||||
for (file in find('.')) {
|
||||
if (!file.match(/\.js$/))
|
||||
continue;
|
||||
// all files at this point end in '.js'
|
||||
}
|
||||
```
|
||||
|
||||
Returns list of all files (however deep) in the given paths. For convenient iteration
|
||||
via `for (file in find(...))`, the format returned is a hash object:
|
||||
`{ 'file1':null, 'dir1/file2':null, ...}`.
|
||||
|
||||
The main difference with respect to `ls('-R', path)` is that the resulting file names
|
||||
include the base directories, e.g. `lib/resources/file1` instead of just `file1`.
|
||||
|
||||
#### cp('[options ,] source [,source ...], dest')
|
||||
#### cp('[options ,] source_array, dest')
|
||||
Available options:
|
||||
@ -195,6 +218,21 @@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above
|
||||
|
||||
Creates directories.
|
||||
|
||||
#### test(expression)
|
||||
Available expression primaries:
|
||||
|
||||
+ `'-d', 'path'`: true if path is a directory
|
||||
+ `'-f', 'path'`: true if path is a regular file
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
if (test('-d', path)) { /* do something with dir */ };
|
||||
if (!test('-f', path)) continue; // skip if it's a regular file
|
||||
```
|
||||
|
||||
Evaluates expression using the available primaries and returns corresponding value.
|
||||
|
||||
#### cat(file [, file ...])
|
||||
#### cat(file_array)
|
||||
|
||||
|
85
external/shelljs/shell.js
vendored
85
external/shelljs/shell.js
vendored
@ -57,6 +57,7 @@ function _pwd(options) {
|
||||
};
|
||||
exports.pwd = wrap('pwd', _pwd);
|
||||
|
||||
|
||||
//@
|
||||
//@ #### ls([options ,] path [,path ...])
|
||||
//@ #### ls([options ,] path_array)
|
||||
@ -159,6 +160,54 @@ function _ls(options, paths) {
|
||||
exports.ls = wrap('ls', _ls);
|
||||
|
||||
|
||||
//@
|
||||
//@ #### find(path [,path ...])
|
||||
//@ #### find(path_array)
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ find('src', 'lib');
|
||||
//@ find(['src', 'lib']); // same as above
|
||||
//@ for (file in find('.')) {
|
||||
//@ if (!file.match(/\.js$/))
|
||||
//@ continue;
|
||||
//@ // all files at this point end in '.js'
|
||||
//@ }
|
||||
//@ ```
|
||||
//@
|
||||
//@ Returns list of all files (however deep) in the given paths. For convenient iteration
|
||||
//@ via `for (file in find(...))`, the format returned is a hash object:
|
||||
//@ `{ 'file1':null, 'dir1/file2':null, ...}`.
|
||||
//@
|
||||
//@ The main difference from `ls('-R', path)` is that the resulting file names
|
||||
//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`.
|
||||
function _find(options, paths) {
|
||||
if (!paths)
|
||||
error('no path specified');
|
||||
else if (typeof paths === 'object')
|
||||
paths = paths; // assume array
|
||||
else if (typeof paths === 'string')
|
||||
paths = [].slice.call(arguments, 1);
|
||||
|
||||
var hash = {};
|
||||
|
||||
// why not simply do ls('-R', paths)? because the output wouldn't give the base dirs
|
||||
// to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory
|
||||
|
||||
paths.forEach(function(file){
|
||||
hash[file] = null;
|
||||
|
||||
if (fs.statSync(file).isDirectory()) {
|
||||
for (subfile in _ls('-Ra', file+'/*'))
|
||||
hash[subfile] = null;
|
||||
}
|
||||
});
|
||||
|
||||
return hash;
|
||||
}
|
||||
exports.find = wrap('find', _find);
|
||||
|
||||
|
||||
//@
|
||||
//@ #### cp('[options ,] source [,source ...], dest')
|
||||
//@ #### cp('[options ,] source_array, dest')
|
||||
@ -438,6 +487,42 @@ function _mkdir(options, dirs) {
|
||||
}; // mkdir
|
||||
exports.mkdir = wrap('mkdir', _mkdir);
|
||||
|
||||
//@
|
||||
//@ #### test(expression)
|
||||
//@ Available expression primaries:
|
||||
//@
|
||||
//@ + `'-d', 'path'`: true if path is a directory
|
||||
//@ + `'-f', 'path'`: true if path is a regular file
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ if (test('-d', path)) { /* do something with dir */ };
|
||||
//@ if (!test('-f', path)) continue; // skip if it's a regular file
|
||||
//@ ```
|
||||
//@
|
||||
//@ Evaluates expression using the available primaries and returns corresponding value.
|
||||
function _test(options, path) {
|
||||
if (!path)
|
||||
error('no path given');
|
||||
|
||||
// hack - only works with unary primaries
|
||||
options = parseOptions(options, {
|
||||
'd': 'directory',
|
||||
'f': 'file'
|
||||
});
|
||||
if (!options.directory && !options.file)
|
||||
error('could not interpret expression');
|
||||
|
||||
if (options.directory)
|
||||
return fs.existsSync(path) && fs.statSync(path).isDirectory();
|
||||
|
||||
if (options.file)
|
||||
return fs.existsSync(path) && fs.statSync(path).isFile();
|
||||
}; // test
|
||||
exports.test = wrap('test', _test);
|
||||
|
||||
|
||||
//@
|
||||
//@ #### cat(file [, file ...])
|
||||
//@ #### cat(file_array)
|
||||
|
56
make.js
56
make.js
@ -149,7 +149,7 @@ target.pagesrepo = function() {
|
||||
echo();
|
||||
echo('Cloning project repo...');
|
||||
echo('(This operation can take a while, depending on network conditions)');
|
||||
exec('git clone -b gh-pages --depth=1 ' + REPO + ' ' + ßGH_PAGES_DIR,
|
||||
exec('git clone -b gh-pages --depth=1 ' + REPO + ' ' + GH_PAGES_DIR,
|
||||
{silent: true});
|
||||
echo('Done.');
|
||||
}
|
||||
@ -168,13 +168,16 @@ target.pagesrepo = function() {
|
||||
//
|
||||
|
||||
var EXTENSION_WEB_FILES =
|
||||
['web/images',
|
||||
['web/debugger.js',
|
||||
'web/images',
|
||||
'web/viewer.css',
|
||||
'web/viewer.js',
|
||||
'web/viewer.html',
|
||||
'web/viewer-production.html'],
|
||||
EXTENSION_BASE_VERSION = '4bb289ec499013de66eb421737a4dbb4a9273eda',
|
||||
EXTENSION_BUILD_NUMBER;
|
||||
EXTENSION_VERSION_PREFIX = '0.2.',
|
||||
EXTENSION_BUILD_NUMBER,
|
||||
EXTENSION_VERSION;
|
||||
|
||||
//
|
||||
// make extension
|
||||
@ -200,6 +203,8 @@ target.buildnumber = function() {
|
||||
.output.match(/\n/g).length; // get # of lines in git output
|
||||
|
||||
echo('Extension build number: ' + EXTENSION_BUILD_NUMBER);
|
||||
|
||||
EXTENSION_VERSION = EXTENSION_VERSION_PREFIX + EXTENSION_BUILD_NUMBER;
|
||||
};
|
||||
|
||||
//
|
||||
@ -215,13 +220,26 @@ target.firefox = function() {
|
||||
FIREFOX_EXTENSION_FILES_TO_COPY =
|
||||
['*.js',
|
||||
'*.rdf',
|
||||
'components'];
|
||||
FIREFOX_EXTENSION_FILES =
|
||||
['content',
|
||||
'*.js',
|
||||
'install.rdf',
|
||||
'*.png',
|
||||
'install.rdf.in',
|
||||
'README.mozilla',
|
||||
'components',
|
||||
'content'];
|
||||
'../../LICENSE'];
|
||||
FIREFOX_EXTENSION_FILES =
|
||||
['bootstrap.js',
|
||||
'install.rdf',
|
||||
'icon.png',
|
||||
'icon64.png',
|
||||
'components',
|
||||
'content',
|
||||
'LICENSE'];
|
||||
FIREFOX_MC_EXTENSION_FILES =
|
||||
['bootstrap.js',
|
||||
'icon.png',
|
||||
'icon64.png',
|
||||
'components',
|
||||
'content',
|
||||
'LICENSE'];
|
||||
FIREFOX_EXTENSION_NAME = 'pdf.js.xpi',
|
||||
FIREFOX_AMO_EXTENSION_NAME = 'pdf.js.amo.xpi';
|
||||
|
||||
@ -258,10 +276,17 @@ target.firefox = function() {
|
||||
|
||||
// We don't need pdf.js anymore since its inlined
|
||||
rm('-Rf', FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR);
|
||||
// Remove '.DS_Store' and other hidden files
|
||||
for (file in find(FIREFOX_BUILD_DIR)) {
|
||||
if (file.match(/^\./))
|
||||
rm('-f', file);
|
||||
}
|
||||
|
||||
// Update the build version number
|
||||
sed('-i', /PDFJSSCRIPT_BUILD/, EXTENSION_BUILD_NUMBER, FIREFOX_BUILD_DIR + '/install.rdf');
|
||||
sed('-i', /PDFJSSCRIPT_BUILD/, EXTENSION_BUILD_NUMBER, FIREFOX_BUILD_DIR + '/update.rdf');
|
||||
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, FIREFOX_BUILD_DIR + '/install.rdf');
|
||||
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, FIREFOX_BUILD_DIR + '/update.rdf');
|
||||
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, FIREFOX_BUILD_DIR + '/install.rdf.in');
|
||||
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, FIREFOX_BUILD_DIR + '/README.mozilla');
|
||||
|
||||
// Create the xpi
|
||||
cd(FIREFOX_BUILD_DIR);
|
||||
@ -275,6 +300,15 @@ target.firefox = function() {
|
||||
exec('zip -r ' + FIREFOX_AMO_EXTENSION_NAME + ' ' + FIREFOX_EXTENSION_FILES.join(' '));
|
||||
echo('AMO extension created: ' + FIREFOX_AMO_EXTENSION_NAME);
|
||||
cd(ROOT_DIR);
|
||||
|
||||
// List all files for mozilla-central
|
||||
cd(FIREFOX_BUILD_DIR);
|
||||
var extensionFiles = '';
|
||||
for (file in find(FIREFOX_MC_EXTENSION_FILES)) {
|
||||
if (test('-f', file))
|
||||
extensionFiles += file+'\n';
|
||||
}
|
||||
extensionFiles.to('extension-files');
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -124,7 +124,7 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
|
||||
}
|
||||
}
|
||||
|
||||
return (function bidi(text, startLevel) {
|
||||
function bidi(text, startLevel) {
|
||||
var str = text.str;
|
||||
var strLength = str.length;
|
||||
if (strLength == 0)
|
||||
@ -429,5 +429,8 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
|
||||
result += ch;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
return bidi;
|
||||
})();
|
||||
|
||||
|
@ -70,7 +70,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
||||
return CanvasExtraState;
|
||||
})();
|
||||
|
||||
function ScratchCanvas(width, height) {
|
||||
function createScratchCanvas(width, height) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
@ -188,9 +188,9 @@ function addContextCurrentTransform(ctx) {
|
||||
}
|
||||
|
||||
var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
// Defines the time the executeIRQueue is going to be executing
|
||||
// Defines the time the executeOperatorList is going to be executing
|
||||
// before it stops and shedules a continue of execution.
|
||||
var kExecutionTime = 50;
|
||||
var kExecutionTime = 15;
|
||||
|
||||
function CanvasGraphics(canvasCtx, objs, textLayer) {
|
||||
this.ctx = canvasCtx;
|
||||
@ -199,7 +199,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
this.pendingClip = null;
|
||||
this.res = null;
|
||||
this.xobjs = null;
|
||||
this.ScratchCanvas = ScratchCanvas;
|
||||
this.objs = objs;
|
||||
this.textLayer = textLayer;
|
||||
if (canvasCtx) {
|
||||
@ -229,7 +228,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
'setStrokeColor': true,
|
||||
'setStrokeColorN': true,
|
||||
'setFillColor': true,
|
||||
'setFillColorN_IR': true,
|
||||
'setFillColorN': true,
|
||||
'setStrokeGray': true,
|
||||
'setFillGray': true,
|
||||
'setStrokeRGBColor': true,
|
||||
@ -268,15 +267,16 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
this.textLayer.beginLayout();
|
||||
},
|
||||
|
||||
executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR,
|
||||
executeOperatorList: function canvasGraphicsExecuteOperatorList(
|
||||
operatorList,
|
||||
executionStartIdx, continueCallback,
|
||||
stepper) {
|
||||
var argsArray = codeIR.argsArray;
|
||||
var fnArray = codeIR.fnArray;
|
||||
var argsArray = operatorList.argsArray;
|
||||
var fnArray = operatorList.fnArray;
|
||||
var i = executionStartIdx || 0;
|
||||
var argsArrayLen = argsArray.length;
|
||||
|
||||
// Sometimes the IRQueue to execute is empty.
|
||||
// Sometimes the OperatorList to execute is empty.
|
||||
if (argsArrayLen == i) {
|
||||
return i;
|
||||
}
|
||||
@ -314,7 +314,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
|
||||
i++;
|
||||
|
||||
// If the entire IRQueue was executed, stop as were done.
|
||||
// If the entire operatorList was executed, stop as were done.
|
||||
if (i == argsArrayLen) {
|
||||
return i;
|
||||
}
|
||||
@ -327,8 +327,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
return i;
|
||||
}
|
||||
|
||||
// If the IRQueue isn't executed completly yet OR the execution time
|
||||
// was short enough, do another execution round.
|
||||
// If the operatorList isn't executed completely yet OR the execution
|
||||
// time was short enough, do another execution round.
|
||||
}
|
||||
},
|
||||
|
||||
@ -556,7 +556,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
this.current.leading = -leading;
|
||||
},
|
||||
setFont: function canvasGraphicsSetFont(fontRefName, size) {
|
||||
var fontObj = this.objs.get(fontRefName).fontObj;
|
||||
var fontObj = this.objs.get(fontRefName);
|
||||
var current = this.current;
|
||||
|
||||
if (!fontObj)
|
||||
@ -707,7 +707,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
this.save();
|
||||
ctx.scale(fontSize, fontSize);
|
||||
ctx.transform.apply(ctx, fontMatrix);
|
||||
this.executeIRQueue(glyph.codeIRQueue);
|
||||
this.executeOperatorList(glyph.operatorList);
|
||||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
@ -908,7 +908,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
getColorN_IR_Pattern: function canvasGraphicsGetColorN_IR_Pattern(IR, cs) {
|
||||
getColorN_Pattern: function canvasGraphicsGetColorN_Pattern(IR, cs) {
|
||||
if (IR[0] == 'TilingPattern') {
|
||||
var args = IR[1];
|
||||
var base = cs.base;
|
||||
@ -930,11 +930,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
}
|
||||
return pattern;
|
||||
},
|
||||
setStrokeColorN_IR: function canvasGraphicsSetStrokeColorN(/*...*/) {
|
||||
setStrokeColorN: function canvasGraphicsSetStrokeColorN(/*...*/) {
|
||||
var cs = this.current.strokeColorSpace;
|
||||
|
||||
if (cs.name == 'Pattern') {
|
||||
this.current.strokeColor = this.getColorN_IR_Pattern(arguments, cs);
|
||||
this.current.strokeColor = this.getColorN_Pattern(arguments, cs);
|
||||
} else {
|
||||
this.setStrokeColor.apply(this, arguments);
|
||||
}
|
||||
@ -946,11 +946,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
setFillColorN_IR: function canvasGraphicsSetFillColorN(/*...*/) {
|
||||
setFillColorN: function canvasGraphicsSetFillColorN(/*...*/) {
|
||||
var cs = this.current.fillColorSpace;
|
||||
|
||||
if (cs.name == 'Pattern') {
|
||||
this.current.fillColor = this.getColorN_IR_Pattern(arguments, cs);
|
||||
this.current.fillColor = this.getColorN_Pattern(arguments, cs);
|
||||
} else {
|
||||
this.setFillColor.apply(this, arguments);
|
||||
}
|
||||
@ -1116,7 +1116,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
// scale the image to the unit square
|
||||
ctx.scale(1 / w, -1 / h);
|
||||
|
||||
var tmpCanvas = new this.ScratchCanvas(w, h);
|
||||
var tmpCanvas = createScratchCanvas(w, h);
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
|
||||
var fillColor = this.current.fillColor;
|
||||
@ -1147,7 +1147,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
// scale the image to the unit square
|
||||
ctx.scale(1 / w, -1 / h);
|
||||
|
||||
var tmpCanvas = new this.ScratchCanvas(w, h);
|
||||
var tmpCanvas = createScratchCanvas(w, h);
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
this.putBinaryImageData(tmpCtx, imgData, w, h);
|
||||
|
||||
|
@ -135,6 +135,7 @@ var ColorSpace = (function ColorSpaceClosure() {
|
||||
basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
|
||||
return ['PatternCS', basePatternCS];
|
||||
case 'Indexed':
|
||||
case 'I':
|
||||
var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
|
||||
var hiVal = cs[2] + 1;
|
||||
var lookup = xref.fetchIfRef(cs[3]);
|
||||
|
130
src/core.js
130
src/core.js
@ -63,13 +63,8 @@ var Page = (function PageClosure() {
|
||||
function Page(xref, pageNumber, pageDict, ref) {
|
||||
this.pageNumber = pageNumber;
|
||||
this.pageDict = pageDict;
|
||||
this.stats = {
|
||||
create: Date.now(),
|
||||
compile: 0.0,
|
||||
fonts: 0.0,
|
||||
images: 0.0,
|
||||
render: 0.0
|
||||
};
|
||||
this.stats = new StatTimer();
|
||||
this.stats.enabled = !!globalScope.PDFJS.enableStats;
|
||||
this.xref = xref;
|
||||
this.ref = ref;
|
||||
|
||||
@ -175,10 +170,10 @@ var Page = (function PageClosure() {
|
||||
return shadow(this, 'rotate', rotate);
|
||||
},
|
||||
|
||||
startRenderingFromIRQueue: function pageStartRenderingFromIRQueue(
|
||||
IRQueue, fonts) {
|
||||
startRenderingFromOperatorList: function pageStartRenderingFromOperatorList(
|
||||
operatorList, fonts) {
|
||||
var self = this;
|
||||
this.IRQueue = IRQueue;
|
||||
this.operatorList = operatorList;
|
||||
|
||||
var displayContinuation = function pageDisplayContinuation() {
|
||||
// Always defer call to display() to work around bug in
|
||||
@ -189,17 +184,20 @@ var Page = (function PageClosure() {
|
||||
};
|
||||
|
||||
this.ensureFonts(fonts,
|
||||
function pageStartRenderingFromIRQueueEnsureFonts() {
|
||||
function pageStartRenderingFromOperatorListEnsureFonts() {
|
||||
displayContinuation();
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
getIRQueue: function pageGetIRQueue(handler, dependency) {
|
||||
if (this.IRQueue) {
|
||||
getOperatorList: function pageGetOperatorList(handler, dependency) {
|
||||
if (this.operatorList) {
|
||||
// content was compiled
|
||||
return this.IRQueue;
|
||||
return this.operatorList;
|
||||
}
|
||||
|
||||
this.stats.time('Build IR Queue');
|
||||
|
||||
var xref = this.xref;
|
||||
var content = xref.fetchIfRef(this.content);
|
||||
var resources = xref.fetchIfRef(this.resources);
|
||||
@ -216,30 +214,33 @@ var Page = (function PageClosure() {
|
||||
|
||||
var pe = this.pe = new PartialEvaluator(
|
||||
xref, handler, 'p' + this.pageNumber + '_');
|
||||
var IRQueue = {};
|
||||
return (this.IRQueue = pe.getIRQueue(content, resources, IRQueue,
|
||||
dependency));
|
||||
|
||||
this.operatorList = pe.getOperatorList(content, resources, dependency);
|
||||
this.stats.timeEnd('Build IR Queue');
|
||||
return this.operatorList;
|
||||
},
|
||||
|
||||
ensureFonts: function pageEnsureFonts(fonts, callback) {
|
||||
this.stats.time('Font Loading');
|
||||
// Convert the font names to the corresponding font obj.
|
||||
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
||||
fonts[i] = this.objs.objs[fonts[i]].data;
|
||||
}
|
||||
|
||||
// Load all the fonts
|
||||
var fontObjs = FontLoader.bind(
|
||||
FontLoader.bind(
|
||||
fonts,
|
||||
function pageEnsureFontsFontObjs(fontObjs) {
|
||||
this.stats.fonts = Date.now();
|
||||
this.stats.timeEnd('Font Loading');
|
||||
|
||||
callback.call(this);
|
||||
}.bind(this),
|
||||
this.objs
|
||||
}.bind(this)
|
||||
);
|
||||
},
|
||||
|
||||
display: function pageDisplay(gfx, callback) {
|
||||
var stats = this.stats;
|
||||
stats.time('Rendering');
|
||||
var xref = this.xref;
|
||||
var resources = xref.fetchIfRef(this.resources);
|
||||
var mediaBox = xref.fetchIfRef(this.mediaBox);
|
||||
@ -253,21 +254,23 @@ var Page = (function PageClosure() {
|
||||
rotate: this.rotate });
|
||||
|
||||
var startIdx = 0;
|
||||
var length = this.IRQueue.fnArray.length;
|
||||
var IRQueue = this.IRQueue;
|
||||
var length = this.operatorList.fnArray.length;
|
||||
var operatorList = this.operatorList;
|
||||
var stepper = null;
|
||||
if (PDFJS.pdfBug && StepperManager.enabled) {
|
||||
stepper = StepperManager.create(this.pageNumber);
|
||||
stepper.init(IRQueue);
|
||||
stepper.init(operatorList);
|
||||
stepper.nextBreakPoint = stepper.getNextBreakPoint();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
function next() {
|
||||
startIdx = gfx.executeIRQueue(IRQueue, startIdx, next, stepper);
|
||||
startIdx =
|
||||
gfx.executeOperatorList(operatorList, startIdx, next, stepper);
|
||||
if (startIdx == length) {
|
||||
self.stats.render = Date.now();
|
||||
gfx.endDrawing();
|
||||
stats.timeEnd('Rendering');
|
||||
stats.timeEnd('Overall');
|
||||
if (callback) callback();
|
||||
}
|
||||
}
|
||||
@ -310,6 +313,22 @@ var Page = (function PageClosure() {
|
||||
return null;
|
||||
return item.get(name);
|
||||
}
|
||||
function isValidUrl(url) {
|
||||
if (!url)
|
||||
return false;
|
||||
var colon = url.indexOf(':');
|
||||
if (colon < 0)
|
||||
return false;
|
||||
var protocol = url.substr(0, colon);
|
||||
switch (protocol) {
|
||||
case 'http':
|
||||
case 'https':
|
||||
case 'ftp':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var annotations = xref.fetchIfRef(this.annotations) || [];
|
||||
var i, n = annotations.length;
|
||||
@ -338,7 +357,12 @@ var Page = (function PageClosure() {
|
||||
if (a) {
|
||||
switch (a.get('S').name) {
|
||||
case 'URI':
|
||||
item.url = a.get('URI');
|
||||
var url = a.get('URI');
|
||||
// TODO: pdf spec mentions urls can be relative to a Base
|
||||
// entry in the dictionary.
|
||||
if (!isValidUrl(url))
|
||||
url = '';
|
||||
item.url = url;
|
||||
break;
|
||||
case 'GoTo':
|
||||
item.dest = a.get('D');
|
||||
@ -410,16 +434,16 @@ var Page = (function PageClosure() {
|
||||
return items;
|
||||
},
|
||||
startRendering: function pageStartRendering(ctx, callback, textLayer) {
|
||||
this.startRenderingTime = Date.now();
|
||||
|
||||
// If there is no displayReadyPromise yet, then the IRQueue was never
|
||||
var stats = this.stats;
|
||||
stats.time('Overall');
|
||||
// If there is no displayReadyPromise yet, then the operatorList was never
|
||||
// requested before. Make the request and create the promise.
|
||||
if (!this.displayReadyPromise) {
|
||||
this.pdf.startRendering(this);
|
||||
this.displayReadyPromise = new Promise();
|
||||
}
|
||||
|
||||
// Once the IRQueue and fonts are loaded, perform the actual rendering.
|
||||
// Once the operatorList and fonts are loaded, do the actual rendering.
|
||||
this.displayReadyPromise.then(
|
||||
function pageDisplayReadyPromise() {
|
||||
var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
|
||||
@ -451,9 +475,6 @@ var Page = (function PageClosure() {
|
||||
* Right now there exists one PDFDocModel on the main thread + one object
|
||||
* for each worker. If there is no worker support enabled, there are two
|
||||
* `PDFDocModel` objects on the main thread created.
|
||||
* TODO: Refactor the internal object structure, such that there is no
|
||||
* need for the `PDFDocModel` anymore and there is only one object on the
|
||||
* main thread and not one entire copy on each worker instance.
|
||||
*/
|
||||
var PDFDocModel = (function PDFDocModelClosure() {
|
||||
function PDFDocModel(arg, callback) {
|
||||
@ -622,9 +643,9 @@ var PDFDoc = (function PDFDocClosure() {
|
||||
|
||||
this.data = data;
|
||||
this.stream = stream;
|
||||
this.pdf = new PDFDocModel(stream);
|
||||
this.fingerprint = this.pdf.getFingerprint();
|
||||
this.catalog = this.pdf.catalog;
|
||||
this.pdfModel = new PDFDocModel(stream);
|
||||
this.fingerprint = this.pdfModel.getFingerprint();
|
||||
this.catalog = this.pdfModel.catalog;
|
||||
this.objs = new PDFObjects();
|
||||
|
||||
this.pageCache = [];
|
||||
@ -711,7 +732,8 @@ var PDFDoc = (function PDFDocClosure() {
|
||||
var page = this.pageCache[pageNum];
|
||||
var depFonts = data.depFonts;
|
||||
|
||||
page.startRenderingFromIRQueue(data.IRQueue, depFonts);
|
||||
page.stats.timeEnd('Page Request');
|
||||
page.startRenderingFromOperatorList(data.operatorList, depFonts);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('obj', function pdfDocObj(data) {
|
||||
@ -738,31 +760,16 @@ var PDFDoc = (function PDFDocClosure() {
|
||||
file = new Stream(file, 0, file.length, fontFileDict);
|
||||
}
|
||||
|
||||
// For now, resolve the font object here direclty. The real font
|
||||
// object is then created in FontLoader.bind().
|
||||
this.objs.resolve(id, {
|
||||
name: name,
|
||||
file: file,
|
||||
properties: properties
|
||||
});
|
||||
// At this point, only the font object is created but the font is
|
||||
// not yet attached to the DOM. This is done in `FontLoader.bind`.
|
||||
var font = new Font(name, file, properties);
|
||||
this.objs.resolve(id, font);
|
||||
break;
|
||||
default:
|
||||
error('Got unkown object type ' + type);
|
||||
}
|
||||
}, this);
|
||||
|
||||
messageHandler.on('font_ready', function pdfDocFontReady(data) {
|
||||
var id = data[0];
|
||||
var font = new FontShape(data[1]);
|
||||
|
||||
// If there is no string, then there is nothing to attach to the DOM.
|
||||
if (!font.str) {
|
||||
this.objs.resolve(id, font);
|
||||
} else {
|
||||
this.objs.setData(id, font);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
messageHandler.on('page_error', function pdfDocError(data) {
|
||||
var page = this.pageCache[data.pageNum];
|
||||
if (page.displayReadyPromise)
|
||||
@ -784,7 +791,7 @@ var PDFDoc = (function PDFDocClosure() {
|
||||
var size = width * height;
|
||||
var rgbaLength = size * 4;
|
||||
var buf = new Uint8Array(size * components);
|
||||
var tmpCanvas = new ScratchCanvas(width, height);
|
||||
var tmpCanvas = createScratchCanvas(width, height);
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
tmpCtx.drawImage(img, 0, 0);
|
||||
var data = tmpCtx.getImageData(0, 0, width, height).data;
|
||||
@ -813,12 +820,13 @@ var PDFDoc = (function PDFDocClosure() {
|
||||
},
|
||||
|
||||
get numPages() {
|
||||
return this.pdf.numPages;
|
||||
return this.pdfModel.numPages;
|
||||
},
|
||||
|
||||
startRendering: function pdfDocStartRendering(page) {
|
||||
// The worker might not be ready to receive the page request yet.
|
||||
this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
|
||||
page.stats.time('Page Request');
|
||||
this.messageHandler.send('page_request', page.pageNumber + 1);
|
||||
}.bind(this));
|
||||
},
|
||||
@ -827,7 +835,7 @@ var PDFDoc = (function PDFDocClosure() {
|
||||
if (this.pageCache[n])
|
||||
return this.pageCache[n];
|
||||
|
||||
var page = this.pdf.getPage(n);
|
||||
var page = this.pdfModel.getPage(n);
|
||||
// Add a reference to the objects such that Page can forward the reference
|
||||
// to the CanvasGraphics and so on.
|
||||
page.objs = this.objs;
|
||||
|
@ -570,7 +570,6 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
||||
};
|
||||
}
|
||||
error('Unknown crypto method');
|
||||
return null;
|
||||
}
|
||||
|
||||
CipherTransformFactory.prototype = {
|
||||
|
@ -112,8 +112,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
};
|
||||
|
||||
PartialEvaluator.prototype = {
|
||||
getIRQueue: function partialEvaluatorGetIRQueue(stream, resources,
|
||||
queue, dependency) {
|
||||
getOperatorList: function partialEvaluatorGetOperatorList(stream, resources,
|
||||
dependency, queue) {
|
||||
|
||||
var self = this;
|
||||
var xref = this.xref;
|
||||
@ -136,8 +136,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
|
||||
var fontRes = resources.get('Font');
|
||||
|
||||
// TODO: TOASK: Is it possible to get here? If so, what does
|
||||
// args[0].name should be like???
|
||||
assert(fontRes, 'fontRes not available');
|
||||
|
||||
fontRes = xref.fetchIfRef(fontRes);
|
||||
@ -177,7 +175,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
|
||||
// Ensure the font is ready before the font is set
|
||||
// and later on used for drawing.
|
||||
// TODO: This should get insert to the IRQueue only once per
|
||||
// OPTIMIZE: This should get insert to the operatorList only once per
|
||||
// page.
|
||||
insertDependency([loadedName]);
|
||||
return loadedName;
|
||||
@ -239,6 +237,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
}, handler, xref, resources, image, inline);
|
||||
}
|
||||
|
||||
if (!queue)
|
||||
queue = {};
|
||||
|
||||
if (!queue.argsArray) {
|
||||
queue.argsArray = [];
|
||||
}
|
||||
@ -280,9 +281,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
// TODO figure out how to type-check vararg functions
|
||||
|
||||
if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
|
||||
// Use the IR version for setStroke/FillColorN.
|
||||
fn += '_IR';
|
||||
|
||||
// compile tiling patterns
|
||||
var patternName = args[args.length - 1];
|
||||
// SCN/scn applies patterns along with normal colors
|
||||
@ -295,15 +293,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
if (typeNum == TILING_PATTERN) {
|
||||
// Create an IR of the pattern code.
|
||||
var depIdx = dependencyArray.length;
|
||||
var queueObj = {};
|
||||
var codeIR = this.getIRQueue(pattern, dict.get('Resources') ||
|
||||
resources, queueObj, dependencyArray);
|
||||
var operatorList = this.getOperatorList(pattern,
|
||||
dict.get('Resources') || resources, dependencyArray);
|
||||
|
||||
// Add the dependencies that are required to execute the
|
||||
// codeIR.
|
||||
// operatorList.
|
||||
insertDependency(dependencyArray.slice(depIdx));
|
||||
|
||||
args = TilingPattern.getIR(codeIR, dict, args);
|
||||
args = TilingPattern.getIR(operatorList, dict, args);
|
||||
}
|
||||
else if (typeNum == SHADING_PATTERN) {
|
||||
var shading = xref.fetchIfRef(dict.get('Shading'));
|
||||
@ -337,14 +334,18 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
fnArray.push('paintFormXObjectBegin');
|
||||
argsArray.push([matrix, bbox]);
|
||||
|
||||
// This adds the IRQueue of the xObj to the current queue.
|
||||
// This adds the operatorList of the xObj to the current queue.
|
||||
var depIdx = dependencyArray.length;
|
||||
|
||||
this.getIRQueue(xobj, xobj.dict.get('Resources') || resources,
|
||||
queue, dependencyArray);
|
||||
// Pass in the current `queue` object. That means the `fnArray`
|
||||
// and the `argsArray` in this scope is reused and new commands
|
||||
// are added to them.
|
||||
this.getOperatorList(xobj,
|
||||
xobj.dict.get('Resources') || resources,
|
||||
dependencyArray, queue);
|
||||
|
||||
// Add the dependencies that are required to execute the
|
||||
// codeIR.
|
||||
// operatorList.
|
||||
insertDependency(dependencyArray.slice(depIdx));
|
||||
|
||||
fn = 'paintFormXObjectEnd';
|
||||
@ -454,10 +455,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
fnArray: fnArray,
|
||||
argsArray: argsArray
|
||||
};
|
||||
return queue;
|
||||
},
|
||||
|
||||
extractDataStructures: function
|
||||
@ -855,12 +853,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
var charProcs = xref.fetchIfRef(dict.get('CharProcs'));
|
||||
var fontResources = xref.fetchIfRef(dict.get('Resources')) || resources;
|
||||
properties.resources = fontResources;
|
||||
properties.charProcIRQueues = {};
|
||||
properties.charProcOperatorList = {};
|
||||
for (var key in charProcs.map) {
|
||||
var glyphStream = xref.fetchIfRef(charProcs.map[key]);
|
||||
var queueObj = {};
|
||||
properties.charProcIRQueues[key] =
|
||||
this.getIRQueue(glyphStream, fontResources, queueObj, dependency);
|
||||
properties.charProcOperatorList[key] =
|
||||
this.getOperatorList(glyphStream, fontResources, dependency);
|
||||
}
|
||||
}
|
||||
|
||||
|
70
src/fonts.js
70
src/fonts.js
@ -409,8 +409,8 @@ var FontLoader = {
|
||||
|
||||
bind: function fontLoaderBind(fonts, callback) {
|
||||
function checkFontsLoaded() {
|
||||
for (var i = 0, ii = objs.length; i < ii; i++) {
|
||||
var fontObj = objs[i];
|
||||
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
||||
var fontObj = fonts[i];
|
||||
if (fontObj.loading) {
|
||||
return false;
|
||||
}
|
||||
@ -423,52 +423,45 @@ var FontLoader = {
|
||||
return true;
|
||||
}
|
||||
|
||||
var rules = [], names = [], objs = [];
|
||||
var rules = [], names = [], fontsToLoad = [];
|
||||
var fontCreateTimer = 0;
|
||||
|
||||
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
||||
var font = fonts[i];
|
||||
|
||||
// If there is already a fontObj on the font, then it was loaded/attached
|
||||
// to the page already and we don't have to do anything for this font
|
||||
// here future.
|
||||
if (font.fontObj) {
|
||||
// Add the font to the DOM only once or skip if the font
|
||||
// is already loaded.
|
||||
if (font.attached || font.loading == false) {
|
||||
continue;
|
||||
}
|
||||
font.attached = true;
|
||||
|
||||
var obj = new Font(font.name, font.file, font.properties);
|
||||
|
||||
// Store the fontObj on the font such that `setFont` in CanvasGraphics
|
||||
// can reuse it later again.
|
||||
font.fontObj = obj;
|
||||
|
||||
objs.push(obj);
|
||||
fontsToLoad.push(font);
|
||||
|
||||
var str = '';
|
||||
var data = obj.data;
|
||||
var data = font.data;
|
||||
if (data) {
|
||||
var length = data.length;
|
||||
for (var j = 0; j < length; j++)
|
||||
str += String.fromCharCode(data[j]);
|
||||
|
||||
var rule = isWorker ? obj.bindWorker(str) : obj.bindDOM(str);
|
||||
var rule = font.bindDOM(str);
|
||||
if (rule) {
|
||||
rules.push(rule);
|
||||
names.push(obj.loadedName);
|
||||
names.push(font.loadedName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.listeningForFontLoad = false;
|
||||
if (!isWorker && rules.length) {
|
||||
FontLoader.prepareFontLoadEvent(rules, names, objs);
|
||||
FontLoader.prepareFontLoadEvent(rules, names, fontsToLoad);
|
||||
}
|
||||
|
||||
if (!checkFontsLoaded()) {
|
||||
document.documentElement.addEventListener(
|
||||
'pdfjsFontLoad', checkFontsLoaded, false);
|
||||
}
|
||||
|
||||
return objs;
|
||||
},
|
||||
// Set things up so that at least one pdfjsFontLoad event is
|
||||
// dispatched when all the @font-face |rules| for |names| have been
|
||||
@ -476,7 +469,7 @@ var FontLoader = {
|
||||
// has already started in this (outer) document, so that they should
|
||||
// be ordered before the load in the subdocument.
|
||||
prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names,
|
||||
objs) {
|
||||
fonts) {
|
||||
/** Hack begin */
|
||||
// There's no event when a font has finished downloading so the
|
||||
// following code is a dirty hack to 'guess' when a font is
|
||||
@ -500,6 +493,15 @@ var FontLoader = {
|
||||
// The postMessage() hackery was added to work around chrome bug
|
||||
// 82402.
|
||||
|
||||
// Validate the names parameter -- the values can used to construct HTML.
|
||||
if (!/^\w+$/.test(names.join(''))) {
|
||||
error('Invalid font name(s): ' + names.join());
|
||||
|
||||
// Normally the error-function throws. But if a malicious code
|
||||
// intercepts the function call then the return is needed.
|
||||
return;
|
||||
}
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.setAttribute('style',
|
||||
'visibility: hidden;' +
|
||||
@ -517,8 +519,8 @@ var FontLoader = {
|
||||
'message',
|
||||
function fontLoaderMessage(e) {
|
||||
var fontNames = JSON.parse(e.data);
|
||||
for (var i = 0, ii = objs.length; i < ii; ++i) {
|
||||
var font = objs[i];
|
||||
for (var i = 0, ii = fonts.length; i < ii; ++i) {
|
||||
var font = fonts[i];
|
||||
font.loading = false;
|
||||
}
|
||||
var evt = document.createEvent('Events');
|
||||
@ -764,7 +766,7 @@ var Font = (function FontClosure() {
|
||||
function Font(name, file, properties) {
|
||||
this.name = name;
|
||||
this.coded = properties.coded;
|
||||
this.charProcIRQueues = properties.charProcIRQueues;
|
||||
this.charProcOperatorList = properties.charProcOperatorList;
|
||||
this.resources = properties.resources;
|
||||
this.sizes = [];
|
||||
|
||||
@ -829,8 +831,6 @@ var Font = (function FontClosure() {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadedName = getUniqueName();
|
||||
properties.id = this.loadedName;
|
||||
var data;
|
||||
switch (type) {
|
||||
case 'Type1':
|
||||
@ -864,6 +864,7 @@ var Font = (function FontClosure() {
|
||||
this.widthMultiplier = !properties.fontMatrix ? 1.0 :
|
||||
1.0 / properties.fontMatrix[0];
|
||||
this.encoding = properties.baseEncoding;
|
||||
this.loadedName = properties.loadedName;
|
||||
this.loading = true;
|
||||
};
|
||||
|
||||
@ -2273,17 +2274,6 @@ var Font = (function FontClosure() {
|
||||
}
|
||||
},
|
||||
|
||||
bindWorker: function font_bindWorker(data) {
|
||||
postMessage({
|
||||
action: 'font',
|
||||
data: {
|
||||
raw: data,
|
||||
fontName: this.loadedName,
|
||||
mimetype: this.mimetype
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
bindDOM: function font_bindDom(data) {
|
||||
var fontName = this.loadedName;
|
||||
|
||||
@ -2337,7 +2327,7 @@ var Font = (function FontClosure() {
|
||||
},
|
||||
|
||||
charToGlyph: function fonts_charToGlyph(charcode) {
|
||||
var fontCharCode, width, codeIRQueue;
|
||||
var fontCharCode, width, operatorList;
|
||||
|
||||
var width = this.widths[charcode];
|
||||
|
||||
@ -2372,7 +2362,7 @@ var Font = (function FontClosure() {
|
||||
break;
|
||||
case 'Type3':
|
||||
var glyphName = this.differences[charcode] || this.encoding[charcode];
|
||||
codeIRQueue = this.charProcIRQueues[glyphName];
|
||||
operatorList = this.charProcOperatorList[glyphName];
|
||||
fontCharCode = charcode;
|
||||
break;
|
||||
case 'TrueType':
|
||||
@ -2415,7 +2405,7 @@ var Font = (function FontClosure() {
|
||||
fontChar: String.fromCharCode(fontCharCode),
|
||||
unicode: unicodeChars,
|
||||
width: width,
|
||||
codeIRQueue: codeIRQueue
|
||||
operatorList: operatorList
|
||||
};
|
||||
},
|
||||
|
||||
|
11
src/obj.js
11
src/obj.js
@ -134,6 +134,8 @@ var Catalog = (function CatalogClosure() {
|
||||
while (queue.length > 0) {
|
||||
var i = queue.shift();
|
||||
var outlineDict = xref.fetch(i.obj);
|
||||
if (outlineDict === null)
|
||||
continue;
|
||||
if (!outlineDict.has('Title'))
|
||||
error('Invalid outline item');
|
||||
var dest = outlineDict.get('A');
|
||||
@ -512,7 +514,6 @@ var XRef = (function XRefClosure() {
|
||||
return dict;
|
||||
// nothing helps
|
||||
error('Invalid PDF structure');
|
||||
return null;
|
||||
},
|
||||
readXRef: function readXref(startXRef) {
|
||||
var stream = this.stream;
|
||||
@ -569,6 +570,8 @@ var XRef = (function XRefClosure() {
|
||||
},
|
||||
getEntry: function xRefGetEntry(i) {
|
||||
var e = this.entries[i];
|
||||
if (e === null)
|
||||
return null;
|
||||
return e.free ? null : e; // returns null is the entry is free
|
||||
},
|
||||
fetchIfRef: function xRefFetchIfRef(obj) {
|
||||
@ -719,12 +722,10 @@ var PDFObjects = (function PDFObjectsClosure() {
|
||||
|
||||
// If there isn't an object yet or the object isn't resolved, then the
|
||||
// data isn't ready yet!
|
||||
if (!obj || !obj.isResolved) {
|
||||
if (!obj || !obj.isResolved)
|
||||
error('Requesting object that isn\'t resolved yet ' + objId);
|
||||
return null;
|
||||
} else {
|
||||
|
||||
return obj.data;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -53,16 +53,15 @@ var Parser = (function ParserClosure() {
|
||||
this.shift();
|
||||
var dict = new Dict();
|
||||
while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
|
||||
if (!isName(this.buf1)) {
|
||||
if (!isName(this.buf1))
|
||||
error('Dictionary key must be a name object');
|
||||
} else {
|
||||
|
||||
var key = this.buf1.name;
|
||||
this.shift();
|
||||
if (isEOF(this.buf1))
|
||||
break;
|
||||
dict.set(key, this.getObj(cipherTransform));
|
||||
}
|
||||
}
|
||||
if (isEOF(this.buf1))
|
||||
error('End of file inside dictionary');
|
||||
|
||||
@ -106,16 +105,15 @@ var Parser = (function ParserClosure() {
|
||||
// parse dictionary
|
||||
var dict = new Dict();
|
||||
while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
|
||||
if (!isName(this.buf1)) {
|
||||
if (!isName(this.buf1))
|
||||
error('Dictionary key must be a name object');
|
||||
} else {
|
||||
|
||||
var key = this.buf1.name;
|
||||
this.shift();
|
||||
if (isEOF(this.buf1))
|
||||
break;
|
||||
dict.set(key, this.getObj(cipherTransform));
|
||||
}
|
||||
}
|
||||
|
||||
// parse image stream
|
||||
var startPos = stream.pos;
|
||||
@ -176,10 +174,8 @@ var Parser = (function ParserClosure() {
|
||||
|
||||
// get length
|
||||
var length = this.fetchIfRef(dict.get('Length'));
|
||||
if (!isInt(length)) {
|
||||
if (!isInt(length))
|
||||
error('Bad ' + length + ' attribute in stream');
|
||||
length = 0;
|
||||
}
|
||||
|
||||
// skip over the stream data
|
||||
stream.pos = pos + length;
|
||||
@ -208,7 +204,7 @@ var Parser = (function ParserClosure() {
|
||||
filter = filterArray[i];
|
||||
if (!isName(filter))
|
||||
error('Bad filter name: ' + filter);
|
||||
else {
|
||||
|
||||
params = null;
|
||||
if (isArray(paramsArray) && (i in paramsArray))
|
||||
params = paramsArray[i];
|
||||
@ -217,7 +213,6 @@ var Parser = (function ParserClosure() {
|
||||
length = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return stream;
|
||||
},
|
||||
makeFilter: function parserMakeFilter(stream, name, length, params) {
|
||||
@ -527,17 +522,15 @@ var Lexer = (function LexerClosure() {
|
||||
// fall through
|
||||
case ')':
|
||||
error('Illegal character: ' + ch);
|
||||
return Error;
|
||||
}
|
||||
|
||||
// command
|
||||
var str = ch;
|
||||
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
|
||||
stream.skip();
|
||||
if (str.length == 128) {
|
||||
if (str.length == 128)
|
||||
error('Command token too long: ' + str.length);
|
||||
break;
|
||||
}
|
||||
|
||||
str += ch;
|
||||
}
|
||||
if (str == 'true')
|
||||
@ -594,7 +587,6 @@ var Linearization = (function LinearizationClosure() {
|
||||
return obj;
|
||||
}
|
||||
error('"' + name + '" field in linearization table is invalid');
|
||||
return 0;
|
||||
},
|
||||
getHint: function linearizationGetHint(index) {
|
||||
var linDict = this.linDict;
|
||||
@ -607,7 +599,6 @@ var Linearization = (function LinearizationClosure() {
|
||||
return obj2;
|
||||
}
|
||||
error('Hints table in linearization table is invalid: ' + index);
|
||||
return 0;
|
||||
},
|
||||
get length() {
|
||||
if (!isDict(this.linDict))
|
||||
|
@ -82,7 +82,7 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
||||
fnObj = xref.fetchIfRef(fnObj);
|
||||
if (isArray(fnObj))
|
||||
error('No support for array of functions');
|
||||
else if (!isPDFFunction(fnObj))
|
||||
if (!isPDFFunction(fnObj))
|
||||
error('Invalid function');
|
||||
var fn = PDFFunction.parse(xref, fnObj);
|
||||
|
||||
@ -190,7 +190,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
var MAX_PATTERN_SIZE = 512;
|
||||
|
||||
function TilingPattern(IR, color, ctx, objs) {
|
||||
var IRQueue = IR[2];
|
||||
var operatorList = IR[2];
|
||||
this.matrix = IR[3];
|
||||
var bbox = IR[4];
|
||||
var xstep = IR[5];
|
||||
@ -222,7 +222,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
width = height = MAX_PATTERN_SIZE;
|
||||
}
|
||||
|
||||
var tmpCanvas = new ScratchCanvas(width, height);
|
||||
var tmpCanvas = createScratchCanvas(width, height);
|
||||
|
||||
// set the new canvas element context as the graphics context
|
||||
var tmpCtx = tmpCanvas.getContext('2d');
|
||||
@ -259,12 +259,12 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
graphics.endPath();
|
||||
}
|
||||
|
||||
graphics.executeIRQueue(IRQueue);
|
||||
graphics.executeOperatorList(operatorList);
|
||||
|
||||
this.canvas = tmpCanvas;
|
||||
}
|
||||
|
||||
TilingPattern.getIR = function tiling_getIR(codeIR, dict, args) {
|
||||
TilingPattern.getIR = function tiling_getIR(operatorList, dict, args) {
|
||||
var matrix = dict.get('Matrix');
|
||||
var bbox = dict.get('BBox');
|
||||
var xstep = dict.get('XStep');
|
||||
@ -272,7 +272,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
var paintType = dict.get('PaintType');
|
||||
|
||||
return [
|
||||
'TilingPattern', args, codeIR, matrix, bbox, xstep, ystep, paintType
|
||||
'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, paintType
|
||||
];
|
||||
};
|
||||
|
||||
|
54
src/util.js
54
src/util.js
@ -402,7 +402,7 @@ var Promise = (function PromiseClosure() {
|
||||
if (this.isResolved) {
|
||||
var data = this.data;
|
||||
callback.call(null, data);
|
||||
} else if (this.isRejected && errorback) {
|
||||
} else if (this.isRejected && errback) {
|
||||
var error = this.error;
|
||||
errback.call(null, error);
|
||||
} else {
|
||||
@ -416,3 +416,55 @@ var Promise = (function PromiseClosure() {
|
||||
return Promise;
|
||||
})();
|
||||
|
||||
var StatTimer = (function StatTimerClosure() {
|
||||
function rpad(str, pad, length) {
|
||||
while (str.length < length)
|
||||
str += pad;
|
||||
return str;
|
||||
}
|
||||
function StatTimer() {
|
||||
this.started = {};
|
||||
this.times = [];
|
||||
this.enabled = true;
|
||||
}
|
||||
StatTimer.prototype = {
|
||||
time: function statTimerTime(name) {
|
||||
if (!this.enabled)
|
||||
return;
|
||||
if (name in this.started)
|
||||
throw 'Timer is already running for ' + name;
|
||||
this.started[name] = Date.now();
|
||||
},
|
||||
timeEnd: function statTimerTimeEnd(name) {
|
||||
if (!this.enabled)
|
||||
return;
|
||||
if (!(name in this.started))
|
||||
throw 'Timer has not been started for ' + name;
|
||||
this.times.push({
|
||||
'name': name,
|
||||
'start': this.started[name],
|
||||
'end': Date.now()
|
||||
});
|
||||
// Remove timer from started so it can be called again.
|
||||
delete this.started[name];
|
||||
},
|
||||
toString: function statTimerToString() {
|
||||
var times = this.times;
|
||||
var out = '';
|
||||
// Find the longest name for padding purposes.
|
||||
var longest = 0;
|
||||
for (var i = 0, ii = times.length; i < ii; ++i) {
|
||||
var name = times[i]['name'];
|
||||
if (name.length > longest)
|
||||
longest = name.length;
|
||||
}
|
||||
for (var i = 0, ii = times.length; i < ii; ++i) {
|
||||
var span = times[i];
|
||||
var duration = span.end - span.start;
|
||||
out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
return StatTimer;
|
||||
})();
|
||||
|
@ -79,7 +79,7 @@ MessageHandler.prototype = {
|
||||
|
||||
var WorkerMessageHandler = {
|
||||
setup: function wphSetup(handler) {
|
||||
var pdfDoc = null;
|
||||
var pdfModel = null;
|
||||
|
||||
handler.on('test', function wphSetupTest(data) {
|
||||
handler.send('test', data instanceof Uint8Array);
|
||||
@ -88,7 +88,7 @@ var WorkerMessageHandler = {
|
||||
handler.on('doc', function wphSetupDoc(data) {
|
||||
// Create only the model of the PDFDoc, which is enough for
|
||||
// processing the content of the pdf.
|
||||
pdfDoc = new PDFDocModel(new Stream(data));
|
||||
pdfModel = new PDFDocModel(new Stream(data));
|
||||
});
|
||||
|
||||
handler.on('page_request', function wphSetupPageRequest(pageNum) {
|
||||
@ -103,14 +103,14 @@ var WorkerMessageHandler = {
|
||||
var start = Date.now();
|
||||
|
||||
var dependency = [];
|
||||
var IRQueue = null;
|
||||
var operatorList = null;
|
||||
try {
|
||||
var page = pdfDoc.getPage(pageNum);
|
||||
var page = pdfModel.getPage(pageNum);
|
||||
// Pre compile the pdf page and fetch the fonts/images.
|
||||
IRQueue = page.getIRQueue(handler, dependency);
|
||||
operatorList = page.getOperatorList(handler, dependency);
|
||||
} catch (e) {
|
||||
var minimumStackMessage =
|
||||
'worker.js: while trying to getPage() and getIRQueue()';
|
||||
'worker.js: while trying to getPage() and getOperatorList()';
|
||||
|
||||
// Turn the error into an obj that can be serialized
|
||||
if (typeof e === 'string') {
|
||||
@ -137,8 +137,8 @@ var WorkerMessageHandler = {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum,
|
||||
Date.now() - start, IRQueue.fnArray.length);
|
||||
console.log('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
|
||||
Date.now() - start, operatorList.fnArray.length);
|
||||
|
||||
// Filter the dependecies for fonts.
|
||||
var fonts = {};
|
||||
@ -151,59 +151,10 @@ var WorkerMessageHandler = {
|
||||
|
||||
handler.send('page', {
|
||||
pageNum: pageNum,
|
||||
IRQueue: IRQueue,
|
||||
operatorList: operatorList,
|
||||
depFonts: Object.keys(fonts)
|
||||
});
|
||||
}, this);
|
||||
|
||||
handler.on('font', function wphSetupFont(data) {
|
||||
var objId = data[0];
|
||||
var name = data[1];
|
||||
var file = data[2];
|
||||
var properties = data[3];
|
||||
|
||||
var font = {
|
||||
name: name,
|
||||
file: file,
|
||||
properties: properties
|
||||
};
|
||||
|
||||
// Some fonts don't have a file, e.g. the build in ones like Arial.
|
||||
if (file) {
|
||||
var fontFileDict = new Dict();
|
||||
fontFileDict.map = file.dict.map;
|
||||
|
||||
var fontFile = new Stream(file.bytes, file.start,
|
||||
file.end - file.start, fontFileDict);
|
||||
|
||||
// Check if this is a FlateStream. Otherwise just use the created
|
||||
// Stream one. This makes complex_ttf_font.pdf work.
|
||||
var cmf = file.bytes[0];
|
||||
if ((cmf & 0x0f) == 0x08) {
|
||||
font.file = new FlateStream(fontFile);
|
||||
} else {
|
||||
font.file = fontFile;
|
||||
}
|
||||
}
|
||||
|
||||
var obj = new Font(font.name, font.file, font.properties);
|
||||
|
||||
var str = '';
|
||||
var objData = obj.data;
|
||||
if (objData) {
|
||||
var length = objData.length;
|
||||
for (var j = 0; j < length; ++j)
|
||||
str += String.fromCharCode(objData[j]);
|
||||
}
|
||||
|
||||
obj.str = str;
|
||||
|
||||
// Remove the data array form the font object, as it's not needed
|
||||
// anymore as we sent over the ready str.
|
||||
delete obj.data;
|
||||
|
||||
handler.send('font_ready', [objId, obj]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -20,6 +20,7 @@
|
||||
!scan-bad.pdf
|
||||
!freeculture.pdf
|
||||
!pdfkit_compressed.pdf
|
||||
!TAMReview.pdf
|
||||
!issue918.pdf
|
||||
!issue1249.pdf
|
||||
!smaskdim.pdf
|
||||
|
BIN
test/pdfs/TAMReview.pdf
Normal file
BIN
test/pdfs/TAMReview.pdf
Normal file
Binary file not shown.
@ -472,6 +472,14 @@
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "tamreview",
|
||||
"file": "pdfs/TAMReview.pdf",
|
||||
"md5": "8039aba56790d3597d2bc8c794a51301",
|
||||
"rounds": 1,
|
||||
"pageLimit": 5,
|
||||
"link": true,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "issue925",
|
||||
"file": "pdfs/issue925.pdf",
|
||||
"md5": "f58fe943090aff89dcc8e771bc0db4c2",
|
||||
|
@ -318,6 +318,58 @@ var Stepper = (function StepperClosure() {
|
||||
return Stepper;
|
||||
})();
|
||||
|
||||
var Stats = (function Stats() {
|
||||
var stats = [];
|
||||
function clear(node) {
|
||||
while (node.hasChildNodes())
|
||||
node.removeChild(node.lastChild);
|
||||
}
|
||||
function getStatIndex(pageNumber) {
|
||||
for (var i = 0, ii = stats.length; i < ii; ++i)
|
||||
if (stats[i].pageNumber === pageNumber)
|
||||
return i;
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
// Poperties/functions needed by PDFBug.
|
||||
id: 'Stats',
|
||||
name: 'Stats',
|
||||
panel: null,
|
||||
manager: null,
|
||||
init: function init() {
|
||||
this.panel.setAttribute('style', 'padding: 5px;');
|
||||
PDFJS.enableStats = true;
|
||||
},
|
||||
enabled: false,
|
||||
active: false,
|
||||
// Stats specific functions.
|
||||
add: function(pageNumber, stat) {
|
||||
if (!stat)
|
||||
return;
|
||||
var statsIndex = getStatIndex(pageNumber);
|
||||
if (statsIndex !== false) {
|
||||
var b = stats[statsIndex];
|
||||
this.panel.removeChild(b.div);
|
||||
stats.splice(statsIndex, 1);
|
||||
}
|
||||
var wrapper = document.createElement('div');
|
||||
wrapper.className = 'stats';
|
||||
var title = document.createElement('div');
|
||||
title.className = 'title';
|
||||
title.textContent = 'Page: ' + pageNumber;
|
||||
var statsDiv = document.createElement('div');
|
||||
statsDiv.textContent = stat.toString();
|
||||
wrapper.appendChild(title);
|
||||
wrapper.appendChild(statsDiv);
|
||||
stats.push({ pageNumber: pageNumber, div: wrapper });
|
||||
stats.sort(function(a, b) { return a.pageNumber - b.pageNumber});
|
||||
clear(this.panel);
|
||||
for (var i = 0, ii = stats.length; i < ii; ++i)
|
||||
this.panel.appendChild(stats[i].div);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
// Manages all the debugging tools.
|
||||
var PDFBug = (function PDFBugClosure() {
|
||||
var panelWidth = 300;
|
||||
@ -327,8 +379,29 @@ var PDFBug = (function PDFBugClosure() {
|
||||
return {
|
||||
tools: [
|
||||
FontInspector,
|
||||
StepperManager
|
||||
StepperManager,
|
||||
Stats
|
||||
],
|
||||
enable: function(ids) {
|
||||
var all = false, tools = this.tools;
|
||||
if (ids.length === 1 && ids[0] === 'all')
|
||||
all = true;
|
||||
for (var i = 0; i < tools.length; ++i) {
|
||||
var tool = tools[i];
|
||||
if (all || ids.indexOf(tool.id) !== -1)
|
||||
tool.enabled = true;
|
||||
}
|
||||
if (!all) {
|
||||
// Sort the tools by the order they are enabled.
|
||||
tools.sort(function(a, b) {
|
||||
var indexA = ids.indexOf(a.id);
|
||||
indexA = indexA < 0 ? tools.length : indexA;
|
||||
var indexB = ids.indexOf(b.id);
|
||||
indexB = indexB < 0 ? tools.length : indexB;
|
||||
return indexA - indexB;
|
||||
});
|
||||
}
|
||||
},
|
||||
init: function init() {
|
||||
/*
|
||||
* Basic Layout:
|
||||
|
@ -65,16 +65,6 @@ body {
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
span#info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@-moz-document regexp("http:.*debug=1.*") {
|
||||
span#info {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
/* === Sidebar === */
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
@ -442,3 +432,11 @@ canvas {
|
||||
background: yellow;
|
||||
opacity: 0.3;
|
||||
}
|
||||
#PDFBug .stats {
|
||||
font-size: 10px;
|
||||
white-space: pre;
|
||||
font-family: courier;
|
||||
}
|
||||
#PDFBug .stats .title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
@ -102,7 +102,6 @@
|
||||
<img src="images/bookmark.svg" alt="Bookmark" align="top" height="16"/>
|
||||
</a>
|
||||
|
||||
<span id="info">--</span>
|
||||
</div>
|
||||
<div id="errorWrapper" hidden='true'>
|
||||
<div id="errorMessageLeft">
|
||||
|
@ -234,6 +234,7 @@ var PDFView = {
|
||||
return;
|
||||
}
|
||||
|
||||
pages[val - 1].updateStats();
|
||||
currentPageNumber = val;
|
||||
var event = document.createEvent('UIEvents');
|
||||
event.initUIEvent('pagechange', false, false, window, 0);
|
||||
@ -870,7 +871,6 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
// Rendering area
|
||||
|
||||
var self = this;
|
||||
stats.begin = Date.now();
|
||||
this.content.startRendering(ctx, function pageViewDrawCallback(error) {
|
||||
if (self.loadingIconDiv) {
|
||||
div.removeChild(self.loadingIconDiv);
|
||||
@ -880,6 +880,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
if (error)
|
||||
PDFView.error('An error occurred while rendering the page.', error);
|
||||
|
||||
self.stats = content.stats;
|
||||
self.updateStats();
|
||||
if (self.onAfterDraw)
|
||||
self.onAfterDraw();
|
||||
@ -893,10 +894,10 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
};
|
||||
|
||||
this.updateStats = function pageViewUpdateStats() {
|
||||
var t1 = stats.compile, t2 = stats.fonts, t3 = stats.render;
|
||||
var str = 'Time to compile/fonts/render: ' +
|
||||
(t1 - stats.begin) + '/' + (t2 - t1) + '/' + (t3 - t2) + ' ms';
|
||||
document.getElementById('info').textContent = str;
|
||||
if (PDFJS.pdfBug && Stats.enabled) {
|
||||
var stats = this.stats;
|
||||
Stats.add(this.id, stats);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -1181,20 +1182,12 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
||||
if ('disableTextLayer' in hashParams)
|
||||
PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
|
||||
|
||||
if ('pdfBug' in hashParams) {
|
||||
if ('pdfBug' in hashParams &&
|
||||
(!PDFJS.isFirefoxExtension || FirefoxCom.request('pdfBugEnabled'))) {
|
||||
PDFJS.pdfBug = true;
|
||||
var pdfBug = hashParams['pdfBug'];
|
||||
var all = false, enabled = [];
|
||||
if (pdfBug === 'all')
|
||||
all = true;
|
||||
else
|
||||
enabled = pdfBug.split(',');
|
||||
var debugTools = PDFBug.tools;
|
||||
for (var i = 0; i < debugTools.length; ++i) {
|
||||
var tool = debugTools[i];
|
||||
if (all || enabled.indexOf(tool.id) !== -1)
|
||||
tool.enabled = true;
|
||||
}
|
||||
var enabled = pdfBug.split(',');
|
||||
PDFBug.enable(enabled);
|
||||
PDFBug.init();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user