GetSnappy.com Technology Blog
Tips & Techniques We've Learned From Practice
FreeBSD OpenJDK6-b17 font issues
Nov 3rd
Quite simply. Fonts look terrible when using openjdk6 on FreeBSD. I’ve been spending quite a bit of time researching and fixing this issue.
This is a simple test program I put together for comparing fonts.
import java.awt.*;
import javax.swing.*;
public class BasicDraw {
public static void main(String[] args) {
new BasicDraw();
}
BasicDraw() {
// Create a frame
JFrame frame = new JFrame();
// Add a component with a custom paint method
frame.getContentPane().add(new MyComponent());
// Display the frame
int frameWidth = 300;
int frameHeight = 300;
frame.setSize(frameWidth, frameHeight);
frame.setVisible(true);
}
class MyComponent extends JComponent {
// This method is called whenever the contents needs to be painted
public void paint(Graphics g) {
// Retrieve the graphics context; this object is used to paint shapes
Graphics2D g2d = (Graphics2D)g;
// Draw an oval that fills the window
int x = 0;
int y = 0;
int width = getSize().width-1;
int height = getSize().height-1;
g2d.drawOval(x, y, width, height);
// Set the desired font if different from default font
String family = "Serif";
int style = Font.PLAIN;
int size = 12;
Font font = new Font(family, style, size);
g.setFont(font);
// Draw a string such that its base line is at x, y
x = 10;
y = 10;
g.drawString("aString", x, y);
// Draw a string such that the top-left corner is at x, y
x = 10;
y = 30;
FontMetrics fontMetrics = g.getFontMetrics();
g.drawString("bString", x, y+fontMetrics.getAscent());
}
}
}
When comparing the results of Openjdk6-b17 vs diablo-jdk-1.6.0.07.02_6, you’ll see a noticeable difference in the fonts being used. Openjdk6 looks terrible.
Here is another executable class that lists all available fonts on a machine:
import java.awt.GraphicsEnvironment;
public class AvailableFonts
{
/**
* @param args
*/
public static void main(String[] args) {
GraphicsEnvironment gEnv = GraphicsEnvironment
.getLocalGraphicsEnvironment();
String envfonts[] = gEnv.getAvailableFontFamilyNames();
for (String font: envfonts) {
System.err.println(font);
}
}
}
When comparing the output between openjdk and diablo-jdk, the only difference were these three lines in the diablo-jdk output:
Lucida Bright Lucida Sans Lucida Sans Typewriter
These fonts turned out to be .ttf font files located at /usr/local/diablo-jdk16/jre/lib/fonts/.
I performed the following command to link them inside openjdk6
ln -s /usr/local/diablo-jdk16/jre/lib/fonts/ /usr/local/openjdk6/jre/lib/fonts/
Now the AvailableFonts class returns identical results, however BasicDraw, doesn’t appear to render the text all together. Trying to run netbeans or eclipse, or any GUI/swing app for that matter causes even more unusual results. It looks as if the fonts are being drawn with a width of 0, and height 10 times their normal size.
I imported a couple of patches for bugs 6761856 and 6817112 from the jdk7 branch, to try and resolve this unusual behavior with no luck. I then started playing with fontconfig.properties, in hopes of resolving the font issues there. It looked like it wanted to use DejaVU LGC fonts as the primary for latin-1. I used the port x11-fonts/dejavu which contains the non LGC fonts since there DejaVU LGC fonts don’t appear to have a port yet. After installing the fonts and updating fontconfig.properties I re-ran my BasicDraw test class… and SUCCESS! Font’s looked equivalent to those in diablo-jdk and the best part is I don’t have to worry about licensing issues with Sun’s Lucida fonts.
I’ve added the following to the ports/java/openjdk6 Makefile:
RUN_DEPENDS+= dejavu:${PORTSDIR}/x11-fonts/dejavu
I’d like to offer a better out-of-the-box installation to our japanese,chinese, and korean audience, but I’m not sure what the best way to do this is. So far this is what I’ve come up with as the ideal fonts for each locality:
korean = korean/unfonts-ttf chinese = chinese/mingunittf japanese = japanese/font-sazanami
I’ve updated the fontconfig.properties to reflect these fonts and their installed locations, however I’m not sure I’ve chosen the right fonts. Furthermore I’d like out-of-box font dependencies to be resolved based on the LOCALE of the machine. I haven’t found any examples of doing this, and I can only assume their is a reason for it. Perhaps the right thing to do is require all fonts for all languages regardless of the LOCALE?
My work so far has been included in pre release 2 and, you can grab the latest preliminary port from this blog:
http://www.getsnappy.com/tech-blog/freebsd-tips-tricks/upgrading-freebsd-port-java-openjdk6-from-b16-to-b17/
Any feedback good or bad, is appreciated.
Upgrading FreeBSD port java/openjdk6 from b16 to b17
Oct 30th
As the maintainer of the java/openjdk6 port for FreeBSD I recently took on the challenge of upgrading the java/openjdk6 port from b16 to the newly released b17. I’ve decided to blog about, partly to document my efforts to review when b18 comes out, but also to share the process with all that are interested.
I started by downloading the new zip from http://download.java.net/openjdk/jdk6/, and updating the distinfo and Makefile for the port to use the b17 bundle.
Next I went to extract and apply patches. I got a weird message during the extraction process that the hotspot/linux/Makefile didn’t exist. This seemed unusual at first, but it turns out there is a post-extract section in the ports Makefile that was copying and running sed expressions, to create bsd files from linux versions. A couple of directories and files needed to be removed, then I moved on to the patching process.
I optimistically tried to patch but patch died complaining about a hunk ordering mismatch. I tried to work with the single patch-set file for several minutes before deciding to take a different approach and split the patch. I separated the single patch file so that every file that required a patch had its own patch file. This allowed me to deal with patches on a file by file basis. I found splitpatch.rb at http://www.clearchain.com/~benjsc/download/splitpatch/splitpatch.rb, and slightly modified the output filename, and quickly got the job done.
Next I seperated patches that applied cleanly from patches that had errors using the following command and parsing the results by hand.
find /usr/ports/java/openjdk6/files/brian1/ -name \*patch\* -print -exec bash -c "patch -lsC < {};" ';' 2&1; | less
Of 288 total files patched, 221 patches merged successfully and 67 patches failed. I started addressing the failed patches by categorizing them. There where 34 makefiles, 13 build files, 12 src files, 6 agent files, and 2 uncategorized files.
My plan was to apply all the clean patches, then hand merge the rest, build, then recreate the patch-set at the very end. I started by making a non-patched work directory using the command make extract. Then I created two copies of this directory called orig and work-progress. I would perform all work inside of work-progress and copy any modified files into the work directory to test my changes. I planned to use orig for creating the patch-set from my modified work-progress copy.
If I made numerous changes, or wanted to verify the entire patch I would start with a fresh copy of my work-progress directory.
# equivalent of a make clean rm -rf work && cp -Rp work-progress work
There was one file that proved to be a pain to patch. hotspot/src/os/bsd/vm/os_bsd.cpp, would not patch with the following error message.
patch: **** misordered hunks! output would be garbled
I started hand merging the patch, and after 15 minutes, I thought to myself there had to be a better way. I decided to split the patch into individual hunks using the splitpatch.rb script, and apply each hunk individually. It worked like a charm, and only one of the hunks had to be hand merged. I did have to instruct patch as to which file these hunks applied to be passing hotspot/src/os/bsd/vm/os_bsd.cpp as an extra argument.
However compiling this file resulted in an error. Some hunks were applied in obviously incorrect locations. Turns out the default fuzz factor of two, was the culprit. I reapplied the patch with a fuzz factor of 0, and this time three hunks failed and needed to be applied by hand. I bet if I tried a fuzz factor of 0, with the original non-split-by-hunk patch that it would have succeeded with the three rejects.
There were lots of small errors that occurred during the building process. All of them were very minor and required small simple changes. Where error lead my to applying patches for PR #138348 and PR #139452. One thing I found very handy for speeding up the porting process was setting the BUILD_
#default BUILD_BUILD_CORBA=true \ BUILD_JAXP=true \ BUILD_JAXWS=true \ BUILD_HOTSPOT=true \ BUILD_MOTIF=true \ BUILD_JDK=true
#only build the hotspot BUILD_CORBA=false \ BUILD_JAXP=false \ BUILD_JAXWS=false \ BUILD_HOTSPOT=true \ BUILD_MOTIF=false \ BUILD_JDK=false
I finally got a clean building work-progress directory after making a lot of little tiny fixes and reapplying some patches.
Below is the script I used to create the patchset from my modified source:
#!/bin/sh
rm -rf /usr/ports/java/openjdk6/work-pristine;
cp -rp /usr/ports/java/openjdk6/work-progress /usr/ports/java/openjdk6/work-pristine;
cd /usr/ports/java/openjdk6/work-pristine;
find ./ -name \*.rej -exec rm '{}' ';'
find ./ -name \*.orig -exec rm '{}' ';'
find ./ -name \*sC -exec rm '{}' ';'
diff -uNr ../orig/ ./ > ../files/make1/patch-set
You can gain early access to this port by downloading it from:
http://www.getsnappy.com/downloads/openjdk6-b17-pr2.tar.gz
To install:
cd /usr/ports/java tar -xjf <path_to_tar_bundle>/openjdk6-b17-pr2.tar.gz cd openjdk6-b17 make
Pre Release 2 features these fixes:
- no more ugly fonts!
- locale data is now correct
- supports building on 9.0 current
- include fastdebug build options creates a mirrored /usr/local/openjdk6-fastdebug installation
openjdk6 b17 is right around the corner
Sep 29th
The openjdk6 team has put in a ton of effort to merge in changes from jdk6 hs14 into the openjdk6 branch. They have also included some security related patches that were fixed in jdk6 hs15. The openjdk6 branch should now contain all security related patches as of jdk6 hs20. All of this will soon be bundled in the openjdk6 b17 snapshot very soon.
As the maintainer of the openjdk6 port on FreeBSD I will be releasing openjdk6 b17 out to the FreeBSD community as soon as it’s available.
Cheers!
Brian
Recent Comments