2014-05-07 61 views
7

我最近發現瞭如何註冊本地GraphicsEnvironment中的某種TTF字體,ST,爲我的使用案例(SVG至PNG轉碼),阿帕奇蠟染可以識別的字體:使用GraphicsEnvironment取消註冊字體?

import java.awt.Font; 
import java.awt.FontFormatException; 
import java.awt.GraphicsEnvironment; 

// [...] 

GraphicsEnvironment lge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
try { 
    Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile); 
    lge.registerFont(font); 
} catch (FontFormatException e) { 
    logger.warn(e.getMessage(), e); 
} catch (IOException e) { 
    logger.warn(e.getMessage(), e); 
} 

不過,我是想知道是否可以註銷任何預先存在的字體,以保證只有我註冊的字體纔會用於轉碼。

沒有GraphicsEnvironment中#unregisterFont(...),我怎麼能做到這一點呢?

PS:我不想繼承GraphicsEnvironment中,因爲我不能假定存在任何特定的子類,像sun.awt.Win32GraphicsEnvironment。

編輯:一些更多的相關信息:

  • 作爲sun.font.FontManager與Java7的變化(從類接口,和諸如此類的東西),我寧可不使用任何解決方法依賴於它。
  • 我的JVM是Oracle JVM。

回答

4

這不能沒有私人靜態變量的反映,這樣......你確定你需要這樣做嗎?

退房源代碼sun.font.FontManager.registerFont,它可以得到你想要的安全性。 (這是做實際的工作,當你調用GraphicsEnvironment.registerFont方法)

public boolean registerFont(Font font) { 
    /* This method should not be called with "null". 
    * It is the caller's responsibility to ensure that. 
    */ 
    if (font == null) { 
     return false; 
    } 

    /* Initialise these objects only once we start to use this API */ 
    synchronized (regFamilyKey) { 
     if (createdByFamilyName == null) { 
      createdByFamilyName = new Hashtable<String,FontFamily>(); 
      createdByFullName = new Hashtable<String,Font2D>(); 
     } 
    } 

    if (! FontAccess.getFontAccess().isCreatedFont(font)) { 
     return false; 
    } 
    /* We want to ensure that this font cannot override existing 
    * installed fonts. Check these conditions : 
    * - family name is not that of an installed font 
    * - full name is not that of an installed font 
    * - family name is not the same as the full name of an installed font 
    * - full name is not the same as the family name of an installed font 
    * The last two of these may initially look odd but the reason is 
    * that (unfortunately) Font constructors do not distinuguish these. 
    * An extreme example of such a problem would be a font which has 
    * family name "Dialog.Plain" and full name of "Dialog". 
    * The one arguably overly stringent restriction here is that if an 
    * application wants to supply a new member of an existing family 
    * It will get rejected. But since the JRE can perform synthetic 
    * styling in many cases its not necessary. 
    * We don't apply the same logic to registered fonts. If apps want 
    * to do this lets assume they have a reason. It won't cause problems 
    * except for themselves. 
    */ 
    HashSet<String> names = getInstalledNames(); 
    Locale l = getSystemStartupLocale(); 
    String familyName = font.getFamily(l).toLowerCase(); 
    String fullName = font.getFontName(l).toLowerCase(); 
    if (names.contains(familyName) || names.contains(fullName)) { 
     return false; 
    } 

    /* Checks passed, now register the font */ 
    Hashtable<String,FontFamily> familyTable; 
    Hashtable<String,Font2D> fullNameTable; 
    if (!maybeMultiAppContext()) { 
     familyTable = createdByFamilyName; 
     fullNameTable = createdByFullName; 
     fontsAreRegistered = true; 
    } else { 
     AppContext appContext = AppContext.getAppContext(); 
     familyTable = 
      (Hashtable<String,FontFamily>)appContext.get(regFamilyKey); 
     fullNameTable = 
      (Hashtable<String,Font2D>)appContext.get(regFullNameKey); 
     if (familyTable == null) { 
      familyTable = new Hashtable<String,FontFamily>(); 
      fullNameTable = new Hashtable<String,Font2D>(); 
      appContext.put(regFamilyKey, familyTable); 
      appContext.put(regFullNameKey, fullNameTable); 
     } 
     fontsAreRegisteredPerAppContext = true; 
    } 
    /* Create the FontFamily and add font to the tables */ 
    Font2D font2D = FontUtilities.getFont2D(font); 
    int style = font2D.getStyle(); 
    FontFamily family = familyTable.get(familyName); 
    if (family == null) { 
     family = new FontFamily(font.getFamily(l)); 
     familyTable.put(familyName, family); 
    } 
    /* Remove name cache entries if not using app contexts. 
    * To accommodate a case where code may have registered first a plain 
    * family member and then used it and is now registering a bold family 
    * member, we need to remove all members of the family, so that the 
    * new style can get picked up rather than continuing to synthesise. 
    */ 
    if (fontsAreRegistered) { 
     removeFromCache(family.getFont(Font.PLAIN)); 
     removeFromCache(family.getFont(Font.BOLD)); 
     removeFromCache(family.getFont(Font.ITALIC)); 
     removeFromCache(family.getFont(Font.BOLD|Font.ITALIC)); 
     removeFromCache(fullNameTable.get(fullName)); 
    } 
    family.setFont(font2D, style); 
    fullNameTable.put(fullName, font2D); 
    return true; 
} 
+0

與Java7的FontManager API的變化,所以,是的,我寧願不碰這個使用反射。 你在哪裏找到源代碼?這是OpenJDK嗎?我的JVM是Oracle的。 – RobertG

+1

@RobertG點擊帖子頂部的鏈接。這是對grepcode – durron597

+0

+1忽視的可點擊的鏈接,謝謝大家了! – RobertG