Merge branch 'master' of github.com:andreasgal/pdf.js into predictor
This commit is contained in:
commit
16c0e0410c
2
Makefile
2
Makefile
@ -12,6 +12,8 @@ PDF_JS_FILES = \
|
||||
pdf.js \
|
||||
crypto.js \
|
||||
fonts.js \
|
||||
metrics.js \
|
||||
charsets.js \
|
||||
glyphlist.js \
|
||||
$(NULL)
|
||||
|
||||
|
70
README.md
70
README.md
@ -27,6 +27,32 @@ For an online demo, visit:
|
||||
This demo provides an interactive interface for displaying and browsing PDFs
|
||||
using the pdf.js API.
|
||||
|
||||
**Getting the code**
|
||||
|
||||
To get a local copy of the current code, clone it using git:
|
||||
|
||||
```bash
|
||||
git clone git://github.com/andreasgal/pdf.js.git pdfjs
|
||||
cd pdfjs
|
||||
```
|
||||
|
||||
Next, you need to start a local web server as some browsers don't allow opening
|
||||
PDF files for a file:// url:
|
||||
|
||||
```bash
|
||||
make server
|
||||
```
|
||||
|
||||
If everything worked out, you can now serve
|
||||
|
||||
http://localhost:8888/web/viewer.html
|
||||
|
||||
You can also view all the test pdf files on the right side serving
|
||||
|
||||
http://localhost:8888/test/pdfs/?frame
|
||||
|
||||
|
||||
|
||||
**Hello world**
|
||||
|
||||
For a "hello world" example, take a look at:
|
||||
@ -38,6 +64,20 @@ in a custom project.
|
||||
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
pdf.js is a community-driver project, so contributors are always welcome.
|
||||
Simply fork our repo and contribute away. A great place to start is our
|
||||
open issues. For better consistency and long-term stability, please do look around the
|
||||
code and try to follow our conventions.
|
||||
|
||||
If you __don't want to hack__ on the project or have short spare times, you still
|
||||
can help! Just open PDFs in the
|
||||
[online demo](http://andreasgal.github.com/pdf.js/web/viewer.html) and report
|
||||
any breakage in rendering.
|
||||
|
||||
|
||||
|
||||
## Running the Tests
|
||||
|
||||
pdf.js comes with browser-level regression tests that allow one to probe
|
||||
@ -64,16 +104,6 @@ images. The test type `load` simply tests whether the file loads without
|
||||
raising any errors.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
pdf.js is a community-driver project, so contributors are always welcome.
|
||||
Simply fork our repo and contribute away. A great place to start is our
|
||||
open issues.
|
||||
|
||||
For better consistency and long-term stability, please do look around the
|
||||
code and try to follow our conventions.
|
||||
|
||||
|
||||
## Additional resources
|
||||
|
||||
Our demo site is here:
|
||||
@ -97,8 +127,28 @@ Join our mailing list:
|
||||
Subscribe either using lists.mozilla.org or Google Groups:
|
||||
|
||||
https://lists.mozilla.org/listinfo/dev-pdf-js
|
||||
|
||||
https://groups.google.com/group/mozilla.dev.pdf-js/topics
|
||||
|
||||
Talk to us on IRC:
|
||||
|
||||
#pdfjs on irc.mozilla.org
|
||||
|
||||
## Additional resources to understand the structure of PDF
|
||||
|
||||
A really basic overview of PDF is described here:
|
||||
|
||||
http://partners.adobe.com/public/developer/en/livecycle/lc_pdf_overview_format.pdf
|
||||
|
||||
A more detailed file example:
|
||||
|
||||
http://gnupdf.org/Introduction_to_PDF
|
||||
|
||||
The PDF specification itself is an ISO and not free available. However, there is
|
||||
a "PDF Reference" from Adobe:
|
||||
|
||||
http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/pdf_reference_1-7.pdf
|
||||
|
||||
Recommanded chapters to read: "2. Overview", "3.4 File Structure",
|
||||
"4.1 Graphics Objects" that lists the PDF commands.
|
||||
|
||||
|
101
charsets.js
Normal file
101
charsets.js
Normal file
@ -0,0 +1,101 @@
|
||||
|
||||
var ISOAdobeCharset = [
|
||||
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
|
||||
'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
|
||||
'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
|
||||
'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
|
||||
'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
|
||||
'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
|
||||
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
|
||||
'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
|
||||
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
|
||||
'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
|
||||
'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
|
||||
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
|
||||
'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
|
||||
'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
|
||||
'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
|
||||
'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
|
||||
'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
|
||||
'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
|
||||
'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
|
||||
'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
|
||||
'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
|
||||
'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
|
||||
'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
|
||||
'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
|
||||
'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
|
||||
'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
|
||||
'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
|
||||
'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
|
||||
'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
|
||||
'ugrave', 'yacute', 'ydieresis', 'zcaron'
|
||||
];
|
||||
|
||||
var ExpertCharset = [
|
||||
'.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
|
||||
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
|
||||
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
|
||||
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
|
||||
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
|
||||
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
|
||||
'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
|
||||
'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
|
||||
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
||||
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
||||
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
||||
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
|
||||
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
|
||||
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
|
||||
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
|
||||
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
|
||||
'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
|
||||
'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
|
||||
'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
|
||||
'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
|
||||
'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
|
||||
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
||||
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
||||
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
||||
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
||||
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
||||
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
||||
'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
|
||||
'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall',
|
||||
'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
|
||||
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
|
||||
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
|
||||
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
|
||||
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
|
||||
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
|
||||
'Ydieresissmall'
|
||||
];
|
||||
|
||||
var ExpertSubsetCharset = [
|
||||
'.notdef', 'space', 'dollaroldstyle', 'dollarsuperior',
|
||||
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
|
||||
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
|
||||
'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
|
||||
'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
|
||||
'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
|
||||
'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior',
|
||||
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
||||
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
||||
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
||||
'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted',
|
||||
'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter',
|
||||
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
||||
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
||||
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
||||
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
||||
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
||||
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
||||
'periodinferior', 'commainferior'
|
||||
];
|
||||
|
49
crypto.js
49
crypto.js
@ -3,7 +3,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var ARCFourCipher = (function() {
|
||||
var ARCFourCipher = (function aRCFourCipher() {
|
||||
function constructor(key) {
|
||||
this.a = 0;
|
||||
this.b = 0;
|
||||
@ -21,7 +21,7 @@ var ARCFourCipher = (function() {
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
encryptBlock: function(data) {
|
||||
encryptBlock: function aRCFourCipherEncryptBlock(data) {
|
||||
var i, n = data.length, tmp, tmp2;
|
||||
var a = this.a, b = this.b, s = this.s;
|
||||
var output = new Uint8Array(n);
|
||||
@ -45,7 +45,7 @@ var ARCFourCipher = (function() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var md5 = (function() {
|
||||
var calculateMD5 = (function calculateMD5() {
|
||||
var r = new Uint8Array([
|
||||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
@ -129,12 +129,12 @@ var md5 = (function() {
|
||||
return hash;
|
||||
})();
|
||||
|
||||
var NullCipher = (function() {
|
||||
var NullCipher = (function nullCipher() {
|
||||
function constructor() {
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
decryptBlock: function(data) {
|
||||
decryptBlock: function nullCipherDecryptBlock(data) {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
@ -142,7 +142,7 @@ var NullCipher = (function() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var AES128Cipher = (function() {
|
||||
var AES128Cipher = (function aES128Cipher() {
|
||||
var rcon = new Uint8Array([
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
|
||||
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
|
||||
@ -372,7 +372,7 @@ var AES128Cipher = (function() {
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
decryptBlock: function(data) {
|
||||
decryptBlock: function aES128CipherDecryptBlock(data) {
|
||||
var i, sourceLength = data.length;
|
||||
var buffer = this.buffer, bufferLength = this.bufferPosition;
|
||||
// waiting for IV values -- they are at the start of the stream
|
||||
@ -395,19 +395,21 @@ var AES128Cipher = (function() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var CipherTransform = (function() {
|
||||
var CipherTransform = (function cipherTransform() {
|
||||
function constructor(stringCipherConstructor, streamCipherConstructor) {
|
||||
this.stringCipherConstructor = stringCipherConstructor;
|
||||
this.streamCipherConstructor = streamCipherConstructor;
|
||||
}
|
||||
constructor.prototype = {
|
||||
createStream: function(stream) {
|
||||
createStream: function cipherTransformCreateStream(stream) {
|
||||
var cipher = new this.streamCipherConstructor();
|
||||
return new DecryptStream(stream, function(data) {
|
||||
return cipher.decryptBlock(data);
|
||||
});
|
||||
return new DecryptStream(stream,
|
||||
function cipherTransformDecryptStream(data) {
|
||||
return cipher.decryptBlock(data);
|
||||
}
|
||||
);
|
||||
},
|
||||
decryptString: function(s) {
|
||||
decryptString: function cipherTransformDecryptString(s) {
|
||||
var cipher = new this.stringCipherConstructor();
|
||||
var data = stringToBytes(s);
|
||||
data = cipher.decryptBlock(data);
|
||||
@ -417,7 +419,7 @@ var CipherTransform = (function() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
var CipherTransformFactory = (function() {
|
||||
var CipherTransformFactory = (function cipherTransformFactory() {
|
||||
function prepareKeyData(fileId, password, ownerPassword, userPassword,
|
||||
flags, revision, keyLength, encryptMetadata) {
|
||||
var defaultPasswordBytes = new Uint8Array([
|
||||
@ -450,11 +452,11 @@ var CipherTransformFactory = (function() {
|
||||
hashData[i++] = 0xFF;
|
||||
hashData[i++] = 0xFF;
|
||||
}
|
||||
var hash = md5(hashData, 0, i);
|
||||
var hash = calculateMD5(hashData, 0, i);
|
||||
var keyLengthInBytes = keyLength >> 3;
|
||||
if (revision >= 3) {
|
||||
for (j = 0; j < 50; ++j) {
|
||||
hash = md5(hash, 0, keyLengthInBytes);
|
||||
hash = calculateMD5(hash, 0, keyLengthInBytes);
|
||||
}
|
||||
}
|
||||
var encryptionKey = hash.subarray(0, keyLengthInBytes);
|
||||
@ -467,7 +469,7 @@ var CipherTransformFactory = (function() {
|
||||
for (j = 0, n = fileId.length; j < n; ++j)
|
||||
hashData[i++] = fileId[j];
|
||||
cipher = new ARCFourCipher(encryptionKey);
|
||||
var checkData = cipher.encryptBlock(md5(hashData, 0, i));
|
||||
var checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
|
||||
n = encryptionKey.length;
|
||||
var derrivedKey = new Uint8Array(n), k;
|
||||
for (j = 1; j <= 19; ++j) {
|
||||
@ -542,7 +544,7 @@ var CipherTransformFactory = (function() {
|
||||
key[i++] = 0x6C;
|
||||
key[i++] = 0x54;
|
||||
}
|
||||
var hash = md5(key, 0, i);
|
||||
var hash = calculateMD5(key, 0, i);
|
||||
return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
|
||||
}
|
||||
|
||||
@ -552,18 +554,18 @@ var CipherTransformFactory = (function() {
|
||||
if (cryptFilter != null)
|
||||
cfm = cryptFilter.get('CFM');
|
||||
if (!cfm || cfm.name == 'None') {
|
||||
return function() {
|
||||
return function cipherTransformFactoryBuildCipherConstructorNone() {
|
||||
return new NullCipher();
|
||||
};
|
||||
}
|
||||
if ('V2' == cfm.name) {
|
||||
return function() {
|
||||
return function cipherTransformFactoryBuildCipherConstructorV2() {
|
||||
return new ARCFourCipher(
|
||||
buildObjectKey(num, gen, key, false));
|
||||
};
|
||||
}
|
||||
if ('AESV2' == cfm.name) {
|
||||
return function() {
|
||||
return function cipherTransformFactoryBuildCipherConstructorAESV2() {
|
||||
return new AES128Cipher(
|
||||
buildObjectKey(num, gen, key, true));
|
||||
};
|
||||
@ -573,7 +575,8 @@ var CipherTransformFactory = (function() {
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
createCipherTransform: function(num, gen) {
|
||||
createCipherTransform: function buildCipherCreateCipherTransform(num,
|
||||
gen) {
|
||||
if (this.algorithm == 4) {
|
||||
return new CipherTransform(
|
||||
buildCipherConstructor(this.cf, this.stmf,
|
||||
@ -583,7 +586,7 @@ var CipherTransformFactory = (function() {
|
||||
}
|
||||
// algorithms 1 and 2
|
||||
var key = buildObjectKey(num, gen, this.encryptionKey, false);
|
||||
var cipherConstructor = function() {
|
||||
var cipherConstructor = function buildCipherCipherConstructor() {
|
||||
return new ARCFourCipher(key);
|
||||
};
|
||||
return new CipherTransform(cipherConstructor, cipherConstructor);
|
||||
|
165
fonts.js
165
fonts.js
@ -124,7 +124,7 @@ var serifFonts = {
|
||||
var FontLoader = {
|
||||
listeningForFontLoad: false,
|
||||
|
||||
bind: function(fonts, callback) {
|
||||
bind: function fontLoaderBind(fonts, callback) {
|
||||
function checkFontsLoaded() {
|
||||
for (var i = 0; i < objs.length; i++) {
|
||||
var fontObj = objs[i];
|
||||
@ -180,7 +180,8 @@ var FontLoader = {
|
||||
// loaded in a subdocument. It's expected that the load of |rules|
|
||||
// has already started in this (outer) document, so that they should
|
||||
// be ordered before the load in the subdocument.
|
||||
prepareFontLoadEvent: function(rules, names, objs) {
|
||||
prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names,
|
||||
objs) {
|
||||
/** Hack begin */
|
||||
// There's no event when a font has finished downloading so the
|
||||
// following code is a dirty hack to 'guess' when a font is
|
||||
@ -219,7 +220,7 @@ var FontLoader = {
|
||||
if (!this.listeningForFontLoad) {
|
||||
window.addEventListener(
|
||||
'message',
|
||||
function(e) {
|
||||
function fontLoaderMessage(e) {
|
||||
var fontNames = JSON.parse(e.data);
|
||||
for (var i = 0; i < objs.length; ++i) {
|
||||
var font = objs[i];
|
||||
@ -247,7 +248,7 @@ var FontLoader = {
|
||||
fontNamesArray += '"' + names[i] + '", ';
|
||||
}
|
||||
src += ' var fontNames=[' + fontNamesArray + '];\n';
|
||||
src += ' window.onload = function () {\n';
|
||||
src += ' window.onload = function fontLoaderOnload() {\n';
|
||||
src += ' parent.postMessage(JSON.stringify(fontNames), "*");\n';
|
||||
src += ' }';
|
||||
src += '</script></head><body>';
|
||||
@ -447,13 +448,14 @@ var Font = (function Font() {
|
||||
}
|
||||
|
||||
var data;
|
||||
switch (properties.type) {
|
||||
var type = properties.type;
|
||||
switch (type) {
|
||||
case 'Type1':
|
||||
case 'CIDFontType0':
|
||||
this.mimetype = 'font/opentype';
|
||||
|
||||
var subtype = properties.subtype;
|
||||
var cff = (subtype === 'Type1C') ?
|
||||
var cff = (subtype == 'Type1C' || subtype == 'CIDFontType0C') ?
|
||||
new Type2CFF(file, properties) : new CFF(name, file, properties);
|
||||
|
||||
// Wrap the CFF data inside an OTF font file
|
||||
@ -475,7 +477,7 @@ var Font = (function Font() {
|
||||
}
|
||||
|
||||
this.data = data;
|
||||
this.type = properties.type;
|
||||
this.type = type;
|
||||
this.textMatrix = properties.textMatrix;
|
||||
this.defaultWidth = properties.defaultWidth;
|
||||
this.loadedName = getUniqueName();
|
||||
@ -598,7 +600,7 @@ var Font = (function Font() {
|
||||
var length = glyphs.length;
|
||||
for (var n = 0; n < length; ++n)
|
||||
codes.push({ unicode: glyphs[n].unicode, code: n });
|
||||
codes.sort(function(a, b) {
|
||||
codes.sort(function fontGetRangesSort(a, b) {
|
||||
return a.unicode - b.unicode;
|
||||
});
|
||||
|
||||
@ -927,7 +929,7 @@ var Font = (function Font() {
|
||||
}
|
||||
|
||||
// Check that table are sorted by platformID then encodingID,
|
||||
records.sort(function(a, b) {
|
||||
records.sort(function fontReplaceCMapTableSort(a, b) {
|
||||
return ((a.platformID << 16) + a.encodingID) -
|
||||
((b.platformID << 16) + b.encodingID);
|
||||
});
|
||||
@ -1060,11 +1062,11 @@ var Font = (function Font() {
|
||||
var itemSize, itemDecode, itemEncode;
|
||||
if (isGlyphLocationsLong) {
|
||||
itemSize = 4;
|
||||
itemDecode = function(data, offset) {
|
||||
itemDecode = function fontItemDecodeLong(data, offset) {
|
||||
return (data[offset] << 24) | (data[offset + 1] << 16) |
|
||||
(data[offset + 2] << 8) | data[offset + 3];
|
||||
};
|
||||
itemEncode = function(data, offset, value) {
|
||||
itemEncode = function fontItemEncodeLong(data, offset, value) {
|
||||
data[offset] = (value >>> 24) & 0xFF;
|
||||
data[offset + 1] = (value >> 16) & 0xFF;
|
||||
data[offset + 2] = (value >> 8) & 0xFF;
|
||||
@ -1072,10 +1074,10 @@ var Font = (function Font() {
|
||||
};
|
||||
} else {
|
||||
itemSize = 2;
|
||||
itemDecode = function(data, offset) {
|
||||
itemDecode = function fontItemDecode(data, offset) {
|
||||
return (data[offset] << 9) | (data[offset + 1] << 1);
|
||||
};
|
||||
itemEncode = function(data, offset, value) {
|
||||
itemEncode = function fontItemEncode(data, offset, value) {
|
||||
data[offset] = (value >> 9) & 0xFF;
|
||||
data[offset + 1] = (value >> 1) & 0xFF;
|
||||
};
|
||||
@ -1322,7 +1324,7 @@ var Font = (function Font() {
|
||||
'cmap': createCMapTable(charstrings.slice(), font.glyphIds),
|
||||
|
||||
// Font header
|
||||
'head': (function() {
|
||||
'head': (function fontFieldsHead() {
|
||||
return stringToArray(
|
||||
'\x00\x01\x00\x00' + // Version number
|
||||
'\x00\x00\x10\x00' + // fontRevision
|
||||
@ -1344,7 +1346,7 @@ var Font = (function Font() {
|
||||
})(),
|
||||
|
||||
// Horizontal header
|
||||
'hhea': (function() {
|
||||
'hhea': (function fontFieldsHhea() {
|
||||
return stringToArray(
|
||||
'\x00\x01\x00\x00' + // Version number
|
||||
string16(properties.ascent) + // Typographic Ascent
|
||||
@ -1367,7 +1369,7 @@ var Font = (function Font() {
|
||||
})(),
|
||||
|
||||
// Horizontal metrics
|
||||
'hmtx': (function() {
|
||||
'hmtx': (function fontFieldsHmtx() {
|
||||
var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
|
||||
for (var i = 0; i < charstrings.length; i++) {
|
||||
hmtx += string16(charstrings[i].width) + string16(0);
|
||||
@ -1376,7 +1378,7 @@ var Font = (function Font() {
|
||||
})(),
|
||||
|
||||
// Maximum profile
|
||||
'maxp': (function() {
|
||||
'maxp': (function fontFieldsMaxp() {
|
||||
return stringToArray(
|
||||
'\x00\x00\x50\x00' + // Version number
|
||||
string16(charstrings.length + 1)); // Num of glyphs
|
||||
@ -1504,7 +1506,7 @@ var Font = (function Font() {
|
||||
* program. Some of its logic depends on the Type2 charstrings
|
||||
* structure.
|
||||
*/
|
||||
var Type1Parser = function() {
|
||||
var Type1Parser = function type1Parser() {
|
||||
/*
|
||||
* Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence
|
||||
* of Plaintext Bytes. The function took a key as a parameter which can be
|
||||
@ -2032,7 +2034,7 @@ var CFFStrings = [
|
||||
|
||||
var type1Parser = new Type1Parser();
|
||||
|
||||
var CFF = function(name, file, properties) {
|
||||
var CFF = function cFF(name, file, properties) {
|
||||
// Get the data block containing glyphs and subrs informations
|
||||
var headerBlock = file.getBytes(properties.length1);
|
||||
type1Parser.extractFontHeader(headerBlock, properties);
|
||||
@ -2232,7 +2234,7 @@ CFF.prototype = {
|
||||
'names': this.createCFFIndexHeader([name]),
|
||||
|
||||
'topDict': (function topDict(self) {
|
||||
return function() {
|
||||
return function cFFWrapTopDict() {
|
||||
var header = '\x00\x01\x01\x01';
|
||||
var dict =
|
||||
'\xf8\x1b\x00' + // version
|
||||
@ -2309,7 +2311,7 @@ CFF.prototype = {
|
||||
'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs),
|
||||
true),
|
||||
|
||||
'private': (function(self) {
|
||||
'private': (function cFFWrapPrivate(self) {
|
||||
var data =
|
||||
'\x8b\x14' + // defaultWidth
|
||||
'\x8b\x15'; // nominalWidth
|
||||
@ -2362,7 +2364,7 @@ CFF.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
var Type2CFF = (function() {
|
||||
var Type2CFF = (function type2CFF() {
|
||||
// TODO: replace parsing code with the Type2Parser in font_utils.js
|
||||
function constructor(file, properties) {
|
||||
var bytes = file.getBytes();
|
||||
@ -2387,16 +2389,21 @@ var Type2CFF = (function() {
|
||||
|
||||
var strings = this.getStrings(stringIndex);
|
||||
|
||||
var baseDict = this.parseDict(dictIndex.get(0));
|
||||
var baseDict = this.parseDict(dictIndex.get(0).data);
|
||||
var topDict = this.getTopDict(baseDict, strings);
|
||||
|
||||
var bytes = this.bytes;
|
||||
|
||||
var privateDict = {};
|
||||
var privateInfo = topDict.Private;
|
||||
var privOffset = privateInfo[1], privLength = privateInfo[0];
|
||||
var privBytes = bytes.subarray(privOffset, privOffset + privLength);
|
||||
baseDict = this.parseDict(privBytes);
|
||||
var privDict = this.getPrivDict(baseDict, strings);
|
||||
if (privateInfo) {
|
||||
var privOffset = privateInfo[1], privLength = privateInfo[0];
|
||||
var privBytes = bytes.subarray(privOffset, privOffset + privLength);
|
||||
baseDict = this.parseDict(privBytes);
|
||||
privateDict = this.getPrivDict(baseDict, strings);
|
||||
} else {
|
||||
privateDict.defaultWidthX = properties.defaultWidth;
|
||||
}
|
||||
|
||||
var charStrings = this.parseIndex(topDict.CharStrings);
|
||||
var charset = this.parseCharsets(topDict.charset,
|
||||
@ -2412,10 +2419,37 @@ var Type2CFF = (function() {
|
||||
if (hasSupplement)
|
||||
bytes[topDict.Encoding] = 0;
|
||||
|
||||
// The CFF specification state that the 'dotsection' command
|
||||
// (12, 0) is deprecated and treated as a no-op, but all Type2
|
||||
// charstrings processors should support them. Unfortunately
|
||||
// the font sanitizer don't. As a workaround the sequence (12, 0)
|
||||
// is replaced by a useless (0, hmoveto).
|
||||
var count = charStrings.length;
|
||||
for (var i = 0; i < count; i++) {
|
||||
var charstring = charStrings.get(i);
|
||||
|
||||
var start = charstring.start;
|
||||
var data = charstring.data;
|
||||
var length = data.length;
|
||||
for (var j = 0; j <= length; j) {
|
||||
var value = data[j++];
|
||||
if (value == 12 && data[j++] == 0) {
|
||||
bytes[start + j - 2] = 139;
|
||||
bytes[start + j - 1] = 22;
|
||||
} else if (value === 28) {
|
||||
j += 2;
|
||||
} else if (value >= 247 && value <= 254) {
|
||||
j++;
|
||||
} else if (value == 255) {
|
||||
j += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// charstrings contains info about glyphs (one element per glyph
|
||||
// containing mappings for {unicode, width})
|
||||
var charstrings = this.getCharStrings(charset, charStrings,
|
||||
privDict, this.properties);
|
||||
privateDict, this.properties);
|
||||
|
||||
// create the mapping between charstring and glyph id
|
||||
var glyphIds = [];
|
||||
@ -2432,10 +2466,8 @@ var Type2CFF = (function() {
|
||||
},
|
||||
|
||||
getCharStrings: function cff_charstrings(charsets, charStrings,
|
||||
privDict, properties) {
|
||||
var defaultWidth = privDict['defaultWidthX'];
|
||||
var nominalWidth = privDict['nominalWidthX'];
|
||||
|
||||
privateDict, properties) {
|
||||
var defaultWidth = privateDict['defaultWidthX'];
|
||||
var charstrings = [];
|
||||
var differences = properties.differences;
|
||||
var index = 0;
|
||||
@ -2472,7 +2504,9 @@ var Type2CFF = (function() {
|
||||
}
|
||||
|
||||
// sort the array by the unicode value
|
||||
charstrings.sort(function(a, b) {return a.unicode - b.unicode});
|
||||
charstrings.sort(function type2CFFGetCharStringsSort(a, b) {
|
||||
return a.unicode - b.unicode;
|
||||
});
|
||||
return charstrings;
|
||||
},
|
||||
|
||||
@ -2492,8 +2526,8 @@ var Type2CFF = (function() {
|
||||
|
||||
if (pos == 0 || pos == 1) {
|
||||
var gid = 1;
|
||||
var baseEncoding =
|
||||
pos ? Encodings.ExpertEncoding : Encodings.StandardEncoding;
|
||||
var baseEncoding = pos ? Encodings.ExpertEncoding.slice() :
|
||||
Encodings.StandardEncoding.slice();
|
||||
for (var i = 0; i < charset.length; i++) {
|
||||
var index = baseEncoding.indexOf(charset[i]);
|
||||
if (index != -1)
|
||||
@ -2538,37 +2572,42 @@ var Type2CFF = (function() {
|
||||
},
|
||||
|
||||
parseCharsets: function cff_parsecharsets(pos, length, strings) {
|
||||
if (pos == 0) {
|
||||
return ISOAdobeCharset.slice();
|
||||
} else if (pos == 1) {
|
||||
return ExpertCharset.slice();
|
||||
} else if (pos == 2) {
|
||||
return ExpertSubsetCharset.slice();
|
||||
}
|
||||
|
||||
var bytes = this.bytes;
|
||||
var format = bytes[pos++];
|
||||
var charset = ['.notdef'];
|
||||
|
||||
// subtract 1 for the .notdef glyph
|
||||
length -= 1;
|
||||
|
||||
switch (format) {
|
||||
case 0:
|
||||
for (var i = 0; i < length; ++i) {
|
||||
var id = bytes[pos++];
|
||||
id = (id << 8) | bytes[pos++];
|
||||
charset.push(strings[id]);
|
||||
for (var i = 0; i < length; i++) {
|
||||
var sid = (bytes[pos++] << 8) | bytes[pos++];
|
||||
charset.push(strings[sid]);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
while (charset.length <= length) {
|
||||
var first = bytes[pos++];
|
||||
first = (first << 8) | bytes[pos++];
|
||||
var numLeft = bytes[pos++];
|
||||
for (var i = 0; i <= numLeft; ++i)
|
||||
charset.push(strings[first++]);
|
||||
var sid = (bytes[pos++] << 8) | bytes[pos++];
|
||||
var count = bytes[pos++];
|
||||
for (var i = 0; i <= count; i++)
|
||||
charset.push(strings[sid++]);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
while (charset.length <= length) {
|
||||
var first = bytes[pos++];
|
||||
first = (first << 8) | bytes[pos++];
|
||||
var numLeft = bytes[pos++];
|
||||
numLeft = (numLeft << 8) | bytes[pos++];
|
||||
for (var i = 0; i <= numLeft; ++i)
|
||||
charset.push(strings[first++]);
|
||||
var sid = (bytes[pos++] << 8) | bytes[pos++];
|
||||
var count = (bytes[pos++] << 8) | bytes[pos++];
|
||||
for (var i = 0; i <= count; i++)
|
||||
charset.push(strings[sid++]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -2643,20 +2682,20 @@ var Type2CFF = (function() {
|
||||
}
|
||||
return dict;
|
||||
},
|
||||
getStrings: function cff_getstrings(stringIndex) {
|
||||
function bytesToString(bytesArr) {
|
||||
var s = '';
|
||||
for (var i = 0, ii = bytesArr.length; i < ii; ++i)
|
||||
s += String.fromCharCode(bytesArr[i]);
|
||||
return s;
|
||||
getStrings: function cff_getStrings(stringIndex) {
|
||||
function bytesToString(bytesArray) {
|
||||
var str = '';
|
||||
for (var i = 0, length = bytesArray.length; i < length; i++)
|
||||
str += String.fromCharCode(bytesArray[i]);
|
||||
return str;
|
||||
}
|
||||
|
||||
var stringArray = [];
|
||||
for (var i = 0, ii = CFFStrings.length; i < ii; ++i)
|
||||
for (var i = 0, length = CFFStrings.length; i < length; i++)
|
||||
stringArray.push(CFFStrings[i]);
|
||||
|
||||
for (var i = 0, ii = stringIndex.length; i < ii; ++i)
|
||||
stringArray.push(bytesToString(stringIndex.get(i)));
|
||||
for (var i = 0, length = stringIndex.length; i < length; i++)
|
||||
stringArray.push(bytesToString(stringIndex.get(i).data));
|
||||
|
||||
return stringArray;
|
||||
},
|
||||
@ -2702,7 +2741,7 @@ var Type2CFF = (function() {
|
||||
} else if (value <= 254) {
|
||||
return -((value - 251) * 256) - dict[pos++] - 108;
|
||||
} else {
|
||||
error('Incorrect byte');
|
||||
error('255 is not a valid DICT command');
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -2779,7 +2818,11 @@ var Type2CFF = (function() {
|
||||
|
||||
var start = offsets[index];
|
||||
var end = offsets[index + 1];
|
||||
return bytes.subarray(start, end);
|
||||
return {
|
||||
start: start,
|
||||
end: end,
|
||||
data: bytes.subarray(start, end)
|
||||
};
|
||||
},
|
||||
length: count,
|
||||
endPos: end
|
||||
|
@ -39,7 +39,7 @@ function load() {
|
||||
|
||||
var r = new XMLHttpRequest();
|
||||
r.open('GET', manifestFile, false);
|
||||
r.onreadystatechange = function(e) {
|
||||
r.onreadystatechange = function loadOnreadystatechange(e) {
|
||||
if (r.readyState == 4) {
|
||||
log('done\n');
|
||||
manifest = JSON.parse(r.responseText);
|
||||
@ -50,7 +50,21 @@ function load() {
|
||||
r.send(null);
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
var styleSheet = document.styleSheets[0];
|
||||
if (styleSheet) {
|
||||
while (styleSheet.cssRules.length > 0)
|
||||
styleSheet.deleteRule(0);
|
||||
}
|
||||
var guard = document.getElementById('content-end');
|
||||
var body = document.body;
|
||||
while (body.lastChild !== guard)
|
||||
body.removeChild(body.lastChild);
|
||||
}
|
||||
|
||||
function nextTask() {
|
||||
cleanup();
|
||||
|
||||
if (currentTaskIdx == manifest.length) {
|
||||
return done();
|
||||
}
|
||||
@ -62,7 +76,7 @@ function nextTask() {
|
||||
var r = new XMLHttpRequest();
|
||||
r.open('GET', task.file);
|
||||
r.mozResponseType = r.responseType = 'arraybuffer';
|
||||
r.onreadystatechange = function() {
|
||||
r.onreadystatechange = function nextTaskOnreadystatechange() {
|
||||
var failure;
|
||||
if (r.readyState == 4) {
|
||||
var data = r.mozResponseArrayBuffer || r.mozResponse ||
|
||||
@ -85,11 +99,15 @@ function isLastPage(task) {
|
||||
return (task.pageNum > task.pdfDoc.numPages);
|
||||
}
|
||||
|
||||
function canvasToDataURL() {
|
||||
return canvas.toDataURL('image/png');
|
||||
}
|
||||
|
||||
function nextPage(task, loadError) {
|
||||
var failure = loadError || '';
|
||||
|
||||
if (!task.pdfDoc) {
|
||||
sendTaskResult(canvas.toDataURL('image/png'), task, failure);
|
||||
sendTaskResult(canvasToDataURL(), task, failure);
|
||||
log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n');
|
||||
++currentTaskIdx;
|
||||
nextTask();
|
||||
@ -126,7 +144,7 @@ function nextPage(task, loadError) {
|
||||
|
||||
page.startRendering(
|
||||
ctx,
|
||||
function(e) {
|
||||
function nextPageStartRendering(e) {
|
||||
snapshotCurrentPage(task, (!failure && e) ?
|
||||
('render : ' + e) : failure);
|
||||
}
|
||||
@ -146,13 +164,13 @@ function nextPage(task, loadError) {
|
||||
function snapshotCurrentPage(task, failure) {
|
||||
log('done, snapshotting... ');
|
||||
|
||||
sendTaskResult(canvas.toDataURL('image/png'), task, failure);
|
||||
sendTaskResult(canvasToDataURL(), task, failure);
|
||||
log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n');
|
||||
|
||||
// Set up the next request
|
||||
var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0;
|
||||
setTimeout(
|
||||
function() {
|
||||
function snapshotCurrentPageSetTimeout() {
|
||||
++task.pageNum;
|
||||
nextPage(task);
|
||||
},
|
||||
@ -201,7 +219,7 @@ function sendTaskResult(snapshot, task, failure) {
|
||||
// (The POST URI is ignored atm.)
|
||||
r.open('POST', '/submit_task_results', true);
|
||||
r.setRequestHeader('Content-Type', 'application/json');
|
||||
r.onreadystatechange = function(e) {
|
||||
r.onreadystatechange = function sendTaskResultOnreadystatechange(e) {
|
||||
if (r.readyState == 4) {
|
||||
inFlightRequests--;
|
||||
}
|
||||
|
105
test/pdfs/extgstate.pdf
Normal file
105
test/pdfs/extgstate.pdf
Normal file
@ -0,0 +1,105 @@
|
||||
%PDF-1.4
|
||||
%öäüß
|
||||
1 0 obj
|
||||
<<
|
||||
/Type /Catalog
|
||||
/Version /1.4
|
||||
/Pages 2 0 R
|
||||
>>
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/Type /Pages
|
||||
/Kids [3 0 R]
|
||||
/Count 1
|
||||
>>
|
||||
endobj
|
||||
3 0 obj
|
||||
<<
|
||||
/Type /Page
|
||||
/MediaBox [0 0 612 792]
|
||||
/Resources 4 0 R
|
||||
/Parent 2 0 R
|
||||
/Contents 5 0 R
|
||||
>>
|
||||
endobj
|
||||
4 0 obj
|
||||
<<
|
||||
/ExtGState 6 0 R
|
||||
/Font 7 0 R
|
||||
/XObject <<
|
||||
>>
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<<
|
||||
/Length 8 0 R
|
||||
>>
|
||||
stream
|
||||
/GS1 gs
|
||||
/F0 12 Tf
|
||||
BT
|
||||
100 700 Td
|
||||
(I should be courier!) Tj
|
||||
ET
|
||||
50 600 m
|
||||
400 600 l
|
||||
S
|
||||
|
||||
endstream
|
||||
endobj
|
||||
6 0 obj
|
||||
<<
|
||||
/GS1 9 0 R
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<<
|
||||
/F0 10 0 R
|
||||
>>
|
||||
endobj
|
||||
8 0 obj
|
||||
82
|
||||
endobj
|
||||
9 0 obj
|
||||
<<
|
||||
/Type /ExtGState
|
||||
/LW 10
|
||||
/LC 1
|
||||
/LJ 2
|
||||
/ML 0.3000000119
|
||||
/D [[0.0917000026 183.3300018311]
|
||||
0]
|
||||
/Font [10 0 R 36]
|
||||
>>
|
||||
endobj
|
||||
10 0 obj
|
||||
<<
|
||||
/Type /Font
|
||||
/Subtype /Type1
|
||||
/BaseFont /Courier
|
||||
/Encoding /WinAnsiEncoding
|
||||
>>
|
||||
endobj
|
||||
xref
|
||||
0 11
|
||||
0000000000 65535 f
|
||||
0000000015 00000 n
|
||||
0000000078 00000 n
|
||||
0000000135 00000 n
|
||||
0000000239 00000 n
|
||||
0000000304 00000 n
|
||||
0000000441 00000 n
|
||||
0000000473 00000 n
|
||||
0000000505 00000 n
|
||||
0000000523 00000 n
|
||||
0000000653 00000 n
|
||||
trailer
|
||||
<<
|
||||
/Root 1 0 R
|
||||
/ID [<BFFF29B7D1C75EC69AC080682C2AFC5B> <BFFF29B7D1C75EC69AC080682C2AFC5B>]
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
749
|
||||
%%EOF
|
1
test/pdfs/f1040.pdf.link
Normal file
1
test/pdfs/f1040.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://www.irs.gov/pub/irs-pdf/f1040.pdf
|
1
test/pdfs/hudsonsurvey.pdf.link
Normal file
1
test/pdfs/hudsonsurvey.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
https://issues.apache.org/jira/secure/attachment/12421789/survey.pdf
|
@ -139,5 +139,23 @@
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
},
|
||||
{ "id": "f1040",
|
||||
"file": "pdfs/f1040.pdf",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
},
|
||||
{ "id": "hudsonsurvey",
|
||||
"file": "pdfs/hudsonsurvey.pdf",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
},
|
||||
{ "id": "extgstate",
|
||||
"file": "pdfs/extgstate.pdf",
|
||||
"link": false,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
}
|
||||
]
|
||||
|
@ -7,12 +7,14 @@
|
||||
<script type="text/javascript" src="/crypto.js"></script>
|
||||
<script type="text/javascript" src="/glyphlist.js"></script>
|
||||
<script type="text/javascript" src="/metrics.js"></script>
|
||||
<script type="text/javascript" src="/charsets.js"></script>
|
||||
<script type="text/javascript" src="driver.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="load();">
|
||||
<pre style="width:800; height:800; overflow: scroll;"id="stdout"></pre>
|
||||
<p>Inflight requests: <span id="inFlightCount"></span></p>
|
||||
<div id="content-end"><!-- cleanup() guard --></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
@ -3,400 +3,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var CFFStrings = [
|
||||
'.notdef',
|
||||
'space',
|
||||
'exclam',
|
||||
'quotedbl',
|
||||
'numbersign',
|
||||
'dollar',
|
||||
'percent',
|
||||
'ampersand',
|
||||
'quoteright',
|
||||
'parenleft',
|
||||
'parenright',
|
||||
'asterisk',
|
||||
'plus',
|
||||
'comma',
|
||||
'hyphen',
|
||||
'period',
|
||||
'slash',
|
||||
'zero',
|
||||
'one',
|
||||
'two',
|
||||
'three',
|
||||
'four',
|
||||
'five',
|
||||
'six',
|
||||
'seven',
|
||||
'eight',
|
||||
'nine',
|
||||
'colon',
|
||||
'semicolon',
|
||||
'less',
|
||||
'equal',
|
||||
'greater',
|
||||
'question',
|
||||
'at',
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z',
|
||||
'bracketleft',
|
||||
'backslash',
|
||||
'bracketright',
|
||||
'asciicircum',
|
||||
'underscore',
|
||||
'quoteleft',
|
||||
'a',
|
||||
'b',
|
||||
'c',
|
||||
'd',
|
||||
'e',
|
||||
'f',
|
||||
'g',
|
||||
'h',
|
||||
'i',
|
||||
'j',
|
||||
'k',
|
||||
'l',
|
||||
'm',
|
||||
'n',
|
||||
'o',
|
||||
'p',
|
||||
'q',
|
||||
'r',
|
||||
's',
|
||||
't',
|
||||
'u',
|
||||
'v',
|
||||
'w',
|
||||
'x',
|
||||
'y',
|
||||
'z',
|
||||
'braceleft',
|
||||
'bar',
|
||||
'braceright',
|
||||
'asciitilde',
|
||||
'exclamdown',
|
||||
'cent',
|
||||
'sterling',
|
||||
'fraction',
|
||||
'yen',
|
||||
'florin',
|
||||
'section',
|
||||
'currency',
|
||||
'quotesingle',
|
||||
'quotedblleft',
|
||||
'guillemotleft',
|
||||
'guilsinglleft',
|
||||
'guilsinglright',
|
||||
'fi',
|
||||
'fl',
|
||||
'endash',
|
||||
'dagger',
|
||||
'daggerdbl',
|
||||
'periodcentered',
|
||||
'paragraph',
|
||||
'bullet',
|
||||
'quotesinglbase',
|
||||
'quotedblbase',
|
||||
'quotedblright',
|
||||
'guillemotright',
|
||||
'ellipsis',
|
||||
'perthousand',
|
||||
'questiondown',
|
||||
'grave',
|
||||
'acute',
|
||||
'circumflex',
|
||||
'tilde',
|
||||
'macron',
|
||||
'breve',
|
||||
'dotaccent',
|
||||
'dieresis',
|
||||
'ring',
|
||||
'cedilla',
|
||||
'hungarumlaut',
|
||||
'ogonek',
|
||||
'caron',
|
||||
'emdash',
|
||||
'AE',
|
||||
'ordfeminine',
|
||||
'Lslash',
|
||||
'Oslash',
|
||||
'OE',
|
||||
'ordmasculine',
|
||||
'ae',
|
||||
'dotlessi',
|
||||
'lslash',
|
||||
'oslash',
|
||||
'oe',
|
||||
'germandbls',
|
||||
'onesuperior',
|
||||
'logicalnot',
|
||||
'mu',
|
||||
'trademark',
|
||||
'Eth',
|
||||
'onehalf',
|
||||
'plusminus',
|
||||
'Thorn',
|
||||
'onequarter',
|
||||
'divide',
|
||||
'brokenbar',
|
||||
'degree',
|
||||
'thorn',
|
||||
'threequarters',
|
||||
'twosuperior',
|
||||
'registered',
|
||||
'minus',
|
||||
'eth',
|
||||
'multiply',
|
||||
'threesuperior',
|
||||
'copyright',
|
||||
'Aacute',
|
||||
'Acircumflex',
|
||||
'Adieresis',
|
||||
'Agrave',
|
||||
'Aring',
|
||||
'Atilde',
|
||||
'Ccedilla',
|
||||
'Eacute',
|
||||
'Ecircumflex',
|
||||
'Edieresis',
|
||||
'Egrave',
|
||||
'Iacute',
|
||||
'Icircumflex',
|
||||
'Idieresis',
|
||||
'Igrave',
|
||||
'Ntilde',
|
||||
'Oacute',
|
||||
'Ocircumflex',
|
||||
'Odieresis',
|
||||
'Ograve',
|
||||
'Otilde',
|
||||
'Scaron',
|
||||
'Uacute',
|
||||
'Ucircumflex',
|
||||
'Udieresis',
|
||||
'Ugrave',
|
||||
'Yacute',
|
||||
'Ydieresis',
|
||||
'Zcaron',
|
||||
'aacute',
|
||||
'acircumflex',
|
||||
'adieresis',
|
||||
'agrave',
|
||||
'aring',
|
||||
'atilde',
|
||||
'ccedilla',
|
||||
'eacute',
|
||||
'ecircumflex',
|
||||
'edieresis',
|
||||
'egrave',
|
||||
'iacute',
|
||||
'icircumflex',
|
||||
'idieresis',
|
||||
'igrave',
|
||||
'ntilde',
|
||||
'oacute',
|
||||
'ocircumflex',
|
||||
'odieresis',
|
||||
'ograve',
|
||||
'otilde',
|
||||
'scaron',
|
||||
'uacute',
|
||||
'ucircumflex',
|
||||
'udieresis',
|
||||
'ugrave',
|
||||
'yacute',
|
||||
'ydieresis',
|
||||
'zcaron',
|
||||
'exclamsmall',
|
||||
'Hungarumlautsmall',
|
||||
'dollaroldstyle',
|
||||
'dollarsuperior',
|
||||
'ampersandsmall',
|
||||
'Acutesmall',
|
||||
'parenleftsuperior',
|
||||
'parenrightsuperior',
|
||||
'266 ff',
|
||||
'onedotenleader',
|
||||
'zerooldstyle',
|
||||
'oneoldstyle',
|
||||
'twooldstyle',
|
||||
'threeoldstyle',
|
||||
'fouroldstyle',
|
||||
'fiveoldstyle',
|
||||
'sixoldstyle',
|
||||
'sevenoldstyle',
|
||||
'eightoldstyle',
|
||||
'nineoldstyle',
|
||||
'commasuperior',
|
||||
'threequartersemdash',
|
||||
'periodsuperior',
|
||||
'questionsmall',
|
||||
'asuperior',
|
||||
'bsuperior',
|
||||
'centsuperior',
|
||||
'dsuperior',
|
||||
'esuperior',
|
||||
'isuperior',
|
||||
'lsuperior',
|
||||
'msuperior',
|
||||
'nsuperior',
|
||||
'osuperior',
|
||||
'rsuperior',
|
||||
'ssuperior',
|
||||
'tsuperior',
|
||||
'ff',
|
||||
'ffi',
|
||||
'ffl',
|
||||
'parenleftinferior',
|
||||
'parenrightinferior',
|
||||
'Circumflexsmall',
|
||||
'hyphensuperior',
|
||||
'Gravesmall',
|
||||
'Asmall',
|
||||
'Bsmall',
|
||||
'Csmall',
|
||||
'Dsmall',
|
||||
'Esmall',
|
||||
'Fsmall',
|
||||
'Gsmall',
|
||||
'Hsmall',
|
||||
'Ismall',
|
||||
'Jsmall',
|
||||
'Ksmall',
|
||||
'Lsmall',
|
||||
'Msmall',
|
||||
'Nsmall',
|
||||
'Osmall',
|
||||
'Psmall',
|
||||
'Qsmall',
|
||||
'Rsmall',
|
||||
'Ssmall',
|
||||
'Tsmall',
|
||||
'Usmall',
|
||||
'Vsmall',
|
||||
'Wsmall',
|
||||
'Xsmall',
|
||||
'Ysmall',
|
||||
'Zsmall',
|
||||
'colonmonetary',
|
||||
'onefitted',
|
||||
'rupiah',
|
||||
'Tildesmall',
|
||||
'exclamdownsmall',
|
||||
'centoldstyle',
|
||||
'Lslashsmall',
|
||||
'Scaronsmall',
|
||||
'Zcaronsmall',
|
||||
'Dieresissmall',
|
||||
'Brevesmall',
|
||||
'Caronsmall',
|
||||
'Dotaccentsmall',
|
||||
'Macronsmall',
|
||||
'figuredash',
|
||||
'hypheninferior',
|
||||
'Ogoneksmall',
|
||||
'Ringsmall',
|
||||
'Cedillasmall',
|
||||
'questiondownsmall',
|
||||
'oneeighth',
|
||||
'threeeighths',
|
||||
'fiveeighths',
|
||||
'seveneighths',
|
||||
'onethird',
|
||||
'twothirds',
|
||||
'zerosuperior',
|
||||
'foursuperior',
|
||||
'fivesuperior',
|
||||
'sixsuperior',
|
||||
'sevensuperior',
|
||||
'eightsuperior',
|
||||
'ninesuperior',
|
||||
'zeroinferior',
|
||||
'oneinferior',
|
||||
'twoinferior',
|
||||
'threeinferior',
|
||||
'fourinferior',
|
||||
'fiveinferior',
|
||||
'sixinferior',
|
||||
'seveninferior',
|
||||
'eightinferior',
|
||||
'nineinferior',
|
||||
'centinferior',
|
||||
'dollarinferior',
|
||||
'periodinferior',
|
||||
'commainferior',
|
||||
'Agravesmall',
|
||||
'Aacutesmall',
|
||||
'Acircumflexsmall',
|
||||
'Atildesmall',
|
||||
'Adieresissmall',
|
||||
'Aringsmall',
|
||||
'AEsmall',
|
||||
'Ccedillasmall',
|
||||
'Egravesmall',
|
||||
'Eacutesmall',
|
||||
'Ecircumflexsmall',
|
||||
'Edieresissmall',
|
||||
'Igravesmall',
|
||||
'Iacutesmall',
|
||||
'Icircumflexsmall',
|
||||
'Idieresissmall',
|
||||
'Ethsmall',
|
||||
'Ntildesmall',
|
||||
'Ogravesmall',
|
||||
'Oacutesmall',
|
||||
'Ocircumflexsmall',
|
||||
'Otildesmall',
|
||||
'Odieresissmall',
|
||||
'OEsmall',
|
||||
'Oslashsmall',
|
||||
'Ugravesmall',
|
||||
'Uacutesmall',
|
||||
'Ucircumflexsmall',
|
||||
'Udieresissmall',
|
||||
'Yacutesmall',
|
||||
'Thornsmall',
|
||||
'Ydieresissmall',
|
||||
'001.000',
|
||||
'001.001',
|
||||
'001.002',
|
||||
'001.003',
|
||||
'Black',
|
||||
'Bold',
|
||||
'Book',
|
||||
'Light',
|
||||
'Medium',
|
||||
'Regular',
|
||||
'Roman',
|
||||
'Semibold'
|
||||
];
|
||||
|
||||
var CFFEncodingMap = {
|
||||
'0': '-reserved-',
|
||||
'1': 'hstem',
|
||||
|
@ -20,17 +20,27 @@ function readCharset(aStream, aCharstrings) {
|
||||
var charset = {};
|
||||
|
||||
var format = aStream.getByte();
|
||||
var count = aCharstrings.length - 1;
|
||||
if (format == 0) {
|
||||
charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);
|
||||
|
||||
var count = aCharstrings.length - 1;
|
||||
for (var i = 1; i < count + 1; i++) {
|
||||
var sid = aStream.getByte() << 8 | aStream.getByte();
|
||||
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
|
||||
//log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
|
||||
}
|
||||
} else if (format == 1) {
|
||||
error('Charset Range are not supported');
|
||||
for (var i = 1; i < count + 1; i++) {
|
||||
var first = aStream.getByte();
|
||||
first = (first << 8) | aStream.getByte();
|
||||
var numLeft = aStream.getByte();
|
||||
for (var j = 0; j <= numLeft; j++) {
|
||||
var sid = first++;
|
||||
if (CFFStrings[sid] == 'three')
|
||||
log(aCharstrings[j]);
|
||||
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[j]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error('Invalid charset format');
|
||||
}
|
||||
@ -44,6 +54,9 @@ function readCharset(aStream, aCharstrings) {
|
||||
* chapter 3.1.
|
||||
*/
|
||||
function readCharstringEncoding(aString) {
|
||||
if (!aString)
|
||||
return '';
|
||||
|
||||
var charstringTokens = [];
|
||||
|
||||
var count = aString.length;
|
||||
@ -71,9 +84,9 @@ function readCharstringEncoding(aString) {
|
||||
} else if (value < 247) {
|
||||
token = parseInt(value, 10) - 139;
|
||||
} else if (value < 251) {
|
||||
token = ((value - 247) * 256) + aString[i++] + 108;
|
||||
token = (value - 247) * 256 + aString[i++] + 108;
|
||||
} else if (value < 255) {
|
||||
token = -((value - 251) * 256) - aString[i++] - 108;
|
||||
token = -(value - 251) * 256 - aString[i++] - 108;
|
||||
} else {// value == 255
|
||||
token = aString[i++] << 24 | aString[i++] << 16 |
|
||||
aString[i++] << 8 | aString[i];
|
||||
@ -146,9 +159,9 @@ function readFontDictData(aString, aMap) {
|
||||
} else if (value <= 246) {
|
||||
token = parseInt(value, 10) - 139;
|
||||
} else if (value <= 250) {
|
||||
token = ((value - 247) * 256) + aString[i++] + 108;
|
||||
token = (value - 247) * 256 + aString[i++] + 108;
|
||||
} else if (value <= 254) {
|
||||
token = -((value - 251) * 256) - aString[i++] - 108;
|
||||
token = -(value - 251) * 256 - aString[i++] - 108;
|
||||
} else if (value == 255) {
|
||||
error('255 is not a valid DICT command');
|
||||
}
|
||||
@ -199,7 +212,7 @@ function readFontIndexData(aStream, aIsByte) {
|
||||
for (var i = 0; i < count + 1; i++)
|
||||
offsets.push(getNextOffset());
|
||||
|
||||
log('Found ' + count + ' objects at offsets :' +
|
||||
dump('Found ' + count + ' objects at offsets :' +
|
||||
offsets + ' (offsize: ' + offsize + ')');
|
||||
|
||||
// Now extract the objects
|
||||
@ -285,23 +298,20 @@ var Type2Parser = function(aFilePath) {
|
||||
font.set('hdrSize', aStream.getByte());
|
||||
font.set('offsize', aStream.getByte());
|
||||
|
||||
// Move the cursor after the header
|
||||
aStream.skip(font.get('hdrSize') - aStream.pos);
|
||||
|
||||
// Read the NAME Index
|
||||
dump('Reading Index: Names');
|
||||
font.set('Names', readFontIndexData(aStream));
|
||||
log('Names: ' + font.get('Names'));
|
||||
dump('Names: ' + font.get('Names'));
|
||||
|
||||
// Read the Top Dict Index
|
||||
dump('Reading Index: TopDict');
|
||||
var topDict = readFontIndexData(aStream, true);
|
||||
log('TopDict: ' + topDict);
|
||||
dump('TopDict: ' + topDict);
|
||||
|
||||
// Read the String Index
|
||||
dump('Reading Index: Strings');
|
||||
var strings = readFontIndexData(aStream);
|
||||
log('strings: ' + strings);
|
||||
dump('strings: ' + strings);
|
||||
|
||||
// Fill up the Strings dictionary with the new unique strings
|
||||
for (var i = 0; i < strings.length; i++)
|
||||
@ -321,7 +331,7 @@ var Type2Parser = function(aFilePath) {
|
||||
|
||||
// Reading Private Dict
|
||||
var priv = font.get('Private');
|
||||
log('Reading Private Dict (offset: ' + priv.offset +
|
||||
dump('Reading Private Dict (offset: ' + priv.offset +
|
||||
' size: ' + priv.size + ')');
|
||||
aStream.pos = priv.offset;
|
||||
|
||||
|
@ -119,6 +119,7 @@ span#info {
|
||||
margin-right:auto;
|
||||
line-height: 134px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.thumbnail:not([data-loaded]) {
|
||||
@ -195,16 +196,17 @@ span#info {
|
||||
canvas {
|
||||
margin: auto;
|
||||
display: block;
|
||||
box-shadow: 0px 4px 10px #000;
|
||||
-moz-box-shadow: 0px 4px 10px #000;
|
||||
-webkit-box-shadow: 0px 4px 10px #000;
|
||||
}
|
||||
|
||||
.page {
|
||||
width: 816px;
|
||||
height: 1056px;
|
||||
margin: 10px auto;
|
||||
position:relative;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-shadow: 0px 4px 10px #000;
|
||||
-moz-box-shadow: 0px 4px 10px #000;
|
||||
-webkit-box-shadow: 0px 4px 10px #000;
|
||||
}
|
||||
|
||||
.page > a {
|
||||
@ -271,3 +273,8 @@ canvas {
|
||||
page-break-after: always;
|
||||
}
|
||||
}
|
||||
|
||||
#loading {
|
||||
margin: 100px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
<script type="text/javascript" src="../crypto.js"></script>
|
||||
<script type="text/javascript" src="../glyphlist.js"></script>
|
||||
<script type="text/javascript" src="../metrics.js"></script>
|
||||
<script type="text/javascript" src="../charsets.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -89,7 +90,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="loading">Loading... 0%</div>
|
||||
<div id="viewer"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -58,9 +58,9 @@ var PDFView = {
|
||||
|
||||
var currentPage = this.pages[this.page - 1];
|
||||
var pageWidthScale = (window.innerWidth - kScrollbarPadding) /
|
||||
currentPage.width / kCssUnits;
|
||||
currentPage.width / kCssUnits;
|
||||
var pageHeightScale = (window.innerHeight - kScrollbarPadding) /
|
||||
currentPage.height / kCssUnits;
|
||||
currentPage.height / kCssUnits;
|
||||
if ('page-width' == value)
|
||||
this.setScale(pageWidthScale, resetAutoSettings);
|
||||
if ('page-height' == value)
|
||||
@ -111,12 +111,14 @@ var PDFView = {
|
||||
xhr.open('GET', url);
|
||||
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
||||
xhr.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
|
||||
xhr.onprogress = PDFView.progressLevel;
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4 && xhr.status === xhr.expected) {
|
||||
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
||||
xhr.responseArrayBuffer || xhr.response);
|
||||
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
PDFView.load(data, scale);
|
||||
}
|
||||
};
|
||||
@ -124,6 +126,11 @@ var PDFView = {
|
||||
xhr.send(null);
|
||||
},
|
||||
|
||||
progressLevel: function(evt) {
|
||||
var p = Math.round((evt.loaded / evt.total) * 100);
|
||||
document.getElementById('loading').innerHTML = 'Loading... ' + p + '%';
|
||||
},
|
||||
|
||||
navigateTo: function(dest) {
|
||||
if (typeof dest === 'string')
|
||||
dest = this.destinations[dest];
|
||||
@ -163,7 +170,7 @@ var PDFView = {
|
||||
var page = pdf.getPage(i);
|
||||
pages.push(new PageView(container, page, i, page.width, page.height,
|
||||
page.stats, this.navigateTo.bind(this)));
|
||||
thumbnails.push(new ThumbnailView(sidebar, pages[i - 1],
|
||||
thumbnails.push(new ThumbnailView(sidebar, page, i,
|
||||
page.width / page.height));
|
||||
var pageRef = page.ref;
|
||||
pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i;
|
||||
@ -230,13 +237,17 @@ var PDFView = {
|
||||
}
|
||||
};
|
||||
|
||||
var PageView = function(container, content, id, width, height,
|
||||
var PageView = function(container, content, id, pageWidth, pageHeight,
|
||||
stats, navigateTo) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.id = id;
|
||||
this.content = content;
|
||||
|
||||
var view = this.content.view;
|
||||
this.x = view.x;
|
||||
this.y = view.y;
|
||||
this.width = view.width;
|
||||
this.height = view.height;
|
||||
|
||||
var anchor = document.createElement('a');
|
||||
anchor.name = '' + this.id;
|
||||
|
||||
@ -265,11 +276,12 @@ var PageView = function(container, content, id, width, height,
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
var links = content.getLinks();
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
var link = document.createElement('a');
|
||||
link.style.left = Math.floor(links[i].x * scale) + 'px';
|
||||
link.style.top = Math.floor(links[i].y * scale) + 'px';
|
||||
link.style.left = (Math.floor(links[i].x - view.x) * scale) + 'px';
|
||||
link.style.top = (Math.floor(links[i].y - view.y) * scale) + 'px';
|
||||
link.style.width = Math.ceil(links[i].width * scale) + 'px';
|
||||
link.style.height = Math.ceil(links[i].height * scale) + 'px';
|
||||
link.href = links[i].url || '';
|
||||
@ -357,8 +369,9 @@ var PageView = function(container, content, id, width, height,
|
||||
canvas.id = 'page' + this.id;
|
||||
canvas.mozOpaque = true;
|
||||
|
||||
canvas.width = this.width * this.scale;
|
||||
canvas.height = this.height * this.scale;
|
||||
var scale = this.scale;
|
||||
canvas.width = pageWidth * scale;
|
||||
canvas.height = pageHeight * scale;
|
||||
div.appendChild(canvas);
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
@ -366,6 +379,7 @@ var PageView = function(container, content, id, width, height,
|
||||
ctx.fillStyle = 'rgb(255, 255, 255)';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
ctx.translate(-this.x * scale, -this.y * scale);
|
||||
|
||||
stats.begin = Date.now();
|
||||
this.content.startRendering(ctx, this.updateStats);
|
||||
@ -384,12 +398,12 @@ var PageView = function(container, content, id, width, height,
|
||||
};
|
||||
};
|
||||
|
||||
var ThumbnailView = function(container, page, pageRatio) {
|
||||
var ThumbnailView = function(container, page, id, pageRatio) {
|
||||
var anchor = document.createElement('a');
|
||||
anchor.href = '#' + page.id;
|
||||
anchor.href = '#' + id;
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.id = 'thumbnailContainer' + page.id;
|
||||
div.id = 'thumbnailContainer' + id;
|
||||
div.className = 'thumbnail';
|
||||
|
||||
anchor.appendChild(div);
|
||||
@ -400,7 +414,7 @@ var ThumbnailView = function(container, page, pageRatio) {
|
||||
return;
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = 'thumbnail' + page.id;
|
||||
canvas.id = 'thumbnail' + id;
|
||||
canvas.mozOpaque = true;
|
||||
|
||||
var maxThumbSize = 134;
|
||||
@ -418,7 +432,15 @@ var ThumbnailView = function(container, page, pageRatio) {
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
|
||||
page.content.startRendering(ctx, function() { });
|
||||
var view = page.view;
|
||||
var scaleX = (canvas.width / page.width);
|
||||
var scaleY = (canvas.height / page.height);
|
||||
ctx.translate(-view.x * scaleX, -view.y * scaleY);
|
||||
div.style.width = (view.width * scaleX) + 'px';
|
||||
div.style.height = (view.height * scaleY) + 'px';
|
||||
div.style.lineHeight = (view.height * scaleY) + 'px';
|
||||
|
||||
page.startRendering(ctx, function() { });
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user