I was going through my bug list today and noticed this bug, Document how to embed fonts in FX apps. A quick google search turned up a single forum posting on the subject which just linked back to the root bug (lucky for me I put the solution in the bug report so people weren’t completely stuck). Surprisingly, I couldn’t find any documentation on the subject here at FXExperience.com, so I thought to rectify that with a short post explaining the subject.
I want to first say that the technique I’m about to describe is supported on all three platforms. This technique requires bundling the font files with your jars. So be sure that you have the rights to redistribute your chosen font files in this manner. We are looking at the CSS 3 specification for web fonts and hope to be able to support it fully when it goes final.
Within your application JAR file is a META-INF directory. It is not uncommon for frameworks to put special properties files or other files into this directory. At runtime, they read these files to bootstrap themselves. This is essentially what we are doing in JavaFX. To embed a TrueType font with a JavaFX application, you need to:
- Add the ttf file to some directory in your source tree
- Create a fonts.mf file
- Add lines to the fonts.mf file mapping a “logical name” to the path of the embedded ttf file
- Modify your build process to copy the fonts.mf file into the META-INF of your final JAR file
- In your JavaFX Script file, simply create a font by name referring to the “logical name” you entered in your fonts.mf file.
The fonts.mf file is nothing more than a properties file, mapping logical names to actual font files. The reason we took this approach as opposed to simply allowing you to load a font from an input stream, is that such dynamic font loading was not supported on the MIDP based JavaFX mobile implementation.
For this tip, I’ve chosen to use one of the fonts which are free for non-commercial use at 1001 Free Fonts. It is called Birth of a Hero. You can just download that file, and extract the ttf file into a directory of your choosing. I created a project called “Hero” which consists of a single package also called “hero” (note the lower case). I extracted the “BIRTH OF A HERO.ttf” file into that package.
I then created the following fonts.mf file and put it in my projects root directory (using NetBeans, I did this by using the “Files” tab).
Hero=/hero/BIRTH\ OF\ A\ HERO.ttf
I could have renamed the TTF file to be something without spaces, but decided for the sake of example to show also how to deal with spaces in file names in the fonts.mf file. Note the leading slash on the path. This is very important.
I next had to modify my build script to make sure fonts.mf gets placed in the application JAR file. In my NetBeans project, I did this by using the following:
<target name="-pre-compile" depends="init"> <mkdir dir="${build.dir}/compiled/META-INF"/> <copy todir="${build.dir}/compiled/META-INF" file="fonts.mf" /> </target>
Now that I have the ttf file and fonts.mf in my jar, I simply have to use the font from JavaFX:
Label { text: "Birth of a Hero" font: Font { name:"Hero" size: 128 } }
Now when I run this application, I get a warning message printed which says “Failed to get style for font ‘Hero'”. You can safely ignore this, but it is annoying and actually it is telling us something useful. If you inspect the style
of the Font, you would find that there is not one. If you would like a style, you need to build it into the name. For example, lets change the name of our font from “Hero” to “Hero Regular”. We will then find that the style of the font is “Regular” and the warning message goes away.
Hero\ Regular=/hero/BIRTH\ OF\ A\ HERO.ttf
import javafx.scene.text.Font; import javafx.scene.control.Label; Label { text: "Birth of a Hero" font: Font { name: "Hero Regular" size: 128 } }
And here is our finished product:
While trying to do this in our FX applicaction, I noticed that this works only with only true type fonts (*.ttf). If I use a open type font (*.otf), it throws a FontFormatException: Unsupported sfnt.
Will be good for your readers if they knew this before trying with otf.
Hope it helps!
-Dhruva
I’m trying to include a custom font in my application. When I test-run the code from within netbeans everything looks great. However, if I deploy it (or even run it from webstart from within netbeans) the fonts are not loaded and are replaced with a generic font.
I made a test class that prints all the fonts returned by Font.getFamilies(). It shows the custom fonts when I run it normally, but not when I run it through webstart.
Can anyone tell me why webstart can’t see the fonts?
Is there any way we can get NetBeans screenshots? I tried following your instructions, but it’s not working for some reason.
Thanks,
Jon
This doesn’t work with newer JRE’s, It works fine with me with my jdk 1.6.14 but using 1.6.21 any custom fonts I use are ignored. Does anyone know of some work arounds?
I created an issue to track the bug with custom fonts not working in applets or net-start: RT-9667. The issue has a zipped up netbeans project all setup as described in this article. I hope it helps someone resolve the issue.
Another way to accomplish this (with JavaFX 2.1 and Jdk 7.0.09) is to put the ttf in the same location as your fxml application class, and use IO’s InputStream…
Button newButton = new Button(“OpenSans Bold”);
InputStream is = this.getClass().getResourceAsStream(“OpenSans-Bold.ttf”);
newButton.setFont(Font.loadFont(is, 12));
how i add hindi font in javafx text filde
Hello, I’m working with Netbeans 6.9.1 and JavaFX 1.3.
Can someone help me with my schoolproject?
I’m trying to get a ‘var number’ into a stage -> label text.
var number:String; doesn’t work
Thanks,
Jack