2013-09-05

Creating font metrics for Apache FOP

Whilst searching for a proper solution to create font metrics for a bunch of TrueType fonts to be used with Apache FOP I came up with the following BASH Shell-Script snippet:

for ttf_file in *.ttf; do
    fop-ttfreader "${ttf_file}" \
                  "${ttf_file%%.ttf}-metrics.xml";
done

It will create metric files for all TrueType fonts (*.ttf) located in the current directory.

Just make sure to install Apache FOP first. On my Ubuntu GNU/Linux box I had to install a package called "fop":

# sudo apt-get install fop

2013-01-15

Using custom fonts in your JavaFX application

If you want to use custom fonts in your JavaFX application you basically have two options. You can perform the loading of the fonts yourself and assign them to your components programmatically:

final Font myFancyFont =
    Font.loadFont(getClass().getResourceAsStream("/My Fancy Font.ttf"), 12.0);

Label label = LabelBuilder.create().setText("w00t w00t!").build();

// First way to set the font:
// Just pass the reference to the object that we created
// a few lines above.
label.setFont(myFancyFont);

// Second way:
// Use a FontBuilder to fetch the font. The name of the font must match
// the name that is embedded into the font's information / metadata!
label.setFont(FontBuilder.create().name("My Fancy Font").build());

There is an easier way to achieve your goal, though: Add a file called "fonts.mf" (basically some kind of "Java Properties" file) into your application's META-INF folder with the following contents:

My\ Fancy\ Font\ Alias = /My\ Fancy\ Font.ttf

(Make sure to escape all whitespaces!)

That way, JavaFX will make sure that your font will be loaded automatically upon application initialization, so you don't have to worry about custom loading routines, font-reference-handling and so on and so on. You can now reference your font using it's alias ("My fancy Font Alias") or the name that was provided in the meta information of the true type font.

UPDATE (June 2013)
Looks like the font loading mechanism via META-INF/fonts.mf is broken or has been abandoned in JavaFX 8. To work around these issues I suggest you still use META-INF/fonts.mf for your apps, but add the following snippet of code into your application's init method, to work around these issues:
 try {
    final Enumeration fontDefinitions = getClass().getClassLoader().getResources("META-INF/fonts.mf");
    while (fontDefinitions.hasMoreElements()) {
        final Properties props = new Properties();
        props.load(fontDefinitions.nextElement().openStream());
        for (final Object v: props.values()) {
            final String fontName = (String) v;
            Font.loadFont(getClass().getResourceAsStream(fontName), 10.0);
        }
    }
} catch (final IOException e) {
    throw new IllegalStateException("Unable to load custom fonts from META-INF/fonts.mf file(s).", e);
}


2013-01-10

Java programming: Utilize UnsupportedOperationException

One of the big differences between Eclipse and Netbeans is the way they both populate their default pre-configured code templates.
Software developers working with Netbeans will probably appreciate the fact that all your implementation methods will automatically look like that:

@Override
public Object methodWithObjectReturnValue() {
    throw new UnsupportedOperationException();
}

@Override
public Object methodWithIntReturnValue() {
    throw new UnsupportedOperationException();
}

Eclipse on the other hand will create a methods that will like like that:

@Override
public Object methodWithObjectReturnValue() {
    // TODO Auto-generated method stub
    return null;
}

@Override
public int methodWithIntReturnValue() {
    // TODO Auto-generated method stub
    return 0;
}


I'll leave it as an exercise for the reader to figure out, why I think that throwing an UnsupportedOperationException is by far the better choice... :-)
So... if you're on Eclipse make sure to adjust your Java Code Templates and throw these pretty UnsupportedOperationExceptions in all the right places before you start to actually implement your stuff!

... oh... and one more piece of advice: don't you confuse Java's UnsupportedOperationException with OperationNotSupportedException. +Dustin Marx wrote a nice article about that topic some years ago that you might want to check out!

2013-01-07

JavaFX and Maven


Making Maven play along nicely with the JavaFX (2.x) runtime is not really something that can be achieved quite easily.

Unfortunately, the file "jfxrt.jar" which represents the JavaFX runtime can be found in most recent's JRE's "lib" folder but is not appended to the classpath of the Java Compiler when being invoked without any additional parameters.
On the other hand, the native components (shared libs) that are necessary to execute JavaFX applications are placed in the lib/${arch} folder of your JRE and can be loaded without any further problems.

To build your JavaFX project using Maven you basically have two options:
Install the JavaFX runtime into your local maven repository (.m2). A rather good description can be found on the dzone webpage: http://java.dzone.com/articles/install-javafx-runtime-local
Declare a "system scope" dependency in you pom.xml
At first, option 1 seems to be the better solution, because we all know that system scope dependencies are evil. I thought about that for a while and finally realized, that since jfxrt.jar is already a part of the Java runtime, even though it is not (yet) added to the classpath, I prefer option 2.

I strongly believe that one day jfxrt.jar will be added to the compiler's classpath I think it might be the best solution to add a profile to your pom.xml that enables the evil system scope dependency only if needed.

A typical pom.xml of mine looks like that:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelversion>4.0.0</modelversion>
  <groupId>com.cathive.fx</groupId>
  <artifactId>javafx-example-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0.0-SNAPSHOT</version>
  <properties>
    <javafx.runtime.jar>${java.home}/lib/jfxrt.jar</javafx>
  </properties>
  <profiles>
    <profile>
      <id>javafx</id>
      <dependencies>
        <dependency>
          <groupId>com.oracle</groupId>
          <artifactId>javafx-runtime</artifactId>
          <version>RELEASE</version>
          <scope>system</scope>
          <systemPath>${javafx.runtime.jar}</systemPath>
        </dependency>
      </dependencies>
    </profile>
  </profiles>
</project>

To build your project it is usually enough to enable the profile "javafx":
mvn -Pjavafx ...


If your JavaFX runtime is NOT yet present in you JRE's "lib"-folder, you'll have to specify an additional variable ("javafx-runtime-jar"):

mvn -Pjavafx -Djavafx.runtime.jar="C:\Program Files\LocationToJavaFXRuntime\jfxrt.jar" ...