测试Font是否在Java中是等宽的

12 java fonts swing

我正在尝试列出用户机器上可用的所有等宽字体.我可以通过Swing获得所有字体系列:

String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment()
                                    .getAvailableFontFamilyNames();
Run Code Online (Sandbox Code Playgroud)

有没有办法弄清楚哪些是等宽的?

提前致谢.

Ada*_*ter 6

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

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

您可以使用FontMetrics类的charWidth(char)方法。例如:

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();
Run Code Online (Sandbox Code Playgroud)


swp*_*mer 6

一个更简单的方法,不需要使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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 谢谢; 很棒的务实解决方案!我添加了一行 'Font testFont = new Font(font.getName(), font.getStyle(), 12)' 并测试此字体(即大小 12),因为来自“getAllFonts()”的字体是全部采用尺寸 1。这产生了差异:从 354 个正面(尺寸 1 时)到 303 字体(尺寸 12 时)。顺便说一句,我添加了一个带有“”(空格)的确认测试 - 结果没有改变 303 字体。 (2认同)

Ben*_*tin 3

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

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