})();
var FontLoader = {
- bind: function(fonts) {
- var ready = true;
+ bind: function(fonts, callback) {
- var worker = (typeof window == "undefined");
-
+ function checkFontsLoaded() {
+ for (var i = 0; i < fonts.length; i++) {
+ var font = fonts[i];
+ if (Fonts.lookup(font.name).loading) {
+ return false;
+ }
+ }
+
+ document.documentElement.removeEventListener(
+ "pdfjsFontLoad", checkFontsLoaded, false);
+
+ callback();
+ return true;
+ }
+ var rules = [ ], names = [ ];
for (var i = 0; i < fonts.length; i++) {
var font = fonts[i];
- if (Fonts.lookup(font.name)) {
- ready = ready && !Fonts.lookup(font.name).loading;
- continue;
+ if (!Fonts.lookup(font.name)) {
+ var obj = new Font(font.name, font.file, font.properties);
+
+ var str = "";
+ var data = Fonts.lookup(font.name).data;
+ var length = data.length;
+ for (var j = 0; j < length; j++)
+ str += String.fromCharCode(data[j]);
+
- var rule = worker ? obj.bindWorker(str) : obj.bindDOM(str);
++ var rule = isWorker ? obj.bindWorker(str) : obj.bindDOM(str);
+ if (rule) {
+ rules.push(rule);
+ names.push(font.name);
+ }
}
+ }
- if (!worker && rules.length) {
- ready = false;
++ if (!isWorker && rules.length) {
+ FontLoader.prepareFontLoadEvent(rules, names);
+ }
- var obj = new Font(font.name, font.file, font.properties);
+ if (!checkFontsLoaded()) {
+ document.documentElement.addEventListener(
+ "pdfjsFontLoad", checkFontsLoaded, false);
+ }
- var str = "";
- var data = Fonts.lookup(font.name).data;
- var length = data.length;
- for (var j = 0; j < length; j++)
- str += String.fromCharCode(data[j]);
+ return;
+ },
+ // 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) {
+ /** 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
+ // ready. This code will be obsoleted by Mozilla bug 471915.
+ //
+ // The only reliable way to know if a font is loaded in Gecko
+ // (at the moment) is document.onload in a document with
+ // a @font-face rule defined in a "static" stylesheet. We use a
+ // subdocument in an <iframe>, set up properly, to know when
+ // our @font-face rule was loaded. However, the subdocument and
+ // outer document can't share CSS rules, so the inner document
+ // is only part of the puzzle. The second piece is an invisible
+ // div created in order to force loading of the @font-face in
+ // the *outer* document. (The font still needs to be loaded for
+ // its metrics, for reflow). We create the div first for the
+ // outer document, then create the iframe. Unless something
+ // goes really wonkily, we expect the @font-face for the outer
+ // document to be processed before the inner. That's still
+ // fragile, but seems to work in practice.
- isWorker ? obj.bindWorker(str) : obj.bindDOM(str);
- }
+ var div = document.createElement("div");
+ div.setAttribute("style",
+ 'visibility: hidden;'+
+ 'width: 10px; height: 10px;'+
+ 'position: absolute; top: 0px; left: 0px;');
+ var html = '';
+ for (var i = 0; i < names.length; ++i) {
+ html += '<span style="font-family:'+ names[i] +'">Hi</span>';
+ }
+ div.innerHTML = html;
+ document.body.appendChild(div);
- return ready;
+ // XXX we should have a time-out here too, and maybe fire
+ // pdfjsFontLoadFailed?
+ var src = '<!DOCTYPE HTML><html><head>';
+ src += '<style type="text/css">';
+ for (var i = 0; i < rules.length; ++i) {
+ src += rules[i];
+ }
+ src += '</style>'
+ src += '<script type="application/javascript">'
+ var fontNamesArray = '';
+ for (var i = 0; i < names.length; ++i) {
+ fontNamesArray += '"'+ names[i] + '", ';
+ }
+ src += ' var fontNames=['+ fontNamesArray +'];\n';
+ src += ' window.onload = function () {\n'
+ src += ' var Fonts = top.document.defaultView.Fonts;\n';
+ src += ' for (var i = 0; i < fontNames.length; ++i) {\n';
+ src += ' var font = Fonts.lookup(fontNames[i]);\n';
+ src += ' font.loading = false;\n';
+ src += ' }\n';
+ src += ' var doc = top.document;\n';
+ src += ' var evt = doc.createEvent("Events");\n';
+ src += ' evt.initEvent("pdfjsFontLoad", true, false);\n'
+ src += ' doc.documentElement.dispatchEvent(evt);\n';
+ src += ' }';
+ src += '</script></head><body>';
+ for (var i = 0; i < names.length; ++i) {
+ src += '<p style="font-family:\''+ fontName +'\'">Hi</p>';
+ }
+ src += '</body></html>';
+ var frame = document.createElement("iframe");
+ frame.src = 'data:text/html,'+ src;
+ frame.setAttribute("style",
+ 'visibility: hidden;'+
+ 'width: 10px; height: 10px;'+
+ 'position: absolute; top: 0px; left: 0px;');
+ document.body.appendChild(frame);
+ /** Hack end */
}
};