PDFiumPas Release Notes
Version history for PDFiumPas user-visible features, fixes, viewer improvements, document generation, PDF/A output, rendering, and documentation updates
Last release
- Latest version: 2.58.3; Release date:
Version 2.58.3
Added
- PDF/X validation now reports
pvxiColorSpaceForbiddenwhen a PDF/X-1a candidate carries/DeviceRGB,/CalRGBor/Lab, which ISO 15930-1 §6.2 excludes from its CMYK exchange - The check is gated on PDF/X-1a alone, so PDF/X-3 and later keep permitting RGB and the device-independent spaces they pair with the output intent
- Only unambiguous colour space name tokens are tested; an
ICCBasedstream needs its/Nresolved and stays with the object-model layer - Delphi, Lazarus, and C++Builder tests cover a flagged RGB space, a flagged Lab space, an accepted CMYK and grayscale pair, and the permitted case on PDF/X-3
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.58.3 consistently
Version 2.58.2
Added
- PDF/X validation now reports
pvxiTransparencyForbiddenfor a transparency group or an active soft mask, which ISO 15930-1 §6.2 (PDF/X-1a) and ISO 15930-3 §6.3 (PDF/X-3) forbid - The check is gated on the detected conformance, so PDF/X-4 and PDF/X-6 keep permitting transparency and a file whose level could not be identified is never flagged for a rule that may not apply to it
- A soft mask explicitly switched off with
/SMask /Noneis not treated as transparency PdfHasActiveSMaskmoved fromFPdfPdfainto theFPdfPdfCommoninterface so every validator can share one soft-mask rule- Delphi, Lazarus, and C++Builder tests cover a flagged group on X-1a, a flagged soft mask on X-3, a disabled soft mask, and the permitted case on X-4
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.58.2 consistently
Version 2.58.1
Added
- PDF/X validation now checks the shape of the output intent required by ISO 15930-7 §6.2.4:
pvxiOutputIntentSchemereports a subtype that is present but is not/GTS_PDFX, andpvxiOutputIntentMissingIdentifierreports a missing/OutputConditionIdentifier - The subtype is matched as a whole name token, so a longer name such as
/GTS_PDFXVersionno longer passes, while a#xxescaped spelling of the same name still does - An output intent that carries no subtype at all is left alone, because its absence is already reported by the marker-level issues
- Preflight reports file both issues under the output intent category and suggest the fix
- Delphi, Lazarus, and C++Builder tests cover the accepted subtype, a PDF/A subtype, a longer name token, an absent subtype, and a missing condition identifier
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.58.1 consistently
Version 2.58.0
Changed
- All 35 callbacks PDFium invokes from its own C++ frames (form fill, XFA, JavaScript platform, progressive render pause, and stream read and write) now contain any Pascal exception and return the documented failure value instead of unwinding across the language boundary
- An event handler that raises, a failing allocation, or an unexpected error inside a callback can therefore no longer take the process down or leave PDFium in an undefined state
Fixed
- Registering a form timer leaked its entry when the underlying timer could not be created
Added
- Delphi, Lazarus, and C++Builder tests now cover saving into a destination stream that refuses writes and assert the document stays usable and savable afterwards
Version 2.57.8
Fixed
- Older Delphi releases (XE5 and earlier) stopped compiling the trial library with
E2003 Undeclared identifier: 'GetTickCount64'inFPdfPades.pas, because the Windows unit shipped with those compilers does not export the symbol - The same compilers also failed on
GetUserDefaultLocaleNameinPDFium.pasand on theTBytestoarray of Byteassignment inGetXfaFormPackets, so the XFA locale callback and packet snapshot now build on those compilers as well
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.8 consistently
Version 2.57.7
Changed
- Every save-side rewrite now truncates the destination stream before writing instead of only rewinding it, so a caller-supplied buffer that already held a longer document cannot keep a stale tail past the new
%%EOF - Delphi, Lazarus, and C++Builder tests now cover saving into a pre-filled stream
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.7 consistently
Version 2.57.6
Fixed
- The object scan that precedes encryption accepted digit runs of any length, so a long number anywhere in the file could wrap into a negative or bogus object number and add a phantom entry to the rebuilt cross-reference table
- Object numbers above the ISO 32000-1 Annex C limit and generations above 65535 are now rejected as object headers instead of being truncated
Added
- Delphi, Lazarus, and C++Builder tests now assert the exact in-use entry count of the rebuilt table
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.6 consistently
Version 2.57.5
Fixed
- Encrypting with
EncryptMetadata = Falsewrote/EncryptMetadata falseinto the Encrypt dictionary but still ciphered the document metadata stream, so a reader following that declaration found unreadable XMP - A
/Type /Metadatastream is now copied unchanged when metadata encryption is switched off, while every other stream is still encrypted
Added
AnsiNameTokenMatchesKeyis now part of theFPdfPdfCommoninterface for delimiter-aware name comparisons- Delphi, Lazarus, and C++Builder tests now cover both metadata encryption modes
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.5 consistently
Version 2.57.4
Fixed
- The cross-reference table rebuilt while encrypting omitted the mandatory object 0 free-list head required by ISO 32000-1 §7.5.4, so its first subsection started one object late
- Every rebuilt entry claimed generation 0; objects written with a higher generation now keep it, so the table agrees with the object headers it points at
Added
- Delphi, Lazarus, and C++Builder tests now cover the free-list head entry and generation preservation in the rebuilt table
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.4 consistently
Version 2.57.3
Fixed
- Encrypted output dropped the
streamkeyword of every stream object, so the saved file was no longer valid PDF syntax and strict readers reported the page content as neither a stream nor an array of streams - The
/Lengthrewrite matched/Lengthas a plain substring, so a stream dictionary carrying/Length1(any embedded font) had its key name corrupted while the real length stayed stale - A stream stating its length indirectly as
/Length N 0 Rhad the object number overwritten with the new length; the entry is now replaced by the direct encrypted length - A stream dictionary with no
/Lengthat all now receives one instead of leaving the reader without a length
Added
AnsiFindDictKeyTokenis now part of theFPdfPdfCommoninterface for top-level, delimiter-aware dictionary key lookups- Delphi, Lazarus, and C++Builder tests now cover
/Length1preservation, indirect length replacement, and stream-body size agreement
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.3 consistently
Version 2.57.2
Fixed
SaveAsEncryptedandSaveAsEncryptedToStreamwithRevision = erR6produced documents that rejected their own correct password in roughly one file out of four, because the ISO 32000-2 §7.6.4.3 algorithm 2.B round counter started one round too low and the extra round changed the/U,/O,/UE, and/OEvalues- R6 encrypted documents now reopen with the user or owner password in any conforming reader, and still reject a wrong password
Added
- Lazarus and C++Builder test suites gained encryption coverage that was previously Delphi-only: R6 key lengths, Encrypt dictionary fields, a repeated encrypt and reopen round trip, and wrong-password rejection
Changed
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.2 consistently
Version 2.57.1
Changed
- Typing in a form field, moving the caret, and toggling checkboxes now repaint only the area PDFium reports as damaged instead of the whole viewer
- Damage boxes are normalized for the upward page Y axis, widened by one pixel so anti-aliased widget borders stay clean, and clipped to the visible client area
- A damage box that is scrolled completely out of the viewport no longer schedules a repaint, while an inactive view or an unmapped page still falls back to a full repaint
- Delphi, Lazarus, and C++Builder tests now cover bounded form invalidation, flipped page boxes, off-screen boxes, and inactive-view safety
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.1 consistently
Version 2.57.0
Added
TPdfThumbnailView.Orientationsupports vertical and horizontal thumbnail layouts while preserving the existing vertical defaultFirstVisiblePageIndex,LastVisiblePageIndex, andEnsureCurrentPageVisibleexpose and control the thumbnail viewport with one-based page indexes
Changed
- Changing
CurrentPageIndexnow scrolls the selected thumbnail into view in either orientation - Delphi, Lazarus, and C++Builder tests now cover orientation defaults, switching, visible ranges, and selected-page visibility
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.57.0 consistently
Version 2.56.2
Changed
HighlightSearchText,AddSearchTextHighlight, andClearHighlightnow invalidate only the device rectangles for search ranges that were added or removed instead of repainting the full viewer- Replacing highlights with the same matches or appending duplicate matches no longer schedules an unnecessary repaint
- Delphi, Lazarus, and C++Builder tests now cover bounded invalidation, idempotent updates, clearing, and inactive-view safety
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.56.2 consistently
Version 2.56.1
Changed
TPdfThumbnailViewnow reuses rendered bitmaps for pages that remain visible across repaints and adjacent scroll positions- The cache retains only the current visible page range and releases entries precisely when pages leave that range, the assigned document changes, or thumbnail dimensions change
- Delphi, Lazarus, and C++Builder tests now cover cache reuse, viewport pruning, size invalidation, document replacement, and component destruction
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.56.1 consistently
Version 2.56.0
Added
TPdfView.CutSelectedFormTextToClipboardandTPdfView.PasteFormTextFromClipboardprovide Unicode clipboard editing for the focused editable form widget
Changed
- Focused form editors now handle the standard copy, cut, paste, and select-all keyboard shortcuts before forwarding text input to PDFium
- Cut and paste reject read-only fields and sessions without form-fill or modify permission, while cut copies successfully before removing selected text
- Delphi, Lazarus, and C++Builder tests now cover no-focus, round-trip shortcut, and read-only rejection behaviour
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.56.0 consistently
Version 2.55.0
Added
TPdfView.AddSearchTextHighlightappends unique matches for another search term to the current page overlay, allowing several queries to remain highlighted together
Changed
HighlightSearchTextremains the replacement entry point and now shares the additive scanner, while duplicate character ranges are ignored andClearHighlightremoves the complete accumulated set- Delphi, Lazarus, and C++Builder tests now cover distinct-query accumulation and duplicate-range suppression
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.55.0 consistently
Version 2.54.0
Added
TPdfnow exposes complete page-object snapshots, batched style updates, affine object transforms, path segments, clip paths, and Form XObject children- Character inspection now includes fill and stroke colours, font name and flags, loose glyph bounds, effective matrices, text-object handles, and character-to-text index conversion
- Annotations now round-trip border geometry and normal, rollover, and down appearance streams
- New raw and decoded thumbnail accessors, page-content and annotation transforms, and
RenderPageWithMatrixprovide direct advanced rendering and editing paths
Changed
- Page-object style changes can be committed as one batch so PDFium regenerates page content only once
- Matrix rendering uses the existing zero-copy bitmap path when the destination bitmap layout is compatible
Version 2.53.1
Fixed
- The built-in Chinese Copy menu caption now uses encoding-independent Unicode code points and displays correctly in Lazarus builds
- Older Delphi toolchains can compile
FPdfAsyncwhen theirWinapi.Windowsunit omits theGetTickCount64declaration
Version 2.53.0
Added
- New
Tests.ApiCoveragetest fixture covering public TPdf APIs that previously had zero end-to-end test coverage:GetPageBox/SetPageBox(MediaBox/CropBox read/write, missing-box errors, and save round-trip),FlattenPage/FlattenAllPages(return value and page-count preservation),GenerateFormAppearances(no-op on non-form documents),SaveAsEncrypted/SaveAsEncryptedToStream(AES-256 with password round-trip — verifies that the encrypted file refuses to open without the password and opens with it),DeletePageboundary validation (page 0 and out-of-range raiseEPdfError), and theHasContents/HasAuthorannotation sentinels introduced in v2.38.0 (verifyingDefault(TPdfAnnotation)leaves themFalse)
Version 2.52.0
Added
TPdfView.CopySelectedFormTextToClipboardcopies the text selection inside the focused AcroForm widget to the Windows clipboard asCF_UNICODETEXT
Changed
- Page-text and focused-form copy operations now share the same defensive Unicode clipboard writer and leave the clipboard unchanged when their selection is empty
- Delphi, Lazarus, and C++Builder tests now cover inactive or unfocused form-copy calls and a focused form selection round trip through the Windows clipboard
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.52.0 consistently
Version 2.51.0
Added
TPdfView.SelectLineAtselects the visual text line containing a one-based page and zero-based character index without requiring mouse input
Changed
- Programmatic line selection, triple-click selection, and
Shift+HomeorShift+Endnow share one character-box line-boundary model - Delphi, Lazarus, and C++Builder tests now cover stable line selection and invalid page or character indexes
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.51.0 consistently
Version 2.50.0
Added
TPdf.LoadDocumentnow accepts a zero-basedIndexandCountwindow into aTBytesbuffer, allowing embedded PDFs to load without allocating a temporary byte-array slice
Changed
- Byte-range loading rejects negative or out-of-bounds windows before changing document state and preserves the existing buffered and borrowed-buffer lifetime options
- Delphi, Lazarus, and C++Builder tests now cover embedded PDF windows and invalid byte-range arguments
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.50.0 consistently
Version 2.49.1
Added
TPdfView.FitModenow supportspfmFitHeightfor fitting the current page to the visible viewport height while allowing horizontal scrolling when needed
Fixed
- Fit modes now converge after scrollbar visibility changes the client area, keeping fit-page, fit-width, and fit-height results consistent across VCL and LCL
- Delphi, Lazarus, and C++Builder viewer tests now cover
pfmFitHeightselection and enum round trips TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.49.1 consistently
Version 2.49.0
Added
- The public PDFium binding surface now covers all 470 exported functions in the reviewed headers, including attachment description access through
FPDFAttachment_SetDescriptionandFPDFAttachment_GetDescription TPdfnow exposes attachment descriptions, cross-reference validity, trailer end offsets, security-handler revision, 64-bit memory loading, signature byte ranges, web-link text ranges, and expanded image data, filter, metadata, and ICC profile snapshots- Form helpers now support native field focus, focused choice-option queries and updates, mouse-wheel forwarding, writable ink strokes, and form overlays after progressive rendering
Changed
FormFieldCount, form-field indexes, and tab order now describe only widget annotations instead of including unrelated page annotations- Headless
TPdfpages now enter and leave the form-fill page lifecycle so native focus and focused-field APIs work without aTPdfView - Attachment description exports are capability-gated so applications using an older PDFium build can still load the library and detect the unavailable feature
Fixed
- Progressive page rendering now paints form controls when form filling is enabled
- Delphi, Lazarus, and C++Builder tests now cover the new document diagnostics, attachment descriptions, ink paths, form behavior, signature byte ranges, web-link ranges, and image metadata
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.49.0 consistently
Version 2.48.0
Added
TPdfMatrixnow exposes factories, cloning and assignment, finite-state and invertibility diagnostics, tolerance-based comparison, translation access, determinant reporting, and affine decomposition- Prepend composition, pivot-aware rotation, scaling, skewing and flips, plus stretch, contain and cover rectangle mapping support local-space and fitted-layout workflows without manual coefficient arithmetic
- Non-mutating inverse access, inverse point mapping, vector and quadrilateral transforms, dynamic point and rectangle batches, in-place variants, and one-pass transformed bounds expand the reusable geometry surface
Changed
- Translation, scaling and axis flips now update only the affected coefficients instead of routing through general affine multiplication
- Rectangle transformation normalizes its input once, uses a specialized exact axis-aligned path where possible, and computes general rotated bounds without temporary point records
- Point and rectangle batch transforms allocate one result array or reuse caller storage, while transformed point bounds are accumulated in one pass without an intermediate array
Fixed
- Rectangle mapping rejects zero-sized, non-finite, and
Single-overflowing results before publishing an unusable matrix - Delphi, Lazarus, and C++Builder tests now verify composition order, pivot invariants, inverse round trips, fitted rectangles, decomposition, and bulk geometry behavior
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.48.0 consistently
Version 2.47.0
Added
FPdfAsyncnow provides structured cancellation reasons and messages, removable callback registrations, timeout-backed sources, cancellation waiting, and atomic try-cancel operations through extended interfaces that preserve the original APITPdfFuture<T>.RunExadds configurable reply dispatch and worker priority while result envelopes expose operation IDs, value validity, exception class names, completion timing, and reusable completion helpersTPdfAsyncExecutoradds a reusable fixed worker pool with four FIFO priority lanes, optional bounded-queue backpressure, cancelable task handles, timeout-aware waiting, task snapshots, aggregate statistics, and graceful shutdown
Changed
- Repeated asynchronous jobs can reuse worker threads and O(1) queue operations instead of creating a thread for every task, while synchronized completion remains available for UI hosts
- Executor and future failures preserve exception class and message diagnostics, cancellation keeps its original reason, and callback exceptions remain isolated from worker lifecycle and shutdown
- Delphi, Lazarus, and C++Builder tests now cover the extended cancellation, future metadata, task control, backpressure, priority ordering, statistics, failure, and shutdown surface
Fixed
- Concurrent cancellation owners now receive a deterministic first-writer result instead of relying on a separate observation and cancel sequence
- Main-thread idle waiting processes synchronized task replies, preventing a completed worker from leaving the executor permanently non-idle during coordinated shutdown
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.47.0 consistently
Version 2.46.0
Added
FPdfAsn1now exposes identifier classes, 64-bit high-tag-number encoding and decoding, parsed TLV records, zero-copy child reader windows, typed primitive decoders, and content or encoded-value slices- DER writers now support the full unsigned 64-bit INTEGER range, validated arbitrary INTEGER content, ENUMERATED, automatic UTCTime or GeneralizedTime selection, application and private tags, multi-value SEQUENCE, and canonically sorted SET OF output
ValidateDerreturns offset-aware validation errors while enforcing configurable nesting, node-count, content-length, error-count, root, and optional SET ordering limits
Changed
- DER concatenation and multi-value composition use one output allocation, writer buffers expose reserve, count, capacity, and ownership-transfer operations, and SET OF sorting now uses
O(n log n)merge sorting - BOOLEAN, INTEGER, BIT STRING, OBJECT IDENTIFIER, NULL, UTF8String, PrintableString, IA5String, UTCTime, and GeneralizedTime values receive canonical form checks during encoding, typed decoding, or validation
- The Lazarus runtime package now exports
FPdfAsn1, and Delphi, Lazarus, and C++Builder test suites exercise the same public DER surface
Fixed
- Context-specific tag numbers greater than 30 are no longer truncated into the low five identifier bits
- Malformed high-tag identifiers, non-minimal definite lengths, invalid UTF-8, non-zero BIT STRING padding, invalid time fields, trailing roots, and resource-limit violations are rejected deterministically
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.46.0 consistently
Version 2.45.0
Added
FPdfPreflightReportnow assigns Info, Warning, or Error severity to every issue and exposes per-standard and report-level severity, status, category, issue-code, lookup, search, flattening, and filtering APIs- Preflight reports now export SARIF 2.1.0, JUnit XML, NDJSON, and native XML through matching
To*andSave*ToFilemethods for CI, automation, and streaming pipelines - Stable SHA-256 report fingerprints identify equivalent validation results independently of source paths and generation timestamps
Changed
- JSON, CSV, text, Markdown, and HTML reports now include severity and expanded status summaries; HTML adds accessible table captions and a status summary
- Issue and standard collection construction uses geometric capacity growth, query results are pre-sized, JSON escaping writes into one bounded output buffer, and all report files use one direct UTF-8 writer
- Issue-category summaries use deterministic ordering, timestamps include milliseconds, JSON carries
formatVersion: 2, and CSV cells neutralize spreadsheet formulas
Fixed
- JSON export now preserves valid supplementary Unicode pairs and replaces isolated UTF-16 surrogate code units instead of emitting malformed scalar data
- HTML export now escapes apostrophes, and filtered report views own independent issue arrays instead of sharing mutable result storage
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.45.0 consistently
Version 2.44.0
Added
- Bookmarks and destinations expose open state, descendant counts, action targets, destination view modes, and up to four view parameters
Metadata,GrantedPermissions,UserGrantedPermissions,HasPermission, andUserHasPermissionprovide typed document-inspection snapshots and permission queriesExtractThumbnail(PageNumber)renders a requested page without changing the active page, and RFC 3161 timestamp results expose policy, generation time, and nonce details
Changed
- Bookmark, JavaScript, metadata, destination, and thumbnail paths use validated two-pass buffers, geometric collection growth, and cycle-safe traversal
- Save post-processing resolves the active catalog, page tree, and open action through the current xref revision, caches decoded object streams, and scans PDF dictionaries with lexical boundaries
- Shared PDF parsing now enforces exact object headers, generations, dictionary keys, stream lengths, predictor geometry, integer ranges, and comment, literal-string, and hexadecimal-string boundaries
- RFC 3161 response validation now binds both nonce and SHA-256
messageImprint, requires a structurally valid signer, and applies strict DER length, OID, INTEGER, and GeneralizedTime rules
Fixed
- Incremental documents no longer select inactive duplicate catalogs or malformed reference suffixes when adding a default open action
- Timestamp tokens with long-form DER lengths retain the complete encoded token, while malformed CMS optional-field ordering and empty signer sets are rejected
- Clean Delphi builds now write PAdES nonce seed fields through aligned-safe byte copies and pass XFA response bytes with the exact native pointer type
TPdf.AboutInfo, Lazarus package metadata, and installer metadata now report Version 2.44.0 consistently
Version 2.43.0
Added
- XFDF field and annotation records now expose presence flags that distinguish an omitted XML value from an explicitly empty value
Changed
- XFDF import accepts namespace-prefixed elements and attributes, mixed text and CDATA content, entity references, and whitespace-significant values while rejecting invalid Unicode scalar references
- XFDF import and export use indexed field matching and bounded geometric buffers, improving throughput and peak allocation behaviour for deeply nested forms, large annotation collections, ink lists, vertices, and markup quadrilaterals
- PDF/A and PDF/UA validation use bounded growth for large page, stream, structure-name, and RoleMap collections; PDF/UA RoleMap resolution now follows direct arrays and exact-generation indirect name or array objects
Fixed
- XFDF round-trips now preserve deeply nested field paths, explicit empty field values, explicit empty annotation contents, and the distinction between absent and empty contents
- Invalid memory-buffer loads and out-of-range page assignments are rejected without leaving partial document or page state, and a failed native page reload preserves the previously active page
- Large marked-content identifiers and signature metadata buffers are bounded and validated before allocation or native access
Version 2.42.0
Added
TPdfMatrixnow providesInvert,TryInvert,TransformPoint, andTransformRectfor coordinate mapping, hit testing, normalized bounds, and explicit singular-matrix handlingTPdf.WrapTextgained aBreakLongWordsoverload that splits CJK and other text without spaces while keeping valid UTF-16 surrogate pairs togetherTPdfAnnotation.AttachmentPointSetsexposes every quadrilateral in multi-line markup annotations while the existingAttachmentPointsfield remains an alias for the first set
Changed
- Text extraction, readable-content construction, word lookup, and spoken-text offset mapping now use bounded allocation and binary lookup paths, reducing repeated allocations and linear scans on large pages
- ASN.1 serialization and encrypted PDF generation now use geometric output buffers; encrypted-object ordering uses
O(n log n)sorting and xref rows are written directly to the final buffer WrapTextpreserves CR, LF, and CRLF line boundaries and reuses one native measurement object for the whole operation- XFDF import and export preserve every markup quadrilateral; import also applies RGB/interior colors and parses decimal coordinates independently of the process locale
Fixed
- Legacy callers can again update annotation content and author by assigning non-empty strings without setting the newer
HasContentsandHasAuthorsentinels - Explicitly empty annotation strings now use a valid zero-terminated native buffer, so clearing
/Contents,/T, and other optional text keys no longer passes a nil pointer to PDFium
Version 2.41.0
Changed
- Preflight report
SaveJsonToFile,SaveMarkdownToFileandSaveTextToFilenow write UTF-8 on Delphi (matching the existingSaveHtmlToFile), instead of the system ANSI code page. Non-ASCII characters in file paths, recommendations and scope notes were garbled on Delphi when saved through these methods SaveCsvToFilenow writes UTF-8 with a BOM prefix, so Excel for Windows auto-detects the encoding. Without the BOM, Excel treats a UTF-8 CSV as code-page 1252 and mangles any non-ASCII characters
Fixed
- The
ExtractImagesdemo leaked the cachedTBitmapobjects inFExtractedImageswhen the form was closed without explicitly clearing them first. The form now overridesDestroyto callClearExtractedImages, releasing every cached bitmap
Version 2.40.0
Changed
TPdf.RenderPage(HDC, ...)now masks FPU/SSE exceptions around theFPDF_RenderPagecall, matchingTPdfView.RenderPage(HDC)(fixed in v2.25.0) and every bitmap-returning rendering entry point. TheTPdf-level direct-to-DC overload previously left FPU exceptions unmasked on pre-D12 compilers
Fixed
ColorToARGBnow returns a fully transparent pixel (alpha 0) forclNoneandclDefaultinstead of treating the sentinel value as a literal RGB colour. The previous behaviour produced a dark, nearly opaque fill when a caller passedclNoneexpecting “no colour”
Version 2.39.1
Fixed
- Explicit PDF 1.3 saves now remove
/SMask /None,/AIS false, and/TK trueentries that only repeat the initial graphics state while continuing to reject non-default transparency state
Version 2.39.0
Changed
CreatePDFandImageToPDFnow use confirmed save destinations and report success only whenSaveAscompletes successfullyBatchExport,PDFtoJpg, andSplitPDFnow allocate unique output directories so repeated runs and same-named inputs preserve earlier resultsSplitViewnow wraps search once without leaving hidden page state behind after cancellation or no match, and aborts incomplete print jobs instead of submitting partial output
Fixed
MergePDFnow rejects malformed page-range tokens and source-overwriting output paths, counts the pages actually imported, and refuses to save an empty result- The Delphi and C++Builder
Attachmentdemos now commit same-path saves through rollback-safe file replacement so a failed rename cannot remove the original PDF
Version 2.38.0
Changed
SetAnnotationDatanow guards the/Contentsand/Authorwrites behindHasContents/HasAuthorsentinels onTPdfAnnotation, matching the existingHasName/HasSubject/HasIconpattern. Previously these two fields were written unconditionally, so assigning aDefault(TPdfAnnotation)record to update only colour or flags silently overwrote the annotation's existing content and author with empty strings.GetPageAnnotationnow sets the sentinels so a read-modify-write cycle preserves the original values
Fixed
GenerateFormAppearancesnow reads the checkbox/radio button value viaFPDFAnnot_GetFormFieldValue(which walks to the parent field dictionary per ISO 32000-1 §12.7.5) instead ofFPDFAnnot_GetStringValue(Annot, 'V', ...)(which reads the widget dictionary). The widget usually carries no/V, so/ASwas never synced to the checked state and a flattened checkbox/radio rendered as unchecked
Version 2.37.0
Changed
ParseTsaUrlnow clamps the port to1..65535after parsing; an oversized port value would otherwise wrap viaDWORDtruncation and could land on a valid port- XFDF
ParseFieldnow accepts a depth parameter (default 0, capped at 64) and returns an empty field at the limit, so a maliciously nested 100 000-deep<field>chain can no longer overflow the stack
Fixed
- TSA HTTP request now guards against an empty request body before passing
@ReqDer[0]toWinHttpSendRequest. A zero-length dynamic array dereference would access an ungrounded pointer;BuildTimeStampReqalways returns a non-empty SEQUENCE, but the call site now defends the contract
Notes
- The
FPdfTsaWinheader comment about HTTPS revocation checking has been corrected: WinHttp validates the server certificate chain by default but does not perform CRL/OCSP revocation checking unless explicitly enabled viaWinHttpSetOption. The previous wording claimed revocation checking “comes for free”, which was misleading
Version 2.36.0
Changed
- TSA HTTP requests now send an explicit
Content-Lengthheader in addition to theContent-TypeandAcceptheaders. WinHttp synthesises it from the total length, but some RFC 3161 proxies require an explicit header and reject the request with411 Length Requiredwithout it - XFDF export now drops C0 control characters (other than TAB/LF/CR which are already escaped) instead of emitting an invalid backslash-hex sequence. The previous
\-01Fescape is not valid XML (backslash has no special meaning in XML), so any conforming reader would have rejected the document as malformed InjectAssociatedFilesnow writes/Subtypeon the EmbeddedFile stream dictionary when the caller suppliesTAssociateFile.MIMEType. The field was declared and documented but the injector previously hard-coded/Type /EmbeddedFileand ignored it (ISO 32000-2 §7.11.4 allows/Subtypeon the stream)
Fixed
- XFDF import skipped the first content byte after a UTF-8 BOM and the first byte when no BOM was present:
BytesToAnsi(Bytes, 4, ...)(BOM) andBytesToAnsi(Bytes, 1, ...)(no BOM) used off-by-one start offsets becauseBytesToAnsitakes a 0-based array index. The calls now use3and0 ExtractSignatureValuehad two dangling-ifindentation bugs whereR.Position:= CNran unconditionally for the optionalcertificates [0]andsignedAttrs [0]branches. The branches are now wrapped inbegin/endso the position is advanced only when the optional TLV was actually read (same class of bug fixed inAddSignatureTimestampToCmsin v2.22.0)
Version 2.35.0
Changed
TFPDFAvail_IsDocAvail,TFPDFAvail_IsPageAvailandTFPDFAvail_IsFormAvailnow takehints: PFX_DOWNLOADHINTSinstead ofvar hints: FX_DOWNLOADHINTS, so the documentednullptrquery-only mode (check current availability without requesting more data) is reachable from Delphi. The PDFium header explicitly allowshintsto be null; the previousvarbinding made that impossibleTFPDF_SetSystemFontInfonow takespFontInfo: PFPDF_SYSFONTINFOinstead ofvar pFontInfo: FPDF_SYSFONTINFO, so callers can passnilto tell PDFium to stop using a previously registered system font interface (the documented disable path)TPdfThumbnailView.Paintnow computesVisibleRowswith the same formula asUpdateScrollBarRange(ClientHeight div RowHeight), so the number of rows painted matches the scrollbar page size. The previous paint-only formula ((ClientHeight - FMarginY) div RowHeight + 1) could differ by one row at edge heights, wasting a render on an off-page row or missing the last visible row
Version 2.34.0
Added
TPdf.SaveAsEncrypted/SaveAsEncryptedToStream— high-level API that saves the document then encrypts it with PDF 2.0 AES-256-CBC (V=5/R=5/R=6). Takes aTPdfEncryptOptionswith user/owner password, permissions and revision; delegates toEncryptDocumentBytes- StrF literal-string encryption:
EncryptDocumentBytesnow encrypts(...)literal strings in non-stream objects (Info dictionary, etc.) to AES-256-CBC hex strings, matching the stream encryption format (16-byte IV + PKCS7 ciphertext). Hex strings<...>are left untouched
Version 2.33.0
Added
- Full-document AES-256-CBC encryption injector in
FPdfEncrypt.pas.EncryptDocumentBytestakes a plaintext PDF and a password, encrypts every indirect stream object (16-byte IV + AES-256-CBC PKCS7 under the file key), patches/Length, appends the/Encryptdictionary object, and rebuilds a complete classic cross-reference table + trailer with/Encryptand/ID. Completes the PDF 2.0 encryption stack (AES block + GCM + SHA-512/384 + R6 key derivation + dictionary + document sweep) EncryptStreamPayloadhelper — the PDF 2.0 AES-256 stream format (IV prepended to AES-CBC-PKCS7 ciphertext), reusable by callers that manage their own object layout
Version 2.32.0
Added
- SHA-512 / SHA-384 hash (FIPS 180-4) in the new
FPdfSha512.pasunit. Pure-Pascal, ported from HotPDF. Required by the PDF 2.0 R6 password-hash iteration, which branches on a 128-bit mod-3 value to pick SHA-256/384/512 each round. FIPS-180-4 B.1 known-answer verified - PDF 2.0 encryption key derivation and Encrypt dictionary builder in the new
FPdfEncrypt.pasunit. Implements ISO 32000-2 §7.6.4.3 algorithm 2.B (R6 hash dance: AES-128-CBC + iterative SHA-256/384/512 selection), derives the 32-byte file encryption key plus the/O,/U,/OE,/UE,/Permsentries, and builds the V=5/R=5/R=6 Encrypt dictionary with/CFM /AESV3. Ported from PDFlibPas, adapted to TBytes style
Version 2.31.0
Added
- AES block cipher primitives (FIPS 197) in the new
FPdfAes.pasunit. Pure-Pascal AES-128 and AES-256 block ciphers plus CBC mode helpers and a CSPRNG backend, ported from HotPDF. FIPS-197 Appendix C.2 / C.3 known-answer tests verify correctness. This is the cryptographic foundation for the PDF 2.0 encryption stack - AES-GCM authenticated encryption (NIST SP 800-38D) in the new
FPdfAesGcm.pasunit. Implements GHASH (GF(2^128) multiplication), GCTR and the GCM AEAD construction on top of the AES block primitives. NIST GCM test cases 1 and 3 (AES-128) match the authoritative ciphertext and tag exactly; test case 13 (AES-256) round-trips. GCM is the ISO/TS 32003 mode for PDF 2.0 - PDF/A Level A ParentTree and ClassMap integrity validation (ISO 19005-1 §6.8.3).
pvaiParentTreeMissingflags a StructTreeRoot without the /ParentTree number tree;pvaiClassMapUnresolvedflags a /C class reference without a /ClassMap
Version 2.30.0
Added
- Associate Files injection (
InjectAssociateFiles/TPdf.SaveAsWithAssociateFiles, ISO 32000-2 §7.11.4). The newFPdfAssocFilesunit attaches/AFarrays of filespec references to the catalog or any page dictionary, covering all eight ISO 32000-2 Table 45/AFRelationshipvalues. Reuses the incremental-update pattern proven byInjectPadesDssMarkers - PDF/X-6 (ISO 15930-9:2020) support.
TPdfXConformanceaddspxc6; the injector and validator thread it throughpdfxid:GTS_PDFXVersionidentification. PDF/X-6 is the PDF 2.0-based successor to PDF/X-4 for complete exchange - PDF/A forbids the
/Threadaction (ISO 19005-1 §6.6.1 whitelist gap). The forbidden-action list now covers Thread alongside Launch, ResetForm, ImportData, SetOCGState, SetState, GoTo3DView, Rendition and Hide
Fixed
- PDF/A-4e validation path now honours the same tagged-structure, MarkInfo and word-break checks as Level A. The v2.29.0 save-side downgrade covered
PdfAIsLevelE, but threeValidatePdfACompliancegates checkedPdfAIsLevelAalone, so a PDF/A-4e document lacking tagged structure passed silently - OCG
/BaseStatetest drift: the v2.28.0 PostProcess pass correctly widened acceptance to/ONor/OFF(ISO 32000-1 Table 8.70), but the Delphi and C++ tests still expected/OFFto be rejected. Tests now use a truly invalid value (/Undefined) and a new positive test locks the/OFFacceptance - Geospatial
/Subtype /GEOover-matching:ContainsDictionarySubtype('GEO')matched any dictionary carrying the token, including unrelated ones like a stray/ViewerPreferences << /Subtype /GEO >>. The newContainsMeasureDictionarySubtypeadditionally requires/Type /Measureor a Measure-exclusive sibling key, so non-Measure dictionaries no longer trip the ADBE ExtensionLevel 3 requirement
Version 2.29.0
Added
- PDF/A-4 (ISO 19005-4:2020) support across the validator, XMP injector and Pdfium object-model layer.
TPdfAConformanceaddspac4base,pac4fandpac4e; the base level is PDF 2.0 (ISO 32000-2) and replaces the legacy A/B/U levels with base + F (form) + E (accessibility).ValidatePdfAreads apdfaid:part=4XMP packet (base omits the conformance element),SaveAsPdfAemits it, andSignPadesWithPdfAacceptspac4baseas a long-term archive container FPDFBookmark_GetColorbinding — the last unbound PDFium public export (469/469).TBookmarkgainsHasColorandColorfields populated from the bookmark/Carray (ISO 32000-1 §12.3.3). The binding uses tolerant loading so older DLLs that predate the export keep working- PDF/E-1 (ISO 24517-1 §5) header version check
pveiBadPdfVersion— PDF/E-1 is based on PDF 1.6 and a non-1.6 header is now flagged - PDF/R-1 (ISO 23504-1)
pvriEncryptVersionMismatch— encryption is permitted only on a%PDF-2.0header; a 1.x body carrying/Encryptis now flagged (previously a no-op statement) - PDF/R-1
pvriBadMediaBox— each pageMediaBoxshall be[0 0 w h];PdfRHasNonZeroMediaBoxOriginis a locale-independent ASCII scanner that skips indirect-reference MediaBoxes - PDF/A Level A
pvaiRoleMapUnresolved(ISO 19005-1 §6.8.3.4) — a present-but-incomplete RoleMap that leaves custom/Sstructure types unmapped is now flagged, closing the gap left by the existing presence-onlypvaiRoleMapMissingcheck
Fixed
PdfVersionToName(20)returned"1.0"instead of"2.0", corrupting the catalog/Versionentry and validator messages for every PDF 2.0 save. The formatter now splits major.minor explicitly for version codes>= 20FPdfAsn1.pasnegative-INTEGER encoder failed to compile under Delphi 12 (E2015onInteger(-(V<0))), blocking the whole test project. Fixed by usingInt64(-Ord(V<0))for the sign-extension mask- PDF/A forbidden-annotation list now includes
/RichMediaacross all parts (previously missed; ISO 32000-1 §12.5.6.35 forbids it in PDF/A)
Version 2.28.0
Added
TPdfVersionnow includespv20for PDF 2.0 (ISO 32000-2).DecodePdfVersion(20)returnspv20instead ofpvUnknown, andEncodePdfVersion(pv20)emits 20 so a PDF 2.0 document's version is no longer lost on read-back and can be written explicitly
Changed
DecodeDatenow parses PDF date strings with optional trailing fields per PDF Reference 3.8.3, instead of requiring the full 23-characterD:YYYYMMDDHHmmSSOHH'mm'form. Conformant truncated dates such asD:20260712,D:20260712153000, andD:20260712153000Zare now accepted; previously they were rejected by a hardLength=23gate. Timezone hour offset is now validated against the real-world UTC-12..UTC+14 range instead of> 23FPdfMeasure.MeasureTextnow encodes the font name as FPCAnsiString/ DelphiUTF8Encode, matching the library's other FPDF_BYTESTRING call sites, instead of a bareAnsiStringcast that garbled non-ASCII family names through the current code page
Fixed
TDerWriter.Integernegative-value path crashed or produced malformed DER: the loopwhile V <> -1 do V := V shr 8leftInnerempty forValue = -1(range error on the subsequentInner[Length(Inner)-1]) and over-produced bytes for other negatives. The encoder now extracts two's-complement bytes with sign-extending shifts and stops correctly when the remainder is pure sign extension. CMS/PAdES INTEGER fields are positive, so this only affects callers passing negative values, but the path is now correctTPdf.GetCharacterOriginandTPdfView.GetCharacterOriginignored theFPDFText_GetCharOriginreturn value and returned an uninitialised point on failure. The result is now zero-initialised and a failed read returns the origin (matchingGetCharacterRectangle's contract)
Version 2.27.0
Changed
- The Delphi, C++Builder, and Lazarus
PDFViewerandMultiPageViewerdemos now wrap document searches once, acceptEnterandF3for the next result, reset the search context when match options change, and reserveEscfor cancelling an active search or print job - Viewer printing now follows the current viewer rotation and selects portrait or landscape output accordingly, so toolbar rotation is reflected in printed pages
- All three
ViewerInteractionLabdemos now supportCtrl+A,Ctrl+C,Enter,F3, andEscshortcuts without intercepting native edit-control selection and copy commands
Fixed
- C++Builder and Lazarus viewer print cancellation now aborts the printer job instead of submitting the pages rendered before cancellation, and Lazarus explicitly exits every nested copy, page, and collation loop
- The Delphi
MultiPageViewerCancel button is now connected to its handler, and C++Builder/LazarusMultiPageViewersearch fields retain native arrow, Home, and End key editing
Version 2.26.0
Changed
TPdf.GetObjectBitmap,TPdf.GetBitmap,TPdf.GetThumbnailand theirTPdfViewcounterparts now acquire the render lock around theFPDFImageObj_GetBitmap/FPDFPage_GetThumbnailAsBitmapcall, matchingRenderPage/RenderTile. These are PDFium rendering-side calls that previously ran without the lock and could race with a concurrentUnloadPage/ReloadPageon the same documentTPdf.RenderPageThumbnailnow honours the page/Rotateentry: the fit is recomputed from the rotated dimensions for/Rotate 90or270pages so the thumbnail aspect ratio matches what the viewer shows, instead of using the intrinsic (unrotated) dimensions returned byFPDF_GetPageSizeByIndex
Fixed
TPdfView.GetCharacterRectangleignored the return value ofFPDFText_GetCharBoxand passed an uninitialisedTPdfRectangletoPageToDevicewhen PDFium reported failure. The rectangle is now zero-initialised and a failedGetCharBoxreturnsRect(0,0,0,0)GetLinkAnnotationsURI path and file path buffer length was off by one: the secondFPDFAction_GetURIPath/GetFilePathcall passedsize(which includes the trailing NUL) as the buffer length to a buffer allocated assize-1. The call now passessize-1so it cannot write past the allocation on a PDFium build that does not self-clamp
Version 2.25.0
Changed
TPdf.AddText,SetText,AddPathandInsertFormObjectFromXObjectnow invalidate the cached text page and link annotations before regenerating page content, matchingSetTextPositionsandRemoveObject. Previously aGetText/GetWebLinks/FindFirstcall after editing the page returned stale text and link data captured before the edit, and the retainedFPDF_TEXTPAGEhandle was used after content regeneration with undefined behaviourTPdfView.RenderPage(HDC, ...)now acquires the render lock and masks FPU/SSE exceptions around theFPDF_RenderPagecall, matching every other rendering entry point. The previous direct-to-DC overload could race with a concurrentUnloadPage/ReloadPageon the same document and left FPU exceptions unmasked on pre-D12 compilers- The Delphi
PrintPDFdemo now callsPrinter.Aborton cancellation instead of letting thefinallyblock reachPrinter.EndDoc, which submitted the pages rendered before the cancel. The Lazarus demo already handled this correctly
Fixed
TPdf.GetCharacter,TPdf.GetCharcodeand theirTPdfViewcounterparts truncated astral-plane code points (emoji, CJK Extension B) returned byFPDFText_GetUnicodeto the low 16 bits viaWideChar(), producing a lone surrogate that corrupted downstream text processing. Characters above U+FFFF now return U+FFFD (replacement character); useGetTextto retrieve the full UTF-16 encoding of astral charactersGetWebLinkscalledSetLength(Rectangles, FPDFLink_CountRects(...))without guarding against a-1return, which raised anEOutOfMemoryon a malformed page. A negative count is now clamped to zeroTPdf.Destroynow scrubs thePasswordstring from memory (viaUniqueString+FillChar) before the reference-counted buffer is released, so the password is not left readable on the heap after the component is destroyed
Version 2.24.0
Added
TPdf.DeletePage,GetAttachment,GetAttachmentName,GetAttachmentType,SetAttachmentandDeleteAttachmentnow validate the page/attachment index and raiseEPdfErroron an out-of-range value, matching the existing behaviour of the annotation accessors. Previously an out-of-range index was passed straight to PDFium and produced a silent no-op or undefined behaviour
Fixed
- Page-object handle leaks on failure in
TPdf.AddText,AddBitmapandAddJpegImage: whenFPDFText_SetText,FPDFImageObj_SetBitmap,FPDFImageObj_SetMatrixorFPDFImageObj_LoadJpegFileInlineraised after the object was created but beforeFPDFPage_InsertObjecthanded it to the page, the nativeFPDF_PAGEOBJECThandle was leaked. Each path now destroys the object on the exception before re-raising TPdf.UnloadPagediscarded an in-progressFPathhandle (set byCreatePathbut not yet consumed byAddPath) by setting it tonilwithout callingFPDFPageObj_Destroy. The handle is now destroyed so a path created then abandoned (or interrupted by a page switch) no longer leaksTPdf.InsertFormObjectFromXObjectomitted theUpdatePage(FPDFPage_GenerateContent) call that every sibling insertion (AddText/AddPath/AddBitmap/AddJpegImage/SetText/RemoveObject) performs, so a Form XObject inserted this way vanished on the next reload or save.UpdatePageis now called after the insertion
Version 2.23.0
Fixed
- Optional-content
/BaseStatevalidation now accepts/OFFin addition to/ON(ISO 32000-1 Table 8.70 permits both). The previous check rejected legitimate/OCProperties /D /BaseState /OFFconfigurations with a “malformed optional content” error even though the file was conformant - Optional-content
/Intentvalidation now accepts/Designand name arrays such as[/View /Design], not only the literal/View. ISO 32000-1 Table 8.70 defines/Intentas a name or array of names drawn from/Viewand/Design; the previous single-value check over-rejected standard authoring output - Geospatial Measure dictionary detection for the PDF 1.7
/Extensions /ADBEExtensionLevel 3 gate no longer requires/Type /Measure, which ISO 32000-1 Table 254 marks optional. GeoPDF producers that omit/Type(PDFBox, QGIS, FME) previously bypassed the gate and silently produced non-conformant PDF 1.7 output; the detector now matches/Subtype /GEOalone
Version 2.22.0
Changed
TPdfViewfit-zoom calculations (GetPageZoom,GetPageWidthZoom,GetPageHeightZoom) now useClientWidth/ClientHeightinstead of the windowWidth/Height, sopfmFitPage/pfmFitWidth/pfmFitHeightsize the page to the visible viewport rather than the outer frame including scrollbars and borders, eliminating the redundant scrollbar that appeared when the fitted page was slightly larger than the client areaAddSignatureTimestampToCmsnow raises an explicitExceptionidentifying the unreadable CMS SignerInfo field (version / sid / digestAlgorithm / signedAttrs / signatureAlgorithm) instead of silentlyExit-ing and letting a partial parse flow on as though it were a complete signed CMS; a missingbegin/endblock around the optionalsignedAttrs [0]branch that leftR.Positionun-advanced is also corrected
Fixed
- CNG private-key handle leak in
ResolveWinSigner: whenCryptAcquireCertificatePrivateKeysucceeded but the subsequent issuer/serial extraction orTWinCmsSigner.Createraised, theNCryptKeyHandlewas never freed because its ownership only transfers to the signer on a successful constructor. The post-acquire setup is now wrapped so the handle is released viaNCryptFreeObjecton any failure first EcDsaP1363ToDernow rejects an all-zerororshalf instead of emitting anINTEGER 0; ECDSA signatures withr = 0ors = 0are invalid (RFC 4754 §6 / FIPS 186-4 §6 require1 ≤ r, s ≤ n-1) and would otherwise be accepted as genuine by a lenient verifier
Version 2.21.12
Fixed
- Explicit PDF 1.5 through PDF 1.7 saves now reject malformed catalog
/OCPropertiesstructures, including missing required/OCGsor/Dentries, invalid default configuration values, and non-array state entries
Version 2.21.11
Fixed
- Explicit PDF-version saves now reject direct or indirect Page
/Annotsentries whose annotation dictionaries omit the required/Subtypeor/Rectentry
Version 2.21.10
Fixed
- Explicit PDF 1.7 saves now require geospatial
/Type /Measure /Subtype /GEOdictionaries and Projection annotations to declare/Extensions /ADBEwith/BaseVersion /1.7and/ExtensionLevel 3or newer
Version 2.21.9
Fixed
- Explicit PDF 1.7 saves now require RichMedia annotations and
RichMediaExecuteactions to declare/Extensions /ADBEwith/BaseVersion /1.7and/ExtensionLevel 3or newer
Version 2.21.8
Fixed
- Explicit PDF 1.7 saves now require PRC 3D streams to declare
/Extensions /ADBEwith/BaseVersion /1.7and/ExtensionLevel 1or newer, instead of treating PRC as a core PDF 1.7 feature
Version 2.21.7
Fixed
- Explicit PDF 1.4 and older saves now reject image XObject
/SMaskInDataentries, including an explicit value of0, because embedded JPEG 2000 soft-mask channels require PDF 1.5 or newer
Version 2.21.6
Fixed
- Explicit PDF 1.4 and older saves now reject 16-bit image XObjects, which require PDF 1.5 or newer, while PDF 1.5 through PDF 1.7 targets preserve their
/BitsPerComponent 16image data
Version 2.21.5
Fixed
- Explicit PDF 1.4 and older saves now reject document catalog
/PageLayout /TwoPageLeftand/TwoPageRightvalues, which require PDF 1.5 or newer, while PDF 1.5 through PDF 1.7 targets preserve the requested two-page layout
Version 2.21.4
Fixed
- Explicit PDF 1.3 saves now reject document catalog
/Langentries, which require PDF 1.4 or newer, while PDF 1.4 through PDF 1.7 targets preserve the language identifier
Version 2.21.3
Fixed
- Explicit PDF 1.3 saves now reject document
/EmbeddedFilesname trees, which require PDF 1.4 or newer, without rejecting embedded-file streams referenced through older file specifications
Version 2.21.2
Fixed
- Explicit PDF 1.3 saves now reject active metadata streams, which require PDF 1.4 or newer, while preserving them for PDF 1.4 through PDF 1.7 targets
Version 2.21.1
Fixed
- Hybrid-reference validation now applies supplemental
/XRefStmentries before same-revision classic xref placeholders, so compressed annotations and other version-gated objects are no longer missed when the compatibility table marks them free
Version 2.21.0
Changed
- All Delphi, C++Builder and Lazarus viewer examples can open a PDF passed as the first command-line argument, and the C++Builder and Lazarus
MultiPageViewerexamples provide explicit select-all and copy shortcuts
Fixed
- Viewer examples now reject invalid bookmark and link page targets, preserve load errors, validate manual zoom input consistently, print the requested form-filled page instead of repeating the visible page, and abort cancelled Delphi print jobs instead of submitting partial output
Version 2.20.0
Changed
- All Delphi, C++Builder and Lazarus viewer examples now provide consistent shortcuts for opening, searching, saving, printing, zooming and page navigation, while every
ViewerInteractionLabvariant also supports page jumps, validated 10–600% manual zoom, persistent interaction logs and click-coordinate round-trip checks
Version 2.19.1
Fixed
- Explicit PDF-version validation now follows the active classic, hybrid or xref-stream revision chain, including compressed-object entries, so superseded, freed and unreferenced objects no longer cause false feature-version failures
Version 2.19.0
Changed
- The C++Builder and Lazarus attachment, image extraction, text extraction, page conversion and split examples now use dedicated output folders or safely finalised files, stable zero-padded names, responsive progress updates, and completion summaries with per-item error counts
Fixed
- The C++Builder
CJKTextLabnow measures text through the exported PDFium editing functions, andMergePDFavoids an ambiguous VCL message overload, restoring clean RAD Studio 37 builds
Version 2.18.3
Fixed
- The PAdES B-LTA Document Time-stamp is now registered as a discoverable signature field — an invisible Widget reachable through the first-page
/Annotsand the AcroForm/Fields(ETSI EN 319 142-1 §5.4.3) — instead of an unreachable orphan object that signature-field-enumerating validators could not find; existing annotations and fields are preserved
Version 2.18.2
Fixed
- PAdES signing and classic cross-reference writing now raise a clear error when a byte offset exceeds the fixed 10-digit field width (~9.3 GB) instead of silently leaving the
/ByteRangeplaceholder unwritten (producing an invalid signature) or overrunning the 20-byte xref line (ISO 32000-1 §7.5.4); cross-reference-stream output uses 8-byte binary fields and is unaffected
Version 2.18.1
Fixed
- PAdES signing now resolves indirect first-page
/Annots,/AcroFormand/Fieldsreferences by whole object header (ISO 32000-1 §7.5.3) and by the reference's actual generation number; a bare substring search previously matched an object number inside a longer one (resolving5 0 Rto15 0 obj) and a hard-coded generation missedgen>0objects, corrupting the signature field arrays or rejecting valid documents - When the catalog, first page,
/Annots,/AcroFormor/Fieldslives inside an object stream, signing now retries on an expanded copy before failing instead of rejecting the document outright
Version 2.18.0
Added
ReadPdfVersionInforeports the header version, effective core version, catalog override and Adobe developer extension level from a PDF stream
Changed
- Explicit PDF 1.3-1.7 saves now validate catalog, page-resource, XFA, redaction and developer-extension structures in their owning object context; encrypted explicit-version output and PDF 1.3 incremental normalization are rejected to preserve document integrity
- File-path saves now write to a sibling temporary file and replace the destination only after all compression, normalization and version checks succeed
Fixed
- PDF 1.3 output now carries the required full
/ProcSetresource and removes PDF 1.4 transparency keys when they only repeat the PDF 1.3 initial graphics-state values - Hybrid-reference, xref-stream and object-stream files are no longer rewritten by the classic-xref compressor, preventing compressed-object entries from being dropped
- Names that resemble transparency or catalog feature keys inside strings, comments or unrelated resource maps no longer cause false target-version failures
Version 2.17.0
Added
- PAdES signatures are now registered as invisible Widget annotations in the first page
/Annotsarray and in the AcroForm/Fieldsarray, preserving existing annotations and form fields
Changed
- Incremental PDF/A, PDF/X, PDF/E, PDF/R, PDF/UA, PDF/VT and PAdES updates now preserve the source cross-reference representation: xref-stream documents receive an xref-stream update as required by ISO 32000-1 §7.5.8.1, while classic documents continue to receive an xref table
- Cross-reference offsets,
startxref,/Prev, PAdES ByteRange values and SHA-256 range processing now use 64-bit positions with chunked hashing, enabling files larger than 2 GB in 64-bit builds - Generated writable XMP packets now reserve 2048 bytes of padding before the closing packet instruction
Version 2.16.10
Fixed
- Object-stream expansion no longer resurrects stale copies of objects that an incremental update migrated out of the object stream into a plain definition (ISO 32000-1 §7.5.7); conformance checks and marker injection previously resolved the outdated catalog or metadata dictionary on such files
Version 2.16.9
Fixed
- On Free Pascal, text strings whose input is not valid UTF-8 are widened byte-by-byte as Latin-1 and written as UTF-16BE hex strings; the raw high bytes previously leaked into a literal string, which is not a legal PDF 1.7 text-string encoding
- Stream decoding now recognises raw deflate data without the RFC 1950 zlib wrapper (a common defect of broken writers) and decompresses it in raw mode, so conformance scans no longer go silently blind on such streams
Version 2.16.8
Fixed
- Incremental updates written by the save post-processing path now refresh the second (changing) trailer
/IDelement as required by ISO 32000-1 §14.4; both elements were previously copied verbatim, so caching and synchronisation tools saw an unchanged identifier after every update
Version 2.16.7
Fixed
- The stream-body blanking used by conformance scans now requires the
streamkeyword to be followed by an end-of-line (ISO 32000-1 §7.3.8.1); the word inside a literal string such as(downstream)previously blanked all following structure up to the nextendstream, hiding real violations from the byte-level checks - The PDF/X and PDF/E forbidden-feature scans additionally blank literal strings and comments (§7.2.2), so a value such as
/Title (see /JavaScript docs)or a commented token no longer produces a falseJavaScript,AcroFormorLZWDecodefinding
Version 2.16.6
Fixed
- PDF/VT DPM entries are now validated at write time as documented: key names violating the ISO 16612-2 §6.6 NMTOKEN rule or the Annex E registrant-prefix rule, and duplicate names, are rejected instead of being written into the DPart dictionary — a name containing a space previously split into a bogus key/value pair and corrupted the dictionary
Version 2.16.5
Fixed
- Removing a dictionary entry whose value is a hex string (such as
/Check <...>) now removes the whole entry; the injectors previously left an orphan hex value behind, producing a syntactically broken dictionary - Removing an entry whose indirect reference uses newlines between the tokens (ISO 32000-1 §7.3.10 allows any whitespace) no longer leaves the generation number and
Rkeyword behind
Version 2.16.4
Fixed
- The maximum-object-number scan no longer requires object headers to start a line (ISO 32000-1 §7.5.3 allows any whitespace or delimiter before them), so injectors can no longer allocate an object number that collides with an inline
N G objheader and silently corrupt the file; object numbers are bounded by the Annex C ceiling - Streams whose
/Lengthis an indirect reference now resolve the referenced integer object and use its value when it lines up with the closingendstream; previously such streams were bounded by a pattern search, which truncated bodies legally containing theendstreambyte sequence — typical for embedded PDF attachments
Version 2.16.3
Fixed
- Stream compression passes cross-reference-stream documents (PDF 1.5+ files without a classic
trailerkeyword) through unchanged; the rebuild path previously misparsedstartxrefas the table location and synthesised a guessed trailer, which could produce an unopenable file - The compressor skips XMP metadata streams so a PDF/A document keeps its mandatory unfiltered metadata stream (ISO 19005-1 §6.7.2), and leaves external file streams (
/Fwith/FFilter) untouched - The rebuilt cross-reference table scans a stream-stripped copy of the document, so binary stream content can no longer fake object headers or inflate the table; the rebuilt trailer's
/Sizenow reflects the actual table and object numbers are capped at the Annex C ceiling - Locating the original cross-reference table accepts CR-only line endings (ISO 32000-1 §7.5.1) and can no longer match the
xrefletters insidestartxref; stream keyword scanning gained the sameendstream-tail guard used elsewhere and now advances past skipped stream bodies
Version 2.16.2
Fixed
- Integer parsing across the byte-level PDF readers now accepts the explicit
+sign allowed by ISO 32000-1 §7.3.3 and rejects digit runs that would overflow, so hostile or corrupt documents can no longer wrap parsed lengths and offsets into misleading values
Version 2.16.1
Fixed
- The PDF/UA injector writes the catalog
/Langvalue as a proper PDF text string; it previously ran the value through the XML escaper, so a language tag containing&or parentheses produced a corrupted entry, and non-ASCII input was written as raw UTF-8 - The PDF/E
/ISO_PDFEVersionInfo entry uses the shared text-string encoder, keeping non-ASCII values legal in PDF 1.7 - XML escaping for XMP packets drops control characters that are illegal in XML 1.0, so metadata copied from a damaged source document can no longer render the whole metadata stream non-well-formed
- PDF-to-XMP date conversion validates that date fields are numeric and pads a missing minute field, preventing malformed ISO 8601 dates in generated XMP; on non-Windows platforms the fallback timestamp now includes the time of day instead of the bare date
Version 2.16.0
Added
- Stream decoding now reconstructs
/DecodeParmspredictors (PNG predictors 10-15 and TIFF predictor 2, ISO 32000-1 §7.4.4.4) after FlateDecode, honouring/Colors,/BitsPerComponentand/Columns; object streams compressed with a predictor — a common PDF 1.5+ writer choice — previously surfaced differenced bytes, so the objects they carry were silently invisible to conformance scans and marker injection
Fixed
- The FlateDecode detection now parses the
/Filtervalue as a name or array instead of a substring match, so cascaded filter chains and occurrences of the word inside unrelated values no longer trigger a bogus inflate; unsupported chains fall back to the raw bytes as before
Version 2.15.1
Fixed
- The dictionary scanner now skips literal strings, hex strings and comments while balancing
<</>>(ISO 32000-1 §7.2.2), so dictionaries containing values such as(A >> B)or a hex string abutting the closing delimiter are no longer truncated during trailer, catalog and conformance-scan parsing - Literal string extraction now decodes the full §7.3.4.2 Table 3 escape set —
\n \r \t \b \f, octal\ddd, line continuations and unescaped EOL normalisation — instead of copying the escape letter verbatim, restoring correct/Producer,/GTS_PDFXVersionand/ISO_PDFEVersioncomparisons for writers that use octal escapes - Literal strings written by the marker injectors now escape CR, LF and other control characters so values survive the reader-side end-of-line normalisation byte-for-byte
Version 2.15.0
Fixed
- Incremental updates written by the PDF/A, PDF/X, PDF/E, PDF/R, PDF/UA and PDF/VT marker injectors and by the PAdES signing and DSS paths now preserve the source document's permanent file identifier: the first trailer
/IDelement is carried over verbatim as required by ISO 32000-1 §14.4 and only the second (changing) element is refreshed; previously both elements were regenerated, so external references and long-term-validation workflows saw a different document identity after every save - PAdES signatures, DSS injection and B-LTA Document Time-stamps now carry the source trailer's
/Inforeference forward (ISO 32000-1 §7.5.6), so document properties no longer disappear from reader panels after signing; the Document Time-stamp trailer also gains the/IDarray - The trailer
/Infofallback for cross-reference-stream documents now locates the XRef stream dictionary correctly and preserves the reference's generation number; it previously never matched on conforming PDF 1.5+ files, silently dropping/Info
Version 2.14.4
Fixed
- The signature dictionary
/Mdate written byTPdf.SignPadesandSignPadesBytesnow carries the mandatoryD:prefix and theZUTC offset marker required by ISO 32000-1 §7.9.4; strict validators previously rejected the signing time as a malformed date string
Version 2.14.3
Fixed
- Dictionary key lookups in the shared PDF reader now match whole name tokens (ISO 32000-1 §7.3.5); previously a stream whose dictionary listed
/Length1before/Length(typical for FontFile streams) was truncated to the wrong byte count, silently blinding PDF/A, PDF/UA and other conformance scans that read font, CMap or metadata streams /Encrypt,/Root,/Sizeand/Infotrailer lookups no longer match longer keys sharing the same prefix (such as/EncryptMetadata)- Object-stream expansion no longer trusts a corrupt or hostile
/Nvalue: non-integer values now yield 0 instead of an uninitialized number, and an upper bound derived from/Firstprevents oversized allocations while scanning malformed documents
Version 2.14.2
Fixed
- The PDF/X, PDF/VT, PDF/UA, PDF/E and PDF/R marker injectors now copy encrypted source documents through unchanged instead of appending plaintext update sections; the previous behaviour produced files whose latest trailer lost the
/Encryptentry (ISO 32000-1 §7.5.6), so conforming readers misread the encrypted body as plaintext TPdf.SignPades,SignPadesBytesandInjectPadesDssMarkersnow raiseEPadesCryptowhen the source document is encrypted, instead of silently emitting a corrupted or unverifiable file; remove encryption before signing or embedding DSS material
Version 2.14.1
Fixed
TPdf.SignPadesandSignPadesBytesnow back-fill all four/ByteRangefields of the signature dictionary; previously the last three fields stayed at their zero placeholders, so produced signatures declared an empty byte range and failed verification in conforming validators- PAdES B-LTA Document Time-stamp dictionaries receive the same
/ByteRangeback-fill correction ValidatePadesCompliancenow accepts the standard signature layout where the byte range gap holds the hex/Contentsvalue, and checks that the second range segment ends exactly at end of file; previously only gapless ranges passed the coverage check
Version 2.14.0
Added
TPdf.ExportXFDFserializes every form field value and annotation across all pages to an XFDF document (ISO 19444-1), emitting<fields>for hierarchical form values and<annots>for all supported annotation subtypes (text, highlight, underline, strikeout, squiggly, line, circle, square, caret, polygon, polyline, stamp, ink, freetext, fileattachment, sound, link, redact)TPdf.ImportXFDFreads an XFDF document back into the loaded PDF, re-creating annotations on the matching pages and applying field values to their widget annotations- The
TPdfAnnotationrecord gainedName(NM),Subject,ModificationDate(M),CreationDate,Icon,Opacity(CA), line endpoints, polygon/polyline vertices and ink-list gesture fields so XFDF round-trips preserve the full annotation metadata - New
XfdfLabsample in the Delphi, C++Builder and Lazarus demo sets demonstrates the export/import round-trip
Version 2.13.6
Fixed
ValidatePdfAnow treats catalog/Metadatastreams without/Type /Metadataor/Subtype /XMLas missing XMP metadata throughpvaiMissingXmpMetadata- PDF/A preflight reports now classify
pvaiMissingXmpMetadataas Metadata and recommend a catalog/Metadatastream with/Type /Metadata,/Subtype /XML, unfiltered XMP, andpdfaidmarkers
Version 2.13.5
Fixed
ValidatePdfAnow reports Widget annotations without an appearance dictionary and PDF/A-2 / PDF/A-3 annotations that require but lack/APthroughpvaiAnnotationApDictViolation- PDF/A preflight reports now categorize
pvaiAnnotationApDictViolationas content that marker injection cannot repair
Version 2.13.4
Fixed
ValidatePdfAnow reports PDF/A-2 and PDF/A-3 inline images whose/Ior/Interpolatevalue istruethroughpvaiImageDictionaryViolation, matching the existing Image XObject dictionary coverage- PDF/A preflight reports now categorize
pvaiImageDictionaryViolationas content that marker injection cannot repair
Version 2.13.3
Fixed
ValidatePdfAnow reports PDF/A-1 inline images that use/LZWDecodeor abbreviated/LZWfilters inside content streams throughpvaiInlineImageLzwForbidden, matching the existing PDF/A-2 and PDF/A-3 inline-image coverage- The inline-image filter scanner now advances past leading resource names such as
/GS1, avoiding stalls while scanning broader PDF/A-1 content streams
Version 2.13.2
Added
TPdf.SetFocusedFormFieldTextwrites text into the currently focused form field's edit buffer viaFORM_ReplaceSelection, symmetric toFocusedFormFieldText. For AcroForm text/combo fields the value commits to/Von focus loss and persists; for XFA text fields the write lands in the in-memory buffer only (PDFium exposes no public API to reconcile XFA values back to the datasets packet, so it does not persist across save)- The JavaScript host platform is now attached whenever the V8 engine is available, regardless of whether the document is XFA — so embedded AcroForm JavaScript (doc-level scripts, field calculations,
app.alert) can execute too. Previouslym_pJsPlatformwas only wired for XFA documents, leaving AcroForm JS silently disabled
Changed
- JavaScript platform attachment is now independent of the XFA decision in
InitializeFormFill— them_pJsPlatformtable is built wheneverV8FeaturesAvailableis true, applied after the XFA version/callback wiring rather than nested inside it
Version 2.13.1
Added
- New host events surface information the v2.13.0 form-fill callbacks previously swallowed:
OnXfaUriAction,OnXfaPageCountChanged,OnXfaFocusChange,OnXfaEmail,OnXfaHttpRequest,OnXfaOpenFile,OnJavaScriptBeep,OnJavaScriptPrint,OnJavaScriptMail,OnJavaScriptSubmitForm. Every event defaults to the existing no-op behavior when unassigned, so existing hosts are unaffected TPdf.XfaFormPacketsread-only property returns a one-shot snapshot of all XFA packets (TXfaPacketList), fulfilling theTXfaPacket/TXfaPacketListtypes previously declared but unused- XFA-specific PDFium error codes
FPDF_ERR_XFALOAD/FPDF_ERR_XFALAYOUTare now bound and surfaced throughLastPdfError, replacing the generic "Unknown error" for XFA load/layout failures
Changed
FFI_DoURIActionWithKeyboardModifiernow consultsOnXfaUriActionbefore shell-executing a URI from an XFA field, giving the host a veto (security: a malicious XFA field could previously launch arbitrary URLs unconditionally). Unassigned handlers preserve the priorShellExecuteWdefaultDecodeFormFieldTypenow routes XFA field types throughIsXfaFormFieldrather than an explicit 8-branch case, keeping the enum aligned withFPDF_FORMFIELD_XFA_*by ordinal offset
Fixed
ValidatePdfAnow reports PDF/A-1 claims that use PDF 1.5 cross-reference streams or object streams with the newpvaiPdfA1Pdf15Structureissue, while continuing to allow object streams for PDF/A-2 and PDF/A-3
Version 2.13.0
Added
- Full XFA (XML Forms Architecture) runtime support:
TPdf.InitializeFormFillnow wires all 14 version-2FPDF_FORMFILLINFOcallbacks (FFI_DisplayCaret,FFI_GotoURL,FFI_PageEvent,FFI_PopupMenu,FFI_OpenFile,FFI_EmailTo,FFI_UploadTo,FFI_GetPlatform,FFI_GetLanguage,FFI_DownloadFromURL,FFI_PostRequestURL,FFI_PutRequestURL,FFI_OnFocusChange,FFI_DoURIActionWithKeyboardModifier) and attaches anIPDF_JsPlatformso an XFA-enabledpdfium.dllcan render and script dynamic XFA forms - New
Lib\FPdfXfa.pasunit declaring the XFA constants (FXFA_PAGEVIEWEVENT_*,FXFA_MENU_*,FXFA_SAVEAS_*,FPDF_FORMFIELD_XFA_*) andTXfaPacket/TXfaSaveFormattypes that were previously only referenced in comments - XFA static packet reader on
TPdf:GetXfaPacketCount/GetXfaPacketName/GetXfaPacketContent/GetXfaPacketByNameplusGetXfaTemplate/GetXfaDatasets/GetXfaConfigextract the XFAtemplate,datasetsandconfigpackets as raw XML without needing an XFA-enabled runtime — useful for compliance auditing and data migration - Capability probes: global
XfaFeaturesAvailable, and per-documentTPdf.XfaRuntimeAvailable(whetherFPDF_LoadXFAactually succeeded) andTPdf.XfaStaticReadable(whether the packet reader exports resolve) TPdfFormFieldTypeextended withfiXfa,fiXfaCheckBox,fiXfaComboBox,fiXfaImageField,fiXfaListBox,fiXfaPushButton,fiXfaSignature,fiXfaTextField, withDecodeFormFieldTypemapping the newFPDF_FORMFIELD_XFA_*values- JavaScript host events on
TPdf:OnJavaScriptAlert,OnJavaScriptResponse,OnXfaGotoUrlandOnXfaRuntimeMissinglet the host customize JS dialogs and XFA navigation, or react when an XFA document cannot run the engine - New
XfaLabDelphi sample demonstrating XFA detection, packet extraction, capability probing and the runtime-missing fallback path
Changed
TPdf.LoadDocumentnow pre-scans the input for XFA markers (/XFAin the AcroForm dictionary, or catalog/NeedsRendering) and, when found, auto-selectspdfium.v8.dllby settingEnableV8Engine := Truebefore the singleton library is first loaded; once a plainpdfium.dllis loaded the process cannot switch, soOnXfaRuntimeMissingsignals that caseTPdf.GetPageCountnow reflects the page count the XFA engine reports viaFFI_PageEventafter dynamic repagination, rather than only the static PDF page tree- When an XFA document is opened but the runtime is unavailable,
InitializeFormFillnow pinsversion=1andxfa_disabled=1instead of requesting version 2 with unassigned callbacks, which previously risked a bad callback pointer dereference
Version 2.12.2
Fixed
ValidatePdfACompliancenow reports used custom XMP namespaces withoutpdfaExtension:schemaswhile still accepting standardpdfaidmetadata without extension declarations- PDF/A-3 embedded file validation now requires both top-level
/Fand/UFentries on filespec dictionaries and ignores nested/EFstream keys when checking those names
Version 2.12.1
Fixed
ValidatePdfACompliancenow decodes escaped PDF name tokens before matching JavaScript, LZWDecode, Type1, and related forbidden names, so obfuscated but semantically identical names are reported correctly- PDF/A inline-image checks now reject
/Filterand/Fvalues that use/LZWDecode, abbreviated/LZW, or/Crypt, including array and escaped-name forms - PDF/A validation now reports metadata streams with forbidden stream filters, OutputIntent ICC profiles whose
/Ncomponent count is missing or inconsistent, and PDF/A-3 embedded file specs with missing or invalid/AFRelationship
Version 2.12.0
Added
- TSA HTTP requests now set explicit 30 s timeouts for each phase (resolve/connect/send/receive) via
WinHttpSetTimeouts, so a slow or unreachable timestamp authority cannot hang the signing thread indefinitely instead of relying on WinHttp's implicit defaults - Per-request nonce derivation for PAdES B-T / B-LTA timestamp requests when the caller omits
TPadesSignOptions.Nonce: a SHA-256 fold of monotonic counter + wall clock +GetTickCount64+ process id replaces the previous fixed$100000000fallback, so two requests issued in the same millisecond no longer reuse the same anti-replay nonce PdfInflatenow caps decompressed output at 256 MiB to stop a zlib-compressed stream from exhausting memory on a hostile or corrupt input (a “zlib bomb”); the cap is generous for any real PDF stream
Changed
TPdfViewoverlay blending (search highlight, text selection, reading word, spread selection) no longer uses per-pixelGetPixel/SetPixelV; the rectangle is now blended through a 32-bpp off-screenTBitmapandScanLinein a single pass, eliminating thousands of GDI kernel crossings per paint and making large selections responsiveFPdfAsn1.TDerReader.ReadIntegernow rejects INTEGER fields longer than 8 bytes (and 8-byte negatives whose sign bit would requireshl >= 64), returning 0 instead of computing a wrong value through undefined-shift behaviour on CMS/PAdES ASN.1 inputParseTimeStampRespno longer echoes the request nonce back asTPadesTimestamp.Nonce; until the TSTInfo walker that verifies the returned nonce lands, the field stays 0 to signal “not verified” rather than giving callers false confidence that the timestamp response is fresh
Fixed
PointsToPixelsreturned its input unchanged for every DPI: the divisor wasPointsPerInch(the 72 constant) instead of the literal 72, collapsing the formula toResult := Points. Any external caller doing points→device-pixel sizing through this helper now gets the correctPoints × PixelsPerInch / 72PdfMaxObjNumundercounted on documents that use object streams (PDF 1.5+ ObjStm): objects compressed inside an/ObjStmcarry noN 0 objmarker, so the raw-byte scan missed them, and injectors that allocateMaxObj+1for new objects would collide with hidden ObjStm members and silently corrupt the file. The scan now expands object streams first so every object number is visibleInjectPdfAMarkersno longer forges a PDF/A conformance claim on an encrypted document: PDF/A (ISO 19005-1 §7.1) forbids encryption, and the injector previously copied the source through with the markers even though the very next validation would reject it. WhenHasEncryptis set the source is now passed through unchanged. The normalTPdf.SaveAsPdfApath already strips encryption (saRemoveSecurity) before injection, so this only affects direct callersPdfReadStreamBytesnow refuses a/Lengthlarger than the entire file before allocating the result buffer, closing an early-allocation path on a corrupt or hostile indirect length
Version 2.11.0
Added
- The PDFium
FPDF_FILEHANDLERrecord now declares its six callbacks (Release,GetSize,ReadBlock,WriteBlock,Flush,Truncate) as real fields instead of comments, matching the C header layout. The XFA FFI file-transfer callbacks (FFI_OpenFile/FFI_EmailTo/FFI_UploadTo/FFI_DownloadFromURL) that return or consumePFPDF_FILEHANDLERare still left unimplemented in the Pascal form-fill layer, but the type is now structurally correct for any future XFA submit/upload path - PDFium library load and unload (
LoadLibrary/UnloadLibrary) are now serialised by a process-global critical section, so twoTPdfFuture<T>worker threads (or a worker racing the main thread) cannot both observePDFiumLibrary=0and double-bind, or free the DLL while another thread is mid-bind - An
initialization/finalizationsection now callsUnloadLibraryon unit unload, ensuringFPDF_DestroyLibraryruns (worker-thread join, V8 isolate disposal, font/cache teardown) instead of relying on the OS to reclaim the DLL
Changed
TPdf.SetActivenow swallows any exception during load (previously onlyEPdfError), so a stream error or access violation during form/page setup leavesActive=Falseinstead of a partially-loaded component with indeterminate state- Consistent character encoding for PDFium metadata key arguments:
TPdf.GetMetaTextnow uses the same FPCAnsiString/ DelphiUTF8Encodesplit asGetViewerPreferenceand the load paths, instead of a bareAnsiString(Tag)cast - Deduplicated the
BytesToAnsi,AnsiToBytes,WriteBytesandWriteStrhelpers:FPdfCompressnow imports them fromFPdfPdfCommon(itsWriteBytesToStream/WriteAnsiToStreamaliases are retired) and the redundant three-argumentBytesToAnsioverload inFPdfPdfais removed.FPdfAsn1keeps its local copy by design to keep the cryptography layer free of the conformance-layer unit
Fixed
- Resource leak in
TPdf.LoadDocument(file, memory,TBytes,TMemoryStream, custom stream) andTPdf.CreateDocument: ifInitializeFormFillorReloadPageraised afterFPDF_LoadDocument/FPDF_CreateNewDocumentsucceeded, the nativeFPDF_DOCUMENThandle was leaked becauseFActivewas still False at that point. Each path now wraps the post-load setup intry/exceptand closes the document on failure, leaving the component cleanly inactive - Friendlier PDFium DLL load diagnostics:
CheckLoadLibrarydetectsERROR_BAD_EXE_FORMAT(193) and reports a 32/64-bit architecture mismatch pointing at the matchingDLLs/Win32orDLLs/Win64build, instead of relaying only the generic OS error.CheckGetProcAddressnow states the deployedpdfium.dllis older than the binding when a required export is missing, rather than the bare OS "procedure not found" text
Version 2.10.1
Fixed
- PAdES SignerInfo sid standardisation: the signer identifier now uses the RFC 5652 §5.3
issuerAndSerialNumberform (issuer Name + serialNumber, both extracted verbatim from the signer certificate DER), replacing the previous non-standardsubjectKeyIdentifier+ full-cert SHA-256 placeholder that Adobe Acrobat and other conforming validators rejected. A new TbsCertificate DER walker (ExtractIssuerAndSerial) reads the issuer SEQUENCE and the serial INTEGER as raw TLV bytes — serials commonly exceedInt64range, so the raw TLV is mandatory. ThesubjectKeyIdentifierform remains as a fallback only when cert DER parsing fails
Changed
TCmsSignerId.SerialNumber: Int64replaced withSerialDer: TBytes(the raw serialNumber TLV). The CMS builder embeds the sliced TLV verbatim inIssuerAndSerialNumber, avoidingInt64overflow on 20-byte CA serials (RFC 5280 §4.1.2.2 upper bound)
Version 2.10.0
Added
- PAdES B-LT long-term validation: when
TPadesSignOptions.Level >= plB_LT,SignPadesBytesappends an incremental update carrying a/DSSdictionary with the signer certificate and the full intermediate chain (the self-signed root is excluded per RFC 5652 §10.2.3), plus the/Extensions /ESICLevel 1 marker (EN 319 142-1 §5.4.2) - PAdES B-LTA archive timestamp: when
Level >= plB_LTAandTsaUrlis set, a Document Time-stamp signature dictionary (/SubFilter /ETSI.RFC3161) is appended whose/ByteRangecovers the entire file; the ESIC marker is promoted to Level 2. This completes the four PAdES baseline levels (B-B, B-T, B-LT, B-LTA) - Certificate chain collection:
ResolveWinSignernow callsCertGetCertificateChainand populatesTPadesResolvedSigner.ChainCertDerwith the intermediate CA certificates, so B-LT/DSS /Certscarries every cert needed to validate the signature without external lookups.CertFreeCertificateContextis now bound, closing the one-context-per-sign leak noted in v2.8.0 - PDF/A integration workflow:
TPdf.SignPadesWithPdfAconverts the document to PDF/A first (highest level the library emits today) then applies the requested PAdES signature — the long-term-archival container pattern EN 319 142-1 Annex A.7 recommends
Version 2.9.0
Added
- PAdES B-T trusted timestamp:
TPadesSignOptionsgainsLevel,TsaUrlandNoncefields. WhenLevel >= plB_TandTsaUrlis set,SignPadesBytesextracts the signature value from the built CMS, requests an RFC 3161 timestamp over it, and embeds the returned TimeStampToken as the SignerInfo unsigned attributesignature-time-stamp— the B-T trusted-time step (EN 319 142-1 §6.3 req o) FPdfTsa: cross-platform RFC 3161 client —BuildTimeStampReq(version 1, SHA-256 messageImprint over the signature value, nonce, certReq=true),ParseTimeStampResp(accepts PKIStatus 0/1, rejects 2+, extracts the TimeStampToken ContentInfo verbatim), andRequestTimestamp(one-shot build+POST+parse).PadesTsaAvailablegates the feature on platforms without an HTTP backendFPdfTsaWin: Windows WinHttp backend, dynamically bound from winhttp.dll (zero new compile-time dependency; HTTPS negotiated by the Windows certificate store). Mirrors theFPdfCryptoWindynamic-binding patternFPdfCms:ExtractSignatureValuewalks a built CMS to recover the raw signature octets (the TSA hash input), andAddSignatureTimestampToCmsrebuilds the ContentInfo with a newunsignedAttrs [1](0xA1) carrying the timestamp attribute. The stage-1 validator recognises the result as a B-T signature
Version 2.8.0
Added
- PAdES B-B signing stack: four new pure-Pascal/cross-platform building blocks (
FPdfSha256,FPdfAsn1,FPdfCms,FPdfCrypto) plus a Windows CNG backend (FPdfCryptoWin) letTPdf.SignPades/SignPadesToStreamproduce a PAdES B-B signature end-to-end. The signer certificate is resolved by SHA-1 thumbprint from the Current User “MY” store; RSA-PSS (recommended), RSA PKCS#1 v1.5 and ECDSA are all supported viaNCryptSignHash FPdfSha256: self-contained FIPS 180-4 SHA-256 (Init/Update/Final + one-shot helpers). FPC 3.2.2 ships no SHA-2 unit, so the library owns one to keep every CMS code path on a singleTSHA256Digesttype with no RTL branchingFPdfAsn1: DER encoder (TDerWriter) and reader (TDerReader) covering SEQUENCE/SET/OID/INTEGER/OCTET STRING/UTCTime/GeneralizedTime/context-specific tags, with the definite-length encoding and IMPLICIT-tag handling CMS requiresFPdfCms: CAdES SignedData builder (BuildSignedData) emitting the content-type, message-digest and signing-certificate-v2 signed attributes PAdES baseline mandates, with optional signing-time and commitment-type-indication. The signedAttrs digest is computed over the SET-tagged (0x31) form and re-emitted with the IMPLICIT [0] (0xA0) tag per RFC 5652 §5.4FPdfCrypto+FPdfCryptoWin: cryptographic-backend abstraction withPadesCryptoAvailable/ResolvePadesSigner, and the Windows implementation binding crypt32.dll / ncrypt.dll dynamically (no new compile-time DLL dependency). ECDSA signatures are re-encoded from the Windows IEEE P1363 r¦s form into the DERECDSA-Sig-ValueCMS requiresSignPadesBytes: byte-level signature injection — reserves a fixed-width/Contentshex slot, computes the covering/ByteRange, digests the document, builds and embeds the CMS, and appends the incremental update. The validator (v2.7.0) recognises the output as a PAdES B-B signature
Version 2.7.0
Added
- PAdES structural validator (ETSI EN 319 142-1 V1.2.1): the new
FPdfPadesunit andTPdf.ValidatePadesmethod inspect signature value dictionaries reachable from/ByteRange, walk the CMSSignedDatainside/Contentsfar enough to confirm the CAdES detached shape, and detect the four baseline levels (B-B, B-T, B-LT, B-LTA) plus Document Time-stamp dictionaries (/SubFilter /ETSI.RFC3161) - PAdES clause-level issue set: 26
ppei*enums cover/SubFilteracceptability (adbe.pkcs7.sha1andadbe.x509.rsa_sha1flagged as forbidden),/ByteRangefile coverage,/Certprohibition, CMSSignedDatashape (single signer, detached eContent, version range), the required signed attributes (content-type,message-digest,signing-certificate/v2), forbidden digests (MD5, SHA-1),/Reasonvscommitment-type-indicationmutual exclusion (req d), the B-T trusted-time requirement, the B-LT/DSS+/Certs+ ESIC Level 1 marker, and the B-LTA Document Time-stamp + ESIC Level 2 marker - DSS injector:
TPdf.SaveAsPadesDss/SaveAsPadesDssToStreamappend an incremental update carrying a/DSSdictionary (with/Certs,/OCSPs,/CRLsstream arrays) and the/Extensions /ESICmarker (Level 1 or 2) onto a copy of the document, preserving the original bytes — the B-LT/B-LTA validation-material embedding step (clause 5.4.2) - Cross-platform, zero-dependency stage: the validator and injector are pure-Pascal and work on every supported IDE (Delphi, Lazarus, FPC, C++Builder); no cryptographic backend is required for this release, and no new DLL dependency is introduced
Version 2.6.0
Changed
- Cross-standard deduplication: seven more duplicated helper functions (PdfEnclosingObjNum, PdfDictRefNum, PdfExpandObjectStreams, PdfTextStr, ExtractLiteralString, ExtractXmpAttr) have been removed from the individual standard units and consolidated into
FPdfPdfCommon, reducing ~300 lines of copy-paste maintenance burden - PreflightReport quality: PDF/X and PDF/E content-class issues that previously fell through to the generic “missing marker” category now carry accurate Content/Metadata/Security categories and clause-specific recommendations (~15 enums across both standards)
- PDF/E and PDF/R test coverage: six more zero-coverage enums gained positive tests (
pveiLzwForbidden,pveiJavaScriptForbidden,pveiFormFieldsForbidden,pveiEmbeddedFilesForbidden,pvriBadHeader,pvriProhibitedInfoEntry) - Lazarus build fix:
Tests.PdfVT(a Delphi-only DUnitX unit added in v2.5.x) is now excluded from the Lazarus project to restore compilation
Version 2.5.3
Added
- OutputIntent completeness (PDF/X-4 §6.2.4):
pvviOutputIntentSchemeflags an OutputIntent whose/Sis not/GTS_PDFX;pvviOutputIntentMissingIdentifierflags a missing/OutputConditionIdentifier - PDF/VT-2 Reference XObject exemption (§6.2.2):
pvviReferenceXObjectForbiddenno longer fires for aPDF/VT-2file, which may legally use Reference XObjects on an X-5g/5pg base - MIME boundary character validation (RFC 2046 §5.1.1):
vtmviBoundaryInvalidCharflags a boundary whose characters fall outside the bchars set or whose length exceeds 70
Fixed
InjectPdfVTMarkersnow writes Info/CreationDateand/ModDatefrom the save options, so the produced file round-tripsValidatePdfVTCompliancewithout a falsepvviInfoModDateMismatch(the injector previously rewrote the XMP dates but left the Info dictionary dates stale)
Version 2.5.2
Added
- Info
/ModDateconsistency (§6.3 NOTE 2, PDF/X-4 base):pvviInfoModDateMismatchflags an Info dictionary/ModDatethat, after PDF-date to XMP-date normalisation, does not equalxmp:ModifyDate - PDF/VT-2s inline chunk conformance (Annex A.2): the MIME validator now runs
ValidatePdfVTComplianceon every inlineapplication/pdfpart and flags a non-PDF/VT body viavtmviInlinePdfNotPdfVT
Version 2.5.1
Added
- DParts chunking validation (ISO 16612-2 §6.5 Table 4):
pvviDPartsBadChunkingflags a/DPartsarray whose non-final sub-arrays do not have exactly 8192 entries or whose last sub-array falls outside 1..8192 - RecordLevel cross-stream consistency (Annex A.2): the PDF/VT-2s MIME validator now extracts each inline PDF's
/RecordLeveland flags disagreement viavtmviRecordLevelMismatch, complementing the existing NodeNameList check - Recurring graphical object hints (§6.7):
pvviGtsScopeInvalidValueflags a/GTS_Scopeoutside {SingleUse, Record, File, Stream, Global, Unknown};pvviGtsScopeRecordWithoutRecordLevelflags/Recordwithout a/RecordLevel;pvviGtsXidNotUuidflags a/GTS_XIDthat is not an RFC 4122 uuid: URI;pvviGtsEnvMissingflags a missing/GTS_Envwhen/GTS_Scopeis Stream or Global (§6.7.4) - MIME forward-reference detection (Annex A.2):
vtmviForwardReferenceflags an inline PDF that cites a filename (via/EF /F) not introduced by an earlier attachment part in the stream
Fixed
ExtractNodeNameListFromPdfandExtractRecordLevelFromPdfinFPdfPdfvtMimeresolved a recurring off-by-one where the 1-based offset returned byAnsiFindKeywas treated as an absolute byte offset into the expanded PDF
Version 2.5.0
Added
- PDF/VT Document Part Metadata (DPM, ISO 16612-2 §6.6):
TPdfVTSaveOptionsgainedDpmEntriesandDpmTargetso a writer can attach a/DPMdictionary to the synthesized DPart node, with key-name validation against the Annex E second-class-prefix rule and the §6.6 NMTOKEN / uniqueness /GTS_Managed-shape rules on the validator side - PDF/VT-2s streaming exchange (Annex A): the new
FPdfPdfvtMimeunit providesBuildPdfVT2sStreamandValidatePdfVT2sStreamfor themultipart/mixedMIME envelope carrying inline PDF/VT chunks plus attachment ICC profiles, with theX-PDFVT-Stream-version: 1header ordering rule and cross-streamNodeNameListconsistency check TPdf.ValidatePdfVTnow performs an authoritative JavaScript-action count viaFPDFDoc_GetJavaScriptActionCount, complementing the byte-level/JavaScriptname scan
Fixed
- PDF/VT
Trappedcorrectness on the PDF/X-4 base: theptvUnknownenum value is removed (PDF/X-4 forbids/Unknown),ptvUnspecifiedis normalized to/Falseat write time (a missing/Trappedis also forbidden), and a newpvviTrappedInvalidissue flags an absent orUnknownvalue ValidatePdfVTCompliancenow expands object streams (PdfExpandObjectStreams) before scanning, so a catalog, OutputIntent or Metadata dictionary stored inside a compressed ObjStm (PDF 1.5+, typical of PDF/X-4 producers) is reachable by the byte-level lookups
Changed
- PDF/VT-1 now inherits the full PDF/X-4 content prohibitions:
pvviAcroFormForbidden(/AcroFormor/XFA),pvviAdditionalActionsForbidden(catalog/AA),pvviMissingTrimBoxandpvviReferenceXObjectForbidden(Reference XObject, X-5g/5pg only) - Cross-standard deduplication:
BuildDictObj,IccComponentCount, the built-in sRGB ICC profile (GetSrgbIccProfile),PdfTextStr,PdfEnclosingObjNum,PdfDictRefNumandPdfExpandObjectStreamswere promoted from triplicated local copies inFPdfPdfa/FPdfPdfx/FPdfPdfvtto a single canonical home inFPdfPdfCommon; the 3144-byte ICC literal now exists exactly once in the codebase
Version 2.4.0
Fixed
InjectPdfUaMarkersno longer drops the trailer/Inforeference on a cross-reference-stream base: the localSourceTrailerInfoRef(which lacked the xref-stream fallback) has been replaced by the sharedPdfSourceTrailerInfoRef(promoted from the PDF/A copy which had the fallback since v2.0.0)- The shared
PdfReadStreamBytesnow handles indirect/Length N G Rreferences (ported from the PDF/A local copy), so the PDF/VT, PDF/R and PDF/E validators no longer mis-read or skip XMP metadata streams produced by tools that use indirect Length (Acrobat, Ghostscript)
Changed
- Cross-standard deduplication: the local
PdfReadTrailercopies inFPdfPdfaandFPdfPdfx, the localSourceTrailerInfoRefcopies inFPdfPdfaandFPdfPdfua, and the localPdfReadStreamBytesinFPdfPdfahave all been deleted — the sharedFPdfPdfCommonversions now apply everywhere. This removes ~330 lines of duplicated code and eliminates the maintenance burden of keeping copies in sync - PDF/X test-debt closure: seven previously zero-coverage content-class enums gained positive tests (
pvxiLzwForbidden,pvxiJavaScriptForbidden,pvxiFormFieldsForbidden,pvxiAdditionalActions,pvxiEmbeddedFilesForbidden,pvxiMissingTrimBox,pvxiTrappedNotSet)
Version 2.3.0
Changed
- PDF/A test-debt closure continues: three more zero-coverage enums gained positive tests.
pvaiForbiddenRenderingIntent(§6.2.9) flags a non-standard rendering-intent name in a content stream.pvaiJpeg2000Violation(§6.2.2) flags a JPXDecode image with/NumComponentsoutside {1,3,4} at Part 2.pvaiInlineImageLzwForbidden(§6.1.10) flags an inline image using the LZW filter at Part 2
Version 2.2.0
Changed
- Cross-reference-stream regression tests: the existing
Validate_XrefStreamTrailer_DetectsConformancenow also verifies that the catalog/Metadatareference is resolved and the XMPpdfaid:partis read on an xref-stream base (not just/Root+/ID). A newInjectPdfA_XrefStreamBase_RoundTripstest guards the injector's xref-stream path added in v2.0.0. Two cross-standard tests (PdfE_XrefStreamBase_NotRejectedAsUnparsable,PdfR_XrefStreamBase_NotRejectedAsUnparsable) verify the PDF/E and PDF/R validators no longer reject xref-stream PDFs as unparsable - PDF/A test-debt closure:
Validate_MinimalPdf_FlagsRequiredMarkersasserts that a bare minimal PDF triggerspvaiMissingPdfAIdentifier,pvaiMissingOutputIntent,pvaiMissingIccProfile,pvaiMissingXmpMetadataandpvaiMissingXmpDates— closing the symmetry gap with the PDF/E and PDF/X validators which already had equivalent tests. Two more zero-coverage enums gained positive tests:pvaiUnembeddedFontandpvaiSubsetMissingCidSet
Version 2.1.0
Fixed
- PDF/E was inadvertently left out of the v2.0.0 cross-reference-stream fix: both
InjectPdfEMarkersandValidatePdfECompliancestill calledPdfReadTrailerwithoutAcceptXrefStream, so the PDF/E injector silently failed on PDF 1.5+ output (pdfium’sSaveAsCopydefault). Both call sites now passTrue - The shared
PdfReadTrailercross-reference-stream fallback now carries the/Type /XRefguard that the PDF/A and PDF/X local copies already had, so a corruptstartxrefoffset pointing at an unrelated dictionary fails cleanly instead of being mis-parsed as the trailer - The indirect-reference
/Langresolver inValidatePdfUaCompliance(v2.0.0) was unreachable:PdfFindObjDictonly finds<<dictionaries, but a/Langstring object is(...)or<...>with no dictionary. Replaced with a direct object-body scan that locates the string token
Changed
- Seven dead-shadow helper duplicates (PdfStructureBytes, PdfHasName, PdfCountName, BuildStreamObj) that were byte-identical copies of the shared
FPdfPdfCommonversions have been removed fromFPdfPdfaandFPdfPdfua— the shared versions now apply everywhere viauses
Version 2.0.0
Fixed
- Cross-standard silent failure: the shared
PdfReadTrailerhelper (used by the PDF/UA, PDF/X, PDF/VT and PDF/R marker injectors and validators) now accepts anAcceptXrefStreamparameter and falls back to the cross-reference-stream object dictionary when notrailerkeyword is present (PDF 1.5+). Previously, pdfium’sSaveAsCopyoutput (which uses a cross-reference stream) caused every marker injector to silently fail — the source bytes were copied through unchanged and the call still returned success. The PDF/R-1.0 validator (whose PDF 2.0 base is always a cross-reference stream) was effectively a no-op. The PDF/A validator’s mature implementation was ported to the shared helper so every standard benefits - Trailer dictionary scanning in
InjectPdfUaMarkersandInjectPdfAMarkersnow uses the depth-awarePdfDictEndinstead of a bare>>search, so a trailer containing a nested dictionary (e.g./Encrypt << ... >>) is no longer cut short before a trailing/Infoentry
Changed
TPdf.ValidatePdfUanow suppresses the coarse byte-levelpvuaiFontNotEmbeddedwhen the precise Pdfium object-modelpvuaiPdfiumFontNotEmbeddedhas already fired, so the preflight report no longer carries two near-duplicate “embed your fonts” rows for the same defectpvuaiLangInvalidFormat(§7.2) now resolves an indirect-reference/Lang(N 0 R) to its string object and validates the content, so an indirectly-referenced language tag is no longer a blind spot
Version 1.99.0
Fixed
pvuaiLangInvalidFormat(§7.2) no longer gives hex-encoded/Langstrings a free pass: UTF-16BE pairs (with aFE FFBOM) and bare ASCII hex strings are now decoded and run through the same BCP 47 grammar check as literal(...)strings, so a malformed hex/Langis caught while a conformant one (e.g. a UTF-16BEen-US) is no longer at risk of being flagged
Changed
pvuaiFontMissingToUnicode(§7.21.7) now exempts/MacExpertEncodingalongside/WinAnsiEncodingand/MacRomanEncoding, matching the four exemption conditions the clause lists
Version 1.98.0
Added
pvuaiNeedAppearancesTrue(§7.18.4) flags an AcroForm whose/NeedAppearancesflag is true, so widget appearances are not reliably locked and assistive technology cannot associate them with the structure tree. Ported from the PDF/A validator and gated on/AcroFormpresence to narrow the scan surface
Changed
- veraPDF corpus regression: wired the §7.20 Reference-XObject pass+fail pair and the §7.21.4.2 subset CharSet/CIDSet pass+fail pairs into
Live_Corpus_ValidatePdfUaMatchesConformance. The §7.21.7 ToUnicode-forbidden-value and §7.18.6.2 media-clip pass samples were also wired as false-positive guards (their fail samples use dictionary layouts the byte-level scan does not catch, so only the pass side is wired) - The corpus pass-path assertion list gained 15 new zero-false-positive guards so every active
pvuai*byte-level and structure check is now exercised against conformant samples (previously only ~30 of the 60 active issues were guarded). ThepvuaiLangInvalidFormatguard was deliberately omitted because the byte-level checker conservatively flags hex-encoded/Langstrings it cannot decode
Version 1.97.0
Fixed
ValidatePdfUaStructureElementshardening: theEnclosingTableparent-chain walk now carries a hop counter (bounded by the element count), so a malformedParentIndexcycle on a synthetic structure-element array can no longer hang the caller. TheValidatePdfUaPageContentTaggingmarked-content-ID array allocation is now capped at one million entries, preventing a multi-GB allocation on a malformed/maliciousMarkedContentID
Changed
- The
pvuaiOrderedListMissingListNumberingenum doc comment now accurately describes what the check does: it flags anLelement whoseListNumberingvalue is outside the ISO 32000-1 Table 347 set (an absent attribute is not flagged). The earlier comment implied it also detected ordered lists missing the attribute, which the implementation does not do - The two
7.21.3.3-t02WMode-mismatch corpus fail samples are now wired intoLive_Corpus_ValidatePdfUaMatchesConformance— since v1.95.0 the CMap stream is FlateDecode-inflated, so the dictionary-vs-content comparison now runs on a readable side. The stale “not wired” comment was removed
Version 1.96.0
Added
- Cross-standard consistency:
TPdf.ValidatePdfUagains two checks ported from the PDF/A validator.pvuaiAnnotationFlagsViolation(§7.18.1) flags a non-exempt annotation carrying the Hidden / Invisible / NoView flag, which breaks the assistive-technology reading flow.pvuaiActionTargetMissing(§7.18.5) flags a GoToR / URI / SubmitForm action that lacks its required target key (/F+/D, /URI, /F), leaving the link unusable by AT
Fixed
- Cross-page structure-tree merge: the
AllElemsaccumulation loop inTPdf.ValidatePdfUanow rebases each element'sParentIndexfrom the page-local array to the merged array. Without this, page 2's child elements kept a page-local index that pointed into page 1's slice, silently corrupting every ParentIndex-dependent check (table/list structure, §7.4.4 H-child count, EnclosingTable) - RoleMap parsing:
PdfReadRoleMapPairsno longer terminates the whole key/value scan when a value is an indirect reference (N 0 R) or an array ([...]) — both valid RoleMap forms per ISO 32000-1 14.8.5.1. It now skips just that entry (Continue) instead ofBreak-ing, eliminatingpvuaiRoleMapUnresolvedfalse positives on types mapped after an indirect/array entry
Changed
FPdfPreflightReport: 18 activeTPdfUaValidationIssuevalues that previously fell through to the catch-all “missing marker” category and recommendation now carry accurate categories (Structure / Content / Metadata / Security) and clause-specific recommendations. Also fixed thepuaNone / pua1→pucNone / puc1typo inPDFSpecComplianceMatrix.md
Version 1.95.0
Changed
TPdf.ValidatePdfUarecall and soundness pass: the §7.21.3.3pvuaiCMapWModeMismatchcheck and the §7.21.7pvuaiToUnicodeForbiddenValuecheck now inflateFlateDecode-compressed CMap / ToUnicode streams before scanning (previously only uncompressed streams were judged, a known false negative). The sharedPdfInflate/PdfReadAndDecodeStreamhelpers were promoted fromFPdfPdfa/FPdfPdfxtoFPdfPdfCommonso every conformance unit shares one copy
Added
pvuaiSubsetCharSetEmpty(§7.21.4.2) flags a Type 1 subsetFontDescriptorthat carries a/CharSetkey whose string value is empty — the existingpvuaiSubsetMissingCharSetonly caught a missing key. An empty/CIDSetis not flagged, since a font with no CIDs may legitimately carry an empty bitmap
Version 1.94.0
Added
- Second-pass
TPdf.ValidatePdfUaaudit closed six ISO 14289-1 gaps surfaced by a clause-by-clause review and a re-scan of Pdfium native APIs already wrapped but unused by the PDF/UA path.pvuaiHeadingFormatInvalid(§7.4.3) flags user-defined heading tags that start with H but carry separators, spaces or Roman numerals instead of pure Arabic digits.pvuaiMissingDocumentOutline(§7.17, should) flags a multi-page document that carries no bookmark outline (single-page documents are exempt).pvuaiStructElementLangInvalid(§7.2) flags a structure element/Langvalue that is not a valid BCP 47 tag.pvuaiWidgetMissingPrintField(§7.14 / §7.18.4) flags a Widget structure element missing the PrintField attribute owner.pvuaiLinkNotInStructureTree(§7.18.5) flags a document whose/Subtype /Linkannotations are not exposed as Link structure elements.pvuaiPdfiumAnnotationMissingContentsandpvuaiPdfiumLinkMissingContents(§7.18.1 / §7.18.5) add a precise Pdfium object-model annotation scan that exempts hidden, off-crop-box, Popup and Widget annotations — eliminating the false positives of the byte-level heuristic, which cannot read the/Fflags or/Rect
Version 1.93.0
Added
TPdf.ValidatePdfUanow layers a Pdfium object-model pass on top of the byte-level inspector, mirroring the PDF/A round-7 architecture: it walks every page’s text objects viaFPDFTextObj_GetFont→FPDFFont_GetIsEmbedded(pvuaiPdfiumFontNotEmbedded, §7.21.4) and scans every character viaFPDFText_HasUnicodeMapError(pvuaiPdfiumUnicodeMapError, §7.21.7) andFPDFText_GetUnicode(pvuaiPdfiumNotDefGlyph, §7.21.8) — more precise than the byte-level heuristics, which only fire when zero font programs are present or no/ToUnicodeappears at all. The walk short-circuits at three levels: the page loop exits when all three Pdfium-layer issues are already set, the per-object loop exits on the first non-embedded font, and the character scan skips the.notdefpass whenUnicodeMapErroralready hit. PDF/UA was the last PDF-standard validator without a Pdfium object-model layer
Version 1.92.0
Added
- Created
Tests.PdfR— the first test file for the PDF/R-1 validator (FPdfPdfr), covering header validation, ObjStm prohibition, raster-marker detection, and a clean-file no-false-positive guard. All six PDF-standard test suites now have dedicated test files: PdfA(80), PdfUa(101), PdfX(7), PdfE(5), PdfVT(15), PdfR(4) = 212 tests total
Version 1.91.0
Added
ValidatePdfEandValidatePdfVTgained content-level checks previously available only in the PDF/A, PDF/UA and PDF/X validators:pveiLzwForbidden,pveiJavaScriptForbidden,pveiFormFieldsForbidden(PDF/E only),pveiEmbeddedFilesForbidden(PDF/E only),pveiOpiForbidden,pvviLzwForbidden,pvviJavaScriptForbidden,pvviEmbeddedFilesForbidden,pvviOpiForbidden.TPdf.ValidatePdfEandTPdf.ValidatePdfVTalso gain a Pdfium object-model layer (pveiPdfiumFontNotEmbedded/pvviPdfiumFontNotEmbedded) that walks page text objects viaFPDFFont_GetIsEmbedded, short-circuiting on the first non-embedded font
Version 1.90.0
Added
TPdf.ValidatePdfXnow layers a Pdfium object-model pass on top of the byte-level inspector: it walks every page’s text objects viaFPDFTextObj_GetFont→FPDFFont_GetIsEmbeddedand reports a non-embedded font aspvxiPdfiumFontNotEmbedded— more precise than the byte-level heuristic which only fires when zero font programs are present. The walk short-circuits on the first non-embedded font found
Changed
TPdf.ValidatePdfUastructure-tree walk: the per-pageValidatePdfUaPageContentTaggingcall (which builds a marked-content-ID claim map and cross-checks every text/image object) is now skipped on subsequent pages oncepvuaiUntaggedContentis already found — structure elements are still collected for the cross-page checks (Note unique ID, heading sequence), but the expensive per-page content-tagging pass stops early
Version 1.89.0
Changed
TPdf.ValidatePdfAPdfium object-model layer performance: the page/object walk now short-circuits at three levels — the page loop exits when all applicable Pdfium-layer issues are already found, the per-object loop exits when both per-object issues (font embed + transparency) are set, and the text-page character scan skips the.notdefpass whenUnicodeMapErroralready hit.Assigned()API-availability checks and conformance flags are cached to local booleans once before the loop instead of being re-evaluated on every page/object/character. On a large non-conformant document the walk can now stop after the first page instead of scanning all pages; on a conformant document the overhead per page is lower (no repeatedAssignedcalls)
Version 1.88.0
Added
ValidatePdfXgained eight new content-levelTPdfXValidationIssuevalues covering the print-exchange restrictions that PDF/X imposes beyond the file-format markers:pvxiLzwForbidden(/LZWDecode),pvxiJavaScriptForbidden(/JavaScript),pvxiFormFieldsForbidden(/AcroForm//XFA),pvxiAdditionalActions(/AA),pvxiEmbeddedFilesForbidden(/EmbeddedFiles//FileAttachment),pvxiOpiForbidden(/OPI//Alternates),pvxiMissingTrimBox(no/TrimBoxon any page), andpvxiTrappedNotSet(/Trappedabsent or/Unknown). The PDF/X validator previously checked only XMP/OutputIntent markers; this is its first content-level pass. SharedPdfStructureBytes/PdfHasName/PdfCountNamehelpers were added toFPdfPdfCommonso all conformance units can use them
Version 1.87.0
Added
- PDF/UA validation now covers the ISO 14289-1 §7.21.3 composite-font rules:
pvuaiCidSystemInfoMismatchflags Type0 fonts whose embedded CMap and descendant CIDFont disagree onRegistry/Orderingor whose CIDFontSupplementexceeds the CMap’s,pvuaiCMapNotEmbeddedflags CMaps referenced by name (asEncodingorUseCMap) that are not ISO 32000-1 Table 118 predefined CMaps, andpvuaiCMapWModeMismatchflags embedded CMaps whose dictionaryWModediffers from the WMode in their stream content
Fixed
- The §7.21.3.2
pvuaiCidFontMissingCidToGidMapcheck missed CIDFontType2 dictionaries whoseSubtypekey/value pair is separated by a newline, and now also flags aCIDToGIDMapname value other thanIdentity
Version 1.86.0
Added
- PDF/UA validation now covers the ISO 14289-1 §7.21.6 TrueType encoding rules:
pvuaiTrueTypeEncodingInvalidflags non-symbolic TrueType fonts whoseEncodingis missing or is neitherMacRomanEncodingnorWinAnsiEncoding(directly or viaBaseEncoding), andpvuaiSymbolicTrueTypeEncodingflags symbolic TrueType fonts carrying a non-standardEncodingname
Version 1.85.1
Changed
- The ISO 14289-1 §7.18.3 tab-order check
pvuaiMissingTabsOrdernow runs per page: every page carrying annotations must declare/Tabs /Sin its own page dictionary, so a conformant sibling page no longer masks a page without one
Version 1.85.0
Added
- PDF/UA validation now distinguishes dynamic from static XFA forms per ISO 14289-1 §7.15:
pvuaiXfaDynamicflags forms whose XFA configuration setsdynamicRendertorequired
Changed
- The former any-XFA candidate flag
pvuaiXfaPresentis retired and no longer raised (static XFA conforms to §7.15); the enum value remains for API compatibility
Version 1.84.0
Added
- PDF/UA validation now detects untagged real content required by ISO 14289-1 §7.1:
pvuaiUntaggedContentflags rendered text and image objects that are neither claimed by the page’s structure tree (via their marked-content IDs) nor marked as an Artifact - New page-level helpers
GetPageContentMarkInfosandValidatePdfUaPageContentTaggingwith theTPdfPageContentMarkInforecord for direct use
Version 1.83.0
Added
- PDF/UA validation now enforces the ISO 14289-1 §7.4.4 heading model:
pvuaiHeadingModelMixedflags documents that mix the genericHtag with numberedH1..Hnheadings, andpvuaiHeadingMultipleInNodeflags structure nodes carrying more than one childHheading
Version 1.82.0
Added
- PDF/UA validation now resolves the RoleMap required by ISO 14289-1 §7.1:
pvuaiRoleMapRemapsStandardflags RoleMap entries that redefine a standard structure type, andpvuaiRoleMapUnresolvedflags used non-standard structure types whose RoleMap chain is missing, dangling or cyclic — indirect chains that reach a standard type are accepted, and unused RoleMap entries are never judged - New helpers
PdfUaIsStandardStructType,PdfReadRoleMapPairs(with PDF name#hhescape decoding) andValidatePdfUaRoleMapUsagefor direct use
Version 1.81.0
Added
- PDF/UA validation now covers the ISO 32000-1 list tagging required by ISO 14289-1 §7.6:
pvuaiListStructureInvalidflags LI items outside an L container and Lbl/LBody parts outside an LI item, while accepting nested lists and the legitimate Lbl usage inside Note and BibEntry elements
Version 1.80.0
Added
- PDF/UA validation now covers the ISO 32000-1 table tagging required by ISO 14289-1 §7.5:
pvuaiTableStructureInvalidflags TH/TD cells outside a TR row and rows or row groups outside their Table container,pvuaiTableHeaderMissingScopeflags header cells whose relationship is determinable neither via a Scope attribute nor a Headers/ID association, andpvuaiTableHeadersUndefinedIdflags Headers references in documents that define no structure element IDs TPdfStructureElementexposes the table attributesScope,HasHeaders,HeadersIds,ColSpanandRowSpan, resolved during the structure-tree walk
Changed
- The structure-tree walk now reads all layout and table attributes in a single pass over each element’s attribute dictionaries instead of one scan per attribute
Version 1.79.1
Added
- Ported the
AnnotationsLabsample to Lazarus and C++Builder, joining the existing Delphi console sample
Fixed
TPdf.CreateAnnotationcould raise “Cannot set attachment points” for markup annotations that use quad points (Highlight, Underline, StrikeOut, Squiggly) because the new annotation had no quad slot yet to replace; it now appends the first quad instead
Version 1.79.0
Added
- New
AnnotationsLabDelphi console sample: creates Text, Highlight, Square and Circle annotations, writes them to a PDF, then reloads the file and enumerates the page annotation list
Version 1.78.0
Added
- New
TPdf.MeasureTextandTPdf.MeasureTextWidth: measure the rendered width and height of a string for a given font and size (PDF user units, 1 unit = 1/72 inch) without adding content to a page, making layout and word-wrap logic possible on top ofAddText; provided by the standaloneFPdfMeasureunit as a class helper - New
TPdf.WrapText: greedy word wrap built onMeasureTextWidththat splits text on spaces and packs words into lines no wider than a given width (PDF user units); an overlong single word gets its own line (no intra-word breaking), returning the wrapped lines as an array
Version 1.77.0
Added
ValidatePdfAgained three newTPdfAValidationIssuevalues covering the clauses previously rated “NO” or “reader behaviour” by the earlier gap audit (appended ordinals, existing values unchanged):pvaiPdfiumNotDefGlyph(PDF/A-2 6.2.11.8 — a character that resolves to Unicode 0 without a mapping error, the runtime symptom of a.notdefglyph reference; detected via the Pdfium object-model layer),pvaiWordBreakMissing(Level A 6.8.3.2 — a content-stream show string longer than 20 characters with no space, a likely merged-words violation; coarse heuristic that avoids CJK false positives), andpvaiLinkActionMissingTarget(6.6.3 — a GoToR/URI/SubmitForm action missing its display target key so a reader cannot present it)
Version 1.76.0
Added
ValidatePdfAgained three newTPdfAValidationIssuevalues (appended ordinals, existing values unchanged):pvaiNameNotValidUtf8(PDF/A-2/3 6.1.8 — a/BaseFontor/FontNametoken containing bytes ≥ 0x80 that do not form valid UTF-8),pvaiInlineImageLzwForbidden(PDF/A-2/3 6.1.10 — an inline image in a page content stream uses the LZW or Crypt filter), andpvaiTrueTypeDifferencesForbidden(6.3.7 Cor.2 — a non-symbolic TrueType font whose Encoding dictionary carries/Differences)
Version 1.75.0
Added
ValidatePdfAgained three newTPdfAValidationIssuevalues (appended ordinals, existing values unchanged):pvaiIntegerImplementationLimit(PDF/A-2/3 6.1.13 — a numeric token exceeding the 32-bit signed integer limit 2,147,483,647),pvaiBlendModeNotWhitelisted(PDF/A-2/3 6.2.10 — a/BMvalue outside the ISO 32000-1 §11.3.5 standard blend-mode set; complements the PDF/A-1pvaiTransparentColorSpacewhich only allows Normal/Compatible), andpvaiHexStringOddDigits(6.1.6 — a<...>hex string with an odd number of hex digits)
Version 1.74.0
Added
ValidatePdfAgained three newTPdfAValidationIssuevalues (appended ordinals, existing values unchanged):pvaiPermissionsViolation(6.1.12 — a/Permsdictionary carrying/DigestLocation,/DigestMethodor/DigestValuealongside/DocMDP),pvaiTransActionForbidden(PDF/A-2 6.5.1 — a Trans transition action, detected via the/S /Transaction-dict pattern to avoid false-matching/Transparency), andpvaiPdfiumObjectTransparency(PDF/A-1 6.4 — a page object carries real transparency perFPDFPageObj_HasTransparency, extending the Pdfium object-model layer introduced in v1.73.0 to catch blend-mode/soft-mask effects the byte-level name scan can miss)
Version 1.73.0
Added
TPdf.ValidatePdfAnow layers a Pdfium object-model pass on top of the byte-level inspector: it walks every page’s text objects viaFPDFPage_GetObject→FPDFTextObj_GetFont→FPDFFont_GetIsEmbeddedand reports a non-embedded rendered font aspvaiPdfiumFontNotEmbedded(ISO 19005 6.3.4), and loads each text page to scanFPDFText_HasUnicodeMapErrorand reports a broken Unicode mapping aspvaiPdfiumUnicodeMapError(6.3.8). These are checks the byte-level inspector cannot do — it only sees name tokens, not resolved font handles or per-character mapping state — and are merged into the byte-level result. The standaloneValidatePdfACompliancebyte-level function is unchanged
Version 1.72.0
Added
ValidatePdfAgained five newTPdfAValidationIssuevalues (appended ordinals, existing values unchanged):pvaiNeedsRenderingPresent(PDF/A-2 6.4.2 — the catalog shall not carry/NeedsRendering),pvaiDestOutputProfileRef(PDF/A-3 6.2.3 — an OutputIntent shall not carry/DestOutputProfileRef),pvaiEmbeddedFileMissingUF(PDF/A-3 6.8 — a file spec with/EFshall also carry/UF),pvaiXmpPacketBytesAttr(6.7.5 — the XMP packet header shall not carry the deprecatedbytes=orencoding=attribute), andpvaiAnnotationToggleNoView(PDF/A-2 6.3.2 — the annotation/FToggleNoView bit, value 512, is forbidden)
Version 1.71.0
Changed
ValidatePdfUanow raisespvuaiOrderedListMissingListNumbering(ISO 14289-1 7.6): the structure-tree walker resolves theListNumberinglayout attribute on everyLelement via the Pdfium attribute API and flags any value outside the ISO 32000-1 Table 347 set (Decimal,UpperRoman,LowerRoman,UpperAlpha,LowerAlpha,None,Circle,Disc,Square). An absent attribute is not flagged, since the list may be unordered; this closes the last residual ISO 14289-1 gap recorded at the end of round 5
Version 1.70.0
Added
ValidatePdfUagained four newTPdfUaValidationIssuevalues (appended ordinals, existing values unchanged):pvuaiSubsetMissingCidSet(ISO 14289-1 7.21.4.2 — a CID subsetFontDescriptorshall declare/CIDSet),pvuaiToUnicodeForbiddenValue(7.21.7 — a ToUnicode CMap shall not map any code toU+FEFForU+FFFE; uncompressed streams are scanned for the<FEFF>/<FFFE>output forms),pvuaiLangInvalidFormat(7.2 —/Langshall be a valid RFC 1766 / BCP 47 tag; a permissive grammar acceptsen,en-US,zh-Hans,es-419and flags clearly non-conforming values), andpvuaiOrderedListMissingListNumbering(7.6 — retained for API completeness; not yet raised by the validator because reliably distinguishing ordered from unordered lists needs theListNumberingattribute value, which the structure-tree walker does not expose)
Version 1.69.0
Added
ValidatePdfUagained two newTPdfUaValidationIssuevalues (appended ordinals, existing values unchanged):pvuaiWidgetOutsideForm(ISO 14289-1 7.18.4 — a Widget structure element shall be nested within aFormelement; the structure-tree walker now verifies each Widget’s direct parent type) andpvuaiSubsetMissingCharSet(7.21.4.2 — a Type 1 subsetFontDescriptorshall declare/CharSet, identified by the six-letter+subset-name prefix on/FontName)
Version 1.68.0
Added
ValidatePdfUagained two newTPdfUaValidationIssuevalues (appended ordinals, existing values unchanged):pvuaiUriActionIsMap(ISO 14289-1 7.18.5 — a URI action dictionary shall not carry/IsMapwith valuetrue, since it disables the accessible link target) andpvuaiHeadingSequenceViolation(7.4.2 — numbered headings shall start atH1and a descending sequence shall not skip an intervening level, e.g.H1→H3is a violation). The heading check is the first structure-tree-level PDF/UA rule in the validator:ValidatePdfUaStructureElementsnow walks the typed element list and verifies theH1…H6(andH7+per 7.4.3) sequence in document order
Version 1.67.0
Added
ValidatePdfUagained five newTPdfUaValidationIssuevalues (appended ordinals, existing values unchanged):pvuaiLinkMissingContents(ISO 14289-1 7.18.5 — a Link annotation shall carry an alternate description via/Contents),pvuaiAnnotationMissingContents(7.18.1 — any non-exempt annotation without/Contentsshall have an alternative description; Popup and Widget are exempt),pvuaiEmbeddedFileMissingName(7.11 — a file specification dictionary shall contain/Fand/UF),pvuaiMediaClipMissingAlt(7.18.6.2 — a media clip data dictionary shall contain/CTand/Alt), andpvuaiCidFontMissingCidToGidMap(7.21.3.2 — an embedded Type 2 CIDFont shall contain/CIDToGIDMap)
Version 1.66.0
Added
ValidatePdfUagained five newTPdfUaValidationIssuevalues (appended ordinals, existing values unchanged):pvuaiRoleMapMissing(ISO 14289-1 7.1 — a tagged document with non-standard structure types shall carry a/RoleMap),pvuaiOptionalContentAsKey(7.10 — an optional-content configuration dictionary shall not carry the/ASauto-state key),pvuaiXfaPresent(7.15 — an AcroForm/XFApresence is flagged since dynamic XFA is forbidden),pvuaiTrapNetAnnotation(7.18.2 —/TrapNetannotations are forbidden), andpvuaiReferenceXObject(7.20 — Reference XObjects, keyed off the/Refmarker, are forbidden)
Fixed
ValidatePdfUano longer false-positivespvuaiEncryptionPresenton every encrypted file: PDF/UA permits encryption as long as the encryption dictionary/Pkey has bit position 10 (value 1024) set, which grants assistive-technology access (7.16). The precise violation is now reported via the newpvuaiEncryptionPBitMissing;pvuaiEncryptionPresentis retained in the enum for API compatibility but is no longer raised by the byte-level validator
Version 1.65.0
Added
ValidatePdfAgained five newTPdfAValidationIssuevalues (appended ordinals, existing values unchanged):pvaiCidFontMissingCidToGidMap(ISO 19005-1 6.3.3.2 Cor.2 — an embedded Type 2 CIDFont shall carry/CIDToGIDMap),pvaiSubsetMissingCharSet(6.3.5 — a Type 1 subsetFontDescriptorshall carry/CharSet),pvaiSubsetMissingCidSet(6.3.5 — a CID subsetFontDescriptorshall carry/CIDSet),pvaiWidgetActionForbidden(6.6.1 — a Widget annotation shall not carry/Aor/AA), andpvaiOptionalContentAsKey(ISO 19005-2 6.9 — an optional-content configuration dictionary shall not carry the/ASauto-state key, newly relevant because PDF/A-2 permits optional content)
Version 1.64.0
Added
ValidatePdfAgained eight newTPdfAValidationIssuevalues (appended ordinals, existing values unchanged):pvaiHeaderBinaryMarkerMissing(ISO 19005-1 6.1.2 — the%PDF-x.yheader must be followed by a%comment with at least four bytes greater than 127),pvaiExternalStreamRef(6.1.7 — a stream dictionary shall not carry/F,/FFilteror/FDecodeParms),pvaiOutputIntentScheme(6.2.2 — the OutputIntent/Sshall be/GTS_PDFA1),pvaiInfoXmpDateMismatch(6.7.3 — InfoCreationDate/ModDateshall also appear asxmp:CreateDate/xmp:ModifyDate),pvaiMarkInfoMissing(6.8.2.2 — Level A requires/MarkInfowith/Marked true),pvaiAnnotationApDictViolation(6.5.3 Cor.2 — the annotation/APdictionary shall contain only/N),pvaiEmbeddedFileMissingAFRelationship(ISO 19005-3 Annex E.2 — each associated filespec shall carry/AFRelationship), andpvaiJpeg2000Violation(ISO 19005-2 6.2.8.3 — a JPEG2000 image shall declare 1, 3 or 4 components)
Fixed
ValidatePdfAno longer false-positivespvaiAnnotationFlagsViolationon documents that use a single-letter font resource name such as/Font << /F 5 0 R >>; the/Fflag scan is now gated on an annotation context (/Subtypeof an annotation type), matching the documented behaviour (6.5.3)ValidatePdfAnow reports the PDF/A-3 associated-file requirement per file: a document is flagged only when an embedded/Type /Filespecthat references an embedded stream via/EFlacks/AFRelationship, instead of the previous whole-document any-or-none check (ISO 19005-3 Annex E.2)- Added the deprecated
/SetStateaction to the forbidden-action set alongside/SetOCGState, so the PDF Reference action name is caught directly (6.6.1)
Version 1.63.0
Added
- Added
TPdf.MeasureTextandTPdf.MeasureTextWidth: measure the rendered width and height of text in a given font and size without adding content to a page (in PDF user units, 1 unit = 1/72 inch), enabling layout calculations and automatic line wrapping on top ofAddText; provided by the standalone unitFPdfMeasureas a class helper
Changed
Demo\Delphi\MergePDF,Demo\CBuilder\MergePDF, andDemo\Lazarus\MergePDFenhanced across all three IDEs: added per-file page range selection, optional output path, deduplication, a run log, a cancel button, and a merge completion summary, with bookmarks and metadata carried over from the first source on importCreatePDFdemos across all three IDEs now include a “European Text” option to write accented text in Czech, French, German, Spanish, Portuguese, Polish, and Turkish, for verifying font selection and Unicode handling (the formerEuropeanTextsample has been merged in)- Removed the
ExtractTextPagesandEuropeanTextsamples: the per-page text output capability ofExtractTextPagesis now covered by the page-range and page-separator options inExtractText; the multilingual text rendering ofEuropeanTexthas been merged intoCreatePDF
Version 1.62.2
Fixed
- Regenerated the C++Builder headers (
.hpp) for every RAD Studio version and platform (Win32/Win64/Win64x); they had drifted from the Pascal sources, leaving stale function signatures and missing units that reached C++Builder users through the source distribution
Version 1.62.1
Fixed
- Restored source compilation on RAD Studio 12 Athens and earlier: a
TArray<Byte>assignment in the PDF/UA validation path used a Delphi 13-only implicit array conversion that failed to compile on older IDEs
Version 1.62.0
Added
TPdf.RenderPageThumbnailrenders any page by index into an aspect-fitted bitmap without changing the document's current page, loaded page or firingOnPageChange
Fixed
TPdfThumbnailViewno longer drives the host document'sPageNumberwhile painting; earlier each repaint reloaded pages, firedOnPageChangeand discarded the text page, which could disrupt a linkedTPdfViewand trigger repaint loops. Thumbnails now render throughRenderPageThumbnailwith no such side effects- PDF/X conformance validation now inspects cross-reference-stream documents (PDF 1.6, typical of PDF/X-4) and objects stored in compressed object streams, instead of reporting such files wholesale as non-conformant; the
GTS_PDFXVersionmarker is read from both element-form and RDF attribute-form XMP - PDF/R validation now reports
pvriInfoXmpMismatchwhen the Info dictionary and XMP disagree on Producer or Creator; the issue was previously declared but never raised - Form-fill timers are tracked per request, so a document that runs several timers at once (for example a JavaScript interval alongside the field caret blink) keeps them all instead of losing every timer but the most recent
TPdfViewpainting and its publicRenderPage/RenderTilemethods now hold the document render lock, serializing against worker-thread rendering of the sameTPdf(PDFium is not thread-safe)- Non-ASCII text written into PDF/X, PDF/R and PDF/VT metadata (OutputIntent condition names, Creator, Producer) is now encoded as a UTF-16BE string per ISO 32000-1 §7.9.2.2 instead of raw UTF-8, which conforming readers would misread
- Conformance helpers read embedded metadata streams whose
/Lengthis an indirect reference correctly, load source bytes withReadBuffer(so a short read fails cleanly), and reject a negativestartxrefoffset instead of risking an out-of-range read
Version 1.61.0
Changed
- FFI/ABI declaration corrections that may require recompiling code which implemented the affected callbacks: the
FFI_OpenFileform-fill callback now carriescdecl(Win32 stack convention), and thevalueparameter ofFPDFAnnot_SetStringValueandFPDFAttachment_SetStringValueis nowFPDF_WIDESTRING(UTF-16LE) to match the PDFium headers - Progressive-load callbacks
FX_FILEAVAIL.IsDataAvailandFX_DOWNLOADHINTS.AddSegmentnow takesize_toffsets, andsize_tis pointer-width on Free Pascal / Lazarus Win64 (previously truncated to 32-bit), fixing data-availability andoutsize_tAPI calls on FPC Win64
Fixed
- Memory safety: a use-after-free of the form-fill timer when destroying a
TPdfwith an active AcroForm caret; a doubleFPDF_CloseDocumenton the error path ofImportNPagesToOne; Pascal exceptions escaping theFPDF_FILEWRITE/FPDF_FILEACCESScallbacks across the C boundary during save and JPEG insert; and an integer overflow in text extraction when reading from a start index to the end of the page TPdfFuture<T>now reliably delivers its result callback; the reply was previously almost always dropped (and could touch a freed thread) because the worker freed itself before the queued reply ran- PDF/A, PDF/X, PDF/E, PDF/R, PDF/VT and PDF/UA output now write cross-reference entries that are exactly 20 bytes as required by ISO 32000-1 §7.5.4
- Standards marker injection no longer destroys a dictionary when the removed key (for example
/Trapped) was the last entry, which previously swallowed the closing>>and produced a malformed object - OutputIntent ICC profile streams now declare the required
/Ncomponent count for PDF/X and PDF/VT (already present for PDF/A); encrypted source documents are decrypted before PDF/X, PDF/E, PDF/R, PDF/VT and PDF/UA markers are injected, so the output is valid rather than silently corrupted - The UTF-8 xpacket BOM in generated XMP is emitted as exact bytes, fixing corruption on Delphi installations whose ANSI code page is not Latin-1; incremental-update trailers now retain the document
/Inforeference SaveAswith compression no longer truncates streams whose/Lengthis an indirect reference, and rebuilt cross-reference tables now use 20-byte entries, real generation numbers, and drop the stale/Prevpointer- Conformance validation reads attribute-form XMP version markers for PDF/E and PDF/X (so attribute-serialised PDF/X-4 files are recognised), requires the exact
PDF/E-1identifier, reads indirect-/Lengthmetadata streams correctly, and no longer false-matches a structure element's/IDor/StructTreeRootkey when checking the PDF/UA trailer; a malformedstartxrefoffset no longer raises a range error TPdfThumbnailView: the final page is now reachable with the scroll bar, the host document's current page is restored after thumbnails are painted, and the standard mouse-leave handling is dispatched again- Grayscale page and image bitmaps are no longer rendered with a wrong palette;
TPdfViewis no longer left with a dangling reference when itsTPdfis freed first - Preflight reports: HTML is saved as UTF-8 to match its declared charset, and JSON string escaping produces correct
\usequences for non-ASCII characters on Free Pascal - Trial builds: the trial reminder dialog now appears instead of being suppressed before it could show
TPdfStreamAdapternow rejects streams larger than 4 GiB with a clear error instead of silently truncating the length passed to PDFium
Version 1.60.1
Changed
- The AccessibilityReader demos for Delphi, Lazarus and C++Builder now run read-aloud on
TPdfReadingSession: each page is assembled into one spoken chunk withBuildSpokenTextFromWords, SAPI word positions feedFeedSpokenPosition, and the session advances pages and drives the view's word cursor, replacing the hand-written orchestration each demo carried before - Word-level karaoke tracking in the demos now also works when NVDA is the speech engine:
EstimatePacingpaces the reading cursor by elapsed speaking time, where NVDA previously read aloud with no word tracking at all - Pause and Resume in the demos now work with NVDA too:
ResumeRestartsChunkre-speaks the current page from its start on Resume, while SAPI keeps its native in-place pause and resume
Version 1.60.0
Added
- Live low-vision rendering on
TPdfView: the newreInvertandreNightDuotonerender options recolour every rendered page tile (full colour inversion, or a night duotone palette) before the search, selection, reading and word-cursor overlays are painted, bringing the existing bitmap colour transforms into the interactive viewer for both single-page and facing-pages layouts; toggling the options repaints immediately NightDuotoneInkandNightDuotonePaperconfigure the night palette, defaulting to amber text on a black page;reInvertwins when both options are set
Version 1.59.0
Added
TPdfReadingSession: a speech-engine-neutral read-aloud orchestration component. It keeps the chunk cursor, the word cursor and the playback state (Play/PlayFrom/Pause/Resume/Stop), advances through the loadedTPdfSpokenTextchunks as the host reports the engine idle viaTick, translates spoken-text offsets back to page characters, and drives an attachedTPdfViewword cursor automatically; the host connects any speech engine throughOnSpeakand the cancel / pause / resume request events, so the library links no speech API itselfFeedSpokenPositionconsumes engine word positions (such as SAPIStatus.InputWordPosition);EstimatePacingwithEstimatedWordsPerMinutepaces engines without a position signal;ResumeRestartsChunkre-speaks the current chunk for engines without a native pauseOnChunkChange,OnWordChangeandOnFinishedfire only on real changes, and a freed attached view detaches itself automatically, so host code stays flicker-free and crash-safe
Version 1.58.0
Added
EstimateSpokenWordIndexestimates which word a speech engine is voicing from the elapsed time and a words-per-minute rate, giving longer words proportionally more time, so engines that report no word position (such as the NVDA controller client) can still drive the word-level reading cursor; the caller supplies the elapsed time, so the routine stays clock-free and unit-testable
Version 1.57.0
Added
- Spoken-text assembly with two-domain mapping for read-aloud tracking:
BuildSpokenTextFromWordsandSpokenTextAppendbuild the string handed to a text-to-speech engine from page word boxes while recording a span table, andSpokenToPageChartranslates an engine-reported spoken offset (such as SAPIStatus.InputWordPosition) back to the page character index, so word-level highlight tracking stays correct when the spoken text is not the whole page text (skipped regions, per-unit reading, pronunciation overrides) TPdfSpokenTextandTPdfSpokenSpantypes carry the spoken string plus the source page ranges it was built from; offsets on inserted separators resolve to the next mapped word and offsets past the mapped runs report no match
Version 1.56.9
Added
Demo\Delphi\PreflightReportadds an Action Plan preview that condenses non-passing standards, priorities, next actions, issue codes, and recommendations into a remediation checklistDemo\Delphi\PreflightReportCliacceptsplan/actionplanas an output format for single-file and batch runs, writing the same remediation checklist to a text file
Changed
- Both Delphi PreflightReport demos now display pass / action / review status counts alongside total standards and issues
Version 1.56.8
Changed
ViewerInteractionLabnow includes page-jump controls, manual zoom controls, click-basedDeviceToPage/PageToDevicecoordinate logging, and a clearer interaction log for selection, search, rotation, and navigation checksViewerInteractionLabreadme pages now document the added interaction workflow across the localized demo readme set
Version 1.56.7
Added
AccessibilityWorkbenchClimaps every triggered finding to its WCAG 2.1 Success Criteria and ISO 14289-1 (PDF/UA-1) clause area and shows a standards-coverage section in the reportsAccessibilityWorkbenchClicomputes a documented 0-100 accessibility score with a published penalty rubric and an excellent / good / needs work / poor band, surfaced per file and as a batch averageAccessibilityWorkbenchCliacceptsfailscore=Nto fail the run (exit code 2) when any file scores below NAccessibilityWorkbenchCliwrites a SARIF 2.1.0 log when the batch summary name ends in.sarif, with one rule per finding kind carrying its WCAG 2.1 and PDF/UA tags for CI and code-scanning ingestionAccessibilityWorkbenchCliadds aversioncommand that prints the linked PDFiumPas version
Version 1.56.6
Added
IntakeWorkbenchClicomputes a SHA-256 forensic hash of each input file (degrading tounavailableon compilers withoutSystem.Hash) and reports it in every formatIntakeWorkbenchCliacceptspasswords=file.txtto trial-unlock password-required documents from a candidate list, recording the matching candidate index without ever logging the password textIntakeWorkbenchCliacceptscopyto=dirto route each audited file into a per-risk-level subfolder, turning the auditor into an intake sorterIntakeWorkbenchCliwrites a SARIF 2.1.0 log when the batch summary name ends in.sarif, with one rule per risk flag and one result per flagged file for CI and code-scanning ingestionIntakeWorkbenchCliadds aversioncommand that prints the linked PDFiumPas version
Version 1.56.5
Added
IntakeWorkbenchClinow derives recommended post-intake actions such as accept, request-password, manual-review, quarantine, and deduplicate, and exposes action counts in batch summariesAccessibilityWorkbenchClinow derives recommended remediation actions such as pass-through, remediate-tags, run-ocr, remediate-semantics, and manual-review, with matching batch action counts
Changed
- Both tool-grade CLI demos surface the recommended action in console, text, HTML, JSON, and CSV output so batch operators can route files without post-processing risk or status fields
Version 1.56.4
Fixed
- Reading annotations, bookmarks, or link annotations in a loop no longer leaks the previous item's text strings: the
TPdfAnnotation,TBookmark, andTLinkAnnotationresult records are now cleared with managed-type-aware initialization instead of raw memory zeroing, so documents carrying very large numbers of text-bearing annotations no longer inflate process memory for the lifetime of the application - Destroying a
TPdfthat had registered anOnUnsupportedFeaturehandler now detaches it from the process-global PDFium callback, so a later document load from anotherTPdfinstance without its own handler can no longer dispatch into the freed component (use-after-free)
Version 1.56.3
Fixed
AccessibilityWorkbenchClino longer counts blank pages as heuristic reading-order pages, so tagged documents with empty separator pages keep their correct accessibility status; pages without readable content are now reported separatelyAccessibilityWorkbenchClitable-header detection no longer credits an outer table forTHcells that belong to a nested table, and form-field and font names are matched case-sensitively so distinct fields are not mergedIntakeWorkbenchCliURL host inventories now strip userinfo, query, and fragment parts, so a crafted link such astrusted.example@evil.exampleis attributed to the real host, andmailto:targets contribute their domain instead of being invisibleIntakeWorkbenchCliMarkdown reports escape backticks in attacker-controlled paths, hosts, and attachment names so report formatting cannot be broken from inside a document
Changed
AccessibilityWorkbenchClireports font-scan and form-field-scan failures as separate counters, marks non-embedded fonts that also have embedded instances, and caps long font lists with an explicit truncation markerIntakeWorkbenchClibatch summaries add an attachment-annotation count column, and the per-page annotation census is capped at 20000 annotations per page with the cap reported in every format
Version 1.56.2
Added
AccessibilityWorkbenchClinow audits font embedding, form-field tooltips, reading-order source, document outlines, table and list structure, suspicious alternate text, and richer per-page review details so accessibility batch reports identify more remediation targetsIntakeWorkbenchClinow reports page scan limits, launch and remote-go-to actions, URI host inventories, annotation counts, unsupported PDFium features, duplicate document identifiers, and expanded risk flags for automated intake review
Changed
IntakeWorkbenchCliacceptsmaxpages=Nin single-file and batch modes to cap per-document page scans while still completing metadata, attachment, script, XFA, signature, and risk reporting
Version 1.56.1
Fixed
- Loading an older
pdfium.dllthat is missing a newer export now fails cleanly: the failure path resets every bound API entry point, soAssigned()checks (for example onFPDF_GetLastErrororFPDF_GetSecurityHandlerRevision) report the library as not loaded instead of calling into the already-unloaded module and crashing with an access violation UnloadLibrarynow clears all PDFium API bindings rather than only the optional V8 helpers, so no stale function pointers survive after the DLL is released
Version 1.56.0
Added
- Word-level karaoke reading cursor on
TPdfView:TrackReadingWordAtmaps a text-to-speech engine's current-word character offset (such as SAPIStatus.InputWordPosition) onto the page word boxes, highlights the word that contains it as a distinct overlay above the reading block, scrolls it into view, and returns the word index, so the spoken word lights up as the voice advances SetReadingWordandClearReadingWordset or clear the highlighted word from aTPdfWordBoxdirectly; re-setting the same word is a no-op, so per-word tracking never flickers the viewReadingWordColorandReadingWordFollowcontrol the word cursor colour and whether the view auto-scrolls the spoken word into view
Version 1.55.2
Fixed
- ViewerInteractionLab now gives the toolbar rows more vertical space so Open PDF, Create Sample, navigation, search, and selection controls no longer overlap under scaled fonts
Version 1.55.1
Fixed
- ViewerInteractionLab now places Prev, Next, and Rotate on the second toolbar row, avoiding the startup overlap with Open PDF and Create Sample
Version 1.55.0
Added
- Word-to-selection bridge for "read it, select it" reading:
TPdfView.SelectWordBoxandSelectWordSpanselect a single word box or a same-page span of word boxes (fromPageWordBoxes) by their character ranges, so the word or line currently being read can also be selected and copied WordBoxIndexAtCharIndexmaps a character index back to the word box that contains it, driving word-by-word highlight as a TTS read cursor advances
Version 1.54.0
Added
- Voice form-filling accessors that read the focused field straight from the logical cursor:
FocusedFormFieldValue,FocusedFormFieldNameandFocusedFormFieldDetailsonTPdfandTPdfViewreport the current field's value, human-readable name (/TUtooltip, falling back to/T) and fullTPdfFormFieldInfo(type, flags, options) — everything a voice UI needs to announce as it steps through a form
Fixed
FocusedFormFieldValuereads the field byFocusedFormFieldIndexrather than pdfium interactive focus, so a voice-driven form filler gets the right value even with no on-screen caret (the existingFocusedFormFieldTextstill reflects pdfium focus and is unchanged)
Version 1.53.0
Added
- Word-level highlighting support:
TPdf.PageWordBoxesandTPdfView.PageWordBoxessplit a page intoTPdfWordBoxrecords, each carrying the word text, its character range and a page-space bounding rectangle, so an accessibility reader can highlight each spoken word in turn ("karaoke" reading) by passing the rectangle toSetReadingHighlight BuildWordBoxesexposes the tokenizer step on its own, turning page text into word boxes with character ranges
Version 1.52.0
Added
- Low-vision rendering helpers
InvertPdfBitmap,GrayscalePdfBitmapandDuotonePdfBitmapapply in-place colour transforms to a rendered 32-bit bitmap, so an accessibility reader can present pages inverted / dark-mode, grayscale, or in a custom two-colour scheme (for example a dark background with light text) for low-vision users - The transforms run per pixel and behave identically on VCL and Lazarus/LCL, leaving bitmap dimensions untouched
Version 1.51.0
Added
- Sentence-level reading units for assistive listen-reading:
TPdf.ReadingUnits,TPdf.DocumentReadingUnitsandTPdfView.ReadingUnitslinearize the readable content stream into ordered, sentence-sizedTPdfReadingUnitrecords — each carries the text to speak plus its semantic kind, page, highlight rectangles and language tag, so a screen-reader app can step through a page or the whole document one spoken unit at a time - Semantic navigation with
NextReadingUnitOfKind, letting a voice UI jump to the next or previous heading, figure, list item or table cell without scanning the stream by hand BuildReadingUnitsconverts anyTPdfContentFragmentsinto reading units directly: headings and figure/alt descriptions stay whole while paragraphs split on sentence boundaries, decimal points are preserved, and the reading cursor is a plain caller-owned index
Version 1.50.0
Added
ValidatePdfAcan now inspect PDF 1.5+ documents that store the catalog, OutputIntent or other dictionaries inside compressed object streams (/Type /ObjStm). The object streams are inflated and the objects they carry are resolved, so such documents are validated on their merits instead of being reported as missing their PDF/A markers
Version 1.49.5
Fixed
ValidatePdfAno longer reports a missingpdfaExtension:schemasdescription as a problem. The PDF/A identifier schema (pdfaid) is well-known, so neither veraPDF nor PDF/A-2/-3 require an extension-schema description for it, and flagging its absence mis-reported every conformant third-party PDF/A. Documents the library itself produces still include the description
Version 1.49.4
Fixed
ValidatePdfAnow detects the conformance level when the PDF/A identifier is written as XML attributes (pdfaid:part="2") rather than child elements, so attribute-form documents are no longer reported with an unknown level. This also corrects a cascade in which an undetected level made the part-specific checks fall back to the strict PDF/A-1 rules and wrongly flag embedded files and transparency that PDF/A-2 and PDF/A-3 permit
Version 1.49.3
Fixed
ValidatePdfAnow inspects PDF 1.5+ documents whose cross-reference data is a cross-reference stream (files that have notrailerkeyword). The conformance level, trailer/IDand the other markers are read from the cross-reference stream dictionary, so such documents are validated on their merits instead of being reported as entirely non-conformant
Version 1.49.2
Fixed
ValidatePdfAno longer reports a spurious non-embedded-font issue on documents that embed all of their fonts. The previous heuristic compared the number of/FontDescriptortokens against embedded font programs, but each embedded font contributes two/FontDescriptortokens (the font dictionary reference plus the descriptor object), so every embedded-font file was wrongly flagged. The check now reports only a document that references fonts yet embeds no font program at all, matching the correspondingValidatePdfUacorrection
Version 1.49.1
Fixed
- PDF/A output now validates as conformant PDF/A-1b and PDF/A-1a with veraPDF: the embedded sRGB OutputIntent ICC profile stream (referenced by
/DestOutputProfile) now declares the required/Ncomponent count (3 for the built-in RGB profile), as mandated by ISO 19005-1 6.2.3.2. Documents produced bySaveAsPdfApreviously failed strict PDF/A-1 validation because the destination profile stream omitted/N; the value is derived from the ICC profile header, so a caller-supplied CMYK or Gray profile receives the correct count as well
Version 1.49.0
Fixed
ValidatePdfUano longer reports spurious missing XMP identification on conformant tagged PDFs — the PDF/UA identifier (pdfuaid:part),dc:title, the XMP dates and the trailer/IDare now read from the original document bytes instead of the re-saved copy, which omits the/MetadataXMP stream and, for cross-reference-stream files, the trailer/IDValidatePdfUafont-embedding check corrected so a document that embeds all of its fonts is no longer reported as having non-embedded fonts; it now flags only a document that references fonts yet embeds no font program at allValidatePdfUanow accepts aFormulastructure element whose alternative text is supplied throughActualTextrather than anAltentry (ISO 14289-1 §7.7), consistent with the existingFigurerule
Version 1.48.0
Added
- Programmatic text selection on
TPdfView:SelectTextRange(by page and character range) andSetSelection(by explicit per-page ranges) select text from code — for example to read and highlight a passage; both repaint and raiseOnSelectionChangewhen the selection changes.SelectionRangesreads the current selection as per-page character ranges, andSelectionRectanglesreturns its rectangles in page coordinates for custom highlighting or scroll-to
Version 1.47.0
Added
- Form field navigation for voice-driven form filling, on both
TPdfandTPdfView:FormFieldTabOrder,FocusedFormFieldIndex,FocusFormField,FocusNextFormField,FocusPreviousFormField,ClearFormFieldFocusandFocusedFormFieldText. These move a logical field cursor over the page's widget fields in tab order (wrapping at the ends), so an assistive reader can walk the form, announce each field viaFormFieldInfo[Index].AlternateName(the /TU tooltip), and fill it viaFormField[Index] TPdfView.OnFormFieldFocusChangeevent, raised when the field cursor moves (carrying the new field index, or -1 when cleared)
Version 1.46.0
Added
- Assistive listen-reading content stream:
TPdf.ReadableContent,TPdf.ReadablePageContent,TPdf.DocumentReadableContentandTPdfView.ReadableContentreturn an ordered list of semanticTPdfContentFragmentitems, each carrying the spoken text (real glyphs, orActualText/Alt for figures), a fragment kind (heading with level, paragraph, figure, list item, table cell, link, plain), language, 1-based page, and block plus per-line highlight rectangles. Tagged PDFs are linearised in logical reading order from the structure tree; untagged pages fall back to render order so any document can be read aloud - Synced reading highlight on
TPdfView:SetReadingHighlight,ClearReadingHighlightand the publishedReadingHighlightColorhighlight the block currently being read, on top of the search and selection overlays - New public types
TPdfContentFragment,TPdfContentFragments,TPdfReadableContent,TPdfContentFragmentKindandTPdfReadingOrderSource, and the new helperClassifyStructType
Version 1.45.0
Added
ValidatePdfUanow also walks the live tagged structure tree and reports three high-confidence content violations that byte-level scanning cannot detect: aFigureelement with neither an Alt entry nor ActualText (ISO 14289-1, 7.3), aFormulaelement without an Alt attribute (7.7), and aNoteelement that lacks a unique ID (7.9). Three newTPdfUaValidationIssuevalues surface these:pvuaiFigureMissingAlt,pvuaiFormulaMissingAltandpvuaiNoteMissingId. The tree walk is skipped for untagged documents- New public helper
ValidatePdfUaStructureElementsapplies those structure-tree rules to a flat element list (as returned byTPdf.StructureElements), so the checks can be run or unit-tested without loading a full document
Version 1.44.5
Fixed
- The
ValidatePdfAfont-embedding check (pvaiFontNotEmbedded, ISO 19005-1, 6.3.4) now also detects non-embedded simple fonts that carry no/FontDescriptor, most importantly the 14 standard Type 1 fonts (Helvetica, Times, Courier, and so on) which PDF/A requires to be embedded with no exemption. Previously such a font went unnoticed; the check now also counts simple-font dictionaries (/Type1,/TrueType,/MMType1) against the embedded font programs, mirroring the PDF/UA fix in 1.44.3
Version 1.44.4
Fixed
ValidatePdfVTnow rejects malformed ISO 16612-2 §6.5 DPart trees where/DPartsis a flat reference array instead of the required array of arrays, or where a leaf DPart repeats its/Startpage as/Endeven though the range contains only one pageValidatePdfVTnow validates/NodeNameListnames as XML NMTOKEN values after PDF name#xxescape expansion, so invalid hierarchy level names are reported throughpvviMissingDPartRootinstead of being accepted as usable DPart structure
Version 1.44.3
Fixed
- The
ValidatePdfUafont-embedding check (pvuaiFontNotEmbedded, ISO 14289-1, 7.21.4) now also detects non-embedded simple fonts that carry no/FontDescriptor, most importantly the 14 standard Type 1 fonts (Helvetica, Times, Courier, and so on) for which PDF/UA grants no embedding exemption. Previously such a font went unnoticed and a document that used it could be reported as compliant; the check now also counts simple-font dictionaries (/Type1,/TrueType,/MMType1) against the embedded font programs
Version 1.44.2
Fixed
ValidatePdfVTnow leaves a present but unrecognizedpdfvtid:GTS_PDFVTVersionmarker aspvcUnknowninstead of downgrading it topvcNone. This keeps invalid file-level strings such asPDF/VT-2sdistinguishable from documents that carry no PDF/VT marker; PDF/VT-2s is identified by the MIME stream header in ISO 16612-2 Annex A, not by a PDF file's XMP marker- The
/DPartRootcheck now validates the ISO 16612-2 §6.5 tree semantics more tightly:/DPartRootNodeand/NodeNameListmust describe the actual DPart depth, DPart parent links must form a tree,/Startand/DPartsare mutually exclusive, and each page/DPartmust point to the covering leaf DPart in the same depth-first order as the page tree
Version 1.44.1
Fixed
SaveAsPdfVTnow writes a minimal ISO 16612-2 §6.5 Document Part Hierarchy when the source PDF lacks a usable/DPartRoot. The generated tree links every page through/DPart, preserves an existing valid hierarchy, and leaves richer recipient/DPM metadata to the calling workflowValidatePdfVTnow validates the usable DPart structure, reads PDF/VT XMP values from both RDF attributes and element text, and enforces the exact PDF/VT-to-PDF/X base pairing: PDF/VT-1 requires PDF/X-4, while PDF/VT-2 requires PDF/X-4p, PDF/X-5g, or PDF/X-5pgTPdfVTSaveOptions.Conformance = pvc2no longer writes invalid single-file PDF/VT-2 markers. The single-file writer normalizes output to PDF/VT-1 because PDF/VT-2 requires file-set semantics
Version 1.44.0
Added
ValidatePdfUanow also reports byte-checkable content-level PDF/UA violations in addition to the file-format markers: a font program that is not embedded (ISO 14289-1, 7.21.4), a font that lacks a/ToUnicodeCMap when no exempt simple-font encoding is present (7.21.7), and a document that carries annotations but declares no page/Tabs /Stab order (7.18.3)- Three new
TPdfUaValidationIssuevalues —pvuaiFontNotEmbedded,pvuaiFontMissingToUnicodeandpvuaiMissingTabsOrder— are surfaced byValidatePdfUaand in the preflight report. They are coarse heuristics intended as preflight hints rather than a full ISO 14289-1 verification
Version 1.43.1
Fixed
SaveAsPdfUanow enforces the ISO 14289-1, 7.1 mandatory/ViewerPreferences/DisplayDocTitle trueand/MarkInfo/Marked true/Suspects falsecatalog entries even when the source document already provides those dictionaries with missing or contradicting values. Previously the markers were injected only when the dictionaries were entirely absent, so a source that carried, for example, a/ViewerPreferenceswithoutDisplayDocTitleor a/MarkInfowith/Marked falseround-tripped to a non-conforming file- Existing keys in a pre-existing
/ViewerPreferencesor/MarkInfodictionary are preserved, and a dictionary supplied as an indirect reference is resolved before the mandatory keys are applied
Version 1.43.0
Added
ValidatePdfAnow applies the PDF/A-2 / PDF/A-3 rules for embedded and associated files and for Level U text. Embedded files are still rejected for PDF/A-1; for PDF/A-3 an embedded file that lacks the required/AFRelationshipkey (ISO 19005-3 Annex E) is flagged, while PDF/A-2 attachments are permitted (their own conformance is not verified recursively). A newpvaiUnicodeMappingMissingissue reports a PDF/A-2u or PDF/A-3u document whose fonts carry no/ToUnicodemapping (ISO 19005-2 6.2.11.7). Transparency and optional content remain flagged only for PDF/A-1
Version 1.42.0
Added
- PDF/A-2 (ISO 19005-2) and PDF/A-3 (ISO 19005-3) are now supported at all three conformance levels — a, b and u — by
SaveAsPdfA,ValidatePdfAand thePdfAConformanceproperty. TheTPdfAConformanceenumeration gainspac2a,pac2u,pac3aandpac3u(PDF/A-1 has no Level u). Saving writes the matchingpdfaid:part(2 or 3) andpdfaid:conformance(A, B or U), keeping theGTS_PDFA1OutputIntent subtype that ISO 19005-2 retains for compatibility. A Level A request still downgrades to the matching Level B (for any part) when the document lacks the tagged structure that level requires
Version 1.41.0
Added
ValidatePdfAnow detects content-level PDF/A violations that marker injection cannot repair, on top of the structural markers it already reported: JavaScript and other forbidden actions, additional-actions (/AA), embedded files,LZWDecode, transparency (soft masks and transparency groups), optional content (/OCProperties), forbidden annotation subtypes (FileAttachment, Sound, Movie, 3D, Screen), AcroForm/NeedAppearances trueand/XFA, fonts whose descriptors lack an embedded font program, and a Level A claim made without the tagged structure required by ISO 19005-1 6.8. The transparency, optional-content and embedded-file checks apply only to PDF/A-1 (these features are permitted in PDF/A-2 and PDF/A-3). NewTPdfAValidationIssuevalues surface each case; the existing values are unchanged
Version 1.40.3
Fixed
SaveAsPdfAnow strips any source-document encryption before producing PDF/A output. ISO 19005-1 6.1.3 forbids the trailer/Encryptkey, but the save path previously preserved the source's security handler, so saving an encrypted document as PDF/A produced an encrypted, non-conformant file. The PDF/A save now decrypts the document first. Unencrypted documents are unaffected
Version 1.40.2
Fixed
- Stopped
SaveAsPdfAfrom emitting a false PDF/A Level A conformance claim. When Level A (pac1a) is requested but the source document lacks the tagged-structure markers required by ISO 19005-1 6.8 — a/StructTreeRootin the catalog and a/MarkInfodictionary with/Marked true— the saved file is now identified as the matching Level B (pdfaid:conformance=B) instead of asserting Level A. Purely visual PDF/A-1b output is unaffected
Version 1.40.1
Fixed
- Tightened PDF version-compliance validation so that the
SetOCGState(set-optional-content-group-state) action is recognized as a PDF 1.5 feature. Saving to a PDF 1.2, 1.3, or 1.4 target that contains aSetOCGStateaction is now rejected to match ISO 32000-1 (Table 198); previously such an action could pass through into lower-version output. The distinct, obsolete PDF 1.2SetStateaction is still accepted from PDF 1.2 onward
Version 1.40.0
Added
- Bound the upstream
FPDFPageObj_AddExistingMark()API, which attaches an existing content mark to a page object. When consecutive page objects share the same mark, the saved PDF collapses them into a single mark that spans all of them; non-consecutive objects receive separate copies - Bound the upstream
FPDFTextObj_SetFontSize()API for changing the point size of an existing text object, complementing the existingFPDFTextObj_GetFontSize()binding
Changed
- Refreshed the bundled PDFium runtime DLLs (Win32 and Win64, standard and V8 builds) to the 2026-06-02 upstream snapshot
Version 1.39.53
Changed
- Changed the Delphi
PDFViewer,SplitView, andMultiPageViewerdemos to open documents inZoom to Pagemode by default - The initial render now fits the whole page into the viewer surface before the user chooses a manual zoom level
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.53
Version 1.39.52
Changed
- Enhanced
Demo\Lazarus\CreatePDFso the introductory sample now generates a two-page PDF with vector paths, table content, an embedded image, a text annotation, rotated text, and a clearer document-building walkthrough - Added polished
README.htmlpages for every Delphi, C++Builder, and Lazarus demo folder, replacing the remaining text-only demo README with a browser-readable guide - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.52
Version 1.39.51
- Enhanced
Demo\Delphi\PreflightReportClibatch summaries with standard status totals for Pass, Action required, and Review results across the selected standards - Per-file rows now include action-required and review counts in TXT / HTML / JSON / CSV summaries, making CI artifacts easier to inspect without opening each generated report
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.51
Version 1.39.50
- Enhanced
Demo\Delphi\PreflightReportClidirectory batch mode sobatchdir=foldercollects discovered PDF paths, sorts them, and then generates reports in a stable order - Recursive directory scans now produce reproducible report order and summary rows, while explicit
batch=list.txtprocessing continues to preserve the list file order - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.50
Version 1.39.49
- Enhanced
Demo\Delphi\PreflightReportClibatch summaries to record run settings: source kind, source path, recursive state, output directory, report format, selected standards, andfailon=mode - JSON summaries now include a
runobject, TXT and HTML summaries show a run settings section, and CSV rows repeat the same audit columns for spreadsheet and CI pipelines - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.49
Version 1.39.48
- Enhanced
Demo\Delphi\PreflightReportClibatch output naming so duplicate input file names that share oneoutdir=no longer overwrite each other's generated reports - Batch runs now append
-2,-3, and later suffixes when a generated report path has already been assigned in the same run, and summaries record the final collision-safe report path - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.48
Version 1.39.47
- Enhanced
Demo\Delphi\PreflightReportClibatch summaries so TXT and JSON outputs now include aggregate totals for total files, processed files, failed files, issues, andfailon=matches - CSV summaries remain a pure row table for existing consumers, while HTML summaries continue to show the same aggregate metrics in the dashboard header
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.47
Version 1.39.46
- Enhanced
Demo\Delphi\PreflightReportCliwithsummary=batch.html/.htmso batch runs can emit a browser-readable dashboard alongside TXT / CSV / JSON manifests - HTML summaries show total, processed, failed, issue, and
failon=match metrics, then list each input with report links, status, counts, and error text - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.46
Version 1.39.45
- Enhanced
Demo\Delphi\PreflightReportCliwithbatchdir=folderandrecursiveso scripts can scan PDF folders directly without first writing a list file - Directory batch mode reuses
outdir=,summary=,standards=, andfailon=behavior from list-based batch mode, while non-recursive scans only the selected folder andrecursiveincludes subfolders - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.45
Version 1.39.44
- Enhanced
Demo\Delphi\PreflightReportCliwithsummary=batch.csv|json|txtso batch runs can emit a machine-readable manifest beside the per-file reports - Batch summaries include each input path, report path, status, standard count, passed count, issue count,
failon=match state, and error text for CI jobs and external scripts - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.44
Version 1.39.43
- Enhanced
Demo\Delphi\PreflightReportCliwithbatch=list.txtandoutdir=reportsso scripts can generate preflight reports for a list of PDF files in one run - Batch mode skips blank and
#comment lines, derives each.preflight.<ext>report name from the input PDF, continues after per-file errors, and summarizes processed and failed files before returning - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.43
Version 1.39.42
- Enhanced
Demo\Delphi\PreflightReportCliwithfailon=none|issues|action|reviewso CI jobs can turn generated preflight results into deterministic exit codes - The CLI now returns exit code 2 when a selected
failon=rule matches after the report file and optional attached-report PDF have been generated, while runtime errors still return exit code 1 - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.42
Version 1.39.41
- Enhanced
Demo\Delphi\PreflightReportCliwithattach=output.pdfso a generated preflight report can be embedded as a document-level attachment in a new PDF copy - The CLI keeps the generated TXT / HTML / Markdown / JSON / CSV report file on disk and refuses to attach back into the original input PDF path, reducing accidental overwrite risk
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.41
Version 1.39.40
- Added
Demo\Delphi\PreflightReportCli, a Delphi console companion for scriptableFPdfPreflightReportgeneration without opening a viewer - The CLI supports no-argument sample creation plus input / output arguments, optional password,
text/html/md/json/csvoutput formats, andstandards=filtering for PDF/A, PDF/UA, PDF/E, PDF/X, PDF/R, and PDF/VT - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.40
Version 1.39.39
- Enhanced
FPdfPreflightReportwithTPdfPreflightReport.ToMarkdownandSaveMarkdownToFileso preflight reports can be exported as issue-tracker-friendly Markdown - Updated the Delphi, C++Builder, and Lazarus
PreflightReportsamples with Markdown preview switching and Save MD actions alongside the existing TXT / HTML / JSON / CSV workflow - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.39
Version 1.39.38
- Enhanced the Delphi, C++Builder, and Lazarus
SecurityAuditsamples with JSON audit report export alongside the existing TXT save / copy workflow - The JSON report contains
format,generatedAt,summary,findingCount, and structuredfindingsrows with severity, area, and detail fields - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.38
Version 1.39.37
- Enhanced
FPdfPreflightReportwithTPdfPreflightReport.ToCsvandSaveCsvToFileso preflight reports can be exported as spreadsheet-friendly CSV - Updated the Delphi, C++Builder, and Lazarus
PreflightReportsamples with CSV preview switching and Save CSV actions alongside the existing TXT / HTML / JSON workflow - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.37
Version 1.39.36
- Enhanced
FPdfPreflightReportwithTPdfPreflightReport.IssueCategoryCountsplus reusableTPdfPreflightIssueCategoryCountandTPdfPreflightIssueCategoryCountstypes for aggregating marker-level issues by category - Updated
TPdfPreflightReport.ToText,ToHtml, andToJsonso generated PreflightReport output includes issue-category count summaries alongside per-standard rows and detailed issue recommendations - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.36
Version 1.39.35
- Renamed the expanded
PrintDialogsample toPrintPreferencesacross Delphi, C++Builder, and Lazarus so the demo name now matches its PDF author print preferences, N-up printing, odd / even filtering, grayscale, cell border, and duplex mapping workflow - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.35
Version 1.39.34
- Enhanced
Demo\Delphi\PrintPDFwith drag-and-drop PDF loading and documented the existingDemo\CBuilder\PrintPDFworkflow alongside the Delphi and Lazarus PrintPDF samples - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.34
Version 1.39.33
- Added
Demo\CBuilder\SplitView, completing the SplitView sample matrix across Delphi, C++Builder, and Lazarus - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.33
Version 1.39.32
- Added
Demo\Lazarus\SplitView, bringing side-by-side PDF comparison to Lazarus with two- or three-pane layouts, active-view navigation, synchronized commands, zoom presets, and rotation - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.32
Version 1.39.31
- Added
Demo\Lazarus\PrintPDF, bringing the standard PDF print workflow to Lazarus with preview navigation, page ranges, copies, collate mode, progress, and cancellation - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.31
Version 1.39.30
- Added
Demo\Lazarus\FontProperties, completing the FontProperties sample matrix across Delphi, C++Builder, and Lazarus - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.30
Version 1.39.29
- Added
Demo\CBuilder\FontProperties, bringing indexed character and font metadata inspection to C++Builder alongside the Delphi sample - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.29
Version 1.39.28
- Added
Demo\Delphi\ExtractTextPages, completing the per-page text extraction sample matrix across Delphi, C++Builder, and Lazarus - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.28
Version 1.39.27
- Added
Demo\Lazarus\PrintDialog, completing the PrintDialog sample matrix across Delphi, C++Builder, and Lazarus - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.27
Version 1.39.26
- Added
Demo\CBuilder\PrintDialog, bringing the N-up printing and PDF author print preferences workflow to C++Builder alongside the Delphi sample - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.26
Version 1.39.25
- Added
Demo\CBuilder\ViewerInteractionLab, completing the ViewerInteractionLab sample matrix across Delphi, C++Builder, and Lazarus - Updated the library build workflow and Win64 C++Builder package outputs so
TPdfViewviewer interaction methods link correctly in Win64 demos - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.25
Version 1.39.24
- Added
Demo\Lazarus\ViewerInteractionLab, bringing the focused viewer interaction workflow to Lazarus alongside the Delphi sample - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.24
Version 1.39.23
- Added
Demo\Lazarus\SearchAndSelect, completing the SearchAndSelect sample matrix across Delphi, C++Builder, and Lazarus - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.23
Version 1.39.22
- Added
Demo\CBuilder\ContentExtractionLabandDemo\Lazarus\ContentExtractionLab, bringing the multi-category content extraction workflow to all supported demo IDEs - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.22
Version 1.39.21
- Enhanced
Demo\Delphi\PreflightReport,Demo\Lazarus\PreflightReport, andDemo\CBuilder\PreflightReportwith a preview format selector so users can inspect text or JSON output before saving reports - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.21
Version 1.39.20
- Added JSON export to
FPdfPreflightReportthroughTPdfPreflightReport.ToJsonandSaveJsonToFile, producing machine-readable summaries, per-standard status / priority, next actions, and issue details - Updated
Demo\Delphi\PreflightReport,Demo\Lazarus\PreflightReport, andDemo\CBuilder\PreflightReportwith Save JSON actions alongside TXT / HTML export - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.20
Version 1.39.19
- Enhanced
FPdfPreflightReportwithTPdfPreflightStatus, issue categories, per-standard priority, and next-action guidance in TXT / HTML reports - Updated
Demo\Delphi\PreflightReport,Demo\Lazarus\PreflightReport, andDemo\CBuilder\PreflightReportto show status, priority, issue count, and next action in the summary grid - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.19
Version 1.39.18
- Added
Demo\Lazarus\SecurityAudit, completing the Delphi, C++Builder, and Lazarus demo matrix for the read-only PDF risk-surface audit workflow - The Lazarus sample enumerates permissions, attachments, JavaScript actions, URI / Launch link annotations, web links, signatures, XFA state, V8 / XFA helper availability, and unsupported-feature callbacks, then saves or copies the finding list as a TXT report
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.18
Version 1.39.17
- Added
Demo\CBuilder\SecurityAudit, bringing the read-only PDF risk-surface audit workflow to C++Builder alongside the existing Delphi sample - The C++Builder sample enumerates permissions, attachments, JavaScript actions, URI / Launch link annotations, web links, signatures, XFA state, V8 / XFA helper availability, and unsupported-feature callbacks, then saves or copies the finding list as a TXT report
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.17
Version 1.39.16
- Added
Demo\CBuilder\SearchAndSelect, bringing the standalone SearchAndSelect viewer workflow to C++Builder alongside the existing Delphi sample - The C++Builder sample creates or opens PDFs, lists all-page matches with page / character-index previews, supports Previous / Next and double-click navigation, and highlights current-page matches with
HighlightSearchText - It also exposes
AllowUserTextSelection,SelectedText,SelectAll,CopySelectionToClipboard,ClearSelection,OnSelectionChange, and spreadDisplayModeoptions; version metadata now reports 1.39.16
Version 1.39.15
- Added
Demo\CBuilder\WatermarkStamp, completing the Delphi, Lazarus, and C++Builder demo matrix for reusable Form XObject watermark and stamp workflows - The C++Builder sample creates target and stamp PDFs, reuses the stamp page through
CreateXObjectFromPage, appliesTPdfMatrixtransforms, and saves centered watermarks, corner stamps, and page number labels - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.15
Version 1.39.14
- Added
Demo\Lazarus\WatermarkStamp, bringing the reusable Form XObject watermark and stamp workflow to Lazarus - The Lazarus sample creates target and stamp PDFs, reuses the stamp page through
CreateXObjectFromPage, appliesTPdfMatrixtransforms, and saves centered watermarks, corner stamps, and page number labels - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.14
Version 1.39.13
- Added
Demo\CBuilder\PreflightReport, completing the Delphi, Lazarus, and C++Builder demo matrix for the reusableFPdfPreflightReportworkflow - The C++Builder sample uses
FPdfPreflightReport.hppto generate standard summaries, TXT report previews, TXT / HTML report files, and Open Last Report behavior - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.13
Version 1.39.12
- Added
Demo\Lazarus\PreflightReport, bringing the PDF/A, PDF/UA, PDF/E, PDF/X, PDF/R, and PDF/VT preflight report workflow to Lazarus - The Lazarus sample can open or create a PDF, select target standards, preview summary rows and TXT report output, save TXT / HTML reports, and open the most recently saved report
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.12
Version 1.39.11
- Enhanced
Demo\Delphi\SearchAndSelectwith an all-page search results list that records page number, character index, and preview text - Added Previous / Next match navigation and double-click result jumping while preserving current-page
HighlightSearchTextbehavior - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.11
Version 1.39.10
- Enhanced
Demo\Delphi\SecurityAuditwith Save Report and Copy Report actions that export the current summary and finding rows as a TXT audit report - The demo now clears report export state when the audit panel is reset, keeping copied or saved reports aligned with the visible findings
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.10
Version 1.39.9
- Enhanced
Demo\Delphi\ContentExtractionLabwith source-PDF save, report copy-to-clipboard, and all / none category selection actions - The demo now invalidates the current report when category selections change, so TXT / JSON exports reflect the visible extraction scope
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.9
Version 1.39.8
- Added
Demo\Delphi\ContentExtractionLab, a unified content extraction workflow sample for document metadata, page text, page objects, images, attachments, links, annotations, bookmarks, and font / character metrics - The sample can open an existing PDF or create a synthetic PDF with text, image, attachment, and annotation content, then generate summary rows and detailed TXT / JSON reports
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.8
Version 1.39.7
- Added
Lib\FPdfPreflightReport.pas, a reusable report helper that wrapsValidatePdfA,ValidatePdfUa,ValidatePdfE,ValidatePdfX,ValidatePdfR, andValidatePdfVTinto oneTPdfPreflightReportobject - Added
Demo\Delphi\PreflightReport, a workflow sample that opens or creates a PDF, selects target standards, previews summary rows and issue recommendations, and saves TXT or HTML reports - The generated reports explicitly describe the built-in marker-level validation boundary so applications can pair them with dedicated content-level preflight tools when required
- Updated
TPdf.AboutInfo, Lazarus package metadata, package project lists, and installer version metadata to report 1.39.7
Version 1.39.6
- Added
Demo\Delphi\SearchAndSelect, a focused viewer workflow sample for search highlighting, text selection, selected-text preview, copy, clear, and spread display modes - The sample demonstrates
HighlightSearchText, match-case / whole-word search options,AllowUserTextSelection,SelectedText,SelectAll,CopySelectionToClipboard, andClearSelectionwithout adding new library API - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.6
Version 1.39.5
- Expanded
Demo\Delphi\ViewerInteractionLabinto a SearchAndSelect-style viewer UX sample withHighlightSearchText, match-case / whole-word options, selected-text preview, and existing selection / clipboard controls - Extended
Demo\Delphi\PrintDialogto inspect PDF author print preferences:PrintCopies,PrintPageRanges,PrintScaling,PrintPaperHandling, and visibleSetPdfPrintPaperHandlingDevModeduplex mapping - Added
Demo\Delphi\SecurityAudit, a read-only risk-surface sample that lists permissions, attachments, document JavaScript, URI / Launch links, web links, signatures, XFA state, and V8 / XFA helper availability - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.5
Version 1.39.4
- Added
Demo\CBuilder\ImageToPDFandDemo\Lazarus\ImageToPDF, completing the ImageToPDF sample matrix across Delphi, C++Builder, and Lazarus - The new samples demonstrate multi-image selection, selected-image preview, one PDF page per image, A4 portrait / landscape page sizing, centered image scaling, per-image progress, and opening the generated PDF after saving
- Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.4
Version 1.39.3
- Added
Demo\CBuilder\BatchExport, bringing the multi-file PDF to JPG export workflow to C++Builder alongside the existing Delphi and Lazarus samples - The sample demonstrates
LoadCustomDocument,IPdfCancellationTokenSource, streamingTFileStreaminput, per-file and per-page progress, cancel handling, DPI / quality / password inputs, and output-folder opening after completion - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.3
Version 1.39.2
- Added
Demo\Delphi\WatermarkStamp, a runnable Form XObject workflow sample that creates a target PDF and reusable stamp PDF, then applies centered watermarks, top-right stamps, and page-number labels across every page - The sample demonstrates
CreateXObjectFromPage,InsertFormObjectFromXObject,TPdfMatrix, andFPDFPageObj_SetMatrixwithout adding new library API - Updated
Docs\en-us\Examples.htmlto use the currentTPdfMatrix.Handlepattern when passing matrices toFPDFPageObj_SetMatrix - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.2
Version 1.39.1
- Added
Demo\Delphi\ViewerInteractionLab, a focusedTPdfViewsample for display modes, fit modes, page colors, rotation, user text selection, clipboard actions, andDeviceToPagecoordinate feedback - Added
Demo\CBuilder\StandardsLab/Demo\Lazarus\StandardsLabso Lazarus users can run the PDF/A, PDF/UA, PDF/E, PDF/X, PDF/R, and PDF/VT validation and marker-output workflow - Listed the standards units in
Lib\37.0\PDFiumPas.dprojandLib\FPC\PDFiumLaz.lpkand fixed the DelphiSplitViewdemo build by removing a duplicateWinapi.ShellAPIimport - Fixed Delphi demo batch-build blockers in
BatchExport,PDFViewer,MultiPageViewer, andSplitViewwithout changing their runtime behavior - Fixed C++Builder demo batch-build compatibility in
PDFViewerandMultiPageViewerby replacingnullptrwithNULLfor the current project mode - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.1
Version 1.39.0
- Added
Demo\Delphi\StandardsLab, a runnable standards workflow sample that loads or creates a PDF, runsValidatePdfA,ValidatePdfUa,ValidatePdfE,ValidatePdfX,ValidatePdfR, andValidatePdfVT, and displays detected conformance, pass/fail status, and issue counts in one grid - The StandardsLab save buttons call
SaveAsPdfA,SaveAsPdfUa,SaveAsPdfE,SaveAsPdfX,SaveAsPdfR, andSaveAsPdfVT, making PDF standards marker output visible without writing a custom harness - Updated
TPdf.AboutInfo, Lazarus package metadata, and installer version metadata to report 1.39.0
Version 1.38.0
TPdfViewsearch and text-selection overlays now use real alpha blending instead of logical mask painting, preserving page content under highlights- Added
SetPdfPrintPaperHandlingDevModeto mapTPrintPaperHandlinginto WindowsDEVMODE.dmDuplexvalues:DMDUP_SIMPLEX,DMDUP_HORIZONTAL, andDMDUP_VERTICAL TPdfView.SmoothScrollnow animates line/page scrollbar commands in timer-driven segments; thumb tracking remains immediate- Updated
TPdf.AboutInfoand installer version metadata to report 1.38.0
Version 1.37.0
TPdfnow owns a per-instance render lock that serializesRenderPage,RenderTile,RenderPageProgressive, page reload, and document unload paths. Worker-driven rendering through a shared component is now practical, while applications still coordinate document mutation and lifetime- Fixed the zero-copy bitmap wrapper to reject bottom-up
TBitmapDIB layouts and fall back to a PDFium-owned buffer before copying out, eliminating stride-corruption / access-violation failures in VCL render tests - Tightened
TPdfViewselection behavior:AllowUserTextSelectiongates user input only, code-level selection APIs still paint, andSelectAllfollows the actual visible spread so the cover page no longer selects page 2. Delphi, Lazarus, and C++Builder tests were expanded accordingly - Updated
TPdf.AboutInfoand installer version metadata to report 1.37.0
Version 1.36.0
- Activated end-user text selection in
TPdfView— theAllowUserTextSelectionproperty reserved in v1.17.0 now drives a complete drag-select pipeline. Left-click on a text character enters select mode (hit-test auto); left-click on a blank area continues to pan as before. The form-fill widget keeps priority, so clicking on a form field still focuses the field rather than starting a selection - Double-click selects the word, triple-click selects the line,
Ctrl+Aselects the current page (both pages in spread display modes), andCtrl+Ccopies the selection to the Windows clipboard asCF_UNICODETEXT Shift+Left/Shift+Rightextends the selection one character at a time (spilling to the adjacent page in spread mode);Shift+Home/Shift+Endextends to the visual line edge using the seed character's box height as the line-cluster tolerance, so mixed-font-size lines stay clustered correctly- Hovering over text changes the cursor to
crIBeam; hovering off text restores the default cursor. While a text-selection drag is in progress, dragging into a 20-pixel dead zone at any viewer edge auto-scrolls the page (50 ms tick, 16 px / tick, clamped to the same bounds the pan path uses) so the selection can extend past the current viewport without first releasing the mouse - Cross-page selection works in spread display modes (
dmTwoPageContinuous,dmTwoPageContinuousWithCover): a drag started on the left page and ending on the right page selects the contiguous range spanning both.SelectedTextjoins the per-page slices with CR/LF so the round-tripped text reads like normal multi-line content - New published property
SelectionColor(defaultclHighlight, the Windows system selection color) — independent fromHighlightColorwhich colors search results in yellow. Search highlights and a live drag-selection can be shown on screen simultaneously without color conflict - New published event
OnSelectionChangefires whenever the selection's materialised ranges actually mutate — never on identical re-application, so host applications can wire it directly to status-bar text or button enabled state without debouncing - New public API on
TPdfView:HasSelection,SelectionCharCount,SelectedText,ClearSelection,SelectAll,CopySelectionToClipboard. These are code-level entry points and always work regardless ofAllowUserTextSelection— the flag only gates user input (mouse, Ctrl+C, Ctrl+A, Shift+arrows), so kiosk hosts can disable user-driven selection while still building "Select All / Copy" toolbar buttons that drive the same API - A default right-click
Copy/复制popup menu is auto-attached when the host has not assigned its ownPopupMenu— standard "select text, right-click, copy" works out of the box. The caption is picked between English and Chinese bySysLocale.PriLangID; hosts that need full localization (or a richer menu) just assign their ownPopupMenuand the default is suppressed - Selection is automatically cleared on
SetPdf,SetPageNumber,SetActive(False), andDisplayModetransitions, withOnSelectionChangefiring exactly once when the previous selection was non-empty. The form-fill subsystem keeps priority — while a form field is being edited, all selection keyboard shortcuts defer so the field receivesCtrl+C/Ctrl+A/Shift+arrowsfor its own selection - Expanded the Delphi and Lazarus regression suites to 202 cases each, and the C++Builder suite to 159 cases, covering default values, round-trip, public API behavior, state-change clears, mouse drag (hit-text / hit-blank), click vs drag, IBeam cursor switching, double-click word, triple-click line, keyboard shortcuts, default popup attach / defer / caption, and spread cross-page selection — including a clipboard CR/LF round-trip check
Version 1.35.0
- Added PDF/VT (ISO 16612-2:2010) marker injection support: TPdf.SaveAsPdfVT promotes the current document to a PDF/VT-1 or PDF/VT-2 conformant file (the variable and transactional printing PDF subset). PDF/VT is built on top of PDF/X-4 — ISO 16612-2 §6.2.1 requires every PDF/VT-1 file to also conform to PDF/X-4 — so the injector writes the full PDF/X-4 marker set (XMP
pdfxid:GTS_PDFXVersion = "PDF/X-4", Info/GTS_PDFXVersion (PDF/X-4)and/Trapped, catalog/OutputIntentsreferencing an OutputIntent dictionary with embedded ICC profile) alongside the PDF/VT-specific properties - The PDF/VT-specific injection covers XMP
pdfvtid:GTS_PDFVTVersion(= "PDF/VT-1" or "PDF/VT-2" per §6.3 Table 2) andpdfvtid:GTS_PDFVTModDate(kept in sync withxmp:ModifyDateper §6.3 NOTE 1), plus a pdfaExtension:schemas description that declares both the pdfxid and pdfvtid namespaces (NPES URIshttp://www.npes.org/pdfx/ns/id/andhttp://www.npes.org/pdfvt/ns/id/). The trailer carries an/IDarray - Added TPdf.SaveAsPdfVTToStream for in-memory PDF/VT output, and a default-options shorthand
TPdf.SaveAsPdfVT(FileName)that produces PDF/VT-1 with the bundled sRGB IEC61966-2.1 OutputIntent (3144 bytes, same profile as SaveAsPdfA / SaveAsPdfX) and/Trapped /False - Added TPdf.ValidatePdfVT: checks an open PDF for PDF/VT compliance markers (XMP
pdfvtid:GTS_PDFVTVersionandGTS_PDFVTModDatepresence, equality betweenpdfvtid:GTS_PDFVTModDateandxmp:ModifyDate, presence of the underlyingpdfxid:GTS_PDFXVersionidentifier, catalog/DPartRootpresence per §6.5,/OutputIntentswith/DestOutputProfile, trailer /ID, encryption status,xmp:CreateDate/ModifyDatepresence) and returns TPdfVTValidationResult with the detected conformance level and the set of issues found - Added TPdf.PdfVTConformance property: returns the conformance level of the currently open document (pvc1, pvc2, pvcNone, or pvcUnknown) without needing to call ValidatePdfVT explicitly
- New types exported in the new unit FPdfPdfvt: TPdfVTConformance (pvcUnknown/None/1/2), TPdfVTTrappedState (ptvUnspecified/True/False/Unknown), TPdfVTValidationResult, TPdfVTValidationIssue, TPdfVTSaveOptions
- Document Part Hierarchy (
DPartRoot/DParttree per §6.5) is application-level structure that depends on the variable-data print workflow's recipient / page-range mapping. SaveAsPdfVT does NOT synthesise a DPart tree — ValidatePdfVT surfaces a missing/DPartRootaspvviMissingDPartRootso callers can route PDF/VT files through a separate DPart-building step. Content-level PDF/X-4 requirements (font embedding, transparency, ICC managed color, OPI / JavaScript / Reference XObject prohibitions, etc.) remain the responsibility of the document author and PDFium's rendering pipeline - Updated TPdf.AboutInfo string to report the current product version
Version 1.34.0
- Added PDF/R-1 (ISO 23504-1:2020) marker injection support: TPdf.SaveAsPdfR promotes the current document to a PDF/R-1 conformant file (the raster-image transport subset of PDF used for scanned documents). The injection covers the file-format level requirements that can be attached by post-processing — the unique
%PDF-raster-1.0version-identification comment written between the trailer dictionary and the startxref keyword (§5), the catalog dictionary stripped down to the §6.3 white list (only Version / ViewerPreferences / PageLayout / PageMode / AcroForm / Metadata survive), the Document Information Dictionary stripped to the §6.4.3 white list (only Creator / Producer / CreationDate / ModDate), a catalog /Metadata XMP stream carrying the four §6.4.4 Table 1 entries (xmp:CreatorTool / pdf:Producer / xmp:CreateDate / xmp:ModifyDate), and a trailer /ID array - Added TPdf.SaveAsPdfRToStream for in-memory PDF/R output, and a default-options shorthand
TPdf.SaveAsPdfR(FileName)for the common case - Added TPdf.ValidatePdfR: checks an open PDF for PDF/R-1 compliance markers (the
%PDF-raster-x.yfooter comment, header version, /Type /ObjStm absence, catalog white-list compliance, Info dictionary white-list compliance, XMP metadata stream presence, trailer /ID) and returns TPdfRValidationResult with the detected conformance level and the set of issues found - Added TPdf.PdfRConformance property: returns the conformance level of the currently open document (prc1, prcNone, or prcUnknown) without needing to call ValidatePdfR explicitly
- New types exported in the new unit FPdfPdfr: TPdfRConformance, TPdfRValidationResult, TPdfRValidationIssue, TPdfRSaveOptions.
TPdfRSaveOptions.Defaultsets StripInfoOptionalEntries and StripCatalogOptionalEntries to True, so the injector defaults to producing a §6.3 / §6.4.3 compliant catalog and Info dictionary; callers may set these to False to preserve source entries (the output then won't satisfy those PDF/R clauses, but other markers stay attached) - Content-level requirements remain the responsibility of the source PDF: per-page Contents structure (§6.5.1), MediaBox
[0 0 w h]form (§6.5.3), filter restrictions (§6.2.2 — only FlateDecode, CCITTFaxDecode bitonal, DCTDecode 8-bit gray/RGB), absence of object streams (§6.2.4), and strip layout per §6.6. These cannot be enforced by post-processing — PDF/R is structurally a much stricter subset than the other PDF/x standards and requires generating the source bytes correctly. ValidatePdfR surfaces the file-format issues this unit can detect; pair with a TWAIN Working Group PDF/R validator for full content-level checks - Updated TPdf.AboutInfo string to report the current product version
Version 1.33.0
- Added PDF/X (ISO 15930 family) marker injection support: TPdf.SaveAsPdfX promotes the current document to a PDF/X-1a:2001, PDF/X-3:2002, or PDF/X-4 conformant file by post-processing the base PDF with an incremental update. The injection covers the file-format level requirements that can be attached by post-processing — XMP metadata stream carrying
pdfxid:GTS_PDFXVersion(andpdfxid:GTS_PDFXConformancefor PDF/X-1a / PDF/X-3) plus the matching pdfaExtension:schemas description, a rewritten Document Information Dictionary with/GTS_PDFXVersion,/GTS_PDFXConformance, and/Trappedentries, an updated catalog with/OutputIntents [N 0 R]referencing an OutputIntent dictionary with/S /GTS_PDFXand an embedded ICC profile, and a trailer/IDarray - Added TPdf.SaveAsPdfXToStream for in-memory PDF/X output, and a default-options shorthand
TPdf.SaveAsPdfX(FileName)that produces PDF/X-4 with the built-in sRGB IEC61966-2.1 OutputIntent (3144 bytes, identical to the profile used by SaveAsPdfA) - Added TPdf.ValidatePdfX: checks an open PDF for PDF/X compliance markers (XMP pdfxid identifier and equality with the Info-dictionary value, pdfxid extension schema description, /OutputIntents array with /DestOutputProfile, Title presence, trailer /ID, encryption status, xmp:CreateDate / xmp:ModifyDate presence) and returns TPdfXValidationResult with the detected level and the set of issues found
- Added TPdf.PdfXConformance property: returns the conformance level of the currently open document (pxc1a, pxc3, pxc4, pxcNone, or pxcUnknown) without needing to call ValidatePdfX explicitly. The XMP version string is parsed to disambiguate among the three conformance levels
- New types exported in the new unit FPdfPdfx: TPdfXConformance (pxcUnknown/None/1a/3/4), TPdfXTrappedState (ptUnspecified/True/False/Unknown), TPdfXValidationResult, TPdfXValidationIssue, TPdfXSaveOptions.
TPdfXSaveOptions.Defaulttargets PDF/X-4 with sRGB OutputIntent and/Trapped /False; callers may overrideConformance, supply a CMYKIccProfileDatablob for commercial print workflows, or changeOutputCondition/OutputConditionIdentifier/RegistryNameto point at a specific ICC characterisation registry entry (e.g. FOGRA39, GRACoL2006_Coated1v2) - Content-level requirements (all fonts embedded, no JavaScript, no visible annotations, OPI prohibition, transparency rules for PDF/X-1a / PDF/X-3, etc.) remain the responsibility of the document author and PDFium's rendering pipeline. Pair ValidatePdfX with a preflight tool such as callas pdfaPilot or the Ghent PDF Workgroup Output Suite for complete conformance verification
- Updated TPdf.AboutInfo string to report the current product version
Version 1.32.0
- Added PDF/E-1 (ISO 24517-1:2008) marker injection support: TPdf.SaveAsPdfE promotes the current document to a PDF/E-1 conformant file by post-processing the base PDF with an incremental update. The injection covers the file-format level requirements that can be attached by post-processing — an XMP metadata stream carrying
pdfe:ISO_PDFEVersion = "PDF/E-1"plus the matching pdfaExtension:schemas description, a rewritten Document Information Dictionary with the mandatory/ISO_PDFEVersion (PDF/E-1)entry required by §5, the Info-XMP bridging blocks inherited from ISO 19005-1 §6.7 via §13.1 (dc:title / dc:creator / dc:description / pdf:Producer / pdf:Keywords / xmp:CreateDate / xmp:ModifyDate / xmp:MetadataDate / xmp:CreatorTool), and a trailer/IDarray required by §6.2 - Added TPdf.SaveAsPdfEToStream for in-memory PDF/E output and a default-options shorthand
TPdf.SaveAsPdfE(FileName)for the common case - Added TPdf.ValidatePdfE: checks an open PDF for PDF/E-1 compliance markers (XMP pdfe:ISO_PDFEVersion presence and equality with the Info-dictionary value, pdfe extension schema description, Info-dictionary /ISO_PDFEVersion entry, trailer /ID, xmp:CreateDate / xmp:ModifyDate presence) and returns a structured result with the detected conformance level and the set of issues found
- Added TPdf.PdfEConformance property: returns the conformance level of the currently open document (pec1, pecNone, or pecUnknown) without needing to call ValidatePdfE explicitly
- New types exported in the new unit FPdfPdfe: TPdfEConformance, TPdfEValidationResult, TPdfEValidationIssue, TPdfESaveOptions
- The Info-dictionary rewrite is a first for PDFiumPas's PDF/x post-processing path — it rewrites the existing Info object with the same object number (so xref subsection / trailer /Info reference stay valid) and synthesises a fresh Info dictionary when the source trailer has no /Info entry. PDFium itself emits an Info dictionary in every SaveAs output, so the common case is the rewrite path
- Content-level requirements (font embedding, ToUnicode CMaps, prohibited XObjects / ExtGState keys / XFA forms, etc.) remain the responsibility of the document author — SaveAsPdfE attaches the file-format markers but does not alter page content or remove prohibited features
- Updated TPdf.AboutInfo string to report the current product version
Version 1.31.0
- Added PDF/UA-1 (ISO 14289-1:2014) marker injection support: TPdf.SaveAsPdfUa promotes the current document to a PDF/UA-1 conformant file by post-processing the base PDF with an incremental update. The injection covers the file-format level requirements that can be enforced by post-processing — an XMP metadata stream carrying
pdfuaid:part = 1plus the matching pdfaExtension:schemas description, mandatorydc:title, catalog/MarkInfo << /Marked true /Suspects false >>and/ViewerPreferences << /DisplayDocTitle true >>(only when the source has none), catalog/Lang(when caller supplies a BCP 47 tag), and a trailer/IDarray - Added TPdf.SaveAsPdfUaToStream for in-memory PDF/UA output, and a default-options shorthand
TPdf.SaveAsPdfUa(FileName)for the common case - Added TPdf.ValidatePdfUa: checks an open PDF for PDF/UA-1 compliance markers (StructTreeRoot existence, /Lang, /MarkInfo /Marked true with /Suspects = false, /ViewerPreferences /DisplayDocTitle true, XMP pdfuaid:part identifier, dc:title presence, trailer /ID, encryption status) and returns a structured result with the detected conformance level and the set of issues found
- Added TPdf.PdfUaConformance property: returns the conformance level of the currently open document (puc1, pucNone, or pucUnknown) without needing to call ValidatePdfUa explicitly
- New types exported in the new unit FPdfPdfua: TPdfUaConformance, TPdfUaValidationResult, TPdfUaValidationIssue, TPdfUaSaveOptions
- Title / Author / Subject / Keywords / Creator / Producer / CreationDate / ModDate / DocumentId / InstanceId / Language fields left empty in TPdfUaSaveOptions are auto-populated from FPDF_GetMetaText / FPDF_GetFileIdentifier / FPDFCatalog_GetLanguage, so existing callers can save with a single line
- Content-level requirements (StructTreeRoot tagging completeness, Figure Alt text, ToUnicode CMaps, font embedding, etc.) remain the responsibility of the document author — SaveAsPdfUa attaches the file-format markers but does not alter page content or invent tags. ValidatePdfUa surfaces the absence of StructTreeRoot as
pvuaiMissingStructTreeRootso callers can route untagged documents through a separate tagging pipeline - Updated TPdf.AboutInfo string to report the current product version
Version 1.30.0
- PDF/A-1b output now satisfies the ISO 19005-1 (with Cor.1:2007) requirements for Document Information Dictionary / XMP equivalence: every Info dictionary entry PDFium writes into the base PDF is mirrored into the XMP packet, including Title (dc:title), Author (dc:creator), Subject (dc:description per Cor.1), Keywords (pdf:Keywords), Creator (xmp:CreatorTool), Producer (pdf:Producer), CreationDate (xmp:CreateDate), and ModDate (xmp:ModifyDate). xmp:MetadataDate is also emitted
- The trailer of a PDF/A document now always contains an /ID array (ISO 19005-1 6.1.3 hard requirement). When TPdf.SaveAsPdfA processes a document whose source already has a file identifier, the existing 16-byte permanent and changing IDs are reused; otherwise a deterministic 16-byte fallback ID is derived from the source bytes
- The injected XMP now embeds the pdfaid extension schema description required by ISO 19005-1 6.7.8 (replaced by Cor.1) — pdfaid is treated as an extension schema relative to XMP Specification 2004, so all conforming files must declare its property names, value types, and categories in the pdfaExtension:schemas container
- TPdfASaveOptions gained five new optional fields: Producer, CreationDate, ModDate (PDF date strings in “D:YYYYMMDDHHmmSSOHH'mm'” form), DocumentId, and InstanceId (16-byte byte strings for the trailer /ID array). TPdf.SaveAsPdfA / SaveAsPdfAToStream auto-populate the missing fields from FPDF_GetMetaText and FPDF_GetFileIdentifier, so existing callers continue to work without changes
- TPdf.ValidatePdfA / TPdf.PdfAConformance now report three additional issues: pvaiMissingTrailerId (no /ID in the trailer), pvaiMissingXmpDates (xmp:CreateDate or xmp:ModifyDate missing), and pvaiMissingExtensionSchema (pdfaid extension schema description absent)
- Non-ASCII characters in Title, Author, Subject, Keywords, Creator, and Producer are now encoded as UTF-8 in the XMP packet (XMP Specification requires UTF-8), preserving multilingual metadata round-trip through SaveAsPdfA
- Updated TPdf.AboutInfo string to report the current product version
Version 1.29.0
- Refreshed the bundled PDFium DLLs (Win32 and Win64, both standard and V8 builds) to the 2026-05-22 upstream snapshot, picking up upstream fixes to FPDFText_SetText / FPDFText_SetCharcodes crash paths and assorted internal hardening from the PDFium project
- Exposed PDFium’s new FPDF_SUBSET_NEW_FONTS save flag in FPdfPageOps.pas, allowing FPDF_SaveAsCopy callers to request automatic subsetting of embedded font files for newly added text objects. The existing FPDF_INCREMENTAL, FPDF_NO_INCREMENTAL, and FPDF_REMOVE_SECURITY constants are now defined using the upstream bit-shift form (the legacy numeric value 3 is preserved as FPDF_REMOVE_SECURITY_DEPRECATED for binary compatibility)
- Added the FPDF_FONT_BACKEND_TYPE enum (FREETYPE / FONTATIONS) and the matching m_FontLibraryType field on FPDF_LIBRARY_CONFIG in FPdfView.pas, so applications that initialize PDFium with the Skia renderer can now pick the font backend at startup
- Updated the TFPDFPage_InsertObject signature to match upstream: the C function now returns FPDF_BOOL (TRUE on success, FALSE if page_object is NULL or ownership transfer fails) instead of void. Existing PDFiumPas callers continue to compile unchanged since Delphi / FPC allow ignoring a function’s return value
- Corrected the TPdf.AboutInfo string to report the current product version (was stale at v1.27.0 since the v1.28.0 documentation-only release)
Version 1.28.0
- Substantially expanded the in-page documentation across the entire API reference: every property, method, event, and global function entry now carries a 3-paragraph Description, a Remarks list, a multi-line Delphi Example, and a richer See Also block — covering 200+ previously thin pages including all TPdf counters, metadata getters, font and character accessors, page-level properties, indexed records, document-level methods, and the full TPdfView state / display / event surface
- Fine-tuned the help layout to match the losLab visual baseline used in the HotXLS reference: matched h1/h2 sizes, consolidated the API navigation grid styles into the shared StyleSheet, and removed the per-page inline CSS overrides on Navigation.html
- Documentation now ships with a helper script (Docs\Build-Expand-Entries.ps1) that regenerates the entry-page enrichment from a single data table for repeatable maintenance
Version 1.27.0
- Added PDF/A-1b creation support: TPdf.SaveAsPdfA saves any open document as a PDF/A-1b conformant file by post-processing the base PDF with an incremental update that injects an XMP metadata stream, an sRGB ICC OutputIntent, and an updated document catalog — all without requiring extra DLL APIs. Works on any platform supported by PDFiumPas
- Added TPdf.SaveAsPdfAToStream for in-memory PDF/A output
- Added TPdf.ValidatePdfA: checks an open PDF for PDF/A compliance (XMP pdfaid markers, OutputIntent with embedded ICC profile, encryption) and returns a structured result with the detected conformance level and a set of specific issues found
- Added TPdf.PdfAConformance property: returns the conformance level of the currently open document (pac1b, pac1a, pac2b, pac3b, pacNone, or pacUnknown) without needing to call ValidatePdfA explicitly
- New types exported: TPdfAConformance, TPdfAValidationResult, TPdfAValidationIssue, TPdfASaveOptions (in new unit FPdfPdfa.pas)
- SaveAsPdfA supports a custom ICC profile via TPdfASaveOptions.IccProfileData; when left empty the built-in sRGB IEC61966-2.1 (HP/Microsoft, 3144 bytes) profile is used automatically
- Replaced the monolithic HTML reference with a restructured web help system: 302 individual API entry pages (one per property, method, event, and global function) covering TPdf and TPdfView, each with a full description, parameter table, Delphi code example, and See Also links
- Added Navigation.html: a comprehensive one-page API navigation index organised into six sections (TPdf properties/methods/events, TPdfView properties/methods/events, global functions) with a 5-column flex grid for fast scanning
- Rebuilt TPdf.html and TPdfView.html as compact component overview pages retaining the type-reference sections (Types, Constants, Global Variables) and linking out to the individual entry pages for all members
- Added full-text search powered by Search.js with incremental client-side matching across all 312 indexed pages
- Updated all navigation bars site-wide to point to Navigation.html
Version 1.26.0
- Added Demo/Lazarus/BatchExport, the LCL port of the v1.14.0 Delphi BatchExport demo. Same feature set: multi-file PDF -> JPG export with per-file overall progress, per-page current progress, DPI / quality / password inputs, and a cooperatively-cancellable batch backed by IPdfCancellationToken. The output folder is opened in the platform file manager when extraction finishes successfully
Version 1.25.0
- Added Form XObject page reuse to TPdf, enabling watermark, template overlay, and “stamp one page onto many” workflows: CreateXObjectFromPage manufactures a reusable handle from any page of another document; InsertFormObjectFromXObject inserts ONE copy of the wrapped page into the current page. Returns the inserted FPDF_PAGEOBJECT so the caller can position / scale / rotate it with FPDFPageObj_SetMatrix and the v1.9.0 TPdfMatrix helpers
- The new TPdfXObject Pascal class wraps PDFium’s FPDF_XOBJECT handle and closes it automatically in its destructor, eliminating the manual FPDF_CloseXObject ceremony
- Expanded the Delphi and Lazarus regression suites to 147 cases each, and the C++Builder suite to 123 cases, covering handle creation and page-object insertion contracts
Version 1.24.0
- Added TPdf.RenderPageProgressive — a cancellable variant of RenderPage that drives PDFium’s progressive rendering loop and polls a v1.7.0 IPdfCancellationToken between iterations, so long high-DPI renders can abort mid-page instead of blocking the caller until completion
- Returns a TPdfProgressiveStatus value: prsDone, prsCancelled, or prsFailed. Pass AToken = nil to render to completion without ever pausing (no possibility of prsCancelled)
- Uses the same zero-copy fast path introduced in v1.21.0 — PDFium renders directly into the destination TBitmap’s DIB. The same legacy fallback applies when the DIB can’t be wrapped
- Expanded the Delphi and Lazarus regression suites to 145 cases each, and the C++Builder suite to 121 cases, covering nil-token (completes), pre-cancelled token (prsCancelled), and pixel-equivalence with sync RenderPage on a live token
Version 1.23.0
- Added six new TPdfView methods that expose PDFium’s form-widget text selection and Undo/Redo to applications: GetSelectedFormText returns the currently selected text inside the focused form widget; SelectAllFormText selects every character; FormUndo / FormRedo / FormCanUndo / FormCanRedo drive the focused widget’s edit history. The underlying PDFium APIs were already bound but had no high-level entry point. All six short-circuit safely when the view is inactive or the document has no AcroForm widget focused
- Expanded the Delphi and Lazarus regression suites to 142 cases each, and the C++Builder suite to 119 cases, covering the no-form-no-focus contract for every new method
Version 1.22.0
- Added page composition wrappers to TPdf: ImportPagesByIndex takes a zero-based index array to copy specific pages from a source document; ImportNPagesToOne returns a brand-new TPdf whose pages are N-up composites of this document; MovePages reorders pages in place. The underlying PDFium APIs were already bound but had no Pascal-friendly entry point
- ImportPagesByIndex accepts an empty array to import every source page (equivalent to passing nil at the C ABI level)
- Expanded the Delphi and Lazarus regression suites to 136 cases each, and the C++Builder suite to 115 cases, covering subset import, whole-document import, page reorder, and N-up composite
Version 1.21.0
- Improved rendering performance by switching TPdf.RenderPage / TPdf.RenderTile (and the corresponding TPdfView helpers) to a zero-copy output path. PDFium now writes directly into the destination TBitmap’s DIB buffer instead of into an internal buffer that was then copied row by row, saving one width x height x 4 bytes memory copy per render. The improvement is most noticeable at high DPI (thumbnail panels, print-quality export, batch export)
- The legacy per-scanline path is kept as a safety fallback for the unlikely case where the destination DIB cannot be wrapped (extreme dimensions, unusual stride, OOM). Behavior is byte-identical between the two paths, just slower in the fallback
- Expanded the Delphi and Lazarus regression suites to 132 cases each, and the C++Builder suite to 112 cases, covering caller-bitmap pf32bit upgrade, dimensions round-trip, and a large-bitmap stride sanity test
Version 1.20.0
- Added search-result highlighting to TPdfView: HighlightSearchText(Text, MatchCase, MatchWholeWord) scans the current view page and returns the number of matches found, painting a HighlightColor mask over each match on every redraw. ClearHighlight removes the highlights; switching the view to a different page clears them automatically since matches are page-specific
- HighlightColor defaults to clYellow and is published so applications can theme the highlight to match their UI palette
- Expanded the Delphi and Lazarus regression suites to 129 cases each, and the C++Builder suite to 109 cases, covering default color, color round-trip, “real fixture word matches” against the sample.pdf string, and the “missing word returns zero matches” contract
Version 1.19.0
- Added FitMode property to TPdfView with four values: pfmNone (manual zoom), pfmActualSize (100%), pfmFitPage (whole page fits in the viewport), and pfmFitWidth (page width matches viewport width). The active fit mode is re-applied automatically on Resize and when the current page changes, so long documents with mixed page sizes stay perfectly framed
- Setting Zoom directly cancels the active fit mode (FitMode reverts to pfmNone), matching the standard PDF viewer convention where typing a zoom value drops out of Fit Page / Fit Width
- Default is pfmNone so existing applications keep their explicit-zoom behavior
- Expanded the Delphi and Lazarus regression suites to 124 cases each, and the C++Builder suite to 106 cases, covering default value, mode round-trip, fit-page producing a real zoom on a loaded document, and manual-zoom-cancels-fit-mode
Version 1.18.0
- Added PageColor property to TPdfView, decoupling the rendered PDF page background from the surrounding control’s Color. Default is clWhite, so PDF pages now render as paper-white regardless of the host application’s theme. Dark-mode viewers can now keep the scroll area dark while leaving the actual PDF page white (or any color the application picks)
- Behavior change: applications that used to set TPdfView.Color in order to recolor the PDF page should set PageColor instead. The default experience improves for the common case (white pages on themed control backgrounds) without any code change
- Expanded the Delphi and Lazarus regression suites to 120 cases each, and the C++Builder suite to 103 cases, covering default value and color round-trip
Version 1.17.0
- Added user-input lock-down toggles to TPdfView so applications embedding the viewer in kiosks, preview panes, or read-only contexts can disable navigation gestures without subclassing: AllowUserPageChange controls the new PgUp / PgDn / Ctrl+Home / Ctrl+End keyboard shortcuts; ChangePageOnMouseScrolling controls the new wheel-up / wheel-down page jumps; AllowUserTextSelection is reserved for the future mouse-drag text-selection path. All three default to True so existing applications upgrade with no behavioral change
- Mouse wheel page navigation skips Ctrl+wheel so applications can keep Ctrl+wheel reserved for zoom
- Expanded the Delphi and Lazarus regression suites to 118 cases each, and the C++Builder suite to 101 cases, covering default values and toggle round-trip
Version 1.16.2
- Expanded TPdfView regression coverage for annotation link clicks when the viewer page differs from the associated TPdf page, using a real headless mouse click path across Delphi, Lazarus, and C++Builder
- The Delphi and Lazarus suites now run 114 cases each, and C++Builder now runs 99 cases
Version 1.16.1
- Fixed TPdfView link-click handling so automatic annotation and web-link actions use the page currently displayed by the viewer, even when the associated TPdf component is parked on a different page
- Hardened TPdfThumbnailView against dangling Pdf references when the linked TPdf component is destroyed
- Added thumbnail-reference lifetime regression coverage; the Delphi and Lazarus suites now run 113 cases each, and C++Builder now runs 98 cases
- Synchronized README, test documentation, HTML Help search/index content, and generated C++ package outputs with the v1.7.0 through v1.16.0 integration updates
Version 1.16.0
- Added a new Delphi PrintDialog demo (Demo/Delphi/PrintDialog) that focuses on N-up printing (1 / 2 / 4 / 9 pages per sheet) with odd / even page filtering, grayscale rendering, and optional 1-pixel cell borders. It is a deliberate small companion to the existing PrintPDF demo, which already covers preview, recent files, zoom, and scaling
Version 1.15.0
- Added a new TPdfThumbnailView component (FPdfThumbnail unit) that renders one page thumbnail per row in a scrollable side panel with hover and selection highlighting plus click-to-go navigation. Designed to sit next to a TPdfView so end users can browse a long document by page
- The component is registered on the losLab palette tab alongside TPdf and TPdfView; key properties: Pdf, CurrentPageIndex, ThumbnailWidth, ThumbnailHeight, TextColor, HoverColor, SelectionColor, BorderColor, and the OnPageClick event
- Expanded the Delphi and Lazarus regression suites to 112 cases each, and the C++Builder suite to 97 cases, covering defaults, thumbnail-size round-trip, extreme-value clamping, color round-trip, and event handler assignment
Version 1.14.0
- Added a new Delphi BatchExport demo (Demo/Delphi/BatchExport) showing how to convert many PDF files to JPG in one pass using TPdf.LoadCustomDocument for streaming load, IPdfCancellationToken for cooperative cancellation, and per-file overall + per-page progress bars. The demo uses one TPdf instance per file (PDFium itself is not thread safe) and opens the output folder in Explorer when extraction finishes successfully
Version 1.13.0
- Added an async-rendering UI overlay to TPdfView through three new properties: AsyncRendering, LoadingText, and LoadingColor. When AsyncRendering is True the single-page paint path draws a small “Loading...” indicator over the rendered page so applications using their own worker for long renders share a consistent visual affordance
- Defaults preserve the existing behavior: AsyncRendering is False, so applications that do not opt in see no visual change
- Documentation clarifies that PDFium itself is not thread safe — actually offloading the render to a worker requires the caller to keep one TPdf per worker; the upcoming batch-export demo shows that pattern
- Expanded the Delphi and Lazarus regression suites to 106 cases each, and the C++Builder suite to 93 cases, covering default values and the three-property round-trip
Version 1.12.0
- Added click-driven link handling to TPdfView. The new LinkOptions property controls automatic behavior for the four PDF link action types: goto (page jump), URI (ShellExecute), launch (ShellExecute), and embedded GotoR (reserved). Defaults enable loAutoGoto and loAutoOpenURI; loAutoLaunch and loAutoEmbeddedGoto stay off so a stray click cannot run an arbitrary program
- Added OnAnnotationLinkClick and OnWebLinkClick events that fire before any automatic action and let applications inspect the link, mark it Handled, or redirect it (for example, to a security prompt)
- Link click detection runs only when the gesture is a click rather than a drag, using a fresh MouseDown anchor so panning gestures still flow through the existing scroll path unchanged
- Expanded the Delphi and Lazarus regression suites to 102 cases each, and the C++Builder suite to 91 cases, covering default LinkOptions, set round-trip, and event-handler assignment
Version 1.11.0
- Added visual polish to TPdfView: PageShadowSize, PageShadowColor, and PageBorderColor properties paint an optional drop shadow under the page rectangle and a one-pixel border around it. Defaults preserve the previous flat look (PageShadowSize = 0; border is drawn in the default clBlack but blends into the default white background until callers change the colors)
- Added a SmoothScroll property as an opt-in flag for future incremental scroll animation; the property round-trips today and is wired up so applications can persist the preference, while the rendering side still uses the existing immediate scroll behavior
- Expanded the Delphi and Lazarus regression suites to 98 cases each, and the C++Builder suite to 89 cases, covering default values, property round-trip, and the negative-shadow-size clamp
Version 1.10.0
- Added direct image insertion through new TPdf.AddImage and TPdfView.AddImage overloads that take either a file path or a TBitmap, in addition to the existing TPicture-based AddPicture. AddImage(FileName) recognizes any format registered with the VCL or LCL graphics units (BMP, PNG via the PngImage unit, JPG, etc.) and goes through the same pipeline as AddPicture so behavior is identical
- AddImage(TBitmap) skips the TPicture intermediary, which simplifies callers that already hold a TBitmap from rendering or batch generation work
- Expanded the Delphi and Lazarus regression suites to 92 cases each, and the C++Builder suite to 84 cases, covering bitmap insertion, page-object bounds, nil bitmap rejection, and BMP file loading
Version 1.9.0
- Added high-level transformation matrix support through the new TPdfMatrix class in the FPdfMatrix unit. TPdfMatrix wraps PDFium’s FS_MATRIX with an OO API for Translate, Scale, Rotate, HorizontalFlip, VerticalFlip, CentralFlip, Skew, and Multiply, suitable for composing transforms before handing them to FPDFPageObj_SetMatrix and similar PDFium APIs
- TPdfMatrix.Multiply correctly snapshots the six matrix elements before computing the new row values, fixing a latent issue where the alternative Pascal implementations overwrite earlier elements during the same call and produce incorrect results for any composition beyond pure translation
- Expanded the Delphi and Lazarus regression suites to 88 cases each, and the C++Builder suite to 81 cases, covering identity, reset, translate / scale / flip, post-multiplicative composition order, and the Multiply regression case
Version 1.8.0
- Added on-demand stream loading through the new TPdf.LoadCustomDocument(AStream, AOwnsStream) method and TPdfStreamAdapter helper class, backed by PDFium’s FPDF_LoadCustomDocument. PDFium now reads blocks from the supplied TStream only when needed, so very large or remote PDFs no longer require an up-front in-memory copy
- Added optional stream ownership: passing AOwnsStream = True hands the TStream’s lifetime to TPdf, which frees it when UnloadDocument runs
- Expanded the Delphi and Lazarus regression suites to 79 cases each, and the C++Builder suite to 75 cases, covering streaming load via TFileStream, owned-stream cleanup, and the externally-owned-stream survives-unload contract
Version 1.7.0
- Added cooperative async cancellation primitives in the new FPdfAsync unit, exposing IPdfCancellationToken / IPdfCancellationTokenSource and a reusable PdfNoCancellationToken singleton so long-running rendering and export workflows can support clean cancel-from-UI semantics
- Added a lightweight TPdfFuture<T> helper that runs a worker on a background thread and posts the TPdfFutureResult<T> envelope back to the main thread, distinguishing success, cancellation, and failure cases
- Expanded the Delphi and Lazarus regression suites to 76 cases each, and the C++Builder suite to 73 cases, with shared coverage of cancellation state, idempotent cancel, callback fan-out, and post-cancel registration
Version 1.6.10
- Added high-level TPdf.PrintPageRanges access to the PDF viewer preference print page range, returning one-based page ranges for application code
- Added TPdf.SetFormFieldFlags / SetFormFieldFlagsAt and matching TPdfView helpers so applications can update AcroForm field flags through the public API, including password and multi-select flag coverage
- Hardened PDFium binding ABI coverage for Windows-sized FPDF_DWORD, FPDF_FILEACCESS callbacks, and V8 embedder slot fields
Version 1.6.9
- Added low-level Skia rendering bindings for the newly exported FPDF_RenderPageSkia and FPDF_FFLDrawSkia APIs in the bundled standard and V8 PDFium DLLs
- Expanded the public binding coverage checks so standard and V8 DLL loading now verifies the Skia render entry points alongside the existing V8/XFA capability probes
Version 1.6.8
- Added TPdf.SetTextPositions and TPdfSingleArray to set per-character positions on existing text objects through the newly exported FPDFText_SetPositions API
- Promoted FPDFText_SetPositions to a required binding for the current bundled PDFium DLLs, while confirming the Skia render entry points remain unavailable because the DLLs still do not export them
- Expanded the Delphi, C++Builder, and Lazarus regression suites to 65 cases each with text-position coverage
Version 1.6.7
- Added high-level TPdf access to document JavaScript name-tree actions, returning action names and scripts through JavaScriptAction and JavaScriptActions
- Added TPdf.FileIdentifier to read permanent and changing trailer IDs as binary TBytes without the PDFium terminator byte
- Added TPdf.PageBox, GetPageBox, and SetPageBox for MediaBox, CropBox, BleedBox, TrimBox, and ArtBox on the current page
- Confirmed the current bundled PDFium DLLs leave only the Skia render entry points unavailable at runtime because those exports are not present
- Expanded the Delphi, C++Builder, and Lazarus regression suites to 64 cases each with document JavaScript, trailer ID, and page-box coverage
Version 1.6.6
- Added runtime support for the bundled V8-enabled PDFium DLL. Setting EnableV8Engine before loading now selects pdfium.v8.dll from the DLLs\Win32 or DLLs\Win64 tree and exposes V8/XFA-only bindings when the loaded DLL provides them
- Added V8FeaturesAvailable, XfaBStrHelpersAvailable, GetRecommendedV8Flags, and low-level optional bindings for FPDF_BStr_*, FPDF_GetRecommendedV8Flags, and FPDF_GetArrayBufferAllocatorSharedInstance
- Made FPDFText_SetPositions optional so PDFiumPas keeps loading with PDFium DLLs that do not export that experimental text-position setter
- Expanded the Delphi, C++Builder, and Lazarus regression suites to 61 cases each with standard-DLL and V8-DLL capability coverage
Version 1.6.5
- Added tagged PDF structure-tree inspection through TPdf.StructureElements and TPdfView.StructureElements, including element type, title, alternate text, actual text, expansion text, language, marked-content IDs, child counts, and attribute counts
- Added Windows PDFium print mode selection through TPdfPrintMode and SetPdfPrintMode, covering EMF, text-only, PostScript, pass-through, image-mask, and Type 42 print modes
- Added low-level bindings for the remaining standard-DLL PDFium public exports covering JavaScript actions, annotation form flags/font color, page-object active state, indexed insertion, content-mark float values, image ICC profile data, form-object removal, and text positions
- Expanded the Delphi, C++Builder, and Lazarus regression suites to 59 cases each with tagged PDF structure-tree, print mode, and public export binding coverage
Version 1.6.4
- Updated the Delphi, C++Builder, and Lazarus demos to automatically open generated PDFs, exported text/images, and batch output folders after successful creation
Version 1.6.3
- Expanded the aligned Delphi, C++Builder, and Lazarus regression suites to 56 cases each with TPdfView GUI coverage for fit-zoom helpers, device/page coordinate round-trips, character hit-testing, and mouse panning through hidden-window viewer controls
- The TPdfView fixtures now use an explicit viewer size and test-only subclasses that exercise protected mouse handlers while keeping the suites fully headless
Version 1.6.2
- Fixed TPdf.AddPage(0, ...) so the inserted first page becomes the active page immediately. Existing sample code keeps working, while PageNumber now reports a valid one-based page after insertion
- Synchronized the Lazarus package version and expanded the aligned Delphi, C++Builder, and Lazarus regression suites to 52 cases each
Version 1.6.1
- Fixed an incorrect minimum-version requirement in the v1.6.0 PDF version compliance validator: the SetState action was reclassified from PDF 1.5 down to PDF 1.2, matching PDF 1.2 Reference 6.9.9. PDF 1.3 / 1.4 SaveAs targets that contain SetState actions now save correctly rather than being rejected
- Added matching PDF 1.2 lexical checks per the same spec section: the Sound, Movie, and NOP actions plus the Separation color space are now blocked when the chosen target version is older than PDF 1.2
- Expanded the Delphi, C++Builder, and Lazarus regression suites to 50 cases each by adding a positive PDF 1.4 SetState acceptance test that locks in the corrected boundary
Version 1.6.0
- Hardened explicit PDF 1.0 through PDF 1.7 SaveAs targets with a full version-feature validator that covers the entire PDF 1.1 through ISO 32000-1 feature timeline. The validator now blocks saves that contain dictionary entries, filter names, annotation subtypes, action types, fonts, color spaces, or encryption parameters introduced after the chosen target version. Examples: JBIG2Decode (1.4+), MarkInfo / Tagged PDF (1.4+), OutputIntents (1.4+), ICCBased / DeviceN / BleedBox / TrimBox / ArtBox / StructTreeRoot (1.3+), Polygon / PolyLine / Caret / Screen / Watermark / Redact annotations, AES and AES-256 encryption (CFM AESV2 / AESV3), Perms / Legal / Requirements / NeedsRendering catalog entries, and version-gated actions such as JavaScript, Trans, SetState, Rendition, GoToE, GoTo3DView are all rejected when the target PDF version cannot represent them
Version 1.5.13
- Expanded the Delphi, C++Builder, and Lazarus regression suites to 49 cases each, adding direct coverage for rejection of ICCBased color spaces, Tagged PDF MarkInfo, Polygon annotations, AES (V2) encryption, and Redact annotations against PDF 1.2 / 1.3 / 1.4 / 1.5 / 1.6 targets respectively
Version 1.5.12
- Fixed SaveAs post-processing for incremental catalog rewrites. PDFiumPas now validates the latest repeated indirect object, so existing catalog /Version overrides are replaced correctly when saving to an explicit older PDF target version
- Expanded the Delphi, C++Builder, and Lazarus regression suites to 44 cases each, adding direct coverage for stale catalog /Version replacement, PDF 1.4 catalog version normalization, and rejection of transparency and portable-collection features when the selected PDF target version cannot represent them
Version 1.5.11
- Hardened versioned SaveAs output for explicit PDF 1.3, 1.4, 1.5, 1.6, and 1.7 targets. PDFiumPas now normalizes catalog version markers, keeps the default Fit Height OpenAction version-safe, and rejects newer PDF features when the selected target version cannot represent them
- Added Delphi, C++Builder, and Lazarus regression coverage that saves and reloads explicit PDF 1.3 through PDF 1.7 files, verifying the final header, the default Fit Height OpenAction, and the reported PDF version
Version 1.5.10
- Stepped from the spec’s option B to option C by adding TPdfView smoke tests in all three IDE suites (Tests.PdfView). Each suite builds a hidden parent TForm (via TForm.CreateNew on Pascal sides and
new TForm(NULL, 0)on the C++Builder side), reparents a TPdfView, sets Active := True, and then verifies the round-trip surface for PageCount, PageNumber default, Zoom, Rotation, DisplayMode, and that View.Text matches the underlying TPdf.Text. Each IDE suite now runs 39 cases
Version 1.5.9
- Stepped from the spec’s option A to option B by adding render smoke tests in all three IDE suites. Each Tests.Render suite calls TPdf.RenderPage on sample.pdf and verifies three robust signals instead of byte-for-byte checksums: the returned bitmap exactly matches the requested pixel size; different requested sizes (200x100, 64x256) produce matching bitmaps; and the rendered page is at least 95% white background with at least 50 (Lazarus: 20) non-white pixels marking the antialiased text. Each IDE suite now runs 33 cases
Version 1.5.8
- Closed out the original A(2) test plan groups by adding seven more regressions per IDE: TPdf.CreateAnnotation building an anHighlight annotation plus a SaveAs/LoadDocument round-trip, the AcroForm read path on Demo/Delphi/FormFill/cmp_fill_out_and_merge_forms.pdf (FormType is ftAcroForm, FormFieldCount > 0, FlattenAllPages drops the fields to zero), and quiet read-path coverage for Bookmarks, LinkAnnotationCount, and WebLinkCount on a document that has none of those features. Each IDE suite now runs 30 cases
Version 1.5.7
- Expanded the Delphi (DUnitX), Lazarus (FPCUnit), and C++Builder (GoogleTest) suites with seven new regressions per IDE: PdfVersion, PageRotation, TPdf.FindFirst / FindNext substring lookup, CharacterOrigin / CharacterRectangle agreement against the AddText origin, CreateAttachment registration plus a SaveAs/LoadDocument round-trip, and an accented-text AddText round-trip that verifies the v1.3.0 European TrueType embedding path keeps Latin-1 supplemental code points intact
Version 1.5.6
- Saved PDFs now get a default first-page Fit Height open action when no existing OpenAction is present, so PDF readers initially display generated documents at page-height zoom
- Added Delphi, Lazarus, and C++Builder regression coverage for the generated OpenAction and Fit Height setting
Version 1.5.5
- Added regression tests across the Delphi (DUnitX), Lazarus (FPCUnit), and C++Builder (GoogleTest) suites for the indexed character and font inspection API surface (TPdf.FontBaseName, FontFamilyName, FontWeight, FontItalicAngle, FontData, FontIsEmbedded, CharacterFontWeight, CharacterAngle). The Lazarus suite intentionally skips FontData, which currently access-violates inside FPDFFont_GetFontData under FPC
Version 1.5.4
- Added a C++Builder Attachment demo ported from the Delphi sample, covering creating PDFs, adding, listing, extracting, deleting, and saving embedded file attachments with MIME subtype display
Version 1.5.3
- Exposed the spread-page calculation that backs TPdfView two-page modes as the unit-level helper ComputeSpreadPages(DisplayMode, PageNumber, PageCount, out LeftPageNo, out RightPageNo). Behavior is unchanged; the helper makes the cover-aware rule independently testable without instantiating a viewer
- Added five regression tests across the Delphi (DUnitX), Lazarus (FPCUnit), and C++Builder (GoogleTest) suites covering empty documents, the standard two-page pairing, the cover page standing alone in dmTwoPageContinuousWithCover, post-cover pairs, and last-page / out-of-range clamping behavior
Version 1.5.2
- Added document language support through TPdf.Language, mapped to the PDF catalog /Lang entry
- Added attachment MIME subtype access with TPdf.AttachmentType
- Added anRedact to TPdfAnnotationSubtype and added page-object removal helpers for TPdf and TPdfView
- Updated viewer and attachment demos to display the new language and attachment type information when available
Version 1.5.1
- Added dmTwoPageContinuousWithCover for TPdfView so viewer layouts can show the first page alone and then continue with two-page spreads
- Updated the Delphi, C++Builder, and Lazarus MultiPageViewer demos to expose the cover-aware two-page display mode
Version 1.5.0
- Added smoke-level automated test suites for Delphi (DUnitX), Lazarus (FPCUnit), and C++Builder (GoogleTest). The three suites share a single fixture PDF in Tests\TestData and run the same seven cases each, covering document loading, page info, text extraction, metadata, save round-trip, PDF header validation, and the Compressed property
Version 1.4.3
- Enhanced the FontProperties demo to show both TPdfView and TPdf font metadata APIs, including font handles, font data size, and character metrics
- Added indexed TPdfView character and font inspection properties and updated the FontProperties demo to query text-object font metadata
Version 1.4.2
- Added indexed character and font inspection properties to TPdf for text analysis without requiring a viewer. Character-indexed properties (CharacterAngle, CharacterFontSize, CharacterFontWeight) query per-character metrics from the current page’s text stream. Page-object-indexed properties (FontAscent, FontBaseName, FontData, FontDescent, FontFamilyName, FontHandle, FontIsEmbedded, FontItalicAngle, FontWeight) query font metadata for any text object on the current page
- Non-text page objects return safe zero or empty values for all Font* properties rather than raising an error, making it straightforward to iterate every page object and inspect only the text ones
- FontBaseName reads the PostScript base font name directly rather than falling back to the font family name, giving a more accurate identifier for embedded fonts
Version 1.4.1
- Added C++Builder and Lazarus versions of the EuropeanText demo so all supported IDE families can verify accented European text generation with system TrueType fonts
- Added C++Builder and Lazarus versions of the FormFill demo, including sample form PDFs, field editing, appearance regeneration, filled saving, and flattened saving workflows
Version 1.4.0
- Added Lazarus / Free Pascal support: the new PDFiumLaz package provides the same TPdf, TPdfView, and related components under the LCL widget set, extending the library to the Lazarus IDE and the Free Pascal compiler alongside the existing Delphi and C++Builder packages
- Added Lazarus versions of the demos so Lazarus developers can explore every feature with runnable examples
- Fixed a Lazarus compilation issue where Free Pascal conditional defines were evaluated together with Delphi compiler-version checks, causing FPC builds to attempt resolving Delphi-specific unit names and fail
Version 1.3.1
- Documented the form flattening workflow in the help set: GenerateFormAppearances, FlattenPage, FlattenAllPages, and the related FLAT_* / FLATTEN_* constants are now covered in TPdf, TPdfView, the API reference, the feature matrix, and the programming examples
- Fixed the architecture table in the overview page so it lists the actual binding units shipped in the Lib folder
Version 1.3.0
- Improved European character support when creating PDFs. TPdf.AddText now loads and caches the matching system TrueType font before creating a text object, preserving accented characters from Czech, French, German, Spanish, Portuguese, Polish, and Turkish that PDFium’s built-in standard fonts cannot represent
- Applications that previously produced question marks or replacement glyphs for non-ASCII Latin text will now render correctly without any code change. Added the EuropeanText demo to illustrate the feature
Version 1.2.0
- Added AcroForm appearance refresh to TPdf: calling GenerateFormAppearances after modifying FormField[] values updates the widget appearance so filled values are visible in standard PDF readers without requiring an interactive edit session
- Added form flattening helpers to TPdf (FlattenPage / FlattenAllPages) and TPdfView (FlattenPage for the current view page). Flattening permanently embeds filled field values as ordinary page content and removes the interactive form layer, producing a static document that renders consistently across all viewers
- Added Demo\Delphi\FormFill to demonstrate the fill-and-save and fill-and-flatten workflows with a sample AcroForm PDF
Version 1.1.2
- Added save-time PDF stream compression. The new TPdf.Compressed property (enabled by default) rewrites uncompressed content streams as FlateDecode-compressed streams on save, significantly reducing file size for programmatically generated PDFs. Applications that require plain uncompressed output can set Compressed to False before calling SaveAs
Version 1.1.1
- Win64 package builds no longer include design-time registration units, preventing build-time failures when the Win64 package is deployed in a runtime-only context
- The PDFium DLL loader now searches the Win32 or Win64 application subdirectory first, using the standard pdfium.dll and pdfium.v8.dll names, and falls back to the application’s flat directory and the Windows system directory. This matches the DLL layout bundled with the component package, making installation straightforward
Version 1.1.0
- Fixed a visual clipping defect in TPdfView two-page mode: page content was bleeding across the gutter because both left and right page tiles shared a single clipping rectangle. Each tile now clips independently so content stays within its page boundary
- Improved the Delphi demo error message when the PDFium DLL cannot be found, providing a clearer prompt with the expected DLL name and location