How to properly check if a font can handle a codePoint in PdfBox

Viewed 33

I am attempting to write text to a PDF using NotoEmoji font only when Emojis are encountered. I am doing a check similar to the one below to determine when to use NotoEmoji instead of my default font. Here is a bit of code that reproduces my problem:

 public static void main(String[] args) throws IOException {
    PDType0Font font = PDType0Font.load(
            new PDDocument(),
            ClassLoader.getSystemResourceAsStream("NotoEmoji-Regular.ttf"),
            false);
    String hex = "01F302";
    int codepoint = Integer.parseInt(hex,16);
    System.out.println("codepoint: " + codepoint);
    System.out.println("contains hex " + hex + ": " + font.hasGlyph(codepoint));

}

I would expect the output to be

codepoint: 127746
contains hex 01F302: true

Instead, the hasGlyph method is returning false. I have verified the font contains this emoji (closed umbrella). I don't know if I'm loading the font incorrectly or if I am completely misunderstanding how this works. This is my first time using PdfBox.

I'm using the following version of pdfbox

    <dependency>
      <groupId>org.apache.pdfbox</groupId>
      <artifactId>pdfbox</artifactId>
      <version>2.0.26</version>
    </dependency>

<-----------------------UPDATE----------------------->

Ok, I think I might have a solution to this, but I'd love for someone to explain it to me. I had been using hasGlyph to check whether a particular codePoint could be handled by the font. I think that is wrong. I found a couple of SO questions that seem to suggest that. Instead, it appears something like font.codeToCID(codepoint) > 0 will work. However, I'm not sure if it's reliable. Also font.codeToGID(codepoint) does not work and I don't know why. Here is a snippet similar to the one above to demonstrate my proposed solution:

    public static void main(String[] args) throws IOException {
        PDType0Font font = PDType0Font.load(
                new PDDocument(),
                ClassLoader.getSystemResourceAsStream("NotoEmoji-Regular.ttf"),
                false);
        String hex = "01F302";
        int codepoint = Integer.parseInt(hex,16);
        System.out.println("codepoint: " + codepoint);
        System.out.println("hasGlyph(0): " + font.hasGlyph('0'));
        System.out.println("cid: " + font.codeToCID(codepoint));
        System.out.println("gid: " + font.codeToGID(codepoint));
        System.out.println("can Encode: " + (font.codeToCID(codepoint) > 0));
    }

Here is the output:

codepoint: 127746
hasGlyph(0): true
cid: 62210
gid: 0
can Encode: true

In addition, I have updated the title of my question to more accurately reflect the problem I am trying to solve, I think.

0 Answers
Related