]> git.parisson.com Git - pdf.js.git/commitdiff
Add a basic non-working OTF generator
authorVivien Nicolas <21@vingtetun.org>
Sat, 11 Jun 2011 01:25:58 +0000 (03:25 +0200)
committerVivien Nicolas <21@vingtetun.org>
Sat, 11 Jun 2011 01:25:58 +0000 (03:25 +0200)
PDFFont.js

index b616075e4b3644d1ef5ecd08e681847c4c1b0c32..3dc4d49574209ce2ae6c333f519e2490b146b13c 100644 (file)
@@ -798,6 +798,13 @@ Type1Font.prototype = {
     return bytes;
   },
 
+  bytesToInteger: function(aBytesArray) {
+    var value = 0;
+    for (var i = 0; i < aBytesArray.length; i++)
+      value = (value << 8) + aBytesArray[i];
+    return value;
+  },
+
   encodeNumber: function(aValue) {
     var x = 0;
     // XXX we don't really care about Type2 optimization here...
@@ -835,7 +842,7 @@ Type1Font.prototype = {
       charstringsCount++;
       charstringsDataLength += glyphs[glyph].length;
     }
-    log("There is " + charstringsCount + " glyphs (size: " + charstringsDataLength + ")");
+    //log("There is " + charstringsCount + " glyphs (size: " + charstringsDataLength + ")");
 
     // Create a CFF font data
     var cff = new Uint8Array(20000);
@@ -1021,7 +1028,242 @@ Type1Font.prototype = {
     return data;
   },
 
+
+  createOpenTypeHeader: function(aNumTables) {
+    // sfnt version (4 bytes)
+    var version = [0x4F, 0x54, 0x54, 0X4F];
+
+    // numTables (2 bytes)
+    var numTables = aNumTables;
+
+    // searchRange (2bytes)
+    // XXX oh man this is dirty, there's probably something obvious to do to
+    // quickly get the maximum power of 2 value...
+    var maxPower = 0;
+    var value = numTables;
+    while (value >= 2) {
+      value /= 2;
+      maxPower++;
+    }
+
+    value = 2;
+    for (var i = 1; i < maxPower; i++)
+      value *= 2;
+    var searchRange = value * 16;
+
+    // entrySelector (2 bytes)
+    var entrySelector = Math.log(value) / Math.log(2);
+
+    // rangeShift (2 bytes)
+    var rangeShift = numTables * 16 - searchRange;
+
+    return [].concat(version,
+                     this.integerToBytes(numTables, 2),
+                     this.integerToBytes(searchRange, 2),
+                     this.integerToBytes(entrySelector, 2),
+                     this.integerToBytes(rangeShift, 2));
+  },
+
+  createTableEntry: function(aTag, aOffset, aData) {
+    // tag
+    var tag = [
+      aTag.charCodeAt(0),
+      aTag.charCodeAt(1),
+      aTag.charCodeAt(2),
+      aTag.charCodeAt(3)
+    ];
+
+    // offset
+    var offset = aOffset;
+
+    // length
+    var length = aData.length;
+
+    // checksum
+    var checksum = this.bytesToInteger(tag) + offset + length;
+
+    return [].concat(tag,
+                    this.integerToBytes(checksum, 4),
+                    this.integerToBytes(offset, 4),
+                    this.integerToBytes(length, 4));
+  },
+
   convertToOTF: function(aData, aFont) {
+    var otf = new Uint8Array(20000);
+    var currentOffset = 0;
+
+    var header = this.createOpenTypeHeader(9);
+    otf.set(header, currentOffset);
+    currentOffset += header.length;
+
+    var tablesLength = 9 * 16;
+    var virtualOffset = tablesLength + currentOffset;
+    var tableEntry = this.createTableEntry("CFF ", tablesLength + currentOffset, aData);
+    otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+
+    virtualOffset += aData.length;
+
+    var OS2 = [
+      0x00, 0x03, // version
+      0x02, 0x24, // xAvgCharWidth
+      0x01, 0xF4, // usWeightClass
+      0x00, 0x05, // usWidthClass
+      0x00, 0x00, // fstype
+      0x02, 0x8A, // ySubscriptXSize
+      0x02, 0xBB, // ySubscriptYSize
+      0x00, 0x00, // ySubscriptXOffset
+      0x00, 0x8C, // ySubscriptYOffset
+      0x02, 0x8A, // ySuperScriptXSize
+      0x02, 0xBB, // ySuperScriptYSize
+      0x00, 0x00, // ySuperScriptXOffset
+      0x01, 0xDF, // ySuperScriptYOffset
+      0x00, 0x31, // yStrikeOutSize
+      0x01, 0x02, // yStrikeOutPosition
+      0x00, 0x00, // sFamilyClass
+      0x02, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Panose
+      0x00, 0x00, 0x00, 0x01, // ulUnicodeRange1 (Bits 0-31)
+      0x00, 0x00, 0x00, 0x00, // ulUnicodeRange2 (Bits 32-63)
+      0x00, 0x00, 0x00, 0x00, // ulUnicodeRange3 (Bits 64-95)
+      0x00, 0x00, 0x00, 0x00, // ulUnicodeRange4 (Bits 96-127)
+      0x47, 0x49, 0x60, 0x20, // achVendID
+      0x00, 0x20, // fsSelection
+      0x00, 0x2D, // usFirstCharIndex
+      0x00, 0x7A, // usLastCharIndex
+      0x03, // sTypoAscender
+      0x20, // sTypeDescender
+      0x00, 0x38, // sTypoLineGap
+      0x00, 0x5A, // usWinAscent
+      0x02, 0xB4, // usWinDescent
+      0x00, 0xCE, 0x00, 0x00, // ulCodePageRange1 (Bits 0-31)
+      0x00, 0x01, 0x00, 0x00, // ulCodePageRange2 (Bits 32-63)
+      0x00, // sxHeight
+      0x00, // sCapHeight
+      0x01, // usDefaultChar
+      0xCD, // usBreakChar
+      0x02  // usMaxContext
+    ];
+
+    var tableEntry = this.createTableEntry("OS/2", virtualOffset, OS2);
+    otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+    virtualOffset += OS2.length;
+
+    var cmap = [
+      0x00, 0x00, // version
+      0x00, 0x00 // numTables
+    ];
+
+    var tableEntry = this.createTableEntry("cmap", virtualOffset, cmap);
+    //otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+    virtualOffset += cmap.length;
+
+
+    var name = [
+      0x00, 0x00, // format
+      0x00, 0x00, // Number of names Record
+      0x00, 0x00 // Storage
+    ];
+
+    var tableEntry = this.createTableEntry("name", virtualOffset, name);
+    otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+    virtualOffset += name.length;
+
+
+    var hmtx = [
+      0x01, 0xF4, 0x00,
+      0x00
+    ];
+    var tableEntry = this.createTableEntry("hmtx", virtualOffset, hmtx);
+    otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+    virtualOffset += hmtx.length;
+
+    var maxp = [
+      0x00, 0x00, 0x50, 0x00, // Version number
+      0x00, 0x01 // Nums of glyphs
+    ];
+    var tableEntry = this.createTableEntry("maxp", virtualOffset, maxp);
+    otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+    virtualOffset += maxp.length;
+
+    var head = [
+      0x00, 0x01, 0x00, 0x00, // Version number
+      0x00, 0x00, 0x50, 0x00, // fontRevision
+      0x00, 0x00, 0x00, 0x00, // checksumAdjustement
+      0x5F, 0x0F, 0x3C, 0xF5, // magicNumber
+      0x00, 0x00, // Flags
+      0x00, 0x00, // unitsPerEM
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // created
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // modified
+      0x00, 0x00, // xMin
+      0x00, 0x00, // yMin
+      0x00, 0x00, // xMax
+      0x00, 0x00, // yMax
+      0x00, 0x00, // macStyle
+      0x00, 0x00, // lowestRecPPEM
+      0x00, 0x00, // fontDirectionHint
+      0x00, 0x00, // indexToLocFormat
+      0x00, 0x00 // glyphDataFormat
+    ];
+    var tableEntry = this.createTableEntry("head", virtualOffset, head);
+    otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+    virtualOffset += head.length;
+
+
+    var hhea = [
+      0x00, 0x01, 0x00, 0x00, // Version number
+      0x00, 0x00, // Typographic Ascent
+      0x00, 0x00, // Typographic Descent
+      0x00, 0x00, // Line Gap
+      0x01, 0xF4, // advanceWidthMax
+      0x00, 0x00, // minLeftSidebearing
+      0x00, 0x00, // minRightSidebearing
+      0x00, 0x00, // xMaxExtent
+      0x00, 0x00, // caretSlopeRise
+      0x00, 0x00, // caretOffset
+      0x00, 0x00, // -reserved-
+      0x00, 0x00, // -reserved-
+      0x00, 0x00, // -reserved-
+      0x00, 0x00, // -reserved-
+      0x00, 0x00, // metricDataFormat
+      0x00, 0x01 // numberOfHMetrics
+    ];
+    var tableEntry = this.createTableEntry("hhea", virtualOffset, hhea);
+    otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+    virtualOffset += hhea.length;
+
+
+    var post = [
+      0x00, 0x03, 0x00, 0x00, // Version number
+      0x00, 0x00, 0x01, 0x00, // italicAngle
+      0x00, 0x00, // underlinePosition
+      0x00, 0x00, // underlineThickness
+      0x00, 0x00, 0x00, 0x01, // isFixedPitch
+      0x00, 0x00, 0x00, 0x00, // minMemType42
+      0x00, 0x00, 0x00, 0x00, // maxMemType42
+      0x00, 0x00, 0x00, 0x00, // minMemType1
+      0x00, 0x00, 0x00, 0x00  // maxMemType1
+    ];
+    var tableEntry = this.createTableEntry("post", virtualOffset, post);
+    otf.set(tableEntry, currentOffset);
+    currentOffset += tableEntry.length;
+    virtualOffset += post.length;
+
+    // Set the CFF data
+    otf.set(aData, currentOffset);
+    currentOffset += aData.length;
+
+    var data = [];
+    for (var i = 0; i < currentOffset; i++)
+      data.push(otf[i]);
+
+    writeToFile(data, "/tmp/pdf.js.otf");
   }
 };