2009-05-28 8 views
10

Ich versuche, alle auf dem Computer eines Benutzers verfügbaren Schriften mit nichtproportionalem Abstand aufzulisten. Ich kann alle Schriftfamilien in Swing erhalten über:Testen, ob eine Schriftart in Java nicht getrennt ist

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

Gibt es eine Möglichkeit, herauszufinden, welche von diesen sind monospaced?

Vielen Dank im Voraus.

Antwort

3

Vergleichen Sie die gezeichneten Längen mehrerer Zeichen (m, i, 1,. Sollte ein guter Satz sein).

Für Schriften mit einem festen Abstand sind sie alle gleich, für Schriften mit variabler Breite nicht.

+0

Können Sie Beispiel-Code hinzufügen zu bekommen? – Jonik

+0

+1 für den praktischen und einfachen Ansatz; Ich benutze ich und m. –

1

Laut this response weiß Java nicht viel über die zugrunde liegenden Schriftartdetails, daher müssten Sie einige Vergleiche der Schriftdimensionen vornehmen.

4

Sie könnten die getWidths() Methode der FontMetrics Klasse verwenden. Gemäß JavaDoc:

Ruft die Fortschrittsbreiten der ersten 256 Zeichen im Font ab. Der Fortschritt ist die Entfernung zwischen dem Punkt ganz links und dem Punkt ganz rechts auf der Grundlinie des Charakters. Beachten Sie, dass der Fortschritt eines Strings nicht unbedingt die Summe der Fortschritte seiner Zeichen ist.

Sie konnten die charWidth(char) Methode der FontMetrics Klasse. Zum Beispiel:

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

Vielen Dank für die Erweiterung Ihres Beispielcodes - es war nicht offensichtlich, wie Sie FontMetrics für eine bestimmte Schriftart erhalten. Aus irgendeinem Grund finde ich auf meinem Rechner keine monospaced Fonts (OS X) ... – Jonik

+0

Ich testete mit einer Schriftart, die bekanntermaßen monospaced ist (java.awt.Font [family = Andale Mono, name = Andale Mono , Stil = Ebene, Größe = 12]). Für diese Schriftart liefert getWidths() Zahlen wie: 7 0 4 4 4 4 4 4 0 7 7 4 7 7 4 ...: -/ – Jonik

+0

Probieren Sie den aktualisierten Code –

1

Wahrscheinlich nicht anwendbar für Ihren Fall, aber wenn Sie einfach festlegen möchten die Schriftart in einer nichtproportionalen Schrift, verwenden Sie die logische Schriftname:

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

Dies wird eine garantierte dicktengleiche Schriftart auf Ihrem System.

4

Eine einfachere Methode, die keine BufferedImage Herstellung erfordert ein Graphics-Objekt 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); 
     } 
    } 
Verwandte Themen