Monthly Archives: June 2015

Know Your Font: update on SQL Developer oddity

A while back I posted a note about an oddity I ran into using SQL Developer on Windows (see here for details). As I couldn’t leave the issue alone I eventually found the root cause with a little help from my friends (fellow developers): It’s the font “DialogInput” SQL Developer uses by default. As I learned, “DialogInput” is a so-called logical font (read about that here). Apparently, these logical fonts are a composition of multiple physical fonts depending on what’s actually installed on your system and hence, differ on my Linux and Windows systems. This little Java program prints out the font composition:

import java.awt.Font;
import java.lang.reflect.Method;
import java.util.Locale;

import sun.font.CompositeFont;
import sun.font.Font2D;
import sun.font.PhysicalFont;

public class Test {
    public static void main(String... args)
    throws Exception
    {
        Font font = new Font("DialogInput", Font.PLAIN, 12);
        describeFont(font);
    }

    private static void describeFont(Font font)
    throws Exception
    {
        Method method = font.getClass().getDeclaredMethod("getFont2D");
        method.setAccessible(true);
        Font2D f = (Font2D)method.invoke(font);

        describeFont2D(f);
    }

    private static void describeFont2D(Font2D font)
    {
        if (font instanceof CompositeFont)
        {
            System.out.println("Font '" + font.getFontName(Locale.getDefault()) + "' is composed of:");

            CompositeFont cf = (CompositeFont)font;
            for (int i = 0; i < cf.getNumSlots(); i++)
            {
                PhysicalFont pf = cf.getSlotFont(i);
                describeFont2D(pf);
            }
        }
        else
            System.out.println("-> " + font);
    }
}

Output from my Linux system:

Font 'DialogInput.plain' is composed of:
-> ** TrueType Font: Family=DejaVu Sans Mono Name=DejaVu Sans Mono style=0 fileName=/usr/share/fonts/dejavu/DejaVuSansMono.ttf
-> ** TrueType Font: Family=DejaVu Sans Mono Name=DejaVu Sans Mono Bold style=1 fileName=/usr/share/fonts/dejavu/DejaVuSansMono-Bold.ttf
-> ** Type1 Font: Family=Nimbus Mono L Name=Nimbus Mono L Regular style=0 fileName=/usr/share/fonts/default/Type1/n022003l.pfb
-> ** TrueType Font: Family=VL Gothic Name=VL Gothic Regular style=0 fileName=/usr/share/fonts/vlgothic/VL-Gothic-Regular.ttf
-> ** TrueType Font: Family=NanumGothic Name=NanumGothic style=0 fileName=/usr/share/fonts/nhn-nanum/NanumGothic.ttf
-> ** TrueType Font: Family=Lohit Bengali Name=Lohit Bengali style=0 fileName=/usr/share/fonts/lohit-bengali/Lohit-Bengali.ttf
-> ** TrueType Font: Family=Lohit Gujarati Name=Lohit Gujarati style=0 fileName=/usr/share/fonts/lohit-gujarati/Lohit-Gujarati.ttf
-> ** TrueType Font: Family=Lohit Punjabi Name=Lohit Punjabi style=0 fileName=/usr/share/fonts/lohit-punjabi/Lohit-Punjabi.ttf
-> ** TrueType Font: Family=Lohit Tamil Name=Lohit Tamil style=0 fileName=/usr/share/fonts/lohit-tamil/Lohit-Tamil.ttf
-> ** TrueType Font: Family=Meera Name=Meera style=0 fileName=/usr/share/fonts/smc/Meera.ttf
-> ** TrueType Font: Family=Lohit Kannada Name=Lohit Kannada style=0 fileName=/usr/share/fonts/lohit-kannada/Lohit-Kannada.ttf
-> ** TrueType Font: Family=Lohit Telugu Name=Lohit Telugu style=0 fileName=/usr/share/fonts/lohit-telugu/Lohit-Telugu.ttf
-> ** TrueType Font: Family=Lohit Oriya Name=Lohit Oriya style=0 fileName=/usr/share/fonts/lohit-oriya/Lohit-Oriya.ttf
-> ** TrueType Font: Family=LKLUG Name=LKLUG style=0 fileName=/usr/share/fonts/lklug/lklug.ttf
-> ** TrueType Font: Family=FreeMono Name=FreeMono style=0 fileName=/usr/share/fonts/gnu-free/FreeMono.ttf
-> ** TrueType Font: Family=FreeSans Name=FreeSans style=0 fileName=/usr/share/fonts/gnu-free/FreeSans.ttf
-> ** TrueType Font: Family=FreeSerif Name=FreeSerif style=0 fileName=/usr/share/fonts/gnu-free/FreeSerif.ttf
-> ** TrueType Font: Family=OpenSymbol Name=OpenSymbol style=0 fileName=/usr/share/fonts/opensymbol/opens___.ttf
-> ** TrueType Font: Family=PakType Naqsh Name=PakType Naqsh style=0 fileName=/usr/share/fonts/paktype-naqsh/PakType_Naqsh.ttf
-> ** TrueType Font: Family=Khmer OS Name=Khmer OS style=0 fileName=/usr/share/fonts/khmeros/KhmerOS.ttf
-> ** TrueType Font: Family=Padauk Name=Padauk style=0 fileName=/usr/share/fonts/sil-padauk/Padauk.ttf
-> ** TrueType Font: Family=Lohit Devanagari Name=Lohit Devanagari style=0 fileName=/usr/share/fonts/lohit-devanagari/Lohit-Devanagari.ttf
-> ** TrueType Font: Family=DejaVu Sans Name=DejaVu Sans style=0 fileName=/usr/share/fonts/dejavu/DejaVuSans.ttf
-> ** TrueType Font: Family=DejaVu Serif Name=DejaVu Serif style=0 fileName=/usr/share/fonts/dejavu/DejaVuSerif.ttf
-> ** TrueType Font: Family=Nuosu SIL Name=Nuosu SIL style=0 fileName=/usr/share/fonts/sil-nuosu/NuosuSIL.ttf
-> ** TrueType Font: Family=PT Sans Name=PT Sans style=0 fileName=/usr/share/fonts/paratype-pt-sans/PTS55F.ttf
-> ** TrueType Font: Family=Abyssinica SIL Name=Abyssinica SIL style=0 fileName=/usr/share/fonts/sil-abyssinica/AbyssinicaSIL-R.ttf
-> ** TrueType Font: Family=Carlito Name=Carlito style=0 fileName=/usr/share/fonts/google-crosextra-carlito/Carlito-Regular.ttf
-> ** TrueType Font: Family=Liberation Sans Name=Liberation Sans style=0 fileName=/usr/share/fonts/liberation/LiberationSans-Regular.ttf
-> ** TrueType Font: Family=Liberation Serif Name=Liberation Serif style=0 fileName=/usr/share/fonts/liberation/LiberationSerif-Regular.ttf
-> ** TrueType Font: Family=Noto Sans Mandaic Name=Noto Sans Mandaic style=0 fileName=/usr/share/fonts/google-noto/NotoSansMandaic-Regular.ttf
-> ** TrueType Font: Family=Noto Sans Meetei Mayek Name=Noto Sans Meetei Mayek style=0 fileName=/usr/share/fonts/google-noto/NotoSansMeeteiMayek-Regular.ttf
-> ** TrueType Font: Family=Noto Sans Tagalog Name=Noto Sans Tagalog style=0 fileName=/usr/share/fonts/google-noto/NotoSansTagalog-Regular.ttf
-> ** TrueType Font: Family=Noto Sans Tai Tham Name=Noto Sans Tai Tham style=0 fileName=/usr/share/fonts/google-noto/NotoSansTaiTham-Regular.ttf
-> ** TrueType Font: Family=Noto Sans Tai Viet Name=Noto Sans Tai Viet style=0 fileName=/usr/share/fonts/google-noto/NotoSansTaiViet-Regular.ttf
-> ** TrueType Font: Family=Waree Name=Waree style=0 fileName=/usr/share/fonts/thai-scalable/Waree.ttf
-> ** TrueType Font: Family=Mingzat Name=Mingzat style=0 fileName=/usr/share/fonts/sil-mingzat/Mingzat-R.ttf
-> ** TrueType Font: Family=Jomolhari Name=Jomolhari style=0 fileName=/usr/share/fonts/jomolhari/Jomolhari-alpha3c-0605331.ttf
-> ** TrueType Font: Family=WenQuanYi Zen Hei Name=WenQuanYi Zen Hei style=0 fileName=/usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc
-> ** TrueType Font: Family=WenQuanYi Zen Hei Name=WenQuanYi Zen Hei style=0 fileName=/usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc
-> ** TrueType Font: Family=AR PL UMing CN Name=AR PL UMing CN style=0 fileName=/usr/share/fonts/cjkuni-uming/uming.ttc
-> ** TrueType Font: Family=AR PL UMing CN Name=AR PL UMing CN style=0 fileName=/usr/share/fonts/cjkuni-uming/uming.ttc
-> ** TrueType Font: Family=AR PL UMing CN Name=AR PL UMing CN style=0 fileName=/usr/share/fonts/cjkuni-uming/uming.ttc

Output from my Windows system:

FFont 'DialogInput.plain' is composed of:
-> ** TrueType Font: Family=Courier New Name=Courier New style=0 fileName=C:\Windows\Fonts\COUR.TTF
-> ** TrueType Font: Family=Wingdings Name=Wingdings style=0 fileName=C:\Windows\Fonts\WINGDING.TTF
-> ** TrueType Font: Family=Symbol Name=Symbol style=0 fileName=C:\Windows\Fonts\SYMBOL.TTF
-> ** TrueType Font: Family=Lucida Sans Name=Lucida Sans Regular style=0 fileName=C:\Program Files\Java\jdk1.7.0_45\jre\lib\fonts\LucidaSansRegular.ttf
-> ** TrueType Font: Family=MingLiU Name=MingLiU style=0 fileName=C:\Windows\Fonts\MINGLIU.TTC
-> ** TrueType Font: Family=Lucida Sans Name=Lucida Sans Regular style=0 fileName=C:\Program Files\Java\jdk1.7.0_45\jre\lib\fonts\LucidaSansRegular.ttf
-> ** TrueType Font: Family=SimSun Name=SimSun style=0 fileName=C:\Windows\Fonts\SIMSUN.TTC
-> ** TrueType Font: Family=Lucida Sans Name=Lucida Sans Regular style=0 fileName=C:\Program Files\Java\jdk1.7.0_45\jre\lib\fonts\LucidaSansRegular.ttf
-> ** TrueType Font: Family=MS Gothic Name=MS Gothic style=0 fileName=C:\Windows\Fonts\MSGOTHIC.TTC
-> ** TrueType Font: Family=Gulim Name=Gulim style=0 fileName=C:\Windows\Fonts\gulim.TTC
-> ** TrueType Font: Family=MingLiU-ExtB Name=MingLiU-ExtB style=0 fileName=C:\Windows\Fonts\MINGLIUB.TTC
-> ** TrueType Font: Family=SimSun-ExtB Name=SimSun-ExtB style=0 fileName=C:\Windows\Fonts\SIMSUNB.TTF
-> ** TrueType Font: Family=Sylfaen Name=Sylfaen style=0 fileName=C:\Windows\Fonts\sylfaen.ttf

And therein lies the tragic of the issue: on Windows “DialogInput” includes the font “MingLiU” which in turn represents Unicode code point U+0092 as right single quotation mark (see here).

Conclusion
I appologize for falsely accusing SQL Developer to do something strange when it is perfectly fine. On the other hand, it’s utterly beyond me why someone would design a font to represent a PRIVATE USE TWO Unicode code point to be a printable, otherwise perfectly well-defined character.
When in doubt, change the SQL Developer properties to a physical font you know or get familiar with the code points it supports – know your font!