如何在Java中检索本机字体名称?

时间:2012-10-25 21:30:22

标签: java fonts

Java中有没有办法从Font对象中获取本机字体名称?

我使用此代码Font.decode("Serif")获取我的字体,并且出于调试目的,我想知道使用的本机字体。

3 个答案:

答案 0 :(得分:5)

可能不那么简单。某些字体由许多物理字体组成,对不同的字形使用不同的物理字体。

例如,在我的Windows系统上,Serif字体使用12种物理字体:

  • ** TrueType字体:Family = Times New Roman Name = Times New Roman style = 0 fileName = C:\ Windows \ Fonts \ TIMES.TTF
  • ** TrueType字体:Family = Wingdings Name = Wingdings style = 0 fileName = C:\ Windows \ Fonts \ WINGDING.TTF
  • ** TrueType字体:系列=符号名称=符号样式= 0 fileName = C:\ Windows \ Fonts \ SYMBOL.TTF
  • ** TrueType字体:Family = Lucida Sans Name = Lucida Sans Regular style = 0 fileName = C:\ Java \ jdk \ jdk1.6.0_37 \ jre \ lib \ fonts \ LucidaSansRegular.ttf
  • ** TrueType字体:Family = MingLiU Name = MingLiU style = 0 fileName = C:\ Windows \ Fonts \ MINGLIU.TTC
  • ** TrueType字体:Family = Lucida Sans Name = Lucida Sans Regular style = 0 fileName = C:\ Java \ jdk \ jdk1.6.0_37 \ jre \ lib \ fonts \ LucidaSansRegular.ttf
  • ** TrueType字体:Family = SimSun Name = SimSun style = 0 fileName = C:\ Windows \ Fonts \ SIMSUN.TTC
  • ** TrueType字体:Family = Lucida Sans Name = Lucida Sans Regular style = 0 fileName = C:\ Java \ jdk \ jdk1.6.0_37 \ jre \ lib \ fonts \ LucidaSansRegular.ttf
  • ** TrueType字体:Family = MS Mincho Name = MS Mincho style = 0 fileName = C:\ Windows \ Fonts \ MSMINCHO.TTC
  • ** TrueType字体:Family = Batang Name = Batang style = 0 fileName = C:\ Windows \ Fonts \ batang.TTC
  • ** TrueType字体:Family = MingLiU-ExtB Name = MingLiU-ExtB style = 0 fileName = C:\ Windows \ Fonts \ MINGLIUB.TTC
  • ** TrueType字体:Family = SimSun-ExtB Name = SimSun-ExtB style = 0 fileName = C:\ Windows \ Fonts \ SIMSUNB.TTF

以下代码可以将字体分解为其物理组件。它使用反射黑客来访问sun.awt.Font2D对象,因此使用风险自负(适用于Oracle Java 6u37):

import java.awt.Font;
import java.lang.reflect.Method;
import java.util.Locale;

import sun.font.CompositeFont;
import sun.font.Font2D;
import sun.font.PhysicalFont;

public class FontTester
{
    public static void main(String... args)
    throws Exception
    {
        Font font = new Font("Serif", Font.PLAIN, 12);
        describeFont(font);
    }

    private static void describeFont(Font font)
    throws Exception
    {
        Method method = font.getClass().getDeclaredMethod("getFont2D");
        method.setAccessible(true);
        Font2D f = (Font2D)method.invoke(font);

        describeFont2D(f);
    }

    private static void describeFont2D(Font2D font)
    {
        if (font instanceof CompositeFont)
        {
            System.out.println("Font '" + font.getFontName(Locale.getDefault()) + "' is composed of:");

            CompositeFont cf = (CompositeFont)font;
            for (int i = 0; i < cf.getNumSlots(); i++)
            {
                PhysicalFont pf = cf.getSlotFont(i);
                describeFont2D(pf);
            }
        }
        else
            System.out.println("-> " + font);
    }
}

答案 1 :(得分:1)

如果系统字体可用,此代码将获取系统字体,如果由于某种原因它们不可用,则会获得默认系列:

static String[] AS_System_Fonts = null;
public static String[] getFontFamilies(){
    if( AS_System_Fonts != null ) return AS_System_Fonts;
    java.awt.GraphicsEnvironment gEnv = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
    AS_System_Fonts = gEnv.getAvailableFontFamilyNames();
    if( AS_System_Fonts == null ){ // should not happen
        AS_System_Fonts = new String[8];
        AS_System_Fonts[0] = "Serif";
        AS_System_Fonts[1] = "Sans-Serif";
        AS_System_Fonts[2] = "Monospaced";
        AS_System_Fonts[3] = "Dialog";
        AS_System_Fonts[4] = "Dialog Input";
        AS_System_Fonts[5] = "Lucida Bright";
        AS_System_Fonts[6] = "Lucida Sans";
        AS_System_Fonts[7] = "Lucida Sans Typewriter";
    }
    return AS_System_Fonts;
}

答案 2 :(得分:0)

prunge的回答几乎是完美的,除了它实际上没有公开本地(物理)字体的名称。对describeFont2D方法的以下微小改动通过再次利用Java反射来实现这一点:

不要忘记导入java.lang.reflect.Field;

private static void describeFont2D( Font2D font ) throws Exception{
    if( font instanceof CompositeFont ){
        System.out.println( "Font '"+font.getFontName( Locale.getDefault() )+"' is composed of:" );
        CompositeFont cf = ( CompositeFont )font;
        for( int i = 0; i<cf.getNumSlots(); i++ ){
            PhysicalFont pf = cf.getSlotFont( i );
            describeFont2D( pf );
        }
    }else if( font instanceof CFont ){
        Field field = CFont.class.getDeclaredField( "nativeFontName" );
        field.setAccessible( true );
        String nativeFontName = ( String )field.get( font );                
        System.out.println( "-> "+nativeFontName );
    }else
        System.out.println( "-> "+font );
}