Page 1 of 1

Embedded fonts not used in PDF conversion?

PostPosted: Fri Jul 06, 2012 10:55 pm
by slambert
Hello,

I'm using docx4j 2.8.0 to mail merge a document and then convert it to PDF. This process is running on a Linux system (it's in a web application running on Tomcat). Consequently, although the result is looking fine, during conversion a stream of errors is logged saying no physical fonts could be located:

Code: Select all
06-07 - 11:06:24 ERROR [http-bio-8085-exec-48] (Conversion.java:141)     - Document font Wingdings is not mapped to a physical font!
06-07 - 11:06:24 ERROR [http-bio-8085-exec-48] (Conversion.java:141)     - Document font Arial Rounded MT Bold is not mapped to a physical font!
06-07 - 11:06:24 ERROR [http-bio-8085-exec-48] (Conversion.java:141)     - Document font Times New Roman is not mapped to a physical font!
06-07 - 11:06:24 ERROR [http-bio-8085-exec-48] (Conversion.java:141)     - Document font Symbol is not mapped to a physical font!
06-07 - 11:06:24 ERROR [http-bio-8085-exec-48] (Conversion.java:141)     - Document font Courier New is not mapped to a physical font!
06-07 - 11:06:24 ERROR [http-bio-8085-exec-48] (Conversion.java:141)     - Document font Verdana is not mapped to a physical font!


According to the "Getting started" documentation, there's 3 solutions to make sure these errors do not appear:

Word's font substitution information is not available to docx4j. As a developer, you 3 options:

- ensure the font is installed or embedded
- tell docx4j which font to use instead, or
- allow docx4j to fallback to a default font


As I'd like our web application to be portable and independent of the fonts installed on the system where it is deployed, my preferred option is to embed the fonts in the document. I've tried this (using Office 2010's options for saving the document) and although my file is clearly larger and has the fonts embedded, the conversion still logs the errors above. I've tried using both the IdentityPlusMapper and BestMatchingMapper to no avail.

Here's the code I'm currently using:

Code: Select all
      Mapper fontMapper = new IdentityPlusMapper();
      // Mapper fontMapper = new BestMatchingMapper();
      try {
         wordprocessingMLPackage.setFontMapper(fontMapper);
      } catch (Exception e) {
         throw new WordIntegrationPdfGenerationException(
            "Error setting font mapper while preparing to write to PDF", e);
      }

      PdfConversion c = new Conversion(wordprocessingMLPackage);

      OutputStream os = null;
      PdfSettings pdfSettings = new PdfSettings();
      pdfSettings.setImageHandler(new LocalPdfConversionImageHandler());
      try {
         try {
            c.output(output, pdfSettings);
         } catch (Docx4JException e) {
            throw new WordIntegrationPdfGenerationException("Error generating PDF", e);
         }
      } finally {
         ((LocalPdfConversionImageHandler) pdfSettings.getImageHandler()).cleanUp();
         if (os != null) {
            try {
               os.close();
            } catch (IOException e) {
               LOGGER.info("Problems while closing stream");
            }
         }
      }


I haven't found any clue in the forum as to whether it's necessary to configure this or do something extra for this to work. Is there?

Thanks in advance for your help!

Re: Embedded fonts not used in PDF conversion?

PostPosted: Mon Jul 09, 2012 11:47 pm
by jason
Embedded fonts are handled by ObfuscatedFontPart.

When deObfuscate is called, they are written to ~/.docx4all/temporary embedded fonts (this should probably be configurable via docx4j.properties)

That is called from FontTablePart:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
    private void getObfuscatedFontFromRelationship(String fontName, FontRel fontRel) {
   
        if (fontRel == null) {
                //log.debug("fontRel not found for '" + fontName + "'");
                return;
        }
       
        String id = fontRel.getId();           
        String fontKey = fontRel.getFontKey();
                 
        ObfuscatedFontPart obfuscatedFont = (ObfuscatedFontPart)this.getRelationshipsPart().getPart(id);
        if (obfuscatedFont != null) {
                obfuscatedFont.deObfuscate(fontName, fontKey);
        } else {
                log.error("Couldn't find ObfuscatedFontPart with id: " + id);
        }
    }

 
Parsed in 0.015 seconds, using GeSHi 1.0.8.4


so with a bit of luck, all that is required is to ensure the font mapper reads the relevant dir.

PhysicalFonts contains:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
        // Add fonts from our Temporary Embedded Fonts dir
        fontFileList = fontFileFinder.find( ObfuscatedFontPart.getTemporaryEmbeddedFontsDir() );
        for (Iterator iter = fontFileList.iterator(); iter.hasNext();) {
            URL fontUrl = getURL(iter.next());
            addPhysicalFont( fontUrl);
        }
 
Parsed in 0.014 seconds, using GeSHi 1.0.8.4


so that much should be working.

Could you please turn logging up on FontTablePart and on org.docx4j.fonts so we can see what is happening?

Re: Embedded fonts not used in PDF conversion?

PostPosted: Tue Jul 10, 2012 8:39 am
by jason
Two further thoughts.

First, that code I mentioned in PhysicalFonts is called from font mapper's static initializer, so if you are processing multiple documents, you'll need to invoke that code yourself (copy it into your own method).

Second, the font must have isEmbeddable() true. We'll see whether this is the case once you have log level warn set.