Merge branch 'master' of https://github.com/andreasgal/pdf.js.git into links

This commit is contained in:
notmasteryet 2011-08-18 22:38:39 -05:00
commit 18172c1b4d
2 changed files with 187 additions and 34 deletions

View File

@ -1469,7 +1469,7 @@ var Type1Parser = function() {
var value = ''; var value = '';
var count = array.length; var count = array.length;
for (var i = 0; i < count; i++) { for (var i = 0; i < count; i++) {
value = parseInt(array[i]); value = array[i];
if (value < 32) { if (value < 32) {
var command = null; var command = null;
@ -1480,7 +1480,8 @@ var Type1Parser = function() {
if (escape == 16) { if (escape == 16) {
var index = charstring.pop(); var index = charstring.pop();
var argc = charstring.pop(); var argc = charstring.pop();
var data = charstring.pop(); for (var j = 0; j < argc; j++)
charstring.push('drop');
// If the flex mechanishm is not used in a font program, Adobe // If the flex mechanishm is not used in a font program, Adobe
// state that that entries 0, 1 and 2 can simply be replace by // state that that entries 0, 1 and 2 can simply be replace by
@ -1532,11 +1533,11 @@ var Type1Parser = function() {
value = command; value = command;
} else if (value <= 246) { } else if (value <= 246) {
value = parseInt(value) - 139; value = value - 139;
} else if (value <= 250) { } else if (value <= 250) {
value = ((value - 247) * 256) + parseInt(array[++i]) + 108; value = ((value - 247) * 256) + array[++i] + 108;
} else if (value <= 254) { } else if (value <= 254) {
value = -((value - 251) * 256) - parseInt(array[++i]) - 108; value = -((value - 251) * 256) - array[++i] - 108;
} else { } else {
value = (array[++i] & 0xff) << 24 | (array[++i] & 0xff) << 16 | value = (array[++i] & 0xff) << 24 | (array[++i] & 0xff) << 16 |
(array[++i] & 0xff) << 8 | (array[++i] & 0xff) << 0; (array[++i] & 0xff) << 8 | (array[++i] & 0xff) << 0;
@ -1598,6 +1599,17 @@ var Type1Parser = function() {
var c = ''; var c = '';
var count = eexecStr.length; var count = eexecStr.length;
for (var i = 0; i < count; i++) { for (var i = 0; i < count; i++) {
var getToken = function() {
while(i < count && (eexecStr[i] == ' ' || eexecStr[i] == '\n'))
++i;
var t = '';
while(i < count && !(eexecStr[i] == ' ' || eexecStr[i] == '\n'))
t += eexecStr[i++];
return t;
}
var c = eexecStr[i]; var c = eexecStr[i];
if ((glyphsSection || subrsSection) && c == 'R') { if ((glyphsSection || subrsSection) && c == 'R') {
@ -1627,7 +1639,25 @@ var Type1Parser = function() {
glyphsSection = true; glyphsSection = true;
break; break;
case '/Subrs': case '/Subrs':
subrsSection = true; ++i;
var num = parseInt(getToken());
getToken(); // read in 'array'
for (var j = 0; j < num; ++j) {
var t = getToken(); // read in 'dup'
if (t == 'ND')
break;
var index = parseInt(getToken());
if (index > j)
j = index;
var length = parseInt(getToken());
getToken(); // read in 'RD'
var data = eexec.slice(i + 1, i + 1 + length);
var encoded = decrypt(data, kCharStringsEncryptionKey, 4);
var str = decodeCharString(encoded);
i = i + 1 + length;
getToken(); //read in 'NP'
program.subrs[index] = str.charstring;
}
break; break;
case '/BlueValues': case '/BlueValues':
case '/OtherBlues': case '/OtherBlues':
@ -1909,8 +1939,13 @@ CFF.prototype = {
for (var i = 0; i < bias; i++) for (var i = 0; i < bias; i++)
type2Subrs.push([0x0B]); type2Subrs.push([0x0B]);
for (var i = 0; i < count; i++) for (var i = 0; i < count; i++) {
type2Subrs.push(this.flattenCharstring(type1Subrs[i], this.commandsMap)); var subr = type1Subrs[i];
if (!subr)
subr = [0x0B];
type2Subrs.push(this.flattenCharstring(subr, this.commandsMap));
}
return type2Subrs; return type2Subrs;
}, },
@ -1932,6 +1967,7 @@ CFF.prototype = {
'sub': [12, 11], 'sub': [12, 11],
'div': [12, 12], 'div': [12, 12],
'pop': [1, 12, 18], 'pop': [1, 12, 18],
'drop' : [12, 18],
'endchar': 14, 'endchar': 14,
'rmoveto': 21, 'rmoveto': 21,
'hmoveto': 22, 'hmoveto': 22,

169
pdf.js
View File

@ -806,6 +806,11 @@ var JpegStream = (function() {
// create DOM image // create DOM image
var img = new Image(); var img = new Image();
img.onload = (function() {
this.loaded = true;
if (this.onLoad)
this.onLoad();
}).bind(this);
img.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes)); img.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));
this.domImage = img; this.domImage = img;
} }
@ -822,6 +827,44 @@ var JpegStream = (function() {
return constructor; return constructor;
})(); })();
// Simple object to track the loading images
// Initialy for every that is in loading call imageLoading()
// and, when images onload is fired, call imageLoaded()
// When all images are loaded, the onLoad event is fired.
var ImagesLoader = (function() {
function constructor() {
this.loading = 0;
}
constructor.prototype = {
imageLoading: function() {
++this.loading;
},
imageLoaded: function() {
if (--this.loading == 0 && this.onLoad) {
this.onLoad();
delete this.onLoad;
}
},
bind: function(jpegStream) {
if (jpegStream.loaded)
return;
this.imageLoading();
jpegStream.onLoad = this.imageLoaded.bind(this);
},
notifyOnLoad: function(callback) {
if (this.loading == 0)
callback();
this.onLoad = callback;
}
};
return constructor;
})();
var DecryptStream = (function() { var DecryptStream = (function() {
function constructor(str, decrypt) { function constructor(str, decrypt) {
this.str = str; this.str = str;
@ -1990,7 +2033,7 @@ var LZWStream = (function() {
this.cachedData = 0; this.cachedData = 0;
this.bitsCached = 0; this.bitsCached = 0;
var maxLzwDictionarySize = 4097; var maxLzwDictionarySize = 4096;
var lzwState = { var lzwState = {
earlyChange: earlyChange, earlyChange: earlyChange,
codeLength: 9, codeLength: 9,
@ -2036,6 +2079,9 @@ var LZWStream = (function() {
var i, j, q; var i, j, q;
var lzwState = this.lzwState; var lzwState = this.lzwState;
if (!lzwState)
return; // eof was found
var earlyChange = lzwState.earlyChange; var earlyChange = lzwState.earlyChange;
var nextCode = lzwState.nextCode; var nextCode = lzwState.nextCode;
var dictionaryValues = lzwState.dictionaryValues; var dictionaryValues = lzwState.dictionaryValues;
@ -2073,6 +2119,7 @@ var LZWStream = (function() {
continue; continue;
} else { } else {
this.eof = true; this.eof = true;
delete this.lzwState;
break; break;
} }
@ -3123,6 +3170,7 @@ var Page = (function() {
create: Date.now(), create: Date.now(),
compile: 0.0, compile: 0.0,
fonts: 0.0, fonts: 0.0,
images: 0.0,
render: 0.0 render: 0.0
}; };
this.xref = xref; this.xref = xref;
@ -3200,25 +3248,33 @@ var Page = (function() {
var gfx = new CanvasGraphics(canvasCtx); var gfx = new CanvasGraphics(canvasCtx);
var fonts = []; var fonts = [];
var images = new ImagesLoader()
this.compile(gfx, fonts); this.compile(gfx, fonts, images);
stats.compile = Date.now(); stats.compile = Date.now();
var displayContinuation = function() {
// Always defer call to display() to work around bug in
// Firefox error reporting from XHR callbacks.
setTimeout(function() {
var exc = null;
try {
self.display(gfx);
stats.render = Date.now();
} catch (e) {
exc = e.toString();
}
continuation(exc);
});
};
var fontObjs = FontLoader.bind( var fontObjs = FontLoader.bind(
fonts, fonts,
function() { function() {
stats.fonts = Date.now(); stats.fonts = Date.now();
// Always defer call to display() to work around bug in images.notifyOnLoad(function() {
// Firefox error reporting from XHR callbacks. stats.images = Date.now();
setTimeout(function() { displayContinuation();
var exc = null;
try {
self.display(gfx);
stats.render = Date.now();
} catch (e) {
exc = e.toString();
}
continuation(exc);
}); });
}); });
@ -3227,7 +3283,7 @@ var Page = (function() {
}, },
compile: function(gfx, fonts) { compile: function(gfx, fonts, images) {
if (this.code) { if (this.code) {
// content was compiled // content was compiled
return; return;
@ -3239,14 +3295,14 @@ var Page = (function() {
if (!IsArray(this.content)) { if (!IsArray(this.content)) {
// content is not an array, shortcut // content is not an array, shortcut
content = xref.fetchIfRef(this.content); content = xref.fetchIfRef(this.content);
this.code = gfx.compile(content, xref, resources, fonts); this.code = gfx.compile(content, xref, resources, fonts, images);
return; return;
} }
// the content is an array, compiling all items // the content is an array, compiling all items
var i, n = this.content.length, compiledItems = []; var i, n = this.content.length, compiledItems = [];
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
content = xref.fetchIfRef(this.content[i]); content = xref.fetchIfRef(this.content[i]);
compiledItems.push(gfx.compile(content, xref, resources, fonts)); compiledItems.push(gfx.compile(content, xref, resources, fonts, images));
} }
// creating the function that executes all compiled items // creating the function that executes all compiled items
this.code = function(gfx) { this.code = function(gfx) {
@ -3836,7 +3892,7 @@ var PartialEvaluator = (function() {
}; };
constructor.prototype = { constructor.prototype = {
eval: function(stream, xref, resources, fonts) { eval: function(stream, xref, resources, fonts, images) {
resources = xref.fetchIfRef(resources) || new Dict(); resources = xref.fetchIfRef(resources) || new Dict();
var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict(); var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict();
var patterns = xref.fetchIfRef(resources.get('Pattern')) || new Dict(); var patterns = xref.fetchIfRef(resources.get('Pattern')) || new Dict();
@ -3881,8 +3937,10 @@ var PartialEvaluator = (function() {
if ('Form' == type.name) { if ('Form' == type.name) {
args[0].code = this.eval(xobj, xref, xobj.dict.get('Resources'), args[0].code = this.eval(xobj, xref, xobj.dict.get('Resources'),
fonts); fonts, images);
} }
if (xobj instanceof JpegStream)
images.bind(xobj); // monitoring image load
} }
} else if (cmd == 'Tf') { // eagerly collect all fonts } else if (cmd == 'Tf') { // eagerly collect all fonts
var fontRes = resources.get('Font'); var fontRes = resources.get('Font');
@ -4202,7 +4260,11 @@ var CanvasExtraState = (function() {
constructor.prototype = { constructor.prototype = {
clone: function canvasextra_clone() { clone: function canvasextra_clone() {
return Object.create(this); return Object.create(this);
} },
setCurrentPoint: function canvasextra_setCurrentPoint(x, y) {
this.x = x;
this.y = y;
},
}; };
return constructor; return constructor;
})(); })();
@ -4254,9 +4316,9 @@ var CanvasGraphics = (function() {
this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height); this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height);
}, },
compile: function(stream, xref, resources, fonts) { compile: function(stream, xref, resources, fonts, images) {
var pe = new PartialEvaluator(); var pe = new PartialEvaluator();
return pe.eval(stream, xref, resources, fonts); return pe.eval(stream, xref, resources, fonts, images);
}, },
execute: function(code, xref, resources) { execute: function(code, xref, resources) {
@ -4329,18 +4391,24 @@ var CanvasGraphics = (function() {
// Path // Path
moveTo: function(x, y) { moveTo: function(x, y) {
this.ctx.moveTo(x, y); this.ctx.moveTo(x, y);
this.current.setCurrentPoint(x, y);
}, },
lineTo: function(x, y) { lineTo: function(x, y) {
this.ctx.lineTo(x, y); this.ctx.lineTo(x, y);
this.current.setCurrentPoint(x, y);
}, },
curveTo: function(x1, y1, x2, y2, x3, y3) { curveTo: function(x1, y1, x2, y2, x3, y3) {
this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
this.current.setCurrentPoint(x3, y3);
}, },
curveTo2: function(x2, y2, x3, y3) { curveTo2: function(x2, y2, x3, y3) {
TODO("'v' operator: need current point in gfx context"); var current = this.current;
this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3);
current.setCurrentPoint(x3, y3);
}, },
curveTo3: function(x1, y1, x3, y3) { curveTo3: function(x1, y1, x3, y3) {
this.curveTo(x1, y1, x3, y3, x3, y3); this.curveTo(x1, y1, x3, y3, x3, y3);
this.current.setCurrentPoint(x3, y3);
}, },
closePath: function() { closePath: function() {
this.ctx.closePath(); this.ctx.closePath();
@ -5757,7 +5825,7 @@ var PDFFunction = (function() {
if (!typeFn) if (!typeFn)
error('Unknown type of function'); error('Unknown type of function');
typeFn.call(this, fn, dict); typeFn.call(this, fn, dict, xref);
}; };
constructor.prototype = { constructor.prototype = {
@ -5902,9 +5970,58 @@ var PDFFunction = (function() {
return out; return out;
} }
}, },
constructStiched: function() { constructStiched: function(fn, dict, xref) {
TODO('unhandled type of function'); var domain = dict.get('Domain');
this.func = function() { return [255, 105, 180]; } var range = dict.get('Range');
if (!domain)
error('No domain');
var inputSize = domain.length / 2;
if (inputSize != 1)
error('Bad domain for stiched function');
var fnRefs = dict.get('Functions');
var fns = [];
for (var i = 0, ii = fnRefs.length; i < ii; ++i)
fns.push(new PDFFunction(xref, xref.fetchIfRef(fnRefs[i])));
var bounds = dict.get('Bounds');
var encode = dict.get('Encode');
this.func = function(args) {
var clip = function(v, min, max) {
if (v > max)
v = max;
else if (v < min)
v = min;
return v;
}
// clip to domain
var v = clip(args[0], domain[0], domain[1]);
// calulate which bound the value is in
for (var i = 0, ii = bounds.length; i < ii; ++i) {
if (v < bounds[i])
break;
}
// encode value into domain of function
var dmin = domain[0];
if (i > 0)
dmin = bounds[i - 1];
var dmax = domain[1];
if (i < bounds.length)
dmax = bounds[i];
var rmin = encode[2 * i];
var rmax = encode[2 * i + 1];
var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
// call the appropropriate function
return fns[i].func([v2]);
}
}, },
constructPostScript: function() { constructPostScript: function() {
TODO('unhandled type of function'); TODO('unhandled type of function');