]> git.parisson.com Git - pdf.js.git/commitdiff
load all newly-created fonts in one document to speed things up
authorChris Jones <jones.chris.g@gmail.com>
Thu, 30 Jun 2011 09:51:42 +0000 (02:51 -0700)
committerChris Jones <jones.chris.g@gmail.com>
Thu, 30 Jun 2011 09:51:42 +0000 (02:51 -0700)
fonts.js

index 9d8a9e806f8f8fd0b8cfc158831a977bd2dbaebc..4a09931e5470a702db178b3d77bf71421abbbc7d 100644 (file)
--- a/fonts.js
+++ b/fonts.js
@@ -137,6 +137,7 @@ var FontLoader = {
       return true;
     }
 
+    var rules = [ ], names = [ ];
     for (var i = 0; i < fonts.length; i++) {
       var font = fonts[i];
       if (!Fonts.lookup(font.name)) {
@@ -148,16 +149,86 @@ var FontLoader = {
         for (var j = 0; j < length; j++)
           str += String.fromCharCode(data[j]);
 
-        worker ? obj.bindWorker(str) : obj.bindDOM(str);
+        worker ? obj.bindWorker(str) : obj.bindDOM(str, rules, names);
       }
     }
 
+    if (!worker && rules.length) {
+      FontLoader.prepareFontLoadEvent(rules, names);
+    }
+
     if (!checkFontsLoaded()) {
       document.documentElement.addEventListener(
         "pdfjsFontLoad", checkFontsLoaded, false);
     }
 
     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
+      // paragraph 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 <p> first (in
+      // |bindDom()| function below), 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.
+
+      // 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 +'\'">Hello</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 */
   }
 };
 
@@ -820,7 +891,7 @@ var Font = (function () {
       });
     },
 
-    bindDOM: function font_bindDom(data) {
+    bindDOM: function font_bindDom(data, rules, names) {
       var fontName = this.name;
 
       // Add the @font-face rule to the document
@@ -829,25 +900,6 @@ var Font = (function () {
       var styleSheet = document.styleSheets[0];
       styleSheet.insertRule(rule, styleSheet.length);
 
-      /** 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
-      // paragraph 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 <p> first, in
-      // the outer document, then create the iframe.  Unless something
-      // goes really wonkily, we expect the @font-face for the outer
-      // document to processed before the inner.  That's still
-      // fragile, but seems to work in practice.
       var p = document.createElement("p");
       p.setAttribute("style",
                      'font-family: "'+ fontName +'";'+
@@ -857,36 +909,8 @@ var Font = (function () {
       p.innerHTML = 'Hello';
       document.body.appendChild(p);
 
-      // 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 type="application/javascript">'
-      src += '  var fontName="'+ fontName +'";\n';
-      src += '  window.onload = function () {\n'
-      src += '    var Fonts = top.document.defaultView.Fonts;\n';
-      src += '    var font = Fonts.lookup(fontName);\n';
-      src += '    font.loading = false;\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>';
-      src += '</head>';
-      src += '<body style="font-family:\''+ fontName +'\'">';
-      src += 'Hello</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 */
+      rules.push(rule);
+      names.push(fontName);
     }
   };