Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8064833

[macosx] Native font lookup uses family+style, not full name/postscript name



    • Bug
    • Resolution: Fixed
    • P3
    • 9
    • 7u4
    • client-libs
    • 2d
    • b52
    • os_x



        There was an FX bug report that text was printed incorrectly
        It wasn't clear if it was a locale problem but the symptom looked like
        a bad char->glyph mapping.

        This was seen only on later OS X systems. Some debugging revealed that
        Helvetica-LightOblique was in use and this helped identify the problem.

        FX printing is using an interface to Java 2D. This prints text by passing
        the font information and glyphs to draw to the 2D pipeline.

        It was eventually determined that the glyph codes passed from FX were the
        correct ones for the font that was specified and that the problem was in
        the 2D side where the wrong font was found. This is not at all specific to
        printing. The same happens on screen. And once you know the font to
        use you can see the problem on 10.7.x too.

        The OS X specific font code correctly registers Helvetica-LightOblique for lookup
        However when it comes to be used it needs to get a pointer to a native font
        resource. It does this by passing the family name - in this case 'Helvetica' - and
        style information.
                    nativeFontPtr = createNativeFont(nativeFontName, style, isFakeItalic);

        This is under-specified and as a result the underlying native font
        that is mapped from the Java CFont is actually Helvetica-Oblique and thus we
        get the glyph ids mapped into that font which is different.

        Note: this is NOT a regression in Oracle JDK for OS X.
        I can reproduce the problem on Apple JDK 6. Its likely been a bug forever ...

        That can be resolved as thus :-
        hg diff CFont.java
        diff --git a/src/java.desktop/macosx/classes/sun/font/CFont.java b/src/java.desktop/macosx/classes/sun/font/CFont.java
        --- a/src/java.desktop/macosx/classes/sun/font/CFont.java
        +++ b/src/java.desktop/macosx/classes/sun/font/CFont.java
        @@ -94,7 +94,7 @@
                 handle = new Font2DHandle(this);
                 fullName = name;
                 familyName = inFamilyName;
        - nativeFontName = inFamilyName;
        + nativeFontName = fullName;

        The two things I am not sure about - that I can think of - are
        1) That this lookup by full name will work reliably - and note this is PSName which is
        how the Apple implementation has always worked, but that is for another day
        2) Since we specify full name we should find the right style, so I am unsure if
        the native code to 'add' that trait is a) always a no-op, b) sometimes a no-op
        but occasionally helpful, or c) harmful in at least some cases.

        The test program below demonstrates the problem - if it finds this font it ought to
        draw "Big red italic font" but instead draws garbage text.

        import javax.swing.*;
        import java.awt.*;
        import java.awt.font.*;

        public class DrawHelveticaGV extends JComponent {

            public static void main(String[] args) throws Exception {
                JFrame f = new JFrame();
                DrawHelveticaGV dgv = new DrawHelveticaGV();
                f.add("Center", dgv);

            public Dimension getPreferredSize() {
              return new Dimension(400,400);

            int[] codes = { 0x23, 0x4a, 0x48, 0x3, 0x4a, 0x55, 0x42, 0x4d,
                            0x4a, 0x44, 0x3,
                            0x53, 0x46, 0x45, 0x3, 0x55, 0x46, 0x59, 0x55, };

            public void paintComponent(Graphics g) {
               Graphics2D g2 = (Graphics2D)g;
               FontRenderContext frc = new FontRenderContext(null, true, true);
               Font f = new Font("Helvetica-LightOblique", Font.PLAIN, 40);
               System.out.println("font = " +f.getFontName());
               GlyphVector gv = f.createGlyphVector(frc, codes);
               g2.drawGlyphVector(gv, 5,200);


          Issue Links



                prr Philip Race
                prr Philip Race
                0 Vote for this issue
                4 Start watching this issue