---
product: Chilkat
product_version: 11.7.0
language: pascal
language_label: Lazarus Pascal
class: Pdf
license: bundle
deprecated: false
reference_html: https://www.chilkatsoft.com/refdoc/pascal_PdfRef.html
---
# Chilkat Pdf — Lazarus Pascal — v11.7.0

> Chilkat 11.7.0 · language=pascal · class=Pdf
> Other versions: replace `11.7.0` in this URL. Other languages: `https://www.chilkatsoft.com/ai-docs/v/11.7.0/<lang>/classes/Pdf.md`.
> Language-wide rules (install, unlock, error model, strings/bytes): `https://www.chilkatsoft.com/ai-docs/v/11.7.0/pascal/guide.md`.

## Purpose

PDF Signing, Metadata, and Attachments

**Work with PDF signatures, embedded files, metadata, and LTV information**

`Chilkat.Pdf` provides PDF operations focused on digital signatures, embedded files, metadata, signature verification, and long-term validation support. It can load PDFs from files or memory, inspect page, signature, and attachment counts, sign PDFs with visible or invisible signatures, verify existing signatures, retrieve signer certificates, and manage DSS/LTV verification information.

**Digital signatures** Sign, certify, countersign, timestamp, and verify PDF signatures.

**Embedded files** Add attachments to PDFs or extract existing embedded files.

**Metadata** Read, update, or insert XMP metadata in an existing PDF.

**LTV and DSS** Inspect or add certificates, OCSP responses, and CRL information.

The class is commonly used for PDF signing workflows, PDF/A-3-style embedded-file scenarios, signature validation, and adding long-term validation material after signing.

For an extended overview, see [Pdf Class Overview](https://www.chilkatsoft.com/pdf_class_overview.asp).

## Object creation, unlocking and error handling

**Create / Free**

```pascal
uses
  Chilkat.Pdf;

var
  obj: TPdf;
begin
  obj := TPdf.Create;
  try
    if not obj.IsValid then
      raise Exception.Create('Failed to create a TPdf instance.');

    // ... use obj ...

  finally
    obj.Free;
  end;
end;
```

`constructor Create;`

Allocates the underlying CkPdf object and returns a new TPdf instance. Simply adding **Chilkat.Pdf** to the unit's `uses` clause is enough to locate and bind to the Chilkat shared library (DLL / .so / .dylib) at runtime — no separate load step is required. Check `obj.IsValid` after calling `Create`; it is `False` if the underlying library could not be found/loaded or the object could not be allocated (for example, when unlicensed).

`destructor Destroy; override;`

Every TPdf created by calling `Create` should eventually be released by calling `.Free` (inherited from `TObject`). The destructor automatically disposes the underlying CkPdf handle. A native (unmanaged) memory leak occurs if the object is never freed.

Call `Global.UnlockBundle` once at the start of the program, before using this or any other Chilkat class. Any string unlocks a fully functional 30-day trial; a purchased unlock code is used in production. See `guide.md` for the exact code in Lazarus Pascal.

## Members common to every Chilkat class

Documented once per language in `common-members.md`; listed here so this page is self-contained.

| Property | Signature | Access | Meaning |
|---|---|---|---|
| `DebugLogFilePath` | `property DebugLogFilePath: string read GetDebugLogFilePath write SetDebugLogFilePath;` | read/write | If set to a file path, this property logs the LastErrorText of each Chilkat method or property call to the specified file. |
| `LastErrorHtml` | `property LastErrorHtml: string read GetLastErrorHtml;` | read-only | Provides HTML-formatted information about the last called method or property. |
| `LastErrorText` | `property LastErrorText: string read GetLastErrorText;` | read-only | Provides plain text information about the last called method or property. |
| `LastErrorXml` | `property LastErrorXml: string read GetLastErrorXml;` | read-only | Provides XML-formatted information about the last called method or property. |
| `LastMethodSuccess` | `property LastMethodSuccess: Boolean read GetLastMethodSuccess write SetLastMethodSuccess;` | read/write | Indicates the success or failure of the most recent method call: `True` means success, `False` means failure. |
| `VerboseLogging` | `property VerboseLogging: Boolean read GetVerboseLogging write SetVerboseLogging;` | read/write | If set to `True`, then the contents of LastErrorText (or LastErrorXml, or LastErrorHtml) may contain more verbose information. |
| `Version` | `property Version: string read GetVersion;` | read-only | Version of the component/library, such as "10.1.0" |

## Member index

| Member | Kind | Signature |
|---|---|---|
| `HasCertificationSig` | property, read-only | `property HasCertificationSig: Boolean read GetHasCertificationSig;` |
| `NumEmbeddedFiles` | property, read-only | `property NumEmbeddedFiles: Integer read GetNumEmbeddedFiles;` |
| `NumPages` | property, read-only | `property NumPages: Integer read GetNumPages;` |
| `NumSignatures` | property, read-only | `property NumSignatures: Integer read GetNumSignatures;` |
| `OwnerPassword` | property, read/write | `property OwnerPassword: string read GetOwnerPassword write SetOwnerPassword;` |
| `PreserveSignatures` | property, read/write | `property PreserveSignatures: Boolean read GetPreserveSignatures write SetPreserveSignatures;` |
| `SigAllocateSize` | property, read/write | `property SigAllocateSize: Integer read GetSigAllocateSize write SetSigAllocateSize;` |
| `UncommonOptions` | property, read/write | `property UncommonOptions: string read GetUncommonOptions write SetUncommonOptions;` |
| `UserPassword` | property, read/write | `property UserPassword: string read GetUserPassword write SetUserPassword;` |
| `AddEmbeddedFiles` | method | `// json is a TJsonObject object. function AddEmbeddedFiles(json: TChilkatBase;     const outFilePath: string): Boolean;` |
| `AddEmbeddedFiles2` | method | `// json is a TJsonObject object. function AddEmbeddedFiles2(json: TChilkatBase): Boolean;` |
| `AddEmbeddedFilesBd` | method | `// json is a TJsonObject object. // bd is a TBinData object. function AddEmbeddedFilesBd(json: TChilkatBase;     bd: TChilkatBase): Boolean;` |
| `AddEncryptCert` | method | `// cert is a TCert object. function AddEncryptCert(cert: TChilkatBase): Boolean;` |
| `AddSigningCert` | method | `// cert is a TCert object. function AddSigningCert(cert: TChilkatBase): Boolean;` |
| `AddVerificationInfo` | method | `// jsonOptions is a TJsonObject object. function AddVerificationInfo(jsonOptions: TChilkatBase;     const outFilePath: string): Boolean;` |
| `AddVerificationInfo2` | method | `// jsonOptions is a TJsonObject object. function AddVerificationInfo2(jsonOptions: TChilkatBase): Boolean;` |
| `ClearEncryptCerts` | method | `procedure ClearEncryptCerts;` |
| `ExtractText` | method | `// jsonIn is a TJsonObject object. // jsonOut is a TJsonObject object. function ExtractText(const op: string;     jsonIn: TChilkatBase;     jsonOut: TChilkatBase): Boolean;` |
| `ExtractTextSb` | method | `// jsonIn is a TJsonObject object. // sbOut is a TStringBuilder object. // jsonOut is a TJsonObject object. function ExtractTextSb(const op: string;     jsonIn: TChilkatBase;     sbOut: TChilkatBase;     jsonOut: TChilkatBase): Boolean;` |
| `GetDss` | method | `// json is a TJsonObject object. function GetDss(json: TChilkatBase): Boolean;` |
| `GetEmbeddedFileBd` | method | `// bd is a TBinData object. function GetEmbeddedFileBd(index: Integer;     bd: TChilkatBase): Boolean;` |
| `GetEmbeddedFileInfo` | method | `// json is a TJsonObject object. function GetEmbeddedFileInfo(index: Integer;     json: TChilkatBase): Boolean;` |
| `GetLastJsonData` | method | `// json is a TJsonObject object. procedure GetLastJsonData(json: TChilkatBase);` |
| `GetMetadata` | method | `// sb is a TStringBuilder object. function GetMetadata(sb: TChilkatBase): Boolean;` |
| `GetSignatureContent` | method | `// bd is a TBinData object. function GetSignatureContent(index: Integer;     bd: TChilkatBase): Boolean;` |
| `GetSignerCert` | method | `// cert is a TCert object. function GetSignerCert(index: Integer;     cert: TChilkatBase): Boolean;` |
| `GetUnsignedSigFields` | method | `// json is a TJsonObject object. function GetUnsignedSigFields(json: TChilkatBase): Boolean;` |
| `LoadBd` | method | `// pdfData is a TBinData object. function LoadBd(pdfData: TChilkatBase): Boolean;` |
| `LoadFile` | method | `function LoadFile(const filePath: string): Boolean;` |
| `Optimize` | method | `// jsonIn is a TJsonObject object. // jsonOut is a TJsonObject object. function Optimize(const op: string;     jsonIn: TChilkatBase;     jsonOut: TChilkatBase): Boolean;` |
| `PreLoadCheck` | method | `// jsonOut is a TJsonObject object. function PreLoadCheck(const path: string;     jsonOut: TChilkatBase): Boolean;` |
| `PreLoadCheckBd` | method | `// bd is a TBinData object. // jsonOut is a TJsonObject object. function PreLoadCheckBd(bd: TChilkatBase;     jsonOut: TChilkatBase): Boolean;` |
| `Protection` | method | `// jsonIn is a TJsonObject object. // jsonOut is a TJsonObject object. function Protection(const op: string;     jsonIn: TChilkatBase;     jsonOut: TChilkatBase): Boolean;` |
| `SetDecryptCert` | method | `// cert is a TCert object. function SetDecryptCert(cert: TChilkatBase): Boolean;` |
| `SetHttpObj` | method | `// http is a THttp object. procedure SetHttpObj(http: TChilkatBase);` |
| `SetSignatureJpeg` | method | `// jpgData is a TBinData object. function SetSignatureJpeg(jpgData: TChilkatBase): Boolean;` |
| `SetSigningCert` | method | `// cert is a TCert object. function SetSigningCert(cert: TChilkatBase): Boolean;` |
| `SetSigningCert2` | method | `// cert is a TCert object. // privateKey is a TPrivateKey object. function SetSigningCert2(cert: TChilkatBase;     privateKey: TChilkatBase): Boolean;` |
| `SignPdf` | method | `// jsonOptions is a TJsonObject object. function SignPdf(jsonOptions: TChilkatBase;     const outFilePath: string): Boolean;` |
| `SignPdf2` | method | `// jsonOptions is a TJsonObject object. function SignPdf2(jsonOptions: TChilkatBase): Boolean;` |
| `SignPdfBd` | method | `// jsonOptions is a TJsonObject object. // bd is a TBinData object. function SignPdfBd(jsonOptions: TChilkatBase;     bd: TChilkatBase): Boolean;` |
| `TextReplace` | method | `// jsonIn is a TJsonObject object. // jsonOut is a TJsonObject object. function TextReplace(const op: string;     jsonIn: TChilkatBase;     jsonOut: TChilkatBase): Boolean;` |
| `UpdateMetadata` | method | `// sb is a TStringBuilder object. function UpdateMetadata(sb: TChilkatBase;     const outFilePath: string): Boolean;` |
| `UpdateMetadata2` | method | `// sb is a TStringBuilder object. function UpdateMetadata2(sb: TChilkatBase): Boolean;` |
| `UpdateMetadataBd` | method | `// sb is a TStringBuilder object. // bd is a TBinData object. function UpdateMetadataBd(sb: TChilkatBase;     bd: TChilkatBase): Boolean;` |
| `VerifySignature` | method | `// sigInfo is a TJsonObject object. function VerifySignature(index: Integer;     sigInfo: TChilkatBase): Boolean;` |
| `Watermark` | method | `// jsonIn is a TJsonObject object. // jsonOut is a TJsonObject object. function Watermark(const op: string;     jsonIn: TChilkatBase;     jsonOut: TChilkatBase): Boolean;` |
| `WriteBd` | method | `// bd is a TBinData object. function WriteBd(bd: TChilkatBase): Boolean;` |
| `WriteFile` | method | `function WriteFile(const path: string): Boolean;` |

## Properties

### Pdf.HasCertificationSig

`Chilkat 11.7.0 · pascal · Pdf · HasCertificationSig · property · read-only · since 9.5.0.96`

```pascal
property HasCertificationSig: Boolean read GetHasCertificationSig;
```

Returns `True` if the currently open PDF has a certification signature.

PDF defines two types of signatures: **approval** and **certification**.

The differences are as follows:

- Approval: There can be any number of approval signatures in a document.
- Certification: There can be only one certification signature and it must be the first one in a document.

### Pdf.NumEmbeddedFiles

`Chilkat 11.7.0 · pascal · Pdf · NumEmbeddedFiles · property · read-only · since 9.5.0.95`

```pascal
property NumEmbeddedFiles: Integer read GetNumEmbeddedFiles;
```

The number of embedded files present in the currently open PDF.

### Pdf.NumPages

`Chilkat 11.7.0 · pascal · Pdf · NumPages · property · read-only · since 9.5.0.85`

```pascal
property NumPages: Integer read GetNumPages;
```

The number of pages in the currently open PDF.

### Pdf.NumSignatures

`Chilkat 11.7.0 · pascal · Pdf · NumSignatures · property · read-only · since 9.5.0.85`

```pascal
property NumSignatures: Integer read GetNumSignatures;
```

The number of digital signatures present in the currently open PDF.

### Pdf.OwnerPassword

`Chilkat 11.7.0 · pascal · Pdf · OwnerPassword · property · read/write · since 11.0.0`

```pascal
property OwnerPassword: string read GetOwnerPassword write SetOwnerPassword;
```

The PDF owner password, if required.

### Pdf.PreserveSignatures

`Chilkat 11.7.0 · pascal · Pdf · PreserveSignatures · property · read/write · since 11.7.0`

```pascal
property PreserveSignatures: Boolean read GetPreserveSignatures write SetPreserveSignatures;
```

Controls what Chilkat may do to a PDF that contains digital signatures. The default is `True`.

A signature covers the bytes of the file as they were when it was signed, so a PDF can only be changed afterwards by appending an incremental update that leaves those bytes untouched. Some changes cannot be made that way: rewriting page content (`TextReplace`, and most `Watermark` approaches), changing the encryption, passwords or permissions (`Protection`), and rewriting the file (`Optimize`). While this property is `True`, such operations are refused on a signed PDF and the reason is given in the LastErrorText; the operations that only append (adding a `Watermark` with the `annotation` approach, adding signatures, embedded files or metadata) remain available.

Set this property to `False` to allow any change, accepting that the existing signatures become invalid: the saved PDF is a full rewrite and viewers report the signatures as broken. The property is also read when the PDF is written: with it `False`, `WriteFile` and `WriteBd` may rewrite a signed PDF instead of appending to it.

### Pdf.SigAllocateSize

`Chilkat 11.7.0 · pascal · Pdf · SigAllocateSize · property · read/write · since 9.5.0.91`

```pascal
property SigAllocateSize: Integer read GetSigAllocateSize write SetSigAllocateSize;
```

Defaults to 15000. This property should generally be left unchanged. If signing fails and the following message is in the LastErrorText: `Did not allocate enough space for the PDF signature.`, then you should increase this value. The actual signature size will be noted in the LastErrorText, and you can use that value to set an allocation size that is somewhat larger.

### Pdf.UncommonOptions

`Chilkat 11.7.0 · pascal · Pdf · UncommonOptions · property · read/write · since 9.5.0.85`

```pascal
property UncommonOptions: string read GetUncommonOptions write SetUncommonOptions;
```

This is a catch-all property to be used for uncommon needs. This property defaults to the empty string. It can be set to a list of one or more of the following comma separated keywords:

- **WriteStandardXref** - When writing the PDF, write the cross reference section in standard format if possible. (The `standard format` is the older non-compressed format.)
- **NO_VERIFY_CERT_SIGNATURES** - When countersigning a PDF (i.e. adding a new signature to a PDF that already contains one or more signatures), Chilkat will automatically validate the existing signatures and their certificates. (The signing certificates are typically embedded within a signature.) If any of these validations fail, the new signature is not added. Sometimes, an existing signature is validated, but the certs in the chain of authentication, such as issuer certs or root CA certs, are not included and not available to check. In this case, you can add the `NO_VERIFY_CERT_SIGNATURES` to skip the existing signature certificate validations.
- **SIGN_IGNORE_PERMISSIONS** - (v11.7.0) Sign an encrypted PDF even when it was not opened with owner rights and its permissions do not allow the signature. Starting in v11.7.0 the signing methods refuse such a PDF (see `SignPdf`); this keyword restores the earlier behavior for applications that depend on it. It does not help with a PDF that could not be opened at all: that one cannot be signed.

### Pdf.UserPassword

`Chilkat 11.7.0 · pascal · Pdf · UserPassword · property · read/write · since 11.0.0`

```pascal
property UserPassword: string read GetUserPassword write SetUserPassword;
```

The PDF user password, if required.

## Methods

### Pdf.AddEmbeddedFiles

`Chilkat 11.7.0 · pascal · Pdf · AddEmbeddedFiles · method · since 9.5.0.97`

```pascal
// json is a TJsonObject object.

function  AddEmbeddedFiles(json: TChilkatBase;
    const outFilePath: string): Boolean;
```

Embeds one or more files in a PDF.

The `json` specifies the files to be attached to the PDF. See the linked example below.

The `json` is a JSON object containing an array of JSON objects, where each object can contain the following members.

- **localFilePath**: (required) The local file to be embedded in the PDF.
- **description**: (required) It is a short description of the embedded file.
- **subType**: (optional) Specifies the file type, such as application/xml, text/plain, etc. If not specified, then Chilkat will automatically choose a subType based on the file extension.
- **embeddedFilename**: (optional) Specifies the name of the file to be used within the PDF in the desire is for it to be different than the filename in the local filesystem. If not present, then the filename part of the localFilePath.
- **AFRelationship**: (optional starting in v11.1.0) Specifies specify the nature of the relationship of the embedded file. Possible values are `Source`, `Data`, `Alternative`, `Supplement`, and `Unspecified`. If unset, the default is `Alternative`.

If successful, the updated PDF with embedded files is written to `outFilePath`.

Returns True for success, False for failure.

### Pdf.AddEmbeddedFiles2

`Chilkat 11.7.0 · pascal · Pdf · AddEmbeddedFiles2 · method · since 11.7.0`

```pascal
// json is a TJsonObject object.

function  AddEmbeddedFiles2(json: TChilkatBase): Boolean;
```

The same as `AddEmbeddedFiles`, except that the updated PDF stays in memory instead of being written to a file. Call `WriteFile` or `WriteBd` to write it, or go on to other operations first: the embedded files are part of the loaded document as soon as this method returns, so `NumEmbeddedFiles` and `GetEmbeddedFileInfo` see them, and so do `Protection`, `Watermark`, `Optimize` and `SignPdf`.

Changes pending from other methods (a watermark added, a security change, an optimization, replaced text) are committed first, so the files are added to the document's current state; the embedded files themselves are added as an incremental update. See `AddEmbeddedFiles` for the members of `json`.

Returns True for success, False for failure.

### Pdf.AddEmbeddedFilesBd

`Chilkat 11.7.0 · pascal · Pdf · AddEmbeddedFilesBd · method · since 9.5.0.97`

```pascal
// json is a TJsonObject object.

// bd is a TBinData object.

function  AddEmbeddedFilesBd(json: TChilkatBase;
    bd: TChilkatBase): Boolean;
```

The same as AddEmbeddedFiles, but writes the resultant PDF to the `bd`.

Returns True for success, False for failure.

### Pdf.AddEncryptCert

`Chilkat 11.7.0 · pascal · Pdf · AddEncryptCert · method · since 11.7.0`

```pascal
// cert is a TCert object.

function  AddEncryptCert(cert: TChilkatBase): Boolean;
```

Adds a recipient certificate for certificate-based encryption. Call it once per recipient before calling `Protection` with the `encrypt` operation and `"method": "certificate"`; the PDF is then encrypted so that any one of the recipients can open it with the matching certificate and private key (see `SetDecryptCert`). Only the public certificate is needed here. The order of the calls matters: the nth certificate added corresponds to `recipientPermissions[n-1]` in the `Protection` options.

The certificates stay in effect for later `encrypt` operations until `ClearEncryptCerts` is called.

Returns True for success, False for failure.

### Pdf.AddSigningCert

`Chilkat 11.7.0 · pascal · Pdf · AddSigningCert · method · since 9.5.0.85`

```pascal
// cert is a TCert object.

function  AddSigningCert(cert: TChilkatBase): Boolean;
```

Adds a certificate to be used for PDF signing. To sign with more than one certificate, call AddSigningCert once per certificate.

**Note:** This method is used to provide the ability to sign once with multiple certificates. This is different than signing with one certificate, and then signing again with a different certificate.

Returns True for success, False for failure.

### Pdf.AddVerificationInfo

`Chilkat 11.7.0 · pascal · Pdf · AddVerificationInfo · method · since 9.5.0.93`

```pascal
// jsonOptions is a TJsonObject object.

function  AddVerificationInfo(jsonOptions: TChilkatBase;
    const outFilePath: string): Boolean;
```

Adds LTV verification information to the PDF, and saves the updated PDF to `outFilePath`. This create or update a DSS (Document Security Store) in the PDF with the needed certificates, OCSP responses, and CRL information.

Pass an empty `jsonOptions`. The `jsonOptions` exists as a placeholder for adding options if needed.

This object keeps its state from before the call; to add the verification information to the loaded document in place (and go on to other operations without reloading), use `AddVerificationInfo2`. Starting in v11.7.0, changes pending from other methods are committed before the verification information is added.

Returns True for success, False for failure.

### Pdf.AddVerificationInfo2

`Chilkat 11.7.0 · pascal · Pdf · AddVerificationInfo2 · method · since 11.7.0`

```pascal
// jsonOptions is a TJsonObject object.

function  AddVerificationInfo2(jsonOptions: TChilkatBase): Boolean;
```

The same as `AddVerificationInfo`, except that the updated PDF stays in memory instead of being written to a file. Call `WriteFile` or `WriteBd` to write it, or go on to other operations first: the DSS (Document Security Store) with the certificates, OCSP responses and CRLs of the existing signatures is part of the loaded document as soon as this method returns.

Changes pending from other methods are committed first; the DSS itself is added as an incremental update, which leaves the existing signatures valid. Pass an empty `jsonOptions` (a placeholder for future options).

Returns `True` on success and `False` on failure.

Returns True for success, False for failure.

### Pdf.ClearEncryptCerts

`Chilkat 11.7.0 · pascal · Pdf · ClearEncryptCerts · method · since 11.7.0`

```pascal
procedure ClearEncryptCerts;
```

Removes every recipient certificate added with `AddEncryptCert`.

### Pdf.ExtractText

`Chilkat 11.7.0 · pascal · Pdf · ExtractText · method · since 11.7.0`

```pascal
// jsonIn is a TJsonObject object.

// jsonOut is a TJsonObject object.

function  ExtractText(const op: string;
    jsonIn: TChilkatBase;
    jsonOut: TChilkatBase): Boolean;
```

**Full documentation for this method (same in every language):** [PDF Text Extraction Overview](https://www.chilkatsoft.com/ai-docs/v/11.7.0/articles/pdf_extract_text.md)

Extracts the text of the loaded PDF. The `op` selects what is returned, the `jsonIn` holds the options (an empty JSON object extracts all pages in automatic reading order with the default clean-up), and the `jsonOut` receives the result together with a `quality` report that says how trustworthy the text is. Returns `True` on success and `False` on failure. A page without extractable text (such as a scanned image) is not a failure: the quality report identifies it. Chilkat does not perform OCR.

See the examples below for more detailed information about the operations and JSON members listed here.

**Operations (`op`)**

- **text** - Plain text, as flowing paragraphs, visual lines, or a layout-preserving grid (see the `layout` option).
- **markdown** - Markdown with headings, emphasis, lists, links, code, ruled tables, image placeholders and page markers. Suited to AI and search pipelines.
- **search** - The matches for a string or regular expression, each with its page and the text around it.
- **tables** - The tables detected on the pages, as rows and cells with spans.
- **assess** - Only the quality report, computed without producing text. Use it to triage documents before extracting: is the text trustworthy, and which pages need OCR.

**Summary of JSON Options (`jsonIn`)**

The options under *Scope*, *Reading order*, *Filters* and *Clean-up* apply to all operations. The groups that follow them apply only to the operation named.

*Scope (all operations)*

- **pages** - The pages to extract. Can be `all` (the default), `first`, `last`, `odd`, `even`, or a list of 1-based pages and ranges such as `1,3,5-9,12-`.
- **label** - Restricts the operation to the text belonging to a label found on the page, such as `Invoice Number:` or `Bill To`, so that fields can be captured without coordinates. Matching ignores case, extra spaces and a trailing colon. Works with every operation: `text` returns the value, `markdown` returns it as Markdown, `search` looks only inside the labelled text, and `tables` returns only the tables inside it.
- **labelValue** - Which text belongs to the label. Can be `auto` (the default), `right`, `below`, or `section`.
  - `auto` - The rest of the label's line if there is text there, otherwise the block directly below the label.
  - `right` - The rest of the label's line.
  - `below` - The block directly below the label, ending at the next gap or heading.
  - `section` - Everything after the label up to the next heading of the same or higher level (the label is itself a heading). Most reliable on tagged PDFs.
- **labelOccurrence** - Which occurrences of the label on the selected pages are used. Can be `first` (the default), `all`, or a number (`2` for the second occurrence). Occurrences are counted in reading order.
- **labelRegex** - Set to *true* to treat `label` as a regular expression. The default is *false*.

*Reading order (all operations)*

- **readingOrder** - Can be `auto` (the default), `structure`, `visual`, or `content`. `auto` follows the structure tree when the PDF is tagged and the tree is usable, otherwise it reads in visual order. `visual` detects columns and reads top to bottom within each column. `content` is the order in which the text is drawn.
- **columns** - Can be `auto` (the default) or `none`. `none` switches off column detection and reads the full page width line by line.

*Filters (all operations)*

Each filter can be `include` or `exclude` and decides whether a kind of text appears in the output.

- **artifacts** - Tagged artifacts, Acrobat and Chilkat watermarks and backgrounds, and Acrobat headers and footers. The default is `exclude`.
- **repeatedHeadersFooters** - Untagged text repeated at the same position on most pages, such as running heads and page numbers. The default is `exclude`.
- **invisibleText** - Text drawn in an invisible rendering mode. Can be `auto` (the default), `include`, or `exclude`. `auto` includes invisible text only on pages that have no visible text, which is exactly an OCR layer over a scanned image.
- **clippedText** - Text hidden by a clipping path. The default is `exclude`.
- **offPageText** - Text outside the page's crop box. The default is `exclude`.
- **obscuredText** - Text drawn in the same color as a filled area directly beneath it (white on white). The default is `exclude`.
- **rotatedText** - Text not aligned with the page, such as vertical margin labels. The default is `include`.
- **formFields** - The values of form fields, placed at the field's position in reading order. The default is `exclude`.
- **annotations** - Free-text annotations and comment text. The default is `exclude`.

*Clean-up (all operations)*

- **expandLigatures** - Boolean (default *true*). Ligatures are expanded, so that "ﬁ" becomes "fi".
- **dehyphenate** - Boolean (default *true*). Rejoins words split by a hyphen at the end of a line, while keeping hyphens that belong to the word.
- **actualText** - Boolean (default *true*). Uses the PDF's ActualText replacements where present (common for symbols and decorative letters).
- **bidi** - Boolean (default *true*). Reorders right-to-left scripts into logical order.
- **normalize** - Unicode normalization of the output. Can be `NFC` (the default), `NFKC`, or `none`.
- **lineEnding** - The line ending used in the text. Can be `\n` (the default) or `\r\n`. The keywords `lf` and `crlf` are also accepted.

*Options for the text operation only*

- **layout** - Can be `flow` (the default), `lines`, or `grid`. `flow` joins the lines of each paragraph; `lines` keeps each visual line on its own line; `grid` pads with spaces so that the horizontal positions are preserved, as in a fixed-pitch rendering of the page.
- **pageSeparator** - The string inserted between pages in the joined `text`. The default is a form feed (`\f`).

*Options for the markdown operation only*

- **headings** - Boolean (default *true*). Headings come from the structure tree when the PDF is tagged; otherwise they are inferred from the font size and weight relative to the body text.
- **maxHeadingLevel** - An integer from 1 to 6 (default `3`). Deeper inferred heading levels are folded into the last level.
- **emphasis** - Boolean (default *true*). Bold and italic spans.
- **lists** - Boolean (default *true*). Bullets, numbering and hanging indents become Markdown lists.
- **links** - Boolean (default *true*). Link annotations over the text become Markdown links.
- **code** - Boolean (default *true*). Monospaced runs become code spans and monospaced blocks become code blocks.
- **tables** - Can be `ruled` (the default), `all`, or `none`. `ruled` converts tables that have drawn cell borders. `all` is accepted for tables detected from column alignment alone, but this release detects only ruled tables.
- **images** - Can be `placeholder` (the default) or `none`. A placeholder such as `![image](page-3-image-2)` marks where an image sits in the flow.
- **pageBreaks** - Can be `comment` (the default), `rule`, or `none`. Pages are separated by an HTML comment such as `<!-- page 3 -->`, by a horizontal rule (`---`), or by nothing.
- **footnotes** - Can be `inline` (the default), `end`, or `none`. Small-print notes at the foot of a page are kept in place, gathered at the end of the document (after the last page, in the joined Markdown), or dropped.

*Options for the search operation only*

- **query** - The string or regular expression to find. Required.
- **regex** - Boolean (default *false*). Set to *true* to treat `query` as a regular expression.
- **caseSensitive** - Boolean (default *false*).
- **wholeWord** - Boolean (default *false*). Matches only whole words.
- **maxResults** - The maximum number of matches to return. The default is to return all matches.
- **context** - The number of characters of text returned before and after each match. The default is `40`.

*Options for the tables operation only*

- **detection** - Can be `ruled` (the default) or `all`. As for the markdown `tables` option; this release detects only ruled tables.
- **minRows**, **minColumns** - Grids smaller than this are not reported as tables. The default for each is `2`.

**Results (`jsonOut`)**

- **text** - The joined text of all selected pages (text operation), and **pages\[i\].page** / **pages\[i\].text** with each page's text.
- **markdown** - The joined Markdown (markdown operation), and **pages\[i\].page** / **pages\[i\].markdown** with each page's Markdown.
- **labelMatches\[i\]** - When `label` is set: one entry per label occurrence used, with **page**, **label** (the label as found) and the value as **text** or **markdown**. The top-level `text` or `markdown` holds the values joined. A label that is not found is still success: `labelMatches` is empty and the quality report carries the issue `labelNotFound`.
- **count** and **matches\[i\]** - Search results: each match has **page**, **text** (the matched text), **before** and **after** (the context).
- **count** and **tables\[i\]** - Each table has **page**, **detectedBy** (`ruled`, `aligned` or `structure`), **rows**, **columns**, and **cells\[j\]** with **row**, **col**, **rowSpan**, **colSpan** and **text**. Rows and columns are counted from 0.

- **quality** - Returned by every operation. **quality.rating** is `good`, `fair`, `poor`, or `none` for the document as a whole (the worst page rating among the pages that have text). **quality.tagged** and **quality.structureUsable** tell whether the PDF has a structure tree and whether it could be used. **quality.pagesNeedingOcr** lists the image-only pages, such as `4,9`. **quality.pages\[i\]** rates each page:
  - **page**, **rating**
  - **textSource** - `text` (real text), `ocrLayer` (invisible text over an image), `imageOnly` (needs OCR), `mixed`, or `empty`.
  - **unicodeCoverage** - The share of glyphs with a reliable Unicode mapping, from 0 to 1.
  - **unmappedFonts** - Fonts whose glyphs could not be mapped, so their text is likely wrong.
  - **suspiciousCharRatio** - The share of replacement, private-use and control characters in the output.
  - **readingOrderSource** - `structure`, `visual`, or `content`: how the reading order was decided.
  - **columns** - The number of columns detected.
  - **structure.headings** - `structure`, `inferred`, or `none`; **structure.tables.ruled** and **structure.tables.aligned** count the tables of each kind.
  - **issues\[j\].code**, **issues\[j\].message** - Machine-readable codes with a sentence each: `imageOnly`, `ocrLayer`, `missingUnicode`, `suspiciousCharacters`, `multiColumn`, `unruledTable`, `structureTreeUnusable`, `rotatedText`, `obscuredTextSkipped`, `clippedTextSkipped`, `labelNotFound`, `structureTreeMisaligned`, `layoutUncertain`.
  - **uncertain** - The layout decisions on the page that were borderline (an empty array when none): `columns` (a gutter close to the minimum width, or sides whose line lengths barely pass or fail the test that tells two text columns from a caption column beside its values), `heading` (a heading candidate whose size is close to the cut-off, or an accepted heading long enough to be a pull quote), `table` (a ruled grid with more empty cells than filled ones, or of the smallest size detected), `paragraph` (a paragraph break decided by a line spacing close to the block's own). The decision is still made; the entry says the output around it deserves a look. When the array is not empty the page also carries the issue `layoutUncertain`.

  A rating of `good` means the coverage is at least 0.99 with no suspicious characters to speak of; `fair` means coverage between 0.95 and 0.99 or structure inferred on a complex page (columns, unruled tables, rotated text); `poor` means coverage below 0.95 or suspicious characters above 1%, so the text should not be trusted without review; `none` means there is no text to extract.

**Permissions**

Extraction is read-only and never affects signatures or the saved output. For an encrypted PDF, every operation except `assess` requires owner rights or the copy permission; load the PDF with the `OwnerPassword` property set to extract from a PDF that restricts copying. `assess` reports only counts and ratings, never text, and is always allowed. Whole-document Markdown can be large; use `ExtractTextSb` to receive it in a StringBuilder.

**Example: capture a field by its label**

```
jsonIn: { "label": "Invoice Number" }
jsonOut: { "text": "INV-2026-0412",
           "pages": [ { "page": 1, "text": "INV-2026-0412" } ],
           "labelMatches": [ { "page": 1, "label": "Invoice Number:", "text": "INV-2026-0412" } ],
           "quality": { "rating": "good", ... } }
```

**Example: find a total with a regular expression**

```
jsonIn: { "query": "Total\\s+\\$?[0-9,]+\\.[0-9]{2}", "regex": true }
jsonOut: { "count": 1,
           "matches": [ { "page": 2, "text": "Total $1,234.56", "before": "... ", "after": " ..." } ],
           "quality": { ... } }
```

**Example: triage before extracting**

```
jsonIn: { }
jsonOut (assess): { "quality": { "rating": "fair", "tagged": true, "structureUsable": false, "pagesNeedingOcr": "4,9",
           "pages": [ { "page": 3, "rating": "fair", "textSource": "text", "unicodeCoverage": 0.97,
                        "unmappedFonts": [ "F12+Wingdings" ], "suspiciousCharRatio": 0.004,
                        "readingOrderSource": "visual", "columns": 2,
                        "structure": { "headings": "inferred", "tables": { "ruled": 1, "aligned": 0 } },
                        "issues": [ { "code": "multiColumn", "message": "Multi-column layout; reading order inferred" } ] },
                      { "page": 4, "rating": "none", "textSource": "imageOnly",
                        "issues": [ { "code": "imageOnly", "message": "No text; page is a scanned image" } ] } ] } }
```

Returns True for success, False for failure.

### Pdf.ExtractTextSb

`Chilkat 11.7.0 · pascal · Pdf · ExtractTextSb · method · since 11.7.0`

```pascal
// jsonIn is a TJsonObject object.

// sbOut is a TStringBuilder object.

// jsonOut is a TJsonObject object.

function  ExtractTextSb(const op: string;
    jsonIn: TChilkatBase;
    sbOut: TChilkatBase;
    jsonOut: TChilkatBase): Boolean;
```

**Full documentation for this method (same in every language):** [PDF Text Extraction Overview](https://www.chilkatsoft.com/ai-docs/v/11.7.0/articles/pdf_extract_text.md)

The same as `ExtractText`, except that the joined text or Markdown is written to `sbOut` instead of being returned in the `text` or `markdown` member of `jsonOut`. Use this method for large documents, where whole-document text or Markdown would be an unwieldy JSON string. `jsonOut` still receives everything else: the `pages` array (the page numbers only; the pages' text is in the StringBuilder), `labelMatches`, the search or table results, and the `quality` report.

See the `ExtractText` method for the operations, the JSON options and the results.

Returns True for success, False for failure.

### Pdf.GetDss

`Chilkat 11.7.0 · pascal · Pdf · GetDss · method · since 9.5.0.85`

```pascal
// json is a TJsonObject object.

function  GetDss(json: TChilkatBase): Boolean;
```

Gets the contents of the PDF's Document Security Store (/DSS) if it exists. Returns the information in JSON format (in `json`). If there is no /DSS then an empty JSON document `{}` is returned in `json`.

Returns True for success, False for failure.

### Pdf.GetEmbeddedFileBd

`Chilkat 11.7.0 · pascal · Pdf · GetEmbeddedFileBd · method · since 9.5.0.95`

```pascal
// bd is a TBinData object.

function  GetEmbeddedFileBd(index: Integer;
    bd: TChilkatBase): Boolean;
```

Loads the `bd` with the contents of the Nth embedded file contained in the currently open PDF. The `index` specifies the index of the embedded file. The 1st embedded file is at index 0. See the example linked below.

Returns True for success, False for failure.

### Pdf.GetEmbeddedFileInfo

`Chilkat 11.7.0 · pascal · Pdf · GetEmbeddedFileInfo · method · since 9.5.0.95`

```pascal
// json is a TJsonObject object.

function  GetEmbeddedFileInfo(index: Integer;
    json: TChilkatBase): Boolean;
```

Gets information about the Nth embedded file contained in the currently open PDF. The `index` specifies the index of the embedded file. The 1st embedded file is at index 0. The `json` is filled with information about the embedded file. See the example linked below.

Returns True for success, False for failure.

### Pdf.GetLastJsonData

`Chilkat 11.7.0 · pascal · Pdf · GetLastJsonData · method · since 11.0.0`

```pascal
// json is a TJsonObject object.

procedure GetLastJsonData(json: TChilkatBase);
```

Provides information about what transpired in the last method called. For many methods, there is no information. For some methods, details about what transpired can be obtained via LastJsonData. For example, after calling a method to verify a signature, the LastJsonData will return JSON with details about the algorithms used for signature verification.

### Pdf.GetMetadata

`Chilkat 11.7.0 · pascal · Pdf · GetMetadata · method · since 9.5.0.92`

```pascal
// sb is a TStringBuilder object.

function  GetMetadata(sb: TChilkatBase): Boolean;
```

If the PDF contains Metadata, then loads the Metadata XML into `sb` and returns `True`. If the PDF does not contain Metadata, then clears `sb` and returns `False`.

Returns True for success, False for failure.

### Pdf.GetSignatureContent

`Chilkat 11.7.0 · pascal · Pdf · GetSignatureContent · method · since 9.5.0.92`

```pascal
// bd is a TBinData object.

function  GetSignatureContent(index: Integer;
    bd: TChilkatBase): Boolean;
```

Returns the CMS signature for the Nth signature contained in the PDF. The 1st signature is at index 0.

Returns True for success, False for failure.

### Pdf.GetSignerCert

`Chilkat 11.7.0 · pascal · Pdf · GetSignerCert · method · since 9.5.0.87`

```pascal
// cert is a TCert object.

function  GetSignerCert(index: Integer;
    cert: TChilkatBase): Boolean;
```

This method retrieves the signer certificate after calling `VerifySignature`. Use the same index for `index` as the one passed to VerifySignature. If successful and the signer certificate is fully available, `cert` will contain the certificate.

Returns True for success, False for failure.

### Pdf.GetUnsignedSigFields

`Chilkat 11.7.0 · pascal · Pdf · GetUnsignedSigFields · method · since 9.5.0.90`

```pascal
// json is a TJsonObject object.

function  GetUnsignedSigFields(json: TChilkatBase): Boolean;
```

Returns JSON containing the name of each unsigned signature field found in the PDF.

Returns True for success, False for failure.

### Pdf.LoadBd

`Chilkat 11.7.0 · pascal · Pdf · LoadBd · method · since 9.5.0.85`

```pascal
// pdfData is a TBinData object.

function  LoadBd(pdfData: TChilkatBase): Boolean;
```

Loads the PDF file contained in `pdfData`.

Returns True for success, False for failure.

### Pdf.LoadFile

`Chilkat 11.7.0 · pascal · Pdf · LoadFile · method · since 9.5.0.85`

```pascal
function  LoadFile(const filePath: string): Boolean;
```

Load a PDF file into this object in memory.

Returns True for success, False for failure.

### Pdf.Optimize

`Chilkat 11.7.0 · pascal · Pdf · Optimize · method · since 11.7.0`

```pascal
// jsonIn is a TJsonObject object.

// jsonOut is a TJsonObject object.

function  Optimize(const op: string;
    jsonIn: TChilkatBase;
    jsonOut: TChilkatBase): Boolean;
```

**Full documentation for this method (same in every language):** [PDF Optimization Overview](https://www.chilkatsoft.com/ai-docs/v/11.7.0/articles/pdf_optimize.md)

Measures and shrinks the loaded PDF without changing how any page looks. The `op` selects the operation, the `jsonIn` holds the options, and the `jsonOut` receives the report. Returns `True` on success and `False` on failure.

**Operations (`op`)**

- **audit** - Reports where the file's bytes go, by category, and what each option would save. Changes nothing, and is allowed on any PDF. The same options as `optimize` select which savings to estimate.
- **optimize** - Applies the selected options to the PDF in memory and reports what was done and the bytes saved per option. The result is written by `WriteFile` or `WriteBd`.

Every option is lossless: pages render identically before and after. JPEG, JPEG 2000, JBIG2 and CCITT image data are never re-encoded. Most of the work is done in memory during the `optimize` call, so its savings are exact; two options (`objectStreams` and `dropOldRevisions`) take effect when the PDF is written, so their savings are estimates until then.

**Summary of JSON Options (`jsonIn`)**

An empty `jsonIn` applies the `lossless` preset, which is every option below at its default. Any option can be set to override the preset.

*General*

- **preset** - `lossless`, the only preset and the default.
- **pages** - Limits the page-level work (page content and resources) to these pages: a list of 1-based pages and ranges such as `1,3,5-9,12-`. The default is all pages. Document-wide work always applies to the whole file.

*Streams*

- **compressUncompressed** - Boolean (default *true*). Flate-encodes streams stored with no filter.
- **recompressFlate** - Boolean (default *true*). Re-deflates Flate streams at `compressionLevel`, keeping the result only if it is smaller.
- **replaceLegacyFilters** - Boolean (default *true*). Re-encodes LZW, ASCIIHex, ASCII85 and RunLength streams as Flate, including chains of several such stages (a RunLength stream that was then Flate-encoded, say), which become one Flate stream. These streams are always re-encoded, even in the rare case where the Flate stream comes out a little larger than the original chain. A chain that includes an image filter or an unknown filter is left as it is.
- **imagePredictors** - Boolean (default *true*). Tries PNG predictors on uncompressed and Flate images, keeping the result only if it is smaller.
- **compressionLevel** - The Flate level, 1 to 9, used by the options above. The default is `9`.

*Duplicates*

- **dedupeStreams** - Boolean (default *true*). Stores byte-identical streams with identical dictionaries once: images, embedded fonts, form XObjects, ICC profiles and page content.
- **dedupeObjects** - Boolean (default *true*). Stores identical non-stream objects (font dictionaries, color spaces, graphics states) once.
- **mergeFontSubsets** - Boolean (default *false*). Reserved for merging several subsets of the same font into one; not implemented in this release and reported in `skipped` when set.

*Unused content*

- **removeUnreferenced** - Boolean (default *true*). Drops objects not reachable from the document catalog.
- **removeUnusedResources** - Boolean (default *true*). Drops entries in page and form resource dictionaries that the content never uses.
- **removeUnusedLayers** - Boolean (default *true*). Drops optional-content layers that no content refers to, such as the empty "Watermark" layer Acrobat leaves behind after removing a watermark.

*Page content*

- **coalesceContent** - Boolean (default *true*). Merges a page's multiple content streams into one, so that they compress together.
- **tidyContent** - Boolean (default *true*). Removes redundant white space, empty q/Q pairs and graphics-state operators that change nothing. Numbers are never rounded and marked-content tags are never dropped.

*Fonts*

- **subsetFonts** - Boolean (default *true*). Reduces fully embedded TrueType/OpenType fonts (CIDFontType2 with a FontFile2 program) to the glyphs used. Fonts that form fields need for newly typed text are left whole, as are Type 1, CFF and already-subset fonts.
- **compactType1Fonts** - Boolean (default *false*). Reserved for converting embedded Type 1 fonts to CFF; not implemented in this release and reported in `skipped` when set.

*File structure*

- **objectStreams** - `generate` (the default), `preserve`, or `disable`. `generate` packs small objects into compressed object streams with a cross-reference stream (PDF 1.5; the file's version is raised to 1.5 if lower, never lowered). `preserve` generates them only if the file already had them. `disable` writes classic objects and a classic cross-reference table, for consumers that cannot read object streams.
- **dropOldRevisions** - Boolean (default *true*). Saves a single revision, discarding the superseded content kept by earlier incremental updates. This is also a privacy gain, since old revisions can hold deleted text.

**Results (`jsonOut`)**

For `audit`:

- **fileSize**, **pdfVersion**, **pdfa** - The file size in bytes, the PDF version, and the PDF/A part and conformance the file claims (such as `2b`), or `none`.
- **usage** - Where the bytes go, as stored (compressed) in the file: **images**, **fonts**, **pageContent**, **formXObjects**, **annotations**, **structureTree**, **metadata**, **embeddedFiles**, **oldRevisions** and **overhead** (cross-reference data, object headers and everything not counted elsewhere), each with **bytes** and, where it makes sense, **count**. The categories cover the whole file, including those the lossless options cannot touch.
- **estimatedSavings** - **total**, and the estimated bytes saved by each option, by option name. Options that would save nothing are omitted.

For `optimize`:

- **fileSize** - The size of the PDF as loaded, so that the saving can be measured against the file written afterwards.
- **bytesSaved** - The bytes the options above account for. The file written afterwards is usually smaller still: rewriting the document also packs objects into object streams, writes a compact cross-reference stream and leaves the old cross-reference sections behind, none of which belongs to a particular option. The exact saving is **fileSize** minus the size of the written file.
- **bytesSavedIsEstimate** - Boolean: `True` while a save-time option (`objectStreams`, `dropOldRevisions`) contributes.
- **actions** - Per option name: **count** (the objects affected, where it makes sense), **bytesSaved**, and **estimate** *true* for the save-time options.

For both:

- **skipped\[i\]** - Options that were requested but not applied: **option**, **pages** (when page-specific) and **reason**, such as page content that could not be parsed, a reserved option, or `objectStreams` on a PDF/A-1 file.

**Signed, encrypted and PDF/A files**

Optimizing rewrites the whole file. With `PreserveSignatures` *true* (the default), `optimize` fails on a signed PDF; with it *false*, the file is optimized and its signatures are invalidated. An encrypted PDF is saved with its original security unchanged, and `optimize` requires owner rights or the modify permission. A PDF/A file stays within its part's rules: for PDF/A-1 object streams are skipped, the output intent and XMP metadata are kept, and fonts stay embedded (subsetting is allowed). The structure tree of a tagged PDF is never touched.

**Example: audit**

```
jsonOut: { "fileSize": 4831022, "pdfVersion": "1.4", "pdfa": "none",
           "usage": { "images": { "bytes": 3120455, "count": 41 }, "fonts": { "bytes": 1204310, "count": 12 },
                      "pageContent": { "bytes": 288112, "count": 60 }, "formXObjects": { "bytes": 61200, "count": 9 },
                      "annotations": { "bytes": 8400, "count": 22 }, "structureTree": { "bytes": 51020 },
                      "metadata": { "bytes": 6400 }, "embeddedFiles": { "bytes": 0, "count": 0 },
                      "oldRevisions": { "bytes": 18210 }, "overhead": { "bytes": 72915 } },
           "estimatedSavings": { "total": 1290410, "subsetFonts": 942000, "dedupeStreams": 211800,
                                 "objectStreams": 54300, "recompressFlate": 41210, "dropOldRevisions": 18210,
                                 "removeUnreferenced": 12890, "coalesceContent": 10000 } }
```

**Example: optimize with the defaults, then write the file**

```
jsonIn: { }
pdf.Optimize("optimize", jsonIn, jsonOut)
pdf.WriteFile("out.pdf")
jsonOut: { "fileSize": 4831022, "bytesSaved": 1236110, "bytesSavedIsEstimate": true,
           "actions": { "subsetFonts": { "count": 7, "bytesSaved": 942000 },
                        "dedupeStreams": { "count": 39, "bytesSaved": 211800 },
                        "objectStreams": { "bytesSaved": 54300, "estimate": true },
                        "recompressFlate": { "count": 88, "bytesSaved": 41210 },
                        "removeUnreferenced": { "count": 17, "bytesSaved": 12890 } },
           "skipped": [ { "option": "tidyContent", "pages": "12", "reason": "content could not be parsed; left unchanged" } ] }
```

**Example: override individual options**

```
jsonIn: { "objectStreams": "disable", "dropOldRevisions": false }
```

Returns True for success, False for failure.

### Pdf.PreLoadCheck

`Chilkat 11.7.0 · pascal · Pdf · PreLoadCheck · method · since 11.7.0`

```pascal
// jsonOut is a TJsonObject object.

function  PreLoadCheck(const path: string;
    jsonOut: TChilkatBase): Boolean;
```

Reports what can be known about a PDF file's encryption before it is loaded, so that an application can decide which password or certificate it needs: whether the file is encrypted, by which method and algorithm, whether a password is needed to open it, what a user may do with it, or which certificates can open it. Nothing is loaded into this object, and no password is needed. Returns `False` only when the file cannot be read or is not a PDF; an unencrypted PDF returns `True` with `encrypted` false.

**Results (`jsonOut`)**

- **encrypted** - Boolean. When `False`, nothing else is returned.
- **method** - `password`, or `certificate` (a certificate with its private key is needed to open the file; see `SetDecryptCert`).
- **algorithm** - `rc4-40`, `rc4-128`, `aes-128`, `aes-256-r5`, `aes-256`, or `aes-256-gcm`.
- **pdfVersion** - The version in the file header, such as `1.7`, with **adobeExtensionLevel** or **isoExtensionLevel** when the file declares one. The declaration is in the document catalog, which an encrypted PDF often stores encrypted (inside an object stream), so the extension level is frequently not reported for a PDF that needs a password to open. `Protection` with `getInfo` reports it once the PDF is loaded.
- **scope** - `all`, `allExceptMetadata`, or `attachmentsOnly`.
- **openPasswordRequired** - Password method only: `False` when the file opens with an empty user password (it may still have restrictions).
- **permissions** - Password method only (readable without any password): **print** (`full`, `lowQuality` or `none`) and the booleans **modify**, **copy**, **accessibility**, **annotate**, **fillForms** and **assemble**.
- **recipients\[i\]** - Certificate method only: the **issuer** and **serialNumber** of each recipient certificate, which tells the application which certificate it needs.

**Example**

```
jsonOut: { "encrypted": true, "method": "password", "algorithm": "aes-256", "pdfVersion": "1.7",
           "adobeExtensionLevel": 8, "scope": "all", "openPasswordRequired": false,
           "permissions": { "print": "full", "modify": false, "copy": true, "accessibility": true,
                            "annotate": false, "fillForms": true, "assemble": false } }
```

Then, typically: if `method` is `certificate`, call `SetDecryptCert`; otherwise if `openPasswordRequired` is `True`, set the `UserPassword` (or `OwnerPassword`) property; then call `LoadFile`.

Returns True for success, False for failure.

### Pdf.PreLoadCheckBd

`Chilkat 11.7.0 · pascal · Pdf · PreLoadCheckBd · method · since 11.7.0`

```pascal
// bd is a TBinData object.

// jsonOut is a TJsonObject object.

function  PreLoadCheckBd(bd: TChilkatBase;
    jsonOut: TChilkatBase): Boolean;
```

The same as `PreLoadCheck`, but examines the PDF contained in `bd` instead of a file. See `PreLoadCheck` for the members returned in `jsonOut`.

Returns True for success, False for failure.

### Pdf.Protection

`Chilkat 11.7.0 · pascal · Pdf · Protection · method · since 11.7.0`

```pascal
// jsonIn is a TJsonObject object.

// jsonOut is a TJsonObject object.

function  Protection(const op: string;
    jsonIn: TChilkatBase;
    jsonOut: TChilkatBase): Boolean;
```

**Full documentation for this method (same in every language):** [PDF Encryption and Permissions Overview](https://www.chilkatsoft.com/ai-docs/v/11.7.0/articles/pdf_protection.md)

Encrypts the loaded PDF, removes or changes its encryption, passwords and permissions, or reports its security settings. The `op` selects the operation, the `jsonIn` holds the options, and the `jsonOut` receives the resulting security settings. Returns `True` on success and `False` on failure.

Every operation except `getInfo` changes the *pending* security: the settings the PDF will be saved with. Nothing is encrypted or decrypted until `WriteFile` or `WriteBd` is called, and if no operation changed anything, the PDF is saved with exactly the security it was loaded with. An operation that changes nothing is still success (`removeEncryption` on an unencrypted PDF returns `True`).

**Owner rights**

Every operation except `getInfo` requires owner rights, which means the PDF was not encrypted, or was loaded with its owner password (set the `OwnerPassword` property before calling `LoadFile` or `LoadBd`), or, under certificate security, was opened by a recipient that has the `changeSecurity` permission. Chilkat does not offer a way to ignore owner restrictions. An operation refused for lack of owner rights returns `False` and says why in the LastErrorText.

**Operations (`op`)**

- **encrypt** - Replaces the pending security entirely: method, algorithm, scope and permissions from `jsonIn`, and the passwords from the `UserPassword` and `OwnerPassword` properties as they are at the time of the call (or the recipients added with `AddEncryptCert`, for the certificate method). An empty `jsonIn` encrypts everything with AES-256 (revision 6) using the two password properties and grants every permission.
- **removeEncryption** - The PDF will be saved unencrypted, with no passwords and no restrictions.
- **removeRestrictions** - Grants every permission; keeps the user password and the algorithm. With an empty user password the result is unencrypted, the same as `removeEncryption`.
- **changePasswords** - Takes the new user and owner passwords from the `UserPassword` and `OwnerPassword` properties; the algorithm, scope and permissions are kept. Password security only.
- **changePermissions** - Takes new permissions from the `permissions` object in `jsonIn` (the same object as for `encrypt`); passwords, algorithm and scope are kept. The object is the complete new set of permissions, not a change to the existing ones: as for `encrypt`, a permission it does not mention is granted, whatever the PDF had before.
- **getInfo** - Changes nothing; reports the security the PDF was loaded with and the security it will be saved with.

Note: for AES-256 PDFs opened with the owner password alone, the user password cannot be recovered from the file, so `changePermissions` and `removeRestrictions` are refused unless `UserPassword` was also set when the PDF was loaded; `changePasswords` and `encrypt` work because they set both passwords afresh.

**Summary of JSON Options for encrypt (`jsonIn`)**

- **method** - `password` (the default) or `certificate`. The certificate method encrypts for the recipients whose certificates were added with `AddEncryptCert`; a recipient opens the PDF with the matching certificate and private key (see `SetDecryptCert`).
- **algorithmChoice** - The encryption algorithm. The PDF version in the file header is raised to what the algorithm requires when the PDF is saved, and never lowered. It can also be raised by the form the file is written in, because object streams and a cross-reference stream are both PDF 1.5 features. The two RC4 choices are the exception: they exist for readers older than PDF 1.5, so a PDF saved with either is always written with a classic cross-reference table and no object streams -- even when `Optimize`'s `objectStreams` asked for them -- and its header keeps to the version RC4 itself needs.
  - `aes-256` - (the default) AES-256, revision 6. Saved as PDF 1.7 with Adobe extension level 8, or as PDF 2.0 if the PDF is already 2.0.
  - `aes-256-gcm` - AES-256-GCM (ISO/TS 32003), authenticated encryption. Saved as PDF 2.0. Few viewers can open it yet.
  - `aes-128` - AES-128, revision 4. Saved as PDF 1.6.
  - `aes-256-r5` - AES-256, Adobe revision 5. Saved as PDF 1.7 with Adobe extension level 3. Deprecated; only for readers that predate revision 6.
  - `rc4-128` - RC4 128-bit, revision 3. Saved as PDF 1.4, or the document's own version if that is higher, with a classic cross-reference table. Broken; for legacy compatibility only.
  - `rc4-40` - RC4 40-bit, revision 2. Saved as PDF 1.3, or the document's own version if that is higher, with a classic cross-reference table. Broken; for legacy compatibility only.
- **scope** - What is encrypted.
  - `all` - (the default) Everything.
  - `allExceptMetadata` - Everything except the XMP metadata stream, which stays readable so that indexers can read the title, author and keywords. Needs `aes-128` or later.
  - `attachmentsOnly` - Only the embedded files; pages, metadata and everything else stay readable, and viewers ask for the password when an attachment is opened. Needs `aes-128` or later and a non-empty `UserPassword`.

- **permissions** - An object with what a user who opens the PDF without the owner password may do. Every permission is granted by default.
  - **print** - `full` (the default), `lowQuality`, or `none`. `lowQuality` is honored from `rc4-128` on.
  - **modify** - Boolean. Changes other than those covered by the permissions below.
  - **copy** - Boolean. Copying and extracting text and graphics.
  - **accessibility** - Boolean. Extraction for screen readers. PDF 2.0 readers always allow it, so it has no effect with `aes-256` or `aes-256-gcm`.
  - **annotate** - Boolean. Adding or changing annotations; also allows filling forms.
  - **fillForms** - Boolean. Filling existing form fields even when `annotate` is false.
  - **assemble** - Boolean. Inserting, deleting and rotating pages, and creating bookmarks.
  - **changeSecurity** - Boolean (default *false*). Certificate method only: the recipient has owner rights (may change or remove the security), and every other permission is implied. The encrypting program normally gives its own certificate this permission so that the file can be managed later.

  With `rc4-40` only `print` (as none or full), `modify`, `copy` and `annotate` exist; the rest are ignored.

- **recipientPermissions\[n\]** - Certificate method only: a permissions object (as above) for the nth certificate added with `AddEncryptCert`, overriding `permissions` for that recipient.

**Passwords**

`encrypt` and `changePasswords` read the `UserPassword` and `OwnerPassword` properties at the time of the call. An empty `UserPassword` gives a PDF that opens without a prompt but keeps its restrictions. `encrypt` with the password method refuses an empty `OwnerPassword` whenever any permission is restricted, since anyone would then have owner rights and the restrictions would mean nothing; an empty `OwnerPassword` is allowed when every permission is granted. With `aes-256` and `aes-256-gcm` a password can be any Unicode text up to 127 bytes as UTF-8; with the older algorithms it is limited to 32 Latin characters, and `encrypt` fails if a password cannot be represented.

**Results (`jsonOut`)**

`getInfo` returns **changed** (whether the pending security differs from the loaded security; when `False`, saving keeps the original security), **loaded** (the security the PDF was loaded with) and **pending** (the security it will be saved with). Every other operation returns **changed** and **pending**. While `changed` is `False`, `pending` is the loaded security exactly as the file has it: the same as `loaded`, without `openedWith`. Each of `loaded` and `pending` is an object with:

- **encrypted** - Boolean. An unencrypted state is just `{ "encrypted": false }`.
- **method** - `password` or `certificate`.
- **algorithm** - The same values as `algorithmChoice`.
- **pdfVersion** - The PDF version, such as `1.7`, with **adobeExtensionLevel** or **isoExtensionLevel** when one applies.
- **scope** - `all`, `allExceptMetadata`, or `attachmentsOnly`.
- **userPasswordRequired**, **ownerPasswordSet** - Password method: whether a password is needed to open the PDF, and whether the owner password is non-empty (when `False`, anyone has owner rights).
- **openedWith** - In `loaded` only: `owner`, `user`, `emptyPassword`, `certificate`, `notOpened`, or `notEncrypted`.
- **permissions** - Password method: the permissions object as above (without `changeSecurity`).
- **recipients\[i\]** - Certificate method: each recipient's **issuer** and **serialNumber**, and its **permissions** (including `changeSecurity`). In `loaded`, only the recipient that opened the PDF has readable permissions; in `pending`, every recipient shows its permissions.

Passwords are never returned.

**Signed PDFs**

A change of security means rewriting the whole file, which invalidates every signature. With `PreserveSignatures` *true* (the default), every operation except `getInfo` fails on a signed PDF; with it *false*, the change is allowed and the signatures are invalidated.

**Example: open password, no copying, low-quality printing**

```
pdf.UserPassword = "open-me"
pdf.OwnerPassword = "admin-secret"
jsonIn: { "permissions": { "print": "lowQuality", "copy": false } }
pdf.Protection("encrypt", jsonIn, jsonOut)      -- AES-256 revision 6 by default
pdf.WriteFile("protected.pdf")                  -- saved as PDF 1.7, Adobe extension level 8
```

**Example: getInfo**

```
jsonOut: { "changed": true,
           "loaded": { "encrypted": true, "method": "password", "algorithm": "aes-128", "pdfVersion": "1.6",
                       "scope": "all", "userPasswordRequired": true, "ownerPasswordSet": true, "openedWith": "owner",
                       "permissions": { "print": "lowQuality", "modify": false, "copy": false, "accessibility": true,
                                        "annotate": false, "fillForms": true, "assemble": false } },
           "pending": { "encrypted": true, "method": "password", "algorithm": "aes-256", "pdfVersion": "1.7",
                        "adobeExtensionLevel": 8, "scope": "all", "userPasswordRequired": true, "ownerPasswordSet": true,
                        "permissions": { "print": "full", "modify": false, "copy": false, "accessibility": true,
                                         "annotate": false, "fillForms": true, "assemble": false } } }
```

**Example: encrypt for two recipients**

```
pdf.AddEncryptCert(aliceCert)
pdf.AddEncryptCert(bobCert)
jsonIn: { "method": "certificate",
          "recipientPermissions": [ { "changeSecurity": true }, { "modify": false } ] }
pdf.Protection("encrypt", jsonIn, jsonOut)
```

**Example: remove encryption (needs the owner password)**

```
pdf.OwnerPassword = "admin-secret"
pdf.LoadFile("protected.pdf")
pdf.Protection("removeEncryption", jsonIn, jsonOut)
pdf.WriteFile("plain.pdf")
```

Returns True for success, False for failure.

### Pdf.SetDecryptCert

`Chilkat 11.7.0 · pascal · Pdf · SetDecryptCert · method · since 11.7.0`

```pascal
// cert is a TCert object.

function  SetDecryptCert(cert: TChilkatBase): Boolean;
```

Sets the certificate (with its private key) used to open a certificate-encrypted PDF. Call it before `LoadFile` or `LoadBd`. The certificate must be one of the PDF's recipients and must have its private key available, such as a certificate loaded from a PFX/.p12 file or from the Windows certificate store. Use `PreLoadCheck` to learn whether a PDF is certificate-encrypted and which recipient certificates (by issuer and serial number) can open it.

On Windows, calling this method is not needed for a certificate that is installed with its private key in the Windows certificate store (Current User or Local Machine): the store is searched for the private key of each recipient when a certificate-encrypted PDF is loaded.

For password-encrypted PDFs, set the `OwnerPassword` or `UserPassword` property instead.

Returns True for success, False for failure.

### Pdf.SetHttpObj

`Chilkat 11.7.0 · pascal · Pdf · SetHttpObj · method · since 9.5.0.85`

```pascal
// http is a THttp object.

procedure SetHttpObj(http: TChilkatBase);
```

Sets the HTTP object to be used to communicate with the timestamp authority (TSA) server for cases where long term validation (LTV) of signatures is desired. The `http` is used to send the requests, and it allows for connection related settings and timeouts to be set. For example, if HTTP or SOCKS proxies are required, these features can be specified on the `http`.

The `http` is also used to send OCSP requests to store OCSP responses in the PDF's document security store (DSS).

### Pdf.SetSignatureJpeg

`Chilkat 11.7.0 · pascal · Pdf · SetSignatureJpeg · method · since 9.5.0.85`

```pascal
// jpgData is a TBinData object.

function  SetSignatureJpeg(jpgData: TChilkatBase): Boolean;
```

Provides an optional JPG image to be included in the signature appearance. The JPG data is passed in `jpgData`.

Note: JPG images must use the BaseLine format and not the Progressive format. (Programs typically save JPEG's using the BaseLine format as default.)

Returns True for success, False for failure.

### Pdf.SetSigningCert

`Chilkat 11.7.0 · pascal · Pdf · SetSigningCert · method · since 9.5.0.85`

```pascal
// cert is a TCert object.

function  SetSigningCert(cert: TChilkatBase): Boolean;
```

Specifies a certificate to be used when signing the PDF. Signing requires both a certificate and private key. In this case, the private key is implicitly specified if the certificate originated from a PFX that contains the corresponding private key, or if on a Windows-based computer where the certificate and corresponding private key are pre-installed.

Returns True for success, False for failure.

### Pdf.SetSigningCert2

`Chilkat 11.7.0 · pascal · Pdf · SetSigningCert2 · method · since 9.5.0.85`

```pascal
// cert is a TCert object.

// privateKey is a TPrivateKey object.

function  SetSigningCert2(cert: TChilkatBase;
    privateKey: TChilkatBase): Boolean;
```

Specifies a digital certificate and private key to be used for signing the PDF.

Returns True for success, False for failure.

### Pdf.SignPdf

`Chilkat 11.7.0 · pascal · Pdf · SignPdf · method · since 9.5.0.85`

```pascal
// jsonOptions is a TJsonObject object.

function  SignPdf(jsonOptions: TChilkatBase;
    const outFilePath: string): Boolean;
```

Signs the open PDF and if successful writes the signed PDF to the ARG3. The `jsonOptions` contains information and instructions about the signature. This object keeps its state from before the call; to sign the loaded document in place (and sign again, or add a DocTimeStamp, without reloading), use `SignPdf2`. Starting in v11.7.0, changes pending from other methods are committed before the signature is added. See the examples below for more detailed information about the JSON options listed here.

**Signing an encrypted PDF** - An encrypted PDF can be signed, with an approval or a certification signature, and stays encrypted: the signature is added with the document's own key and everything it adds is encrypted, except the signature value itself, which PDF never encrypts. The PDF must have been opened (load it with its `UserPassword` or `OwnerPassword`). Starting in v11.7.0, a PDF that was not opened with owner rights is signed only if its permissions allow it: adding a new signature field needs both the `modify` and the `annotate` permission, and filling in an existing unsigned signature field (`appearance.fillUnsignedSignatureField`) needs the `fillForms` or the `annotate` permission. Otherwise the call fails and the `LastErrorText` names what is missing; load the PDF with its owner password to sign it regardless of its permissions. (See `Protection` for a PDF's permissions, and the `SIGN_IGNORE_PERMISSIONS` keyword of `UncommonOptions`.)

**Summary of PDF Signing Options**

- **appearance.fillUnsignedSignatureField** - Can be set to *true*) to tell Chilkat to sign an existing unsigned signature field. Chilkat will automatically scale the visual appearance (text + graphics) to fit the pre-existing signature field. When fillUnsignedSignatureField is specified, it is not necessary to set appearance.x, appearance.y, appearance.fontScale, etc.

  Starting in v9.5.0.90, the **unsignedSignatureField** option (see below) can be used to specify the unsigned signature field to be used. Otherwise, the 1st available unsigned field is used.

  See [PDF Unsigned Signature Fields for more information.](https://cknotes.com/pdf-unsigned-signature-fields/)

- **appearance.fontScale** - The font scale (in pts) to be used, such as `10.0`.

- **appearance.height** - Optional to specify the exact height of the visible signature rectangle in points, where 72 points equals 1 inch. If the appearance.height is set, then appearance.width should be set to `auto` (or left unset). Chilkat will compute the font scale to achieve the desired rectangle height, and the resulting width will depend on the text.

- **appearance.image** - Indicates an image will be included in the signature. Set to the keyword `custom-jpg` to use an image set by calling the SetSignatureJpeg method. Otherwise can be set to one of the following keywords to indicate a built-in SVG graphic. (These are graphics embedded within the Chilkat library itself.)
  - green-check-grey-circle
  - green-check-green-circle
  - application-approved
  - application-rejected
  - document-accepted
  - approved
  - blue-check-mark
  - green-check-mark
  - green-check-grey-circle
  - red-x-red-circle
  - rejected
  - result-failure
  - result-pass
  - signature
  - document-check
  - document-x
  - red-x-grey-circle

- **appearance.imageOpacity** - Sets the image opacity. Can be an integer from 1 to 100.

- **appearance.imagePlacement** - Sets the image placment within the signature rectangle. Can be `left`, `right`, or `center`. Images placed in the center typically have opacity 50% or less because the text is displayed over the image (i.e. it is a background image). Images placed left or right are not background images. The signature rectangle is divided into two sub-rectangles, one for the image, and one for the text.

- **appearance.margin_x** - If the appearance.x is set to `left`, then this can optionally be use to specify the position from the left edge. The default margin is 10.0 (10 points, where 72 points equals 1 inch).

- **appearance.margin_y** - If the appearance.y is set to `top`, then this can optionally be use to specify the position from the top. The default margin for y is 20.0 (20 points, where 72 points equals 1 inch).

- **appearance.text\[i\]** - The text that should appear in the signature box. Each line is specified in a JSON array item, where `i` is an integer starting with `0` as the 1st line. The text can contain the following keywords which are replaced with actual values:
  - cert_country - The signing certificate's subject country (C).
  - cert_cn - The signing certificate's subject common name (CN).
  - cert_dn - The signing certificate's DN (distinguished name).
  - cert_email - The signing certificate's subject email address (E).
  - cert_issuer_cn - The signing certificate's issuer's common name (CN).
  - cert_locality - The signing certificate's subject locality (L).
  - cert_organization - The signing certificate's subject organization (O).
  - cert_org_id - The signing certificate's organization ID.
  - cert_ou - The signing certificate's subject organizational unit (OU).
  - cert_san_rfc822name - The signing certificate's RFC822 subject alternative name.
  - cert_serial_dec - The signing certificate's serial number in decimal format.
  - cert_serial_hex - The signing certificate's serial number in hex format.
  - cert_state - The signing certificate's subject state (S).
  - cert_thumbprint - The signing certificate's thumbprint (The SHA1 hash of the binary DER representation in hex format).
  - current_datetime - Current local date/time in the format such as `Sep 11 2020 16:30:54`.
  - current_dt - Current local date/time in PDF date/time string format, such as YYYY.MM.DD hh:mm:ss -05'00'.
  - current_rfc822_dt_gmt - Current GMT date/time in RFC822 format, such as `Mon, 22 Nov 2021 15:58:41 GMT`.
  - current_rfc822_dt_local - Current local date/time in RFC822 format, such as `Mon, 22 Nov 2021 09:56:16 -0600`.
  - current_timestamp_gmt - Current GMT date/time in timestamp format, such as `1990-12-31T23:59:60Z`.
  - current_timestamp_local - Current local date/time in timestamp format, such as `2019-10-12T03:20:50.52-04:00`.

- **appearance.width** - Optional to specify the exact width of the visible signature rectangle in points, where 72 points equals 1 inch. If the appearance.width is set, then appearance.height should be set to `auto` (or left unset). Chilkat will compute the font scale to achieve the desired rectangle width, and the resulting height will depend on the text and number of lines of text.

- **appearance.x** - The horizontal position on the page of the left edge of the signature box. Can be a keyword such as `left`, `right`, or `middle` to specify a typical placement with default margins. Otherwise can be a floating point number where 0.0 is the leftmost coordinate of a page, and 612.0 is the right most. Can also be the keyword `after` to place the signature just to the right of the rightmost signature on the page. Starting in v11.7.0, if the signature would not fit on the page there, it continues as a line of text does: to the right of the signatures in the lowest row if there is room, and otherwise at the left margin in a new row under the existing signatures. (In earlier versions it was placed to the right of the rightmost signature regardless, and could lie partly or entirely off the page.)

- **appearance.y** - The vertical position on the page of the top edge of the signature box. Can be one of the keywords `top` or `bottom` to specify a typical placement with default margins. Otherwise can be a floating point number where 0.0 is the bottom coordinate of a page, and 792.0 is the top. Can also be the keyword `under` to place the signature just under the bottommost signature on the page. Invisible signatures are not counted (starting in v11.7.0; in earlier versions a signature placed `under` on a page that had an invisible signature was put below the bottom of the page).

  **Rotated pages** - On a page that is displayed rotated (a page with a /Rotate of 90, 180 or 270), **appearance.x**, **appearance.y**, the keywords and the margins all refer to the page as it is displayed: x is measured from the displayed left edge and y from the displayed bottom edge, and the signature is upright as the page is read. Starting in v11.7.0 this holds for every rotation. In earlier versions a page rotated by 180 or 270 was treated as if it were not rotated, and on a page rotated by 90 a numeric appearance.y was misplaced.

- **contactInfo** - Optional to provide free-form text with contact information about the signer.

- **docMDP.add** - Set this boolean value to *true* to include the Document MDP Permissions with a certifying signature. When a certifying signature is desired, both `lockAfterSigning` and `docMDP.add` should be specified. The default Doc MDP permission level is 2.

- **docMDP.accessPermissions** - Include this if the docMDP.add is specified, and a permission level different from the default value of 2 is desired. Possible values are:
  - 1: No changes to the document are permitted and any changes invalidate the signature.
  - 2: Permitted changes include filling in forms, instantiating page templates and signing.
  - 3: Same as 2, but also allow annotation creation, deletion, and modification.

- **embedCertChain** - Boolean to control whether the certificate chain is included in the signature. The default is to include the certificates in the chain of authentication. Set this to *false* to only include the signing certificate (this is not common).

- **hashAlgorithm** - If the signing certificate is RSA-based, and the signing scheme (padding scheme) is RSA-PSS, then this specifies the PSS hash algorithm. Can be `sha1`, `sha256`, `sha384`, or `sha512`. (`sha256` is what should be commonly chosen.)

- **includeRootCert** - Boolean to control whether the root CA certificate is included in the certificate chain (assuming the certificate chain is included). The default is to include the root CA certificate. Set this to *false* to exclude the root CA certificate from being included (this is not common).

- **info.\*** - (added in Chilkat v9.5.0.90) Provides the ability to add or update the PDF document's `/Info`, such as `Creator`, `Producer`, `Title`, etc. Any number of arbitrary member names can be specified and these will be added to the document's /Info dictionary. However, Chilkat will ignore `ModDate` and `CreationDate` because ModDate is automatically set to the current system date/time and the CreationDate should not change.

- **invisibleSignature** - Set this boolean to *true* to create an invisible signature with no appearance.

- **legalAttestation** - Set to provide a free-form text legal attestation.

- **location** - Optional to provide free-form text with a description of the geographic location where the PDF was signed.

- **lockAfterSigning** - Set this boolean to *true* to certify and lock a PDF as opposed to adding an approval signature (the default) which allows for additional countersignatures.

- **ltvOcsp** - Set this boolean to *true* to create an LTV-enabled signature.

- **noDss** - Set this boolean to *true* to prevent adding a /DSS (Document Security Store).

- **page** - The page number where the signature will be placed. Page 1 is the 1st page.

- **reason** - Optional to provide text indicating the reason for the signature.

- **signingAlgorithm** - If the signing certificate is RSA-based, then chooses the RSA padding scheme. Possible values are `pkcs` for PKCS-v1_5 or `pss` for RSASSA-PSS.

- **signingCertificateV2** - Set to `1` to include the `SigningCertificateV2` authenticated attribute. This is desired in most cases.

- **signingTime** - Set to `1` to include the `SigningTime` authenticated attribute. This is desired in most cases. Note: This is not the same as time-stamping. This is a fundamental authenticated attribute that should be included with or without the addition of time-stamping.

- **sigTextLabel** - Set to provide free-form text for the signatures annotation text label, which is the name of the new signature field. If not set, the field is named `Signature2`, `Signature3`, and so on. Starting in v11.7.0 a name that a field of the PDF already has is skipped; in earlier versions a PDF with an unsigned field of that name got a second field of the same name, and viewers did not show the new signature.

- **subFilter** - Set to `/ETSI.CAdES.detached`, `/adbe.pkcs7.detached`, or something else.

- **timestampToken.enabled** - Set to *true* to tell Chilkat to request a timestamp from a TSA server and include the timestamp token in the signature's authentication attributes

- **timestampToken.tsaUrl** - The timestamp server's URL.

- **timestampToken.tsaUsername, timestampToken.tsaPassword** - If the timestamp server requires a login and password.

- **timestampToken.bearerToken** - Use this if the timestamp server requires a bearer token instead of a password. This feature was added in Chilkat `v11.2.0`.

- **timestampToken.requestTsaCert** - Set to *true* to ask the timestamp server to include its certificate in the timestamp token.

- **unsignedSignatureField** - (added in Chilkat v9.5.0.90) Can be set to specify the name of the unsigned signature field that is to be signed.

Returns True for success, False for failure.

### Pdf.SignPdf2

`Chilkat 11.7.0 · pascal · Pdf · SignPdf2 · method · since 11.7.0`

```pascal
// jsonOptions is a TJsonObject object.

function  SignPdf2(jsonOptions: TChilkatBase): Boolean;
```

The same as `SignPdf`, except that the signed PDF stays in memory instead of being written to a file. Call `WriteFile` or `WriteBd` to write it, or go on to other operations first: the signature is part of the loaded document as soon as this method returns, so `NumSignatures` and `VerifySignature` see it, and a second call adds another signature (or a DocTimeStamp) on top of it.

Changes pending from other methods (a watermark added, a security change, an optimization, replaced text) are committed first, so the signature covers the document's current state; the signature itself is added as an incremental update, which leaves earlier signatures valid. See `SignPdf` for the members of `jsonOptions`.

Returns `True` on success and `False` on failure.

Returns True for success, False for failure.

### Pdf.SignPdfBd

`Chilkat 11.7.0 · pascal · Pdf · SignPdfBd · method · since 9.5.0.94`

```pascal
// jsonOptions is a TJsonObject object.

// bd is a TBinData object.

function  SignPdfBd(jsonOptions: TChilkatBase;
    bd: TChilkatBase): Boolean;
```

Signs the open PDF and if successful writes the signed PDF to the `bd`. The `jsonOptions` contains information and instructions about the signature. This object keeps its state from before the call; to sign the loaded document in place (and sign again, or add a DocTimeStamp, without reloading), use `SignPdf2`. Starting in v11.7.0, changes pending from other methods are committed before the signature is added. See the reference documentation for the SignPdf method for details about `jsonOptions`.

Returns True for success, False for failure.

### Pdf.TextReplace

`Chilkat 11.7.0 · pascal · Pdf · TextReplace · method · since 11.7.0`

```pascal
// jsonIn is a TJsonObject object.

// jsonOut is a TJsonObject object.

function  TextReplace(const op: string;
    jsonIn: TChilkatBase;
    jsonOut: TChilkatBase): Boolean;
```

**Full documentation for this method (same in every language):** [PDF Text Replacement Overview](https://www.chilkatsoft.com/ai-docs/v/11.7.0/articles/pdf_replace_text.md)

Replaces text in the page content of the loaded PDF: placeholders such as `{{name}}`, and the values that follow labels such as `Invoice #:`. The `op` selects the operation, the `jsonIn` names the values to put in, and the `jsonOut` receives a report. Returns `True` on success and `False` on failure; for `apply`, `False` also when the replacements could not be made, in which case the PDF is unchanged and the report says why.

A PDF stores positioned glyphs drawn with particular fonts, not editable text, so a replacement is only possible when the new text can be drawn with the font the original used. Chilkat finds each placeholder or label on the assembled lines of the selected pages, encodes the new value with that font and size, recomputes its width, and rewrites the content stream in place. The font rule: a standard-14 font (Helvetica, Times, Courier and their faces, or a non-embedded font that every viewer substitutes with one of them: Arial, Times New Roman, Courier New) can draw any character its encoding has; an embedded font can draw any character it has a glyph for; any other font that is not embedded cannot be used. Every replacement is checked first, and `apply` is all or nothing: if any replacement fails the rule, nothing is changed.

**Operations (`op`)**

- **check** - Finds every placeholder and label and applies the font rule, but changes nothing. The report says whether `apply` would succeed (`ok`) and lists the problems.
- **apply** - The same, then makes the replacements when there are no problems. The changes are written when `WriteFile` or `WriteBd` is called; the PDF is then saved as a full rewrite, so that the old values do not survive in an earlier revision of the file.

**Summary of JSON Options (`jsonIn`)**

- **pages** - The pages to search. Can be `all` (the default), `first`, `last`, `odd`, `even`, or a list of 1-based pages and ranges such as `1,3,5-9,12-`.
- **placeholders** - An object whose member names are placeholder names and whose values are the text to put in, such as `{ "customer": "Acme Corp", "total": "$1,234.56" }` for the placeholders `{{customer}}` and `{{total}}`. A value may be a string, number or boolean; `null` means an empty string. Every occurrence of a placeholder on the selected pages is replaced.
- **placeholderSyntax** - The delimiters around a placeholder name, written around the word `name`: the default is `{{name}}`; `[[name]]` or `<<name>>` are other choices.
- **labels** - An array of objects, each with:
  - **label** - The label text as it appears on the page, such as `Invoice #:`. Matching ignores case, extra spaces and a trailing colon.
  - **value** - The new text. It replaces the rest of the label's line; when nothing follows the label, the value is inserted after it.
  - **occurrence** - `first` (the default), `all`, or a number (`2` for the second occurrence). Occurrences are counted in reading order across the selected pages.
- **align** - `auto` (the default), `left`, `right`, or `center`. Where the new text sits when its width differs from the old. `auto` keeps a placeholder in place when it is right-aligned with other text on the page, or centered on the page, and otherwise keeps the left edge; a label's value is always left-aligned after its label.
- **unusedPlaceholders** - What to do with a placeholder found on the page that has no value in `placeholders`: `error` (the default; a problem with the reason `unusedPlaceholder`), `blank` (replaced by nothing), or `keep` (left as it is).
- **unmatchedValues** - What to do with a value whose placeholder or label is not found on the selected pages: `error` (the default; a problem with the reason `notFound`) or `ignore`.

**Results (`jsonOut`)**

- **applied** - Boolean: the replacements were made (`apply` only).
- **ok** - Boolean (`check` only): no problems were found, so `apply` would succeed.
- **replacements\[i\]** - One entry per placeholder or label that was (or would be) replaced: **field** (the placeholder name) or **label**, **pages** (such as `1,3`) and **count**.
- **problems\[i\]** - What prevents `apply`: **field** or **label**, **reason**, **page**, and for font problems **font** and **chars** (the characters the font cannot draw). The reasons:
  - `notFound` - The placeholder or label was not found on the selected pages.
  - `unusedPlaceholder` - A placeholder on the page has no value (see `unusedPlaceholders`).
  - `missingGlyph` - The embedded font has no glyph for one or more characters of the value.
  - `notInEncoding` - The standard font's encoding has no code for one or more characters of the value.
  - `nonStandardUnembeddedFont` - The text is drawn with a font that is neither standard-14 nor embedded, so Chilkat has no way to know what it can draw.
  - `unsupportedFont` - The font cannot be used for new text (a Type 3 font, or a font program that could not be read).
  - `placeholderSpansFonts` - The placeholder or value is drawn with more than one font or size, so there is no single font to draw the replacement with.
- **warnings\[i\]** - Replacements that were made but may not look right: the reason `overlap` means the new text runs into neighbouring text or off the page.
- **notReplaced\[i\]** - Placeholders found outside the page content, which this method does not change: **field** and **where** (`metadata` for the document's Title, Author, Subject, Keywords, Creator or Producer; `linkTarget` for a link's URL; `formField` for a form field value).

**Signed and encrypted PDFs**

`apply` rewrites the page content, which invalidates signatures: on a signed PDF it is refused while `PreserveSignatures` is *true* (the default). An encrypted PDF must have been opened, and `apply` requires owner rights or the modify permission. `check` only reads.

**Example: fill a template**

```
jsonIn: { "placeholders": { "customer": "Acme Corp", "date": "2026-10-18", "total": "$1,234.56" },
          "labels": [ { "label": "Invoice #:", "value": "INV-2026-0412" } ] }
pdf.TextReplace("apply", jsonIn, jsonOut)
jsonOut: { "applied": true,
           "replacements": [ { "field": "customer", "pages": "1", "count": 1 },
                             { "field": "date", "pages": "1", "count": 1 },
                             { "field": "total", "pages": "1", "count": 1 },
                             { "label": "Invoice #:", "pages": "1", "count": 1 } ],
           "warnings": [], "problems": [], "notReplaced": [] }
```

**Example: a check that fails the font rule**

```
jsonIn: { "placeholders": { "customer": "Müller GmbH" } }
pdf.TextReplace("check", jsonIn, jsonOut)
jsonOut: { "applied": false, "ok": false,
           "replacements": [],
           "problems": [ { "field": "customer", "reason": "missingGlyph", "chars": "ü", "font": "ABCDEF+OpenSans-Regular", "page": 1 } ],
           "warnings": [], "notReplaced": [] }
```

Returns True for success, False for failure.

### Pdf.UpdateMetadata

`Chilkat 11.7.0 · pascal · Pdf · UpdateMetadata · method · since 10.1.0`

```pascal
// sb is a TStringBuilder object.

function  UpdateMetadata(sb: TChilkatBase;
    const outFilePath: string): Boolean;
```

Updates or adds XMP metadata to a PDF. The metadata is passed in `sb`. If successful, the PDF with updated or inserted metadata is written to `outFilePath`, and the loaded document is the updated PDF. To update the metadata of the loaded document without writing a file, use `UpdateMetadata2`. Starting in v11.7.0, changes pending from other methods are committed before the metadata is updated.

Returns True for success, False for failure.

### Pdf.UpdateMetadata2

`Chilkat 11.7.0 · pascal · Pdf · UpdateMetadata2 · method · since 11.7.0`

```pascal
// sb is a TStringBuilder object.

function  UpdateMetadata2(sb: TChilkatBase): Boolean;
```

The same as `UpdateMetadata`, except that the updated PDF stays in memory instead of being written to a file. The XMP metadata is passed in `sb` and replaces the document's metadata (or is added when the document has none). Call `WriteFile` or `WriteBd` to write it, or go on to other operations first: the new metadata is part of the loaded document as soon as this method returns (`GetMetadata` returns it).

Changes pending from other methods are committed first; the metadata itself is added as an incremental update, which leaves existing signatures valid.

Returns `True` on success and `False` on failure.

Returns True for success, False for failure.

### Pdf.UpdateMetadataBd

`Chilkat 11.7.0 · pascal · Pdf · UpdateMetadataBd · method · since 10.1.0`

```pascal
// sb is a TStringBuilder object.

// bd is a TBinData object.

function  UpdateMetadataBd(sb: TChilkatBase;
    bd: TChilkatBase): Boolean;
```

Updates or adds XMP metadata to a PDF. The metadata is passed in `sb`. If successful, the PDF with updated or inserted metadata is written to `bd`, and the loaded document is the updated PDF. See `UpdateMetadata`.

Returns True for success, False for failure.

### Pdf.VerifySignature

`Chilkat 11.7.0 · pascal · Pdf · VerifySignature · method · since 9.5.0.85`

```pascal
// sigInfo is a TJsonObject object.

function  VerifySignature(index: Integer;
    sigInfo: TChilkatBase): Boolean;
```

Verifies the Nth signature contained in the PDF, where the 1st signature is indicated by an `index` of 0. Returns `True` if the signature valid, otherwise returns `False`. The `sigInfo` is an output argument and is populated with information about the validated or unvalidated signature.

Returns True for success, False for failure.

### Pdf.Watermark

`Chilkat 11.7.0 · pascal · Pdf · Watermark · method · since 11.7.0`

```pascal
// jsonIn is a TJsonObject object.

// jsonOut is a TJsonObject object.

function  Watermark(const op: string;
    jsonIn: TChilkatBase;
    jsonOut: TChilkatBase): Boolean;
```

**Full documentation for this method (same in every language):** [PDF Watermarks Overview](https://www.chilkatsoft.com/ai-docs/v/11.7.0/articles/pdf_watermark.md)

Adds, detects, lists and removes watermarks in the loaded PDF. The `op` selects the operation, the `jsonIn` holds the options or the filter, and the `jsonOut` receives the result. Returns `True` on success and `False` on failure. Finding nothing is still success: `detect` returns `True` with `found` false, and `remove` returns `True` with `removed` 0. Changes are made in memory and are written when `WriteFile` or `WriteBd` is called.

**Operations (`op`)**

- **add** - Adds one watermark (text, an image, or a page of another PDF) to the selected pages. `jsonOut` receives the `id` of the new watermark and the `pages` it was added to. A text watermark plus a logo is two calls.
- **detect** - Answers whether any watermark matching the filter is present. `jsonOut` receives `found` and `count`.
- **list** - Enumerates the matching watermarks with their properties. `jsonOut` receives `count` and a `watermarks` array.
- **remove** - Removes the matching watermarks. `jsonOut` receives `removed`, the number removed. An empty filter is refused unless `all` is *true*.

**How a watermark is stored (the approach)**

The `approach` member of `jsonIn` selects how an added watermark is stored, which decides whether it can be found and removed later:

- **artifact** - (the default) Marked content tagged as a Watermark or Background artifact. Visible in all viewers, removable later, skipped by text extraction.
- **annotation** - A Watermark annotation. Always drawn on top, removable later; the only approach allowed on a signed PDF while `PreserveSignatures` is *true*.
- **layer** - An optional-content layer, which the viewer's layers panel can hide, and which can be made print-only. Removable later.
- **content** - Drawn directly into the page content with no identifying marker. Visible in all viewers and the tamper-resistant choice, but by design it cannot be listed or removed afterwards.

For every approach except `content`, Chilkat stores a private identifier with the watermark; that is what lets `list` and `remove` target it later.

**Summary of JSON Options for add (`jsonIn`)**

Only `type` and the content for that type are required; every other member has a default. Members are given as dotted paths, as used with the JsonObject update methods.

*General*

- **approach** - `artifact` (the default), `annotation`, `layer`, or `content`. See above.
- **id** - A string identifying the watermark, returned in `jsonOut` and used by `list` and `remove`. Generated when not given. An id already present in the document is refused. Not stored for the `content` approach.
- **label** - A free-form description stored with the watermark and returned by `list`.
- **zOrder** - `front` (the default) or `back`: in front of or behind the existing page content. Ignored for the `annotation` approach, which is always in front.
- **pages** - The pages to stamp. Can be `all` (the default), `first`, `last`, `odd`, `even`, or a list of 1-based pages and ranges such as `1,3,5-9,12-`.
- **excludePages** - A range list of pages to leave out, applied after `pages`.
- **units** - `pt` (the default), `in`, `mm`, or `cm`: the units of the image size, wrap width, padding, margins, offsets, maximum sizes and tile spacing. Font size, outline width and border width are always in points.
- **pageBox** - `crop` (the default) or `media`: the page box that placement is measured against.
- **followPageRotation** - Boolean (default *true*). Keeps the watermark upright for the reader on pages that have a /Rotate setting.

*Content*

- **type** - Required: `text`, `image`, or `pdfPage`. Any type can be stored with any approach. (`barcode` is reserved for a later release; an existing barcode or QR image can be added as an `image`.)
- **text** - Required for `text`. A newline breaks lines. Placeholders are replaced per page: `{page}` (the page number), `{pages}` (the page count), `{date:FORMAT}` (the current local date/time, with `yyyy`, `yy`, `M`/`MM`, `d`/`dd`, `H`/`HH`, `h`/`hh`, `m`/`mm`, `s`/`ss` and `tt` for AM/PM; the format defaults to `yyyy-MM-dd`), and `{filename}` (the name of the file loaded by `LoadFile`). `{{` gives a literal brace.
- **image.path** or **image.base64** - Required for `image`: the path of a JPEG or PNG file, or its data in base64. PNG transparency is kept. Interlaced PNGs are not supported.
- **image.width**, **image.height** - The size to draw the image at. Give one of the two to keep the aspect ratio; the default is the image's natural size.
- **pdf.path** or **pdf.base64** - Required for `pdfPage`: another PDF whose page is placed as the watermark, such as a letterhead, a cover overlay, or a vector logo saved as PDF.
- **pdf.password** - The password of the source PDF, if it is encrypted.
- **pdf.page** - The 1-based page of the source PDF to use (default `1`), or `match` to place source page n on target page n, cycling when the source has fewer pages.

*Text styling (type = text)*

- **font.name** - `Helvetica` (the default), another standard-14 font name such as `Times-Roman` or `Courier`, or the path of a TTF/OTF font file, which is embedded as a subset. Symbol and ZapfDingbats are not supported.
- **font.size** - The size in points (default `48`), or `auto` to size the text to the box chosen by `scale.fit`.
- **font.bold**, **font.italic**, **font.underline**, **font.strikeout** - Booleans (default *false*). Bold and italic select the matching standard-14 face, or are synthesized for an embedded font file.
- **color** - The fill color: `#RRGGBB`, `#RGB`, or a color name such as `red` or `gray`. The default is `#808080`.
- **render** - `fill` (the default), `stroke` (outlined, hollow text), `fillStroke`, or `invisible` (present and searchable, but not seen).
- **outline.color**, **outline.width** - The outline color (default `#000000`) and width in points (default `1`), used by `stroke` and `fillStroke`.
- **textAlign** - `center` (the default), `left`, or `right`: the alignment of multi-line text within its own box.
- **lineSpacing** - The line spacing as a multiple of the font size. The default is `1.2`.
- **wrapWidth** - Wraps long text to this width. The default is no wrapping.
- **pageNumber.start** - The value of `{page}` on the first page. The default is `1`.
- **pageNumber.style** - The format of `{page}` and `{pages}`: `decimal` (the default), `romanUpper`, `romanLower`, `letterUpper`, or `letterLower`.
- **background.color**, **background.opacity**, **background.padding** - A box filled behind the stamp (text or image): its color (none by default), opacity (default `1.0`) and the space between the content and the box edge (default `0`).
- **border.color**, **border.width** - A box stroked around the stamp: its color (none by default) and width in points (default `1`).

*Appearance*

- **opacity** - From 0.0 to 1.0 (default `1.0`), applied to the whole stamp.
- **rotation** - Degrees counter-clockwise (default `0`), or `diagonal` (bottom-left to top-right, computed per page size) or `diagonalReverse`.
- **blendMode** - `normal` (the default), `multiply`, `darken`, `lighten`, `screen`, or `overlay`. `multiply` makes a front watermark read as if it were behind scanned pages.

*Placement and scaling*

- **position.align** - `center` (the default), `top`, `bottom`, `left`, `right`, `topLeft`, `topRight`, `bottomLeft`, or `bottomRight`.
- **position.margin** - The inset from the page edges, used for alignment and fitting: a single number, or an object with `left`, `top`, `right` and `bottom`. The default is `0`.
- **position.offsetX**, **position.offsetY** - A nudge from the aligned position (default `0`); positive values move right and down.
- **scale.factor** - Multiplies the natural size. The default is `1.0`.
- **scale.fit** - `none` (the default), `page`, `width`, or `height`: fits the rotated stamp inside the margin box.
- **scale.fitPercent** - The share of the fit box to fill. The default is `100`.
- **scale.maxWidth**, **scale.maxHeight** - Caps on the final size. No cap by default.
- **tile.enabled** - Boolean (default *false*). Repeats the stamp across the page, which overrides `position.align`.
- **tile.spacingX**, **tile.spacingY** - The gaps between tiles. The default is `72` points for each.
- **tile.stagger** - Boolean (default *true*). Offsets alternate rows by half a tile.

*Approach-specific*

- **annotation.view**, **annotation.print** - Booleans (default *true*). `view` false with `print` true gives a print-only watermark.
- **annotation.locked** - Boolean (default *true*). Users cannot move or delete the annotation in a viewer.
- **annotation.fixedPrint** - Boolean (default *false*). Keeps the printed size and position fixed whatever the paper size.
- **artifact.subtype** - `Watermark` (the default) or `Background`: the artifact subtype written to the marked content.
- **artifact.acrobatCompatible** - Boolean (default *false*). Also writes the structure that Acrobat's own watermark tool uses, so that Acrobat can update or remove the watermark.
- **layer.name** - The name shown in the viewer's layers panel. The default is `Watermark`. An existing layer of the same name is reused.
- **layer.view**, **layer.print** - `on` (the default) or `off`. `view` off with `print` on gives a print-only watermark.
- **layer.locked** - Boolean (default *false*). Prevents users from toggling the layer in the layers panel.

*Extras*

- **link.url** - Adds a link annotation over the stamp's area on each page, opening this URL.

**The filter for detect, list and remove (`jsonIn`)**

An empty filter means every watermark in the document. These operations recognize Chilkat's own watermarks and the standard forms other tools write: Watermark annotations from any producer, marked content tagged as a Watermark or Background artifact, Acrobat watermarks and backgrounds (Acrobat headers and footers are not watermarks and are ignored), and optional-content layers whose name contains "watermark".

- **pages** - Restricts the operation to these pages; the same syntax as for `add`. The default is `all`.
- **approach** - `any` (the default), or one of `annotation`, `artifact`, `layer`, `content`.
- **source** - `any` (the default), `chilkat`, `acrobat`, or `other`: who produced the watermark.
- **id** - An exact match on the watermark's id.
- **label** - An exact match on a Chilkat label.
- **textContains** - A case-insensitive match on the watermark's text.
- **heuristic** - Boolean (default *false*). Reserved for finding untagged page content that looks like a watermark; accepted but not implemented in this release.
- **all** - Boolean (default *false*). For `remove` only: required to remove with an otherwise empty filter.

**Results (`jsonOut`)**

- **add** - **id** (the watermark's id, generated or as given) and **pages** (the pages it was added to, such as `1-12`).
- **detect** - **found** and **count**.
- **list** - **count** and **watermarks\[i\]** with **id**, **label**, **source** (`chilkat`, `acrobat` or `other`), **approach**, **type**, **text**, **zOrder**, **opacity**, **rotation**, **removable** and **pages**. Watermarks from other producers have no id of their own, so Chilkat assigns one (`ext1`, `ext2`, ...) that stays valid until the PDF is changed, so that a `list` followed by a `remove` by id works. Properties that cannot be read back are omitted rather than guessed.
- **remove** - **removed**, the number of watermarks removed. An annotation is deleted; an artifact's marked content, and any form XObject used only by it, is deleted; a layer's content is deleted, and the layer itself once nothing else uses it. `content` watermarks are never removable.

**Signed and encrypted PDFs**

On a signed PDF with `PreserveSignatures` *true* (the default), only the `annotation` approach can be added and nothing can be removed, because any other change to the page content would invalidate the signatures. Set `PreserveSignatures` to *false* to allow such changes. An encrypted PDF must have been opened (see the `OwnerPassword` and `UserPassword` properties), and adding or removing requires owner rights or the modify permission.

**Example: diagonal CONFIDENTIAL across every page, removable later**

```
jsonIn: { "type": "text", "text": "CONFIDENTIAL", "id": "conf",
          "color": "#C00000", "opacity": 0.25, "rotation": "diagonal",
          "scale": { "fit": "page", "fitPercent": 80 } }
jsonOut: { "id": "conf", "pages": "1-12" }
```

**Example: company logo bottom-right, printed only**

```
jsonIn: { "approach": "layer", "type": "image", "image": { "path": "logo.png", "width": 1.5 },
          "units": "in", "layer": { "name": "Print logo", "view": "off", "print": "on" },
          "position": { "align": "bottomRight", "margin": 0.5 } }
```

**Example: tiled user ID behind the content**

```
jsonIn: { "type": "text", "text": "jdoe@example.com  {date:yyyy-MM-dd}", "zOrder": "back",
          "font": { "size": 14 }, "opacity": 0.15, "rotation": 30,
          "tile": { "enabled": true, "spacingX": 60, "spacingY": 80 } }
```

**Example: letterhead behind page 1 from another PDF**

```
jsonIn: { "approach": "artifact", "artifact": { "subtype": "Background" },
          "type": "pdfPage", "zOrder": "back", "pages": "first",
          "pdf": { "path": "letterhead.pdf", "page": 1 }, "scale": { "fit": "page" } }
```

**Example: list, then remove every Acrobat watermark**

```
list:    jsonIn: { "source": "acrobat" }
         jsonOut: { "count": 1, "watermarks": [ { "id": "ext1", "source": "acrobat", "approach": "artifact",
                    "type": "text", "text": "DRAFT", "opacity": 0.3, "rotation": 45, "removable": true, "pages": "1-4" } ] }
remove:  jsonIn: { "source": "acrobat" }
         jsonOut: { "removed": 1 }
```

Returns True for success, False for failure.

### Pdf.WriteBd

`Chilkat 11.7.0 · pascal · Pdf · WriteBd · method · since 11.7.0`

```pascal
// bd is a TBinData object.

function  WriteBd(bd: TChilkatBase): Boolean;
```

The same as `WriteFile`, but the PDF is written to `bd` (a BinData object) instead of a file. See `WriteFile` for what is written and when the file is rewritten in full.

Returns True for success, False for failure.

### Pdf.WriteFile

`Chilkat 11.7.0 · pascal · Pdf · WriteFile · method · since 11.7.0`

```pascal
function  WriteFile(const path: string): Boolean;
```

Writes the loaded PDF, with every change made since it was loaded, to the file at `path`. The changes written are those made by `Watermark` (`add` and `remove`), `Protection`, `Optimize` and `TextReplace` (`apply`), which are kept in memory until this method or `WriteBd` is called. Files embedded with `AddEmbeddedFiles2` are already part of the loaded document and are written as well. Returns `True` on success and `False` on failure.

When nothing requires more, the PDF is written as an incremental update: the original bytes are kept and the changes are appended, which leaves existing digital signatures valid. The file is written in full (a rewrite) when a change requires it: an `Optimize` with `dropOldRevisions` or generated object streams, a change of security by `Protection`, or a `TextReplace` `apply`. A rewrite invalidates existing signatures, which is why those operations are refused on a signed PDF while `PreserveSignatures` is `True`.

After writing, this object reloads the PDF it wrote, so that later calls work on the saved state. With no changes pending, the PDF is written as it was loaded.

To sign a PDF, use `SignPdf2`, which adds the signature to the loaded document (this method then writes it), or `SignPdf` / `SignPdfBd`, which write the signed PDF themselves.

Returns True for success, False for failure.

## Events and callbacks

Chilkat for Pascal supports three synchronous event callbacks: `OnAbortCheck`, `OnPercentDone`, and `OnProgressInfo`. Each is a property of the class; assign a method of one of your own objects (an *of object* handler) to receive the callbacks, or assign `nil` to unhook. The handler types are declared in the `Chilkat.Base` unit:

```pascal
TChilkatAbortCheckEvent   = function(Sender: TChilkatBase): Boolean of object;
TChilkatPercentDoneEvent  = function(Sender: TChilkatBase; PctDone: Integer): Boolean of object;
TChilkatProgressInfoEvent = procedure(Sender: TChilkatBase; const Name, Value: string) of object;
```

All Chilkat methods are synchronous, so callbacks are invoked on the thread that called the method -- if the method was called from the main thread, it is safe to access UI elements from the handler. The `HeartbeatMs` property controls the frequency of `OnAbortCheck` callbacks (the default of 0 means no AbortCheck events fire). Returning `True` from an `OnAbortCheck` or `OnPercentDone` handler aborts the running method.

### Pdf.AbortCheck (event)

`Chilkat 11.7.0 · pascal · Pdf · AbortCheck · event`

```pascal
// TChilkatAbortCheckEvent = function(Sender: TChilkatBase): Boolean of object;

property OnAbortCheck: TChilkatAbortCheckEvent;
```

Enables a method call to be aborted by triggering the AbortCheck event at intervals defined by the `HeartbeatMs` property. If HeartbeatMs is set to its default value of 0, no events will occur. For instance, set HeartbeatMs to 200 to trigger 5 AbortCheck events per second.

**Event callback implementation:**

```pascal
// A handler is a method of one of your own classes, e.g. a form:
function TMyObject.PdfAbortCheck(Sender: TChilkatBase): Boolean;
begin
  // Called every HeartbeatMs milliseconds while a method is running.
  // Return True to abort the method; return False to continue.
  Result := False;
end;
```

**To add an event handler:**

```pascal
pdf := TPdf.Create;
pdf.HeartbeatMs := 250;   // fire OnAbortCheck 4 times per second
pdf.OnAbortCheck := MyObject.PdfAbortCheck;
```

### Pdf.PercentDone (event)

`Chilkat 11.7.0 · pascal · Pdf · PercentDone · event`

```pascal
// TChilkatPercentDoneEvent = function(Sender: TChilkatBase; PctDone: Integer): Boolean of object;

property OnPercentDone: TChilkatPercentDoneEvent;
```

This provides the percentage completion for any method involving network communications or time-consuming processing, assuming the progress can be measured as a percentage. This event is triggered only when it's possible and logical to express the operation's progress as a percentage. The `pctDone` argument will range from 1 to 100. For methods that finish quickly, the number of PercentDone callbacks may vary, but the final callback will have `pctDone` equal to 100. For longer operations, callbacks will not exceed one per percentage point (e.g., 1, 2, 3, ..., 98, 99, 100).

The PercentDone callback also acts as an `AbortCheck` event. For fast methods where PercentDone fires, an AbortCheck event may not trigger since the PercentDone callback already provides an opportunity to abort. For longer operations, where time between PercentDone callbacks is extended, AbortCheck callbacks enable more responsive operation termination.

To abort the operation, set the `abort` output argument to `True`. This will cause the method to terminate and return a failure status or corresponding failure value.

**Event callback implementation:**

```pascal
// A handler is a method of one of your own classes, e.g. a form:
function TMyObject.PdfPercentDone(Sender: TChilkatBase; PctDone: Integer): Boolean;
begin
  // PctDone ranges from 1 to 100.
  WriteLn('Percent done: ', PctDone);
  // Return True to abort the method; return False to continue.
  Result := False;
end;
```

**To add an event handler:**

```pascal
pdf := TPdf.Create;
pdf.OnPercentDone := MyObject.PdfPercentDone;
```

### Pdf.ProgressInfo (event)

`Chilkat 11.7.0 · pascal · Pdf · ProgressInfo · event`

```pascal
// TChilkatProgressInfoEvent = procedure(Sender: TChilkatBase; const Name, Value: string) of object;

property OnProgressInfo: TChilkatProgressInfoEvent;
```

This event callback provides `tag name`/value pairs that detail what occurs during a method call. To discover existing tag names, create code to handle the event, emit the pairs, and review them. Most tag names are self-explanatory.

Note: Some Chilkat methods don't fire any ProgressInfo events.

**Event callback implementation:**

```pascal
// A handler is a method of one of your own classes, e.g. a form:
procedure TMyObject.PdfProgressInfo(Sender: TChilkatBase; const Name, Value: string);
begin
  WriteLn(Name, ': ', Value);
end;
```

**To add an event handler:**

```pascal
pdf := TPdf.Create;
pdf.OnProgressInfo := MyObject.PdfProgressInfo;
```

## Related classes

[`BinData`](https://www.chilkatsoft.com/ai-docs/v/11.7.0/pascal/classes/BinData.md), [`Cert`](https://www.chilkatsoft.com/ai-docs/v/11.7.0/pascal/classes/Cert.md), [`Http`](https://www.chilkatsoft.com/ai-docs/v/11.7.0/pascal/classes/Http.md), [`JsonObject`](https://www.chilkatsoft.com/ai-docs/v/11.7.0/pascal/classes/JsonObject.md), [`PrivateKey`](https://www.chilkatsoft.com/ai-docs/v/11.7.0/pascal/classes/PrivateKey.md), [`StringBuilder`](https://www.chilkatsoft.com/ai-docs/v/11.7.0/pascal/classes/StringBuilder.md)

