From 06cef910fb033e5abc208f65d4f4534db6191f6e Mon Sep 17 00:00:00 2001 From: Julian Viereck <julian.viereck@gmail.com> Date: Thu, 15 Sep 2011 23:27:22 -0700 Subject: [PATCH] Cleanup Moz support in FontLoader --- fonts.js | 197 ++++++++++++++++-------------------------------------- worker.js | 7 +- 2 files changed, 59 insertions(+), 145 deletions(-) diff --git a/fonts.js b/fonts.js index ff176c264..0de8fd379 100755 --- a/fonts.js +++ b/fonts.js @@ -290,152 +290,69 @@ var FontLoader = { return rule; }, - bind: function(fonts, callback) { + bind: function(fontObj) { // If this isn't Gecko, we assume it's WebKit. See notes in bindWebKit. if (!isGecko) { - var fontObj = fonts[0]; this.bindWebKit(fontObj.loadedName, fontObj); - return; + } else { + var rule = this.bindDOM(fontObj); + FontLoader.prepareFontLoadEvent(fontObj, rule); } - - 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); + // 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(fontObj, rule) { + /** 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. + // + // The postMessage() hackery was added to work around chrome bug + // 82402. - callback(); - return true; - } - - var rules = [], names = [], objs = []; - - for (var i = 0; i < fonts.length; i++) { - var font = fonts[i]; - var obj = font; - - objs.push(obj); - - var str = ''; - var rule = this.bindDOM(font); - if (rule) { - rules.push(rule); - names.push(obj.loadedName); - } - } - - // console.log("bind", fonts, rules, names); - - this.listeningForFontLoad = false; - if (!isWorker && rules.length) { - FontLoader.prepareFontLoadEvent(rules, names, objs); - } - - if (!checkFontsLoaded()) { - document.documentElement.addEventListener( - 'pdfjsFontLoad', checkFontsLoaded, false); - } - - return objs; - }, - // 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) { - /** 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. - // - // The postMessage() hackery was added to work around chrome bug - // 82402. - - 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); - - 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>'; - 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 += ' parent.postMessage(JSON.stringify(fontNames), "*");\n'; - src += ' }'; - src += '</script></head><body>'; - for (var i = 0; i < names.length; ++i) { - src += '<p style="font-family:\'' + names[i] + '\'">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); - frame.onload = function() { - Objects.resolve(names[0]); - } - /** Hack end */ - } - }; + // XXX we should have a time-out here too, and maybe fire + // pdfjsFontLoadFailed? + var src = '<!DOCTYPE HTML><html><head>'; + src += '<style type="text/css">'; + src += rule; + src += '</style>'; + src += '</script>'; + src += '</head><body>'; + src += '<p style="font-family:\'' + fontObj.loadedName + '\'">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); + + frame.onload = function() { + Objects.resolve(fontObj.loadedName); + } + /** Hack end */ + } +}; if (!isWorker) { FontLoader.setup(); diff --git a/worker.js b/worker.js index 38b60ad8c..021114683 100644 --- a/worker.js +++ b/worker.js @@ -136,7 +136,7 @@ var Promise = (function() { resolve: function(data) { if (this.isResolved) { - throw "A Promise can be resolved only once"; + throw "A Promise can be resolved only once " + this.name; } this.isResolved = true; @@ -229,10 +229,7 @@ var WorkerPDFDoc = (function() { Objects.resolve(objId, fontObj); } else { Objects.setData(objId, fontObj); - FontLoader.bind([fontObj], function() { - console.log("loaded", fontObj.loadedName); - Objects.resolve(objId); - }); + FontLoader.bind(fontObj); } });