将 paper.js 路径转换为 opentype.js 路径
Convert paper.js path into an opentype.js path
我在 paper.js 中有一个路径描述了一个字体。我通过加载带有 opentype.js 函数 path.toSVG(); 的字体获得了路径;比我通过 .importSVG() 将它加载到 paper.js;
现在我对 paper.js 进行了一些操作,然后希望将其作为可下载的字体文件返回。所以我的问题是,有没有一种简单的方法可以将它从 paper.js 恢复到 opentype.js?
编辑:
好吧,我假设没有简单的方法。所以我尝试用js手动转换路径:
for(var i=0; i<fragments.children.length; i++) {
var glyphName = fragments.children[i].name;
if (glyphName.indexOf('0x') > -1) {
var unicode = String.fromCharCode(parseInt(glyphName, 16));
glyphName = 'uni' + glyphName.charCodeAt(0);
} else {
var unicode = glyphName.charCodeAt(0);
}
var w = 0;
var glyphPath = new opentype.Path();
//Going through the array with the segments of the paper.js Path
for(var i2 = 0; i2 < fragments.children[i].segments.length; i2++) {
// handle In
var x1 = fragments.children[i].segments[i2].handleIn.x;
var y1 = fragments.children[i].segments[i2].handleIn.y;
// handle Out
var x2 = fragments.children[i].segments[i2].handleOut.x;
var y2 = fragments.children[i].segments[i2].handleOut.y;
// Point
var x = fragments.children[i].segments[i2].point.x;
var y = fragments.children[i].segments[i2].point.y;
if (i2 === 0) {
// if its the first segment use move to
glyphPath.moveTo(x, y);
} else if(x1==0 && y1==0 && x2 == 0 && y2 == 0) {
// if there is no curve use line to
glyphPath.lineTo(x, y);
} else {
// use curve if its a curve
glyphPath.curveTo(x1+x,y1+y, x2+x,y2+y, x,y,);
}
if(i2+1 == fragments.children[i].segments.length) {
glyphPath.close();
}
w = Math.max(w, x);
}
var glyph = new opentype.Glyph({
name: fragments.children[i].name,
unicode: unicode,
advanceWidth: (w + 1),
path: glyphPath
});
}
这让我可以下载一个 opentype 字体文件。但是,如果我在字体查看器中打开字体,整个表单就会颠倒过来并且句柄是错误的。它们的位置似乎是正确的,但不知何故,错误的手柄在另一个应该在的位置……它们似乎被 sed。我不知道我错过了什么..
This is how it should look
This is how it looks..
好的。根据图像,您至少有 2 个问题。
首先是Yco-ordinates倒转了。
importSVG 可能会为您正确处理该问题,但您需要在返回时处理它。
这将意味着第二次迭代 glyphPath 并反转 Y 值。看起来您已经在跟踪最大 Y(或 X?),并且您将需要它。您可能还需要一个偏移值。
第二个问题(猜测)是曲线正在变成直线。
恐怕我不能就此提出真正的建议,除了这可能意味着您的曲线检测不正确。
问题是如何解决的:
正如评论中提到的,我看到即使在应该有直线的片段中也没有直线。所以我检查了坐标并意识到有直线(句柄 x1/y2 和 x2/y2 的路径都在坐标 0/0 上)如果我只是将它们向前推。
例如:
x y x1 y1 x2 y2
1: 148.29 92.125 0 0 -1.25 -3.5
2: 140 85 3.93 1.084 0 0
3: 139.99 74.16 0 0 12.95 2.02
4: 159.55 92.1 -1.238 -8.283 0 0
所以我不得不更改 for 循环以实际获取最后一个点的句柄与实际点的句柄。
所以在这个例子中nr。 1 和天然橡胶。 3 会得到 x1: 0, y1: 0 // x2: 0, y2: 0
在我的 for 循环中,我从最后一段取 x1/y1:
// handle In
var x1 = fragmentPathObj.segments[i2-1].handleOut.x * letterScale;
var y1 = fragmentPathObj.segments[i2-1].handleOut.y*-1 * letterScale;
// handle Out
var x2 = fragmentPathObj.segments[i2].handleIn.x * letterScale;
var y2 = fragmentPathObj.segments[i2].handleIn.y*-1 * letterScale;
如果我这样做,我可以检查直线:
if(x1==0 && y1==0 && x2 == 0 && y2 == 0) {
glyphTempPath.lineTo(x, y);
}
并在有手柄的情况下绘制曲线:
var lastX = fragmentPathObj.segments[i2-1].point.x * letterScale - letterPosCorrectionX;
var lastY = fragmentPathObj.segments[i2-1].point.y*-1 * letterScale - letterPosCorrectionY;
glyphTempPath.curveTo(x1+lastX, y1+lastY, x2+x, y2+y, x,y);
lastX/lastY:由于x1/y1来自最后一段,我还需要用最后一点的x/y计算句柄的位置。
letter Scale:用于字母的缩放,计算方法是将字形的advanceWidth除以scaledAdvanceWith
y*-1 : 用于解决倒置问题
letterPosCorrectionX 和 letterPosCorrectionY;是位置的更正(因此它们被移动到字体中的正确位置。)
也许这可以帮助某人节省一些时间:)
我在 paper.js 中有一个路径描述了一个字体。我通过加载带有 opentype.js 函数 path.toSVG(); 的字体获得了路径;比我通过 .importSVG() 将它加载到 paper.js;
现在我对 paper.js 进行了一些操作,然后希望将其作为可下载的字体文件返回。所以我的问题是,有没有一种简单的方法可以将它从 paper.js 恢复到 opentype.js?
编辑: 好吧,我假设没有简单的方法。所以我尝试用js手动转换路径:
for(var i=0; i<fragments.children.length; i++) {
var glyphName = fragments.children[i].name;
if (glyphName.indexOf('0x') > -1) {
var unicode = String.fromCharCode(parseInt(glyphName, 16));
glyphName = 'uni' + glyphName.charCodeAt(0);
} else {
var unicode = glyphName.charCodeAt(0);
}
var w = 0;
var glyphPath = new opentype.Path();
//Going through the array with the segments of the paper.js Path
for(var i2 = 0; i2 < fragments.children[i].segments.length; i2++) {
// handle In
var x1 = fragments.children[i].segments[i2].handleIn.x;
var y1 = fragments.children[i].segments[i2].handleIn.y;
// handle Out
var x2 = fragments.children[i].segments[i2].handleOut.x;
var y2 = fragments.children[i].segments[i2].handleOut.y;
// Point
var x = fragments.children[i].segments[i2].point.x;
var y = fragments.children[i].segments[i2].point.y;
if (i2 === 0) {
// if its the first segment use move to
glyphPath.moveTo(x, y);
} else if(x1==0 && y1==0 && x2 == 0 && y2 == 0) {
// if there is no curve use line to
glyphPath.lineTo(x, y);
} else {
// use curve if its a curve
glyphPath.curveTo(x1+x,y1+y, x2+x,y2+y, x,y,);
}
if(i2+1 == fragments.children[i].segments.length) {
glyphPath.close();
}
w = Math.max(w, x);
}
var glyph = new opentype.Glyph({
name: fragments.children[i].name,
unicode: unicode,
advanceWidth: (w + 1),
path: glyphPath
});
}
这让我可以下载一个 opentype 字体文件。但是,如果我在字体查看器中打开字体,整个表单就会颠倒过来并且句柄是错误的。它们的位置似乎是正确的,但不知何故,错误的手柄在另一个应该在的位置……它们似乎被 sed。我不知道我错过了什么..
This is how it should look
This is how it looks..
好的。根据图像,您至少有 2 个问题。 首先是Yco-ordinates倒转了。
importSVG 可能会为您正确处理该问题,但您需要在返回时处理它。
这将意味着第二次迭代 glyphPath 并反转 Y 值。看起来您已经在跟踪最大 Y(或 X?),并且您将需要它。您可能还需要一个偏移值。
第二个问题(猜测)是曲线正在变成直线。
恐怕我不能就此提出真正的建议,除了这可能意味着您的曲线检测不正确。
问题是如何解决的:
正如评论中提到的,我看到即使在应该有直线的片段中也没有直线。所以我检查了坐标并意识到有直线(句柄 x1/y2 和 x2/y2 的路径都在坐标 0/0 上)如果我只是将它们向前推。
例如:
x y x1 y1 x2 y2
1: 148.29 92.125 0 0 -1.25 -3.5
2: 140 85 3.93 1.084 0 0
3: 139.99 74.16 0 0 12.95 2.02
4: 159.55 92.1 -1.238 -8.283 0 0
所以我不得不更改 for 循环以实际获取最后一个点的句柄与实际点的句柄。
所以在这个例子中nr。 1 和天然橡胶。 3 会得到 x1: 0, y1: 0 // x2: 0, y2: 0
在我的 for 循环中,我从最后一段取 x1/y1:
// handle In
var x1 = fragmentPathObj.segments[i2-1].handleOut.x * letterScale;
var y1 = fragmentPathObj.segments[i2-1].handleOut.y*-1 * letterScale;
// handle Out
var x2 = fragmentPathObj.segments[i2].handleIn.x * letterScale;
var y2 = fragmentPathObj.segments[i2].handleIn.y*-1 * letterScale;
如果我这样做,我可以检查直线:
if(x1==0 && y1==0 && x2 == 0 && y2 == 0) {
glyphTempPath.lineTo(x, y);
}
并在有手柄的情况下绘制曲线:
var lastX = fragmentPathObj.segments[i2-1].point.x * letterScale - letterPosCorrectionX;
var lastY = fragmentPathObj.segments[i2-1].point.y*-1 * letterScale - letterPosCorrectionY;
glyphTempPath.curveTo(x1+lastX, y1+lastY, x2+x, y2+y, x,y);
lastX/lastY:由于x1/y1来自最后一段,我还需要用最后一点的x/y计算句柄的位置。
letter Scale:用于字母的缩放,计算方法是将字形的advanceWidth除以scaledAdvanceWith
y*-1 : 用于解决倒置问题
letterPosCorrectionX 和 letterPosCorrectionY;是位置的更正(因此它们被移动到字体中的正确位置。)
也许这可以帮助某人节省一些时间:)