2014-05-07 11 views
7

Niedawno okazało się, jak zarejestrować czcionkę TTF z lokalną GraphicsEnvironment, st, dla mojego przypadku użycia (SVG do PNG transkodowania), Apache Batik może rozpoznać czcionki:Wyrejestruj czcionkę za pomocą 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); 
} 

Jednak byłem Zastanawiam się, czy mogę wyrejestrować istniejące wcześniej czcionki, aby zagwarantować, że w transkodowaniu będą używane tylko czcionki, które rejestruję.

Brak elementu GraphicsEnvironment # unregisterFont (...), w jaki sposób mogę to osiągnąć?

PS: Nie chcę podklasy GraphicsEnvironment, ponieważ nie mogę założyć, że istnieje jakakolwiek specyficzna podklasa, np. Sun.awt.Win32GraphicsEnvironment.

EDIT: Niektóre dalsze informacje:

  • Jak zmienia sun.font.FontManager z Java7 (od klasy interfejs i etażerka), wolałbym nie używać żadnego obejścia powołując się na niego.
  • Moje JVM to Oracle JVM.

Odpowiedz

4

Nie można tego zrobić bez odzwierciedlenia prywatnych zmiennych statycznych i takich ... czy na pewno trzeba to zrobić?

Sprawdź kod źródłowy na sun.font.FontManager.registerFont, może on już mieć pożądane bezpieczeństwo. (Jest to metoda, która ma faktyczną pracę podczas rozmowy 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

W FontManager zmiany API z Java7, tak, tak, ja raczej nie dotykać tego przy użyciu odbicia. Gdzie znalazłeś kod źródłowy? Czy to OpenJDK? Moja JVM to wersja Oracle. – RobertG

+1

@RobertG Kliknij link u góry wpisu. To na grepcode – durron597

+0

+1 przeoczyłem klikalny link, dziękuję za to! – RobertG

Powiązane problemy