update to master

This commit is contained in:
= 2011-09-23 17:49:23 -07:00
commit 8006faf74e
9 changed files with 163 additions and 85 deletions

View File

@ -3,7 +3,7 @@
'use strict'; 'use strict';
var ARCFourCipher = (function() { var ARCFourCipher = (function aRCFourCipher() {
function constructor(key) { function constructor(key) {
this.a = 0; this.a = 0;
this.b = 0; this.b = 0;
@ -21,7 +21,7 @@ var ARCFourCipher = (function() {
} }
constructor.prototype = { constructor.prototype = {
encryptBlock: function(data) { encryptBlock: function aRCFourCipherEncryptBlock(data) {
var i, n = data.length, tmp, tmp2; var i, n = data.length, tmp, tmp2;
var a = this.a, b = this.b, s = this.s; var a = this.a, b = this.b, s = this.s;
var output = new Uint8Array(n); var output = new Uint8Array(n);
@ -45,7 +45,7 @@ var ARCFourCipher = (function() {
return constructor; return constructor;
})(); })();
var md5 = (function() { var md5 = (function md5Md5() {
var r = new Uint8Array([ var r = new Uint8Array([
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
@ -129,12 +129,12 @@ var md5 = (function() {
return hash; return hash;
})(); })();
var NullCipher = (function() { var NullCipher = (function nullCipher() {
function constructor() { function constructor() {
} }
constructor.prototype = { constructor.prototype = {
decryptBlock: function(data) { decryptBlock: function nullCipherDecryptBlock(data) {
return data; return data;
} }
}; };
@ -142,7 +142,7 @@ var NullCipher = (function() {
return constructor; return constructor;
})(); })();
var AES128Cipher = (function() { var AES128Cipher = (function aES128Cipher() {
var rcon = new Uint8Array([ var rcon = new Uint8Array([
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
@ -372,7 +372,7 @@ var AES128Cipher = (function() {
} }
constructor.prototype = { constructor.prototype = {
decryptBlock: function(data) { decryptBlock: function aES128CipherDecryptBlock(data) {
var i, sourceLength = data.length; var i, sourceLength = data.length;
var buffer = this.buffer, bufferLength = this.bufferPosition; var buffer = this.buffer, bufferLength = this.bufferPosition;
// waiting for IV values -- they are at the start of the stream // waiting for IV values -- they are at the start of the stream
@ -395,19 +395,21 @@ var AES128Cipher = (function() {
return constructor; return constructor;
})(); })();
var CipherTransform = (function() { var CipherTransform = (function cipherTransform() {
function constructor(stringCipherConstructor, streamCipherConstructor) { function constructor(stringCipherConstructor, streamCipherConstructor) {
this.stringCipherConstructor = stringCipherConstructor; this.stringCipherConstructor = stringCipherConstructor;
this.streamCipherConstructor = streamCipherConstructor; this.streamCipherConstructor = streamCipherConstructor;
} }
constructor.prototype = { constructor.prototype = {
createStream: function(stream) { createStream: function cipherTransformCreateStream(stream) {
var cipher = new this.streamCipherConstructor(); var cipher = new this.streamCipherConstructor();
return new DecryptStream(stream, function(data) { return new DecryptStream(stream,
function cipherTransformDecryptStream(data) {
return cipher.decryptBlock(data); return cipher.decryptBlock(data);
}); }
);
}, },
decryptString: function(s) { decryptString: function cipherTransformDecryptString(s) {
var cipher = new this.stringCipherConstructor(); var cipher = new this.stringCipherConstructor();
var data = stringToBytes(s); var data = stringToBytes(s);
data = cipher.decryptBlock(data); data = cipher.decryptBlock(data);
@ -417,7 +419,7 @@ var CipherTransform = (function() {
return constructor; return constructor;
})(); })();
var CipherTransformFactory = (function() { var CipherTransformFactory = (function cipherTransformFactory() {
function prepareKeyData(fileId, password, ownerPassword, userPassword, function prepareKeyData(fileId, password, ownerPassword, userPassword,
flags, revision, keyLength, encryptMetadata) { flags, revision, keyLength, encryptMetadata) {
var defaultPasswordBytes = new Uint8Array([ var defaultPasswordBytes = new Uint8Array([
@ -552,18 +554,18 @@ var CipherTransformFactory = (function() {
if (cryptFilter != null) if (cryptFilter != null)
cfm = cryptFilter.get('CFM'); cfm = cryptFilter.get('CFM');
if (!cfm || cfm.name == 'None') { if (!cfm || cfm.name == 'None') {
return function() { return function cipherTransformFactoryBuildCipherConstructorNone() {
return new NullCipher(); return new NullCipher();
}; };
} }
if ('V2' == cfm.name) { if ('V2' == cfm.name) {
return function() { return function cipherTransformFactoryBuildCipherConstructorV2() {
return new ARCFourCipher( return new ARCFourCipher(
buildObjectKey(num, gen, key, false)); buildObjectKey(num, gen, key, false));
}; };
} }
if ('AESV2' == cfm.name) { if ('AESV2' == cfm.name) {
return function() { return function cipherTransformFactoryBuildCipherConstructorAESV2() {
return new AES128Cipher( return new AES128Cipher(
buildObjectKey(num, gen, key, true)); buildObjectKey(num, gen, key, true));
}; };
@ -573,7 +575,8 @@ var CipherTransformFactory = (function() {
} }
constructor.prototype = { constructor.prototype = {
createCipherTransform: function(num, gen) { createCipherTransform: function buildCipherCreateCipherTransform(num,
gen) {
if (this.algorithm == 4) { if (this.algorithm == 4) {
return new CipherTransform( return new CipherTransform(
buildCipherConstructor(this.cf, this.stmf, buildCipherConstructor(this.cf, this.stmf,
@ -583,7 +586,7 @@ var CipherTransformFactory = (function() {
} }
// algorithms 1 and 2 // algorithms 1 and 2
var key = buildObjectKey(num, gen, this.encryptionKey, false); var key = buildObjectKey(num, gen, this.encryptionKey, false);
var cipherConstructor = function() { var cipherConstructor = function buildCipherCipherConstructor() {
return new ARCFourCipher(key); return new ARCFourCipher(key);
}; };
return new CipherTransform(cipherConstructor, cipherConstructor); return new CipherTransform(cipherConstructor, cipherConstructor);

View File

@ -124,7 +124,7 @@ var serifFonts = {
var FontLoader = { var FontLoader = {
listeningForFontLoad: false, listeningForFontLoad: false,
bind: function(fonts, callback) { bind: function fontLoaderBind(fonts, callback) {
function checkFontsLoaded() { function checkFontsLoaded() {
for (var i = 0; i < objs.length; i++) { for (var i = 0; i < objs.length; i++) {
var fontObj = objs[i]; var fontObj = objs[i];
@ -180,7 +180,8 @@ var FontLoader = {
// loaded in a subdocument. It's expected that the load of |rules| // loaded in a subdocument. It's expected that the load of |rules|
// 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(rules, names, objs) { prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names,
objs) {
/** 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
@ -219,7 +220,7 @@ var FontLoader = {
if (!this.listeningForFontLoad) { if (!this.listeningForFontLoad) {
window.addEventListener( window.addEventListener(
'message', 'message',
function(e) { function fontLoaderMessage(e) {
var fontNames = JSON.parse(e.data); var fontNames = JSON.parse(e.data);
for (var i = 0; i < objs.length; ++i) { for (var i = 0; i < objs.length; ++i) {
var font = objs[i]; var font = objs[i];
@ -247,7 +248,7 @@ var FontLoader = {
fontNamesArray += '"' + names[i] + '", '; fontNamesArray += '"' + names[i] + '", ';
} }
src += ' var fontNames=[' + fontNamesArray + '];\n'; src += ' var fontNames=[' + fontNamesArray + '];\n';
src += ' window.onload = function () {\n'; src += ' window.onload = function fontLoaderOnload() {\n';
src += ' parent.postMessage(JSON.stringify(fontNames), "*");\n'; src += ' parent.postMessage(JSON.stringify(fontNames), "*");\n';
src += ' }'; src += ' }';
src += '</script></head><body>'; src += '</script></head><body>';
@ -599,7 +600,7 @@ var Font = (function Font() {
var length = glyphs.length; var length = glyphs.length;
for (var n = 0; n < length; ++n) for (var n = 0; n < length; ++n)
codes.push({ unicode: glyphs[n].unicode, code: 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; return a.unicode - b.unicode;
}); });
@ -928,7 +929,7 @@ var Font = (function Font() {
} }
// Check that table are sorted by platformID then encodingID, // Check that table are sorted by platformID then encodingID,
records.sort(function(a, b) { records.sort(function fontReplaceCMapTableSort(a, b) {
return ((a.platformID << 16) + a.encodingID) - return ((a.platformID << 16) + a.encodingID) -
((b.platformID << 16) + b.encodingID); ((b.platformID << 16) + b.encodingID);
}); });
@ -1061,11 +1062,11 @@ var Font = (function Font() {
var itemSize, itemDecode, itemEncode; var itemSize, itemDecode, itemEncode;
if (isGlyphLocationsLong) { if (isGlyphLocationsLong) {
itemSize = 4; itemSize = 4;
itemDecode = function(data, offset) { itemDecode = function fontItemDecodeLong(data, offset) {
return (data[offset] << 24) | (data[offset + 1] << 16) | return (data[offset] << 24) | (data[offset + 1] << 16) |
(data[offset + 2] << 8) | data[offset + 3]; (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] = (value >>> 24) & 0xFF;
data[offset + 1] = (value >> 16) & 0xFF; data[offset + 1] = (value >> 16) & 0xFF;
data[offset + 2] = (value >> 8) & 0xFF; data[offset + 2] = (value >> 8) & 0xFF;
@ -1073,10 +1074,10 @@ var Font = (function Font() {
}; };
} else { } else {
itemSize = 2; itemSize = 2;
itemDecode = function(data, offset) { itemDecode = function fontItemDecode(data, offset) {
return (data[offset] << 9) | (data[offset + 1] << 1); 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] = (value >> 9) & 0xFF;
data[offset + 1] = (value >> 1) & 0xFF; data[offset + 1] = (value >> 1) & 0xFF;
}; };
@ -1323,7 +1324,7 @@ var Font = (function Font() {
'cmap': createCMapTable(charstrings.slice(), font.glyphIds), 'cmap': createCMapTable(charstrings.slice(), font.glyphIds),
// Font header // Font header
'head': (function() { 'head': (function fontFieldsHead() {
return stringToArray( return stringToArray(
'\x00\x01\x00\x00' + // Version number '\x00\x01\x00\x00' + // Version number
'\x00\x00\x10\x00' + // fontRevision '\x00\x00\x10\x00' + // fontRevision
@ -1345,7 +1346,7 @@ var Font = (function Font() {
})(), })(),
// Horizontal header // Horizontal header
'hhea': (function() { 'hhea': (function fontFieldsHhea() {
return stringToArray( return stringToArray(
'\x00\x01\x00\x00' + // Version number '\x00\x01\x00\x00' + // Version number
string16(properties.ascent) + // Typographic Ascent string16(properties.ascent) + // Typographic Ascent
@ -1368,7 +1369,7 @@ var Font = (function Font() {
})(), })(),
// Horizontal metrics // Horizontal metrics
'hmtx': (function() { 'hmtx': (function fontFieldsHmtx() {
var hmtx = '\x00\x00\x00\x00'; // Fake .notdef var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
for (var i = 0; i < charstrings.length; i++) { for (var i = 0; i < charstrings.length; i++) {
hmtx += string16(charstrings[i].width) + string16(0); hmtx += string16(charstrings[i].width) + string16(0);
@ -1377,7 +1378,7 @@ var Font = (function Font() {
})(), })(),
// Maximum profile // Maximum profile
'maxp': (function() { 'maxp': (function fontFieldsMaxp() {
return stringToArray( return stringToArray(
'\x00\x00\x50\x00' + // Version number '\x00\x00\x50\x00' + // Version number
string16(charstrings.length + 1)); // Num of glyphs string16(charstrings.length + 1)); // Num of glyphs
@ -1505,7 +1506,7 @@ var Font = (function Font() {
* program. Some of its logic depends on the Type2 charstrings * program. Some of its logic depends on the Type2 charstrings
* structure. * structure.
*/ */
var Type1Parser = function() { var Type1Parser = function type1Parser() {
/* /*
* Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence * Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence
* of Plaintext Bytes. The function took a key as a parameter which can be * of Plaintext Bytes. The function took a key as a parameter which can be
@ -2033,7 +2034,7 @@ var CFFStrings = [
var type1Parser = new Type1Parser(); 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 // Get the data block containing glyphs and subrs informations
var headerBlock = file.getBytes(properties.length1); var headerBlock = file.getBytes(properties.length1);
type1Parser.extractFontHeader(headerBlock, properties); type1Parser.extractFontHeader(headerBlock, properties);
@ -2233,7 +2234,7 @@ CFF.prototype = {
'names': this.createCFFIndexHeader([name]), 'names': this.createCFFIndexHeader([name]),
'topDict': (function topDict(self) { 'topDict': (function topDict(self) {
return function() { return function cFFWrapTopDict() {
var header = '\x00\x01\x01\x01'; var header = '\x00\x01\x01\x01';
var dict = var dict =
'\xf8\x1b\x00' + // version '\xf8\x1b\x00' + // version
@ -2310,7 +2311,7 @@ CFF.prototype = {
'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs), 'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs),
true), true),
'private': (function(self) { 'private': (function cFFWrapPrivate(self) {
var data = var data =
'\x8b\x14' + // defaultWidth '\x8b\x14' + // defaultWidth
'\x8b\x15'; // nominalWidth '\x8b\x15'; // nominalWidth
@ -2363,7 +2364,7 @@ CFF.prototype = {
} }
}; };
var Type2CFF = (function() { var Type2CFF = (function type2CFF() {
// TODO: replace parsing code with the Type2Parser in font_utils.js // TODO: replace parsing code with the Type2Parser in font_utils.js
function constructor(file, properties) { function constructor(file, properties) {
var bytes = file.getBytes(); var bytes = file.getBytes();
@ -2503,7 +2504,9 @@ var Type2CFF = (function() {
} }
// sort the array by the unicode value // sort the array by the unicode value
charstrings.sort(function(a, b) {return a.unicode - b.unicode}); charstrings.sort(function type2CFFGetCharStringsSort(a, b) {
return a.unicode - b.unicode;
});
return charstrings; return charstrings;
}, },

69
pdf.js
View File

@ -3321,8 +3321,35 @@ var Page = (function pagePage() {
}, },
get mediaBox() { get mediaBox() {
var obj = this.inheritPageProp('MediaBox'); var obj = this.inheritPageProp('MediaBox');
return shadow(this, 'mediaBox', // Reset invalid media box to letter size.
((IsArray(obj) && obj.length == 4) ? obj : null)); if (!IsArray(obj) || obj.length === 4)
obj = [0, 0, 612, 792];
return shadow(this, 'mediaBox', obj);
},
get view() {
var obj = this.inheritPageProp('CropBox');
var view = {
x: 0,
y: 0,
width: this.width,
height: this.height
};
if (IsArray(obj) && obj.length == 4) {
var rotate = this.rotate;
if (rotate == 0 || rotate == 180) {
view.x = obj[0];
view.y = obj[1];
view.width = obj[2] - view.x;
view.height = obj[3] - view.y;
} else {
view.x = obj[1];
view.y = obj[0];
view.width = obj[3] - view.x;
view.height = obj[2] - view.y;
}
}
return shadow(this, 'cropBox', view);
}, },
get annotations() { get annotations() {
return shadow(this, 'annotations', this.inheritPageProp('Annots')); return shadow(this, 'annotations', this.inheritPageProp('Annots'));
@ -5097,7 +5124,8 @@ var CanvasGraphics = (function canvasGraphics() {
ctx.scale(1 / textHScale, 1); ctx.scale(1 / textHScale, 1);
var width = 0; var width = 0;
for (var i = 0; i < glyphs.length; i++) { var glyphsLength = glyphs.length;
for (var i = 0; i < glyphsLength; ++i) {
var glyph = glyphs[i]; var glyph = glyphs[i];
if (glyph === null) { if (glyph === null) {
// word break // word break
@ -5106,34 +5134,35 @@ var CanvasGraphics = (function canvasGraphics() {
} }
var unicode = glyph.unicode; var unicode = glyph.unicode;
var char = unicode >= 0x10000 ? var char = (unicode >= 0x10000) ?
String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10), String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode); 0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode);
var charWidth = glyph.width * fontSize * 0.001;
charWidth += charSpacing;
ctx.fillText(char, width, 0); ctx.fillText(char, width, 0);
width += charWidth; width += glyph.width * fontSize * 0.001 + charSpacing;
} }
current.x += width; current.x += width;
this.ctx.restore(); this.ctx.restore();
}, },
showSpacedText: function canvasGraphicsShowSpacedText(arr) { showSpacedText: function canvasGraphicsShowSpacedText(arr) {
for (var i = 0; i < arr.length; ++i) { var ctx = this.ctx;
var current = this.current;
var fontSize = current.fontSize;
var textHScale = current.textHScale;
var arrLength = arr.length;
for (var i = 0; i < arrLength; ++i) {
var e = arr[i]; var e = arr[i];
if (IsNum(e)) { if (IsNum(e)) {
if (this.ctx.$addCurrentX) { if (ctx.$addCurrentX) {
this.ctx.$addCurrentX(-e * 0.001 * this.current.fontSize); ctx.$addCurrentX(-e * 0.001 * fontSize);
} else { } else {
this.current.x -= e * 0.001 * this.current.fontSize * current.x -= e * 0.001 * fontSize * textHScale;
this.current.textHScale;
} }
} else if (IsString(e)) { } else if (IsString(e)) {
this.showText(e); this.showText(e);
} else { } else {
malformed('TJ array element ' + e + " isn't string or num"); malformed('TJ array element ' + e + ' is not string or num');
} }
} }
}, },
@ -5495,7 +5524,7 @@ var ColorSpace = (function colorSpaceColorSpace() {
constructor.parse = function colorspace_parse(cs, xref, res) { constructor.parse = function colorspace_parse(cs, xref, res) {
if (IsName(cs)) { if (IsName(cs)) {
var colorSpaces = res.get('ColorSpace'); var colorSpaces = xref.fetchIfRef(res.get('ColorSpace'));
if (IsDict(colorSpaces)) { if (IsDict(colorSpaces)) {
var refcs = colorSpaces.get(cs.name); var refcs = colorSpaces.get(cs.name);
if (refcs) if (refcs)
@ -6503,7 +6532,7 @@ var PDFFunction = (function pDFFunction() {
return out; return out;
}; };
}, },
constructStiched: function(fn, dict, xref) { constructStiched: function pDFFunctionConstructStiched(fn, dict, xref) {
var domain = dict.get('Domain'); var domain = dict.get('Domain');
var range = dict.get('Range'); var range = dict.get('Range');
@ -6522,8 +6551,8 @@ var PDFFunction = (function pDFFunction() {
var bounds = dict.get('Bounds'); var bounds = dict.get('Bounds');
var encode = dict.get('Encode'); var encode = dict.get('Encode');
this.func = function(args) { this.func = function pDFFunctionConstructStichedFunc(args) {
var clip = function(v, min, max) { var clip = function pDFFunctionConstructStichedFuncClip(v, min, max) {
if (v > max) if (v > max)
v = max; v = max;
else if (v < min) else if (v < min)
@ -6556,9 +6585,9 @@ var PDFFunction = (function pDFFunction() {
return fns[i].func([v2]); return fns[i].func([v2]);
}; };
}, },
constructPostScript: function() { constructPostScript: function pDFFunctionConstructPostScript() {
TODO('unhandled type of function'); TODO('unhandled type of function');
this.func = function() { this.func = function pDFFunctionConstructPostScriptFunc() {
return [255, 105, 180]; return [255, 105, 180];
}; };
} }

View File

@ -39,7 +39,7 @@ function load() {
var r = new XMLHttpRequest(); var r = new XMLHttpRequest();
r.open('GET', manifestFile, false); r.open('GET', manifestFile, false);
r.onreadystatechange = function(e) { r.onreadystatechange = function loadOnreadystatechange(e) {
if (r.readyState == 4) { if (r.readyState == 4) {
log('done\n'); log('done\n');
manifest = JSON.parse(r.responseText); manifest = JSON.parse(r.responseText);
@ -50,7 +50,21 @@ function load() {
r.send(null); 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() { function nextTask() {
cleanup();
if (currentTaskIdx == manifest.length) { if (currentTaskIdx == manifest.length) {
return done(); return done();
} }
@ -62,7 +76,7 @@ function nextTask() {
var r = new XMLHttpRequest(); var r = new XMLHttpRequest();
r.open('GET', task.file); r.open('GET', task.file);
r.mozResponseType = r.responseType = 'arraybuffer'; r.mozResponseType = r.responseType = 'arraybuffer';
r.onreadystatechange = function() { r.onreadystatechange = function nextTaskOnreadystatechange() {
var failure; var failure;
if (r.readyState == 4) { if (r.readyState == 4) {
var data = r.mozResponseArrayBuffer || r.mozResponse || var data = r.mozResponseArrayBuffer || r.mozResponse ||
@ -85,11 +99,15 @@ function isLastPage(task) {
return (task.pageNum > task.pdfDoc.numPages); return (task.pageNum > task.pdfDoc.numPages);
} }
function canvasToDataURL() {
return canvas.toDataURL('image/png');
}
function nextPage(task, loadError) { function nextPage(task, loadError) {
var failure = loadError || ''; var failure = loadError || '';
if (!task.pdfDoc) { if (!task.pdfDoc) {
sendTaskResult(canvas.toDataURL('image/png'), task, failure); sendTaskResult(canvasToDataURL(), task, failure);
log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n');
++currentTaskIdx; ++currentTaskIdx;
nextTask(); nextTask();
@ -126,7 +144,7 @@ function nextPage(task, loadError) {
page.startRendering( page.startRendering(
ctx, ctx,
function(e) { function nextPageStartRendering(e) {
snapshotCurrentPage(task, (!failure && e) ? snapshotCurrentPage(task, (!failure && e) ?
('render : ' + e) : failure); ('render : ' + e) : failure);
} }
@ -146,13 +164,13 @@ function nextPage(task, loadError) {
function snapshotCurrentPage(task, failure) { function snapshotCurrentPage(task, failure) {
log('done, snapshotting... '); log('done, snapshotting... ');
sendTaskResult(canvas.toDataURL('image/png'), task, failure); sendTaskResult(canvasToDataURL(), task, failure);
log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n'); log('done' + (failure ? ' (failed !: ' + failure + ')' : '') + '\n');
// Set up the next request // Set up the next request
var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0; var backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0;
setTimeout( setTimeout(
function() { function snapshotCurrentPageSetTimeout() {
++task.pageNum; ++task.pageNum;
nextPage(task); nextPage(task);
}, },
@ -201,7 +219,7 @@ function sendTaskResult(snapshot, task, failure) {
// (The POST URI is ignored atm.) // (The POST URI is ignored atm.)
r.open('POST', '/submit_task_results', true); r.open('POST', '/submit_task_results', true);
r.setRequestHeader('Content-Type', 'application/json'); r.setRequestHeader('Content-Type', 'application/json');
r.onreadystatechange = function(e) { r.onreadystatechange = function sendTaskResultOnreadystatechange(e) {
if (r.readyState == 4) { if (r.readyState == 4) {
inFlightRequests--; inFlightRequests--;
} }

View File

@ -0,0 +1 @@
https://issues.apache.org/jira/secure/attachment/12421789/survey.pdf

View File

@ -146,6 +146,12 @@
"rounds": 1, "rounds": 1,
"type": "load" "type": "load"
}, },
{ "id": "hudsonsurvey",
"file": "pdfs/hudsonsurvey.pdf",
"link": true,
"rounds": 1,
"type": "load"
},
{ "id": "extgstate", { "id": "extgstate",
"file": "pdfs/extgstate.pdf", "file": "pdfs/extgstate.pdf",
"link": false, "link": false,

View File

@ -14,6 +14,7 @@
<body onload="load();"> <body onload="load();">
<pre style="width:800; height:800; overflow: scroll;"id="stdout"></pre> <pre style="width:800; height:800; overflow: scroll;"id="stdout"></pre>
<p>Inflight requests: <span id="inFlightCount"></span></p> <p>Inflight requests: <span id="inFlightCount"></span></p>
<div id="content-end"><!-- cleanup() guard --></div>
</body> </body>
</html> </html>

View File

@ -119,6 +119,7 @@ span#info {
margin-right:auto; margin-right:auto;
line-height: 134px; line-height: 134px;
text-align: center; text-align: center;
overflow: hidden;
} }
.thumbnail:not([data-loaded]) { .thumbnail:not([data-loaded]) {
@ -195,9 +196,6 @@ span#info {
canvas { canvas {
margin: auto; margin: auto;
display: block; display: block;
box-shadow: 0px 4px 10px #000;
-moz-box-shadow: 0px 4px 10px #000;
-webkit-box-shadow: 0px 4px 10px #000;
} }
.page { .page {
@ -205,6 +203,10 @@ canvas {
height: 1056px; height: 1056px;
margin: 10px auto; margin: 10px auto;
position: relative; position: relative;
overflow: hidden;
box-shadow: 0px 4px 10px #000;
-moz-box-shadow: 0px 4px 10px #000;
-webkit-box-shadow: 0px 4px 10px #000;
} }
.page > a { .page > a {

View File

@ -170,7 +170,7 @@ var PDFView = {
var page = pdf.getPage(i); var page = pdf.getPage(i);
pages.push(new PageView(container, page, i, page.width, page.height, pages.push(new PageView(container, page, i, page.width, page.height,
page.stats, this.navigateTo.bind(this))); page.stats, this.navigateTo.bind(this)));
thumbnails.push(new ThumbnailView(sidebar, pages[i - 1], thumbnails.push(new ThumbnailView(sidebar, page, i,
page.width / page.height)); page.width / page.height));
var pageRef = page.ref; var pageRef = page.ref;
pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i; pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i;
@ -237,13 +237,17 @@ var PDFView = {
} }
}; };
var PageView = function(container, content, id, width, height, var PageView = function(container, content, id, pageWidth, pageHeight,
stats, navigateTo) { stats, navigateTo) {
this.width = width;
this.height = height;
this.id = id; this.id = id;
this.content = content; this.content = content;
var view = this.content.view;
this.x = view.x;
this.y = view.y;
this.width = view.width;
this.height = view.height;
var anchor = document.createElement('a'); var anchor = document.createElement('a');
anchor.name = '' + this.id; anchor.name = '' + this.id;
@ -272,11 +276,12 @@ var PageView = function(container, content, id, width, height,
return false; return false;
}; };
} }
var links = content.getLinks(); var links = content.getLinks();
for (var i = 0; i < links.length; i++) { for (var i = 0; i < links.length; i++) {
var link = document.createElement('a'); var link = document.createElement('a');
link.style.left = Math.floor(links[i].x * scale) + 'px'; link.style.left = (Math.floor(links[i].x - view.x) * scale) + 'px';
link.style.top = Math.floor(links[i].y * scale) + 'px'; link.style.top = (Math.floor(links[i].y - view.y) * scale) + 'px';
link.style.width = Math.ceil(links[i].width * scale) + 'px'; link.style.width = Math.ceil(links[i].width * scale) + 'px';
link.style.height = Math.ceil(links[i].height * scale) + 'px'; link.style.height = Math.ceil(links[i].height * scale) + 'px';
link.href = links[i].url || ''; link.href = links[i].url || '';
@ -364,8 +369,9 @@ var PageView = function(container, content, id, width, height,
canvas.id = 'page' + this.id; canvas.id = 'page' + this.id;
canvas.mozOpaque = true; canvas.mozOpaque = true;
canvas.width = this.width * this.scale; var scale = this.scale;
canvas.height = this.height * this.scale; canvas.width = pageWidth * scale;
canvas.height = pageHeight * scale;
div.appendChild(canvas); div.appendChild(canvas);
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
@ -373,6 +379,7 @@ var PageView = function(container, content, id, width, height,
ctx.fillStyle = 'rgb(255, 255, 255)'; ctx.fillStyle = 'rgb(255, 255, 255)';
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore(); ctx.restore();
ctx.translate(-this.x * scale, -this.y * scale);
stats.begin = Date.now(); stats.begin = Date.now();
this.content.startRendering(ctx, this.updateStats); this.content.startRendering(ctx, this.updateStats);
@ -391,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'); var anchor = document.createElement('a');
anchor.href = '#' + page.id; anchor.href = '#' + id;
var div = document.createElement('div'); var div = document.createElement('div');
div.id = 'thumbnailContainer' + page.id; div.id = 'thumbnailContainer' + id;
div.className = 'thumbnail'; div.className = 'thumbnail';
anchor.appendChild(div); anchor.appendChild(div);
@ -407,7 +414,7 @@ var ThumbnailView = function(container, page, pageRatio) {
return; return;
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
canvas.id = 'thumbnail' + page.id; canvas.id = 'thumbnail' + id;
canvas.mozOpaque = true; canvas.mozOpaque = true;
var maxThumbSize = 134; var maxThumbSize = 134;
@ -425,7 +432,15 @@ var ThumbnailView = function(container, page, pageRatio) {
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore(); ctx.restore();
page.content.startRendering(ctx, function() { }); var view = page.view;
var scaleX = (canvas.width / page.width);
var scaleY = (canvas.height / page.height);
ctx.translate(-view.x * scaleX, -view.y * scaleY);
div.style.width = (view.width * scaleX) + 'px';
div.style.height = (view.height * scaleY) + 'px';
div.style.lineHeight = (view.height * scaleY) + 'px';
page.startRendering(ctx, function() { });
}; };
}; };