]> git.parisson.com Git - pdf.js.git/commitdiff
add another hackity hack to detect font loaded-ness
authorChris Jones <jones.chris.g@gmail.com>
Thu, 30 Jun 2011 09:08:53 +0000 (02:08 -0700)
committerChris Jones <jones.chris.g@gmail.com>
Thu, 30 Jun 2011 09:08:53 +0000 (02:08 -0700)
fonts.js
multi_page_viewer.js
test/test_slave.html
viewer.js

index e25b2ae2d26420de9ea5307fbd373a5cba85d8d3..80651d22410017afb656ddbd893d23533aa720c4 100644 (file)
--- a/fonts.js
+++ b/fonts.js
@@ -95,31 +95,45 @@ var Fonts = {
 };
 
 var FontLoader = {
-  bind: function(fonts) {
+  bind: function(fonts, callback) {
     var worker = (typeof window == "undefined");
-    var ready = true;
 
-    for (var i = 0; i < fonts.length; i++) {
-      var font = fonts[i];
-      if (Fonts[font.name]) {
-        ready = ready && !Fonts[font.name].loading;
-        continue;
+    function checkFontsLoaded() {
+      for (var i = 0; i < fonts.length; i++) {
+        var font = fonts[i];
+        if (Fonts[font.name].loading) {
+          return false;
+        }
       }
 
-      ready = false;
+      document.documentElement.removeEventListener(
+        "pdfjsFontLoad", checkFontsLoaded, false);
 
-      var obj = new Font(font.name, font.file, font.properties);
+      callback();
+      return true;
+    }
 
-      var str = "";
-      var data = Fonts[font.name].data;
-      var length = data.length;
-      for (var j = 0; j < length; j++)
-        str += String.fromCharCode(data[j]);
+    for (var i = 0; i < fonts.length; i++) {
+      var font = fonts[i];
+      if (!Fonts[font.name]) {
+        var obj = new Font(font.name, font.file, font.properties);
 
-      worker ? obj.bindWorker(str) : obj.bindDOM(str);
+        var str = "";
+        var data = Fonts[font.name].data;
+        var length = data.length;
+        for (var j = 0; j < length; j++)
+          str += String.fromCharCode(data[j]);
+
+        worker ? obj.bindWorker(str) : obj.bindDOM(str);
+      }
     }
 
-    return ready;
+    if (!checkFontsLoaded()) {
+      document.documentElement.addEventListener(
+        "pdfjsFontLoad", checkFontsLoaded, false);
+    }
+
+    return;
   }
 };
 
@@ -793,60 +807,73 @@ var Font = (function () {
       });
     },
 
-    bindDOM: function font_bindDom(data, callback) {
+    bindDOM: function font_bindDom(data) {
       var fontName = this.name;
 
-      // Just adding the font-face to the DOM doesn't make it load. It
-      // seems it's loaded once Gecko notices it's used. Therefore,
-      // add a div on the page using the loaded font.
-      var div = document.createElement("div");
-      var style = 'font-family:"' + name + 
-        '";position: absolute;top:-99999;left:-99999;z-index:-99999';
-      div.setAttribute("style", style);
-      document.body.appendChild(div);
-
-      /** Hack begin */
-      // Actually there is not event when a font has finished downloading so
-      // the following code are a dirty hack to 'guess' when a font is ready
-      // This code could go away when bug 471915 has landed
-      var canvas = document.createElement("canvas");
-      var ctx = canvas.getContext("2d");
-      ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
-      var testString = "    ";
-
-      // Periodicaly check for the width of the testString, it will be
-      // different once the real font has loaded
-      var textWidth = ctx.measureText(testString).width;
-
-      var interval = window.setInterval(function canvasInterval(self) {
-        this.start = this.start || Date.now();
-        ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
-
-        // For some reasons the font has not loaded, so mark it loaded for the
-        // page to proceed but cry
-        if (textWidth == ctx.measureText(testString).width) {
-          if ((Date.now() - this.start) < kMaxWaitForFontFace) {
-            return;
-          } else {
-            warn("Is " + fontName + " loaded?");
-          }
-        }
-        
-        window.clearInterval(interval);
-        Fonts[fontName].loading = false;
-        this.start = 0;
-        if (callback) {
-          callback();
-        }
-      }, 30, this);
-
-      /** Hack end */
-
       // Add the @font-face rule to the document
       var url = "url(data:" + this.mimetype + ";base64," + window.btoa(data) + ");";
       var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}";
       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 +'";'+
+                     'visibility: hidden;'+
+                     'width: 10px; height: 10px;'+
+                     'position: absolute; top: 0px; left: 0px;');
+      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[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 */
     }
   };
 
index 87e2c8f14c2be18a7229fb6b3a08303457f351b6..d60e96cb26643e947d57a020655ff8f7d914642d 100644 (file)
@@ -125,14 +125,7 @@ var PDFViewer = {
       var fonts = [];
       page.compile(gfx, fonts);
 
-      var loadFont = function() {
-        if (!FontLoader.bind(fonts)) {
-          pageTimeout = window.setTimeout(loadFont, 10);
-          return;
-        }
-        page.display(gfx);
-      }
-      loadFont();
+      FontLoader.bind(fonts, function() { page.display(gfx); });
     }
   },
   
@@ -194,17 +187,10 @@ var PDFViewer = {
       var fonts = [];
       page.compile(gfx, fonts);
 
-      var loadFont = function() {
-        if (!FontLoader.bind(fonts)) {
-          pageTimeout = window.setTimeout(loadFont, 10);
-          return;
-        }
-        page.display(gfx);
-      }
-      loadFont();
+      FontLoader.bind(fonts, function() { page.display(gfx); });
     }
   },
-  
+
   changeScale: function(num) {
     while (PDFViewer.element.hasChildNodes()) {
       PDFViewer.element.removeChild(PDFViewer.element.firstChild);
index d70e362af724c9ffe18c0bf5fe75a4adee44f29a..8564b52b4b5086d266db48f57071b57291f38f52 100644 (file)
@@ -113,25 +113,18 @@ function nextPage() {
     failure = 'page setup: '+ e.toString();
   }
 
-  var fontLoaderTimer = null;
-  function checkFontsLoaded() {
+  if (!failure) {
     try {
-      if (!FontLoader.bind(fonts)) {
-        fontLoaderTimer = window.setTimeout(checkFontsLoaded, 10);
-        return;
-      }
+      FontLoader.bind(fonts, function() { snapshotCurrentPage(gfx); });
     } catch(e) {
       failure = 'fonts: '+ e.toString();
     }
-    snapshotCurrentPage(gfx);
   }
 
   if (failure) {
-    // Skip font loading if there was a failure, since the fonts might
-    // be in an inconsistent state.
+    // Skip right to snapshotting if there was a failure, since the
+    // fonts might be in an inconsistent state.
     snapshotCurrentPage(gfx);
-  } else {
-    checkFontsLoaded();
   }
 }
 
index 5db2effdab59a405dbb4ef6b4694a3fb6354f715..765a26b3b9b15a728712047582999fb407302a6a 100644 (file)
--- a/viewer.js
+++ b/viewer.js
@@ -3,7 +3,7 @@
 
 "use strict";
 
-var pdfDocument, canvas, pageScale, pageDisplay, pageNum, numPages, pageTimeout;
+var pdfDocument, canvas, pageScale, pageDisplay, pageNum, numPages;
 function load(userInput) {
     canvas = document.getElementById("canvas");
     canvas.mozOpaque = true;
@@ -53,8 +53,6 @@ function gotoPage(num) {
 }
 
 function displayPage(num) {
-    window.clearTimeout(pageTimeout);
-
     document.getElementById("pageNumber").value = num;
 
     var t0 = Date.now();
@@ -82,22 +80,18 @@ function displayPage(num) {
     page.compile(gfx, fonts);
     var t2 = Date.now();
 
-    function loadFont() {
-      if (!FontLoader.bind(fonts)) {
-        pageTimeout = window.setTimeout(loadFont, 10);
-        return;
-      }
+    function displayPage() {
+        var t3 = Date.now();
 
-      var t3 = Date.now();
+        page.display(gfx);
 
-      page.display(gfx);
+        var t4 = Date.now();
 
-      var t4 = Date.now();
+        var infoDisplay = document.getElementById("info");
+        infoDisplay.innerHTML = "Time to load/compile/fonts/render: "+ (t1 - t0) + "/" + (t2 - t1) + "/" + (t3 - t2) + "/" + (t4 - t3) + " ms";
+    }
 
-      var infoDisplay = document.getElementById("info");
-      infoDisplay.innerHTML = "Time to load/compile/fonts/render: "+ (t1 - t0) + "/" + (t2 - t1) + "/" + (t3 - t2) + "/" + (t4 - t3) + " ms";
-    };
-    loadFont();
+    FontLoader.bind(fonts, displayPage);
 }
 
 function nextPage() {