为啥字体大小为 101 的 Graphics2D.drawString 的字母“o”会损坏?

Posted

技术标签:

【中文标题】为啥字体大小为 101 的 Graphics2D.drawString 的字母“o”会损坏?【英文标题】:Why is letter "o" with Graphics2D.drawString at font size 101 broken?为什么字体大小为 101 的 Graphics2D.drawString 的字母“o”会损坏? 【发布时间】:2019-11-18 07:51:58 【问题描述】:

我想在 png 中绘制字符串。我需要高度不超过 600 像素的字母。

因此我尝试使用 Graphics2D.drawString:

    String text = "o";
    graphics.setFont(font.deriveFont(Font.PLAIN, fontsize));
    graphics.drawString(text, 0, 200);

字体大小最大为 100 的文本可以正常工作。 问题:字体大小为 101 时,一些圆形字符(如“o”)有点倾斜。

这可通过字体“Abril_Fatface”、“Amatic_SC”和“Cinzel_Decorative”重现(来自谷歌字体,例如https://fonts.google.com/specimen/Abril+Fatface 或https://fonts.google.com/specimen/Amatic+SC;可通过“选择此字体”然后“下载此部分”下载 ttf 文件在“选择 1 个家庭”对话框中)。使用其他字体,字符串绘制正常。

LibreOffice 将字符显示为圆形(如预期的那样)。

这里是完整的代码:

    import java.awt.Color;
    import java.awt.Font;
    import java.awt.FontFormatException;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    public class CustomFontWriting 
        public static void main(String[] args) throws FontFormatException, IOException 
            Font font = Font.createFont(Font.TRUETYPE_FONT, new File("Amatic_SC.ttf"));
            // Create empty image
            BufferedImage image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_ARGB);
            Graphics2D graphics = image.createGraphics();
            graphics.setColor(Color.BLACK);
            // Draw letter "o" with fontsize 101 in an image
            graphics.setFont(font.deriveFont(Font.PLAIN, 101));
            graphics.drawString("o", 0, 200);
            // Write image to disk
            File output = new File("output.png");
            ImageIO.write(image, "png", output);
        
    

预期结果:圆形字母“o”。

实际结果:斜角字母“o”。

【问题讨论】:

看起来任何负责解释路径坐标的人都做错了——你可能想问这个问题,在 java 错误跟踪器上使用适当的minimal reproducible example。这是 Oracle 的 JDK 还是 OpenJDK? (甚至是第三个,其他版本?) OpenJDK 1.8.0_212 会发生这种情况。 这个例子现在有点短,但仍然重现了问题。使用 Java SE RE 1.8.0_171-b11 就没有这样的问题。示例字母是完美的圆形。 那么(基于this)您可能想在 bugs.java.com 上提交此文件,明确提到这是针对 OpenJDK 1.8(而不是 Oracle JDK)。有可能他们使用的是旧版本的 harfbuzz/freetype/uniscribe/etc,需要进行版本升级,或者他们所依赖的整形引擎中甚至可能存在需要先修复的错误。 好的,我在 bugs.java.com 上提交了这个文件,并使用更新的 OpenJDK 版本 1.11.3 (2019-04-16) 进行了额外测试。使用 OpenJDK 11,我的测试用例成功生成了圆形字母。伟大的。这是我将遵循的解决方案。谢谢! :-) 【参考方案1】:

解决方案是使用 OpenJDK 11 或更高版本。请参阅问题中的 cmets。

【讨论】:

以上是关于为啥字体大小为 101 的 Graphics2D.drawString 的字母“o”会损坏?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的大小为 11 的 truetype 字体呈现与 windows 不同?

为啥微软雅黑字体打印出来大小不一?电脑显示正常,字号为小四,求解~

为啥 Twitter Bootstrap 使用像素作为字体大小?

为啥 Graphics2D.setStoke() 不适用于 Graphics2D.drawString?

为啥字体大小(和其他元素)在移动设备上显得如此之小

Graphics2D在linux上使用Font字体出现乱码或者中文字无法显示的问题