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

This commit is contained in:
notmasteryet 2011-07-20 23:08:28 -05:00
commit cecd26d56d
3 changed files with 78 additions and 93 deletions

View File

@ -21,47 +21,18 @@ var kMaxWaitForFontFace = 1000;
* http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65 * http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65
*/ */
var Fonts = (function Fonts() { var FontMeasure = (function FontMeasure() {
var kScalePrecision = 40; var kScalePrecision = 40;
var fonts = [];
if (!isWorker) { var ctx = document.createElement('canvas').getContext('2d');
var ctx = document.createElement('canvas').getContext('2d'); ctx.scale(1 / kScalePrecision, 1);
ctx.scale(1 / kScalePrecision, 1);
}
var fontCount = 0;
function FontInfo(name, data, properties) {
this.name = name;
this.data = data;
this.properties = properties;
this.id = fontCount++;
this.loading = true;
this.sizes = [];
}
var current; var current;
var measureCache; var measureCache;
return { return {
registerFont: function fonts_registerFont(fontName, data, properties) { setActive: function fonts_setActive(font, size) {
var font = new FontInfo(fontName, data, properties); if (current = font) {
fonts.push(font);
return font.id;
},
blacklistFont: function fonts_blacklistFont(fontName) {
var id = registerFont(fontName, null, {});
markLoaded(fontName);
return id;
},
lookupById: function fonts_lookupById(id) {
return fonts[id];
},
setActive: function fonts_setActive(fontName, fontObj, size) {
// |current| can be null is fontName is a built-in font
// (e.g. "sans-serif")
if (fontObj && (current = fonts[fontObj.id])) {
var sizes = current.sizes; var sizes = current.sizes;
if (!(measureCache = sizes[size])) if (!(measureCache = sizes[size]))
measureCache = sizes[size] = Object.create(null); measureCache = sizes[size] = Object.create(null);
@ -69,7 +40,7 @@ var Fonts = (function Fonts() {
measureCache = null measureCache = null
} }
ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; ctx.font = (size * kScalePrecision) + 'px "' + font.loadedName + '"';
}, },
measureText: function fonts_measureText(text) { measureText: function fonts_measureText(text) {
var width; var width;
@ -88,9 +59,9 @@ var FontLoader = {
bind: function(fonts, callback) { bind: function(fonts, callback) {
function checkFontsLoaded() { function checkFontsLoaded() {
for (var i = 0; i < allIds.length; i++) { for (var i = 0; i < objs.length; i++) {
var id = allIds[i]; var fontObj = objs[i];
if (Fonts.lookupById(id).loading) { if (fontObj.loading) {
return false; return false;
} }
} }
@ -102,18 +73,17 @@ var FontLoader = {
return true; return true;
} }
var allIds = []; var rules = [], names = [], objs = [];
var rules = [], names = [], ids = [];
for (var i = 0; i < fonts.length; i++) { for (var i = 0; i < fonts.length; i++) {
var font = fonts[i]; var font = fonts[i];
var obj = new Font(font.name, font.file, font.properties); var obj = new Font(font.name, font.file, font.properties);
font.fontDict.fontObj = obj; obj.loading = true;
allIds.push(obj.id); objs.push(obj);
var str = ''; var str = '';
var data = Fonts.lookupById(obj.id).data; var data = obj.data;
var length = data.length; var length = data.length;
for (var j = 0; j < length; j++) for (var j = 0; j < length; j++)
str += String.fromCharCode(data[j]); str += String.fromCharCode(data[j]);
@ -122,13 +92,12 @@ var FontLoader = {
if (rule) { if (rule) {
rules.push(rule); rules.push(rule);
names.push(obj.loadedName); names.push(obj.loadedName);
ids.push(obj.id);
} }
} }
this.listeningForFontLoad = false; this.listeningForFontLoad = false;
if (!isWorker && rules.length) { if (!isWorker && rules.length) {
FontLoader.prepareFontLoadEvent(rules, names, ids); FontLoader.prepareFontLoadEvent(rules, names, objs);
} }
if (!checkFontsLoaded()) { if (!checkFontsLoaded()) {
@ -136,14 +105,14 @@ var FontLoader = {
'pdfjsFontLoad', checkFontsLoaded, false); 'pdfjsFontLoad', checkFontsLoaded, false);
} }
return; return objs;
}, },
// Set things up so that at least one pdfjsFontLoad event is // Set things up so that at least one pdfjsFontLoad event is
// dispatched when all the @font-face |rules| for |names| have been // dispatched when all the @font-face |rules| for |names| have been
// 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, ids) { prepareFontLoadEvent: function(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
@ -184,8 +153,8 @@ var FontLoader = {
'message', 'message',
function(e) { function(e) {
var fontNames = JSON.parse(e.data); var fontNames = JSON.parse(e.data);
for (var i = 0; i < fontNames.length; ++i) { for (var i = 0; i < objs.length; ++i) {
var font = Fonts.lookupById(fontNames[i].substring(7) | 0); var font = objs[i];
font.loading = false; font.loading = false;
} }
var evt = document.createEvent('Events'); var evt = document.createEvent('Events');
@ -377,12 +346,12 @@ var Font = (function() {
this.name = name; this.name = name;
this.textMatrix = properties.textMatrix || IDENTITY_MATRIX; this.textMatrix = properties.textMatrix || IDENTITY_MATRIX;
this.encoding = properties.encoding; this.encoding = properties.encoding;
this.sizes = [];
// If the font is to be ignored, register it like an already loaded font // If the font is to be ignored, register it like an already loaded font
// to avoid the cost of waiting for it be be loaded by the platform. // to avoid the cost of waiting for it be be loaded by the platform.
if (properties.ignore) { if (properties.ignore) {
this.id = Fonts.blacklistFont(name); this.loadedName = 'Arial';
this.loadedName = 'pdfFont' + this.id;
return; return;
} }
@ -412,11 +381,15 @@ var Font = (function() {
} }
this.data = data; this.data = data;
this.type = properties.type; this.type = properties.type;
this.id = Fonts.registerFont(name, data, properties); this.loadedName = getUniqueName();
this.loadedName = 'pdfFont' + this.id;
this.compositeFont = properties.compositeFont; this.compositeFont = properties.compositeFont;
}; };
var numFonts = 0;
function getUniqueName() {
return 'pdfFont' + numFonts++;
}
function stringToArray(str) { function stringToArray(str) {
var array = []; var array = [];
for (var i = 0; i < str.length; ++i) for (var i = 0; i < str.length; ++i)

87
pdf.js
View File

@ -19,6 +19,7 @@ function warn(msg) {
} }
function error(msg) { function error(msg) {
log(backtrace());
throw new Error(msg); throw new Error(msg);
} }
@ -43,6 +44,16 @@ function assertWellFormed(cond, msg) {
malformed(msg); malformed(msg);
} }
function backtrace() {
var stackStr;
try {
throw new Error();
} catch(e) {
stackStr = e.stack;
};
return stackStr.split('\n').slice(1).join('\n');
}
function shadow(obj, prop, value) { function shadow(obj, prop, value) {
Object.defineProperty(obj, prop, { value: value, enumerable: true, configurable: true, writable: false }); Object.defineProperty(obj, prop, { value: value, enumerable: true, configurable: true, writable: false });
return value; return value;
@ -2959,7 +2970,7 @@ var Page = (function() {
return shadow(this, 'mediaBox', return shadow(this, 'mediaBox',
((IsArray(obj) && obj.length == 4) ? obj : null)); ((IsArray(obj) && obj.length == 4) ? obj : null));
}, },
startRendering: function(canvasCtx, continuation) { startRendering: function(canvasCtx, continuation, onerror) {
var self = this; var self = this;
var stats = self.stats; var stats = self.stats;
stats.compile = stats.fonts = stats.render = 0; stats.compile = stats.fonts = stats.render = 0;
@ -2970,18 +2981,26 @@ var Page = (function() {
this.compile(gfx, fonts); this.compile(gfx, fonts);
stats.compile = Date.now(); stats.compile = Date.now();
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 // Always defer call to display() to work around bug in
// Firefox error reporting from XHR callbacks. // Firefox error reporting from XHR callbacks.
setTimeout(function () { setTimeout(function () {
self.display(gfx); var exc = null;
stats.render = Date.now(); try {
continuation(); self.display(gfx);
stats.render = Date.now();
} catch (e) {
exc = e.toString();
}
continuation(exc);
}); });
}); });
for (var i = 0, ii = fonts.length; i < ii; ++i)
fonts[i].fontDict.fontObj = fontObjs[i];
}, },
@ -3544,23 +3563,9 @@ var PartialEvaluator = (function() {
eval: function(stream, xref, resources, fonts) { eval: function(stream, xref, resources, fonts) {
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 parser = new Parser(new Lexer(stream), false); var parser = new Parser(new Lexer(stream), false);
var objpool = []; var args = [], argsArray = [], fnArray = [], obj;
function emitArg(arg) {
if (typeof arg == 'object' || typeof arg == 'string') {
var index = objpool.length;
objpool[index] = arg;
return 'objpool[' + index + ']';
}
return arg;
}
var src = '';
var args = [];
var obj;
while (!IsEOF(obj = parser.getObj())) { while (!IsEOF(obj = parser.getObj())) {
if (IsCmd(obj)) { if (IsCmd(obj)) {
var cmd = obj.cmd; var cmd = obj.cmd;
@ -3582,10 +3587,7 @@ var PartialEvaluator = (function() {
); );
if ('Form' == type.name) { if ('Form' == type.name) {
args[0].code = this.eval(xobj, args[0].code = this.eval(xobj, xref, xobj.dict.get('Resources'), fonts);
xref,
xobj.dict.get('Resources'),
fonts);
} }
} }
} else if (cmd == 'Tf') { // eagerly collect all fonts } else if (cmd == 'Tf') { // eagerly collect all fonts
@ -3605,21 +3607,19 @@ var PartialEvaluator = (function() {
} }
} }
src += 'this.'; fnArray.push(fn);
src += fn; argsArray.push(args);
src += '('; args = [];
src += args.map(emitArg).join(',');
src += ');\n';
args.length = 0;
} else { } else {
assertWellFormed(args.length <= 33, 'Too many arguments'); assertWellFormed(args.length <= 33, 'Too many arguments');
args.push(obj); args.push(obj);
} }
} }
var fn = Function('objpool', src); return function(gfx) {
return function(gfx) { fn.call(gfx, objpool); }; for(var i = 0, length = argsArray.length; i < length; i++)
gfx[fnArray[i]].apply(gfx, argsArray[i]);
}
}, },
translateFont: function(fontDict, xref, resources) { translateFont: function(fontDict, xref, resources) {
@ -3638,7 +3638,12 @@ var PartialEvaluator = (function() {
if (!df) if (!df)
return null; return null;
compositeFont = true; compositeFont = true;
descendant = xref.fetch(df[0]);
if (IsRef(df)) {
df = xref.fetch(df);
}
descendant = xref.fetch(IsRef(df) ? df : df[0]);
subType = descendant.get('Subtype'); subType = descendant.get('Subtype');
fd = descendant.get('FontDescriptor'); fd = descendant.get('FontDescriptor');
} else { } else {
@ -4090,7 +4095,7 @@ var CanvasGraphics = (function() {
this.ctx.$setFont(fontName, size); this.ctx.$setFont(fontName, size);
} else { } else {
this.ctx.font = size + 'px "' + fontName + '"'; this.ctx.font = size + 'px "' + fontName + '"';
Fonts.setActive(fontName, fontObj, size); FontMeasure.setActive(fontObj, size);
} }
}, },
setTextRenderingMode: function(mode) { setTextRenderingMode: function(mode) {
@ -4142,7 +4147,7 @@ var CanvasGraphics = (function() {
text = font.charsToUnicode(text); text = font.charsToUnicode(text);
} }
ctx.fillText(text, 0, 0); ctx.fillText(text, 0, 0);
current.x += Fonts.measureText(text); current.x += FontMeasure.measureText(text);
} }
this.ctx.restore(); this.ctx.restore();
@ -4853,10 +4858,10 @@ var ColorSpace = (function() {
case 'Lab': case 'Lab':
case 'DeviceN': case 'DeviceN':
default: default:
error("unrecognized color space object '" + mode + "'"); error("unimplemented color space object '" + mode + "'");
} }
} else { } else {
error('unrecognized color space object'); error('unrecognized color space object: "'+ cs +"'");
} }
}; };
@ -5130,6 +5135,10 @@ var PDFImage = (function() {
this.bpc = bitsPerComponent; this.bpc = bitsPerComponent;
var colorSpace = dict.get('ColorSpace', 'CS'); var colorSpace = dict.get('ColorSpace', 'CS');
if (!colorSpace) {
TODO('JPX images (which don"t require color spaces');
colorSpace = new Name('DeviceRGB');
}
this.colorSpace = ColorSpace.parse(colorSpace, xref, res); this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
this.numComps = this.colorSpace.numComps; this.numComps = this.colorSpace.numComps;

View File

@ -111,7 +111,10 @@ function nextPage(task, loadError) {
page.startRendering( page.startRendering(
ctx, ctx,
function() { snapshotCurrentPage(page, task, failure); }); function(e) {
snapshotCurrentPage(page, task,
(!failure && e) ? ('render: '+ e) : failure);
});
} catch(e) { } catch(e) {
failure = 'page setup: '+ e.toString(); failure = 'page setup: '+ e.toString();
} }