JDK-6591278 : Wrong rendering of transformed fonts on Windows with Java 6
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-08-09
  • Updated: 2011-03-08
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u10Fixed 7 b33Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
Java 1.6.0_01-b06

ADDITIONAL OS VERSION INFORMATION :
Windows XP sp2

A DESCRIPTION OF THE PROBLEM :
Wrong rendering of transformed fonts on Windows with Java 6.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the example, with real transformation matrix (which was obtained after some transformation in real program). Note, that it doesn't appear with Java 1.4.2, only with Java 6.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Normal string "3 500"
ACTUAL -
Expected string with skewed numbers.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

import java.awt.*;

import java.awt.event.*;
import java.awt.geom.AffineTransform;

class DrawStringTest extends Frame
{  
	DrawStringTest(String s)
	{
		super(s);
		setBounds(0, 0, 500, 300);
		setVisible(true);
	}

	public void paint(Graphics g)
	{
		Font f = new Font("Dialog", Font.PLAIN, 12);
		
		String s1 = "3 500";
        
        AffineTransform tr = new AffineTransform();
        double[] m = new double[6];
        tr.getMatrix(m);
        //m00 m10 m01 m11 m02 m12
        m[0] = 0.8749999999999999;
        m[1] = 0.0;
        m[2] = 0.0;
        m[3] = 0.875;
        m[4] = 5.675000000000001;
        m[5] = 107.11192516891774;
        /*m[0] = 0.875;
        m[1] = 0.0;
        m[2] = 0.0;
        m[3] = 0.875;
        m[4] = 7.0;
        m[5] = 107.11192516891774;*/
        tr = new AffineTransform(m);
        g.setFont(f);
        ((Graphics2D)g).transform(tr);
		g.drawString(s1, 0, 0);
}  

	public static void main(String[] args)
	{
		DrawStringTest f = new DrawStringTest("DrawStringTest");
		
		f.addWindowListener(new WindowAdapter(){
		
		public void windowClosing(WindowEvent ev){
			System.exit(0);}
		});
	}
} 

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
"Rounding" of transformation matrix, like:

double[] m = new double[6];
_graphics.getTransform().getMatrix(m);
for (int i = 0; i < 6; i ++)
m[i] = (double)Math.round(m[i]*1000000000)/1000000000;
_graphics.setTransform(new AffineTransform(m));

Release Regression From : 5
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
EVALUATION If scale factors are almost the same then process them as identical. This resolves the problem when identity is lost due to precision loss. Note that explicitly setting transformation matrix that is close to identity but exceeds this threshold will still lead to noticeable change in rasterization result.
28-05-2008

EVALUATION This problem is not reproducible with latest 6u10 and 7 builds. First, fix for 6656651 make it difficult to observe because t2k is not default rasterizer in many cases. Morover fix for 6223022 changed rounding logic (in uril.c) and this prevents discrepancy in this particular case. The root reason is still there, rasterizer uses fixed math and input transform may be not identity due to float point math. Converstion from float to fixed increases discrepancy and this may eventually lead to very noticeable changes in the glyph appearance (because hinting code was not supposed to work with all different transforms). However, importance of this issue for 6u10 seems to have decreased significantly.
20-05-2008

EVALUATION Transformation matrix is not pure scale transform. T2K is performing hinting with different x and y point sizes. (and difference is getting beiiger because t2k uses fixed math internally) I am not sure why exaclty difference is that noticeable. Looks like hinting was disabled for some reason. To avoid this we can update logic of preparation of transformation matrix for hinting engine to be more tolerant to small differences and rounding errors. In particular we can consider x/y sizes of point to be the same if they differ by 1 (i.e. in last bit of fixed math representation).
18-08-2007