From 999a484d8a19d5d90be0ed8e88fe805074cdb470 Mon Sep 17 00:00:00 2001 From: mkwiser Date: Wed, 24 Sep 2014 23:36:31 +0800 Subject: [PATCH] modify ttf reader --- demo/js/glyfcanvas.js | 14 +++-- demo/js/glyfsvg.js | 15 +++-- demo/js/ttfparse.js | 4 +- src/ttf/ttf.js | 99 ++----------------------------- src/ttf/ttfreader.js | 133 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 158 insertions(+), 107 deletions(-) diff --git a/demo/js/glyfcanvas.js b/demo/js/glyfcanvas.js index 3579bee..d814914 100644 --- a/demo/js/glyfcanvas.js +++ b/demo/js/glyfcanvas.js @@ -29,11 +29,11 @@ define( function showTTFGlyf(ttfData) { ttf = new TTF(ttfData); - var chars = ttf.chars(); + var codes = ttf.codes(); var str = ''; // 获取unicode字符 - chars.forEach(function(item) { + codes.forEach(function(item) { str += '
  • ' + ''+ String.fromCharCode(item) +'' + (item > 255 ? '\\u' + Number(item).toString(16) : item) @@ -44,7 +44,7 @@ define( } function showGlyf(charcode) { - var glyfData = ttf.getCharGlyf(charcode); + var glyfData = ttf.getCodeGlyf(charcode); var glyf = { xMin: glyfData.xMin, @@ -86,7 +86,9 @@ define( var binaryData = e.target.result; setFont(binaryData); - var ttfData = new ttfreader().read(binaryData); + var ttfReander = new ttfreader(); + ttfReander.read(binaryData); + var ttfData = ttfReander.resolve(); showTTFGlyf(ttfData); } @@ -110,7 +112,9 @@ define( onSuccess: function(binaryData) { setFont(binaryData); - var ttfData = new ttfreader().read(binaryData); + var ttfReander = new ttfreader(); + ttfReander.read(binaryData); + var ttfData = ttfReander.resolve(); showTTFGlyf(ttfData); }, onError: function() { diff --git a/demo/js/glyfsvg.js b/demo/js/glyfsvg.js index 8ab9fca..2384281 100644 --- a/demo/js/glyfsvg.js +++ b/demo/js/glyfsvg.js @@ -28,12 +28,12 @@ define( function showTTFGlyf(ttfData) { console.log(ttfData); ttf = new TTF(ttfData); - var chars = ttf.chars(); + var codes = ttf.codes(); var str = ''; // 获取unicode字符 - chars.forEach(function(item) { + codes.forEach(function(item) { str += '
  • ' + ''+ String.fromCharCode(item) +'' + (item > 255 ? '\\u' + Number(item).toString(16) : item) @@ -53,7 +53,7 @@ define( + '' + ''; var svg = $(tpl); - var glyf = ttf.getCharGlyf(charcode); + var glyf = ttf.getCodeGlyf(charcode); var lang = require('common/lang'); // 调整大小 @@ -90,8 +90,9 @@ define( reader.onload = function(e) { var binaryData = e.target.result; setFont(binaryData); - - var ttfData = new ttfreader().read(binaryData); + var ttfReander = new ttfreader(); + ttfReander.read(binaryData); + var ttfData = ttfReander.resolve(); showTTFGlyf(ttfData); } @@ -115,7 +116,9 @@ define( onSuccess: function(binaryData) { setFont(binaryData); - var ttfData = new ttfreader().read(binaryData); + var ttfReander = new ttfreader(); + ttfReander.read(binaryData); + var ttfData = ttfReander.resolve(); showTTFGlyf(ttfData); }, onError: function() { diff --git a/demo/js/ttfparse.js b/demo/js/ttfparse.js index 30d179f..6e3f1fc 100644 --- a/demo/js/ttfparse.js +++ b/demo/js/ttfparse.js @@ -39,7 +39,9 @@ define( ajaxBinaryFile({ url: '../font/baiduHealth.ttf', onSuccess: function(binaryData) { - var ttfData = new ttfreader().read(binaryData); + var ttfReader = new ttfreader(); + ttfReader.read(binaryData); + var ttfData = ttfReader.resolve(); console.log(ttfData); var ttf = new TTF(ttfData); diff --git a/src/ttf/ttf.js b/src/ttf/ttf.js index 746b605..2b99e44 100644 --- a/src/ttf/ttf.js +++ b/src/ttf/ttf.js @@ -11,91 +11,6 @@ define( function(require) { - /** - * 读取ttf中windows字符表的字符 - * - * @return {Object} 字符字典索引,key:unicode,value:glyf index - * - * @see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html - */ - function readWindowsAllChars(ttf) { - // 读取windows unicode 编码段 - var usc2Arr = ttf.cmap.tables.filter(function(item) { - return item.platformID == 3 && item.encodingID == 1 && item.format == 4; - }); - - if(usc2Arr.length) { - // 只取第一个format - var format4 = usc2Arr[0]; - var segCount = format4.segCountX2 / 2; - - var chars = {}; - - // graphIdArray 和idRangeOffset的偏移量 - var graphIdArrayIndexOffset = (format4.glyphIdArrayOffset - format4.idRangeOffsetOffset) / 2; - - for (var i = 0; i < segCount; ++i) { - // 读取单个字符 - for( - var start = format4.startCode[i], end = format4.endCode[i]; - start <= end; - ++start - ) { - // range offset = 0 - if(format4.idRangeOffset[i] === 0) { - chars[start] = (start + format4.idDelta[i]) % 65536; - } - // rely on to glyphIndexArray - else { - var index = i + format4.idRangeOffset[i] / 2 - + (start - format4.startCode[i]) - - graphIdArrayIndexOffset; - - var graphId = format4.glyphIdArray[index]; - if(graphId !== 0) { - chars[start] = (graphId + format4.idDelta[i]) % 65536; - } - else { - chars[start] = 0; - } - - } - } - } - - return chars; - } - else { - return {}; - } - } - - /** - * 关联glyf相关的信息 - */ - function resolveGlyf(ttf) { - var chars = ttf.chars; - var glyf = ttf.glyf; - - Object.keys(chars).forEach(function(c) { - var i = chars[c]; - glyf[i].unicode = +c; - }); - - if (ttf.post && 2 == ttf.post.format) { - var nameIndex = ttf.post.glyphNameIndex; - var names = ttf.post.names; - nameIndex.forEach(function(name, i) { - if (name <= 257) { - glyf[i].name = name; - } - else { - glyf[i].name = names[name - 258] || ''; - } - }); - } - } - /** * ttf读取函数 * @@ -104,8 +19,6 @@ define( */ function TTF(ttf) { this.ttf = ttf; - this.ttf.chars = readWindowsAllChars(ttf); - resolveGlyf.call(this, this.ttf); } /** @@ -113,8 +26,8 @@ define( * * @return {Object} 字符信息 */ - TTF.prototype.chars = function() { - return Object.keys(this.ttf.chars); + TTF.prototype.codes = function() { + return Object.keys(this.ttf.codes); }; /** @@ -123,9 +36,9 @@ define( * * @return {?number} 返回glyf索引号 */ - TTF.prototype.getCharGlyfIndex = function(c) { + TTF.prototype.getCodeGlyfIndex = function(c) { var charCode = typeof c == 'number' ? c : c.charCodeAt(0); - var glyfIndex = this.ttf.chars[charCode] || 0; + var glyfIndex = this.ttf.codes[charCode] || 0; return glyfIndex; }; @@ -135,8 +48,8 @@ define( * * @return {?Object} 返回glyf对象 */ - TTF.prototype.getCharGlyf = function(c) { - var glyfIndex = this.getCharGlyfIndex(c); + TTF.prototype.getCodeGlyf = function(c) { + var glyfIndex = this.getCodeGlyfIndex(c); return this.ttf.glyf[glyfIndex]; }; diff --git a/src/ttf/ttfreader.js b/src/ttf/ttfreader.js index 7c009f0..339a91a 100644 --- a/src/ttf/ttfreader.js +++ b/src/ttf/ttfreader.js @@ -20,7 +20,7 @@ define( /** * 初始化 */ - function init() { + function read() { var reader = this.reader; var ttf = this.ttf; @@ -47,8 +47,121 @@ define( var offset = ttf.tables[tableName].offset; ttf[tableName] = new supportTables[tableName](offset).read(reader, ttf); }); + } + + /** + * 读取ttf中windows字符表的字符 + * + * @return {Object} 字符字典索引,key:unicode,value:glyf index + * + * @see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html + */ + function readWindowsAllCodes(ttf) { + // 读取windows unicode 编码段 + var usc2Arr = ttf.cmap.tables.filter(function(item) { + return item.platformID == 3 && item.encodingID == 1 && item.format == 4; + }); + + if(usc2Arr.length) { + // 只取第一个format + var format4 = usc2Arr[0]; + var segCount = format4.segCountX2 / 2; + + var codes = {}; + + // graphIdArray 和idRangeOffset的偏移量 + var graphIdArrayIndexOffset = (format4.glyphIdArrayOffset - format4.idRangeOffsetOffset) / 2; + + for (var i = 0; i < segCount; ++i) { + // 读取单个字符 + for( + var start = format4.startCode[i], end = format4.endCode[i]; + start <= end; + ++start + ) { + // range offset = 0 + if(format4.idRangeOffset[i] === 0) { + codes[start] = (start + format4.idDelta[i]) % 65536; + } + // rely on to glyphIndexArray + else { + var index = i + format4.idRangeOffset[i] / 2 + + (start - format4.startCode[i]) + - graphIdArrayIndexOffset; + + var graphId = format4.glyphIdArray[index]; + if(graphId !== 0) { + codes[start] = (graphId + format4.idDelta[i]) % 65536; + } + else { + codes[start] = 0; + } + + } + } + } + + return codes; + } + else { + return {}; + } + } + + /** + * 关联glyf相关的信息 + */ + function resolveGlyf(ttf) { + var codes = ttf.codes; + var glyf = ttf.glyf; + + // unicode + Object.keys(codes).forEach(function(c) { + var i = codes[c]; + glyf[i].unicode = +c; + }); + + // advanceWidth + ttf.hmtx.forEach(function(item, i) { + glyf[i].advanceWidth = item.advanceWidth; + glyf[i].leftSideBearing = item.leftSideBearing; + }); + + //name + if (ttf.post && 2 == ttf.post.format) { + var nameIndex = ttf.post.glyphNameIndex; + var names = ttf.post.names; + nameIndex.forEach(function(name, i) { + if (name <= 257) { + glyf[i].name = String.fromCharCode(name); + } + else { + glyf[i].name = names[name - 258] || ''; + } + }); + } + } + + /** + * 清除非必须的表 + */ + function cleanTables(ttf) { + delete ttf.tables; + delete ttf.DSIG; + delete ttf.GDEF; + delete ttf.GPOS; + delete ttf.GSUB; + delete ttf.cmap; + delete ttf.gasp; + delete ttf.hmtx; + delete ttf.loca; + delete ttf.post; + delete ttf.maxp; + } + + /** * TTF的构造函数 * @@ -65,10 +178,26 @@ define( TTFReader.prototype.read = function(buffer) { this.reader = new Reader(buffer, 0, buffer.byteLength, false); this.ttf = {}; - init.call(this); + read.call(this); return this.ttf; }; + /** + * 对ttf文件做进一步解析处理 + * + * @param {Object} ttf ttf格式文件 + * + * @return {Object} 解析后的格式 + */ + TTFReader.prototype.resolve = function(ttf) { + ttf = ttf || this.ttf; + ttf.codes = readWindowsAllCodes(ttf); + resolveGlyf.call(this, ttf); + cleanTables.call(this, ttf); + return ttf; + }; + + return TTFReader; } );