2009-05-28 9 views
10

J'essaye de lister toutes les polices à espacement fixe disponibles sur la machine d'un utilisateur. Je peux obtenir toutes les familles de polices dans Swing via:Tester si une police est monospaced en Java

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

Existe-t-il un moyen de déterminer lesquels sont à espacement fixe?

Merci d'avance.

Répondre

3

Comparer les longueurs dessinées de plusieurs caractères (m, i, 1,., Devrait être un bon ensemble).

Pour les polices à espacement fixe, elles seront toutes égales, ce qui n'est pas le cas pour les polices à largeur variable.

+0

Pouvez-vous ajouter du code exemple? – Jonik

+0

+1 pour l'approche pratique et simple; J'utilise i et m. –

1

Selon Java this response, Java ne connaît pas grand-chose des détails de la police sous-jacente, donc vous devrez faire quelques comparaisons des dimensions de la police.

4

Vous pouvez utiliser la méthode getWidths() de la classe FontMetrics. Selon JavaDoc:

Obtient les largeurs d'avance des 256 premiers caractères de la police. L'avance est la distance entre le point le plus à gauche et le point le plus à droite sur la ligne de base du personnage. Notez que l'avance d'une chaîne n'est pas nécessairement la somme des avances de ses caractères.

Vous pouvez utiliser la méthode charWidth(char) de la classe FontMetrics. Par exemple:

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

Merci d'avoir étendu votre exemple de code - il n'était pas évident de savoir comment obtenir FontMetrics pour une police donnée. Pourtant, pour une raison quelconque, cela ne trouve pas de polices monospaced sur ma machine (OS X) ... – Jonik

+0

J'ai testé avec une police qui est connue pour être monospaced (java.awt.Font [famille = Andale Mono, nom = Andale Mono , style = plaine, taille = 12]). Pour cette police getWidths() renvoie des nombres comme: 7 0 4 4 4 4 4 4 0 7 7 4 7 7 4 ...: -/ – Jonik

+0

Essayez le code mis à jour –

1

Probablement pas applicable pour votre cas, mais si vous voulez simplement définir la police à une police à espacement fixe, utilisez le nom logique de la police:

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

Ce sera une garantie monospaced police sur votre système.

4

Une méthode plus simple qui ne nécessite pas de faire un BufferedImage pour obtenir un objet 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); 
     } 
    } 
Questions connexes