FlyUp/packages/字体精简工具/node_modules/fontmin/plugins/svgs2ttf.js
2024-07-10 18:24:08 +08:00

227 lines
4.7 KiB
JavaScript

/**
* @file svgs2ttf
* @author junmer
*/
/* eslint-env node */
var isSvg = require('is-svg');
var through = require('through2');
var path = require('path');
var replaceExt = require('replace-ext');
var ab2b = require('b3b').ab2b;
var _ = require('lodash');
var bufferToVinyl = require('buffer-to-vinyl');
var TTFWriter = require('fonteditor-core').TTFWriter;
var TTF = require('fonteditor-core').TTF;
var svg2ttfobject = require('fonteditor-core').svg2ttfobject;
var getEmptyttfObject = require('fonteditor-core/ttf/getEmptyttfObject');
/**
* SvgFont
*
* @constructor
* @param {string} name filename
* @param {Object} opts opts
*/
function SvgFont(name, opts) {
this.opts = _.extend(
{
adjust: {
leftSideBearing: 0,
rightSideBearing: 0,
ajdustToEmBox: true,
ajdustToEmPadding: 0
},
name: {
fontFamily: name,
fontSubFamily: name,
uniqueSubFamily: name,
postScriptName: name
}
},
opts
);
// empty ttfobj
var ttfobj = getEmptyttfObject();
// for save name
ttfobj.post.format = 2;
// new TTF
this.ttf = new TTF(ttfobj);
// set name
this.ttf.setName(this.opts.name);
// unicode start
this.startCode = opts.startCode || 0xe001;
}
/**
* add svg
*
* @param {string} name svg basename
* @param {buffer} contents svg contents
*/
SvgFont.prototype.add = function (name, contents) {
var ttfObj = svg2ttfobject(
contents.toString('utf-8'),
{
combinePath: true
}
);
var glyf = ttfObj.glyf[0];
glyf.name = path.basename(name, '.svg');
if (!Array.isArray(glyf.unicode)) {
glyf.unicode = [this.startCode++];
}
this.ttf.addGlyf(glyf);
};
/**
* compile ttf contents
*
*/
SvgFont.prototype.compile = function () {
if (this.opts.adjust) {
this.ttf.adjustGlyfPos(null, this.opts.adjust);
this.ttf.adjustGlyf(null, this.opts.adjust);
}
this.contents = ab2b(
new TTFWriter(
this.opts
)
.write(
this.ttf.ttf
)
);
};
/**
* svgs2ttf fontmin plugin
*
* @param {string} file filename
* @param {Object} opts opts
* @param {string} opts.fontName font name
* @return {Object} stream.Transform instance
* @api public
*/
module.exports = function (file, opts) {
if (!file) {
throw new Error('Missing file option for fontmin-svg2ttf');
}
opts = _.extend({hinting: true}, opts);
var firstFile;
var fileName;
var svgFont;
if (typeof file === 'string') {
// fix file ext
file = replaceExt(file, '.ttf');
// set file name
fileName = file;
}
else if (typeof file.path === 'string') {
fileName = path.basename(file.path);
firstFile = bufferToVinyl.file(null, fileName);
}
else {
throw new Error('Missing path in file options for fontmin-svg2ttf');
}
function bufferContents(file, enc, cb) {
// ignore empty files
if (file.isNull()) {
cb();
return;
}
// check stream
if (file.isStream()) {
this.emit('error', new Error('Streaming not supported'));
cb();
return;
}
// check svg
if (!isSvg(file.contents)) {
cb();
return;
}
// set first file if not already set
if (!firstFile) {
firstFile = file;
}
// construct SvgFont instance
if (!svgFont) {
var fontName = opts.fontName || path.basename(fileName, '.ttf');
svgFont = new SvgFont(fontName, opts);
}
// add file to SvgFont instance
svgFont.add(file.relative, file.contents);
cb();
}
function endStream(cb) {
// no files passed in, no file goes out
if (!firstFile || !svgFont) {
cb();
return;
}
var joinedFile;
// if file opt was a file path
// clone everything from the first file
if (typeof file === 'string') {
joinedFile = firstFile.clone({
contents: false
});
joinedFile.path = path.join(firstFile.base, file);
}
else {
joinedFile = firstFile;
}
// complie svgfont
svgFont.compile();
// set contents
joinedFile.contents = svgFont.contents;
joinedFile.ttfObject = svgFont.ttf.ttf;
this.push(joinedFile);
cb();
}
return through.obj(bufferContents, endStream);
};