3

ttf: ttf

otf: otf

both are the same font but different fontfile types

I am running Java 7 in Windows 7

According to Miguel Sousa by Adobe the bug is not in the fonts https://github.com/adobe/source-sans-pro/issues/32#issuecomment-23319673

I am just setting the default font to the new font. The TTF version works without any issues

Font font_o = Font.createFont(Font.TRUETYPE_FONT, fonts.class.getResourceAsStream("fonts/TTF/SourceSansPro-Regular.ttf"));
//Font font_o = Font.createFont(Font.TRUETYPE_FONT, fonts.class.getResourceAsStream("fonts/OTF/SourceSansPro-Regular.otf"));
Font font_n=font_o.deriveFont(Font.PLAIN, UIManager.getLookAndFeelDefaults().getFont("defaultFont").getSize());
UIManager.getLookAndFeelDefaults().put("defaultFont",font_n);

Why is there a difference in the lineheight?

  • no, you misunderstood something. be sure that not, I'm delete my answer here to avoiding any further discusion about – mKorbel Aug 27 '13 at 11:25
  • and what did I misunderstand exactly? I tried the ttf version here: looks great, then tried the otf version (commenting out the ttf version) lokks not the same, see the 2 images above and see the space above the "O" –  Aug 27 '13 at 11:28
  • I see that, but I'm trying to avoid any debugging of methods on my side, nothing else :-) – mKorbel Aug 27 '13 at 11:33
  • In FontForge both versions (otf, ttf) are really the same and look the same, seems to be a Java Swing (Nimbus L&F) bug –  Aug 27 '13 at 11:40
  • if it is also reproduced by other Java users it will be a bug, so let's see what the community says and maybe we have to file a bug report for this. I will keep this stackoverflow question updated so other users will know in the future https://forums.oracle.com/thread/2573652 –  Aug 27 '13 at 11:59
  • I'm debugged that, everything is accesible from TextAttribute, this is bug, (too lazy create an screenshots before) – mKorbel Aug 27 '13 at 12:58
  • I don't think Java uses the same font renderer for TTF as OTF fonts. I can't find any "hard" evidence for this, but check out e.g. the second answer to [this question](http://stackoverflow.com/questions/872569/how-to-use-open-type-fonts-in-java). Googling does appear to support the idea that not all features in OTF fonts are supported by Java. In other words, OTF font rendering simply may not be as good. – bobby_light Aug 27 '13 at 13:23
  • @bobby_light read [The values for WEIGHT, WIDTH, and POSTURE are interpolated by the system, which can select the 'nearest available' font or use other techniques to approximate the user's request.](http://docs.oracle.com/javase/7/docs/api/java/awt/font/TextAttribute.html), but this isn't somehow, an important issue here – mKorbel Aug 27 '13 at 13:27
  • @bobby_light http://mindprod.com/jgloss/opentype.html for Linux and other operating systems you have to use otf, it is currently the best option to support most platforms –  Aug 27 '13 at 13:31

1 Answers1

3

conclusion (forums.oracle.com/thread/2573652 similair as many his post there, nothing special)


  • not true that Java, nor Nimbus bug, this bug in Font, you can to see that in Metal, Win, WinClassic and Nimbus Laf, OTF_Font missing 2pixels above glyph

enter image description here . Windows . enter image description here

enter image description here . Metal . enter image description here

enter image description here . Nimbus . enter image description here

enter image description here . Classic . enter image description here


WinXp on Java6

enter image description here . versus . enter image description here


  • this code will help you to find difference(ies) between two fonts (and to report all diff's to author)

  • returns all available atributes from (java.awt.font.)TextAttribute for concrete Font

  • you can to get detailed properties from (almost) all TextAttributes

enter image description here

with output

java.awt.font.TextAttribute(family)
java.awt.font.TextAttribute(weight)
java.awt.font.TextAttribute(width)
java.awt.font.TextAttribute(posture)
java.awt.font.TextAttribute(size)
java.awt.font.TextAttribute(transform)
java.awt.font.TextAttribute(superscript)
java.awt.font.TextAttribute(char_replacement)
java.awt.font.TextAttribute(foreground)
java.awt.font.TextAttribute(background)
java.awt.font.TextAttribute(underline)
java.awt.font.TextAttribute(strikethrough)
java.awt.font.TextAttribute(run_direction)
java.awt.font.TextAttribute(bidi_embedding)
java.awt.font.TextAttribute(justification)
java.awt.font.TextAttribute(input method highlight)
java.awt.font.TextAttribute(input method underline)
java.awt.font.TextAttribute(swap_colors)
java.awt.font.TextAttribute(numeric_shaping)
java.awt.font.TextAttribute(kerning)
java.awt.font.TextAttribute(ligatures)
java.awt.font.TextAttribute(tracking)

from code Nimbus L&F

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class SystemFontDisplayer {

    private static final long serialVersionUID = 1L;
    private JFrame frame = new JFrame("Nimbus UIDeafaults and Font");
    private JComboBox fontsBox;
    private javax.swing.Timer timer = null;
    private JButton testButton = new JButton("testButton");
    private JTextField testTextField = new JTextField("testTextField", JLabel.CENTER);
    private JLabel testLabel = new JLabel("testLabel");
    private Font font1, font2;
    private JMenuBar menuBar1 = new JMenuBar();
    private JMenu menu1= new JMenu("Menu 1");
    private JMenu menu2= new JMenu("Menu 2");
    private JMenuItem menuItem1= new JMenuItem("MenuItem 1");
    private JMenuItem menuItem2= new JMenuItem("MenuItem 2");

    public SystemFontDisplayer() {
        try {
            font1 = Font.createFont(Font.TRUETYPE_FONT, SystemFontDisplayer.class.getResourceAsStream("/Images/SourceSansPro-Regular.ttf"));
            font2 = Font.createFont(Font.TRUETYPE_FONT, SystemFontDisplayer.class.getResourceAsStream("/Images/SourceSansPro-Regular.otf"));
        } catch (FontFormatException ex) {
            Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
        }
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        //ge.registerFont(font1);
        ge.registerFont(font2);
        String[] fontFamilyNames = ge.getAvailableFontFamilyNames(Locale.getDefault());
        fontsBox = new JComboBox(fontFamilyNames);
        fontsBox.setSelectedItem(0);
        fontsBox.setRenderer(new ComboRenderer());
        fontsBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    final String fontName = fontsBox.getSelectedItem().toString();
                    fontsBox.setFont(new Font(fontName, Font.PLAIN, 16));
                    start();
                }
            }
        });
        fontsBox.setSelectedItem(0);
        fontsBox.getEditor().selectAll();

        menu1.add(menuItem1);
        menuBar1.add(menu1);
        menu2.add(menuItem2);
        menuBar1.add(menu2);
        frame.setJMenuBar(menuBar1);
        frame.setLayout(new GridLayout(4, 0, 5, 5));
        frame.add(fontsBox);
        frame.add(testButton);
        frame.add(testTextField);
        frame.add(testLabel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(200, 105);
        frame.pack();
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                fontsBox.setPopupVisible(true);
                fontsBox.setPopupVisible(false);
            }
        });
        frame.setVisible(true);
    }

    private void start() {
        timer = new javax.swing.Timer(250, updateCol());
        timer.setRepeats(false);
        timer.start();
    }

    public Action updateCol() {
        return new AbstractAction("text load action") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                final Font fnt = new Font(fontsBox.getSelectedItem().toString(), Font.PLAIN, 16);
                try {
                    LookAndFeel lnf = UIManager.getLookAndFeel().getClass().newInstance();
                    final FontUIResource res = new FontUIResource(fnt);
                    UIDefaults uiDefaults = lnf.getDefaults();
                    uiDefaults.put("defaultFont", res);
                    UIManager.getLookAndFeel().uninitialize();
                    UIManager.setLookAndFeel(lnf);
                } catch (InstantiationException ex) {
                    Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
                } catch (UnsupportedLookAndFeelException ex) {
                    Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
                }
                UIDefaults defaults = UIManager.getDefaults();
                final FontUIResource res = new FontUIResource(fnt);
                Object[] obj = res.getAvailableAttributes();
                for (Object objs : obj) {
                    System.out.println(objs); //returns java.awt.font.TextAttribute
                }
                defaults.put("defaultFont", res);
                SwingUtilities.updateComponentTreeUI(frame);
                frame.pack();
            }
        };
    }

    public static void main(String arg[]) {
        try {
            for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(laf.getName())) {
                    UIManager.setLookAndFeel(laf.getClassName());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                SystemFontDisplayer systemFontDisplayer = new SystemFontDisplayer();
            }
        });
    }

    private class ComboRenderer extends BasicComboBoxRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            final Object fntObj = value;
            final String fontFamilyName = (String) fntObj;
            setFont(new Font(fontFamilyName, Font.PLAIN, 16));
            return this;
        }
    }
}

from code Oldies L&Fs

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class SystemFontDisplayer extends JFrame {

    private static final long serialVersionUID = 1L;
    private JFrame frame = new JFrame("Nimbus UIDeafaults and Font");
    private JComboBox fontsBox;
    private javax.swing.Timer timer = null;
    private JButton testButton = new JButton("testButton");
    private JTextField testTextField = new JTextField("testTextField");
    private JLabel testLabel = new JLabel("testLabel");
    private Font font1, font2;
    private JMenuBar menuBar1 = new JMenuBar();
    private JMenu menu1 = new JMenu("Menu 1");
    private JMenu menu2 = new JMenu("Menu 2");
    private JMenuItem menuItem1 = new JMenuItem("MenuItem 1");
    private JMenuItem menuItem2 = new JMenuItem("MenuItem 2");

    public SystemFontDisplayer() {
        try {
            font1 = Font.createFont(Font.TRUETYPE_FONT, SystemFontDisplayer.class.getResourceAsStream("/Images/SourceSansPro-Regular.ttf"));
            font2 = Font.createFont(Font.TRUETYPE_FONT, SystemFontDisplayer.class.getResourceAsStream("/Images/SourceSansPro-Regular.otf"));
        } catch (FontFormatException ex) {
            Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
        }
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        //ge.registerFont(font1);
        ge.registerFont(font2);
        String[] fontFamilyNames = ge.getAvailableFontFamilyNames(Locale.getDefault());
        fontsBox = new JComboBox(fontFamilyNames);
        fontsBox.setSelectedItem(0);
        fontsBox.setRenderer(new ComboRenderer());
        fontsBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    final String fontName = fontsBox.getSelectedItem().toString();
                    fontsBox.setFont(new Font(fontName, Font.PLAIN, 16));
                    start();
                }
            }
        });
        fontsBox.setSelectedItem(0);
        fontsBox.getEditor().selectAll();
        menu1.add(menuItem1);
        menuBar1.add(menu1);
        menu2.add(menuItem2);
        menuBar1.add(menu2);
        frame.setJMenuBar(menuBar1);
        frame.setLayout(new GridLayout(4, 0, 20, 20));
        frame.add(fontsBox);
        frame.add(testButton);
        frame.add(testTextField);
        frame.add(testLabel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(200, 105);
        frame.pack();
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                fontsBox.setPopupVisible(true);
                fontsBox.setPopupVisible(false);
            }
        });
        frame.setVisible(true);
    }

    private void start() {
        timer = new javax.swing.Timer(750, updateCol());
        timer.setRepeats(false);
        timer.start();
    }

    public Action updateCol() {
        return new AbstractAction("text load action") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                final Font fnt = new Font(fontsBox.getSelectedItem().toString(), Font.PLAIN, 12);
                final FontUIResource res = new FontUIResource(fnt);
                UIManager.getLookAndFeelDefaults().put("Button.font", res);
                UIManager.getLookAndFeelDefaults().put("TextField.font", res);
                UIManager.getLookAndFeelDefaults().put("Label.font", res);
                SwingUtilities.updateComponentTreeUI(frame);
                frame.pack();
            }
        };
    }

    public static void main(String arg[]) {
        /*try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                SystemFontDisplayer systemFontDisplayer = new SystemFontDisplayer();
            }
        });
    }

    private class ComboRenderer extends BasicComboBoxRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            final Object fntObj = value;
            final String fontFamilyName = (String) fntObj;
            setFont(new Font(fontFamilyName, Font.PLAIN, 16));
            return this;
        }
    }
}

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • how does this help me to compare the otf and ttf version of Adobe Source Sans Pro? Also it does not print the values of the attributes to the console but just which attributes exist, did you take a look at the Github issue? –  Aug 27 '13 at 10:57
  • `1) how does this help me to compare the otf and ttf version of Adobe Source Sans Pro?` ---> each of Font has many attributes, one of them is insets, empty borders, available space for displaying higher of Unicodes glyph `2) Also it does not print the values of the attributes to the console but just which attributes exist` ---> again you can to get detailed properties from all Attributes 3) reason for Visual Font Designer by @ Darryl Burke and don't reinvent the wheel in my answer here `4) did you take a look at the Github issue?` ---> standard answer for OpenSource ... – mKorbel Aug 27 '13 at 11:16
  • no, you misunderstood something. I am using the font Source Sans Pro by Adobe. And I am using the otf or ttf version of this font. Only the otf font has some issues (line height?) but Miguel by Adobe says they both are the same. You can just select one version of the font from the list (ttf or otf?) but you can not compare them or select between otf and ttf version to compare them directly. –  Aug 27 '13 at 11:22
  • what did you find? In FontForge the 2 font files and metrics are the same so there are not 2px missinbg. Did you think about a Swing bug? Which textattribute differs when you compare both versions of the same font? –  Aug 27 '13 at 13:34
  • don't know, never caused before, if is feature or bug, but better will be to test with another Otf Font, I'm bet that with the same output in WinXP on Java6 too, have to wait a few moments – mKorbel Aug 27 '13 at 13:38
  • WinXp/Java with the same issue, hehehe are someone talking about bug in Java7_025, – mKorbel Aug 27 '13 at 13:46
  • maybe is there issue with Otf Fonts only, have to test with another Otf Font, but out of my endless lazyness and interest about – mKorbel Aug 27 '13 at 13:47
  • you can to use three, test with separate methods from SwingUtilitieshttp://docs.oracle.com/javase/7/docs/api/javax/swing/SwingUtilities.html, every returns -2 pixels for FONT_SIZE.16 – mKorbel Aug 27 '13 at 13:53
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/36330/discussion-between-daniel-ruf-and-mkorbel) –  Aug 27 '13 at 13:57
  • @Daniel Ruf [see answer (code lined in body)](http://stackoverflow.com/a/20311513/714968) by Andrew Thompson – mKorbel Dec 02 '13 at 09:12
  • no idea, only helicopter view, seems like as coordinates are repaired in the View, maybe programatically added one/two pixel, still/but I'd add 1-2 moreover (on top) – mKorbel Dec 02 '13 at 09:51
  • code lined in body? do you mean the hyperlink? seems this fixed the issue, but why? the ttf font gets a bit blurry, but the otf font is fixed and looks ok. what do you mean by helicopter view? it looks ok/right here, no need to add more pixels at the top –  Dec 02 '13 at 09:51
  • you have to notify author of code about, maybe he's able to fix issue with this Font in his code, his test will be faster as our comments about here – mKorbel Dec 02 '13 at 09:54
  • can you take a look at this and answer the comments from Miguel Sousa? https://github.com/adobe/source-sans-pro/issues/32#issuecomment-29776247 –  Dec 05 '13 at 08:15
  • 1. this will be accepted as offical bug in the case that only one of JComponents caused by different layout, bug could be in the case that JTextField (then JComboBox too)for example there is but in Java7 (still not Offical) with (java.swing.)View for JTextComponents, there is difference between APIs docs and binnary source, – mKorbel Dec 05 '13 at 08:49
  • 2. a) font can be registred in Native OS, b) font can be registred in JVM only, have to test if is there some difference, – mKorbel Dec 05 '13 at 08:53
  • 3. there isn't any difference between Java6 and Java7 as is demonstrated in my answer here and for various Standard LookAndFeels on varianous WinOS version, there is important fact that renderings core is very different for WinXP and for Win7/8, then my answers is that isn't Java bug – mKorbel Dec 05 '13 at 08:58
  • 4. most of Java bug are accesible only from SystemLookAndFeels (WindowsLook...) or WindowsClassicLook..., the result is same as for Nimbus (only one different rendering algorithm in Swing APIs) – mKorbel Dec 05 '13 at 09:00
  • 5. my question (don not take as flamewar) is for why reasons one part of font is rendered correctly (after font is converted, fixed), second isn't, there is possible to calculate required Rectange from SwingUtilities.(layoutCompoundLabel, e.i.) but by default there isn't some direct way to get this height (everything is about how to computeStringWidth), this value came from Font and isn't directly accesible from deriveFont for Graphics too, – mKorbel Dec 05 '13 at 09:10
  • 6. if is there any different conclusion I can to abuse my rep power, to ask question here about how to get, set, manage required height for Fonts from Graphics, because for JComponents is in BasicXxxUI everything about paint/paintText, but I'm think that layout for this font in Graphics will be the same as for JComponents – mKorbel Dec 05 '13 at 09:17
  • please answer on Github, this is better for all ;-) –  Dec 05 '13 at 19:04
  • https://github.com/adobe/source-sans-pro/issues/32#issuecomment-30657669 any news/updates? –  Dec 19 '13 at 22:10
  • not I tested another Fonts, part of them with the similair and wrong offset, BugParade (everything after merging is with Oracle names but bugs are still Sun) is [official Java Bug Database](http://bugs.sun.com/), – mKorbel Dec 20 '13 at 09:56
  • 1
    you know already that I have filed an issue which does not exist - which is very weird - it should exists as I have a bug id ... =( this is very disappointing with Oracle and Java and that there is no answer for this issue/answer which solves all the problems. –  Dec 20 '13 at 17:59
  • 1
    all this brings us to nothing, Adobe says it is not a font bug, Oracle says nothing, so for me it is a Java bug –  Jan 31 '14 at 20:31