将 paper.js 路径转换为 ​​opentype.js 路径

Posted

技术标签:

【中文标题】将 paper.js 路径转换为 ​​opentype.js 路径【英文标题】:Convert paper.js path into an opentype.js path 【发布时间】:2019-10-01 21:23:45 【问题描述】:

我在 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 字体文件。但是,如果我在字体查看器中打开字体,则整个表单是颠倒的,并且句柄是错误的。它们的位置似乎是正确的,但不知何故,错误的手柄位于另一个应该在的位置……它们似乎被调换了。我无法弄清楚我错过了什么..

This is how it should look

This is how it looks..

【问题讨论】:

在我看来,您的 X/Y 轴倒置(上/下和或左/右)。您可以链接前后字母的参考图片吗? @RogerWillcocks 感谢您对此进行调查。我添加了两个图片链接。第一个显示了它的外观,第二个显示了它现在的外观.. 【参考方案1】:

问题是如何解决的: 正如评论中提到的,我看到即使在应该有直线的片段中也没有直线。所以我检查了坐标并意识到如果我只是将它们向前推,就会有直线(手柄 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和nr。 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;是对位置的更正(因此它们被移动到字体中的正确位置。)

也许这可以帮助某人节省一些时间:)

【讨论】:

【参考方案2】:

好的。根据图像,您至少有 2 个问题。 首先是Y坐标倒置了。

importSVG 可能会为您正确地处理它,但您需要处理它回来。

这将意味着第二次迭代 glyphPath 并反转 Y 值。看起来您已经在跟踪最大 Y(或 X?),您将需要它。而且您可能还需要一个偏移值。

第二个问题(这是一个猜测)是曲线正在变成直线。

恐怕我无法就此提供真正的建议,除非这可能意味着您的曲线检测不正确。

【讨论】:

感谢您的输入,我再次检查了路径。我看到即使在应该有直线的片段中也没有直线。所以我检查了坐标并意识到如果我只是将它们向前推,就会有直线(手柄 x1/y2 和 x2/y2 都在坐标 0/0 上的路径)。所以我需要做的是将最后一段的句柄与实际点的实际段的句柄混合。也许这听起来令人困惑,但我会用代码更新我的问题。 :) 再次感谢您对此进行调查。

以上是关于将 paper.js 路径转换为 ​​opentype.js 路径的主要内容,如果未能解决你的问题,请参考以下文章

将opentype转入paper.js,贝塞尔曲线问题

使用图层和混合模式制作的 Paper.js 橡皮擦工具

raphael.js 与 paper.js

Canvas清除Paper.js

如何在动态创建的画布上使用 Paper.js?

将轮廓路径转换为 ​​svg 路径