add glyf reader
This commit is contained in:
parent
3bb0dd5a56
commit
1dd7e958e9
@ -204,7 +204,7 @@ define(
|
||||
delta = e.wheelDelta / 120;
|
||||
}
|
||||
else if (e.detail) {
|
||||
delta = e.detail / 3;
|
||||
delta = -e.detail / 3;
|
||||
}
|
||||
|
||||
var event = getEvent(e);
|
||||
|
@ -5,195 +5,14 @@
|
||||
* @description
|
||||
* glyf表
|
||||
*
|
||||
* modified from svg2ttf
|
||||
* https://github.com/fontello/svg2ttf
|
||||
*/
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
var glyFlag = require('../enum/glyFlag');
|
||||
var componentFlag = require('../enum/componentFlag');
|
||||
|
||||
var table = require('./table');
|
||||
var TTFglyf = require('./ttfglyf');
|
||||
|
||||
/**
|
||||
* 获取glyf的大小
|
||||
*
|
||||
* @param {Object} glyf glyf对象
|
||||
* @return {number} 大小
|
||||
*/
|
||||
function sizeof(glyf, glyfSupport) {
|
||||
if (!glyf.contours.length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//fixed header + instructions + endPtsOfContours
|
||||
var result = 10
|
||||
+ 2
|
||||
+ (glyf.instructions ? glyf.instructions.length : 0)
|
||||
+ glyf.contours.length * 2
|
||||
+ glyfSupport.flags.length;
|
||||
|
||||
|
||||
glyfSupport.xCoord.forEach(function(x) {
|
||||
result += -0xFF <= x && x <= 0xFF ? 1 : 2;
|
||||
});
|
||||
|
||||
glyfSupport.yCoord.forEach(function(y) {
|
||||
result += -0xFF <= y && y <= 0xFF ? 1 : 2;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 复合图元size
|
||||
*
|
||||
* @param {Object} glyf glyf对象
|
||||
* @return {number} 大小
|
||||
*/
|
||||
function sizeofCompound(glyf) {
|
||||
var size = 10;
|
||||
glyf.glyfs.forEach(function(g) {
|
||||
// flags + glyfIndex
|
||||
size += 4;
|
||||
|
||||
// a, b, c, d, e
|
||||
// xy values or points
|
||||
if(g.e >= -0xFF && g.e <= 0xFF && g.f >= 0xFF && g.f <= 0xFF) {
|
||||
size += 2;
|
||||
}
|
||||
else {
|
||||
size += 4;
|
||||
}
|
||||
|
||||
// scale
|
||||
if (g.a != 1 || g.d != 1) {
|
||||
size += g.a == g.d ? 2 : 4;
|
||||
}
|
||||
|
||||
// 01 , 10
|
||||
if (g.b || g.c) {
|
||||
size += 4;
|
||||
}
|
||||
});
|
||||
|
||||
if (glyf.instructions) {
|
||||
size += 2 + glyf.instructions.length;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取flats
|
||||
*
|
||||
* @param {Object} glyf glyf对象
|
||||
* @return {Array}
|
||||
*/
|
||||
function getFlags(glyf, glyfSupport) {
|
||||
|
||||
if (!glyf.contours.length) {
|
||||
return glyfSupport;
|
||||
}
|
||||
|
||||
var flags = [];
|
||||
var prevFlag = -1;
|
||||
var prev = {};
|
||||
var xCoord = [];
|
||||
var yCoord = [];
|
||||
var first = true;
|
||||
var x, y, flag, repeatPoint = -1;
|
||||
glyf.contours.forEach(function(contour) {
|
||||
contour.forEach(function(p) {
|
||||
flag = p.onCurve ? glyFlag.ONCURVE : 0;
|
||||
|
||||
if (first) {
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
}
|
||||
else {
|
||||
x = p.x - prev.x;
|
||||
y = p.y - prev.y;
|
||||
}
|
||||
|
||||
if (-0xFF <= x && x <= 0xFF) {
|
||||
|
||||
if (!first && x == 0) {
|
||||
if (xCoord[xCoord.length - 1] > 0 ) {
|
||||
flag += glyFlag.XSAME;
|
||||
}
|
||||
else {
|
||||
flag += glyFlag.XSHORT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
flag += glyFlag.XSHORT;
|
||||
if(x > 0) {
|
||||
flag += glyFlag.XSAME;
|
||||
}
|
||||
}
|
||||
x = Math.abs(x);
|
||||
}
|
||||
|
||||
|
||||
if (-0xFF <= y && y <= 0xFF) {
|
||||
if (!first && y == 0) {
|
||||
if (yCoord[yCoord.length - 1] > 0 ) {
|
||||
flag += glyFlag.YSAME;
|
||||
}
|
||||
else {
|
||||
flag += glyFlag.YSHORT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
flag += glyFlag.YSHORT;
|
||||
if(y > 0) {
|
||||
flag += glyFlag.YSAME;
|
||||
}
|
||||
}
|
||||
y = Math.abs(y);
|
||||
}
|
||||
|
||||
|
||||
if (prevFlag == flag) {
|
||||
// 记录重复个数
|
||||
if (-1 == repeatPoint) {
|
||||
repeatPoint = flags.length - 1;
|
||||
flags[repeatPoint] |= glyFlag.REPEAT;
|
||||
flags.push(1);
|
||||
}
|
||||
else {
|
||||
++flags[repeatPoint + 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
repeatPoint = -1;
|
||||
flags.push(flag);
|
||||
prevFlag = flag;
|
||||
}
|
||||
|
||||
if (first || 0 != x) {
|
||||
xCoord.push(x);
|
||||
}
|
||||
|
||||
if (first || 0 != y) {
|
||||
yCoord.push(y);
|
||||
}
|
||||
|
||||
prev = p;
|
||||
first = false;
|
||||
});
|
||||
});
|
||||
|
||||
glyfSupport.flags = flags;
|
||||
glyfSupport.xCoord = xCoord;
|
||||
glyfSupport.yCoord = yCoord;
|
||||
|
||||
return glyfSupport;
|
||||
}
|
||||
|
||||
var GlyfContour = require('./glyfcontour');
|
||||
var glyfWriter = require('./glyfwriter');
|
||||
|
||||
var glyf = table.create(
|
||||
'glyf',
|
||||
@ -207,7 +26,7 @@ define(
|
||||
var loca = ttf.loca;
|
||||
var numGlyphs = ttf.maxp.numGlyphs;
|
||||
var glyf = [];
|
||||
var glyfPath = new TTFglyf();
|
||||
var glyfPath = new GlyfContour();
|
||||
|
||||
reader.seek(glyfOffset);
|
||||
|
||||
@ -217,7 +36,7 @@ define(
|
||||
|
||||
// 空路径
|
||||
if(i + 1 < l && loca[i] === loca[i + 1]) {
|
||||
glyf[i] = TTFglyf.empty();
|
||||
glyf[i] = GlyfContour.empty();
|
||||
}
|
||||
else {
|
||||
glyfPath.offset = offset;
|
||||
@ -226,212 +45,8 @@ define(
|
||||
}
|
||||
return glyf;
|
||||
},
|
||||
write: function(writer, ttf) {
|
||||
|
||||
ttf.glyf.forEach(function(glyf, index) {
|
||||
|
||||
if (!glyf.compound && 0 == glyf.contours.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// header
|
||||
writer.writeUint16(glyf.compound ? -1 : glyf.contours.length);
|
||||
writer.writeInt16(glyf.xMin);
|
||||
writer.writeInt16(glyf.yMin);
|
||||
writer.writeInt16(glyf.xMax);
|
||||
writer.writeInt16(glyf.yMax);
|
||||
|
||||
// 复合图元
|
||||
if (glyf.compound) {
|
||||
|
||||
for (var i = 0, l = glyf.glyfs; i < l; i++) {
|
||||
|
||||
var flags = componentFlag.ARGS_ARE_XY_VALUES; // xy values
|
||||
|
||||
// more components
|
||||
if (i < l - 1) {
|
||||
flags += componentFlag.MORE_COMPONENTS;
|
||||
}
|
||||
|
||||
var g = glyf.glyfs[i];
|
||||
|
||||
// instructions
|
||||
flags += glyf.instructions ? componentFlag.WE_HAVE_INSTRUCTIONS : 0;
|
||||
// use my metrics
|
||||
flags += g.useMyMetrics ? componentFlag.USE_MY_METRICS : 0;
|
||||
// overlap compound
|
||||
flags += g.overlapCompound ? componentFlag.OVERLAP_COMPOUND : 0;
|
||||
|
||||
var a = g.a;
|
||||
var b = g.b;
|
||||
var c = g.c;
|
||||
var d = g.d;
|
||||
var e = g.e;
|
||||
var f = g.f;
|
||||
|
||||
// xy values or points
|
||||
if(e < -0xFF || e > 0xFF || f < 0xFF || f > 0xFF) {
|
||||
flags += componentFlag.ARG_1_AND_2_ARE_WORDS;
|
||||
}
|
||||
|
||||
if (b || c) {
|
||||
flags += componentFlag.WE_HAVE_A_TWO_BY_TWO;
|
||||
}
|
||||
else {
|
||||
if (a != 1 || d != 1 && a == d) {
|
||||
flags += componentFlag.WE_HAVE_A_SCALE;
|
||||
}
|
||||
else if (a != 1 || d != 1) {
|
||||
flags += componentFlag.WE_HAVE_AN_X_AND_Y_SCALE;
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeUint16(e);
|
||||
|
||||
if (componentFlag.ARG_1_AND_2_ARE_WORDS & flags) {
|
||||
writer.writeInt16(e);
|
||||
writer.writeInt16(f);
|
||||
|
||||
}
|
||||
else {
|
||||
writer.writeInt8(e);
|
||||
writer.writeInt8(f);
|
||||
}
|
||||
|
||||
if (componentFlag.WE_HAVE_A_SCALE & flags) {
|
||||
writer.writeInt16(Math.round(a * 16384));
|
||||
}
|
||||
else if (componentFlag.WE_HAVE_AN_X_AND_Y_SCALE & flags) {
|
||||
writer.writeInt16(Math.round(a * 16384));
|
||||
writer.writeInt16(Math.round(d * 16384));
|
||||
}
|
||||
else if (componentFlag.WE_HAVE_A_TWO_BY_TWO & flags) {
|
||||
writer.writeInt16(Math.round(a * 16384));
|
||||
writer.writeInt16(Math.round(b * 16384));
|
||||
writer.writeInt16(Math.round(c * 16384));
|
||||
writer.writeInt16(Math.round(d * 16384));
|
||||
}
|
||||
}
|
||||
|
||||
if (glyf.instructions) {
|
||||
var instructions = glyf.instructions;
|
||||
writer.writeUint16(instructions.length);
|
||||
for (var i = 0, l = instructions.length; i < l; i++) {
|
||||
writer.writeUint8(instructions[i] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
var endPtsOfContours = -1;
|
||||
glyf.contours.forEach(function(contour) {
|
||||
endPtsOfContours += contour.length;
|
||||
writer.writeUint16(endPtsOfContours);
|
||||
});
|
||||
|
||||
// not support instruction
|
||||
if (glyf.instructions) {
|
||||
var instructions = glyf.instructions;
|
||||
writer.writeUint16(instructions.length);
|
||||
for (var i = 0, l = instructions.length; i < l; i++) {
|
||||
writer.writeUint8(instructions[i] & 0xFF);
|
||||
}
|
||||
}
|
||||
else {
|
||||
writer.writeUint16(0);
|
||||
}
|
||||
|
||||
// 获取暂存中的flags
|
||||
var flags = ttf.support.glyf[index].flags;
|
||||
for (var i = 0, l = flags.length; i < l; i++) {
|
||||
writer.writeUint8(flags[i]);
|
||||
}
|
||||
|
||||
var xCoord = ttf.support.glyf[index].xCoord;
|
||||
for (var i = 0, l = xCoord.length; i < l; i++) {
|
||||
if (0 <= xCoord[i] && xCoord[i] <= 0xFF) {
|
||||
writer.writeUint8(xCoord[i]);
|
||||
}
|
||||
else {
|
||||
writer.writeInt16(xCoord[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var yCoord = ttf.support.glyf[index].yCoord;
|
||||
for (var i = 0, l = yCoord.length; i < l; i++) {
|
||||
if (0 <= yCoord[i] && yCoord[i] <= 0xFF) {
|
||||
writer.writeUint8(yCoord[i]);
|
||||
}
|
||||
else {
|
||||
writer.writeInt16(yCoord[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4字节对齐
|
||||
var glyfSize = ttf.support.glyf[index].glyfSize;
|
||||
if (glyfSize % 4) {
|
||||
for (var i = 0, l = 4 - glyfSize % 4; i < l; i++) {
|
||||
writer.writeUint8(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return writer;
|
||||
},
|
||||
size: function(ttf) {
|
||||
|
||||
ttf.support.glyf = [];
|
||||
var tableSize = 0;
|
||||
ttf.glyf.forEach(function(glyf) {
|
||||
var glyfSupport = {};
|
||||
var glyfSupport = glyf.compound ? glyfSupport : getFlags(glyf, glyfSupport);
|
||||
var contoursSize = glyf.compound ? sizeofCompound(glyf) : sizeof(glyf, glyfSupport);
|
||||
var size = contoursSize;
|
||||
|
||||
// 记录实际size, 用于4字节对齐
|
||||
var glyfSize = size;
|
||||
|
||||
// glyph size must be divisible by 4.
|
||||
if (size % 4) {
|
||||
size += 4 - size % 4;
|
||||
}
|
||||
|
||||
glyfSupport.glyfSize = glyfSize;
|
||||
glyfSupport.size = size;
|
||||
|
||||
ttf.support.glyf.push(glyfSupport);
|
||||
|
||||
tableSize += size;
|
||||
});
|
||||
|
||||
ttf.support.glyf.tableSize = tableSize;
|
||||
|
||||
// 设置其他表的信息
|
||||
var xMin = 16384, yMin = 16384, xMax = -16384, yMax = -16384;
|
||||
ttf.glyf.forEach(function(glyf) {
|
||||
if (glyf.xMin < xMin) {
|
||||
xMin = glyf.xMin;
|
||||
}
|
||||
if (glyf.yMin < yMin) {
|
||||
yMin = glyf.yMin;
|
||||
}
|
||||
if (glyf.xMax > xMax) {
|
||||
xMax = glyf.xMax;
|
||||
}
|
||||
if (glyf.yMax > yMax) {
|
||||
yMax = glyf.yMax;
|
||||
}
|
||||
});
|
||||
|
||||
ttf.head.xMin = xMin;
|
||||
ttf.head.yMin = yMin;
|
||||
ttf.head.xMax = xMax;
|
||||
ttf.head.yMax = yMax;
|
||||
ttf.head.indexToLocFormat = tableSize > 65536 ? 1 : 0;
|
||||
|
||||
return ttf.support.glyf.tableSize;
|
||||
}
|
||||
write: glyfWriter.write,
|
||||
size: glyfWriter.size
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file ttfglyf.js
|
||||
* @file glyfcontour.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
@ -134,16 +134,16 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
var ttfglyf = table.create(
|
||||
'ttfglyf',
|
||||
var glyfcontour= table.create(
|
||||
'contour',
|
||||
[],
|
||||
{
|
||||
/**
|
||||
* 解析ttfglyfl表
|
||||
* 解析contour表
|
||||
*/
|
||||
read: function(reader, ttf) {
|
||||
var offset = this.offset;
|
||||
var val = ttfglyf.empty();
|
||||
var val = glyfcontour.empty();
|
||||
|
||||
reader.seek(offset);
|
||||
|
||||
@ -269,12 +269,12 @@ define(
|
||||
);
|
||||
|
||||
// 空路径
|
||||
ttfglyf.empty = function() {
|
||||
glyfcontour.empty = function() {
|
||||
var val = {};
|
||||
val.contours = [];
|
||||
return val;
|
||||
};
|
||||
|
||||
return ttfglyf;
|
||||
return glyfcontour;
|
||||
}
|
||||
);
|
432
src/ttf/table/glyfwriter.js
Normal file
432
src/ttf/table/glyfwriter.js
Normal file
@ -0,0 +1,432 @@
|
||||
/**
|
||||
* @file glyfwriter.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* glyf 相关的写方法
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var glyFlag = require('../enum/glyFlag');
|
||||
var componentFlag = require('../enum/componentFlag');
|
||||
|
||||
/**
|
||||
* 获取glyf的大小
|
||||
*
|
||||
* @param {Object} glyf glyf对象
|
||||
* @return {number} 大小
|
||||
*/
|
||||
function sizeof(glyf, glyfSupport) {
|
||||
if (!glyf.contours.length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//fixed header + instructions + endPtsOfContours
|
||||
var result = 10
|
||||
+ 2
|
||||
+ (glyf.instructions ? glyf.instructions.length : 0)
|
||||
+ glyf.contours.length * 2
|
||||
+ glyfSupport.flags.length;
|
||||
|
||||
|
||||
glyfSupport.xCoord.forEach(function(x) {
|
||||
result += 0 <= x && x <= 0xFF ? 1 : 2;
|
||||
});
|
||||
|
||||
glyfSupport.yCoord.forEach(function(y) {
|
||||
result += 0 <= y && y <= 0xFF ? 1 : 2;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 复合图元size
|
||||
*
|
||||
* @param {Object} glyf glyf对象
|
||||
* @return {number} 大小
|
||||
*/
|
||||
function sizeofCompound(glyf) {
|
||||
var size = 10;
|
||||
glyf.glyfs.forEach(function(g) {
|
||||
// flags + glyfIndex
|
||||
size += 4;
|
||||
|
||||
// a, b, c, d, e
|
||||
// xy values or points
|
||||
if(g.e >= -0xFF && g.e <= 0xFF && g.f >= 0xFF && g.f <= 0xFF) {
|
||||
size += 2;
|
||||
}
|
||||
else {
|
||||
size += 4;
|
||||
}
|
||||
|
||||
// scale
|
||||
if (g.a != 1 || g.d != 1) {
|
||||
size += g.a == g.d ? 2 : 4;
|
||||
}
|
||||
|
||||
// 01 , 10
|
||||
if (g.b || g.c) {
|
||||
size += 4;
|
||||
}
|
||||
});
|
||||
|
||||
if (glyf.instructions) {
|
||||
size += 2 + glyf.instructions.length;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取flags
|
||||
*
|
||||
* @param {Object} glyf glyf对象
|
||||
* @return {Array}
|
||||
*/
|
||||
function getFlags(glyf, glyfSupport) {
|
||||
|
||||
if (!glyf.contours.length) {
|
||||
return glyfSupport;
|
||||
}
|
||||
|
||||
|
||||
var prev = {};
|
||||
var flags = [];
|
||||
var xCoord = [];
|
||||
var yCoord = [];
|
||||
var first = true;
|
||||
|
||||
glyf.contours.forEach(function(contour) {
|
||||
contour.forEach(function(p) {
|
||||
if (first) {
|
||||
xCoord.push(p.x);
|
||||
yCoord.push(p.y);
|
||||
}
|
||||
else {
|
||||
xCoord.push(p.x - prev.x);
|
||||
yCoord.push(p.y - prev.y);
|
||||
}
|
||||
flags.push(p.onCurve ? glyFlag.ONCURVE : 0);
|
||||
prev = p;
|
||||
first = false;
|
||||
});
|
||||
});
|
||||
|
||||
// compress
|
||||
var flagsC = [];
|
||||
var xCoordC = [];
|
||||
var yCoordC = [];
|
||||
var x, y, prevX, prevY, prevFlag, repeatPoint = -1;
|
||||
|
||||
flags.forEach(function(flag, index) {
|
||||
|
||||
x = xCoord[index];
|
||||
y = yCoord[index];
|
||||
|
||||
// 第一个
|
||||
if (index == 0) {
|
||||
|
||||
if (-0xFF <= x && x <= 0xFF) {
|
||||
flag += glyFlag.XSHORT;
|
||||
if(x >= 0) {
|
||||
flag += glyFlag.XSAME;
|
||||
}
|
||||
|
||||
x = Math.abs(x);
|
||||
}
|
||||
|
||||
|
||||
if (-0xFF <= y && y <= 0xFF) {
|
||||
flag += glyFlag.YSHORT;
|
||||
if(y >= 0) {
|
||||
flag += glyFlag.YSAME;
|
||||
}
|
||||
|
||||
y = Math.abs(y);
|
||||
}
|
||||
|
||||
|
||||
flagsC.push(prevFlag = flag);
|
||||
xCoordC.push(x);
|
||||
yCoordC.push(y);
|
||||
}
|
||||
//后续
|
||||
else {
|
||||
prevX = xCoord[index - 1];
|
||||
prevY = yCoord[index - 1];
|
||||
|
||||
if (x == 0) {
|
||||
flag += glyFlag.XSAME;
|
||||
}
|
||||
else {
|
||||
if (-0xFF <= x && x <= 0xFF) {
|
||||
flag += glyFlag.XSHORT;
|
||||
if(x > 0) {
|
||||
flag += glyFlag.XSAME;
|
||||
}
|
||||
|
||||
x = Math.abs(x);
|
||||
}
|
||||
|
||||
xCoordC.push(x);
|
||||
}
|
||||
|
||||
if (y == 0) {
|
||||
flag += glyFlag.YSAME;
|
||||
}
|
||||
else {
|
||||
if (-0xFF <= y && y <= 0xFF) {
|
||||
flag += glyFlag.YSHORT;
|
||||
if(y > 0) {
|
||||
flag += glyFlag.YSAME;
|
||||
}
|
||||
y = Math.abs(y);
|
||||
}
|
||||
yCoordC.push(y);
|
||||
}
|
||||
|
||||
// repeat
|
||||
if (flag == prevFlag) {
|
||||
// 记录重复个数
|
||||
if (-1 == repeatPoint) {
|
||||
repeatPoint = flagsC.length - 1;
|
||||
flagsC[repeatPoint] |= glyFlag.REPEAT;
|
||||
flagsC.push(1);
|
||||
}
|
||||
else {
|
||||
++flagsC[repeatPoint + 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
repeatPoint = -1;
|
||||
flagsC.push(prevFlag = flag);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
glyfSupport.flags = flagsC;
|
||||
glyfSupport.xCoord = xCoordC;
|
||||
glyfSupport.yCoord = yCoordC;
|
||||
|
||||
return glyfSupport;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
write: function(writer, ttf) {
|
||||
|
||||
ttf.glyf.forEach(function(glyf, index) {
|
||||
|
||||
if (!glyf.compound && 0 == glyf.contours.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// header
|
||||
writer.writeUint16(glyf.compound ? -1 : glyf.contours.length);
|
||||
writer.writeInt16(glyf.xMin);
|
||||
writer.writeInt16(glyf.yMin);
|
||||
writer.writeInt16(glyf.xMax);
|
||||
writer.writeInt16(glyf.yMax);
|
||||
|
||||
// 复合图元
|
||||
if (glyf.compound) {
|
||||
|
||||
for (var i = 0, l = glyf.glyfs; i < l; i++) {
|
||||
|
||||
var flags = componentFlag.ARGS_ARE_XY_VALUES; // xy values
|
||||
|
||||
// more components
|
||||
if (i < l - 1) {
|
||||
flags += componentFlag.MORE_COMPONENTS;
|
||||
}
|
||||
|
||||
var g = glyf.glyfs[i];
|
||||
|
||||
// instructions
|
||||
flags += glyf.instructions ? componentFlag.WE_HAVE_INSTRUCTIONS : 0;
|
||||
// use my metrics
|
||||
flags += g.useMyMetrics ? componentFlag.USE_MY_METRICS : 0;
|
||||
// overlap compound
|
||||
flags += g.overlapCompound ? componentFlag.OVERLAP_COMPOUND : 0;
|
||||
|
||||
var a = g.a;
|
||||
var b = g.b;
|
||||
var c = g.c;
|
||||
var d = g.d;
|
||||
var e = g.e;
|
||||
var f = g.f;
|
||||
|
||||
// xy values or points
|
||||
if(e < -0xFF || e > 0xFF || f < 0xFF || f > 0xFF) {
|
||||
flags += componentFlag.ARG_1_AND_2_ARE_WORDS;
|
||||
}
|
||||
|
||||
if (b || c) {
|
||||
flags += componentFlag.WE_HAVE_A_TWO_BY_TWO;
|
||||
}
|
||||
else {
|
||||
if (a != 1 || d != 1 && a == d) {
|
||||
flags += componentFlag.WE_HAVE_A_SCALE;
|
||||
}
|
||||
else if (a != 1 || d != 1) {
|
||||
flags += componentFlag.WE_HAVE_AN_X_AND_Y_SCALE;
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeUint16(e);
|
||||
|
||||
if (componentFlag.ARG_1_AND_2_ARE_WORDS & flags) {
|
||||
writer.writeInt16(e);
|
||||
writer.writeInt16(f);
|
||||
|
||||
}
|
||||
else {
|
||||
writer.writeInt8(e);
|
||||
writer.writeInt8(f);
|
||||
}
|
||||
|
||||
if (componentFlag.WE_HAVE_A_SCALE & flags) {
|
||||
writer.writeInt16(Math.round(a * 16384));
|
||||
}
|
||||
else if (componentFlag.WE_HAVE_AN_X_AND_Y_SCALE & flags) {
|
||||
writer.writeInt16(Math.round(a * 16384));
|
||||
writer.writeInt16(Math.round(d * 16384));
|
||||
}
|
||||
else if (componentFlag.WE_HAVE_A_TWO_BY_TWO & flags) {
|
||||
writer.writeInt16(Math.round(a * 16384));
|
||||
writer.writeInt16(Math.round(b * 16384));
|
||||
writer.writeInt16(Math.round(c * 16384));
|
||||
writer.writeInt16(Math.round(d * 16384));
|
||||
}
|
||||
}
|
||||
|
||||
if (glyf.instructions) {
|
||||
var instructions = glyf.instructions;
|
||||
writer.writeUint16(instructions.length);
|
||||
for (var i = 0, l = instructions.length; i < l; i++) {
|
||||
writer.writeUint8(instructions[i] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
var endPtsOfContours = -1;
|
||||
glyf.contours.forEach(function(contour) {
|
||||
endPtsOfContours += contour.length;
|
||||
writer.writeUint16(endPtsOfContours);
|
||||
});
|
||||
|
||||
// not support instruction
|
||||
if (glyf.instructions) {
|
||||
var instructions = glyf.instructions;
|
||||
writer.writeUint16(instructions.length);
|
||||
for (var i = 0, l = instructions.length; i < l; i++) {
|
||||
writer.writeUint8(instructions[i] & 0xFF);
|
||||
}
|
||||
}
|
||||
else {
|
||||
writer.writeUint16(0);
|
||||
}
|
||||
|
||||
// 获取暂存中的flags
|
||||
var flags = ttf.support.glyf[index].flags;
|
||||
for (var i = 0, l = flags.length; i < l; i++) {
|
||||
writer.writeUint8(flags[i]);
|
||||
}
|
||||
|
||||
var xCoord = ttf.support.glyf[index].xCoord;
|
||||
for (var i = 0, l = xCoord.length; i < l; i++) {
|
||||
if (0 <= xCoord[i] && xCoord[i] <= 0xFF) {
|
||||
writer.writeUint8(xCoord[i]);
|
||||
}
|
||||
else {
|
||||
writer.writeInt16(xCoord[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var yCoord = ttf.support.glyf[index].yCoord;
|
||||
for (var i = 0, l = yCoord.length; i < l; i++) {
|
||||
if (0 <= yCoord[i] && yCoord[i] <= 0xFF) {
|
||||
writer.writeUint8(yCoord[i]);
|
||||
}
|
||||
else {
|
||||
writer.writeInt16(yCoord[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4字节对齐
|
||||
var glyfSize = ttf.support.glyf[index].glyfSize;
|
||||
if (glyfSize % 4) {
|
||||
for (var i = 0, l = 4 - glyfSize % 4; i < l; i++) {
|
||||
writer.writeUint8(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return writer;
|
||||
},
|
||||
size: function(ttf) {
|
||||
|
||||
ttf.support.glyf = [];
|
||||
var tableSize = 0;
|
||||
ttf.glyf.forEach(function(glyf) {
|
||||
var glyfSupport = {};
|
||||
var glyfSupport = glyf.compound ? glyfSupport : getFlags(glyf, glyfSupport);
|
||||
var contoursSize = glyf.compound ? sizeofCompound(glyf) : sizeof(glyf, glyfSupport);
|
||||
var size = contoursSize;
|
||||
|
||||
// 记录实际size, 用于4字节对齐
|
||||
var glyfSize = size;
|
||||
|
||||
// glyph size must be divisible by 4.
|
||||
if (size % 4) {
|
||||
size += 4 - size % 4;
|
||||
}
|
||||
|
||||
glyfSupport.glyfSize = glyfSize;
|
||||
glyfSupport.size = size;
|
||||
|
||||
ttf.support.glyf.push(glyfSupport);
|
||||
|
||||
tableSize += size;
|
||||
});
|
||||
|
||||
ttf.support.glyf.tableSize = tableSize;
|
||||
|
||||
// 设置其他表的信息
|
||||
var xMin = 16384, yMin = 16384, xMax = -16384, yMax = -16384;
|
||||
ttf.glyf.forEach(function(glyf) {
|
||||
if (glyf.xMin < xMin) {
|
||||
xMin = glyf.xMin;
|
||||
}
|
||||
if (glyf.yMin < yMin) {
|
||||
yMin = glyf.yMin;
|
||||
}
|
||||
if (glyf.xMax > xMax) {
|
||||
xMax = glyf.xMax;
|
||||
}
|
||||
if (glyf.yMax > yMax) {
|
||||
yMax = glyf.yMax;
|
||||
}
|
||||
});
|
||||
|
||||
ttf.head.xMin = xMin;
|
||||
ttf.head.yMin = yMin;
|
||||
ttf.head.xMax = xMax;
|
||||
ttf.head.yMax = yMax;
|
||||
ttf.head.indexToLocFormat = tableSize > 65536 ? 1 : 0;
|
||||
|
||||
return ttf.support.glyf.tableSize;
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user