}
var FontLoader = {
- listeningForFontLoad: false,
+ fontLoadData: {},
+ fonts: {},
bind: function(fonts, callback) {
- function checkFontsLoaded() {
- for (var i = 0; i < objs.length; i++) {
- var fontObj = objs[i];
- if (fontObj.loading) {
- return false;
- }
- }
-
- document.documentElement.removeEventListener(
- 'pdfjsFontLoad', checkFontsLoaded, false);
-
- callback(objs);
- return true;
- }
-
+ console.log("requesting fonts", fonts[0].properties.loadedName, fonts[0].name);
+
var rules = [], names = [], objs = [];
for (var i = 0; i < fonts.length; i++) {
if (rule) {
rules.push(rule);
names.push(obj.loadedName);
+ this.fonts[obj.loadedName] = obj;
+ this.fontLoadData[obj.loadedName] = obj;
}
}
}
- this.listeningForFontLoad = false;
- if (!isWorker && rules.length) {
- FontLoader.prepareFontLoadEvent(rules, names, objs);
- }
-
- if (!checkFontsLoaded()) {
- document.documentElement.addEventListener(
- 'pdfjsFontLoad', checkFontsLoaded, false);
+ if (rules.length) {
+ this.fontsLoading += rules.length;
+ FontLoader.prepareFontLoadEvent(rules, names);
}
return objs;
},
+
+ postFontLoadEvent: function(names) {
+ for (var i = 0; i < names.length; i++) {
+ var name = names[i];
+ Objects.resolve(name, this.fontLoadData[name]);
+ }
+ },
+
// Set things up so that at least one pdfjsFontLoad event is
// dispatched when all the @font-face |rules| for |names| have been
// 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(rules, names, callback) {
/** 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
div.innerHTML = html;
document.body.appendChild(div);
- if (!this.listeningForFontLoad) {
- window.addEventListener(
- 'message',
- function(e) {
- var fontNames = JSON.parse(e.data);
- for (var i = 0; i < objs.length; ++i) {
- var font = objs[i];
- font.loading = false;
- }
- var evt = document.createEvent('Events');
- evt.initEvent('pdfjsFontLoad', true, false);
- document.documentElement.dispatchEvent(evt);
- },
- false);
- this.listeningForFontLoad = true;
- }
-
// XXX we should have a time-out here too, and maybe fire
// pdfjsFontLoadFailed?
var src = '<!DOCTYPE HTML><html><head>';
}
};
+if (!isWorker) {
+ window.addEventListener(
+ 'message',
+ function(e) {
+ FontLoader.postFontLoadEvent(JSON.parse(e.data));
+ }.bind(this),
+ false);
+}
+
+
var UnicodeRanges = [
{ 'begin': 0x0000, 'end': 0x007F }, // Basic Latin
{ 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement
} catch (e) {
exc = e.toString();
continuation(exc);
+ throw e;
}
});
};
- this.ensureFonts(fonts, function() {
+ // this.ensureFonts(fonts, function() {
displayContinuation();
- });
+ // });
},
- getIRQueue: function(handler, fonts) {
+ getIRQueue: function(handler) {
if (this.IRQueue) {
// content was compiled
return this.IRQueue;
var pe = this.pe = new PartialEvaluator();
var IRQueue = {};
- return this.IRQueue = pe.getIRQueue(content, xref, resources, IRQueue, handler, fonts, "p" + this.pageNumber + "_");
+ return this.IRQueue = pe.getIRQueue(content, xref, resources, IRQueue, handler, "p" + this.pageNumber + "_");
},
ensureFonts: function(fonts, callback) {
};
constructor.prototype = {
- getIRQueue: function(stream, xref, resources, queue, handler, fonts, uniquePrefix) {
+ getIRQueue: function(stream, xref, resources, queue, handler, uniquePrefix) {
+
+ function insertDependency(depList) {
+ fnArray.push("dependency");
+ argsArray.push(depList);
+ }
+
function buildPaintImageXObject(image, inline) {
var dict = image.dict;
var w = dict.get('Width', 'W');
handler.send("obj", [objId, "JpegStream", image.getIR()]);
// Add the dependency on the image object.
- fnArray.push("dependency");
- argsArray.push([ objId ]);
-
+ insertDependency([objId]);
+
// The normal fn.
fn = 'paintJpegXObject';
args = [ objId, w, h ];
// TODO: Add dependency here.
// Create an IR of the pattern code.
var codeIR = this.getIRQueue(pattern, xref,
- dict.get('Resources'), {}, handler, fonts, uniquePrefix);
+ dict.get('Resources'), {}, handler, uniquePrefix);
args = TilingPattern.getIR(codeIR, dict, args);
}
// This adds the IRQueue of the xObj to the current queue.
this.getIRQueue(xobj, xref, xobj.dict.get('Resources'), queue,
- handler, fonts, uniquePrefix);
+ handler, uniquePrefix);
fn = "paintFormXObjectEnd";
assertWellFormed(IsDict(font));
if (!font.translated) {
font.translated = this.translateFont(font, xref, resources);
- if (fonts && font.translated) {
+ if (font.translated) {
// keep track of each font we translated so the caller can
// load them asynchronously before calling display on a page
- fonts.push(font.translated);
-
var loadedName = uniquePrefix + "font_" + (FontLoadedCounter++);
font.translated.properties.loadedName = loadedName;
FontsMap[loadedName] = font;
+
+ handler.send("obj", [
+ loadedName,
+ "Font",
+ font.translated.name,
+ font.translated.file,
+ font.translated.properties
+ ]);
+
+ // Ensure the font is ready before the font is set
+ // and later on used for drawing.
+ insertDependency([loadedName]);
}
}
args[0].name = font.translated.properties.loadedName;
var depObjId = deps[n];
var promise;
if (!Objects[depObjId]) {
- promise = Objects[depObjId] = new Promise();
+ promise = Objects[depObjId] = new Promise(depObjId);
} else {
promise = Objects[depObjId];
}
// If the promise isn't resolved yet, add the continueCallback
// to the promise and bail out.
if (!promise.isResolved) {
+ console.log("depending on obj", depObjId);
promise.then(continueCallback);
return i;
}
setFont: function(fontRef, size) {
// Lookup the fontObj using fontRef only.
var fontRefName = fontRef.name;
- var fontObj = FontsMap[fontRefName].fontObj;
+ var fontObj = Objects.get(fontRefName);
if (!fontObj) {
throw "Can't find font for " + fontRefName;
}
var name = fontObj.loadedName;
+ console.log("setFont", name);
if (!name) {
// TODO: fontDescriptor is not available, fallback to default font
name = 'sans-serif';
var Objects = {
resolve: function(objId, data) {
// In case there is a promise already on this object, just resolve it.
- if (Objects[objId] instanceof Promise) {
+ if (Objects[objId]) {
Objects[objId].resolve(data);
} else {
- Objects[objId] = new Promise(data);
+ Objects[objId] = new Promise(objId, data);
}
+ },
+
+ get: function(objId) {
+ var obj = Objects[objId];
+ if (!obj || !obj.isResolved) {
+ throw "Requesting object that isn't resolved yet";
+ }
+ return obj.data;
}
};
var Promise = (function() {
- function Promise(data) {
+ function Promise(name, data) {
+ this.name = name;
// If you build a promise and pass in some data it's already resolved.
if (data != null) {
this.isResolved = true;
Promise.prototype = {
resolve: function(data) {
+ console.log("resolve", this.name);
+
if (this.isResolved) {
throw "A Promise can be resolved only once";
}
var pageNum = data.pageNum;
var page = this.pageCache[pageNum];
- // Add necessary shape back to fonts.
- var fonts = data.fonts;
- for (var i = 0; i < fonts.length; i++) {
- var font = fonts[i];
-
- // Some fonts don't have a file, e.g. the build in ones like Arial.
- if (font.file) {
- var fontFileDict = new Dict();
- fontFileDict.map = font.file.dict.map;
-
- var fontFile = new Stream(font.file.bytes, font.file.start,
- font.file.end - font.file.start, fontFileDict);
-
- // Check if this is a FlateStream. Otherwise just use the created
- // Stream one. This makes complex_ttf_font.pdf work.
- var cmf = font.file.bytes[0];
- if ((cmf & 0x0f) == 0x08) {
- font.file = new FlateStream(fontFile);
- } else {
- font.file = fontFile;
- }
- }
- }
page.startRenderingFromIRQueue(data.IRQueue, data.fonts);
}, this);
var IR = data[2];
new JpegStreamIR(objId, IR);
break;
+ case "Font":
+ var name = data[2];
+ var file = data[3];
+ var properties = data[4];
+
+ console.log("got new font", name);
+
+ var font = {
+ name: name,
+ file: file,
+ properties: properties
+ };
+
+ // Some fonts don't have a file, e.g. the build in ones like Arial.
+ if (file) {
+ var fontFileDict = new Dict();
+ fontFileDict.map = file.dict.map;
+
+ var fontFile = new Stream(file.bytes, file.start,
+ file.end - file.start, fontFileDict);
+
+ // Check if this is a FlateStream. Otherwise just use the created
+ // Stream one. This makes complex_ttf_font.pdf work.
+ var cmf = file.bytes[0];
+ if ((cmf & 0x0f) == 0x08) {
+ font.file = new FlateStream(fontFile);
+ } else {
+ font.file = fontFile;
+ }
+ }
+
+ FontLoader.bind(
+ [ font ],
+ function(fontObjs) {
+ var fontObj = fontObjs[0];
+ Objects.resolve(objId, fontObj);
+ }
+ );
+ break;
default:
throw "Got unkown object type " + objType;
}
// The following code does quite the same as Page.prototype.startRendering,
// but stops at one point and sends the result back to the main thread.
var gfx = new CanvasGraphics(null);
- var fonts = [];
var start = Date.now();
// Pre compile the pdf page and fetch the fonts/images.
- var IRQueue = page.getIRQueue(handler, fonts);
+ var IRQueue = page.getIRQueue(handler);
console.log("page=%d - getIRQueue: time=%dms, len=%d", pageNum, Date.now() - start, IRQueue.fnArray.length);
- // Extract the minimum of font data that is required to build all required
- // font stuff on the main thread.
- var fontsMin = [];
- for (var i = 0; i < fonts.length; i++) {
- var font = fonts[i];
-
- fontsMin.push({
- name: font.name,
- file: font.file,
- properties: font.properties
- });
- }
if (false /* show used commands */) {
var cmdMap = {};
handler.send("page", {
pageNum: pageNum,
- fonts: fontsMin,
IRQueue: IRQueue,
});
}, this);