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.
|
# copy of the pdf.js source.
|
||||||
CONTENT_DIR := content
|
CONTENT_DIR := content
|
||||||
BUILD_NUMBER := `git log --format=oneline $(EXTENSION_BASE_VERSION).. | wc -l | awk '{print $$1}'`
|
BUILD_NUMBER := `git log --format=oneline $(EXTENSION_BASE_VERSION).. | wc -l | awk '{print $$1}'`
|
||||||
|
PDFJSSCRIPT_VERSION := 0.2.$(BUILD_NUMBER)
|
||||||
EXTENSION_WEB_FILES = \
|
EXTENSION_WEB_FILES = \
|
||||||
web/images \
|
web/images \
|
||||||
web/viewer.css \
|
web/viewer.css \
|
||||||
@ -225,14 +226,28 @@ FIREFOX_CONTENT_DIR := $(EXTENSION_SRC)/firefox/$(CONTENT_DIR)/
|
|||||||
FIREFOX_EXTENSION_FILES_TO_COPY = \
|
FIREFOX_EXTENSION_FILES_TO_COPY = \
|
||||||
*.js \
|
*.js \
|
||||||
*.rdf \
|
*.rdf \
|
||||||
|
*.png \
|
||||||
|
install.rdf.in \
|
||||||
|
README.mozilla \
|
||||||
components \
|
components \
|
||||||
|
../../LICENSE \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
FIREFOX_EXTENSION_FILES = \
|
FIREFOX_EXTENSION_FILES = \
|
||||||
content \
|
bootstrap.js \
|
||||||
*.js \
|
|
||||||
install.rdf \
|
install.rdf \
|
||||||
|
icon.png \
|
||||||
|
icon64.png \
|
||||||
components \
|
components \
|
||||||
content \
|
content \
|
||||||
|
LICENSE \
|
||||||
|
$(NULL)
|
||||||
|
FIREFOX_MC_EXTENSION_FILES = \
|
||||||
|
bootstrap.js \
|
||||||
|
icon.png \
|
||||||
|
icon64.png \
|
||||||
|
components \
|
||||||
|
content \
|
||||||
|
LICENSE \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
CHROME_BUILD_DIR := $(BUILD_DIR)/chrome
|
CHROME_BUILD_DIR := $(BUILD_DIR)/chrome
|
||||||
@ -265,9 +280,12 @@ extension: | production
|
|||||||
# We don't need pdf.js anymore since its inlined
|
# We don't need pdf.js anymore since its inlined
|
||||||
@rm -Rf $(FIREFOX_BUILD_CONTENT)/$(BUILD_DIR)/;
|
@rm -Rf $(FIREFOX_BUILD_CONTENT)/$(BUILD_DIR)/;
|
||||||
# Update the build version number
|
# Update the build version number
|
||||||
@sed -i.bak "s/PDFJSSCRIPT_BUILD/$(BUILD_NUMBER)/" $(FIREFOX_BUILD_DIR)/install.rdf
|
@sed -i.bak "s/PDFJSSCRIPT_VERSION/$(PDFJSSCRIPT_VERSION)/" $(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.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
|
@rm -f $(FIREFOX_BUILD_DIR)/*.bak
|
||||||
|
@find $(FIREFOX_BUILD_DIR) -name ".*" -delete
|
||||||
# Create the xpi
|
# Create the xpi
|
||||||
@cd $(FIREFOX_BUILD_DIR); zip -r $(FIREFOX_EXTENSION_NAME) $(FIREFOX_EXTENSION_FILES)
|
@cd $(FIREFOX_BUILD_DIR); zip -r $(FIREFOX_EXTENSION_NAME) $(FIREFOX_EXTENSION_FILES)
|
||||||
@echo "extension created: " $(FIREFOX_EXTENSION_NAME)
|
@echo "extension created: " $(FIREFOX_EXTENSION_NAME)
|
||||||
@ -276,6 +294,8 @@ extension: | production
|
|||||||
@rm -f $(FIREFOX_BUILD_DIR)/*.bak
|
@rm -f $(FIREFOX_BUILD_DIR)/*.bak
|
||||||
@cd $(FIREFOX_BUILD_DIR); zip -r $(FIREFOX_AMO_EXTENSION_NAME) $(FIREFOX_EXTENSION_FILES)
|
@cd $(FIREFOX_BUILD_DIR); zip -r $(FIREFOX_AMO_EXTENSION_NAME) $(FIREFOX_EXTENSION_FILES)
|
||||||
@echo "AMO extension created: " $(FIREFOX_AMO_EXTENSION_NAME)
|
@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
|
# Clear out everything in the chrome extension build directory
|
||||||
@rm -Rf $(CHROME_BUILD_DIR)
|
@rm -Rf $(CHROME_BUILD_DIR)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# PDF.JS
|
# PDF.JS
|
||||||
|
|
||||||
|
|
||||||
pdf.js is an HTML5 technology experiment that explores building a faithful
|
pdf.js is an HTML5 technology experiment that explores building a faithful
|
||||||
and efficient Portable Document Format (PDF) renderer without native code
|
and efficient Portable Document Format (PDF) renderer without native code
|
||||||
assistance.
|
assistance.
|
||||||
|
@ -1,18 +1,28 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
function isPdfDownloadable(details) {
|
||||||
|
return details.url.indexOf('pdfjs.action=download') >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
chrome.webRequest.onBeforeRequest.addListener(
|
chrome.webRequest.onBeforeRequest.addListener(
|
||||||
function(details) {
|
function(details) {
|
||||||
|
if (isPdfDownloadable(details))
|
||||||
|
return;
|
||||||
|
|
||||||
var viewerPage = 'content/web/viewer.html';
|
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 };
|
return { redirectUrl: url };
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
urls: [
|
urls: [
|
||||||
"http://*/*.pdf",
|
"http://*/*.pdf",
|
||||||
"file://*/*.pdf",
|
"file://*/*.pdf"
|
||||||
],
|
],
|
||||||
types: [ "main_frame" ]
|
types: [ "main_frame" ]
|
||||||
},
|
},
|
||||||
["blocking"]);
|
["blocking"]);
|
||||||
|
|
||||||
</script>
|
</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
|
||||||
|
|
24
extensions/firefox/bootstrap.js
vendored
24
extensions/firefox/bootstrap.js
vendored
@ -10,10 +10,14 @@ 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;
|
||||||
|
let application = Cc['@mozilla.org/fuel/application;1']
|
||||||
|
.getService(Ci.fuelIApplication);
|
||||||
|
|
||||||
Cu.import('resource://gre/modules/Services.jsm');
|
Cu.import('resource://gre/modules/Services.jsm');
|
||||||
|
|
||||||
function log(str) {
|
function log(str) {
|
||||||
|
if (!application.prefs.getValue(EXT_PREFIX + '.pdfBugEnabled', false))
|
||||||
|
return;
|
||||||
dump(str + '\n');
|
dump(str + '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,12 +64,7 @@ function startup(aData, aReason) {
|
|||||||
var ioService = Services.io;
|
var ioService = Services.io;
|
||||||
var resProt = ioService.getProtocolHandler('resource')
|
var resProt = ioService.getProtocolHandler('resource')
|
||||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||||
var aliasFile = Cc['@mozilla.org/file/local;1']
|
var aliasURI = ioService.newURI('content/', 'UTF-8', aData.resourceURI);
|
||||||
.createInstance(Ci.nsILocalFile);
|
|
||||||
var componentPath = aData.installPath.clone();
|
|
||||||
componentPath.append('content');
|
|
||||||
aliasFile.initWithPath(componentPath.path);
|
|
||||||
var aliasURI = ioService.newFileURI(aliasFile);
|
|
||||||
resProt.setSubstitution(RESOURCE_NAME, aliasURI);
|
resProt.setSubstitution(RESOURCE_NAME, aliasURI);
|
||||||
|
|
||||||
// Load the component and register it.
|
// Load the component and register it.
|
||||||
@ -73,12 +72,11 @@ function startup(aData, aReason) {
|
|||||||
'components/PdfStreamConverter.js';
|
'components/PdfStreamConverter.js';
|
||||||
Cu.import(pdfStreamConverterUrl);
|
Cu.import(pdfStreamConverterUrl);
|
||||||
Factory.register(PdfStreamConverter);
|
Factory.register(PdfStreamConverter);
|
||||||
Services.prefs.setBoolPref('extensions.pdf.js.active', true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function shutdown(aData, aReason) {
|
function shutdown(aData, aReason) {
|
||||||
if (Services.prefs.getBoolPref('extensions.pdf.js.active'))
|
if (aReason == APP_SHUTDOWN)
|
||||||
Services.prefs.setBoolPref('extensions.pdf.js.active', false);
|
return;
|
||||||
var ioService = Services.io;
|
var ioService = Services.io;
|
||||||
var resProt = ioService.getProtocolHandler('resource')
|
var resProt = ioService.getProtocolHandler('resource')
|
||||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||||
@ -87,18 +85,14 @@ function shutdown(aData, aReason) {
|
|||||||
// Remove the contract/component.
|
// Remove the contract/component.
|
||||||
Factory.unregister();
|
Factory.unregister();
|
||||||
// Unload the converter
|
// Unload the converter
|
||||||
if (pdfStreamConverterUrl) {
|
Cu.unload(pdfStreamConverterUrl);
|
||||||
Cu.unload(pdfStreamConverterUrl);
|
pdfStreamConverterUrl = null;
|
||||||
pdfStreamConverterUrl = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function install(aData, aReason) {
|
function install(aData, aReason) {
|
||||||
Services.prefs.setBoolPref('extensions.pdf.js.active', false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function uninstall(aData, aReason) {
|
function uninstall(aData, aReason) {
|
||||||
Services.prefs.clearUserPref('extensions.pdf.js.active');
|
|
||||||
application.prefs.setValue(EXT_PREFIX + '.database', '{}');
|
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/XPCOMUtils.jsm');
|
||||||
Cu.import('resource://gre/modules/Services.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) {
|
function log(aMsg) {
|
||||||
|
if (!application.prefs.getValue(EXT_PREFIX + '.pdfBugEnabled', false))
|
||||||
|
return;
|
||||||
let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
|
let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
|
||||||
Services.console.logStringMessage(msg);
|
Services.console.logStringMessage(msg);
|
||||||
dump(msg + '\n');
|
dump(msg + '\n');
|
||||||
@ -40,11 +48,6 @@ function topWindow(win) {
|
|||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIDOMWindow);
|
.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.
|
// All the priviledged actions.
|
||||||
function ChromeActions() {
|
function ChromeActions() {
|
||||||
@ -66,6 +69,9 @@ ChromeActions.prototype = {
|
|||||||
if (this.inPrivateBrowswing)
|
if (this.inPrivateBrowswing)
|
||||||
return '{}';
|
return '{}';
|
||||||
return application.prefs.getValue(EXT_PREFIX + '.database', '{}');
|
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
|
// nsIStreamConverter::asyncConvertData
|
||||||
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
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.
|
// Ignoring HTTP POST requests -- pdf.js has to repeat the request.
|
||||||
var skipConversion = false;
|
var skipConversion = false;
|
||||||
try {
|
try {
|
||||||
var request = aCtxt;
|
var request = aCtxt;
|
||||||
request.QueryInterface(Ci.nsIHttpChannel);
|
request.QueryInterface(Ci.nsIHttpChannel);
|
||||||
skipConversion = (request.requestMethod === 'POST');
|
skipConversion = (request.requestMethod !== 'GET');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Non-HTTP request... continue normally.
|
// 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">
|
<Description about="urn:mozilla:install-manifest">
|
||||||
<em:id>uriloader@pdf.js</em:id>
|
<em:id>uriloader@pdf.js</em:id>
|
||||||
<em:name>pdf.js</em:name>
|
<em:name>PDF Viewer</em:name>
|
||||||
<em:version>0.2.PDFJSSCRIPT_BUILD</em:version>
|
<em:version>PDFJSSCRIPT_VERSION</em:version>
|
||||||
<em:iconURL>chrome://pdf.js/skin/logo.png</em:iconURL>
|
|
||||||
<em:targetApplication>
|
<em:targetApplication>
|
||||||
<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>13.0a1</em:maxVersion>
|
<em:maxVersion>14.0a1</em:maxVersion>
|
||||||
</Description>
|
</Description>
|
||||||
</em:targetApplication>
|
</em:targetApplication>
|
||||||
<em:bootstrap>true</em:bootstrap>
|
<em:bootstrap>true</em:bootstrap>
|
||||||
<em:unpack>true</em:unpack>
|
<em:creator>Mozilla</em:creator>
|
||||||
<em:creator>Mozilla Labs</em:creator>
|
<em:description>Uses HTML5 to display PDF files directly in Firefox.</em:description>
|
||||||
<em:description>pdf.js uri loader</em:description>
|
|
||||||
<em:homepageURL>https://github.com/mozilla/pdf.js/</em:homepageURL>
|
<em:homepageURL>https://github.com/mozilla/pdf.js/</em:homepageURL>
|
||||||
<em:type>2</em:type>
|
<em:type>2</em:type>
|
||||||
<!-- Use the raw link for updates so we we can use SSL. -->
|
<!-- 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:Seq>
|
||||||
<RDF:li>
|
<RDF:li>
|
||||||
<RDF:Description>
|
<RDF:Description>
|
||||||
<em:version>0.2.PDFJSSCRIPT_BUILD</em:version>
|
<em:version>PDFJSSCRIPT_VERSION</em:version>
|
||||||
<em:targetApplication>
|
<em:targetApplication>
|
||||||
<RDF:Description>
|
<RDF:Description>
|
||||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
<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)
|
# 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.
|
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
|
### Example
|
||||||
@ -12,7 +14,7 @@ require('shelljs/global');
|
|||||||
|
|
||||||
// Copy files to release dir
|
// Copy files to release dir
|
||||||
mkdir('-p', 'out/Release');
|
mkdir('-p', 'out/Release');
|
||||||
cp('-R', 'lib/*.js', 'out/Release');
|
cp('-R', 'stuff/*', 'out/Release');
|
||||||
|
|
||||||
// Replace macros in each .js file
|
// Replace macros in each .js file
|
||||||
cd('lib');
|
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:
|
For convenient iteration via `for (file in ls())`, the format returned is a hash object:
|
||||||
`{ 'file1':null, 'dir1/file2':null, ...}`.
|
`{ '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 [,source ...], dest')
|
||||||
#### cp('[options ,] source_array, dest')
|
#### cp('[options ,] source_array, dest')
|
||||||
Available options:
|
Available options:
|
||||||
@ -195,6 +218,21 @@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above
|
|||||||
|
|
||||||
Creates directories.
|
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 [, file ...])
|
||||||
#### cat(file_array)
|
#### 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);
|
exports.pwd = wrap('pwd', _pwd);
|
||||||
|
|
||||||
|
|
||||||
//@
|
//@
|
||||||
//@ #### ls([options ,] path [,path ...])
|
//@ #### ls([options ,] path [,path ...])
|
||||||
//@ #### ls([options ,] path_array)
|
//@ #### ls([options ,] path_array)
|
||||||
@ -159,6 +160,54 @@ function _ls(options, paths) {
|
|||||||
exports.ls = wrap('ls', _ls);
|
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 [,source ...], dest')
|
||||||
//@ #### cp('[options ,] source_array, dest')
|
//@ #### cp('[options ,] source_array, dest')
|
||||||
@ -438,6 +487,42 @@ function _mkdir(options, dirs) {
|
|||||||
}; // mkdir
|
}; // mkdir
|
||||||
exports.mkdir = wrap('mkdir', _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 [, file ...])
|
||||||
//@ #### cat(file_array)
|
//@ #### cat(file_array)
|
||||||
|
56
make.js
56
make.js
@ -149,7 +149,7 @@ target.pagesrepo = function() {
|
|||||||
echo();
|
echo();
|
||||||
echo('Cloning project repo...');
|
echo('Cloning project repo...');
|
||||||
echo('(This operation can take a while, depending on network conditions)');
|
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});
|
{silent: true});
|
||||||
echo('Done.');
|
echo('Done.');
|
||||||
}
|
}
|
||||||
@ -168,13 +168,16 @@ target.pagesrepo = function() {
|
|||||||
//
|
//
|
||||||
|
|
||||||
var EXTENSION_WEB_FILES =
|
var EXTENSION_WEB_FILES =
|
||||||
['web/images',
|
['web/debugger.js',
|
||||||
|
'web/images',
|
||||||
'web/viewer.css',
|
'web/viewer.css',
|
||||||
'web/viewer.js',
|
'web/viewer.js',
|
||||||
'web/viewer.html',
|
'web/viewer.html',
|
||||||
'web/viewer-production.html'],
|
'web/viewer-production.html'],
|
||||||
EXTENSION_BASE_VERSION = '4bb289ec499013de66eb421737a4dbb4a9273eda',
|
EXTENSION_BASE_VERSION = '4bb289ec499013de66eb421737a4dbb4a9273eda',
|
||||||
EXTENSION_BUILD_NUMBER;
|
EXTENSION_VERSION_PREFIX = '0.2.',
|
||||||
|
EXTENSION_BUILD_NUMBER,
|
||||||
|
EXTENSION_VERSION;
|
||||||
|
|
||||||
//
|
//
|
||||||
// make extension
|
// make extension
|
||||||
@ -200,6 +203,8 @@ target.buildnumber = function() {
|
|||||||
.output.match(/\n/g).length; // get # of lines in git output
|
.output.match(/\n/g).length; // get # of lines in git output
|
||||||
|
|
||||||
echo('Extension build number: ' + EXTENSION_BUILD_NUMBER);
|
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 =
|
FIREFOX_EXTENSION_FILES_TO_COPY =
|
||||||
['*.js',
|
['*.js',
|
||||||
'*.rdf',
|
'*.rdf',
|
||||||
'components'];
|
'*.png',
|
||||||
FIREFOX_EXTENSION_FILES =
|
'install.rdf.in',
|
||||||
['content',
|
'README.mozilla',
|
||||||
'*.js',
|
|
||||||
'install.rdf',
|
|
||||||
'components',
|
'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_EXTENSION_NAME = 'pdf.js.xpi',
|
||||||
FIREFOX_AMO_EXTENSION_NAME = 'pdf.js.amo.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
|
// We don't need pdf.js anymore since its inlined
|
||||||
rm('-Rf', FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR);
|
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
|
// Update the build version number
|
||||||
sed('-i', /PDFJSSCRIPT_BUILD/, EXTENSION_BUILD_NUMBER, FIREFOX_BUILD_DIR + '/install.rdf');
|
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, 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 + '/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
|
// Create the xpi
|
||||||
cd(FIREFOX_BUILD_DIR);
|
cd(FIREFOX_BUILD_DIR);
|
||||||
@ -275,6 +300,15 @@ target.firefox = function() {
|
|||||||
exec('zip -r ' + FIREFOX_AMO_EXTENSION_NAME + ' ' + FIREFOX_EXTENSION_FILES.join(' '));
|
exec('zip -r ' + FIREFOX_AMO_EXTENSION_NAME + ' ' + FIREFOX_EXTENSION_FILES.join(' '));
|
||||||
echo('AMO extension created: ' + FIREFOX_AMO_EXTENSION_NAME);
|
echo('AMO extension created: ' + FIREFOX_AMO_EXTENSION_NAME);
|
||||||
cd(ROOT_DIR);
|
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');
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
869
src/bidi.js
869
src/bidi.js
@ -1,433 +1,436 @@
|
|||||||
/* -*- 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';
|
'use strict';
|
||||||
|
|
||||||
var bidi = PDFJS.bidi = (function bidiClosure() {
|
var bidi = PDFJS.bidi = (function bidiClosure() {
|
||||||
// Character types for symbols from 0000 to 00FF.
|
// Character types for symbols from 0000 to 00FF.
|
||||||
var baseTypes = [
|
var baseTypes = [
|
||||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS',
|
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS',
|
||||||
'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
||||||
'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON',
|
'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON',
|
||||||
'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN',
|
'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN',
|
||||||
'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON',
|
'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON',
|
||||||
'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON',
|
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON',
|
||||||
'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
||||||
'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN',
|
'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN',
|
||||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
||||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
||||||
'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON',
|
'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON',
|
||||||
'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON',
|
'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON',
|
||||||
'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
||||||
'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
||||||
'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
|
'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Character types for symbols from 0600 to 06FF
|
// Character types for symbols from 0600 to 06FF
|
||||||
var arabicTypes = [
|
var arabicTypes = [
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL',
|
'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
|
'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
|
||||||
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL',
|
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN',
|
'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN',
|
||||||
'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL',
|
'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
|
'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
|
||||||
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM',
|
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM',
|
||||||
'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
|
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
|
||||||
];
|
];
|
||||||
|
|
||||||
function isOdd(i) {
|
function isOdd(i) {
|
||||||
return (i & 1) != 0;
|
return (i & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEven(i) {
|
function isEven(i) {
|
||||||
return (i & 1) == 0;
|
return (i & 1) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findUnequal(arr, start, value) {
|
function findUnequal(arr, start, value) {
|
||||||
var j;
|
var j;
|
||||||
for (var j = start, jj = arr.length; j < jj; ++j) {
|
for (var j = start, jj = arr.length; j < jj; ++j) {
|
||||||
if (arr[j] != value)
|
if (arr[j] != value)
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setValues(arr, start, end, value) {
|
function setValues(arr, start, end, value) {
|
||||||
for (var j = start; j < end; ++j) {
|
for (var j = start; j < end; ++j) {
|
||||||
arr[j] = value;
|
arr[j] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reverseValues(arr, start, end) {
|
function reverseValues(arr, start, end) {
|
||||||
for (var i = start, j = end - 1; i < j; ++i, --j) {
|
for (var i = start, j = end - 1; i < j; ++i, --j) {
|
||||||
var temp = arr[i];
|
var temp = arr[i];
|
||||||
arr[i] = arr[j];
|
arr[i] = arr[j];
|
||||||
arr[j] = temp;
|
arr[j] = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mirrorGlyphs(c) {
|
function mirrorGlyphs(c) {
|
||||||
/*
|
/*
|
||||||
# BidiMirroring-1.txt
|
# BidiMirroring-1.txt
|
||||||
0028; 0029 # LEFT PARENTHESIS
|
0028; 0029 # LEFT PARENTHESIS
|
||||||
0029; 0028 # RIGHT PARENTHESIS
|
0029; 0028 # RIGHT PARENTHESIS
|
||||||
003C; 003E # LESS-THAN SIGN
|
003C; 003E # LESS-THAN SIGN
|
||||||
003E; 003C # GREATER-THAN SIGN
|
003E; 003C # GREATER-THAN SIGN
|
||||||
005B; 005D # LEFT SQUARE BRACKET
|
005B; 005D # LEFT SQUARE BRACKET
|
||||||
005D; 005B # RIGHT SQUARE BRACKET
|
005D; 005B # RIGHT SQUARE BRACKET
|
||||||
007B; 007D # LEFT CURLY BRACKET
|
007B; 007D # LEFT CURLY BRACKET
|
||||||
007D; 007B # RIGHT CURLY BRACKET
|
007D; 007B # RIGHT CURLY BRACKET
|
||||||
00AB; 00BB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
|
00AB; 00BB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||||
00BB; 00AB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
|
00BB; 00AB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||||
*/
|
*/
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '(':
|
case '(':
|
||||||
return ')';
|
return ')';
|
||||||
case ')':
|
case ')':
|
||||||
return '(';
|
return '(';
|
||||||
case '<':
|
case '<':
|
||||||
return '>';
|
return '>';
|
||||||
case '>':
|
case '>':
|
||||||
return '<';
|
return '<';
|
||||||
case ']':
|
case ']':
|
||||||
return '[';
|
return '[';
|
||||||
case '[':
|
case '[':
|
||||||
return ']';
|
return ']';
|
||||||
case '}':
|
case '}':
|
||||||
return '{';
|
return '{';
|
||||||
case '{':
|
case '{':
|
||||||
return '}';
|
return '}';
|
||||||
case '\u00AB':
|
case '\u00AB':
|
||||||
return '\u00BB';
|
return '\u00BB';
|
||||||
case '\u00BB':
|
case '\u00BB':
|
||||||
return '\u00AB';
|
return '\u00AB';
|
||||||
default:
|
default:
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (function bidi(text, startLevel) {
|
function bidi(text, startLevel) {
|
||||||
var str = text.str;
|
var str = text.str;
|
||||||
var strLength = str.length;
|
var strLength = str.length;
|
||||||
if (strLength == 0)
|
if (strLength == 0)
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
// get types, fill arrays
|
// get types, fill arrays
|
||||||
|
|
||||||
var chars = new Array(strLength);
|
var chars = new Array(strLength);
|
||||||
var types = new Array(strLength);
|
var types = new Array(strLength);
|
||||||
var oldtypes = new Array(strLength);
|
var oldtypes = new Array(strLength);
|
||||||
var numBidi = 0;
|
var numBidi = 0;
|
||||||
|
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
chars[i] = str.charAt(i);
|
chars[i] = str.charAt(i);
|
||||||
|
|
||||||
var charCode = str.charCodeAt(i);
|
var charCode = str.charCodeAt(i);
|
||||||
var charType = 'L';
|
var charType = 'L';
|
||||||
if (charCode <= 0x00ff)
|
if (charCode <= 0x00ff)
|
||||||
charType = baseTypes[charCode];
|
charType = baseTypes[charCode];
|
||||||
else if (0x0590 <= charCode && charCode <= 0x05f4)
|
else if (0x0590 <= charCode && charCode <= 0x05f4)
|
||||||
charType = 'R';
|
charType = 'R';
|
||||||
else if (0x0600 <= charCode && charCode <= 0x06ff)
|
else if (0x0600 <= charCode && charCode <= 0x06ff)
|
||||||
charType = arabicTypes[charCode & 0xff];
|
charType = arabicTypes[charCode & 0xff];
|
||||||
else if (0x0700 <= charCode && charCode <= 0x08AC)
|
else if (0x0700 <= charCode && charCode <= 0x08AC)
|
||||||
charType = 'AL';
|
charType = 'AL';
|
||||||
|
|
||||||
if (charType == 'R' || charType == 'AL' || charType == 'AN')
|
if (charType == 'R' || charType == 'AL' || charType == 'AN')
|
||||||
numBidi++;
|
numBidi++;
|
||||||
|
|
||||||
oldtypes[i] = types[i] = charType;
|
oldtypes[i] = types[i] = charType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect the bidi method
|
// detect the bidi method
|
||||||
// if there are no rtl characters then no bidi needed
|
// if there are no rtl characters then no bidi needed
|
||||||
// if less than 30% chars are rtl then string is primarily ltr
|
// if less than 30% chars are rtl then string is primarily ltr
|
||||||
// if more than 30% chars are rtl then string is primarily rtl
|
// if more than 30% chars are rtl then string is primarily rtl
|
||||||
if (numBidi == 0) {
|
if (numBidi == 0) {
|
||||||
text.direction = 'ltr';
|
text.direction = 'ltr';
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startLevel == -1) {
|
if (startLevel == -1) {
|
||||||
if ((strLength / numBidi) < 0.3) {
|
if ((strLength / numBidi) < 0.3) {
|
||||||
text.direction = 'ltr';
|
text.direction = 'ltr';
|
||||||
startLevel = 0;
|
startLevel = 0;
|
||||||
} else {
|
} else {
|
||||||
text.direction = 'rtl';
|
text.direction = 'rtl';
|
||||||
startLevel = 1;
|
startLevel = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var levels = new Array(strLength);
|
var levels = new Array(strLength);
|
||||||
|
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
levels[i] = startLevel;
|
levels[i] = startLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
var diffChars = new Array(strLength);
|
var diffChars = new Array(strLength);
|
||||||
var diffLevels = new Array(strLength);
|
var diffLevels = new Array(strLength);
|
||||||
var diffTypes = new Array(strLength);
|
var diffTypes = new Array(strLength);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
X1-X10: skip most of this, since we are NOT doing the embeddings.
|
X1-X10: skip most of this, since we are NOT doing the embeddings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var e = isOdd(startLevel) ? 'R' : 'L';
|
var e = isOdd(startLevel) ? 'R' : 'L';
|
||||||
var sor = e;
|
var sor = e;
|
||||||
var eor = sor;
|
var eor = sor;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
W1. Examine each non-spacing mark (NSM) in the level run, and change the
|
W1. Examine each non-spacing mark (NSM) in the level run, and change the
|
||||||
type of the NSM to the type of the previous character. If the NSM is at the
|
type of the NSM to the type of the previous character. If the NSM is at the
|
||||||
start of the level run, it will get the type of sor.
|
start of the level run, it will get the type of sor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var lastType = sor;
|
var lastType = sor;
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
if (types[i] == 'NSM')
|
if (types[i] == 'NSM')
|
||||||
types[i] = lastType;
|
types[i] = lastType;
|
||||||
else
|
else
|
||||||
lastType = types[i];
|
lastType = types[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
W2. Search backwards from each instance of a European number until the
|
W2. Search backwards from each instance of a European number until the
|
||||||
first strong type (R, L, AL, or sor) is found. If an AL is found, change
|
first strong type (R, L, AL, or sor) is found. If an AL is found, change
|
||||||
the type of the European number to Arabic number.
|
the type of the European number to Arabic number.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var lastType = sor;
|
var lastType = sor;
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
var t = types[i];
|
var t = types[i];
|
||||||
if (t == 'EN')
|
if (t == 'EN')
|
||||||
types[i] = (lastType == 'AL') ? 'AN' : 'EN';
|
types[i] = (lastType == 'AL') ? 'AN' : 'EN';
|
||||||
else if (t == 'R' || t == 'L' || t == 'AL')
|
else if (t == 'R' || t == 'L' || t == 'AL')
|
||||||
lastType = t;
|
lastType = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
W3. Change all ALs to R.
|
W3. Change all ALs to R.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
var t = types[i];
|
var t = types[i];
|
||||||
if (t == 'AL')
|
if (t == 'AL')
|
||||||
types[i] = 'R';
|
types[i] = 'R';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
W4. A single European separator between two European numbers changes to a
|
W4. A single European separator between two European numbers changes to a
|
||||||
European number. A single common separator between two numbers of the same
|
European number. A single common separator between two numbers of the same
|
||||||
type changes to that type:
|
type changes to that type:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (var i = 1; i < strLength - 1; ++i) {
|
for (var i = 1; i < strLength - 1; ++i) {
|
||||||
if (types[i] == 'ES' && types[i - 1] == 'EN' && types[i + 1] == 'EN')
|
if (types[i] == 'ES' && types[i - 1] == 'EN' && types[i + 1] == 'EN')
|
||||||
types[i] = 'EN';
|
types[i] = 'EN';
|
||||||
if (types[i] == 'CS' && (types[i - 1] == 'EN' || types[i - 1] == 'AN') &&
|
if (types[i] == 'CS' && (types[i - 1] == 'EN' || types[i - 1] == 'AN') &&
|
||||||
types[i + 1] == types[i - 1])
|
types[i + 1] == types[i - 1])
|
||||||
types[i] = types[i - 1];
|
types[i] = types[i - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
W5. A sequence of European terminators adjacent to European numbers changes
|
W5. A sequence of European terminators adjacent to European numbers changes
|
||||||
to all European numbers:
|
to all European numbers:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
if (types[i] == 'EN') {
|
if (types[i] == 'EN') {
|
||||||
// do before
|
// do before
|
||||||
for (var j = i - 1; j >= 0; --j) {
|
for (var j = i - 1; j >= 0; --j) {
|
||||||
if (types[j] != 'ET')
|
if (types[j] != 'ET')
|
||||||
break;
|
break;
|
||||||
types[j] = 'EN';
|
types[j] = 'EN';
|
||||||
}
|
}
|
||||||
// do after
|
// do after
|
||||||
for (var j = i + 1; j < strLength; --j) {
|
for (var j = i + 1; j < strLength; --j) {
|
||||||
if (types[j] != 'ET')
|
if (types[j] != 'ET')
|
||||||
break;
|
break;
|
||||||
types[j] = 'EN';
|
types[j] = 'EN';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
W6. Otherwise, separators and terminators change to Other Neutral:
|
W6. Otherwise, separators and terminators change to Other Neutral:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
var t = types[i];
|
var t = types[i];
|
||||||
if (t == 'WS' || t == 'ES' || t == 'ET' || t == 'CS')
|
if (t == 'WS' || t == 'ES' || t == 'ET' || t == 'CS')
|
||||||
types[i] = 'ON';
|
types[i] = 'ON';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
W7. Search backwards from each instance of a European number until the
|
W7. Search backwards from each instance of a European number until the
|
||||||
first strong type (R, L, or sor) is found. If an L is found, then change
|
first strong type (R, L, or sor) is found. If an L is found, then change
|
||||||
the type of the European number to L.
|
the type of the European number to L.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var lastType = sor;
|
var lastType = sor;
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
var t = types[i];
|
var t = types[i];
|
||||||
if (t == 'EN')
|
if (t == 'EN')
|
||||||
types[i] = (lastType == 'L') ? 'L' : 'EN';
|
types[i] = (lastType == 'L') ? 'L' : 'EN';
|
||||||
else if (t == 'R' || t == 'L')
|
else if (t == 'R' || t == 'L')
|
||||||
lastType = t;
|
lastType = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
N1. A sequence of neutrals takes the direction of the surrounding strong
|
N1. A sequence of neutrals takes the direction of the surrounding strong
|
||||||
text if the text on both sides has the same direction. European and Arabic
|
text if the text on both sides has the same direction. European and Arabic
|
||||||
numbers are treated as though they were R. Start-of-level-run (sor) and
|
numbers are treated as though they were R. Start-of-level-run (sor) and
|
||||||
end-of-level-run (eor) are used at level run boundaries.
|
end-of-level-run (eor) are used at level run boundaries.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
if (types[i] == 'ON') {
|
if (types[i] == 'ON') {
|
||||||
var end = findUnequal(types, i + 1, 'ON');
|
var end = findUnequal(types, i + 1, 'ON');
|
||||||
var before = sor;
|
var before = sor;
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
before = types[i - 1];
|
before = types[i - 1];
|
||||||
var after = eor;
|
var after = eor;
|
||||||
if (end + 1 < strLength)
|
if (end + 1 < strLength)
|
||||||
after = types[end + 1];
|
after = types[end + 1];
|
||||||
if (before != 'L')
|
if (before != 'L')
|
||||||
before = 'R';
|
before = 'R';
|
||||||
if (after != 'L')
|
if (after != 'L')
|
||||||
after = 'R';
|
after = 'R';
|
||||||
if (before == after)
|
if (before == after)
|
||||||
setValues(types, i, end, before);
|
setValues(types, i, end, before);
|
||||||
i = end - 1; // reset to end (-1 so next iteration is ok)
|
i = end - 1; // reset to end (-1 so next iteration is ok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
N2. Any remaining neutrals take the embedding direction.
|
N2. Any remaining neutrals take the embedding direction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
if (types[i] == 'ON')
|
if (types[i] == 'ON')
|
||||||
types[i] = e;
|
types[i] = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
I1. For all characters with an even (left-to-right) embedding direction,
|
I1. For all characters with an even (left-to-right) embedding direction,
|
||||||
those of type R go up one level and those of type AN or EN go up two
|
those of type R go up one level and those of type AN or EN go up two
|
||||||
levels.
|
levels.
|
||||||
I2. For all characters with an odd (right-to-left) embedding direction,
|
I2. For all characters with an odd (right-to-left) embedding direction,
|
||||||
those of type L, EN or AN go up one level.
|
those of type L, EN or AN go up one level.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (var i = 0; i < strLength; ++i) {
|
for (var i = 0; i < strLength; ++i) {
|
||||||
var t = types[i];
|
var t = types[i];
|
||||||
if (isEven(levels[i])) {
|
if (isEven(levels[i])) {
|
||||||
if (t == 'R') {
|
if (t == 'R') {
|
||||||
levels[i] += 1;
|
levels[i] += 1;
|
||||||
} else if (t == 'AN' || t == 'EN') {
|
} else if (t == 'AN' || t == 'EN') {
|
||||||
levels[i] += 2;
|
levels[i] += 2;
|
||||||
}
|
}
|
||||||
} else { // isOdd, so
|
} else { // isOdd, so
|
||||||
if (t == 'L' || t == 'AN' || t == 'EN') {
|
if (t == 'L' || t == 'AN' || t == 'EN') {
|
||||||
levels[i] += 1;
|
levels[i] += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
L1. On each line, reset the embedding level of the following characters to
|
L1. On each line, reset the embedding level of the following characters to
|
||||||
the paragraph embedding level:
|
the paragraph embedding level:
|
||||||
|
|
||||||
segment separators,
|
segment separators,
|
||||||
paragraph separators,
|
paragraph separators,
|
||||||
any sequence of whitespace characters preceding a segment separator or
|
any sequence of whitespace characters preceding a segment separator or
|
||||||
paragraph separator, and any sequence of white space characters at the end
|
paragraph separator, and any sequence of white space characters at the end
|
||||||
of the line.
|
of the line.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// don't bother as text is only single line
|
// don't bother as text is only single line
|
||||||
|
|
||||||
/*
|
/*
|
||||||
L2. From the highest level found in the text to the lowest odd level on
|
L2. From the highest level found in the text to the lowest odd level on
|
||||||
each line, reverse any contiguous sequence of characters that are at that
|
each line, reverse any contiguous sequence of characters that are at that
|
||||||
level or higher.
|
level or higher.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// find highest level & lowest odd level
|
// find highest level & lowest odd level
|
||||||
|
|
||||||
var highestLevel = -1;
|
var highestLevel = -1;
|
||||||
var lowestOddLevel = 99;
|
var lowestOddLevel = 99;
|
||||||
for (var i = 0, ii = levels.length; i < ii; ++i) {
|
for (var i = 0, ii = levels.length; i < ii; ++i) {
|
||||||
var level = levels[i];
|
var level = levels[i];
|
||||||
if (highestLevel < level)
|
if (highestLevel < level)
|
||||||
highestLevel = level;
|
highestLevel = level;
|
||||||
if (lowestOddLevel > level && isOdd(level))
|
if (lowestOddLevel > level && isOdd(level))
|
||||||
lowestOddLevel = level;
|
lowestOddLevel = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now reverse between those limits
|
// now reverse between those limits
|
||||||
|
|
||||||
for (var level = highestLevel; level >= lowestOddLevel; --level) {
|
for (var level = highestLevel; level >= lowestOddLevel; --level) {
|
||||||
// find segments to reverse
|
// find segments to reverse
|
||||||
var start = -1;
|
var start = -1;
|
||||||
for (var i = 0, ii = levels.length; i < ii; ++i) {
|
for (var i = 0, ii = levels.length; i < ii; ++i) {
|
||||||
if (levels[i] < level) {
|
if (levels[i] < level) {
|
||||||
if (start >= 0) {
|
if (start >= 0) {
|
||||||
reverseValues(chars, start, i);
|
reverseValues(chars, start, i);
|
||||||
start = -1;
|
start = -1;
|
||||||
}
|
}
|
||||||
} else if (start < 0) {
|
} else if (start < 0) {
|
||||||
start = i;
|
start = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (start >= 0) {
|
if (start >= 0) {
|
||||||
reverseValues(chars, start, levels.length);
|
reverseValues(chars, start, levels.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
L3. Combining marks applied to a right-to-left base character will at this
|
L3. Combining marks applied to a right-to-left base character will at this
|
||||||
point precede their base character. If the rendering engine expects them to
|
point precede their base character. If the rendering engine expects them to
|
||||||
follow the base characters in the final display process, then the ordering
|
follow the base characters in the final display process, then the ordering
|
||||||
of the marks and the base character must be reversed.
|
of the marks and the base character must be reversed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// don't bother for now
|
// don't bother for now
|
||||||
|
|
||||||
/*
|
/*
|
||||||
L4. A character that possesses the mirrored property as specified by
|
L4. A character that possesses the mirrored property as specified by
|
||||||
Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved
|
Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved
|
||||||
directionality of that character is R.
|
directionality of that character is R.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// don't mirror as characters are already mirrored in the pdf
|
// don't mirror as characters are already mirrored in the pdf
|
||||||
|
|
||||||
// Finally, return string
|
// Finally, return string
|
||||||
|
|
||||||
var result = '';
|
var result = '';
|
||||||
for (var i = 0, ii = chars.length; i < ii; ++i) {
|
for (var i = 0, ii = chars.length; i < ii; ++i) {
|
||||||
var ch = chars[i];
|
var ch = chars[i];
|
||||||
if (ch != '<' && ch != '>')
|
if (ch != '<' && ch != '>')
|
||||||
result += ch;
|
result += ch;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
}
|
||||||
})();
|
|
||||||
|
return bidi;
|
||||||
|
})();
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
|||||||
return CanvasExtraState;
|
return CanvasExtraState;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function ScratchCanvas(width, height) {
|
function createScratchCanvas(width, height) {
|
||||||
var canvas = document.createElement('canvas');
|
var canvas = document.createElement('canvas');
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
@ -188,9 +188,9 @@ function addContextCurrentTransform(ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var CanvasGraphics = (function CanvasGraphicsClosure() {
|
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.
|
// before it stops and shedules a continue of execution.
|
||||||
var kExecutionTime = 50;
|
var kExecutionTime = 15;
|
||||||
|
|
||||||
function CanvasGraphics(canvasCtx, objs, textLayer) {
|
function CanvasGraphics(canvasCtx, objs, textLayer) {
|
||||||
this.ctx = canvasCtx;
|
this.ctx = canvasCtx;
|
||||||
@ -199,7 +199,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
this.pendingClip = null;
|
this.pendingClip = null;
|
||||||
this.res = null;
|
this.res = null;
|
||||||
this.xobjs = null;
|
this.xobjs = null;
|
||||||
this.ScratchCanvas = ScratchCanvas;
|
|
||||||
this.objs = objs;
|
this.objs = objs;
|
||||||
this.textLayer = textLayer;
|
this.textLayer = textLayer;
|
||||||
if (canvasCtx) {
|
if (canvasCtx) {
|
||||||
@ -229,7 +228,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
'setStrokeColor': true,
|
'setStrokeColor': true,
|
||||||
'setStrokeColorN': true,
|
'setStrokeColorN': true,
|
||||||
'setFillColor': true,
|
'setFillColor': true,
|
||||||
'setFillColorN_IR': true,
|
'setFillColorN': true,
|
||||||
'setStrokeGray': true,
|
'setStrokeGray': true,
|
||||||
'setFillGray': true,
|
'setFillGray': true,
|
||||||
'setStrokeRGBColor': true,
|
'setStrokeRGBColor': true,
|
||||||
@ -268,15 +267,16 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
this.textLayer.beginLayout();
|
this.textLayer.beginLayout();
|
||||||
},
|
},
|
||||||
|
|
||||||
executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR,
|
executeOperatorList: function canvasGraphicsExecuteOperatorList(
|
||||||
executionStartIdx, continueCallback,
|
operatorList,
|
||||||
stepper) {
|
executionStartIdx, continueCallback,
|
||||||
var argsArray = codeIR.argsArray;
|
stepper) {
|
||||||
var fnArray = codeIR.fnArray;
|
var argsArray = operatorList.argsArray;
|
||||||
|
var fnArray = operatorList.fnArray;
|
||||||
var i = executionStartIdx || 0;
|
var i = executionStartIdx || 0;
|
||||||
var argsArrayLen = argsArray.length;
|
var argsArrayLen = argsArray.length;
|
||||||
|
|
||||||
// Sometimes the IRQueue to execute is empty.
|
// Sometimes the OperatorList to execute is empty.
|
||||||
if (argsArrayLen == i) {
|
if (argsArrayLen == i) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -314,7 +314,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
// If the entire IRQueue was executed, stop as were done.
|
// If the entire operatorList was executed, stop as were done.
|
||||||
if (i == argsArrayLen) {
|
if (i == argsArrayLen) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -327,8 +327,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the IRQueue isn't executed completly yet OR the execution time
|
// If the operatorList isn't executed completely yet OR the execution
|
||||||
// was short enough, do another execution round.
|
// time was short enough, do another execution round.
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -556,7 +556,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
this.current.leading = -leading;
|
this.current.leading = -leading;
|
||||||
},
|
},
|
||||||
setFont: function canvasGraphicsSetFont(fontRefName, size) {
|
setFont: function canvasGraphicsSetFont(fontRefName, size) {
|
||||||
var fontObj = this.objs.get(fontRefName).fontObj;
|
var fontObj = this.objs.get(fontRefName);
|
||||||
var current = this.current;
|
var current = this.current;
|
||||||
|
|
||||||
if (!fontObj)
|
if (!fontObj)
|
||||||
@ -707,7 +707,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
this.save();
|
this.save();
|
||||||
ctx.scale(fontSize, fontSize);
|
ctx.scale(fontSize, fontSize);
|
||||||
ctx.transform.apply(ctx, fontMatrix);
|
ctx.transform.apply(ctx, fontMatrix);
|
||||||
this.executeIRQueue(glyph.codeIRQueue);
|
this.executeOperatorList(glyph.operatorList);
|
||||||
this.restore();
|
this.restore();
|
||||||
|
|
||||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||||
@ -908,7 +908,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
this.ctx.strokeStyle = color;
|
this.ctx.strokeStyle = color;
|
||||||
this.current.strokeColor = 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') {
|
if (IR[0] == 'TilingPattern') {
|
||||||
var args = IR[1];
|
var args = IR[1];
|
||||||
var base = cs.base;
|
var base = cs.base;
|
||||||
@ -930,11 +930,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
}
|
}
|
||||||
return pattern;
|
return pattern;
|
||||||
},
|
},
|
||||||
setStrokeColorN_IR: function canvasGraphicsSetStrokeColorN(/*...*/) {
|
setStrokeColorN: function canvasGraphicsSetStrokeColorN(/*...*/) {
|
||||||
var cs = this.current.strokeColorSpace;
|
var cs = this.current.strokeColorSpace;
|
||||||
|
|
||||||
if (cs.name == 'Pattern') {
|
if (cs.name == 'Pattern') {
|
||||||
this.current.strokeColor = this.getColorN_IR_Pattern(arguments, cs);
|
this.current.strokeColor = this.getColorN_Pattern(arguments, cs);
|
||||||
} else {
|
} else {
|
||||||
this.setStrokeColor.apply(this, arguments);
|
this.setStrokeColor.apply(this, arguments);
|
||||||
}
|
}
|
||||||
@ -946,11 +946,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
this.ctx.fillStyle = color;
|
this.ctx.fillStyle = color;
|
||||||
this.current.fillColor = color;
|
this.current.fillColor = color;
|
||||||
},
|
},
|
||||||
setFillColorN_IR: function canvasGraphicsSetFillColorN(/*...*/) {
|
setFillColorN: function canvasGraphicsSetFillColorN(/*...*/) {
|
||||||
var cs = this.current.fillColorSpace;
|
var cs = this.current.fillColorSpace;
|
||||||
|
|
||||||
if (cs.name == 'Pattern') {
|
if (cs.name == 'Pattern') {
|
||||||
this.current.fillColor = this.getColorN_IR_Pattern(arguments, cs);
|
this.current.fillColor = this.getColorN_Pattern(arguments, cs);
|
||||||
} else {
|
} else {
|
||||||
this.setFillColor.apply(this, arguments);
|
this.setFillColor.apply(this, arguments);
|
||||||
}
|
}
|
||||||
@ -1116,7 +1116,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
// scale the image to the unit square
|
// scale the image to the unit square
|
||||||
ctx.scale(1 / w, -1 / h);
|
ctx.scale(1 / w, -1 / h);
|
||||||
|
|
||||||
var tmpCanvas = new this.ScratchCanvas(w, h);
|
var tmpCanvas = createScratchCanvas(w, h);
|
||||||
var tmpCtx = tmpCanvas.getContext('2d');
|
var tmpCtx = tmpCanvas.getContext('2d');
|
||||||
|
|
||||||
var fillColor = this.current.fillColor;
|
var fillColor = this.current.fillColor;
|
||||||
@ -1147,7 +1147,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
// scale the image to the unit square
|
// scale the image to the unit square
|
||||||
ctx.scale(1 / w, -1 / h);
|
ctx.scale(1 / w, -1 / h);
|
||||||
|
|
||||||
var tmpCanvas = new this.ScratchCanvas(w, h);
|
var tmpCanvas = createScratchCanvas(w, h);
|
||||||
var tmpCtx = tmpCanvas.getContext('2d');
|
var tmpCtx = tmpCanvas.getContext('2d');
|
||||||
this.putBinaryImageData(tmpCtx, imgData, w, h);
|
this.putBinaryImageData(tmpCtx, imgData, w, h);
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ var ColorSpace = (function ColorSpaceClosure() {
|
|||||||
basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
|
basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
|
||||||
return ['PatternCS', basePatternCS];
|
return ['PatternCS', basePatternCS];
|
||||||
case 'Indexed':
|
case 'Indexed':
|
||||||
|
case 'I':
|
||||||
var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
|
var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
|
||||||
var hiVal = cs[2] + 1;
|
var hiVal = cs[2] + 1;
|
||||||
var lookup = xref.fetchIfRef(cs[3]);
|
var lookup = xref.fetchIfRef(cs[3]);
|
||||||
|
132
src/core.js
132
src/core.js
@ -63,13 +63,8 @@ var Page = (function PageClosure() {
|
|||||||
function Page(xref, pageNumber, pageDict, ref) {
|
function Page(xref, pageNumber, pageDict, ref) {
|
||||||
this.pageNumber = pageNumber;
|
this.pageNumber = pageNumber;
|
||||||
this.pageDict = pageDict;
|
this.pageDict = pageDict;
|
||||||
this.stats = {
|
this.stats = new StatTimer();
|
||||||
create: Date.now(),
|
this.stats.enabled = !!globalScope.PDFJS.enableStats;
|
||||||
compile: 0.0,
|
|
||||||
fonts: 0.0,
|
|
||||||
images: 0.0,
|
|
||||||
render: 0.0
|
|
||||||
};
|
|
||||||
this.xref = xref;
|
this.xref = xref;
|
||||||
this.ref = ref;
|
this.ref = ref;
|
||||||
|
|
||||||
@ -175,10 +170,10 @@ var Page = (function PageClosure() {
|
|||||||
return shadow(this, 'rotate', rotate);
|
return shadow(this, 'rotate', rotate);
|
||||||
},
|
},
|
||||||
|
|
||||||
startRenderingFromIRQueue: function pageStartRenderingFromIRQueue(
|
startRenderingFromOperatorList: function pageStartRenderingFromOperatorList(
|
||||||
IRQueue, fonts) {
|
operatorList, fonts) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.IRQueue = IRQueue;
|
this.operatorList = operatorList;
|
||||||
|
|
||||||
var displayContinuation = function pageDisplayContinuation() {
|
var displayContinuation = function pageDisplayContinuation() {
|
||||||
// Always defer call to display() to work around bug in
|
// Always defer call to display() to work around bug in
|
||||||
@ -189,17 +184,20 @@ var Page = (function PageClosure() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.ensureFonts(fonts,
|
this.ensureFonts(fonts,
|
||||||
function pageStartRenderingFromIRQueueEnsureFonts() {
|
function pageStartRenderingFromOperatorListEnsureFonts() {
|
||||||
displayContinuation();
|
displayContinuation();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
getIRQueue: function pageGetIRQueue(handler, dependency) {
|
getOperatorList: function pageGetOperatorList(handler, dependency) {
|
||||||
if (this.IRQueue) {
|
if (this.operatorList) {
|
||||||
// content was compiled
|
// content was compiled
|
||||||
return this.IRQueue;
|
return this.operatorList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.stats.time('Build IR Queue');
|
||||||
|
|
||||||
var xref = this.xref;
|
var xref = this.xref;
|
||||||
var content = xref.fetchIfRef(this.content);
|
var content = xref.fetchIfRef(this.content);
|
||||||
var resources = xref.fetchIfRef(this.resources);
|
var resources = xref.fetchIfRef(this.resources);
|
||||||
@ -216,30 +214,33 @@ var Page = (function PageClosure() {
|
|||||||
|
|
||||||
var pe = this.pe = new PartialEvaluator(
|
var pe = this.pe = new PartialEvaluator(
|
||||||
xref, handler, 'p' + this.pageNumber + '_');
|
xref, handler, 'p' + this.pageNumber + '_');
|
||||||
var IRQueue = {};
|
|
||||||
return (this.IRQueue = pe.getIRQueue(content, resources, IRQueue,
|
this.operatorList = pe.getOperatorList(content, resources, dependency);
|
||||||
dependency));
|
this.stats.timeEnd('Build IR Queue');
|
||||||
|
return this.operatorList;
|
||||||
},
|
},
|
||||||
|
|
||||||
ensureFonts: function pageEnsureFonts(fonts, callback) {
|
ensureFonts: function pageEnsureFonts(fonts, callback) {
|
||||||
|
this.stats.time('Font Loading');
|
||||||
// Convert the font names to the corresponding font obj.
|
// Convert the font names to the corresponding font obj.
|
||||||
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
||||||
fonts[i] = this.objs.objs[fonts[i]].data;
|
fonts[i] = this.objs.objs[fonts[i]].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all the fonts
|
// Load all the fonts
|
||||||
var fontObjs = FontLoader.bind(
|
FontLoader.bind(
|
||||||
fonts,
|
fonts,
|
||||||
function pageEnsureFontsFontObjs(fontObjs) {
|
function pageEnsureFontsFontObjs(fontObjs) {
|
||||||
this.stats.fonts = Date.now();
|
this.stats.timeEnd('Font Loading');
|
||||||
|
|
||||||
callback.call(this);
|
callback.call(this);
|
||||||
}.bind(this),
|
}.bind(this)
|
||||||
this.objs
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
display: function pageDisplay(gfx, callback) {
|
display: function pageDisplay(gfx, callback) {
|
||||||
|
var stats = this.stats;
|
||||||
|
stats.time('Rendering');
|
||||||
var xref = this.xref;
|
var xref = this.xref;
|
||||||
var resources = xref.fetchIfRef(this.resources);
|
var resources = xref.fetchIfRef(this.resources);
|
||||||
var mediaBox = xref.fetchIfRef(this.mediaBox);
|
var mediaBox = xref.fetchIfRef(this.mediaBox);
|
||||||
@ -253,21 +254,23 @@ var Page = (function PageClosure() {
|
|||||||
rotate: this.rotate });
|
rotate: this.rotate });
|
||||||
|
|
||||||
var startIdx = 0;
|
var startIdx = 0;
|
||||||
var length = this.IRQueue.fnArray.length;
|
var length = this.operatorList.fnArray.length;
|
||||||
var IRQueue = this.IRQueue;
|
var operatorList = this.operatorList;
|
||||||
var stepper = null;
|
var stepper = null;
|
||||||
if (PDFJS.pdfBug && StepperManager.enabled) {
|
if (PDFJS.pdfBug && StepperManager.enabled) {
|
||||||
stepper = StepperManager.create(this.pageNumber);
|
stepper = StepperManager.create(this.pageNumber);
|
||||||
stepper.init(IRQueue);
|
stepper.init(operatorList);
|
||||||
stepper.nextBreakPoint = stepper.getNextBreakPoint();
|
stepper.nextBreakPoint = stepper.getNextBreakPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
function next() {
|
function next() {
|
||||||
startIdx = gfx.executeIRQueue(IRQueue, startIdx, next, stepper);
|
startIdx =
|
||||||
|
gfx.executeOperatorList(operatorList, startIdx, next, stepper);
|
||||||
if (startIdx == length) {
|
if (startIdx == length) {
|
||||||
self.stats.render = Date.now();
|
|
||||||
gfx.endDrawing();
|
gfx.endDrawing();
|
||||||
|
stats.timeEnd('Rendering');
|
||||||
|
stats.timeEnd('Overall');
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,6 +313,22 @@ var Page = (function PageClosure() {
|
|||||||
return null;
|
return null;
|
||||||
return item.get(name);
|
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 annotations = xref.fetchIfRef(this.annotations) || [];
|
||||||
var i, n = annotations.length;
|
var i, n = annotations.length;
|
||||||
@ -338,7 +357,12 @@ var Page = (function PageClosure() {
|
|||||||
if (a) {
|
if (a) {
|
||||||
switch (a.get('S').name) {
|
switch (a.get('S').name) {
|
||||||
case 'URI':
|
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;
|
break;
|
||||||
case 'GoTo':
|
case 'GoTo':
|
||||||
item.dest = a.get('D');
|
item.dest = a.get('D');
|
||||||
@ -410,16 +434,16 @@ var Page = (function PageClosure() {
|
|||||||
return items;
|
return items;
|
||||||
},
|
},
|
||||||
startRendering: function pageStartRendering(ctx, callback, textLayer) {
|
startRendering: function pageStartRendering(ctx, callback, textLayer) {
|
||||||
this.startRenderingTime = Date.now();
|
var stats = this.stats;
|
||||||
|
stats.time('Overall');
|
||||||
// If there is no displayReadyPromise yet, then the IRQueue was never
|
// If there is no displayReadyPromise yet, then the operatorList was never
|
||||||
// requested before. Make the request and create the promise.
|
// requested before. Make the request and create the promise.
|
||||||
if (!this.displayReadyPromise) {
|
if (!this.displayReadyPromise) {
|
||||||
this.pdf.startRendering(this);
|
this.pdf.startRendering(this);
|
||||||
this.displayReadyPromise = new Promise();
|
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(
|
this.displayReadyPromise.then(
|
||||||
function pageDisplayReadyPromise() {
|
function pageDisplayReadyPromise() {
|
||||||
var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
|
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
|
* 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
|
* for each worker. If there is no worker support enabled, there are two
|
||||||
* `PDFDocModel` objects on the main thread created.
|
* `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() {
|
var PDFDocModel = (function PDFDocModelClosure() {
|
||||||
function PDFDocModel(arg, callback) {
|
function PDFDocModel(arg, callback) {
|
||||||
@ -622,9 +643,9 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
this.pdf = new PDFDocModel(stream);
|
this.pdfModel = new PDFDocModel(stream);
|
||||||
this.fingerprint = this.pdf.getFingerprint();
|
this.fingerprint = this.pdfModel.getFingerprint();
|
||||||
this.catalog = this.pdf.catalog;
|
this.catalog = this.pdfModel.catalog;
|
||||||
this.objs = new PDFObjects();
|
this.objs = new PDFObjects();
|
||||||
|
|
||||||
this.pageCache = [];
|
this.pageCache = [];
|
||||||
@ -711,7 +732,8 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
var page = this.pageCache[pageNum];
|
var page = this.pageCache[pageNum];
|
||||||
var depFonts = data.depFonts;
|
var depFonts = data.depFonts;
|
||||||
|
|
||||||
page.startRenderingFromIRQueue(data.IRQueue, depFonts);
|
page.stats.timeEnd('Page Request');
|
||||||
|
page.startRenderingFromOperatorList(data.operatorList, depFonts);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
messageHandler.on('obj', function pdfDocObj(data) {
|
messageHandler.on('obj', function pdfDocObj(data) {
|
||||||
@ -738,31 +760,16 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
file = new Stream(file, 0, file.length, fontFileDict);
|
file = new Stream(file, 0, file.length, fontFileDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, resolve the font object here direclty. The real font
|
// At this point, only the font object is created but the font is
|
||||||
// object is then created in FontLoader.bind().
|
// not yet attached to the DOM. This is done in `FontLoader.bind`.
|
||||||
this.objs.resolve(id, {
|
var font = new Font(name, file, properties);
|
||||||
name: name,
|
this.objs.resolve(id, font);
|
||||||
file: file,
|
|
||||||
properties: properties
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error('Got unkown object type ' + type);
|
error('Got unkown object type ' + type);
|
||||||
}
|
}
|
||||||
}, this);
|
}, 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) {
|
messageHandler.on('page_error', function pdfDocError(data) {
|
||||||
var page = this.pageCache[data.pageNum];
|
var page = this.pageCache[data.pageNum];
|
||||||
if (page.displayReadyPromise)
|
if (page.displayReadyPromise)
|
||||||
@ -784,7 +791,7 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
var size = width * height;
|
var size = width * height;
|
||||||
var rgbaLength = size * 4;
|
var rgbaLength = size * 4;
|
||||||
var buf = new Uint8Array(size * components);
|
var buf = new Uint8Array(size * components);
|
||||||
var tmpCanvas = new ScratchCanvas(width, height);
|
var tmpCanvas = createScratchCanvas(width, height);
|
||||||
var tmpCtx = tmpCanvas.getContext('2d');
|
var tmpCtx = tmpCanvas.getContext('2d');
|
||||||
tmpCtx.drawImage(img, 0, 0);
|
tmpCtx.drawImage(img, 0, 0);
|
||||||
var data = tmpCtx.getImageData(0, 0, width, height).data;
|
var data = tmpCtx.getImageData(0, 0, width, height).data;
|
||||||
@ -813,12 +820,13 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
get numPages() {
|
get numPages() {
|
||||||
return this.pdf.numPages;
|
return this.pdfModel.numPages;
|
||||||
},
|
},
|
||||||
|
|
||||||
startRendering: function pdfDocStartRendering(page) {
|
startRendering: function pdfDocStartRendering(page) {
|
||||||
// The worker might not be ready to receive the page request yet.
|
// The worker might not be ready to receive the page request yet.
|
||||||
this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
|
this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
|
||||||
|
page.stats.time('Page Request');
|
||||||
this.messageHandler.send('page_request', page.pageNumber + 1);
|
this.messageHandler.send('page_request', page.pageNumber + 1);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
@ -827,7 +835,7 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
if (this.pageCache[n])
|
if (this.pageCache[n])
|
||||||
return 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
|
// Add a reference to the objects such that Page can forward the reference
|
||||||
// to the CanvasGraphics and so on.
|
// to the CanvasGraphics and so on.
|
||||||
page.objs = this.objs;
|
page.objs = this.objs;
|
||||||
|
@ -570,7 +570,6 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
error('Unknown crypto method');
|
error('Unknown crypto method');
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherTransformFactory.prototype = {
|
CipherTransformFactory.prototype = {
|
||||||
|
@ -112,8 +112,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PartialEvaluator.prototype = {
|
PartialEvaluator.prototype = {
|
||||||
getIRQueue: function partialEvaluatorGetIRQueue(stream, resources,
|
getOperatorList: function partialEvaluatorGetOperatorList(stream, resources,
|
||||||
queue, dependency) {
|
dependency, queue) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var xref = this.xref;
|
var xref = this.xref;
|
||||||
@ -136,8 +136,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
|
|
||||||
var fontRes = resources.get('Font');
|
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');
|
assert(fontRes, 'fontRes not available');
|
||||||
|
|
||||||
fontRes = xref.fetchIfRef(fontRes);
|
fontRes = xref.fetchIfRef(fontRes);
|
||||||
@ -177,7 +175,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
|
|
||||||
// Ensure the font is ready before the font is set
|
// Ensure the font is ready before the font is set
|
||||||
// and later on used for drawing.
|
// 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.
|
// page.
|
||||||
insertDependency([loadedName]);
|
insertDependency([loadedName]);
|
||||||
return loadedName;
|
return loadedName;
|
||||||
@ -239,6 +237,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}, handler, xref, resources, image, inline);
|
}, handler, xref, resources, image, inline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!queue)
|
||||||
|
queue = {};
|
||||||
|
|
||||||
if (!queue.argsArray) {
|
if (!queue.argsArray) {
|
||||||
queue.argsArray = [];
|
queue.argsArray = [];
|
||||||
}
|
}
|
||||||
@ -280,9 +281,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
// TODO figure out how to type-check vararg functions
|
// TODO figure out how to type-check vararg functions
|
||||||
|
|
||||||
if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
|
if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
|
||||||
// Use the IR version for setStroke/FillColorN.
|
|
||||||
fn += '_IR';
|
|
||||||
|
|
||||||
// compile tiling patterns
|
// compile tiling patterns
|
||||||
var patternName = args[args.length - 1];
|
var patternName = args[args.length - 1];
|
||||||
// SCN/scn applies patterns along with normal colors
|
// SCN/scn applies patterns along with normal colors
|
||||||
@ -295,15 +293,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
if (typeNum == TILING_PATTERN) {
|
if (typeNum == TILING_PATTERN) {
|
||||||
// Create an IR of the pattern code.
|
// Create an IR of the pattern code.
|
||||||
var depIdx = dependencyArray.length;
|
var depIdx = dependencyArray.length;
|
||||||
var queueObj = {};
|
var operatorList = this.getOperatorList(pattern,
|
||||||
var codeIR = this.getIRQueue(pattern, dict.get('Resources') ||
|
dict.get('Resources') || resources, dependencyArray);
|
||||||
resources, queueObj, dependencyArray);
|
|
||||||
|
|
||||||
// Add the dependencies that are required to execute the
|
// Add the dependencies that are required to execute the
|
||||||
// codeIR.
|
// operatorList.
|
||||||
insertDependency(dependencyArray.slice(depIdx));
|
insertDependency(dependencyArray.slice(depIdx));
|
||||||
|
|
||||||
args = TilingPattern.getIR(codeIR, dict, args);
|
args = TilingPattern.getIR(operatorList, dict, args);
|
||||||
}
|
}
|
||||||
else if (typeNum == SHADING_PATTERN) {
|
else if (typeNum == SHADING_PATTERN) {
|
||||||
var shading = xref.fetchIfRef(dict.get('Shading'));
|
var shading = xref.fetchIfRef(dict.get('Shading'));
|
||||||
@ -337,14 +334,18 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
fnArray.push('paintFormXObjectBegin');
|
fnArray.push('paintFormXObjectBegin');
|
||||||
argsArray.push([matrix, bbox]);
|
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;
|
var depIdx = dependencyArray.length;
|
||||||
|
|
||||||
this.getIRQueue(xobj, xobj.dict.get('Resources') || resources,
|
// Pass in the current `queue` object. That means the `fnArray`
|
||||||
queue, dependencyArray);
|
// 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
|
// Add the dependencies that are required to execute the
|
||||||
// codeIR.
|
// operatorList.
|
||||||
insertDependency(dependencyArray.slice(depIdx));
|
insertDependency(dependencyArray.slice(depIdx));
|
||||||
|
|
||||||
fn = 'paintFormXObjectEnd';
|
fn = 'paintFormXObjectEnd';
|
||||||
@ -454,10 +455,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return queue;
|
||||||
fnArray: fnArray,
|
|
||||||
argsArray: argsArray
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
extractDataStructures: function
|
extractDataStructures: function
|
||||||
@ -855,12 +853,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
var charProcs = xref.fetchIfRef(dict.get('CharProcs'));
|
var charProcs = xref.fetchIfRef(dict.get('CharProcs'));
|
||||||
var fontResources = xref.fetchIfRef(dict.get('Resources')) || resources;
|
var fontResources = xref.fetchIfRef(dict.get('Resources')) || resources;
|
||||||
properties.resources = fontResources;
|
properties.resources = fontResources;
|
||||||
properties.charProcIRQueues = {};
|
properties.charProcOperatorList = {};
|
||||||
for (var key in charProcs.map) {
|
for (var key in charProcs.map) {
|
||||||
var glyphStream = xref.fetchIfRef(charProcs.map[key]);
|
var glyphStream = xref.fetchIfRef(charProcs.map[key]);
|
||||||
var queueObj = {};
|
properties.charProcOperatorList[key] =
|
||||||
properties.charProcIRQueues[key] =
|
this.getOperatorList(glyphStream, fontResources, dependency);
|
||||||
this.getIRQueue(glyphStream, fontResources, queueObj, dependency);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
70
src/fonts.js
70
src/fonts.js
@ -409,8 +409,8 @@ var FontLoader = {
|
|||||||
|
|
||||||
bind: function fontLoaderBind(fonts, callback) {
|
bind: function fontLoaderBind(fonts, callback) {
|
||||||
function checkFontsLoaded() {
|
function checkFontsLoaded() {
|
||||||
for (var i = 0, ii = objs.length; i < ii; i++) {
|
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
||||||
var fontObj = objs[i];
|
var fontObj = fonts[i];
|
||||||
if (fontObj.loading) {
|
if (fontObj.loading) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -423,52 +423,45 @@ var FontLoader = {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rules = [], names = [], objs = [];
|
var rules = [], names = [], fontsToLoad = [];
|
||||||
|
var fontCreateTimer = 0;
|
||||||
|
|
||||||
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
for (var i = 0, ii = fonts.length; i < ii; i++) {
|
||||||
var font = fonts[i];
|
var font = fonts[i];
|
||||||
|
|
||||||
// If there is already a fontObj on the font, then it was loaded/attached
|
// Add the font to the DOM only once or skip if the font
|
||||||
// to the page already and we don't have to do anything for this font
|
// is already loaded.
|
||||||
// here future.
|
if (font.attached || font.loading == false) {
|
||||||
if (font.fontObj) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
font.attached = true;
|
||||||
|
|
||||||
var obj = new Font(font.name, font.file, font.properties);
|
fontsToLoad.push(font);
|
||||||
|
|
||||||
// Store the fontObj on the font such that `setFont` in CanvasGraphics
|
|
||||||
// can reuse it later again.
|
|
||||||
font.fontObj = obj;
|
|
||||||
|
|
||||||
objs.push(obj);
|
|
||||||
|
|
||||||
var str = '';
|
var str = '';
|
||||||
var data = obj.data;
|
var data = font.data;
|
||||||
if (data) {
|
if (data) {
|
||||||
var length = data.length;
|
var length = data.length;
|
||||||
for (var j = 0; j < length; j++)
|
for (var j = 0; j < length; j++)
|
||||||
str += String.fromCharCode(data[j]);
|
str += String.fromCharCode(data[j]);
|
||||||
|
|
||||||
var rule = isWorker ? obj.bindWorker(str) : obj.bindDOM(str);
|
var rule = font.bindDOM(str);
|
||||||
if (rule) {
|
if (rule) {
|
||||||
rules.push(rule);
|
rules.push(rule);
|
||||||
names.push(obj.loadedName);
|
names.push(font.loadedName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.listeningForFontLoad = false;
|
this.listeningForFontLoad = false;
|
||||||
if (!isWorker && rules.length) {
|
if (!isWorker && rules.length) {
|
||||||
FontLoader.prepareFontLoadEvent(rules, names, objs);
|
FontLoader.prepareFontLoadEvent(rules, names, fontsToLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkFontsLoaded()) {
|
if (!checkFontsLoaded()) {
|
||||||
document.documentElement.addEventListener(
|
document.documentElement.addEventListener(
|
||||||
'pdfjsFontLoad', checkFontsLoaded, false);
|
'pdfjsFontLoad', checkFontsLoaded, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return objs;
|
|
||||||
},
|
},
|
||||||
// Set things up so that at least one pdfjsFontLoad event is
|
// Set things up so that at least one pdfjsFontLoad event is
|
||||||
// dispatched when all the @font-face |rules| for |names| have been
|
// 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
|
// has already started in this (outer) document, so that they should
|
||||||
// be ordered before the load in the subdocument.
|
// be ordered before the load in the subdocument.
|
||||||
prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names,
|
prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names,
|
||||||
objs) {
|
fonts) {
|
||||||
/** Hack begin */
|
/** Hack begin */
|
||||||
// There's no event when a font has finished downloading so the
|
// There's no event when a font has finished downloading so the
|
||||||
// following code is a dirty hack to 'guess' when a font is
|
// 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
|
// The postMessage() hackery was added to work around chrome bug
|
||||||
// 82402.
|
// 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');
|
var div = document.createElement('div');
|
||||||
div.setAttribute('style',
|
div.setAttribute('style',
|
||||||
'visibility: hidden;' +
|
'visibility: hidden;' +
|
||||||
@ -517,8 +519,8 @@ var FontLoader = {
|
|||||||
'message',
|
'message',
|
||||||
function fontLoaderMessage(e) {
|
function fontLoaderMessage(e) {
|
||||||
var fontNames = JSON.parse(e.data);
|
var fontNames = JSON.parse(e.data);
|
||||||
for (var i = 0, ii = objs.length; i < ii; ++i) {
|
for (var i = 0, ii = fonts.length; i < ii; ++i) {
|
||||||
var font = objs[i];
|
var font = fonts[i];
|
||||||
font.loading = false;
|
font.loading = false;
|
||||||
}
|
}
|
||||||
var evt = document.createEvent('Events');
|
var evt = document.createEvent('Events');
|
||||||
@ -764,7 +766,7 @@ var Font = (function FontClosure() {
|
|||||||
function Font(name, file, properties) {
|
function Font(name, file, properties) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.coded = properties.coded;
|
this.coded = properties.coded;
|
||||||
this.charProcIRQueues = properties.charProcIRQueues;
|
this.charProcOperatorList = properties.charProcOperatorList;
|
||||||
this.resources = properties.resources;
|
this.resources = properties.resources;
|
||||||
this.sizes = [];
|
this.sizes = [];
|
||||||
|
|
||||||
@ -829,8 +831,6 @@ var Font = (function FontClosure() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadedName = getUniqueName();
|
|
||||||
properties.id = this.loadedName;
|
|
||||||
var data;
|
var data;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'Type1':
|
case 'Type1':
|
||||||
@ -864,6 +864,7 @@ var Font = (function FontClosure() {
|
|||||||
this.widthMultiplier = !properties.fontMatrix ? 1.0 :
|
this.widthMultiplier = !properties.fontMatrix ? 1.0 :
|
||||||
1.0 / properties.fontMatrix[0];
|
1.0 / properties.fontMatrix[0];
|
||||||
this.encoding = properties.baseEncoding;
|
this.encoding = properties.baseEncoding;
|
||||||
|
this.loadedName = properties.loadedName;
|
||||||
this.loading = true;
|
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) {
|
bindDOM: function font_bindDom(data) {
|
||||||
var fontName = this.loadedName;
|
var fontName = this.loadedName;
|
||||||
|
|
||||||
@ -2337,7 +2327,7 @@ var Font = (function FontClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
charToGlyph: function fonts_charToGlyph(charcode) {
|
charToGlyph: function fonts_charToGlyph(charcode) {
|
||||||
var fontCharCode, width, codeIRQueue;
|
var fontCharCode, width, operatorList;
|
||||||
|
|
||||||
var width = this.widths[charcode];
|
var width = this.widths[charcode];
|
||||||
|
|
||||||
@ -2372,7 +2362,7 @@ var Font = (function FontClosure() {
|
|||||||
break;
|
break;
|
||||||
case 'Type3':
|
case 'Type3':
|
||||||
var glyphName = this.differences[charcode] || this.encoding[charcode];
|
var glyphName = this.differences[charcode] || this.encoding[charcode];
|
||||||
codeIRQueue = this.charProcIRQueues[glyphName];
|
operatorList = this.charProcOperatorList[glyphName];
|
||||||
fontCharCode = charcode;
|
fontCharCode = charcode;
|
||||||
break;
|
break;
|
||||||
case 'TrueType':
|
case 'TrueType':
|
||||||
@ -2415,7 +2405,7 @@ var Font = (function FontClosure() {
|
|||||||
fontChar: String.fromCharCode(fontCharCode),
|
fontChar: String.fromCharCode(fontCharCode),
|
||||||
unicode: unicodeChars,
|
unicode: unicodeChars,
|
||||||
width: width,
|
width: width,
|
||||||
codeIRQueue: codeIRQueue
|
operatorList: operatorList
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
13
src/obj.js
13
src/obj.js
@ -134,6 +134,8 @@ var Catalog = (function CatalogClosure() {
|
|||||||
while (queue.length > 0) {
|
while (queue.length > 0) {
|
||||||
var i = queue.shift();
|
var i = queue.shift();
|
||||||
var outlineDict = xref.fetch(i.obj);
|
var outlineDict = xref.fetch(i.obj);
|
||||||
|
if (outlineDict === null)
|
||||||
|
continue;
|
||||||
if (!outlineDict.has('Title'))
|
if (!outlineDict.has('Title'))
|
||||||
error('Invalid outline item');
|
error('Invalid outline item');
|
||||||
var dest = outlineDict.get('A');
|
var dest = outlineDict.get('A');
|
||||||
@ -512,7 +514,6 @@ var XRef = (function XRefClosure() {
|
|||||||
return dict;
|
return dict;
|
||||||
// nothing helps
|
// nothing helps
|
||||||
error('Invalid PDF structure');
|
error('Invalid PDF structure');
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
readXRef: function readXref(startXRef) {
|
readXRef: function readXref(startXRef) {
|
||||||
var stream = this.stream;
|
var stream = this.stream;
|
||||||
@ -569,6 +570,8 @@ var XRef = (function XRefClosure() {
|
|||||||
},
|
},
|
||||||
getEntry: function xRefGetEntry(i) {
|
getEntry: function xRefGetEntry(i) {
|
||||||
var e = this.entries[i];
|
var e = this.entries[i];
|
||||||
|
if (e === null)
|
||||||
|
return null;
|
||||||
return e.free ? null : e; // returns null is the entry is free
|
return e.free ? null : e; // returns null is the entry is free
|
||||||
},
|
},
|
||||||
fetchIfRef: function xRefFetchIfRef(obj) {
|
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
|
// If there isn't an object yet or the object isn't resolved, then the
|
||||||
// data isn't ready yet!
|
// data isn't ready yet!
|
||||||
if (!obj || !obj.isResolved) {
|
if (!obj || !obj.isResolved)
|
||||||
error('Requesting object that isn\'t resolved yet ' + objId);
|
error('Requesting object that isn\'t resolved yet ' + objId);
|
||||||
return null;
|
|
||||||
} else {
|
return obj.data;
|
||||||
return obj.data;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,15 +53,14 @@ var Parser = (function ParserClosure() {
|
|||||||
this.shift();
|
this.shift();
|
||||||
var dict = new Dict();
|
var dict = new Dict();
|
||||||
while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
|
while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
|
||||||
if (!isName(this.buf1)) {
|
if (!isName(this.buf1))
|
||||||
error('Dictionary key must be a name object');
|
error('Dictionary key must be a name object');
|
||||||
} else {
|
|
||||||
var key = this.buf1.name;
|
var key = this.buf1.name;
|
||||||
this.shift();
|
this.shift();
|
||||||
if (isEOF(this.buf1))
|
if (isEOF(this.buf1))
|
||||||
break;
|
break;
|
||||||
dict.set(key, this.getObj(cipherTransform));
|
dict.set(key, this.getObj(cipherTransform));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (isEOF(this.buf1))
|
if (isEOF(this.buf1))
|
||||||
error('End of file inside dictionary');
|
error('End of file inside dictionary');
|
||||||
@ -106,15 +105,14 @@ var Parser = (function ParserClosure() {
|
|||||||
// parse dictionary
|
// parse dictionary
|
||||||
var dict = new Dict();
|
var dict = new Dict();
|
||||||
while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
|
while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
|
||||||
if (!isName(this.buf1)) {
|
if (!isName(this.buf1))
|
||||||
error('Dictionary key must be a name object');
|
error('Dictionary key must be a name object');
|
||||||
} else {
|
|
||||||
var key = this.buf1.name;
|
var key = this.buf1.name;
|
||||||
this.shift();
|
this.shift();
|
||||||
if (isEOF(this.buf1))
|
if (isEOF(this.buf1))
|
||||||
break;
|
break;
|
||||||
dict.set(key, this.getObj(cipherTransform));
|
dict.set(key, this.getObj(cipherTransform));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse image stream
|
// parse image stream
|
||||||
@ -176,10 +174,8 @@ var Parser = (function ParserClosure() {
|
|||||||
|
|
||||||
// get length
|
// get length
|
||||||
var length = this.fetchIfRef(dict.get('Length'));
|
var length = this.fetchIfRef(dict.get('Length'));
|
||||||
if (!isInt(length)) {
|
if (!isInt(length))
|
||||||
error('Bad ' + length + ' attribute in stream');
|
error('Bad ' + length + ' attribute in stream');
|
||||||
length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip over the stream data
|
// skip over the stream data
|
||||||
stream.pos = pos + length;
|
stream.pos = pos + length;
|
||||||
@ -208,14 +204,13 @@ var Parser = (function ParserClosure() {
|
|||||||
filter = filterArray[i];
|
filter = filterArray[i];
|
||||||
if (!isName(filter))
|
if (!isName(filter))
|
||||||
error('Bad filter name: ' + filter);
|
error('Bad filter name: ' + filter);
|
||||||
else {
|
|
||||||
params = null;
|
params = null;
|
||||||
if (isArray(paramsArray) && (i in paramsArray))
|
if (isArray(paramsArray) && (i in paramsArray))
|
||||||
params = paramsArray[i];
|
params = paramsArray[i];
|
||||||
stream = this.makeFilter(stream, filter.name, length, params);
|
stream = this.makeFilter(stream, filter.name, length, params);
|
||||||
// after the first stream the length variable is invalid
|
// after the first stream the length variable is invalid
|
||||||
length = null;
|
length = null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
@ -527,17 +522,15 @@ var Lexer = (function LexerClosure() {
|
|||||||
// fall through
|
// fall through
|
||||||
case ')':
|
case ')':
|
||||||
error('Illegal character: ' + ch);
|
error('Illegal character: ' + ch);
|
||||||
return Error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// command
|
// command
|
||||||
var str = ch;
|
var str = ch;
|
||||||
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
|
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
|
||||||
stream.skip();
|
stream.skip();
|
||||||
if (str.length == 128) {
|
if (str.length == 128)
|
||||||
error('Command token too long: ' + str.length);
|
error('Command token too long: ' + str.length);
|
||||||
break;
|
|
||||||
}
|
|
||||||
str += ch;
|
str += ch;
|
||||||
}
|
}
|
||||||
if (str == 'true')
|
if (str == 'true')
|
||||||
@ -594,7 +587,6 @@ var Linearization = (function LinearizationClosure() {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
error('"' + name + '" field in linearization table is invalid');
|
error('"' + name + '" field in linearization table is invalid');
|
||||||
return 0;
|
|
||||||
},
|
},
|
||||||
getHint: function linearizationGetHint(index) {
|
getHint: function linearizationGetHint(index) {
|
||||||
var linDict = this.linDict;
|
var linDict = this.linDict;
|
||||||
@ -607,7 +599,6 @@ var Linearization = (function LinearizationClosure() {
|
|||||||
return obj2;
|
return obj2;
|
||||||
}
|
}
|
||||||
error('Hints table in linearization table is invalid: ' + index);
|
error('Hints table in linearization table is invalid: ' + index);
|
||||||
return 0;
|
|
||||||
},
|
},
|
||||||
get length() {
|
get length() {
|
||||||
if (!isDict(this.linDict))
|
if (!isDict(this.linDict))
|
||||||
|
@ -82,7 +82,7 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
|||||||
fnObj = xref.fetchIfRef(fnObj);
|
fnObj = xref.fetchIfRef(fnObj);
|
||||||
if (isArray(fnObj))
|
if (isArray(fnObj))
|
||||||
error('No support for array of functions');
|
error('No support for array of functions');
|
||||||
else if (!isPDFFunction(fnObj))
|
if (!isPDFFunction(fnObj))
|
||||||
error('Invalid function');
|
error('Invalid function');
|
||||||
var fn = PDFFunction.parse(xref, fnObj);
|
var fn = PDFFunction.parse(xref, fnObj);
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
var MAX_PATTERN_SIZE = 512;
|
var MAX_PATTERN_SIZE = 512;
|
||||||
|
|
||||||
function TilingPattern(IR, color, ctx, objs) {
|
function TilingPattern(IR, color, ctx, objs) {
|
||||||
var IRQueue = IR[2];
|
var operatorList = IR[2];
|
||||||
this.matrix = IR[3];
|
this.matrix = IR[3];
|
||||||
var bbox = IR[4];
|
var bbox = IR[4];
|
||||||
var xstep = IR[5];
|
var xstep = IR[5];
|
||||||
@ -222,7 +222,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
width = height = MAX_PATTERN_SIZE;
|
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
|
// set the new canvas element context as the graphics context
|
||||||
var tmpCtx = tmpCanvas.getContext('2d');
|
var tmpCtx = tmpCanvas.getContext('2d');
|
||||||
@ -259,12 +259,12 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
graphics.endPath();
|
graphics.endPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics.executeIRQueue(IRQueue);
|
graphics.executeOperatorList(operatorList);
|
||||||
|
|
||||||
this.canvas = tmpCanvas;
|
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 matrix = dict.get('Matrix');
|
||||||
var bbox = dict.get('BBox');
|
var bbox = dict.get('BBox');
|
||||||
var xstep = dict.get('XStep');
|
var xstep = dict.get('XStep');
|
||||||
@ -272,7 +272,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
var paintType = dict.get('PaintType');
|
var paintType = dict.get('PaintType');
|
||||||
|
|
||||||
return [
|
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) {
|
if (this.isResolved) {
|
||||||
var data = this.data;
|
var data = this.data;
|
||||||
callback.call(null, data);
|
callback.call(null, data);
|
||||||
} else if (this.isRejected && errorback) {
|
} else if (this.isRejected && errback) {
|
||||||
var error = this.error;
|
var error = this.error;
|
||||||
errback.call(null, error);
|
errback.call(null, error);
|
||||||
} else {
|
} else {
|
||||||
@ -416,3 +416,55 @@ var Promise = (function PromiseClosure() {
|
|||||||
return Promise;
|
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 = {
|
var WorkerMessageHandler = {
|
||||||
setup: function wphSetup(handler) {
|
setup: function wphSetup(handler) {
|
||||||
var pdfDoc = null;
|
var pdfModel = null;
|
||||||
|
|
||||||
handler.on('test', function wphSetupTest(data) {
|
handler.on('test', function wphSetupTest(data) {
|
||||||
handler.send('test', data instanceof Uint8Array);
|
handler.send('test', data instanceof Uint8Array);
|
||||||
@ -88,7 +88,7 @@ var WorkerMessageHandler = {
|
|||||||
handler.on('doc', function wphSetupDoc(data) {
|
handler.on('doc', function wphSetupDoc(data) {
|
||||||
// Create only the model of the PDFDoc, which is enough for
|
// Create only the model of the PDFDoc, which is enough for
|
||||||
// processing the content of the pdf.
|
// 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) {
|
handler.on('page_request', function wphSetupPageRequest(pageNum) {
|
||||||
@ -103,14 +103,14 @@ var WorkerMessageHandler = {
|
|||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
|
|
||||||
var dependency = [];
|
var dependency = [];
|
||||||
var IRQueue = null;
|
var operatorList = null;
|
||||||
try {
|
try {
|
||||||
var page = pdfDoc.getPage(pageNum);
|
var page = pdfModel.getPage(pageNum);
|
||||||
// Pre compile the pdf page and fetch the fonts/images.
|
// Pre compile the pdf page and fetch the fonts/images.
|
||||||
IRQueue = page.getIRQueue(handler, dependency);
|
operatorList = page.getOperatorList(handler, dependency);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
var minimumStackMessage =
|
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
|
// Turn the error into an obj that can be serialized
|
||||||
if (typeof e === 'string') {
|
if (typeof e === 'string') {
|
||||||
@ -137,8 +137,8 @@ var WorkerMessageHandler = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum,
|
console.log('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
|
||||||
Date.now() - start, IRQueue.fnArray.length);
|
Date.now() - start, operatorList.fnArray.length);
|
||||||
|
|
||||||
// Filter the dependecies for fonts.
|
// Filter the dependecies for fonts.
|
||||||
var fonts = {};
|
var fonts = {};
|
||||||
@ -151,59 +151,10 @@ var WorkerMessageHandler = {
|
|||||||
|
|
||||||
handler.send('page', {
|
handler.send('page', {
|
||||||
pageNum: pageNum,
|
pageNum: pageNum,
|
||||||
IRQueue: IRQueue,
|
operatorList: operatorList,
|
||||||
depFonts: Object.keys(fonts)
|
depFonts: Object.keys(fonts)
|
||||||
});
|
});
|
||||||
}, this);
|
}, 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
|
!scan-bad.pdf
|
||||||
!freeculture.pdf
|
!freeculture.pdf
|
||||||
!pdfkit_compressed.pdf
|
!pdfkit_compressed.pdf
|
||||||
|
!TAMReview.pdf
|
||||||
!issue918.pdf
|
!issue918.pdf
|
||||||
!issue1249.pdf
|
!issue1249.pdf
|
||||||
!smaskdim.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,
|
"rounds": 1,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "tamreview",
|
||||||
|
"file": "pdfs/TAMReview.pdf",
|
||||||
|
"md5": "8039aba56790d3597d2bc8c794a51301",
|
||||||
|
"rounds": 1,
|
||||||
|
"pageLimit": 5,
|
||||||
|
"link": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue925",
|
{ "id": "issue925",
|
||||||
"file": "pdfs/issue925.pdf",
|
"file": "pdfs/issue925.pdf",
|
||||||
"md5": "f58fe943090aff89dcc8e771bc0db4c2",
|
"md5": "f58fe943090aff89dcc8e771bc0db4c2",
|
||||||
|
@ -318,6 +318,58 @@ var Stepper = (function StepperClosure() {
|
|||||||
return Stepper;
|
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.
|
// Manages all the debugging tools.
|
||||||
var PDFBug = (function PDFBugClosure() {
|
var PDFBug = (function PDFBugClosure() {
|
||||||
var panelWidth = 300;
|
var panelWidth = 300;
|
||||||
@ -327,8 +379,29 @@ var PDFBug = (function PDFBugClosure() {
|
|||||||
return {
|
return {
|
||||||
tools: [
|
tools: [
|
||||||
FontInspector,
|
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() {
|
init: function init() {
|
||||||
/*
|
/*
|
||||||
* Basic Layout:
|
* Basic Layout:
|
||||||
|
@ -65,16 +65,6 @@ body {
|
|||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span#info {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-moz-document regexp("http:.*debug=1.*") {
|
|
||||||
span#info {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* === Sidebar === */
|
/* === Sidebar === */
|
||||||
#sidebar {
|
#sidebar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -442,3 +432,11 @@ canvas {
|
|||||||
background: yellow;
|
background: yellow;
|
||||||
opacity: 0.3;
|
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"/>
|
<img src="images/bookmark.svg" alt="Bookmark" align="top" height="16"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<span id="info">--</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="errorWrapper" hidden='true'>
|
<div id="errorWrapper" hidden='true'>
|
||||||
<div id="errorMessageLeft">
|
<div id="errorMessageLeft">
|
||||||
|
@ -234,6 +234,7 @@ var PDFView = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pages[val - 1].updateStats();
|
||||||
currentPageNumber = val;
|
currentPageNumber = val;
|
||||||
var event = document.createEvent('UIEvents');
|
var event = document.createEvent('UIEvents');
|
||||||
event.initUIEvent('pagechange', false, false, window, 0);
|
event.initUIEvent('pagechange', false, false, window, 0);
|
||||||
@ -870,7 +871,6 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
|||||||
// Rendering area
|
// Rendering area
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
stats.begin = Date.now();
|
|
||||||
this.content.startRendering(ctx, function pageViewDrawCallback(error) {
|
this.content.startRendering(ctx, function pageViewDrawCallback(error) {
|
||||||
if (self.loadingIconDiv) {
|
if (self.loadingIconDiv) {
|
||||||
div.removeChild(self.loadingIconDiv);
|
div.removeChild(self.loadingIconDiv);
|
||||||
@ -880,6 +880,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
|||||||
if (error)
|
if (error)
|
||||||
PDFView.error('An error occurred while rendering the page.', error);
|
PDFView.error('An error occurred while rendering the page.', error);
|
||||||
|
|
||||||
|
self.stats = content.stats;
|
||||||
self.updateStats();
|
self.updateStats();
|
||||||
if (self.onAfterDraw)
|
if (self.onAfterDraw)
|
||||||
self.onAfterDraw();
|
self.onAfterDraw();
|
||||||
@ -893,10 +894,10 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.updateStats = function pageViewUpdateStats() {
|
this.updateStats = function pageViewUpdateStats() {
|
||||||
var t1 = stats.compile, t2 = stats.fonts, t3 = stats.render;
|
if (PDFJS.pdfBug && Stats.enabled) {
|
||||||
var str = 'Time to compile/fonts/render: ' +
|
var stats = this.stats;
|
||||||
(t1 - stats.begin) + '/' + (t2 - t1) + '/' + (t3 - t2) + ' ms';
|
Stats.add(this.id, stats);
|
||||||
document.getElementById('info').textContent = str;
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1181,20 +1182,12 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
|||||||
if ('disableTextLayer' in hashParams)
|
if ('disableTextLayer' in hashParams)
|
||||||
PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
|
PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
|
||||||
|
|
||||||
if ('pdfBug' in hashParams) {
|
if ('pdfBug' in hashParams &&
|
||||||
|
(!PDFJS.isFirefoxExtension || FirefoxCom.request('pdfBugEnabled'))) {
|
||||||
PDFJS.pdfBug = true;
|
PDFJS.pdfBug = true;
|
||||||
var pdfBug = hashParams['pdfBug'];
|
var pdfBug = hashParams['pdfBug'];
|
||||||
var all = false, enabled = [];
|
var enabled = pdfBug.split(',');
|
||||||
if (pdfBug === 'all')
|
PDFBug.enable(enabled);
|
||||||
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;
|
|
||||||
}
|
|
||||||
PDFBug.init();
|
PDFBug.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user