> For the complete documentation index, see [llms.txt](https://docs.pd4ml.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pd4ml.com/legacy/pd4ml-v3-programmers-manual-legacy.md).

# PD4ML v3 Programmer's Manual (Legacy)

{% hint style="warning" %}
**Legacy reference.** This page preserves PD4ML's original v3-era programmer's manual, describing the classic `org.zefer.pd4ml.PD4ML` API. That API is not dead code: it still ships today as a backward-compatibility wrapper around the current v4 engine (`com.pd4ml.PD4ML`), so an existing v3 integration keeps working unchanged on a current PD4ML build. New projects should start from the current [PD4ML Programmer's Manual](https://docs.pd4ml.com/) instead, and an existing v3 codebase considering a move onto the modern API surface should read the [PD4ML v3 to v4 Migration Guide](/legacy/pd4ml-v3-to-v4-migration-guide.md). Notes marked **Current (v4)** below call out where the underlying mechanics have since changed.
{% endhint %}

## 1. Basics

PD4ML v3 shipped in two variants: **Standard**, covering core HTML/CSS-to-PDF conversion, and **Professional**, adding TrueType font embedding, HTML (not just text) headers/footers, image watermarks, an auto-generated table of contents, and PDF/A output. Which one a given build behaved as was determined by the license key in effect, checked at runtime by the library itself.

The Java API additionally required the (patched) open-source [CSS Parser](https://cssparser.sourceforge.net/) library, `ss_css2.jar`, on the classpath alongside `pd4ml.jar` -- PD4ML delegated CSS tokenizing to it rather than shipping its own parser.

Core document-level features -- page size/format, running headers and footers, page backgrounds, watermarks, and password/permission protection -- were all available in both variants and are covered with code samples below.

{% hint style="info" %}
**Current (v4):** the Standard/Professional split and the separate `ss_css2.jar` dependency are both gone. A current PD4ML build is a single jar with its own built-in CSS engine; which features are unlocked is governed entirely by the activation license installed (`pd4ml.lic`), not by which jar you happened to download. See the [PD4ML v3 to v4 Migration Guide](/legacy/pd4ml-v3-to-v4-migration-guide.md)'s Activation section (§1).
{% endhint %}

## 2. Installation Methods

### 2.1 Standalone Application

`org.zefer.pd4ml.tools.PD4Browser` doubled as both a GUI HTML-to-PDF converter and a command-line tool:

```
java -jar pd4ml.jar -gui
java -jar pd4ml.jar https://example.com/report.html report.pdf
```

### 2.2 Java API

Include both `pd4ml.jar` and `ss_css2.jar` on the classpath, then drive conversion through `org.zefer.pd4ml.PD4ML`:

```java
import org.zefer.pd4ml.PD4ML;

PD4ML pd4ml = new PD4ML();
pd4ml.render(new java.net.URL("https://example.com/report.html"), new java.io.FileOutputStream("report.pdf"));
```

### 2.3 JSP Integration

Deploying into a servlet container required registering PD4ML's taglib descriptor (bundled inside `pd4ml.jar`) and declaring it in the JSP:

```jsp
<%@ taglib uri="https://pd4ml.com/tlds/3.0" prefix="pd4ml"%>
<pd4ml:transform screenWidth="600" pageFormat="A4">
<html>
<body>Hello, World!</body>
</html>
</pd4ml:transform>
```

{% hint style="info" %}
**Current (v4):** the taglib is no longer a separate concern layered on top of `pd4ml.jar` -- it's built into the main library. The recommended tag prefix also changed from `pd4ml:` to `pd4tl:`, freeing `pd4ml:` to refer unambiguously to PD4ML's own content tags (`<pd4ml:page.break>` and similar) within the same page. See the [PD4ML v3 to v4 Migration Guide](/legacy/pd4ml-v3-to-v4-migration-guide.md)'s JSP Taglib section (§5).
{% endhint %}

## 3. HTML Conversion Examples

**Converting a URL to PDF, through a proxy:**

```java
import org.zefer.pd4ml.PD4ML;
import org.zefer.pd4ml.PD4Constants;
import java.util.HashMap;
import java.util.Map;

PD4ML pd4ml = new PD4ML();
Map params = new HashMap();
params.put(PD4Constants.PD4ML_HTTP_PROXY, "proxy.example.com:8080");
pd4ml.setDynamicParams(params);
pd4ml.render(new java.net.URL("https://example.com/report.html"),
             new java.io.FileOutputStream("report.pdf"));
```

See [Configuring an HTTP Proxy](/features/configuring-an-http-proxy.md) for the current v4 equivalents, including the simpler `setHttpOptions(...)` call.

**Converting HTML from an input stream, with a base URL for relative resources:**

```java
import org.zefer.pd4ml.PD4ML;
import java.io.*;

PD4ML pd4ml = new PD4ML();
StringReader reader = new StringReader("<html><body><h1>Report</h1></body></html>");
pd4ml.render(reader, new FileOutputStream("report.pdf"), new java.net.URL("https://example.com/"));
```

**Text-based header/footer with a template:**

```java
import org.zefer.pd4ml.PD4ML;
import org.zefer.pd4ml.PD4PageMark;

PD4PageMark footer = new PD4PageMark() {
    public String getHtmlTemplate(int pageNumber) {
        return "<html><body>Page $[page] of $[total]";
    }
};
footer.setAreaHeight(30);
pd4ml.setPageFooter(footer);
```

**Document encryption (40-bit or 128-bit):**

```java
import org.zefer.pd4ml.PD4ML;
import org.zefer.pd4ml.PD4Constants;

pd4ml.setPermissions("ownerPassword", PD4Constants.PRINT_PERMISSION, true); // true = 128-bit AES
pd4ml.setPermissions("ownerPassword", PD4Constants.PRINT_PERMISSION, false); // false = 40-bit RC4
```

## 4. Advanced Features

**PDF Bookmarks**, generated from HTML headings or named anchors:

```java
pd4ml.generateOutlines(true); // true = from headings, false = from <a name="..."> anchors
```

**Page Breaks**, inserted anywhere in the source markup:

```html
First page content
<pd4ml:page.break>
Second page content
```

**Web Integration:** beyond the plain JSP taglib shown in §2.3, the v3 manual documented working with **ColdFusion** (invoking PD4ML as a Java object via `CreateObject("java", "org.zefer.pd4ml.PD4ML")`) and a compatibility workaround for **Struts** applications, whose `ActionServlet` intercepted request dispatching in a way that needed an explicit forward through `org.zefer.pd4ml.tools.PD4ForwarderServlet` to reach PD4ML's own JSP taglib correctly.

## 5. Professional Edition Features

**TTF font embedding**, for Unicode and non-Latin scripts:

```java
pd4ml.useTTF("java:myfonts", true); // true = embed into the PDF
```

**HTML headers/footers** (not just plain text), via the same `PD4PageMark` mechanism as §3, with `getHtmlTemplate()` returning markup instead of plain text.

**Watermark images**, with opacity control, set on the header/footer mark:

```java
import java.awt.Rectangle;

PD4PageMark mark = new PD4PageMark() { public String getHtmlTemplate(int p) { return ""; } };
mark.setWatermarkUrl("file:///path/to/watermark.png");
mark.setWatermarkBounds(new Rectangle(50, 50, 300, 300));
mark.setWatermarkOpacity(30); // percent
```

**Table of Contents**, auto-generated from document structure -- enabled via the same `generateOutlines(true)` call as PDF bookmarks, or with a dedicated `<pd4ml:toc>` tag placed in the source HTML.

**PDF/A support**, for long-term archival compliance:

```java
pd4ml.generatePdfa(true);
```

## 6. Configuration Details

Embedding TrueType fonts required a `pd4fonts.properties` mapping file, associating logical font family names with the `.ttf` files that back them. It could be generated by pointing the standalone tool at a directory of fonts:

```
java -jar pd4ml.jar -configure.fonts /path/to/fonts [pd4fonts.properties location]
```

{% hint style="info" %}
**Current (v4):** the `-configure.fonts` flag and its output format are unchanged -- see the [Pd4Cmd Command-Line Reference](/pd4cmd-command-line-reference.md) for the current invocation and the full set of `pd4fonts.properties` options.
{% endhint %}

## 7. Best Practices

`<style>` blocks were expected to reside in the document `<head>`, matching the general HTML recommendation rather than any PD4ML-specific requirement. The original manual also listed several HTML authoring restrictions to avoid with PD4ML v2.x -- most of these were already noted as obsolete by v3.x and no longer apply to any currently supported PD4ML release.

## Technical Requirements

* JDK 1.3.1 minimum for the Standard edition; JDK 1.4.2 or later for Professional-edition features (TTF embedding in particular relied on APIs not present in 1.3.1).
* The CSS Parser open-source library (`ss_css2.jar`), patched, bundled alongside `pd4ml.jar`.
* HTTP/proxy-aware resource loading for remote images, stylesheets, and linked documents.

## See Also

* [PD4ML Programmer's Manual](https://docs.pd4ml.com/) -- the current v4 API manual.
* [PD4ML v3 to v4 Migration Guide](/legacy/pd4ml-v3-to-v4-migration-guide.md) -- full method-by-method correspondence table.
* [Pd4Cmd Command-Line Reference](/pd4cmd-command-line-reference.md) -- the current standalone tool, successor to `PD4Browser`.
* [Using PD4ML with Apache Maven](/features/using-pd4ml-with-apache-maven.md) -- current dependency coordinates (no separate CSS Parser artifact needed).
* [Configuring an HTTP Proxy](/features/configuring-an-http-proxy.md) -- v3 vs. v4 proxy configuration side by side.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.pd4ml.com/legacy/pd4ml-v3-programmers-manual-legacy.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
