I am trying to use OpenDyslexic as a font option in a Swing application. But it is surprising that OpenDyslexic looks much larger than any other font with the same dot size, although it usually looks in other applications. Ive tried several other OpenType fonts and they don't look particularly large or small. Why is OpenDyslexic so big in Java, and how can I get Java to change it normally, so I donβt need the special size of OpenDyslexic?
In the Oracle JRE (I tried 1.7.0_11, 1.7.0_15 and the last 1.7.0_21) on all OSs, the font is too large when Java loads the font file using Font.createFont . However, when I install the font in the operating system, the behavior on all three platforms is different:
- On Linux, setting the font to
~/.fonts not suitable. The screenshot looks the same before installing the font and after installing it. - On Windows, installing the font fixes the glyphs of the fonts, but the spacing between the fonts is still too long! See screenshot below.
- On OS X, installing a font fixes it! It looks like a regular font in OS X.
Update . Interestingly, OpenJDK (both the 7u21 Ubuntu package on Linux and the obuildfactory on OS X) shows no error. 15pt OpenDyslexic 'm has a width of 15px on OpenJDK, as it should be, both when creating a font from a file, or when processing a font by the operating system. The error is in the latest version of Oracle JRE, but not in the latest version of OpenJDK.
Here is my example program. Note: to try, you need to put OpenDyslexic files in / resources. Alternatively, install OpenDyslexic on your system and take out the registerFonts() call.




import java.awt.BorderLayout; import java.awt.Component; import java.awt.Font; import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.HashSet; import java.util.Locale; import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListCellRenderer; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; public class FontFrame { private static void registerFonts() { String[] resources = { "OpenDyslexic-Regular.otf", "OpenDyslexic-Italic.otf", "OpenDyslexic-Bold.otf", "OpenDyslexic-BoldItalic.otf" }; GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); for (String filename: resources) { InputStream stream = FontFrame.class.getResourceAsStream("resources/" + filename); try { Font font = Font.createFont(Font.TRUETYPE_FONT, stream); ge.registerFont(font); } catch (FontFormatException | IOException e) { throw new IllegalStateException(e); } } } private static void createUI(boolean allFonts) { final JTextArea textArea = new JTextArea( "Font created to help dyslexic readers. " + "Bottom heavy and unique character shapes help " + "prevent letters and numbers from being confused."); textArea.setWrapStyleWord(true); textArea.setLineWrap(true); final DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>(); if (allFonts) { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); HashSet<Object> seenFamilies = new HashSet<>(); Font[] fonts = ge.getAllFonts(); for (Font font: fonts) { String familyName = font.getFamily(Locale.ENGLISH); if (seenFamilies.contains(familyName)) continue; seenFamilies.add(familyName); model.addElement(familyName); } } else { model.addElement("SansSerif"); model.addElement("OpenDyslexic"); } final int fontSize = 15; textArea.setFont(new Font("SansSerif", Font.PLAIN, fontSize)); model.addListDataListener(new ListDataListener() { @Override public void intervalRemoved(ListDataEvent e) {} @Override public void intervalAdded(ListDataEvent e) {} @Override public void contentsChanged(ListDataEvent e) { if (e.getIndex0() == -1 && e.getIndex1() == -1) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { String selectedFamily = (String) model.getSelectedItem(); Font font = new Font(selectedFamily, Font.PLAIN, fontSize); textArea.setFont(font); }}); } } }); JComboBox<String> familyChooser = new JComboBox<>(model); familyChooser.setMaximumRowCount(50); familyChooser.setRenderer(new DefaultListCellRenderer() { private static final long serialVersionUID = 1L; public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); String familyName = (String) value; Font font = new Font(familyName, Font.PLAIN, fontSize); comp.setFont(font); return comp; } }); JPanel jpanel = new JPanel(); jpanel.setLayout(new BorderLayout()); jpanel.add(familyChooser, BorderLayout.NORTH); jpanel.add(textArea, BorderLayout.CENTER); JFrame jframe = new JFrame(); jframe.getContentPane().add(jpanel); jframe.setSize(300, 300); jframe.invalidate(); jframe.setVisible(true); jframe.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); } public static void main(String[] args) throws InvocationTargetException, InterruptedException { registerFonts(); final boolean allFonts = Arrays.asList(args).contains("--all"); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createUI(allFonts); } }); } }
java fonts swing jtextcomponent letter-spacing
yonran
source share