]> git.parisson.com Git - pdf.js.git/commitdiff
CMAP creation code is now more readable
authorVivien Nicolas <21@vingtetun.org>
Mon, 13 Jun 2011 01:35:56 +0000 (03:35 +0200)
committerVivien Nicolas <21@vingtetun.org>
Mon, 13 Jun 2011 01:35:56 +0000 (03:35 +0200)
PDFFont.js

index 8cddb2360cebaf2a498ad26c4bc7a9c52fc73eb9..479b05addbcd045fb1ab9549ca9ff76c01dc95a8 100644 (file)
@@ -147,6 +147,7 @@ Font.prototype = {
     for (var i = 0; i < aGlyphs.length; i++)
       data[aGlyphs[i].unicode] = i + 1;
 
+    // Separate the glyphs into continuous range of codes, aka segment.
     var ranges = [];
     var range = [];
     for (var i = 0; i < data.length; i++) {
@@ -164,80 +165,68 @@ Font.prototype = {
     }
 
 
-    var cmap = [];
-    var segCount = ranges.length + 1;
+    // The size in bytes of the header is equal to the size of the
+    // different fields * length of a short + (size of the 4 parallels arrays
+    // describing segments * length of a short).
+    var headerSize = (12 * 2 + (ranges.length * 4 * 2));
 
+    var segCount = ranges.length + 1;
     var segCount2 = segCount * 2;
     var searchRange = FontsUtils.getMaxPower2(segCount) * 2;
     var searchEntry = Math.log(segCount) / Math.log(2);
     var rangeShift = 2 * segCount - searchRange;
-    cmap = cmap.concat(FontsUtils.integerToBytes(segCount2, 2));
-    cmap = cmap.concat(FontsUtils.integerToBytes(searchRange, 2));
-    cmap = cmap.concat(FontsUtils.integerToBytes(searchEntry, 2));
-    cmap = cmap.concat(FontsUtils.integerToBytes(rangeShift, 2));
-
-    // End characters code with an additional 0xFFFF to finish the array
-    for (var i = 0; i < ranges.length; i++) {
-      var range = ranges[i];
-      cmap = cmap.concat(FontsUtils.integerToBytes(range[range.length - 1], 2));
-    };
-    cmap = cmap.concat([0xFF, 0xFF]);
-
-    // reserved pad
-    cmap = cmap.concat([0x00, 0x00]);
-
-    // Start characters code with an additional 0xFFFF to finish the array
-    for (var i = 0; i < ranges.length; i++) {
+    var cmap = [].concat(
+      [
+        0x00, 0x00, // version
+        0x00, 0x01, // numTables
+        0x00, 0x03, // platformID
+        0x00, 0x01, // encodingID
+        0x00, 0x00, 0x00, 0x0C, // start of the table record
+        0x00, 0x04  // format
+      ],
+      FontsUtils.integerToBytes(headerSize, 2), // length
+      [0x00, 0x00], // language
+      FontsUtils.integerToBytes(segCount2, 2),
+      FontsUtils.integerToBytes(searchRange, 2),
+      FontsUtils.integerToBytes(searchEntry, 2),
+      FontsUtils.integerToBytes(rangeShift, 2)
+    );
+
+    // Fill up the 4 parallel arrays describing the segments.
+    var startCount = [];
+    var endCount = [];
+    var idDeltas = [];
+    var idRangeOffsets = [];
+    var glyphsIdsArray = [];
+    var bias = 0;
+    for (var i = 0; i < segCount - 1; i++) {
       var range = ranges[i];
-      cmap = cmap.concat(FontsUtils.integerToBytes(range[0], 2));
-    };
-    cmap = cmap.concat([0xFF, 0xFF]);
+      var start = FontsUtils.integerToBytes(range[0], 2);
+      var end = FontsUtils.integerToBytes(range[range.length - 1], 2);
 
-    // Fill idDelta
-    var delta = 0;
-    var p = 0;
-    for (var i = 0; i < ranges.length; i++) {
-      var range = ranges[i];
-      var start = range[0];
-      var delta = ((start - 1) - p) % 65536;
+      var delta = FontsUtils.integerToBytes(((range[0] - 1) - bias) % 65536, 2);
+      bias += range.length;
 
-      var value = FontsUtils.integerToBytes(delta, 2);
-      value[0] ^= 0xFF;
-      value[1] ^= 0xFF;
-      value[1] += 1;
-      cmap = cmap.concat([value[0], value[1]]);
+      // deltas are signed shorts
+      delta[0] ^= 0xFF;
+      delta[1] ^= 0xFF;
+      delta[1] += 1;
 
-      p += range.length;
-    };
-    cmap = cmap.concat([0x00, 0x01]);
+      startCount.push(start[0], start[1]);
+      endCount.push(end[0], end[1]);
+      idDeltas.push(delta[0], delta[1]);
+      idRangeOffsets.push(0x00, 0x00);
 
-
-    // Fill id Offsets with 0x00
-    for (var i = 0; i < ranges.length; i++) {
-      var range = ranges[i];
-      cmap = cmap.concat([0x00, 0x00]);
-    };
-    cmap = cmap.concat([0x00, 0x00]);
-
-    var cmapHeader = [
-      0x00, 0x00, // version
-      0x00, 0x01, // numTables
-      0x00, 0x03, // platformID
-      0x00, 0x01, // encodingID
-      0x00, 0x00, 0x00, 0x0C, // start of the table record
-      0x00, 0x04  // format
-    ];
-    cmapHeader = cmapHeader.concat(FontsUtils.integerToBytes(cmap.length + 6, 2)); // length
-    cmapHeader = cmapHeader.concat(0x00, 0x00); // language
-
-    // Fill up data!
-    for (var i = 0; i < ranges.length; i++) {
-      var range = ranges[i];
       for (var j = 0; j < range.length; j++)
-        cmap = cmap.concat(range[j]);
-    };
-    cmap = cmapHeader.concat(cmap);
-    return cmap;
+        glyphsIdsArray.push(range[j]);
+    }
+    startCount.push(0xFF, 0xFF);
+    endCount.push(0xFF, 0xFF);
+    idDeltas.push(0x00, 0x01);
+    idRangeOffsets.push(0x00, 0x00);
+
+    return cmap.concat(endCount, [0x00, 0x00], startCount,
+                       idDeltas, idRangeOffsets, glyphsIdsArray);
   },
 
   cover: function font_cover(aFont) {
@@ -442,7 +431,7 @@ Font.prototype = {
     for (var i = 0; i < currentOffset; i++)
       fontData.push(otf[i]);
 
-    //writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".otf");
+    writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".otf");
     return fontData;
   }
 };