JDK-8208666 : Missing glyphs from custom made font when rendering on Graphics2D
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 7u13,7u40,8,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2018-08-01
  • Updated: 2019-08-16
  • Resolved: 2019-05-17
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.
Windows 10  + JRE Reproducible on latest Java 10 as well.
Red Hat 6.8 + JRE is also affected.

We are using custom made fonts and most of the time TTF version of fonts do not render some glyphs with Java, no matter what version. I can provide a font file on demand, and also screenshots of incorrect images with rendered text. Glyphs are inside font file indeed, well rendered used other software like MS Word. What is interesting that rendered image retain boundaries of missed glyph but no actual symbol graphics is rendered. GlyphVector of particular missed font keystroke is empty.

Run the provided code snippet, obtaining font file on request preliminary.

Image with text contains all glyphs in provided char sequence.
Generated image with text won't contain some glyphs.

---------- BEGIN SOURCE ----------
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics2D;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import javax.imageio.ImageIO;

public class MissedGlyphs {
    private static final int FONT_SIZE = 50;

    public static void main(String[] args) throws IOException {
        BufferedImage result = new BufferedImage(1500,500,BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = result.createGraphics();
        File initialFile = new File(new File("C:\\"), "font.ttf");
        InputStream targetStream = new FileInputStream(initialFile);
        Font font = null;
        try {
            Font sourceFont = Font.createFont(Font.TRUETYPE_FONT, targetStream);
            Map<TextAttribute, Object> attributes = (Map<TextAttribute, Object>) sourceFont.getAttributes();
            attributes.put(TextAttribute.SIZE, FONT_SIZE);
            font = sourceFont.deriveFont(attributes);
        } catch (FontFormatException e) {
        graphics.drawString("ABCDEF", 10, 100);
        graphics.drawString("GHIJK", 10, 200);
        ImageIO.write(result,"BMP",new File(new File("C:\\"), "MISSING_GLYPH.BMP"));

---------- END SOURCE ----------

Sometimes using OTF version of the same font fixes issue, but only on Linux OS. In addition, OpenJDK renders everything without any issues, but actual image view is a bit different than Oracle JDK provides.

FREQUENCY : always

Seems to affect Oracle proprietary T2K, not OpenJDK freetype. Adding openjdk-na.

I have confirmed the main problem is with some sanity checks added in 7u13 and is in all 8 releases. They would need to be revised for this - rather unusual - font to work.

I wasn't sure why above there's a claim the bug is reproducible with JDK 11 + 12 which uses freetype. I am guessing that is just about the dashed line image mapped as "J" which is index 12 and renders as invisible at sizes BELOW 40 pixels. I see the same occuring in the Moicrosoft VOLT font editing tool. The segments are 4 font units in height and the font uses upem=1000 So if the font is 10 pixels high, 100 units is "approximately" a pixel and these segments will be 0.04 pixels high 40 pixels high and they are about 0.4 pixels high .. just about close enough that they show up. So that looks to me to be a problem in the font design making it too thin. The remaining problems are not appliable to 11 and 12, so I am removing those releases from the affected releases and marking it 11-na, 12-na.

I regressed this to 7u13 which contains a fix which sanity checks the bounding box of glyphs. Since we have some HUGE glyphs in here this seems likely to be the source of the problem.

Correction to the above statement "char 4A ('I') which should be mapped as glyph index 12." I is not mapped to index 12, it is mapped to Index 0 in the 1,0 CMAP and unmapped in the 3.0 CMAP .. so missing glyph is correct there.

It seems likely that this ran afoul of some correctness tightening in a JDK 7 update. It would require investigation to see if the font is malformed, or if JDK is too strict. The report is that OpenJDK is fine, so I'd expect JDK 11 to be OK as it uses freetype like OpenJDK And in JDK 11 builds toggling between the two I can see that with freetype - and hence JDK 11, contrary to what is written above - seems to render all these glyphs except one. For that one we are getting a missing glyph box for char 4A ('I') which should be mapped as glyph index 12. Perhaps we have a bug in the 3,0 CMAP code which this is tripping over, but it is a format 4 subtable, which is code that has been exercised more than any other.

Custom made fonts and most of the time TTF version of fonts do not render some glyphs with Java. Checked this with reported JDK version and could confirm this as a regression in JDK 7u40 and onward. Results: ========== 7u25: Ok 7u40: Fail 8: Fail 8u181: Fail 9: Fail 11 ea b24: Fail 12 ea b04: Fail To verify, run the attached test program with attached font file. See attached screenshots as a reference.

Writing back to the submitter requesting detailed information including font file and screenshots reflecting issue.