ChangeLog
Release history
Version history of the PDFlibPas library. Entries are listed newest first; each release follows semantic versioning per the project release policy.
Languages:English (US)English (UK)Español (España)Español (Latinoamérica)DeutschFrançaisItaliano日本語Português (Brasil)NederlandsSvenskaPolskiTürkçe한국어العربيةРусский简体中文繁體中文
v3.56.42 2026-05-27
- Fixed the buffer-based AES-256 decrypt path introduced in v3.56.41 so callers can assign the decrypt result back to the same
AnsiStringthat supplied the ciphertext buffer without access violations. - The normal API
LoadFromFile,Encrypt,SaveToFile, reload,Decrypt, andSaveToFileworkflow now completes again on large loaded PDFs while retaining the reduced-copy AES-CBC decrypt optimisation. - Added AES regression coverage for input-buffer/result-alias cases used by encrypted stream save rollback, including large 504 KB payloads that previously exposed the failure.
v3.56.41 2026-05-27
- Added
TPDFlib.DACopyFilefor Direct Access workflows that need a page count and an unchanged file copy without building the full normal object graph. - Optimised AES-256 decryption by adding buffer-based AES-CBC decrypt paths and using them when decrypting loaded strings and streams, reducing extra ciphertext copying on large encrypted streams.
- The Delphi
HugeFileBenchmarkdemo now includes adirect-copyrow plus--opsand--skipfilters for focused large-file runs.
v3.56.40 2026-05-26
- The Delphi and C++Builder
HelloWorlddemos now create a richer starter PDF with document information, selected standard font output, a styled title block, simple vector drawing, and next-step guidance while keeping the same build-and-run workflow. - All Delphi and C++Builder demo notes have been replaced with browser-friendly
Readme.htmlpages, including auxiliary password, restricted-file, and signing-result notes, and the demo indexes now direct users to the HTML notes.
v3.56.39 2026-05-26
- Direct file API saves now build cross-reference lookup tables linearly, making
DASaveAsFileand related direct-save paths much faster on PDFs with very high object counts or dense page trees. - The optimised writer preserves the same free-object chain semantics while avoiding repeated object-number scans during full xref generation, improving large direct-save workflows without changing the public API or output contract.
v3.56.38 2026-05-26
- Fixed normal API encryption output so
Encryptcreates or preserves the trailer/IDbefore writing AES-256 security data, keeping encrypted PDFs reload-detectable throughEncryptionStatus. - The normal API
LoadFromFile,Encrypt,SaveToFile, reload,Decrypt, andSaveToFileworkflow now preserves encrypted state before explicitDecrypt, matching the direct file API behaviour for large legacy PDFs.
v3.56.37 2026-05-26
- Added
TPDFlib.ComparePreflightReports, a line-by-line comparator for plain-text preflight reports that ignores volatileGenerated:timestamp lines and returns an empty string when stable report content matches. - The Delphi
PreflightReportdemo now supports--compare <file>in single-file mode, writing a UTF-8.diff.txtreport and returning exit code 2 when the generated text report differs from the baseline.
v3.56.36 2026-05-26
- The Delphi
PreflightReportdemo now supports batch directory runs with--input-dir,--output-dir, and--recursive, writing one report per PDF as<basename>.preflight.<ext>. - Batch mode writes a UTF-8
preflight-summary.csvfile that records each source PDF, pass/fail status, issue count, and generated report path while preserving the existing exit-code contract for automation.
v3.56.35 2026-05-26
ReportFormat = 3adds CSV output toTPDFlib.CreatePreflightReportExandTPDFlib.SavePreflightReportEx, producing UTF-8 rows for report metadata, each selected compliance check, individual issue codes and messages, and the final summary.- The Delphi
PreflightReportdemo now supports--format csvand--csvso command-line preflight runs can feed spreadsheets or simple CI parsers without post-processing JSON or scraping text.
v3.56.34 2026-05-26
- Added format-aware
TPDFlib.CreatePreflightReportExandTPDFlib.SavePreflightReportExAPIs for generating PDF/A and PDF/UA-1 preflight reports as plain text, JSON, or standalone HTML while preserving the existing text-only report APIs. - The Delphi
PreflightReportdemo now supports--format text|json|htmlplus--jsonand--htmlshortcuts, so the same command-line workflow can produce human-readable reports or machine-readable CI artifacts.
v3.56.33 2026-05-26
- Added
TPDFlib.CreatePreflightReportandTPDFlib.SavePreflightReportso applications can generate reusable plain-text reports from the built-in PDF/A and PDF/UA-1 compliance checks without manually enumerating string-list handles. - The Delphi
PreflightReportdemo now calls the library-level report APIs directly, keeping the sample focused on command-line workflow, selected checks, first-issue mode, and automation-friendly exit codes.
v3.56.32 2026-05-26
- Added a new Delphi
PreflightReportconsole demo that runs PDF/A and PDF/UA-1 checks withCheckFileCompliance, enumerates issue lists withGetStringListCountandGetStringListItem, and writes a plain-text preflight report. - The demo supports
--input,--output,--pdfa,--pdfua,--both, and--first-issueoptions, plus exit codes for automation-friendly pass, issue-found, and runtime-error results.
v3.56.31 2026-05-25
GetCustomKeys(2)now hides library-managed Catalog system entries consistently, including/OutputIntents,/Extensions,/Requirements,/Collection, and/NeedsRendering.- PDF/A output intents created by
SetPDFAModeno longer appear as custom Catalog keys, keeping application metadata enumeration separate from PDF compliance structures.
v3.56.25 2026-05-23
- Writer-side GetPDFUADiagnostics gains the matching
MULTIPLE-H-CHILDREN:Nissue, parity with reader10044from v3.56.24. ISO 14289-1 §7.4.4 forbids more than one direct H child per tag tree node — the writer-side check fires whenever the in-memory FStructElems tree contains such a violation. - A new nested CountMultipleHChildren helper walks the tree depth-first, counting H children at each level. The check runs alongside the existing LIST-STRUCT / LIST-NO-NUMBERING walks and shares the same FStructElems traversal pattern.
v3.56.24 2026-05-23
- The PDF/UA-1 audit gains ISO 14289-1 §7.4.4 H-tag uniqueness check.
10044reports any structure node that carries more than one direct H child — the spec forbids that under strongly-structured documents, and the same constraint applies to any tag tree node regardless of overall structure mode. The other §7.4.4 SHALL (a document shall be either strongly or weakly structured, not both) needs document-wide heuristics and is intentionally left out of this audit. - A new pre-order struct-tree walker (UAVisitStructNodeForHUniqueness / ScanStructTreeForHUniqueness) counts direct H children per node and recurses depth-first. Reuses the same K-shape decoder as the existing heading / list / note walkers.
v3.56.23 2026-05-23
- The PDF/UA-1 audit gains the two ISO 14289-1 §7.21.6 font-program checks that the dictionary-layer checks of v3.56.10 had to defer until a TrueType parser was available.
10034reports non-symbolic TrueType programs whose embedded SFNT cmap table contains only the symbolic (platformID=3, encodingID=0) entry — §7.21.6 first paragraph requires at least one non-symbolic cmap subtable so the program can render the codepoints declared by its /Encoding.10035reports non-symbolic TrueType/Encoding /Differencesarrays whose glyph names are not Adobe Glyph List members (.notdefexcepted) — §7.21.6 third paragraph requires every Differences entry to land in AGL. - New
Lib/PDFlibPDFUAFontInspect.pasimplements a tolerant SFNT table-directory walker and cmap subtable directory parser. The 4281-name Adobe Glyph List table added as scaffold in the previous infrastructure commit is now wired in via the Differences check. Programs that don't parse as SFNT (Type 1 PFB / PFA, OpenType collection, arbitrary garbage) are silently skipped — false negatives are preferred over false positives at the audit layer.
v3.56.22 2026-05-23
- The PDF/UA-1 audit gains ISO 14289-1 §7.18.6 media clip data checks.
10042reports media clip data dictionaries (identified by/S /MCD, optionally/Type /MediaClip) missing the required/CTcontent-type entry.10043reports the same dictionaries missing the required/Altarray. ISO 32000-1 Table 274 lists both keys as optional, but ISO 14289-1 §7.18.6 promotes them to required so screen readers can announce a meaningful description for embedded multimedia. - This is Phase 6 of the PDF/UA deep-audit plan (
.superpowers/plans/2026-05-23-pdfua-deep-audit-plan.md). It runs without any font-program or content-stream parser dependency, so it is the first follow-up sub-class after the v3.56.0..v3.56.13 series.
v3.56.21 2026-05-23
- New
SetSignProcessCommitmentTypeemits the CAdEScommitment-type-indicationsigned attribute (OID 1.2.840.113549.1.9.16.2.16, ETSI EN 319 122-1 v1.2.1 §5.2.3) inside the PAdES-B-B SignerInfo. Accepts integer codes 1..6 mapping to the well-known ETSI commitment OIDsid-cti-ets-proofOfOriginthroughid-cti-ets-proofOfCreation; pass 0 to clear. Out-of-range codes are rejected. - New
SetSignProcessSignaturePolicyemits the CAdESsignature-policy-identifiersigned attribute (OID 1.2.840.113549.1.9.16.2.15, §5.2.9). Takes the dotted-decimal policy OID, the policy document hash as an uppercase-hex string, and a digest algorithm code (1=SHA-1, 2=SHA-256, 3=SHA-384, 4=SHA-512, 0=auto/SHA-256). The attribute carries theSignaturePolicyIdSEQUENCE withsigPolicyId+sigPolicyHash(OtherHashAlgAndValueSEQUENCE). - Both attributes only take effect when the SubFilter is
ETSI.CAdES.detached(the PAdES-B-B path); they extend the existingrgAuthAttrarray alongsidecontent-typeandsigning-certificate-v2. PAdES Table 1 row d) forbids combiningcommitment-type-indicationwith the PDF Signature Dictionary/Reasonentry; the caller is responsible for not setting both.
v3.56.20 2026-05-23
- New
AddPAdESDSSVRIattaches a Signature VRI subdictionary entry to the DSS being assembled, completing the ETSI EN 319 142-1 v1.2.1 clause 5.4.2.3 Validation Related Information structure. The entry is keyed by the uppercase-hex SHA-1 of the signature's/Contentsbytes; itsCert/CRL/OCSPsub-arrays are populated by referencing the corresponding parent DSS streams via 0-based indexes supplied as comma-separated lists (e.g."0,2,5"). - The underlying
TSmartPDFDocument.AddPAdESDSSWithVRItracks the stream object numbers emitted for each cert / CRL / OCSP and uses them to write the VRI sub-arrays as indirect references back into the same streams the parent DSS arrays already point to, satisfying the spec requirement that VRI entries share storage with the parent DSS dictionary. The originalAddPAdESDSSentry point continues to work unchanged for callers that do not need VRI. - Each per-signature VRI subdictionary carries the optional
/Type /VRImarker so tooling that walks the catalog byTypetags can recognise the structure without re-resolving the parent path.
v3.56.19 2026-05-23
- New PAdES-B-T workflow for attaching an RFC 3161 / RFC 5816 signature-time-stamp (id-aa-signatureTimeStampToken, OID 1.2.840.113549.1.9.16.2.14) to an existing PAdES-B-B signature.
NewPAdESSignatureTimeStampProcessFromFile/FromStream/FromStringopen a signed PDF,SetPAdESSignatureTimeStampFieldnames the field,GetPAdESSignatureValueHashHexreturns the SHA-256 (or 384 / 512) hash of the signer'ssignatureValuefor submission to a TSA,GetPAdESSignatureCMSBytesexposes the existing CMS payload,SetPAdESSignatureCMSBytesaccepts the augmented CMS bytes the caller assembles via its CMS library of choice, andEndPAdESSignatureTimeStampProcessToFile/ToStream/ToStringsplices the new CMS into the original/Contentsplaceholder. BuildPAdESSignatureTimeStampAttributeis a stateless helper that wraps a TSA-issued TimeStampToken in the CMS Attribute SEQUENCE thatSignerInfo.unsignedAttrsexpects, so callers that already have a CMS library handy can skip the OID + SET-of plumbing.- New
SetSignProcessReserveContentsByteswidens the/Contentsplaceholder at initial sign time so the post-hoc augmented CMS fits without overflowing the original reservation. Typical TSA-issued TimeStampTokens add 2-6 KB to the SignerInfo; pass 1024-8192 here to leave headroom. Without enough reserve the augmentation call returns13(output overflow). - The library does not ship a TSA HTTP client; the caller fetches the TimeStampToken (typically 30-50 lines of TSP request + HTTP POST against e.g. FreeTSA or DigiCert). Windows CryptoAPI
CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTRwould in principle automate the CMS injection in-library, but returnsCRYPT_E_INVALID_INDEX(0x80091008) on the detached SignedData shape PAdES emits, so the caller-supplied CMS bytes path is used instead.
v3.56.18 2026-05-23
- The PAdES
signing-certificate-v2attribute now embeds the optionalIssuerSerialfield defined by RFC 5035 (ESSCertIDv2). The signing certificate's issuer Distinguished Name is wrapped in aGeneralName [4] EXPLICIT directoryNameCHOICE insideGeneralNames, followed by the certificate serial number as an ASN.1 INTEGER. The serial number bytes arrive little-endian from Windows CryptoAPI (CRYPT_INTEGER_BLOB) and are reversed to big-endian with the positive-integer pad byte added when the high bit is set, matching how OpenSSL and BouncyCastle emit the same field. - Verifiers that cross-check the issuer name + serial pair against their path-building candidate set (notably EU DSS in strict mode) now find both identifiers in the signing-cert-v2 attribute; the previous v3.56.17 output supplied only the
certHashreference. - New ASN.1 helpers
DER_IntegerFromLittleEndian(handles the Win32CRYPT_INTEGER_BLOBbyte order) andDER_ContextTagExplicit(wraps a payload in a constructed context-specific tag) round out thePDFlibASN1micro-encoder. NewCERT_INFO/CRYPT_ALGORITHM_IDENTIFIER/CRYPT_INTEGER_BLOB/PCERT_CONTEXTdeclarations inPDFlibCryptoAPIgive the sign path access to the parsed certificate fields.
v3.56.17 2026-05-23
- The built-in
ETSI.CAdES.detachedsign path now produces structurally conformant PAdES-B-B signatures. The library builds the CMS authenticated attributes itself -content-type(id-data) andsigning-certificate-v2from RFC 5035 / RFC 5816 with a SHA-256 hash of the signing certificate - and hands them toCryptSignMessageviargAuthAttr. Once that field is non-NULL, Windows CryptoAPI stops auto-injecting thesigning-timeattribute that PAdES (ETSI EN 319 142-1 v1.2.1 Table 1) forbids, so the resultingSignerInfocarries the required attributes and only those. - New
PDFlibASN1unit provides a focused DER (X.690) micro-encoder - length prefix, OCTET STRING, SEQUENCE, SET, OBJECT IDENTIFIER - used to build theSigningCertificateV2attribute value. The encoder follows the standard rules for base-128 OID arcs and omits the optionalhashAlgorithmfield when it would only repeat the SHA-256 default, matching what OpenSSL and BouncyCastle emit. ApplySignaturenow routesETSI.CAdES.detachedthrough the raw-byte path (the same one used byadbe.pkcs7.detached) instead of feeding a precomputed digest. CryptoAPI now computes themessageDigestauthenticated attribute over the actual signed content, which is what verifiers expect.- SHA-384 and SHA-512 are also honoured when building the signing-certificate-v2 attribute: the
hashAlgorithmfield is emitted with the matchingAlgorithmIdentifierrather than relying on the default. SHA-1 is silently upgraded to SHA-256 in this context because PAdES-B-B does not authorise SHA-1 (clause 6.2.1).
v3.56.16 2026-05-23
- New
SetSignProcessDigestAlgorithmselects the signing message-digest algorithm:1= SHA-1 (deprecated),2= SHA-256 (modern default),3= SHA-384,4= SHA-512,0= auto (SHA-256 for every SubFilter except the legacyadbe.pkcs7.sha1path, which stays on SHA-1 for byte-stable backward compatibility). ETSI EN 319 142-1 v1.2.1 §6.2.1 forbids MD5 and defers to ETSI TS 119 312 for the recommended cryptographic suites, so PAdES signers should pick SHA-256 or stronger. - Added
SHA256StreamRange,SHA384StreamRange, andSHA512StreamRangehash helpers next to the existingSHA1StreamRange; the sign path uses them to digest the PDF ByteRange under the selected algorithm. The PKCS#7SignerInfo.digestAlgorithmOID and the actual hash bytes are now guaranteed to agree (the previous code always passed the SHA-1 digest regardless of negotiated algorithm). TPDFlibPFXFile.SignDatanow takes aDigestAlgorithmparameter and chooses the correct OID for each (SubFilter, algorithm) pair:2.16.840.1.101.3.4.2.1/.2/.3for SHA-256/384/512 on detached and custom SubFilters (RFC 5754), and the matchingsha256WithRSAEncryptionfamily OIDs for the legacyadbe.pkcs7.sha1path.
v3.56.15 2026-05-23
- New
SetSignProcessDocTimeStampswitches a sign process into PAdES Document Time-stamp mode per ETSI EN 319 142-1 v1.2.1 §5.4.3. The resulting Signature Dictionary carries/Type /DocTimeStampand/SubFilter /ETSI.RFC3161, omits the disallowed/M,/Reason,/Location,/ContactInfo, and/Namekeys, and reserves an 8192-byte (or caller-sized) hex placeholder in/Contentsfor an externally-fetched RFC 3161 TimeStampToken. - Passthrough is enabled automatically when DocTimeStamp mode is selected because the TimeStampToken comes from an external TSA.
SetSignProcessInfocalls made after switching to DocTimeStamp mode are silently ignored to keep the signature dictionary spec-conformant. - The existing PAdES
/Extensions /ESICauto-injection added in v3.56.8 already covers DocTimeStamp because its SubFilter starts withETSI., so a Document Time-stamp PDF declares the required catalog extension without additional wiring.
v3.56.14 2026-05-23
- New PAdES Document Security Store (DSS) augmentation API.
NewPAdESDSSProcessFromFile/NewPAdESDSSProcessFromStream/NewPAdESDSSProcessFromStringopen a previously signed PDF,AddPAdESDSSCertificate/AddPAdESDSSCRL/AddPAdESDSSOCSPstage DER-encoded validation material, andEndPAdESDSSProcessToFile/EndPAdESDSSProcessToStream/EndPAdESDSSProcessToStringwrite an incremental update containing a/DSS << /Type /DSS /Certs [...] /CRLs [...] /OCSPs [...] >>dictionary as specified by ETSI EN 319 142-1 v1.2.1 §5.4.2.2. This is the building block for promoting a PAdES-B-B / B-T signature to PAdES-B-LT long-term validation. - The DSS process auto-bumps the catalog
/Extensions /ESICentry to at leastExtensionLevel 1when adding validation material, matching the requirement in §5.6, and merges new certificates, CRLs, and OCSP responses into the existing/Certs//CRLs//OCSPsarrays on repeated invocations so revisions accumulate rather than overwrite. GetPAdESDSSProcessResult/ReleasePAdESDSSProcesscomplete the lifecycle, mirroring the existingSignProcessAPI surface.
v3.56.8 2026-05-23
- PAdES baseline conformance: when a signature is created with a PAdES SubFilter (
ETSI.CAdES.detachedorETSI.RFC3161), the document catalog now automatically receives the/Extensions /ESIC <</BaseVersion /1.7 /ExtensionLevel 2>>entry required by ETSI EN 319 142-1 v1.2.1 §5.6. The entry is added through the same incremental update that carries the signature, never downgrades an existing higher/ExtensionLevel, and follows indirect/Extensionsor/ESICreferences when the source PDF already stores them as separate objects. - The Adobe-equivalent extension marker written by SetSignProcessCustomSubFilter for PDFs authored through
TPDFlibis now/ADBE /BaseVersion /1.7 /ExtensionLevel 8(wasExtensionLevel 5), matching the alternative declaration that PAdES baseline signatures are allowed to use; level 5 only covered ISO 32000-2 forms / 3D / RichMedia features and did not actually identify the PAdES extensions.
v3.56.13 2026-05-23
- When SetPDFUAMode is active and the document is saved, any L (list) structure element that lacks an explicit
ListNumberingattribute now automatically receives/O = List /ListNumbering = None. ISO 14289-1 §7.6 requires every L tag to declare its numbering style; the newApplyPDFUAListNumberingsave-time fix-up joins the existingApplyPDFUATabOrder/ApplyPDFUAFormFieldTU/ApplyPDFUAAnnotContents/ApplyPDFUAEmbeddedAFRelationship/ApplyPDFUAStripTrapNetfamily. - Authors who care about a specific list style should still call SetStructElemListNumbering before EndTag; the auto-fixup only fires when no ListNumbering attribute is present at save time, so explicit values are preserved.
- The writer-side
LIST-NO-NUMBERING:Ndiagnostic message now notes that the auto-fixup will mask the issue at save time, so users understand both the missing attribute and the automatic repair behaviour.
v3.56.12 2026-05-23
- The PDF/UA-1 audit gains three new ISO 14289-1 checks.
10031reports Link annotations whose URI action dictionary carries/IsMap = true(forbidden by §7.18.5 unless equivalent functionality is provided elsewhere in the content; authors with a legitimate IsMap use case can suppress the diagnostic on their own).10032reportsNotestructure elements missing the/IDentry — §7.9 requires every Note tag to declare a unique ID.10033reports duplicate-pair counts when two or more Note tags share the same/IDvalue. - Note ID collision detection is done by collecting the IDs in a sorted TStringList and walking adjacent pairs, so a group of three Notes sharing one ID counts as two duplicate pairs.
- URI action checking walks every page's
/Annotsarray, filters by/Subtype /Link, then inspects/A /S /URIand the/IsMapboolean. Indirect references are dereferenced at every step so split-out action dicts behave the same as inline ones.
v3.56.11 2026-05-23
- ISO 14289-1 §7.6 requires every L (list) structure element to carry an explicit
ListNumberingattribute.10030(reader-side) andLIST-NO-NUMBERING:N(writer-side) report L tags that omit it. The reader-side walker decodes both/Ashapes (single attribute dictionary, or an array of dictionaries mixed with revision integers) and looks for the/ListNumberingkey regardless of owner. The writer-side check inspectsTPDFStructElem.Attributesfor the same name across both the finalised structure list and the still-open tag stack. - Valid
ListNumberingvalues per ISO 32000-1 Table 347 areNone,Disc,Circle,Square,Decimal,UpperRoman,LowerRoman,UpperAlpha,LowerAlpha. The audit only checks presence of the key, not which value is chosen — every L tag needs one of these.
v3.56.10 2026-05-23
- The PDF/UA-1 audit gains the ISO 14289-1 §7.21.6 TrueType encoding rules.
10028reports non-symbolic TrueType fonts whose/Encoding(or the/BaseEncodinginside an Encoding dictionary) is neitherMacRomanEncodingnorWinAnsiEncoding.10029reports symbolic TrueType fonts that carry an/Encodingentry at all (forbidden by §7.21.6 fourth paragraph). - Symbolic vs. non-symbolic is decided from the FontDescriptor
/Flagsbit 3 (mask4), reusing the existingUAFontDescriptorSymbolichelper from sub-class 4. The full §7.21.6 first paragraph (the embedded TrueType program must contain matching cmap entries) requires parsing the TrueType font program and is still pending; the dictionary-level rules above are the practical layer this audit can verify without a TrueType parser. - Differences-array rules in §7.21.6 (AGL-only glyph names, Microsoft Unicode cmap presence) remain out of scope for the same reason — they require font-program inspection.
v3.56.9 2026-05-23
- The PDF/UA-1 audit gains a full ISO 14289-1 §7.18.4 check.
10027reports Widget annotations whose/StructParentresolves through the structure tree's/ParentTreebut does not land on a structure element with/S = Form. The previous v3.56.7 partial check (10026) only caught Widgets that lack/StructParententirely; the new check completes the rule by following the number-tree pointer and verifying the destination tag. - A new
NumberTreeLookuphelper implements the ISO 32000-1 §7.9.7 number-tree shape (flat/Numsroot, intermediate/Kidsranged by/Limits). Future audits that need to resolve/StructParentspage entries or/PageLabelslabels can reuse it. - The Widget annotation Form-tag verification uses a two-tier model: a Widget without
/StructParentis reported as10026; a Widget whose/StructParentexists but does not resolve to/S = Formis reported as the more specific10027. This avoids double-counting the same violation under both codes.
v3.56.7 2026-05-23
- When SetPDFUAMode is active and the document is saved, any
TrapNetannotation entries are now automatically removed from every page's/Annotsarray. ISO 14289-1 §7.18.2 forbidsTrapNetannotations; the newApplyPDFUAStripTrapNetsave-time fix-up joins the existingApplyPDFUATabOrder/ApplyPDFUAFormFieldTU/ApplyPDFUAAnnotContents/ApplyPDFUAEmbeddedAFRelationshipfamily so PDF/UA-mode documents stop silently emittingTrapNetstragglers. - The PDF/UA-1 audit gains a partial §7.18.4 check.
10026reports Widget annotations that lack/StructParent— a Widget without/StructParentcannot be reached from the structure tree and therefore cannot be nested in aFormstructure tag. Full structural verification (resolving/StructParentthrough theParentTreeand confirming the parent/SisForm) is left for a follow-up release. - Writer-side GetPDFUADiagnostics gains the matching
WIDGET-NO-STRUCTPARENT:Nissue. The existing TRAPNET-ANNOT message now also notes that SetPDFUAMode auto-strips these at save time.
v3.56.6 2026-05-23
- The PDF/UA-1 audit gains two ISO 14289-1 §7.4.2 heading hierarchy checks.
10024reports when the first heading element in document order is not H1 (or H).10025reports the number of heading-level skips in a descending sequence (e.g. H1 followed by H3 without H2). Both checks share a single structure-tree pre-order walk that decodes the nested/Kshapes (single StructElem, array of StructElems / IndRefs / MCRs). - Writer-side GetPDFUADiagnostics gains the matching
FIRST-HEADING-NOT-H1issue, parity with reader10024. The previously-existing HEADING-LEVEL-SKIP writer check now has a companion that also catches "first heading was H2" style problems.
v3.56.5 2026-05-23
- When SetPDFUAMode is active and the document is later encrypted, the encryption permission key (
/Pin the encrypt dictionary) now automatically has bit 10 (mask$200, "Extract text and graphics in support of accessibility") set, even when the caller did not includeppCanCopyAccessin theTPDFExtraPermissionspassed to Encrypt. ISO 14289-1 §7.16 requires every encrypted conforming file to permit accessibility extraction, and the bit is otherwise easy to miss. The bit is always safe to set — it only grants additional access to assistive technology, not to other extract paths. - Writer-side GetPDFUADiagnostics gains a new
ENCRYPT-NO-ACCESSissue that fires when PDFUAMode is on and the encrypt dictionary's/Pbit 10 is cleared. This catches the call-order edge case in which the user calledEncrypt()first and SetPDFUAMode only afterwards — the diagnostic tells the user to callEncrypt()again so the encrypt dict is re-emitted with the corrected/P.
v3.56.4 2026-05-23
- Writer-side GetPDFUADiagnostics gains five new ISO 14289-1 checks so the in-memory document audit catches the same violations as the reader-side CheckFileCompliance ComplianceTest=2 audit.
SUSPECTS-TRUEflags MarkInfo/Suspects=true (§7.1: PDF/UA conforming files require Suspects=false).ROLEMAP-STANDARD-REMAP:Nflags AddRoleMap calls that would remap a standard structure tag — §7.1 forbids remapping standard tags.DC-TITLE-MISSINGflags an empty XMP dc:title (separate from DOCINFO-TITLE-MISSING, which checks /Info /Title).TRAPNET-ANNOT:Nflags TrapNet annotations (§7.18.2 forbids them).ANNOT-PAGE-NO-TABS-S:Nflags pages carrying annotations whose page dictionary /Tabs is not /S (§7.18.3 requires structure-tree tab order on those pages). - Writer-side and reader-side PDF/UA-1 audits are now roughly in parity: every issue the reader-side audit raises on a saved file is also reachable from the in-memory diagnostic, modulo the format conventions of each function (newline-separated text vs. NNNNN-code string list).
v3.56.3 2026-05-23
- The PDF/UA-1 audit gains its §7.21 font checks.
10020reports any non-Standard-14 font whose FontDescriptor lacksFontFile/FontFile2/FontFile3(§7.21.4.1: every rendered font must embed its program).10021reports CIDFontType2 descendants without a/CIDToGIDMapentry (§7.21.3.2).10022calls out Standard 14 fonts (Helvetica, Times, Courier, Symbol, ZapfDingbats and bold / oblique variants) that are referenced without an embedded program — §7.21.4 NOTE 5 makes clear there is no exemption from embedding for these fonts.10023reports fonts that lack a/ToUnicodeCMap and do not match the §7.21.7 exemption list (predefined MacRoman / MacExpert / WinAnsi encodings, Type 0 with Adobe-GB1 / CNS1 / Japan1 / Korea1 character collections, non-symbolic TrueType). - Composite Type 0 fonts are inspected at both layers:
/ToUnicodeon the Type 0 parent dictionary itself, and embedding //CIDToGIDMapon the first descendant CIDFont. Type 3 fonts skip the embedding check (their glyphs are inline CharProcs) but still participate in the/ToUnicodecheck. - The PDFlibPDFA helpers for similar font work were intentionally not shared — a half-dozen short routines (subset-prefix stripping, Standard-14 name table, FontFile presence, Symbolic flag) are duplicated locally as
UA*helpers so the PDF/A audit can keep evolving without breaking PDF/UA, and vice versa.
v3.56.2 2026-05-23
- The PDF/UA-1 audit gains five more ISO 14289-1 checks covering annotations, embedded files, and optional content.
10015reports Link annotations that lack a non-empty/Contentsalternate description (§7.18.5) so screen readers can announce link targets.10016and10017flag embedded-file FileSpec dictionaries that are missing the required/For/UFfile-name keys (§7.11).10018flags optional-content configuration dictionaries that omit a non-empty/Nametext string (§7.10).10019flags optional-content configuration dictionaries that contain the forbidden/ASkey (§7.10). - The per-page annotation walk that already powered the TrapNet and
/Tabs /Schecks now also collects Link //Contentsdata in the same pass, keeping the audit O(N) on object count.
v3.56.1 2026-05-23
- The PDF/UA-1 audit gains five new ISO 14289-1 checks.
10010verifies the accessibility extract permission (bit 10 of the encryption/Pkey) on encrypted files (§7.16).10011detects dynamic XFA forms via the<dynamicRender>required</dynamicRender>element inside the XFA XDP packet (§7.15).10012flags Form XObjects that carry a/Refentry — reference XObjects are forbidden (§7.20).10013flagsTrapNetannotations (§7.18.2).10014walks every page and reports any page carrying annotations whose page dictionary does not set/Tabs /S(§7.18.3) so tab order follows the structure tree. - All five new codes flow through the same CheckFileCompliance + GetStringListItem handle pair the prior release added — there is no new public API surface.
v3.56.0 2026-05-23
- New reader-side audit
CheckCompliancePDFUAvalidates an external PDF against ISO 14289-1 (PDF/UA-1). It complements the existing GetPDFUADiagnostics writer-side check by accepting any input PDF (own output, scanner output, third-party content) and listing PDF/UA-1 violations the same way CheckFileCompliance already reports PDF/A problems. - CheckFileCompliance now accepts
ComplianceTest = 2to run the new PDF/UA-1 audit. The PDF/A test underComplianceTest = 1is unchanged, and the issue list still flows back through the existing GetStringListCount / GetStringListItem handle pair. - The first cut covers the foundational PDF/UA-1 conformance gates from §5 (XMP
pdfuaid:partidentification) and §7.1 (Catalog/Metadatastream, tagged-PDF marker, structure tree, viewer title preference, document language, XMPdc:title,/Suspectsvalue, and the prohibition on remapping standard structure tags). Eight diagnostic codes are issued —10001through10009— keeping the numeric range visually separate from the PDF/A00xxxcodes. - Deeper PDF/UA-1 clauses (security, annotations, XObjects, font subsetting) are tracked for follow-up patch releases on top of the same audit framework.
v3.55.6 2026-05-22
- Every freshly-generated XMP packet now carries an xmpMM:InstanceID property in the format uuid:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. The identifier is generated via Win32 CoCreateGuid and gives each produced document a unique, version-independent fingerprint as recommended by ISO 19005-1 §6.7.2 (Cor2) and PDF/A best-practice guides. The non-Windows builds (where the XMP packet remains empty) are unaffected.
- The xmpMM namespace (http://ns.adobe.com/xap/1.0/mm/) is now part of the XMP packet's SelectionNamespaces; new SetXMPMM and GenerateInstanceID helpers underpin the InstanceID emission and provide the foundation for future xmpMM:History / xmpMM:DerivedFrom support.
- PDF/A Extension Schema description schema (pdfaExtension / pdfaSchema / pdfaProperty / pdfaType / pdfaField) is not added in this release. Authoring a custom extension schema requires multi-step bag / seq / structured-property construction beyond the current SetDublinCore / SetXMPBasic shape; the work is tracked for a future release. Documents that need to declare custom XMP properties continue to fall back to the LoadFromString path.
v3.55.5 2026-05-22
- PDF/A documents now have their annotation /F flags normalised at save time. ISO 19005-1 §6.5.3 requires the Print bit to be 1 and the Hidden / Invisible / NoView bits to be 0 on every annotation; the writer now applies that mask at save time so callers do not have to remember the bit layout. The /Subtype /Popup case is exempt — popups are children of other annotations and traditionally not printed.
- The AcroForm /NeedAppearances flag is now force-set to false at save time when the document is in any PDF/A mode. ISO 19005-1 §6.9 requires the flag to be absent or false; previously the writer left whatever value the caller had set, which produced documents that asked the viewer to regenerate appearances at open time and silently violated the spec when the caller had set it to true. The fix also runs for documents that previously had the flag absent — the writer emits an explicit /NeedAppearances false to leave no ambiguity for the validator.
v3.55.4 2026-05-22
- AddStandardFont now rejects calls in PDF/A mode. ISO 19005-1 §6.3.4 revokes the PDF reference's "Standard 14 may be unembedded" exemption: every font program in a conforming file must be embedded, and the library does not bundle the Standard 14 outlines. The facade returns 0 silently; callers should switch to AddTrueTypeFont or AddType1Font with a real font file.
- AddTrueTypeFont now silently promotes Embed=0 (no embedding) to Embed=1 (embed full font) when PDF/A mode is active. The non-embedded reference path produced PDF that depended on the viewer's font fallback to a system Arial / Times / Courier installation, which violates ISO 19005-1 §6.3.4. Existing callers that asked for embedding (Embed=1 or 2) are unaffected.
- The non-symbolic TrueType /Encoding compliance check (ISO 19005-1 §6.3.7 Cor2 requires WinAnsi or MacRoman as the encoding name or BaseEncoding, with no /Differences) is not added in this release because the library already emits /WinAnsiEncoding for non-symbolic TrueType subsets, and the deeper enforcement would require tracking symbolic-vs-non-symbolic dispatch through the subset path. CheckCompliancePDFA 00034 / 00035 (added v3.51.0) flag any non-conforming output at validation time.
v3.55.3 2026-05-22
- TrueType-backed CIDFontType2 font dictionaries now carry /CIDToGIDMap /Identity explicitly. ISO 19005-1 §6.3.3.2 (Cor2) requires the entry to be present for every embedded Type 2 CIDFont; the PDF reference permits the implicit Identity default, but PDF/A demands an explicit value. The writer was previously omitting the key entirely, causing veraPDF (and CheckCompliancePDFA 00033 added in v3.51.0) to flag the file. The /Identity name matches the GID-as-CID layout that the writer was already producing implicitly, so existing documents render identically.
- FontDescriptor /CharSet (for Type 1 subsets) and /CIDSet (for CIDFont subsets) remain TODO; the writer would need to track which glyph names / CIDs ended up in the subset to populate them accurately. CheckCompliancePDFA 00031 and 00032 (also added in v3.51.0) will flag the absence so users see the issue at validation time.
v3.55.2 2026-05-22
- AddImageDirectFromString now rejects PDF/A-incompatible filters at the entry point. Passing Filter = 'LZWDecode' is rejected for every PDF/A part (ISO 19005-1 §6.1.10 plus the equivalent ISO 19005-2 / -3 rules). Passing Filter = 'JBIG2Decode' or 'JPXDecode' is rejected for PDF/A-1 (modes 1 and 2). PDF/A-2 and PDF/A-3 admit JPXDecode under ISO 19005-2 §6.2.8.3 with sub-spec constraints (colour-channel count, bit-depth uniformity, METH/APPROX requirements) that the writer-side gate does not enforce — callers in those modes still need to ensure the JPEG 2000 stream is conformant. The facade returns 0 silently when a forbidden filter is requested.
- TIFF, PNG, JPEG and JPEG 2000 inputs loaded through AddImageFromFile / AddImageFromStream are unaffected: the importer decompresses the source bytes and re-encodes with FlateDecode (or DCTDecode for JPEG payloads), so LZW input never propagates to the output Filter chain. The CheckCompliancePDFA validator added in v3.50.0 (00004) and v3.52.0 (00022, 00023) provides a second line of defence at validation time for any indirect path that still slips a forbidden filter into the output.
v3.55.1 2026-05-22
- AddLinkToHideField now rejects calls in PDF/A mode. The previous release left a comment claiming the action was PDF/A compatible, but ISO 19005-1 Cor2 added /Hide to the forbidden-action list (§6.6.1), and ISO 19005-2 / -3 inherit the restriction. The facade returns 0 silently when called in PDF/A mode, matching AddLinkToJavaScript and AddLinkToImportData.
- AddSWFAnnotationFromFile now rejects calls in PDF/A mode. SWF / RichMedia annotations wrap Flash media which is forbidden by ISO 19005-1 §6.5.2 (no Movie / Sound subtypes) and reinforced by ISO 19005-2 §6.3.1 (no 3D / Sound / Screen / Movie). The facade returns 0 silently.
- AddEmbeddedFile and AddLinkToEmbeddedFile now reject calls in PDF/A-1 and PDF/A-2 modes. ISO 19005-1 §6.1.11 forbids /EF, and ISO 19005-2 §6.8 admits only embedded PDF/A files; rather than verify the recursive PDF/A-ness of the attached payload, the writer simply refuses the call in these modes. PDF/A-3 (SetPDFAMode 5 or 6) remains permitted — see v3.55.0 for the automatic /AFRelationship injection.
- SetOpenActionMenu now rejects MenuItem values outside the {NextPage, PrevPage, FirstPage, LastPage} whitelist when the document is in PDF/A mode. ISO 19005-1 §6.6.1 restricts named actions to that set, so previously the API silently produced non-conforming Find / Print / FullScreen Open-Action dictionaries that veraPDF would reject.
- NewOptionalContentGroup now rejects calls in PDF/A-1 modes (SetPDFAMode 1 or 2). ISO 19005-1 §6.1.13 forbids the Catalog /OCProperties key. PDF/A-2 (modes 3/4) and PDF/A-3 (modes 5/6) admit optional content with the constraints in their respective §6.9, so the gate only fires for PDF/A-1.
v3.55.0 2026-05-22
- PDF/A-3 documents now automatically receive an /AFRelationship entry on every embedded file. Previously a PDF/A-3 file created with the library could fail validation because ISO 19005-3 Annex E, Table E.1 requires AFRelationship on every embedded file specification. The writer now injects the configured default value ('Unspecified' out of the box) on any FileSpec dictionary that lacks the entry at save time, mirroring the PDF/UA AFRelationship auto-injection introduced earlier. Only PDF/A-3 modes (SetPDFAMode 5 = PDF/A-3b or 6 = PDF/A-3a) trigger the auto-injection; PDF/A-1 and PDF/A-2 still reject embedded files outright per ISO 19005-1 §6.1.11 and ISO 19005-2 §6.8.
- SetPDFA3DefaultAFRelationship is a new API that overrides the default value written by the writer when an embedded file lacks an /AFRelationship entry. Accepts the ISO 19005-3 Table E.1 values 'Source' (the embedded file is the source material that produced the PDF content), 'Data' (the file is the structured data backing a visual table or chart), 'Alternative' (an alternative rendition such as an audio version), 'Supplement' (a supplementary representation such as a MathML form of an equation), 'Unspecified' (relationship cannot be characterised by the above), or any registered second-class name. Empty string resets to 'Unspecified'. Per-file overrides remain available via SetEmbeddedFileAFRelationship.
- The new APIs are exposed on the Delphi facade as TPDFlib.SetPDFA3DefaultAFRelationship and via the DLL as DLSetPDFA3DefaultAFRelationship (PWideChar) and DLSetPDFA3DefaultAFRelationshipA (PAnsiChar).
v3.54.0 2026-05-22
- LoadOutputIntentProfile is a new API that replaces the bundled sRGB OutputIntent profile with an external ICC profile loaded from disk. Required when producing PDF/A documents in DeviceCMYK or DeviceGray colour spaces, since the library only ships an sRGB profile. Typical use is to call SetPDFAMode first (which initialises the OutputIntent skeleton), then LoadOutputIntentProfile('C:\\path\\to\\FOGRA39.icc', 'DeviceCMYK') to swap the profile bytes and tag the document with the new colour space. Returns 1 on success, 0 on file-not-found or unknown colour space. Exposed on the Delphi facade as TPDFlib.LoadOutputIntentProfile and via the DLL as DLLoadOutputIntentProfile (PWideChar form) and DLLoadOutputIntentProfileA (PAnsiChar form). ISO 19005-1 §6.2.2 allows any registered ICC profile in the DestOutputProfile stream.
- SetFillColorCMYK, SetTextColorCMYK, SetTextHighlightColorCMYK, SetTextUnderlineColorCMYK, AddSeparationColor, SetFillColorSep, SetLineColorSep, SetTextHighlightColorSep and SetTextColorSep now succeed in PDF/A mode when the document's OutputIntent profile is DeviceCMYK. Previously these APIs rejected every call in PDF/A mode regardless of the OutputIntent, which prevented compliant CMYK documents from being produced. The gate is now PDFAMode = 0 OR OutputIntentColorSpace = 'DeviceCMYK', matching the ISO 19005-1 §6.2.3.3 rule that DeviceCMYK is permitted when the OutputIntent uses a CMYK profile, and ISO 19005-1 §6.2.3.4 which allows Separation alternates whose base colour space is also compliant.
- SetTextShader now succeeds in PDF/A mode when the OutputIntent profile is either DeviceRGB or DeviceCMYK. Shaders themselves are not banned by PDF/A; the validator (read side) verifies the shader's internal colour space matches the OutputIntent. The previous strict-reject behaviour denied compliant shader use.
- The CMYK / Separation / Shader unblock depends on the OutputIntentColorSpace tag set by AddOutputIntent and LoadOutputIntentProfile (introduced in v3.53.0). Calling SetPDFAMode without LoadOutputIntentProfile keeps the colour space as DeviceRGB (the bundled sRGB profile), so CMYK calls still reject by default — the new behaviour is opt-in via LoadOutputIntentProfile.
v3.53.0 2026-05-22
- OutputIntent dictionary now carries the full PDF/A skeleton fields recommended by ISO 19005-1 §6.2.2 and Adobe Acrobat preflight: /OutputCondition (human-readable colour-condition description), /Info (long-form identification text), and /RegistryName (registry URL, defaults to http://www.colour.org). The values default to "sRGB IEC61966-2.1" / "sRGB IEC61966-2.1" / "http://www.colour.org" for the legacy single-argument call sites; the new AddOutputIntent overload takes the four custom fields directly so callers can populate them for their own colour conditions.
- AddOutputIntent gains a new five-argument overload: AddOutputIntent(ColorSpace, OutputConditionIdentifier, OutputCondition, Info, RegistryName). The legacy single-argument form keeps working unchanged; it now delegates to the new overload with the sRGB defaults. The ColorSpace argument also selects the /N component count written into the embedded ICC profile dictionary (3 for DeviceRGB, 4 for DeviceCMYK, 1 for DeviceGray); the embedded profile itself remains the bundled sRGB stream until the upcoming LoadOutputIntentProfile API ships in v3.54.0.
- TPDFDocument exposes OutputIntentColorSpace as a read/write property tracking the colour space of the last AddOutputIntent call. This becomes the gate condition for the CMYK / Separation / Shader writer-side restrictions in v3.54.0, where colour APIs that today reject every call in PDF/A mode will reject only when the colour space is mismatched with the OutputIntent.
v3.52.0 2026-05-22
- CheckCompliancePDFA now audits annotations, graphics-state, actions, and form XObjects, completing the PDF/A read-side validator's coverage of ISO 19005-1 chapters 6.2-6.6 and the equivalent PDF/A-2/-3 differential rules. The validator reports 14 new issue classes (00050-00067): forbidden annotation subtypes (00050; ISO 19005-1 §6.5.2 forbids FileAttachment / Sound / Movie for PDF/A-1, and ISO 19005-2 §6.3.1 forbids 3D / Sound / Screen / Movie for PDF/A-2 and PDF/A-3), annotation /CA other than 1.0 (00051; §6.5.3), annotation /F missing or with Print=0 / Hidden=1 / Invisible=1 / NoView=1 (00052; §6.5.3, with /Subtype /Popup exempted), annotation /AA (00054; §6.6.2), annotation appearance dict with keys other than /N or non-conforming /N value (00055; §6.5.3 Cor2), Widget annotation with /A (00056; §6.9), ExtGState /TR (00058; §6.2.8), ExtGState /TR2 other than /Default (00059; §6.2.8), and in PDF/A-1 only: ExtGState /SMask other than /None (00061; §6.4), /BM other than Normal or Compatible (00062; §6.4), /CA or /ca other than 1.0 (00063; §6.4).
- Action-anywhere audit (00064, 00065) replaces the OpenAction-only check from v3.50.0 with a full sweep that flags forbidden /S action values (Launch, Sound, Movie, ResetForm, ImportData, JavaScript, Hide, SetState, NOP, Trans, GoTo3DView, Rendition, SetOCGState) and named actions whose /N is outside {NextPage, PrevPage, FirstPage, LastPage} regardless of where the action lives (annotation /A, widget /A, outline /A, catalog /OpenAction, etc.). ISO 19005-1 §6.6.1.
- XObject audit (00066, 00067) reports PostScript and Reference XObjects, plus forbidden keys on Form XObjects (/OPI, /PS, /Subtype2 = /PS) and Image XObjects (/Alternates, /OPI, /Interpolate true). ISO 19005-1 §6.2.4 - §6.2.7.
v3.51.0 2026-05-22
- CheckCompliancePDFA now audits font and colour-space conformance in addition to the structural checks added in v3.50.0. The validator reports nine new issue classes: at least one font program is not embedded (00030; ISO 19005-1 §6.3.4 requires every font program, including the Standard 14 substitutions, to be embedded), Type 1 subset missing /CharSet in its FontDescriptor (00031; §6.3.5), CIDFont subset missing /CIDSet (00032; §6.3.5), CIDFontType2 missing /CIDToGIDMap (00033; §6.3.3.2 Cor2), non-symbolic TrueType with a non-conforming /Encoding (00034; §6.3.7 Cor2 requires WinAnsi/MacRoman directly or as BaseEncoding, with no /Differences), symbolic TrueType that still carries /Encoding (00035; §6.3.7 Cor2), at least one font missing /ToUnicode in PDF/A-Na or PDF/A-Nu documents (00036; §6.3.8 four-class exemption applied), ICCBased colour space that does not embed its profile stream (00037; §6.2.3.2), and a file that uses both DeviceRGB and DeviceCMYK (00038; §6.2.3.3 forbids the mix).
- The /ToUnicode check (00036) is scoped to conformance levels A and U because only those levels require Unicode mapping per ISO 19005-1 §6.3.8 and ISO 19005-2 §6.2.11.7. Level B files (PDF/A-1b, PDF/A-2b, PDF/A-3b) are not flagged. The four-class exemption recognises predefined encodings (MacRomanEncoding, MacExpertEncoding, WinAnsiEncoding), Standard 14 Type 1 BaseFonts as a proxy for Adobe Standard Latin / Symbol glyph-name fonts, and Type 0 fonts whose descendant CIDFont uses Adobe-GB1, Adobe-CNS1, Adobe-Japan1 or Adobe-Korea1 registries.
- The font audit walks every Font dictionary, classifies it by Subtype (Type1, MMType1, TrueType, Type3, Type0 with its descendant CIDFontType0 or CIDFontType2), then dispatches the relevant checks. Type 0 composite fonts delegate embedding and subset checks to their descendant CIDFont while keeping /ToUnicode on the Type 0 wrapper. Subset detection uses the standard six-uppercase-letter prefix convention.
v3.50.0 2026-05-22
- CheckCompliancePDFA now reports 15 additional PDF/A non-conformance issues that the validator previously missed: missing trailer /ID array (00013), missing Document Catalog /Metadata stream (00014), /Filter applied to the /Metadata stream (00015), stream dictionaries that reference external files via /F, /FFilter or /FDecodeParms (00016), embedded files declared via /EF in any file-specification dictionary or via the Name tree /EmbeddedFiles entry in PDF/A-1 documents (00017, 00018), /OpenAction pointing at a forbidden action type (00019), /AA additional-action dictionaries in the Document Catalog or any Page (00020, 00021), JBIG2Decode or JPXDecode filters in PDF/A-1 documents (00022, 00023), Crypt filters whose /Name is not /Identity (00024), /Requirements in the Document Catalog (00025), /Perms with keys other than /UR3 and /DocMDP (00026), and /AcroForm /NeedAppearances set to true (00027). The validator now flags forbidden Catalog /OpenAction action types (/Launch, /Sound, /Movie, /ResetForm, /ImportData, /JavaScript, /Hide, /SetState, /NOP, /Trans, /GoTo3DView, /Rendition, /SetOCGState) and named-action /N values outside the {NextPage, PrevPage, FirstPage, LastPage} allowlist per ISO 19005-1 §6.6.1.
- The PDFAID parser accepts the U conformance suffix (PDF/A-2U, PDF/A-3U) alongside the existing A and B variants, so CheckCompliancePDFA no longer raises a spurious "00005 PDFA Mark NOT Found or invalid" warning when scanning a PDF/A-2U or PDF/A-3U file produced by another tool. The Unicode-mapping conformance levels added in ISO 19005-2:2011 are now recognised by the validator.
- Filter-specific checks (JBIG2Decode, JPXDecode) and embedded-file checks (/EF, /EmbeddedFiles) remain scoped to PDF/A-1 because ISO 19005-2 §6.2.8.3 and §6.8 explicitly relax those restrictions for PDF/A-2 and PDF/A-3. Document-structure checks (/Metadata, /AcroForm /NeedAppearances, /OpenAction, /AA, /Requirements, /Perms) apply to every PDF/A part.
v3.49.0 2026-05-21
- AddLinkToImportData creates a Link annotation whose action is a PDF import-data action (/S /ImportData) that populates the document's AcroForm fields from an external FDF file when the user clicks the link (ISO 32000-1 §12.6.4.8, Table 198). The FileName parameter is referenced as a filespec dictionary, with the same path-normalisation rules used by AddLinkToFile / AddLinkToFileEx (backslashes converted to forward-slashes per ISO 32000-1 §7.11.2.1). Options bit 0 toggles the visible border and bits 1–3 select the link highlight mode (Invert, Outline, Push), matching the existing AddLinkTo* conventions. PDF 1.4 or later. NOT permitted in PDF/A because the action references an external resource; the facade silently returns 0 when called in PDF/A mode. Exposed in the Delphi library and the DLL interface as DLAddLinkToImportData / DLAddLinkToImportDataA (PWideChar and PAnsiChar form).
v3.48.0 2026-05-21
- AddLinkToHideField creates a Link annotation whose action is a PDF hide action (/S /Hide) toggling the visibility of one or more AcroForm fields when the user clicks the link (ISO 32000-1 §12.6.4.10, Table 196). FieldNames accepts one or more fully-qualified field names separated by commas, semicolons, or line breaks; a single name emits /T as a text string and two or more names emit /T as an array, both forms permitted by the spec. HideFlag selects the visibility direction: a non-zero value hides the listed fields (/H true) and zero shows them (/H false). Options bit 0 toggles the visible border and bits 1–3 select the link highlight mode (Invert, Outline, Push), matching AddLinkToWeb / AddLinkToNamedAction. PDF 1.2 or later. PDF/A-compatible because no external resource is referenced. Exposed in the Delphi library and the DLL interface as DLAddLinkToHideField / DLAddLinkToHideFieldA (PWideChar and PAnsiChar form).
v3.47.0 2026-05-21
- AddLinkToNamedAction creates a Link annotation whose action is a PDF named action (/S /Named) triggering one of the four standardized viewer navigation commands defined in ISO 32000-1 §12.6.4.11, Table 194: NextPage, PrevPage, FirstPage, and LastPage. The NamedActionType parameter selects the command (0=NextPage, 1=PrevPage, 2=FirstPage, 3=LastPage); values outside this range fall back to NextPage so the writer always emits a spec-conforming /N name. Options bit 0 toggles the visible border and bits 1–3 select the link highlight mode (Invert, Outline, Push), matching the existing AddLinkToWeb / AddLinkToPage conventions. The annotation requires PDF 1.1 or later and is compatible with PDF/A because no external resource is referenced. Available in the Delphi library and DLL interfaces.
v3.46.1 2026-05-21
- AddCaretAnnotation creates a caret markup annotation (PDF /Subtype /Caret) at the given rectangle, marking a position on the page where text or content has been inserted, omitted, or otherwise needs reviewer attention. Supports two symbol types (None and Paragraph) via SymbolType (0 / 1), configurable colour, opacity, title, contents, and creation/modification timestamps. Defined in ISO 32000-1 §12.5.6.11. PDF 1.5 or later. Available in the Delphi library and DLL interfaces.
- This entry completes the geometric-annotation backfill that began with v3.44.0 Square+Circle. PDFlibPas now creates Text, Stamp, FreeText, TextMarkup (Highlight/Underline/Squiggly/StrikeOut), Square, Circle, Line, Polygon, PolyLine, Ink, and Caret annotations, in addition to existing Link, FileAttachment, SVG, U3D, and SWF support.
v3.46.0 2026-05-21
- AddInkAnnotation creates an ink markup annotation (PDF /Subtype /Ink) representing handwritten strokes or freeform marks drawn on the page. Strokes are supplied as a single string where multiple strokes are separated by '|' or newline, and within each stroke the coordinate pairs follow the same space/comma/semicolon/tab format used by AddPolygonAnnotation. For example "100 100 110 105 120 110 | 200 200 210 205" describes two separate strokes. Supports configurable border width, ink colour, opacity, title, contents, and timestamps. Defined in ISO 32000-1 §12.5.6.13. PDF 1.3 or later. Available in the Delphi library and DLL interfaces.
- Each stroke must contain an even number of values (at least four), otherwise the call returns 0 with no annotation written. The /Rect is computed automatically from the combined extent of all strokes plus a small padding so the strokes remain inside the annotation bounding box.
v3.45.0 2026-05-21
- AddPolygonAnnotation creates a closed polygon markup annotation (PDF /Subtype /Polygon) with vertices supplied as a string of space-, comma-, semicolon-, or tab-separated coordinate pairs (e.g. "100 100 200 100 200 200 100 200"). Supports configurable border width, border colour, optional interior fill colour, opacity, title, contents, and timestamps. Defined in ISO 32000-1 §12.5.6.9. PDF 1.5 or later. Available in the Delphi library and DLL interfaces.
- AddPolyLineAnnotation creates an open polyline markup annotation (PDF /Subtype /PolyLine) with the same vertex-string format and configurable end-line styles at each terminal (None, Square, Circle, Diamond, OpenArrow, ClosedArrow, Butt, ROpenArrow, RClosedArrow, Slash). Defined in ISO 32000-1 §12.5.6.9. PDF 1.5 or later. Available in the Delphi library and DLL interfaces.
- Both annotations require at least two vertex points (four numbers) and an even total count of numbers; the call returns 0 if the vertex string fails to parse to a valid pair list. The /Rect is computed from the vertex extent plus a border-width-proportional padding so end decorations remain visible.
- Both annotations bump the document version to PDF 1.5 when emitted under a lower minimum-version lock.
v3.44.1 2026-05-21
- AddLineAnnotation creates a line markup annotation (PDF /Subtype /Line) between two endpoints, with configurable border width, line colour, optional interior fill colour, end-line styles for both ends (None, Square, Circle, Diamond, OpenArrow, ClosedArrow, Butt, ROpenArrow, RClosedArrow, Slash), opacity, title, contents, and creation/modification timestamps. Defined in ISO 32000-1 §12.5.6.7. PDF 1.3 or later. Available in the Delphi library and DLL interfaces.
- The annotation /Rect is computed from the two endpoints plus a padding proportional to the border width so end-decorations remain inside the annotation bounding box.
v3.44.0 2026-05-21
- AddSquareAnnotation creates a rectangle markup annotation (PDF /Subtype /Square) at the given rectangle, with a configurable border width, border colour, optional interior fill colour, opacity, title, contents, and creation/modification timestamps. Defined in ISO 32000-1 §12.5.6.8. PDF 1.3 or later. Available in the Delphi library and DLL interfaces.
- AddCircleAnnotation creates an ellipse markup annotation (PDF /Subtype /Circle) inscribed in the given rectangle, with the same configurable border, fill, opacity, title, contents, and timestamps as AddSquareAnnotation. Defined in ISO 32000-1 §12.5.6.8. PDF 1.3 or later. Available in the Delphi library and DLL interfaces.
- Both new annotations auto-bump the document version to PDF 1.3 when emitted under a lower minimum-version lock and emit a standard markup-annotation field set (/Type /Subtype /Rect /C /IC /BS /Border /CA /F /M /CreationDate /NM /T /Contents /Subj /P) so existing review workflows in Acrobat, Foxit, and Edge can edit them after creation.
v3.43.0 2026-05-20
- SetStructElemSpaceBefore and SetStructElemSpaceAfter set the /SpaceBefore and /SpaceAfter attributes (Layout owner) on the currently open structure element, expressing spacing before and after block-level elements in points. Defined in ISO 32000-1 §14.8.5.4.2 Table 340. Available in the Delphi library, ActiveX (Dispids 73008051/73008052), and DLL interfaces.
- SetStructElemStartIndent and SetStructElemEndIndent set the /StartIndent and /EndIndent attributes (Layout owner), expressing indentation from the writing-mode-aware start and end edges of the content rectangle in points. Defined in ISO 32000-1 §14.8.5.4.2 Table 340. Available in the Delphi library, ActiveX (Dispids 73008053/73008054), and DLL interfaces.
- SetStructElemColor sets the /Colour attribute (Layout owner) as an RGB triplet (each component 0.0-1.0), describing the foreground colour of the element for re-flow engines and downstream colour-contrast checkers. Defined in ISO 32000-1 §14.8.5.4.2 Table 340. Available in the Delphi library, ActiveX (Dispid 73008055), and DLL interfaces.
- Fixed a serialisation bug in BuildStructElemDictRef: single-token numeric attribute values (such as SpaceBefore, SpaceAfter, StartIndent, EndIndent) were being written as PDF names instead of PDF numbers. The fix applies to both single-owner and multi-owner attribute branches.
v3.42.0 2026-05-20
- CheckCompliancePDFA now correctly validates all six PDF/A modes (1a, 1b, 2a, 2b, 3a, 3b). The PDFAID check (code 00005) accepts any of the six valid XMP markers instead of only '1B'. The version ceiling check (00002) applies 1.4 for PDF/A-1 and 1.7 for PDF/A-2 and PDF/A-3.
- The OCProperties check (code 00003) is now conditional: it applies only to PDF/A-1 documents, where optional content (layers) is forbidden. PDF/A-2 and PDF/A-3 permit layers and are no longer flagged.
- Three new compliance checks added: code 00006 flags encrypted documents (encryption is forbidden in all PDF/A versions); code 00007 flags documents missing an OutputIntents entry in the catalog (required by all PDF/A versions); codes 00011 and 00012 flag documents missing MarkInfo or StructTreeRoot when the conformance level is -a (accessibility).
v3.41.0 2026-05-20
- PDF/A mode now enforces prohibited operations at the API level. When a PDF/A mode is active (any of modes 1-6), calling SetEncryption, AddSeparationColor, SetFillColorCMYK, SetTextColorCMYK, or any other CMYK/Separation/Shader API returns 0 and has no effect, consistent with PDF/A's requirement for a single sRGB output intent.
- Transparency is prohibited in PDF/A-1 (modes 1 and 2): SetTransparency, SetBlendMode, and SetPageTransparencyGroup return 0 and are no-ops when the active mode is 1 or 2. PDF/A-2 and PDF/A-3 (modes 3-6) allow limited transparency and are not restricted.
- JavaScript actions are prohibited in all PDF/A modes (1-6): SetOpenActionJavaScript, PageJavaScriptAction, DocJavaScriptAction, AddGlobalJavaScript, and AddLinkToJavaScript all return 0 and are no-ops when any PDF/A mode is active. ISO 19005-1 §6.6.1 explicitly bans JavaScript from PDF/A documents.
- File attachment APIs (EmbedFile, AddFileAttachment) are blocked in PDF/A-1 and PDF/A-2 modes (1-4). They remain functional in PDF/A-3 (modes 5 and 6), which explicitly permits arbitrary embedded files.
v3.40.0 2026-05-20
- SetPDFAMode now supports PDF/A-2 and PDF/A-3 conformance levels. Pass NewMode=3 for PDF/A-2b, 4 for PDF/A-2a, 5 for PDF/A-3b, or 6 for PDF/A-3a. PDF/A-2 targets PDF 1.7 and permits layers, interactive forms, JPEG2000 images, and limited transparency. PDF/A-3 extends PDF/A-2 by allowing arbitrary embedded files (any MIME type). All -a variants automatically write /MarkInfo and the tagged-PDF structure markers required by the accessibility conformance level.
- Fixed: SetPDFAMode(1) (PDF/A-1a) was previously a no-op due to an internal routing bug introduced in v3.20.0. It now correctly writes /MarkInfo and /OutputIntents and sets XMP pdfaid:part=1/conformance=A.
- GetInformation(201) returns '1' through '6' matching the active PDF/A mode, consistent with the new mode numbering.
v3.39.0 2026-05-20
- SetStructElemWritingMode sets the /WritingMode attribute (Layout owner) on the currently open structure element. Valid values are LrTb (left-to-right, the default for Latin scripts), RlTb (right-to-left, for Arabic and Hebrew), and TbRl (top-to-bottom right-to-left, for traditional CJK vertical text). Defined in ISO 32000-1 §14.8.5.4.2 Table 340. Available in the Delphi library, ActiveX (Dispid 73008049), and DLL interfaces.
- SetStructElemListNumbering sets the /ListNumbering attribute (List owner) on the currently open structure element. Supported values include None, Disc, Circle, Square (unordered markers) and Decimal, UpperRoman, LowerRoman, UpperAlpha, LowerAlpha (ordered numbering). The attribute is set on the L (list) element and enables assistive technology to announce the list type correctly. Defined in ISO 32000-1 §14.8.5.3.2 Table 336. Available in the Delphi library, ActiveX (Dispid 73008050), and DLL interfaces.
v3.38.0 2026-05-20
- SetStructElemColSpan sets the /ColSpan attribute (Table owner) on the currently open structure element, indicating how many columns the cell spans. Defined in ISO 32000-1 §14.8.5.7.2 Table 337. Available in the Delphi library, ActiveX (Dispid 73008047), and DLL interfaces.
- SetStructElemRowSpan sets the /RowSpan attribute (Table owner) on the currently open structure element, indicating how many rows the cell spans. Defined in ISO 32000-1 §14.8.5.7.2 Table 337. Available in the Delphi library, ActiveX (Dispid 73008048), and DLL interfaces.
- Both functions are convenience wrappers equivalent to calling AddTagAttribute with Owner='Table' and the respective attribute name. They complement SetStructElemScope for fully described table cells in complex or spanning-header tables.
v3.37.2 2026-05-20
- GetPDFUADiagnostics now reports FORM-NO-TOOLTIP:N when N interactive form fields (Widget annotations) are missing a TU (tooltip / accessible name) entry. ISO 14289-1 §7.18.4 requires all interactive form fields to carry a TU entry so assistive technology can announce the field's purpose to the user when the field receives focus. /TU is the accessible name that screen readers speak aloud; it is distinct from /T, which is the partial field name used for programmatic access and form submission.
v3.37.1 2026-05-20
- GetPDFUADiagnostics now reports LIST-STRUCT:N when N LI or LBody structure elements appear outside their required parent element. ISO 32000-1 §14.8.4.4 requires LI to be a direct child of L (list) and LBody to be a direct child of LI (list item). Malformed list nesting prevents assistive technology from correctly traversing and announcing list content, and can cause document structure validation failures in PDF/UA-1 validators.
v3.37.0 2026-05-20
- BeginTagEx2 is a new API that opens a structure element and sets all main element properties in a single call. In addition to the TagType, AltText, ActualText, and Lang parameters of BeginTagEx, BeginTagEx2 accepts Title (/T, for the Tags navigation panel), ElemID (/ID, unique element identifier), and Expansion (/E, full text of an abbreviation or acronym). Passing an empty string for any of these three additional parameters is equivalent to omitting the corresponding setter. BeginTagEx2 reduces boilerplate for well-described elements — rather than calling BeginTagEx followed by SetStructElemTitle, SetStructElemID, and SetStructElemExpansion separately, all seven properties can be set in one call. The function is available in the Delphi library, ActiveX (Dispid 73008046), and DLL interfaces.
v3.36.1 2026-05-20
- GetPDFUADiagnostics now reports TABLE-TH-NO-SCOPE:N when N TH (table header cell) structure elements are missing a Scope attribute. ISO 32000-1 §14.8.4.3.4 Table 337 defines Scope (Row, Column, or Both) as the attribute that describes which data cells a header cell applies to. Without it, screen readers and other assistive technology cannot reliably associate header cells with data cells in complex or multi-header tables, which is required by ISO 14289-1 §7.5. Call SetStructElemAttr('Table','Scope', 'Column') (or 'Row' / 'Both') immediately after tagging each TH element.
v3.36.0 2026-05-20
- SetStructElemExpansion is a new API that sets the /E (expansion text) entry on the currently open structure element (ISO 32000-1 §14.9.5). The expansion text is the fully spelled-out form of an abbreviation or acronym contained in the element — e.g. "World Wide Web" for a Span whose text is "WWW". Screen readers speak the expansion instead of attempting to pronounce the abbreviated characters, which is critical for accessibility of technical and scientific content. PDF/UA-1 (ISO 14289-1 §7.2) requires that natural language be unambiguously determinable; /E is the standard mechanism for abbreviations and acronyms. The function is available in the Delphi library, ActiveX, and DLL interfaces.
v3.35.1 2026-05-20
- GetPDFUADiagnostics now reports DOCINFO-TITLE-MISSING when the document information dictionary /Title entry is absent or empty. PDF/UA-1 (ISO 14289-1) requires a document title so screen readers can announce it when the document is opened. The existing DISPLAYDOCTITLE-FALSE check confirms that the title is shown in the viewer title bar; DOCINFO-TITLE-MISSING is complementary — it confirms the title value itself is set. Call SetDocumentInfo('Title', ...) to supply the value.
v3.35.0 2026-05-20
- SetStructElemTitle is a new API that sets the /T (title) entry on the currently open structure element (ISO 32000-1 §14.7.2 Table 324). The title is a human-readable label that identifies the specific element instance — for example "Chapter 1", "Summary Table", or "Figure 3: Quarterly Sales" — and is shown in the Tags navigation panel of PDF viewers and used by accessibility remediation tools. /T is distinct from /Alt (alternative text for rendering-impaired users) and /ActualText (glyph-level text correction); it is most useful on non-text container elements such as Table, Figure, Form, Sect, and Div. Pass an empty string to clear a previously set value. The function is available in the Delphi library, ActiveX, and DLL interfaces.
v3.34.0 2026-05-20
- SetStructElemAltText is a new API that sets the /Alt entry on the currently open structure element (ISO 32000-1 §14.9.3). It is equivalent to passing AltText to BeginTag but allows the alternative text description to be set or updated after the element has been opened — useful when the description is computed separately from the element type. PDF/UA-1 (ISO 14289-1 §7.5) requires Alt text on Figure and Formula elements; GetPDFUADiagnostics already reports FIGURE-NO-ALT:N for missing values. The function is available in the Delphi library, ActiveX, and DLL interfaces.
v3.33.1 2026-05-20
- GetPDFUADiagnostics now includes a ROLEMAP-UNMAPPED:N check that detects custom structure element type names used in the document that have no entry in the /RoleMap dictionary. ISO 14289-1 §7.1 and ISO 32000-1 §14.7.3 require every non-standard structure type to be mapped to a standard PDF type (such as P, Span, or Figure) so assistive technology can determine how to handle the element. When N unmapped types are found the issue description includes the list of type names so callers know which AddRoleMap entries are needed. All 49 standard structure types defined in ISO 32000-1 Table 333 (PDF 1.7) are recognised and excluded from the report.
v3.33.0 2026-05-20
- SetStructElemLang is a new API that sets the /Lang entry on the currently open structure element (ISO 32000-1 §14.9.2). The language tag overrides the document-level language declared by SetDocumentLanguage or SetPDFUAMode for the element and all its descendants, enabling mixed-language documents to mark each span with its correct BCP 47 language tag (e.g. 'en-US', 'fr', 'zh-Hant-TW'). Screen readers use the element-level /Lang to select the appropriate text-to-speech engine or voice when reading the document aloud. The function is available in the Delphi library, ActiveX, and DLL interfaces.
v3.32.0 2026-05-20
- SetStructElemActualText is a new API that sets the /ActualText entry on the currently open structure element (ISO 32000-1 §14.9.4). Use it to specify the exact Unicode text that a glyph sequence represents when content-stream extraction would yield incorrect results — the most common cases are OpenType ligature glyphs (U+FB00 ff, U+FB01 fi, U+FB02 fl) and abbreviations with non-obvious expansions. ActualText supplements, rather than replaces, the rendered content; it overrides what assistive technology and text extractors read out for that element without suppressing visual rendering. The function is available in the Delphi library, ActiveX, and DLL interfaces.
v3.31.1 2026-05-20
- GetPDFUADiagnostics now checks Formula structure elements in addition to Figure elements when reporting missing Alt text (FIGURE-NO-ALT:N). ISO 32000-1 §14.9.3 requires alternative descriptions for both graphical figures and mathematical formulas; previously only Figure elements were scanned.
- GetPDFUADiagnostics now reports PDF-VERSION-LOW when the document's PDF version is below 1.7. PDF/UA-1 (ISO 14289-1) is defined against PDF 1.7 (ISO 32000-1:2008); documents at PDF 1.5 or 1.6 would not satisfy the base specification requirements. Call SetPDFUAMode to automatically raise the version to 1.7.
v3.31.0 2026-05-19
- Structure element IDs and table header association are now supported. SetStructElemID assigns a unique string identifier (/ID) to the currently open structure element; IDs are collected into an /IDTree name tree on the structure tree root when the document is saved, enabling accessibility tools and cross-references to locate elements by ID (ISO 32000-1 §14.7.4). SetStructElemHeaders associates the current table cell (TD or TH) with one or more header cells via a comma-separated list of previously assigned IDs, writing the /Headers array in the Table attribute owner dictionary (ISO 32000-1 §14.8.5.7.2). Together these two functions support complex table markup for PDF/UA-1 (ISO 14289-1 §7.10) and WCAG 2.x SC 1.3.1. Both functions are available in the Delphi library, ActiveX, and DLL interfaces. AddTagAttribute also now correctly handles the /Headers attribute with comma-delimited values written as PDF text string arrays.
v3.30.1 2026-05-19
- GetPDFUADiagnostics now includes a HEADING-LEVEL-SKIP:N check that detects heading level jumps in document order (e.g. an H1 immediately followed by an H3 without an H2 in between). The check performs a pre-order traversal of the entire structure element tree and counts each occurrence where the next heading level exceeds the previous by more than one. Generic H elements are treated as H1. Going back to a higher-level heading (H3 → H1) is not counted as a skip. WCAG 2.x Success Criterion 1.3.1 and ISO 14289-1 §7.1 require headings to nest without gaps.
v3.30.0 2026-05-19
- Structure element attributes are now supported for tagged PDF and PDF/UA documents. Three new API functions allow attributes to be attached to the structure element currently being built on the tag stack: AddTagAttribute (general-purpose, any owner/name/value), SetStructElemScope (convenience wrapper that sets the /Scope attribute under the Table owner, for TH header cells — ISO 32000-1 §14.8.5.7.2), and SetStructElemBBox (convenience wrapper that sets the /BBox attribute under the Layout owner, for figures and other visually-positioned elements — ISO 32000-1 §14.8.5.4). When the document is saved, attributes are written as /A attribute dictionaries in each structure element; multiple attributes from the same owner are grouped into one dict, and attributes from different owners are written as an array of dicts. All three functions are available in the Delphi library, ActiveX, and DLL interfaces.
v3.29.1 2026-05-19
- GetPDFUADiagnostics now includes two additional checks: whether any Figure structure elements in the document are missing an Alt text value (reported as FIGURE-NO-ALT:N, per ISO 14289-1 §7.5 and ISO 32000-1 §14.9.3), and whether any structure elements are still open because EndTag was not called (reported as STRUCT-UNCLOSED:N). The figure check performs a full recursive walk of the structure element tree, covering elements at all nesting depths.
v3.29.0 2026-05-19
- GetPDFUADiagnostics is a new diagnostic API that checks a document for potential PDF/UA-1 (ISO 14289-1) compliance issues and returns a newline-separated list of findings. Six checks are performed: whether MarkInfo/Marked is set (tagged PDF), whether the document catalog has a /Lang entry, whether ViewerPreferences/DisplayDocTitle is true, whether the XMP metadata contains a pdfuaid:part identifier, the count of non-exempt annotations lacking a Contents entry, and the count of embedded files lacking an AFRelationship entry. Each finding is identified by a short code (e.g. LANG-MISSING, ANNOT-NO-CONTENTS:3) followed by a human-readable description. Returns an empty string when no issues are found. Available in the Delphi library, ActiveX, and DLL interfaces.
v3.28.5 2026-05-19
- PDF/UA-1 annotation accessibility improvement: when a FileAttachment annotation has no Contents entry and no /T field, the filename from the annotation's embedded file specification (/FS /UF or /F) is now used as the fallback accessible description. This completes the annotation Contents fallback chain: /T → Link URI → Stamp name → FileAttachment filename. Screen readers receive the name of the attached file rather than silence, satisfying ISO 14289-1 §7.18.1 for the most common annotation types.
v3.28.4 2026-05-19
- PDF/UA-1 annotation accessibility improvement: when a Stamp annotation has no Contents entry (or an empty one) and no /T field, the stamp type name from the annotation's /Name entry is now used as the fallback accessible description (e.g. "Approved", "Draft", "Confidential", "Final"). This extends the annotation Contents fallback chain introduced in v3.28.3 to cover stamp annotations, which are common in workflows involving reviewed or approved documents and frequently lack an explicit Contents value.
v3.28.3 2026-05-19
- PDF/UA-1 annotation accessibility improvement: when a Link annotation has no Contents entry (or an empty one) and no /T field, the URI from the annotation's URI action is now used as the fallback accessible description. This applies only during SetPDFUAMode processing and only to Link annotations that carry a /URI action. Screen readers receive the URL as a last-resort label, satisfying ISO 14289-1 §7.18.1 in the common case where authors create hyperlinks without providing a human-readable description.
v3.28.2 2026-05-19
- SetEmbeddedFileAFRelationship is a new API for explicitly setting the AFRelationship value on an embedded file's file specification dictionary. Required by ISO 14289-1 (PDF/UA-1) §7.11, this allows callers to specify the semantic relationship of an embedded file to the document content by choosing from the five valid values: Source, Data, Alternative, Supplement, or Unspecified. When SetPDFUAMode is active, any embedded file without an AFRelationship key is automatically assigned Unspecified; use this function to override that default before saving. Available in the Delphi library, ActiveX, and DLL interfaces.
v3.28.1 2026-05-19
- When SetPDFUAMode is called on a document whose XMP metadata carries the generic library-default title rather than a document-specific one, the title is now automatically replaced with the value from the document's /Info Title entry (if one is present). This ensures that the pdfuaid:part-1 XMP packet reflects the actual document title rather than a placeholder, satisfying PDF/UA-1 verifier expectations.
- The XMP parser (LoadFromString) now reads the dc:title value from existing XMP metadata when a document is loaded, so round-tripping a PDF that already has dc:title correctly preserves that title instead of reverting to the default placeholder.
v3.28.0 2026-05-19
- BeginArtifactEx(ArtifactType, ArtifactSubtype) is a new tagged-PDF API that extends BeginArtifact to express both the artifact /Type and the Pagination /Subtype in a single call. When both parameters are non-empty the operator written is /Artifact << /Type /T /Subtype /S >> BMC, enabling fully specified Pagination artifacts such as headers and footers per ISO 32000-1 §14.8.2.2.1. If only one parameter is non-empty the corresponding single-key form is used. DLL entry points DLBeginArtifactEx and DLBeginArtifactExA are also exported.
v3.27.2 2026-05-19
- BeginArtifact now correctly distinguishes artifact types from pagination subtypes. When the argument is Pagination, Layout, or Page (artifact types per ISO 32000-1 §14.8.2.2.1 Table 330), the marked-content operator writes /Type rather than /Subtype. Other values such as Header, Footer, and Watermark continue to be written as /Subtype. This corrects the previously incorrect output that would write /Subtype /Pagination when the caller intended to mark a pagination artifact.
v3.27.1 2026-05-19
- When PDF/UA mode is active and the document contains embedded files, each file specification dictionary that lacks an AFRelationship entry now receives one automatically at save time. The value written is /Unspecified, satisfying the ISO 14289-1 §7.11 requirement that every embedded file carry an AFRelationship key. This applies both to files added via EmbedFile and to embedded files already present in a loaded document.
v3.27.0 2026-05-19
- AddRoleMap(CustomType, StandardType) is a new tagged-PDF API that registers a mapping from a custom (non-standard) structure element type name to a standard PDF structure type. When saved, the mappings are written to the RoleMap dictionary in the structure tree root, satisfying the ISO 14289-1 §7.1 requirement for documents that use application-specific tag names. Multiple mappings may be registered; duplicate keys are overwritten by the last call. DLL entry points DLAddRoleMap and DLAddRoleMapA are also exported.
v3.26.0 2026-05-19
- BeginTagEx(TagType, AltText, ActualText, Lang) is a new tagged-PDF API that extends BeginTag with an explicit natural-language attribute. When Lang is non-empty it is written to the structure element's /Lang attribute, enabling per-element language annotation required by ISO 14289-1 §7.2 for multilingual documents. Pass an empty Lang string to behave identically to BeginTag. DLL entry points DLBeginTagEx and DLBeginTagExA are also exported.
v3.25.1 2026-05-19
- Non-subsetted TrueType fonts loaded with the default Windows code page (WinAnsiEncoding) now receive a ToUnicode CMap stream, enabling reliable Unicode text extraction and copy/paste for these fonts. Previously a ToUnicode stream was only written when an explicit code-page override or Differences array was present; the common default-encoding path was missing it.
- The same fix applies to TrueType fonts loaded with an explicit non-default code page but no Differences array, and to fonts loaded via the packaged-font format.
v3.25.0 2026-05-19
- When PDF/UA mode is active, non-exempt annotations (all types except Widget, PrinterMark, and TrapNet) that lack a non-empty Contents entry now receive one automatically at save time. The annotation's /T (title / author) value is used as the fallback, satisfying ISO 14289-1 §7.18.1 for annotations that carry a title but no explicit accessible description.
v3.24.0 2026-05-19
- When PDF/UA mode is active, interactive form fields that lack a TU (tooltip / alternate description) entry now receive one automatically at save time. The field's partial name (/T entry) is used as the fallback value, ensuring screen readers can identify every field. Push buttons are correctly excluded from this requirement per ISO 14289-1 §7.18.4.
v3.23.1 2026-05-19
- GetInformation(200) returns '1' when PDF/UA-1 mode is active on the selected document, enabling callers to query conformance mode status at runtime.
- GetInformation(201) returns '1' for PDF/A-1a, '2' for PDF/A-1b, or an empty string when PDF/A mode is off.
- GetInformation(311) and GetInformation(312) now correctly return the version requirement string and feature name from the most recent version-lock conflict (previously advertised in the v3.20.3 entry but not yet implemented).
- GetInformation(313) returns the PDF version string at which the save target is currently locked, or an empty string for freely-versioning documents.
v3.23.0 2026-05-19
- SetMarkInfo(Marked) is now a public API, allowing the MarkInfo.Marked flag to be set independently of the full PDF/UA-1 setup performed by SetPDFUAMode. When Marked is 1, MarkInfo.Suspects is also set to false as required by ISO 14289-1 §7.18.6.
- When PDF/UA mode is active, all pages automatically receive a /Tabs /S entry at save time, satisfying the structure-based tab-order requirement of ISO 14289-1 §7.18.4.
- HTML reference documentation added for SetPDFUAMode, SetDocumentLanguage, SetMarkInfo, BeginTag, EndTag, BeginArtifact, and EndArtifact, with full syntax tables and usage examples.
v3.22.0 2026-05-19
- BeginTag(TagType, AltText, ActualText) opens a tagged-PDF structure element in the current content stream, writing a BDC operator with an auto-assigned MCID and registering the element in the document structure tree. TagType is any PDF standard structure type (P, H1, Figure, Table, etc.). AltText and ActualText are optional accessibility strings encoded as PDF text strings (UTF-16BE).
- EndTag closes the most recently opened structure element, writing the matching EMC operator to the content stream.
- BeginArtifact(SubType) marks a content region as a PDF artifact (pagination artefact, background, etc.), writing a BMC operator. SubType is optional; when provided it is written as /Artifact << /Subtype /SubType >>.
- EndArtifact closes the artifact region with an EMC operator.
- At save time, when any tagged structure elements have been registered, the library automatically builds the complete StructTreeRoot, assigns StructParents keys to affected pages, and writes the ParentTree number tree, satisfying ISO 32000-1 §14.7 requirements for tagged PDF.
- Standard Type 1 fonts (Helvetica, Times, Courier family, Symbol) and embedded Type 1 fonts with WinAnsi encoding now receive a ToUnicode CMap stream, enabling reliable Unicode text extraction and copy/paste for these font types.
v3.21.0 2026-05-19
- SetPDFUAMode(Language) activates PDF/UA-1 (ISO 14289-1) conformance mode: auto-bumps the document to PDF 1.7, writes MarkInfo.Marked and MarkInfo.Suspects, enables DisplayDocTitle in ViewerPreferences, sets Catalog.Lang when Language is non-empty, and writes the pdfuaid:part = 1 XMP namespace entry required by ISO 14289-1 Section 6.7.11.
- SetDocumentLanguage(Language) writes the Catalog /Lang entry directly, allowing the document language to be declared independently of PDF/UA mode.
- MarkInfo.Suspects is now set to false whenever MarkInfo.Marked is set to true, satisfying the ISO 14289-1 tagged-PDF structure requirement (Section 7.18.6).
- Encrypt now forces the CanCopyAccess (content copying for accessibility) permission flag when the document is in PDF/UA mode, as required by ISO 14289-1 Section 7.17.
- Choice (dropdown) form fields no longer carry a meaningless hardcoded tooltip value; TU is left unset so the caller can assign a meaningful label via the form field property API.
v3.20.3 2026-05-19
- Encrypt and AddSWFAnnotationFromFile now return 0 immediately with LastErrorCode 602 when the save version is locked below the minimum required by the selected encryption strength or annotation type, instead of silently proceeding and failing only at save time.
- GetInformation(311) and GetInformation(312) now reflect the conflicting version requirement at write time when a locked version blocks extension-level features such as AES-256 or RichMedia annotations.
v3.20.2 2026-05-19
- AddU3DAnnotationFromFile now auto-bumps the document version to PDF 1.6 when a 3D annotation is added to a lower-version document, consistent with the version auto-bump behaviour of all other PDF 1.6+ API entry points.
v3.20.1 2026-05-17
- PDF 1.2 save targets are now enforced as strict PDF 1.2 contracts. Saving PDF 1.3+ objects such as page TrimBox data under a PDF 1.2 target fails before output is written instead of emitting a mixed-version file.
- PDF 1.7 Adobe extension-level compliance is now part of save preflight. AESV3, AES-256, RichMedia, Projection, geospatial dictionaries, and ETSI signature subfilters are checked against the required ExtensionLevel.
- AES-256 encryption, RichMedia annotations, geospatial dictionaries, and ETSI signature subfilters now declare the matching Adobe Extensions entry when PDFlib auto-bumps a document to PDF 1.7 extension content.
- Append saves now use the same version-compliance gate as full saves.
- Bundled optional PDFium runtime DLLs were refreshed for Win32 and Win64. GDI+ remains the default renderer; PDFium stays opt-in via SetPDFiumFileName and SelectRenderer(3).
- Validation: Delphi Win32 and Win64 DUnitX suites passed 207/207 each, and C++Builder Win64x GoogleTest passed 61 tests with 2 existing sample-dependent tests skipped.
v3.20.0 2026-05-17
- Eight more PDFlib writer entry points now route through Phase 3 EnsureMinVersion so the document version auto-bumps to the minimum required by the feature being emitted: SetDocumentMetadata (PDF 1.4 - /Metadata XMP stream) SetPDFAMode(1 or 2) (PDF 1.4 - /MarkInfo + /OutputIntents) PageJavaScriptAction (PDF 1.5 - Page /AA + JavaScript) DocJavaScriptAction (PDF 1.4 - Catalog /AA + JavaScript) SetTabOrderMode (PDF 1.5 - Page /Tabs) NewOptionalContentGroup (PDF 1.5 - /Type /OCG) SetNeedAppearances (PDF 1.5 - AcroForm /NeedAppearances) NewFormField(ftSignature) (PDF 1.5 - AcroForm /SigFlags AppendOnly)
- Combined with the v3.15.0 set (SetTransparency, SetPageUserUnit, Encrypt, SetPageLayout) and the v3.17.0 set (eight JavaScript / embedded-file / XFA / SWF entries), PDFlib now auto-bumps FVersion across twenty-one writer entry points.
- NewOptionalContentGroup previously bumped FVersion directly; it now goes through EnsureMinVersion so LockSaveVersion is honoured and the bump is recorded in AutoBumpedFeatures.
v3.19.0 2026-05-17
- Save-time and load-time PDF version compliance now also recognises four previously deferred features: Btn /Ff bit 15 NoToggleToOff (radio-button-only) -> PDF 1.4 DeviceN /Subtype /NChannel (colour-space refinement) -> PDF 1.6 FontFile3 /Subtype /OpenType (font program type) -> PDF 1.6 Sig /SubFilter ETSI.CAdES.detached or ETSI.RFC3161 -> PDF 1.7
- The NChannel rule matches the DeviceN colour-space array form [/DeviceN names alternateSpace tintTransform attributes] when the attributes dictionary at index 4 carries /Subtype /NChannel.
- The FontFile3 OpenType rule fires only when the stream is reached through a parent key named 'FontFile3', so unrelated streams that happen to carry /Subtype /OpenType are not flagged.
- The PDFFeatureRules table now carries 103 rules (99 + 4 new).
v3.18.6 2026-05-17
- Save-time and load-time PDF version compliance now recognises /AA (additional actions) with container-type awareness: Catalog /AA (document-level triggers) -> PDF 1.4 Annot /AA (annotation triggers) -> PDF 1.4 Page /AA (page triggers) -> PDF 1.5
- Form-field /AA (PDF 1.2) remains covered by the existing PDF 1.3 save contract; no rule needed.
- The PDFFeatureRules table now carries 99 rules (96 + 3 new).
v3.18.5 2026-05-17
- Save-time and load-time PDF version compliance now correctly classify Page /Tabs as a PDF 1.5 feature; it was previously misclassified as PDF 1.4. PDF 1.4 spec changes document (Adobe TN #5409) does not list /Tabs, and PDF 1.5 Table 8.10 introduces "Tabs (Optional; PDF 1.5)".
- New rule: AcroForm /NeedAppearances is recognised as a PDF 1.5 feature per PDF 1.5 Table 218.
- The PDFFeatureRules table now carries 96 rules (95 + 1 new).
v3.18.4 2026-05-13
- PDFlibZLib now always uses the bundled static zlib-ng object backend on normal library builds, removing the remaining System.ZLib fallback path.
- The zlib-ng regression coverage now includes boundary-sized payloads, PNG-like scanline data, stored multi-block streams, and known zlib streams across Delphi and C++Builder test runners.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 194/194 each, and C++Builder Win64x GoogleTest passed 58 tests with 2 existing sample-dependent tests skipped.
v3.18.3 2026-05-12
- Delphi and C++Builder demos that generate PDF or text output now open the generated document automatically after a successful save.
- Installer packaging now keeps build artifacts out of demo folders and makes C++Builder samples plus DLL and ActiveX/OCX modules opt-in components; their matching files are installed only when the component is selected.
v3.18.2 2026-05-12
- The Delphi and C++Builder EditFormField demos now clear /NeedAppearances before updating field values, so every edited text field gets a refreshed normal appearance stream in the saved PDF.
- This keeps the saved /AP stream in sync with the stored /V value and avoids viewer-dependent differences where focusing the field reveals text that was missing from the static field appearance.
v3.18.1 2026-05-10
- Save-time and load-time PDF version compliance now also recognises bit-level form-field /Ff flags and the AcroForm /SigFlags AppendOnly bit: /Ff bit 21 (FileSelect, mask 1048576) -> PDF 1.4 /Ff bit 22 (MultiSelect, mask 2097152) -> PDF 1.4 /Ff bit 23 (DoNotSpellCheck, mask 4194304) -> PDF 1.4 /Ff bit 24 (DoNotScroll, mask 8388608) -> PDF 1.4 /Ff bit 25 (Comb, mask 16777216) -> PDF 1.5 /Ff bit 26 (RichText / RadiosInUnison, 33554432) -> PDF 1.5 /Ff bit 27 (CommitOnSelChange, mask 67108864) -> PDF 1.5 /SigFlags bit 2 (AppendOnly, mask 2) -> PDF 1.5
- /Parent inheritance is not followed: only dictionaries that explicitly carry /Ff or /SigFlags trigger the rules.
- The PDFFeatureRules table now carries 95 rules (87 + 8 new bit-level).
- Validation: Delphi Win32 and Win64 DUnitX suites passed 191/191 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.18.0 2026-05-10
- Save-time and load-time PDF version compliance now also recognises nine more sub-key and bit-level features: bit-level annotation flags (/F mask): Locked (128) -> PDF 1.4 ToggleNoView (256) -> PDF 1.5 LockedContents (512) -> PDF 1.7 distinctive catalog and page sub-keys: /BoxColorInfo (page) -> PDF 1.4 /Permissions, /Legal, /PresSteps -> PDF 1.5 /VP (page geospatial viewport) -> PDF 1.6 /Collection (catalog portable collection) -> PDF 1.7
- The PDFFeatureRules table now carries 87 rules (78 chapter-level + 9 sub-key / bit-level).
- Validation: Delphi Win32 and Win64 DUnitX suites passed 189/189 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.17.0 2026-05-10
- Eight more PDFlib writer entry points now route through Phase 3 EnsureMinVersion so the document version auto-bumps to the minimum required by the feature being emitted: AddLinkToJavaScript, SetOpenActionJavaScript, AddGlobalJavaScript, FormFieldJavaScriptAction (PDF 1.3 - JavaScript actions) AddEmbeddedFile, AddFileAttachment (PDF 1.3 - file attachments) SetXFAFromString (PDF 1.5 - XFA forms) AddSWFAnnotationFromFile (PDF 1.7 - RichMedia annotation)
- Combined with the v3.15.0 set (SetTransparency, SetPageUserUnit, Encrypt, SetPageLayout) PDFlib now covers thirteen high-version writer entry points end-to-end.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 187/187 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.16.3 2026-05-10
- New PDFlib API: LockSaveVersion(Version) pins the document at Version and stops Phase 3 writer-side EnsureMinVersion from auto-bumping above it. UnlockSaveVersion clears the lock.
- The save-time gate is unchanged: writer-emitted features above the locked version still produce LastErrorCode 602 at save time, instead of silently bumping the header.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 184/184 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.16.2 2026-05-10
- Loaded PDFs now expose a contributor-only view of the load-time feature detection through GetInformation(103) ("ContributorFeatures"). The list contains only features whose minimum required version is strictly greater than HeaderVersion (key 100), so it directly answers "why is the effective version higher than the file header?".
- GetInformation(101) ("DetectedFeatures") is unchanged and still lists every matched feature regardless of contribution.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 181/181 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.16.1 2026-05-10
- Expanded loader-side detection test coverage with six additional synthetic fixtures: in-page transparency ExtGState (no version bump), Catalog /MarkInfo (PDF 1.3 -> PDF 1.4), /OCProperties + OCG content (PDF 1.4 -> PDF 1.5), /Type /3DStream (PDF 1.5 -> PDF 1.6), a multi-feature combination fixture, and a snapshot-stability check.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 179/179 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.16.0 2026-05-10
- Loaded PDF documents now go through a content-driven version detection pass: every indirect object is walked through the feature-to-minimum- version table used by the save-time gate, and FVersion is bumped above the literal %PDF-X.Y header value when content actually requires a higher version. For example a /UserUnit page entry bumps the effective version to PDF 1.6 even when the file header says PDF 1.4.
- New GetInformation keys: 100 returns HeaderVersion (literal %PDF-X.Y), 101 returns DetectedFeatures (CRLF-delimited features matched on load), 102 returns AutoBumpedFeatures (CRLF-delimited features that triggered writer-side EnsureMinVersion).
- The save-time gate is unaffected: documents whose effective version was bumped on load, then explicitly downgraded with SetInformation(0, ...), still produce LastErrorCode 602 at save time.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 173/173 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.15.0 2026-05-10
- Writer entry points that produce features requiring a particular minimum PDF version now auto-bump the document's PDF version automatically. Calling SetTransparency on a document marked as PDF 1.3 now promotes the header to PDF 1.4 instead of failing the save with LastErrorCode 602.
- Wired the same auto-bump into SetPageUserUnit (>=1.6), Encrypt with Strength 1/2/3/4 (>=1.4/1.6/1.7/1.7 respectively), and the two-page variants of SetPageLayout (>=1.5).
- Behaviour change versus 3.14.x: applications that previously relied on the v3.12.6 "save target rejects writer-emitted features" gate now succeed at the bumped version. Loaded PDFs that already contain higher- version features still go through the existing save-time gate, so loading a tagged PDF and selecting PDF 1.3 still fails with LastErrorCode 602.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 170/170 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.14.3 2026-05-10
- Save-time PDF version compliance now also recognises the remaining PDF 1.6 3D dictionary types (/Type /3DStream /3DRef /3DBackground /3DRenderMode /3DLightingScheme /3DCrossSection /3DNode) and the PDF 1.7 Redact, RichMedia, and Projection annotation subtypes plus the /Type /Requirement and /ReqHandler companion dictionaries.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 168/168 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.14.2 2026-05-10
- Save-time PDF version compliance now also recognises PDF 1.5 features: /XFA forms, /AlternatePresentations, /Renditions name tree, the /Type /Rendition /MediaCriteria /MediaPermissions /MediaPlayers multimedia dictionaries, and the Screen annotation subtype.
- Saving as PDF 1.4 now rejects documents that carry these features with LastErrorCode 602.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 166/166 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.14.1 2026-05-10
- Save-time PDF version compliance now also recognises PDF 1.4 features: tagged-PDF /StructTreeRoot /MarkInfo and StructElem dictionaries, the document /Lang and page /Tabs entries, /OutputIntents and /OutputIntent dictionaries, the /UR3 usage-rights signature, and the PDF 1.4 annotation subtypes Polygon, PolyLine, Caret, Ink, Popup, and Watermark.
- Saving as PDF 1.3 now rejects documents that carry these features with LastErrorCode 602.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 165/165 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.14.0 2026-05-10
- Save-time PDF version compliance now also recognises PDF 1.3 features such as smooth shading, function objects, ICCBased and DeviceN colour spaces, /TrimBox /BleedBox /ArtBox page entries, /ToUnicode CMaps, file attachment and /Sound and /Movie annotations, /Type /Filespec and /Type /EmbeddedFile dicts, the /Group /EF /Alternates /Mask keys, and JavaScript actions.
- PDF 1.2 callers now save under the PDF 1.3 contract: the literal %PDF-1.2 header is preserved, but the gate accepts PDF 1.3 features. PDF 1.4 and later features are still rejected with LastErrorCode 602.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 162/162 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.13.0 2026-05-10
- Refactored the PDF version-compliance gate that rejects later-version features at save time into a dedicated module so the rule set can grow without churning the document core.
- No user-visible behaviour change versus v3.12.7: the same out-of-version features are still rejected with LastErrorCode 602.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 155/155 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.12.7 2026-05-09
- Expanded automated test coverage for the PdfToImage direct-access rendering workflow in both Delphi DUnitX and C++Builder GoogleTest suites.
- The Delphi VCL GUI test runner now registers the Syntax and XRef fixtures, matching the console runner coverage.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 147/147 each, and C++Builder Win64x GoogleTest passed 57/57.
v3.12.6 2026-05-09
- Saving as PDF 1.3, 1.4, 1.5, 1.6, or 1.7 now enforces the selected version as the full-save output contract.
- Full saves remove catalog /Version overrides, remove unsupported catalog extension and metadata entries for lower targets, and suppress PDF 1.4 XMP metadata streams when saving as PDF 1.3.
- SaveToFile, SaveToString, and SaveToStream now fail with LastErrorCode 602 when the selected PDF target version is lower than features still present in the document, such as transparency, optional content, JPX, UserUnit, 3D, or AES crypt-filter features.
v3.12.5 2026-05-09
- Improved PDF 1.7 literal string parsing so unknown escape sequences ignore the backslash as required by the standard.
- Literal string octal escapes now consume only octal digits and preserve a following non-octal digit as regular string data.
- Added regression coverage for unknown literal-string escapes and mixed octal/non-octal escape sequences.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 141/141 each.
v3.12.4 2026-05-09
- Improved PDF 1.7 lexical parsing so name objects now stop correctly at the right-brace delimiter.
- Fixed SmartAccess loading of xref stream compressed-object entries whose object stream number is larger than the PDF byte length.
- Added regression coverage for right-brace name delimiters and sparse compressed-object xref stream entries.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 139/139 each.
v3.12.3 2026-05-08
- Improved PDF 1.7 encrypted-document compatibility for standard security handler files that use StrF, StmF, EFF, Identity, None, or named StdCF-style crypt filters.
- Metadata streams now honour EncryptMetadata=false during decrypt, encrypt, and copy/save workflows instead of being processed like ordinary streams.
- Embedded file streams now carry /Type /EmbeddedFile and use the embedded-file crypt-filter decision path when encrypted documents are loaded or saved.
- External embedded file streams now promote FDecodeParms to DecodeParms when FFilter is promoted to Filter, preserving stream decode parameters.
- New AES encrypted PDFs now write crypt-filter Length values as bit lengths, matching the PDF 1.7 crypt filter dictionary contract.
- XRef stream Prev/XRefStm values and large numeric offsets now keep 64-bit precision through parser and SmartAccess paths.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 137/137 each.
v3.12.2 2026-05-08
- Improved PDF 1.7 stream decoding compatibility. Generic stream decoding now honours /DP as a DecodeParms alias, resolves indirect decode-parameter array entries, and accepts the /AHx and /LZW standard filter abbreviations.
- Large-file PDF output now writes xref, startxref, linearization, and digital signature ByteRange offsets through 64-bit formatting paths instead of narrowing those values through 32-bit integer helpers.
- Loaded documents now treat a catalog /Version entry as the effective PDF version when it is newer than the file header version.
- Rewritten xref-stream trailers no longer retain stream-only DecodeParms keys when PDFlibPas saves them as classic trailer dictionaries.
- Validation: Delphi Win32 and Win64 DUnitX suites passed 134/134 each.
v3.12.1 2026-05-06
- Generated PDFs now open with the first page sized to the viewer window's available height, so the entire first page is visible top-to-bottom at the largest zoom that fits the window. Configure a custom OpenAction (SetOpenActionDestination, SetOpenActionMenu, SetOpenActionJavaScript) on the document to override this default.
v3.12.0 2026-05-06
- The Windows static backends now include libjpeg-turbo NASM SIMD objects for Win32 and Win64, plus zlib-ng x86 SIMD dispatch objects for the Win64x zlib-ng set.
- Reworked the zlib-ng rebuild scripts so Win64x bcc64x and diagnostic MSVC builds compile the generic, SSE2, SSSE3, SSE4.1/SSE4.2, PCLMULQDQ, and AVX2 source files with per-file feature flags instead of relying on one global compiler switch.
- Added 32-byte aligned malloc/calloc/realloc/free CRT stubs for the static C libraries and fixed TPDFJPEGImage.Compress to release jpeg_mem_dest buffers through the same C free path that allocated them.
- Expanded the public validation notes to call out the strict automated coverage behind this release: library builds, compression round trips, HelloWorld /FlateDecode output, JPEG rendering, image workflows, fonts, forms, security, signing, printing, and C++Builder demo-derived workflows.
v3.11.0 2026-05-05
- Switched Windows Flate compression and decompression to zlib-ng in zlib-compatible mode. Win32, Delphi Win64, and C++Builder Win64x now link ABI-matched zlib-ng static object sets from Lib\thirdparty\Win32, Lib\thirdparty\Win64, and Lib\thirdparty\Win64x.
- The Win64 path no longer routes through Delphi's System.ZLib unit, so PDF stream compression/decompression can benefit from the zlib-ng backend just like the 32-bit build.
- Added a small zlib-ng bridge object for Win64 builds so Pascal code keeps stable zlib-compatible entry points while Delphi and C++Builder consume their own linker-compatible object sets.
- Updated all C++Builder demo projects to define PDFLIB_CPPBUILDER, matching the GoogleTest runner and preventing Win64x demos from linking the Delphi Win64 zlib-ng objects.
v3.10.3 2026-05-01
- Extended the C++Builder GoogleTest suite to cover every demo under Demo\C++Builder. The 7-fixture phase-1 layout grew to 15 fixtures / 52 GoogleTest cases, all passing on Win64x. Newly covered demos: AddFormattedTitle, AddTextImage, AddTrueTypeSubsettedFont, AddWebLink, CanvasText, CaptureToNewSize, CopyPageRanges, CreateWithImage, CreateWithImageToStream, DoInTheStream, DrawWrappedText, EditFormField, EmbeddedFonts, ExtractAnnotAttach, ExtractEmbeddedFonts, ExtractImage, ImageToPdf, ImportEMF, MultiFunction (renderer switch), PageOperations, PdfDecrypt, PdfPermission, PrintPDF, TextMeasure, TextPaging.
v3.10.2 2026-05-01
- Added a C++Builder GoogleTest runner under Tests\C++Builder that exercises Lib\PDFlibrary.pas through the same {$JPHNE}-emitted HPP headers used by the C++Builder demos. The first phase mirrors seven core Delphi scenarios (HelloWorld, DrawShapes, CreateTable, PdfEncrypt, ExtractText, PdfSigning, PdfToImage rendering) as 17 GoogleTest cases, all passing on Win64x.
- Extended the Delphi DUnitX suite with Tests.Print covering the PrintPDF and ShowPrinterBins demos (default-printer enumeration, custom-printer setup, print options, redirect-to-file print job) and a renderer-switch test in Tests.Render exercising the MultiFunction demo's GDI+ / PDFium / Cairo engine selection on the same source PDF.
v3.10.1 2026-05-01
- Added 57 named page sizes to SetPageSize so the same canonical page-size names work here too: SIZE8X11, QUADA0, DOUBA0, B0PLUS, ENVB4/B5/C6/DL/MONARCH, ENV9/10/11, ANSIA/B/C/D/E, ARCHA/B/C/D/E1/E, SHIROKU, G1K, USBC/EUBC/ASBC, ID1/ID2/ID3, ONEINCH/TWOINCH/L2INCH/USVISA, P2R..P24R / S8R / P4D photo prints, plus the Chinese / Taiwanese octavo and sextodecimo sheet formats LARGE/STANDARD/CROWN/ROC 8K and the matching 16K halves.
v3.10.0 2026-04-30
- Added native C++Builder versions for every Delphi sample under Demo. The PDF-creation, page-manipulation, font, image, security, signing, rendering and printing demos can now be built and run from C++Builder without any Delphi-side wrapper.
- Each new demo lives in Demo\C++Builder\<Name>\ as a console project that consumes Lib\PDFlibrary.pas directly and ships the input files needed to run.
- Added a brief English Readme.txt to every Delphi demo folder describing what the demo shows, the API it focuses on, and how to run it; an HTML overview at Demo\Delphi\index.html links to all of them grouped by topic.
- Mirrored the same Readme.txt for every C++Builder demo with a Run section rewritten for the console workflow (argv arguments instead of Open/SaveDialogs); a matching Demo\C++Builder\index.html lists every C++Builder demo with the same topic groups.
- Fixed a memory leak in the ImportEMF demo (the TPDFlib instance was created but never freed).
v3.9.14 2026-04-30
- Fixed the page-range copy demo so it actually copies pages instead of always reporting failure.
- Tidied up the wrapped-text and HTML pagination demos so each one focuses on its own API and runs from a single button.
- Renamed two demo projects (EmbeddedFonts and PdfPermission) so the compiled executables match the folder names instead of older prototype names.
v3.9.13 2026-04-30
- Fixed a stream-position bug in the internal buffer reader: two-byte word reads were advancing the read cursor by four bytes instead of two. In buffers longer than two bytes, subsequent reads landed at the wrong offset and silently returned incorrect data. The effect was most visible when parsing binary data structures that interleave byte and word reads.
- Introduced an automated DUnitX test suite (console and VCL GUI runners) covering utility units — buffer, AES, ZLib, Unicode, and digest hashing — and library-level workflows including document creation, save-to-file and save-to-stream, load round-trips, and AES-128/AES-256 encryption.
v3.9.12 2026-04-30
- GDI+ image rendering now defaults to smooth, high-quality bicubic interpolation when scaling raster images to screen or export resolution. Previously the default was nearest-neighbour, which produced visible staircase artefacts on small images (logos, thumbnails) enlarged for screen preview or high-DPI export. Callers that prefer the sharper nearest-neighbour mode can restore the old behaviour via SetGDIPlusOptions.
v3.9.11 2026-04-30
- Fixed Cairo rendering of PDF images that use colour-key transparency (a /Mask colour-range array in the image dictionary). Previously, when a page contained an image with this form of transparency, the Cairo renderer omitted the image entirely rather than compositing it against the page background. The fix derives a per-pixel alpha channel from the declared colour-key ranges and renders the result as a transparent image, producing output visually consistent with the GDI+ renderer.
v3.9.10 2026-04-30
- Fixed a Cairo rendering regression where all page content following a clipped-image sequence was incorrectly confined to the image's clipping rectangle. PDF pages that save the graphics state, apply a clip path, paint an image, then restore the state — a common layout technique for framed or bordered images — would render all subsequent text, shapes, and graphics inside the clipped region only. Cairo state save and restore now map correctly to the PDF q/Q operators, so the clipping region is discarded after the image is drawn.
v3.9.9 2026-04-29
- Added a Cairo-based PDF rendering engine as a third rendering option alongside GDI+ and PDFium. Call SelectRenderer(2) before rendering to activate it; the engine requires cairo.dll from the bundled DLL\Cairo folder. Cairo rendering supports the same output modes as GDI+: bitmap file and stream export (BMP, JPEG, PNG, GIF, TIFF, G4 TIFF), device-context rendering, and direct printer output.
- The MultiFunction View/Print demo now exposes a three-way renderer selector so users can compare GDI+, PDFium, and Cairo output side-by-side on the same document without any code changes.
v3.9.8 2026-04-29
- Suppressed two spurious compiler diagnostics in the Win32 C-runtime shim that appeared on RAD Studio 13.1 and later. A deprecation warning (W1000) was raised because a compiler-version capability guard was not propagated to compilers newer than Delphi 2009, causing them to compile against a deprecated memory-manager API. An unused-variable hint (H2164) was raised for an internal compatibility variable only needed for Delphi 7 builds; it is now scoped to that version's conditional block. Both issues were diagnostic-only with no runtime impact.
v3.9.7 2026-04-29
- Added optional PDFium-based page rendering on Windows, including BMP stream rendering, device-context rendering, memory rendering, and printer output.
- Updated the Delphi MultiFunction View/Print demo with a renderer selector so users can switch between the existing GDI+ renderer and PDFium.
v3.9.6 2026-04-29
- Added separate Inno Setup scripts for the full PDFlibPas package and the trial package, with release-focused exclusions for source-control metadata, build outputs, IDE caches, local agent files, and bundled third-party source trees that are not part of the shipped package.
- The trial installer now builds and packages trial binary libraries for RAD Studio 11.3, 12.3, and 13.1, plus the trial Delphi demos, before the setup executable is generated.
v3.9.5 2026-04-29
- Fixed Win32 library builds under RAD Studio 9.0 / Delphi XE2. The build script was passing a DCU output-directory flag that only exists from Delphi 2010 onward; XE2's compiler interpreted the flag differently, producing a garbled output path and a fatal error before any source file was processed. The script now selects the appropriate flag automatically based on the target compiler version.
- Corrected a related compiler-version guard in the library source that was calling a name-qualified runtime function introduced in XE4 under an XE2+ condition. Builds targeting XE2 and XE3 now resolve the correct compatibility import instead.
v3.9.4 2026-04-29
- Fixed printer setup for network and server-shared printers by applying paper tray, media, duplex, quality, and other print settings through the printer DEVMODE handle instead of the printer device context handle.
v3.9.3 2026-04-29
- Refreshed the bundled AES backend to Brian Gladman's 2018 AES sources on both Win32 and Win64. Reproducible build scripts now allow the static AES objects to be rebuilt from source at any time. An ABI defect in the Pascal bindings was discovered and fixed in the process: the AES-CBC encrypt and decrypt functions were missing their C calling-convention declaration, so Win32 builds silently passed arguments in the wrong register order, potentially producing incorrect encrypted output. Win64 builds were unaffected because the platform enforces a uniform calling convention.
- Hardened the third-party rebuild scripts so the MSVC-based zlib, JPEG, and CRT-stub scripts can be launched from the repository root as well as from the thirdparty directory; previously they required the working directory to be set to the thirdparty folder.
v3.9.2 2026-04-29
- Upgraded the JPEG 2000 backend from the legacy OpenJPEG 1.5 to OpenJPEG 2.5.4 on both Win32 and Win64. Both platforms now use static object linking, so JPEG 2000 encoding and decoding work without an additional runtime DLL. The modern codec brings current JP2/J2K header handling, a callback-driven stream API, and accumulated bug and security fixes from the upstream project. The public TJpeg2000Bitmap API is unchanged.
v3.9.1 2026-04-29
- Fixed JPEG page rendering and image export after the libjpeg-turbo upgrade, restoring PdfToImage JPG conversion and TPDFJPEGImage.SaveToStream output on Win32 and Win64.
- Corrected Win32 libjpeg-turbo ABI bindings so callbacks, structure alignment, boolean fields, and memory-backed JPEG destinations match libjpeg-turbo 3.1.90.
- Fixed Win32 FlateDecode stream decompression with the bundled zlib 1.3.2 backend, restoring PDF xref stream loading for files such as the PdfToImage sample document.
v3.9.0 2026-04-29
- Upgraded the bundled JPEG 2000 backend from legacy OpenJPEG 1.5 to OpenJPEG 2.5.4. JPEG 2000 loading and saving now use the modern codec, callback-driven stream API, and current JP2/J2K header handling while preserving the public TJpeg2000Bitmap API.
- JPEG 2000 output now selects a valid OpenJPEG resolution count for small images automatically, and the Win32 static backend no longer depends on missing MSVCRT helper exports.
v3.8.1 2026-04-29
- Eliminated all 16 cosmetic linker W1028 "Bad global symbol definition" warnings on Win32 and Win64. Source-level renames remove the redundant Pascal-side duplicates (jpeg_std_error and the jmemnobs allocator stubs now resolve solely from the obj layer); the three remaining bcc32 / vc64 obj symbols (jpeg_natural_order, jpeg_aritab, jpeg_nbits_table) that must stay link-resolved against Pascal-side data are now stripped of their COFF symbol names via an ObjConv post-processing pass during thirdparty\build-jpeg-vc64.bat. No public API change; clean linker output for both Delphi Win32 and Win64 builds.
v3.8.0 2026-04-29
- Win64 JPEG codec upgraded from IJG-style libjpeg to libjpeg-turbo 3.1.90, completing the JPEG migration started in v3.7.0 (Win32). Both Win32 and Win64 paths now share the same modern JPEG codec, with the same SIMD- optimised inner loops and 30+ accumulated CVE / fuzz fixes from upstream. Public PDFlibPas API unchanged.
v3.7.0 2026-04-28
- Win32 JPEG codec upgraded from IJG libjpeg-6b to libjpeg-turbo 3.1.90. Significantly faster JPEG encode/decode through SIMD-optimised inner loops, plus the 30+ CVE / fuzz fixes accumulated in libjpeg-turbo upstream. Public PDFlibPas API (TPDFJPEGImage class, DumpJPEG functions) is unchanged; existing PDF/JPEG code paths run faster with no source changes required.
v3.6.0 2026-04-28
- Win32 zlib upgraded from 1.2.x to 1.3.2. Includes the standard 25+ CVE / fuzz fixes accumulated upstream since 1.2.8, plus the new inflateBack9 / inflateTree9 entry points used by 64-bit-window streams. Public PDFlibPas API (DeflateStr / InflateStr / InflateStrParms) is unchanged.
- Win64 zlib path is unchanged in this release - it continues to use the Delphi-bundled System.ZLib unit.
- Activated the Win64 link-time CRT shim PDFlibCLibs.pas (introduced in v3.5.0) for the Win32 zlib path, providing memcpy / memset / malloc / free symbols that the new zlib 1.3.2 obj files reference.
v3.5.0 2026-04-28
- Vendored fresh build infrastructure for the bundled C image / compression libraries: zlib 1.3.2, libjpeg-turbo 3.1.90, libtiff 4.7.1. Build scripts for both Embarcadero bcc32 (Win32) and MSVC cl.exe (Win64) live in Lib/thirdparty/ alongside the source trees, so anyone with RAD Studio + VS2022 can rebuild the static obj files from clean source.
- Added build infrastructure for OpenJPEG 2.5.4. The OpenJPEG source tree itself is fetched independently by the user (git clone uclouvain/openjpeg into Lib/thirdparty/OpenJPEG/) so it can be upgraded without touching PDFlibPas's build configuration.
- Added Lib/PDFlibCLibs.pas, a Win64 link-time CRT shim used by the Win64 backend. It bridges the gap between the MSVC-compiled C obj files and Delphi's Win64 linkers (dcc64 / Win64x ld.lld / BCB ilink64), which do not pull in msvcrt.dll automatically.
v3.4.0 2026-04-28
- Hardened encryption key, AES initialization vector and Perms permission block generation against predictable random number sources. Encrypted PDFs produced on systems started near the same wall-clock time are no longer trivially correlatable; AES-256 documents now keep their full key strength.
- Hardened image dictionary parsing against malformed or hostile PDFs that declare unreasonable Width, Height, BitsPerComponent or DeviceN component counts. Out-of-range values are clamped before any pixel-buffer arithmetic, preventing crashes when opening such files.
- Hardened cross-reference and page-tree traversal against documents whose /Prev xref chains or /Parent page links form a cycle or are excessively deep. The reader now rejects malformed structures cleanly instead of recursing until it runs out of stack.
v3.3.1 2026-04-27
- Streamlined the per-component Windows build scripts. The DLL/, OCX/ and Dylib/ folders no longer carry separate build12-* / build13-* variants: each platform now has a single build-Win32 / build-Win64 script that pins to the latest RAD Studio and accepts an optional "debug" argument.
- Added inline rationale comments around the PDFlibRenderer.pas render fixes that were already present in the initial Git baseline. The comments document why SetPen scales stroke widths by the active canvas transform, and why Type 3 font CharProc d0/d1 operators must consume their operands. No runtime behaviour changed.
v3.3.0 2026-04-26
- Fixed transformed stroke rendering in PDFlibRenderer.pas. SetPen now applies the current canvas-transform scale to PDF line widths before calling Picasso, preventing oversized or undersized strokes on paths whose coordinates have already been transformed. This fixes Type 3 glyph outlines that could render as thick, irregular blocks.
- Fixed Type 3 font CharProc d0/d1 handling in the content stream parser. d0 now consumes its two width operands, and d1 consumes its six width/bounding box operands before later drawing commands run, preventing stale operands from corrupting glyph or path geometry.