Comparing version 1.0.0 to 1.0.1
@@ -0,1 +1,9 @@ | ||
1.0.1 / 2013-07-24 | ||
------------------ | ||
* Added options support | ||
* Added `ttfinfo` utility | ||
* Multiple fixes | ||
1.0.0 / 2013-07-19 | ||
@@ -2,0 +10,0 @@ ------------------ |
12
index.js
@@ -14,9 +14,13 @@ /* | ||
function svg2ttf(svgString /*, options*/) { | ||
function svg2ttf(svgString, options) { | ||
var font = new sfnt.Font(); | ||
var svgFont = svg.load(svgString); | ||
font.id = svgFont.id; | ||
font.familyName = svgFont.familyName; | ||
font.copyright = svgFont.copyright; | ||
options = options || {}; | ||
font.id = options.id || svgFont.id; | ||
font.familyName = options.familyname || svgFont.familyName || svgFont.id; | ||
font.copyright = options.copyright || svgFont.metadata; | ||
font.sfntNames.push({ id: 2, value: options.subfamilyname || 'Regular' }); // subfamily name | ||
font.sfntNames.push({ id: 4, value: options.fullname || svgFont.id }); // full name | ||
font.sfntNames.push({ id: 5, value: '1.0' }); // version ID for TTF name table | ||
@@ -23,0 +27,0 @@ font.unitsPerEm = svgFont.unitsPerEm; |
@@ -71,3 +71,3 @@ 'use strict'; | ||
var font = { | ||
copyright: metadata.firstChild.data, | ||
metadata: metadata.firstChild.data, | ||
id: fontElem.getAttribute('id') || 'fontello', | ||
@@ -74,0 +74,0 @@ familyName: fontFaceElem.getAttribute('font-family') || 'fontello', |
'use strict'; | ||
var _ = require('lodash'); | ||
var _ = require('lodash'); | ||
var jDataView = require('jDataView'); | ||
var createOS2Table = require('./ttf/tables/os2'); | ||
var createCMapTable = require('./ttf/tables/cmap'); | ||
@@ -15,3 +16,2 @@ var createGlyfTable = require('./ttf/tables/glyf'); | ||
var createPostTable = require('./ttf/tables/post'); | ||
var createOS2Table = require('./ttf/tables/os2'); | ||
@@ -22,2 +22,3 @@ var utils = require('./ttf/utils'); | ||
var TABLES = [ | ||
{ innerName: 0x4f532f32, create: createOS2Table }, //OS/2 | ||
{ innerName: 0x636d6170, create: createCMapTable }, // cmap | ||
@@ -31,4 +32,3 @@ { innerName: 0x676c7966, create: createGlyfTable }, // glyf | ||
{ innerName: 0x6e616d65, create: createNameTable }, // name | ||
{ innerName: 0x706f7374, create: createPostTable }, // post | ||
{ innerName: 0x4f532f32, create: createOS2Table } //OS/2 | ||
{ innerName: 0x706f7374, create: createPostTable } // post | ||
]; | ||
@@ -39,3 +39,2 @@ | ||
VERSION: 0x10000, | ||
TABLE_COUNT: 10, | ||
CHECKSUM_ADJUSTMENT: 0xB1B0AFBA | ||
@@ -55,18 +54,20 @@ }; | ||
var sum = 0; | ||
buf.seek(0); | ||
var len = buf.byteLength; | ||
var nlongs = Math.floor(buf.byteLength / 4); | ||
while (buf.tell() < len) { | ||
sum = ulong(sum + buf.getUint32()); | ||
for (var i = 0; i < nlongs; ++i) { | ||
var t = buf.getUint32(i * 4); | ||
sum = ulong(sum + t); | ||
} | ||
var leftBytes = buf.byteLength - nlongs * 4; //extra 1..3 bytes found, because table is not aligned. Need to include them in checksum too. | ||
if (leftBytes > 0) { | ||
var leftRes = 0; | ||
for (i = 0; i < 4; i++) { | ||
/*jshint bitwise:false*/ | ||
leftRes = (leftRes << 8) + ((i < leftBytes) ? buf.getUint8(nlongs * 4 + i) : 0); | ||
} | ||
sum = ulong(sum + leftRes); | ||
} | ||
return sum; | ||
} | ||
function writeTableHeader(buf, innerName, checkSum, offset, length) { | ||
buf.writeUint32(innerName); //inner name | ||
buf.writeUint32(checkSum); //checksum | ||
buf.writeUint32(offset); //offset | ||
buf.writeUint32(length); //length | ||
} | ||
function generateTTF(font) { | ||
@@ -76,4 +77,4 @@ | ||
// ttf contours are just plain arrays of points | ||
_.forEach(font.glyphs, function(glyph) { | ||
glyph.ttfContours = _.map(glyph.contours, function(contour) { | ||
_.forEach(font.glyphs, function (glyph) { | ||
glyph.ttfContours = _.map(glyph.contours, function (contour) { | ||
return contour.points; | ||
@@ -84,3 +85,3 @@ }); | ||
// Process ttf contours data | ||
_.forEach(font.glyphs, function(glyph) { | ||
_.forEach(font.glyphs, function (glyph) { | ||
@@ -101,21 +102,26 @@ // 0.3px accuracy is ok. fo 1000x1000. | ||
// Add tables | ||
var fullTablesLength = 0; | ||
var headerSize = 12 + 16 * TABLES.length; // TTF header plus table headers | ||
var bufSize = headerSize; | ||
_.forEach(TABLES, function (table) { | ||
//store each table in its own buffer | ||
table.buffer = table.create(font); | ||
fullTablesLength += table.buffer.byteLength; | ||
table.offset = bufSize; | ||
table.length = table.buffer.byteLength; | ||
table.corLength = table.length + (4 - table.length % 4) % 4; // table size should be divisible to 4 | ||
table.checkSum = calc_checksum(table.buffer); | ||
bufSize += table.corLength; | ||
}); | ||
//create TTF buffer | ||
var tablesDataOffset = 4 * 2 + 4 + 4 * 4 * TABLES.length; // TTF header plus table headers | ||
var buf = new jDataView(tablesDataOffset + fullTablesLength); | ||
var buf = new jDataView(bufSize); | ||
//special constants | ||
var entrySelector = Math.floor(Math.log(CONST.TABLE_COUNT, 2)); | ||
var entrySelector = Math.floor(Math.log(TABLES.length)/Math.LN2); | ||
var searchRange = Math.pow(2, entrySelector) * 16; | ||
var rangeShift = CONST.TABLE_COUNT * 16; | ||
var rangeShift = TABLES.length * 16 - searchRange; | ||
// Add TTF header | ||
buf.writeUint32(CONST.VERSION); | ||
buf.writeUint16(CONST.TABLE_COUNT); | ||
buf.writeUint16(TABLES.length); | ||
buf.writeUint16(searchRange); | ||
@@ -125,6 +131,7 @@ buf.writeUint16(entrySelector); | ||
var offset = 0; | ||
_.forEach(TABLES, function (table) { | ||
writeTableHeader(buf, table.innerName, calc_checksum(table.buffer), tablesDataOffset + offset, table.buffer.byteLength); | ||
offset += table.buffer.byteLength; | ||
buf.writeUint32(table.innerName); //inner name | ||
buf.writeUint32(table.checkSum); //checksum | ||
buf.writeUint32(table.offset); //offset | ||
buf.writeUint32(table.length); //length | ||
}); | ||
@@ -138,2 +145,5 @@ | ||
buf.writeBytes(table.buffer.buffer); | ||
for (var i = table.length; i < table.corLength; i++) { //align table to be divisible to 4 | ||
buf.writeUint8(0); | ||
} | ||
}); | ||
@@ -140,0 +150,0 @@ |
@@ -58,10 +58,6 @@ 'use strict'; | ||
function createSubTableHeader (platformID, encodingID) { | ||
var buf = new jDataView(8); //fixed bug size | ||
function writeSubTableHeader (buf, platformID, encodingID, offset) { | ||
buf.writeUint16(platformID); // platform | ||
buf.writeUint16(encodingID); // encoding | ||
buf.writeUint32(0); // offset, just a zero value, it will be filled later | ||
return buf; | ||
buf.writeUint32(offset); // offset | ||
} | ||
@@ -88,9 +84,4 @@ | ||
var glyphs2bytes = _.filter(glyphs, function (glyph) { | ||
return glyph.unicode <= 0xFFFF; | ||
}); | ||
var bufSize = 24; // subtable 4 header and required array elements | ||
bufSize += segments2bytes.length * 8; // subtable 4 segments | ||
bufSize += glyphs2bytes.length * 2; // subtable 4 glyphs | ||
var buf = new jDataView(bufSize); //fixed bug size | ||
@@ -103,5 +94,6 @@ | ||
buf.writeUint16(segCount * 2); // segCountX2 | ||
var searchRange = 2 * Math.floor(Math.log(segCount)); | ||
var maxExponent = Math.floor(Math.log(segCount)/Math.LN2); | ||
var searchRange = 2 * Math.pow(2, maxExponent); | ||
buf.writeUint16(searchRange); // searchRange | ||
buf.writeUint16(Math.round(Math.log(searchRange / 2))); // entrySelector | ||
buf.writeUint16(maxExponent); // entrySelector | ||
buf.writeUint16(2 * segCount - searchRange); // rangeShift | ||
@@ -137,6 +129,4 @@ | ||
//Array of glyph IDs | ||
_.forEach(glyphs2bytes, function (glyph) { | ||
buf.writeUint16(glyph.id); | ||
}); | ||
//Array of glyph IDs should be written here, but it seem to be unuseful when deltas present, at least TTX tool doesn't | ||
// write them. So we omit this array too. | ||
@@ -179,30 +169,11 @@ return buf; | ||
// Create subtable headers. | ||
var subtableHeaderBuffers = []; | ||
//subtables must be sorted by platformID, encodingID | ||
subtableHeaderBuffers.push(createSubTableHeader(0, 3)); // subtable 4, unicode | ||
subtableHeaderBuffers.push(createSubTableHeader(1, 0)); // subtable 0, mac standard | ||
subtableHeaderBuffers.push(createSubTableHeader(3, 1)); // subtable 4, windows standard | ||
if (segments4bytes) { | ||
subtableHeaderBuffers.push(createSubTableHeader(3, 10)); // subtable 12 | ||
} | ||
// Create subtables first. | ||
var subTable0 = createSubTable0(font.glyphs); // subtable 0 | ||
var subTable4 = createSubTable4(font.glyphs, segments2bytes); // subtable 4 | ||
var subTable12 = segments4bytes ? createSubTable12(segments4bytes) : null; // subtable 12 | ||
// Create subtables. | ||
var subTableBuffers = []; | ||
subTableBuffers.push(createSubTable4(font.glyphs, segments2bytes)); // subtable 4 | ||
subTableBuffers.push(createSubTable0(font.glyphs)); // subtable 0 | ||
subTableBuffers.push(createSubTable4(font.glyphs, segments2bytes)); // subtable 4 again | ||
if (segments4bytes) { | ||
subTableBuffers.push(createSubTable12(segments4bytes)); // subtable 12 | ||
} | ||
// Calculate bufsize | ||
var subTableOffset = 4 + (subTable12 ? 32 : 24); | ||
var bufSize = subTableOffset + subTable0.byteLength + subTable4.byteLength + (subTable12 ? subTable12.byteLength : 0); | ||
// Calculate table size | ||
var bufSize = 4; | ||
var i; | ||
for (i = 0; i < subtableHeaderBuffers.length; i++) { | ||
bufSize += subtableHeaderBuffers[i].byteLength; | ||
bufSize += subTableBuffers[i].byteLength; | ||
} | ||
bufSize += (4 - bufSize % 4) % 4; // length of a table must be a multiple of four bytes | ||
var buf = new jDataView(bufSize); | ||
@@ -214,25 +185,17 @@ | ||
// Write table headers | ||
for (i = 0; i < subtableHeaderBuffers.length; i++) { | ||
buf.writeBytes(subtableHeaderBuffers[i].buffer); | ||
// Create subtable headers. Subtables must be sorted by platformID, encodingID | ||
writeSubTableHeader(buf, 0, 3, subTableOffset); // subtable 4, unicode | ||
writeSubTableHeader(buf, 1, 0, subTableOffset + subTable4.byteLength); // subtable 0, mac standard | ||
writeSubTableHeader(buf, 3, 1, subTableOffset); // subtable 4, windows standard | ||
if (subTable12) { | ||
writeSubTableHeader(buf, 3, 10, subTableOffset + subTable0.byteLength + subTable4.byteLength); // subtable 12 | ||
} | ||
var tableOffsets = []; | ||
// Write tables | ||
for (i = 0; i < subTableBuffers.length; i++) { | ||
tableOffsets.push(buf.tell()); | ||
buf.writeBytes(subTableBuffers[i].buffer); | ||
// Write tables, order of table seem to be magic, it is taken from TTX tool | ||
buf.writeBytes(subTable4.buffer); | ||
buf.writeBytes(subTable0.buffer); | ||
if (subTable12) { | ||
buf.writeBytes(subTable12.buffer); | ||
} | ||
// Fill left space with zeros | ||
while (buf.tell() < bufSize) { | ||
buf.writeUint8(0); | ||
} | ||
// Write table offsets | ||
for (i = 0; i < subtableHeaderBuffers.length; i++) { | ||
buf.setUint32(8 + i * 8, tableOffsets[i]); | ||
} | ||
return buf; | ||
@@ -239,0 +202,0 @@ } |
@@ -14,3 +14,3 @@ 'use strict'; | ||
var buf = new jDataView(56); // fixed table length | ||
var buf = new jDataView(54); // fixed table length | ||
@@ -38,3 +38,2 @@ buf.writeInt32(0x10000); // version | ||
buf.writeInt16(0); // glyphDataFormat | ||
buf.writeInt16(0); // 2 bytes to align table | ||
@@ -41,0 +40,0 @@ return buf; |
@@ -25,3 +25,3 @@ 'use strict'; | ||
buf.writeInt16(0); // metricDataFormat | ||
buf.writeUint16(font.glyphs.length); // numberOfHMetrics | ||
buf.writeUint16(font.glyphs.length); // numberOfHMetrics, missed glyph is empty and excluded from this property | ||
@@ -28,0 +28,0 @@ return buf; |
@@ -10,3 +10,3 @@ 'use strict'; | ||
var buf = new jDataView(font.glyphs.length * 4); | ||
var buf = new jDataView(font.glyphs.length * 4 + 2); | ||
@@ -17,3 +17,2 @@ _.forEach(font.glyphs, function (glyph) { | ||
}); | ||
return buf; | ||
@@ -20,0 +19,0 @@ } |
@@ -10,3 +10,2 @@ 'use strict'; | ||
var result = (font.glyphs.length + 1) * (isShortFormat ? 2 : 4); // by glyph count + tail | ||
result += (4 - result % 4) % 4; // length of a table must be a multiple of four bytes | ||
return result; | ||
@@ -19,4 +18,3 @@ } | ||
var bufSize = tableSize(font, isShortFormat); | ||
var buf = new jDataView(bufSize); | ||
var buf = new jDataView(tableSize(font, isShortFormat)); | ||
@@ -41,7 +39,2 @@ var location = 0; | ||
// Fill left space with zeros | ||
while (buf.tell() < bufSize) { | ||
buf.writeUint8(0); | ||
} | ||
return buf; | ||
@@ -48,0 +41,0 @@ } |
@@ -22,3 +22,2 @@ 'use strict'; | ||
}); | ||
result += (4 - result % 4) % 4; // length of a table must be a multiple of four bytes | ||
return result; | ||
@@ -72,4 +71,3 @@ } | ||
var bufSize = tableSize(names); | ||
var buf = new jDataView(bufSize); | ||
var buf = new jDataView(tableSize(names)); | ||
@@ -100,7 +98,2 @@ buf.writeUint16(0); // formatSelector | ||
// Fill left space with zeros | ||
while (buf.tell() < bufSize) { | ||
buf.writeUint8(0); | ||
} | ||
return buf; | ||
@@ -107,0 +100,0 @@ } |
@@ -32,3 +32,3 @@ 'use strict'; | ||
var buf = new jDataView(88); // fixed table length | ||
var buf = new jDataView(86); | ||
@@ -78,3 +78,2 @@ buf.writeUint16(1); //version | ||
buf.writeInt32(0); // ulCodePageRange2 | ||
buf.writeInt16(0); // 2 bytes to align table | ||
@@ -81,0 +80,0 @@ return buf; |
@@ -14,3 +14,2 @@ 'use strict'; | ||
}); | ||
result += (4 - result % 4) % 4; // length of a table must be a multiple of four bytes | ||
return result; | ||
@@ -36,4 +35,3 @@ } | ||
var bufSize = tableSize(font, names); | ||
var buf = new jDataView(bufSize); | ||
var buf = new jDataView(tableSize(font, names)); | ||
@@ -64,7 +62,2 @@ buf.writeInt32(0x20000); // formatType, version 2.0 | ||
// Fill left space with zeros | ||
while (buf.tell() < bufSize) { | ||
buf.writeUint8(0); | ||
} | ||
return buf; | ||
@@ -71,0 +64,0 @@ } |
{ | ||
"name" : "svg2ttf", | ||
"version" : "1.0.0", | ||
"version" : "1.0.1", | ||
@@ -17,13 +17,14 @@ "description" : "Convert SVG graphics to TTF font", | ||
"type": "MIT", | ||
"url": "https://github.com/fontello/ttf2eot/raw/master/LICENSE" | ||
"url": "https://github.com/fontello/svg2ttf/raw/master/LICENSE" | ||
} | ||
], | ||
"dependencies" : { "argparse": "~0.1.12", | ||
"lodash": "~ 1.2.1", | ||
"xmldom": "~ 0.1.5", | ||
"jDataView": "~ 2.2.1" | ||
"dependencies" : { | ||
"argparse": "~ 0.1.15", | ||
"lodash": "~ 1.3.1", | ||
"xmldom": "~ 0.1.16", | ||
"jDataView": "~ 2.2.4" | ||
}, | ||
"repository" : { | ||
"repository" : { | ||
"type": "git", | ||
@@ -30,0 +31,0 @@ "url": "git://github.com/fontello/svg2ttf.git" |
@@ -30,2 +30,11 @@ #!/usr/bin/env node | ||
parser.addArgument( | ||
['-d', '--details'], | ||
{ | ||
help: 'Show table dump', | ||
action: 'storeTrue', | ||
required: false | ||
} | ||
); | ||
var args = parser.parseArgs(); | ||
@@ -63,2 +72,20 @@ var ttf; | ||
console.log("- %s: %d bytes (%d offset)", info.name, info.length, info.offset); | ||
if (args.details) { | ||
var bufTable = ttf.slice(info.offset, info.offset + info.length); | ||
var count = Math.floor(bufTable.length / 32); | ||
var offset = 0; | ||
//split buffer to the small chunks to fit the screen | ||
for (var i = 0; i < count; i++) { | ||
console.log(bufTable.slice(offset, offset + 32)); | ||
offset += 32; | ||
} | ||
//output the rest | ||
if (offset < (info.length)) { | ||
console.log(bufTable.slice(offset, info.length)); | ||
} | ||
console.log(""); | ||
} | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
76886
1867
+ Addedlodash@1.3.1(transitive)
- Removedlodash@1.2.1(transitive)
Updatedargparse@~ 0.1.15
UpdatedjDataView@~ 2.2.4
Updatedlodash@~ 1.3.1
Updatedxmldom@~ 0.1.16