diff --git a/README.md b/README.md index 862b197..847550c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# fonteditor-core +# fonteditor-core -**font editor core functions** +**FontEditor core functions** [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] @@ -9,7 +9,7 @@ ## Feature - sfnt parse -- read, write, transform fonts (ttf, woff, eot, svg, otf) +- read, write, transform fonts (ttf, woff, eot, svg, otf) - ttf glyph adjust - svg to glyph @@ -17,17 +17,21 @@ ```js // read font file +var Font = require('fonteditor-core').Font; var fs = require('fs'); -var bufferToArrayBuffer = require('b3b').bufferToArrayBuffer; -var fontBuffer = fs.readFileSync('font.ttf'); -var fontArrayBuffer = bufferToArrayBuffer(fontBuffer); +var buffer = fs.readFileSync('font.ttf'); // read font data -var TTFReader = require('fonteditor-core').TTFReader; -var ttfReader = new TTFReader({ hinting: true }); -var fontData = ttfReader.read(fontArrayBuffer); - -console.log(Object.keys(fontData)); +var font = Font.create(buffer, { + type: 'ttf', // support ttf,woff,eot,otf,svg + subset: [65, 66], // only read `a`, `b` glyf + hinting: true, // save font hinting + compound2simple: true, // transform ttf compound glyf to simple + inflate: null, // inflate function for woff + combinePath: false, // for svg path +}); +var fontObject = font.get(); +console.log(Object.keys(fontObject)); /* => [ 'version', 'numTables', 'searchRenge', @@ -47,6 +51,43 @@ console.log(Object.keys(fontData)); ] */ +// write font file +var buffer = font.write({ + type: 'woff', // support ttf,woff,eot,otf,svg + hinting: true, // save font hinting + deflate: null, // deflate function for woff +}); +// fs.writeFileSync('font.woff', buffer); + +// to base64 str +font.toBase64({ + type: 'ttf' // support ttf,woff,eot,svg +}); + +// optimize glyf +font.optimize() + +// compound2simple +font.compound2simple() + +// sort glyf +font.sort() + +// find glyf +var result = font.find({ + unicode: [65] +}); +var result = font.find({ + filter: function (glyf) { + return glyf.name == 'icon' + } +}); + +// merge another font object +font.merge(font1, { + scale: 1 +}); + ``` ## Demo diff --git a/package.json b/package.json index 4f1d513..623a3bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fonteditor-core", - "version": "0.0.18", + "version": "0.0.20", "description": "fonts (ttf, woff, eot, svg, otf) parse, write, transform. glyph adjust.", "keywords": [ "sfnt", @@ -34,7 +34,8 @@ ], "scripts": { "npm_publish": "sh tool/publish-node.sh", - "test": "phantomjs test/run-jasmine.js test/SpecRunner.html" + "test": "phantomjs test/run-jasmine.js test/SpecRunner.html", + "test_node": "sh tool/test-node.sh" }, "edp": { "main": "src/main", @@ -52,6 +53,7 @@ "graphics", "math", "ttf", + "nodejs", "main.js" ], "main": "main.js", diff --git a/src/main.js b/src/main.js index 9380103..83c3a73 100644 --- a/src/main.js +++ b/src/main.js @@ -7,6 +7,7 @@ define( function (require) { return { + Font: require('./ttf/font'), TTF: require('./ttf/ttf'), TTFReader: require('./ttf/ttfreader'), TTFWriter: require('./ttf/ttfwriter'), diff --git a/src/nodejs/buffer.js b/src/nodejs/buffer.js new file mode 100644 index 0000000..fcdb4d8 --- /dev/null +++ b/src/nodejs/buffer.js @@ -0,0 +1,60 @@ +/** + * @file Buffer和ArrayBuffer转换 + * @author mengke01(kekee000@gmail.com) + */ + +/** + * Buffer转换成ArrayBuffer + * + * @param {Buffer} buffer 缓冲数组 + * @return {ArrayBuffer} + */ +function toArrayBuffer(buffer) { + var length = buffer.length; + var view = new DataView(new ArrayBuffer(length), 0, length); + for (var i = 0, l = length; i < l; i++) { + view.setUint8(i, buffer[i], false); + } + return view.buffer; +} + +/** + * ArrayBuffer转换成Buffer + * + * @param {ArrayBuffer} arrayBuffer 缓冲数组 + * @return {Buffer} + */ +function toBuffer(arrayBuffer) { + if (Array.isArray(arrayBuffer)) { + return new Buffer(arrayBuffer); + } + else { + var length = arrayBuffer.byteLength; + var view = new DataView(arrayBuffer, 0, length); + var buffer = new Buffer(length); + for (var i = 0, l = length; i < l; i++) { + buffer[i] = view.getUint8(i, false); + } + } + + return buffer; +} + +if (typeof exports !== 'undefined') { + module.exports = { + toArrayBuffer: toArrayBuffer, + toBuffer: toBuffer + }; +} +else { + define( + function (require) { + return { + toArrayBuffer: toArrayBuffer, + toBuffer: toBuffer + }; + } + ); +} + + diff --git a/src/ttf/font.js b/src/ttf/font.js new file mode 100644 index 0000000..b6bd0f1 --- /dev/null +++ b/src/ttf/font.js @@ -0,0 +1,326 @@ +/** + * @file 字体管理对象,处理字体相关的读取、查询、转换 + * + * @author mengke01(kekee000@gmail.com) + */ + + +define(function (require) { + var lang = require('../common/lang'); + var bufferTool = require('../nodejs/buffer'); + + var getEmptyttfObject = require('./getEmptyttfObject'); + var TTF = require('./ttf'); + + var woff2ttf = require('./woff2ttf'); + var otf2ttfobject = require('./otf2ttfobject'); + var eot2ttf = require('./eot2ttf'); + var svg2ttfobject = require('./svg2ttfobject'); + var TTFReader = require('./ttfreader'); + + var TTFWriter = require('./ttfwriter'); + var ttf2eot = require('./ttf2eot'); + var ttf2woff = require('./ttf2woff'); + var ttf2svg = require('./ttf2svg'); + + var ttf2base64 = require('./ttf2base64'); + var eot2base64 = require('./eot2base64'); + var woff2base64 = require('./woff2base64'); + var svg2base64 = require('./svg2base64'); + + var optimizettf = require('./util/optimizettf'); + + /** + * 字体对象构造函数 + * + * @param {ArrayBuffer|Buffer|string} buffer 字体数据 + * @param {Object} options 读取参数 + */ + function Font(buffer, options) { + options = options || { + type: 'ttf' + }; + + // 字形对象 + if (typeof buffer === 'object' && buffer.glyf) { + this.set(buffer); + } + // buffer + else if (buffer) { + this.read(buffer, options); + } + // 空 + else { + this.readEmpty(); + } + } + + /** + * 创建一个空的ttfObject对象 + * + * @return {Font} + */ + Font.prototype.readEmpty = function () { + this.data = getEmptyttfObject(); + return this; + }; + + /** + * 读取字体数据 + * + * @param {ArrayBuffer|Buffer|string} buffer 字体数据 + * @param {Object} options 读取参数 + * @param {string} options.type 字体类型 + * + * ttf, woff , eot 读取配置 + * @param {boolean} options.hinting 保留hinting信息 + * @param {boolean} options.compound2simple 复合字形转简单字形 + * + * woff 读取配置 + * @param {Object} options.inflate 解压相关函数 + * + * svg 读取配置 + * @param {boolean} options.combinePath 是否合并成单个字形,仅限于普通svg导入 + * @return {Font} + */ + Font.prototype.read = function (buffer, options) { + // nodejs buffer + if (typeof Buffer === 'function') { + if (buffer instanceof Buffer) { + buffer = bufferTool.toArrayBuffer(buffer); + } + } + + if (options.type === 'ttf') { + this.data = new TTFReader(options).read(buffer); + } + else if (options.type === 'otf') { + this.data = otf2ttfobject(buffer, options); + } + else if (options.type === 'eot') { + buffer = eot2ttf(buffer, options); + this.data = new TTFReader(options).read(buffer); + } + else if (options.type === 'woff') { + buffer = woff2ttf(buffer, options); + this.data = new TTFReader(options).read(buffer); + } + else if (options.type === 'svg') { + this.data = svg2ttfobject(buffer, options); + } + else { + throw new Error('not support font type' + options.type); + } + + this.type = options.type; + return this; + }; + + /** + * 写入字体数据 + * + * @param {Object} options 写入参数 + * @param {string} options.type 字体类型, 默认 ttf + * @param {boolean} options.toBuffer nodejs 环境中返回 Buffer 对象, 默认 true + * + * ttf 字体参数 + * @param {boolean} options.hinting 保留hinting信息 + * + * svg,woff 字体参数 + * @param {Object} options.metadata 字体相关的信息 + * + * woff 字体参数 + * @param {Object} options.deflate 压缩相关函数 + * @return {Buffer|ArrayBuffer|string} + */ + Font.prototype.write = function (options) { + options = options || {}; + if (!options.type) { + options.type = this.type; + } + + var buffer = null; + if (options.type === 'ttf') { + buffer = new TTFWriter(options).write(this.data); + } + else if (options.type === 'eot') { + buffer = new TTFWriter(options).write(this.data); + buffer = ttf2eot(buffer, options); + } + else if (options.type === 'woff') { + buffer = new TTFWriter(options).write(this.data); + buffer = ttf2woff(buffer, options); + } + else if (options.type === 'svg') { + buffer = ttf2svg(this.data, options); + } + else { + throw new Error('not support font type' + options.type); + } + + if (typeof Buffer === 'function') { + if (false !== options.toBuffer && buffer instanceof ArrayBuffer) { + buffer = bufferTool.toBuffer(buffer); + } + } + + return buffer; + }; + + /** + * 转换成 base64编码 + * + * @param {Object} options 写入参数 + * @param {string} options.type 字体类型, 默认 ttf + * 其他 options参数, 参考 write + * @see Font.prototype.write + * + * @param {ArrayBuffer} buffer 如果提供了buffer数据则使用 buffer数据, 否则转换现有的 font + * @return {Buffer|ArrayBuffer|string} + */ + Font.prototype.toBase64 = function (options, buffer) { + options = options || {}; + if (!options.type) { + options.type = this.type; + } + + if (buffer) { + if (typeof Buffer === 'function') { + if (buffer instanceof Buffer) { + buffer = bufferTool.toArrayBuffer(buffer); + } + } + } + else { + options.toBuffer = false; + buffer = this.write(options); + } + + var base64Str; + if (options.type === 'ttf') { + base64Str = ttf2base64(buffer); + } + else if (options.type === 'eot') { + base64Str = eot2base64(buffer); + } + else if (options.type === 'woff') { + base64Str = woff2base64(buffer); + } + else if (options.type === 'svg') { + base64Str = svg2base64(buffer); + } + else { + throw new Error('not support font type' + options.type); + } + + return base64Str; + }; + + /** + * 设置 font 对象 + * + * @return {Object} ttfObject 对象 + */ + Font.prototype.set = function (data) { + this.data = data; + return this; + }; + + /** + * 获取 font 数据 + * + * @return {Object} ttfObject 对象 + */ + Font.prototype.get = function () { + return this.data; + }; + + /** + * 对字形数据进行优化 + * + * @param {Object} out 输出结果 + * @param {boolean|Object} out.result `true` 或者有问题的地方 + * @return {Font} + */ + Font.prototype.optimize = function (out) { + var result = optimizettf(this.data); + if (out) { + out.result = result; + } + return this; + }; + + /** + * 将字体中的复合字形转为简单字形 + * + * @return {this} + */ + Font.prototype.compound2simple = function () { + var ttf = new TTF(this.data); + ttf.compound2simple(); + this.data = ttf.get(); + return this; + }; + + /** + * 对字形按照unicode编码排序 + * + * @return {this} + */ + Font.prototype.sort = function () { + var ttf = new TTF(this.data); + ttf.sortGlyf(); + this.data = ttf.get(); + return this; + }; + + /** + * 查找相关字形 + * + * @param {Object} condition 查询条件 + * @param {Array|number} condition.unicode unicode编码列表或者单个unicode编码 + * @param {string} condition.name glyf名字,例如`uniE001`, `uniE` + * @param {Function} condition.filter 自定义过滤器 + * @example + * condition.filter = function (glyf) { + * return glyf.name === 'logo'; + * } + * @return {Array} glyf字形列表 + */ + Font.prototype.find = function (condition) { + var ttf = new TTF(this.data); + var indexList = ttf.findGlyf(condition); + return indexList.length ? ttf.getGlyf(indexList) : indexList; + }; + + /** + * 合并 font 到当前的 font + * + * @param {Object} font Font 对象 + * @param {Object} options 参数选项 + * @param {boolean} options.scale 是否自动缩放 + * @param {boolean} options.adjustGlyf 是否调整字形以适应边界 + * (和 options.scale 参数互斥) + * + * @return {Font} + */ + Font.prototype.merge = function (font, options) { + var ttf = new TTF(this.data); + ttf.mergeGlyf(font.get(), options); + this.data = ttf.get(); + return this; + }; + + /** + * 读取字体数据 + * + * @param {ArrayBuffer|Buffer|string} buffer 字体数据 + * @param {Object} options 读取参数 + * @return {Font} + */ + Font.create = function (buffer, options) { + return new Font(buffer, options); + }; + + return Font; +}); diff --git a/src/ttf/ttf.js b/src/ttf/ttf.js index 09489e9..7c12e55 100644 --- a/src/ttf/ttf.js +++ b/src/ttf/ttf.js @@ -120,13 +120,16 @@ define( * @param {Object} ttf ttfObject * @param {Object} imported ttfObject * @param {Object} options 参数选项 - * @param {boolean} options.scale 是否自动缩放 + * @param {boolean} options.scale 是否自动缩放,默认true * @param {boolean} options.adjustGlyf 是否调整字形以适应边界 + * (与 options.scale 互斥) * * @return {Object} 合并后的ttfObject */ function merge(ttf, imported, options) { - options = options || {}; + options = options || { + scale: true + }; var list = imported.glyf.filter(function (g, index) { // 简单轮廓 @@ -280,6 +283,8 @@ define( * @param {Object} imported ttfObject * @param {Object} options 参数选项 * @param {boolean} options.scale 是否自动缩放 + * @param {boolean} options.adjustGlyf 是否调整字形以适应边界 + * (和 options.scale 参数互斥) * * @return {Array} 添加的glyf */ @@ -461,6 +466,9 @@ define( * * @param {Array=} indexList 索引列表 * @param {Object} setting 选项 + * @param {number=} setting.leftSideBearing 左边距 + * @param {number=} setting.rightSideBearing 右边距 + * @param {number=} setting.verticalAlign 垂直对齐 * @return {Array} 改变的glyf */ TTF.prototype.adjustGlyfPos = function (indexList, setting) { @@ -481,6 +489,11 @@ define( * * @param {Array=} indexList 索引列表 * @param {Object} setting 选项 + * @param {boolean=} setting.reverse 字形反转操作 + * @param {boolean=} setting.mirror 字形镜像操作 + * @param {number=} setting.scale 字形缩放 + * @param {boolean=} setting.ajdustToEmBox 是否调整字形到 em 框 + * @param {number=} setting.ajdustToEmPadding 调整到 em 框的留白 * @return {boolean} */ TTF.prototype.adjustGlyf = function (indexList, setting) { @@ -554,8 +567,12 @@ define( * @param {Object} condition 查询条件 * @param {Array|number} condition.unicode unicode编码列表或者单个unicode编码 * @param {string} condition.name glyf名字,例如`uniE001`, `uniE` - * - * @return {Array} glyf字形列表 + * @param {Function} condition.filter 自定义过滤器 + * @example + * condition.filter = function (glyf) { + * return glyf.name === 'logo'; + * } + * @return {Array} glyf字形索引列表 */ TTF.prototype.findGlyf = function (condition) { if (!condition) { diff --git a/src/ttf/util/optimizettf.js b/src/ttf/util/optimizettf.js index d878cfd..55e4adc 100644 --- a/src/ttf/util/optimizettf.js +++ b/src/ttf/util/optimizettf.js @@ -39,12 +39,10 @@ define( } if (!glyf.compound && glyf.contours) { - // 整数化 glyf.contours.forEach(function (contour) { pathCeil(contour); }); - // 缩减glyf reduceGlyf(glyf); } @@ -58,10 +56,14 @@ define( glyf.advanceWidth = Math.round(glyf.advanceWidth || 0); }); - // 过滤无轮廓字体 - ttf.glyf = ttf.glyf.filter(function (glyf, index) { - return index === 0 || glyf.contours && glyf.contours.length; - }); + // 过滤无轮廓字体,如果存在复合字形不进行过滤 + if (!ttf.glyf.some(function (a) { + return a.compound; + })) { + ttf.glyf = ttf.glyf.filter(function (glyf, index) { + return index === 0 || glyf.contours && glyf.contours.length; + }); + } if (!repeatList.length) { return true; diff --git a/test/node-spec/font.spec.js b/test/node-spec/font.spec.js new file mode 100644 index 0000000..e92505e --- /dev/null +++ b/test/node-spec/font.spec.js @@ -0,0 +1,45 @@ + +var fs = require('fs'); +var Font = require('./fonteditor-core').Font; +var assert = require('assert'); + +function readttf(file) { + return fs.readFileSync(file); +} + +function writettf(buffer) { + var font = Font.create(buffer, { + type: 'ttf' + }); + + assert(font.data.name.fontFamily === 'Bebas', 'test read ttf'); + + + var ttfBuffer = font.write(); + + // 写ttf + assert(ttfBuffer.length, 'test write ttf'); + + // 写eot + var eotBuffer = font.write({ + type: 'eot' + }); + assert(eotBuffer.length, 'test write eot'); + + // 写woff + var woffBuffer = font.write({ + type: 'woff' + }); + assert(woffBuffer, 'test write woff'); + + // 写svg + var svg = font.write({ + type: 'svg' + }); + assert(svg.length, 'test write svg'); + +} + +var buffer = readttf(__dirname + '/../data/bebas.ttf'); + +writettf(buffer); diff --git a/test/node-spec/main.js b/test/node-spec/main.js new file mode 100644 index 0000000..04e5111 --- /dev/null +++ b/test/node-spec/main.js @@ -0,0 +1,12 @@ +/** + * @file node 测试 + * @author mengke01(kekee000@gmail.com) + */ + +require('./adjustttf.spec'); +require('./font.spec'); +require('./otf2ttf.spec'); +require('./readotf.spec'); +require('./readttf.spec'); +require('./svg2ttf.spec'); +require('./writettf.spec'); diff --git a/test/node-spec/writettf.spec.js b/test/node-spec/writettf.spec.js index 3920965..6857297 100644 --- a/test/node-spec/writettf.spec.js +++ b/test/node-spec/writettf.spec.js @@ -19,26 +19,26 @@ function writettf(buffer) { var ttfObject = new TTFReader().read(buffer); - assert(ttfObject.name.fontFamily === 'Bebas', 'test writettf'); + assert(ttfObject.name.fontFamily === 'Bebas', 'test read ttf'); assert(JSON.stringify(ttfObject), 'test writettf'); var ttfBuffer = new TTFWriter().write(ttfObject); // 写ttf - assert(util.toBuffer(ttfBuffer).length, 'test writettf'); + assert(util.toBuffer(ttfBuffer).length, 'test write ttf'); // 写eot var eotBuffer = ttf2eot(buffer); - assert(util.toBuffer(eotBuffer).length, 'test writettf'); + assert(util.toBuffer(eotBuffer).length, 'test write eot'); // 写woff var woffBuffer = ttf2woff(buffer); - assert(util.toBuffer(woffBuffer).length, 'test writettf'); + assert(util.toBuffer(woffBuffer).length, 'test write woff'); // 写svg var svg = ttf2svg(ttfObject); - assert(svg.length, 'test writettf'); + assert(svg.length, 'test write svg'); } diff --git a/test/spec/main.js b/test/spec/main.js index f2470d4..15bb209 100644 --- a/test/spec/main.js +++ b/test/spec/main.js @@ -30,5 +30,6 @@ define( require('./ttf/eot2ttf.spec'); require('./ttf/svg2ttfobject.spec'); require('./ttf/ttf2svg.spec'); + require('./ttf/font.spec'); } ); diff --git a/test/spec/ttf/font.spec.js b/test/spec/ttf/font.spec.js new file mode 100644 index 0000000..bc664cb --- /dev/null +++ b/test/spec/ttf/font.spec.js @@ -0,0 +1,328 @@ + +define( + function (require) { + + var Font = require('ttf/font'); + + describe('测试 Font 对象============================', function () { + it('test create empty', function () { + var font = Font.create(); + expect(font.data.version).toBe(1); + expect(font.data.glyf.length).toBe(1); + }); + + it('test create by object', function () { + var font = Font.create({ + version: 1, + glyf: [] + }); + expect(font.data.version).toBe(1); + expect(font.data.glyf.length).toBe(0); + }); + }); + + describe('读ttf数据', function () { + var font = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }); + it('test read ttf', function () { + expect(font.data.version).toBe(1); + expect(font.data.numTables).toBe(15); + }); + }); + + describe('转换compound到simple', function () { + var font = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf', + compound2simple: true + }); + it('test read ttf glyf', function () { + expect(!!font.data.glyf[16].compound).toBe(false); + expect(!!font.data.glyf[16].glyfs).toBe(false); + expect(font.data.glyf[16].contours.length).toBe(4); + }); + }); + + describe('读otf数据', function () { + var font = Font.create(require('data/BalladeContour.otf'), { + type: 'otf' + }); + it('test read otf', function () { + expect(font.data.version).toBe(0x1); + expect(font.data.numTables).toBe(9); + expect(font.data.rengeShift).toBe(16); + expect(font.data.searchRenge).toBe(128); + }); + }); + + describe('读取 woff 数据', function () { + var buffer = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).write({ + type: 'woff' + }); + var font = Font.create(buffer, { + type: 'woff' + }); + + it('test read woff', function () { + expect(font.data.version).toBe(1); + expect(font.data.head.magickNumber).toBe(1594834165); + expect(font.data.head.unitsPerEm).toBe(512); + }); + }); + + describe('读取 eot 数据', function () { + var buffer = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).write({ + type: 'eot' + }); + var font = Font.create(buffer, { + type: 'eot' + }); + + it('test read eot', function () { + expect(font.data.version).toBe(1); + expect(font.data.head.magickNumber).toBe(1594834165); + expect(font.data.head.unitsPerEm).toBe(512); + }); + }); + + describe('读取 svg 文件', function () { + var font = Font.create(require('data/iconfont-xin.svg'), { + type: 'svg' + }); + it('test read svg', function () { + expect(font.data.from).toBe('svg'); + expect(font.data.glyf.length).toBe(2); + expect(font.data.glyf[0].contours.length).toBe(7); + expect(font.data.glyf[1].contours.length).toBe(1); + }); + }); + + describe('读取 svg 字体', function () { + var font = Font.create(require('data/icomoon.svg'), { + type: 'svg' + }); + it('test read svg font', function () { + expect(font.data.from).toBe('svgfont'); + expect(font.data.id).toBe('icomoon'); + expect(font.data.name.fontFamily).toBe('icomoon'); + expect(font.data.metadata).toBe('Generated by IcoMoon'); + }); + + it('test svg font glyf', function () { + expect(font.data.glyf.length).toBe(3); + expect(font.data.glyf[2].leftSideBearing).toBe(0); + expect(font.data.glyf[2].advanceWidth).toBe(1024); + expect(font.data.glyf[2].contours.length).toBe(7); + expect(font.data.glyf[2].unicode[0]).toBe(57345); + }); + }); + + + + describe('写ttf数据', function () { + + it('test write ttf', function () { + var buffer = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).write(); + expect(buffer.byteLength).toBeGreaterThan(1000); + expect(buffer.byteLength).toBeLessThan(10000); + + var font = Font.create(buffer, { + type: 'ttf' + }); + expect(font.data.version).toBe(1); + expect(font.data.head.magickNumber).toBe(1594834165); + expect(font.data.head.unitsPerEm).toBe(512); + }); + + it('test write ttf hinting', function () { + var buffer = Font.create(require('data/baiduHealth-hinting.ttf'), { + type: 'ttf', + hinting: true + }).write({ + hinting: true + }); + expect(buffer.byteLength).toBeGreaterThan(1000); + expect(buffer.byteLength).toBeLessThan(10000); + + var font = Font.create(buffer, { + type: 'ttf', + hinting: true + }); + expect(font.data.cvt.length).toBe(24); + expect(font.data.fpgm.length).toBe(371); + expect(font.data.prep.length).toBe(204); + expect(font.data.gasp.length).toBe(8); + }); + }); + + describe('写eot数据', function () { + var buffer = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).write({ + type: 'eot' + }); + it('test eot format', function () { + expect(buffer.byteLength).toBeGreaterThan(1000); + expect(buffer.byteLength).toBeLessThan(10000); + }); + + it('test read eot', function () { + var font = Font.create(buffer, { + type: 'eot' + }); + expect(font.data.version).toBe(1); + expect(font.data.head.magickNumber).toBe(1594834165); + expect(font.data.head.unitsPerEm).toBe(512); + }); + }); + + describe('写woff数据', function () { + var buffer = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).write({ + type: 'woff' + }); + it('test woff format', function () { + expect(buffer.byteLength).toBeGreaterThan(1000); + expect(buffer.byteLength).toBeLessThan(10000); + }); + + it('test read woff', function () { + var font = Font.create(buffer, { + type: 'woff' + }); + expect(font.data.version).toBe(1); + expect(font.data.head.magickNumber).toBe(1594834165); + expect(font.data.head.unitsPerEm).toBe(512); + }); + }); + + + describe('toBase64', function () { + it('test ttf to toBase64', function () { + var base64Str = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).toBase64({ + type: 'ttf' + }); + expect(base64Str.indexOf('data:font/ttf;')) + .toBe(0); + expect(base64Str.length).toBeGreaterThan(1000); + expect(base64Str.length).toBeLessThan(10000); + }); + + it('test woff to toBase64', function () { + var base64Str = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).toBase64({ + type: 'woff' + }); + expect(base64Str.indexOf('data:font/woff;')) + .toBe(0); + expect(base64Str.length).toBeGreaterThan(1000); + expect(base64Str.length).toBeLessThan(10000); + }); + + it('test eot to toBase64', function () { + var base64Str = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).toBase64({ + type: 'eot' + }); + expect(base64Str.indexOf('data:font/eot;')) + .toBe(0); + expect(base64Str.length).toBeGreaterThan(1000); + expect(base64Str.length).toBeLessThan(10000); + }); + + it('test svg to toBase64', function () { + var base64Str = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }).toBase64({ + type: 'svg' + }); + expect(base64Str.indexOf('data:font/svg;')) + .toBe(0); + expect(base64Str.length).toBeGreaterThan(1000); + expect(base64Str.length).toBeLessThan(20000); + }); + }); + + describe('font method', function () { + it('compound2simple', function () { + var font = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }); + font.compound2simple(); + expect(!!font.data.glyf[16].compound).toBe(false); + expect(!!font.data.glyf[16].glyfs).toBe(false); + expect(font.data.glyf[16].contours.length).toBe(4); + }); + + it('optimize', function () { + var font = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }); + font.compound2simple() + expect(font.data.glyf.length).toBe(17); + font.optimize(); + expect(font.data.glyf.length).toBe(15); + }); + + it('sort', function () { + var font = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }); + font.sort(); + expect(font.data.glyf[2].unicode).toBeUndefined(); + font.compound2simple().sort(); + expect(font.data.glyf[2].unicode[0]).toBe(0xe003); + }); + + it('find', function () { + var font = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }); + var list = font.find({ + unicode: 0xe003 + }); + expect(list.length).toBe(1); + expect(list[0].unicode[0]).toBe(0xe003); + + var list = font.find({ + name: 'uniE00' + }); + expect(list.length).toBe(4); + + var list = font.find({ + filter: function (glyf) { + return glyf.name === 'uniE003'; + } + }); + expect(list.length).toBe(1); + }); + + it('merge', function () { + var font = Font.create(require('data/baiduHealth.ttf'), { + type: 'ttf' + }); + var font1 = Font.create(require('data/icomoon.svg'), { + type: 'svg' + }); + font1.optimize(); + expect(font.data.glyf.length).toBe(17); + expect(font1.data.glyf.length).toBe(2); + font.merge(font1); + expect(font.data.glyf.length).toBe(18); + }); + + }); + + } +); diff --git a/test/spec/ttf/ttf2eot.spec.js b/test/spec/ttf/ttf2eot.spec.js index 9564677..8d9c862 100644 --- a/test/spec/ttf/ttf2eot.spec.js +++ b/test/spec/ttf/ttf2eot.spec.js @@ -10,12 +10,12 @@ define( var eotBuffer = ttf2eot(require('data/baiduHealth.ttf')) - it('test woff format', function () { + it('test eot format', function () { expect(eotBuffer.byteLength).toBeGreaterThan(1000); expect(eotBuffer.byteLength).toBeLessThan(10000); }); - it('test read ttf2eot', function () { + it('test read eot', function () { var ttf = new TTFReader().read(eot2ttf(eotBuffer)); expect(ttf.version).toBe(1); diff --git a/test/spec/ttf/ttf2woff.spec.js b/test/spec/ttf/ttf2woff.spec.js index 83fea08..6632ebb 100644 --- a/test/spec/ttf/ttf2woff.spec.js +++ b/test/spec/ttf/ttf2woff.spec.js @@ -15,7 +15,7 @@ define( expect(woffBuffer.byteLength).toBeLessThan(10000); }); - it('test read ttf2woff', function () { + it('test read woff', function () { var ttf = new TTFReader().read(woff2ttf(woffBuffer)); expect(ttf.version).toBe(1); diff --git a/tool/test-node.sh b/tool/test-node.sh new file mode 100644 index 0000000..b830025 --- /dev/null +++ b/tool/test-node.sh @@ -0,0 +1,8 @@ +#/bin/bash +fileDir=$(cd "$(dirname "$0")"; pwd) +projectDir=$(dirname "$fileDir") +cd $projectDir + +source $projectDir/tool/build-node.sh +node $projectDir/test/node-spec/main.js +source $projectDir/tool/clean-node.sh