0

I am working on embedding fonts those are not embedded to PDF. For this, I am using PDFBox library to identify missing fonts using PDFont class. Using this I am able to identify list of missing fonts. But when I am trying to embed them using my local machine font's(grabbed TTF files from my local machine fonts folder), I am not able to do it, getting following result.

enter image description here

I am using following code to get list of (not embedded) fonts,

private static List<FontsDetails> checkAllFontsEmbeddedOrNot(PDDocument pdDocument) throws Exception {
    List<FontsDetails> notEmbFonts = null;
    try {
        if(null != pdDocument){
            PDPageTree pageTree = pdDocument.getDocumentCatalog().getPages();
            notEmbFonts = new ArrayList<>();
            for (PDPage pdPage : pageTree) {
                PDResources resources = pdPage.getResources();
                Iterable<COSName> cosNameIte = resources.getFontNames();
                Iterator<COSName> names = cosNameIte.iterator();
                while (names.hasNext()) {
                    COSName name = names.next();
                    PDFont font = resources.getFont(name);
                    boolean isEmbedded = font.isEmbedded();
                    if(!isEmbedded){
                        FontsDetails fontsDetails = new FontsDetails();
                        fontsDetails.setFontName(font.getName().toString());
                        fontsDetails.setFontSubType(font.getSubType());
                        notEmbFonts.add(fontsDetails);
                    }
                }
            }
        }
    } catch (Exception exception) {
        logger.error("Exception occurred while validating fonts : ", exception);
        throw new PDFUtilsException("Exception occurred while validating fonts : ",exception);
    }
    return notEmbFonts;
}

Following is the code which I am using to embed fonts which I am getting from above list,

public List<FontsDetails> embedFontToPdf(File pdf, FontsDetails fontToEmbed) {
    ArrayList<FontsDetails> notSupportedFonts = new ArrayList<>();
    try (PDDocument pdDocument = PDDocument.load(pdf)) {
        LOGGER.info("Embedding font : " + fontToEmbed.getFontName());
        InputStream ttfFileStream =  PDFBoxOperationsUtility.class.getClassLoader()
                .getResourceAsStream(fontToEmbed.getFontName() + ".ttf");//loading ttf file
        if (null != ttfFileStream) {
            PDFont font = PDType0Font.load(pdDocument, ttfFileStream);
            PDPage pdfPage = new PDPage();
            PDResources pdfResources = new PDResources();
            pdfPage.setResources(pdfResources);

            PDPageContentStream contentStream = new PDPageContentStream(pdDocument, pdfPage);
            if (fontToEmbed.getFontSize() == 0) {
                fontToEmbed.setFontSize(DEFAULT_FONT_SIZE);
            }
            font.encode("ANSI");
            contentStream.setFont(font, fontToEmbed.getFontSize());
            contentStream.close();

            pdDocument.addPage(pdfPage);
            pdDocument.save(pdf);
        } else {
            LOGGER.info("Font : " + fontToEmbed.getFontName() + " not supported");
            notSupportedFonts.add(fontToEmbed);
        }
    } catch (Exception exception) {
        notSupportedFonts.add(fontToEmbed);
        LOGGER.error("Error ocurred while embedding font to pdf : " + pdf.getName(), exception);
    }
    return notSupportedFonts;
}

Could someone pleas help me to identify what mistake I am doing or any other approach I will need to take.

Tushar Deshpande
  • 448
  • 2
  • 9
  • 28
  • 1
    See https://stackoverflow.com/questions/64752894/ not a real duplicate, but it should give some hints. – Tilman Hausherr Nov 19 '20 at 14:27
  • Sure @TilmanHausherr I will try with this, will let you know. – Tushar Deshpande Nov 19 '20 at 14:40
  • @TilmanHausherr I am using pdfbox version 2.0.17 but not able to get getEncoding() method in PDFont class, shall I use any different version – Tushar Deshpande Nov 19 '20 at 14:48
  • Always use the latest version. `getEncoding()` is available in some of the subclasses. (There is no perfect solution, i.e. the linked answer may or may not work, but it shows the how to replace fonts in the resources) – Tilman Hausherr Nov 19 '20 at 15:10
  • Also consider that there are not only resources at page level but also Xobjects, patterns, etc. may have their own resources with fonts to update. – mkl Nov 19 '20 at 16:06
  • yes @TilmanHausherr Thank you that linked help me atleast to embed fonts I am able to embed fonts now. But I have one doubt everytime when fonts are getting embedded with this approach it is getting encoded as WinAnsiEncoding.INSTANCE and SubType as TrueType. Will converting it's original encoding and subtype to new one can affect PDF at printing side.? (Now I am able to see all fonts embedded in the pdf) – Tushar Deshpande Nov 20 '20 at 12:06
  • I don't know... One possible problem would be when the non embedded font isn't truetype but something else, e.g. type0. You should use your tool only for files that you know, not for random files from the wild. For these it would be better to use a commercial tool. – Tilman Hausherr Nov 20 '20 at 12:12

0 Answers0