JDK-6313541 : Fonts loaded with createFont cannot be converted into FontUIResource
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.1,5.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-08-19
  • Updated: 2017-05-16
  • Resolved: 2005-09-06
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.
Other JDK 6
5.0u7Fixed 6 b51Fixed
Related Reports
Duplicate :  
Duplicate :  
Description
A DESCRIPTION OF THE REQUEST :
The following is from the FontUIResource class:
A subclass of java.awt.Font that implements UIResource. UI classes which set default font properties should use this class.

This Font subclass which implements the UIResource marker interface allows implementers of the ComponentUI.installUI and ComponentUI.uninstallUI to determine if the font is a default for the Look and Feel or if it was installed by the application.  This prevents default fonts for one Look and Feel from being used when the Look and Feel is changed in the application.

FontUIResource (or any other subclass of Font that implements the UIResource) has to call an accessible constructor of the Font class.  Neither of the available constructors is able to convert a font loaded from a file with the creatFont() method to be used to construct a new Font.  The only way to get a new Font instance from a created font is with one of the deriveFont() methods.  This means that the resulting Font created as a result of the new FontUIResource will not display the loaded font, but will display the nearest registered font.

It looks like the font2DHandle instance variable needs to be copied from the original Font to the new Font.  The constructors for the

JUSTIFICATION :
This means that a Look and Feel cannot simply include a font file in a .jar file with the other classes of the custom Look and Feel.  The font needs to be registered with the system in order to be displayed as a component default.



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The FontUIResource(Font) method should return a FontUIResource that will display the original font if it was loaded with a creatFont() method call.

---------- BEGIN SOURCE ----------
/**
 * This example requires that a True Type font file that is not registered with
*  the operating system is available in the same directory as the FontTestPanel
*  class.  You can pick up the free Augie handwriting font from the following
* location: http://www.speakeasy.org/~ecf/augie.zip
 *
 */
public class FontTestPanel extends JPanel {

	private JLabel testLabel = null;
	private JButton fontButton = null;
	private JLabel badFontLabel = null;
	private JButton badButton = null;
	private Font labelFont;
	private FontUIResource badLabelFont;

	/**
	 * This is the default constructor
	 */
	public FontTestPanel() {
		super();
//
// replace fontFileName with the name of the font file being used.
//
		InputStream fontStream = FontTestPanel.class.getResourceAsStream("fontFileName.ttf");
		if (fontStream != null) {
			Font newFont;
			try {
				newFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
				labelFont = newFont.deriveFont((float)24);
				badLabelFont = new FontUIResource(labelFont);
			} catch (FontFormatException e1) {
				e1.printStackTrace();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		initialize();
	}

	/**
	 * This method initializes this
	 *
	 * @return void
	 */
	private void initialize() {
		badFontLabel = new JLabel();
		badFontLabel.setText("Only font size will change with a button press!");
		testLabel = new JLabel();
		testLabel.setText("The font and size will both change with a button press");
		this.setSize(300, 200);
		this.add(testLabel, null);
		this.add(getFontButton(), null);
		this.add(badFontLabel, null);
		this.add(getBadButton(), null);
	}

	/**
	 * This method initializes fontButton
	 *
	 * @return javax.swing.JButton
	 */
	private JButton getFontButton() {
		if (fontButton == null) {
			fontButton = new JButton();
			fontButton.setText("Change Font");
			fontButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					testLabel.setFont(labelFont);
					testLabel.revalidate();
				}
			});
		}
		return fontButton;
	}

	/**
	 * This method initializes badButton
	 *
	 * @return javax.swing.JButton
	 */
	private JButton getBadButton() {
		if (badButton == null) {
			badButton = new JButton();
			badButton.setText("Change Font");
			badButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					badFontLabel.setFont(badLabelFont);
					badFontLabel.revalidate();
				}
			});
		}
		return badButton;
	}

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

Comments
EVALUATION I have implemented the protected Font(Font) constructor and updated FontUIResource to use it.
25-08-2005

EVALUATION There are several potential ways to address this #1 - a native method called from the FontUIResource(Font) constructor which hooks up the Font as suggested by the submitter. This should be easy(ish) and requires no new API. This could even copy other attributes besides the basic family, style and integer point size. #2 - a new protected constructor in java.awt.Font : protected Font(Font) which is called by the FontUIResource constructor and does the same hooking up as above, and additionally may copy other attributes besides just the name etc as mentioned above. For what is essentially a copying constructor to ignore other attributes would be plain wrong. This also may be useful to some other subclassers of Font although I can't say I know of any other such cases. #3 - Implementing 6245665: Font's created with createFont to be available to new Font(..) FontUIResource would not need to be changed in this case as it would pick up the new Font automatically. This doesn't address copying additional attributes but it does address the unmentioned issue that code sometimes (as in the case of the existing FontUIResource constructors) incorrectly assume that supplying the family name of the font is sufficient. It could be that to address most uses we need to do both #2 and #3. Remaining unaddressed would be that FontUIResource doesn't override most of the APIs in Font, including the various Font.deriveFont() methods. Clients which want to use those, and obtain a FontUIResource would first need to call Font.deriveFont() and then pass the returned Font to the FontUIResource() constructor which take a Font(). Painful, but possible.
19-08-2005