0

I'm making an installer of sorts and basically need to copy a font from the installed fonts on the computer to an outside directory. Here's an example of what I want:

Font f = new Font("Arial Black", Font.PLAIN, 20);
FontWriter.write(f, new File("C:\temp\ariblk.ttf"));

The font gets loaded into the Java program and is then written to disk as "ariblk.ttf" and can be used in another program. Note: I need to do this because this other program can not load from the system's installed fonts, period. Please don't try to suggest a workaround or ask why.

So, how can I achieve this? Any ideas?

Is there a built-in feature in Java or something I can download from somewhere? I hope I don't need to code it myself since I'd have to read up on how ttf files are structured.

TMan
  • 27
  • 2
  • Here you are writing a java object to file and it cannot be ttf file. – James Jithin Sep 24 '15 at 09:28
  • Package your font file and Refer: http://stackoverflow.com/questions/8364787/how-do-you-import-a-font – James Jithin Sep 24 '15 at 09:57
  • What? I need to get the font from inside Java (from the installed system fonts). If I had the font as a ttf file already there would be no problem. – TMan Sep 24 '15 at 10:41
  • Which operating system and which Java Version? – James Jithin Sep 24 '15 at 12:07
  • Windows 7 and Java 1.7. Just found a solution but it's not pretty. – TMan Sep 24 '15 at 12:25
  • What happens when someone does not have this Arial Black on his computer? You are probably better off if you find a good free substitute (i.e., not "free" as in "it came for free on my computer"!) and distribute it along with your program. – Jongware Sep 24 '15 at 12:39

1 Answers1

1

Figured out a way to do it myself. It's not pretty!

try {
    Font font = new Font("Arial Black", Font.PLAIN, 20);
    File physicalFont = null;
    Method method = font.getClass().getDeclaredMethod("getFont2D");
    method.setAccessible(true);
    String str = method.invoke(font).toString();
    if (str.contains(" fileName=")) {
        str = str.substring(str.indexOf(" fileName=")+10).replace("\r\n", "\n")+"\n";
        str = str.substring(0, str.indexOf("\n"));
        physicalFont = new File(str);
    }
    if (physicalFont==null || !physicalFont.isFile()) {
        System.out.println("not found");
    } else {
        System.out.println("font file: "+ physicalFont.getAbsolutePath());
    }
} catch (Throwable t) {
    t.printStackTrace();
}

Basically, reflection is used to hack the Font class so that information about the file can be accessed. The dumb thing about this is that this info could be reached easily in Java 1.6 but they made it inaccessible in Java 1.7 for some reason when they discontinued FontManager. Very annoying.

I just can't find another way to do it than this. I hope the hack doesn't break in the future! As long as the target Java platform is 1.7 maybe it will be fine?

Edit: "You can accept your own answer in 2 days." Really StackOverflow? You STILL do this? It's beyond stupid to have that wait period, time to realize it and let new users accept their own answers whenever. I don't even know if I will remember the login for this account in 2 days. Such a badly designed system... for shame.

TMan
  • 27
  • 2
  • If that font is not open-source, you are violating someone's copyright by redistributing it. They can sue you and win. Use an open-source font. In general, dynamically loaded fonts in Java are more trouble than they're worth - you have to pass around a reference to the loaded font object (new Font("Some font you created dynamically") will not get you the font you loaded. Where possible, have a list of preferred fonts that may or may not be available on various OS's, that have similar appearance and styling to the one you want, and use the best match you can find on the user's system. – Tim Boudreau Apr 17 '20 at 18:56