JDK-8139741 : [macosx] Font ligature is not rendered on OS X for natively loaded font
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 8u60,9
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: os_x
  • CPU: x86_64
  • Submitted: 2015-10-16
  • Updated: 2015-11-12
  • Resolved: 2015-11-12
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.
JDK 9
9Resolved
Related Reports
Duplicate :  
Description
1. Summary
---------------
Optional font ligature is not rendered on Mac OS X when natively loaded 
font is used.
When the same font is loaded in application using java.awt.Font.createFont() method, 
it works fine.

2. How to reproduce
--------------------------
The issue is reproduced on Mac OS X Yosemite version 10.10.5 using latest Java 9 EA:

$ uname -a
Darwin xxx 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64
$ 

$  ../jdk1.9.0.jdk/Contents/Home/bin/java -version
java version "1.9.0-ea"
Java(TM) SE Runtime Environment (build 1.9.0-ea-b86)
Java HotSpot(TM) 64-Bit Server VM (build 1.9.0-ea-b86, mixed mode)
$ 

To reproduce the issue, please do the following:
(1) compile attached file 'Ligatures1Test.java' and run it.
$  ../jdk1.9.0.jdk/Contents/Home/bin/javac Ligatures1Test.java
$  ../jdk1.9.0.jdk/Contents/Home/bin/java Ligatures1Test &
[1] 4133
$
(2) Actual behaviour:
    The window shows characters that are rendered separately.
    (see attached file 'Ligatures1_OSX.png')

(3) Expected behaviour:
    On Windows, the expected behaviour is shown
    (see attached file 'Ligatures1-Windows.png')

(4) Loading the font in the application using java.awt.Font.createFont() method,
it works fine: 
(unfortunately, this approach is not usable as a workaround, as the font mapping
is too complex.)

(4.1) install attached font 'Hasklig-Regular.noDFLT.otf':
      (copy the file into ~/Library/Fonts folder)
$ cp Hasklig-Regular.noDFLT.otf ../Library/Fonts
$ ls ../Library/Fonts
Hasklig-Regular.noDFLT.otf
$
(4.2) compile attached file 'Ligatures2Test.java' and run it.
The window shows characters that are rendered as a single glyph.
(see attached file 'Ligatures2_OSX.png')

3. Sources
--------------
% more Ligatures1Test.java
import javax.swing.*;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.util.HashMap;
import java.util.Map;

public class Ligatures1Test {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame();
            JLabel label = new JLabel("->");
            label.setFont(createFont());
            frame.add(label);
            frame.pack();
            frame.setVisible(true);
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        });
    }

    private static Font createFont() {
        try {
            Font font = new Font("Hasklig", Font.PLAIN, 1);
            Map<TextAttribute, Object> attributes = new HashMap<>();
            attributes.put(TextAttribute.SIZE, 30);
            attributes.put(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON);
            return font.deriveFont(attributes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}


% more Ligatures2Test.java
import javax.swing.*;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

public class Ligatures2Test {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame();
            JLabel label = new JLabel("->");
            label.setFont(createFont());
            frame.add(label);
            frame.pack();
            frame.setVisible(true);
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        });
    }

    private static Font createFont() {
        try {
            Font font = Font.createFont(Font.TRUETYPE_FONT, new File(System.getProperty("user.home"), "Library/Fonts/Hasklig-Regular.noDFLT.otf"));
            Map<TextAttribute, Object> attributes = new HashMap<>();
            attributes.put(TextAttribute.SIZE, 30);
            attributes.put(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON);
            return font.deriveFont(attributes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}


Comments
Seems this was reported a long time ago as https://bugs.openjdk.java.net/browse/JDK-7162125.
12-11-2015

I recently noticed that the java class, CFont, implemented to wrap the native OS X font does not implement some required interfaces. As a result there is no access to the font table needed to implement this. When use via Font.createFont(..) it uses TrueTypeFont, which does implement the required interfaces. Whilst fixing this is not that hard it immediately makes other things worse, since now the layout engine will try to use that table for all code points mapped by the font But CFont uses core text font cascading and so some code points are from other fonts where you would want to use the table from the font that really maps it. So if we had a mixed latin+arabic string then currently the layout engine will use canonical property tables and do a creditable job. But the table lookup fix would by pass that and the latin would be OK, but the arabic incorrect - displaying as isolated forms.
19-10-2015