增加svg导入 自动调整大小
This commit is contained in:
parent
e70014f381
commit
41f1322992
@ -32,7 +32,8 @@ define(
|
||||
program.loading.hide();
|
||||
if (program.ttfManager.get()) {
|
||||
program.ttfManager.merge(imported, {
|
||||
scale: true
|
||||
scale: true,
|
||||
adjustGlyf: imported.from === 'svg' ? true : false
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
@ -40,6 +40,11 @@ define(
|
||||
url: 'http://vs-static.baidu.com/m-health/new-composite/20141223/asset/common/css/font/baiduHealth.woff',
|
||||
from: '百度健康图标'
|
||||
},
|
||||
{
|
||||
name: 'fonteditor.woff',
|
||||
url: 'http://vs-static.baidu.com/m-health/med-detail/201412301413/asset/common/css/fonts/fonteditor.woff',
|
||||
from: '百度健康医药馆图标'
|
||||
},
|
||||
{
|
||||
name: 'i-edu.woff',
|
||||
url: 'http://vs-static.baidu.com/edu/m/asset/common/css/font/i-edu.woff',
|
||||
|
@ -47,7 +47,10 @@ define(
|
||||
type: ext,
|
||||
success: function (imported) {
|
||||
if (imported.glyf.length) {
|
||||
program.ttfManager.merge(imported, {scale: true});
|
||||
program.ttfManager.merge(imported, {
|
||||
scale: true,
|
||||
adjustGlyf: imported.from === 'svg' ? true : false
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -162,6 +162,7 @@ define(
|
||||
* @param {Object} imported ttfObject
|
||||
* @param {Object} options 参数选项
|
||||
* @param {boolean} options.scale 是否自动缩放
|
||||
* @param {boolean} options.adjustGlyf 是否调整字形以适应边界
|
||||
*
|
||||
* @return {this}
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@ define(
|
||||
var svg2contours = require('./util/svg2contours');
|
||||
var computeBoundingBox = require('graphics/computeBoundingBox');
|
||||
var error = require('./error');
|
||||
var glyfAdjust = require('./util/glyfAdjust');
|
||||
|
||||
/**
|
||||
* 加载xml字符串
|
||||
@ -51,6 +52,39 @@ define(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据边界获取unitsPerEm
|
||||
*
|
||||
* @param {number} xMin x最小值
|
||||
* @param {number} xMax x最大值
|
||||
* @param {number} yMin y最小值
|
||||
* @param {number} yMax y最大值
|
||||
* @return {number}
|
||||
*/
|
||||
function getUnitsPerEm(xMin, xMax, yMin, yMax) {
|
||||
var seed = Math.ceil(Math.min(yMax - yMin, xMax - xMin));
|
||||
|
||||
if (!seed) {
|
||||
return 1024;
|
||||
}
|
||||
|
||||
if (seed <= 128) {
|
||||
return seed;
|
||||
}
|
||||
|
||||
// 获取合适的unitsPerEm
|
||||
var unitsPerEm = 128;
|
||||
while (unitsPerEm < 16384) {
|
||||
|
||||
if (seed <= 1.2 * unitsPerEm) {
|
||||
return unitsPerEm;
|
||||
}
|
||||
|
||||
unitsPerEm = unitsPerEm << 1;
|
||||
}
|
||||
|
||||
return 1024;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对ttfObject进行处理,去除小数
|
||||
@ -60,58 +94,41 @@ define(
|
||||
*/
|
||||
function resolve(ttf) {
|
||||
|
||||
var scale = 1;
|
||||
|
||||
// 对于小尺寸svg进行合理的缩放
|
||||
if (ttf.head.unitsPerEm && ttf.head.unitsPerEm < 256) {
|
||||
scale = 1024 / ttf.head.unitsPerEm;
|
||||
// 如果是svg格式字体,则去小数
|
||||
if (ttf.from === 'svgfont' && ttf.head.unitsPerEm > 128) {
|
||||
ttf.glyf.forEach(function (g) {
|
||||
glyfAdjust(g);
|
||||
});
|
||||
}
|
||||
// 否则重新计算字形大小,缩放到1024的em
|
||||
else {
|
||||
var xMin = 16384;
|
||||
var xMax = -16384;
|
||||
var yMin = 16384;
|
||||
var yMax = -16384;
|
||||
|
||||
ttf.glyf.forEach(function (g) {
|
||||
if (g.contours) {
|
||||
var bound = computeBoundingBox.computePathBox.apply(null, g.contours);
|
||||
if (bound) {
|
||||
xMin = Math.min(xMin, bound.x);
|
||||
xMax = Math.max(xMax, bound.x + bound.width);
|
||||
yMin = Math.min(yMin, bound.y);
|
||||
yMax = Math.max(yMax, bound.y + bound.height);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var unitsPerEm = getUnitsPerEm(xMin, xMax, yMin, yMax);
|
||||
var scale = 1024 / unitsPerEm;
|
||||
|
||||
ttf.glyf.forEach(function (g) {
|
||||
glyfAdjust(g, scale, scale);
|
||||
});
|
||||
ttf.head.unitsPerEm = 1024;
|
||||
}
|
||||
|
||||
ttf.glyf.forEach(function (glyf) {
|
||||
if (glyf.contours && glyf.contours.length) {
|
||||
|
||||
var pointIterator = function (p) {
|
||||
p.x = Math.round(p.x * scale);
|
||||
p.y = Math.round(p.y * scale);
|
||||
};
|
||||
var contourIterator = function (contour) {
|
||||
contour.forEach(pointIterator);
|
||||
};
|
||||
|
||||
glyf.contours.forEach(contourIterator);
|
||||
|
||||
var bound = computeBoundingBox.computePathBox.apply(null, glyf.contours);
|
||||
glyf.xMin = bound.x;
|
||||
glyf.xMax = bound.x + bound.width;
|
||||
glyf.yMin = bound.y;
|
||||
glyf.yMax = bound.y + bound.height;
|
||||
|
||||
if (glyf.leftSideBearing) {
|
||||
glyf.leftSideBearing = Math.round(glyf.leftSideBearing * scale);
|
||||
}
|
||||
else {
|
||||
glyf.leftSideBearing = glyf.xMin;
|
||||
}
|
||||
|
||||
if (glyf.advanceWidth) {
|
||||
glyf.advanceWidth = Math.round(glyf.advanceWidth * scale);
|
||||
}
|
||||
else {
|
||||
glyf.advanceWidth = glyf.xMax + Math.abs(glyf.xMin);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (undefined !== ttf.head.xMin && undefined !== ttf.head.yMax) {
|
||||
ttf.head.xMin = Math.round(ttf.head.xMin * scale);
|
||||
ttf.head.xMax = Math.round(ttf.head.xMax * scale);
|
||||
ttf.head.yMin = Math.round(ttf.head.yMin * scale);
|
||||
ttf.head.yMax = Math.round(ttf.head.yMax * scale);
|
||||
}
|
||||
|
||||
ttf.head.unitsPerEm = ttf.head.unitsPerEm ? Math.round(ttf.head.unitsPerEm) : 1024;
|
||||
|
||||
return ttf;
|
||||
}
|
||||
|
||||
@ -132,10 +149,11 @@ define(
|
||||
ttf.metadata = string.decodeHTML(metaNode.textContent.trim());
|
||||
}
|
||||
|
||||
// 解析font
|
||||
// 解析font,如果有font节点说明是svg格式字体文件
|
||||
if (fontNode) {
|
||||
ttf.id = fontNode.getAttribute('id') || '';
|
||||
ttf.hhea.advanceWidthMax = +(fontNode.getAttribute('horiz-adv-x') || 0);
|
||||
ttf.from = 'svgfont';
|
||||
}
|
||||
|
||||
if (fontFaceNode) {
|
||||
@ -174,15 +192,6 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有定义unitsPerEm,可以用viewBox代替
|
||||
var svgNode = xmlDoc.getElementsByTagName('svg')[0];
|
||||
if (!ttf.head.unitsPerEm && svgNode.getAttribute('viewBox')) {
|
||||
var bound = svgNode.getAttribute('viewBox').split(' ');
|
||||
if (bound.length === 4) {
|
||||
ttf.head.unitsPerEm = +bound[2];
|
||||
}
|
||||
}
|
||||
|
||||
return ttf;
|
||||
}
|
||||
|
||||
|
121
src/ttf/ttf.js
121
src/ttf/ttf.js
@ -18,6 +18,54 @@ define(
|
||||
var computeBoundingBox = require('graphics/computeBoundingBox');
|
||||
var glyfAdjust = require('./util/glyfAdjust');
|
||||
|
||||
|
||||
/**
|
||||
* 缩放到EM框
|
||||
*
|
||||
* @param {Array} glyfList glyf列表
|
||||
* @param {number} ascent 上升
|
||||
* @param {number} descent 下降
|
||||
* @param {number} ajdustToEmPadding 顶部和底部留白
|
||||
* @return {Array} glyfList
|
||||
*/
|
||||
function adjustToEmBox(glyfList, ascent, descent, ajdustToEmPadding) {
|
||||
|
||||
glyfList.forEach(function (g) {
|
||||
|
||||
if (g.contours && g.contours.length) {
|
||||
var rightSideBearing = g.advanceWidth - g.xMax;
|
||||
var bound = computeBoundingBox.computePath.apply(null, g.contours);
|
||||
var scale = (ascent - descent - ajdustToEmPadding) / bound.height;
|
||||
var center = (ascent + descent) / 2;
|
||||
var yOffset = center - (bound.y + bound.height / 2) * scale;
|
||||
|
||||
g.contours.forEach(function (contour) {
|
||||
if (scale !== 1) {
|
||||
pathAdjust(contour, scale, scale);
|
||||
}
|
||||
|
||||
pathAdjust(contour, 1, 1, 0, yOffset);
|
||||
pathCeil(contour);
|
||||
});
|
||||
|
||||
var box = computeBoundingBox.computePathBox.apply(null, g.contours);
|
||||
|
||||
g.xMin = box.x;
|
||||
g.xMax = box.x + box.width;
|
||||
g.yMin = box.y;
|
||||
g.yMax = box.y + box.height;
|
||||
|
||||
g.leftSideBearing = g.xMin;
|
||||
g.advanceWidth = g.xMax + rightSideBearing;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return glyfList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 合并两个ttfObject,此处仅合并简单字形
|
||||
*
|
||||
@ -25,18 +73,13 @@ define(
|
||||
* @param {Object} imported ttfObject
|
||||
* @param {Object} options 参数选项
|
||||
* @param {boolean} options.scale 是否自动缩放
|
||||
* @param {boolean} options.adjustGlyf 是否调整字形以适应边界
|
||||
*
|
||||
* @return {Object} 合并后的ttfObject
|
||||
*/
|
||||
function merge(ttf, imported, options) {
|
||||
options = options || {};
|
||||
|
||||
var scale = 1;
|
||||
// 调整glyf对导入的轮廓进行缩放处理
|
||||
if (options.scale && imported.head.unitsPerEm && imported.head.unitsPerEm !== ttf.head.unitsPerEm) {
|
||||
scale = ttf.head.unitsPerEm / imported.head.unitsPerEm;
|
||||
}
|
||||
|
||||
var list = imported.glyf.filter(function (g, index) {
|
||||
// 简单轮廓
|
||||
return g.contours && g.contours.length
|
||||
@ -44,14 +87,37 @@ define(
|
||||
&& g.name !== '.notdef' && g.name !== '.null' && g.name !== 'nonmarkingreturn';
|
||||
});
|
||||
|
||||
list.forEach(function (g) {
|
||||
glyfAdjust(g, scale, scale);
|
||||
ttf.glyf.push(g);
|
||||
});
|
||||
// 调整字形以适应边界
|
||||
if (options.adjustGlyf) {
|
||||
var ascent = ttf.hhea.ascent;
|
||||
var descent = ttf.hhea.descent;
|
||||
var ajdustToEmPadding = 0;
|
||||
adjustToEmBox(list, ascent, descent, ajdustToEmPadding);
|
||||
|
||||
list.forEach(function (g) {
|
||||
ttf.glyf.push(g);
|
||||
});
|
||||
}
|
||||
// 根据unitsPerEm 进行缩放
|
||||
else if (options.scale) {
|
||||
|
||||
var scale = 1;
|
||||
|
||||
// 调整glyf对导入的轮廓进行缩放处理
|
||||
if (imported.head.unitsPerEm && imported.head.unitsPerEm !== ttf.head.unitsPerEm) {
|
||||
scale = ttf.head.unitsPerEm / imported.head.unitsPerEm;
|
||||
}
|
||||
|
||||
list.forEach(function (g) {
|
||||
glyfAdjust(g, scale, scale);
|
||||
ttf.glyf.push(g);
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ttf读取函数
|
||||
*
|
||||
@ -342,7 +408,6 @@ define(
|
||||
|
||||
// 基线高度
|
||||
if (undefined !== setting.verticalAlign) {
|
||||
|
||||
changed = true;
|
||||
|
||||
var verticalAlign = setting.verticalAlign || 0;
|
||||
@ -404,39 +469,11 @@ define(
|
||||
else if (setting.ajdustToEmBox) {
|
||||
|
||||
changed = true;
|
||||
|
||||
var dencent = this.ttf.hhea.descent;
|
||||
var unitsPerEm = this.ttf.head.unitsPerEm;
|
||||
var ascent = this.ttf.hhea.ascent;
|
||||
var descent = this.ttf.hhea.descent;
|
||||
var ajdustToEmPadding = 2 * (setting.ajdustToEmPadding || 0);
|
||||
|
||||
glyfList.forEach(function (g) {
|
||||
if (g.contours && g.contours.length) {
|
||||
|
||||
var rightSideBearing = g.advanceWidth - g.xMax;
|
||||
var bound = computeBoundingBox.computePath.apply(null, g.contours);
|
||||
var scale = (unitsPerEm - ajdustToEmPadding) / bound.height;
|
||||
|
||||
if (scale !== 1) {
|
||||
var yOffset = (unitsPerEm / 2 + dencent) - (bound.y + bound.height / 2) * scale;
|
||||
g.contours.forEach(function (contour) {
|
||||
pathAdjust(contour, scale, scale);
|
||||
pathAdjust(contour, 1, 1, 0, yOffset);
|
||||
pathCeil(contour);
|
||||
});
|
||||
|
||||
var box = computeBoundingBox.computePathBox.apply(null, g.contours);
|
||||
|
||||
g.xMin = box.x;
|
||||
g.xMax = box.x + box.width;
|
||||
g.yMin = box.y;
|
||||
g.yMax = box.y + box.height;
|
||||
|
||||
g.leftSideBearing = g.xMin;
|
||||
g.advanceWidth = g.xMax + rightSideBearing;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
adjustToEmBox(glyfList, ascent, descent, ajdustToEmPadding);
|
||||
}
|
||||
|
||||
return changed ? glyfList : [];
|
||||
|
@ -14,6 +14,7 @@ define(
|
||||
var pathCeil = require('graphics/pathCeil');
|
||||
var computeBoundingBox = require('graphics/computeBoundingBox');
|
||||
|
||||
/* eslint-disable max-params */
|
||||
/**
|
||||
* 简单字形的缩放和平移调整
|
||||
*
|
||||
@ -22,9 +23,11 @@ define(
|
||||
* @param {number} scaleY y缩放比例
|
||||
* @param {number} offsetX x偏移
|
||||
* @param {number} offsetY y偏移
|
||||
* @param {boolan} ceil 是否对字形设置取整,默认取整
|
||||
*
|
||||
* @return {Object} 调整后的glyf对象
|
||||
*/
|
||||
function glyfAdjust(g, scaleX, scaleY, offsetX, offsetY) {
|
||||
function glyfAdjust(g, scaleX, scaleY, offsetX, offsetY, ceil) {
|
||||
|
||||
scaleX = scaleX || 1;
|
||||
scaleY = scaleY || 1;
|
||||
@ -35,7 +38,6 @@ define(
|
||||
if (scaleX !== 1 || scaleY !== 1) {
|
||||
g.contours.forEach(function (contour) {
|
||||
pathAdjust(contour, scaleX, scaleY);
|
||||
pathCeil(contour);
|
||||
});
|
||||
}
|
||||
|
||||
@ -44,6 +46,12 @@ define(
|
||||
pathAdjust(contour, 1, 1, offsetX, offsetY);
|
||||
});
|
||||
}
|
||||
|
||||
if (false !== ceil) {
|
||||
g.contours.forEach(function (contour) {
|
||||
pathCeil(contour);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 重新计算xmin,xmax,ymin,ymax
|
||||
@ -94,6 +102,7 @@ define(
|
||||
|
||||
return g;
|
||||
}
|
||||
/* eslint-enable max-params */
|
||||
|
||||
return glyfAdjust;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user