【问题标题】:How do I get the height and width of a text printed on a 300 dpi label printer?如何获得在 300 dpi 标签打印机上打印的文本的高度和宽度?
【发布时间】:2013-10-26 06:25:54
【问题描述】:

我需要打印一个文本,例如“产品名称”到标签,由 300 dpi 标签打印机打印,来自 JAVA。 字体为宋体。字体大小 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 打印机打印在标签上时,如何获得以毫米为单位的宽度?

【问题讨论】:

  • 您尝试过的代码在哪里?
  • 我试过了,但对 graphics2D 感到困惑: String str = "Hello World";字体 font = new Font("Arial", 0, 6); Graphics2D ig2; BufferedImage bi = new BufferedImage(150, 100, BufferedImage.TYPE_INT_ARGB); ig2 = bi.createGraphics(); Rectangle2D r2D = font.getStringBounds(str, ig2.getFontRenderContext());
  • edit您的问题包含代码。

标签: java


【解决方案1】:

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

This doc 明确表示 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() 的输出。 (矩形的顶部是任意的。)您可以看到字符串宽度与文本接触基线的点无关,但也不是从最左边到最右边的填充像素的距离。相反,它是沿着基线向右推进,从这个字符串被绘制到下一个字符串通常被绘制的地方。

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

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

如果结果在您看来并不居中,则可能是您的数学计算有误,或者您的打印代码中的某些内容没有按照您的想法执行,或者字体设计师根本没有平衡视觉重量随心所欲。如果是后者,请随意申请一些艺术许可,然后将其添加到您喜欢的地方。

【讨论】:

  • 感谢您的帖子。那么有什么方法可以确保获得正确的文本宽度?
  • @JakobMathiasen 用我用来获取字符串宽度的代码更新了答案。
  • 感谢您的回答。我可以使用这个.. 一个小问题是,stringWidth("xxx") 方法给出了从基线起点到基线终点的长度,而不是从整体起点到终点的长度。在有关此的所有文档中,他们都说我不能通过获取每个字符的宽度并将它们加在一起来依赖结果..
  • @JakobMathiasen 不能添加单个字符宽度的原因是字体对 AV 和 XO 等字符对进行了字距调整。因此,假设您将文本打印为完整的字符串(而不是一次一个字符),stringWidth 会返回您想要的答案。如果按照整体宽度,您指的是允许 W 的左上角从起点稍偏左侧开始的方式,这是一个微妙的细节,需要您以小于 mm 的单位进行思考。
  • 正是“W”给了我这个问题。我需要将文本 NCW 居中在一个矩形内。但是 stringWidth("NCW") 给了我基线的宽度。因此,当我将文本居中时,由于“W”的右上角,它似乎没有居中。我仍然不知道如何正确计算。
【解决方案2】:

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

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

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

【讨论】:

  • 有没有办法避免Graphics2D,当我想计算字符串的宽度?
  • 我想你在问这个问题的内容:stackoverflow.com/questions/10677876/…
  • 感谢您的链接。当我实现它时,我得到(示例)stringWidth(“产品名称”)= 37。但是“37”在这种情况下是什么意思? 37像素? 37/300 = 0.1233 英寸 = 3.1 毫米。但是标签上的字符串实际上是 12 毫米..
  • 没有你的代码,很难说。听起来你在某处有另一个重新缩放(4x)。您能否发布所有您的代码,从您获取 FontMetrics 的位置一直到您将其发送到打印机的位置?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-30
相关资源
最近更新 更多