Search code examples
javagraphics2d

Graphics2D drawString produces nonsense characters after Java 6


While migrating an older application to a newer server with Java 8, this problem came up: words in an image that look fine with Java 6 became nonsense characters in Java 7 and 8.

Here is my test code:

package test;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.imageio.*;
import java.io.*;

public class PicTest {

    public static void main(String[] args){
        String testNum = args[0];
        String fileName = "image"+testNum+".jpg";
        String testText = "Test "+testNum;

        BufferedImage image = new BufferedImage(200,200, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        Font font = new Font("Serif", Font.PLAIN, 24);
        g2.setFont(font);
        g2.drawString(testText, 10, 20);
        File outputfile = new File(fileName);
        try {
            ImageIO.write(image, "jpg", outputfile);
        } catch (Exception e) {
            e.printStackTrace();
        }
   }
}

When I run this with Java 6...

$ /usr/local/java/java6/bin/javac test/PicTest.java
$ /usr/local/java/java6/bin/java test/PicTest 4

... here is the (expected, normal) output image: test image 4 using Java 6

And when I run this with Java 7...

$ /usr/local/java/java7_17/bin/javac test/PicTest.java
$ /usr/local/java/java7_17/bin/java test/PicTest 5

... here is the output image (with nonsense chars): test image 5 using Java 7

The image I get using Java 8 is the same as Java 7.

By Java 6 I mean jdk1.6.0_34 By Java 7 I mean jdk1.7.0_17

Should I be using different libraries or setting things up differently to make this work with more recent versions of Java?


Solution

  • In java 6 "Serif" is a logical font. Physical fonts were introduced at some point, and it seems you actually have a physical font by the name of "Serif" on your system. Use a different, physical, font family. Or "Sans-Serif" for the moment.

    In java one can iterate through all GrahicsEnvironment's fonts:

    GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
    for (String fontName : getAvailableFontFamilyNames()) {
        System.out.println(fontName);
    }