简体   繁体   中英

how to add unicode in truetype0font on pdfbox 2.0.0?

I've been using the PDFBOX version 2.0.0 in a Java project to convert pdfs to text.

several of my pdfs are missing the ToUnicode method, so they come out in Gibberish while I export them.

2016-09-14 10:44:55 WARN org.apache.pdfbox.pdmodel.font.PDSimpleFont(1):322 - No Unicode mapping for 694 (30) in font MPBAAA+F1

in the WARN above, instead of the real character, a gibberish unicode (30) was presented.

I was able to overcome it by editing the additional.txt file in pdfbox, since from trial & error I understood that the code of the character (694 in this case) represents a certain Hebrew letter (צ).

here's a short example of what I've edited inside the file:

-694;05E6 #HexaDecimal value for the letter צ
-695;05E7
-696;05E8

later I've encountered almost the same warning on a different pdf, but instead of gibberish characters I got no characters at all. a more detailed explination of this issue can be seen here - pdf reading via pdfbox in java

2016-09-14 11:07:10 WARN org.apache.pdfbox.pdmodel.font.PDType0Font(1):431 - No Unicode mapping for CID+694 (694) in font ABCDEE+Tahoma,Bold

As you can see, the warning came from a different class ( PDType0Font ) rather than the first warning ( PDSimpleFont ), but the code name (694) is the same in both of them and they are both talking about the same character.

Does there's a different file that I should edit other than additional.txt to point the 694 code (the Hebrew letter צ) to it's correct unicode?

Thanks主根

向下钻取第一个 type0 字体

Here's some code to add a ToUnicode CMap stream in a font. Obviously I can't do it with your file, so I used one of my test files, which can be found here . I had to work on each entry separately and didn't do all. However the result is good enough to extract the first word in the green print ("Bedingungen").

The scenario is somewhat tailored to you:

  • Identity-H entry
  • no ToUnicode entry
  • specific font name

    try (PDDocument doc = PDDocument.load(f)) { for (int p = 0; p < doc.getNumberOfPages(); ++p) { PDPage page = doc.getPage(p); PDResources res = page.getResources(); for (COSName fontName : res.getFontNames()) { PDFont font = res.getFont(fontName); COSBase encoding = font.getCOSObject().getDictionaryObject(COSName.ENCODING); if (!COSName.IDENTITY_H.equals(encoding)) { continue; } // get real name String fname = font.getName(); int plus = fname.indexOf('+'); if (plus != -1) { fname = fname.substring(plus + 1); } if (font.getCOSObject().containsKey(COSName.TO_UNICODE)) { continue; } System.out.println("File '" + f.getName() + "', page " + (p + 1) + ", " + fontName.getName() + ", " + font.getName()); if (!fname.startsWith("Calibri-Bold")) { continue; } COSStream toUnicodeStream = new COSStream(); try (PrintWriter pw = new PrintWriter(toUnicodeStream.createOutputStream(COSName.FLATE_DECODE))) { // "9.10 Extraction of Text Content" in the PDF 32000 specification pw.println ("/CIDInit /ProcSet findresource begin\\n" + "12 dict begin\\n" + "begincmap\\n" + "/CIDSystemInfo\\n" + "<< /Registry (Adobe)\\n" + "/Ordering (UCS) /Supplement 0 >> def\\n" + "/CMapName /Adobe-Identity-UCS def\\n" + "/CMapType 2 def\\n" + "1 begincodespacerange\\n" + "<0000> <FFFF>\\n" + "endcodespacerange\\n" + "10 beginbfchar\\n" + // number is count of entries "<0001><0020>\\n" + // space "<0002><0041>\\n" + // A "<0003><0042>\\n" + // B "<0004><0044>\\n" + // D "<0013><0065>\\n" + // e "<0012><0064>\\n" + // d "<0017><0069>\\n" + // i "<001B><006E>\\n" + // n "<0015><0067>\\n" + // g "<0020><0075>\\n" + // u "endbfchar\\n" + "endcmap CMapName currentdict /CMap defineresource pop end end"); } font.getCOSObject().setItem(COSName.TO_UNICODE, toUnicodeStream); } } doc.save("huhu.pdf"); }

Btw the unreleased 2.1 version of PDFDebugger has some improved features to show fonts, you can get it here :

You can use it to verify that your ToUnicode CMap makes sense. Here's what I get with my changes: 在此处输入图片说明

Can the above code be used to add unicode Mapping for all pdf files, if all characters are added? If yes, how do you come up with these numbers here? "<0002><0041>\n" + // A

I know that 0041 corresponds to the ASCII code ( 0x41). What about 0020?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM