4

我需要从 JAVA 打印一个文本,例如“产品名称”到标签,由 300 dpi 标签打印机打印。字体为宋体。FontSize 6. 如何计算文字的宽度(单位:mm)?

String fontName = "Arial";
int fontSize = 6;
String string = "Product name";
Font font = new Font(fontName, Font.PLAIN, fontSize);
Canvas c = new Canvas();
FontMetrics fm = c.getFontMetrics(font);
int i = fm.stringWidth(string);

在上面的代码中,i=36。但是“36”是什么意思?使用 300DPI 打印机在标签上打印时,如何获得以毫米为单位的宽度?

4

2 回答 2

2

您问题中的代码正在调用new Canvas(),它将假定您的屏幕是预期的输出设备,从而为不同系统上的不同行为创造潜力。

该文档明确指出 Java 2D 中的用户空间旨在为每英寸 72 个单位。FontMetrics 的 Javadoc 没有明确说明它返回的单位,但它是用户空间坐标是有意义的。这意味着您看到的 36 是 36/72 英寸,即 12.7 毫米。

更新 2:

您的问题没有说明您是如何将渲染文本发送到打印机的,因此您可能已经有一个 Graphics 或 Graphics2D 对象,可以从中获取实际输出设备上下文中的字体度量。如果你不这样做,下面的代码应该创建一个独立于屏幕的图形上下文:

    BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = image.createGraphics();
    FontMetrics fm = g.getFontMetrics(new Font("Arial", Font.PLAIN, 6));
    int width = fm.stringWidth("Product name");

结果仍然是 36,以 1/72 英寸为单位。

更新 3:

在下图中,字符串“NCW”以 Arial 显示,由 Java 呈现。矩形的底部是基线,矩形的左下角是我告诉 Java 绘制字符串的点。矩形的宽度fm.stringWidth()如上输出。(矩形的顶部是任意的。)您可以看到字符串宽度与文本接触基线的点无关,但也不是从最左边到最右边的填充像素的距离。相反,它是沿着基线向右推进,从这个字符串被绘制到下一个字符串通常被绘制的地方。

由简短的 Java 程序生成的用于演示 stringWidth 的图像

C 和 W 之间的间距是字距调整的一个很好的例子。字体设计者还选择让 C 的底部边缘稍微延伸到基线下方,因为除非你作弊,否则圆形在视觉上看起来与直的不对齐。请注意 N 的左侧有一些空间,而 W 的右侧则少得多。这与 C 和 W 之间的空间较小的原因相同:使其看起来正确。如果字体设计师想要,他可以让 W 延伸到盒子之外,就像 C 延伸到它下面一样。

最终结果是字母形式的视觉重量应该是均匀分布的,所以那个框的中心应该是文本的视觉中心。所以你应该可以忽略我刚才说的一切,在起点加上一半的弦宽,称之为中心,然后开心。

如果结果看起来不以您为中心,那么您可能有数学错误,或者您的打印代码中的某些内容没有按照您的想法执行,或者字体设计师根本没有根据您的喜好平衡视觉重量. 如果是后者,请随意申请一些艺术许可并将其软化到您喜欢的地方。

于 2013-10-23T19:35:07.663 回答
1

你想要的类是FontMetrics,你可以从你的Graphics2D对象中得到它。

获得 FontMetrics 对象后,您可以使用 、 和 等方法charsWidthgetHeight确定getAscent字符串的适当宽度和高度(取决于“高度”的含义,请参阅此处第 73 页的说明以了解一些关于字体大小的基础知识)以像素为单位。

如您所知,像素与纸上的英寸不同 - 但如果您知道打印机的 DPI,您应该能够通过除法确定以英寸为单位的尺寸:像素 / DPI = 英寸。

于 2013-10-23T12:57:08.490 回答