Merge branch 'master' of https://github.com/andreasgal/pdf.js.git into aes-crypto
This commit is contained in:
commit
cecd26d56d
75
fonts.js
75
fonts.js
@ -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)
|
||||||
|
81
pdf.js
81
pdf.js
@ -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 () {
|
||||||
|
var exc = null;
|
||||||
|
try {
|
||||||
self.display(gfx);
|
self.display(gfx);
|
||||||
stats.render = Date.now();
|
stats.render = Date.now();
|
||||||
continuation();
|
} 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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user