2009-05-28 16 views
10

Estoy intentando enumerar todas las fuentes monoespaciadas disponibles en la máquina de un usuario. Puedo obtener todas las familias de fuentes de oscilación a través de:Comprobando si una fuente está monoespaciada en Java

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

¿Hay una manera de averiguar cuál de estos son monospaced?

Gracias de antemano.

Respuesta

3

Compara las longitudes dibujadas de varios caracteres (m, i, 1,. Debería ser un buen conjunto).

Para fuentes monoespaciadas, todas serán iguales, para fuentes de ancho variable no lo serán.

+0

se puede añadir código de ejemplo? – Jonik

+0

+1 para el enfoque práctico y simple; Yo uso i y m. –

1

De acuerdo con this response, Java no sabe demasiado sobre los detalles de fuente subyacentes, por lo que tendría que hacer algunas comparaciones de las dimensiones de la fuente.

4

Puede utilizar el método getWidths() de la clase FontMetrics. De acuerdo con JavaDoc:

Obtiene los anchos de avance de los primeros 256 caracteres en la Fuente. El avance es la distancia desde el punto más a la izquierda hasta el punto más a la derecha en la línea base del personaje. Tenga en cuenta que el avance de una cadena no es necesariamente la suma de los avances de sus caracteres.

Se puede usar el método de la clase FontMetricscharWidth(char). Por ejemplo:

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(); 
+0

Gracias por extender su código de ejemplo: no era obvio cómo obtener FontMetrics para una fuente determinada. Sin embargo, por alguna razón, esto no encuentra ningún tipo de letra monoespaciado en mi máquina (OS X) ... – Jonik

+0

Probé con una fuente que se sabe que tiene un monoespacio (java.awt.Font [family = Andale Mono, name = Andale Mono , style = plain, size = 12]). Para esta fuente getWidths() devuelve números como: 7 0 4 4 4 4 4 4 0 7 7 4 7 7 4 ...: -/ – Jonik

+0

Pruebe el código actualizado –

1

Probablemente no es aplicable a su caso, pero si simplemente desea establecer la fuente a una fuente de espacio fijo, utilice el nombre de la fuente lógica:

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

Este será un garantizado de espacio fijo fuente en su sistema.

4

Un método más sencillo que no requiere hacer una BufferedImage para obtener un objeto Graphics, 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); 
     } 
    } 
Cuestiones relacionadas