在 C++ 中测量 postscript 字体宽度

Posted

技术标签:

【中文标题】在 C++ 中测量 postscript 字体宽度【英文标题】:Measure postscript font width in C++ 【发布时间】:2018-11-04 18:13:10 【问题描述】:

这不可能这么难,但我根本做不到。 google 和 *** 或 ubuntu 或 ghostscript 的文档都没有帮助。

我正在从 C++ 生成后记。我逐字放置文本以处理换行。为了决定下一个单词的放置位置以及它是否适合当前行,我依靠 freetype 来衡量每个字形的“前进”。

文本是普通文本和源代码的混合体,所以我涉及两种字体。我为普通文本选择了 Helvetica,为源代码选择了 Courier,因为两者都可以在 postscript 中轻松获得,并且不需要嵌入。我的后记输出的问题部分并不比

复杂得多
(Helvetica) findfont 11 scalefont setfont
40 100 moveto (hello world) show
123 100 moveto (hello again) show   % I care for the first number

当然,还有合适的 eps 标头等

我没有设法在我的 ubuntu 16.04 系统上找到字体文件,所以我从免费字体网站下载了最佳猜测。事实证明,它们显然与我的 postscript 解释器使用的不同。至少,在使用epstopdf(据我所知,LaTeX 附带)转换为 PDF 后,我看到我的 Helvetica 字体太宽,我的 Courier 字体太窄,所以字间距关闭,最多长词与后续词重叠的点。

我的问题:如何获得与 postscript 解释器匹配的字体宽度测量值?

我什至不确定这个问题是否恰当,但不知何故,我确实假设只有一种参考 Helvetica 字体,因此 postscript 输出在所有系统和打印机上看起来都是一样的。 让 freetype 加载正确的字体可能是最简单的解决方案,但我不知道如何找到文件。 下载完全匹配的字体的来源也可以解决问题,尽管有两次会很奇怪。 更好的是,最好向 ghostscript 之类的 postscript 解释器询问基本事实,但 ghostscript 库文档很少,我没有找到任何示例。 我可以创建一个 postscript 文件,打印使用 textwidth 获得的文本的宽度,转换为 pdf,然后提取文本。那将是丑陋和缓慢的,我想要一个合适的 C++ 解决方案。

在这些或其他方向上的任何进展都绝对很棒!

【问题讨论】:

如果您使用 C++ 进行编码,请不要询问 C — 它们是(完全)不同的语言,尤其是 C++17 与 C11 (C18)。 @Jonathan Leffler:要点。我之所以提到 C,是因为我希望 C 库可以帮助我。在这种情况下,我发现“彻底”值得商榷:) 请求库是题外话,当然 :D — C 和 C++ 的某些部分是常见的,但惯用的现代 C++ 与惯用的现代 C 完全不同(完全完全不同)。 您可以“脱壳”到 ghostscript 并运行一个小 ps 程序并解析结果。类似/Helvetica 24 selectfont 0 0 moveto (my string) stringwidth pop =. 能否请反对者发表评论解释他们的推理?我真的很想知道这个问题是错误的。解决这个案子让我的头发变白了。 【参考方案1】:

您使用的字体应该有一个 .afm (Adobe Font Metrics) 文件,您可以从 如果 它是 PostScript 字体中读取字体指标。就所有 PostScript 实现的度量而言,“base 13”字体应该是相同的,这也是事实。当然,如果您使用 TrueType 字体从中获取指标,那么它们很可能与 PostScript 字体不同。

你还没有说你使用的是什么 PostScript 解释器,可能是它没有使用标准字体,但我猜你使用的是来自 Ubuntu 的 TrueType 字体,它与你使用的 PostScript 字体不太匹配在您的“解释器”中使用。如果没记错的话,您可以查看 /etc/fonts/fonts.conf 以查看字体的存储位置。

FWIW Ghostscript 附带了与 Adob​​e 字体匹配的基本 13 种字体的实现,PostScript 解释器应该与这些字体匹配。然而,我们不提供 AFM 文件,但您可以将字体加载到 Fontographer 中,或使用 FreeType,或者在 PostScript 程序中使用 stringwidth(而不是 textwidth)简单地获取提前宽度。

我不会说 Ghostscript 的文档是“稀疏的”。也许很难找到你想要的东西,但那里有很多文档。只需使用.htm,基本信息,就是一个265Kb的html文件。

当然,最后一种选择是下载您在 PostScript 程序中实际使用的字体,然后您就知道它们与您最初用于创建 PostScript 的指标相匹配。与 PDF 一样,强烈建议这样做,尤其是对于 base 13 以外的字体,这是获得可靠输出的唯一方法。

【讨论】:

非常感谢您的详细回复。我的解释器是“epstopdf”,我相信它是 ghostscript。我检查了系统上的 .afm 文件,发现了 Helvetica.afm 的三个(相同的)副本,所有这些似乎都带有 matplotlib。好东西,它们相当容易解析,甚至是人类可读的,并且标题表明它们是由 Adob​​e 制作的。快速检查显示,这些指标与 freetype 给我的有很大不同。我会继续这条路线。 我终于按照您的建议解决了我的问题,再次感谢。起初,我解析了 .afm 文件,包括使用 Adob​​e 的 AGL 将字形名称转换为 unicode。出于某种原因,.afm 文件在大多数情况下运行良好,但在少数情况下非常错误,例如减号。最后我写了一个小脚本,使用 PostScript 的 show 将 stringwidth 转换为字符串的结果,应用于整个字符范围。我将文件转换为 pdf 并通过从查看器中复制和粘贴来获取数字。没有很好的解决方案,但结果正确。

以上是关于在 C++ 中测量 postscript 字体宽度的主要内容,如果未能解决你的问题,请参考以下文章

测量指定字体的宽度问题

测量指定字体的宽度问题

如何测量给定字体/大小的数字的像素宽度(C#)

postscript 到 pdf 的转换不保留字体

将带有 PostScript 轮廓的 OpenTypeFonts 转换为 TrueType 字体

字体truetype postscript opentype