- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在开发一个应用程序,它可以解析 TrueType 字体中的字形数据,并将其转换为多边形,以便使用 OpenGL ES 2.0 进行渲染。
我已成功将字形数据转换为离散指令,例如 MOVE_TO
、LINE_TO
、QUAD_TO
和 CLOSE
,类似于 Java 的 Path2D
类。然后我 triangulate 这些路径进行渲染。
我遇到的问题是,我似乎以非标准方式处理这些指令,因为我可以有效地渲染一些字体,但无法渲染其他字体,如下所示。经过一些测试后,这似乎是我在 LINE_TO 和 BEZIER_TO 指令之间移动时使用的决策逻辑,但我找不到与这两种字体兼容的序列。
是否有关于如何对 Java 的 Path2D
数据进行三角测量的在线文档?
1。正确渲染的字形('c')。
2。错误渲染的字形,来自不同的字体('c')。
在下面的代码片段中,我选择了要绘制三角测量的点。无论我们在曲线的内部还是外部,我们都会绘制贝塞尔曲线的端点或贝塞尔控制点。贝塞尔曲线单独正确渲染到此代码。
switch(lVectorPathComponent) {
case MOVE_TO :
/* Append the current vertex to PolygonPoints. */
if((lLastPathComponent == EVectorPathComponent.BEZIER_TO || lLastPathComponent == EVectorPathComponent.MOVE_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
/* Initialize the start location of the path. */
lStartX = pVectorPath.getPathData()[i + 1];
lStartY = pVectorPath.getPathData()[i + 2];
break;
case LINE_TO :
if(lLastPathComponent != EVectorPathComponent.MOVE_TO) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
else {
if((lNextPathComponent == EVectorPathComponent.LINE_TO || lNextPathComponent == EVectorPathComponent.BEZIER_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
}
break;
case BEZIER_TO :
if(VectorPathGlobal.onCalculateBezierDirection(pVectorPath, i) == pVectorPath.getWindingOrder()) {
if(!(lLastPathComponent == EVectorPathComponent.LINE_TO && lNextPathComponent == EVectorPathComponent.BEZIER_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i - 2], pVectorPath.getPathData()[i - 1])); /* Last X, Y */
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2])); /* Control Point */
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 3], pVectorPath.getPathData()[i + 4])); /* Bezier end X, Y */
}
}
else {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 3], pVectorPath.getPathData()[i + 4]));
}
break;
case CLOSE :
lPolygonPoints.add(new PolygonPoint(lStartX, lStartY));
break;
}
}
正确渲染的曲线由以下命令组成:
MOVE_TO x:121.0 y:682.0
BEZIER_TO cx:121.0 cy:840.0 x:164.0 y:969.0
BEZIER_TO cx:208.0 cy:1098.0 x:289.0 y:1189.0
BEZIER_TO cx:370.0 cy:1281.0 x:485.0 y:1330.0
BEZIER_TO cx:601.0 cy:1380.0 x:746.0 y:1380.0
BEZIER_TO cx:797.0 cy:1380.0 x:838.0 y:1374.0
BEZIER_TO cx:880.0 cy:1369.0 x:914.0 y:1360.0
BEZIER_TO cx:949.0 cy:1351.0 x:978.0 y:1339.0
BEZIER_TO cx:1007.0 cy:1327.0 x:1033.0 y:1314.0
LINE_TO x:978.0 y:1184.0
BEZIER_TO cx:929.0 cy:1207.0 x:872.0 y:1220.0
BEZIER_TO cx:816.0 cy:1234.0 x:746.0 y:1234.0
BEZIER_TO cx:650.0 cy:1234.0 x:571.0 y:1202.0
BEZIER_TO cx:492.0 cy:1170.0 x:435.0 y:1102.0
BEZIER_TO cx:379.0 cy:1035.0 x:348.0 y:931.0
BEZIER_TO cx:317.0 cy:827.0 x:317.0 y:682.0
BEZIER_TO cx:317.0 cy:537.0 x:349.0 y:432.0
BEZIER_TO cx:382.0 cy:327.0 x:441.0 y:259.0
BEZIER_TO cx:500.0 cy:191.0 x:583.0 y:158.0
BEZIER_TO cx:666.0 cy:126.0 x:768.0 y:126.0
BEZIER_TO cx:811.0 cy:126.0 x:847.0 y:131.0
BEZIER_TO cx:884.0 cy:137.0 x:915.0 y:146.0
BEZIER_TO cx:946.0 cy:155.0 x:972.0 y:165.0
BEZIER_TO cx:998.0 cy:176.0 x:1020.0 y:186.0
LINE_TO x:1062.0 y:58.0
BEZIER_TO cx:1009.0 cy:25.0 x:933.0 y:2.0
BEZIER_TO cx:858.0 cy:-20.0 x:746.0 y:-20.0
BEZIER_TO cx:601.0 cy:-20.0 x:485.0 y:30.0
BEZIER_TO cx:370.0 cy:81.0 x:289.0 y:173.0
BEZIER_TO cx:208.0 cy:265.0 x:164.0 y:394.0
BEZIER_TO cx:121.0 cy:524.0 x:121.0 y:682.0
错误渲染的曲线使用这些:
MOVE_TO x:831.0 y:1391.0
BEZIER_TO cx:556.0 cy:1391.0 x:398.0 y:1215.0
BEZIER_TO cx:240.0 cy:1039.0 x:240.0 y:733.0
BEZIER_TO cx:240.0 cy:420.0 x:389.0 y:247.0
BEZIER_TO cx:538.0 cy:74.0 x:815.0 y:74.0
BEZIER_TO cx:999.0 cy:74.0 x:1153.0 y:121.0
LINE_TO x:1153.0 y:31.0
BEZIER_TO cx:1008.0 cy:-20.0 x:791.0 y:-20.0
BEZIER_TO cx:483.0 cy:-20.0 x:306.0 y:179.0
BEZIER_TO cx:129.0 cy:378.0 x:129.0 y:735.0
BEZIER_TO cx:129.0 cy:958.0 x:213.0 y:1128.0
BEZIER_TO cx:298.0 cy:1298.0 x:456.0 y:1390.0
BEZIER_TO cx:615.0 cy:1483.0 x:825.0 y:1483.0
BEZIER_TO cx:1039.0 cy:1483.0 x:1208.0 y:1403.0
LINE_TO x:1167.0 y:1311.0
BEZIER_TO cx:1007.0 cy:1391.0 x:831.0 y:1391.0
最佳答案
是的,代码没问题。下面的代码使用标准 Path2DquadTo/curveTo。也许这与奇偶缠绕规则等有关。
public class JavaGUI extends JPanel {
public static void main(String[] args) {
final JFrame f = new JFrame("Glyphs");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JavaGUI());
f.pack();
f.setLocationRelativeTo(null);
EventQueue.invokeLater(() -> {
f.setVisible(true);
});
}
public JavaGUI() {
setPreferredSize(new Dimension(600, 600));
setBackground(new Color(0xDDEEFF));
}
private double x0;
private double y0;
@Override
public void paintComponent(Graphics g) {
final String aString = "c";
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
double scale = 0.25;
g2d.translate(100, 100);
g2d.scale(scale, scale);
Path2D.Double path = new Path2D.Double(); // May add rule and such.
moveTo(path, 121.0, 682.0);
bezierTo(path, 121.0, 840.0, 164.0, 969.0);
bezierTo(path, 208.0, 1098.0, 289.0, 1189.0);
bezierTo(path, 370.0, 1281.0, 485.0, 1330.0);
bezierTo(path, 601.0, 1380.0, 746.0, 1380.0);
bezierTo(path, 797.0, 1380.0, 838.0, 1374.0);
bezierTo(path, 880.0, 1369.0, 914.0, 1360.0);
bezierTo(path, 949.0, 1351.0, 978.0, 1339.0);
bezierTo(path, 1007.0, 1327.0, 1033.0, 1314.0);
lineTo(path, 978.0, 1184.0);
bezierTo(path, 929.0, 1207.0, 872.0, 1220.0);
bezierTo(path, 816.0, 1234.0, 746.0, 1234.0);
bezierTo(path, 650.0, 1234.0, 571.0, 1202.0);
bezierTo(path, 492.0, 1170.0, 435.0, 1102.0);
bezierTo(path, 379.0, 1035.0, 348.0, 931.0);
bezierTo(path, 317.0, 827.0, 317.0, 682.0);
bezierTo(path, 317.0, 537.0, 349.0, 432.0);
bezierTo(path, 382.0, 327.0, 441.0, 259.0);
bezierTo(path, 500.0, 191.0, 583.0, 158.0);
bezierTo(path, 666.0, 126.0, 768.0, 126.0);
bezierTo(path, 811.0, 126.0, 847.0, 131.0);
bezierTo(path, 884.0, 137.0, 915.0, 146.0);
bezierTo(path, 946.0, 155.0, 972.0, 165.0);
bezierTo(path, 998.0, 176.0, 1020.0, 186.0);
lineTo(path, 1062.0, 58.0);
bezierTo(path, 1009.0, 25.0, 933.0, 2.0);
bezierTo(path, 858.0, -20.0, 746.0, -20.0);
bezierTo(path, 601.0, -20.0, 485.0, 30.0);
bezierTo(path, 370.0, 81.0, 289.0, 173.0);
bezierTo(path, 208.0, 265.0, 164.0, 394.0);
bezierTo(path, 121.0, 524.0, 121.0, 682.0);
path.closePath();
g2d.setColor(Color.RED);
g2d.fill(path);
// ------
path = new Path2D.Double(); // May add rule and such.
moveTo(path, 831.0, 1391.0);
bezierTo(path, 556.0, 1391.0, 398.0, 1215.0);
bezierTo(path, 240.0, 1039.0, 240.0, 733.0);
bezierTo(path, 240.0, 420.0, 389.0, 247.0);
bezierTo(path, 538.0, 74.0, 815.0, 74.0);
bezierTo(path, 999.0, 74.0, 1153.0, 121.0);
lineTo(path, 1153.0, 31.0);
bezierTo(path, 1008.0, -20.0, 791.0, -20.0);
bezierTo(path, 483.0, -20.0, 306.0, 179.0);
bezierTo(path, 129.0, 378.0, 129.0, 735.0);
bezierTo(path, 129.0, 958.0, 213.0, 1128.0);
bezierTo(path, 298.0, 1298.0, 456.0, 1390.0);
bezierTo(path, 615.0, 1483.0, 825.0, 1483.0);
bezierTo(path, 1039.0, 1483.0, 1208.0, 1403.0);
lineTo(path, 1167.0, 1311.0);
bezierTo(path, 1007.0, 1391.0, 831.0, 1391.0 );
path.closePath();
g2d.setColor(new Color(0x8800CC00, true));
g2d.fill(path);
g2d.scale(1/scale, 1/scale);
}
private void bezierTo(Path2D.Double path, double cx, double cy,
double x, double y) {
path.quadTo(cx, cy, x, y);
//path.curveTo(x0, y0, cx, cy, x, y);
x0 = x;
y0 = y;
}
private void moveTo(Path2D.Double path, double x, double y) {
path.moveTo(x, y);
x0 = x;
y0 = y;
}
private void lineTo(Path2D.Double path, double x, double y) {
path.lineTo(x, y);
x0 = x;
y0 = y;
}
}
关于java - Java 如何对 Path2D 进行三角剖分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27869859/
这是我的作业 What does echo PATH $PATH \$PATH do? 我不知道它是如何工作的。 echo PATH打印“路径” $PATH创建一个“PATH”变量......也许?
我想弄清楚两者之间的区别 路径=路径+[节点1] 路径+=[节点1] path.append(node1) 我得到的是 path = path + [node1] 的正确路径,但不是其他两个。 def
我使用 Robot 框架在 Ride 中创建了一个测试用例。运行时出现错误。 我更新了python的路径。我更新了库和 Ride。我换了文件夹还是不行 *** Settings *** Documen
我尝试使用额外的功能自定义 pathlib.Path()。特别是,我真的很喜欢使用上下文管理器作为移入和移出目录的方法。我一直在使用它,但我似乎在让 Path() 与自定义上下文管理器一起工作时遇到错
编辑:基于 Ulf Rompe 的评论,重要的是使用“1”而不是“0”,否则您将破坏 sys.path . 我已经做 python 很长一段时间了(一年多),我总是很困惑为什么人们建议你使用 sys.
我有兴趣这样做的原因是因为我的路径中有一部分将保持不变,但我希望将其与其所有父部分一起删除。 所以如果我们说, some/unknown/path/foo/bar/baz 我想回去 bar/baz 但
在几个 SO 的问题中,有这些行可以访问代码的父目录,例如os.path.join(os.path.dirname(__file__)) returns nothing和 os.path.join(o
我已经在我的 Linux 中安装了 anaconda 来导入 python 包。 安装 anaconda 后,我无法在 python 中使用 anaconda,经过一番搜索后我发现输入此命令我能够使用
哪个更好用,为什么?我的意思是这两个命令在哪些方面不同以及如何不同?性能、可读性…… new FileInfo(path).Name 或 Path.GetFileName(path) 最佳答案 因为您
这不适用于某些设备。 在三星设备中,他们不允许使用下载管理器下载文件。 我已经在 list 中定义了权限并获得了运行时权限。 DownloadManager downloadManager = (Do
我想知道在这个例子中使用 Paths.get() 和 Path.resolve 有什么区别: public static void main(String[] args) { Path p1
目前我正在开发一个转换由 Inkscape 创建的 svg-paths 的应用程序。现在我不清楚关于绝对和相对路径组合的路径规范。规范是否说明了同时包含相对和绝对坐标的路径定义? 特别是关于绝对贝塞尔
我正在编写脚本,我需要在用户的 $PATH 上查找命令并获取该命令的完整路径。问题是我不知道用户的登录 shell 是什么,或者他们的 do 文件中可能有什么奇怪的东西。我将 bourne shell
Metalsmith 的文档对 path() 函数没有太多解释:#path(paths...): Resolve any amount of paths... relative to the work
我知道我可以通过 regedit 更改我的 wine PATH,但实际上我只需要为一次运行更改 PATH。 例如,我的软件名为frontend.exe,这取决于example/mylib.dll,我需
因此,绝对路径是一种到达某个文件或位置的方法,描述了它的完整路径、完整路径,并且它依赖于操作系统(Windows 和 Linux 的绝对路径,例如,不同)。另一方面,相对路径是从当前位置 ..(两个点
我对编程有点陌生(不是真的,但我仍在学习 - 我们不是吗?)。虽然我了解 Java 和 Python,并且了解 C、C++、JS、C#、HTML、CSS 等(并且我可以在终端中很好地导航),但我不熟悉
我对编程有点陌生(不是真的,但我仍在学习 - 我们不是吗?)。虽然我了解 Java 和 Python,并且了解 C、C++、JS、C#、HTML、CSS 等(并且我可以在终端中很好地导航),但我不熟悉
这个问题不太可能对任何 future 的访客有帮助;它只与一个较小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于全世界的互联网受众。如需帮助使此问题更广泛适用,visit the
使用环境变量(如 PATH)作为 $PATH 或 ${PATH} 有什么区别? 最佳答案 在大多数情况下没有区别。唯一重要的是你是否想在扩展后包含尾随文本。例如,假设您的 PATH 包含字符串 FOO
我是一名优秀的程序员,十分优秀!