From d0e96dc8550a43746c70913c46dd22a9c7f697a4 Mon Sep 17 00:00:00 2001 From: mkwiser Date: Thu, 25 Sep 2014 23:26:55 +0800 Subject: [PATCH] add compound glyf --- demo/js/glyfcanvas.js | 12 +--- demo/js/glyfsvg.js | 12 ++-- font/baiduHealth.fcp | Bin 5132 -> 5169 bytes font/baiduHealth.ttf | Bin 5048 -> 5096 bytes font/baiduHealth.woff | Bin 5161 -> 5209 bytes src/graphics/transform.js | 51 ++++++++++++++++ src/ttf/table/ttfglyf.js | 117 +++++++++++++++++++++++------------- src/ttf/ttf.js | 22 ++++++- src/ttf/util/glyf2canvas.js | 44 +++++++++++--- src/ttf/util/glyf2svg.js | 43 ++++++++++--- src/ttf/util/glyfAdjust.js | 47 --------------- 11 files changed, 228 insertions(+), 120 deletions(-) create mode 100644 src/graphics/transform.js delete mode 100644 src/ttf/util/glyfAdjust.js diff --git a/demo/js/glyfcanvas.js b/demo/js/glyfcanvas.js index d814914..89c1894 100644 --- a/demo/js/glyfcanvas.js +++ b/demo/js/glyfcanvas.js @@ -15,6 +15,7 @@ define( var ajaxBinaryFile = require('common/ajaxBinaryFile'); var setFontface = require('./setFontface'); var glyf2canvas = require('ttf/util/glyf2canvas'); + var lang = require('common/lang'); var ttf = null; @@ -44,15 +45,8 @@ define( } function showGlyf(charcode) { - var glyfData = ttf.getCodeGlyf(charcode); - - var glyf = { - xMin: glyfData.xMin, - xMax: glyfData.xMax, - yMin: glyfData.yMin, - yMax: glyfData.yMax, - contours: glyfData.contours - }; + + var glyf = lang.clone(ttf.getCodeGlyf(charcode)); var canvas = $('#glyf-canvas').get(0); diff --git a/demo/js/glyfsvg.js b/demo/js/glyfsvg.js index 2384281..116ba97 100644 --- a/demo/js/glyfsvg.js +++ b/demo/js/glyfsvg.js @@ -15,6 +15,9 @@ define( var ajaxBinaryFile = require('common/ajaxBinaryFile'); var glyf2svg = require('ttf/util/glyf2svg'); var setFontface = require('./setFontface'); + var lang = require('common/lang'); + + var ttf = null; // 设置字体 @@ -26,7 +29,7 @@ define( // 查看ttf glyf function showTTFGlyf(ttfData) { - console.log(ttfData); + ttf = new TTF(ttfData); var codes = ttf.codes(); @@ -53,11 +56,10 @@ define( + '' + ''; var svg = $(tpl); - var glyf = ttf.getCodeGlyf(charcode); - var lang = require('common/lang'); - + var glyf = lang.clone(ttf.getCodeGlyf(charcode)); + // 调整大小 - var width = glyf.xMax - glyf.xMin; + var width = glyf.xMax; var height = glyf.yMax - glyf.yMin; var scale = 1; diff --git a/font/baiduHealth.fcp b/font/baiduHealth.fcp index 65f2c70b470c9cd77157c843a0e731e9ab11e3a9..e6a3d94bf5c15b75841776a1c475171be80c97e5 100644 GIT binary patch delta 3295 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 delta 3258 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 diff --git a/font/baiduHealth.ttf b/font/baiduHealth.ttf index 42e0278bcae4d502ccbd65cd5ab9d8b5187d0f0e..0df71c6fc45d18c8dbdb5906073970a58e776fd0 100644 GIT binary patch delta 432 zcmdm?{z83%c>Mwf1_lmy7gsk1Mj(qpcmKXn36_{lJMOgBfW&sT}0rFKca!V@YYMF$9{2M^N zOHO`rqO6UAAJBjcAo<+HiUI~>rbwWC1dy+gmzbN{UNUDh1A|}!P^`HizqrIA>MR$~ z?N5O6Tfm+JdQidb;k$T#o39MqOh91n(0Bap=)Tmd9_+ynfB86+8afczF9U&uW;)G23TNk5Q3 z1ISnK57syG-|J(+z`zJnpOBoJSa4v~!p#f}OcFr;ru4+(g8%;+n1SjufP9YhoXWK4 zW}y#&@*fx&_&hRF6H^$f_}Lg3>KXn36_{lJMOgBfW&#Z~0rFKca!V>?T$nh3{2M^N zLr#8jqO6T1&~TQ#II diff --git a/font/baiduHealth.woff b/font/baiduHealth.woff index 05ed7b586abedc98e4d8eb8b88bbe9efc0afc316..b5e98f458964d67a61bccd0b9eefbac4e1495c32 100644 GIT binary patch delta 550 zcmYjNOGsNm6uom_&=AG=@*)_D@+h&02o-E47EviN@rMbGLKTC&T5AeP6irbP$wJVT z_?cZ0!KKobX6ZuEt+wuTr?{|gT;`9VEBf zjek#ETbl{@<1gFf#@`Ue5Cfj z-90X%!X?MWHK>zRS+0n8HM)IN=OTJTU&x`%uYyt4#Em=`Z6Y8md6>CbPH{8HZ{FhK zru|;6v+OPYsDvuHL0oekX=l1g-bM6Ei#}iO60h;)cfapD=iKvtq~4{h?R+*%OgNDx z3aH!o_|GeSdLj|13z_0Z4)rh4`hPf=xsyfq4c_N~w{nGi5t$7ic8HNLS1jE|HieHX z>VxjfeDTJ>3R-KGhS??(UF07WpN0pcs@XwiOyHeevl(gC`p#n_?JkjjUGZzBWY@OL zO(MRJz7>bvfV+ke*(>-f3RhFSsWrMi>{y1srC7)az22&z&(cx|5{kuiEZQ)8Sj=Pi zxWjdkY?_TNqR?yP&lLU6+flpK!4Dfz^b8f(p8S!-P++(6^wGmW`h>g!0nzbz@>$(q zH#~i!nJvm}!|J5U@&zZa2A$EMaMMM)} contour 轮廓点 + * @param {number} a m11 + * @param {number} b m12 + * @param {number} c m21 + * @param {number} d m22 + * @param {number} e dx + * @param {number} f dy + * @return {Array.} contour 轮廓点 + */ + function transform(contour, a, b, c, d, e, f) { + var x, y, p; + for (var i = 0, l = contour.length; i < l; i++) { + p = contour[i]; + x = p.x; + y = p.y; + p.x = x * a + y * c + e; + p.y = x * b + y * d + f; + } + return contour; + } + + return transform; + } +); diff --git a/src/ttf/table/ttfglyf.js b/src/ttf/table/ttfglyf.js index 4d06927..a901f54 100644 --- a/src/ttf/table/ttfglyf.js +++ b/src/ttf/table/ttfglyf.js @@ -149,26 +149,29 @@ define( val.xMax = reader.readInt16(); val.yMax = reader.readInt16(); - // endPtsOfConturs - var endPtsOfContours = []; - if (numberOfContours >= 0) { - for ( var i = 0; i < numberOfContours; i++) { - endPtsOfContours.push(reader.readUint16()); - } - val.endPtsOfContours = endPtsOfContours; - } - - // instructions - var length = reader.readUint16(); - var instructions = []; - for ( var i = 0; i < length; ++i) { - instructions.push(reader.readUint8()); - } - - val.instructions = instructions; - // 读取简单字形 if (numberOfContours >= 0) { + + // endPtsOfConturs + var endPtsOfContours = []; + if (numberOfContours >= 0) { + for ( var i = 0; i < numberOfContours; i++) { + endPtsOfContours.push(reader.readUint16()); + } + val.endPtsOfContours = endPtsOfContours; + } + + // instructions + var length = reader.readUint16(); + if (length) { + var instructions = []; + for ( var i = 0; i < length; ++i) { + instructions.push(reader.readUint8()); + } + val.instructions = instructions; + } + + readSimpleGlyf.call( this, reader, @@ -181,47 +184,77 @@ define( } else { val.compound = true; - val.glyf = []; + val.glyfs = []; + var flags; // 读取复杂字形 do { var glyf = {}; - var flags = glyf.flags = reader.readUint16(); - val.glyphIndex = reader.readUint16(); - var arg1, arg2, scaleX = 1, scaleY = 1; + flags = glyf.flags = reader.readUint16(); + glyf.glyphIndex = reader.readUint16(); + + var arg1 = 0, arg2 = 0, scaleX = 16384, scaleY = 16384, + scale01 = 0, scale10 = 0; + if (componentFlag.ARG_1_AND_2_ARE_WORDS & flags) { - if (componentFlag.ARGS_ARE_XY_VALUES & flags) { - arg1 = reader.readUint16(); - arg2 = reader.readUint16(); - } - else { - arg1 = reader.readInt16(); - arg2 = reader.readInt16(); - } + arg1 = reader.readInt16(); + arg2 = reader.readInt16(); } else { - if (componentFlag.ARGS_ARE_XY_VALUES & flags) { - arg1 = reader.readUint8(); - arg2 = reader.readUint8(); - } - else { - arg1 = reader.readInt8(); - arg2 = reader.readInt8(); - } + arg1 = reader.readInt8(); + arg2 = reader.readInt8(); } if (componentFlag.ROUND_XY_TO_GRID & flags) { arg1 = Math.round(arg1); arg2 = Math.round(arg2); } - glyf.x = arg1; - glyf.y = arg2; - val.glyf.push(glyf); + if (componentFlag.WE_HAVE_A_SCALE & flags) { + scaleX = reader.readInt16(); + scaleY = scaleX; + } + else if (componentFlag.WE_HAVE_AN_X_AND_Y_SCALE & flags) { + scaleX = reader.readInt16(); + scaleY = reader.readInt16(); + } + else if (componentFlag.WE_HAVE_A_TWO_BY_TWO & flags) { + scaleX = reader.readInt16(); + scale01 = reader.readInt16(); + scale10 = reader.readInt16(); + scaleY = reader.readInt16(); + } + + if (componentFlag.ARGS_ARE_XY_VALUES & flags) { + + glyf.transform = { + a: Math.round(10000 * scaleX / 16384) / 10000, + b: Math.round(10000 * scale01 / 16384) / 10000, + c: Math.round(10000 * scale10 / 16384) / 10000, + d: Math.round(10000 * scaleY / 16384) / 10000, + e: arg1, + f: arg2 + }; + } + else { + console.error('not support !ARGS_ARE_XY_VALUES!'); + } + + val.glyfs.push(glyf); } while(componentFlag.MORE_COMPONENTS & flags); - } + + if (componentFlag.WE_HAVE_INSTRUCTIONS & flags) { + var length = reader.readUint16(); + var instructions = []; + for ( var i = 0; i < length; ++i) { + instructions.push(reader.readUint8()); + } + val.instructions = instructions; + } + + } return val; } diff --git a/src/ttf/ttf.js b/src/ttf/ttf.js index 2b99e44..5b8818f 100644 --- a/src/ttf/ttf.js +++ b/src/ttf/ttf.js @@ -50,9 +50,29 @@ define( */ TTF.prototype.getCodeGlyf = function(c) { var glyfIndex = this.getCodeGlyfIndex(c); - return this.ttf.glyf[glyfIndex]; + return this.getIndexGlyf(glyfIndex); }; + /** + * 获取字符的glyf信息 + * @param {number} glyfIndex glyf的索引 + * + * @return {?Object} 返回glyf对象 + */ + TTF.prototype.getIndexGlyf = function(glyfIndex) { + var glyfList = this.ttf.glyf; + var glyf = glyfList[glyfIndex]; + // 如果是复合图元, 则把相关的glyf代入 + if(glyf.compound) { + glyf.glyfs.forEach(function(g) { + g.glyf = glyfList[g.glyphIndex]; + }); + } + + return glyf; + }; + + return TTF; } ); diff --git a/src/ttf/util/glyf2canvas.js b/src/ttf/util/glyf2canvas.js index 763dcf4..54395ea 100644 --- a/src/ttf/util/glyf2canvas.js +++ b/src/ttf/util/glyf2canvas.js @@ -28,6 +28,8 @@ define( options = options || {}; + ctx.save(); + if(options.stroke) { ctx.strokeWidth = options.strokeWidth || 1; ctx.strokeStyle = options.strokeStyle || 'black'; @@ -36,16 +38,43 @@ define( ctx.fillStyle = options.fillStyle || 'black'; } + var height = glyf.yMax; + ctx.translate(options.x || 0, height + (options.y || 0)); + ctx.scale(options.scale || 1, -(options.scale || 1)); - // 对轮廓进行反向,以及坐标系调整,取整 - glyf = glyfAdjust(glyf, options.scale, options.x, options.y); - - var contours = glyf.contours; - // 处理glyf轮廓 ctx.beginPath(); - for ( var i = 0, l = contours.length; i < l; i++) { - drawContour(ctx, contours[i]); + + if (!glyf.compound) { + + var contours = glyf.contours; + for ( var i = 0, l = contours.length; i < l; i++) { + drawContour(ctx, contours[i]); + } + } + // 复合图元绘制 + else { + var glyfs = glyf.glyfs; + glyfs.forEach(function(g) { + + ctx.save(); + var transform = g.transform; + ctx.transform ( + transform.a, + transform.b, + transform.c, + transform.d, + transform.e, + transform.f + ); + + var contours = g.glyf.contours; + for ( var i = 0, l = contours.length; i < l; i++) { + drawContour(ctx, contours[i]); + } + + ctx.restore(); + }); } if(false !== options.stroke) { @@ -55,6 +84,7 @@ define( if (false !== options.fill) { ctx.fill(); } + ctx.restore(); } diff --git a/src/ttf/util/glyf2svg.js b/src/ttf/util/glyf2svg.js index 25bf60c..38c6690 100644 --- a/src/ttf/util/glyf2svg.js +++ b/src/ttf/util/glyf2svg.js @@ -14,7 +14,8 @@ define( function(require) { var contour2svg = require('./contour2svg'); - var glyfAdjust = require('ttf/util/glyfAdjust'); + var pathAdjust = require('graphics/pathAdjust'); + var matrixTransform = require('graphics/transform'); /** * glyf转换svg @@ -27,15 +28,39 @@ define( return null; } var pathArray = []; - - - // 对轮廓进行反向,以及坐标系调整,取整 - glyf = glyfAdjust(glyf, options.scale, options.x, options.y); - var contours = glyf.contours; - - for ( var i = 0, l = contours.length; i < l; i++) { - pathArray.push(contour2svg(contours[i])); + var height = glyf.yMax; + var x = options.x || 0; + var y = height + (options.y || 0); + var scale = options.scale || 1; + + + if (!glyf.compound) { + for ( var i = 0, l = contours.length; i < l; i++) { + pathAdjust(contours[i], 1, -1); + pathAdjust(contours[i], scale, scale, x, y); + pathArray.push(contour2svg(contours[i])); + } + } + else { + var glyfs = glyf.glyfs; + glyfs.forEach(function(g) { + var contours = g.glyf.contours; + var transform = g.transform; + for ( var i = 0, l = contours.length; i < l; i++) { + matrixTransform(contours[i], + transform.a, + transform.b, + transform.c, + transform.d, + transform.e, + transform.f + ); + pathAdjust(contours[i], 1, -1); + pathAdjust(contours[i], scale, scale, x, y); + pathArray.push(contour2svg(contours[i])); + } + }); } return pathArray.join(' '); diff --git a/src/ttf/util/glyfAdjust.js b/src/ttf/util/glyfAdjust.js deleted file mode 100644 index 3f4f708..0000000 --- a/src/ttf/util/glyfAdjust.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file glyfAdjust.js - * @author mengke01 - * @date - * @description - * 将glyf坐标系平移到原点 - */ - - -define( - function(require) { - - /** - * 对glyf坐标进行调整 - * - * @param {Object} glyf glyf结构 - * @param {number} scale 缩放比例 - * @param {number} offsetX x偏移 - * @param {number} offsetY y偏移 - * @return {number} glyf结构 - */ - function glyfAdjust(glyf, scale, offsetX, offsetY) { - - // 对轮廓进行反向,以及坐标系调整,取整 - var middleYx2 = glyf.yMax + glyf.yMin; - var scale = scale || 1; - var x = offsetX || 0; - var y = offsetY || 0; - - glyf.contours.forEach(function (path) { - path.forEach(function(p) { - p.x = x + scale * (p.x); - p.y = y + scale * (middleYx2 - p.y); - }); - }); - - glyf.xMin = x + glyf.xMin * scale; - glyf.yMin = y + glyf.yMin * scale; - glyf.xMax = x + glyf.xMax * scale; - glyf.yMax = y + glyf.yMax * scale; - - return glyf; - } - - return glyfAdjust; - } -);