4

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

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

4

3 回答 3

6

可能没那么简单。有些字体是由很多物理字体组成的,不同的字形使用不同的物理字体。

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

  • ** TrueType 字体:Family=Times New Roman 名称=Times New Roman 样式=0 文件名=C:\Windows\Fonts\TIMES.TTF
  • ** TrueType 字体:Family=Wingdings 名称=Wingdings 样式=0 文件名=C:\Windows\Fonts\WINGDING.TTF
  • ** TrueType 字体:Family=Symbol Name=Symbol style=0 fileName=C:\Windows\Fonts\SYMBOL.TTF
  • ** TrueType 字体:Family=Lucida Sans 名称=Lucida Sans 常规样式=0 文件名=C:\Java\jdk\jdk1.6.0_37\jre\lib\fonts\LucidaSansRegular.ttf
  • ** TrueType 字体:Family=MingLiU 名称=MingLiU 样式=0 文件名=C:\Windows\Fonts\MINGLIU.TTC
  • ** TrueType 字体:Family=Lucida Sans 名称=Lucida Sans 常规样式=0 文件名=C:\Java\jdk\jdk1.6.0_37\jre\lib\fonts\LucidaSansRegular.ttf
  • ** TrueType 字体:Family=SimSun 名称=SimSun 样式=0 文件名=C:\Windows\Fonts\SIMSUN.TTC
  • ** TrueType 字体:Family=Lucida Sans 名称=Lucida Sans 常规样式=0 文件名=C:\Java\jdk\jdk1.6.0_37\jre\lib\fonts\LucidaSansRegular.ttf
  • ** TrueType 字体:Family=MS Mincho 名称=MS Mincho 样式=0 文件名=C:\Windows\Fonts\MSMINCHO.TTC
  • ** TrueType 字体:Family=Batang 名称=Batang 样式=0 文件名=C:\Windows\Fonts\batang.TTC
  • ** TrueType 字体:Family=MingLiU-ExtB 名称=MingLiU-ExtB 样式=0 文件名=C:\Windows\Fonts\MINGLIUB.TTC
  • ** TrueType 字体:Family=SimSun-ExtB 名称=SimSun-ExtB 样式=0 文件名=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);
    }
}
于 2012-10-25T22:50:52.843 回答
2

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 );
}
于 2016-05-11T18:00:31.647 回答
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;
}
于 2012-10-25T22:45:09.897 回答