From cf3218d76560d964788f27fddd4bc97d02ef06fa Mon Sep 17 00:00:00 2001 From: Adrian Leonhard Date: Sat, 18 Aug 2018 20:30:03 +0200 Subject: [PATCH] Add .gitignore. Use versions in package dependencies instead of repos. Generate reader/write from .proto file and use that instead of manually writing buffer. Fix code to work with updated dependencies. Pass font explicitly to glyphToSDF. --- .gitignore | 1 + bin/createsdf | 46 +++++++++++++++++---------------- lib/glyphs_pbf.js | 59 ++++++++++++++++++++++++++++++++++++++++++ lib/sdf.js | 6 ++--- package-lock.json | 65 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 +++-- 6 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 .gitignore create mode 100644 lib/glyphs_pbf.js create mode 100644 package-lock.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/bin/createsdf b/bin/createsdf index 8bb5363..41008c9 100755 --- a/bin/createsdf +++ b/bin/createsdf @@ -6,6 +6,8 @@ var zlib = require('zlib'); var argv = require('minimist')(process.argv.slice(2)); var opentype = require('opentype.js'); var Protobuf = require('pbf'); + +var glyphsPbfIO = require('../lib/glyphs_pbf') var sdf = require('../lib/sdf').glyphToSDF; @@ -62,8 +64,8 @@ if (cluster.isMaster) { }); var basename = fonts.map(function(font) { - return (font.tables.name.preferredFamily || font.tables.name.fontFamily) + ' ' + - (font.tables.name.preferredSubfamily || font.tables.name.fontSubfamily); + return (font.tables.name.preferredFamily.en || font.tables.name.fontFamily.en) + ' ' + + (font.tables.name.preferredSubfamily.en || font.tables.name.fontSubfamily.en); }).join(', '); try { @@ -88,41 +90,41 @@ if (cluster.isMaster) { } + function createGlyphs(from, to, callback) { var out = path.join(basename, from + '-' + to + '.pbf'); console.warn('Generating ' + out); - var fontstack_pbf = new Protobuf(new Buffer(16384)); - fontstack_pbf.writeTaggedString(/* name */ 1, basename); - fontstack_pbf.writeTaggedString(/* range */ 2, from + '-' + to); + var fontstack = { + name: basename, + range: from + '-' + to, + glyphs: [], + } for (var chr = from; chr <= to; chr++) { for (var i = 0; i < fonts.length; i++) { var font = fonts[i]; var glyph = font.charToGlyph(String.fromCharCode(chr)); if (glyph.index > 0) { - var info = sdf(glyph, fontSize, buffer, cutoff); - var glyph_pbf = new Protobuf(new Buffer(512)); - glyph_pbf.writeTaggedVarint(/* id */ 1, chr); - if (info.data) { - glyph_pbf.writeTaggedBuffer(/* bitmap */ 2, new Buffer(info.data)); - } - glyph_pbf.writeTaggedVarint(/* width */ 3, info.glyphWidth); - glyph_pbf.writeTaggedVarint(/* height */ 4, info.glyphHeight); - glyph_pbf.writeTaggedSVarint(/* left */ 5, info.glyphBearingX); - glyph_pbf.writeTaggedSVarint(/* top */ 6, info.glyphTop); - glyph_pbf.writeTaggedVarint(/* advance */ 7, info.glyphAdvance); - - fontstack_pbf.writeMessage(/* glyphs */ 3, glyph_pbf); + var info = sdf(glyph, fontSize, buffer, cutoff, font); + + fontstack.glyphs.push({ + id: chr, + bitmap: info.data && new Buffer(info.data), + width: info.glyphWidth, + height: info.glyphHeight, + left: info.glyphBearingX, + top: info.glyphTop, + advance: info.glyphAdvance + }) break; } } } + var glyphsBuffer = new Protobuf(); + glyphsPbfIO.glyphs.write({ stacks: [fontstack] }, glyphsBuffer); - var glyphs_pbf = new Protobuf(new Buffer(fontstack_pbf.pos + 8)); - glyphs_pbf.writeMessage(/* stacks */ 1, fontstack_pbf); - - zlib.deflate(glyphs_pbf.finish(), function(err, data) { + zlib.deflate(glyphsBuffer.finish(), function(err, data) { if (err) console.warn(err.stack); fs.writeFile(out, data, function(err) { if (err) console.warn(err.stack); diff --git a/lib/glyphs_pbf.js b/lib/glyphs_pbf.js new file mode 100644 index 0000000..883f941 --- /dev/null +++ b/lib/glyphs_pbf.js @@ -0,0 +1,59 @@ +'use strict'; // code generated by pbf v3.1.0 + +// glyph ======================================== + +var glyph = exports.glyph = {}; + +glyph.read = function (pbf, end) { + return pbf.readFields(glyph._readField, {id: 0, bitmap: null, width: 0, height: 0, left: 0, top: 0, advance: 0}, end); +}; +glyph._readField = function (tag, obj, pbf) { + if (tag === 1) obj.id = pbf.readVarint(); + else if (tag === 2) obj.bitmap = pbf.readBytes(); + else if (tag === 3) obj.width = pbf.readVarint(); + else if (tag === 4) obj.height = pbf.readVarint(); + else if (tag === 5) obj.left = pbf.readSVarint(); + else if (tag === 6) obj.top = pbf.readSVarint(); + else if (tag === 7) obj.advance = pbf.readVarint(); +}; +glyph.write = function (obj, pbf) { + if (obj.id) pbf.writeVarintField(1, obj.id); + if (obj.bitmap) pbf.writeBytesField(2, obj.bitmap); + if (obj.width) pbf.writeVarintField(3, obj.width); + if (obj.height) pbf.writeVarintField(4, obj.height); + if (obj.left) pbf.writeSVarintField(5, obj.left); + if (obj.top) pbf.writeSVarintField(6, obj.top); + if (obj.advance) pbf.writeVarintField(7, obj.advance); +}; + +// fontstack ======================================== + +var fontstack = exports.fontstack = {}; + +fontstack.read = function (pbf, end) { + return pbf.readFields(fontstack._readField, {name: "", range: "", glyphs: []}, end); +}; +fontstack._readField = function (tag, obj, pbf) { + if (tag === 1) obj.name = pbf.readString(); + else if (tag === 2) obj.range = pbf.readString(); + else if (tag === 3) obj.glyphs.push(glyph.read(pbf, pbf.readVarint() + pbf.pos)); +}; +fontstack.write = function (obj, pbf) { + if (obj.name) pbf.writeStringField(1, obj.name); + if (obj.range) pbf.writeStringField(2, obj.range); + if (obj.glyphs) for (var i = 0; i < obj.glyphs.length; i++) pbf.writeMessage(3, glyph.write, obj.glyphs[i]); +}; + +// glyphs ======================================== + +var glyphs = exports.glyphs = {}; + +glyphs.read = function (pbf, end) { + return pbf.readFields(glyphs._readField, {stacks: []}, end); +}; +glyphs._readField = function (tag, obj, pbf) { + if (tag === 1) obj.stacks.push(fontstack.read(pbf, pbf.readVarint() + pbf.pos)); +}; +glyphs.write = function (obj, pbf) { + if (obj.stacks) for (var i = 0; i < obj.stacks.length; i++) pbf.writeMessage(1, fontstack.write, obj.stacks[i]); +}; diff --git a/lib/sdf.js b/lib/sdf.js index d8edf04..bc90f46 100644 --- a/lib/sdf.js +++ b/lib/sdf.js @@ -228,9 +228,9 @@ function ringsToSDF(rings, width, height, buffer, cutoff) { return data; } -exports.glyphToSDF = function(glyph, fontSize, buffer, cutoff) { - var fontScale = glyph.font.unitsPerEm / fontSize; - var ascender = Math.round(glyph.font.ascender / fontScale); +exports.glyphToSDF = function(glyph, fontSize, buffer, cutoff, font) { + var fontScale = font.unitsPerEm / fontSize; + var ascender = Math.round(font.ascender / fontScale); var info = { width: 0, diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..89a6bd0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,65 @@ +{ + "name": "fontnik", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "dev": true + }, + "opentype.js": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-0.10.0.tgz", + "integrity": "sha512-1jkmAZYL9FWPHueYYh5OyP+6nYtcubY9CFrYN+RMDBjyWAAGcrVdMeooXfGl8dP+YWc67JYVnZcMyvTU29Bocg==", + "requires": { + "string.prototype.codepointat": "0.2.1", + "tiny-inflate": "1.0.2" + } + }, + "pbf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.1.0.tgz", + "integrity": "sha512-/hYJmIsTmh7fMkHAWWXJ5b8IKLWdjdlAFb3IHkRBn1XUhIYBChVGfVwmHEAV3UfXTxsP/AKfYTXTS/dCPxJd5w==", + "requires": { + "ieee754": "1.1.12", + "resolve-protobuf-schema": "2.1.0" + } + }, + "protocol-buffers-schema": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz", + "integrity": "sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w==" + }, + "rbush": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-1.3.5.tgz", + "integrity": "sha1-GvMSQpLb/I49f0W+QXXyVt981Q4=" + }, + "resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "requires": { + "protocol-buffers-schema": "3.3.2" + } + }, + "string.prototype.codepointat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", + "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" + }, + "tiny-inflate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", + "integrity": "sha1-k9nez/yIBb1X6uQxDwt0Xptvs6c=" + } + } +} diff --git a/package.json b/package.json index 55b750d..42f627d 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,14 @@ "license": "BSD-2-Clause", "main": "lib/sdf.js", "dependencies": { - "opentype.js": "git+https://github.com/nodebox/opentype.js.git", - "pbf": "git+https://github.com/mapbox/pbf.git", + "opentype.js": "^0.10.0", + "pbf": "^3.1.0", "rbush": "~1.3.2" }, "devDependencies": { "minimist": "~0.2.0" + }, + "bin": { + "fontnik": "bin/createsdf" } }