]> git.parisson.com Git - pdf.js.git/commitdiff
Fix an issue with the vhea/vmtx tables
authorVivien Nicolas <21@vingtetun.org>
Fri, 9 Sep 2011 14:37:56 +0000 (16:37 +0200)
committerVivien Nicolas <21@vingtetun.org>
Fri, 9 Sep 2011 14:37:56 +0000 (16:37 +0200)
fonts.js

index a7fb509d055f9a516e27c7554d614a01f7aafdb1..32de47c56389e0f4b3981bb8822d3d01d35d9449 100755 (executable)
--- a/fonts.js
+++ b/fonts.js
@@ -1032,9 +1032,9 @@ var Font = (function Font() {
             var end = denseRange[1];
             var index = firstCode;
             for (var j = start; j <= end; j++) {
-              var code = j - firstCode - 1;
+              var code = glyphs[j - start];
               var mapping = encoding[index] || {};
-              mapping.unicode = glyphs[code].unicode;
+              mapping.unicode = code.unicode;
               encoding[index++] = mapping;
             }
             return cmap.data = createCMapTable(glyphs);
@@ -1043,6 +1043,39 @@ var Font = (function Font() {
         return cmap.data;
       };
 
+      function sanitizeMetrics(font, header, metrics, numGlyphs) {
+        if (!header && !metrics)
+          return;
+
+        // The vhea/vmtx tables are not required, so it happens that
+        // some fonts embed a vmtx table without a vhea table. In this
+        // situation the sanitizer assume numOfLongVerMetrics = 1. As
+        // a result it tries to read numGlyphs - 1 SHORT from the vmtx
+        // table, and if it is not possible, the font is rejected.
+        // So remove the vmtx table if there is no vhea table.
+        if (!header && metrics) {
+          metrics.data = null;
+          return;
+        }
+
+        font.pos = (font.start ? font.start : 0) + header.offset;
+        font.pos += header.length - 2;
+        var numOfMetrics = int16(font.getBytes(2));
+      
+        var numOfSidebearings = numGlyphs - numOfMetrics;
+        var numMissing = numOfSidebearings -
+          ((hmtx.length - numOfMetrics * 4) >> 1);
+        if (numMissing > 0) {
+          font.pos = (font.start ? font.start : 0) + metrics.offset;
+          var entries = '';
+          for (var i = 0; i < hmtx.length; i++)
+            entries += String.fromCharCode(font.getByte());
+          for (var i = 0; i < numMissing; i++)
+            entries += '\x00\x00';
+          metrics.data = stringToArray(entries);
+        }
+      };
+
       // Check that required tables are present
       var requiredTables = ['OS/2', 'cmap', 'head', 'hhea',
                              'hmtx', 'maxp', 'name', 'post'];
@@ -1050,7 +1083,7 @@ var Font = (function Font() {
       var header = readOpenTypeHeader(font);
       var numTables = header.numTables;
 
-      var cmap, maxp, hhea, hmtx;
+      var cmap, maxp, hhea, hmtx, vhea, vmtx;
       var tables = [];
       for (var i = 0; i < numTables; i++) {
         var table = readTableEntry(font);
@@ -1066,6 +1099,11 @@ var Font = (function Font() {
             hmtx = table;
 
           requiredTables.splice(index, 1);
+        } else {
+          if (table.tag == 'vmtx')
+            vmtx = table;
+          else if (table.tag == 'vhea')
+            vhea = table;
         }
         tables.push(table);
       }
@@ -1091,28 +1129,14 @@ var Font = (function Font() {
         });
       }
 
-      // Ensure the hmtx tables contains an advance width and a sidebearing
-      // for the number of glyphs declared in the maxp table
+      // Ensure the [h/v]mtx tables contains the advance width and
+      // sidebearings information for numGlyphs in the maxp table
       font.pos = (font.start ? font.start : 0) + maxp.offset;
       var version = int16(font.getBytes(4));
       var numGlyphs = int16(font.getBytes(2));
 
-      font.pos = (font.start ? font.start : 0) + hhea.offset;
-      font.pos += hhea.length - 2;
-      var numOfHMetrics = int16(font.getBytes(2));
-
-      var numOfSidebearings = numGlyphs - numOfHMetrics;
-      var numMissing = numOfSidebearings -
-        ((hmtx.length - numOfHMetrics * 4) >> 1);
-      if (numMissing > 0) {
-        font.pos = (font.start ? font.start : 0) + hmtx.offset;
-        var metrics = '';
-        for (var i = 0; i < hmtx.length; i++)
-          metrics += String.fromCharCode(font.getByte());
-        for (var i = 0; i < numMissing; i++)
-          metrics += '\x00\x00';
-        hmtx.data = stringToArray(metrics);
-      }
+      sanitizeMetrics(font, hhea, hmtx, numGlyphs);
+      sanitizeMetrics(font, vhea, vmtx, numGlyphs);
 
       // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
       // Sometimes it's 0. That needs to be fixed