JDK-6515337 : Font.deriveFont(int style) loses transform and other attributes
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-01-19
  • 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
6u2Fixed 7 b08Fixed
Description
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
If you derive a font from a font with a transform, the transform is lost.  This is a regression from 1.5.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Create a font with a transform.
2) Derive a new font from it
3) Displaying text with this font will not have the transform applied.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The transform should have still existed for the derived font.
ACTUAL -
The transform is not preserved.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Font;
import java.awt.font.TextAttribute;
import java.awt.font.TransformAttribute;
import java.awt.geom.AffineTransform;

public class FontTest {
    
    public static void main(String[] args) {
        System.out.println("Java Version:\t" + System.getProperty("java.vm.version"));
        runTest();
    }
    
    private static void runTest() {
        Font originalFont = new Font("Arial", Font.PLAIN, 18);
        AffineTransform transform = originalFont.getTransform();
        System.out.println("Original font transform: " + transform);
        AffineTransform scaleTransform = new AffineTransform();
        scaleTransform.scale(2, 2);
        Font scaledFont = originalFont.deriveFont(scaleTransform);
        transform = scaledFont.getTransform();
        System.out.println("Scaled font transform: " + transform);
        Font boldScaledFont = scaledFont.deriveFont(Font.BOLD);
        transform = boldScaledFont.getTransform();
        System.out.println("Bold scaled font (separate derives) transform: " + transform);
        Font boldScaledFont2 = originalFont.deriveFont(Font.BOLD, transform);
        transform = boldScaledFont2.getTransform();
        System.out.println("Bold scaled font (combination derive) transform: " + transform);
    }

}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
I have not yet found a workaround that will work on both 1.5 and 1.6.

Comments
EVALUATION This appears to have been introduced in b33 (April 2005) The change was a large one under several bug ids including : 4296952 Cannot underline Font using Map 4339577 Adding kerning to the text layout process The change meant that a legacy internal variable "fRequestedAttributes" in java.awt.Font was relegated to being used only for serialisation. In its place a new Map variable 'values' is used and the various deriveFont methods were updated to test for values != null to see if there were attributes such as a transform to consider. However one method : deriveFont(int style) still tested the old legacy "fRequestedAttributes" which is now always null. The result is that all attributes, except for the base ones (family, style, size .. ) are lost. The fix is just to change the variable that is tested to the new one as in the other deriveFont methods. Code inspection shows that this is the only remaining case.
19-01-2007

WORK AROUND replace : Font boldScaledFont = scaledFont.deriveFont(Font.BOLD); with Font boldScaledFont = scaledFont.deriveFont(Font.BOLD, scaledFont.getSize2D()); the font will re-use its original size so that's a no-op and this by-passes the buggy method.
19-01-2007