Creating DOCX Files


v4.0.19 introduces support for creating OOXML (DOCX) files from HTML.

It is already functionally superior to the long-standing PD4ML HTML to RTF converter. It allows you to define text and paragraph styles, nested tables, ordered and unordered lists, headers and footers, table of contents, hyperlinks, bookmarks, borders, backgrounds, and embed images.

To force DOCX output you only need to trigger pd4ml.writeDOCX() API method instead of pd4ml.writePDF() in usual conversion scenarios.

The converter is available under the PD4ML DMS or PD4ML UA license.

Read more: https://pd4ml.com/creation-of-ooxml-docx-documents/

PD4ML Fonts Tool


To simplify the creation of font mapping files, PD4ML v4.0.16 introduces a handy tool. The tool is implemented as an utility of the interactive PD4ML Converter

How to use it

Run the converter, as described by the link /support-topics/pd4ml-v4-programmers-manual/ and click the [Fonts Tool] button on the status bar of the application window.

It will prompt you for the location of the font directory. Select a directory. We can start with system fonts like C:\Windows\Fonts

Because the system font directory contains an excessive number of fonts that your application doesn’t really need, you can filter them out by entering a comma-separated list of font name patterns in the input field next to the “Filter by Font File Name” button. Apply the filter by pressing the button. The resulting list will include only those fonts whose filenames case-insensitively match the given patterns.

The generated list is editable, so you can manually refine it.

At this point you have four options:

  • Close – is obvious: close the tool and lose the current font mapping configuration
  • Use – use the font configuration only in the current session of the PD4ML Converter, without saving it.
  • Save Mapping File – creates a pd4fonts.properties file that can later be referenced from your application with pd4ml.useTTF() API call. If the chosen mapping file location is different from the original font directory (which is a good idea if you are using the system font directory), pd4fonts.properties will include a link to the font dir, allowing PD4ML to find the actual font files.
  • Save as JAR – packages the listed fonts and the corresponding pd4fonts.properties into a JAR file. Fonts are stored in the “pdffonts” JAR subdirectory by default, so once the JAR is deployed with a PD4ML-enabled application, the font configuration can be referenced with pd4ml.useTTF("java:pdffonts") API call. The subdirectory name can be customized by uncommenting and setting the jar.folder=pdffonts property.

Apache Batik SVG plugin control


PD4ML implements its own basic SVG renderer, and also allows you to use third-party libraries for the task. If it finds Apache Batik SVG Toolkit among the available libraries, it will automatically switch to it.

Batik tries to implement most of the features of SVG. But, unfortunately, it is very sensitive to even minor file format errors, and there is no way to change its error policy: it always throws exceptions, and there is no switch to turn them into warnings, for example.

In such cases, the best workaround would be to disable Batik and let the built-in SVG engine do the rendering.

Java code to disable Batik:

com.pd4ml.plugins.BatikSvgCustomTag.disable = true;

Disable in pd4browser.properties:

svg.batik=false

CSS Flexible Box Layout support added


PD4ML v4.0.6 introduces flexbox layout support.

Children of a flex container can “flex” their sizes, either growing to fill unused space or shrinking to avoid overflowing the parent. Both horizontal and vertical alignment of the children is supported.

Automatic Font Kerning Support


PD4ML v4.0.4 introduces optional font kerning support. Kerning is an addition or reduction of space between two characters (glyphs) of a proportional font. As a rule a rendered text is visually much more pleasing when the kerning is applied.

PD4ML uses kerning pairs info from TTF/OTF fonts (if available). For the standard built-in Type1 fonts the kerning info is known and included to PD4ML product itself.

The feature is also implemented in our older development branch v3.11.0 due to its importance

Creating high quality accessible PDF/UA documents


One of the major reasons to migrate to PD4ML v4 API is the support of the PDF/UA standard (Universal Accessibility).

PDF/UA standard is to let people with disabilities access PDF information in an efficient manner without assistance from others and be able to receive the same value from the content as others. PDF/UA does not add any new features to the PDF file format, but makes some aspects required which are optional in a regular PDF.

A lot of the requirements, like fonts embedding, were implicitly fulfilled even by older versions of PD4ML. But the major ones are covered only starting from PD4ML v4 – thanks to the new product architecture, which has been designed bearing in mind PDF/UA conformance.

PDF/UA requirements
  • PDF/UA document must be tagged. It must include information regarding the nesting and relationship of different types of structure elements. It is probably the most annoying task to fulfill if you create PDF/UA using WYSIWYG tools from scratch or do manual PDF post-processing to achieve PDF/UA conformance. With PD4ML the task is trivial: a document structure comes from input HTML and can be perfectly automatically transformed to PDF tags.
  • The document structure elements must have alternative descriptions. PD4ML uses for that a content specified by TITLE and ALT attributes of HTML tags. It is also a good idea to specify LANG attribute if the content not in English.
  • PDF/UA document must be supplied with XML metadata. PD4ML generates it for you from known document/environment info. Make sure your input HTML document specifies <title>, <meta name="description" content="document subject">, <meta name="author" content="author name">, <meta name="keywords" content="comma-delimited list of keywords"> etc.
Enabling PDF/UA output

First you need to obtain PD4ML UA license with a license code. See the documentation.

Without the license code (or with a code of PD4ML license type, which does not enable PDF/UA feature) it still going to generate PDF/UA documents, but watermarked with “Evaluation” banner.

The next step is straightforward: invoke writePDF() method with PDFUA parameter.

PD4ML pd4ml = new PD4ML();

// important! PDF/UA requires TTF fonts to be embedded
// "arial,times,courier" is a comma-delimited list of font file name patterns to use
pd4ml.useTTF("c:/Windows/Fonts/", "arial,times,courier");

String html = "<html>\n" + 
		"<head>\n" + 
		"<title>PDF/UA Test</title>\n" + 
		"<meta name=\"description\" content=\"Document Subject\" />\n" + 
		"<meta name=\"author\" content=\"Max Mustermann\" />\n" + 
		"</head>\n" + 
		"<body lang=\"DE-de\">\n" + 
		"<div title=\"PDF/UA test content\">Prüfung auf PDF/UA-Konformität</div>\n" + 
		"</body>\n" + 
		"</html>";

ByteArrayInputStream bais =
        new ByteArrayInputStream(html.getBytes());

// read and parse HTML
pd4ml.readHTML(bais);

File pdf = File.createTempFile("result", ".pdf");
FileOutputStream fos = new FileOutputStream(pdf);

// render and write the result as PDF
pd4ml.writePDF(fos, Constants.PDFUA);

// open the just-generated PDF with a default PDF viewer
Desktop.getDesktop().open(pdf);

If you run PD4ML as a standalone command line tool, you may force it to output PDF/UA with -outformat pdfua parameter.

In both cases do not forget to point PD4ML to a folder with indexed TTF/OTF fonts using pd4ml.useTTF(fontDir) API call or -ttf <ttf_fonts_dir> command line parameter.

PDF/UA validation

After PDF document is generated, it is a good idea to validate it for PDF/UA conformity. PD4ML did the best, but there are some aspects, that cannot be fully automated (e.g. providing of alternative descriptions).

There is a variety of PDF and PDF/UA validator tools. Our choice is free Free PDF Accessibility Checker (PAC 3)

The PAC3 tool creates detailed validation reports, allows to browse the document structure to the problem elements and highlight them in the rendered content. However error messages can be not always clear. With some practice and collected validation experience their meaning becomes less confusing.

Alternatively you may use Preflight included to Adobe Acrobat Pro or diverse online validator applications (e.g. 3-HEIGHTS™ PDF VALIDATOR ONLINE TOOL). The tools are also great, but comparing to PAC3, they are mostly focused not on accessibility issues, but on technical/syntax aspects of PDF code (which should be not your, but our concern).

Most typical validation errors
  1. Despite the message, the real validation error reason is a missing of <thead> section in a table. Add missing <thead> section to suppress the message. PD4ML creates an implicit <thead> section if leading table rows contain <th> cells only.
  2. The message is clear: in PDF/UA you are not allowed to nest, let’s say, <h4> heading to <h2>, which happens quite often in real life HTML documents.

RTF Output Performance


The recent PD4ML builds (both v3 and v4) refactor RTF output logic to improve conversion performance by bulky input HTML documents.

Now, even in extreme situations, the performance is comparable with PDF output and very often outperforms it.

 

 

 

 

 

 

 

 

Creating PDF documents from IBM Notes with PD4ML


v3.x.x v4.1.0

PD4ML can be used to convert IBM Notes documents to PDF (as well as to RTF or to a raster image) a variety of ways.

The most straightforward method is to capture HTML documents, returned by Notes Domino via HTTP: an URL like one of the following is to be passed to render() method of PD4ML.

http://Host/Database/PageUNID?OpenPage
(i.e. http://www.acme.com/discussion.nsf/35AE8FBFA573336A852563D100741784?OpenPage)

http://Host/Database/View/DocumentUniversalID?OpenDocument
(http://www.acme.com/leads.nsf/By+Rep/35AE8FBFA573336A852563D100741784?OpenDocument)

http://Host/Database/FormUniversalID?ReadForm
(http://www.acme.com/products.nsf/625E6111C597A11B852563DD00724CC2?ReadForm)

More IBM Notes URL syntax info…

If you run JSP infrastructure on IBM Domino server, another online method of PDF generation would be to use PD4ML JSP custom tag library (TODO).

If an online document generation method (involving HTTP, JSP etc) is undesired, there is a possibility to generate PDF documents from their XML representations (so called DXL).

DXL is an adaptation of XML used to describe, in detail, the structure and data contained in a Domino database. It describes data and design elements such as views, forms, and documents and provides a basis for importing or exporting XML representations of data to and from a Domino/Notes application.

Schematically a process of Notes document conversion to PDF can be seen like that:

All conversion steps can be implemented at once as a IBM Lotus Notes Java agent, or can be implemented as two-step batch: DXL export request followed by a conversion with Pd4Cmd command-line tool

java -Djava.awt.headless=true -Xmx512m -jar pd4ml.jar test.dxl 1200 -xsl notesdefault

The command line overrides the default Java memory heap size limit with -Xmx512m. Here it is set to 512Mb.

On UNIX platform -Djava.awt.headless=true allows to run the application on non-graphics-enabled servers or from remote ssh/telnet sessions.

test.dxl 1200 are DXL location and htmlWidth (virtual “browser” frame width) parameters.

On Win32 the path is enclosed, if needed, to double quotes, on UNIX – to single quotes.

-xsl notesdefault applies XSL stylesheet to the input document. In the case it refers to the built-in default DXL-to-HTML XSL, but it can be an URI of an arbitrary external stylesheet.

The default PDF document format: A4 / PORTRAIT

In the example 1200px width of rendered document will be mapped to 595pt widths of A4 page format.

As long as an output file path omitted, the output is sent to STDOUTand can be piped to another application.

See more command line arguments…
PD4ML as Notes Agent…

PD4ML Integration with Macromedia® ColdFusion®


1. Integration of PD4ML with ColdFusion MX 6 Professional or ColdFusion MX 6 Development edition running on JRun 4

Please follow the link to the corresponding section in the Reference manual.

2. Integration of PD4ML with ColdFusion Standard edition

Unfortunately not all runtime modes of ColdFusion allow to use JSP tag libraries. In that case the only way to
integrate PD4ML is to use PD4ML Java API.

The following is the integration example .cfm contributed by David REYNAUD:

<html>
<head>
<title>PD4ML under CFMX 6.x Std Edition</title>
</head>
 
<body>
<!---
BEFORE RUNNING :
       Idea 1 :
             put the JAR file : pd4ml_demo.jar
             in the same folder as current CFM page
       Idea 2 :
             maybe you can put the JAR file : pd4ml_demo.jar
             into the ColfdFusion's CustomTags directory
       Idea 3 :
             use the ColdFusion Admin to configure classpath to use the jar
--->
<cfscript>
       // The source file to convert  (http:// or file:)
       inURI="file:n:/web/tests/pd4ml/test.html";
       // The pdf file to generate (full pathname)
       fileOut="n:/web/tests/pd4ml/test.pdf";
      
       unnitsvalue="mm";  // Millimeters
       // A4 'vertical' in mm
       format = createObject("java","java.awt.Dimension").init(210,297);
       topValue = 10;     // mm
       leftValue = 10;    // mm
       rightValue = 10;   // mm
       bottomValue = 10;  // mm
       landscapevalue="yes";
      
       userSpaceWidth=780; // px
       splitValue=0;
       patchValue=1;
 
       authorName="";
 
       // PD4ML Object instantiation
       pd4ml = createObject("java","org.zefer.pd4ml.PD4ML");
      
       // Format, orientation, insets
       if (landscapeValue) format = pd4ml.changePageOrientation(format);
       insets = createObject("java","java.awt.Insets")
.init(topValue,leftValue,bottomValue,rightValue);
       if (unnitsvalue EQ "mm") {
              pd4ml.setPageSizeMM(format);
             pd4ml.setPageInsetsMM(insets);
} else {
             pd4ml.setPageSize(format);
             pd4ml.setPageInsets(insets);
       }
      
       if(authorName NEQ "")
pd4ml.setAuthorName(authorname);
      
       if (userSpaceWidth NEQ "") pd4ml.setHtmlWidth( userSpaceWidth );
       pd4ml.enableImgSplit( splitValue );
       pd4ml.enableRenderingPatch( patchValue );
 
       fos = createObject("java","java.io.FileOutputStream").init(fileOut);
       pd4ml.render(inURI,fos); // Start rendering
 
</cfscript>
<cfoutput>File '#inURI#' converted to '#fileOut#'</cfoutput>
</body>
</html>