[Pkg-javascript-commits] [pdf.js] 162/210: Refactors loadFont for translateFont be async; fixes type3 dup data

David Prévot taffit at moszumanska.debian.org
Thu Jun 5 14:21:13 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch upstream
in repository pdf.js.

commit e5a0d89da9d221af47ba81687462a7b64e30bc49
Author: Yury Delendik <ydelendik at mozilla.com>
Date:   Mon May 19 16:27:54 2014 -0500

    Refactors loadFont for translateFont be async; fixes type3 dup data
---
 src/core/evaluator.js | 185 ++++++++++++++++++++++++++++++--------------------
 src/core/fonts.js     |  23 ++++---
 src/core/obj.js       |   1 -
 src/display/canvas.js |   7 +-
 4 files changed, 126 insertions(+), 90 deletions(-)

diff --git a/src/core/evaluator.js b/src/core/evaluator.js
index 5752f64..2498d97 100644
--- a/src/core/evaluator.js
+++ b/src/core/evaluator.js
@@ -292,28 +292,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         fontArgs = fontArgs.slice();
         fontName = fontArgs[0].name;
       }
-      var self = this;
-      return this.loadFont(fontName, fontRef, this.xref, resources,
-                               operatorList).then(function (font) {
-          state.font = font;
-          var loadedName = font.loadedName;
-          if (!font.sent) {
-            var fontData = font.translated.exportData();
-
-            self.handler.send('commonobj', [
-              loadedName,
-              'Font',
-              fontData
-            ]);
-            font.sent = true;
-          }
 
-          return loadedName;
+      var self = this;
+      return this.loadFont(fontName, fontRef, this.xref, resources).then(
+          function (translated) {
+        if (!translated.font.isType3Font) {
+          return translated;
+        }
+        return translated.loadType3Data(self, resources, operatorList).then(
+            function () {
+          return translated;
         });
+      }).then(function (translated) {
+        state.font = translated.font;
+        translated.send(self.handler);
+        return translated.loadedName;
+      });
     },
 
     handleText: function PartialEvaluator_handleText(chars, state) {
-      var font = state.font.translated;
+      var font = state.font;
       var glyphs = font.charsToGlyphs(chars);
       var isAddToPathSet = !!(state.textRenderingMode &
                               TextRenderingMode.ADD_TO_PATH_FLAG);
@@ -439,16 +437,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
     },
 
     loadFont: function PartialEvaluator_loadFont(fontName, font, xref,
-                                                 resources,
-                                                 parentOperatorList) {
+                                                 resources) {
 
       function errorFont() {
-        return Promise.resolve({
-          translated: new ErrorFont('Font ' + fontName + ' is not available'),
-          loadedName: 'g_font_error'
-        });
+        return Promise.resolve(new TranslatedFont('g_font_error',
+          new ErrorFont('Font ' + fontName + ' is not available'), font));
       }
-
       var fontRef;
       if (font) { // Loading by ref.
         assert(isRef(font));
@@ -471,6 +465,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         return errorFont();
       }
 
+      // We are holding font.translated references just for fontRef that are not
+      // dictionaries (Dict). See explanation below.
+      if (font.translated) {
+        return font.translated;
+      }
+
       var fontCapability = createPromiseCapability();
 
       var preEvaluatedFont = this.preEvaluateFont(font, xref);
@@ -487,8 +487,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
           var aliasFontRef = fontAliases[hash].aliasRef;
           if (aliasFontRef && this.fontCache.has(aliasFontRef)) {
             this.fontCache.putAlias(fontRef, aliasFontRef);
-            var cachedFont = this.fontCache.get(fontRef);
-            return cachedFont;
+            return this.fontCache.get(fontRef);
           }
         }
 
@@ -517,49 +516,28 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
       font.loadedName = 'g_font_' + (fontRefIsDict ?
         fontName.replace(/\W/g, '') : fontID);
 
-      if (!font.translated) {
-        var translated;
-        try {
-          translated = this.translateFont(preEvaluatedFont, xref);
-        } catch (e) {
-          UnsupportedManager.notify(UNSUPPORTED_FEATURES.font);
-          translated = new ErrorFont(e instanceof Error ? e.message : e);
-        }
-        font.translated = translated;
-      }
-
-      var loadCharProcsPromise = Promise.resolve();
-      if (font.translated.loadCharProcs) {
-        var charProcs = font.get('CharProcs').getAll();
-        var fontResources = (font.get('Resources') || resources);
-        var charProcKeys = Object.keys(charProcs);
-        var charProcOperatorList = {};
-        for (var i = 0, n = charProcKeys.length; i < n; ++i) {
-          loadCharProcsPromise = loadCharProcsPromise.then(function (key) {
-            var glyphStream = charProcs[key];
-            var operatorList = new OperatorList();
-            return this.getOperatorList(glyphStream, fontResources,
-                                        operatorList).
-              then(function () {
-                charProcOperatorList[key] = operatorList.getIR();
-
-                // Add the dependencies to the parent operator list so they are
-                // resolved before sub operator list is executed synchronously.
-                if (parentOperatorList) {
-                  parentOperatorList.addDependencies(operatorList.dependencies);
-                }
-              });
-          }.bind(this, charProcKeys[i]));
-        }
-        loadCharProcsPromise = loadCharProcsPromise.then(function () {
-          font.translated.charProcOperatorList = charProcOperatorList;
-        });
-      }
-      return loadCharProcsPromise.then(function () {
-        font.loaded = true;
-        fontCapability.resolve(font);
-        return fontCapability.promise;
-      }, fontCapability.reject);
+      font.translated = fontCapability.promise;
+
+      // TODO move promises into translate font
+      var translatedPromise;
+      try {
+        translatedPromise = Promise.resolve(
+          this.translateFont(preEvaluatedFont, xref));
+      } catch (e) {
+        translatedPromise = Promise.reject(e);
+      }
+
+      translatedPromise.then(function (translatedFont) {
+        fontCapability.resolve(new TranslatedFont(font.loadedName,
+          translatedFont, font));
+      }, function (reason) {
+        // TODO fontCapability.reject?
+        UnsupportedManager.notify(UNSUPPORTED_FEATURES.font);
+        fontCapability.resolve(new TranslatedFont(font.loadedName,
+          new ErrorFont(reason instanceof Error ? reason.message : reason),
+          font));
+      });
+      return fontCapability.promise;
     },
 
     buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) {
@@ -830,11 +808,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
       }
 
       function handleSetFont(fontName, fontRef) {
-        return self.loadFont(fontName, fontRef, xref, resources, null).
-          then(function (font) {
-            var fontTranslated = textState.font = font.translated;
-            textState.fontMatrix = fontTranslated.fontMatrix ?
-              fontTranslated.fontMatrix :
+        return self.loadFont(fontName, fontRef, xref, resources).
+          then(function (translated) {
+            textState.font = translated.font;
+            textState.fontMatrix = translated.font.fontMatrix ||
               FONT_IDENTITY_MATRIX;
           });
       }
@@ -1609,7 +1586,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
       this.extractWidths(dict, xref, descriptor, properties);
 
       if (type.name === 'Type3') {
-        properties.coded = true;
+        properties.isType3Font = true;
       }
 
       return new Font(fontName.name, fontFile, properties);
@@ -1619,6 +1596,64 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
   return PartialEvaluator;
 })();
 
+var TranslatedFont = (function TranslatedFontClosure() {
+  function TranslatedFont(loadedName, font, dict) {
+    this.loadedName = loadedName;
+    this.font = font;
+    this.dict = dict;
+    this.type3Loaded = null;
+    this.sent = false;
+  }
+  TranslatedFont.prototype = {
+    send: function (handler) {
+      if (this.sent) {
+        return;
+      }
+      var fontData = this.font.exportData();
+      handler.send('commonobj', [
+        this.loadedName,
+        'Font',
+        fontData
+      ]);
+      this.sent = true;
+    },
+    loadType3Data: function (evaluator, resources, parentOperatorList) {
+      assert(this.font.isType3Font);
+
+      if (this.type3Loaded) {
+        return this.type3Loaded;
+      }
+
+      var translatedFont = this.font;
+      var loadCharProcsPromise = Promise.resolve();
+      var charProcs = this.dict.get('CharProcs').getAll();
+      var fontResources = this.dict.get('Resources') || resources;
+      var charProcKeys = Object.keys(charProcs);
+      var charProcOperatorList = {};
+      for (var i = 0, n = charProcKeys.length; i < n; ++i) {
+        loadCharProcsPromise = loadCharProcsPromise.then(function (key) {
+          var glyphStream = charProcs[key];
+          var operatorList = new OperatorList();
+          return evaluator.getOperatorList(glyphStream, fontResources,
+            operatorList).
+            then(function () {
+              charProcOperatorList[key] = operatorList.getIR();
+
+              // Add the dependencies to the parent operator list so they are
+              // resolved before sub operator list is executed synchronously.
+              parentOperatorList.addDependencies(operatorList.dependencies);
+            });
+        }.bind(this, charProcKeys[i]));
+      }
+      this.type3Loaded = loadCharProcsPromise.then(function () {
+        translatedFont.charProcOperatorList = charProcOperatorList;
+      });
+      return this.type3Loaded;
+    }
+  };
+  return TranslatedFont;
+})();
+
 var OperatorList = (function OperatorListClosure() {
   var CHUNK_SIZE = 1000;
   var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size
diff --git a/src/core/fonts.js b/src/core/fonts.js
index 5620cbc..205fc95 100644
--- a/src/core/fonts.js
+++ b/src/core/fonts.js
@@ -2118,23 +2118,23 @@ function adjustWidths(properties) {
 }
 
 var Glyph = (function GlyphClosure() {
-  function Glyph(fontChar, unicode, accent, width, vmetric, operatorList) {
+  function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId) {
     this.fontChar = fontChar;
     this.unicode = unicode;
     this.accent = accent;
     this.width = width;
     this.vmetric = vmetric;
-    this.operatorList = operatorList;
+    this.operatorListId = operatorListId;
   }
 
   Glyph.prototype.matchesForCache =
-      function(fontChar, unicode, accent, width, vmetric, operatorList) {
+      function(fontChar, unicode, accent, width, vmetric, operatorListId) {
     return this.fontChar === fontChar &&
            this.unicode === unicode &&
            this.accent === accent &&
            this.width === width &&
            this.vmetric === vmetric &&
-           this.operatorList === operatorList;
+           this.operatorListId === operatorListId;
   };
 
   return Glyph;
@@ -2154,8 +2154,7 @@ var Font = (function FontClosure() {
 
     this.name = name;
     this.loadedName = properties.loadedName;
-    this.coded = properties.coded;
-    this.loadCharProcs = properties.coded;
+    this.isType3Font = properties.isType3Font;
     this.sizes = [];
 
     this.glyphCache = {};
@@ -4376,7 +4375,7 @@ var Font = (function FontClosure() {
     },
 
     charToGlyph: function Font_charToGlyph(charcode) {
-      var fontCharCode, width, operatorList;
+      var fontCharCode, width, operatorListId;
 
       var widthCode = charcode;
       if (this.cMap && charcode in this.cMap.map) {
@@ -4398,9 +4397,9 @@ var Font = (function FontClosure() {
         fontCharCode = mapSpecialUnicodeValues(fontCharCode);
       }
 
-      if (this.type === 'Type3') {
+      if (this.isType3Font) {
         // Font char code in this case is actually a glyph name.
-        operatorList = this.charProcOperatorList[fontCharCode];
+        operatorListId = fontCharCode;
       }
 
       var accent = null;
@@ -4418,9 +4417,9 @@ var Font = (function FontClosure() {
       var glyph = this.glyphCache[charcode];
       if (!glyph ||
           !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric,
-                                 operatorList)) {
+                                 operatorListId)) {
         glyph = new Glyph(fontChar, unicode, accent, width, vmetric,
-                          operatorList);
+                          operatorListId);
         this.glyphCache[charcode] = glyph;
       }
       return glyph;
@@ -4485,6 +4484,8 @@ var Font = (function FontClosure() {
 var ErrorFont = (function ErrorFontClosure() {
   function ErrorFont(error) {
     this.error = error;
+    this.loadedName = 'g_font_error';
+    this.loading = false;
   }
 
   ErrorFont.prototype = {
diff --git a/src/core/obj.js b/src/core/obj.js
index 67a191d..f2c3586 100644
--- a/src/core/obj.js
+++ b/src/core/obj.js
@@ -513,7 +513,6 @@ var Catalog = (function CatalogClosure() {
       });
       return Promise.all(promises).then(function (fonts) {
         for (var i = 0, ii = fonts.length; i < ii; i++) {
-          delete fonts[i].sent;
           delete fonts[i].translated;
         }
         this.fontCache.clear();
diff --git a/src/display/canvas.js b/src/display/canvas.js
index 646f8a3..ee5a4e7 100644
--- a/src/display/canvas.js
+++ b/src/display/canvas.js
@@ -1196,7 +1196,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
       this.current.font = fontObj;
       this.current.fontSize = size;
 
-      if (fontObj.coded) {
+      if (fontObj.isType3Font) {
         return; // we don't need ctx.font for Type3 fonts
       }
 
@@ -1343,7 +1343,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
       }
 
       // Type3 fonts - each glyph is a "mini-PDF"
-      if (font.coded) {
+      if (font.isType3Font) {
         ctx.save();
         ctx.transform.apply(ctx, current.textMatrix);
         ctx.translate(current.x, current.y);
@@ -1363,7 +1363,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
           this.save();
           ctx.scale(fontSize, fontSize);
           ctx.transform.apply(ctx, fontMatrix);
-          this.executeOperatorList(glyph.operatorList);
+          var operatorList = font.charProcOperatorList[glyph.operatorListId];
+          this.executeOperatorList(operatorList);
           this.restore();
 
           var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git



More information about the Pkg-javascript-commits mailing list