2014-05-07 25 views
7

thời gian gần đây tôi phát hiện ra làm thế nào để đăng ký một phông chữ TTF với GraphicsEnvironment địa phương, st, đối với trường hợp sử dụng của tôi (SVG-to-PNG chuyển mã), Apache Batik có thể nhận ra font:Hủy đăng ký phông chữ bằng 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); 
} 

Tuy nhiên, tôi đã tự hỏi liệu tôi có thể hủy đăng ký bất kỳ phông chữ nào có sẵn để đảm bảo rằng chỉ các phông chữ tôi đăng ký mới được sử dụng trong chuyển mã hay không.

Không có GraphicsEnvironment # unregisterFont (...), làm cách nào tôi có thể đạt được điều này?

PS: Tôi không muốn phân lớp GraphicsEnvironment, vì tôi không thể giả định sự hiện diện của bất kỳ lớp con cụ thể nào, như sun.awt.Win32GraphicsEnvironment.

EDIT: Một số infos thêm:

  • Như sun.font.FontManager thay đổi với Java7 (từ lớp giao diện, và không có điều gì), tôi không muốn sử dụng bất kỳ cách giải quyết dựa vào nó.
  • JVM của tôi là JVM của Oracle.

Trả lời

4

Điều này không thể được thực hiện mà không phản ánh các biến tĩnh riêng tư và như vậy ... bạn có chắc chắn bạn cần thực hiện việc này không?

Kiểm tra mã nguồn để sun.font.FontManager.registerFont, nó có thể đã có sự an toàn mà bạn mong muốn. (Đây là phương pháp để làm công việc thực tế khi bạn gọi 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

Các FontManager thay đổi API với Java7, vì vậy, yeah, tôi không muốn chạm này phản ánh sử dụng. Bạn đã tìm thấy mã nguồn ở đâu? Đây có phải là OpenJDK không? JVM của tôi là Oracle. – RobertG

+1

@RobertG Nhấp vào liên kết ở đầu bài đăng. Trên grepcode – durron597

+0

+1 đã bỏ qua liên kết có thể nhấp, cảm ơn bạn vì điều đó! – RobertG

Các vấn đề liên quan