在 Java 中测试字体是否为等宽字体

发布于 2024-07-22 11:34:06 字数 263 浏览 5 评论 0原文

我正在尝试列出用户计算机上可用的所有等宽字体。 我可以通过以下方式获取 Swing 中的所有字体系列:

String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment()
                                    .getAvailableFontFamilyNames();

有没有办法找出其中哪些是等宽字体?

提前致谢。

I'm trying list all of the monospaced fonts available on a user's machine. I can get all of the font families in Swing via:

String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment()
                                    .getAvailableFontFamilyNames();

Is there a way to figure out which of these are monospaced?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

花开雨落又逢春i 2024-07-29 11:34:06

一种更简单的方法,不需要制作 BufferedImage 来获取 Graphics 对象等:

    Font fonts[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
    List<Font> monoFonts1 = new ArrayList<>();

    FontRenderContext frc = new FontRenderContext(null, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT, RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT);
    for (Font font : fonts) {
        Rectangle2D iBounds = font.getStringBounds("i", frc);
        Rectangle2D mBounds = font.getStringBounds("m", frc);
        if (iBounds.getWidth() == mBounds.getWidth()) {
            monoFonts1.add(font);
        }
    }

A simpler method that doesn't require making a BufferedImage to get a Graphics object etc.:

    Font fonts[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
    List<Font> monoFonts1 = new ArrayList<>();

    FontRenderContext frc = new FontRenderContext(null, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT, RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT);
    for (Font font : fonts) {
        Rectangle2D iBounds = font.getStringBounds("i", frc);
        Rectangle2D mBounds = font.getStringBounds("m", frc);
        if (iBounds.getWidth() == mBounds.getWidth()) {
            monoFonts1.add(font);
        }
    }
街道布景 2024-07-29 11:34:06

您可以使用 getWidths () FontMetrics 类。 根据 JavaDoc:


获取 Font 中前 256 个字符的提前宽度。 前进是角色基线上从最左边的点到最右边的点的距离。 请注意,字符串的前进不一定是其字符的前进之和。

您可以使用 FontMetrics 类。 例如:

Set<String> monospaceFontFamilyNames = new HashSet<String>();

GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontFamilyNames = graphicsEnvironment.getAvailableFontFamilyNames();

BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics graphics = bufferedImage.createGraphics();

for (String fontFamilyName : fontFamilyNames) {
    boolean isMonospaced = true;

    int fontStyle = Font.PLAIN;
    int fontSize = 12;
    Font font = new Font(fontFamilyName, fontStyle, fontSize);
    FontMetrics fontMetrics = graphics.getFontMetrics(font);

    int firstCharacterWidth = 0;
    boolean hasFirstCharacterWidth = false;
    for (int codePoint = 0; codePoint < 128; codePoint++) { 
        if (Character.isValidCodePoint(codePoint) && (Character.isLetter(codePoint) || Character.isDigit(codePoint))) {
            char character = (char) codePoint;
            int characterWidth = fontMetrics.charWidth(character);
            if (hasFirstCharacterWidth) {
                if (characterWidth != firstCharacterWidth) {
                    isMonospaced = false;
                    break;
                }
            } else {
                firstCharacterWidth = characterWidth;
                hasFirstCharacterWidth = true;
            }
        }
    }

    if (isMonospaced) {
        monospaceFontFamilyNames.add(fontFamilyName);
    }
}

graphics.dispose();

You could use the getWidths() method of the FontMetrics class. According to the JavaDoc:

Gets the advance widths of the first 256 characters in the Font. The advance is the distance from the leftmost point to the rightmost point on the character's baseline. Note that the advance of a String is not necessarily the sum of the advances of its characters.

You could use the charWidth(char) method of the FontMetrics class. For example:

Set<String> monospaceFontFamilyNames = new HashSet<String>();

GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontFamilyNames = graphicsEnvironment.getAvailableFontFamilyNames();

BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics graphics = bufferedImage.createGraphics();

for (String fontFamilyName : fontFamilyNames) {
    boolean isMonospaced = true;

    int fontStyle = Font.PLAIN;
    int fontSize = 12;
    Font font = new Font(fontFamilyName, fontStyle, fontSize);
    FontMetrics fontMetrics = graphics.getFontMetrics(font);

    int firstCharacterWidth = 0;
    boolean hasFirstCharacterWidth = false;
    for (int codePoint = 0; codePoint < 128; codePoint++) { 
        if (Character.isValidCodePoint(codePoint) && (Character.isLetter(codePoint) || Character.isDigit(codePoint))) {
            char character = (char) codePoint;
            int characterWidth = fontMetrics.charWidth(character);
            if (hasFirstCharacterWidth) {
                if (characterWidth != firstCharacterWidth) {
                    isMonospaced = false;
                    break;
                }
            } else {
                firstCharacterWidth = characterWidth;
                hasFirstCharacterWidth = true;
            }
        }
    }

    if (isMonospaced) {
        monospaceFontFamilyNames.add(fontFamilyName);
    }
}

graphics.dispose();
沉默的熊 2024-07-29 11:34:06

比较几个字符的绘制长度(m、i、1、. 应该是一个很好的集合)。

对于等宽字体,它们都是相等的,对于可变宽度字体,它们则不然。

Compare the drawn lengths of several characters (m, i, 1, . should be a good set).

For monospaced fonts they will all be equal, for variable width fonts they won't.

極樂鬼 2024-07-29 11:34:06

根据 此回复,Java 并不知道太多关于底层字体细节,因此您必须对字体尺寸进行一些比较。

According to this response, Java doesn't know too much about underlying font details, so you'd have to do some comparisons of the font's dimensions.

小猫一只 2024-07-29 11:34:06

可能不适用于您的情况,但如果您只是想将字体设置为等宽字体,请使用逻辑字体名称:

Font mono = new Font("Monospaced", Font.PLAIN, 12);

这将是您系统上有保证的等宽字体。

Probably not applicable for your case, but if you simply want to set the font to a monospaced font, use the logical font name:

Font mono = new Font("Monospaced", Font.PLAIN, 12);

This will be a guaranteed monospaced font on your system.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文