HotPDF Notes de version

Version history for HotPDF user-visible features, fixes, compatibility updates, and documentation changes.

Version 2.137.6

  • Added THotPDF.DACopyFile for large-file workflows that only need a page count and an original byte-for-byte saved copy without building the full normal object graph.
  • Improved file-based encrypted PDF loading so password opens no longer cache the whole source PDF just to recover raw encryption dictionary values.
  • Reduced AES-256 stream decryption memory copying by decrypting from existing buffers where possible, including loaded stream memory for large encrypted image streams.
  • The HugeFileBenchmark demo now includes a direct-copy row while the default operation set still covers the full LoadFromFile + SaveLoadedDocument path.

Version 2.137.5

  • Added Direct File API object-source editing for large-file workflows: applications can open a PDF with DAOpenFileReadOnly, inspect object counts and source bodies, replace or append object bodies, update document information, and save a full rewritten copy.
  • Expanded Direct File API indexing to cover traditional xref tables and xref streams, including compressed object entries, so image-heavy PDFs and object-heavy PDFs can use the lightweight path.
  • Optimized Direct File API full rewrites by copying unchanged direct objects in source-offset order and merging contiguous ranges, greatly reducing random I/O on PDFs with hundreds of thousands of objects.
  • The HugeFileBenchmark demo now includes a direct-rewrite operation and documents HTML/CSV benchmark runs for image-only and mixed text/image huge PDFs.

Version 2.137.4

  • La démo Delphi PreflightReport a été transformée d'un console sample en outil VCL GUI interactif pour les single-file preflight workflows.
  • La GUI couvre désormais les rapports text, JSON et HTML standard, les mots de passe optionnels, les profile INI files, les presets intégrés, la single-file PDF/VT validation, l'embedded-report PDF output, la report preview, le status logging, l'automatic output naming et l'accès rapide aux fichiers générés.
  • L'ancien comportement de démarrage a été supprimé : aucun sample PDF ni report n'est créé automatiquement quand aucun command-line argument n'est fourni.

2026-05-26 Version 2.137.3

  • PDF/VT validation now recognizes XMP properties written as RDF attributes as well as element text, covering common pdfvtid:GTS_PDFVTVersion, pdfvtid:GTS_PDFVTModDate, and xmp:ModifyDate packet styles.
  • Added Delphi regression coverage that keeps attribute-style PDF/VT metadata detection separate from the remaining structural PDF/VT checks.

2026-05-26 Version 2.137.2

  • Improved embedded preflight report validation so source PDFs that legitimately end with a final line break after %%EOF keep matching their stored fingerprint.
  • Preflight profiles saved as UTF-8 with a BOM now load correctly when the first line is a section header.
  • Hardened PDF literal string escape decoding, improving password validation and unencrypted-copy output for encrypted PDFs with escaped owner or user entries.

2026-05-26 Version 2.137.1

  • Extended CFF parser safety to direct byte-array checks, restoring the reader position after malformed input and clearing stale layout state on failed checks.
  • Hardened the C++Builder wrapper-compatible CFF stream loader so nil stream input returns False and resets the wrapper state instead of dereferencing the stream.

2026-05-26 Version 2.137.0

  • Added THotPDF.ValidatePDFVT with password-aware overloads for focused PDF/VT validation. The text report checks the XMP PDF/VT claim, metadata namespace, PDF/VT modification date matching, PDF/X base marker, output intent, catalog DPartRoot structure, loadable pages, and page-level DPart coverage.
  • The standalone HotPDFPreflight CLI now accepts --pdfvt to write .pdfvt.txt validation reports for a single PDF or recursive directory scan.

2026-05-26 Version 2.136.8

  • Improved Type 1 PFB and CFF parser failure handling so malformed stream checks preserve the input position and clear stale metadata instead of leaving a previous font name visible after a failed check.
  • Added additional Type 1/CFF smoke coverage for malformed CFF and Type 1 streams, including stream-position preservation and stale-metadata cleanup after failed parser calls.

2026-05-26 Version 2.136.7

  • Hardened the Type 1 PFB and CFF parser entry points so stream-based checks preserve the caller's stream position, reject malformed data safely, and expose basic Type 1/CFF font metadata through the Delphi and C++Builder wrapper paths.
  • Expanded the Type 1/CFF smoke test with in-memory CFF data, ASCII Type 1 font data, wrapper-level PFB file loading, and wrapper-level CFF stream loading to protect both Delphi and C++Builder integration surfaces.

2026-05-26 Version 2.136.6

  • Added Delphi feature demos for CJK Unicode text output, large multi-page document generation, PFX signing, and expanded image-compression coverage with CCITT Group 3 1D and 2D output.

2026-05-26 Version 2.136.5

  • Preflight reports now continue when a loaded page entry cannot return a MediaBox. The report marks that page as unavailable instead of aborting, so large or inconsistent page trees still produce diagnostic output.
  • Optimized several byte-level preflight scanners to avoid repeated full-tail string copies and linear duplicate-object searches. The 10,000-page implementation-limit sample now completes within the 120-second stress-test budget.
  • The preflight stress runner now defaults to a 120-second per-file timeout, and the PreflightReport demo rebuilds cleanly after the profile-aware output path.

2026-05-26 Version 2.136.4

  • Added a preflight cookbook, a generated preflight API map, and a large-directory stress-test workflow for the HotPDFPreflight command-line tool. The stress runner isolates each PDF behind a per-file timeout and records JSON, Markdown, CSV, report, and log evidence.
  • Fixed a full rebuild issue in the preflight fingerprint helper by declaring the helper before CreatePreflightReport uses it, so console tools that rebuild HPDFDoc.pas from source compile cleanly.
  • Recorded a 1000-file baseline against D:\PDFdoc\PDF-Samples: 997 passed, 1 failed, 2 timed out, 111.422 seconds elapsed, 8.975 files per second.

2026-05-25 Version 2.136.3

  • The standalone HotPDFPreflight CLI tool gains an --aggregate <file> option that writes a batch summary produced by THotPDF.AggregatePreflightReports after the per-file reports finish. The aggregate lists every processed PDF with status / size / warning counts and totals.
  • Works with single files and recursive directory walks, with or without --profile / --preset. The aggregate is computed from the text body of each report so filtering by profile is reflected in the summary.
  • Example: HotPDFPreflight C:\Archive -r --preset silent-actions -f json -o C:\Archive\reports --aggregate C:\Archive\Aggregate.txt writes JSON reports for every PDF plus a single batch summary.

2026-05-25 Version 2.136.2

  • The standalone HotPDFPreflight CLI tool gains --profile <file> and --preset <name> options to filter each report through a preflight profile before writing it. Works alongside -f text|json|html, -p <password>, and -r recursive directory walks.
  • The two new options are mutually exclusive (passing both, the later one wins). The preset values match what THotPDF.GetBuiltInPreflightProfile recognises so CI pipelines can pull a canonical configuration without staging an INI file.
  • Example: HotPDFPreflight C:\Archive -r --preset silent-actions -f json -o C:\Archive\reports writes JSON reports for every PDF in the directory tree with the silent-actions preset applied.

2026-05-25 Version 2.136.1

  • The Delphi PreflightReport demo now accepts profile=<file> or preset=<name> as an additional CLI argument to filter the report through a profile before writing it. Works alongside the existing json / html / embed output format flag.
  • Examples: PreflightReport.exe Input.pdf Report.txt "" text profile=tuned.ini or preset=compact / preset=silent-actions.
  • The preset values mirror the names recognised by THotPDF.GetBuiltInPreflightProfile so the demo doubles as a profile testbed without having to author an INI file.

2026-05-25 Version 2.136.0

  • Added THotPDF.MergePreflightProfiles for layering profiles. The result is the deduplicated union of both inputs (DisableChecks and DisableWarnings are merged, DisableHints is the logical OR), useful for combining a preset such as compact with project-specific tweaks.
  • Added THotPDF.DiffPreflightProfiles for structural comparison. Returns True when two profiles are equivalent, otherwise the OnlyInA and OnlyInB out parameters list the entries exclusive to each side as newline-separated check:<name> / warn:<name> / option:hints=false tokens.
  • The two helpers complete the profile lifecycle: Load / GetBuiltIn / Save / Apply / Validate / Merge / Diff.

2026-05-25 Version 2.135.0

  • Added THotPDF.CreatePreflightReportWithProfile, a one-stop convenience wrapper that composes CreatePreflightReport, LoadPreflightProfile, ApplyPreflightProfile, and the format converters into a single call.
  • The new overload accepts a source PDF, optional password, optional profile file, and target format (pfText, pfJSON, or pfHTML) and returns the final report body. Passing an empty ProfileFile skips the profile step entirely so callers can keep a single call site regardless of whether they have a profile configured.
  • The four underlying APIs remain available so existing call chains keep working unchanged; the new wrapper is purely additive.

2026-05-25 Version 2.134.0

  • Added THotPDF.SavePreflightProfile for writing a THPDFPreflightProfile record back to an INI file. The output format matches what LoadPreflightProfile consumes, so the two functions are exact inverses for well-formed profiles.
  • Enables a 'load preset, tweak, save' workflow: pull a built-in preset with GetBuiltInPreflightProfile (v2.133.0), modify the lists or flags, then SavePreflightProfile the result for later reuse or sharing across projects.
  • Sections with no content are omitted from the output so an empty profile produces a single comment line instead of three empty section headers.

2026-05-25 Version 2.133.0

  • Added THotPDF.GetBuiltInPreflightProfile, which returns ready-to-use THPDFPreflightProfile records for common workflows so callers do not have to maintain INI files for canonical configurations.
  • Recognised names (case-insensitive): default or empty string returns an empty profile; compact disables every Hint line for shorter reports; silent-actions disables every PDF 1.7 sec 12.6.4 action warning plus EmbeddedFile and RichMedia, intended for workflows that intentionally embed multimedia or interactive actions.
  • Unknown names also return an empty profile so the function never raises on a typo; pair with ValidatePreflightProfile (v2.132.0) when the caller wants typos surfaced as errors.

2026-05-25 Version 2.132.0

  • Added THotPDF.ValidatePreflightProfile for defensive profile checking. The function walks the loaded profile's DisableChecks and DisableWarnings lists and flags any name that is not recognised by the current preflight implementation, returning the unknown names joined by ', ' in the UnknownNames out parameter.
  • Useful to detect profile files authored against a newer or older HotPDF version. Without validation a typo (OpneAction instead of OpenAction) or a renamed check would silently disable nothing.
  • The check is purely defensive; the profile itself is not modified. Callers can decide whether to abort, log a warning, or proceed with the partially-effective profile.

2026-05-25 Version 2.131.0

  • Added THotPDF.ConvertPreflightReportToVeraPDFStyle, a converter that shapes a HotPDF preflight report into a JSON document modeled on veraPDF's validation output: top-level profile, a jobs array containing itemDetails / taskResult / validationResult, plus a ruleViolations array under validationResult.details.
  • HotPDF-styled rather than wire-compatible with veraPDF; the goal is to let downstream tooling that already consumes veraPDF JSON adapt to HotPDF output with minimal field-name remapping rather than re-learning a different data layout.
  • Rule violations carry the same specification ISO clause cross-reference that the native HotPDF JSON output emits, so callers retain spec-level traceability when consuming via the veraPDF-style path.

2026-05-25 Version 2.130.0

  • Added THotPDF.EmbedPreflightReportAsXMP with two overloads (with and without an optional Password argument). The function writes a copy of the source PDF with the preflight report appended as a PDF-style comment block whose payload is XMP / RDF with the xmlns:hotpdf namespace.
  • Each report line becomes a hotpdf:<name> element. PASS / FAIL checks carry the severity as an attribute; warnings, hints, and info lines use warn, hint, and info prefixes on the element name.
  • XMP-aware tools that scan a file for xpacket markers can surface the embedded report. PDF readers continue to ignore the appended bytes because they fall outside the object graph. This is archival-friendly XMP embedding, not a spec-compliant XMP integration; the XMP payload is not referenced from the catalog /Metadata entry.

2026-05-25 Version 2.129.0

  • Added THotPDF.LoadPreflightProfile and THotPDF.ApplyPreflightProfile with a new THPDFPreflightProfile record. Profiles let callers tailor the report output without re-running the analysis, suppressing specific check / warning names or every Hint line.
  • Profile files use a simple INI-style format with [disable-checks], [disable-warnings], and [options] sections. Comments and blank lines are ignored. Empty profiles pass the report through unchanged.
  • After filtering, the trailing Summary and Warnings lines are recomputed so the suppressed entries no longer contribute to the Failed and Warnings totals. The rest of the report passes through unchanged, so JSON / HTML converters, diff helper, validate / embed / aggregate APIs continue to work on the filtered report without code changes.

2026-05-25 Version 2.128.2

  • Added a Delphi PreflightDashboard console demo that scans a directory of PDFs and writes a self-contained static HTML dashboard: one <stem>.preflight.html per file plus an index.html summary table.
  • The dashboard shows total / passed / failed counts at the top and a table of every PDF with status, size, summary, and a link to the detailed report. Failed rows are highlighted; PASS and FAIL badges are colour-coded for quick scanning.
  • Output is a static directory of files (no HTTP server required); publish the directory to a CI artifact page, serve it from any web server, or open index.html directly in a browser.

2026-05-25 Version 2.128.1

  • Added tools/validate-preflight-json.py, a Python utility that validates HotPDF preflight JSON output against the published schema (Docs/preflight-schema.json). The script reports one PASS/FAIL line per input and exits with a non-zero status when any input fails validation, so CI pipelines can gate on schema conformance.
  • Validation is strict because the schema declares additionalProperties: false on every object, so unknown fields cause a hard failure rather than silently slipping through. Required dependency is the standard jsonschema Python package.

2026-05-25 Version 2.128.0

  • Added THotPDF.AggregatePreflightReports for batch summaries. The function accepts an array of per-file preflight reports and emits a single aggregate that lists each file's pass/fail status with byte size and warning count, plus totals for passed, failed, warnings, and bytes scanned.
  • Pairs naturally with the v2.125.1 HotPDFPreflight standalone CLI: run the CLI to produce one report per PDF, then feed the report bodies into AggregatePreflightReports for a dashboard-ready batch summary.
  • Empty input arrays yield an empty result string so callers can append the aggregate to other output unconditionally without guarding against zero-file directories.

2026-05-25 Version 2.127.0

  • Added THotPDF.RepairPDFFromPreflightReport with two overloads (with and without an optional Password argument). The function applies a conservative subset of byte-level repairs to damaged PDFs: it drops trailing bytes that follow the final %%EOF marker, and appends a missing %%EOF when one is not present anywhere.
  • Returns True when at least one repair was applied; RepairsApplied is an out parameter that lists the repairs one per line, so callers can decide whether to keep the repaired file or escalate to a heavier recovery tool.
  • Object-graph repairs (rebuilding xref tables, patching stream lengths, fixing trailers) are intentionally out of scope because such fixes can make a partially-recoverable file less recoverable. The repairs in this overload are limited to operations that are unambiguously safe on well-formed and lightly-damaged PDFs alike.

2026-05-25 Version 2.126.1

  • Published a formal JSON Schema for the preflight JSON output at Docs/preflight-schema.json, conforming to JSON Schema draft 2020-12.
  • The schema documents every top-level field (input, size, pdfVersion, xrefStyle), the checks / info / hints / warnings arrays, and the summary object so consumer pipelines can validate the JSON output before parsing.
  • The help topic now points downstream consumers at the schema file for reference.

2026-05-25 Version 2.126.0

  • Added THotPDF.ComparePreflightReports for line-by-line preflight report comparison. The function emits a unified-diff-like body where shared lines use a two-space prefix, lines unique to ReportA use , and lines unique to ReportB use .
  • Pairs naturally with LoadAndValidatePreflightReport: when a roundtrip validation fails, feed the original and current reports into ComparePreflightReports to surface exactly which lines changed.
  • The diff algorithm is a small greedy walk tuned for the deterministic key/value output of CreatePreflightReport; it produces compact diffs for typical inputs without pulling in a general-purpose LCS implementation.

2026-05-25 Version 2.125.1

  • Added a standalone Delphi console tool HotPDFPreflight for batch-running the preflight report against single files or whole directories. The tool accepts -o output directory, -f text|json|html output format, -p password, -r recursive directory walk, and -v verbose progress flags.
  • Exit codes follow standard CLI conventions: 0 success, 1 usage error, 2 input not found, 3 one or more PDFs failed preflight, so the tool can be integrated into CI pipelines and shell scripts.
  • Each report is named <basename>.preflight.<ext> with the extension picked from the requested format.

2026-05-25 Version 2.125.0

  • Added THotPDF.LoadAndValidatePreflightReport with two overloads (with and without an optional Password argument). The function extracts the report that EmbedPreflightReportInPDF previously appended, re-runs the current preflight algorithm against the source bytes, and returns True when the embedded InputFingerprint still matches the freshly-generated one.
  • Out parameters OriginalReport and CurrentReport receive both reports so callers can diff them when validation fails, identifying what changed between the time the report was embedded and the validation run.
  • Pairs naturally with EmbedPreflightReportInPDF: embed once during archival, validate any time later to detect tampering or accidental modification.

2026-05-25 Version 2.124.2

  • Added two fingerprint lines to THotPDF.CreatePreflightReport for CI stability checks. InputFingerprint emits a 64-bit FNV-1a hash of the source PDF bytes as 16 lowercase hex digits, immediately after the Size: line. ReportFingerprint emits a 64-bit FNV-1a hash of the assembled report (everything above the fingerprint line) at the end of the report.
  • CI pipelines can compare fingerprints across runs to detect unintended drift in either the input file or the report content without parsing every diagnostic line.
  • Both fingerprints are non-cryptographic; FNV-1a is deliberately chosen for low overhead and inline implementation without pulling in an external hashing module.
  • JSON output places InputFingerprint in the info array and ReportFingerprint at the tail of info; both entries carry a spec field labelled "FNV-1a 64-bit (non-cryptographic)".

2026-05-25 Version 2.124.1

  • Added two conditional incremental-update revision diagnostic lines to THotPDF.CreatePreflightReport. When IncrementalUpdates > 0, the report now includes RevisionStartXRefPositions (byte offsets of each startxref keyword in the file, ordered oldest first) and RevisionXRefTargets (the xref offsets each marker points to), so callers can trace the incremental update chain without parsing the file manually.
  • Clean and single-revision PDFs remain byte-stable: the new lines are emitted only when more than one startxref marker is found.
  • ISO 32000-1 sec 7.5.6 spec references are added in the JSON output for the new fields.

2026-05-25 Version 2.124.0

  • Added THotPDF.EmbedPreflightReportInPDF with two overloads, one with an optional Password argument for supported encrypted PDFs. The method writes a copy of the source PDF with the preflight report appended after the last %%EOF as PDF-style comment lines.
  • The report travels with the document for archive workflows: text editors, grep, and audit tools can surface it long after the file leaves the originating workstation.
  • PDF readers continue to render the document as-is because the appended bytes fall outside the object graph; the cross-reference table and trailer dictionary are untouched.
  • The Delphi PreflightReport demo gains an embed CLI argument that writes the embedded variant alongside the standalone report.

2026-05-25 Version 2.123.1

  • Added a regression test that hand-crafts a PDF with duplicate object numbers, a malformed xref row, and an unbalanced stream/endstream pair, then verifies that the three Phase F root-cause diagnostic lines (DuplicateObjectList, FirstMalformedXRefOffset, StreamEndStreamDelta) trigger as expected.
  • No library behaviour change: the test fills a gap in the regression suite that previously only covered the clean and "not a PDF" cases.

2026-05-25 Version 2.123.0

  • Added HTML output format to THotPDF.CreatePreflightReport and THotPDF.SavePreflightReport. The THPDFPreflightFormat enum gains a third value pfHTML alongside pfText and pfJSON.
  • HTML output is a self-contained dashboard-style document with inline CSS, severity-coloured rows (green for PASS, red for FAIL, yellow for WARN), per-section tables for checks, hints, info, and warnings, plus a summary card. No external CSS, JavaScript, or fonts are required.
  • Each table row includes the ISO 32000-1 / ISO 19005 / ISO 15930 / ISO 14289 spec reference when available, matching the JSON output spec field added in v2.122.1.
  • HTML output is byte-safe: ampersand, less-than, greater-than, double-quote, and single-quote are escaped; UTF-8 byte sequences pass through unchanged.
  • The Delphi PreflightReport demo accepts html as the fourth CLI argument to request HTML output.

2026-05-25 Version 2.122.4

  • Added PDF/X subset detection to preflight reports. When a PDF/X claim is detected, the new Hint PDFXVersion line names the specific subset (X-1a:2001, X-1a:2003, X-3:2002, X-3:2003, X-4, X-4p, X-5g, X-5pg, X-5n, or X-5).
  • Added PDF/UA part extraction. When a PDF/UA claim is detected, the new Hint PDFUAPart line reports the value from pdfuaid:part in the XMP metadata.
  • ISO 15930 and ISO 14289 spec cross-references are added to the JSON output for the new hint entries.
  • Clean PDFs with no PDF/X or PDF/UA claim remain byte-stable: the new hints are only emitted when the underlying claim is detected.

2026-05-25 Version 2.122.3

  • Added root-cause diagnostic lines to THotPDF.CreatePreflightReport. When a damaged PDF triggers a defect count, the report now lists actionable detail.
  • DuplicateObjectList appears whenever DuplicateObjectNumbers > 0 and lists up to five repeated object numbers, so callers can pinpoint which objects collide.
  • FirstMalformedXRefOffset appears whenever XRefMalformedEntries > 0 and gives the 1-based byte offset of the first malformed cross-reference row.
  • StreamEndStreamDelta appears whenever the stream and endstream marker counts differ and gives the signed difference, indicating how many markers are missing or duplicated.
  • Clean PDFs remain byte-stable: the new diagnostic lines are only emitted when the underlying defect counters are non-zero.

2026-05-25 Version 2.122.2

  • Extended preflight action warnings to cover the full PDF 1.7 §12.6.4 action set. Added 15 advisory warnings: GoToRAction, GoToEAction, ThreadAction, URIAction, SoundAction, MovieAction, HideAction, NamedAction, SubmitFormAction, ResetFormAction, ImportDataAction, SetOCGStateAction, RenditionAction, TransAction, and GoTo3DViewAction.
  • Warnings are emitted only when the corresponding action token is detected; clean PDFs that contain no actions stay byte-stable.
  • The ISO 32000-1 spec cross-references in the JSON output now cover the new action warnings as well.

2026-05-25 Version 2.122.1

  • Extended THotPDF.CreatePreflightReport JSON output with ISO specification cross-references. Every checks, hints, and warnings entry now carries a spec field naming the ISO 32000-1, ISO 19005, ISO 15930, or ISO 14289 clause for that diagnostic.
  • The plain-text report is unchanged and remains byte-stable; the spec field appears only in pfJSON output.
  • The mapping covers every check, hint, and warning emitted by the report through v2.122.0, so JSON consumers can route findings to the matching spec clause without an external lookup table.

2026-05-25 Version 2.122.0

  • Added machine-readable JSON output to THotPDF.CreatePreflightReport and THotPDF.SavePreflightReport. New THPDFPreflightFormat enum exposes pfText (default plain-text path) and pfJSON (CI-friendly JSON document) values.
  • New format-aware overloads accept the Format parameter while keeping the legacy text overloads byte-stable. Existing applications continue to work without code changes.
  • JSON output groups entries into top-level input, size, pdfVersion, and xrefStyle fields plus checks, info, hints, warnings arrays and a summary object with failed, warnings, and result counters.
  • Built-in JSON encoder escapes ", \, control bytes, and preserves UTF-8 byte sequences without requiring an external JSON library.
  • The Delphi PreflightReport demo accepts a fourth CLI argument json to request JSON output for an input PDF.

2026-05-25 Version 2.121.36

  • Enhanced preflight reports with compliance marker hints. Reports now expose Hint PDFAClaimed, Hint PDFAPart, Hint PDFAConformance, Hint PDFXClaimed, Hint PDFUAClaimed, Hint TaggedPDF, and Hint HasTransparency lines for downstream tooling.
  • Added advisory warnings PDFAWithEncryption, PDFAWithJavaScript, and PDFA1WithTransparency that fire when a PDF/A-claimed document also carries encryption, JavaScript, or PDF/A-1-forbidden transparency markers.
  • Hint lines never increment the Failed counter, and the helpers remain advisory; they do not replace a full PDF/A, PDF/X, PDF/UA, or ISO 32000 conformance engine.

2026-05-25 Version 2.121.35

  • Enhanced preflight reports with content resource integrity diagnostics. Reports now include resource dictionary, font, embedded font program, image XObject, form XObject, ColorSpace, annotation, widget, and link counts.
  • Reports now include filter chain usage counts for FlateDecode, DCTDecode, CCITTFaxDecode, JBIG2Decode, LZWDecode, ASCIIHexDecode, ASCII85Decode, RunLengthDecode, and JPXDecode.
  • Added pass/fail check FontsHaveEmbeddedPrograms that verifies at least one /FontFile, /FontFile2, or /FontFile3 is present whenever font resources are declared.
  • Added pass/fail check AnnotationCountConsistent that verifies the sum of widget and link annotation counts does not exceed the overall annotation count.

2026-05-25 Version 2.121.34

  • Enhanced preflight reports with trailer root type diagnostics. Reports now verify that the trailer /Root indirect reference targets an object declared as /Type /Catalog.

2026-05-25 Version 2.121.33

  • Enhanced preflight reports with trailer ID diagnostics. Reports now count hex string entries in the trailer /ID array and verify that the file identifier is present as a valid two-entry pair when an ID array is supplied.

2026-05-25 Version 2.121.32

  • Enhanced preflight reports with trailer indirect-reference diagnostics. Reports now show the trailer /Root and /Info object references and verify that the referenced objects are defined in the file.

2026-05-25 Version 2.121.31

  • Enhanced preflight reports with stream length coverage diagnostics. Reports now count stream /Length entries and verify that detected streams have length entries available.

2026-05-25 Version 2.121.30

  • Enhanced preflight reports with revision marker diagnostics. Reports now count %%EOF markers and startxref sections, verify that the counts are balanced, and check that the final startxref marker appears before the final EOF marker.

2026-05-25 Version 2.121.29

  • Enhanced preflight reports with page tree consistency diagnostics. Reports now include the declared page tree /Count and pass/fail checks that compare it, and the counted page objects, with the pages loaded by HotPDF.

2026-05-25 Version 2.121.28

  • Enhanced preflight reports with xref table row diagnostics. Reports now include xref subsection, entry, free-entry, in-use-entry, and malformed-row counts, plus pass/fail checks for xref row syntax and whether xref coverage reaches the highest object number.

2026-05-25 Version 2.121.27

  • Enhanced preflight reports with bounded PDF name-pair counting and additional consistency checks. Reports now distinguish catalog, page tree, and page objects; verify that object numbers are unique; and check whether trailer /Size covers the highest object number and whether trailer /Root is present.

2026-05-25 Version 2.121.26

  • Enhanced the preflight report object and trailer diagnostics. Reports now include indirect object definition counts, highest object number, duplicate object number count, balanced stream/endstream checks, and trailer details for /Size, /Root, /Info, /ID, and /Encrypt.

2026-05-25 Version 2.121.25

  • Enhanced THotPDF.CreatePreflightReport and THotPDF.SavePreflightReport with deeper cross-reference diagnostics. Reports now verify that the final %%EOF marker is near the end of the file, parse the last startxref offset, identify whether it targets an xref table or xref stream, and include xref table, xref stream, object stream, trailer, incremental update, and linearization counts.

2026-05-25 Version 2.121.24

  • Expanded the preflight report helpers with password-aware overloads and richer diagnostics. Reports now include the PDF header version, xref style, resolved loaded page MediaBox entries, form field count, stream count, feature presence flags, JavaScript/action/media attachment warnings, warning totals, and pass/fail summaries for damaged files. The Delphi PreflightReport demo accepts an optional password argument for supported encrypted PDFs.

2026-05-25 Version 2.121.23

  • Added library-level preflight report helpers with THotPDF.CreatePreflightReport and THotPDF.SavePreflightReport. Applications can now generate a text summary for an input PDF covering the header, EOF marker, startxref, trailer or XRef stream, loadable page count, encryption state, catalog, page tree, page object, page box, information dictionary, root reference, indirect object count, and overall pass/fail status. The Delphi PreflightReport demo now uses these APIs directly.

2026-05-25 Version 2.121.22

  • Added a Delphi PreflightReport console demo that creates a sample PDF and writes a text report with lightweight structural checks, including the PDF header, EOF marker, loadable page count, encryption state, catalog, page tree, page box, and document information dictionary. The workflow keeps AutoLaunch disabled and can also report on an existing input PDF from the command line.

2026-05-25 Version 2.121.21

  • Added a Delphi SearchAndSelect console demo that builds a report, searches controlled text rows, and marks every matching term with PDF highlight annotations and /QuadPoints. The sample keeps AutoLaunch disabled so it is suitable for command-line and automated validation.

2026-05-25 Version 2.121.20

  • Added password loading for RC4-40 and RC4-128 Standard encrypted PDFs. Applications can now call LoadFromFile or LoadFromStream with a password, or call DecryptLoadedDocument after loading, then save an unencrypted loaded-document copy with SaveLoadedDocument. The new Delphi DecryptPDF console demo creates a password-protected sample and writes a decrypted copy without launching a PDF viewer.

2026-05-25 Version 2.121.19

  • Added a Delphi Printer console demo that generates a print-ready PDF preset. The sample writes print-focused /ViewerPreferences, page BleedBox and TrimBox entries, printable annotation flags, and a print-control ExtGState without launching a PDF viewer or sending a job to a physical printer.

2026-05-25 Version 2.121.18

  • Added a Delphi ConvertTo console demo that converts supported source graphics into PDF output files. The workflow creates separate PDF files from JPEG, BMP, TIFF, and EMF inputs with AutoLaunch disabled, making the sample suitable for command-line and automated checks.

2026-05-25 Version 2.121.17

  • Added loaded page operation helpers with InsertPagesFromDocument, ExtractPagesToFile, and MovePage. Applications can now insert pages from another loaded document, extract selected pages to a new PDF, and reorder loaded pages while keeping subsequent saves and extraction calls in the updated page order. The Delphi PageOperations demo shows the insert, extract, and reorder workflow without auto-launching a PDF viewer.

2026-05-25 Version 2.121.16

  • Expanded loaded AcroForm editing with RemoveFormField and FlattenFormFields. Applications can now remove loaded fields by index or name, or flatten loaded fields into static page content while removing the interactive AcroForm tree and widget annotations. The Delphi FormFields demo now shows descriptions, removal, and flattening without auto-launching a PDF viewer.

2026-05-25 Version 2.121.15

  • Added loaded bookmark title search with THotPDF.FindLoadedBookmarkPageIndex. Applications can now load an existing PDF, search the outline tree by bookmark title, and resolve matching /Dest or local GoTo action destinations to zero-based page indexes.

2026-05-24 Version 2.121.14

  • Added THPDFPage.AddTextWatermark for drawing rotated transparent text watermarks on generated or loaded pages. The new Delphi Watermark demo creates a source PDF, loads it, applies the watermark to every page, and saves the edited document.

2026-05-24 Version 2.121.13

  • Added loaded AcroForm field description inspection with GetFormFieldDescription. Applications can now read a loaded field's /TU tooltip text by index or name alongside field values, options, read-only state, and rename operations.

2026-05-24 Version 2.121.12

  • Added loaded choice-field option inspection with GetFormFieldOptionCount and GetFormFieldOptionValue. Applications can now load an existing combo box or list box field, enumerate its allowed /Opt values, and continue using the same loaded-form update and save workflow.

2026-05-24 Version 2.121.11

  • Expanded loaded AcroForm editing with IsFormFieldReadOnly and RenameFormField. Applications can now inspect a loaded field's read-only flag, rename fields by index or name, save the loaded document, and reload it with the updated field names intact.

2026-05-24 Version 2.121.10

  • Added THotPDF.GetLoadedPageBox for inspecting page boundaries after LoadFromFile. Applications can now read a loaded page's MediaBox, CropBox, BleedBox, TrimBox, and ArtBox, including the standard fallback chain for boxes that are not declared directly.

2026-05-24 Version 2.121.9

  • Added loaded AcroForm field inspection and update APIs. Applications can now load an existing form PDF, enumerate field names and types, read and update field values, toggle a field's read-only flag, and save the loaded document with SaveLoadedDocument. The new Delphi FormFields demo shows the full load, edit, and save workflow.

2026-05-24 Version 2.121.8

  • Added THotPDF.RegisterLineGraphicsState for reusable line drawing ExtGState resources. Applications can now register line width, cap style, join style, and miter limit once, then apply the named state with THPDFPage.SetGraphicsState before stroking paths.

2026-05-24 Version 2.121.7

  • Added annotation interaction helpers for writing annotation /F flags and link /H highlight modes. Link helper methods now update LastAnnotation, so flags, highlight modes, border styles, and popup helpers can be chained consistently after link creation.

2026-05-24 Version 2.121.6

  • Added reusable Form XObject authoring APIs with page-level drawing helpers, including placement, scaling, and rotation support. Added current-transformation-matrix convenience helpers and bounded text helpers for single-line alignment, wrapped text output, and row-count calculation.

2026-05-24 Version 2.121.5

  • Added reusable Type 1 PFB and CFF parser units for HotPDF, including byte-array readers, Type 1 glyph-outline command extraction, CFF dictionary, INDEX, charset, and encoding readers, plus Type 1 PFB metadata and glyph lookup helpers. Delphi and C++Builder package projects now include the new parser units.

2026-05-24 Version 2.121.4

  • PDFACompliance='2A' and PDFACompliance='3A' now enable Tagged PDF basics without implicitly emitting a PDF/UA-1 XMP claim. PDF/A Level A files keep /MarkInfo, /StructTreeRoot, document title, language, and archival metadata, while pdfuaid metadata is emitted only when PDFUACompliance is explicitly enabled.
  • The PDF/A-2/3 smoke coverage now includes PDF/A-3A and asserts that Level A archival output does not advertise PDF/UA unless requested separately. The generated PDF/A-2A and PDF/A-3A smoke files pass veraPDF validation.

2026-05-24 Version 2.121.3

  • THPDFPage.UnicodeTextOut réutilise désormais la ressource de police Type 0 produite par RegisterUnicodeTTF pour la sortie Unicode des plans supplémentaires, afin que le texte de page et les flux d'apparence AcroForm partagent le même chemin d'encodage CID interne.
  • La passe de finalisation partagée synchronise maintenant la sortie SMP au niveau de la page via FUnicodeUsedCps, /CIDToGIDMap, l'entrée /W de la police descendante et /ToUnicode, en évitant l'ancien mappage SMP local à la page.

2026-05-24 Version 2.121.2

  • THPDFPage.UnicodeTextOut prend désormais en charge les caractères Unicode du plan supplémentaire, en les acheminant via la correspondance des glyphes (cmap) de format 12 enregistrée dans la police de la page lorsque RegisterUnicodeTTF a chargé la police active. Les emojis et autres valeurs supérieures ou égales à U+10000 sont émis sous forme d'un seul glyphe CID dans le flux de texte de la page, au lieu de deux demi-glyphes de substitution.
  • La police de page enregistre les identifiants de glyphes SMP dans la table CMap `/ToUnicode`, ce qui permet de conserver l'extraction de texte et l'accessibilité, tout en conservant le chemin de police de page `/CIDToGIDMap /Identity` existant.

2026-05-24 Version 2.121.1

  • Les flux d'apparence AcroForm basés sur RegisterUnicodeTTF rendent désormais les caractères Unicode du plan supplémentaire, tels que les emoji, via un seul CID interne au lieu d'écrire une paire de substituts UTF-16 comme deux CID Identity-H. Le /CIDToGIDMap généré pointe ce CID vers le glyph réel, et /ToUnicode le remappe vers la paire de substituts UTF-16BE d'origine pour l'extraction de texte.
  • L'étape de finalisation des polices Unicode actualise /CIDToGIDMap, /W et /ToUnicode après que tous les flux d'apparence ont enregistré leurs correspondances CID internes tardives, afin que le sous-ensemble TrueType et les apparences de formulaire générées utilisent l'ensemble final des CID utilisés.

2026-05-23 Version 2.121.0

  • PDF 1.7 §12.6.4.13–15 : les actions multimédias (Rendu / Son / Vidéo) gagnent trois nouvelles méthodes auxiliaires de bouton-poussoir dans `THPDFPage` : `AddPushButtonWithRenditionAction` pour §12.6.4.13 (associe une annotation Screen à un MediaRendition + MediaClipData décrivant le clip audio/vidéo et une opération /OP de 0 à 4) ; `AddPushButtonWithSoundAction` pour §12.6.4.14, avec deux versions (chemin de fichier ou charge utile TBytes brute), un enregistrement THPDFSoundParams fourni par l'appelant (Fréquence d'échantillonnage / Canaux / Bits par échantillon / Codage) et facultatif /Volume + /Repeat + /Synchronous ; `AddPushButtonWithMovieAction` pour §12.6.4.15 (fait référence à une annotation Movie via /Annotation et sélectionne /Operation Play / Stop / Pause / Resume).
  • `AddScreenAnnotation` et `AddMovieAnnotation` renvoient désormais le dictionnaire de l'annotation créée, permettant aux appelants de l'intégrer dans l'assistant d'action correspondant. Le changement de signature de `procedure` à `function` est compatible avec l'ABI de Delphi ; les appelants existants qui les invoquent et ignorent le résultat continuent de compiler et génèrent des fichiers PDF identiques en octets.
  • Implémentation standard : chaque composant génère les entrées obligatoires spécifiées dans la norme, ainsi que les champs optionnels les plus couramment utilisés (Sound /Volume /Repeat /Synchronous ; Rendition /JS). Les paramètres de lecture multimédia, les paramètres d'écran, le sélecteur de rendu et le mixage audio sont intentionnellement omis ; les valeurs par défaut du lecteur couvrent 95 % des cas, et les composants restent minimalistes.
  • PDF/A (tous niveaux) et PDF/X (tous profils) rejettent les trois actions multimédias au point d'entrée de l'assistant, en affichant un diagnostic référencé par la norme ISO (ISO 19005-1 §6.6.1 / ISO 19005-2 §6.5.1 / ISO 19005-3 §6.5.1 / ISO 15930). Les mécanismes de contrôle d'annotation existants pour `AddScreenAnnotation` / `AddSoundAnnotation` / `AddMovieAnnotation` restent en place.
  • L'action Rendition associe le fichier de spécifications MediaClipData avec /P /TF (TEMPACCESS) pour les permissions média conformément à la section §13.2.6.1, Tableau 280 — ce qui représente le niveau de permission minimal qui permet au lecteur de transmettre les données aux codecs audio/vidéo de la plateforme.
  • Les flux d'actions audio définissent par défaut les champs optionnels aux valeurs spécifiées (Volume=1.0, Repeat=false, Synchronous=false) et les émettent uniquement lorsque l'appelant fournit des valeurs non par défaut, afin de maintenir le dictionnaire d'actions aussi compact que possible pour les cas courants.
  • Sound stream metadata (/R sample rate / /C channels / /B bits per sample / /E encoding) is caller-supplied via the new THPDFSoundParams record. The v2.16-era AddSoundAnnotation entry point still hard-codes 22050 / 16-bit / Stereo / Signed; the new Sound action path avoids that pitfall so callers can play 44.1 kHz mp3, 8 kHz µ-law telephony audio, or any other source at the correct rate.
  • Vérifié avec les nouvelles versions Win32 et Win64. Les tests `smoke_multimedia_actions` (couverture positive de tous les quatre types d'actions, ainsi que l'enchaînement des annotations "Screen" et "Movie") et `smoke_multimedia_actions_pdfa_pdfx` (8 assertions couvrant 3 actions × PDF/A + PDF/X) ont été exécutés. Le test de régression `smoke_button_actions` passe toujours après la refactorisation des procédures `AddScreenAnnotation` et `AddMovieAnnotation` en fonctions.

2026-05-23 Version 2.120.15

  • Correction : Avant, la fonction EndDoc sérialisait le graphe d'objets PDF avant que deux modules de post-traitement ne soient exécutés (le module de réduction de polices TrueType de la version 2.84.0 et le module d'ajout automatique de balises "/Tabs /S" conforme à la norme PDF/UA-1 §7.18.3 de la version 2.94.0). Par conséquent, aucun de ces changements n'était appliqué au fichier généré. Les documents qui utilisaient RegisterUnicodeTTF + AddTextField incluaient le fichier de police complet (~1 Mo pour le Latin / ~14 Mo pour le CJK) au lieu de la version réduite (~150 Ko / ~500 Ko), le préfixe de sous-ensemble "AAAAAA+" de six lettres manquait dans /BaseFont, le flux /CIDSet du descripteur de police, requis pour la conformité PDF/A, était absent (veraPDF signalait une erreur conforme à la norme ISO 19005-1 §6.3.5 / -2 -3 §6.2.11), et les fichiers PDF/UA-1 qui ne contenaient pas la clé §7.18.3 /Tabs /S sur les pages annotées déclenchaient la règle 21-001 du vérificateur Matterhorn et les échecs PAC 3 "Tabs".
  • Les deux fonctions de modification s'exécutent désormais AVANT SaveToStream / SaveToFile. Elles parcourent la liste des objets indirects et écrivent le fichier PDF. La sortie est identique à celle de la version v2.120.14 pour les documents qui n'enregistrent pas de police Unicode TTF ni n'activent PDFUACompliance ; les deux fonctions de modification étaient déjà des opérations sans effet dans ces cas, donc le réarrangement ne modifie que les documents dont la sortie de la version v2.120.14 était silencieusement corrompue.
  • Vérifié avec le test Win32 smoke_unicode_ttf_subset (la taille des octets est de 33,6 % de la police Arial stockée sur le disque, ce qui permet d'économiser 676 Ko) — /BaseFont le préfixe UYENHH+ArialMT est cohérent dans les types de police 0 / CIDFontType2 / FontDescriptor.FontName) et le test Win32 smoke_pdfua_annot_structparents (/Tabs /S est estampillé dans le dictionnaire de la page annotée, les cinq assertions de structure d'annotation et de câblage §7.18.3 sont correctes).

2026-05-23 Version 2.120.14

  • PDF/UA-1 : ajout d'une validation stricte de la structure et du rôle (ISO 14289-1 §7.7 + ISO 32000-1 §14.7.3) : avec PDFUACompliance activé, AddStructureElement rejette désormais tout rôle /S qui ne correspond ni à l'un des 41 types de structure standard définis dans le Tableau 333 de la section §14.8.4 de la norme PDF 1.7 (Document / Part / Art / Sect / Div / BlockQuote / Caption / TOC / TOCI / Index / NonStruct / Private / H / H1..H6 / P / L / LI / Lbl / LBody / Table / TR / TH / TD / THead / TBody / TFoot / Span / Quote / Note / Reference / BibEntry / Code / Link / Annot / Ruby / RB / RT / RP / Warichu / WT / WP / Figure / Formula / Form), ni à un rôle personnalisé que l'appelant a pré-enregistré via AddStructRoleMap. L'exception de diagnostic inclut la chaîne de rôle concernée, fait référence à la section §7.7 / Tableau 333 de la norme PDF/UA-1, et suggère la correction AddStructRoleMap. Un rôle vide est également rejeté avec un message spécifique. Sans cette validation, les rôles non conformes se retrouveraient silencieusement dans l'arbre de structure et provoqueraient des erreurs "type de structure inconnu" dans les outils veraPDF / PAC.
  • La nouvelle fonctionnalité ne s'active que lorsque PDFUACompliance est défini sur True ; les appels non-UA conservent le comportement précédent de la fonction freeform-role, byte par byte. Les quatre versions de AddStructureElement (la version de base avec 4 arguments AnsiString, la version v2.88.0 avec 6 arguments pour /Alt et /ActualText, la version v2.95.0 avec 7 arguments pour /ID, et la version v2.119.41 utilisant l'énumération THPDFStandardStructureType) convergent vers le même chemin, donc une seule condition est suffisante. La version utilisant l'énumération passe toujours un nom de Table 333 et passe donc toujours la vérification ; les utilisateurs préfèrent cette version pour éviter les erreurs de frappe ou les problèmes de sensibilité à la casse (par exemple, 'Para' vs 'P', 'Lbody' vs 'LBody') au moment de la compilation.
  • v2.119.41 a déjà inclus l'énumération THPDFStandardStructureType (41 noms de spécifications regroupés en 5 catégories de rôles PDF : §14.8.4.1 Grouping, §14.8.4.2 Block-level, §14.8.4.3 Inline-level, §14.8.4.4 Ruby+Warichu, §14.8.4.5 Illustration), la fonction StandardStructureTypeToName(T) pour la correspondance entre l'énumération et le nom, et la fonction IsStandardStructureType(Name) pour la validation côté appelant ; v2.120.14 intègre ces fonctionnalités dans le point d'entrée AddStructureElement afin que la vérification stricte soit automatique. Une nouvelle fonction auxiliaire privée, _IsCustomRoleInRoleMap, parcourt le tableau dynamique FStructRoleMap en utilisant CompareMem, qui est sûr pour les octets, et qui correspond correctement aux noms de rôles personnalisés non-ASCII sur les systèmes CP_ACP=65001.

2026-05-23 Version 2.120.13

  • Correction : La source de HotPDF v2.120.12 ne se compilait pas sur RAD Studio car les deux surcharge de EnableShapingFeatureForSubset se trouvaient dans la section publiée de THotPDF, ce que Delphi rejette avec l'erreur E2266 ("un seul des ensembles de méthodes surchargées peut être publié"). Dans v2.120.13, les deux surcharges sont encadrées par une paire de sections publiques localisées, de sorte que la même API publique se compile correctement sur dcc32 / dcc64 ; les propriétés et les fonctions auxiliaires environnantes restent publiées sans modification. Aucun changement de comportement au moment de l'exécution.

2026-05-23 Version 2.120.12

  • EnableShapingFeatureForSubset (complétion de la phase 8f) : THotPDF.EnableShapingFeatureForSubset (FeatureTag) / the THPDFShapingFeature surcharge, parcourt chaque recherche GSUB associée à la fonctionnalité demandée, dans la version v2.119.49. SetGSUBScript / SetGSUBLanguage définit l'état de sélection de la langue GSU, énumère chaque GID substituable potentiel pour LookupType 1 (Simple - delta sur les glyphes Coverage + tableau substituteGlyphIDs pour le format 2), LookupType 2 (Multiple - Sequence.substituteGlyphIDs[]), LookupType 3 (Alternate - AlternateSet.alternateGlyphIDs[]), LookupType 4 (Ligature - Ligature.ligatureGlyph), LookupType 5 / 6 (Contextual / Chained Contextual - effectue une récursion dans les recherches imbriquées SequenceLookupRecord avec une limite de profondeur de 8), LookupType 7 (Extension - déballe automatiquement pour obtenir le type de recherche effectif), et LookupType 8 (Reverse Chained - substituteGlyphIDs[]), puis effectue une fusion par OU des GID dans FUnicodeExtraUsedGlyphs, afin que le sous-ensembleur EndDoc de la version v2.84.0 inclue tous les glyphes que la fonctionnalité peut produire dans le sous-ensemble de police intégré. La phase 8f complète la fonctionnalité MarkUnicodeGlyphUsed au niveau du glyphe de la version v2.119.50, avec une option d'activation par fonctionnalité pour les appelants dont le pipeline de production active une fonctionnalité de manière universelle.
  • L'implémentation de l'énumération distribue chaque valeur de THPDFShapingFeature à son ensemble de balises de fonctionnalité OpenType conventionnel de 4 octets : sfArabicGSUB → init / medi / fina / isol / rlig ; sfStandardLigatures → liga ; sfContextualLigatures → clig + rlig ; sfStylisticAlternates → salt ; sfIndicShaping → nukt / akhn / rphf / rkrf / pref / half / vatu / cjct / pres / blws / abvs / psts / haln / pstf ; sfContextualAlternates → rclt + calt. L'implémentation de la chaîne accepte n'importe quelle balise de fonctionnalité OpenType de 4 octets pour un ciblage précis, au-delà des cas d'énumération intégrés. Attention au gonflement excessif : l'activation de fonctionnalités larges (par exemple, aalt Access All Alternates, certaines polices incluent chaque glyphe d'un script) peut entraîner l'inclusion d'une grande partie de l'ensemble de glyphes de la police dans le sous-ensemble, ce qui annule les efforts de réduction de la taille effectués dans la version 2.84.0 ; les appelants doivent préférer Phase 9 MarkUnicodeGlyphUsed lorsqu'ils connaissent les GID émis. Désactivé par défaut, activation explicite requise. Ferme la dernière sous-phase restante de la feuille de route de la phase 8 du moteur GSUB.
  • Les règles de sécurité correspondent à la version v2.119.50 : aucune police n'est enregistrée, aucune table GSUB, balise non de 4 octets, fonctionnalité absente du chemin (script, langue), chaîne de recherche vide — chaque condition "rien à faire" est une opération silencieuse (sans exception). Les appels répétés sont idempotents (le bitmap est fusionné par un OU). La récursion de recherche imbriquée du sous-tableau contextuel de format 1 / 2 est reportée à une version ultérieure ; le format 3 domine les polices du monde réel et est implémenté. Les appelants qui ont besoin d'une couverture contextuelle précise du format 1 / 2 peuvent revenir à MarkUnicodeGlyphUsed par glyphe.

2026-05-23 Version 2.120.11

  • ToUnicode CMap caller-side reverse mapping (Phase 8d completion): three new public methods on THotPDF let callers register additional (substitute codepoint, original Unicode source codepoint sequence) reverse mappings into the EndDoc Adobe-Identity-UCS ToUnicode CMap. The v2.119.61 / v2.119.62 / v2.119.65 release series added 35 hard-coded bfchar entries for the Arabic ligatures (LAM-ALEF / YEH-HAMZA / Allah / Bismillah) and Latin Alphabetic Presentation Forms (fi / fl / ffi / ffl / ff / ſt / st) that HotPDF's producer-side shaping pipeline emits automatically; v2.120.11 closes Phase 8d by letting callers register their own mappings for the substitute glyphs they drive via the v2.119.43-50 GSUB engine APIs (GetSingleSubstituteGlyph, GetMultipleSubstituteGlyphs, GetAlternateGlyph, ApplyLigatureSubstitution, ApplyContextualSubst, ApplyReverseChainedContextualSubst).
  • `RegisterToUnicodeReverseMapping (SubstCodepoint, SourceCodepoints) enregistre une entrée (séquence de substitution → séquence source). Les cas d'utilisation typiques sont les suivants : après une substitution multiple (1 GID → N GIDs), la séquence de substitution est émise, et la correspondance inverse est enregistrée afin que la copie/coller par le lecteur conserve le point de code original ; après une substitution de ligature (N GIDs → 1 ligature GID), la ligature est émise, et le point de code de la ligature est enregistré pour revenir à la séquence source de N éléments (par exemple, une ligature contextuelle CALT arbitraire qui revient à ses points de code constitutifs). `ClearToUnicodeReverseMappings` supprime tous les enregistrements effectués par l'appelant ; `ToUnicodeReverseMappingCount` indique le nombre d'enregistrements en attente.
  • EndDoc émet et ajoute les entrées enregistrées par l'appelant en tant que blocs bfchar supplémentaires après le bloc intégré de 35 entrées, divisés automatiquement en sous-blocs de 100 entrées par Adobe CMap et la spécification des fichiers CIDFont (Note technique n°5014) §1.4.2, en respectant la limite de l'opérateur bfchar. Les points de code BMP émettent 4 chiffres hexadécimaux ; les points de code SMP émettent une paire surrogate UTF-16BE (8 chiffres hexadécimaux) selon la spécification Adobe CMap. L'ordre d'enregistrement est conservé, de sorte que la sémantique "dernière écriture l'emporte" des lecteurs PDF permet aux appelants de remplacer de manière déterministe les 35 entrées intégrées (un appelant qui enregistre une correspondance personnalisée pour <FB01> "fi" remplace la valeur par défaut de la version 2.119.65 au niveau du lecteur). Les appelants qui n'appellent jamais RegisterToUnicodeReverseMapping conservent la carte ToUnicode identique en octets à la version de référence 2.120.10. SetFormUnicodeFontDict ('', nil) réinitialise le chemin et efface l'enregistrement de l'appelant, de sorte que l'enregistrement de la prochaine police Unicode commence proprement.

2026-05-23 Version 2.120.10

  • Le module de mise en forme de texte pour le Myanmar (phase 8f.10) enregistre le Myanmar (balise OpenType mymr) comme la dixième et dernière écriture indic dans HotPDF, couvrant à la fois le bloc de base du Myanmar (U+1000-U+109F : birman, mon, Sgaw Karen, Pwo occidental, Shan, Rumai Palaung, Pa'o) et le bloc étendu-A (U+AA60-U+AA7F). Une nouvelle fonctionnalité, ApplyMyanmarReorder, effectue une réorganisation préliminaire, et GetMyanmarCategory permet la recherche de points de code, et les deux sont réutilisables via le répartiteur ApplyIndicReorder.
  • La structure de syllabe la plus complexe du lot : Kinzi 3-CP Le préfixe (U+1004 + U+103A + U+1039) au début de la syllabe est détecté, mis de côté et émis au tout début de la sortie, conformément à R8 ; la voyelle de base E (U+1031) est déplacée au début de la syllabe, conformément à R10 ; les quatre consonnes médianes Y / R / W / H (U+103B-U+103E) sont collectées et émises dans un ordre fixe Y → R → W → H, conformément à R9, indépendamment de l'ordre source.
  • ASAT (U+103A) et VIRAMA (U+1039) sont tous deux traités comme des viramas pour la gestion des consonnes empilées. DOT BELOW (U+1037) est rendu en dessous de la base ; les autres signes diacritiques sont rendus au-dessus. ANUSVARA (Bindu) est placé au-dessus ; VISARGA est placé après. Pas de Repha.
  • Deux entrées de registre `IndicScripts` (bloc principal et bloc Extended-A) partagent les mêmes fonctions de réorganisation pour le Myanmar, de sorte que les consonnes du bloc Extended-A et les signes diacritiques Pa'o Karen sont interprétés de manière transparente par le gestionnaire.
  • **Complète le traitement par lots en 11 phases pour les écritures indiennes non-devanagari** (phases 8f.0-8f.10) : infrastructure + 10 scripts indiens enregistrés, notamment le dévanagari, le bengali, le gujarati, le tamoul, le télougou, le kannada, le malayalam, le sinhala (famille Brahmic SIA), le khmer et le myanmar (Asie du Sud-Est).
  • Conformément à Unicode 16.0 §16.3 (Myanmar) et à la spécification de mise en forme OpenType pour le Myanmar.

2026-05-23 Version 2.120.9

  • Le module de mise en forme de texte Khmer (phase 8f.9) enregistre le Khmer (balise OpenType khmr, bloc Unicode U+1780-U+17FF) en tant que neuvième script Indic dans HotPDF et comme premier script d'Asie du Sud-Est. Une nouvelle fonction ApplyKhmerReorder effectue une passe de réorganisation préliminaire, et GetKhmerCategory effectue une recherche de point de code, les deux pouvant être réutilisés via le répartiteur ApplyIndicReorder.
  • Structure syllabique indépendante (différente du modèle Brahmic R1-R5 utilisé par les phases 8f.1-8f.8) : les voyelles pré-radicales (E / AE / AI / OE / OO / AU) se déplacent au début de la syllabe ; les signes de modification (MUUSIKATOAN, TRIISAP) et les autres signes situés au-dessus de la base sont acheminés vers le tampon supérieur ; le Bindu (NIKAHIT) est rendu au-dessus ; le Visarga (REAHMUK, YUUKALEAPINTU) est rendu après.
  • Gestion des indices COENG : chaque COENG (U+17D2) + la paire de consonnes forme un groupe de consonnes empilées qui reste dans le tampon de base dans l'ordre d'origine, permettant aux fonctionnalités 'pres' / 'blws' de GSUB de la police de gérer le positionnement des indices. Les indices COENG imbriqués sont pris en charge.
  • Pas de Repha : les scripts khmers ne forment pas une unité visuelle "Repha", donc `Ra + COENG + Consonant` conserve son ordre d'origine plutôt que de pivoter pour se terminer par une syllabe.
  • Conformément à Unicode 16.0 §16.4 (khmer) et à la spécification de formation OpenType Khmer.

2026-05-23 Version 2.120.8

  • PAdES adbe-revocationInfoArchival CMS attribut signé (PAdES Phase 9) : émet l'OID privé d'Adobe 1.2.840.113583.1.1.8 contenant les valeurs de révocation CRL et OCSP directement dans la signature CMS. Adobe Acrobat privilégie cet attribut pour la vérification de la révocation de la signature, avant les recherches dans le dictionnaire DSS et les récupérations réseau OCSP/CRL, ce qui est essentiel pour les fichiers PDF validables hors ligne et pour une compatibilité optimale avec Adobe Acrobat.
  • Nouveaux champs `THPDFCMSSignOptions`:
    • AdobeCRLsDER: tableau de TBytes - chaque élément est une séquence DER de type CertificateList (RFC 5280), du même format que les flux /CRLs de DSS.
    • AdobeOCSPsDER: tableau de TBytes - chaque élément est une séquence DER de type BasicOCSPResponse (RFC 6960 §4.2.1). Notez : il ne s'agit *pas* du conteneur OCSPResponse externe ; les appelants disposant de réponses OCSP complètes doivent d'abord décompresser la chaîne d'octets responseBytes.response pour extraire la BasicOCSPResponse.
  • Activation : attribut émis lorsque l'un au moins des deux tableaux n'est pas vide. La valeur par défaut, qui est un tableau vide (les deux tableaux), maintient la stabilité au niveau des octets dans la version v2.120.7.
  • ASN.1 DER selon la spécification Adobe : RevocationInfoArchival ::= SEQUENCE { crl [0] EXPLICIT SEQUENCE OF CRL OPTIONAL, ocsp [1] EXPLICIT SEQUENCE OF BasicOCSPResponse OPTIONAL, otherRevInfo [2] EXPLICIT SEQUENCE OF OtherRevInfo OPTIONAL }. Les connexions HotPDF utilisent [0] et [1] ; [2] (otherRevInfo pour les systèmes de révocation autres que X.509) reste en dehors du champ d'application.
  • Forme du fil (les deux branches sont renseignées) : 30 A0 30 <...> A1 30 <...>
  • **Coexiste avec le dictionnaire DSS :** cet attribut est *parallèle* (et non un remplacement) au dictionnaire PAdES-B-LT DSS (introduit au niveau du catalogue avec /DSS /Certs /OCSPs /CRLs /VRI dans la version v2.110.0). Les validateurs PAdES stricts (EU DSS, mTOM) ont tendance à prendre en compte le DSS ; Adobe Acrobat prend en charge adbe-revocationInfoArchival. Pour une compatibilité maximale, remplissez les deux niveaux avec les mêmes octets CRL/OCSP via AddPAdESDSSCRL / AddPAdESDSSOCSP ainsi que AdobeCRLsDER / AdobeOCSPsDER.
  • Le wrapper `HPDFCMSBuildSignedData` à 4 arguments met les champs nouveaux à zéro afin que les anciens bundles CMS restent identiques en termes de taille.
  • Conformément à la référence Adobe Acrobat PDF + RFC 5280 (CRL) + RFC 6960 (OCSP).

2026-05-23 Version 2.120.7

  • PAdES content-time-stamp CMS signé, attribut (PAdES Phase 8) : émet id-aa-ets-contentTimestamp (OID 1.2.840.113549.1.9.16.2.20, ETSI EN 319 122-1 §5.2.8 + RFC 5126 §5.11.4) contenant un TimeStampToken conforme à la norme RFC 3161, prouvant que le contenu du document existait au moment indiqué par le TSA avant que le signataire ne le signe. Différent de signature-time-stamp (attribut non signé de la Phase 4, appliqué après la signature).
  • Nouveau champ `THPDFCMSSignOptions`. `GetContentTimeStamp: THPDFCMSTimestampCallback`. Conception miroir de `GetSignatureTimeStamp` dans la version v2.120.3 : HotPDF invoque le rappel avec le hachage SHA-256 du document (le même hachage que l'attribut `messageDigest` signé), et intègre le `TimeStampToken` DER renvoyé comme valeur de l'attribut `content-time-stamp` à l'intérieur de `SignedAttributes`.
  • Par défaut, `nil` signifie qu'aucune horodatage n'est émis. Les appelants qui le souhaitent doivent assigner une closure qui gère un TSA (Timestamping Service) RFC 3161 via HTTP. Un retour de `TBytes` vide signifie qu'il est ignoré silencieusement (dégradation contrôlée lorsque le TSA n'est pas accessible).
  • **Points de terminaison TSA gratuits** (sans abonnement requis) pour les cas d'utilisation non qualifiés : http://timestamp.digicert.com, http://timestamp.sectigo.com, http://timestamp.globalsign.com/tsa/r6advanced1, https://freetsa.org/tsr, http://timestamp.apple.com/ts01. Les scénarios qualifiés eIDAS nécessitent un QTSA commercial ; la signature pour un usage non juridique fonctionne avec les points de terminaison gratuits (avec une limite de débit, mais suffisante pour les flux de travail typiques).
  • Callback contract : invoqué une fois par opération de signature, *avant* que les SignedAttributes ne soient finalisés. Les octets TST font partie de ce qui est signé, donc la signature elle-même couvre l'empreinte temporelle des données - c'est pourquoi il s'agit d'un attribut signé (par opposition à l'empreinte temporelle de la signature, qui est non signée et se trouve dans unsignedAttrs après la signature).
  • Les wrappers `HPDFCMSBuildSignedData` à 4 arguments définissent `GetContentTimeStamp:=nil` afin que les anciens bundles CMS restent identiques en termes de bytes.
  • Responsabilité de l'appelant : les espaces réservés PAdES nécessitent le paramètre ContentsBytes de taille appropriée pour la signature, ainsi que pour le horodatage du contenu (TST) (généralement de 4 à 8 Ko). Pour les flux de travail B-T combinant le horodatage du contenu et le horodatage de la signature, il faut tenir compte des deux TST. La valeur par défaut de 16 Ko pour AddPAdESSignatureField(Profile='B-T') suffit généralement pour la plupart des combinaisons.
  • Conformément à ETSI EN 319 122-1 V1.2.1 §5.2.8 + RFC 3161 §6 + RFC 5126 §5.11.4.

2026-05-23 Version 2.120.6

  • PAdES signer-attributes-v2 signedAssertions [2] Branche (PAdES Phase 7) : Fermeture du troisième et dernier champ optionnel SignerAttributeV2. Permet au signataire d'ajouter des assertions signées identifiées par OID (assertions SAML 2.0, jetons JWT en forme compacte, attestations OAuth, jetons d'attestation spécifiques à l'organisation) à l'intérieur de la signature CMS.
  • Nouveau type d'enregistrement `THPDFSignedAssertion` : `SignedAssertionID` (OID pointillé identifiant le type d'assertion) plus `AssertionBody: TBytes` (octets ANY pré-encodés définis par le schéma de l'OID - généralement une chaîne d'octets encapsulant le XML SAML ou la forme compacte JWT). Si `AssertionBody` est vide, le champ ANY est omis, ne laissant que `signedAssertionID` (valide selon les spécifications pour les assertions de type booléen enregistrées par OID).
  • Nouveau champ `THPDFCMSSignOptions` : `SignedAssertions: tableau de THPDFSignedAssertion`. Plusieurs assertions sont prises en charge ; HotPDF encapsule la séquence dans `[2] EXPLICIT` (balise `0xA2`).
  • La condition pour déclencher l'émission de `SignerAttributeV2` est maintenant activée pour chacun des trois champs OPTIONNELS. Lorsque les trois champs sont remplis, le résultat est : SignerAttributeV2 SEQUENCE { [0] claimed..., [1] certified..., [2] signedAssertions... }, dans l'ordre spécifié.
  • Selon la norme ASN.1 de ETSI EN 319 122-1 §5.2.6 : SignedAssertion ::= SEQUENCE { signedAssertionID OBJECT IDENTIFIER, signedAssertion ANY DEFINED BY signedAssertionID OPTIONAL }. Structure pour une seule assertion avec son contenu : A2 30 30 06 .
  • Réutilise `CMSEncodeOIDFromString` (v2.120.1) pour l'encodage des OID, acceptant n'importe quel OID en notation pointée.
  • Le wrapper `HPDFCMSBuildSignedData` à 4 arguments met à zéro le nouveau champ afin que les anciens bundles CMS restent identiques en termes de taille.
  • signer-attributes-v2 收口: all three OPTIONAL fields ([0] claimedAttributes, [1] certifiedAttributesV2, [2] signedAssertions) now wired through Phases 5/6/7. Full ETSI EN 319 122-1 §5.2.6 attribute coverage from the PAdES producer side.
  • Conformément à ETSI EN 319 122-1 V1.2.1 §5.2.6 + ANNEX A.1.

2026-05-23 Version 2.120.5

  • PAdES signer-attributes-v2 certifiedAttributesV2 [1] branch (PAdES Phase 6) : émet des certificats d'attribut X.509 (RFC 5755) à l'intérieur de la séquence SignerAttributeV2, en complément ou à la place des attributs déclarés [0] de la version v2.120.4. Cela permet au signataire d'ajouter des certificats de rôle émis par une autorité d'attribut (AA) qui soutiennent cryptographiquement l'identité/capacité déclarée.
  • Nouveau champ `THPDFCMSSignOptions` : `CertifiedAttributeCertsDER: tableau de TBytes`. Chaque élément est le certificat `AttributeCertificate` (RFC 5755) encodé en DER complet que l'appelant a reçu de l'autorité de signature (AA). HotPDF les émet tels quels dans une séquence `CertifiedAttributesV2` enveloppée par `[1] EXPLICIT` (balise `0xA1`).
  • L'attribut `signer-attributes-v2` est maintenant émis lorsque `ClaimedRoles` ou `CertifiedAttributeCertsDER` ne sont pas vides. Lorsque les deux sont renseignés, une séquence `SignerAttributeV2` est créée, contenant `[0]` et `[1]` dans l'ordre correspondant aux spécifications.
  • Format ASN.1 DER pour les attributs (uniquement pour CertifiedAttributesV2) : A1 30 où chaque ACn est une séquence AttributeCertificate fournie par l'appelant, telle que définie dans la RFC 5755. Le choix entre AttributeCertificate et OtherAttributeCertificate est déterminé par l'entrée DER de l'appelant (les deux alternatives commencent par une balise SEQUENCE 0x30 ; HotPDF n'effectue pas d'introspection).
  • Le wrapper `HPDFCMSBuildSignedData` à 4 arguments met à zéro le nouveau champ, afin que les anciens bundles CMS restent identiques en termes de taille aux versions v2.119.27.
  • Les assertions signées [2] (jetons SAML / JWT / OID arbitraires) sont toujours en cours de finalisation et seront disponibles dans la prochaine phase.
  • Conformément à ETSI EN 319 122-1 V1.2.1 §5.2.6 + ANNEXE A.1 + RFC 5755.

2026-05-23 Version 2.120.4

  • PAdES signer-attributes-v2, signature CMS signée pour l'attribut (PAdES Phase 5) : émet id-aa-ets-signerAttrV2 (OID 0.4.0.19122.1.1, ETSI EN 319 122-1 §5.2.6), permettant au signataire de déclarer les rôles revendiqués (par exemple, "Directeur Financier", "Représentant Autorisé") dans le paquet CMS. Remplace la version 1 signerAttr (RFC 5126 §5.10) obsolète pour les nouvelles signatures.
  • Nouveau type d'enregistrement `THPDFClaimedRole` : `RoleOID` (identifiant de type d'attribut en notation ponctuelle, généralement un identifiant de rôle organisationnel ou `1.3.6.1.5.5.7.20.1 id-id-aa-PERMrole`) + `RoleValue` (chaîne UTF-8 contenant l'étiquette de rôle lisible par l'homme).
  • Nouveau champ `THPDFCMSSignOptions`. `ClaimedRoles: tableau de THPDFClaimedRole`. Plusieurs rôles sont pris en charge ; chacun devient un `Attribute` dans la séquence `claimedAttributes [0]`. Un tableau vide (par défaut) supprime cet attribut, ce qui maintient la stabilité au niveau des octets pour les clients qui n'ont pas activé cette fonctionnalité, comme dans la version 2.120.3.
  • ASN.1 DER selon ETSI EN 319 122-1 §5.2.6 + ANNEX A.1 (module `DEFINITIONS EXPLICIT TAGS`): `SignerAttributeV2 SEQUENCE { [0] EXPLICIT ClaimedAttributes }` où `ClaimedAttributes ::= SEQUENCE OF Attribute`. Chaque rôle est sérialisé comme `Attribute { type OID, values SET OF UTF8String }`. La balise EXPLICIT signifie que `0xA0` englobe littéralement la `SEQUENCE OF` interne (la balise interne `0x30` est conservée).
  • L'identifiant (OID) du corps est encodé manuellement : 04 00 81 95 32 01 01 (arc 0.4.0.19122.1.1; base-128 et continuation sur 19122 → 0x81 0x95 0x32). Les valeurs personnalisées futures peuvent utiliser la fonction CMSEncodeOIDFromString à partir de la version v2.120.1.
  • **Champ d'application :** uniquement La fonctionnalité `claimedAttributes [0]` est implémentée dans cette phase. `certifiedAttributesV2 [1]` (certificats d'attributs X.509 selon la RFC 5755) et `signedAssertions [2]` (jetons de type SAML / JWT) nécessitent des mécanismes supplémentaires et ne seront inclus que lorsque des demandes concrètes seront formulées.
  • L'objet `HPDFCMSBuildSignedData` enveloppant à 4 arguments est mis à zéro, ce qui permet aux anciens bundles CMS de conserver une identité de byte identique à la version v2.119.27. La longueur de `ClaimedRoles` est également ajustée.
  • Conformément à ETSI EN 319 122-1 V1.2.1 §5.2.6 + EN 319 142-1 V1.2.1, §6.3, Tableau 1, ligne signer-attributes-v2 (FACULTATIF, 0 ou 1).

2026-05-23 Version 2.120.3

  • PAdES signature-time-stamp CMS, attribut non signé (PAdES Phase 4) : émet id-aa-signatureTimeStampToken (OID 1.2.840.113549.1.9.16.2.14, RFC 3161 §6 + ETSI EN 319 122-1 §5.3) dans le [1] IMPLICIT unsignedAttrs SET. Fournit le chemin de signature-time-stamp pour le service de temps fiable PAdES-B-T (Tableau 1 : B-T doit être fourni via signature-time-stamp ou document-time-stamp).
  • Nouveau type de méthode anonyme `THPDFCMSTimestampCallback` : `reference to function(const SigValueSHA256: TBytes): TBytes`. HotPDF invoque le rappel avec le hachage SHA-256 de `SignerInfo.signatureValue` (l'empreinte du message RFC 3161 selon la section 2.4.2) et intègre le DER du `TimeStampToken` renvoyé comme valeur de l'attribut.
  • Nouveau champ `THPDFCMSSignOptions`: `GetSignatureTimeStamp`. La valeur par défaut est `nil`, ce qui signifie qu'aucun horodatage n'est utilisé. Les appelants de PAdES-B-T doivent définir une closure qui gère l'interaction HTTP/RFC 3161 avec le TSA et renvoie les octets du TST. Si les octets TBytes sont vides, l'opération est ignorée sans erreur (par exemple, si le TSA n'est pas accessible, mais la signature doit toujours être générée).
  • Les fonctionnalités de réseau/authentification/gestion des comptes TSA restent dans le code appelant ; HotPDF se contente de transmettre le résultat dans l'attribut `unsignedAttrs`. Cela s'accorde naturellement avec la taille de l'espace réservé existant `AddPAdESSignatureField(Profile='B-T', ContentsBytes >= 16384)`.
  • ASN.1 fil d'attributs : la séquence `SignerInfo` transporte désormais, de manière optionnelle, un `[1] IMPLICIT SET OF Attribute` à la fin (balise `0xA1`) contenant un attribut `signature-time-stamp` dont la valeur est le `TimeStampToken ContentInfo` fourni par l'appelant, tel quel.
  • Les ensembles d'enveloppes `HPDFCMSBuildSignedData` à 4 arguments définissent `GetSignatureTimeStamp:=nil` afin que les anciens bundles CMS restent identiques en termes de bytes.
  • Conformément à la RFC 3161 §6 + ETSI EN 319 122-1 §5.3 + EN 319 142-1 V1.2.1 §6.3 Tableau 1, note q (B-T peut utiliser soit une signature horodatée, soit un horodatage du document pour une confiance temporelle).

2026-05-23 Version 2.120.2

  • PAdES commitment-type-indication CMS Support des attributs signés (PAdES Phase 3) : émet l'attribut id-aa-ets-commitmentType (OID 1.2.840.113549.1.9.16.2.16, ETSI EN 319 122-1 §5.2.3 + RFC 5126 §5.11), qui indique le type d'engagement que le signataire effectue par le biais de la signature (par exemple, preuve d'origine / réception / livraison / expéditeur / approbation / création).
  • Nouvelle énumération `THPDFCommitmentType` : `ctNone` (par défaut, supprime l'attribut), `ctProofOfOrigin`, `ctProofOfReceipt`, `ctProofOfDelivery`, `ctProofOfSender`, `ctProofOfApproval`, `ctProofOfCreation` (six OID standard `id-cti-ets-*` provenant de RFC 5126 §5.11.1, arc `1.2.840.113549.1.9.16.6.{1..6}`), et `ctCustom` (l'appelant fournit un OID arbitraire via le nouveau champ `CommitmentTypeOID`).
  • Activation : émise chaque fois que `THPDFCMSSignOptions.CommitmentType` n'est pas `ctNone`. La valeur par défaut vide maintient la stabilité au niveau des octets dans la version 2.120.1 pour les clients qui n'ont pas choisi de l'activer.
  • **Responsabilité de l'appelant (PAdES Partie 1 §6.3 Tableau 1, note d)** : lors de l'émission de l'indication de type d'engagement, l'entrée `/Reason` dans le dictionnaire de signature doit être absente (exclusion mutuelle). HPDFCMS ne détecte pas l'état du dictionnaire de signature ; l'appelant choisit l'une ou l'autre option via `AddPAdESSignatureField(Reason='', ...)` plus `CommitmentType`, ou en laissant `CommitmentType=ctNone` et en fournissant `Reason`.
  • Structure ASN.1 DER : CommitmentTypeIndication SEQUENCE { commitmentTypeId OBJECT IDENTIFIER }. Le CommitmentTypeQualifier (RFC 5126 §5.11.2) est omis car les six OID standard id-cti-ets-* ne définissent pas de qualificateurs. Les engagements personnalisés nécessitant des qualificateurs peuvent étendre la fonctionnalité.
  • Le wrapper `HPDFCMSBuildSignedData` à 4 arguments met à zéro le nouveau champ `CommitmentType` afin que les anciens bundles CMS restent identiques en termes de taille aux versions antérieures à v2.119.27.
  • Conformément à ETSI EN 319 122-1 §5.2.3 + RFC 5126 §5.11 + ETSI EN 319 142-1 V1.2.1 §6.3, Tableau 1, note d.

2026-05-23 Version 2.120.1

  • PAdES signature-policy-identifier CMS Prise en charge de l'attribut SignedAttribute (Phase 2 de PAdES) : émet l'attribut id-aa-ets-sigPolicyId (OID 1.2.840.113549.1.9.16.2.15, ETSI EN 319 122-1 §5.2.9 + RFC 5126 §5.8) qui déclare la politique de signature selon laquelle la signature a été produite. Obligatoire pour PAdES-E-EPES (Partie 2 V1.2.1 §5.4 Tableau 2 : doit être présent) ; peut être présent dans tous les autres niveaux de PAdES.
  • Nouveaux champs de l'enregistrement `THPDFCMSSignOptions` : `SignaturePolicyOID` (chaîne OID pointée représentant le document de politique), `SignaturePolicyHash` (somme de contrôle du document de politique), `SignaturePolicyHashAlgOID` (OID de l'algorithme de somme de contrôle, par défaut SHA-256 si vide) et `SignaturePolicyURI` (qualificatif SPuri optionnel selon RFC 5126 §5.8.1, OID `1.2.840.113549.1.9.16.5.1`, pointant vers l'URL du document de politique).
  • Activation : l'attribut de stratégie est émis uniquement lorsque les deux éléments suivants sont renseignés par l'appelant : SignaturePolicyOID et SignaturePolicyHash. Les valeurs par défaut vides indiquent que l'attribut est supprimé, ce qui permet aux signataires de base de conserver une stabilité au niveau des octets avec la version v2.120.0.
  • La nouvelle fonction d'aide `CMSEncodeOIDFromString` encode les OID (Object Identifiers) en notation ponctillée arbitraire au format DER conformément à X.690 §8.19 (les deux premiers segments sont combinés comme `40*arc1 + arc2`, les segments suivants utilisent une base de 128 avec des bits de continuation). Les OID de politique sont spécifiques à chaque entreprise, donc le fabricant ne peut pas les coder en dur sous forme de littéraux octets.
  • Structure ASN.1 DER : SignaturePolicyId SEQUENCE { sigPolicyId OBJECT IDENTIFIER, sigPolicyHash OtherHashAlgAndValue [, sigPolicyQualifiers SEQUENCE OF SigPolicyQualifierInfo] }. Le qualificateur SPuri encapsule l'URL sous forme de IA5String (balise 0x16) à l'intérieur d'un SigPolicyQualifierInfo.
  • Compatibilité : les versions v2.120.0 qui n'utilisent pas les nouveaux champs de stratégie produisent une sortie identique en termes de bytes. Le wrapper `HPDFCMSBuildSignedData` à 4 arguments met les nouveaux champs à zéro, ce qui permet de conserver les anciens bundles CMS inchangés.
  • Conformément à ETSI EN 319 122-1 §5.2.9 + ETSI EN 319 142-2 V1.2.1 §5.4 Tableau 2 + RFC 5126 §5.8.

2026-05-23 Version 2.120.0

  • Conformité aux attributs CMS de base PAdES (phase 1 de PAdES) : `SignPDFWithPFX` génère désormais, par défaut, l'attribut signé **ESS signing-certificate-v2** (RFC 5035 / OID `1.2.840.113549.1.9.16.2.47`), ce qui protège l'identité du certificat de signature contre les attaques par substitution. Le tableau 1 de la section 6.3 de l'ETSI EN 319 142-1 V1.2.1 indique que cet attribut doit être fourni pour tous les niveaux de base (B-B / B-T / B-LT / B-LTA).
  • La fonctionnalité de base PAdES exclut désormais par défaut l'attribut `signing-time` du CMS. Le tableau 1 impose une cardinalité de 0 pour les profils de base (l'heure de signature déclarée est indiquée dans l'entrée `/M` du dictionnaire de signature, conformément à la note g du tableau 1). La version précédente, v2.119.27, incluait `signing-time` quel que soit le profil, ce qui est rejeté par les vérificateurs PAdES stricts (EU DSS, mode de base PAdES d'Adobe Acrobat).
  • Nouvelle API publique : l'énumération `THPDFPAdESLevel` (8 valeurs couvrant les niveaux de base B-B / B-T / B-LT / B-LTA, les niveaux étendus E-BES / E-EPES / E-LTV, et l'ancienne méthode `adbe.pkcs7`), la structure `THPDFCMSSignOptions` (niveau + heure de signature + commutateurs de signature-cert-v2 + horodatage UTC), l'aide `HPDFCMSDefaultOptions(Level)` qui renvoie les valeurs par défaut conformes à la spécification pour chaque niveau, et le constructeur CMS `HPDFCMSBuildSignedDataEx` piloté par les options.
  • Compatibilité descendante : la signature HPDFCMSBuildSignedData avec quatre arguments de la version v2.119.27 est conservée sous forme d'une couche d'abstraction et génère une sortie identique en octets (le certificat de signature v2 est absent, l'heure de signature est définie comme demandé). Les applications qui ont calculé le hachage du paquet CMS de la version v2.119.27 lors des tests continuent de fonctionner correctement.
  • Modification du comportement de la sortie PDF signée : tout appel à `THotPDF.SignPDFWithPFX` utilisant un espace réservé PAdES (avec `AddPAdESSignatureField` et le sous-filtre `ETSI.CAdES.detached`) génère désormais des signatures qui passent la validation de base PAdES stricte. Les appelants souhaitant conserver l'ensemble d'attributs hérité de la version 2.119.27 doivent utiliser directement `HPDFCMSBuildSignedDataEx` avec les options `HPDFCMSDefaultOptions(palLegacy_adbePkcs7)`.
  • Structure ASN.1 DER conformément à la RFC 5035 §3 : `SigningCertificateV2 SEQUENCE { certs SEQUENCE OF ESSCertIDv2 }` avec l'identificateur d'algorithme SHA-256 omis (règle DER par défaut de X.690 §11.5), hachage du certificat SHA-256, et `IssuerSerial` réutilisant l'extraction existante de l'émetteur et du numéro de série de X.509 à partir de `CMSExtractIssuerAndSerial`.
  • Conformément à ETSI EN 319 142-1 V1.2.1 §6.3 Tableau 1 et RFC 5035 §3.

2026-05-23 Version 2.119.77

  • Un module de formation pour l'écriture Sinhala a été ajouté (Phase 8f.8). Le Sinhala ('sinh', U+0D80-U+0DFF) devient la 8ème écriture indic enregistrée. De nouvelles méthodes `ApplySinhalaReorder` et `GetSinhalaCategory` ont été ajoutées à THotPDF.
  • Fonctionnalités Sinhala : inclut Repha (Ra=U+0DBB + Halant=U+0DCA AL-LAKUNA) ; trois matras pré-de base (E=U+0DD9, EE=U+0DDA, AI=U+0DDB) – unique en ayant trois matras pré-de base ; 3 matras divisées (U+0DDC O, U+0DDD OO, U+0DDE AU) avec une décomposition Unicode canonique ; U+0DDD OO est une séquence de 3 parties (E + AA + AL-LAKUNA).
  • Le répartiteur `ApplyIndicReorder` prend désormais en charge le sinhala de manière transparente (le registre IndicScripts est maintenant un tableau d'index 0 à 7).
  • 21 nouveaux tests DUnitX. Au total, 187 tests sur 187 sont réussis sur Win32 et Win64.
  • Conformément à Unicode 16.0 §12.11 (Sinhala) et aux spécifications de formation OpenType pour le Sinhala.

2026-05-23 Version 2.119.76

  • Un module de formatage pour le Malayalam a été ajouté (Phase 8f.7). Le Malayalam ('mlym', U+0D00-U+0D7F) devient la 7ème écriture indic enregistrée. De nouvelles méthodes `ApplyMalayalamReorder` et `GetMalayalamCategory` pour THotPDF ont été ajoutées.
  • Fonctionnalités Malayalam : inclut Repha (Ra=U+0D30 + Halant=U+0D4D CHANDRAKKALA) ; I-matra (U+0D3F) est une base POST comme le tamoul (unique par rapport aux bases préfixes Devanagari/Bengali/Gujarati) ; bases préfixes E/EE/AI ; 3 matras divisées (U+0D4A O / U+0D4B OO / U+0D4C AU) avec une décomposition canonique préfixe+suffixe ; lettres chillu (U+0D54-U+0D56, U+0D7A-U+0D7F) et DOT REPH (U+0D4E) classées comme consonnes.
  • Le répartiteur `ApplyIndicReorder` prend désormais en charge le Malayalam de manière transparente (le registre IndicScripts est maintenant un tableau de taille 0 à 6).
  • 21 nouveaux tests DUnitX, couvrant notamment la catégorie chillu/DOT-REPH. Au total, 166 tests sur 166 sont passés sur Win32 et Win64.
  • Conformément à Unicode 16.0 §12.10 (malayalam) et aux spécifications de mise en forme OpenType pour le malayalam.

2026-05-23 Version 2.119.75

  • Un module de formatage pour la langue Kannada a été ajouté (feuille de route du moteur GSUB, phase 8f.6). Kannada ('knda', U+0C80-U+0CFF) devient la sixième écriture indic enregistrée. De nouvelles méthodes publiques, ApplyKannadaReorder et GetKannadaCategory, ont été ajoutées à THotPDF.
  • Le kannada possède des signes Repha (Ra=U+0CB0 + Halant=U+0CCD) similaires au dévanagari, au bengali, au gujarati et au télougou. Comme le télougou, le kannada n'a pas de voyelles préfixes ; chaque voyelle du kannada est située au-dessus, en dessous ou après la consonne de base, ou est divisée.
  • 5. Les signes diacritiques ont été divisés en utilisant la décomposition canonique Unicode 16.0 : U+0CC0 II → U+0CBF (supérieur) + U+0CD5 (postérieur) ; U+0CC7 EE → U+0CC6 (supérieur) + U+0CD5 (postérieur) ; U+0CC8 AI → U+0CC6 + U+0CD6 (les deux supérieurs) ; U+0CCA O → U+0CC6 (supérieur) + U+0CC2 (postérieur) ; U+0CCB OO est divisé en trois parties : U+0CC6 (supérieur) + U+0CC2 (postérieur) + U+0CD5 (postérieur) — la première division en trois parties est gérée par la famille de formateurs Phase 8f.
  • Matras situés au-dessus de la ligne de base (R3) : I (U+0CBF), E (U+0CC6), AU (U+0CCC), signe de longueur AI (U+0CD6). Matras situés en dessous de la ligne de base (R4) : R/RR vocaliques (U+0CC3-U+0CC4), matras L/LL vocaliques (U+0CE2-U+0CE3). Matras situés après la ligne de base (R5) : AA (U+0CBE), U/UU (U+0CC1-U+0CC2), signe de longueur post-base (U+0CD5).
  • Le répartiteur `ApplyIndicReorder` sélectionne automatiquement le Kannada via le registre (maintenant un tableau de taille 0 à 5).
  • Tests : 21 nouveaux cas de tests DUnitX, incluant les 5 cas de split-matra, ainsi qu'une vérification dédiée en trois parties pour les glyphes OO. Au total, 145 tests sur 145 sont réussis sur Win32 et Win64.
  • Conformément à Unicode 16.0 §12.9 (Kannada) et aux spécifications de mise en forme Kannada pour OpenType.

2026-05-23 Version 2.119.74

  • Un module de formatage pour le télougou a été ajouté (feuille de route du moteur GSUB, phase 8f.5). Le télougou ('telu', U+0C00-U+0C7F) devient la cinquième écriture indic enregistrée. De nouvelles méthodes publiques, ApplyTeluguReorder et GetTeluguCategory, ont été ajoutées à THotPDF.
  • Le télougou utilise des signes diacritiques appelés Repha (Ra=U+0C30 + Halant=U+0C4D), comme le dévanagari, le bengali et le gujarati. Contrairement à tous les scripts indiens précédents, il n'y a PAS de signes diacritiques pré-de base ; chaque signe diacritique télougou est soit au-dessus de la base, soit en dessous de la base, soit divisé.
  • Les signes diacritiques (R3) situés au-dessus de la base : AA/I/II/E/EE/O/OO/AU, plus le signe de longueur. U+0C55. Les signes diacritiques (R4) situés en dessous de la base : U/UU/R vocalique/RR (U+0C41-U+0C44), marque de longueur AI (U+0C56), signes diacritiques pour L/LL vocaliques (U+0C62-U+0C63).
  • 1. La voyelle "AI" (U+0C48) est décomposée en U+0C46 (E au-dessus de la base) + U+0C56 (marque de longueur "AI" en dessous de la base) lors du réarrangement.
  • Le dispatcher `ApplyIndicReorder` sélectionne automatiquement le télougou via le registre (maintenant un tableau de taille 0 à 4).
  • Tests : 17 nouveaux cas de tests DUnitX. Au total, 124 tests sur 124 sont réussis sur Win32 et Win64.
  • Conforme à la norme Unicode 16.0 §12.8 (telougou) et aux spécifications de mise en forme OpenType pour le telougou.

2026-05-23 Version 2.119.73

  • Un module de formation de texte en tamoul a été ajouté (feuille de route du moteur GSUB, phase 8f.4). Le tamoul ('taml', U+0B80-U+0BFF) devient la quatrième écriture indic enregistrée. De nouvelles méthodes publiques, ApplyTamilReorder et GetTamilCategory, ont été ajoutées à THotPDF.
  • Les différences du tamoul par rapport aux autres écritures brahmiques : PAS de Repha (le tamoul ne forme traditionnellement pas de Repha visuel) ; I-matra (U+0BBF) est placée APRÈS la lettre de base, ce qui est unique parmi les écritures brahmiques ; II (U+0BC0) est placée AU-DESSUS de la lettre de base ; E/EE/AI (U+0BC6-U+0BC8) sont placées AVANT la lettre de base ; 3 matras divisées (U+0BCA O = U+0BC6+U+0BBE, U+0BCB OO = U+0BC7+U+0BBE, U+0BCC AU = U+0BC6+U+0BD7).
  • Halant est nommé PULLI en tamoul à la position U+0BCD. La fonction `ApplyIndicReorder` est utilisée, et le système sélectionne automatiquement le tamoul via le registre (maintenant un tableau de taille 0 à 3).
  • Tests : 20 nouveaux cas de tests DUnitX. Au total, 107 tests sur 107 sont réussis sur Win32 + Win64.
  • Conformément à Unicode 16.0 §12.7 (tamoul) et aux spécifications de formation de caractères OpenType pour le tamoul.

2026-05-23 Version 2.119.72

  • Un module de formation pour la langue gujarati a été ajouté (feuille de route du moteur GSUB, phase 8f.3). Le gujarati ('gujr', U+0A80-U+0AFF) devient le troisième script indic enregistré, après le dévanagari et le bengali. De nouvelles méthodes publiques, ApplyGujaratiReorder et GetGujaratiCategory, ont été ajoutées à THotPDF.
  • Réorganisation des règles : R1 Repha (Ra=U+0AB0 + Halant=U+0ACD), R2 pré-base (U+0ABF I), R3 au-dessus de la base (U+0AC5 CANDRA E, U+0AC7 E, U+0AC8 AI — notez que au-dessus de la base en Gujarati est comme en Devanagari, et non comme en bengali, qui est pré-base), R4 en dessous de la base (U+0AC1-U+0AC4, U+0AE2-U+0AE3), R5 après la base (U+0ABE AA, U+0AC0 II, U+0AC9 CANDRA O, U+0ACB-U+0ACC O/AU). Pas de signes diacritiques divisés.
  • Le gestionnaire `ApplyIndicReorder` sélectionne automatiquement le gujarati via le registre `IndicScripts` (maintenant un tableau [0..2]). L'intégration de `BuildUnicode*FieldContent` avec `sfIndicShaping` permet de gérer le gujarati sans modifications d'intégration.
  • Tests : 18 nouveaux cas de tests DUnitX, y compris une couverture R3 au-dessus de la base, afin de distinguer la gestion des caractères E/AI du gujarati de celle du bengali. Au total, 87 tests sur 87 passent sur Win32 et Win64.
  • Conformément à Unicode 16.0 §12.6 (Gujarati) et aux spécifications de formation OpenType pour le Gujarati.

2026-05-23 Version 2.119.71

  • Un module de formatage bengali a été ajouté (feuille de route du moteur GSUB, phase 8f.2). Le bengali ('beng', U+0980-U+09FF) devient le deuxième script indic enregistré après le dévanagari. De nouvelles méthodes publiques, ApplyBengaliReorder et GetBengaliCategory, ont été ajoutées à THotPDF, suivant le modèle de l'API dévanagari de la phase 8e.
  • Règles de réorganisation bengali : R1 Repha (Ra=U+09B0 + Halant=U+09CD), R2 matras de base (I=U+09BF, E=U+09C7, AI=U+09C8 — note que E/AI sont des éléments de base dans le bengali, contrairement à Devanagari qui sont au-dessus de la base), R4 en dessous de la base (U+09C1-U+09C4, U+09E2-U+09E3), R5 après la base (U+09BE, U+09C0, U+09D7). Il n'y a pas de matras au-dessus de la base dans le bloc principal du bengali.
  • Décomposition des signes diacritiques : `U+09CB` Oo et `U+09CC` AU sont décomposés en leurs composants visuels pendant le réarrangement (U+09C7 + U+09BE / U+09C7 + U+09D7) afin que le pipeline GSUB les voie dans des positions canoniques préfixe+suffixe.
  • Le dispatcher `ApplyIndicReorder` redirige de manière transparente les caractères bengalis vers l'entrée bengalie ; les fonctions utilitaires `BuildUnicode*FieldContent` avec `sfIndicShaping` activé couvrent désormais le bengali, ainsi que le dévanagari, sans modification de l'intégration.
  • Tests : 18 nouveaux cas de tests DUnitX couvrant les fonctionnalités Bengali R1/R2/R4/R5, la décomposition, la préservation des caractères conjunct, la transmission inter-scripts, l'idempotence et l'équivalence des dispatchers. Au total, 69 tests sur 69 réussissent sur Win32 + Win64.
  • Conformément à Unicode 16.0 §12.2 (Bengali) et aux spécifications de formation OpenType pour le bengali.

2026-05-23 Version 2.119.70

  • Mise à jour complète du moteur de formation de Devanagari (feuille de route du moteur GSUB, phase 8f.1) : `ApplyDevanagariReorder` applique désormais la totalité des 5 règles de réorganisation (R1 Repha + R2 pré-base + R3 au-dessus de la base + R4 en dessous de la base + R5 post-base) au lieu du sous-ensemble R1 + R2 uniquement de la version v2.119.55. L'ordre des clusters de sortie est le suivant : `[pré-matras] + [base + halant + nukta + bindu/visarga/ modificateur] + [matras supérieurs] + [matras inférieurs] + [post-matras] + [Repha]`.
  • Conservation des ligatures : les groupes de consonnes-halant-consonnes restent regroupés dans le bloc de base ; le réarrangement ne modifie que les matras et les Repha. Opération en une seule passe et idempotente.
  • Modifications de comportement par rapport à la version v2.119.69 : pour les syllabes contenant des signes diacritiques supérieurs/inférieurs/postérieurs à la base (ou des groupes de signes diacritiques multiples), le flux d'octets PDF reflète désormais la disposition de réorganisation canonique. Le rendu visuel après GSUB/GPOS reste inchangé. Les entrées contenant uniquement les formes R1 Repha ou les signes diacritiques pré-base I-matra (la version v2.119.55) produisent une sortie identique en termes de flux d'octets.
  • Tests : 8 nouveaux cas de tests DUnitX couvrant individuellement les règles R3, R4 et R5, l'ordre des signes diacritiques multiples, la préservation des caractères conjuncts sous les signes diacritiques, le mélange de Repha avec des signes diacritiques supérieurs et inférieurs, et l'idempotence des signes diacritiques multiples. Au total, 51 tests sur 51 sont réussis sur Win32 et Win64.
  • Conformément à Unicode 16.0 §12.1 (Devanagari) et aux spécifications de formation Devanagari OpenType.

2026-05-23 Version 2.119.69

  • Infrastructure de formation des écritures indiennes (feuille de route du moteur GSUB, phase 8f.0) : refactorisation de la passe de pré-réordonnancement Devanagari v2.119.55 / v2.119.67 en un framework de dispatch indépendant du système d'écriture. De nouveaux types `TIndicScriptInfo` / `TIndicCategoryFunc` / `TIndicFindSyllableFunc` / `TIndicReorderFunc` et un nouveau registre `IndicScripts` permettent aux prochaines écritures indiennes de s'intégrer via des pointeurs de fonction.
  • Nouvelle méthode publique `ApplyIndicReorder(Wide)` qui envoie chaque point de code de `Wide` à son script enregistré correspondant et applique les callbacks de syllabe et de réorganisation de ce script. Le contenu non-Indic est transmis tel quel, byte par byte.
  • Les trois fonctions utilitaires `BuildUnicode*FieldContent` invoquent désormais `ApplyIndicReorder` (au lieu de la fonction wrapper spécifique à Devanagari) lorsque `sfIndicShaping` est présent dans `FShapingFeatures`. La version 8f.0 inclut uniquement le support pour Devanagari ; les versions ultérieures, de 8f.2 à 8f.10, ajoutent le bengali, le gujarati, le tamoul, le télougou, le kannada, le malayalam, le cinghalais, le khmer et le birman sans modifier ce point d'intégration.
  • La fonction `ApplyDevanagariReorder` existante est conservée en tant que wrapper spécifique à Devanagari pour assurer la compatibilité avec les versions antérieures v2.119.55. La sortie reste inchangée par rapport à la version v2.119.67.
  • Conformément à Unicode 16.0 §12 (scripts d'Asie du Sud) et ISO 32000-1 §9.10.

2026-05-22 Version 2.119.68

  • Phase 8c.6 — Émission au niveau des GID côté producteur via une correspondance de points de code synthétiques de la zone d'utilisation privée : deux nouvelles méthodes publiques dans THotPDF permettent aux appelants d'émettre des GID de substitution qui n'ont pas de point de code Unicode naturel en allouant des points de code PUA (U+E000-U+F8FF) à la demande. `AssignSyntheticCodepointForGID (GID; out SyntheticCP): Boolean` alloue l'emplacement PUA disponible suivant, reflète l'affectation dans `FUnicodeCpToGid + FAcroFormUnicodeAdvances +` un nouveau tableau de recherche `FUnicodeSyntheticCpForGID` par GID, de sorte que le pipeline de codage hexadécimal existant côté producteur émet le point de code synthétique sous forme de jeton à 4 chiffres hexadécimaux que le lecteur consommateur résout via `/CIDToGIDMap` pour obtenir le glyphe de substitution. `GetSyntheticCodepointForGID (GID): Word` interroge les affectations existantes (renvoie 0 lorsqu'aucun point de code synthétique n'est affecté). Les deux méthodes sont idempotentes : les appels répétés avec le même GID renvoient le même point de code synthétique.
  • Cela permet la génération côté producteur de substitutions GSUB spécifiques aux polices qui ne possèdent pas de codepoints de forme de présentation Unicode : formes de clusters Devanagari (les sorties 'akhn' / 'rphf' / 'pres' / 'blws' / 'psts' / 'haln' se trouvent généralement dans les GID internes de la police), alternatives stylistiques ('salt' / 'ss01-20' sans codepoints), ligatures discrétionnaires ('dlig' / 'hlig' glyphes spécifiques à la police) et substitutions de séquences de variations idéographiques CJK. Combiné avec les API du moteur GSUB v2.119.43-50 et la fonction de sous-ensemble MarkUnicodeGlyphUsed v2.119.50, les utilisateurs peuvent désormais créer des pipelines de formation complets côté producteur qui génèrent des GID de substitution arbitraires via le pipeline hexadécimal basé sur les codepoints existant.
  • La durée de vie de l'état : les correspondances synthétiques persistent jusqu'à ce que RegisterUnicodeTTF soit appelé à nouveau ou que BeginDoc soit déclenché (les deux réinitialisent l'état de chaque police, y compris la table synthétique). La plage PUA U+E000-U+F8FF fournit 6400 emplacements, ce qui est suffisant pour l'ensemble de substitution GSUB de n'importe quelle police pratique. La correspondance inverse de la carte CMap ToUnicode est de la responsabilité de l'appelant ; les points de code PUA synthétiques n'ont pas de points de code source à mapper inversement ; les appelants qui se soucient de l'extraction de texte doivent encapsuler l'émission de texte dans le contenu PDF marqué avec la propriété /ActualText, en spécifiant les points de code source originaux. Les PDF dont les appelants n'invoquent pas AssignSyntheticCodepointForGID sont identiques à la sortie de la version v2.119.67 (les nouvelles méthodes sont des fonctions d'aide de requête sans état / d'allocation explicite ; aucun effet secondaire automatique). Ce commit complète la matrice de fonctionnalités de la phase 8 de la feuille de route du moteur GSUB.

2026-05-22 Version 2.119.67

  • Réorganisation automatique de Devanagari (feuille de route du moteur GSUB, phase 8e) : les trois fonctions utilitaires BuildUnicode*FieldContent invoquent désormais automatiquement la méthode ApplyDevanagariReorder v2.119.55 lorsque sfIndicShaping est inclus dans FShapingFeatures. Cette étape de pré-traitement parcourt l'entrée de gauche à droite, appliquant les deux réorganisations spécifiques à Devanagari (déplacement de Repha pour le Ra-Halant initial de la syllabe, et déplacement de la voyelle I (U+093F) vers le début de son groupe de syllabes) afin que le flux de codepoints généré corresponde à l'ordre de lecture visuel. Le moteur GSUB du lecteur consomme ensuite la chaîne de formatage Indic ('nukt' / 'akhn' / 'rphf' / 'rkrf' / 'pref' / 'half' / 'vatu' / 'cjct' / 'pres' / 'blws' / 'abvs' / 'psts' / 'haln') sur les codepoints réorganisés pour produire les glyphes de cluster finaux.
  • La version 8e concerne uniquement le réordonnement côté producteur. L'application des chaînes GSUB côté producteur (où le producteur effectue la formation des clusters au moment de la création du fichier PDF, plutôt que de s'appuyer sur le lecteur) est reportée à la phase 8c.6, car la plupart des substitutions GSUB pour Devanagari utilisent des GID spécifiques à la police sans point de code de forme de présentation Unicode. Contrairement à l'arabe/latin, où les blocs Forms-A/Forms-B fournissent des substitutions accessibles par point de code, Devanagari ne possède pas de plage de formes de présentation équivalente dans Unicode. La cartographie des points de code synthétiques PUA de la phase 8c.6 permettra l'émission de GSUB côté producteur pour Devanagari et d'autres scripts indiens/d'Asie du Sud-Est où les GID de substitution sont spécifiques à la police.
  • Le contenu non-devanagari est traité par `ApplyDevanagariReorder` de manière identique au niveau des octets (la méthode ne traite que les syllabes devanagari ; les autres plages de caractères sont émises sans modification). Les fichiers PDF dont les appelants laissent `sfIndicShaping` désactivé (par défaut) produisent une sortie identique à celle de la version v2.119.66. Combiné avec la couche de fonctionnalités v2.119.55 ( `GetDevanagariCategory` + `ApplyDevanagariReorder` en tant que méthodes publiques), ce commit complète l'intégration de réorganisation côté producteur pour le devanagari : les appelants qui activent `sfIndicShaping` n'ont plus besoin de pré-réorganiser en amont ou d'appeler `ApplyDevanagariReorder` manuellement avant `BuildUnicode*FieldContent` — HotPDF le fait automatiquement.

2026-05-22 Version 2.119.66

  • Intégration automatique de 'rclt' (Alternatives Contextuelles Obligatoires) : la nouvelle méthode THotPDF.ApplyArabicGSUBContextualRefinement (Wide) est similaire à v2.119.63 ApplyArabicGSUBRefinement, mais applique une substitution contextuelle (GSUB de type 5/6) via l'API v2.119.47 ApplyContextualSubst au lieu d'une substitution de ligature (type 4). 'rclt' encode les substitutions contextuelles obligatoires, généralement utilisées par les polices arabes pour des variantes positionnelles supplémentaires au-delà de la correspondance Forms-B statique de v2.85.0, et par les polices d'Asie du Sud-Est/indiennes pour des formes réordonnées au niveau du cluster qui dépendent du contexte des caractères voisins.
  • Gestion de la sortie de longueur variable : contrairement à `ApplyLigatureSubstitution` (N GID d'entrée -> 1 GID substitué), `ApplyContextualSubst` peut produire M GID substitués à partir de N GID d'entrée. Lorsqu'une règle contextuelle est déclenchée, TOUS les GID substitués doivent être accessibles via les points de code de la forme de présentation Unicode, via une cmap inverse (FB00-FDFF + FE70-FEFF, environ 770 points de code analysés), pour que la substitution soit validée ; si l'un des GID substitués ne possède pas de mappage inverse, la fenêtre d'entrée est transmise sans modification (une émission partielle corromprait la séquence). La plage de la cmap inverse a été étendue pour couvrir les formes de présentation latine/arménienne/hébraïque (FB00-FB4F) ainsi que les plages arabes complètes, afin que les substitutions 'rclt' de n'importe quel script puissent être émises.
  • Nouveau membre de l'énumération `THPDFShapingFeature` : `sfContextualAlternates` (ajouté à la fin pour la compatibilité descendante ; les appels existants utilisant `FShapingFeatures` restent compatibles et se compilent sans modification). Intégré aux trois fonctions `BuildUnicode*FieldContent`, qui sont conditionnelles en fonction de `sfContextualAlternates` dans `FShapingFeatures` (optionnel, par défaut désactivé). Indépendant de `FAutoShapeArabic` ; la fonctionnalité `'rclt'` peut s'appliquer à des scripts non arabes (latin, hébreu, indic). Les GIDs de substitution sont transmis via `MarkUnicodeGlyphUsed` pour le module de sous-ensemble v2.84.0. Opération sans effet si la police ne contient pas de règles `'rclt'` ou si les GIDs de substitution ne possèdent pas de codepoints de forme de présentation. Les fichiers PDF générés lorsque `sfContextualAlternates` est désactivé sont identiques en termes de bytes à la sortie v2.119.65.

2026-05-22 Version 2.119.65

  • Les ligatures standard Latin (feuille de route du moteur GSUB, phase 8b) : la nouvelle méthode THotPDF.ApplyLatinLigatureRefinement (Wide) est similaire à v2.119.63 ApplyArabicGSUBRefinement, mais cible les formes de présentation alphabétiques Latin / arménienne / hébraïque dans U+FB00-U+FB4F. Elle parcourt la chaîne d'entrée en mode "Wide", construit un tableau GID parallèle via FUnicodeCpToGid, et interroge la fonctionnalité 'liga' (ligatures standard) du jeu de caractères via l'API v2.119.43-50 ApplyLigatureSubstitution à chaque position. Si une substitution de ligature est effectuée ET que le GID de substitution est accessible via un point de code de forme de présentation alphabétique Unicode, la fenêtre de point de code source est remplacée par le point de code de la substitution. Cette fonctionnalité est intégrée aux trois fonctions BuildUnicode*FieldContent (à une seule ligne, multiligne et pour les champs AcroForm /AP de type "comb"), et est activée par sfStandardLigatures dans FShapingFeatures (optionnelle, et stable en termes de taille en octets lorsqu'elle n'est pas définie).
  • Passage optionnel pour 'clig' (Ligatures Contextuelles) : lorsque sfContextualLigatures est également inclus dans FShapingFeatures, la méthode réévalue le résultat de 'liga' en appliquant 'clig' pour prendre en compte les ligatures contextuelles spécifiques à la police, au-delà de l'ensemble standard fi / fl / ffi / ffl. Chaque GID de substitution généré est transmis à MarkUnicodeGlyphUsed pour le module de sous-ensemble TTF v2.84.0. La cmap inverse effectue une analyse linéaire d'environ 80 points de code (FB00-FB4F) ; les substitutions sont peu fréquentes et le coût est négligeable.
  • ToUnicode CMap bfchar block extended from 28 to 35 entries: 7 new entries cover the Latin Alphabetic Presentation Forms FB00 (ff -> f + f), FB01 (fi -> f + i), FB02 (fl -> f + l), FB03 (ffi -> f + f + i), FB04 (ffl -> f + f + l), FB05 (ſt -> long s + t), FB06 (st -> s + t). Consumer-side text extraction (copy / paste / accessibility) now restores the original ASCII letter sequence when a Latin ligature codepoint appears in the PDF text stream. PDFs whose callers leave sfStandardLigatures off (the default) emit byte-identical to v2.119.64 output. Scope: only emits ligature substitutes reachable through Alphabetic Presentation Form codepoints — decorative / discretionary Latin ligatures with no Unicode codepoint (font-specific GIDs) cannot be emitted through this path and remain reserved for Phase 8c.6 GID-level emit.

2026-05-22 Version 2.119.64

  • API de requête de progression des points de code (feuille de route du moteur GSUB, phase 8c.5) : la nouvelle fonction THotPDF.GetCodepointAdvance (CP: Cardinal) expose le cache v2.76.0 /W, permettant aux applications qui construisent des calculs de retour à la ligne personnalisés, en dehors de l'aide BuildUnicodeMultilineFieldContent, de demander la progression réelle de l'em pour n'importe quel point de code, dérivée de la table hmtx de la police via la cmap mise en cache. Après la chaîne statique de post-traitement des ligatures v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62, ainsi que l'amélioration GSUB au niveau des GID v2.119.63, qui génère des points de code de ligature (LAM-ALEF FEF5-FEFC, YEH-HAMZA FBEA-FBFB, Allah FDF2, Bismillah FDFD, et les formes de présentation substituées par GSUB dans FB50-FDFF / FE70-FEFF), la méthode renvoie la progression réelle de la glyphe de ligature (qui est généralement plus étroite que la somme des progressions des points de code sources), afin que les budgets de retour à la ligne des applications correspondent au rendu côté consommateur.
  • Amélioration de la méthode heuristique de construction du contenu des champs multilignes Unicode : le chemin de repli v2.65 (utilisé lorsque le cache /W n'est pas disponible, par exemple, le chemin RegisterUnicodeFontDict au lieu de RegisterUnicodeTTF) traitait auparavant tous les points de code >= U+2E80 comme larges (1,0 em). Les formes de présentation arabe (FB50-FBFF, formes-A, lettres ; FC00-FDFF, formes-A, ligatures + FDF0-FDFD, coraniques ; FE70-FEFF, formes-B, formes de base + LAM-ALEF) sont en réalité étroites (environ 0,55 em en moyenne dans les polices arabes courantes), et non larges. La version v2.119.64 dirige ces trois plages de formes de présentation arabe vers le chemin étroit (0,5 em) dans la méthode de repli heuristique, corrigeant ainsi le cas particulier où les ligatures arabes émises par les versions v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62 / v2.119.63 seraient incorrectement avancées de 1,0 em lorsque le cache n'est pas rempli.
  • Renvoie 0 pour le chemin typique sans information (aucune police enregistrée, cache non encore rempli, point de code supérieur à BMP, point de code sans glyphe dans la cmap de la police). Purement fonctionnel, sans effets secondaires, il est sûr de l'appeler depuis n'importe quel contexte après que RegisterUnicodeTTF a réussi. Les fichiers PDF dont la police chargée a le cache /W rempli et qui n'utilisent pas la nouvelle méthode de requête produisent une sortie identique en octets à la version v2.119.63. La phase 8c.5 clôt la feuille de route du moteur GSUB §8c et met en place un pipeline de formation GSUB arabe automatique côté producteur au niveau des fonctionnalités. Les phases 8c.1 à 8c.5 fournissent ensemble des post-traitements de tables statiques (4 familles de ligatures) + une correspondance inverse ToUnicode + un raffinement GSUB au niveau GID + une requête d'avance publique, le tout fonctionnant ensemble pour rendre le rendu des ligatures arabes côté producteur précis au niveau des octets avec l'affichage côté consommateur.

2026-05-22 Version 2.119.63

  • Amélioration du post-traitement de la substitution de glyphes (GSUB) au niveau GID pour la fonctionnalité 'rlig' (feuille de route du moteur GSUB, phase 8c.2) : la nouvelle méthode THotPDF.ApplyArabicGSUBRefinement (Wide) parcourt la chaîne Wide de gauche à droite, construisant un tableau GID parallèle via le cmap mis en cache (FUnicodeCpToGid), et à chaque position où GID est différent de zéro, interroge la fonctionnalité GSUB 'rlig' (ligatures requises) de la police via l'API ApplyLigatureSubstitution v2.119.43-50. Si une substitution de ligature est effectuée ET que le GID de substitution est accessible via un point de code de forme de présentation arabe Unicode (analyse inverse du cmap sur U+FB50-U+FDFF + U+FE70-U+FEFF, environ 690 points de code), la fenêtre de point de code source est remplacée par le point de code de la ligature. Les glyphes de substitution sont également transmis à MarkUnicodeGlyphUsed pour la finalisation du sous-ensembleur TTF v2.84.0.
  • Intégré aux trois fonctions `BuildUnicode*FieldContent` immédiatement après la chaîne statique de post-traitement au niveau des points de code (LAM-ALEF / YEH-HAMZA / Allah / Bismillah) v2.85.0 / v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62. Complète le tableau statique en récupérant les règles 'rlig' spécifiques à la police que les quatre familles codées en dur ne prennent pas en charge, notamment les variantes contextuelles dans les polices persanes / ourdoues / sindhies / kurdes (Vazirmatn, Markazi Text, Lateef, Scheherazade, Amiri) qui correspondent aux formes de présentation Unicode au-delà de l'ensemble LAM-ALEF / YEH-HAMZA / Allah / Bismillah. S'exécute uniquement lorsque `FAutoShapeArabic` est vrai ET que `sfArabicGSUB` n'est PAS dans `FShapingFeatures` (un mécanisme de verrouillage empêche le chemin "piloté par l'appelant" de v2.119.59) ET que la police chargée possède une table GSUB.
  • La portée de cette modification est limitée aux substitutions dont les GID sont accessibles via un point de code de formulaire de présentation via la table cmap. Les substitutions spécifiques à la police qui se trouvent sur des GID arbitraires (sans mappage inverse de point de code) ne peuvent pas être émises via ce chemin ; elles nécessitent une émission complète au niveau des GID dans le pipeline de production réservé à la phase 8c.5+. La recherche inverse dans la table cmap est une analyse linéaire de ~690 points de code par tentative de substitution ; les substitutions sont rares en pratique, donc le coût est négligeable. Les fichiers PDF dont la police chargée ne contient pas de contenu GSUB 'rlig' ou dont les substitutions n'ont pas de points de code de formulaire de présentation produisent une sortie identique à celle de la version v2.119.62 (dans ces cas, la méthode est une opération sans effet). Avec cette modification, le pipeline de formation automatique de l'arabe côté producteur du moteur GSUB gagne une fonctionnalité de regroupement de ligatures sensible à la police, au-delà de la chaîne de table statique codée en dur.

2026-05-22 Version 2.119.62

  • Bismillah phrase-level ligature post-pass (GSUB engine roadmap Phase 8c.4): the v2.85.0 producer-side Arabic shaper now folds the 22-codepoint canonical Bismillah phrase "بسم الله الرحمن الرحيم" ("In the name of God, the Most Gracious, the Most Merciful") into a single U+FDFD ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM codepoint. Runs FIRST in the post-pass chain (before LAM-ALEF / YEH-HAMZA / Allah folds) so the full phrase is detected before the الله sub-phrase gets folded by the v2.119.60 Allah post-pass. Each letter position matches the base codepoint or any of its v2.85.0 Forms-B shaped variants (R-joining letters 3 variants each, D-joining 5 variants each); the three space positions require U+0020 exactly. Phrase-level detection on the canonical un-vowelled spelling.
  • La table CMap "ToUnicode" a été étendue avec une 28e entrée "bfchar" qui mappe U+FDFD à la séquence source complète de 22 caractères (BEH + SEEN + MEEM + ESPACE + ALEF + LAM + LAM + HEH + ESPACE + ALEF + LAM + REH + HAH + MEEM + NOON + ESPACE + ALEF + LAM + REH + HAH + YEH + MEEM). L'extraction de texte côté consommateur (copier/coller/accessibilité) restaure désormais la phrase originale de 22 caractères plutôt que le glyphe de ligature unique, complétant ainsi le comportement de "aller-retour" pour les quatre familles de ligatures à table statique (LAM-ALEF / YEH-HAMZA / Allah / Bismillah).
  • Known limitations (deliberate scope reductions): tatweel (U+0640) between letters not matched; harakat / diacritics between letters not matched (canonical fold targets un-vowelled Bismillah); non-breaking space U+00A0 or multiple spaces between words not matched (only single ASCII U+0020); alternative spellings (الرحمٰن with superscript alef) not matched; phrase must appear exactly without trailing modifiers. False-positive risk is essentially zero because the canonical 22-codepoint sequence is uniquely Bismillah by intent. Other Quranic honorifics (FDFA SALLALLAHOU ALAYHE WASALLAM, FDFB JALLAJALALOUHOU) and single-word ligatures (FDF3 AKBAR / FDF4 MOHAMMAD / FDF5 SALAM / etc.) remain out of scope because those source words also appear as ordinary Arabic terms in non-religious text and would generate false positives.

2026-05-22 Version 2.119.61

  • ToUnicode CMap reverse-mapping for Arabic ligatures (GSUB engine roadmap Phase 8c.3): the v2.83.0 RegisterUnicodeTTF Adobe-Identity-UCS CMap is now extended with 27 bfchar entries that override the bfrange identity mapping for every ligature codepoint emitted by the v2.85.0 producer-side Arabic shaper post-pass chain. Each entry restores the source codepoint sequence on consumer-side text extraction, fixing the limitation where copy / paste from PDF readers previously returned a single ligature character (e.g., "ﷲ" for Allah) rather than the original source word ("الله"). Bfchar takes precedence over bfrange per Adobe CMap and CIDFont Files Specification.
  • Couverture : 8 entrées LAM-ALEF U+FEF5-U+FEFC (ligature obligatoire v2.119.32, 4 variantes d'ALEF × 2 formes) → paires sources LAM + ALEF / ALEF MADDA / ALEF HAMZA SUPERIEURE / ALEF HAMZA INFERIEURE ; 18 entrées de la famille YEH-HAMZA U+FBEA-U+FBFB (v2.119.58, inclut les formes initiales FBF8 et FBFB que le post-traitement automatique ne génère pas, mais que les appelants peuvent utiliser directement) → paires sources YEH-HAMZA + ALEF / AE / WAW / U / OE / YU / E / ALEF MAKSURA ; 1 entrée Allah U+FDF2 (v2.119.60) → séquence source de quatre codepoints ALEF + LAM + LAM + HEH. Avec cette mise à jour, la copie / collage / accessibilité est complète pour les trois familles de ligatures à table statique.
  • Stable pour les contenus non arabes : le bloc bfchar ajoute environ 700 octets de texte PostScript non compressé au flux CMap, ce que FlateDecode réduit généralement à environ 150 à 200 octets. Les fichiers PDF sans contenu arabe conservent la même structure de flux /ToUnicode ; l'extension est ajoutée au sein du même objet de flux FlateDecode indirect. Tous les lecteurs grand public (Adobe Reader, Foxit, PDF.js, Apple Preview, etc.) respectent la priorité de bfchar par rapport à bfrange et appliquent correctement la correspondance inverse. Le bloc de 27 entrées est codé en dur dans le texte du CMap (aucune personnalisation spécifique à chaque fichier PDF n'est nécessaire) ; une version ultérieure, Phase 8c.4, ajoutera des entrées bfchar supplémentaires pour la ligature Bismillah U+FDFD.

2026-05-22 Version 2.119.60

  • Allah ligature static post-pass: the v2.85.0 producer-side Arabic shaper now folds the four-codepoint sequence ALEF + LAM + LAM + HEH (الله in standard Arabic) into the single codepoint U+FDF2 ARABIC LIGATURE ALLAH ISOLATED FORM after the v2.119.32 LAM-ALEF and v2.119.58 YEH-HAMZA post-passes finish. Same model as the two earlier ligature post-passes: detect the source sequence in any combination of raw and shaped forms, emit a single codepoint output, trust the font to have the ligature glyph at the Unicode-defined cmap entry. This is the first slice of the GSUB engine roadmap Phase 8c (producer-side automatic Arabic GSUB shaping pipeline) — codepoint-level ligature folding for the most prevalent Arabic religious ligature.
  • Source-letter form matching covers all valid combinations after the v2.85.0 walker has shaped the sequence: ALEF in raw U+0627 or isolated FE8D or final FE8E form (R-joining, no init / medi); LAM in raw U+0644 or any of the four shaped forms FEDD-FEE0 (D-joining, full 4 positional forms); HEH in raw U+0647 or any of the four shaped forms FEE9-FEEC (D-joining). A typical standalone "الله" word emerges from the walker as FE8D + FEDF + FEE0 + FEEA (ALEF isol + LAM init + LAM medi + HEH final), which folds to FDF2. PDFs without the Allah codepoint sequence emit byte-identical to v2.119.59 output.
  • Known limitations of codepoint-level ligature folding: (1) Output is the isolated form FDF2 only — Unicode does not define final / initial / medial forms for the Allah ligature, but in practice Allah is almost always rendered standalone, so the single FDF2 codepoint suffices for visual rendering. (2) Consumer-side text extraction (copy / paste / accessibility) yields the single character "ﷲ" rather than the four-character word "الله" because the ToUnicode CMap has not yet been extended to reverse-map FDF2 to its 4-codepoint source. A future Phase 8c.3 installment will add the bfchar reverse mapping. (3) Font dependency: the loaded TTF / OTF must have a cmap entry mapping U+FDF2 to its Allah glyph; mainstream Arabic fonts (Noto Sans Arabic, Amiri, Scheherazade, Lateef, Markazi Text, Tahoma / Times New Roman Arabic) all include it. Other Quranic ligatures (FDF0 / FDF1 / FDF3-FDFB Allah-family honorifics, FDFD Bismillah) plus GID-level GSUB integration for font-specific substitutions are reserved for future Phase 8c.2-8c.4 installments.

2026-05-22 Version 2.119.59

  • Framework optionnel pour l'intégration côté serveur du pipeline de mise en forme (feuille de route du moteur GSUB, phase 8a) : la nouvelle énumération `THPDFShapingFeature` ainsi que le type d'ensemble `THPDFShapingFeatures` modélisent les indicateurs de fonctionnalité prévus pour les phases 8a à 8e, pour l'intégration de la mise en forme de texte côté serveur. Les cinq membres de l'énumération sont `sfArabicGSUB` (implémenté dans cette version), `sfStandardLigatures` (phase 8b, futur), `sfContextualLigatures` (phase 8b, futur), `sfStylisticAlternates` (phase 8d, futur) et `sfIndicShaping` (phase 8e, futur). `THotPDF` acquiert une propriété `ShapingFeatures` de type `THPDFShapingFeatures` avec une valeur par défaut de `[]` (toutes les fonctionnalités désactivées) ; les appelants de la version `v2.119.32-58` verront une sortie identique à celle de la version précédente tant que la propriété est laissée à sa valeur par défaut.
  • sfArabicGSUB agit comme un verrou pour empêcher l'utilisation du moteur de formatage arabe statique de la version 2.85.0. Lorsque sfArabicGSUB est inclus dans ShapingFeatures, les trois fonctions utilitaires BuildUnicode*FieldContent (pour les champs sur une seule ligne, les champs multilignes et les éléments AcroForm /AP) ignorent complètement _ApplyArabicShaping : il n'y a pas de réécriture des points de code à quatre positions de la version 2.85.0, ni de post-traitement LAM-ALEF de la version 2.119.32, ni de post-traitement YEH-HAMZA + voyelle de la version 2.119.58. L'appelant est responsable de la sélection du formatage arabe via les API du moteur GSUB de la version 2.119.43-50 (SetGSUBScript ('arab') + GetSingleSubstituteGlyph pour les balises de fonctionnalité 'init' / 'medi' / 'fina' / 'isol' + MarkUnicodeGlyphUsed pour la fermeture du sous-ensembleur de la version 2.84.0). Combiné avec sfArabicGSUB, les appelants utilisant des polices arabes telles que Noto Sans Arabic / Amiri / Scheherazade / Markazi Text peuvent désormais contrôler le formatage GSUB arabe complet côté police au moment de la création, au lieu de s'appuyer sur le mécanisme de repli statique.
  • Companion Arabic capability API: two new public methods GetArabicJoiningClass (CP) and GetArabicPosition (Wide, Index) mirror the v2.119.53 GetSyriacJoiningClass / v2.119.54 GetMongolianJoiningClass pattern, exposing the internal joining-class table and 4-position contextual walker the static shaper uses. Callers driving Arabic GSUB shaping manually no longer need to re-derive joining-class data per codepoint — they can reuse the cumulative v2.85.0 / v2.119.35 / v2.119.52 / v2.119.57 table that already covers basic Arabic (U+0600-U+06FF), Arabic Supplement (U+0750-U+077F), and Arabic Extended-A (U+08A0-U+08FF). With this slice landed, the user's two-item request "Forms-A FBEA-FBFB 装饰类合字 (v2.119.58) + Producer-side 自动 Arabic GSUB shaping pipeline (this release)" is fulfilled at the capability + opt-in framework layer. Full producer-side automatic GSUB application inside TextOut / BuildUnicode*FieldContent (auto cmap-to-GID + per-position GSUB substitute + substitute GID emit, with no caller code) remains reserved for the deeper Phase 8c integration commits.

2026-05-22 Version 2.119.58

  • YEH-HAMZA + ligature de la lettre vocale, étape finale : le module de formation arabe côté serveur, version v2.85.0, intègre désormais les 8 paires de ligatures encodées dans le bloc Arabic Presentation Forms-A, aux positions U+FBEA-U+FBFB, en les transformant en points de ligature uniques après l'étape de parcours à 4 positions et l'étape finale LAM-ALEF. Il utilise le même modèle et la même intégration que LAM-ALEF (substitution statique obligatoire, 2 formes de sortie par ligature). Les paires concernées sont les suivantes : YEH-HAMZA + ALEF -> FBEA/FBEB (arabe standard / persan / ourdou), YEH-HAMZA + AE U+06D5 -> FBEC/FBED (kashmiri / ouïghour), YEH-HAMZA + WAW -> FBEE/FBEF (arabe standard), YEH-HAMZA + U U+06C7 -> FBF0/FBF1 (ouïghour / kazakh / kirghiz), YEH-HAMZA + OE U+06C6 -> FBF2/FBF3 (identique), YEH-HAMZA + YU U+06C8 -> FBF4/FBF5 (identique), YEH-HAMZA + E U+06D0 -> FBF6/FBF7 (identique), YEH-HAMZA + ALEF MAKSURA -> FBF9/FBFA (arabe standard).
  • YEH-HAMZA est associé sous sa forme brute U+0626 ou dans l'une de ses formes modifiées v2.85.0 (FE89 isol, FE8A final, FE8B init, FE8C medial) ; la voyelle suivante est associée sous sa forme brute ou dans l'une de ses variantes de forme v2.119.57 (FBD7-FBD8 pour U, FBD9-FBDA pour OE, FBDB-FBDC pour YU, FBE4-FBE7 pour E) ou dans l'une de ses variantes de forme v2.85.0 (FE8D-FE8E pour ALEF, FEED-FEEE pour WAW, FEEF-FEF0 pour ALEF MAKSURA). La sélection de la forme finale (base + 1) suit la règle LAM-ALEF : lorsque le YEH-HAMZA a été modifié aux formes finale (FE8A) ou médiale (FE8C) (c'est-à-dire qu'il est précédé d'une lettre à double liaison), la ligature est émise sous sa forme finale ; sinon, la forme isolée est utilisée.
  • Les limites de la portée : seuls les formes isolées et finales (sortie en 2 formes) sont générées par cette étape ultérieure. Les formes initiales définies par Unicode, FBF8 (YEH-HAMZA + E) et FBFB (YEH-HAMZA ouïghour + ALEF MAKSURA), ne sont pas produites. Les appelants qui ont besoin de ces variantes à trois formes doivent activer les recherches GSUB liées à 'rlig' / 'clig' via ApplyContextualSubst. Les autres régions de ligatures arabes (Allah U+FDFA / FDFB, ligatures décoratives à FC00-FDC7) nécessitent également des recherches GSUB 'rlig' / 'dlig' et ne sont pas prises en compte par le formateur à table statique. Les fichiers PDF qui ne contiennent pas YEH-HAMZA suivi de l'une des huit voyelles prises en charge produisent une sortie identique à v2.119.57 ; cette nouvelle étape ultérieure ne s'exécute que pour les séquences spécifiques de 2 points de code.

2026-05-22 Version 2.119.57

  • Persian / Urdu / Sindhi / Kashmiri / Uyghur / Kazakh / Kyrgyz Arabic Extended letter coverage: the v2.85.0 producer-side Arabic shaper joining-class table now spans the entire U+0672-U+06D5 range per Unicode 16.0 ArabicShaping.txt, closing the "Persian/Urdu Form-B 扩展" work-item that was deferred when v2.119.35 shipped the 9-letter Persian/Urdu core and v2.119.52 added the ALEF WASLA / NOON GHUNNA / HEH variants. About 80 letters are added to the joining-class table covering REH / DAL / SEEN / SAD / TAH / AIN / FEH / QAF / KAF / GAF / LAM / NOON / HEH / WAW / YEH variants — so adjacent letters now pick correct positional forms regardless of which Arabic Extended-A letter sits next to them.
  • 26 des nouvelles lettres classifiées possèdent également des entrées statiques de formes de présentation A dans U+FB52-U+FBFC et sont désormais mappées directement par le moteur de mise en forme de table statique, sans nécessiter un moteur de mise en forme GSUB de la police : 15 lettres de liaison D en forme de 4 (TTEHEH U+067A → FB5E-FB61, BEEH U+067B → FB52-FB55, TEHEH U+067F → FB62-FB65, BEHEH U+0680 → FB5A-FB5D, NYEH U+0683 → FB76-FB79, DYEH U+0684 → FB72-FB75, TCHEHEH U+0687 → FB7E-FB81, VEH U+06A4 → FB6A-FB6D, PEHEH U+06A6 → FB6E-FB71, NG U+06AD → FBD3-FBD6, NGOEH U+06B1 → FB9A-FB9D, GUEH U+06B3 → FB96-FB99, RNOON U+06BB → FBA0-FBA3, HEH DOACHASHMEE U+06BE → FBAA-FBAD qui est la lettre 'h' standard de l'ourdou, E U+06D0 → FBE4-FBE7 pour l'arabe kazakh/kirghiz), et 11 lettres de liaison R en forme de 2 (DAHAL U+068C → FB84-FB85, DDAHAL U+068D → FB82-FB83, DUL U+068E → FB86-FB87, KIRGHIZ OE U+06C5 → FBE0-FBE1, OE U+06C6 → FBD9-FBDA, U U+06C7 → FBD7-FBD8, YU U+06C8 → FBDB-FBDC, KIRGHIZ YU U+06C9 → FBE2-FBE3, VE U+06CB → FBDE-FBDF, YEH BARREE U+06D2 → FBAE-FBAF qui est le 'yeh' final de mot en ourdou, YEH BARREE WITH HAMZA ABOVE U+06D3 → FBB0-FBB1).
  • Les deux lettres HEH DOACHASHMEE et YEH BARREE méritent une mention spéciale car leurs emplacements de forme A (FBAA-FBAD et FBAE-FBAF) étaient ceux que l'erreur de la version 2.119.52 avait incorrectement attribués aux caractères U+06C2 HEH GOAL WITH HAMZA ABOVE et U+06C3 TEH MARBUTA GOAL. Avec la version 2.119.56 qui corrige ces affectations incorrectes et la version 2.119.57 qui associe les emplacements aux lettres sources correctes, la trace d'audit est propre et la confusion est résolue de manière permanente. Les lettres de la plage U+0672-U+06D5 qui ne possèdent pas d'entrées de forme de présentation A dans Unicode 16 (environ 50 points de code supplémentaires, principalement des variantes de REH / DAL / SEEN / SAD / TAH / AIN / FEH / QAF / KAF sans formes pré-encodées) continuent de participer à l'analyse de classe de liaison afin que les caractères voisins soient correctement formatés ; les caractères eux-mêmes sont traités comme des points de code bruts et s'appuient sur les tables de recherche GSUB de la police pour leur propre sélection de forme, en utilisant le moteur GSUB de la version 2.119.43-50. Compilé avec 78018 lignes ; les fichiers PDF qui ne contiennent pas ces nouveaux points de code produisent des fichiers identiques en octets à la version 2.119.56.

2026-05-22 Version 2.119.56

  • Correction d'un bug concernant la mise en forme de l'arabe : la version v2.119.52 avait introduit des correspondances incorrectes pour les formes de présentation arabe-A pour deux caractères de la région ourdou/sindhi. Le caractère U+06C2 HEH GOAL WITH HAMZA ABOVE était mappé à FBAA-FBAD, qui est en réalité la plage de codepoints pour U+06BE HEH DOACHASHMEE ; les lecteurs consommant ce contenu affichaient le glyphe ourdou "Goal-Heh-with-Hamza" comme le glyphe standard ourdou "Heh-Doachashmee". Le caractère U+06C3 TEH MARBUTA GOAL était mappé à FBAE-FBAF, qui est en réalité la plage de codepoints pour U+06D2 YEH BARREE ; les lecteurs affichaient "Teh-Marbuta-Goal" comme le mot ourdou "Yeh-Barree". Conformément à Unicode 16.0, ni U+06C2 ni U+06C3 ne possèdent d'entrées pré-encodées pour les formes de présentation-A ; les deux doivent être transmis sans modification en tant que codepoints bruts (les lecteurs consommant ce contenu les affichent correctement via la table cmap de la police et toute mise en forme basée sur GSUB).
  • Correction : les deux entrées incorrectes dans le tableau de recherche "_ArabicShape Presentation Forms-A" du module de formatage arabe côté producteur, version v2.85.0, ont été supprimées ; U+06C2 et U+06C3 passent maintenant au chemin de contournement et sont émis sans modification. Les entrées de classe de liaison de la version v2.119.52 (D pour U+06C2, R pour U+06C3) sont conservées afin que les lettres adjacentes conservent les formes positionnelles correctes lorsque ces caractères apparaissent dans un mot. Cette correction n'affecte que les fichiers PDF qui contiennent U+06C2 ou U+06C3 avec AutoShapeArabic activé ; les fichiers PDF qui ne contiennent pas ces deux points de code sont identiques à la sortie de la version v2.119.55. La version compagnon v2.119.57 étend la couverture de Forms-A à des lettres supplémentaires du perse, de l'ourdou, du sindhi, du kashmiri, de l'ouïghour, du kazakh et du kirghiz, y compris les caractères HEH DOACHASHMEE et YEH BARREE, qui étaient incorrectement regroupés dans l'erreur de la version v2.119.52.

2026-05-22 Version 2.119.55

  • Capacité de mise en forme de l'écriture Devanagari : deux nouvelles méthodes publiques dans THotPDF couvrent le paradigme de mise en forme de l'écriture Indic qui ne correspond pas à l'algorithme de parcours de classe de liaison à 4 positions utilisé pour l'arabe, le syriaque et le mongol (v2.85.0 + v2.119.32-54). GetDevanagariCategory (CP) renvoie la catégorie syllabique Indic simplifiée (0 = Autre, 1 = Consonne, 2 = Voyelle indépendante, 3 = Matra, 4 = Virama, 5 = Nukta, 6 = Bindu, 7 = Visarga, 8 = Danda, 9 = Chiffre, 10 = ZWJ, 11 = ZWNJ, 12 = Modificateur) conformément à Unicode 16.0 §12.1 + IndicSyllabicCategory.txt ; le tableau couvre l'ensemble du bloc Devanagari U+0900-U+097F, y compris les extensions Marwari, Sindhi et védiques dans U+0978-U+097F.
  • `ApplyDevanagariReorder (Wide)` parcourt la chaîne d'entrée de gauche à droite et applique la phase de réorganisation Devanagari à chaque syllabe Devanagari rencontrée, renvoyant une chaîne Unicode réorganisée, prête pour les processus cmap et GSUB. Le contenu non-Devanagari (latin, chiffres, ponctuation, autres scripts) est transmis tel quel, byte par byte. Deux réorganisations sont implémentées (celles qui dominent la formation Devanagari dans le monde réel) : (1) Repha — lorsqu'une syllabe commence par Ra (U+0930) + Halant (U+094D) + Consonne, la paire (Ra, Halant) est déplacée à la FIN de la syllabe, de sorte que la fonctionnalité GSUB 'rphf' de la police remplace cette paire par le glyphe Repha qui se fixe visuellement au-dessus et à droite de la base de la syllabe ; (2) I-matra de base — U+093F est déplacé au tout DÉBUT de la syllabe (après toute suppression de Repha), de sorte que le traitement GSUB de gauche à droite le voit devant le groupe de consonnes, ce qui correspond à son ordre de rendu visuel.
  • Le pipeline de l'appelant applique la réorganisation Devanagari au texte dans l'ordre logique, puis définit les substituts en exposant ('deva'). Ensuite, il parcourt les points de code réorganisés, appliquant les fonctionnalités GSUB ('nukt' / 'akhn' / 'rphf' / 'rkrf' / 'half' / 'vatu' / 'cjct' / 'pres' / 'blws' / 'abvs' / 'psts' / 'haln') via GetSingleSubstituteGlyph + ApplyLigatureSubstitution + ApplyContextualSubst. Enfin, il émet les GID résultants vers le flux de texte PDF, tout en appelant MarkUnicodeGlyphUsed (GID) pour chaque émission, pour le module de sous-ensemble v2.84.0. Avec la phase A (module v2.119.52 pour l'extension arabe), la phase B (capacité syriaque v2.119.53), la phase C (capacité mongole v2.119.54) et la phase D (capacité Devanagari Indic v2.119.55) maintenant implémentées, le "décalage de matrice" entre le mongol, le syriaque et la mise en forme Devanagari est entièrement comblé. Hors de portée : les scripts Devanagari Indic non-Devanagari (bengali, tamoul, télougou, gujarati - chacun a ses propres données de catégorie et règles de réorganisation), les règles de réorganisation au-delà de Repha + I-matra de base, et la mise en forme Devanagari automatique côté producteur dans TextOut / BuildUnicode*FieldContent (réservé pour la phase 8 de la feuille de route du moteur GSUB).

2026-05-22 Version 2.119.54

  • Capacité de mise en forme mongole : deux nouvelles méthodes publiques sur THotPDF exposent la recherche de classe de liaison mongole (U+1800-U+18AF) et l'analyse contextuelle à 4 positions, permettant aux appelants de contrôler la mise en forme du texte mongol côté producteur. GetMongolianJoiningClass (CP) renvoie la classe de liaison mongole Unicode 16.0 §13.5 (0 = U non-liaison, 2 = D double-liaison, 4 = T transparent / sélecteur de variation) pour n'importe quel point de code ; le tableau couvre le mongol de base ainsi que les extensions de lettres Todo, Sibe, Manchu et Ali Gali (U+1820-U+1878 + U+1887-U+18A8 + ALI GALI DAGALGA U+18A9 + MANCHU ALI GALI LHA U+18AA) et classifie NIRUGU (U+180A), les trois sélecteurs de variation libres FVS1-FVS3 (U+180B-U+180D) et les marques vocaliques Ali Gali BALUDA / THREE BALUDA (U+1885-U+1886) comme transparentes. GetMongolianPosition (Wide, Index) parcourt le texte environnant en ignorant les marques transparentes et renvoie 0 = isolé, 1 = final, 2 = initial ou 3 = médian pour la lettre à l'index 0.
  • Comme pour le syriaque (v2.119.53), le mongol n'a PAS de formes de présentation pré-encodées dans Unicode. Chaque police de caractères compatible avec le mongol (Mongolian Baiti, Noto Sans Mongolian, Noto Serif Mongolian, etc.) utilise le positionnement via les recherches OpenType GSUB dans ses fonctionnalités 'init' / 'medi' / 'fina' / 'isol' sous l'étiquette de script 'mong'. Par conséquent, v2.119.54 suit le même modèle que v2.119.53, qui est un modèle basé uniquement sur les fonctionnalités. Les appelants composent la sortie de positionnement avec les API du moteur GSUB v2.119.43-50 (SetGSUBScript ('mong'), GetSingleSubstituteGlyph pour l'étiquette de fonctionnalité de positionnement appropriée, MarkUnicodeGlyphUsed pour le sous-ensembleur v2.84.0) afin de produire des GID formatés qui sont directement émis dans le flux de texte PDF.
  • Le mongol est écrit verticalement, de haut en bas, dans son mode d'écriture natif ; le module de traitement opère sur l'ordre logique des points de code (prédécesseur/successeur dans le flux de points de code), indépendamment de l'orientation visuelle. Le rendu réel de haut en bas est géré au moment de la génération du fichier PDF via /WMode 1 (écriture verticale) ou la rotation de la matrice de police, et non par le module de mise en forme. La classification des sélecteurs de variation libre (Free Variation Selectors) comme transparent signifie que le module de traitement résout correctement les formes positionnelles, même lorsqu'un FVS suit une lettre ; la recherche GSUB de la police sous les fonctionnalités 'fina' / 'medi' / 'init' / 'isol' sélectionne automatiquement la variante conditionnée par le FVS lorsque celui-ci est présent dans la séquence d'entrée. La mise en forme du Devanagari (écriture indic) reste réservée aux versions futures, car elle nécessite une phase de réorganisation préalable spécifique aux écritures indic, conformément à UAX #38 (réorganisation des signes virama, des groupes de consonnes et des éléments de base), ce qui ne correspond pas au module de traitement à 4 positions utilisé pour l'arabe, le syriaque et le mongol. La mise en forme automatique du mongol dans TextOut / BuildUnicode*FieldContent reste réservée à la phase 8 de la feuille de route du moteur GSUB.

2026-05-22 Version 2.119.53

  • Capacité de mise en forme syriaque : deux nouvelles méthodes publiques dans THotPDF exposent la recherche de classe de liaison syriaque (U+0700-U+074F) et l'analyse contextuelle à 4 positions, permettant aux appelants de contrôler la mise en forme du texte syriaque côté producteur. GetSyriacJoiningClass (CP) renvoie la classe de liaison SyriacShaping.txt (0 = U non-liaison, 1 = R liaison droite, 2 = D liaison double, 4 = T transparente / NSM) pour n'importe quel point de code ; le tableau couvre les 35 lettres syriaques de la plage de base, ainsi que les extensions perse et sogdienne (PERSE BHETH / GHAMAL / DHALATH à U+072D-U+072F, SOGDIEN ZHAIN / KHAPH / FE à U+074D-U+074F) et classifie l'ALAPH SUPÉRIEUR (U+0711) et les signes de combinaison syriaques (U+0730-U+074A) comme transparents. GetSyriacPosition (Wide, Index) parcourt le texte environnant, en ignorant les signes transparents, et renvoie 0 = isolé, 1 = final, 2 = initial ou 3 = médian pour la lettre à l'index (base 0).
  • Contrairement à l'arabe (qui possède des blocs de formes de présentation pré-encodés, les blocs U+FE70-U+FEFF et U+FB50-U+FBFF, qui permettent à HotPDF de réécrire directement les points de code en variantes formatées), le bloc syriaque ne possède AUCUNE forme de présentation pré-encodée dans Unicode ; chaque police de caractères compatible avec le syriaque (Estrangelo Edessa, Serto Jerusalem, East Syriac Adiabene, Noto Sans Syriac, etc.) utilise le positionnement via les recherches OpenType GSUB dans ses fonctionnalités 'init', 'medi', 'fina' et 'isol'. Par conséquent, la version v2.119.53 inclut uniquement la couche de fonctionnalité ; l'appelant compose la sortie de positionnement avec les API du moteur GSUB v2.119.43-50 (SetGSUBScript ('syrc'), GetSingleSubstituteGlyph par rapport à la balise de fonctionnalité de positionnement appropriée, MarkUnicodeGlyphUsed pour le sous-ensembleur v2.84.0) pour produire des GID formatés qui sont directement émis dans le flux de texte PDF.
  • La portée de la forme terminale d'Alaph : Unicode §9.3 documente deux fonctionnalités terminales contextuelles («fin2» appliquée après DALATH / RISH, «fin3» appliquée après FINAL LAMADH) que les polices syriaques utilisent pour échanger le glyphe final d'Alaph. La version v2.119.53 classifie Alaph (U+0710) comme une base de jointure droite et renvoie uniquement 0 (isolé) ou 1 (final) ; les appelants qui ont besoin de la différenciation «fin2» / «fin3» doivent activer les recherches contextuelles chaînées de la police via ApplyContextualSubst avec ces balises de fonctionnalité. La mise en forme mongole et dévanagari (indic) reste réservée aux versions futures : la mongole utilise des sélecteurs de variation libre ainsi que l'harmonie vocalique, le dévanagari nécessite une passe de réorganisation indic selon UAX #38, et aucun des deux ne correspond à l'algorithme de parcours à 4 positions de style syriaque. La mise en forme syriaque automatique dans TextOut / BuildUnicode*FieldContent reste réservée à la phase 8 de la feuille de route du moteur GSUB.

2026-05-22 Version 2.119.52

  • Extension de la mise en forme pour la famille de caractères arabes : le module de mise en forme statique arabe côté serveur, version v2.85.0, couvre désormais les caractères restants de la plage Arabic Extended-A (ALEF WASLA U+0671, NOON GHUNNA U+06BA, variantes de HEH U+06C0-U+06C3), le bloc Arabic Supplement U+0750-U+077F (lettres arabes africaines utilisées dans les langues haoussa, wolofal et autres langues africaines) et la nouvelle région Arabic Extended-A U+08A0-U+08FF (arabe coranique + lettres étendues wolofal/haoussa + signes diacritiques coraniques). Les classes de liaison sont issues du fichier ArabicShaping.txt de Unicode 16.0 et sont appliquées lors de l'analyse positionnelle à quatre positions de la version v2.85.0, afin que les caractères voisins choisissent la forme correcte (init / medi / fina / isol) quel que soit le variant arabe auquel ils sont adjacents.
  • Les lettres qui possèdent des formes de présentation statiques pré-encodées dans le bloc Arabic Presentation Forms-A (U+FB50-U+FBFF) sont désormais directement mappées à ces formes, sans nécessiter un moteur de substitution OpenType (GSUB) : ALEF WASLA -> FB50/FB51 (jonction droite, deux formes), NOON GHUNNA -> FB9E/FB9F (jonction double selon Unicode, mais seulement deux formes pré-encodées ; init/medi se dégradent gracieusement en isol), HEH WITH YEH ABOVE -> FBA4/FBA5 (jonction droite, deux formes), HEH GOAL -> FBA6/FBA7/FBA8/FBA9 (jonction double, les quatre formes complètes), HEH GOAL WITH HAMZA ABOVE -> FBAA/FBAB/FBAC/FBAD (jonction double, les quatre formes complètes), TEH MARBUTA GOAL -> FBAE/FBAF (jonction droite, deux formes). Combiné avec le post-traitement obligatoire de ligature LAM-ALEF de la version 2.119.32 et le sous-ensemble de 9 lettres de base pour le persan/ourdou de la version 2.119.35, le moteur de formatage statique couvre désormais pratiquement tous les textes arabes modernes, persans, ourdous, sindhis, pachtous, kurdes, ouïghours, coraniques et arabes africains (haoussa, wolofal, etc.) sans dépendre de la table GSUB de la police.
  • Les compléments arabes (U+0750-U+077F) et la région de lettres arabes étendues A plus récente (U+08A0-U+08C7) ne disposent pas de formes de présentation statiques pré-encodées ; leurs entrées de classe de liaison permettent aux caractères voisins de se former correctement, mais les lettres elles-mêmes restent des points de code bruts et dépendent d'une police compatible GSUB (ou des API du moteur GSUB v2.119.43-50, contrôlées par l'appelant) pour leur propre mise en forme positionnelle. La région des signes diacritiques arabes étendus A (U+08CA-U+08E1, U+08E3-U+08FF), classée comme transparente (liaison de type T), est ignorée lors de l'analyse positionnelle des caractères voisins, ce qui correspond au traitement existant des harakat U+064B-U+065F. Le texte qui ne contient pas ces caractères étendus reste identique en termes de bytes à la sortie de la version v2.119.51. La mise en forme mongole/syriaque/devanagari (qui utilise des modèles de mise en forme différents de l'arabe) est réservée aux futures versions.

2026-05-22 Version 2.119.51

  • Prise en charge côté producteur de XFA (XML Forms Architecture) : PDF 1.7 §12.7.6 + §12.7.8 permet à un AcroForm de contenir une entrée /XFA en plus (ou à la place) du tableau /Fields statique. La nouvelle fonction THotPDF.AddXFAPacket (PacketName, XMLBytes) enregistre un paquet XFA nommé ; les noms typiques sont 'template' (mise en page du formulaire + scripts), 'datasets' (liaison de données), 'config' (configuration du visualiseur), 'connectionSet', 'localeSet', 'stylesheet', 'xfdf', 'xmpmeta', 'signature' et 'sourceSet'. Chaque paquet enregistré devient un flux FlateDecode compressé indirect à la fin du document, et le tableau /XFA alterne des chaînes de caractères PDF représentant les noms des paquets avec des références aux flux, dans l'ordre d'enregistrement, afin que la mise en page soit déterministe en termes de bytes. Les fonctions THotPDF.ClearXFAPackets et THotPDF.XFAPacketCount complètent l'interface de l'API.
  • Seulement une prise en charge au niveau du conteneur — HotPDF ne traite pas le code XML XFA, n'implémente pas le moteur de mise en page dynamique XFA, n'exécute pas FormCalc ou JavaScript à l'intérieur du modèle XFA et ne valide pas la structure du modèle. L'appelant crée lui-même le code XML XFA (généralement via Adobe LiveCycle Designer ou en le créant manuellement selon la spécification XFA 3.3) et HotPDF émet les octets tels quels. Les lecteurs compatibles XFA (versions antérieures d'Acrobat/Reader, FormsCentral, certains produits de bornes interactives) affichent le formulaire ; les lecteurs sans moteur XFA (Adobe Reader DC à partir de 2017, la plupart des lecteurs open source) affichent les champs AcroForm de secours si le document est un flux de travail hybride AcroForm + XFA.
  • Conformité PDF/A et PDF/X : les normes ISO 19005-1 §6.4.2 / ISO 19005-2 §6.4.2 / ISO 19005-3 §6.4.2 interdisent explicitement les formulaires XFA (le moteur de mise en page dynamique ne peut pas être archivé de manière déterministe). Les flux de travail de prépresse ISO 15930 rejettent complètement les formulaires interactifs. La fonction AddXFAPacket lève immédiatement si PDFACompliance ou PDFXCompliance n'est pas vide, avec la référence de spécification correspondante. Les noms de paquets en double provoquent une erreur. Un PacketName vide ou des XMLBytes vides provoquent une erreur. RequirePDFVersion (pdf15) augmente automatiquement la version du document. Le dictionnaire AcroForm est maintenant généré si /Fields contient au moins une entrée OU si au moins un paquet XFA a été enregistré ; les versions antérieures à v2.119.51 qui n'enregistrent aucun paquet conservent une sortie /AcroForm identique en termes de taille.

2026-05-22 Version 2.119.50

  • Fermeture du sous-ensembleur TTF pour les glyphes de substitution GSUB : la nouvelle fonction THotPDF.MarkUnicodeGlyphUsed (GID : mot) inclut un glyphe dans le sous-ensemble v2.84.0, quel que soit le fait que la table cmap contienne ou non un point de code correspondant à ce glyphe. La fermeture v2.84.0 dérive l'ensemble des glyphes utilisés de FUnicodeUsedCps via la table cmap, de sorte que chaque glyphe de substitution introduit par GSUB – alternatives stylistiques, ligatures, variantes contextuelles, l'ensemble de la sortie des API de requête de phase 1 à 6 – était auparavant invisible pour le sous-ensembleur, et le lecteur affichait .notdef à leur place. Après avoir émis n'importe quel GID renvoyé par GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst dans un flux de texte PDF, l'appelant appelle maintenant MarkUnicodeGlyphUsed (GID) une fois par GID émis pour l'inclure dans le sous-ensemble intégré.
  • L'outil est idempotent (les appels répétés avec le même GID n'ont aucun effet), robuste (les GID >= FUnicodeNumGlyphs sont ignorés silencieusement, les appels effectués avant tout RegisterUnicodeTTF n'ont aucun effet), et s'intègre à la passe de fermeture de glyphes composites v2.84.0 dans _BuildSubsetTTF : les appelants doivent uniquement marquer le GID de substitution de niveau supérieur ; les composants composites sont automatiquement récupérés par la fonction _TTFWalkCompositeClosure existante. L'ensemble est alloué de manière paresseuse lors du premier appel et est réinitialisé à vide à chaque appel de RegisterUnicodeTTF ('', nil), ainsi que le reste de l'état de l'ensemble. Avec l'intégration de la phase 9, chaque requête d'API GSUB des phases 1 à 7 peut être associée à l'émission d'un ensemble sans que les glyphes de substitution disparaissent de la police intégrée.

2026-05-22 Version 2.119.49

  • Nouvelle API de sélection de script/système de langue GSUB OpenType : cinq nouvelles méthodes publiques dans THotPDF permettent aux utilisateurs d'associer les recherches GSUB à un script et une langue spécifiques, au lieu de la méthode de repli historique vers le script DFLT/système de langue par défaut. `SetGSUBScript ('latn' / 'arab' / 'cyrl' / 'hani' / 'kana' / 'deva' / 'beng' / 'taml' / etc.)` sélectionne une balise de script OpenType ; la chaîne vide par défaut conserve le comportement de la version 2.119.43-48 (préférer 'DFLT', sinon le premier script). `SetGSUBLanguage ('ENG ' / 'TUR ' / 'AZE ' / 'JAN ' / 'KOR ' / 'ARA ' / etc., avec un espace à la fin pour remplir 4 octets)` sélectionne une balise de langue OpenType ; une chaîne vide correspond au système de langue par défaut du script. Ces deux paramètres sont conservés pour les requêtes GSUB et sont réinitialisés à une chaîne vide lors de `RegisterUnicodeTTF ('', nil)`.
  • Trois nouveaux outils d'énumération permettent de connaître les informations que la police de caractères chargée indique : `GetGSUBScripts` renvoie chaque balise de script dans l'ordre de `ScriptList` ; `GetGSUBLanguages (ScriptTag)` renvoie chaque balise de langue associée au script donné (avec un espace réservé "" à l'index 0 lorsque le script a un système de langue par défaut) ; `GetGSUBFeatures (ScriptTag, LangTag)` renvoie chaque balise de fonctionnalité (par exemple, 'liga', 'salt', 'aalt', 'ss01' à 'ss20') annoncée par le chemin (script, langue) dans l'ordre des index de fonctionnalité de `LangSys`. L'utilisation de `ScriptTag` ou `LangTag` vides utilise le même mécanisme de repli vers le premier élément par défaut/système de langue par défaut que les API de substitution, de sorte que les appelants peuvent appeler `GetGSUBFeatures ('', '')` pour énumérer les fonctionnalités du chemin par défaut sans avoir à examiner au préalable la liste des scripts.
  • Sélecteur strict par rapport à la solution de repli : lorsque SetGSUBScript est défini sur un identifiant que la police chargée n'annonce pas, les requêtes GSUB suivantes renvoient des résultats vides ou sans effet — le moteur NE revient PAS silencieusement à DFLT, de sorte que les appelants peuvent clairement déterminer que le script choisi n'est pas disponible. Lorsque SetGSUBLanguage est défini sur un identifiant non reconnu, il revient à la valeur LangSys par défaut du script, conformément à la recommandation de la spécification OpenType. Les sept méthodes de substitution GSUB existantes (GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyphCount / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst) conservent leurs signatures publiques identiques ; seuls les deux paramètres supplémentaires de l'aide interne _GSUBFindFeatureLookups sont ajoutés, et tous les sites d'appel acheminent désormais ces paramètres. Avec l'API Script / LangSys et la matrice LookupType 1 à 8, le moteur GSUB est complet pour une utilisation axée uniquement sur les fonctionnalités ; les phases de feuille de route restantes (pipeline de mise en forme automatique + outil de réduction TTF) visent l'intégration côté producteur plutôt que de nouvelles surfaces de requête.

2026-05-22 Version 2.119.48

  • OpenType GSUB Reverse Chained Contextual Single Substitution (LookupType 8) : le nouveau `THotPDF.ApplyReverseChainedContextualSubst (const InputGIDs; StartIndex; FeatureTag; out OutGID): Boolean` est le dernier type de recherche GSUB à être implémenté. Le type 8 effectue une substitution simple 1:1 sensible au contexte, où le glyphe de substitution est sélectionné par l'index de couverture du glyphe d'entrée, et sa caractéristique distinctive est que les appelants doivent l'appliquer dans un ordre de balayage inverse sur une séquence de plusieurs glyphes (de la fin au début), car chaque glyphe de substitution peut dépendre du contexte futur qui n'a pas encore été substitué. Cet utilitaire est un applicateur à point unique : l'appelant contrôle la boucle de balayage inverse. Les formats de couverture 1 et 2, le drapeau de recherche qui honore (saut de l'entrée, du retour arrière et de l'anticipation), et l'extension (LookupType 7) sont tous pris en charge.
  • Cas d'utilisation principal : certaines alternatives contextuelles arabes, syriaques, N'Ko ou indic dont la forme finale dépend de la forme spécifique du glyphe suivant. Certaines polices utilisent également cette fonctionnalité pour la disambiguation de séquences latines. Contrairement aux LookupType 5/6, le Type 8 ne possède pas de mécanisme de recherche imbriquée, car la substitution est intrinsèquement 1:1. Si aucune correspondance n'est trouvée, la fonction renvoie False. OutGID = InputGIDs[StartIndex] (une tentative de correspondance qui correspond au contrat de GetSingleSubstituteGlyph v2.119.43).
  • Ferme la matrice LookupType : avec la version v2.119.48, chaque type de recherche GSUB OpenType (de 1 à 8) dispose d'une capacité publique dédiée dans THotPDF. L'API de sélection de script/langue, l'intégration automatique du pipeline de mise en forme et le chargement automatique des glyphes de substitution par le sous-ensembleur TTF restent réservés aux phases 7 à 9 ; les appelants sont toujours responsables de marquer les glyphes de substitution choisis dans le sous-ensemble de police intégré et de gérer eux-mêmes la boucle de balayage inverse.

2026-05-22 Version 2.119.47

  • OpenType GSUB Substitution contextuelle + Substitution contextuelle chaînée (LookupType 5 + 6) : la nouvelle fonction THotPDF.ApplyContextualSubst (const InputGIDs; StartIndex; FeatureTag; var OutGIDs; out ConsumedLen): Boolean est un point d'entrée unique qui couvre à la fois le LookupType 5 (contexte d'entrée uniquement) et le LookupType 6 (recul / entrée / anticipation) pour tous les trois formats de sous-table : Format 1 (séquences d'ID de glyphe littéral), Format 2 (séquences de classes ClassDef) et Format 3 (séquences de tables de couverture, la forme canonique utilisée par la plupart des polices modernes). Les utilisateurs canoniques sont 'rclt' (Alternatives contextuelles requises - formes positionnelles arabes init/medi/fina/isol lorsque la police les gère via GSUB), 'clig' (Ligatures contextuelles), 'calt' (Alternatives contextuelles) et les fonctionnalités de mise en forme indic 'pres' / 'blws' / 'psts' / 'half' / 'pstf' / 'cjct'.
  • SequenceLookupRecord : lorsqu'une règle contextuelle correspond, les entrées de SequenceLookupRecord déclenchent chacune une recherche imbriquée à une position spécifique à l'intérieur de la sous-séquence d'entrée correspondante. La nouvelle fonction d'aide _GSUBApplyNestedLookup réentre dans la liste de recherche GSUB, résout de manière transparente les wrappers Extension et dirige vers les applicateurs Single (Type 1) / Multiple (Type 2) / Alternate (Type 3, première alternative) / Ligature (Type 4). Le répartiteur suit les indices des MatchPositions[] actifs afin que les entrées SequenceLookupRecord suivantes continuent de cibler les positions de travail correctes, même lorsqu'une substitution Multiple étend 1→N ou qu'une substitution de ligature réduit N→1 glyphes autour d'elles. Les recherches imbriquées de type 5 / 6 / 8 (contextuelles récursives) sont intentionnellement différées ; la plupart des polices réelles utilisent des recherches imbriquées de type 1 / 4.
  • Lorsqu'une correspondance est trouvée, la méthode renvoie True, ainsi que la séquence de glyphes de sortie qui doit remplacer InputGIDs[StartIndex..StartIndex+ConsumedLen-1]. La longueur de OutGIDs peut différer de ConsumedLen lorsque des recherches imbriquées 1→N ou N→1 sont déclenchées. ConsumedLen représente toujours la plage totale d'entrée que la règle contextuelle a absorbée (y compris les glyphes ignorés par LookupFlag entre les glyphes significatifs) ; un appel typique d'une boucle d'analyse avance de ConsumedLen et émet OutGIDs. En cas de non-correspondance, la méthode renvoie False, OutGIDs est vide, et ConsumedLen = 1, ce qui correspond au même contrat de fonctionnement sûr que les fonctions auxiliaires v2.119.43-46. Le paramètre LookupFlag (phase 4) s'applique tout au long de la correspondance contextuelle : les parcours de retour arrière, d'entrée et de prévision ignorent tous les glyphes marqués comme devant être ignorés. Les paramètres Script / LangSys restent fixés à la valeur par défaut DFLT pour cette portion ; l'API de sélection est applicable à la phase 7.

2026-05-22 Version 2.119.46

  • Les tables de substitution d'extension GSUB (LookupType 7) : le moteur GSUB décompresse désormais de manière transparente les sous-tables de substitution d'extension, qui constituent une couche d'indirection définie par la spécification OpenType pour les polices trop volumineuses dont la sous-table de substitution réelle se trouve au-delà de la portée des 16 bits de l'Offset16 de la LookupList. Chaque API publique v2.119.43-45 (GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyphCount / GetAlternateGlyph / ApplyLigatureSubstitution) suit automatiquement l'indirection 32 bits vers la véritable sous-table LookupType 1 / 2 / 3 / 4. Il s'agit du changement de disposition binaire qui permet le fonctionnement des polices CJK / Indic OpenType volumineuses (Noto Sans CJK, Noto Sans Devanagari, etc.) dont les tables GSUB dépassent 64 Ko et qui utilisaient depuis longtemps des wrappers LookupType 7 pour leurs recherches ; auparavant, ces polices apparaissaient comme ne comportant aucune fonctionnalité dans HotPDF.
  • Analyse de la table GDEF (définition des glyphes) d'OpenType : RegisterUnicodeTTF met désormais en cache la table GDEF de la police lorsqu'elle est présente. Trois sous-tables GDEF contrôlent la logique de respect des LookupFlag : GlyphClassDef classe chaque GID comme base (1) / ligature (2) / marque (3) / composant (4) ; MarkAttachClassDef attribue à chaque glyphe de marque une classe d'attachement ; MarkGlyphSetsDef (v1.2+) déclare des ensembles nommés de glyphes de marque. Les formats de ClassDef 1 (startGlyphID + classValueArray) et 2 (classRangeRecords triés) sont tous deux implémentés ; tous les en-têtes GDEF v1.0 / v1.1 / v1.2 sont acceptés (l'élément itemVariationStore de v1.3 est ignoré). Pour les polices qui ne possèdent pas de table GDEF, le comportement par défaut de v2.119.43-45 est utilisé ("aucun glyphe n'est ignoré"), ce qui permet de préserver une sortie identique pour les applications qui utilisent des polices dépourvues de GDEF.
  • OpenType GSUB : respect des indicateurs : toutes les API publiques GSUB prennent désormais en compte l'indicateur LookupFlag de chaque table de recherche (et le uint16 optionnel trailing markFilteringSet lorsque LookupFlag.useMarkFilteringSet est défini) et ignorent les glyphes d'entrée marqués pour être ignorés. Les bits d'indicateur définis dans la spécification sont respectés : 0x0002 ignoreBaseGlyphs (ignore la classe 1 de GDEF.GlyphClassDef), 0x0004 ignoreLigatures (ignore la classe 2), 0x0008 ignoreMarks (ignore la classe 3), 0x0010 useMarkFilteringSet (seuls les marqueurs de MarkGlyphSet spécifié participent) et le byte de poids élevé markAttachmentType (seuls les marqueurs de la classe MarkAttachClassDef demandée participent). Pour la substitution de ligatures (LookupType 4), c'est le changement le plus important : les ligatures arabes 'rlig' / indic 'akhn' dont les composants sont séparés par des glyphes de marque (par exemple, LAM + Fatha + ALEF) correspondent désormais correctement lorsque l'indicateur LookupFlag.ignoreMarks est défini, et le ConsumedCount renvoyé inclut les marqueurs ignorés, de sorte que la boucle de lecture de l'appelant avance au-delà de chaque glyphe d'entrée absorbé. Le bit 0x0001 (rightToLeft) est spécifique à GPOS et reste ignoré pour les recherches GSUB.
  • Les mêmes règles de sécurité s'appliquent : les polices sans table GSUB, les appels avec une balise non de 4 octets, les fonctionnalités que le script DFLT de la police ne prend pas en charge, les GID pour lesquels aucun sous-tableau n'est disponible, et maintenant les glyphes ignorés par LookupFlag renvoient tous le résultat sûr et sans effet secondaire de la version v2.119.43-45. Les cinq signatures d'API publiques sont stables en termes de taille des octets ; seule la recherche interne prend en charge la gestion des extensions, le respect de LookupFlag et la classification GDEF. L'API de sélection de script/langue, l'intégration automatique du pipeline de mise en forme et l'extraction automatique de glyphes de substitution par le sous-ensembleur TTF restent réservées aux futures versions.

2026-05-22 Version 2.119.45

  • OpenType GSUB Ligature Substitution (LookupType 4) : la nouvelle fonction THotPDF.ApplyLigatureSubstitution (const InputGIDs: array of Word; StartIndex; FeatureTag; out OutGID; out ConsumedCount): Boolean regroupe une séquence de plusieurs glyphes en un seul glyphe de ligature. Les utilisateurs canoniques sont 'liga' (Ligatures standard — fi / fl / ffi / ffl), 'clig' (Ligatures contextuelles), 'dlig' (Ligatures discrétionnaires), 'hlig' (Ligatures historiques), 'rlig' (Ligatures obligatoires — LAM-ALEF arabe et similaires lorsque la police contrôle la mise en forme via GSUB), et les fonctionnalités de ligature des scripts indic ('akhn', 'pres', 'blws', 'psts'). L'appelant transmet la séquence d'ID de glyphe post-cmap et une position de départ basée sur 0 ; en cas de correspondance complète, l'aide renvoie True, OutGID = le glyphe de remplacement de la ligature et ConsumedCount = le nombre total de composants d'entrée consommés (>= 2 en pratique). En cas de non-correspondance, renvoie False, OutGID = 0, ConsumedCount = 1, afin que l'appelant puisse avancer d'une étape et continuer la recherche. L'implémentation respecte la convention OpenType selon laquelle les entrées LigatureSet sont généralement listées de la plus longue à la plus courte, ce qui permet aux polices ayant des préfixes qui se chevauchent (par exemple, une ligature 'ffi' à trois composants et une ligature 'ff' à deux composants) d'obtenir la correspondance la plus longue. Même contrat de sécurité que les fonctions v2.119.43/.44 : une balise vide ou non de 4 octets, aucune GSUB, fonctionnalité non annoncée, StartIndex hors plage et aucune sous-table LookupType 4 correspondant à la position renvoient tous l'opération sans effet (False / OutGID = 0 / ConsumedCount = 1). Le saut de marque LookupFlag, l'intégration GDEF GlyphClassDef, l'application automatique lors de l'émission de texte et l'extraction automatique des glyphes de ligature par le sous-ensembleur TTF sont réservés aux futures versions.

2026-05-22 Version 2.119.44

  • OpenType GSUB Substitution multiple (LookupType 2) : la nouvelle fonction THotPDF.GetMultipleSubstituteGlyphs (InputGID, FeatureTag, var OutGIDs) renvoie un glyphe d'entrée sous forme d'une séquence de glyphes de substitution. L'utilisateur principal est la fonctionnalité de composition/décomposition de glyphes 'ccmp', qui divise les lettres latines accentuées précomposées en base + marques de combinaison pour le positionnement des marques en aval. Cette fonction parcourt le même chemin DFLT (script par défaut / LangSys par défaut / FeatureList / LookupList) que GetSingleSubstituteGlyph v2.119.43 et applique chaque sous-table LookupType 2 associée à la fonctionnalité demandée pour InputGID ; la première correspondance l'emporte. OutGIDs est réinitialisé au début, de sorte que les appelants n'ont pas besoin de le vider à l'avance. Une séquence vide (glyphCount = 0, suppression canonique du glyphe Unicode) autorisée par la spécification est signalée comme Result = True avec Length(OutGIDs) = 0, afin que l'appelant puisse supprimer le glyphe d'entrée de la séquence.
  • OpenType GSUB Substitution alternative (LookupType 3) : deux nouvelles méthodes exposent le cycle complet des glyphes alternatifs pour les caractéristiques stylistiques. `THotPDF.GetAlternateGlyphCount (InputGID, FeatureTag)` renvoie le nombre de formes alternatives qu'une police offre pour `InputGID` sous `FeatureTag`, et `THotPDF.GetAlternateGlyph (InputGID, FeatureTag, AlternateIndex)` renvoie le glyphe alternatif à l'index demandé, en commençant à 0. Les utilisateurs principaux sont 'aalt' (toutes les alternatives), 'salt' (alternatives stylistiques), 'titl' (alternatives de titrage) et 'ss01' à 'ss20' (ensembles stylistiques 1 à 20) lorsqu'ils sont associés à `LookupType 3` au lieu de `LookupType 1` ; dans la version 2.119.43, `GetSingleSubstituteGlyph` ignorait silencieusement ces sous-tables, de sorte que les appelants de 'aalt' ne voyaient auparavant que les remplacements transitifs de `LookupType 1`. Cette paire permet aux appelants de parcourir les cycles de glyphes décoratifs (différentes formes de 'a', 'g', '7'), les variantes de majuscules et les alternatives d'ensembles stylistiques de manière explicite. Si `AlternateIndex` est hors de portée ou négatif, `InputGID` est renvoyé inchangé, ce qui permet aux appelants de vérifier en toute sécurité.
  • Les deux fonctions respectent le même contrat de sécurité que v2.119.43 : les polices sans table GSUB, les appels qui passent une balise non valide de 4 octets, les fonctionnalités que le script DFLT de la police ne déclare pas, et les GID pour lesquels la sous-table LookupType 2 / 3 ne couvre pas tous, renvoient l'opération sans effet sécurisée (False + OutGIDs vides pour Multiple ; 0 / InputGID pour Alternate). Les sous-tables LookupType 1 / 4-8 rencontrées dans la chaîne de recherche de la fonctionnalité sont ignorées silencieusement dans cette version. Le filtrage par marque, l'intégration de GDEF GlyphClassDef, l'API de sélection de script / LangSys, l'intégration automatique du pipeline de mise en forme et l'extraction automatique des glyphes de substitution sélectionnés par le sous-ensembleur TTF restent réservés aux futures versions ; les appelants sont toujours responsables de marquer les glyphes choisis dans le sous-ensemble de la police intégrée.

2026-05-22 Version 2.119.43

  • OpenType GSUB : la nouvelle fonction THotPDF.GetSingleSubstituteGlyph (InputGID, FeatureTag) parcourt la chaîne GSUB ScriptList / FeatureList / LookupList de la police, en utilisant le LangSys par défaut du script DFLT, et applique chaque sous-table de type LookupType 1 (substitution simple) associée à la fonctionnalité demandée, renvoyant l'ID du glyphe substitué. Les balises de fonctionnalité de substitutions stylistiques les plus courantes sont 'salt' (substitutions stylistiques), 'ss01' à 'ss20' (ensembles stylistiques 1 à 20), 'aalt' (utiliser toutes les substitutions), 'titl' (substitutions pour les titres), 'subs' / 'sups' (indices / exposants), 'frac' (fractions) et 'ordn' (ordonnaux) ; toute balise de fonctionnalité OpenType de 4 octets dont la chaîne de fonctionnalités contient des sous-tables de type LookupType 1 est prise en charge. Les formats de couverture 1 (tableau de glyphes trié, recherche binaire) et 2 (enregistrements de plage) sont tous pris en charge. Les formats de substitution simple 1 (delta) et 2 (tableau de substitution) sont tous les deux implémentés. RegisterUnicodeTTF met désormais en cache le décalage/la longueur de la table GSUB, ainsi que la table cmap, afin que les recherches GSUB au moment de la requête n'impliquent pas de relecture du répertoire de la table. Si une police ne possède pas de table GSUB, si l'appelant transmet une balise de 4 octets que le script DFLT de la police n'annonce pas, ou si les GID ne sont pas présents dans la couverture de la recherche, l'ID d'entrée est renvoyé inchangé, ce qui rend l'API sûre à appeler comme une substitution ou un passage en mode "passthrough". Les sous-tables de type LookupType 2 à 8 rencontrées sur la chaîne de recherche de la fonctionnalité sont ignorées silencieusement dans cette première version ; les chaînes de substitutions multiples / substitutions alternatives / substitutions de ligatures et l'intégration du pipeline de mise en forme automatique sont réservées aux futures versions.

2026-05-22 Version 2.119.42

  • AcroForm : les ressources /DR acceptent désormais plusieurs polices Unicode. Dans la version 2.56.0, SetFormUnicodeFontDict ne suit qu'une seule police fournie par l'appelant, qui devient la police par défaut de l'AcroForm /DA ; les formulaires multilingues nécessitant des scripts différents par champ (arabe + CJK + latin dans un même PDF) devaient définir manuellement le dictionnaire /DR /Font. La nouvelle fonction THotPDF.RegisterAcroFormFont (LogicalName, FontDict) enregistre une police Unicode supplémentaire sous n'importe quel nom logique, la rend disponible pour les chaînes /DA par champ (/ 12 Tf) et l'émet dans le dictionnaire /DR /Font de l'AcroForm, à côté de la police par défaut de la version 2.56.0. L'ordre d'enregistrement est conservé, ce qui rend le /DR émis déterministe. Les conflits de noms avec la police par défaut de SetFormUnicodeFontDict ou une police précédemment enregistrée génèrent une erreur avec le nom en cause. Un LogicalName vide ou un FontDict nul génèrent également une erreur. Le chemin de réinitialisation de SetFormUnicodeFontDict ('', nil) efface également l'enregistrement des polices supplémentaires, ce qui permet de démarrer un nouveau flux de travail Unicode à partir d'un état propre et connu. Autorisé dans tous les niveaux PDF/A / PDF/X : les polices Unicode composites sont des métadonnées structurelles du formulaire, et non des scripts interactifs.

2026-05-22 Version 2.119.41

  • Énumération de types de structure standard couvrant le tableau 333 de la section 14.8.4 de la norme PDF 1.7 : la nouvelle énumération THPDFStandardStructureType répertorie les environ 40 rôles de structure prescrits par la norme, regroupés par leur catégorie de rôle PDF (Groupement : Document / Part / Art / Sect / Div / BlockQuote / Caption / TOC / TOCI / Index / NonStruct / Private ; Niveau bloc : H / H1-H6 / P / L / LI / Lbl / LBody / Table / TR / TH / TD / THead / TBody / TFoot ; Niveau inline : Span / Quote / Note / Reference / BibEntry / Code / Link / Annot ; Ruby + Warichu : Ruby / RB / RT / RP / Warichu / WT / WP ; Illustration : Figure / Formula / Form). Deux fonctions utilitaires de niveau unitaire convertissent l'énumération en noms PDF exacts selon la norme : StandardStructureTypeToName (T) renvoie le nom sensible à la casse utilisé comme clé /S de l'élément de structure, et IsStandardStructureType (Name) teste une chaîne Ansi arbitraire par rapport à l'ensemble standard, afin que les appelants puissent vérifier les noms de rôle personnalisés et les acheminer via AddStructRoleMap si nécessaire. Une nouvelle surcharge de l'énumération AddStructureElement accepte directement THPDFStandardStructureType, éliminant ainsi l'erreur de frappe / le risque de sensibilité à la casse ('Para' par rapport à 'P', 'Lbody' par rapport à 'LBody') des surcharges de chaînes ouvertes, tout en transmettant l'appel à la même implémentation de base. Les surcharges existantes basées sur des chaînes Ansi restent identiques en termes d'octets pour les appelants utilisant des noms personnalisés ou acheminés via RoleMap.

2026-05-22 Version 2.119.40

  • Structure element attribute setters : trois nouvelles fonctions permettent de définir les attributs de chaîne de texte PDF pour chaque élément, qui sont associés aux versions v2.88.0 /Alt + /ActualText et v2.95.0 /ID. THotPDF.SetStructureElementLanguage (Elem, BCP-47 Lang) écrit PDF 1.7 §14.9.2 /Lang, remplaçant la langue par défaut du document pour le contenu situé sous cet élément, jusqu'à ce qu'une autre langue soit spécifiée. Cette fonction est généralement utilisée pour les passages cités dans une autre langue ou les sections de contenu mixte. THotPDF.SetStructureElementExpansionText (Elem, ExpansionText) écrit §14.9.5 /E, qui est l'expansion de l'abréviation lue par les lecteurs d'écran à la place d'un acronyme (par exemple, 'NASA' → 'National Aeronautics and Space Administration'), et la valeur extraite lors de l'extraction de contenu. THotPDF.SetStructureElementTitle (Elem, Title) écrit §14.7.5.2 /T, qui est le titre lisible par l'homme qui distingue l'élément des éléments frères de même rôle dans l'arborescence de structure (le volet "Tags" d'Acrobat affiche /T à côté du nom du rôle). Les trois fonctions sont de simples setters, avec une sémantique "no-op" si la valeur est vide, une valeur nil pour Elem lève une exception, et sont autorisées dans tous les niveaux PDF/A et PDF/X, car les clés sont des métadonnées structurelles.

2026-05-22 Version 2.119.39

  • AcroForm : complétion de la famille de déclencheurs de champs de formulaire : trois nouveaux outils rejoignent AttachFieldKeyStrokeAction (v2.119.37) pour fermer PDF 1.7 §12.7.5.3 Tableau 246. THotPDF.AttachFieldFormatAction installe /AA /F (événement de formatage, se déclenche lorsque la valeur affichée du champ doit être reformattée après une validation – l'utilisation typique est d'appliquer des masques de devise, de date ou de séparateurs de milliers via AFNumber_Format / AFDate_FormatEx). THotPDF.AttachFieldValidateAction installe /AA /V (événement de validation, se déclenche après que l'utilisateur a saisi une nouvelle valeur – l'utilisation typique est de vérifier la plage ou de valider l'entrée par expression régulière via event.rc := false). THotPDF.AttachFieldCalculateAction installe /AA /C (événement de calcul, se déclenche lorsque tout champ de dépendance change selon l'ordre de calcul du catalogue /AcroForm /CO – l'utilisation typique est de calculer des totaux ou des taxes). Les quatre outils partagent la même recherche FFormFields /T, la même sémantique de remplacement idempotent (le dernier appel l'emporte) et les mêmes protections JavaScript PDF/A + PDF/X. Les autres clés de déclenchement du même dictionnaire /AA (les déclencheurs d'annotations /E /X /D /U /Fo /Bl et les trois déclencheurs de champs de formulaire frères) sont préservés et inchangés. Refactorisation interne : AttachFieldKeyStrokeAction délègue désormais à un outil partagé _InstallFieldTriggerJSAction ; les appels existants v2.119.37 voient des messages d'exception identiques.

2026-05-22 Version 2.119.38

  • RegisterUnicodeTTF capture désormais les correspondances entre les points de code du plan multilingue supplémentaire (SMP, U+10000-U+10FFFF) et les glyphes à partir de la sous-table de format 12 de la table cmap de la police chargée. Les versions précédentes ignoraient silencieusement les entrées SMP car la recherche de point de code vers glyphe était un tableau de taille BMP ; v2.119.38 ajoute une liste creuse parallèle (FUnicodeCpToGidSMP) qui est remplie en parallèle avec le tableau BMP. La nouvelle méthode publique GetUnicodeGlyphForCodepoint(Cp) renvoie l'ID du glyphe pour n'importe quel point de code Unicode jusqu'à U+10FFFF (effectue une recherche binaire dans la liste SMP pour les points de code supérieurs au BMP), ou 0 (.notdef) lorsque le point de code n'est pas mappé dans la table cmap de la police chargée. Il s'agit d'une fonctionnalité uniquement : le pipeline d'encodage hexadécimal côté producteur, le flux /CIDToGIDMap et la carte CMap ToUnicode restent ancrés au BMP, de sorte que l'écriture d'un caractère SMP dans un flux de texte PDF nécessite toujours que les appelants émettent eux-mêmes des paires de substitution UTF-16BE. L'émission complète de flux de texte prenant en charge les paires de substitution est réservée à une version ultérieure. Les polices au format 4 ne reçoivent qu'une liste SMP vide, comme prévu.

2026-05-22 Version 2.119.37

  • Nouvelle fonction d'assistance pour les déclencheurs de touches AcroForm : THotPDF.AttachFieldKeyStrokeAction(FieldName, JavaScriptBody) localise le widget de formulaire nommé par sa valeur /T et installe une action JavaScript /AA /K afin que les lecteurs PDF exécutent le script à chaque pression de touche pendant la saisie de texte. Les cas d'utilisation incluent la validation des entrées en temps réel (numérique, date, regex), le masquage des entrées et les mises à jour des champs calculés déclenchées par des modifications dans un autre champ. Cette fonction est idempotente : les appels répétés remplacent l'entrée /K tout en préservant les autres touches de déclenchement déjà présentes dans le même dictionnaire /AA (format /F, validation /V, recalcul /C, flou /Bl, focus /Fo, etc.). Les niveaux PDF/A (ISO 19005-1 §6.6.1, -2/-3 §6.5.1) et les niveaux PDF/X (ISO 15930 préimpression) interdisent les actions JavaScript, donc cette fonction génère immédiatement une erreur avec la référence de spécification pertinente si l'un de ces indicateurs de conformité n'est pas vide. Cette fonctionnalité est basée sur le dictionnaire d'événements de déclenchement PDF 1.7 §12.6.3 et le champ /K de la table 246 des formulaires §12.7.5.3.

2026-05-22 Version 2.119.36

  • `BeginTaggedContent` accepte désormais quatre propriétés optionnelles de séquence de contenu marqué (Lang / Alt / ActualText / ExpansionText) selon la section 14.8.4 du tableau 322 de la spécification PDF 1.7 et les émet comme un seul dictionnaire de propriétés BDC en ligne, en plus de l'entrée MCID existante. `Lang` contient l'étiquette de langue naturelle BCP-47 pour le segment (utilisée par les lecteurs d'écran et l'extraction de texte sensible à la langue) ; `Alt` est la description alternative pour les segments non textuels ou décoratifs ; `ActualText` est le texte de remplacement utilisé par l'extraction de contenu et le copier-coller à la place de la séquence de glyphes visuelle (essentiel pour les ligatures et les glyphes stylisés où le caractère visible diffère du texte sémantique sous-jacent) ; `ExpansionText` contient la clé `/E` qui développe les abréviations. Les paramètres vides permettent de sauter l'entrée correspondante, de sorte que le dictionnaire en ligne ne contienne que les clés que l'appelant remplit explicitement, et le chemin d'appel existant à deux arguments reste identique en termes de bytes à la sortie v2.119.35. L'échappement automatique des chaînes littérales PDF (parenthèses et antislash) est automatique ; pour les charges utiles non-ASCII (ActualText CJK, Alt Indic, etc.), les appelants pré-encodent leurs octets en UTF-16BE avec le BOM U+FEFF et empaquettent le résultat dans l'argument AnsiString. L'API de flux de page de bas niveau correspondante `BeginMarkedContentMCIDProps` est également exposée pour les appelants qui ont besoin d'un contrôle direct du BDC sans le câblage de `StructElem` de haut niveau.

2026-05-22 Version 2.119.35

  • L'ensemble de caractères de base "Arabic Extended-A" comprenant 9 lettres persanes/ourdou est désormais intégré au module de formation de texte à quatre positions côté serveur dans la version v2.85.0. Lorsque "AutoShapeArabic" est activé, les lettres suivantes sont mappées à leurs glyphes "Arabic Presentation Forms-A" correspondants (U+FB50-U+FBFF) en utilisant le même algorithme de contexte de liaison que celui utilisé pour le bloc arabe de base : PEH U+067E, TCHEH U+0686, JEH U+0698, KEHEH U+06A9, GAF U+06AF, FARSI YEH U+06CC (noyau persan), ainsi que TTEH U+0679, DDAL U+0688, RREH U+0691 (noyau rétroflexe ourdou). Les lettres à double liaison exposent l'ensemble complet isolé/final/initial/médial ; les lettres à liaison droite (JEH / DDAL / RREH) exposent uniquement les formes isolées/finales, conformément au modèle de formation de texte arabe. Les autres lettres "Arabic Extended-A" (ALEF WASLA U+0671, NOON GHUNNA U+06BA, variantes de HEH U+06C0-U+06C3, supplément arabe complet U+0750-U+077F) restent inchangées et seront traitées dans une version ultérieure. Le texte arabe non persan/ourdou reste identique à la sortie de la version v2.119.34.

2026-05-22 Version 2.119.34

  • La gestion des noms de PDF décode désormais les séquences d'échappement ISO 32000-1 #XX lors de l'importation ou de la copie d'objets PDF. Les noms de ressources, les noms de couleurs spéciales, les noms de rôles de structure et d'autres objets de noms, tels que /PANTONE#20216#20CVC, transitent désormais par HotPDF avec leurs valeurs d'octets prévues, au lieu d'être recopiés avec un signe dièse double.

2026-05-22 Version 2.119.33

  • La gestion des dates PDF suit désormais plus étroitement les règles des chaînes de date définies dans la norme ISO 32000-1. Les informations du document, les dates dérivées de XMP et les horodatages des signatures utilisent désormais la valeur TDateTime fournie par l'appelant, au lieu de remplacer silencieusement par l'heure actuelle, tandis que l'analyseur accepte les champs de date optionnels standard et les suffixes de fuseau horaire sans corrompre les champs de date/heure locaux.
  • Le filtre d'importation PDF dispose désormais de fonctions explicites pour ASCIIHexDecode, ASCII85Decode et RunLengthDecode, et la valeur par défaut de LZWDecode "EarlyChange" correspond désormais à la valeur par défaut de PDF, qui est 1. Cela améliore la compatibilité avec les pages importées ou copiées qui utilisent les anciens filtres de flux PDF.

2026-05-21 Version 2.119.32

  • Les ligatures obligatoires de LAM-ALEF sont désormais intégrées au moteur de mise en forme côté serveur dans la version v2.85.0. Lorsque AutoShapeArabic est activé, toute séquence de U+0644 LAM (sous sa forme brute ou l'une de ses quatre formes mises en forme FEDD-FEE0) suivie d'une des quatre variantes d'ALEF (MADDA U+0622, HAMZA-above U+0623, HAMZA-below U+0625, simple U+0627 ; sous forme brute ou après mise en forme) se transforme en un seul glyphe de ligature du bloc U+FEF5-U+FEFC. La forme de ligature connectée ou isolée est sélectionnée en fonction de si le LAM a été mis en forme en une forme finale (FEDE) ou médiale (FEE0) par le mécanisme de mise en forme à quatre positions. Les autres ligatures obligatoires arabes (Allah U+FDFB et les ligatures honorifiques décoratives) nécessitent toujours un moteur GSUB complet et restent en dehors de la portée du modèle de mise en forme à table statique. Le texte non LAM-ALEF et les appels avec AutoShapeArabic désactivé restent identiques à la sortie de la version v2.119.31. Trois utilitaires AcroForm Unicode /AP (monoligne, multiligne, combinaison) héritent automatiquement de ce changement via le point d'entrée partagé _ApplyArabicShaping.

2026-05-21 Version 2.119.31

  • Nouveau module d'exportation dxHotPDFExportReportLinkToFile / dxHotPDFExportReportLinkToStream pour le système ExpressPrinting de DevExpress : ces modules prennent n'importe quel objet TBasedxReportLink (la famille d'interfaces qui relie cxGrid, cxRichEdit, cxScheduler, cxPivotGrid et des composants imprimables similaires à TdxComponentPrinter) et acheminent chaque page rendue via HotPDF au lieu du module d'émission dxPSExportToPDF de DevExpress. Le module reflète la boucle d'exportation interne de DevExpress : reconstruire le rapport, puis pour chaque page, dessiner la page sur un TMetafileCanvas, puis afficher le métafichier amélioré dans HotPDF. Les options enregistrées exposent les champs Titre, Auteur, Sujet, Mots-clés, PDFVersion, Compression et RenderDPI. Ce module a les mêmes limitations que les modules FastReport, QuickReport et ReportBuilder : pas de champs AcroForm, pas de plans, pas de conformité PDF/A ou PDF/X. Le module se trouve dans Lib/Addons/DevExpress/ et ne fait pas partie du fichier HotPDF*.dpk principal.

2026-05-20 Version 2.119.30

  • Nouvelle classe de périphérique ReportBuilder : `TppHotPDFDevice` hérite de `TppGraphicsDevice`, ce qui lui permet de s'intégrer à la chaîne standard de publication → périphérique de ReportBuilder lorsqu'elle est affectée à `TppReport.PrinterDevice` ou à `TppPublisher.Device`. Chaque page est rendue sur un `TMetafileCanvas` temporaire (créé dans `BeforeRenderPage`, finalisé dans `AfterRenderPage`), capturée sous forme de `TMetafile` et acheminée via l'importateur EMF de HotPDF (`HPDFEmf.ShowEnhancedMetafile`). Les propriétés exposent les champs Titre / Auteur / Sujet / Mots-clés / `PDFVersion` / `CompressionLevel` / `Compressed` ; `SetOutputStream` envoie les octets PDF à un `TStream` fourni par l'appelant. Les mêmes limitations que les adaptateurs FastReport / QuickReport : pas de champs AcroForm, pas de plans, pas de profils PDF/A / PDF/X. L'adaptateur se trouve dans `Lib/Addons/ReportBuilder/` et ne fait pas partie du fichier `HotPDF*.dpk` principal.

2026-05-20 Version 2.119.29

  • Nouveau filtre d'exportation QuickReport : `TQRHotPDFExportFilter` dérive de `TQRExportFilter`, ce qui lui permet de s'intégrer au flux de travail standard `MyReport.ExportToFilter(MyFilterInstance)` sans modification du cœur de QuickReport. L'adaptateur récupère les métafichiers par page que QuickReport met déjà en cache dans `QRPrinter.PageList` et envoie chacun via l'importateur EMF de HotPDF (`HPDFEmf.ShowEnhancedMetafile`). Les propriétés exposent le titre, l'auteur, le sujet, les mots-clés, la version PDF, le niveau de compression et l'option de compression. `SetOutputStream` dirige les octets PDF vers un flux fourni par l'appelant au lieu du disque. Les mêmes limitations concernant les métafichiers que l'adaptateur FastReport : pas de champs AcroForm, pas de plans, pas de profils PDF/A / PDF/X. L'adaptateur se trouve dans le répertoire `Lib/Addons/QuickReport/` et ne figure pas dans le fichier `HotPDF*.dpk` principal.

2026-05-20 Version 2.119.28

  • Nouveau module d'exportation FastReport 4 / FastReport VCL : `TfrxHotPDFExport` dérive de `TfrxCustomExportFilter`, ce qui lui permet de s'intégrer au flux de travail standard `MyReport.Export(MyExportInstance)` sans modification du cœur de FastReport. Le module dirige chaque page préparée vers l'importateur EMF de HotPDF (via `TfrxPreviewPages.DrawPage` de FastReport → `TMetafileCanvas` → `HotPDF.ShowEnhancedMetafile`), de sorte que le contenu vectoriel et matriciel de la page, rendu par le moteur de mise en page standard de FastReport, est préservé sans code d'émission spécifique à chaque objet. Les propriétés permettent de contrôler le titre, l'auteur, le sujet, les mots-clés, la version PDF, le niveau de compression et la résolution de rendu du PDF résultant. Limitations : pas de champs AcroForm, pas de plans, pas de profils PDF/A / PDF/X (ceux-ci nécessitent un pipeline d'émission spécifique à chaque objet, prévu pour une version ultérieure). Le module est fourni dans le répertoire `Lib/Addons/FastReport4/` et NE se trouve PAS dans le fichier `HotPDF*.dpk` principal ; les utilisateurs doivent l'ajouter à leur propre projet, en plus du package FastReport correspondant.

2026-05-20 Version 2.119.27

  • Nouvelle fonctionnalité de signature PDF basée sur PFX, de bout en bout : `THotPDF.SignPDFWithPFX(InputPDFPath, OutputPDFPath, PFXFilePath, Password)`. Cette fonction charge un fichier PDF non signé qui contient déjà un espace réservé `AddSignedSignatureField`, analyse le fichier PFX / PKCS#12, construit une structure CMS SignedData (RFC 5652) complète sur les octets couverts par `/ByteRange`, et écrit le fichier PDF signé en une seule opération. Une surcharge basée sur `TStream` est également disponible pour les workflows en mémoire. La taille du budget `/Contents` du PDF doit être suffisamment grande pour contenir l'hexadécimal DER de la structure CMS ; par défaut, 8192 octets suffisent pour les clés RSA de 1024/2048 bits. Seuls les fichiers PFX utilisant PBES2 + AES-256-CBC sont pris en charge (limite du parseur PKCS#12 v2.119.26).
  • Nouvelle unité HPDFCMS : constructeur SignedData pour CMS. HPDFCMSBuildSignedData assemble ContentInfo → SignedData → SignerInfo avec contenu détaché id-data, attributs signés (contentType + messageDigest + signingTime, triés par ordre croissant DER selon RFC 5652 §5.4), identifiant de signataire IssuerAndSerialNumber extrait du certificat X.509, algorithme de signature RSA + SHA-256, et le certificat X.509 encapsulé dans [0] certificats IMPLICITES. Expose également HPDFCMSSHA256ByteRanges pour le calcul de digests en deux fenêtres en streaming et HPDFCMSBytesToHex pour l'injection de marqueurs /Contents. Complète la pile de signature interne initiée avec HPDFASN1 (v2.119.23) + HPDFRSA (v2.119.24) + extensions HPDFCrypt (v2.119.25) + HPDFPFX (v2.119.26).

2026-05-20 Version 2.119.26

  • Nouvelle unité HPDFPFX : analyseur de conteneurs PKCS#12 / PFX. Lit les fichiers .pfx / .p12 à partir d'OpenSSL ≥ 3.0, de certutil pour Windows 11+ et de Keychain Access pour macOS, déchiffre les charges utiles SafeBag PBES2 (PBKDF2-HMAC-SHA-256 + AES-256-CBC) et extrait les paramètres de la clé privée RSA et du certificat X.509 au format DER. Renvoie un enregistrement THPDFPFXKeyMaterial contenant CertDER, Modulus, PublicExponent et PrivateExponent, que le code de signature CMS ou d'autres applications peut utiliser directement. Un mot de passe incorrect est détecté par l'échec du dépadding PKCS#7 qui suit une mauvaise clé AES. Les anciens fichiers PBE-SHA1-3DES génèrent une erreur avec une indication claire de migration pour réexporter en utilisant les options `-keypbe AES-256-CBC -certpbe AES-256-CBC`.

2026-05-20 Version 2.119.25

  • Nouvelles primitives cryptographiques : chiffrement inverse AES-256 avec AES256DecryptBlock + AES256CBCDecryptPKCS7 + AES256CBCDecryptNoPad (FIPS-197 §5.3, complétant les fonctions de chiffrement existantes), HMAC-SHA-256 (RFC 2104) et PBKDF2-HMAC-SHA-256 (RFC 8018 §5.2). Vérifié par rapport aux vecteurs HMAC de la RFC 4231 et aux résultats de référence standard de PBKDF2-SHA-256. Combiné avec le décodeur ASN.1 de la version 2.119.23 et les primitives RSA de la version 2.119.24, cela complète la base cryptographique nécessaire pour le chemin de décryptage PBES2-AES-256 SafeBag utilisé par les fichiers PKCS#12 / PFX modernes (OpenSSL ≥ 3.0 / Windows 11+).

2026-05-20 Version 2.119.24

  • Nouvelle unité HPDFRSA : arithmétique entière multi-précision + exponentiation modulaire RSA + encodage EMSA PKCS#1 v1.5. Suffisamment grande pour signer avec des clés RSA réelles de 2048/4096 bits. Combinée au décodeur ASN.1 de la version 2.119.23, elle complète les primitives cryptographiques nécessaires pour la future chaîne de signature PDF basée sur PFX. Aucune API utilisateur n'utilise encore ceci ; il s'agit d'une infrastructure interne en attente des couches PKCS#12 + CMS.

2026-05-20 Version 2.119.23

  • Nouvelle unité HPDFASN1 : un décodeur BER/DER compact pour le sous-ensemble ASN.1 dont HotPDF a besoin pour lire les magasins de clés PKCS#12, les certificats X.509 et les conteneurs CMS/PKCS#7 SignedData. Elle expose THPDFASN1Node (descripteur Tag-Length-Value analysé), les accesseurs THPDFASN1ParseNode / ParseAt, Content / ToInteger / ToBigInt / ToOID / ToString, et les itérateurs FirstChild / NextSibling / Children. Elle rejette explicitement les formes BER de longueur indéfinie et les encodages avec des numéros de balises élevés (>= 31), reflétant le sous-ensemble strict de DER. Il s'agit d'une infrastructure interne pour le pipeline de signature PFX intégré qui arrivera dans les prochaines versions ; aucune API destinée aux utilisateurs n'en dépend pour le moment.

2026-05-20 Version 2.119.22

  • Nouvelles versions surchargées pour les annotations PolyLine et Polygon avec des métadonnées complètes : THPDFPage.AddPolylineAnnotation et AddPolygonAnnotation gagnent deux nouvelles versions qui acceptent un tableau de sommets THPDFCurrPoint et un enregistrement THPDFPolyExtras facultatif. L'enregistrement extras expose les entrées facultatives ISO 32000-1 §12.5.6.9, notamment /IC (couleur intérieure), /BE (bordure nuageuse, avec /I (intensité)), /IT (intention : PolyLineDimension, PolyLineFlight, PolygonCloud, PolygonDimension) et /LE (styles de terminaison de ligne) pour PolyLine. Utilisez HPDFDefaultPolyExtras() pour obtenir un enregistrement initialisé à zéro. Les nouvelles versions vérifient qu'au moins deux sommets sont fournis et incrémentent automatiquement la version du document (PDF 1.5 / 1.6 / 1.7 en fonction de l'intention). Les versions précédentes, qui combinaient Single, continuent de compiler sans modification.

2026-05-20 Version 2.119.21

  • Nouvelles fonctionnalités pour l'annotation "Ligne" : la fonction `AddLineAnnotation` reçoit une troisième surcharge qui accepte un enregistrement `THPDFLineExtras` permettant de contrôler les entrées optionnelles du tableau 175 de la section §12.5.6.7 de la norme PDF 1.6/1.7 — notamment, la couleur intérieure (/IC) pour les têtes de flèche et les losanges, la longueur de la ligne de guidage (/LL), l'extension de la ligne de guidage (/LLE), le décalage de la ligne de guidage (PDF 1.7) (/LLO), un indicateur de légende avec son emplacement (/CP) (/Inline ou /Top, PDF 1.7) et son décalage (/CO), ainsi que l'intention de la ligne (/IT, LineArrow / LineDimension). Utilisez `HPDFDefaultLineExtras()` pour initialiser l'enregistrement à zéro. La nouvelle surcharge met automatiquement à jour la version du document à PDF 1.6 (ou 1.7 lorsque /LLO, /CP et /CO sont demandés). Les deux anciennes surcharges continuent de produire une sortie identique en termes de bytes, et seules les entrées que l'appelant demande sont écrites.

2026-05-20 Version 2.119.20

  • Nouvelles actions de boutons "baShow" et "baImportData" : THPDFButtonAction inclut maintenant "baShow" (qui est le miroir de "baHide" et qui émet "/H false" pour réafficher un widget caché) et "baImportData" (/S /ImportData /F filespec pour charger les données du formulaire FDF au clic, ISO 32000-1 §12.7.5.4). "baShow" est autorisé selon les spécifications pour PDF/A et PDF/X ; "baImportData" est bloqué dans les deux cas, conformément à la norme ISO 19005-1 §6.6.1 et à la norme ISO 15930 pour la prépresse, respectivement.
  • Nouvelle surcharge pour masquer/afficher plusieurs champs : `THPDFPage.AddPushButtonWithHideAction(FieldName, Caption, Targets, Hide, Rectangle, Flags)` accepte un tableau de noms de champs cibles et un booléen explicite pour masquer, afin qu'un seul bouton puisse basculer la visibilité de plusieurs éléments graphiques en un seul clic. Un tableau `Targets` vide lèvera une exception. PDF/A et PDF/X prennent tous deux en charge cette surcharge (masquage de la visibilité des éléments graphiques uniquement).

2026-05-20 Version 2.119.19

  • Nouvelle fonctionnalité de contrôle utilisateur SubmitForm /Flags : THPDFPage.AddPushButtonWithSubmitAction(FieldName, Caption, URL, Rectangle, SubmitFlags) expose l'ensemble complet des drapeaux spécifiés dans le tableau 237 de l'ISO 32000-1 §12.7.5.2, via le nouveau type THPDFSubmitFormFlags. Les utilisateurs peuvent maintenant combiner sffExportFormatHTML / sffXFDF / sffSubmitPDF (format de soumission), sffGetMethod (HTTP GET ou POST), sffIncludeAnnotations, sffSubmitCoordinates, sffCanonicalFormat, sffIncludeNoValueFields, sffIncludeAppendSaves, sffExclNonUserAnnots, sffEmbedForm et d'autres options, remplaçant la valeur /Flags 0 (FDF + POST) codée en dur de l'ancienne méthode baSubmitURL. La méthode existante AddPushButtonWithAction(.., baSubmitURL, ..) continue de générer /Flags 0 pour assurer la compatibilité descendante au niveau des octets. Les mêmes restrictions PDF/A / PDF/X s'appliquent qu'à baSubmitURL : autorisée sous PDF/A, bloquée sous PDF/X.

2026-05-20 Version 2.119.18

  • Types d'actions de boutons améliorés : THPDFButtonAction inclut maintenant baNamed et baHide. baNamed émet une action /S /Named /N (ISO 32000-1 §12.6.4.11) adaptée aux quatre commandes de navigation standard : NextPage, PrevPage, FirstPage et LastPage (PDF/A autorise les quatre, conformément à l'ISO 19005-1 §6.6.1), ainsi qu'aux extensions Acrobat telles que Print et SaveAs. baHide émet une action /S /Hide /T /H true (§12.6.4.10) qui masque le champ de formulaire nommé lorsque le bouton est cliqué. Les deux types d'action sont conformes aux spécifications PDF/A et PDF/X ; seuls baJavaScript, baResetForm et baSubmitURL conservent leurs mécanismes de conformité existants.

2026-05-20 Version 2.119.17

  • Nouveau registre de destinations nommées : `THotPDF.RegisterNamedDestination(Name, PageIndex, FitMode, ...)` enregistre une destination symbolique dans l'arborescence de noms du catalogue `/Names /Dests` (ISO 32000-1 §12.3.2.3). Les actions "GoTo" / "GoToR" et les entrées de plan peuvent alors référencer une destination par nom au lieu de coder en dur les numéros de page, ce qui maintient les références croisées stables lors de l'insertion, de la suppression ou du réarrangement des pages. La nouvelle énumération `THPDFDestinationFitMode` couvre les huit modes d'ajustement spécifiés (XYZ, Fit, FitH, FitV, FitR, FitB, FitBH, FitBV). La méthode génère une exception si le nom est vide, si `PageIndex` est hors plage ou si le nom est dupliqué ; elle incrémente automatiquement la version du document à PDF 1.2 si nécessaire. Aucune restriction PDF/A / PDF/X — les aides à la navigation sont autorisées dans tous les profils.

2026-05-20 Version 2.119.16

  • Nouvelles annotations de ligne / styles de terminaison de ligne : `THPDFPage.AddLineAnnotation` dispose désormais d'une surcharge qui accepte les styles de terminaison de début et de fin de ligne. L'ensemble complet défini dans la table 176 de l'ISO 32000-1 §12.5.6.7 est accessible via la nouvelle énumération `THPDFLineEndingStyle` : `None`, `Square`, `Circle`, `Diamond`, `OpenArrow`, `ClosedArrow`, `Butt`, `ROpenArrow`, `RClosedArrow`, `Slash`. Les annotations de ligne peuvent désormais être affichées sous forme de flèches, de marqueurs de dimensionnement ou de repères, directement dans Adobe Acrobat / Foxit, sans que l'application hôte ait à dessiner manuellement les têtes de flèche sur la page. La surcharge existante à quatre paramètres fonctionne toujours de manière identique.

2026-05-20 Version 2.119.15

  • Nouveau style pour les éléments de plan (marque-pages) : THPDFDocOutlineObject expose désormais les propriétés Couleur, Gras et Italique (ISO 32000-1 §12.3.3 Tableau 153 /C et /F). Le panneau des éléments de plan peut maintenant afficher les marque-pages en couleur et avec une mise en gras ou en italique, ce qui est utile pour regrouper les chapitres, marquer les sections incomplètes ou nécessitant une attention particulière, et pour correspondre au style de la marque. La couleur par défaut est clNone (aucune entrée /C n'est émise, identique aux sorties précédentes) ; Gras et Italique sont par défaut définis sur faux. La définition des propriétés après l'ajout d'un enfant met à jour le dictionnaire de plan en direct. La définition de la couleur sur clNone ou la définition de Gras et Italique sur faux supprime les entrées /C et /F.

2026-05-20 Version 2.119.14

  • Nouveau registre JavaScript nommé au niveau du document : THotPDF expose désormais RegisterDocumentJavaScript(Name, Body). Chaque entrée enregistrée est sérialisée dans l'arborescence de noms du catalogue (/Names /JavaScript) (ISO 32000-1 §7.7.4.4 + §12.6.4.16) sous la forme d'un dictionnaire indirect /S /JavaScript /JS. Les actions des widgets AcroForm et les actions d'ouverture du document peuvent invoquer la fonction enregistrée par son nom via le moteur JavaScript du lecteur (Acrobat, Foxit). Cela est utile pour partager une bibliothèque d'utilitaires de validation, de formatage ou de calcul entre de nombreux widgets sans dupliquer le code source JavaScript dans chaque dictionnaire /A. Cette méthode est interdite quel que soit le niveau de conformité PDFA (ISO 19005-1 §6.6.1) et quel que soit le niveau de conformité PDFX (ISO 15930, flux de travail de prépresse), et rejette les noms et les corps vides, ainsi que les enregistrements de noms en double.

2026-05-20 Version 2.119.13

  • Nouvelle prise en charge des miniatures de pages : THPDFPage expose désormais les fonctions SetPageThumbnail(ImageIndex) et ClearPageThumbnail. Les lecteurs de PDF (Acrobat, Foxit, lecteurs intégrés aux navigateurs) utilisent l'entrée /Thumb de la page (ISO 32000-1 §12.3.4) pour afficher une miniature pré-générée dans leur barre de navigation, sans avoir à rasteriser la page, ce qui est particulièrement utile pour les archives riches en images, où le rasteriseur du lecteur serait lent. L'outil réutilise toutes les images enregistrées via AddImage / AddImageFromFile, ce qui permet aux utilisateurs de préparer une bitmap de miniature réduite et de l'associer en un seul appel ; SetPageThumbnail(-1) ou ClearPageThumbnail supprime une miniature précédemment attachée. Les indices d'image hors plage génèrent une exception descriptive.

2026-05-20 Version 2.119.12

  • Correction de la conformité PDF/A : la fonction AddPushButtonWithAction lève désormais une exception lorsque les types d'action baJavaScript ou baResetForm sont utilisés, quel que soit le niveau de conformité PDFA (PDF/A-1/2/3). Les normes ISO 19005-1 §6.6.1, ISO 19005-2 §6.5.1 et ISO 19005-3 §6.5.1 interdisent les actions JavaScript, ResetForm et ImportData pour tous les niveaux PDF/A. Les actions baSubmitURL (SubmitForm), baURI et baNone restent autorisées dans PDF/A ; SubmitForm figure dans la liste des actions autorisées de la section §6.6.1. Auparavant, les boutons-poussoir pouvaient contenir des actions interdites, même lorsque PDFACompliance était activé, car la protection de la version v2.119.5 ne couvrait que les chemins Catalog /AA et OpenAction au niveau du document.
  • Correction de la conformité PDF/X : `AddPushButtonWithAction` lève maintenant une exception lorsque les types d'action `baJavaScript`, `baResetForm` ou `baSubmitURL` sont utilisés, quel que soit le niveau de conformité PDF/X. Les flux de travail de prépresse conformes à la norme ISO 15930 excluent la programmation interactive, la modification des formulaires et la soumission des formulaires à des points de terminaison externes.

2026-05-20 Version 2.119.11

  • Correction de la conformité PDF/A : les protections de type d'annotation PDF/A garantissent l'intégrité. Les fonctions AddScreenAnnotation, Add3DAnnotation et AddRichMediaAnnotation lèvent désormais une erreur lorsque PDFACompliance est activé à tout niveau (PDF/A-1/2/3). Les normes ISO 19005-1 §6.5.2, ISO 19005-2 §6.6.1 et ISO 19005-3 §6.6.1 interdisent les sous-types d'annotation Screen, 3D et RichMedia (multimédia / extension Adobe niveau 3) dans tous les niveaux PDF/A. Les mêmes protections sont également appliquées pour la conformité PDFX : les flux de travail de prépresse ISO 15930 rejettent les sous-types multimédia.
  • Correction de la conformité PDF/A-1 : `AddWatermarkAnnotation` et `AddRedactAnnotation` lèvent désormais une exception lorsque `PDFACompliance` est défini sur PDF/A-1. Les annotations de type "watermark" (PDF 1.6) et "redact" (PDF 1.7) sont des sous-types d'annotations incompatibles avec la base PDF 1.4 de PDF/A-1 (ISO 19005-1 §6.5.2). PDF/A-2 et PDF/A-3 (base PDF 1.7) continuent de prendre en charge les deux types d'annotations.

2026-05-20 Version 2.119.10

  • Correction de la conformité PDF/A : `AddImageWithSMask` et `AddImageWithSMask32` lèvent désormais une erreur lorsque `PDFACompliance` est défini sur PDF/A-1. L'ISO 19005-1:2005 §6.4 interdit tous les effets de transparence ; un flux /SMask d'image active la composition de transparence en demi-teinte. Pré-composez l'image sur une couleur de fond et transmettez le résultat à `AddImage()`, ou utilisez PDF/A-2 ou une version ultérieure pour la prise en charge de la transparence. PDF/A-2 et PDF/A-3 continuent de permettre la transparence en demi-teinte des images.

2026-05-20 Version 2.119.9

  • Correction de la conformité PDF/A : `SetTransparencyGroup` et `SetTransparencyGroupICC` lèvent désormais une erreur lorsque `PDFACompliance` est défini sur PDF/A-1. L'ISO 19005-1:2005 §6.4 interdit tous les effets de transparence ; les groupes de transparence au niveau de la page (dictionnaire `/Group` `/S` `/Transparency` de la page) activent le modèle de composition de la transparence pour l'ensemble de la page, ce qui constitue une violation directe du §6.4. PDF/A-2 et PDF/A-3 continuent de permettre les groupes de transparence au niveau de la page.

2026-05-20 Version 2.119.8

  • Correction de la conformité PDF/A : RegisterHalftoneState lève désormais une erreur lorsque PDFACompliance est activé et qu'un dictionnaire de demi-tons personnalisé est fourni (c'est-à-dire, HTDefaultName = false). Les normes ISO 19005-1:2005 §6.2.9 et ISO 19005-2:2011 / ISO 19005-3:2012 §6.3.7 autorisent uniquement la chaîne de caractères "/Default" pour l'ExtGState /HT ; les dictionnaires de demi-tons personnalisés (de type 1, 5, 6, 10, 16) sont interdits. La possibilité de définir HTDefaultName=True pour revenir aux demi-tons par défaut continue de fonctionner pour tous les niveaux PDF/A.
  • Correction de la conformité PDF/A : `RegisterSoftMaskState` lève maintenant une exception lorsque `PDFACompliance` est défini sur PDF/A-1 et qu'un dictionnaire de masques doux personnalisé est fourni (paramètre `SMaskDict`). L'ISO 19005-1:2005 §6.4 interdit tous les effets de transparence ; une valeur /SMask différente de None active la transparence du masque doux. Il est toujours possible de passer `SMaskNone=True` pour réinitialiser les masques doux. La conformité PDF/A-2 et PDF/A-3 continuent de permettre la transparence du masque doux.

2026-05-20 Version 2.119.7

  • Correction de la conformité PDF/A : `AddDocumentAttachment` (intégration de fichiers au niveau du document via Catalog /Names /EmbeddedFiles) génère désormais une erreur lorsque `PDFACompliance` est activé pour PDF/A-1 ou PDF/A-3. L'ISO 19005-1:2005 §6.1.11 interdit explicitement la clé `/EmbeddedFiles` dans le dictionnaire Names du document pour PDF/A-1. Pour PDF/A-3, les pièces jointes doivent être enregistrées via `AddPDFA3AssociatedFile()` afin d'inclure le tableau `/AF` et la clé `/AFRelationship` requis, conformément à l'annexe E de l'ISO 19005-3:2012. PDF/A-2 continue de permettre les pièces jointes, à condition que les fichiers joints soient eux-mêmes conformes à la norme PDF/A.

2026-05-20 Version 2.119.6

  • Correction de la conformité PDF/A : l'utilisation de polices standard (Arial, Helvetica, Times New Roman, Courier New, Symbol, ZapfDingbats) avec l'émulation de police standard activée déclenche désormais une exception descriptive lorsque PDFACompliance est activé. Les normes ISO 19005-1:2005 §6.3 et ISO 19005-2:2011 / ISO 19005-3:2012 §6.3 exigent que toutes les polices soient intégrées dans les fichiers conformes ; le chemin d'émulation de police standard génère une référence de police non intégrée, ce qui constitue une violation directe de la section 6.3. Les utilisateurs doivent définir StandardFontEmulation := false ou passer à RegisterUnicodeTTF() avec les fichiers de police réels pour la sortie PDF/A.
  • Correction de la conformité PDF/A : les polices non standard sont désormais toujours intégrées lorsque PDFACompliance est activé, quel que soit le paramètre de la propriété FontEmbedding. L'optimisation FontEmbedding = false est silencieusement annulée en mode PDF/A pour satisfaire à l'exigence de §6.3 selon laquelle toutes les polices doivent être intégrées.

2026-05-20 Version 2.119.5

  • Correction de la conformité PDF/A : les actions JavaScript et les éléments /AA (actions supplémentaires) au niveau du catalogue sont désormais bloqués lorsque PDFACompliance est activé. Les normes ISO 19005-1:2005 §6.6.1/§6.6.2 et ISO 19005-2:2011 / ISO 19005-3:2012 §6.5.1/§6.6.2 interdisent tous les types d'actions JavaScript et interdisent la clé /AA dans le dictionnaire du catalogue. L'appel de SetActionScript avec n'importe quelle valeur de PDFACompliance déclenche désormais une exception descriptive. En tant que mesure de sécurité supplémentaire, les chemins d'émission OpenAction JavaScript et Catalog /AA dans EndDoc sont également contrôlés pour ignorer silencieusement la sortie lorsque PDFACompliance est activé, garantissant qu'aucune clé non conforme n'est écrite, même via les chemins internes.

2026-05-20 Version 2.119.4

  • Correction de la conformité PDF/A : AcroForm /NeedAppearances est maintenant forcé à false lorsque PDFACompliance est activé, quel que soit le paramètre AutoFormAppearances. Les normes ISO 19005-1:2005 §6.9 et ISO 19005-2:2011 / ISO 19005-3:2012 §6.4 exigent que cette clé soit absente ou définie à false dans les fichiers conformes. Auparavant, si AutoFormAppearances était désactivé alors que PDFACompliance était activé, /NeedAppearances était défini à true, ce qui générait un fichier non conforme.

2026-05-20 Version 2.119.3

  • Correction de la conformité PDF/A : les sous-ensembles de polices CIDFont intégrés incluent désormais un flux /CIDSet dans le descripteur de police lorsque PDFACompliance est activé. Les normes ISO 19005-1:2005 §6.3.5 et ISO 19005-2:2011 / ISO 19005-3:2012 §6.2.11 exigent que les sous-ensembles de polices CIDFont contiennent un flux de bits /CIDSet indiquant quelles valeurs CID sont présentes dans le programme de police intégré. HotPDF utilise l'encodage Identity-H où CID est égal au point de code Unicode, donc le CIDSet est construit directement à partir de l'ensemble des points de code utilisés dans le document. Le flux de bits est compressé avec FlateDecode et ajouté au descripteur de police existant en tant qu'objet de flux indirect. Cela corrige une lacune précédemment non détectée dans tous les niveaux de conformité PDF/A (l'audit de conformité précédent indiquait à tort que cela était déjà en place).

2026-05-20 Version 2.119.2

  • Correction de la conformité aux normes PDF/A-2 et PDF/A-3 : le dictionnaire d'apparence des annotations (/AP /N) est désormais automatiquement généré pour les types d'annotations qui ne sont ni des liens ni des fenêtres contextuelles (TextNotes, FreeText, Line, Square, Circle, Stamp, FileAttachment) lorsque PDFACompliance est défini sur un niveau PDF/A-2 ou PDF/A-3. Les normes ISO 19005-2:2011 §6.3.3 et ISO 19005-3:2012 §6.3.3 exigent que chaque annotation possède au moins un dictionnaire d'apparence (avec la forme XObject "N"). Un objet Form XObject vide minimal est généré pour satisfaire cette exigence structurelle ; la plupart des lecteurs PDF utilisent leur propre rendu intégré pour les types d'annotations standard, quel que soit le contenu du flux /AP. Les annotations de type lien et fenêtre contextuelle sont explicitement exemptées par la norme et restent inchangées. Cette exigence ne s'applique pas à PDF/A-1 (la norme ISO 19005-1 §6.5.3 ne contraint que le format de /AP lorsqu'il est présent, et non sa présence).

2026-05-20 Version 2.119.1

  • Correction de la conformité PDF/A : tous les types d'annotations autres que les widgets (notes textuelles, tampons, lignes, formes, hyperliens, liens GoTo, liens GoToR, liens URI) ont maintenant automatiquement le flag /F Print (bit 3 = 1, valeur 4) lorsque PDFACompliance est activé. Les normes ISO 19005-1:2005 §6.5.3 et ISO 19005-2:2011 / ISO 19005-3:2012 §6.3.2 stipulent que chaque dictionnaire d'annotation doit contenir une clé /F avec le bit Print défini. Auparavant, seul les annotations de type widget (champs de formulaire) avaient ce flag ; tous les autres types d'annotations l'omettaient, ce qui rendait les fichiers produits non conformes.
  • Correction de la conformité PDF/A-1 : les groupes de contenu optionnels (calques) sont maintenant bloqués lorsque PDFACompliance est défini sur un niveau PDF/A-1 ('A' ou 'B'). L'ISO 19005-1:2005 §6.1.13 interdit la clé /OCProperties dans le dictionnaire Catalog ; l'appel de RegisterOptionalContentGroup sous PDF/A-1 déclenche désormais une exception descriptive, invitant les utilisateurs à utiliser PDF/A-2 ou une version ultérieure si des contenus optionnels sont nécessaires. L'émission de /OCProperties à la fin du document est également bloquée pour éviter une non-conformité silencieuse, même si des groupes de contenu optionnels ont été enregistrés.

2026-05-20 Version 2.119.0

  • Prise en charge du conteneur XAdES-in-PDF conformément à la norme ETSI EN 319 142-2 V1.2.0 §6.2 (fin de la série B/C/D, étape 3 sur 3). Les octets XML signés XAdES fournis par l'appelant sont intégrés en tant que fichier intégré PDF, la spécification du fichier est enregistrée dans le tableau /AF du catalogue, et la relation /AF est définie conformément à l'énumération PDF 2.0 spécifiée par l'appelant. Il s'agit uniquement d'un wrapper côté producteur ; la construction réelle de la signature XAdES (XML-DSig + propriétés qualifiées ETSI EN 319 132-1 + horodatage RFC 3161 intégré dans xades:UnsignedSignatureProperties) est la responsabilité de la bibliothèque cryptographique XML de l'appelant (par exemple, Apache Santuario, .NET SignedXml, libxmlsec, Saxon avec extensions XAdES, etc.).
  • Nouvelle méthode `THotPDF.AddXAdESAssociatedFile(FileName, XMLBytes, Description, MimeType, Relationship)`. Les valeurs par défaut sont : MimeType `'application/xml'` (également couramment `'application/vnd.etsi.asic-e+zip'` pour les archives ASiC-E), Relationship `'Source'` (le fichier XML signé XAdES est le contenu principal du document). Renvoie le dictionnaire Filespec indirect afin que les appelants puissent y ajouter des métadonnées supplémentaires ou des références croisées à partir d'entrées personnalisées du catalogue.
  • Indépendamment de PDF/A : contrairement à `AddPDFA3AssociatedFile` de la version v2.108 (qui nécessite PDFACompliance='3*'), cette fonction utilitaire ne dépend pas de PDF/A ; XAdES-in-PDF constitue sa propre famille de profils, conformément à la section 6 de la norme PAdES Part 2 V1.2.0.
  • Correction d'un bug critique dans `_EscapePDFNameBytes` (PDF 1.7 ISO 32000-1 §7.3.5 + Tableau 2). L'échappement précédent ne convertissait que les octets en dehors de la plage [0x21..0x7E] et le caractère `#`; les délimiteurs PDF (`/ ( ) < > [ ] { } %`) sont obligatoires dans les spécifications et doivent être échappés sous la forme `#XX` à l'intérieur des noms, mais ils étaient laissés tels quels. Les noms comme `/Subtype /application/xml` étaient donc interprétés par les lecteurs stricts comme deux jetons de nom distincts (/application suivi de /xml), ce qui empêchait la reconnaissance de EmbeddedFile /Subtype. Dans la version 2.119, tous les 10 délimiteurs sont échappés conformément aux spécifications ; les noms qui ne sont pas des délimiteurs (la grande majorité des émissions HotPDF) restent identiques en termes d'octets. Les types MIME PDF/A-3 Annex E (v2.108) sont désormais émis correctement (`/application#2Fxml` au lieu de `/application/xml` incorrect).
  • La série PAdES B/C/D est maintenant finalisée avec 3 commits : v2.117 (profils étendus E-BES / E-EPES / E-LTV conformément à la partie 2 §5) + v2.118 (valeurs initiales conformément à l'ISO 32000-1 §12.7.5.5 + partie 2 §4.2.6) + v2.119 (XAdES-in-PDF + correction de l'échappement des délimiteurs conformément à la partie 2 §6.2). Combiné avec les versions v2.109 à v2.116, HotPDF couvre désormais l'ensemble du champ d'application des producteurs PAdES, y compris les profils de base, les profils étendus, les horodatages de documents, les informations de validation DSS, les extensions ESIC, les contraintes de signature via les valeurs initiales et le conteneur XAdES-in-PDF.
  • Compilation propre pour Win32 et Win64 ; les versions de référence v2.108 à v2.118 ont toutes été recompilées sans modification. De nouveaux tests "smoke" ont été ajoutés, comprenant 2 tests positifs (fichiers XML signés XAdES en tant que /AFRelationship /Source et archives ASiC-E en tant que /Data) et 4 tests négatifs (nom de fichier vide, octets XML vides, type MIME vide, relation non valide). Le vérificateur Python effectue des tests complets sur les deux spécifications de fichiers, y compris les formats d'échappement `/Subtype /application#2Fxml` et `/Subtype /application#2Fvnd.etsi.asic-e+zip`. Les tests "smoke" pour PDF/A-3, PAdES et PDF/X de la version v2.108 ont tous été relancés et se sont exécutés correctement.

2026-05-20 Version 2.118.0

  • Valeurs de graine PAdES conformément à l'ISO 32000-1 §12.7.5.5 + ETSI EN 319 142-1 V1.2.1 §5.5 + ETSI EN 319 142-2 V1.2.0 §4.2.6 (étape 2 sur 3 de la série B/C/D). Un dictionnaire de valeur de graine (SV) attaché à un champ de signature limite les options que l'outil de signature du lecteur peut choisir pour ce champ spécifique, notamment le gestionnaire, le sous-filtre, la méthode de hachage, si les informations de révocation sont obligatoires et quelle est la version minimale requise de PDF.
  • Nouvelle méthode `THotPDF.AttachPAdESSeedValue(FieldName, SubFilters, DigestMethods, ForceSubFilter, ForceDigestMethod, AddRevInfo, MinPDFVersion, ForceMinPDFVersion)`. Elle recherche le champ de signature nommé dans la liste des champs du formulaire (qui doit déjà avoir été créé par un appel précédent à `AddPAdESSignatureField` ou `AddDocumentTimestampSignature`) et y attache un sous-dictionnaire /SV avec les contraintes fournies par l'appelant.
  • Les entrées de valeur de départ (Seed Value) sont émises (voir le tableau 234) :
    • `/Type /SV`
    • `/SubFilter` : tableau de noms — par exemple, [/ETSI.CAdES.detached]
    • `/DigestMethod` : tableau de noms — par exemple, [/SHA256 /SHA384 /SHA512]
    • `/AddRevInfo` : valeur booléenne — l'outil de signature doit inclure OCSP/CRL dans le CMS
    • `/V` : nombre — version minimale de PDF (par exemple, 1.7)
    • `/Ff` : entiers représentant des bits (voir le tableau 235) — chaque paramètre Force* définit le bit correspondant, donc l'outil de signature DOIT respecter cette contrainte (bit 2 = force SubFilter, bit 3 = force V, bit 6 = force AddRevInfo, bit 7 = force DigestMethod)
  • Règles de conformité aux spécifications : PAdES Part 2 V1.2.0 §4.2.6 interdit les valeurs de seed qui obligeraient les outils de signature à violer le profil PAdES (par exemple, en spécifiant le sous-filtre PKCS#1). HotPDF n'applique pas cette contrainte côté producteur ; l'appelant est responsable de fournir uniquement les valeurs autorisées par la spécification (par exemple, `'adbe.pkcs7.detached'` ou `'ETSI.CAdES.detached'` pour SubFilter, SHA-256+ pour DigestMethod). Le commentaire de documentation explicite précise cette contrainte.
  • Compilation propre pour Win32 et Win64 ; les versions de référence v2.108 à v2.117 ont été recompilées sans modification. Le nouveau module "smoke_pades_seedvalue" crée un champ PAdES-B-T, puis ajoute un ensemble complet de contraintes de valeur de départ (SubFilter limité à ETSI.CAdES.detached, DigestMethod limité à SHA256/384/512, AddRevInfo défini sur true, MinPDFVersion défini sur 1.7, tous les bits de contrainte sont activés). Le vérificateur Python parcourt le sous-dictionnaire "/SV" et vérifie la structure de chaque entrée ; il teste également le mécanisme de rejet pour les "FieldNames" inconnus.
  • Série, étape 3 (v2.119) : Le conteneur XAdES-in-PDF, conformément à la partie 2, version 1.2.0, §6, clôt la série B/C/D. Du côté du producteur, il s'agit d'une couche mince qui s'appuie sur les fonctionnalités existantes de HotPDF pour les fichiers intégrés, le catalogue et le composant de formulaire (AF) (outil d'aide PDF/A-3, version v2.108), ainsi que sur la sémantique de la relation /AF que la partie 2, version 1.2.0, §6.2.2 de PAdES attend pour les charges utiles XML signées avec XAdES.

2026-05-20 Version 2.117.0

  • Profils PAdES étendus conformément à la norme ETSI EN 319 142-2 V1.2.0 §5 (étape 1 des 3 séries B/C/D). La partie 1 établit les combinaisons d'attributs CMS fixes (V1.2.1 §6 B-B / B-T / B-LT / B-LTA) ; la partie 2 §5 définit une famille parallèle de profils "étendus" (E-BES / E-EPES / E-LTV) avec une plus grande flexibilité des attributs CMS pour les utilisateurs qui ont besoin de fonctionnalités au-delà des fonctionnalités de base (par exemple, déploiements d'entreprise multi-politiques, profils CAdES personnalisés dans l'enveloppe PAdES).
  • `AddPAdESSignatureField` : Le paramètre de profil accepte désormais trois valeurs supplémentaires, en plus des quatre noms de base :
    • `'E-BES'` : signature de base + liaison non ambiguë du certificat de signature via l'attribut ESS du certificat de signature (équivalent de CAdES-BES dans l'enveloppe PAdES). Budget par défaut de 16 Ko pour le contenu.
    • `'E-EPES'` : E-BES + attribut de signature explicite de l'identificateur de la politique de signature. Budget par défaut de 16 Ko ; l'appelant transmet généralement 18 à 20 Ko pour inclure les octets de l'OID de la politique et des qualificateurs.
    • `'E-LTV'` : validation à long terme avec une chaîne de certificats flexible basée sur les attributs CMS + intégration de la révocation. Augmente automatiquement à un minimum de 20 Ko (similaire à B-LT).
  • Le format de transmission côté producteur est identique pour les profils de base et étendus : les sept utilisent le SubFilter `ETSI.CAdES.detached`, le même motif de sentinelle /ByteRange + /Contents, et la même infrastructure DSS + ESIC (v2.110 / v2.116). La distinction de niveau réside entièrement dans la composition des attributs signés CMS que la bibliothèque cryptographique de l'appelant produit. La chaîne Profile varie uniquement pour le diagnostic de validation et le budget par défaut de /Contents ; HotPDF n'encode pas CAdES-BES par rapport à CAdES-EPES par rapport à CAdES-T dans le dictionnaire PDF lui-même.
  • Mise à jour de la documentation d'aide de PAdES concernant les responsabilités de l'appelant, telles que définies dans la partie 2, version 1.2.0, §4.2 : sélection du hachage SHA-256 (phase d'élimination de SHA-1), un seul SignerInfo par champ Sig, pas de certificats d'attributs RFC 5755, et l'exigence E-EPES d'inclure l'attribut signé signature-policy-identifier. Les éléments relatifs au domaine de l'appelant restent en dehors de la portée du producteur, mais le contrat est désormais explicite sur l'interface de l'API.
  • Compilation propre pour Win32 et Win64 ; les versions de référence v2.108 à v2.116 ont été recompilées sans modification. `smoke_pades_signature` a été étendu avec 3 nouveaux champs (SigEBES / SigEEPES / SigELTV), et chaque nouvelle valeur de profil est testée via les chemins d'auto-redimensionnement, de budget explicite et de budget par défaut. Le vérificateur Python a été étendu pour parcourir les 7 champs et vérifie l'extension Catalog ESIC (hérité de la version v2.116).
  • Étape 2 de la série B/C/D : la version 2.118 ajoute des valeurs initiales (PDF 1.7 §12.7.5.5 + ETSI EN 319 142-1 V1.2.1 §5.5 + Partie 2 V1.2.0 §4.2.6) afin que les champs de signature PAdES puissent déclarer des contraintes de gestionnaire/SubFilter/méthode de hachage que le lecteur doit respecter lors de la signature. Étape 3 : la version 2.119 ajoute la prise en charge des conteneurs XAdES-in-PDF conformément à la partie 2 V1.2.0 §6 (XML signé XAdES intégré en tant que EmbeddedFile + association Catalog /AF).

2026-05-20 Version 2.116.0

  • Mise à jour de PAdES conformément aux dernières versions normatives de l'ETSI et à la décision d'application eIDAS : ETSI EN 319 142-1 V1.2.1 (2024-01, publié) + ETSI EN 319 142-2 V1.2.0 (2025-03, brouillon de profils supplémentaires + famille de profils étendus + XAdES-in-PDF) + ETSI TS 119 142-3 V1.1.1 (2016-12, horodatage de document PAdES-DTS) + EU 2015/1506 (reconnaissance du secteur public). Les versions de base de HotPDF v2.109 - v2.111 (B-B / B-T / B-LT / B-LTA + horodatage autonome) continuent de satisfaire le même format de données ; cette version corrige deux problèmes liés aux versions des spécifications.
  • L'entrée du dictionnaire `/Type "DSS"` (EN 319 142-1 V1.2.1 §5.4.2.2). L'entrée `/Type` est facultative, mais si elle est présente, elle doit être le nom `/DSS`. HotPDF l'émet maintenant de manière proactive afin que les validateurs stricts qui inspectent `/Type` avant d'analyser le reste du dictionnaire reconnaissent immédiatement la structure.
  • Le dictionnaire des extensions ESIC (TS 119 142-3 §5.1, recommandé) introduit une nouvelle méthode `EnsurePAdESESICExtensions` qui écrit de manière idempotente les informations suivantes dans le catalogue chaque fois qu'un helper PAdES est invoqué : `<< /Extensions << /ESIC << /BaseVersion /1.7 /ExtensionLevel 1 >> >> >>`. Les validateurs (Adobe Acrobat pre-flight, EU DSS, callas pdfaPilot) utilisent cette entrée pour identifier le document comme un conteneur PAdES déclarant les extensions PDF 1.7 + ESIC de niveau 1.
  • Correction d'un bug critique dans le chemin de traitement aller-retour de `EnsurePAdESDSS`. Avant la version v2.116, la fonction utilitaire résolvait à nouveau le dictionnaire DSS à chaque appel via `Catalog.GetIndexedItem(FindValue('DSS'))`, ce qui renvoyait le lien indirect THPDFLink stocké dans le catalogue au lieu du dictionnaire DSS réel. La conversion silencieuse en THPDFDictionaryObject modifiait discrètement le pointeur, ce qui entraînait l'omission silencieuse de l'ajout de chaque appel suivant à `AddPAdESDSSCertificate` / `AddPAdESDSSOCSP` / `AddPAdESDSSCRL` / `AddPAdESDSSVRI` après le premier appel (le tableau auquel on essayait d'ajouter l'élément pointait vers une valeur nulle, FindValue renvoyait -1, et la condition "if-Idx-less-than-zero-Exit" était déclenchée). La correction de la version v2.116 met en cache la référence réelle du dictionnaire dans un champ `FPAdESDSSDict`, de sorte que les appels suivants accèdent directement à ce cache. Le test `smoke_pades_dss` émet désormais correctement 2 certificats + 1 OCSP + 1 CRL + 1 entrée VRI (précédemment, seul le premier certificat était inclus dans /DSS, et les tableaux /OCSPs et /CRLs étaient vides).
  • Mises à jour des commentaires de documentation concernant les fonctions d'aide PAdES, couvrant les responsabilités de l'appelant, telles que mises en évidence dans la partie 2, version 1.2.0, §4.2 : suppression progressive de SHA-1 (les appelants doivent choisir SHA-256+ pour CMS), un seul SignerInfo par signature PDF (partie 2, §4.2.1 h / partie 1, §4.1 a), les certificats d'attributs RFC 5755 ne doivent pas être utilisés (partie 2, §4.2 g), et les documents PAdES-DTS ne doivent pas contenir de dictionnaires VRI (TS 119 142-3, §6.3 h - DSS est suffisant). Le format de transmission côté producteur de HotPDF satisfait déjà les quatre contraintes par construction ; le commentaire indique aux appelants ce que leurs bibliothèques de construction CMS doivent faire.
  • Compilation propre pour Win32 et Win64 ; les tests de signature, de signature DSS et de horodatage de documents PAdES, ainsi que leurs vérificateurs, passent tous avec succès. Les extensions de vérification : `smoke_pades_dss` vérifie maintenant `/Type /DSS` et `Catalog /Extensions /ESIC /BaseVersion /1.7 /ExtensionLevel 1` ; `smoke_pades_doctimestamp` vérifie la même extension ESIC et accepte les rectangles de zone nulle inversés verticalement (`[0 H 0 H]` où H est la hauteur de la page). La documentation d'audit et les notes techniques ont été mises à jour pour faire référence à EN 319 142-1 V1.2.1 / Partie 2 V1.2.0 / TS 119 142-3 / EU 2015/1506.

2026-05-20 Version 2.115.0

  • Fermeture de la série de producteurs PDF/X (ISO 15930) (4/4) : types d'annotations et d'actions interdits conformément à la norme ISO 15930-1:2001 / ISO 15930-3:2002 / ISO 15930-7:2010 + ISO 32000-1 §12.5.6 / §12.6.4. Les flux de travail d'impression PDF/X ne consomment que le contenu imprimable visible ; les annotations multimédias, les fichiers intégrés et les actions interactives n'ont aucun rôle dans le processus d'impression, de sorte que les outils de vérification préliminaire (Adobe Acrobat, Enfocus PitStop, callas pdfaPilot) rejettent les documents qui les contiennent.
  • Types d'annotations interdites (rejetées quel que soit le profil PDF/XCompliance ∈ {X-1a, X-3, X-4}) :
    • FileAttachment — la presse d'impression ne traite pas les fichiers intégrés.
    • Sound — les contenus multimédias ne sont pas adaptés aux flux de travail d'impression.
    • Movie — même raisonnement pour les contenus multimédias.
    Chaque point d'entrée (AddFileAttachmentAnnotation, AddSoundAnnotation, AddMovieAnnotation) génère désormais un diagnostic basé sur la section de la spécification et la valeur de PDF/XCompliance lorsqu'il est appelé dans le cadre de n'importe quel profil PDF/X.
  • Actions interdites (rejetées dans tous les contextes de conformité PDF/X) : Lancer, JavaScript, SoumettreFormulaire, ImporterDonnées, Vidéo, Son, RéinitialiserFormulaire. Les flux de travail de prépresse doivent déclencher tout programme externe ; le fichier PDF est consommé uniquement par la presse/le RIP et n'est jamais exécuté. `AddLaunchLink` génère désormais une erreur dans tous les profils PDF/X (les autres actions ne sont pas exposées comme API publiques par HotPDF, elles sont donc satisfaites automatiquement).
  • La série PDF/X est maintenant fonctionnellement complète : v2.112 (activation optionnelle + identité XMP + Trapped /Name) + v2.113 (OutputIntent + ICC GTS_PDFX) + v2.114 (gestion de la transparence + application des contraintes de PageBox) + v2.115 (interdiction des annotations/actions). Les trois profils standard de l'industrie (X-1a:2001, X-3:2002, X-4:2010) sont pris en charge. L'utilisateur continue de créer du contenu de prépresse au niveau de la page (avec des cibles CMYK correctes, intégration des polices via le sous-ensembleur TTF v2.84, dimensions de TrimBox correspondant à la conception, BleedBox lorsque nécessaire), mais toutes les vérifications de conformité structurelle sont en place.
  • Compilation propre pour Win32 et Win64 ; les versions de référence v2.108 à v2.114 ont toutes été recompilées sans modification. `smoke_pdfx_optin` a été étendu avec 4 nouveaux tests de rejet (TestRejectFileAttachmentAnnot, TestRejectSoundAnnot, TestRejectMovieAnnot, TestRejectLaunchAction) — chaque test génère le type interdit dans l'un des trois profils PDF/X et confirme un rejet correct. Au total, les tests automatiques couvrent maintenant 11 scénarios : 3 succès + 8 chemins de rejet.
  • Deux séries de versions multiples parallèles ont été intégrées dans ce groupe : PAdES (ETSI EN 319 142, v2.109 - v2.111, 3 commits, prenant en charge les modes B-B / B-T / B-LT / B-LTA ainsi que les horodatages autonomes) et PDF/X (ISO 15930, v2.112 - v2.115, 4 commits, avec toutes les vérifications de conformité structurelle côté producteur pour les profils X-1a / X-3 / X-4).

2026-05-20 Version 2.114.0

  • PDF/X (ISO 15930) série de producteurs, tranche 3/4 : ajout d'une gestion de la transparence et application des contraintes de PageBox conformément à la norme ISO 15930-1:2001 / ISO 15930-3:2002 / ISO 15930-7:2010 + ISO 32000-1 §14.11.2. Cette tranche couvre deux restrictions indépendantes qui s'appliquent à chaque page ; la structure de la gestion de la transparence est similaire au modèle de fonctionnalités de transparence et de mise en page de PDF/A-1 v2.103.
  • Transparence (section 7.5) : RegisterExtGState rejette les valeurs alpha de remplissage inférieures à 1 (/ca), les valeurs alpha de contour inférieures à 1 (/CA) ou les modes de fusion en dehors de {Normal, Compatible} lorsque PDFXCompliance est 'X-1a' ou 'X-3'. Les normes PDF/X-1a (ISO 15930-1:2001) et PDF/X-3 (ISO 15930-3:2002) exigent une base PDF 1.3, qui est antérieure à la transparence PDF 1.4. PDF/X-4 (ISO 15930-7:2010, base PDF 1.6) autorise explicitement la transparence, donc cette vérification ne s'applique pas sous X-4. Le message de diagnostic explique la cause et suggère de passer à X-4 si la transparence est nécessaire.
  • Application des contraintes de PageBox (§14.11.2) : une nouvelle méthode, `EnsurePDFXPageBoxes`, analyse chaque page et exige la présence d'au moins l'un des éléments suivants : /TrimBox ou /ArtBox. Seul MediaBox ne suffit pas, car il représente la zone de conception, et non les dimensions de la page finale, que l'imprimerie doit connaître pour le découpage. L'absence de PageBoxes génère une erreur, indiquant l'index de la page (en base 1), la référence à la section de la spécification et la signature recommandée pour l'appel de SetTrimBox. La fonction EndDoc PDFXCompliance appelle automatiquement EnsurePDFXPageBoxes après la vérification de OutputIntent.
  • Motif d'appel typique : après avoir défini PDFXCompliance, Trapped et AddPDFXOutputIntent, chaque page du document doit inclure `CurrentPage.SetTrimBox(Left, Bottom, Right, Top)` correspondant aux dimensions du produit fini (par exemple, 0 0 612 792 pour le format US Letter, 0 0 595 842 pour le format A4). L'utilisation de BleedBox est recommandée, mais pas obligatoire.
  • Compilation propre pour Win32 et Win64 ; les versions de référence v2.108 à v2.113 ont été recompilées sans modification. `smoke_pdfx_optin` a été étendu avec : un appel positif à `SetTrimBox` dans chacun des 3 profils, un chemin de rejet pour les valeurs `TrimBox` manquantes, un chemin de rejet pour la transparence X-1a (l'appel à `RegisterExtGState` avec `ca=0.5` lève une exception), un chemin positif pour la transparence autorisée X-4 (le même appel réussit et `ExtGState` est enregistré). Le vérificateur Python parcourt chaque dictionnaire `/Type /Page` et vérifie qu'au moins l'un des éléments suivants est présent pour chaque page : `/TrimBox` ou `/ArtBox`.
  • La version v2.115 du module PDF/X corrige les problèmes liés aux types d'actions interdits (JavaScript, Launch, SubmitForm, ImportData, Movie, Sound), aux types d'annotations interdits (Movie, Sound, FileAttachment, Screen) et au rejet des formulaires AcroForm/XFA. Les flux de travail d'impression n'ont pas besoin de ces fonctionnalités ; les outils de vérification préliminaire destinés aux utilisateurs les signalent comme des erreurs critiques.

2026-05-19 Version 2.113.0

  • PDF/X (ISO 15930) série de producteurs, tranche 2/4 : application de l'intention de sortie et du profil ICC conformément à la norme ISO 15930-1:2001 §6.2.2 / ISO 15930-3:2002 §6.2.2 / ISO 15930-7:2010 §6.2 + ISO 32000-1 §14.11.5. Chaque profil PDF/X exige au moins une entrée de type /OutputIntent /S /GTS_PDFX, qui nomme la condition d'impression cible et fournit le flux de profil ICC /DestOutputProfile. Les imprimeries utilisent cela pour faire correspondre les couleurs du PDF à leur combinaison d'imprimante/papier/encre.
  • Nouvelle fonction `AddPDFXOutputIntent(OutputConditionIdentifier, Info, ICCProfileStream, NumComponents, AlternateCS)` qui reproduit le comportement du wrapper PDF/A v2.102, mais génère le sous-type GTS_PDFX au lieu de GTS_PDFA1. Elle vérifie que `ICCProfileStream` n'est pas nul et que `OutputConditionIdentifier` n'est pas vide ; elle appelle `RegisterICCProfile` pour intégrer le profil (gère automatiquement la correspondance de l'espace colorimétrique de secours /Alternate avec `NumComponents`) et `AddOutputIntent` pour créer le dictionnaire `OutputIntent`.
  • Application des règles de fin de document : lorsque `PDFXCompliance` est activé, `EnsurePDFXOutputIntent` parcourt le tableau `OutputIntents` et exige au moins une entrée avec `/S /GTS_PDFX` et `/DestOutputProfile`. L'absence de cette entrée génère une erreur avec la suggestion d'identifiant appropriée (FOGRA39 pour l'impression offset, CGATS TR 001 SWOP pour le marché nord-américain, Japan Color 2001 Coated pour les marchés asiatiques).
  • Workflow PDF/X typique : 1) `Doc.PDFXCompliance := 'X-4'`, 2) `Doc.Trapped := 'False'`, 3) charger le flux de profil CMYK (FOGRA39 / SWOP / etc.) dans un objet TStream, 4) `Doc.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)', '', ICCStream, 4, 'DeviceCMYK')`, 5) concevoir le contenu, 6) `Doc.EndDoc` génère la balise OutputIntent liée au tableau /OutputIntents du catalogue ; les outils de vérification préalable (Adobe Acrobat, Enfocus PitStop, callas pdfaPilot) valident l'association de gestion des couleurs.
  • Compilation propre pour Win32 et Win64 ; les versions de base v2.108, v2.109, v2.110, v2.111 et v2.112 ont toutes été recompilées sans modification. `smoke_pdfx_optin` (initialement v2.112) a été étendu pour : enregistrer un profil ICC factice et ajouter `AddPDFXOutputIntent` dans chacune des 3 émissions de profil (X-1a → FOGRA39 CMYK, X-3 → SWOP CMYK, X-4 → sRGB RGB) et ajouter un chemin de rejet qui vérifie que l'absence de `OutputIntent` génère une erreur. Le vérificateur Python a été étendu pour parcourir chaque dictionnaire et confirmer la présence de l'entrée `/Type /OutputIntent /S /GTS_PDFX` avec `/DestOutputProfile`.
  • Les fonctionnalités PDF/X restantes : la version v2.114 ajoute la gestion de la transparence (les profils X-1a et X-3 rejettent les valeurs alpha des remplissages et des contours inférieurs à 1, ainsi que les masques bitmap non standard ; le profil X-4 autorise la transparence) et applique les contraintes de la zone de page (chaque page doit avoir une zone de découpe ou une zone d'art percé selon la section 14.11.2) ; la version v2.115 clôt cette série en interdisant les actions / annot / XFA (les éléments Movie, Sound, FileAttachment, Screen, JavaScript, Launch, SubmitForm et ImportData, ainsi que XFA, sont rejetés car les flux de travail d'impression ne doivent pas les contenir).

2026-05-19 Version 2.112.0

  • A commencé la série de producteurs de pré-impression PDF/X (ISO 15930). PDF/X est la famille ISO pour l'envoi de fichiers PDF prêts pour l'impression aux imprimeurs commerciaux ; les profils X-1a (CMYK + couleurs spéciales strictes), X-3 (gestion des couleurs ICC) et X-4 (transparence PDF 1.6 + ICCN) sont les trois les plus utilisés dans l'industrie. La version 2.112 est la tranche 1/4 : fonctionnalité optionnelle + métadonnées d'identité. Un audit complet et une feuille de route pour 4 versions sont archivés à l'adresse .superpowers/specs/2026-05-19-pdfx-compliance-audit.md.
  • Nouvelle propriété `PDFXCompliance: AnsiString` dans THotPDF qui accepte `''` (désactivé, par défaut), `'X-1a'` (ISO 15930-1:2001), `'X-3'` (ISO 15930-3:2002) ou `'X-4'` (ISO 15930-7:2010). Définir une valeur non vide active automatiquement toutes les exigences que HotPDF peut satisfaire structurellement pour ce profil.
  • Nouvelle propriété `Trapped: AnsiString` (obligatoire selon PDFXCompliance) qui accepte les valeurs `'True'`, `'False'` ou `'Unknown'`. La famille de normes PDF/X exige cette entrée DocInfo afin que l'imprimerie sache si le fichier PDF a déjà été traité pour la trap ou s'il nécessite un traitement de trap en pré-impression. Elle est émise sous la forme d'un objet PDF /Name (et non d'une chaîne de caractères), conformément à la norme ISO 32000-1 §14.11.6.1 ; par exemple : `<< /Trapped /False >>`.
  • Identification des métadonnées XMP : le paquet annonce désormais `xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/"` avec `` défini sur la chaîne exacte spécifiée (`PDF/X-1:2001`, `PDF/X-3:2002` ou `PDF/X-4`) et (pour X-1a + X-4) `` défini sur le nom complet du profil (`PDF/X-1a:2001` ou `PDF/X-4:2010`). Adobe Acrobat, Enfocus PitStop et callas pdfaPilot reconnaissent le document comme un candidat PDF/X.
  • Validation de la fin du document : rejette les valeurs de profil inconnues, rejette les valeurs de "Trapped" vides ou non reconnues, exige un titre et augmente automatiquement la version du PDF à la version minimale obligatoire du profil (X-1a/X-3 → PDF 1.3, X-4 → PDF 1.6). L'activation du chiffrement et de la conformité PDF/X est une incompatibilité majeure ; l'appel de `EnableEncrypt` (ou `ActivateProtection := True`) génère une erreur avec un message explicatif indiquant que les flux de travail PDF/X doivent inspecter chaque objet sans gestion des mots de passe.
  • L'appelant continue de définir le profil ICC et l'OutputIntent, ainsi que les zones de découpe (TrimBox/ArtBox), les espaces colorimétriques valides pour la prépresse et l'intégration correcte des polices (et évite la transparence pour X-1a/X-3) pour garantir la conformité totale à la norme PDF/X. Les versions v2.113 à v2.115 corrigent ces lacunes : v2.113 ajoute `AddPDFXOutputIntent` (l'intent /GTS_PDFX obligatoire), v2.114 ajoute un contrôle de la transparence et l'application des contraintes sur les zones de page, et v2.115 termine la série en ajoutant des contrôles pour les actions, les annotations et les objets XFA interdits.
  • Compilation propre pour Win32 et Win64 ; les versions de base v2.108, v2.109, v2.110 et v2.111 ont été recompilées sans modification. Le nouveau test "smoke_pdfx_optin" génère trois fichiers PDF (un par profil) et vérifie l'espace de noms XMP, ainsi que les attributs GTS_PDFXVersion et GTS_PDFXConformance, en plus des informations de document /Trapped /Name, et teste les chemins d'erreur pour les profils non valides, les champs /Trapped vides, les valeurs /Trapped inconnues et les rejets liés au chiffrement.
  • Note de la série PAdES : les versions v2.109, v2.110 et v2.111 couvrent les cas d'utilisation B-B, B-T, B-LT et B-LTA, ainsi que l'utilisation autonome des horodatages. La version v2.112, initialement prévue (un PDF avec uniquement un horodatage ETSI.RFC3161), est implicitement incluse : la fonction `AddDocumentTimestampSignature` de la version v2.111 fonctionne sur un document vierge sans signature interne. Par conséquent, la série PAdES est considérée comme terminée en 3 commits, et la version v2.112 est réaffectée à PDF/X. Tous les profils de base ETSI EN 319 142-1 sont pris en charge.

2026-05-19 Version 2.111.0

  • Série de producteurs PAdES, tranche 3/4 : prise en charge de la signature de horodatage de document PAdES-B-LTA conformément à la norme ISO 32000-1 §12.8.5 + ETSI EN 319 142-1 §5.7. Le horodatage du document est une deuxième signature appliquée APRÈS la finalisation de la signature de validation à long terme ; il couvre l'intégralité du fichier d'état à long terme (signature originale + DSS) et prouve que le matériel à long terme existait à un moment notarié. Il s'agit du profil d'archivage requis pour la conservation réglementée par l'UE, au-delà de la durée de vie du certificat CA d'origine.
  • Nouvelle fonction utilitaire `THPDFPage.AddDocumentTimestampSignature(FieldName, ContentsBytes)`. Contrairement à une signature PAdES classique, une signature de date et heure de document a :
    • Un sous-filtre `/ETSI.RFC3161` (un TimeStampToken conforme à la RFC 3161, et non CAdES).
    • Un rectangle de widget de surface nulle (une signature de date et heure n'a pas d'apparence visible ; il s'agit uniquement de métadonnées cryptographiques).
    • Aucune entrée pour `/Reason`, `/Location` ou `/ContactName` (ces informations se trouvent dans les attributs signés du TST, et non dans le dictionnaire de signature).
    • Une taille par défaut de 16 Ko pour les octets de `/Contents` (l'appelant peut spécifier une taille inférieure, jusqu'à un minimum de 1 Ko ; un TimeStampToken complet conforme à la RFC 3161, avec la chaîne de certificats, fait généralement de 4 à 8 Ko).
  • La portée du créateur de signature s'arrête au format binaire : l'outil crée le dictionnaire temporaire avec les clés /Type /Sig, contenant le sous-filtre spécifique à l'horodatage et un marqueur /ByteRange + /Contents pour la correction ultérieure via PreparePDFForSigning + InsertSignatureHex. L'appelant obtient les octets TST (Timestamp Signed Data) réels, conformément à la norme RFC 3161, auprès d'une autorité d'horodatage (TSA, par exemple DigiCert / GlobalSign / FreeTSA via HTTP POST) et les insère. Le flux de travail typique d'archivage PAdES-B-LTA est le suivant : 1) émission de la signature de base PAdES-B-LT (v2.109), 2) remplissage du catalogue /DSS avec la chaîne de certificats et les informations OCSP/CRL (v2.110), 3) sauvegarde sous forme de mise à jour incrémentielle, 4) ajout du champ d'horodatage du document sur les octets de l'état LT (v2.111), 5) demande de l'horodatage à la TSA en spécifiant la plage d'octets, 6) insertion des octets de l'horodatage.
  • Compilation propre pour Win32 et Win64 ; les versions de référence v2.108, v2.109 et v2.110 ont toutes été recompilées sans modification. Le nouveau module "smoke_pades_doctimestamp" génère un champ "SigInner" conforme à la norme PAdES-B-LT, ainsi qu'un champ de horodatage de document "DocTS", grâce à une nouvelle fonction utilitaire. Le vérificateur Python s'assure que la signature interne possède le filtre "/SubFilter /ETSI.CAdES.detached", que le rectangle du widget de horodatage a une aire nulle, que le dictionnaire "/V" du horodatage possède le filtre "/SubFilter /ETSI.RFC3161" et ne contient pas les clés "/Reason", "/Location", "/ContactName", et que "/Contents" est un espace réservé de 16 Ko (32768 caractères hexadécimaux).
  • La fonctionnalité PAdES restante : v2.112 (facultative) ajoute des fichiers PDF autonomes avec horodatage ETSI.RFC3161 (sans signature interne CAdES, uniquement un conteneur de document d'horodatage).

2026-05-19 Version 2.110.0

  • Série de producteurs PAdES, tranche 2/4 : prise en charge du dictionnaire Document Security Store (DSS) conformément à la norme ISO 32000-2 §12.8.4.3 + ETSI EN 319 142-1 §5.6. Les versions PAdES-B-LT (et B-LTA) nécessitent que les informations relatives à la validation, telles que la chaîne de certificats, les réponses OCSP et les listes de révocation (CRLs), soient intégrées directement dans le document PDF, afin que les signatures puissent être vérifiées longtemps après le moment de la signature initiale, sans avoir à interroger des serveurs PKI externes.
  • Nouveaux outils pour THotPDF :
    • `EnsurePAdESDSS` — crée de manière paresseuse le dictionnaire indirect Catalog /DSS avec ses tableaux /Certs, /OCSPs, /CRLs et un sous-dictionnaire /VRI vide ; les appels suivants renvoient le dictionnaire existant.
    • `AddPAdESDSSCertificate(CertDERBytes)` — ajoute un certificat X.509 encodé en DER sous forme de flux indirect dans /DSS /Certs ; renvoie l'objet de flux indirect pour une utilisation dans les références VRI.
    • `AddPAdESDSSOCSP(OCSPDERBytes)` — de même, pour la réponse OCSP BasicOCSPResponse dans /DSS /OCSPs.
    • `AddPAdESDSSCRL(CRLDERBytes)` — de même, pour la liste de révocation des certificats dans /DSS /CRLs.
    • `AddPAdESDSSVRI(SigContentsHexSHA1, Certs, OCSPs, CRLs)` — crée une entrée VRI par signature, indexée par le SHA-1 hexadécimal en MAJUSCULES des octets /Contents de la signature (la forme de clé requise par la spécification) ; chaque entrée contient les tableaux /Cert, /OCSP et /CRL, qui font référence aux flux indirects créés ci-dessus.
  • La portée du générateur de signature s'arrête au format de fichier. L'appelant calcule toujours le SHA-1 du contenu signé final et fournit les certificats encodés en DER / les réponses OCSP / les listes de révocation de certificats (CRLs) provenant de ses outils PKI. Le flux de travail typique est le suivant : créer une signature de base PAdES-B-T (v2.109), puis ajouter les certificats / les réponses OCSP / les CRLs au DSS pour la vérification à long terme, puis ajouter des entrées VRI qui relient les informations de validation aux signatures spécifiques.
  • Compilation propre pour Win32 et Win64 ; les versions de référence v2.108 et v2.109 ont été recompilées sans modification. Le nouveau test "smoke_pades_dss" crée un champ de signature PAdES-B-LT, ajoute 2 certificats + 1 OCSP + 1 CRL à DSS, et ajoute une entrée VRI avec un digest hexadécimal de test. Le vérificateur Python parcourt la structure du dictionnaire DSS : référence à Catalog /DSS, /Certs, /OCSPs, /CRLs (tableau), vérifie le nombre d'éléments, la correspondance de la clé VRI, et la correspondance des références de certificat/OCSP/CRL dans l'entrée VRI avec les tableaux DSS de niveau supérieur.
  • Les fonctionnalités PAdES restantes : la version 2.111 implémente la signature de document horodatée PAdES-B-LTA (deuxième champ Sig avec le filtre SubFilter ETSI.RFC3161 couvrant l'intégralité du fichier LT) ; la version 2.112 (facultative) ajoute des fichiers PDF horodatés autonomes.

2026-05-19 Version 2.109.0

  • Début des travaux sur la production de signatures numériques PAdES (ETSI EN 319 142). La version v2.109 ajoute une couche d'abstraction de haut niveau au-dessus de l'infrastructure de signature ISO 32000-1 §12.8 existante (v2 de l'outil AddSignedSignatureField), qui définit de manière explicite le SubFilter requis par PAdES et valide le profil de conformité. Un audit complet ainsi qu'une feuille de route pour 4 versions ont été archivés à l'adresse .superpowers/specs/2026-05-19-pades-compliance-audit.md.
  • Nouvelle fonction `THPDFPage.AddPAdESSignatureField(FieldName, Rect, Profile, Reason, Location, ContactName, ContentsBytes, Flags)`. Le paramètre `Profile` sélectionne le niveau de base ETSI EN 319 142-1 : `'B-B'` (CAdES de base, sans horodatage), `'B-T'` (avec horodatage fiable RFC 3161, minimum pour une utilisation légale dans l'UE), `'B-LT'` (avec informations de validation DSS pour une vérification à long terme) ou `'B-LTA'` (avec signature horodatée pour l'archivage). Les quatre utilisent le `SubFilter` `'ETSI.CAdES.detached'`; le paramètre `profile` modifie les informations de diagnostic et le budget par défaut des octets `/Contents`. D'autres chaînes de caractères pour le paramètre `profile` génèrent une erreur, conformément à l'énumération ETSI.
  • Budget de contenu automatiquement ajusté : Pour PAdES-B-B + B-T, la valeur par défaut est de 16 Ko (l'appelant peut fournir une valeur inférieure ; nous imposons un minimum de 64 octets, hérité de la version 2.108). Pour PAdES-B-LT, la taille est automatiquement ajustée à un minimum de 20 Ko (chaîne de certificats CAdES + données OCSP/CRL). Pour PAdES-B-LTA, la taille est automatiquement ajustée à un minimum de 24 Ko (B-LT + horodatage du document). Les valeurs plus importantes fournies par l'appelant sont acceptées ; l'outil ne fait que appliquer le minimum.
  • Champ d'application du créateur : le wrapper crée le dictionnaire de remplacement `/Type /Sig` avec `/SubFilter /ETSI.CAdES.detached`, `/Reason`, `/Location`, `/ContactName` et `/M` (date de signature), ainsi que les marqueurs `/ByteRange` et `/Contents` pour la correction ultérieure via `PreparePDFForSigning` et `InsertSignatureHex`. La gestion des octets CMS/CAdES réels, la récupération de l'horodatage RFC 3161, la collecte des informations OCSP/CRL et la construction du dictionnaire DSS restent la responsabilité de l'appelant, car elles nécessitent une bibliothèque cryptographique externe (OpenSSL, Bouncy Castle, Windows CAPI, etc.) qui ne fait pas partie du champ d'application du créateur PDF.
  • Compilation propre pour Win32 et Win64. La nouvelle fonctionnalité `smoke_pades_signature` génère quatre champs de signature PAdES (B-B / B-T / B-LT / B-LTA) et vérifie que les valeurs de profil invalides entraînent une erreur. Le vérificateur Python affirme que `AcroForm /SigFlags` est égal à 3, que chaque widget possède `/FT /Sig` et une référence indirecte vers un dictionnaire de type `/Sig` avec `/SubFilter /ETSI.CAdES.detached`, et que la longueur hexadécimale du placeholder `/Contents` correspond à la taille de l'octet attendue (ajustée automatiquement).
  • Les prochaines fonctionnalités PAdES prévues : la version 2.110 ajoute le constructeur de dictionnaire /DSS (Document Security Store) pour les informations de validation PAdES-B-LT (chaîne de certificats + OCSP/CRL) ; la version 2.111 ajoute le champ de signature de horodatage de document autonome pour l'archivage PAdES-B-LTA ; la version 2.112 (facultative) ajoute les PDF horodatés uniquement selon la norme ETSI.RFC3161.

2026-05-19 Version 2.108.0

  • PDF/A-2 + PDF/A-3, série de producteurs, FONCTIONNALITÉ TERMINÉE (4/4) : Fichiers associés, Annexe E, ISO 19005-3. La nouvelle fonction d'aide de haut niveau `AddPDFA3AssociatedFile(FileName, MimeType, Description, Relationship, FileBytes)` permet de joindre un fichier arbitraire (facture XML, feuille de calcul source, métadonnées JSON, etc.) à un conteneur hybride PDF/A-3 et de l'enregistrer dans le tableau `/AF` du catalogue, en utilisant la sémantique `/AFRelationship` de la section E.4.
  • Flux de conteneur hybride : un cas d'utilisation typique est la facturation PDF/A-3 de type ZUGFeRD, où le rendu de la facture lisible par l'homme se trouve dans le flux de page PDF et la source XML lisible par la machine est incluse en tant que fichier associé. La clé `/AFRelationship` indique aux utilisateurs comment le fichier joint est lié au contenu visible : 'Source' (données sources originales), 'Data' (données brutes visualisées par le PDF), 'Alternative' (représentation alternative), 'Supplement' (matériel supplémentaire), 'Unspecified' (aucune des options ci-dessus).
  • Règles de validation : `AddPDFA3AssociatedFile` génère une erreur pour toute valeur de `PDFACompliance` autre que PDF/A-3 (l'annexe E est spécifique à la partie 3), avec un message indiquant d'utiliser `AddFileAttachmentAnnotation` pour PDF/A-2, et précisant que PDF/A-1 §6.1.11 interdit complètement les pièces jointes. Une valeur vide pour `FileName` ou `MimeType` génère une erreur ; une valeur `Relationship` non valide génère une erreur avec l'énumération spécifiée dans la section E.4.
  • La structure d'émission : un flux EmbeddedFile indirect contient /Type /EmbeddedFile + /Subtype + /Params <> + les octets du fichier. Le dictionnaire Filespec indirect contient /Type /Filespec + /F + /UF (les deux = FileName) + éventuellement /Desc + /EF <> + /AFRelationship (clé de l'Annexe E). Le tableau /AF dans le catalogue est créé de manière paresseuse lors de la première association et est ajouté lors des appels suivants. Le dictionnaire Filespec renvoyé permet aux appelants d'ajouter des clés optionnelles supplémentaires (par exemple, /CI checksum/info) si nécessaire.
  • Compilation propre pour Win32 et Win64. La nouvelle fonctionnalité smoke_pdfa3_associated crée une facture hybride PDF/A-3B avec une facture XML réelle attachée en tant que source /AFRelationship, puis teste trois chemins de rejet : PDF/A-1 rejeté, PDF/A-2 rejeté, /AFRelationship invalide rejeté. Le vérificateur Python valide le graphe du dictionnaire Filespec / EmbeddedFile (Type / F / UF / Desc / AFRelationship / EF F UF / EmbeddedFile Type / Subtype #2F escape / Params Size).
  • La surface de production PDF/A-2 + PDF/A-3 est maintenant entièrement verrouillée pour l'audit (option d'enveloppement v2.105 + XMP, couverture des annotations/actions interdites dans la v2.106, limites de mise en œuvre de la section 6.1.13 dans la v2.107, fichiers associés de l'annexe E dans la v2.108). Étant donné que PDF/A-1 (v2.101-104) et PDF/UA-1 (v2.94-v2.100) sont déjà conformes aux normes les plus strictes, HotPDF couvre désormais l'ensemble de la matrice de production d'archivage/accessibilité PDF/A-1/2/3 + PDF/UA-1, de bout en bout.

2026-05-19 Version 2.107.0

  • PDF/A-2 + PDF/A-3, série de producteurs, tranche 3/4 : application des limites de l'implémentation conformément à l'ISO 19005-2 §6.1.13 + ISO 19005-3 §6.1.13. La section PDF/A-1 §6.1.13 est beaucoup moins restrictive (pas de limite stricte sur la longueur des chaînes de caractères), donc cette nouvelle vérification ne s'applique que lorsque PDFACompliance est PDF/A-2 ou une version ultérieure ('2*' / '3*').
  • Nouvelle méthode publique `EnsurePDFAImplementationLimits` qui valide les valeurs contrôlées par l'appelant dans le document par rapport aux limites strictes de la spécification : les chaînes Doc.Title, Author, Subject, Keywords et Lang doivent être inférieures ou égales à 32767 octets ; chaque dimension de MediaBox de chaque page doit être comprise entre [3..14400] unités. `EndDoc` invoque automatiquement le validateur lorsque `PDFACompliance` est défini sur PDF/A-2/3 ; les appelants peuvent également l'invoquer directement pendant la construction pour un diagnostic précoce.
  • Les limites, naturellement respectées et documentées dans le rapport d'audit, sont les suivantes : plage entière (-2³¹..2³¹-1), plage réelle (±3,403×10³⁸, proche de zéro ≥1,175×10⁻³⁸), longueur du nom ≤127 octets, nombre maximal d'objets indirects ≤8388607, profondeur d'imbrication q/Q ≤28, nombre maximal de colorants DeviceN ≤32, CID ≤65535. Les chemins d'émission de HotPDF ne dépassent jamais ces limites, car ils sont liés aux structures de données contrôlées par le fabricant. Le validateur se concentre sur les chaînes fournies par l'appelant et les limites de page, car ce sont les seuls paramètres qu'un appelant réel peut dépasser.
  • Les formulaires XFA (ISO 19005-1 §6.4.2) : HotPDF n'émet pas les éléments AcroForm /XFA ou Catalog /NeedsRendering. Ces éléments sont naturellement satisfaits dans les versions PDF/A-1/2/3, comme documenté dans le rapport d'audit, afin que les extensions futures des fabricants ne les réintroduisent pas.
  • Glyphe .notdef (§6.2.11.8 dans PDF/A-2) : la spécification interdit aux opérateurs d'affichage de texte de faire référence au glyphe .notdef. La gestion des polices de HotPDF évite ce problème lorsque les appelants utilisent des polices TTF Unicode enregistrées (version 2.74 à 2.86), car le créateur associe chaque point de code à un glyphe réel ou refuse l'enregistrement. La responsabilité de l'émission de texte brut incombe à l'appelant ; cela est documenté dans le rapport d'audit.
  • Espace de noms XMP (section 6.6.2) : la spécification interdit l'attribut "bytes" ou "encoding" dans l'en-tête du paquet XMP. `BuildXMPPacket` génère un en-tête minimal (id="W5M0MpCehiHzreSzNTczkc9d") sans aucun de ces attributs, ce qui est naturellement respecté dans toutes les parties PDF/A.
  • Compilation propre pour Win32 et Win64. De nouveaux tests "smoke" pour `smoke_pdfa2_limits` couvrent trois scénarios : le test PDF/A-2, qui passe dans les limites spécifiées ; le test PDF/A-1 avec un champ "Title" de 32768 octets, qui passe (sans déclencher la vérification de la section §6.1.13) ; et le test PDF/A-2 avec un champ "Title" de 32768 octets, qui est rejeté avec le diagnostic correspondant à la section de la spécification. Les anciennes configurations de référence PDF/A-2/3 ont été recompilées sans modification.
  • La partie restante du module de création de PDF/A-2/3 : la version 2.108 implémente les fichiers associés de PDF/A-3, annexe E (la fonctionnalité de conteneur hybride spécifique à PDF/A-3 : tableau /AF dans le catalogue, contenant les spécifications des fichiers avec la clé /AFRelationship, ainsi que les fichiers intégrés avec les paramètres /CheckSum et /ModDate).

2026-05-19 Version 2.106.0

  • PDF/A-2 + série de producteurs PDF/A-3, version 2/4 : couverture de PDF/A-2 §6.3.1 + §6.5.1 (et de PDF/A-3 §6.3.1 + §6.5.1, identiques). Les mécanismes de restriction des annotations et des actions PDF/A-1, déjà actifs pour tout PDFACompliance non vide dans la version 2.104, continuent de fonctionner sans modification sous PDF/A-2/3. La version 2.106 confirme ce comportement, met à jour les messages de diagnostic pour faire référence aux sections unifiées de la spécification pour toutes les parties PDF/A, et documente les sous-types interdits supplémentaires introduits dans PDF/A-2, que HotPDF satisfait naturellement (sans chemin d'émission public).
  • Actions interdites : PDF/A-1 interdit 6 actions (Lancer / Son / Film / Réinitialiser le formulaire / Importer des données / JavaScript). PDF/A-2 + PDF/A-3 étendent cet ensemble interdit à 13 en ajoutant Masquer / Définir l'état de l'OCG / Rendu / Transparence / Aller à la vue 3D, ainsi que les sous-types obsolètes de définition d'état / non-opérationnels. `AddLaunchLink` continue de générer une erreur ; HotPDF n'a pas de fonctionnalité publique qui déclenche les 12 autres, ils sont donc automatiquement satisfaits.
  • Matrices de types d'annotations interdits : PDF/A-1 interdit les pièces jointes de fichiers / sons / vidéos. PDF/A-2 / PDF/A-3 suppriment l'interdiction des pièces jointes de fichiers (assouplie dans la version v2.105), mais ajoutent les éléments 3D / écran à la liste des éléments interdits. Les fonctions `AddSoundAnnotation` et `AddMovieAnnotation` continuent de générer des erreurs dans toutes les parties de PDF/A ; HotPDF ne prend pas en charge l'émission d'éléments 3D / écran, donc ces exigences sont naturellement satisfaites.
  • Message de diagnostic mis à jour : les trois fonctions v2.104 (AddSoundAnnotation, AddMovieAnnotation, AddLaunchLink) font désormais référence aux trois sections de spécification pertinentes dans leur texte d'erreur (par exemple, "PDF/A-1 §6.5.2 / PDF/A-2 §6.3.1 / PDF/A-3 §6.3.1"), afin que les développeurs puissent constater l'interdiction unifiée. Le message AddLaunchLink énumère également l'ensemble étendu des actions interdites pour PDF/A-2/3.
  • Compilation propre pour Win32 et Win64. Le nouveau test smoke `smoke_pdfa2_annot_action` vérifie les trois fonctions pour tous les six niveaux PDF/A-2/3 (2B, 2U, 2A, 3B, 3U, 3A) ; chaque appel vérifie l'exception attendue avec un diagnostic §6.3.1 / §6.5.1. Les tests de référence PDF/A-1 précédents (smoke_pdfa1_compliance / smoke_pdfa1_forbidden / smoke_pdfa1_annot_action) et le test smoke v2.105 `smoke_pdfa2_compliance` ont tous été recompilés sans modification.
  • Les portions de code concernant les producteurs PDF/A-2/3 restantes : la version v2.107 applique les limites de mise en œuvre de la norme ISO 19005-2 §6.1.13 (plages de valeurs entières/réelles/chaînes/octets pour les noms, imbrication q/Q, colorants DeviceN, CID, limites de page) + §6.4.2 XFA + §6.2.11 Type 3 / .notdef strict ; la version v2.108 implémente les fichiers associés de l'annexe E de PDF/A-3 (fichiers PDF conteneurs hybrides avec des types de fichiers intégrés arbitraires).

2026-05-19 Version 2.105.0

  • Nous avons commencé une série de quatre versions axées sur la conformité aux normes PDF/A-2 (ISO 19005-2:2011) et PDF/A-3 (ISO 19005-3:2012). L'audit et la feuille de route sont archivés à l'adresse .superpowers/specs/2026-05-19-pdfa2-pdfa3-compliance-audit.md. La version v2.105 introduit l'option d'activation de la couche d'encapsulation, les extensions d'espace de noms XMP pdfaid, une mise à jour automatique de la version de base du PDF à 1.7, et un assouplissement sélectif des contraintes strictes des versions v2.101 à v2.104 pour PDF/A-1, contraintes que les spécifications PDF/A-2 et PDF/A-3 autorisent explicitement.
  • La propriété PDFACompliance accepte désormais six nouvelles valeurs, en plus des valeurs existantes '' / 'A' / 'B' pour PDF/A-1 : '2A' / '2B' / '2U' (niveaux A / B / U de PDF/A-2) et '3A' / '3B' / '3U' (niveaux A / B / U de PDF/A-3). Le niveau U est le nouveau niveau "préservation de l'Unicode uniquement" introduit par PDF/A-2 (texte visuel + texte extractible en Unicode, sans exigence de PDF balisé).
  • BuildXMPPacket a été étendu : l'élément `` reflète désormais le numéro de partie analysé (1 / 2 / 3) et `` reflète la lettre de niveau analysée (A / B / U). Les validateurs tels que veraPDF identifient la partie PDF/A du document grâce à cette paire. Conformément à l'ISO 19005-2 §6.6.4 + ISO 19005-3 §6.6.4 Tableau 8.
  • Auto-bump : PDFACompliance '2*' / '3*' incrémente automatiquement la version du document à PDF 1.7, car PDF/A-2 et PDF/A-3 sont tous deux basés sur ISO 32000-1 (PDF 1.7). PDF/A-1 reste ancré à PDF 1.4.
  • v2.103 : la restriction de la transparence a été assouplie. `RegisterExtGState` ne génère désormais une erreur que lorsque la transparence alpha est utilisée avec un mode de fusion autre que "Normal", et uniquement lorsque `PDFACompliance` est défini sur PDF/A-1 strict ('A' ou 'B'). Les normes PDF/A-2 et PDF/A-3 §6.4 autorisent explicitement la transparence (avec des exigences spécifiques telles que la présence de `OutputIntent` et les modes de fusion nommés complets de PDF 1.4), de sorte que les valeurs `PDFACompliance` '2*' et '3*' permettent à l'appel de passer.
  • v2.104 : La restriction concernant les pièces jointes de fichiers est assouplie. La fonction `AddFileAttachmentAnnotation` génère désormais une erreur uniquement dans le cas de PDF/A-1 strict. Le PDF/A-2 §6.3.1 interdit uniquement les types d'annotations 3D, audio, vidéo et les animations ; les pièces jointes de fichiers sont autorisées et constituent la base du flux de travail hybride de fichiers associés de l'annexe E du PDF/A-3. Les autres restrictions concernant les annotations/actions (annotations audio et vidéo ; action de lancement) restent en vigueur pour toutes les versions de PDF/A, conformément aux interdictions communes des sections §6.3.1 et §6.5.1.
  • Nouvelles méthodes d'assistance THotPDF PDFAPart, PDFAConformanceLevel, IsPDFA1Strict et IsPDFA2OrLater facilitent la gestion des différentes options. Les anciennes versions PDF/A (v2.101-104) utilisent désormais ces méthodes pour un code plus propre et des messages d'erreur plus clairs, suggérant de passer à PDF/A-2 ou PDF/A-3 lorsque cela est approprié.
  • Compilation propre pour Win32 et Win64 ; les versions de référence v2.101-104 (tests de conformité/interdiction/actions d'annotation PDF/A-1) ont été recompilées sans modification. Le nouveau test smoke smoke_pdfa2_compliance génère quatre fichiers PDF (niveaux 2B/2U/2A/3U), teste la relaxation de la transparence v2.103, la relaxation des pièces jointes v2.104, ainsi que deux chemins de validation (un niveau '4Q' invalide est rejeté ; la vérification de la transparence PDF/A-1 est toujours active). Le vérificateur Python affirme que les métadonnées XMP pdfaid:part correspondent à la conformité pour chaque niveau, et que le niveau 2A hérite des balises PDF.
  • Les versions v2.106 ajoutent 7 actions supplémentaires à la liste des actions interdites (Hide, SetOCGState, Rendition, Trans, GoTo3DView ont été ajoutées ; certaines actions ont été dépréciées et remplacées par des opérations sans effet) et modifient les restrictions sur les types d'annotations (3D et Screen ont été ajoutés, FileAttachment a été supprimé) ; v2.107 applique les limites de mise en œuvre de l'ISO 19005-2 §6.1.13 et active les contrôles XFA ; v2.108 implémente les fichiers associés de l'annexe E du PDF/A-3 (fichiers PDF conteneurs hybrides).

2026-05-19 Version 2.104.0

  • La série de correctifs PDF/A-1 pour le producteur est maintenant terminée (slice 4/4) : les types d'annotations interdits (FileAttachment, Sound, Movie) dans la section §6.5.2 et le sous-type d'action de lancement dans la section §6.6.1 ont été corrigés. Avec la version v2.104, les 17 lacunes initialement identifiées lors de l'audit PDF/A-1 du 19 mai 2026 (.superpowers/specs/2026-05-19-pdfa1-compliance-audit.md) ont été corrigées : les quatre points majeurs (§5, §6.7.11 identification, §6.1.3 interdiction du chiffrement, §6.2.2 OutputIntent, §6.4 transparence) ainsi que les diverses fonctionnalités interdites.
  • §6.5.2 types d'annotations interdites : `AddFileAttachmentAnnotation`, `AddSoundAnnotation` et `AddMovieAnnotation` lèvent désormais une exception dans le contexte de la conformité PDFA, avec un diagnostic clair indiquant la section de la spécification concernée. Conformément à la spécification, "les types FileAttachment, Sound et Movie ne doivent pas être autorisés" afin d'éviter les dépendances de contenu externe et les éléments multimédias dans les fichiers d'archivage.
  • §6.6.1 Action de lancement : `AddLaunchLink` lève désormais une exception dans le contexte de la conformité PDFA, avec un message de diagnostic indiquant la cible du lancement. Conformément à la spécification, "les actions de lancement, de son, de film, de réinitialisation de formulaire, d'importation de données et de JavaScript ne sont pas autorisées". Les cinq autres types d'actions interdits (son/film/réinitialisation de formulaire/importation de données/JavaScript) n'ont pas de point d'entrée public dans HotPDF qui les génère, ils sont donc naturellement conformes sans passerelles explicites.
  • La combinaison de PDFUACompliance et PDFACompliance fonctionne désormais correctement sur les quatre variantes de PDF/A. Les deux options s'imbriquent : le niveau A hérite de PDFUACompliance, qui est activé automatiquement pour les PDF avec balises ; les deux enveloppements appliquent leurs propres protections spécifiques (Suspects/Onglets/Langue pour PDF/UA ; Cryptage/Transparence/Annotations/Action pour PDF/A) sans interférence.
  • Résumé de la finalisation des audits : tous les aspects des exigences de format de fichier PDF/A-1, côté fabricant, que HotPDF peut satisfaire structurellement, sont maintenant finalisés. Les responsabilités de l'appelant restantes (correspondant aux sections 6.1.5 sur l'équivalence Info-XMP, 6.2.3.3 sur l'adéquation de l'espace colorimétrique et de l'OutputIntent, et 6.3 sur les spécificités des polices, qui étaient déjà largement gérées dans les versions 2.74 à 2.86 pour PDF/UA) sont conformes aux responsabilités correspondantes dans PDF/UA-1.
  • Compilation propre pour Win32 et Win64 ; v2.103, recompilation propre de smoke_pdfa1_forbidden. Le nouveau test smoke smoke_pdfa1_annot_action exécute les quatre chemins conditionnels (AddFileAttachmentAnnotation, AddSoundAnnotation, AddMovieAnnotation, AddLaunchLink) dans PDFACompliance et vérifie que chaque appel génère une erreur avec un diagnostic §6.5.2 ou §6.6.1.
  • La surface de production PDF/A-1 est maintenant entièrement verrouillée pour l'audit. Les extensions PDF/A-2 (basée sur l'ISO 19005-2:2011 et le PDF 1.7, permettant la transparence et les calques) et PDF/A-3 (ISO 19005-3:2012, permettant l'intégration de fichiers pour les flux de travail hybrides) restent des candidats potentiels pour le futur, en fonction de la demande des utilisateurs.

2026-05-19 Version 2.103.0

  • PDF/A-1, série de producteurs, tranche 3/4 : correction de la section §6.4 concernant la transparence (lacune critique n°15) + section §6.2.8 concernant la fonction de transfert /TR de ExtGState (lacune n°14). Deux sections de la section §6 liées aux chemins de producteurs HotPDF existants sont naturellement satisfaites sans modifications du code : la section §6.1.10 concernant le filtre LZW (HotPDF n'émet que FlateDecode dans son chemin d'écriture) et la section §6.2.4 concernant l'interpolation d'images (/Interpolate) (HotPDF n'émet jamais /Interpolate). Celles-ci sont maintenant documentées comme étant automatiques dans le rapport d'audit.
  • §6.4 La transparence interdit les valeurs alpha autres que 1.0 et les modes de fusion autres que Normal/Compatible. RegisterExtGState est désormais conditionné par PDFACompliance : une valeur alpha de remplissage inférieure à 1 déclenche une erreur (PDF/A-1 exige /ca = 1.0) ; une valeur alpha de contour inférieure à 1 déclenche une erreur (/CA = 1.0) ; un mode de fusion autre que `Normal` ou `Compatible` déclenche une erreur. Les trois diagnostics indiquent la section de la spécification et la valeur incorrecte. L'état ExtGState par défaut (sans clés alpha, sans mode de fusion) et les valeurs autorisées explicites (valeurs alpha de 1.0, modes de fusion Normal/Compatible) restent inchangés.
  • §6.2.8 ExtGState interdit la clé de fonction de transfert /TR (dépréciée ; PDF/A-1 autorise uniquement /TR2 avec la valeur /Default, et même cela est préférable à éviter). RegisterTransferFunctionState génère maintenant une erreur dans le mode PDFACompliance avec un message explicatif. Les utilisateurs qui ont besoin de fonctions de transfert pour les flux de travail PDF/X peuvent toujours utiliser cette fonctionnalité en dehors du mode PDFACompliance.
  • §6.1.10 LZW + §6.2.4 Interpolate : documenté comme étant naturellement satisfait par les chemins de production existants de HotPDF (uniquement l'encodeur FlateDecode, sans émission de "/Interpolate"). Aucune modification de code n'est nécessaire ; cela a été signalé dans les commentaires du rapport d'audit afin que les futurs utilisateurs ne réintroduisent pas ces éléments.
  • Compilation propre pour Win32 et Win64 ; recompilation propre de v2.102 pour smoke_pdfa1_compliance. Le nouveau test smoke smoke_pdfa1_forbidden exécute les trois chemins conditionnels (ca<1, CA<1, BM=Multiply, enregistrement /TR) et vérifie que les chemins autorisés (ca=1.0, CA=1.0, BM=Normal/Compatible, sans alpha) fonctionnent toujours. Aucun vérificateur — le test lui-même affirme via try/except que chaque appel conditionnel lève une exception.
  • La partie restante du module PDF/A-1 concernant le fabricant : la version 2.104 corrige les types d'annotations interdits (FileAttachment, Sound, Movie) conformément à la section 6.5.2, ainsi que les règles relatives aux annotations /F /AP de la section 6.5.3, et les types d'actions interdits (Launch, Sound, Movie, ResetForm, ImportData, JavaScript) de la section 6.6.1, ainsi que les champs de formulaire /A /AA et /NeedAppearances de la section 6.9. Après le déploiement de la version 2.104, le module PDF/A-1 concernant le fabricant sera entièrement finalisé et ne pourra plus être modifié.

2026-05-19 Version 2.102.0

  • PDF/A-1 (ISO 19005-1:2005) série de producteurs, tranche 2/4 : correction de l'absence de profil ICC dans la section §6.2.2 OutputIntent. Une nouvelle fonction d'aide de haut niveau `AddPDFAOutputIntent(OutputConditionIdentifier, Info, ICCProfileStream, NumComponents, AlternateCS)` regroupe les deux appels `RegisterICCProfile` et `AddOutputIntent('GTS_PDFA1', ...)` en un seul. PDF/A-1 strict exige une entrée `/Type /OutputIntent /S /GTS_PDFA1` avec un flux ICC `/DestOutputProfile` valide ; sans cela, les fichiers conformes ne peuvent pas reproduire fidèlement les couleurs sur différentes plateformes.
  • La fonctionnalité PDFACompliance ajoute une vérification `EnsurePDFAOutputIntent` : elle parcourt la liste des OutputIntent enregistrés, recherche au moins une entrée `/S /GTS_PDFA1` avec `/DestOutputProfile`. En l'absence de cette entrée, un message d'erreur clair est généré, indiquant la section de la spécification concernée et orientant les utilisateurs vers la fonction AddPDFAOutputIntent. Conformément à la section §6.2.2 et à l'annexe A.
  • Workflow d'archivage typique : transmettez un flux de profil ICC sRGB IEC61966-2.1 pour les PDF/A destinés à l'écran, FOGRA39 / GRACoL pour l'impression, ou le profil CMYK enregistré approprié pour la prépresse. NumComponents doit être 1 (Gray), 3 (RGB / Lab) ou 4 (CMYK) conformément à la table 66 de la section 8.6.5.5 de la norme PDF 1.7 ; l'outil transmet la validation à RegisterICCProfile.
  • L'outil de validation vérifie : une valeur vide pour OutputConditionIdentifier provoque une erreur (la section 6.2.2 exige que l'identifiant soit présent) ; une valeur nulle pour ICCProfileStream provoque une erreur (DestOutputProfile est obligatoire). La fonction ne renvoie aucune valeur ; l'OutputIntent est automatiquement enregistré dans FOutputIntents et est accessible via le chemin de sérialisation existant du catalogue /OutputIntents.
  • Compilation propre pour Win32 et Win64 ; `v2.101 smoke_pdfa1_compliance` mis à jour pour appeler `AddPDFAOutputIntent` (avec un faux fichier ICC de 192 octets ; les appels réels utilisent un vrai fichier ICC). Un nouveau cas de validation vérifie que l'absence de `OutputIntent` dans `PDFACompliance` génère une erreur conformément à la section 6.2.2. Le vérificateur Python a été étendu pour vérifier le tableau `/OutputIntents` dans `Catalog`, en parcourant les entrées pour trouver `/S /GTS_PDFA1` avec une référence indirecte à `/DestOutputProfile`.
  • Les portions de code du producteur PDF/A-1 restantes : v2.103 corrige les problèmes #15 (transparence, CRITIQUE), #5 (filtre LZW), #10 (interpolation d'images) et #14 (ExtGState /TR) ; v2.104 corrige les problèmes #16 (pièces jointes/sons/vidéos pour les annotations), #17 (règles pour les annotations /F /AP), #18 (actions de lancement/sons/vidéos/réinitialisation du formulaire/importation de données/JavaScript) et #20 (champs de formulaire /A /AA et /NeedAppearances).

2026-05-19 Version 2.101.0

  • Une série de quatre versions conformes à la norme PDF/A-1 (ISO 19005-1:2005) a été lancée, avec une option d'activation de la couche d'enveloppe. Le rapport d'audit complet des 17 points est archivé à l'adresse `.superpowers/specs/2026-05-19-pdfa1-compliance-audit.md`; la version 2.101 apporte les éléments fondamentaux (propriété PDFACompliance, identification XMP pdfaid, rigueur du titre/langue, protection contre les conflits de chiffrement). Les versions 2.102 à 2.104 comblent les lacunes restantes en matière de gestion des couleurs, de transparence, de polices et d'annotations/actions.
  • Nouvelle propriété `PDFACompliance: AnsiString` qui accepte '' (désactivé, par défaut), 'A' (niveau A : visuel + PDF balisé + accessibilité) ou 'B' (niveau B : préservation visuelle uniquement). Les valeurs non valides génèrent une erreur à la fin du document. Conformément à la norme ISO 19005-1:2005 §5, les niveaux de conformité.
  • Définir PDFACompliance sur 'A' active automatiquement PDFUACompliance (le niveau A hérite des exigences de PDF balisé de la section 6.8, qui correspondent aux exigences de structure logique de la section 7 de PDF/UA-1). Les deux fonctionnalités peuvent être combinées sans conflit ; la couche v2.94 PDF/UA-1 Lang/Title/Suspects s'ajoute aux protections v2.101 PDF/A.
  • Cela active automatiquement FEnableXMPMetadata, ce qui permet au document de contenir le flux /Metadata XMP requis. Conformément à la section 6.7.2, les métadonnées du catalogue sont obligatoires.
  • BuildXMPPacket amélioré : lorsque PDFACompliance n'est pas vide, le paquet XMP déclare `xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"` ainsi que `1` et `A` (ou `B`). Les validateurs tels que veraPDF s'appuient sur ce triple exact pour classer le document comme un candidat PDF/A-1A ou 1B. Conformément à la section §6.7.11, Tableau 6, schéma d'identification PDF/A.
  • Titre / Strictesse de la langue : Lorsque PDFACompliance est activé et que Doc.Title est vide, une erreur est levée (PDF/A-1 §6.7.3 exige dc:title dans le format XMP équivalent à Info /Title). La strictesse de la langue correspond au comportement de v2.94 pour PDFUACompliance (§6.8.4 pour le niveau A), de sorte que les auteurs doivent choisir une balise BCP-47 valide au lieu de recevoir une valeur par défaut silencieuse de 'en'.
  • Protection contre les conflits de chiffrement : conformément à la section 6.1.3, la balise de fin de fichier ne doit pas contenir "/Encrypt". La fonction EnableEncrypt (l'entrée interne appelée lorsque les options de mot de passe du propriétaire/utilisateur/protection sont définies) génère désormais un message d'erreur clair lorsque PDFACompliance n'est pas vide. La fonction EndDoc signale le conflit par le même chemin, afin que les appelants puissent constater l'échec avant la sérialisation.
  • La responsabilité du côté de l'appelant comprend toujours : l'émission d'un OutputIntent PDF/A-1 valide avec profil ICC (suite à la version 2.102), l'évitement de la transparence (version 2.103), l'évitement des types d'annotations/actions interdits (version 2.104) et la création d'une structure sémantique réelle pour le niveau A (couvert par les outils PDF étiquetés des versions 2.96 à 2.99).
  • Compilation propre pour Win32 et Win64 ; la version de base v2.100 et le test smoke_pdfua_link_contents sont recompilés proprement. Le nouveau test smoke smoke_pdfa1_compliance génère à la fois des fichiers PDF de niveau A et de niveau B, et teste trois chemins de validation (niveau Z invalide, titre vide, conflit entre chiffrement et PDFACompliance). Le vérificateur Python affirme xmlns:pdfaid + pdfaid:part=1 + et vérifie la conformité, le titre (dc:title) et, pour le niveau A, ajoute également /MarkInfo /Marked true + Catalog /Lang + /StructTreeRoot + xmlns:pdfuaid (héritage automatique).

2026-05-19 Version 2.100.0

  • Correction d'un manque de couverture concernant les annotations de lien /Contents dans PDF/UA-1 §7.18.5, identifié lors de l'audit du 2026-05-19. La version v2.95 a ajouté laDescription à AddURILink ; la version v2.100 apporte le même support pour les descriptions alternatives aux trois points d'entrée de lien restants : AddGoToLink (saut intra-document), AddGoToRLink (saut inter-fichier) et AddLaunchLink (lancement de fichier externe).
  • Chaque fonction auxiliaire gagne un paramètre final optionnel `const Description: AnsiString = ''`. Lorsqu'il n'est pas vide, le dictionnaire d'annotation contient une entrée `/Contents (Description)`; dans le mode `PDFUACompliance`, une description vide génère une erreur avec un message clair indiquant le lien cible concerné, afin qu'une description alternative manquante ne passe pas silencieusement. La valeur par défaut, vide, assure la compatibilité ascendante en dehors du mode PDFUACompliance.
  • Conformément à PDF/UA-1 §7.18.5, de manière stricte : "Les liens doivent contenir une description alternative via leur clé 'Contents', comme décrit dans ISO 32000-1:2008, 14.9.3." Cette spécification s'applique à tous les types d'annotations de liens, et non seulement aux liens URI ; les signatures d'assistance rendent désormais cela uniforme.
  • Flux de travail typique : `Page.AddGoToLink(R, 1, 700, 'Jump to page 2: Methodology'); Page.AddGoToRLink(R, 'companion.pdf', 0, -1, false, 'Open companion document for full data tables'); Page.AddLaunchLink(R, 'readme.txt', false, 'Open README in default text editor');`
  • Compilation propre pour Win32 et Win64 ; la version de base v2.99 et le test smoke_pdfua_figure ont été recompilés avec succès. Le nouveau test smoke smoke_pdfua_link_contents crée un document de 2 pages avec trois annotations de type "Lien" sur la page 0 (aller à la page 1, aller à "companion.pdf", lancer "readme.txt") et teste également le chemin d'exception empty-Description pour la conformité PDFUA pour les trois liens. Le vérificateur Python affirme que chaque annotation de lien contient /Subtype /Link, le type d'action correspondant /S /GoTo (ou /GoToR ou /Launch) et une valeur /Contents correspondant à la description fournie.
  • Résumé de la couverture de la surface du producteur PDF/UA-1 : avec la version 2.100, les quatre points d'entrée des annotations de liens satisfont désormais la section 7.18.5. Combiné avec la finalisation de l'audit de la version 2.94 (Suspects, Onglets, Langue), de la version 2.95 (Contenu de l'URI, Bit 10, ID) et de la série d'aides sémantiques pour PDF balisés des versions 2.96 à 2.99 (Titre, Liste, Tableau, Figure), la surface du producteur PDF/UA-1 de HotPDF est maintenant entièrement finalisée par l'audit, tant au niveau de la couche d'encapsulation stricte par rapport aux spécifications qu'au niveau de la couche d'API ergonomique.

2026-05-19 Version 2.99.0

  • Ajout de `BeginTaggedFigure(Parent, AltText, BBox): FigureElem` + `EndTaggedFigure` comme quatrième et dernière partie de la série d'outils sémantiques pour PDF/UA-1 §7.3 (Graphiques). Ces éléments encapsulent les opérations de dessin fournies par l'appelant (objet X image, chemin vectoriel, rectangle rempli) dans un élément de structure "Figure", avec l'attribut de mise en page obligatoire "/Alt" et l'attribut optionnel "/BBox".
  • /Alt est obligatoire (il n'y a pas de valeur par défaut). Conformément à PDF/UA-1 §7.3, la norme est stricte : "Les balises de figure doivent inclure une représentation alternative ou un texte de remplacement qui représente le contenu marqué avec la balise de figure." Un texte Alt vide génère une erreur avec un message clair indiquant aux utilisateurs d'utiliser la surcharge à 6 arguments de `AddStructureElement` (si `/ActualText`, et non `/Alt`, est le mécanisme de texte alternatif approprié).
  • Une BBox optionnelle est un tableau de 4 valeurs [llx, lly, urx, ury] décrivant la zone englobante de la figure dans l'espace utilisateur par défaut, et est ajoutée comme /A << /O /Layout /BBox [...] >> conformément à la norme ISO 32000-1 14.8.5.4.5, qui définit le propriétaire de l'attribut de mise en page. Pour supprimer complètement l'attribut BBox, transmettez un tableau vide. Une BBox de longueur incorrecte (1/2/3/5 éléments ou plus) génère une erreur, en utilisant la disposition rectangulaire spécifiée comme guide.
  • Flux de travail typique : `Fig := Doc.BeginTaggedFigure(Root, 'Logo de l'entreprise : flèche pointant vers la droite', [72, 600, 200, 720]); ... dessiner le contenu de la figure ... Doc.EndTaggedFigure;` La figure participe à la même structure MCID / ParentTree que les autres chemins BeginTaggedContent de la version 2.90, mais avec les attributs /Alt et /BBox ajoutés automatiquement.
  • Cela corrige la partie relative à la responsabilité de l'appelant, conformément à la section 7.3 de la norme PDF/UA-1, telle que mentionnée dans le rapport d'audit. La série d'assistants sémantiques pour les PDF étiquetés couvre désormais les quatre types de structures complexes : section 7.4 (Titre, v2.96), section 7.6 (Liste, v2.97), section 7.5 (Tableau, v2.98) et section 7.3 (Figure, v2.99). Combinées aux corrections de la couche d'interface de v2.94 et v2.95, la fonctionnalité de création de PDF/UA-1 de HotPDF est désormais conforme aux spécifications au niveau de la conformité et ergonomique au niveau de l'API.
  • Compilation propre pour Win32 et Win64 ; la version de base v2.98 et les tests smoke_pdfua_table ont été recompilés avec succès. Le nouveau test smoke smoke_pdfua_figure génère deux éléments de structure Figure (un avec /Alt + /BBox, un avec /Alt uniquement) et teste également les cas d'exception pour les textes alternatifs vides et les boîtes englobantes mal formées. Le vérificateur Python affirme les deux types de Figure /S, vérifie que le contenu du texte /Alt correspond et que les valeurs du tableau BBox sont [72, 600, 200, 720].

2026-05-19 Version 2.98.0

  • Ajout de quatre utilitaires pour les tableaux étiquetés conformément à la section 7.5 (Tableaux) de PDF/UA-1, dans le cadre de la série d'utilitaires sémantiques pour les PDF étiquetés. `BeginTaggedTable(Parent): TableElem` crée le conteneur de structure de tableau ; `AddTaggedTableRow(Table): TRElem` ajoute une ligne TR ; `EmitTaggedTableHeader(TR, X, Y, Text, Scope): THElem` génère une cellule TH avec l'attribut obligatoire /Scope ; `EmitTaggedTableCell(TR, X, Y, Text): TDElem` génère une cellule de données TD. Les cinq types d'étiquettes (Table, TR, TH, TD, ainsi que l'objet attribut) sont conformes à la spécification.
  • L'attribut /Scope (ISO 32000-1 14.8.5.7 Tableau 350) est obligatoire pour l'élément helper (sans valeur par défaut), avec des valeurs valides telles que `Row`, `Col` ou `Both`. Les chaînes /Scope non valides génèrent une erreur, en suivant les directives de la spécification. PDF/UA-1 §7.5 est strict : "Les éléments de structure de type TH doivent avoir un attribut /Scope. Si la structure du tableau ne peut pas être déterminée via les en-têtes et les ID, alors les éléments de structure de type TH doivent avoir un attribut /Scope." L'imposition de l'attribut /Scope dans la signature de l'élément helper empêche l'échec de conformité dû à l'absence de l'attribut /Scope.
  • La sérialisation de la portée suit le format standard des objets d'attribut : `/A << /O /Table /Scope / >>` (conformément à la norme ISO 32000-1 14.7.5.3, Classe Map), de sorte que les lecteurs consommant les données la reconnaissent comme un attribut de l'espace de noms Table. C'est le même schéma que l'attribut List de la version 2.97 : `/A << /O /List /ListNumbering ... >>`.
  • Les éléments `` et `` sont de simples conteneurs de structure (sans contenu marqué sur la page), mais les éléments `
    ` et `` contiennent du texte visible, ils passent donc par les étapes `BeginTaggedContent + TextOut + EndTaggedContent`. Chaque cellule `` et `` reçoit son propre MCID, l'opérateur `BDC` dans le flux de contenu de la page et une entrée `ParentTree`. Une fonction auxiliaire renvoie l'élément `StructElem` de la cellule pour les appelants qui souhaitent ajouter des attributs supplémentaires (par exemple, la liste `/Headers` pour les tableaux complexes, `/RowSpan`, `/ColSpan`).
  • Flux de travail typique : `T := Doc.BeginTaggedTable(Root); R := Doc.AddTaggedTableRow(T); Doc.EmitTaggedTableHeader(R, 72, 750, WideString('Name'), 'Col'); Doc.EmitTaggedTableHeader(R, 200, 750, WideString('Age'), 'Col'); R2 := Doc.AddTaggedTableRow(T); Doc.EmitTaggedTableCell(R2, 72, 730, WideString('Alice')); ...` Remplace la structure multi-étapes de la version 2.90 ainsi que la séquence BDC/EMC pour chaque cellule.
  • Cela corrige la section 7.5 relative à la responsabilité de l'appelant, conformément à la norme PDF/UA-1, telle que mentionnée dans le rapport d'audit. La série d'assistants sémantiques pour les PDF étiquetés couvre désormais la section 7.4 (Titre, v2.96), la section 7.6 (Liste, v2.97) et la section 7.5 (Tableau, v2.98). La partie restante (v2.99+) : assistant pour les figures, pour la section 7.3, avec /BBox + /Alt + bloc de dessin fourni par l'appelant.
  • Compilation propre pour Win32 et Win64 ; la version de base v2.97 et le test smoke_pdfua_list ont été recompilés avec succès. Le nouveau test smoke smoke_pdfua_table crée un tableau à 3 lignes (1 en-tête + 2 données) avec 3 cellules TH (Scope=Col) + 6 cellules TD + et teste l'exception "invalid-Scope". Le vérificateur Python affirme la structure complète Table > TR > TH/TD avec /Scope /Col sur chaque TH.
  • 2026-05-19 Version 2.97.0

    • Ajout de deux utilitaires PDF/UA-1 §7.6 pour les listes, qui constituent la deuxième partie de la série d'utilitaires sémantiques pour les PDF étiquetés : `BeginTaggedList(Parent, NumberingStyle): ListElem` crée l'élément de structure L avec un objet d'attribut /A << /O /List /ListNumbering /<Style> >> conformément à la norme ISO 32000-1 14.8.5.5 ; `EmitTaggedListItem(ListElem, LblX, LblY, LabelText, BodyX, BodyY, BodyText): LIElem` génère une sous-structure LI complète > {Lbl, LBody} avec du contenu marqué pour l'étiquette visible et le texte du corps.
    • Le paramètre NumberingStyle accepte les 8 noms spécifiés dans la norme PDF/UA-1 / ISO 32000-1 : `None`, `Decimal`, `UpperRoman`, `LowerRoman`, `UpperAlpha`, `LowerAlpha`, `Circle`, `Disc`. Les noms de style non valides génèrent une erreur avec la valeur incorrecte et l'ensemble complet des spécifications comme référence. Une chaîne vide omet complètement /ListNumbering, permettant aux appelants de joindre un objet d'attribut personnalisé avant la validation.
    • Selon PDF/UA-1 §7.6 : les listes ordonnées nécessitent un attribut `/ListNumbering` explicite ; les listes non ordonnées peuvent utiliser `None` ou l'un des glyphes de puce. L'outil ne force aucune de ces options ; il appartient à l'appelant de choisir le style qui correspond au contenu visible.
    • Flux de travail typique : `Lst := Doc.BeginTaggedList(Root, 'Decimal'); Doc.EmitTaggedListItem(Lst, 72, 750, WideString('1.'), 96, 750, WideString('First item')); ...` Chaque élément de liste est une seule instruction qui remplace la chaîne de six lignes de la version 2.90, à savoir LI + Lbl-BDC-TextOut-EMC + LBody-BDC-TextOut-EMC.
    • Les éléments enfants Lbl et LBody passent tous les deux par la fonction BeginTaggedContent (de sorte que chacun reçoit son propre MCID et son entrée ParentTree), et la fonction auxiliaire EmitTaggedListItem renvoie l'élément de structure LI pour les appelants qui souhaitent ajouter des éléments enfants LI imbriqués, l'attribut /Alt ou l'attribut /Lang.
    • Cela corrige le problème lié à la section 7.6 de la norme PDF/UA-1 concernant la responsabilité de l'appelant, tel que mentionné dans le rapport d'audit. Les fonctions d'aide sémantique pour les PDF balisés restantes (v2.98+) : la fonction d'aide pour les tableaux couvre la section 7.5 (Tableau / TR / TH / TD avec /Scope), et la fonction d'aide pour les figures couvre la section 7.3 (Figure + /Alt + attribut /BBox).
    • Compilation propre pour Win32 et Win64 ; la version de base v2.96 et le test smoke_pdfua_heading sont recompilés proprement. Le nouveau test smoke smoke_pdfua_list crée une liste ordonnée avec 3 éléments numérotés en décimal, ainsi qu'une liste non ordonnée avec 2 éléments sans numéro, et teste le chemin d'exception pour les styles non valides. Le vérificateur Python affirme l'existence de deux StructElems avec l'attribut /S /L, avec des valeurs distinctes pour l'attribut /ListNumbering (3 vs 2), et des éléments enfants Lbl/LBody dans le premier élément LI de la liste ordonnée.

    2026-05-19 Version 2.96.0

    • Ajout d'une fonction utilitaire de haut niveau `EmitTaggedHeading(Level, Parent, X, Y, Text)` pour PDF/UA-1 §7.4. Un appel génère un élément de structure `/H1`..`/H6` complet, associé à son texte visible sur la page actuelle : la fonction utilitaire alloue un MCID spécifique à chaque page, exécute l'opérateur BDC, puis `TextOut`, suivi de `EMC`, construit l'élément `StructElem` avec le rôle `/H<Level>` approprié et le connecte à `/ParentTree`. Remplace la séquence de trois lignes `BeginTaggedContent + TextOut + EndTaggedContent` utilisée couramment pour les en-têtes dans la version 2.90.
    • Le paramètre Level accepte les valeurs de 1 à 6 (l'ensemble standard des titres). Si la valeur de Level est hors plage, une exception est levée avec un message d'erreur clair. La norme PDF/UA-1 §7.4.3 autorise l'utilisation de balises H7+ définies par l'utilisateur, mais elles sont rares ; les applications qui en ont besoin peuvent revenir à la séquence explicite BeginTaggedContent('H7', ...).
    • Retourne l'élément StructElem afin que les appelants puissent chaîner l'ajout d'attributs (tels que /Lang, /Alt pour les titres décoratifs, etc.) après que l'aide ait renvoyé une valeur.
    • Flux de travail typique : `Doc.EmitTaggedHeading(1, RootElem, 72, 750, WideString('Chapitre 1'));` remplace désormais entièrement la structure complexe existante, qui consistait en plusieurs lignes de code utilisant BDC + TextOut + EMC + AddStructureElement.
    • Il s'agit de la première partie d'une série de "fonctions utilitaires sémantiques pour les PDF étiquetés", qui fait suite à la finalisation du module PDF/UA-1 dans la version v2.95. Les versions ultérieures (v2.97 et suivantes) couvriront les fonctions utilitaires pour les listes (L / LI / Lbl / LBody) et les tableaux (Table / TR / TH / TD avec /Scope), afin de finaliser les aspects de responsabilité de l'appelant dans les sections §7.5 et §7.6 du rapport d'audit.
    • Compilation propre pour Win32 et Win64 ; recompilation propre des bases de référence v2.95. Le nouveau test smoke `smoke_pdfua_heading` génère trois titres (H1/H2/H3) et teste également le chemin d'exception de vérification de plage Level=7 ; le vérificateur Python affirme l'existence de trois éléments StructElems /S /H et des opérateurs BDC /H correspondants dans le flux de contenu de page décompressé.

    2026-05-19 Version 2.95.0

    • Fermeture de l'audit PDF/UA-1 : les trois lacunes restantes, identifiées côté fabricant dans l'audit de la version 2.94 (section 7.18.5, contenu des liens ; section 7.16, bit 10 du chiffrement ; section 7.9, ID de l'élément de structure), ont été corrigées. La conformité PDF/UA-1 du produit est désormais complète selon les spécifications ; les six lacunes initialement identifiées lors de l'audit ont été corrigées dans les versions 2.94 et 2.95.
    • §7.18.5 Contenu des liens (HAUT) : La fonction `AddURILink(Rect, URL, Description='')` gagne un troisième paramètre, `Description`, qui, lorsqu'il n'est pas vide, remplit la clé `/Contents` de l'annotation avec la description alternative fournie. La norme PDF/UA-1 §7.18.5 rend cela obligatoire : "Les liens doivent contenir une description alternative via leur clé Contents." Dans le contexte de PDFUACompliance, une description vide déclenche désormais une erreur avec un message clair, garantissant ainsi que chaque lien est accompagné d'un texte lisible à l'écran. La valeur par défaut de Description est '' pour assurer la compatibilité avec les versions antérieures en dehors du mode PDFUACompliance.
    • §7.16 Bit de chiffrement 10 (MED) : lorsque PDFUACompliance est True et que le document est chiffré (via EnableEncrypt), HotPDF effectue automatiquement une opération OU logique sur `ProtectFlags := ProtectFlags or $200` (le bit 10 correspond à "Extraire le texte et les graphiques pour une utilisation avec les technologies d'assistance"). Conformément à PDF/UA-1 §7.16 : "Un fichier conforme et chiffré doit contenir une clé P dans son dictionnaire de chiffrement. Le 10e bit de la clé P doit être défini à True." Sans ce bit, les lecteurs d'écran ne peuvent pas extraire le contenu d'un PDF chiffré, ce qui compromet l'accessibilité. La correction est conditionnelle : le chiffrement non conforme à PDF/UA conserve les flags fournis par l'appelant.
    • §7.9 StructElem ID (LOW) : la nouvelle surcharge de `AddStructureElement` avec 7 arguments accepte un paramètre `IDStr` non vide qui définit la clé `/ID` de l'élément de structure. Cette fonction auxiliaire maintient un ensemble interne d'ID attribués et génère une erreur en cas de conflit, afin d'éviter que des ID de notes en double (ce qui pourrait perturber les liens de référence vers les notes et les technologies d'assistance) ne passent à travers. Conformément à la spécification : "Chaque balise de note doit avoir une entrée unique dans la clé ID."
    • Refactorisation de `EnableEncrypt` : le code principal est maintenant situé dans `EnableEncryptInternal`, et la fonction publique `EnableEncrypt` est une enveloppe de 6 lignes qui effectue d'abord le marquage PDF/UA-1 Bit 10, puis transmet la requête. Les branches de chiffrement v2, v4 et v5 sont inchangées, byte par byte ; les appels existants à la fonction de chiffrement conservent une sortie identique, sauf s'ils activent explicitement `PDFUACompliance`.
    • Vérifier la couverture : de nouveaux tests "smoke_pdfua_gap_closure" pour la section §7.18.5 (lien avec la description) et la section §7.9 (deux éléments de structure "Note" avec des ID distincts + une tentative de collision qui doit générer une erreur). Vérifier que l'attribut `/Contents` est présent et correspond à la description, et que deux valeurs uniques de `/ID` pour les éléments "Note" existent. La correction de l'octet 10 pour le chiffrement est documentée dans le rapport d'audit ; la couverture des tests "smoke" pour les PDF chiffrés sera reportée à une refonte plus importante des tests de chiffrement.
    • Couverture des spécifications : avec la version v2.95, les 6 lacunes identifiées lors de l'audit PDF/UA-1 du 2026-05-19 (`.superpowers/specs/2026-05-19-pdfua-compliance-audit.md`) sont maintenant corrigées. La conformité de HotPDF aux exigences PDF/UA-1, côté producteur, est désormais stricte pour la couche d'enrobage (métadonnées §5, conformité §6, exigences du catalogue §7.1, langue §7.2, chiffrement §7.16, onglets §7.18.3, contenu des liens §7.18.5, identifiants de notes §7.9). Les décisions concernant la structure sémantique (hiérarchie des titres, imbrication des listes, structure TH/portée des tableaux, qualité des légendes/texte alternatif) restent de la responsabilité de l'appelant, comme toujours.

    2026-05-19 Version 2.94.0

    • Audit de conformité côté producteur pour PDF/UA-1 (ISO 14289-1:2014) : nous avons corrigé trois problèmes de conformité réels qui n'étaient pas couverts par l'activation optionnelle de haut niveau de la version 2.87. L'audit a comparé la sortie de HotPDF v2.93 à chaque clause des exigences de format de fichier §7 et a identifié six problèmes ; cette version corrige les trois problèmes liés à la fin du document (Suspects key, onglets de pages annotées, stricteté de la langue). Les trois problèmes restants (Link Contents, bit 10 du chiffrement, StructElem ID) seront corrigés dans les versions 2.95 à 2.97.
    • §7.1 Suspects (gravité élevée) : le dictionnaire MarkInfo du Catalog émet maintenant `/Suspects false` lorsque `PDFUACompliance` est True. Conformément à la spécification "Les fichiers prétendant être conformes à cette norme internationale doivent avoir une valeur Suspects de false" – veraPDF et des validateurs similaires vérifient la présence explicite de la clé, et non simplement son absence. Dans la version 2.93, la clé était complètement absente, ce qui a déclenché l'erreur "Catalog MarkInfo ne contient pas d'entrée Suspects" lors d'une validation stricte par rapport à la spécification.
    • §7.18.3 Tabulations (sévérité MED) : `EndDoc` parcourt désormais chaque page et ajoute `/Tabs /S` à toute page qui contient un tableau `/Annots` non vide et qui ne déclare pas déjà `/Tabs`. Conformément à la spécification : "Chaque page contenant une annotation doit contenir dans son dictionnaire de page la clé `Tabs`... et sa valeur doit être `S`." Cette fonctionnalité ne s'active que dans le mode `PDFUACompliance` ; les appelants qui définissent explicitement `/Tabs` (via `THPDFPage.SetTabsOrder`) conservent leur choix.
    • §7.2 Lang (gravité MED) : `PDFUACompliance=True` avec un `Doc.Lang` vide déclenche désormais une exception avec un message clair, au lieu de remplir silencieusement avec la valeur `'en'`. Dans les versions antérieures à v2.94, les documents non anglais étaient incorrectement étiquetés (tout contenu chinois, arabe, japonais, etc., générait silencieusement une mauvaise étiquette BCP-47, que les lecteurs d'écran utilisaient pour changer la prononciation). Les appelants doivent maintenant déclarer explicitement la langue du document ; utilisation typique : `Doc.Lang := 'en-US'`, `'zh-CN'`, `'ar-SA'`, etc.
    • Note de compatibilité descendante : les clients existants de PDFUACompliance doivent ajouter `Doc.Lang := '...'` avant BeginDoc / EndDoc. Les quatre exemples (smoke_pdfua_compliance, smoke_pdfua_alt_actualtext, smoke_pdfua_annot_structparents, smoke_pdfua_tagged_content) ont été mis à jour pour définir `Doc.Lang := 'en-US'` en conséquence. Les clients qui n'utilisent pas PDFUACompliance ne sont pas affectés.
    • Vérification de la couverture : le script `smoke_pdfua_compliance_verify.py` vérifie maintenant la présence de `/Suspects false` dans le dictionnaire MarkInfo du catalogue ; le script `smoke_pdfua_annot_structparents_verify.py` vérifie la présence de `/Tabs /S` sur la page annotée. Les deux scripts sont exécutés de bout en bout sur le fichier PDF résultant.
    • Rapport d'audit : un rapport d'audit complet de conformité PDF/UA-1, couvrant les 21 clauses du format de fichier §7, est archivé à l'emplacement `.superpowers/specs/2026-05-19-pdfua-compliance-audit.md` (local au projet, non enregistré). Le rapport classe chaque clause comme étant « satisfaite automatiquement par HotPDF », « responsabilité de l'appelant avec une API d'assistance » ou « écart réel du fabricant » et classe les écarts restants par gravité pour la feuille de route v2.95+.

    2026-05-19 Version 2.93.0

    • Ajout de `RegisterColorConversionLUT3D(GridR, GridG, GridB, OutputComponents, Samples, BitsPerSample=8, Order=1): THPDFStreamObject`, un wrapper de haut niveau pour le type de fonction primitif 0 de la version 2.52, utilisé pour les cas d'utilisation courants de LUT de gestion des couleurs avec 3 entrées. Il construit en interne les tableaux standard /Domain=[0,1]*3 + /Range=[0,1]*OutputComponents + /Size=[GridR, GridG, GridB] et les transmet à RegisterSampledFunction.
    • Flux de travail typique : conversion basée sur les profils ICC, de sRGB vers Lab, de sRGB vers CMYK, ou de RGB vers une conversion de lien de périphérique RGB, exprimée sous forme de LUT 3D. Le wrapper valide les tailles de grille par axe et la plage de OutputComponents ; la fonction RegisterSampledFunction sous-jacente valide BitsPerSample / Order / le nombre total d'octets par rapport à la taille de charge utile Sample attendue. Les tampons incompatibles génèrent une erreur avec un diagnostic clair.
    • Disposition des octets d'exemple : ordre des lignes sur la grille 3D, avec R le plus rapide, puis G, puis B ; nombre d'octets par cellule pour OutputComponents lorsque BitsPerSample=8. Total = GridR * GridG * GridB * OutputComponents octets. Les profondeurs de bits plus élevées (12, 16) nécessitent que l'appelant emballe les données conformément aux règles d'emballage d'octets MSB-first spécifiées dans la documentation.
    • Impact visible pour l'utilisateur : un flux de travail de gestion des couleurs peut maintenant exprimer une simulation RGB 17x17x17 -> CMYK ICC en une seule ligne, en utilisant un tableau d'échantillons précalculé, plutôt que de construire manuellement les paramètres /Domain, /Range et /Size. L'objet indirect THPDFStreamObject renvoyé peut être utilisé dans n'importe quelle API qui consomme des fonctions : emplacements de dégradés axiaux/radiaux de type 2, transformations de teinte via RegisterSeparationLUT, fonction de transfert /TR dans l'ExtGState, génération de noir /BG dans l'ExtGState.
    • Compatibilité descendante : la fonction primitive RegisterSampledFunction existante n'a pas été modifiée ; le nouveau wrapper est une simple extension. Les utilisateurs qui ont besoin de plages /Domain non par défaut (par exemple, Lab L* dans [0..100], a* / b* dans [-128..127]) ou de plages non rectangulaires continuent d'utiliser directement RegisterSampledFunction.
    • Statut du candidat n°4 : il s'agit de la seule portion de la matrice de candidats correspondant à la fonction "Type 0 3D". Ce wrapper de haut niveau rend la primitive N=3 existante plus conviviale pour les cas d'utilisation typiques de gestion des couleurs ; le candidat n°4 est donc fermé.

    2026-05-19 Version 2.92.0

    • Ajout de `RegisterHalftoneType5(ColorantNames, Halftones, DefaultHalftone, HalftoneName)` pour finaliser la famille de demi-tons ExtGState `/HT`. Le type 5 est un dictionnaire multi-composants indexé par nom de colorant (par exemple, /Cyan, /Magenta, /Yellow, /Black, /Red, /Green, /Blue, /Gray, ainsi que toute couleur spot Separation/DeviceN enregistrée), dont les valeurs sont des références indirectes vers des demi-tons secondaires de type 1/6/10/16. Les flux de travail de prépresse CMYK peuvent désormais attribuer à chaque encre sa propre fréquence de trame/angle/forme de point dans une seule entrée ExtGState.
    • Signature de tableau parallèle : `ColorantNames` et `Halftones` sont appairés et validés pour avoir la même longueur. Les noms de colorants vides ou les valeurs `nil` pour les demi-tons génèrent une erreur avec l'index concerné. Le `DefaultHalftone` optionnel devient la valeur de repli `/Default` du dictionnaire, utilisée par les lecteurs pour tout colorant qui ne figure pas dans la liste explicite (ce qui est courant pour les documents contenant des couleurs spéciales inattendues).
    • La structure du dictionnaire de sortie (PDF 1.7 ISO 32000-1 10.5.5.2) est la suivante : /Type /Halftone + /HalftoneType 5 + optionnel /HalftoneName + une entrée /ColorantName par paire + optionnel /Default. Elle renvoie l'objet de dictionnaire indirect THPDFDictionaryObject afin que l'appelant puisse le transmettre à `RegisterHalftoneState` v2.64, comme pour tout autre objet de demi-tonnage.
    • Validation : au moins un composant ou un `DefaultHalftone` est requis (un Type 5 vide sans `/Default` n'a pas de sens). L'outil de validation ne vérifie pas que les demi-tons secondaires fournis ne sont pas de Type 5 (la spécification interdit l'imbrication de Type 5), car l'appelant devrait activement construire un graphe auto-référentiel, et les flux de travail de prépresse réels ne rencontrent pas ce problème.
    • Impact visible pour l'utilisateur : un ingénieur de prépresse publiant une brochure en quatre couleurs peut maintenant configurer quatre écrans indépendants (Cyan à 105° / 75 lpi, Magenta à 75° / 75 lpi, Jaune à 90° / 75 lpi, Noir à 45° / 75 lpi via des fonctions spot de type 1, ou remplacer n'importe lequel par des rasters de seuil de type 6 pour un écrêtage FM) et les englober dans un seul ExtGState. Le même ExtGState est ensuite activé par tout appel de dessin qui nécessite les écrans par canal.
    • Statut du candidat n°3 : ceci est la deuxième et dernière partie de la famille de demi-tons `/HT` ExtGState. L'ensemble complet des fonctionnalités (fonction ponctuelle de type 1 dans la version 2.64, composant multiple de type 5 dans la version 2.92, seuil de type 6/10/16 dans la version 2.91) est maintenant conforme à la spécification PDF 1.7. Le candidat n°3 est terminé.

    2026-05-19 Version 2.91.0

    • Trois constructeurs de demi-tons en flux de seuil ont été ajoutés pour compléter la famille de demi-tons `ExtGState /HT` initiée dans la version 2.64 : `RegisterHalftoneType6` (raster de seuil 8 bits, indexé par largeur/hauteur), `RegisterHalftoneType10` (raster de seuil 8 bits avec cellules parallélogrammes via Xsquare/Ysquare pour des motifs inclinés) et `RegisterHalftoneType16` (raster de seuil 16 bits, précision de 65536 niveaux pour la prépresse haut de gamme).
    • Chaque constructeur renvoie un objet de flux indirect de type /Type /Halftone que les appelants peuvent transmettre à `RegisterHalftoneState` v2.64 pour l'encapsuler dans une entrée ExtGState /HT, exactement comme les demi-tons de fonction ponctuelle de type 1. Les entrées facultatives /HalftoneName, /TransferFunction ou /TransferFunction /Identity correspondent au modèle de type 1.
    • Validation de la taille : pour le type 6, `len(ThresholdBytes)` doit être égal à `Width*Height` ; pour le type 10, `Xsquare^2 + Ysquare^2` (disposition de carrés empilés, selon la spécification PDF 1.7, section 10.5.5.4) ; pour le type 16, `Width*Height*2` (paires uint16 en ordre de poids fort vers poids faible, fournies par l'appelant). Les tampons incompatibles déclenchent une exception, indiquant à la fois le nombre de bytes réel et le nombre de bytes attendu.
    • La fonction interne partagée `_HotPDFCreateHalftoneStream` élimine les doublons dans la construction par type : allocation de flux indirecte, en-tête "/Type /Halftone + /HalftoneType N", nom facultatif + entrées de fonction de transfert, écriture de la charge utile + horodatage "/Length". Chaque fonction publique valide uniquement les clés de taille spécifiques au type et les transmet.
    • Impact visible pour l'utilisateur : les flux de travail de prépresse qui nécessitent des motifs de trame définis par l'utilisateur (formes de points personnalisées, trames à modulation de fréquence, cellules inclinées) disposent désormais d'un point d'entrée HotPDF. L'appelant fournit l'image raster de seuil (qu'il crée généralement hors ligne à partir d'un générateur de motifs de trame), HotPDF génère l'objet de flux /Type /Halftone conforme à la spécification et l'intègre à la chaîne de ressources ExtGState.
    • Couverture des spécifications : PDF 1.7 ISO 32000-1 10.5.5.3 (Type 6) + 10.5.5.4 (Type 10) + 10.5.5.5 (Type 16). La version est automatiquement mise à jour à PDF 1.2 (pour correspondre à la version minimale requise, car les demi-tons ont été implémentés ensemble).
    • Statut du candidat n°3 : ceci est la première partie de la matrice de candidats "ExtGState /HT halftone remaining types". Le deuxième et dernier élément, un demi-tonnage multi-composants de type 5 (un dictionnaire indexé par le nom du composant de couleur, qui délègue à des sous-dictionnaires de type 1/6/10/16 pour les écrans par canal, pour la prépresse CMYK), sera inclus dans la version 2.92.

    2026-05-19 Version 2.90.0

    • Ajout d'une paire d'utilitaires pour les séquences de contenu marqué de haut niveau : `THotPDF.BeginTaggedContent(Role, Parent): THPDFDictionaryObject` + `THotPDF.EndTaggedContent`. Cet utilitaire alloue automatiquement un MCID par page, émet l'opérateur BDC dans le flux de contenu de la page actuelle, crée l'élément StructElem sous Parent, et le connecte à /ParentTree en une seule opération. Le résultat final est que les utilisateurs de PDF/UA-1 peuvent étiqueter les paragraphes de contenu visible sans avoir à gérer manuellement les compteurs MCID.
    • Utilisation typique : `Para := Doc.BeginTaggedContent('P', Root); Doc.CurrentPage.TextOut(...); Doc.EndTaggedContent;` L'objet StructElem renvoyé peut être chaîné à AddStructureElement('Span', Para, ...) pour une sous-structure, ou il peut contenir les attributs /Alt et /ActualText via le chemin d'attribut v2.88.
    • Nouveau champ THPDFPage.FNextMCID qui suit l'allocation de MCID par page ; il est réinitialisé pour chaque page (initialisé à 0 de manière paresseuse lors de l'initialisation de BeginDoc). Les opérateurs de bas niveau BeginMarkedContentMCID / EndMarkedContent (disponibles dans HotPDF depuis la version v2.11) restent disponibles pour les appelants qui souhaitent un contrôle explicite du MCID.
    • Intégration de la pipeline : `BeginTaggedContent` émet "/Role <> BDC" dans le flux de contenu de la page actuelle, puis appelle `AddStructureElement(Role, Parent, PageIdx, MCID)`, qui construit l'élément de structure et exécute `RegisterMCIDForPage` (le chemin v2.11 qui ajoute de manière paresseuse "/StructParents" dans le dictionnaire de la page et agrandit le tableau par page dans "/ParentTree"). `EndTaggedContent` émet "EMC" dans le flux de contenu de la page actuelle. L'imbrication fonctionne car les paires BDC/EMC s'imbriquent implicitement via l'ordre linéaire du flux de contenu de la page.
    • Impact visible pour l'utilisateur : un document candidat PDF/UA-1 peut désormais étiqueter chaque paragraphe, titre, bloc de texte ou légende de figure visible avec une structure sémantique, en utilisant deux lignes de texte encadrant l'appel de dessin. veraPDF accepte les séquences de contenu de page et de contenu marqué résultantes, ainsi que les liens vers l'arborescence de structure ; les technologies d'assistance suivent la structure du document vers le contenu marqué et annoncent le rôle et le texte.
    • Statut du candidat n°1 : quatrième et dernière étape. La fonctionnalité PDF/UA-1 côté producteur couvre désormais l'option d'inclusion (v2.87) + les attributs /Alt et /ActualText (v2.88) + la connexion inverse annot/StructParent et OBJR (v2.89) + l'enveloppement automatique BDC/EMC du contenu de la page (v2.90). Les appelants conservent toujours le contrôle des décisions concernant la topologie de l'arbre de structure (hiérarchie des titres, imbrication des listes, en-têtes de tableau), mais le câblage mécanique est entièrement automatisé. Le candidat n°1 est terminé.

    2026-05-19 Version 2.89.0

    • Ajout de la liaison entre les annotations et la structure conformément à la spécification PDF 1.7, section 14.7.4.4. La nouvelle fonction d'aide `THotPDF.RegisterAnnotForStructure(AnnotDict, StructElem)` alloue une nouvelle clé /ParentTree, ajoute /StructParent à l'annotation, stocke l'élément StructElem à /ParentTree[Key] (une forme de référence unique pour les annotations, distincte de la forme de tableau de références utilisée par les entrées MCID de page), et ajoute `<< /Type /OBJR /Obj >` au tableau /K de l'élément StructElem. Les lecteurs d'écran peuvent désormais naviguer depuis n'importe quelle annotation étiquetée jusqu'à son élément de structure parent et vice versa.
    • Ajout de `THPDFPage.AddURILink(Rect, URL): THPDFDictionaryObject` afin de fournir un point d'entrée pour les appels PDF/UA-1 qui nécessitent un objet de dictionnaire PDF avec une valeur de retour pour l'annotation URI. Les méthodes existantes `AddGoToLink`, `AddGoToRLink` et `AddLaunchLink` ne renvoient pas leurs dictionnaires d'annotations (une limitation de l'API issue des versions précédentes) ; la nouvelle méthode `AddURILink` renvoie le dictionnaire d'annotation indirect pour qu'il puisse être transmis directement à `RegisterAnnotForStructure`.
    • Impact visible pour l'utilisateur : un document candidat PDF/UA-1 peut maintenant associer une structure sémantique à un hyperlien en trois lignes : `LinkAnnot := Doc.CurrentPage.AddURILink(R, 'https://example.org/'); LinkElem := Doc.AddStructureElement('Link', RootElem, -1, -1); Doc.RegisterAnnotForStructure(LinkAnnot, LinkElem);`. Les technologies d'assistance suivant la structure du document peuvent maintenant accéder au lien, annoncer son objectif et le présenter comme un élément activable.
    • Note d'implémentation : la boucle v2.11 `EmitTaggedPDFRoot` qui génère les entrées `/ParentTree` et `/Nums` utilisait un transtypage forcé `THPDFArrayObject(FParentTree.Items[I])`. Dans la version v2.89, le transtypage est élargi à `THPDFObject` car les entrées d'annotation stockent un dictionnaire unique plutôt qu'un tableau ; `THPDFArrayObject.AddObject` effectue déjà une vérification de type à l'exécution, donc le transtypage était toujours nominal. Dans la version v2.11+, il est confirmé que les tableaux stockés dans `FParentTree` restent stables en termes de taille.
    • Note concernant la spécification : PDF 1.7, section 14.7.4, autorise les valeurs de /ParentTree à être soit un tableau (pour les séquences de contenu marqué indexées par MCID), soit une référence directe à un élément de structure (StructElem) (pour les annotations, les éléments et autres éléments structurels non-MCID). La version v2.89 est la première version qui utilise la forme de référence unique ; la forme de tableau continue de fonctionner via le chemin v2.11 AddStructureElement-with-MCID.
    • Statut du candidat n°1 : troisième étape de l'implémentation côté producteur pour la conformité PDF/UA. Une étape reste : l'auto-ajustement BDC/EMC du contenu de la page, afin que les chemins AddTextField + CurrentPage.TextOut puissent générer des séquences de contenu marqué sans appels d'opérateurs manuels. Après cela, la fonctionnalité PDF/UA côté producteur atteindra un niveau de qualité satisfaisant.

    2026-05-19 Version 2.88.0

    • Ajout d'une signature surchargée pour `AddStructureElement` qui accepte les chaînes d'attributs optionnels `/Alt` et `/ActualText`. PDF/UA-1 (ISO 14289-1) exige que le contenu non textuel (figures, formules, glyphes décoratifs) fournisse des alternatives accessibles aux lecteurs d'écran ; la nouvelle surcharge permet de les associer facilement à un StructElem en un seul appel.
    • `/Alt` (description alternative) est ce que les technologies d'assistance lisent à haute voix pour le contenu non textuel - utilisation typique : éléments de structure de figure englobant une image ou un graphique. `/ActualText` est ce qui est renvoyé lors du copier-coller lorsque les glyphes visibles diffèrent des caractères Unicode attendus - utilisation typique : ligatures décoratives, initiales, calligraphie difficile à extraire.
    • Les deux attributs sont des chaînes de texte PDF émises via le chemin d'échappement standard et sécurisé pour les chaînes de caractères ; les chaînes vides permettent de sauter l'entrée correspondante, de sorte que les appels existants avec quatre arguments conservent une sortie identique en termes de bytes. La signature originale `AddStructureElement(Role, Parent, PageIndex, MCID)` avec quatre arguments est conservée grâce à la directive `overload` de Pascal.
    • Impact visible : un document candidat PDF/UA-1 peut maintenant marquer une figure de logo avec `AddStructureElement('Figure', Root, 0, 0, 'Logo de l'entreprise', '')` et une ligature avec `AddStructureElement('Span', Root, 0, 1, '', 'Arrêt de bus')`; veraPDF et les technologies d'assistance consomment les entrées /Alt et /ActualText résultantes sans configuration supplémentaire.
    • Placement de la pipeline : la surcharge de la version 2.88 est redirigée vers l'implémentation de base de la version 2.11 (de sorte que le branchement de StructTreeRoot, l'ajout du tableau /K, le lien arrière /Pg et l'enregistrement MCID/ParentTree fonctionnent de la même manière) et ajoute uniquement les deux entrées d'attributs par la suite. Aucune modification des sites d'appel existants ; la stabilité des octets de la version 2.74 à 2.87 est préservée.
    • Statut du candidat n°1 : ceci est la deuxième étape du développement côté producteur pour la conformité PDF/UA. Améliorations à venir : ajustement automatique des sauts de ligne pour le contenu de la page (afin que les fonctions `AddTextField` et `CurrentPage.TextOut` puissent générer des séquences de contenu marqué sans appels d'opérateurs manuels) ; intégration de `/StructParents` pour les annotations (afin que la navigation des lecteurs d'écran atteigne également les liens et les widgets de formulaire).

    2026-05-19 Version 2.87.0

    • Ajout d'une option de conformité PDF/UA-1 (ISO 14289-1) de haut niveau via la nouvelle propriété `PDFUACompliance`. Définir la valeur sur True avant BeginDoc/EndDoc active automatiquement toutes les exigences du côté du créateur de PDF/UA-1 que HotPDF peut satisfaire sans intervention de l'appelant : /MarkInfo /Marked = true, stub pour /StructTreeRoot, /Lang (par défaut 'en' si vide), /ViewerPreferences /DisplayDocTitle = true, flux de métadonnées XMP et l'identifiant pdfuaid:part = 1 enregistré par AIIM dans le paquet XMP.
    • Au lieu de six options, une seule propriété : auparavant, pour obtenir la conformité PDF/UA-1, l'appelant devait définir EnableTaggedPDF, EnableXMPMetadata, Lang, ViewerPreferences := [vpDisplayDocTitle] et Title séparément, puis créer un paquet XMP personnalisé pour ajouter l'espace de noms pdfuaid. La version 2.87 regroupe tout cela en PDFUACompliance:=True ; les options individuelles restent disponibles et sont prises en compte si l'appelant les définit explicitement.
    • Mise à jour du paquet XMP : `BuildXMPPacket` émet désormais `xmlns:pdfuaid="http://www.aiim.org/pdfua/ns/id/"` ainsi que `1` chaque fois que `PDFUACompliance` est vrai. VeraPDF et d'autres validateurs PDF/UA-1 détectent les documents comme des candidats PDF/UA-1 grâce à cette combinaison exacte d'espace de noms et d'identifiant.
    • Impact visible pour l'utilisateur : un document PDF créé avec `Doc.Title := '...'; Doc.PDFUACompliance := True; Doc.BeginDoc; ...; Doc.EndDoc;` est validé comme candidat PDF/UA-1 dans veraPDF sans configuration supplémentaire de l'appelant, à condition que l'auteur du corps du document crée une véritable structure arborescente via les séquences AddStructureElement et contenu marqué. Les flux de publication obligatoires pour les secteurs gouvernementaux, éducatifs et liés à l'accessibilité disposent désormais d'un seul interrupteur.
    • Responsabilité de l'appelant : PDF/UA-1 exige également l'intégrité de l'arborescence de structure (chaque glyphe doit appartenir à un élément de structure étiqueté), la présence de /Alt ou /ActualText pour le contenu des figures/formules, un ordre de tabulation logique, une hiérarchie de titres valide, etc. Cette option couvre l'enveloppe de métadonnées du catalogue que les validateurs automatisés vérifient en premier ; la conformité sémantique complète dépend toujours du fait que l'appelant crée honnêtement l'arborescence de structure via AddStructureElement et les opérateurs BDC/EMC pour le contenu marqué.
    • Compatibilité descendante : PDFUACompliance par défaut est False, ce qui permet aux versions antérieures (v2.74 à v2.86) de conserver une sortie identique en termes de bytes. Les flags existants EnableTaggedPDF et EnableXMPMetadata continuent de fonctionner de manière indépendante lorsque la nouvelle option est désactivée.
    • Il s'agit de la première étape de la matrice candidate n°1 (génération côté producteur pour les PDF étiquetés / PDF/UA). Les améliorations suivantes (v2.88+) incluent : prise en charge de /Alt et /ActualText dans AddStructureElement, fonctions d'aide BDC / EMC pour le contenu de la page dans AddTextField et CurrentPage.TextOut, et configuration de /StructParents pour les annotations.

    2026-05-19 Version 2.86.0

    • Amélioration du parseur de cmap de RegisterUnicodeTTF pour prendre en charge le format 12 d'OpenType (couverture complète et segmentée de l'Unicode). Les versions v2.75 à v2.85 ne parsaient que le format 4 (mappage de segment BMP hérité) ; les polices modernes qui incluent le format 12 en plus du format 4 utilisent désormais cette table plus complète. La sélection de la sous-table privilégie le format 12 par rapport au format 4, car le format 12 est l'autorité pour la plage complète de points de code.
    • Nouveau parseur `_TTFParseCmapFormat12` : il lit l'en-tête de 16 octets (format/réservé/longueur/langue/nombre de groupes), puis itère sur les groupes de 12 octets (charCode de début/charCode de fin/ID de glyphe de début). Pour chaque point de code C dans [charCode de début..charCode de fin], l'ID du glyphe est égal à l'ID du glyphe de début + (C - charCode de début). Les limites sont vérifiées pour chaque lecture multi-octets ; les groupes tronqués ou malformés sont ignorés silencieusement.
    • La pondération des sous-tableaux a été mise à jour :
      • plateforme 3 (Microsoft) + encodage 10 (Unicode complet) + format 12 : 120 (meilleur)
      • plateforme 0 (Unicode) + encodage 4 ou 6 + format 12 : 110
      • tout autre format 12 : 105
      • plateforme 3 + encodage 1 (Unicode BMP) + format 4 : 100 (repli vers BMP obsolète)
      • plateforme 0 + encodage 3..4 + format 4 : 80
      • plateforme 3 + encodage 10 + format 4 : 70
      • tout autre format 4 : 50
    • La plage SMP : le tableau de sortie CpToGid conserve une taille de BMP (10000 entrées × 2 octets = 128 Ko) car notre encodage Identity-H utilise des CID de 2 octets (0..65535). Les 12 entrées SMP (U+10000+) sont analysées mais ne sont pas stockées ; le mécanisme de parcours des entrées de format 12 tronque endCharCode à $FFFF avant l'itération. Une couverture complète de la plage SMP dans /CIDToGIDMap nécessiterait un encodage différent (Identity-V avec une table CMap de paires substituées ou Adobe-Japan1) et est en dehors du champ d'application.
    • Impact visible : les polices qui ne sont disponibles qu'au format 12 (certaines polices CJK modernes, Segoe UI Emoji / Symbol) remplissent désormais correctement les champs /W, /CIDToGIDMap, /FontFile2 et sont correctement traitées par le sous-ensembleur v2.84. Avant la version v2.86, ces polices utilisaient une solution de repli silencieuse pour l'analyse de la table cmap et ignoraient les quatre flux, ce qui revenait au résultat basé uniquement sur les métriques de la version v2.74.
    • Stabilité des octets : les polices au format 4 (Arial, Tahoma) continuent de suivre le même chemin de code et produisent la même sortie CpToGid. Les polices qui ont à la fois le format 4 et le format 12 utilisent désormais le format 12 pour BMP, ce qui donne généralement la même correspondance BMP (le format 12 est un ensemble strict). Les tests existants des versions 2.74 à 2.85 pour ces polices restent stables en termes de taille de fichier.
    • Ceci clôt la phase de conformité aux spécifications PDF denses de la version v2.4.0 à v2.86.0. Les travaux restants de la version v2.86+ (encodage SMP via les CMaps de paires substituées, alternatives stylistiques GSUB spécifiques aux polices, typographie plus avancée) sont en dehors de la portée du "Type 0 / Identity-H + AcroForm Unicode" de base et sont reportés indéfiniment en attendant une demande réelle des utilisateurs.

    2026-05-19 Version 2.85.0

    • Ajout de la mise en forme contextuelle optionnelle de la forme de présentation arabe B via la nouvelle propriété `AutoShapeArabic`. Lorsque cette propriété est définie sur True, les trois fonctions utilitaires `BuildUnicode*FieldContent` remplacent les lettres arabes de base (U+0621..U+064A) par leur forme de présentation appropriée (U+FE70..U+FEFF) AVANT l'inversion bidirectionnelle. Les lecteurs PDF ne nécessitent plus un module de mise en forme de texte intégré (HarfBuzz / FreeType / recherche binaire GSUB) pour sélectionner la forme positionnelle correcte au moment du rendu.
    • Algorithme de disposition : analyser le tampon UTF-16 dans l'ordre logique ; pour chaque lettre arabe, rechercher les lettres non transparentes précédentes et suivantes (NSM / harakat U+064B..U+065F + alef khanjareeya U+0670 transparentes). Déterminer la position en fonction du contexte de la classe de liaison : D (liaison double : BEH, TEH, SEEN, LAM, MEEM, NOON, etc.) prend en charge les formes isolées / initiales / médianes / finales en fonction de si les lettres fortes environnantes permettent la liaison de leurs côtés respectifs ; R (liaison droite : ALEF, DAL, ZAL, REH, ZAIN, WAW, etc.) prend en charge uniquement les formes isolées / finales.
    • Impact direct sur l'utilisateur (avec AutoShapeArabic=True) : l'entrée ""بسم"" (BEH + SEEN + MEEM) génère une commande Tj avec les formes de présentation FE91 (BEH initial), FEB4 (SEEN médiale) et FEE2 (MEEM finale). Après l'inversion RTL, l'opérande Tj est FEE2 FEB4 FE91, ce que n'importe quel lecteur PDF affiche comme une écriture arabe connectée, même sans un module de mise en forme intégré.
    • Couverture : 35 lettres arabes de base (variantes de HAMZA, variantes de ALEF, l'alphabet arabe de 28 lettres, YEH MAKSURA). Une recherche statique basée sur la norme Unicode remplace l'analyse binaire spécifique à la police GSUB, de sorte que la mise en forme fonctionne avec n'importe quelle police qui possède des glyphes dans la plage U+FE70..U+FEFF (Arial, Tahoma, Segoe UI Arabic, Noto Sans Arabic, Amiri, etc.).
    • Non pris en charge dans cette version : les lettres d'extension persanes/ourdou (U+0671..U+06D3) ; les glyphes de ligature LAM-ALEF (FEFB / FEFC) ; le mongol/syriaque (modèles de mise en forme différents) ; les alternatives stylistiques GSUB spécifiques à la police, au-delà du modèle de base à 4 positions.
    • Stabilité des octets : Par défaut, AutoShapeArabic est désactivé, de sorte que tous les appelants des versions 2.74 à 2.84 conservent une sortie /AP identique en termes d'octets. Les appelants qui pré-shape déjà en amont (ou utilisent un shapeur côté consommateur) ne sont pas affectés.
    • Placement des pipelines : la formation des séquences dans chaque fonction `Build*UnicodeFieldContent` se fait APRÈS le décodage UTF-8 mais AVANT l'inversion bidirectionnelle, afin que les formes de présentation post-formation soient correctement inversées de droite à gauche lorsque `AutoDetectFormBidi` / `FormUnicodeRTL` est également activé.
    • Travaux restants concernant UAX #9 : le format de la table de correspondance SMP (cmap) version 12 (couverture des points de code U+10000+ dans RegisterUnicodeTTF) doit encore être implémenté.

    2026-05-18 Version 2.84.0

    • Ajout d'un sous-ensemblier TrueType basé sur des fichiers qui s'exécute au moment de la fin du document. Après RegisterUnicodeTTF + AddTextField, le document accumule un ensemble d'utilisation par point de code pendant l'émission de BuildUnicode*FieldContent ; EndDoc traduit les points de code utilisés en ID de glyphe, parcourt la fermeture des glyphes composites et reconstruit le programme de police intégré avec uniquement ces glyphes. L'intégration brute de la version 2.82 est remplacée ; la structure de table restante reste valide car le sous-ensemblier conserve les ID de glyphe inchangés (compactage glyf/loca uniquement).
    • Impact direct sur l'utilisateur : les fichiers PDF contenant des polices Unicode TTF intégrées sont considérablement réduits. Un document "Hello World" avec la police Arial intégrée faisait environ 350 Ko dans la version 2.82 ; dans la version 2.84, il passe à environ 10-15 Ko. Les polices CJK, avec les 1000 à 3000 glyphes typiques, passent d'environ 14 Mo à environ 500 Ko-2 Mo une fois compressées.
    • Algorithme de sous-ensemble : les identifiants des glyphes sont conservés inchangés afin que les tableaux cmap, hmtx, /CIDToGIDMap et /W restent valides. Pour chaque index de glyphe de 0 à numGlyphs-1, la nouvelle table glyf copie les octets originaux (si elle est utilisée) ou génère une entrée vide via loca[i+1] = loca[i] (si elle n'est pas utilisée). Le format de loca (court/long selon head.indexToLocFormat) est conservé. Les sommes de contrôle par table et head.checksumAdjustment sont recalculées pour une validation TTF conforme aux spécifications.
    • Fermeture des glyphes composites : lorsqu'un glyphe utilisé a numContours == -1 (composite), le sous-ensembleur parcourt sa liste de composants (en analysant les indicateurs, l'index du glyphe et les arguments variables/sauts de transformation de chaque composant), marque les composants utilisés et itère jusqu'à ce qu'aucun nouveau glyphe ne soit ajouté. La vérification des limites garantit que les chaînes de composants mal formées ne peuvent pas provoquer de boucle infinie.
    • Conformité aux spécifications : la clé /BaseFont dans le dictionnaire de type 0, la police descendante CIDFontType2 et la clé /FontName dans le descripteur de police reçoivent toutes un préfixe de sous-ensemble de 6 lettres (AAAAAA+) dérivé d'un hachage FNV-1a déterministe de l'ensemble des glyphes utilisés. Conformément à la spécification 9.6.4, le préfixe indique que le programme de police a été sous-ensemble, et sans celui-ci, les lecteurs conformes aux spécifications avertissent des modifications de la police intégrée.
    • Infrastructure de suivi de l'utilisation : un tableau booléen `FUnicodeUsedCps[]` de 65536 entrées est alloué de manière paresseuse lors du premier appel à `RegisterUnicodeTTF`. Chaque une des trois fonctions utilitaires `BuildUnicode*FieldContent` (monoligne, multiligne, combinaison) marque les unités de code lorsqu'elle génère les opérandes hexadécimaux UTF-16BE `Tj`. `SetFormUnicodeFontDict('', nil)` et un réinitialisation future de `BeginDoc` effacent l'état.
    • Sécurité en cas d'échec : toute étape de sous-ensemble qui ne peut pas être terminée (tableaux manquants, données de localisation corrompues, échec de la fermeture composite, échec de la compression) laisse la version brute v2.82 intacte. Le fichier PDF reste valide ; seule la taille du fichier est affectée. Cela préserve la fiabilité de la version v2.82 tout en offrant l'avantage de la réduction de la taille du fichier dans les cas réussis.
    • Ce que cette version ne contient pas : la fonctionnalité de jointure contextuelle OpenType GSUB pour l'arabe/syriaque/devanagari ; le format de carte de couleurs SMP 12 (toujours limité à BMP). Ces fonctionnalités seront disponibles dans la version 2.85 et suivantes.

    2026-05-18 Version 2.83.0

    • Ajout d'une référence à "PDF 1.7 ISO 32000-1 9.10.3 /ToUnicode CMap" dans RegisterUnicodeTTF. Le dictionnaire de police de type 0 contient désormais une référence indirecte à un flux de CMap Adobe-Identity-UCS, ce qui permet aux lecteurs de récupérer du texte Unicode à partir du PDF. Sans la référence "/ToUnicode", la copie-colle à partir d'un fichier PDF de la version 2.74 à 2.82 renvoie des index CID bruts au lieu de points de code Unicode ; les lecteurs d'écran ne peuvent pas lire le contenu à haute voix ; la conformité PDF/A échoue.
    • Structure de la CMap : CMap Adobe-Identity-UCS minimal avec /CIDSystemInfo (Adobe / UCS / 0), /CMapName /Adobe-Identity-UCS, /CMapType 2, une seule plage de codes couvrant <0000>..<FFFF>, et une seule plage de base mappant <0000> <FFFF> à <0000> (identité). Le texte de la CMap PostScript est compressé en environ 150 octets via FlateDecode, de sorte que la surcharge d'intégration est négligeable.
    • Justification du mappage direct : dans notre configuration v2.74-v2.82, nous utilisons Identity-H + Adobe-Identity-0 + CID = point de code Unicode, de sorte que le mappage inverse ToUnicode est réellement un mappage direct pour l'ensemble du BMP. Une seule entrée bfrange suffit pour capturer l'ensemble du mappage ; aucune liste bfchar par point de code n'est nécessaire.
    • Impact visible pour l'utilisateur : la sélection de texte et le copier-coller à partir des lecteurs PDF (Adobe, Foxit, visualiseur PDF de Chrome) produisent désormais les points de code Unicode originaux au lieu de données CID corrompues. Les lecteurs d'écran (NVDA, JAWS, VoiceOver) peuvent lire à voix haute le contenu textuel des formulaires AcroForm pour améliorer l'accessibilité. La conformité aux normes PDF/A-1/2/3 devient possible (PDF/A nécessite la présence de "/ToUnicode" pour toutes les polices de type 0).
    • Placement de la pipeline : l'émission de /ToUnicode se trouve DANS le bloc try/except de WArrayValid, car le mappage d'identité ne dépend pas du succès de l'analyse de la cmap. Même si /W, /CIDToGIDMap et /FontFile2 étaient ignorés en raison de tables de polices corrompues, la CMap ToUnicode est toujours générée et est sémantiquement correcte.
    • Objet de flux : THPDFStreamObject indirect + /Filter /FlateDecode (pas de /Length1 car ToUnicode est un flux de texte, et non un programme de police). Attaché au dictionnaire d'enveloppe de type 0 via Result.AddValue('ToUnicode', ...). Partage le motif de compression zlib avec v2.77 /CIDToGIDMap et v2.82 /FontFile2.
    • Ce qui n'est pas inclus dans cette version : les entrées bfchar par point de code (qui permettraient de mapper les CID non-identité à des séquences Unicode multi-caractères, comme fi -> f+i, mais notre configuration Identity n'a jamais besoin de cela) ; la couverture SMP au-delà de la plage BMP (toujours la plage 0x0000..0xFFFF). Les deux seront implémentés dans la version v2.84+.

    2026-05-18 Version 2.82.0

    • Ajout de la prise en charge de l'intégration de polices brutes PDF 1.7 ISO 32000-1 9.6.4 + 9.9 via `/FontFile2` à `RegisterUnicodeTTF`. Le programme de police réel (les octets binaires TTF/OTF) est désormais inclus dans le PDF sous forme d'un flux `/FontFile2` attaché au descripteur de police, de sorte que les lecteurs ne doivent plus résoudre le nom `/BaseFont` via le cache de polices du système d'exploitation/de l'application. Résultat : un PDF autonome qui s'affiche correctement sur les systèmes ne disposant pas de la police nommée.
    • Structure du flux : objet THPDFStreamObject indirect avec les attributs /Filter /FlateDecode et /Length1 correspondant à la taille du fichier de police non compressé (selon le tableau 124 des spécifications). La compression utilise TZCompressionStream (zcDefault, windowBits 15), suivant le modèle /CIDToGIDMap de la version 2.77. Les fichiers TTF latins typiques sont compressés de 30 à 50 % (par exemple, Arial de 700 Ko devient 350 Ko après compression).
    • Intégration dans le pipeline : l'émission se produit dans la même branche `WArrayValid` que les tableaux `/W` de la version 2.75 et `/CIDToGIDMap` de la version 2.77. Ainsi, lorsque l'analyse de la table cmap échoue (sous-table corrompue/format non pris en charge), les trois flux de fonctionnalités sont ignorés ensemble, ce qui permet une dégradation contrôlée vers le résultat basé uniquement sur les métriques de la version 2.74.
    • Impact visible : les fichiers PDF de la version v2.74 à v2.81 étaient techniquement des polices composites de type 0 / CIDFontType2, mais le programme de police était MANQUANT. Les lecteurs grand public devaient faire correspondre la police de base (nom PostScript) avec leur propre cache de polices. Sur les systèmes où la police nommée exacte était installée, l'affichage fonctionnait ; sur les systèmes où elle ne l'était pas, le lecteur remplaçait la police par une autre (ce qui affichait des glyphes/métriques incorrects) ou affichait des blocs de remplissage. La version v2.82 inclut le programme de police directement dans le fichier PDF, le même programme de police que le créateur a analysé lors de l'enregistrement de la police TTF, de sorte que l'affichage par les lecteurs est déterministe, quel que soit la disponibilité des polices du système d'exploitation.
    • Compromis : les fichiers PDF gagnent environ 150 à 500 Ko par police intégrée pour les polices Latin typiques (taille compressée) ; les polices CJK ajoutent de 2 à 20 Mo compressés. Cela évite le même problème de gonflement dû à la substitution de polices côté client, mais au prix d'un rendu non déterministe. La fonctionnalité de sous-ensemble (disponible depuis la version 2.83) réduira ce gonflement en supprimant les glyphes inutilisés du programme intégré.
    • Notes concernant les spécifications : dans notre version 2.82, la propriété /BaseFont conserve le nom PostScript original (sans le préfixe de sous-ensemble "AAAAAA+"), car nous intégrons la police complète. Le préfixe de 6 lettres, tel que spécifié dans la section 9.6.4, s'applique uniquement lorsque le programme de la police a été sous-ensemblé ; à partir de la version 2.83, le préfixe sera ajouté dans le cadre de l'intégration du sous-ensemblage.
    • Ce qui ne figure pas dans cette version : la création de sous-ensembles de polices (par conséquent, une seule police intégrée ajoute la taille complète du fichier au PDF). La table CMap "ToUnicode" (pour la copie-coller dans les documents PDF/A). Le format de la table cmap SMP 12 (les points de code U+10000+ ne sont toujours pas mappés). Tout cela sera pris en charge dans la version v2.83 et suivantes.

    2026-05-18 Version 2.81.0

    • UAX #9 W4 (séparateur entre chiffres) et W5 (terminateur adjacent au chiffre) ont été intégrés au chemin de réorganisation des paragraphes LTR. Auparavant, cela ne fonctionnait qu'avec les langues RTL (depuis les versions v2.72.0 / v2.73.0) ; dans la version v2.81, les deux passes sont extraites dans les fonctions auxiliaires `_ApplyUAX9W4Rules` et `_ApplyUAX9W5Rules`, afin que les deux directions de paragraphe appliquent les mêmes transformations de règles faibles.
    • Refactorisation : Les étapes 1b (W4) et 1c (W5) du chemin RTL, où le code intégré a été remplacé par des appels de fonctions auxiliaires sur une seule ligne. Ces fonctions prennent la chaîne étendue et le tableau Classes[] en entrée, et modifient le tableau Classes[] directement ; la logique est identique aux implémentations intégrées des versions v2.72/v2.73, de sorte que la sortie RTL est stable en termes de bytes lors de cette refactorisation.
    • Le chemin LTR ajoute l'étape 1c (W4) et l'étape 1c.2 (W5) entre l'héritage NSM de W1 (étape 1b) et W7 précédé par EN (étape 1d). Les règles N suivantes (étape 1e) et la règle I (étape 1f) ont été renommérées pour maintenir l'ordre explicite du pipeline.
    • Impact visible pour la direction de texte de gauche à droite (LTR) : dans les contextes mixtes LTR où une séquence forte RTL précède un chiffre ou une expression, W5 promeut désormais l'expression à gauche à droite (EN) avant que N1 n'ait la possibilité de la regrouper dans une séquence de droite à gauche (R). Exemple : "Hi shin $1" (paragraphe LTR avec une lettre hébraïque "shin" interne suivie de "$1") produisait auparavant "Hi $ shin 1", où le symbole "$" était inclus dans la séquence R et échangé avec "shin". La version 2.81 produit "Hi shin $1", où le symbole "$" reste adjacent à son chiffre. La même chose s'applique à W4 : "Hi shin $1,2 widgets" conserve "$1,2" comme un bloc logique au lieu de le diviser autour de la virgule.
    • Dans les scénarios où la stabilité des octets est importante pour le chemin LTR, les entrées LTR pures sans caractères R précédents (par exemple, "12 345 widgets") ne présentent aucun changement visible, car W7 sor=L absorbe déjà tous les caractères EN vers L. Les entrées LTR contenant uniquement des caractères L et RTL, sans chiffres ni caractères spéciaux, ne sont pas non plus affectées. Les tests LTR existants de la version 2.79 (smoke_bidi_n_rules_ltr, smoke_bidi_ltr_reorder) continuent de passer sans modification des octets.
    • Ordre du pipeline (le chemin RTL n'a pas changé) : W1 -> W4 -> W5 -> W7 -> N0 -> N1 -> N2 -> I2 -> L2. Le chemin LTR est maintenant : W1 -> W4 -> W5 -> W7 -> N0 -> N1 -> N2 -> règle I -> L2. Les deux chemins partagent les modules auxiliaires W4/W5/W7/N ; seule la classification (étape 1a) et la dernière étape L2 diffèrent entre RTL et LTR.
    • Travaux restants concernant UAX #9 : l'intégration OpenType GSUB pour les contextes arabes/syriaques/devanagari, ainsi que les améliorations suivantes de RegisterUnicodeTTF (ToUnicode CMap, format de cmap SMP 12, /FontFile2 et sous-ensemble) sont toujours en cours.

    2026-05-18 Version 2.80.0

    • Ajout de la fonctionnalité Unicode UAX #9 pour les nombres européens : lorsqu'une recherche inversée trouve un "L" fort (ou sor=L lorsque la recherche atteint le début du tampon de paragraphe), ce "L" est transformé en "L". Cette transformation s'effectue après les séquences W4 (séparateur entre les chiffres) et W5 (terminateur adjacent au chiffre) sur les chemins de paragraphe RTL et LTR, de sorte que tout séparateur promu à EN par W4 est également soumis à la conversion en "L".
    • Impact visible pour les langues RTL : une entrée comme ""Hello 123 Arabic"" dans un paragraphe RTL affichait auparavant la disposition visuelle ""Arabic SP 123 SP Hello"" car la séquence de caractères EN se trouvait entre L (Hello) et AL (Arabic), et les règles N divisaient la phrase LTR en deux séquences indépendantes (avec un espace inséré entre elles). Dans la version 2.80 pour W7, la séquence EN est convertie en L (puisque L précède), et N1 absorbe l'espace initial entre Hello et 123 dans la séquence L ; l'ensemble de ""Hello 123"" devient une sous-chaîne de niveau 2 qui s'inverse comme une unité. La disposition visuelle finale devient ""Arabic SP Hello SP 123"", ce qui correspond au comportement strict de UAX #9.
    • W7 ne s'active pas lorsque : la lettre arabe la plus proche de la lettre EN est R ou AL (les lettres arabes précèdent les chiffres) ; la lettre EN se trouve au début du tampon dans un paragraphe RTL (sor=R) ; ou il n'y a pas de lettre L avant la lettre EN. Le comportement antérieur à la version 2.80 est conservé dans ces cas : les références de base W4/W5 des versions 2.72/2.73 restent stables au niveau des octets.
    • Effet de paragraphe LTR : W7 fonctionne également sur le chemin LTR (pour la cohérence avec la spécification), avec sor=L lorsque la numérisation atteint le début du tampon. Dans la règle LTR simple à un seul encodage de HotPDF, L et EN se trouvent tous deux au niveau 0, de sorte que la transformation EN -> L ne modifie pas directement les niveaux, mais elle modifie le motif d'absorption de N1 : un espace entre L et un EN relié à L satisfait désormais la condition de même direction de N1 et rejoint la séquence. Pour les entrées LTR pures sans RTL interne, la modification est une opération sans effet stable au niveau des octets ; pour les entrées LTR contenant du RTL à la fin (par exemple, "Hello 123 shalom"), le positionnement de l'espace par rapport au bloc RTL est décalé d'une position.
    • W6 (promotion implicite des scripts ES/CS/ET vers ON selon la règle stricte UAX #9) est intégré dans le tableau simplifié Classes[] de HotPDF : ES, CS, ET, WS et ON partagent tous la classe 0 (bcOther), et les règles N traitent la classe 0 de manière uniforme. La promotion de W6 vers ON est une opération sans effet dans notre modèle, car N1/N2 ne font pas de distinction entre ON et WS. Ceci est documenté dans le commentaire du code à côté de l'aide W7.
    • Ordre du pipeline (chemin RTL) : héritage NSM W1 -> ES/CS entre les chiffres W4 -> ET adjacent aux chiffres W5 -> EN précédé de L W7 -> parenthèses appairées N0 -> absorption NI dans la même direction N1 -> passage par défaut à l'intégration N2 -> affectation de niveau I2 -> inversion de l'inversion L2. Même ordre sur le chemin LTR, à l'exception de W4/W5 (qui restent uniquement pour RTL dans cette section ; le port LTR de W4/W5 est le prochain candidat).
    • Nouvelle procédure utilitaire partagée `_ApplyUAX9W7Rules(Classes, ParaIsRTL)` qui opère directement sur le tableau Classes[]. La fonction de "scan-back" ignore les positions faibles, les positions NSM, EN et AN ; seules les positions L, R et AL sont considérées comme des types forts. Lorsque la recherche s'épuise sans trouver un type fort, la direction du paragraphe (sor) est utilisée comme type fort implicite. Le chemin RTL transmet ParaIsRTL=True, tandis que le chemin LTR transmet False.
    • Travaux restants concernant UAX #9 : portage des chemins LTR pour W4/W5 (actuellement uniquement RTL), OpenType GSUB pour l'arabe, le syriaque et le dévanagari, ainsi que les améliorations suivantes de RegisterUnicodeTTF (ToUnicode CMap, format de cmap SMP 12, /FontFile2 et sous-ensemble).

    2026-05-18 Version 2.79.0

    • Les règles v2.78.0 pour N0/N1/N2 ont été appliquées au chemin de réorganisation des paragraphes LTR. Cela corrige un bug qui causait l'inversion visuelle des mots dans une phrase RTL contenant plusieurs mots (par exemple, une phrase anglaise contenant plusieurs mots hébreux ou arabes séparés par des espaces), car l'espace entre les mots restait au niveau 0, ce qui divisait la phrase RTL en plusieurs blocs indépendants. Avec la version v2.79 N1, l'espace est intégré au bloc RTL environnant ; la phrase entière devient une seule sous-chaîne de niveau 1, et la fonction de retournement de niveau 2 maintient les mots dans l'ordre logique.
    • Refactorisation du chemin de paragraphe LTR (`_ApplyUAX9L2ReversalLTRPara`) pour qu'il reflète la structure du chemin RTL : chaque unité de code UTF-16 est classée dans un tableau d'octets `Classes[]`, l'héritage W1 NSM est appliqué à `Classes[]` (auparavant, c'était `Levels[]` avant la version 2.79), puis une fonction auxiliaire partagée `_ApplyUAX9NRules` est appelée, qui opère sur `Classes[]` en fonction d'un paramètre de direction d'intégration (1 = L pour LTR, 2 = R pour RTL). La règle I dérive ensuite `Levels[]` à partir de `Classes[]`. Les chemins RTL et LTR partagent désormais une seule implémentation des règles N.
    • La fonction `_ApplyUAX9NRules(Wide, Classes, EmbedDirCls)` accepte la direction d'intégration sous forme de valeur de classe (1 ou 2) et applique la résolution des parenthèses appariées N0, l'absorption NI dans la même direction N1 et l'uniformisation par défaut vers l'intégration N2. Le chemin RTL utilise la valeur 2 (R) ; le chemin LTR utilise la valeur 1 (L). Tout le comportement du côté RTL de la version 2.78 est conservé byte par byte.
    • Impact visible du côté LTR : "Hi shalom olam World" avec l'entrée logique H i SP shin lamed vav final-mem SP ayin vav lamed final-mem SP W o r l d, qui était auparavant affichée avec les deux mots hébreux inversés l'un par rapport à l'autre (chaque mot correct individuellement, mais leurs positions RELATIVES échangées). La version 2.79 conserve l'ordre logique des mots, de sorte qu'un lecteur RTL voit "Hi shalom olam World" avec le bloc hébreu dans l'ordre attendu. La même correction s'applique aux phrases RTL multi-mots encadrées par des crochets, grâce à la coopération entre N0 et N1.
    • Dans le chemin LTR (miroir du chemin RTL), l'ordre des étapes est le suivant : classification dans les Classes[] -> héritage W1 NSM -> accolades appariées N0 -> absorption NI dans la même direction N1 -> passage par défaut à l'intégration N2 -> règle I (dérivation des Levels[]) -> inversion des séquences de niveau 1 L2. Les étapes W4/W5 de gestion des chiffres ne sont pas encore portées vers le chemin LTR ; les paragraphes LTR contenant des chiffres et des séparateurs suivent les règles N sans modification.
    • Les tests LTR existants sont maintenant stables au niveau des octets : le texte LTR ASCII pur, les mots RTL uniques dans les paragraphes LTR, et le mélange RTL + LTR sans espaces inter-mots RTL produisent tous des tableaux Levels[] identiques après la refactorisation (l'étape d'héritage NSM W1 est observable équivalente, qu'elle opère sur Levels[] ou Classes[]). Les tests LTR v2.67, v2.69 et v2.71 continuent de passer avec une identité de octets.
    • Travaux restants concernant UAX #9 : nettoyage mineur des éléments restants de W6/W7, gestion des chiffres pour les chemins LTR (actuellement uniquement RTL), jointure contextuelle OpenType GSUB pour l'arabe, le syriaque et le dévanagari, et finalisation de RegisterUnicodeTTF (ToUnicode CMap, format de la carte cmap SMP 12, /FontFile2 + sous-ensemble).

    2026-05-18 Version 2.78.0

    • Ajout de la résolution simplifiée des parenthèses appariées Unicode UAX #9, ainsi que des règles d'absorption neutre entre les mêmes éléments forts (N1) et des règles neutres par défaut vers l'intégration (N2) dans le pipeline de réorganisation des paragraphes RTL. Cela corrige un bug visible où une phrase LTR multi-mots intégrée dans un paragraphe RTL (par exemple, du texte hébreu ou arabe entourant du texte anglais avec des espaces internes) était émise avec les MOTS inversés, car l'espace entre les blocs de texte (L runs) restait au niveau d'intégration et divisait la phrase LTR en sous-blocs indépendants. Avec N1, l'espace est absorbé dans le bloc de texte (L run) environnant, de sorte que toute la phrase devient une sous-chaîne de niveau 2, et l'inversion de l'inversion (L2 reverse-of-reverse) la maintient dans l'ordre logique.
    • N0 : 22 paires de crochets BMP couverts, allant des parenthèses/crochets/accolades ASCII aux symboles mathématiques/typographiques (plafond, plancher, angle mathématique, carré blanc mathématique, accolade blanche) aux symboles de ponctuation CJK (angle, double angle, coin, coin blanc, lenticulaire noir, carapace, carapace blanche, carré blanc) aux formes à largeur complète. BD16 : détection de paires de crochets basée sur une pile (capacité de 63 entrées par spécification) ; la résolution de la paire analyse l'intérieur pour déterminer la première direction forte (G, D, GL, GD, GA, où GD/GA comptent comme D selon la spécification), avec une option de repli pour vérifier la direction avant d'ouvrir le crochet si l'intérieur diffère de la direction d'intégration.
    • Absorption N1 : parcourt les tableaux `Classes[]` pour identifier les séquences maximales de `bcOther` (neutre), trouve les types forts "left" et "right" qui ne sont pas des types NSM, et lorsque les deux côtés ont la même direction (les deux "L" ou les deux équivalents "R", en comptant EN/AN comme "R"), toute la séquence prend cette direction. Impact réel : les espaces, les virgules, les points et les deux-points situés à l'intérieur des phrases anglaises intégrées dans des paragraphes arabes ou hébreux sont maintenant regroupés avec la phrase plutôt que de la diviser.
    • Par défaut, les positions restantes de `bcOther` (sans balises `` environnantes ou avec des balises gauche/droite non correspondantes) adoptent la direction de l'intégration. Pour les paragraphes RTL, cette direction est R ; classe 2. Après N2, chaque entrée dans `Classes[]` se trouve dans l'ensemble résolu {1..6}, de sorte que l'attribution du niveau I2 ne dépend plus du fait que `bcOther` par défaut est au niveau 1.
    • Impact visible : précédemment, HotPDF produisait "aleph aleph SP a b c SP d e f SP aleph aleph" (entrée logique avec la phrase anglaise "abc def" dans un paragraphe RTL) et l'affichait comme "aleph aleph SP d e f SP a b c SP aleph aleph", avec les mots inversés car l'espace inter-mot était au niveau 1 (incorporation RTL). La version 2.78 produit "aleph aleph SP a b c SP d e f SP aleph aleph" avec la phrase intacte. Les parenthèses autour de la phrase intégrée sont maintenant résolues correctement grâce au miroir N0 + L4 côté consommateur.
    • Ordre du pipeline : héritage NSM W1 -> W2/I2 (affectation de classe EN/AN dans la table BIDI, pas dans cette étape) -> W4 espaces/sauts entre chiffres -> W5 espaces adjacents à des chiffres -> N0 parenthèses appairées -> N1 absorption dans la même direction -> N2 valeur par défaut d'intégration -> affectation de niveau I2 -> L2 inversion de l'inversion. Les règles N sont placées entre les règles W et I ; les sorties des règles W existantes sont utilisées comme entrées pour les règles N.
    • Stable pour les polices existantes qui ne contiennent pas de phrase LTR multi-mots à l'intérieur d'un bloc RTL : RTL pur, LTR pur (la fonction renvoie l'entrée), un seul mot LTR dans un bloc RTL (pas de caractères neutres internes à absorber), arabe + chiffres formatés avec espace + virgule (les espaces passent de bcOther à l'équivalent R, mais restent au même niveau, ce qui ne modifie pas la sortie inversée L2). Les polices de référence v2.66, v2.67, v2.68, v2.71, v2.72 et v2.73 continuent de passer les tests de stabilité des octets.
    • Les travaux restants concernant UAX #9 comprennent : nettoyage mineur des éléments restants de W6/W7, miroir LTR-paragraphe des règles N (phrase RTL multi-mots intégrée dans un paragraphe LTR), jointure contextuelle OpenType GSUB pour l'arabe, le syriaque et le dévanagari, et les actions suivantes concernant RegisterUnicodeTTF (ToUnicode CMap, format de cmap SMP 12, /FontFile2 + sous-ensemble).

    2026-05-18 Version 2.77.0

    • Ajout du flux /CIDToGIDMap conformément à la norme PDF 1.7 ISO 32000-1 9.7.4.2 à la fonction RegisterUnicodeTTF. Chaque point de code Unicode (CID) dans le BMP est maintenant mappé à l'index de glyphe réel à l'intérieur du programme de police intégré. Avant la version v2.77, la configuration de type 0 / CIDFontType2 + Identity-H de HotPDF laissait l'entrée /CIDToGIDMap non spécifiée, ce qui par défaut correspond à /Identity selon la spécification. Le lecteur consommant indexait alors directement la table de glyphes de la police par CID, ce qui affichait le glyphe incorrect pour presque tous les caractères, car les tables de glyphes réelles alignent rarement l'index de glyphe N avec le point de code Unicode N.
    • L'implémentation réutilise l'analyse de la table cmap déjà effectuée pour le tableau /W de la version 2.75. La table CpToGid[0..$FFFF] en mémoire est sérialisée sous forme d'un flux de 131072 octets (2 octets en ordre de poids fort vers faible par CID) et compressée avec FlateDecode ; la réduction de taille typique pour les polices réelles est de 80 à 95 %, car la grande majorité des points de code BMP n'ont pas de glyphe et sont sérialisés sous la forme 0x0000. Le flux compressé est ajouté en tant qu'entrée indirecte /CIDToGIDMap dans le dictionnaire descendant de type CIDFontType2.
    • Impact visible : un fichier PDF généré via RegisterUnicodeTTF + SetFormUnicodeFontDict + les widgets AcroForm Tx affiche désormais les mêmes glyphes dans le lecteur du destinataire que ceux que la police source afficherait nativement. Les fichiers PDF antérieurs à la version 2.77 qui reposaient sur le paramètre /Identity par défaut affichaient des erreurs de rendu visibles (glyphes aléatoires à la place des caractères latins, des chiffres ou de la ponctuation) sur les lecteurs conformes aux spécifications ; les lecteurs qui se rabattaient sur l'interprétation de la cmap via Unicode affichaient correctement, mais le faisaient via un comportement non standard.
    • Placement du pipeline : la construction de /CIDToGIDMap se déroule dans la même branche WArrayValid qui construit /W, de sorte que les deux éléments partagent le parcours de la cmap et seule la deuxième passe de compression est nouvelle. Si l'analyse de la cmap, de /hmtx ou de /maxp échoue, le mécanisme de repli silencieux ignore à la fois /W et /CIDToGIDMap ; le lecteur consommant les données voit alors l'ancienne version du dictionnaire (antérieure à la v2.77) et revient à son interprétation par défaut de la cmap.
    • Ce qui N'EST PAS inclus dans cette version (reporté à la version v2.78 et suivantes) : le format de la table cmap SMP 12 (les points de code U+10000+ sont toujours mappés à GID 0 dans la table), l'intégration du flux /FontFile2 (le lecteur doit toujours résoudre le nom /BaseFont via sa propre correspondance de polices), le découpage de polices (la carte brute de 128 Ko est à plage complète) et la table CMap ToUnicode pour les opérations de copie-coller et d'accessibilité.

    2026-05-18 Version 2.76.0

    • Nous avons intégré le tableau de largeur d'avance TTF de la version v2.75.0 dans l'algorithme de retour à la ligne multiline propre à HotPDF. L'utilitaire BuildUnicodeMultilineFieldContent.CodeUnitAdvance de la version v2.65.0 consulte désormais un cache de largeur d'avance par point de code, alimenté par RegisterUnicodeTTF, remplaçant l'heuristique étroite/large de 0,5/1,0 par les métriques réelles des glyphes. Les sauts de ligne côté producteur s'alignent désormais sur le rendu côté consommateur : le point de retour à la ligne que HotPDF sélectionne correspond à l'endroit où le lecteur consommateur effectuera réellement le retour à la ligne lors du rendu de l'opérateur /Tj.
    • Nouveaux champs privés : FAcroFormUnicodeAdvances (tableau dynamique de Word, de taille 65536 ou vide) qui met en cache les largeurs d'avance par point de code dans les unités de conception PDF (1000 par em). Le drapeau FAcroFormUnicodeAdvancesActive permet de distinguer les cas où "le cache est rempli par RegisterUnicodeTTF" de ceux où "aucune police n'est chargée (l'heuristique revient à une solution de repli)". RegisterUnicodeTTF remplit ces champs pendant la même analyse de hmtx + cmap qui construit le tableau /W, de sorte qu'une passe d'analyse supplémentaire n'est pas nécessaire.
    • Ordre de recherche de CodeUnitAdvance : si FAcroFormUnicodeAdvancesActive est activé ET le cache contient une valeur non nulle pour l'unité de code, divisez la largeur mise à l'échelle par 1000,0 et renvoyez le résultat sous forme de fraction de em ; sinon, utilisez l'heuristique de la version 2.65 (étroit pour ASCII / Latin-1, large pour CJK / Hangul / Hiragana / Katakana / pleine largeur). Les moitiés de paires surrogées continuent d'utiliser l'heuristique, car le cache est limité au BMP.
    • Cycle de vie du cache : effacé lors de THotPDF.Create (par défaut, vide/inactif), effacé lors de SetFormUnicodeFontDict('','') lorsque l'appelant réinitialise explicitement l'enregistrement de la police Unicode, et repopulé à chaque appel ultérieur de RegisterUnicodeTTF. Il conserve 128 Ko (64 000 points de code * 2 octets) uniquement lorsqu'au moins une police TTF a été chargée ; les instances qui n'utilisent jamais de polices Unicode n'entraînent aucun coût mémoire.
    • RegisterUnicodeFontDict (v2.70.0) et RegisterUnicodeTTF (v2.74.0) sans un tableau /W (par exemple, tables maxp / cmap / hmtx manquantes) laissent le cache vide/inactif, de sorte que le retour à la ligne automatique passe à l'heuristique v2.65 - la sortie est identique à v2.65 pour ces chemins.
    • Impact visible : un widget AcroForm multiligne avec une police latine standard (Arial, Segoe UI, Times) s'enroule désormais aux limites des caractères, ce qui correspond à la mise en page réelle du lecteur. Sans la version 2.76, l'heuristique de la version 2.65 traitait chaque caractère ASCII comme ayant une largeur de 0,5 em ; pour une police réelle où "M" fait environ 0,8 em et "i" fait environ 0,3 em, cette heuristique surestime ou sous-estime de 30 à 60 %, ce qui fait que le lecteur effectue un retour à la ligne différent de ce que HotPDF avait prévu, entraînant un débordement de texte ou des lignes trop courtes.
    • Les fonctions `BuildUnicodeTextFieldContent` et `BuildUnicodeCombFieldContent` ne font pas appel à `CodeUnitAdvance` et ne sont pas affectées (la fonction à une seule ligne n'a pas de retour à la ligne ; la fonction "comb" utilise des cellules de largeur égale).
    • Ce qui N'EST PAS inclus dans cette version : le format de la table de correspondance SMP 12 (les points de code U+10000 et supérieurs continuent d'être traités via une méthode heuristique pour chaque moitié surrogate), la table CMap /ToUnicode, l'intégration du flux /FontFile2, la création de sous-ensembles de polices. Ces fonctionnalités sont disponibles dans les versions v2.77 et ultérieures.

    2026-05-18 Version 2.75.0

    • Nouvelle version v2.74.0 de THotPDF. La fonction `RegisterUnicodeTTF` a été améliorée pour analyser les tables hmtx, maxp et cmap, de sorte que la police CIDFontType2 résultante contienne un tableau réel de largeurs d'avance par point de code (/W). Les lecteurs utilisent désormais de véritables métriques de police pour le rendu de la largeur du texte, au lieu de revenir à une valeur de /DW = 1000 pour chaque glyphe. Le texte à l'intérieur d'un flux d'apparence AcroForm (/AP) occupe désormais la même largeur que celle que la police source rendrait.
    • De nouveaux outils de bas niveau permettent d'analyser les trois tables SFNT supplémentaires : `_TTFParseMaxpNumGlyphs` (lit `numGlyphs` à partir de `maxp`), `_TTFParseHmtxAdvances` (lit le tableau des largeurs d'avance par glyphe à partir de `hmtx`, dont la taille est déterminée par `numberOfHMetrics` dans `hhea`), `_TTFFindAndParseCmap` + `_TTFParseCmapFormat4` (recherche et analyse la table de mappage BMP de format 4 pour la conversion des points de code Unicode en ID de glyphe). `_TTFBuildWArray` crée le tableau épars /W de type 1, conformément à la section 9.7.4.3 de la spécification PDF 1.7, en regroupant les points de code de largeur non par défaut consécutifs dans des séquences [startCID [w1 w2 w3 ...]] et en omettant les points de code dont la largeur est égale à /DW = 1000 afin de réduire la taille du tableau.
    • La sélection des sous-tableaux de la carte de caractères préfère Microsoft Unicode BMP (plateforme 3, encodage 1, format 4) – la disposition universelle de la carte de caractères des polices Windows. En cas d'impossibilité, elle utilise la plateforme Unicode (0, encodage 3 ou 4) pour les polices OpenType multiplateformes, puis la plateforme 3, encodage 10 (uniquement pour les cartes de caractères Unicode complètes, format 4), et enfin, tout autre format 4. Les sous-tableaux qui ne sont pas au format 4 (formats 0, 2, 6, 8, 12, 13, 14) sont ignorés dans cette version ; la couverture SMP via le format 12 est disponible à partir de la version 2.76.
    • Le tableau /W est attaché au dictionnaire descendant CIDFontType2 par une recherche directe : Type0 -> /DescendantFonts -> [0] -> AddValue('W', WArray). La signature de RegisterUnicodeFontDict reste inchangée dans la version v2.70 ; le dictionnaire descendant est modifié directement après l'assemblage.
    • Les largeurs des caractères FUnit, provenant de hmtx, sont mises à l'échelle en unités de conception PDF (1000 par em) en utilisant la valeur unitsPerEm de la table d'en-tête. Les points de code sans mappage de glyphe (cmap renvoie 0 / .notdef) sont traités comme DW = 1000 et sont omis de /W. Pour une police latine typique (Arial, Segoe UI, Times), le tableau /W résultant contient 500 à 1500 entrées de points de code ; pour les polices CJK, le tableau peut atteindre 10 000 entrées ou plus.
    • Ce qui N'EST PAS inclus dans cette version (reporté à la v2.76+) : les données de largeur /W ne sont PAS encore utilisées par l'algorithme de retour à la ligne multiline propre à HotPDF ; la fonction v2.65 BuildUnicodeMultilineFieldContent utilise toujours l'heuristique étroite/large 0,5/1,0 pour le calcul des sauts de ligne ; le tableau /W sert uniquement à améliorer la précision du rendu côté consommateur. L'implémentation parfaite du retour à la ligne côté producteur (utilisant /W pour calculer le retour à la ligne) sera disponible dans la v2.76+. De plus, les fonctionnalités suivantes sont reportées : la table CMap ToUnicode à partir de la correspondance inverse cmap, l'intégration du flux /FontFile2, le découpage de polices et le format 12 des tables cmap SMP.
    • La gestion de `/W` inclut une solution de repli avec `try/except` : si `maxp`, `cmap` ou `hmtx` sont manquants, ou si une sous-table est mal formée, `RegisterUnicodeTTF` continue silencieusement avec le résultat métrique de la version 2.74 ; le lecteur utilise `/DW = 1000` pour chaque caractère. Aucune corruption silencieuse : les tables sont vérifiées pour les dépassements de capacité lors de chaque lecture multi-octets.

    2026-05-18 Version 2.74.0

    • Ajout de THotPDF.RegisterUnicodeTTF, un wrapper basé sur un fichier autour de v2.70.0 RegisterUnicodeFontDict qui charge une police TTF/OTF, analyse les tables "head", "hhea", "OS/2", "post" et "name", convertit les métriques FUnit en unités de conception PDF (1000 par em) et transmet les valeurs à RegisterUnicodeFontDict pour créer le dictionnaire de police composite Type 0 / CIDFontType2 + Identity-H. Le dictionnaire renvoyé est prêt pour SetFormUnicodeFontDict ; les appelants n'ont plus besoin de connaître les valeurs métriques exactes de la police ni le format binaire SFNT.
    • API : RegisterUnicodeTTF(FontPath, LogicalName=""). FontPath est un chemin absolu ou relatif vers un fichier .ttf ou .otf. LogicalName est réservé pour les versions v2.75 et ultérieures (où il peut servir à distinguer les polices qui partagent le même nom PostScript).
    • Analyse des tableaux : head (unitsPerEm, dimensions de la boîte de caractères xMin/yMin/xMax/yMax en unités de police), hhea (hauteur de l'ascendante, profondeur de la descendante en unités de police), OS/2 (usWeightClass pour l'estimation de /StemV, sCapHeight, fsSelection pour le bit italique), post (italicAngle en FIXED 16.16 -> degrés, isFixedPitch -> bit 1 de /Flags), name (nom PostScript à nameID 6 provenant de la plateforme Windows ou Mac, en cas de problème, utilise le nom complet à nameID 4). Vérification des limites pour chaque décalage/longueur de tableau et pour chaque lecture multi-octets, afin qu'une police mal formée provoque une exception claire plutôt qu'une erreur de mémoire.
    • Métriques dérivées automatiquement : /FontBBox L/B/R/T mis à l'échelle en unités de conception PDF, /Ascent + /Descent mis à l'échelle, /CapHeight extrait de OS/2 sCapHeight (par défaut, utilise l'ascendant pour les tables OS/2 antérieures à la version 2), /ItalicAngle extrait de post.italicAngle, /StemV estimé comme 50 + (usWeightClass - 400) / 5, limité à [50, 250], /Flags = Symbolic + FixedPitch (si post l'indique) + Italic (si le bit 0 de fsSelection est défini ou italicAngle != 0). /BaseFont utilise le nom PostScript analysé ; par défaut, utilise ""UnnamedTTF"" si la table des noms ne renvoie rien d'utilisable.
    • Des exceptions descriptives sont levées en cas d'erreurs : fichier manquant, taille impossible (< 12 octets ou > 64 Mo), sfntVersion non reconnu (doit être 0x00010000 / 'OTTO' / 'true' / 'typ1'), tables obligatoires manquantes (head / hhea / OS/2 / post / name), taille de la table trop petite pour les champs requis.
    • Cette version ne comprend pas (reporté à la version 2.75 et suivantes) : le tableau de largeur d'avance /W provenant de hmtx (nécessite maxp pour le nombre de glyphes + cmap pour la correspondance Unicode -> glyphe ; actuellement, le retour à la ligne multiple de la version 2.65 conserve son heuristique 0.5/1.0), une carte CMap ToUnicode provenant de cmap (actuellement, la correspondance Identity-H de la version 2.56 suppose que CID == point de code Unicode), l'intégration des octets de police bruts sous forme de flux /FontFile2 et le sous-ensemble de polices. Avec la version 2.74.0, le lecteur doit toujours résoudre le nom /BaseFont via son propre mécanisme de correspondance de polices.
    • Smoke smoke_unicode_ttf.dpr charge une police de caractères du système Windows (elle recherche %SystemRoot%\Fonts pour arial.ttf / segoeui.ttf / times.ttf / verdana.ttf dans cet ordre) et vérifie que RegisterUnicodeTTF renvoie un dictionnaire de type 0 contenant les métriques extraites du fichier. Le vérificateur s'assure que la police de base résultante (/BaseFont) n'est pas un espace réservé, et que les valeurs de FontBBox, Ascent, Descent et ItalicAngle se situent dans des plages plausibles pour une police réelle.

    2026-05-18 Version 2.73.0

    • Added Unicode UAX #9 simplified W5 (European Terminator adjacent to European Number) for RTL paragraphs. Fixes the visible bug where Arabic text with currency / percent symbols — "$12.50", "50%", "€100", "شار 12.50$ ريال" — left the currency or percent glyph stranded at the boundary between the digit substring and the surrounding RTL text. With v2.73 W5, ETs adjacent to digits join the digit run and reverse with the digits, preserving the currency-and-number unit as one LTR substring inside the RTL paragraph.
    • W5 ETs reconnus (ensemble de points de code) : U+0023 # (signe dièse), U+0024 $ (dollar), U+0025 % (pourcentage), U+00A2..U+00A5 (¢ £ ¤ ¥), U+00B0 ° (degré), U+00B1 ± (plus-moins), U+066A ٪ (pourcentage arabe), U+2030..U+2031 (‰ ‱ par mille / par dix mille), U+20A0..U+20CF (bloc des symboles monétaires, y compris € ₹ ₽ ₩, etc.). Une séquence maximale d'ETs adjacents à un EN de chaque côté (en sautant uniquement les NSMs) est transformée en EN.
    • Extension de la spécification : La version simplifiée W5 de HotPDF transforme également les ET (Extended Text) adjacents aux chiffres AN (arabe-indic) en chiffres AN, en plus de la règle EN (anglais) spécifiée dans la norme. Cela maintient la symétrie entre les contextes ASCII et arabe-indic, de sorte que ""٥٠٪"" (50 en arabe-indic + pourcentage en arabe-indic) traite le pourcentage de la même manière que ""50%"" traite le pourcentage ASCII.
    • Concrete fix: "شار $12.50 ريال" (logical UTF-16 0634 0627 0631 0020 0024 0031 0032 002E 0035 0030 0020 0631 064A 0627 0644). v2.72 output: 0644 0627 064A 0631 0020 0031 0032 002E 0035 0030 0024 0020 0631 0627 0634 — the $ glyph stranded at memory position 11, between the digit substring and the trailing space, reading awkwardly. v2.73 output: 0644 0627 064A 0631 0020 0024 0031 0032 002E 0035 0030 0020 0631 0627 0634 — "$12.50" intact as one LTR substring inside the RTL flow.
    • Correction de la table BIDI_Class : le caractère U+066A ARABIC PERCENT SIGN a été déplacé de bcAL vers bcOther (afin que le test W5 ET puisse le détecter et le transformer). La recherche de blocs arabes inclut maintenant des exceptions pour les plages de chiffres (bcAN), le bloc des signes diacritiques / shadda (bcNSM), le alef khanjareeya (bcNSM), les séparateurs décimaux / de milliers (bcAN) et le signe pourcentage (bcOther + ET via W5).
    • Ordre du pipeline : héritage NSM W1 (chemin LTR explicite, RTL implicite) -> W4 pour les espaces/sauts entre les chiffres -> W5 pour les caractères de séparation adjacents aux chiffres -> I2 pour l'attribution de niveau. W5 s'exécute après W4, donc un séparateur transformé par W4 et devenu EN est correctement identifié comme étant "adjacent à EN" par W5 lors du passage suivant ; les interactions entre plusieurs règles dans des expressions complexes de chiffres avec séparateurs et devises sont résolues en une seule traversée du pipeline.
    • Le texte brut, sans caractères spéciaux adjacents aux chiffres, est identique en termes de bytes à la sortie de la version v2.72. Les tests existants des versions v2.59 à v2.72 (prise en charge de l'arabe/hébreu RTL, positionnement SMP RTL, réorganisation de paragraphes LTR, gestion des chiffres, W4) restent tous stables en termes de bytes.
    • Les travaux restants concernant UAX #9 (nettoyage W6 / W7, paire de crochets N0 via la numérisation de la pile BD16 UAX #9, résolution neutre N1 / N2, jointure contextuelle GSUB OpenType pour l'arabe / le syriaque, enregistrement de polices Unicode basé sur des fichiers) doivent encore être effectués.

    2026-05-18 Version 2.72.0

    • Added Unicode UAX #9 simplified W4 (ES / CS between same-typed digits) for RTL paragraphs. Fixes the visible bug where Arabic text with formatted numbers — "السعر 12,345 ريال" (price with thousands comma), "12.50" (decimal point), "12:30" (time colon) — split the digit run at the separator in the reversed /Tj output, producing visually-broken numbers that read backwards within the RTL flow. With v2.72 W4 the separator joins the digit run, both reverse together once and then reverse together again at the whole-string pass, preserving the digit + separator logical order inside the RTL paragraph.
    • Les séparateurs W4 reconnus sont : le séparateur européen U+002B (+) / U+002D (-), le séparateur commun U+002C (,) / U+002E (.) / U+002F (/) / U+003A (:) / U+00A0 (espace insécable), et le séparateur arabe commun U+060C (virgule arabe). Chacun se transforme en EN lorsqu'il est encadré par deux EN, ou en AN lorsqu'il est encadré par deux AN. Les voisins de types mixtes (EN + AN, ou chiffre + non-chiffre) laissent le séparateur inchangé dans le flux bcOther / niveau-1 / environnant-RTL, comme auparavant. Simplifié vs complet UAX #9 W4 : la vérification au-delà des NSM est gérée (les NSM proches du séparateur ne perturbent pas la recherche W4), mais les chaînes de plusieurs séparateurs suivent une transformation par position plutôt que la restriction "unique" du séparateur spécifiée dans la norme (impact pratique faible, car les nombres réels ont rarement des séparateurs adjacents).
    • Concrete fix: "شار 12,345 ريال" (logical UTF-16 starts with Arabic letters, then space, "1" "2" "," "3" "4" "5", then space, then Arabic letters). v2.71 previous output: 0644 0627 064A 0631 0020 0035 0034 0033 002C 0031 0032 0020 0631 0627 0634 — digits split at the comma, reversed within each fragment ("345" before "12"), reads as "345,12" inside the LTR substring user perception. v2.72 fixed output: 0644 0627 064A 0631 0020 0031 0032 002C 0033 0034 0035 0020 0631 0627 0634 — "12,345" intact as one LTR substring, user reads it naturally in numeric order.
    • Correction de la table BIDI (v2.72.0) : les caractères U+066B ARABIC DECIMAL SEPARATOR et U+066C ARABIC THOUSANDS SEPARATOR sont désormais classés comme bcAN (valeur de retour 5) conformément à la spécification UnicodeData, au lieu de bcAL. Ces séparateurs sont définis dans la spécification comme faisant partie de la mise en forme numérique arabe, ils rejoignent donc naturellement la séquence de chiffres arabe-indi pour le réordonnement de niveau 2 sans nécessiter le passage W4. Le caractère U+066A ARABIC PERCENT SIGN est désormais classé comme bcAL (espace réservé ; le traitement spécifique de l'ET/terminateur de nombre européen est reporté au passage W5).
    • Refactorisation interne : l'étape d'attribution de niveau dans `_ApplyUAX9L2Reversal` crée désormais un tableau parallèle explicite `Classes[]` (un octet par position d'unité de code UTF-16) afin que la passe W4 puisse examiner les classes des voisins sans ré-décoder les points de code. Les points de code de paires substituées partagent les octets `Classes[]` et `Levels[]` entre les moitiés haute et basse. Une refactorisation équivalente pour `_ApplyUAX9L2ReversalLTRPara` est reportée (la passe W4 n'a aucun impact visible dans les paragraphes LTR car EN/AN restent déjà au niveau de base 0 dans le modèle simplifié à un seul niveau d'intégration).
    • Le texte RTL/LTR/mixte, sans séparateurs W4 entre les chiffres du même type, est identique en octets à la sortie des versions v2.66 à v2.71. Les tests existants (RTL arabe/hébreu/SMP RTL/positionnement NSM/réorganisation des paragraphes LTR/gestion des chiffres/détecteur) des versions v2.59 à v2.71 restent stables en termes de taille de fichier.
    • Les travaux restants concernant UAX #9 (W5, zone ET adjacente à EN, nettoyage de W6/W7, paire de crochets N0 via la numération en pile BD16 de UAX #9, résolution neutre simplifiée pour N1/N2, jointure contextuelle OpenType GSUB pour l'arabe/syriaque, enregistrement de polices Unicode basé sur des fichiers) doivent encore être effectués.

    2026-05-18 Version 2.71.0

    • Correction d'un bug de positionnement des signes diacritiques non séparateurs (NSM) dans le réarrangement du texte arabe/hébreu. Auparavant, l'inversion naïve de la chaîne entière déplaçait les signes diacritiques combinés (comme les harakat arabes telles que fatha, kasra, damma, shadda ; les niqqud hébreux tels que sheva, kamatz, patah ; les diacritiques latins combinés dans le bloc U+0300..U+036F) du mauvais côté de leur caractère de base dans le flux /Tj inversé. Les moteurs de rendu des signes diacritiques des lecteurs PDF attachaient ensuite le NSM au glyphe précédent dans l'ordre d'affichage, c'est-à-dire au caractère de base incorrect. Le bug visible était le suivant : "ALEF + FATHA + BA" (en arabe) affichait la fatha sur le glyphe BA au lieu de l'ALEF.
    • Ajout de l'héritage simplifié UAX #9 W1 NSM, ainsi qu'un passage inverse partagé par les trois algorithmes de réorganisation L2 (étape 2 + étape 3 du paragraphe RTL, réorganisation unique du paragraphe LTR). Le passage inverse traite désormais [base, NSM*] comme une unité : lors du parcours de droite à gauche, les NSM sont mis en mémoire tampon dans une pile et vidés dans l'ordre logique d'origine immédiatement après la base non-NSM suivante dans la sortie. Les paires de caractères de substitution restent intactes pendant le même passage inverse, et les NSM de la plage SMP (rares) sont traités de manière symétrique.
    • Correction concrète : "ALEF + FATHA + BA" (UTF-16 logique 0623 064E 0628) était précédemment émis comme 0628 064E 0623 (ordre inverse, FATHA entre BA et ALEF). Avec la version v2.71.0, la fonction de retournement compatible NSM émet la même entrée comme 0628 0623 064E, plaçant BA à gauche, ALEF au milieu et FATHA après ALEF, ce qui permet au moteur de rendu de l'attacher à la base correcte.
    • La table interne BIDI_Class a été étendue avec la classe bcNSM (valeur de retour 6) pour les principaux blocs de signes diacritiques combinés : les signes diacritiques combinés généraux U+0300..U+036F (latin / accents généraux), les signes diacritiques hébreux U+0591..U+05BD, ainsi que les entrées dispersées U+05BF / U+05C1..U+05C2 / U+05C4..U+05C5 / U+05C7 (extraites de la plage hébraïque R), les signes diacritiques arabes U+064B..U+065F et l'alef khanjareeya U+0670 (extraits de la plage arabe AL). Les signes diacritiques combinés sont toujours ignorés lors de la première analyse forte de la direction du paragraphe (P2/P3).
    • Pour les paragraphes LTR, une passe explicite d'héritage de niveau W1 est exécutée après l'attribution initiale du niveau : chaque élément NSM adopte le niveau de l'élément non-NSM précédent, de sorte qu'un élément NSM arabe suivant une base AL rejoint la séquence de niveau 1 de cette base pour le processus inverse unique L2. Pour les paragraphes RTL, le niveau est implicitement hérité (les éléments NSM et R / AL se résolvent tous deux au niveau 1 dans le modèle simplifié à un seul niveau d'intégration), de sorte qu'aucune passe W1 séparée n'est nécessaire.
    • Les entrées RTL/LTR/mixtes sans NSM sont identiques en termes de bytes aux sorties v2.66/v2.67/v2.68/v2.69/v2.70 (l'absence de NSM signifie qu'il n'y a pas de changement de comportement). Les tests existants de RTL arabe v2.59, de LTR-in-RTL v2.66, de LTR-para v2.67, de EN-AN v2.68 et de SMP-RTL v2.69 restent stables en termes de bytes.
    • Les travaux restants concernant UAX #9 (transitions de types faibles détaillées W3-W7, résolution des paires de parenthèses et des caractères neutres N0-N2, jointure contextuelle OpenType GSUB pour l'arabe/syriaque, enregistrement de polices Unicode basé sur des fichiers) doivent encore être réalisés.

    2026-05-18 Version 2.70.0

    • Ajout de l'aide THotPDF.RegisterUnicodeFontDict qui assemble un dictionnaire de police composite PDF 1.7 ISO 32000-1 9.7 / 9.7.6 de type 0 / CIDFontType2 + Identity-H en un seul appel. Les utilisateurs de la voie AcroForm /AP de SetFormUnicodeFontDict (version v2.56.0) n'ont plus besoin de coder manuellement les ~30 lignes de construction des sous-dictionnaires CIDSystemInfo / FontDescriptor / CIDFontType2 / Type 0 / Identity-H. Renvoie un objet THPDFDictionaryObject indirect prêt à être transmis à SetFormUnicodeFontDict.
    • API : RegisterUnicodeFontDict(BaseFont, FontBBoxL/B/R/T, Ascent, Descent, CapHeight, ItalicAngle, StemV, Flags, DefaultWidth). Tous les arguments de mesure ont des valeurs par défaut raisonnables (géométrie des polices intégrées CJK/arabe : FontBBox [-1000 -300 2000 1300], Ascent 1000, Descent -300, CapHeight 750, StemV 100, Flags 4 = Symbolique, DW 1000). Pour les polices Latin/hébraïques/cyrilliques, remplacez individuellement ces valeurs avec une bbox plus petite et Flags = 32 (non symbolique).
    • La structure du dictionnaire construite correspond à la disposition correcte selon les spécifications du Type 0 + CIDFontType2 utilisée par smoke_acroform_cid_rtl / smoke_bidi_* dans les versions v2.59-v2.69 : Adobe / Identity / Supplement 0 CIDSystemInfo, FontDescriptor avec toutes les entrées obligatoires 9.8.2, encodage Identity-H, descendant CIDFontType2 dans le tableau DescendantFonts, /DW pour la largeur de caractère par défaut. Lorsque non spécifié, /CIDToGIDMap par défaut est /Identity (CID == GID), ce qui correspond à ce que l'encodage Identity-H + l'ordre Adobe-Identity-0 impliquent.
    • Dans une version future (v2.71 et suivantes), une fonctionnalité sera ajoutée pour permettre l'enregistrement de polices Unicode à partir de fichiers .ttf/.otf. Cette fonctionnalité analysera les fichiers, extraira les métriques réelles ainsi que les valeurs de largeur d'avance (hmtx/W) pour des calculs de retour à la ligne précis, intégrera la police en tant que /FontFile2, générera une ToUnicode CMap à partir de cmap, et appellera RegisterUnicodeFontDict en interne pour gérer les aspects structurels.

    2026-05-18 Version 2.69.0

    • La table de recherche interne de classes BIDI Unicode a été étendue pour couvrir les blocs d'écriture de droite à gauche du plan multilingue supplémentaire (SMP) à U+10800..U+10FFF. La détection de la direction des paragraphes et le réarrangement L1-L2 reconnaissent désormais correctement le phénicien, l'araméen impérial, le palmyrénien, le nabatéen, le hatrien, le lydien, les hiéroglyphes/l'écriture meroïtique, le kharoshthi, l'arabe du sud, l'arabe du nord, le manichéen, l'avestique, le parthe inscrit/le pahlavi, le pahlavi des psaumes, le vieux turc, le vieux hongrois, le Hanifi Rohingya (AL, l'écriture actuellement utilisée pour la langue Rohingya au Myanmar), le Garay, le Yezidi, l'arabe étendu-C (AL), le vieux sogdien, le sogdien, le vieux ouïghour, le chorasmian et l'elymaïque.
    • Les paragraphes SMP RTL sont maintenant automatiquement détectés comme étant RTL via `DetectBidiParagraphDirection` (la première analyse des caractères examine les paires de caractères de substitution et correspond à la classe R/AL appropriée) et subissent le réarrangement RTL L1-L2 de la version 2.66 pour la sortie UTF-16BE Tj visuelle. Les paragraphes LTR contenant des sous-chaînes SMP RTL intégrées seront également inversés lorsque l'option `EnableLTRParaReorder` est activée (chemin d'accès optionnel de la version 2.67) ; sinon, ils sont affichés dans l'ordre logique et s'appuient sur la gestion BIDI intégrée du lecteur.
    • La préservation des paires surrogées continue de fonctionner lors de toutes les passes de réversion L2 : les caractères SMP RTL restent intacts sous forme de paires haute+basse dans le flux hexadécimal /Tj, tandis que le paragraphe environnant est correctement réorganisé.
    • v2.67 : Le test de vérification (smoke_bidi_ltr_reorder) contenait une assertion n°7 qui utilisait le caractère U+10840 IMPERIAL ARAMAIC LETTER ALEPH pour démontrer que "le point de code SMP est traité comme bcOther dans les paragraphes LTR". Cette assertion a été mise à jour dans cette version pour refléter la classification bcR désormais correcte : U+10840 dans un paragraphe LTR fait partie de la séquence de niveau 1 R/AL et est réorganisé à la position visuelle, à côté de toute sous-chaîne hébraïque/arabe voisine.
    • Les travaux restants concernant UAX #9 (héritage NSM W1 + transitions de type faible W3-W7 + neutre N0-N2 + résolution des paires de parenthèses + résolution explicite du niveau I + jointure contextuelle GSUB OpenType pour l'arabe/syriaque) sont toujours en cours. Avec la prise en charge de SMP RTL, tous les scripts RTL Unicode standardisés sont désormais correctement classés pour la direction du paragraphe et le réordonnement de base L1-L2.

    2026-05-18 Version 2.68.0

    • Fixed visible direction bug for digits embedded in Arabic / Hebrew paragraphs. Added Unicode UAX #9 weak-class BIDI_Class entries for European digits (EN, U+0030..U+0039) and Arabic-Indic digit ranges (AN, U+0660..U+0669 + U+06F0..U+06F9), with simplified UAX #9 I2 + L2 level assignment: in an RTL paragraph these digit codepoints now get resolved level 2 (same as embedded LTR runs) rather than level 1 alongside the surrounding RTL text. The two-pass L2 reorder then preserves their logical order inside the visual RTL flow, matching the spec-correct "شارع 12345" user reading even when the paragraph is rendered LTR for the PDF /Tj stream.
    • Concrete fix: an input "شار 12345" (logical UTF-16 0634 0627 0631 0020 0031 0032 0033 0034 0035) previously emitted as the Tj operand 0035 0034 0033 0032 0031 0020 0631 0627 0634 (whole-string reverse - digits inverted, the visible bug). With the v2.68 fix the same input emits 0031 0032 0033 0034 0035 0020 0631 0627 0634 - digits stay 1-2-3-4-5 in reading order while the Arabic word still renders in visual RTL.
    • `DetectBidiParagraphDirection` traite désormais EN et AN comme des caractères faibles conformément à UAX #9 P2 : les paragraphes composés uniquement de chiffres ou commençant par des chiffres ne font plus basculer la direction vers la droite (RTL) en raison des chiffres ; le premier caractère FORT (L / R / AL) l'emporte toujours. Une entrée vide ou ne contenant que des caractères faibles conserve la direction de gauche à droite (LTR) conformément à P3. Le test automatisé vérifie que les chiffres purs renvoient LTR, tandis que les chiffres suivis de caractères arabes renvoient RTL (le caractère arabe AL est le premier caractère fort) et les chiffres suivis de caractères latins renvoient LTR (le caractère latin L est le premier caractère fort).
    • La plage de caractères arabe U+0600..U+06FF a été divisée dans la table de recherche pour créer deux plages distinctes, bcAN ; les plages environnantes U+0600..U+065F + U+066A..U+06EF + U+06FA..U+06FF conservent la classification bcAL. Les autres points de code de la plage arabe (ponctuation, signes de pourcentage/mille, devises, etc.) conservent pour l'instant la classification bcAL ; une gestion plus fine des classes faibles (ET / CS / ON / NSM) sera intégrée dans une version ultérieure, ainsi que le reste du pipeline W1-W7 / N0-N2.
    • L'entrée RTL pure, sans séquences de chiffres, est identique en termes de bytes à la sortie des versions v2.66 / v2.67 (aucune transition de classe W n'est déclenchée). Les paragraphes LTR ne sont pas affectés (les chiffres sont déjà rendus en LTR par la direction de base du paragraphe). La correction s'active automatiquement pour tous les clients existants utilisant AutoDetectFormBidi ou FormUnicodeRTL avec UseUAX9LevelReversal=True (par défaut).
    • Il reste encore à implémenter la portée UAX #9 + GSUB (héritage NSM W1 + prise en charge complète de W3/W4/W5/W6/W7 + parenthèses N0-N2 + résolution explicite de niveau I1 + jointure contextuelle GSUB OpenType pour l'arabe/syriaque + scripts RTL SMP BIDI_Class).

    2026-05-18 Version 2.67.0

    • Ajout d'un réordonnancement Unicode UAX #9 L2 côté serveur pour les paragraphes LTR contenant des sous-chaînes RTL intégrées. Une nouvelle propriété, `THotPDF.EnableLTRParaReorder` (par défaut : False), permet aux appelants d'activer une sortie conforme à la spécification, indépendante du lecteur et basée sur `/AP` : un paragraphe LTR contenant de l'hébreu/de l'arabe est réordonné au moment de la génération de `/AP`, de sorte que les lecteurs consommateurs n'ont pas besoin d'effectuer leur propre traitement BIDI sur les sous-chaînes RTL dans l'ordre logique.
    • Algorithme en une seule passe, symétrique à celui de la version v2.66.0 pour les paragraphes RTL-L1-L2 : le niveau de base pour les paragraphes LTR est 0 ; chaque point de code "strong-R" / "strong-AL" est résolu au niveau 1 ; tout le reste reste au niveau 0. Conformément à UAX #9 L2, le niveau impair le plus bas est 1, donc la boucle effectue une seule passe : inversez chaque sous-chaîne de niveau 1 maximale (séquence continue de caractères R/AL). Les caractères LTR et les caractères faibles/neutres sont copiés sans modification. Les paires de caractères de substitution sont préservées pendant l'inversion.
    • La méthode publique `THotPDF.ApplyUAX9L2ReversalLTRPara` expose le nouvel algorithme de manière autonome (entrée et sortie en UTF-8). Elle est distincte de `ApplyUAX9L2Reversal` de la version v2.66.0 : le chemin `ParagraphRTL=False` de cette dernière reste inchangé dans la version v2.66, de sorte que les appelants qui dépendent du comportement de la version v2.66 obtiennent une sortie identique en octets ; utilisez la nouvelle méthode pour le réordonnement dans la direction LTR.
    • Activez par défaut `EnableLTRParaReorder` à "False", ce qui maintient une sortie /AP identique à la version 2.59-2.66 pour les appels de paragraphes LTR. Ce paramètre n'a aucun effet lorsque `UseUAX9LevelReversal` est défini sur "False" (l'inversion simple de la version 2.59 ne réorganise jamais les paragraphes LTR) ; les deux paramètres sont indépendants dans les autres cas.
    • Les transitions de type faible UAX #9 W1-W7 + les neutres N0-N2 + la résolution des paires de crochets + la résolution explicite de niveau I1-I2 + la formation OpenType GSUB restent dans la portée de la version 2.68+.

    2026-05-18 Version 2.66.0

    • Ajout d'une fonctionnalité de retournement sensible aux séquences UAX #9 pour les flux Unicode des formulaires AcroForm. Une nouvelle propriété, `THotPDF.UseUAX9LevelReversal` (par défaut, `True`), remplace l'inversion naïve de chaînes entières pour les paragraphes RTL, introduite dans la version 2.59.0, par un réordonnement correct selon la spécification, en deux passes, qui préserve l'ordre logique interne des sous-chaînes LTR intégrées dans les paragraphes RTL.
    • Concrete fix: an input "<Hebrew>AB" (logical UTF-16 05D0 05D0 0041 0042) previously emitted as the Tj operand hex 0042 0041 05D0 05D0 ("BAאא"), which inverts the embedded LTR "AB" - wrong per UAX #9. With L1-L2 active the same input now emits 0041 0042 05D0 05D0 ("ABאא"). Pure-RTL input with no L runs (e.g. the v2.59.0 pre-shaped Arabic smoke) remains byte-identical to the legacy naive reverse.
    • La méthode publique THotPDF.ApplyUAX9L2Reversal expose le nouvel algorithme en tant qu'outil autonome (entrée et sortie en UTF-8) pour les utilisateurs qui créent leurs propres flux d'apparence ou qui souhaitent prévisualiser le réarrangement avant la génération de /AP.
    • Une version simplifiée, avec un seul niveau d'intégration, de UAX #9 I1 + L2 est utilisée dans cette section : dans un paragraphe RTL, chaque caractère "fort-L" reçoit le niveau 2 ; tout le reste (R, AL, faible, neutre, substitut) reste au niveau 1. Ensuite, L2 inverse d'abord les séquences de niveau 2 (restaure l'ordre logique des sous-chaînes LTR intégrées) et, enfin, inverse la séquence de niveau 1 de toute la chaîne (produisant la disposition RTL visuelle). Les paires de caractères de substitution sont conservées lors des deux étapes.
    • Les transitions de type faible (UAX #9 W1-W7) ainsi que les neutres et les paires de parenthèses (N0-N2), la résolution explicite de niveau (I1-I2) et le réordonnement des paragraphes LTR contenant des blocs RTL restent dans la portée de la version 2.67+. La version 2.66.0 corrige le problème le plus courant : les paragraphes RTL contenant des sous-chaînes LTR multi-caractères.
    • Utilisez `UseUAX9LevelReversal` avec la valeur par défaut "True". Définissez-la sur "False" pour revenir à l'inversion de chaîne entière naïve de la version v2.59.0, ce qui permet d'obtenir une sortie compatible avec les versions antérieures. Les deux options continuent de lire `FormUnicodeRTL` et `AutoDetectFormBidi` de la même manière.

    2026-05-18 Version 2.65.0

    • Ajout de la détection automatique de la direction du paragraphe conformément à l'annexe #9 de la norme Unicode pour les flux d'apparence Unicode AcroForm. Nouvelle propriété THotPDF.AutoDetectFormBidi qui remplace le commutateur FormUnicodeRTL manuel de la version v2.59.0 par une détection de la direction du paragraphe à chaque appel. Grâce à cela, la même séquence de définition de propriétés peut gérer un ensemble de champs LTR et RTL dans un même document, sans avoir à activer manuellement un indicateur.
    • La direction est déterminée en analysant l'entrée pour trouver le premier caractère fort (règles UAX #9 P2 + P3) et en le classant avec BIDI_Class L (gauche), R (droite-à-gauche) ou AL (lettre arabe). Un caractère fort de type R ou AL ancre le paragraphe en RTL ; un caractère fort de type L ancre le paragraphe en LTR ; un paragraphe sans caractère fort adopte par défaut la direction LTR selon P3.
    • Reconnaissance de la classe BIDI : Forte L - ASCII Latin, Latin-1, Latin Extended, grec, copte, cyrillique, arménien, idéogrammes unifiés CJK, Hangul, Hiragana, Katakana, Yi. Forte R - bloc hébreu (U+0590..U+05FF), formes de présentation hébraïques (U+FB1D..U+FB4F), N'Ko, samaritain, mandaïque. Forte AL - bloc arabe, supplément arabe, arabe étendu-A, syriaque, thaana, formes de présentation arabe A + B (U+FB50..U+FDFF + U+FE70..U+FEFF). Les paires substituées et les caractères faibles/neutres (chiffres, ponctuation, espaces) sont ignorés pendant la recherche.
    • La méthode publique THotPDF.DetectBidiParagraphDirection expose le détecteur aux appelants qui souhaitent pré-calculer la direction (par exemple, pour l'étiquetage /Lang, la sortie neutre inversée ou le routage personnalisé des champs). Elle accepte une chaîne Ansi UTF-8 et renvoie un booléen (True = RTL). Une entrée vide renvoie False, conformément à P3.
    • AutoDetectFormBidi par défaut est défini sur False; le comportement précédent des versions v2.59.0-v2.64.0 est conservé. Lorsque la valeur est True, les fonctions ignorent FormUnicodeRTL pour chaque appel. Désactivez AutoDetectFormBidi pour rétablir le contrôle manuel.
    • Résolution implicite de niveau UAX #9, avec typage faible et résolution de parenthèses neutres (règles W1-W7, N0-N2, I1-I2, L1-L4), ainsi que la liaison contextuelle automatique pour les polices OpenType Arabic/Syriac, sont toujours prévues pour la version v2.66+. Les paragraphes bidirectionnels mixtes nécessitent toujours une intervention manuelle de l'appelant, au-delà du niveau du paragraphe.

    2026-05-18 Version 2.64.0

    • Ajout d'une entrée de demi-tonnage "ExtGState" (/HT) conforme à la norme PDF 1.2 ISO 32000-1 10.5.5, ainsi que d'un générateur de dictionnaire de demi-tonnage spot de type 1. Nouvelle fonction `THotPDF.RegisterHalftoneType1` qui crée le dictionnaire de demi-tonnage de type 1 selon le tableau 76 de la norme PDF 1.7, permettant au client de contrôler la séparation CMYK (fréquence en lignes par pouce, angle de l'écran en degrés, forme du spot, option de demi-tonnage précis, fonction de transfert, nom descriptif du demi-tonnage). Associez-la à `THotPDF.RegisterHalftoneState` pour intégrer cette référence de dictionnaire dans une entrée "ExtGState" /HT, à utiliser avec `THPDFPage.SetGraphicsState`.
    • /SpotFunction accepte soit un nom de spot intégré de tableau 78 de PDF 1.7 (SimpleDot, InvertedSimpleDot, DoubleDot, InvertedDoubleDot, CosineDot, Double, InvertedDouble, Line, LineX, LineY, Round, Ellipse, EllipseA, InvertedEllipseA, EllipseB, EllipseC, InvertedEllipseC, Square, Cross, Rhomboid, DiamondRhomboid), soit une référence à un dictionnaire de fonction créé par l'appelant. Les noms intégrés inconnus génèrent une erreur, avec la liste complète des noms spécifiés dans le message. Les paramètres Spot-name et Function sont mutuellement exclusifs.
    • /TransferFunction est facultatif. Passez une référence à un dictionnaire Function pour un contrôle de la reproduction des tons par l'appelant, ou définissez TransferFunctionDefault = True pour générer /TransferFunction /Identity (par défaut pour le lecteur). Les deux formes sont mutuellement exclusives.
    • RegisterHalftoneState accepte soit une référence vers un dictionnaire de demi-tons (généralement la valeur de retour de RegisterHalftoneType1), soit la valeur HTDefaultName = True pour réinitialiser le chemin d'accès au nom littéral "/HT /Default", ce qui restaure le demi-ton intégré du lecteur.
    • Toutes les émissions augmentent automatiquement la version du document à PDF 1.2. La fréquence doit être supérieure à 0 ; les noms de fonctions spot non valides génèrent une erreur avant que le dictionnaire ne soit alloué.
    • Les autres types de demi-tons sont prévus pour la version v2.65 et suivantes : demi-tons multi-composants de type 5, et demi-tons de type 6 / 10 / 16 utilisant un flux de seuil. Avec le type 1 déjà implémenté, les "entrées ExtGState" de la matrice sont une étape vers une couverture complète.

    2026-05-18 Version 2.63.0

    • Ajout des entrées de masquage progressif (soft-mask) et de transparence (alpha-is-shape) conformes à PDF 1.4 ISO 32000-1 11.6.5 + 11.7.4. La nouvelle fonction `THotPDF.RegisterSoftMaskState` regroupe les paramètres liés à la transparence, à savoir `/SMask` et `/AIS`, dans un seul dictionnaire ExtGState, complétant ainsi la couverture de la chaîne d'entrées ExtGState pour toutes les entrées définies dans la spécification, à l'exception du filtre de demi-teinte `/HT` multi-type (prévu pour la version v2.64 et suivantes).
    • `/SMask` contient soit la chaîne de caractères `/None` (l'appelant passe `SMaskNone = True`, un schéma de réinitialisation courant après une composition complexe), soit une référence indirecte à un dictionnaire de masque soft (l'appelant passe `SMaskDict`, cas d'utilisation avancé). Les deux formes sont mutuellement exclusives. L'appelant est responsable du contenu du dictionnaire de masque soft et de l'objet Forme transparent sous-jacent ; à partir de la version 2.64, un outil de construction dédié sera ajouté.
    • /AIS contrôle si les valeurs alpha actuelles sont interprétées comme des valeurs alpha (false) ou comme des formes (true) pour le reste de l'état graphique. Par défaut, la valeur de sentinelle AIS = -1 ignore complètement l'entrée /AIS. La transmission de AIS = 0 ou 1 génère respectivement /AIS false ou /AIS true. Toute autre valeur de AIS entraîne une erreur avec un message descriptif.
    • Au moins l'un des éléments suivants doit être fourni : /SMask (soit None, soit un dictionnaire) ou /AIS ; l'absence de l'un de ces éléments provoque une erreur. L'émission de toute entrée met automatiquement le document à jour vers la version PDF 1.4.
    • Renvoie le nom de l'ExtGState généré automatiquement (GS1, GS2, ...) à utiliser avec THPDFPage.SetGraphicsState. Différent de AddImageWithSMask dans la version v2.42.0 : ce dernier utilise un alpha au niveau de l'image sur un seul XObject ; celui-ci utilise un masque au niveau de l'ExtGState, qui affecte tous les opérateurs de dessin suivants.
    • L'entrée ExtGState restante est prévue pour la version v2.64 et supérieure : /HT représente l'écran de demi-tons (types 1, 5, 6, 10 et 16).

    2026-05-18 Version 2.62.0

    • Ajout des entrées de génération de noir et de suppression de la sous-couleur dans ExtGState pour PDF 1.2/1.3+ et ISO 32000-1 11.7.5.4. La nouvelle fonction THotPDF.RegisterBlackGenerationState regroupe les quatre paramètres d'état graphique référençant des fonctions (/BG, /BG2, /UCR, /UCR2) dans un seul dictionnaire ExtGState pour les flux de travail de prépresse CMYK, où la conversion de l'espace colorimétrique RGB en CMYK a lieu au moment du rendu (ce qui est typique pour les journaux, les emballages et la production grand format, où les décisions de dépôt d'encre sont spécifiques à l'appareil de sortie).
    • /BG et /UCR (PDF 1.2) sont des dictionnaires de fonctions avec 1 entrée et 1 sortie ; /BG2 et /UCR2 (PDF 1.3 et versions ultérieures) sont soit des dictionnaires de fonctions, soit le nom littéral /Default qui restaure la courbe par défaut du lecteur. Le setter accepte un objet THPDF pour chaque emplacement de fonction (généralement créé via RegisterSampledFunction depuis la version 2.52.0) et deux indicateurs booléens BG2DefaultName et UCR2DefaultName pour la forme littérale /Default. L'utilisation d'un dictionnaire de fonctions et de l'indicateur Default pour le même emplacement /BG2 ou /UCR2 génère un message d'erreur explicatif.
    • Au moins l'un des éléments suivants doit être fourni : /BG, /BG2, /UCR, /UCR2 (soit une fonction, soit une valeur par défaut) ; l'appel sans aucun de ces éléments génère une erreur. La version du PDF est automatiquement mise à jour à la version 1.3 lorsqu'un élément /BG2 ou /UCR2 (soit une fonction, soit une valeur par défaut) est utilisé.
    • Renvoie le nom de l'ExtGState généré automatiquement (GS1, GS2, ...) à utiliser avec THPDFPage.SetGraphicsState. S'intègre naturellement avec v2.60.0 RegisterTransferFunctionState (courbes de sortie par canal) - une chaîne de production CMYK typique enregistre un ExtGState BG/UCR pour la conversion RGB vers CMYK, ainsi qu'un ExtGState /TR pour la reproduction finale des tons sur le périphérique de sortie.
    • Les entrées ExtGState restantes seront ajoutées dans la version v2.63 et suivantes : /HT pour les écrans de demi-tons (types 1, 5, 6, 10, 16) et les masques doux /SMask et /AIS au niveau de l'ExtGState.

    2026-05-17 Version 2.61.0

    • Ajout des entrées de contrôle d'impression ExtGState pour PDF 1.2/1.3+ ISO 32000-1 8.6.5.7 + 8.6.5.8 + 11.7.4. Nouveau : THotPDF.RegisterPrintControlState regroupe les paramètres d'état graphique orientés vers la prépresse, à savoir /OP, /op, /OPM, /SA, /RI et /FL, dans un seul dictionnaire ExtGState, ce qui est adapté aux flux de travail de production PDF/X-1/X-3/X-4 qui nécessitent des contrôles de superposition, d'ajustement du trait, d'intention de rendu et d'aplatissement des courbes.
    • Tous les six paramètres sont indépendamment optionnels. Les valeurs par défaut sont : Overprint = -1 (ignore /OP + /op), OverprintMode = -1 (ignore /OPM), StrokeAdjustment = -1 (ignore /SA), RenderingIntent = '' (ignore /RI), Flatness < 0 (ignore /FL). L'appelant doit fournir au moins une entrée ; les dictionnaires vides lèvent une exception.
    • Les paramètres de superposition /OP et /op sont maintenant combinés (la spécification PDF attribue par défaut la valeur /OP à /op lorsque seul ce dernier est défini, mais les pipelines PDF/X conformes à la spécification attendent les deux entrées explicitement). La définition de OverprintMode = 1 active la superposition CMYK compatible avec la version 1.3 de PDF, où toute composante nulle est affichée en transparence ; cela augmente automatiquement la version du document à 1.3.
    • `RenderingIntent` accepte les quatre valeurs standard suivantes : 'AbsoluteColorimetric' / 'RelativeColorimetric' / 'Saturation' / 'Perceptual' ; toute autre chaîne de caractères non vide génère une erreur. `Flatness` est limité à la plage spécifiée [0.0..100.0] ; toute valeur hors de cette plage génère une erreur.
    • Renvoie le nom de l'ExtGState généré automatiquement (GS1, GS2, ...) à utiliser avec THPDFPage.SetGraphicsState. S'intègre naturellement avec v2.20.0 RegisterExtGState (transparence / mode de fusion) et v2.60.0 RegisterTransferFunctionState (courbes de sortie) - une configuration PDF/X typique enchaîne un de chaque.
    • Les fonctionnalités liées à la génération de noir et à la suppression de la couleur de fond (/BG, /UCR, /BG2, /UCR2) ainsi que le complexe écran de demi-tons /HT et le masque doux de niveau ExtGState (/SMask) restent des objectifs pour les versions futures.

    2026-05-17 Version 2.60.0

    • Ajout du support pour PDF 1.3+ ISO 32000-1 11.7.3.4 ExtGState /TR (fonction de transfert). La nouvelle méthode THotPDF.RegisterTransferFunctionState enregistre un dictionnaire ExtGState contenant une entrée /TR qui applique une courbe de reproduction de tons lors de la rasterisation des couleurs. La courbe est fournie sous la forme d'une LUT échantillonnée de type 0 (v2.52.0) (ou tout autre dictionnaire de fonction que l'appelant a créé) ; ce wrapper s'associe naturellement à la primitive RegisterSampledFunction existante pour créer des courbes gamma / de luminosité / de caractérisation de presse optimisées, sans passer par les mécanismes de profil ICC.
    • Deux façons d'appeler la fonction :
    • Formulaire SingleFunc : une fonction unique appliquée à chaque canal de sortie (cas d'utilisation de la correction gamma / luminosité).
    • Format de tableau par canal : un tableau de 4 éléments [TR_R, TR_G, TR_B, TR_A] pour les pipelines RGB-A ou [TR_C, TR_M, TR_Y, TR_K] pour les courbes de reproduction CMYK ; les quatre emplacements doivent être non nuls, conformément à la spécification PDF.
    • Renvoie le nom de l'ExtGState généré automatiquement (GS1, GS2, ...) à utiliser avec THPDFPage.SetGraphicsState. Appliquez l'état avant d'utiliser les opérateurs de dessin (texte / chemins / images) qui doivent bénéficier du traitement de transfert.
    • Les appels combinés (SingleFunc non nul + PerChannel non vide) génèrent une exception afin de faire respecter l'exclusion mutuelle spécifiée au niveau de l'interface de l'API.

    2026-05-17 Version 2.59.0

    • Ajout du support de l'orientation de gauche à droite pour AcroForm Unicode /AP (PDF 1.7 ISO 32000-1 12.7.4.3). Nouvelle propriété booléenne `THotPDF.FormUnicodeRTL` ; lorsqu'elle est définie sur true, les trois fonctions d'aide Unicode /AP (monoligne, multiligne, combinée) inversent l'ordre des unités de code UTF-16 dans les opérandes hexadécimaux Tj générés, de sorte que le contenu arabe/hébreu/syriaque préformaté s'affiche dans l'ordre visuel de gauche à droite. Les paires de caractères UTF-16 sont conservées comme une unité pendant l'inversion (la partie haute reste adjacente à la partie basse dans l'ordre d'origine, de sorte que les points de code SMP tels que les caractères de scripts anciens s'affichent correctement).
    • Champ d'application : la version v2.59.0 gère uniquement l'étape d'inversion directionnelle. L'appelant est responsable de deux étapes antérieures que v2.59.0 ne réalise pas intentionnellement : (1) la résolution complète de l'algorithme bidirectionnel UAX #9 (contenu mixte LTR/RTL/numérique/neutre) et (2) la liaison contextuelle de l'arabe/syriaque (sélection des formes de glyphes initiales/médiales/finales/isolées). Les appelants doivent formater l'arabe dans ses formes de présentation Unicode (U+FB50..U+FDFF + U+FE70..U+FEFF) avant de le passer à AddTextField. L'hébreu ne possède pas de liaison contextuelle, il fonctionne donc sans formatage préalable.
    • /V (ordre Unicode logique) reste inchangé : les chaînes de texte PDF conservent toujours l'ordre typé, ce qui permet aux extracteurs de texte conformes à la spécification de voir la séquence logique correcte. Seuls les opérateurs /AP Tj inversent l'ordre, de sorte que le rendu affiche le texte de droite à gauche. Avec cette version, la chaîne internationale /AP d'AcroForm de la version v2.55.0-v2.59.0 est complète : elle prend en charge le texte riche, les lignes simples et multiples, les polices CID et l'inversion directionnelle RTL préformatée. La prise en charge complète de UAX #9 ainsi que la formation GSUB automatique restent dans le périmètre de la version v2.60.0+.

    2026-05-17 Version 2.58.0

    • Dans la version v2.56.0 / v2.57.0, la chaîne de polices Unicode fournie par l'utilisateur pour l'objet /AP a été étendue à la branche ffComb (PDF 1.7 ISO 32000-1 12.7.4.3 Tx /Ff bit 25). Lorsque SetFormUnicodeFontDict a enregistré une police composite de type 0 et qu'un widget Tx est ajouté avec ffComb et une valeur initiale non-ASCII, HotPDF génère désormais un flux d'apparence /AP /N réel qui affiche un code point CJK par cellule de comb de largeur égale, en utilisant une matrice Tm absolue par cellule et des opérandes Tj en chaîne hexadécimale UTF-16BE.
    • Les paires de caractères UTF-16 (points de code >= U+10000, par exemple les emojis et les idéogrammes supplémentaires CJK Extension B/C/D) occupent une seule cellule combinée, ce qui correspond à la façon dont Acrobat organise les cellules combinées de polices composites à un seul glyphe. La formule de centrage de la cellule est identique à celle de la branche ASCII à partir de la version v2.46.0, de sorte que la sortie visuelle reflète la disposition des caractères ASCII uniques.
    • Les champs combinés ASCII conservent l'identité des octets par rapport à la sortie de la version v2.46.0. Les champs combinés non-ASCII, sans l'utilisation de `SetFormUnicodeFontDict`, continuent de revenir à la zone de remplissage vide de la version v2.46.0 (sans modification). Avec cette version, la chaîne internationale /AP d'AcroForm (monoligne, multiligne, combinée) de la version v2.55.x à v2.58.0 est complète ; la mise en forme bidirectionnelle RTL (UAX #9 + liaison contextuelle arabe) reste dans le périmètre de la version v2.59.0+.

    2026-05-17 Version 2.57.0

    • La prise en charge des chemins de police Unicode fournis par l'utilisateur pour les champs de texte multilignes (PDF 1.7, ISO 32000-1, 12.7.4.3, ffMultiline / Tx /Ff, bit 13) a été étendue. Lorsque SetFormUnicodeFontDict a enregistré une police composite de type 0 et qu'un widget Tx est ajouté avec ffMultiline et une valeur initiale non-ASCII, HotPDF effectue maintenant un retour à la ligne du texte UTF-16 et génère une chaîne hexadécimale UTF-16BE par ligne visible, en utilisant Td/T* avec /TL au début (ce qui correspond à la mise en page multiligne ASCII de la version 2.46.0).
    • Word-wrap utilise une heuristique simple : 1 em pour chaque unité de code CJK/large (>= U+2E80) et 0,5 em pour chaque unité de code étroite (plage ASCII et ponctuation Latin-1), de sorte que le contenu mixte Latin/CJK se coupe de manière logique sans lire le tableau /W de la police. Les sauts de ligne forcés (CR/LF/CRLF) sont respectés. Les lignes qui dépassent le rectangle du widget sont tronquées au nombre de lignes qui tiennent à la taille de police actuelle ; ce comportement de troncature est le même que celui de la branche multi-lignes ASCII.
    • Les chemins ASCII multi-lignes, ASCII mono-lignes, ASCII combinés et les chemins non-ASCII mono-lignes de la version v2.56.0 restent identiques au niveau des octets. Le chemin combiné non-ASCII (ffComb + texte multi-octets) continue pour l'instant à utiliser l'aideur mono-ligne de la version v2.56.0 ; la disposition Unicode spécifique à ffComb, ainsi que la gestion bidirectionnelle RTL (UAX #9 + liaison contextuelle arabe), sont disponibles à partir de la version v2.58.0.

    2026-05-17 Version 2.56.0

    • Ajout du support des polices Unicode fournies par l'appelant pour le rendu du flux d'apparence /AP des formulaires AcroForm (PDF 1.7 ISO 32000-1 12.7.2 + 12.7.4.3). Avant cette version, le chemin GenerateTextFieldAP générait un espace réservé /AP vide chaque fois que la valeur initiale du champ contenait un octet >= 0x80, de sorte que le texte non-ASCII ne pouvait être rendu qu'à l'aide de la régénération /NeedAppearances=true (en fonction des polices installées par le lecteur) ou via le chemin de texte enrichi v2.55.0 /RV (en fonction du moteur de texte enrichi du lecteur). La version 2.56.0 comble cette lacune : les appelants peuvent enregistrer une police composite de type 0 /CIDFontType2 + Identity-H via SetFormUnicodeFontDict et HotPDF génère un flux d'apparence /AP /N réel qui sélectionne la police enregistrée via l'opérateur Tf et rend la valeur sous forme de chaîne hexadécimale UTF-16BE.
    • Nouvelle fonction THotPDF.SetFormUnicodeFontDict(LogicalName, FontDict) : enregistre une paire nom de police logique + dictionnaire de police. Une fois enregistrée, le nom logique est utilisé pour /DA au niveau du formulaire, pour /DA de chaque widget Tx et pour le flux /AP pour les valeurs initiales non-ASCII de Tx ; le dictionnaire /DR/Font du formulaire contient également la police, aux côtés de /Helv et /ZaDb ; le sous-dictionnaire /Resources/Font de l'objet XObject du formulaire fait également référence à la même police indirecte, ce qui rend le flux AP autonome et indépendant de la résolution /DR au moment du rendu. Pour revenir au comportement /Helv-only de la version 2.46.0, passez une valeur vide et nil.
    • Nouvelle fonction `THotPDF.CreateIndirectFontDict` : fonction d'aide publique qui alloue un nouvel objet `THPDFDictionaryObject` vide, enregistré en tant qu'objet PDF indirect, afin que les appelants puissent créer des dictionnaires personnalisés pour les polices, les couleurs, les OCG (éléments de contrôle de la transparence) et les fonctions, qui doivent être sérialisés sous forme de références "N G R". Elle est naturellement associée à `SetFormUnicodeFontDict` pour la création de dictionnaires de polices composites de type 0.
    • Les champs de transmission ASCII continuent d'utiliser "/Helv" et génèrent une sortie "/AP" identique en octets aux versions v2.46.0 et v2.55.0. La transmission multi-octets sans l'utilisation de SetFormUnicodeFontDict continue de revenir au comportement de l'espace réservé "/AP" vide de la version v2.46.0 (conservé tel quel) pour assurer la compatibilité.
    • La prise en charge des chaînes multi-lignes et des caractères non-ASCII pour /AP, ainsi que la gestion de la disposition RTL bidi (UAX #9 + liaison contextuelle arabe), restent dans le périmètre de la version v2.57.0+ ; la version v2.56.0 prend en charge les scripts CJK/cyrilliques/vietnamiens/grecques et scripts similaires dans un ordre logique en une seule ligne.

    2026-05-17 Version 2.55.0

    • Ajout du support des widgets de texte enrichi AcroForm (PDF 1.7 ISO 32000-1 12.7.4.3 + Annexe L). La nouvelle méthode THPDFPage.AddRichTextField génère un widget de texte contenant /RV (corps XHTML de texte enrichi), /DS (style par défaut semblable à CSS), le drapeau ffRichText (/Ff bit 26), et la version texte brute /V + /DV utilisée par les lecteurs qui ne traitent pas /RV. Acrobat et Foxit rendent directement à partir de /RV lorsque le drapeau RichText est activé, en utilisant les polices par défaut du lecteur à partir des polices Unicode installées, ce qui permet d'afficher correctement le contenu multi-octets (CJK / cyrillique / arabe / latin accentué) sans que HotPDF n'intègre une police CID dans /DR Resources. L'intégration d'une police CID pour le générateur de flux d'apparence propre de HotPDF (/AP) reste une tâche à accomplir ultérieurement ; les lecteurs compatibles avec le texte enrichi n'en ont pas besoin.
    • Les paramètres /V et /RV détectent automatiquement les entrées multi-octets et passent au codage hexadécimal UTF-16BE (marqueur de début d'ordre d'octet FE FF + unités de code en ordre grand) lorsque cela est nécessaire, ce qui correspond au comportement existant de AddTextField pour les champs de texte brut internationaux. Le contenu ASCII reste sous forme de chaînes PDF littérales pour obtenir une sortie identique à celle du chemin d'émission de texte brut de la version 2.46.0.
    • Trois points doivent encore être traités concernant les caractères internationaux dans les formulaires Acrobat : (1) le chemin d'accès aux ressources de police CID /DR, afin que les flux /AP générés par HotPDF prennent en charge les caractères non-ASCII sans dépendre du moteur de texte enrichi du lecteur, (2) la gestion de la disposition bidirectionnelle (RTL) pour le texte enrichi en arabe/hébreu, et (3) l'outil d'assistance pour les actions de touches /AA /K.

    2026-05-17 Version 2.54.0

    • Fonction de type 0 (échantillonnée) PDF 1.7 ISO 32000-1 7.10.2 avec interpolation cubique. `RegisterSampledFunction` gagne un nouveau paramètre optionnel "Order" (par défaut 1, valeurs acceptées 1 ou 3, conformément au tableau 38 de la spécification PDF 1.7). Lorsque "Order" est égal à 3, une interpolation cubique est appliquée sur chaque axe d'entrée ; lorsque "Order" est égal à 1, le comportement linéaire existant est conservé, garantissant une compatibilité parfaite avec les versions v2.52.0 et v2.53.0, sans modification visible.
    • Ajout d'une couverture de régression complète pour le chemin de code du type de fonction 0 avec plusieurs entrées / plusieurs sorties. Un nouveau test de base enregistre une fonction échantillonnée avec 2 entrées / 3 sorties sur une grille de 4x4 avec interpolation cubique et teste la règle d'ordre d'échantillonnage de la spécification ("les coordonnées d'entrée augmentent le plus rapidement le long de la première dimension d'entrée"), en comparant par octet les 16 points de la grille x 3 canaux avec une formule analytique redérivée dans le vérificateur Python.
    • Acrobat, Foxit et qpdf prennent tous en charge la valeur Order = 3 ; certains anciens lecteurs mobiles utilisent silencieusement une interpolation linéaire lorsqu'ils rencontrent une valeur Order inconnue. L'interpolation cubique reste une option pour maintenir la compatibilité maximale avec les lecteurs.

    2026-05-17 Version 2.53.0

    • Ajout d'un registre d'espace colorimétrique de séparation de haut niveau qui utilise une fonction échantillonnée de type 0 (LUT) comme transformation de teinte (PDF 1.7 ISO 32000-1 8.6.6.4 + 7.10.2). La nouvelle fonction `THotPDF.RegisterSeparationLUT (ColorantName, AlternateCS, Samples)` s'appuie sur la fonction primitive `RegisterSampledFunction` de la version v2.52.0, permettant aux utilisateurs de définir une courbe de teinte non linéaire complète sous forme d'un flux d'octets plat de (M-tuples) d'échantillons, sans avoir à construire manuellement un dictionnaire de type 0.
    • Utilisez la nouvelle variante de LUT lorsque la transition de couleur n'est pas linéaire (dégradés de tons de type PANTONE Hexachrome, courbes de densité corrigées gamma, courbes de tons dessinées à la main correspondant à une caractérisation de presse, LUT ICC pour la conversion sRGB vers des couleurs spot sans l'ensemble des mécanismes de profil ICC). Utilisez RegisterSeparation v2.45.0 lorsque une transition linéaire de 0 à une extrémité de pleine intensité est suffisante (le cas le plus courant pour les couleurs spot PANTONE à une seule encre).
    • Les échantillons sont des octets RVB/CMJN/gris 8 bits, ordonnés (c0_0, c1_0, ..., cM-1_0, c0_1, ..., cM-1_S-1), où S est le nombre de points de grille, calculé comme Length(Samples) / M. S doit être au moins 2 pour que la fonction ait une plage d'interpolation. L'interpolation linéaire entre les points de grille est la valeur par défaut (PDF 1.7 /Order 1). La fonction renvoie le nom de l'espace colorimétrique enregistré (Sep1, Sep2, ...) à utiliser avec THPDFPage.SetFillColorSpace / SetStrokeColorSpace + SetFillColor([tint]), où 0 <= tint <= 1.
    • Internally, THPDFSeparationParams.TintFunc a été étendu de THPDFDictionaryObject à la classe de base commune THPDFObject afin qu'il puisse contenir soit un objet de type de fonction 2 (chemin d'accès de la version 2.45.0), soit un flux de type de fonction 0 (chemin d'accès de la version 2.53.0) ; les deux formes sont sérialisées de manière identique via THPDFArrayObject.AddObject en tant que référence indirecte "N G R" dans le tableau /Separation.

    2026-05-17 Version 2.52.0

    • Ajout de l'enregistrement du type de fonction 0 (échantillonnée) selon la norme PDF 1.7 ISO 32000-1 7.10.2. Les fonctions échantillonnées expriment une correspondance arbitraire entre l'entrée et la sortie sous la forme d'une grille régulière d'échantillons de sortie M-dimensionnels ; le rendu effectue une interpolation linéaire entre les points de la grille pour évaluer les entrées intermédiaires. Utilisez le type 0 lorsque la gestion des profils ICC est excessive, mais qu'une table de correspondance des couleurs (LUT) personnalisée est souhaitée (courbes de tonalité pour /TransferFunction dans ExtGState, transformations de teinte échantillonnées pour /Separation / /DeviceN, au-delà des chemins linéaires de type 2 / arithmétiques de type 4 déjà pris en charge, courbes de seuil de demi-teinte ou toute autre construction PDF qui utilise un dictionnaire de fonction).
    • La nouvelle fonction `THotPDF.RegisterSampledFunction(Domain, Range, Size, BitsPerSample, Samples)` génère un flux indirect de type `/FunctionType 0` avec les paramètres `/Domain` (2N), `/Range` (2M), `/Size` (N), `/BitsPerSample` (1, 2, 4, 8, 12, 16, 24 ou 32), `/Order 1` (interpolation linéaire) et la charge utile brute des échantillons compressés en bits. Elle renvoie l'objet `THPDFStreamObject` indirect pour que les appelants puissent l'attacher partout où un dictionnaire `Function` est attendu.
    • La longueur du tableau d'octets Samples est validée par rapport à ceil(GridPoints * M * BitsPerSample / 8). Les largeurs 8 / 16 / 24 / 32 BitsPerSample sont alignées sur les octets, en ordre de poids fort, et les largeurs inférieures à un octet (1 / 2 / 4 / 12) suivent l'encodage MSB-first tel que défini dans PDF 1.7 §7.10.2, avec le dernier octet complété à zéro.
    • Les types de fonctions 3 (assemblage) et 4 (calculateur PostScript) étaient utilisables en interne via HPDFRegisterFunctionType3 / HPDFRegisterFunctionType4 depuis les versions v2.18.0 / v2.47.0 ; cette version met le type 0 au même niveau de prise en charge de l'API publique.

    2026-05-17 Version 2.51.6

    • La série de corrections pour la sécurité binaire v2.51.x est terminée, avec la correction du dernier problème de boucle "Source=Target" dans la classe TStringList, concernant la carte des rôles de structure (PDF 1.7 ISO 32000-1 14.7.3 /StructTreeRoot /RoleMap). Les noms de rôles de structure personnalisés enregistrés via AddStructRoleMap ne sont plus modifiés silencieusement sur les systèmes Windows avec CP_ACP=65001 (option de région "Beta: Use Unicode UTF-8"); le stockage a été migré vers un tableau dynamique d'enregistrements (Source: TBytes; Target: TBytes), avec une opération Move() qui préserve les octets lors de chaque insertion/lecture. Les types de structure PDF standard (Document, P, H1..H6, Span, Div, etc.) sont en ASCII selon la spécification, donc les versions précédentes fonctionnaient en pratique ; cette correction est importante uniquement pour les applications qui mappent les noms de rôles Latin-1 spécifiques aux outils de création vers les types standard.
    • J'ai étendu l'échappement de nom PDF #XX (PDF 1.7 7.3.5) aux CLÉS de dictionnaire dans SaveDictionaryObject. Auparavant, les clés de dictionnaire étaient copiées telles quelles dans le flux de sortie, ce qui laissait les octets >= 0x80 non échappés et produisait une sortie non conforme à la spécification. Ce problème pouvait être rencontré via AddStructRoleMap avec un rôle source non-ASCII. La logique de suppression au niveau de l'octet et d'échappement #XX est maintenant dans une fonction auxiliaire partagée (_EscapePDFNameBytes), appelée à la fois par SaveNameObject (valeurs de nom) et SaveDictionaryObject (clés de dictionnaire). Les clés ASCII (le cas universel pour les dictionnaires générés par HotPDF) sont échappées pour produire une sortie identique à l'octet, de sorte que les fichiers et les tests existants ne sont pas affectés.
    • Après cette version, la chaîne de sécurité binaire v2.51.x (destinataires PubSec, ColorantNames de DeviceN, émission de valeurs de nom PDF, émission de clés de nom PDF, stockage de la carte des rôles structuraux) est structurellement complète - il ne reste plus de conversion aller-retour AnsiString-via-UnicodeString pour n'importe quel bloc d'octets connu par HotPDF. 34 tests positifs sur 34 et 27 vérificateurs sur 27 ont réussi.

    2026-05-17 Version 2.51.5

    • Nous avons continué l'analyse de sécurité binaire de la version 2.51.4 sur deux autres chemins de sortie, qui pourraient potentiellement corrompre silencieusement les octets non-ASCII sur les systèmes où Windows CP_ACP=65001 ( "Beta: Utilisez Unicode UTF-8 pour la prise en charge des langues du monde entier") est activé.
    • Les noms de colorants DeviceN sont désormais stockés sous forme de tableau dynamique de TBytes dans THPDFDeviceNParams (auparavant, une liste de chaînes Unicode). L'ancienne représentation obligeait une conversion AnsiString -> UnicodeString -> AnsiString pour chaque nom de couleur, ce qui, sur les systèmes ANSI UTF-8, réécrivait chaque octet >= 0x80 en une séquence de remplacement de 3 octets EF BF BD. Les noms de couleurs ASCII uniquement (PANTONE / Hexachrome et les noms de style "Red" / "Blue") n'étaient pas affectés ; les noms de couleurs personnalisés non-ASCII (par exemple, les noms de couleurs spot accentués Latin-1 dans les flux de travail d'impression non anglais) étaient silencieusement corrompus avant cette version.
    • Le chemin d'émission du nom PDF (SaveNameObject) est désormais sûr au niveau des octets et conforme à la spécification. L'implémentation précédente utilisait AnsiString(Trim(String(ValObject.Value))), ce qui effectuait la même opération destructrice pour chaque nom PDF écrit sur le disque. Les noms sont maintenant tronqués par comparaison d'octets ("caractère <= 0x20", ce qui correspond à la sémantique de Trim de Delphi) et tout octet en dehors de la plage de noms réguliers 0x21..0x7E est émis avec l'échappement #XX requis par la spécification (PDF 1.7, ISO 32000-1, 7.3.5). Les noms ASCII sans espaces au début ni à la fin et sans octets spéciaux intégrés produisent une sortie bit-à-bit identique à celle d'avant, de sorte que les fichiers et les tests existants ne sont pas affectés.
    • Un nouveau vérificateur aller-retour (smoke_devicen_binary_safe) enregistre une encre DeviceN dont le nom contient un octet 0xA0 intégré et vérifie que le tableau /Names émis contient l'échappement conforme à la spécification ""#A0"" au lieu de la séquence corrompue ""#EF#BF#BD"". Avec cette version, la chaîne de sécurité binaire v2.51.x (destinataires PubSec, noms d'encre DeviceN, émission générique de noms PDF) est complète ; 33 tests sur 33 réussissent, ainsi que 26 vérificateurs sur 26.

    2026-05-17 Version 2.51.4

    • Correction d'une corruption silencieuse des octets de l'enveloppe du destinataire dans le gestionnaire de sécurité par clé publique (PDF 1.7 ISO 32000-1 7.6.5). Lorsque le système hôte a activé la fonctionnalité Windows "Bêta : Utiliser Unicode UTF-8 pour la prise en charge des langues mondiales" (CP_ACP=65001), le stockage précédent des blocs de données enveloppés PKCS#7 basé sur TStringList forçait une conversion AnsiString -> UnicodeString -> AnsiString qui réécrivait chaque octet non-ASCII en tant que séquence de remplacement UTF-8 (EF BF BD). Cette corruption se propageait de la même manière dans le calcul de la clé de fichier SHA-1 (algorithme 9) et dans les chaînes hexadécimales /Recipients, de sorte que le fichier PDF résultant pouvait toujours être déchiffré avec la clé corrompue propre à HotPDF, mais aucun lecteur tiers ne pouvait dériver la même clé des octets d'origine de l'enveloppe, ce qui signifie que le fichier chiffré était effectivement uniquement lisible par HotPDF lui-même sur le même système verrouillé par CP_ACP.
    • La correction remplace le magasin de destinataires par un tableau dynamique de `TBytes`; la signature de l'API publique `AddPubKeyRecipient` reste inchangée. Les octets de l'enveloppe sont maintenant copiés tels quels via `Move()`; aucun chemin de conversion de page de code n'est conservé.
    • Les valeurs hexadécimales de "/Recipients" reproduisent désormais les enveloppes fournies byte par byte, indépendamment de la locale de l'hôte ; Acrobat, Foxit, qpdf et tout lecteur compatible PKCS#7 peuvent récupérer la clé de chiffrement du fichier, comme le spécifie la norme.
    • Un nouveau vérificateur aller-retour (smoke_pubsec_verify) a été ajouté à la version v2.33.0 et échoue dans cette compilation depuis lors ; la version v2.51.4 le fait passer de "ÉCHEC" à "OK". Avec cette version, l'ensemble de la chaîne d'audit v2.51.x (audit R=5, audit utilisateur-mot de passe R=6, correction du mot de passe du propriétaire K0, correction des octets du destinataire PubSec) est terminée, et pour la première fois depuis v2.33.0, 25 vérificateurs rapides sur 25 passent avec succès.

    2026-05-16 Version 2.51.3

    • Correction de la validation du mot de passe du propriétaire utilisant AES-256 V=5 R=6, afin qu'elle soit conforme à l'algorithme 2.B de la norme ISO 32000-2, tel qu'il est écrit. La séquence de hachage PDF 2.0 prescrit l'état initial K comme étant SHA-256(mot de passe || sel || udata), où udata, pour les dérivations du mot de passe du propriétaire, est l'entrée /U complète de 48 octets. Dans les versions précédentes de HotPDF (de la v2.22.0 à la v2.51.2), udata n'était inclus que dans l'étape itérative K1 et était omis de l'état K initial, ce qui produisait un hachage /O[0:32] non conforme que les lecteurs de type Acrobat / Foxit / qpdf rejetteraient lors de la validation du mot de passe du propriétaire. Le déchiffrement par mot de passe utilisateur n'a pas été affecté, car sa séquence de hachage est appelée avec un argument udata vide et est donc bit-identique avec ou sans la correction.
    • Acrobat / Foxit / qpdf valident désormais le mot de passe du propriétaire par rapport aux fichiers R=6 générés par HotPDF. Les valeurs /O[0:32] et /OE produites avant la version v2.51.3 restent lisibles pour le déchiffrement par mot de passe utilisateur, mais ne peuvent pas être déverrouillées par leur mot de passe propriétaire par des lecteurs conformes aux spécifications ; régénérez les fichiers R=6 concernés avec la version v2.51.3 si la validation du mot de passe propriétaire est nécessaire en externe.
    • /U / /UE / /Perms : V=5 R=5 ; les chemins sont identiques à la sortie antérieure à la version v2.51.3 ; la correction est limitée au premier hachage SHA-256 K dans PDF20HashDanceR6 et ne modifie la sortie que lorsqu'elle est appelée avec un UEntry non vide (le point d'appel du mot de passe du propriétaire dans CreateKeysV5).
    • Une nouvelle vérification bidirectionnelle (smoke_aes256_r6_owner_verify) dérive /O[0:32] à la fois à partir de l'algorithme de préfixe et de l'algorithme de spécification ; elle affirme que la valeur /O[0:32] générée correspond à la variante de la spécification et que la variante du préfixe ne reproduit plus la sortie.

    2026-05-16 Version 2.51.2

    • Nous avons étendu l'audit de v2.51.1 /Perms pour couvrir le chemin standard de gestion de la sécurité V=5 R=6 ("hash dance") (ISO 32000-2 7.6.4.3.4 / Algorithme 2.B). Un nouveau vérificateur aller-retour réimplémente le mélangeur itératif SHA-256 / SHA-384 / SHA-512 + AES-128-CBC en Python pur, dérive la clé de chiffrement de fichier de 32 octets à partir du mot de passe utilisateur vide, déchiffre en AES-256-ECB le bloc /Perms de 16 octets, et vérifie chaque champ par rapport aux valeurs du dictionnaire de chiffrement (/P en little-endian, 0xFF comme remplissage, balises 'T' / 'F', littéraux 'a' 'd' 'b'). Aucun changement de comportement ; cette version est une couverture de régression pure pour le chemin R=6, correspondant au verrouillage R=5 introduit dans v2.51.1.

    2026-05-16 Version 2.51.1

    • Dans la suite de tests de régression, la liaison /P -> /Perms du gestionnaire de sécurité standard V=5 R=5 a été verrouillée. Le chemin de chiffrement AES-256 génère un bloc /Perms de 16 octets, conformément à l'algorithme 10 de l'ISO 32000-1 : les octets 0 à 3 contiennent la valeur /P en little-endian 32 bits, les octets 4 à 7 sont des octets de remplissage 0xFF, l'octet 8 indique 'T' ou 'F' pour le suivi de /EncryptMetadata, les octets 9 à 11 sont les marqueurs littéraux 'a', 'd', 'b', et les octets 12 à 15 sont des données aléatoires. Un nouvel audit aller-retour dérive la clé de chiffrement du fichier à partir du mot de passe de l'utilisateur via l'algorithme 2.A (SHA-256(pw || U_Key_Salt) -> AES-CBC-décryptage /UE -> clé de fichier), déchiffre /Perms avec AES-256-ECB et vérifie chaque champ par rapport aux valeurs du dictionnaire de chiffrement. Aucun changement de comportement ; cette version est une couverture de régression pour garantir qu'une refactorisation future ne puisse pas rompre silencieusement la relation /P <-> /Perms spécifiée.

    2026-05-16 Version 2.51.0

    • Ajout du support duombrage de maillage par produit tensoriel (PDF 1.3+ ISO 32000-1 8.7.4.5.7, Type deombrage 7), la dernière entrée de la famille desombrages de maillage, après le Type 4 (forme libre) dans la version v2.48, le Type 5 (treillis) dans la version v2.49 et le Type 6 (Coons) dans la version v2.50. Chaque patch par produit tensoriel contient une grille complète de 4 x 4 points de contrôle de Bezier cubiques p[i][j] (12 points de bordure + 4 points intérieurs), ainsi qu'une couleur par coin, offrant un contrôle précis à la fois de la bordure du patch et de son intérieur. Utile pour les conversions SVG de maillage et pour toute œuvre d'art vectorielle qui nécessite une surface de Bezier par produit tensoriel plutôt qu'une surface mélangée de type Coons.
    • `THotPDF.RegisterTensorProductPatchMesh(XMin, YMin, XMax, YMax, NumComponents, Patches)` génère un flux binaire de type `/ShadingType 7` avec `/BitsPerCoordinate 16`, `/BitsPerComponent 8` et `/BitsPerFlag 8`, l'encapsule dans un motif de type 2, et renvoie un nom de motif (Sh1, Sh2, ...) qui peut être utilisé via les pipelines habituels `SetFillPattern` ou `SetStrokePattern`.
    • Chaque patch dans le tableau plat est empaqueté en 16 points de contrôle (32 nombres à virgule flottante X+Y, dans l'ordre spécifié : p[0][0..3], p[1][3], p[2][3], p[3][3], p[3][2..0], p[2][0], p[1][0], p[1][1], p[1][2], p[2][2], p[2][1]), suivi de 4 couleurs de coin (4 * NumComponents nombres à virgule flottante à p[0][0] / p[0][3] / p[3][3] / p[3][0]), avec une taille de pas de 32 + 4 * NumComponents. Chaque patch émis porte le drapeau = 0 (patch indépendant).
    • Avec cette version, toute la famille de dégradés maillés ISO 32000-1 8.7.4.5 (types 4, 5, 6 et 7) est désormais prise en charge.

    2026-05-16 Version 2.50.0

    • Ajout du support duombrage de maillage Coons (PDF 1.3+ ISO 32000-1 8.7.4.5.6, Type deombrage 6) - la troisième entrée dans la famille desombrages de maillage, après le Type 4 (forme libre) dans la version 2.48 et le Type 5 (treillis) dans la version 2.49. Chaque patch Coons est délimité par quatre courbes de Bézier cubiques et possède une couleur par coin ; le moteur de rendu ajuste la surface Coons entre les quatre arêtes, créant ainsi un quadrilatère de couleur de forme arbitraire. Utile pour les dégradés métalliques et les dégradés métallisés sur les chemins courbes, les maillages de dégradés dérivés de SVG, et tout quadrilatère avec des arêtes courbes qui nécessiterait autrement de nombreux petits triangles pour être approximé.
    • `THotPDF.RegisterCoonsPatchMesh(XMin, YMin, XMax, YMax, NumComponents, Patches)` génère un flux binaire de type `/ShadingType 6` avec `/BitsPerCoordinate 16`, `/BitsPerComponent 8` et `/BitsPerFlag 8`, l'encapsule dans un motif de type 2, et renvoie un nom de motif (Sh1, Sh2, ...) qui peut être utilisé via les pipelines habituels `SetFillPattern` ou `SetStrokePattern`.
    • Les tableaux plats de correctifs emballent chaque correctif en 12 points de contrôle (24 nombres à virgule flottante X+Y), suivis de 4 couleurs de coin (4 * NumComponents nombres à virgule flottante), avec un pas de 24 + 4 * NumComponents. Les 12 points de contrôle sont ordonnés de c1 à c12 dans le sens des aiguilles d'une montre autour de la limite du correctif, en commençant par le coin 1, avec c1 / c4 / c7 / c10 aux quatre coins, et les 8 restants comme points de Bézier internes. Chaque correctif émis porte le drapeau = 0 (correctif indépendant) ; les drapeaux de continuation 1 / 2 / 3 (partage de bord) ne sont pas exposés dans cette surcharge pratique.
    • Le type 7 (structure de patch de produit tensoriel) reste un travail à réaliser ultérieurement.

    2026-05-16 Version 2.49.0

    • Ajout du support pour les maillages triangulaires ombragés de Gouraud en forme de grille (PDF 1.3+ ISO 32000-1 8.7.4.5.5, Type deombrage 5), complément de la fonctionnalité de type 4 en forme libre de la version v2.48.0. Utilisez-la lorsque les données sources sont déjà organisées sur une grille de points réguliers (terrains, résultats d'analyse par éléments finis, cartes thermiques scientifiques) et que l'application ne souhaite pas générer une topologie triangulaire explicite ; le moteur de rendu triangule automatiquement chaque paire de lignes adjacentes pour former une bande de triangles.
    • Nouvelle fonction `THotPDF.RegisterLatticeFormGouraudShading(XMin, YMin, XMax, YMax, NumComponents, VerticesPerRow, Vertices)` qui encapsule une grille de M lignes x N colonnes dans un flux de dégradé binaire avec `/BitsPerCoordinate` de 16, `/BitsPerComponent` de 8 et `/VerticesPerRow` de N. Contrairement au type 4, il n'y a pas de byte d'indicateur par sommet et `/BitsPerFlag` est absent du dictionnaire de dégradé. Renvoie un nom de motif (Sh1, Sh2, ...) qui peut être utilisé via le pipeline standard de définition de motif de remplissage ou de contour.
    • Le tableau plat de sommets est organisé selon l'ordre "row-major", chaque sommet contribuant avec les valeurs (X, Y, c0, c1, ..., c_{NumComponents-1}); le nombre total de sommets doit être un multiple de VerticesPerRow, avec au moins deux lignes. NumComponents accepte les valeurs 1 (DeviceGray), 3 (DeviceRGB) ou 4 (DeviceCMYK).
    • Les effets de maillage de type 6 (patch de Coons) et de type 7 (produit tensoriel) restent des travaux à réaliser ultérieurement.

    2026-05-16 Version 2.48.0

    • Ajout du support pour les maillages de triangles texturés de type Gouraud (PDF 1.3+ ISO 32000-1 8.7.4.5.4, Type de dégradé 4) pour les dégradés de couleurs dans les illustrations vectorielles, offrant une solution plus générale que les variantes axiales/radiales existantes. Toute surface triangulée avec des couleurs par sommet peut désormais être intégrée directement.
    • La nouvelle fonction `THotPDF.RegisterFreeFormGouraudShading(XMin, YMin, XMax, YMax, NumComponents, Vertices)` encapsule le maillage triangulaire dans un flux de dégradé binaire avec `/BitsPerCoordinate` de 16, `/BitsPerComponent` de 8 et `/BitsPerFlag` de 8, l'emballe dans un motif de type 2, et renvoie un nom de motif (Sh1, Sh2, ...) qui peut être utilisé via les pipelines habituels `THPDFPage.SetFillPattern` ou `THPDFPage.SetStrokePattern`.
    • Les tableaux de sommets contiennent les coordonnées (X, Y) et les composantes de couleur (c0, c1, ...) pour chaque sommet ; chaque groupe de trois sommets consécutifs forme un triangle indépendant. Les coordonnées/composantes de sortie sont encodées sous forme d'entiers non signés en ordre de octets fort ; le tableau /Decode mappe la plage encodée à la zone de délimitation fournie par l'utilisateur dans l'espace utilisateur.

    2026-05-16 Version 2.47.0

    • Ajout du support de l'espace colorimétrique DeviceN (PDF 1.3+ ISO 32000-1 8.6.6.5), généralisant la séparation à N colorants pour l'impression en six couleurs, les mélanges d'encres métalliques/fluorescentes et les flux de travail d'encres personnalisés PDF/X. Nouvelle fonction THotPDF.RegisterDeviceN(ColorantNames, AlternateCS, TintC1Matrix) qui renvoie un nom d'espace colorimétrique généré automatiquement (DevN1, DevN2, ...) qui contrôle le pipeline habituel SetFillColorSpace + SetFillColor avec N opérandes de teinte dans la plage [0..1].
    • La transformation de teinte est une fonction de type 4 de PostScript qui génère un mélange pondéré linéaire à partir de la matrice N x M fournie, de sorte que, en l'absence de prise en charge des couleurs spéciales, le rendu de secours effectue une interpolation de chaque canal de sortie en tant que somme des contributions des colorants.
    • ColorantNames accepte tout nom d'encre spécifique ; les espaces sont échappés en "#20" conformément à la norme PDF 1.7, section 7.3.5, par le chemin de gestion des noms existant. Le nom spécial ""None"" indique un emplacement de colorant inutilisé.
    • AlternateCS accepte DeviceGray, DeviceRGB ou DeviceCMYK ; toute autre valeur provoque une exception.

    2026-05-15 Version 2.46.0

    • Génération améliorée des flux d'apparence (AutoFormAppearances) pour les champs de texte, conformément à la norme PDF 1.7, ISO 32000-1, section 12.7.4.3. Dans la version de base v2.28.0, une chaîne littérale unique était générée pour chaque widget de texte ; les champs multilignes et les champs combinés utilisent désormais leurs propres chemins de mise en page de l'AP.
    • Les champs de texte multilignes (avec les attributs ffMultiline) ajustent automatiquement la longueur du texte initial à la largeur du widget, prennent en compte les séparateurs de retour chariot (CR), saut de ligne (LF) et retour chariot-saut de ligne (CRLF) intégrés, tronquent le texte au nombre de lignes visibles et génèrent une mise en page multiligne correcte avec Td + T* et un espacement initial /TL.
    • Les champs de texte combinés (avec les attributs ffComb, MaxLen > 0) rendent chaque caractère dans sa propre cellule de largeur égale, en utilisant une matrice Tm absolue par glyphe, ce qui correspond à ce que Acrobat affiche.
    • Les champs de texte à une seule ligne conservent la mise en page de la version v2.28.0, byte par byte, afin que les clients existants ne constatent aucun changement de comportement.

    2026-05-14 Version 2.45.0

    • Ajout du support de l'espace colorimétrique de séparation pour les flux de travail d'impression en couleurs séparées, conformément à la norme ISO 32000-1 8.6.6.4. La nouvelle fonction `THotPDF.RegisterSeparation(ColorantName, AlternateCS, TintC1)` renvoie un nom d'espace colorimétrique généré automatiquement (Sep1, Sep2, ...) qui contrôle la séquence habituelle `SetFillColorSpace / SetStrokeColorSpace + SetFillColor([tint]) / SetStrokeColor([tint])` avec un seul paramètre de teinte dans la plage [0..1].
    • AlternateCS accepte DeviceGray, DeviceRGB ou DeviceCMYK ; TintC1 décrit la couleur de l'encre spéciale à pleine intensité (tint = 1.0). Une transformation de teinte linéaire de type 2 est construite en interne, de sorte que le rendu de secours sur les lecteurs sans prise en charge des couleurs spéciales effectue une interpolation fluide entre zéro encre (tint = 0) et TintC1 (tint = 1).
    • Les noms de couleurs Pantone et autres noms d'encres contenant des espaces sont acceptés directement ; THotPDF les échappe en séquences ""#20"" conformément à la spécification PDF 1.7, section 7.3.5, lors de l'écriture du nom de l'espace colorimétrique.
    • Refuse les documents dont la version est inférieure à PDF 1.3 grâce à la fonctionnalité "RequirePDFVersion", de sorte que la sortie en mode strict 1.2 ou versions antérieures reste conforme.

    2026-05-14 Version 2.44.0

    • Ajout du support de l'espace colorimétrique CIELab conformément à la norme ISO 32000-1 8.6.5.3. Nouvelle fonction `THotPDF.RegisterLabColorSpace(Xw, Yw, Zw, aMin, aMax, bMin, bMax)` qui renvoie un nom d'espace colorimétrique généré automatiquement (Lab1, Lab2, ...) et qui permet de contrôler les opérations `THPDFPage.SetFillColorSpace / SetStrokeColorSpace` ainsi que les chaînes `SetFillColor([L, a, b]) / SetStrokeColor([L, a, b])`.
    • Workflow courant : enregistrez une seule valeur par illuminant (D50 pour l'impression ICC, D65 pour un affichage équivalent à sRGB), puis appliquez une valeur L* dans la plage [0..100] et des valeurs a* et b* dans la plage choisie (généralement -128..127). Les lecteurs PDF (Adobe Acrobat, Foxit, MuPDF, lecteurs intégrés aux navigateurs) tiennent compte de la WhitePoint lors de la conversion de Lab en RGB d'affichage.
    • Refuse les documents dont la version est inférieure à PDF 1.3 grâce à la fonctionnalité "RequirePDFVersion", de sorte que la sortie en mode strict 1.2 ou versions antérieures reste conforme.

    2026-05-14 Version 2.43.1

    • Nous avons vérifié l'encodeur CCITTFaxDecode existant de bout en bout sur une véritable image binaire : une image TBitmap de 240x120, encodée en pf1bit avec des bandes alternées, est correctement intégrée dans les trois modes (icCCITT31 G3 1D / icCCITT32 G3 2D / icCCITT42 G4 / T.6). Les tailles des flux encodés suivent l'ordre de compression attendu G3-1D > G3-2D > G4, les flux sont décodés dans Adobe Acrobat / Foxit / MuPDF sans avertissement, et l'échantillonnage des pixels confirme que le motif de bandes noir/blanc alternées est conservé dans les trois modes. Aucune modification du code de l'encodeur n'a été apportée ; cette version verrouille simplement la couverture existante de PDF 1.7 ISO 32000-1 7.4.9 dans la suite de tests.

    2026-05-14 Version 2.43.0

    • Ajout d'un motif de remplissage non coloré (PaintType=2) de bout en bout, conformément à la norme ISO 32000-1 8.6.6.1. Le flux de motif contient uniquement la géométrie de la tuile (sans couleur) ; la couleur de teinte est appliquée via l'opérateur scn / SCN dans le flux de contenu de la page au moment du remplissage/du trait.
    • Nouvelles méthodes THPDFPage : SetFillPatternRGB / SetStrokePatternRGB / SetFillPatternGray / SetStrokePatternGray / SetFillPatternCMYK / SetStrokePatternCMYK acceptent un nom de motif non coloré enregistré, ainsi que les composantes de teinte (DeviceRGB, DeviceGray ou DeviceCMYK, dans la plage [0..1]). Chaque appel enregistre automatiquement l'espace colorimétrique de teinte correspondant [/Pattern /BaseCS] dans le dictionnaire Ressources/ColorSpace de la page lors de la première utilisation.
    • Les fonctions `SetFillPattern` et `SetStrokePattern` existantes couvrent déjà la variante de `PaintType=1` où la couleur est définie directement dans le motif, sans utiliser de composantes de teinte.
    • Les deux chemins de code partagent le point d'entrée `RegisterTilingPattern` existant ; lorsque `Colored=true`, `PaintType=1` (couleur) est émis, et lorsque `Colored=false`, `PaintType=2` (sans couleur) est émis.

    2026-05-14 Version 2.42.0

    • Ajout du support des images avec masque de transparence (SMask) selon la norme PDF 1.4. La nouvelle méthode `THotPDF.AddImageWithSMask` prend un plan RGB brut et un plan alpha parallèle de 8 bits, génère l'objet image couleur ainsi qu'un objet masque de transparence DeviceGray, et configure la référence croisée `/SMask` conformément à la norme ISO 32000-1 8.9.5.4. Utilisez l'index de l'image renvoyée avec la méthode `ShowImage` existante ; aucun autre changement n'est nécessaire.
    • Ajout de l'utilitaire pratique THotPDF.AddImageWithSMask32 qui extrait les plans de couleur et d'alpha d'une bitmap BGRA 32 bits, permettant ainsi d'intégrer des bitmaps de type PNG avec canal alpha en un seul appel.
    • Les deux appels refusent les documents dont la version est inférieure à PDF 1.4, grâce à la fonctionnalité "RequirePDFVersion", ce qui garantit que la sortie en mode strict 1.3 reste conforme.

    2026-05-14 Version 2.41.0

    • Ajout du flux d'objet PDF 1.5. Définissez THotPDF.UseObjectStreams sur true, ainsi que les paramètres UseXRefStream et SaveToStream, pour regrouper les objets indirects éligibles (tout sauf les flux, le dictionnaire de chiffrement et les dictionnaires Catalog et Info référencés par la section finale) dans un ou plusieurs flux conteneurs de type /ObjStm.
    • Réduction de la taille des fichiers pour les documents PDF volumineux (nombreuses pages, annotations, widgets AcroForm, éléments de l'arborescence de structure ou calques de contenu optionnel). Un test simple avec des graphiques uniquement, sur un document de 30 pages, réduit la taille de 14502 octets à 8488 octets (une réduction de 41,5 %) sans modification visible.
    • Les flux de références croisées génèrent désormais des entrées d'objets compressés de type 2, dont le champ 2 est le numéro de l'objet ObjStm hôte et le champ 3 est l'index de l'entrée dans ce flux. La fonction UseObjectStreams passe silencieusement à "false" lorsque UseXRefStream est désactivée (les références croisées textuelles ne peuvent pas encoder les entrées de type 2) ou lorsque la version est inférieure à PDF 1.5.

    2026-05-12 Version 2.40.1

    • Correction du rendu des fichiers PDF générés dans Adobe Acrobat, Foxit, SumatraPDF et les visualisations intégrées aux navigateurs sur les systèmes Windows 10 / 11, lorsque l'option de région "Bêta : Utiliser Unicode UTF-8 pour la prise en charge des langues mondiales" est activée. Les flux de contenu des pages ne contiennent plus de préambule UTF-8 BOM indésirable que les lecteurs PDF stricts rejettent comme une erreur de syntaxe.

    2026-05-11 Version 2.40.0

    • Ajout du sous-ensemble de polices CFF indexées par CID pour les grandes polices CJK et OpenType-CFF multi-FD, y compris les polices Adobe CJK qui utilisent les données FDArray et FDSelect.
    • Amélioration de la gestion des sous-routines CFF afin que les polices OpenType-CFF volumineuses puissent être intégrées en tant que sous-ensembles PDF compacts au lieu de fichiers de polices complets.

    2026-05-11 Version 2.39.1

    • Amélioration de la compatibilité avec les polices OpenType-CFF du monde réel, y compris les polices de style Adobe MinionPro avec des tables CFF plus volumineuses et des décalages en plusieurs octets.
    • Révélé HPDFExtractTTFPostScriptName afin que les applications dotées de code de chargement de polices personnalisé puissent lire le nom PostScript à partir des données de police TrueType et OpenType-CFF.

    2026-05-11 Version 2.39.0

    • Ajout du sous-ensemblement de Global Subr et de Local Subr pour les polices CFF, ce qui réduit encore la taille des polices OpenType-CFF intégrées.
    • La version conserve le bytecode des sous-routines CFF tout en remplaçant de manière sécurisée les entrées inutilisées par des blocs de retour compacts.

    2026-05-11 Version 2.38.0

    • Ajout de l'intégration automatique OpenType-CFF dans StoreFont. HotPDF génère désormais des polices CID basées sur CFF via /FontFile3 lorsque la police chargée par GDI est un conteneur OpenType-CFF (sfnt 'OTTO').
    • Des API auxiliaires HPDFSfntIsOTF, HPDFOTFFindCFFTable et HPDFSubsetOTFContainer ont été ajoutées pour les applications qui traitent directement les polices OpenType-CFF.

    2026-05-11 Version 2.37.0

    • Ajout de HPDFSubsetCFF pour le format de police compact et les charges utiles de polices Type 1C, ce qui permet de réduire la taille des programmes de police CFF intégrés.
    • Les identifiants de glyphes originaux ont été conservés lors de la sous-échantillonnage CFF, afin de maintenir la compatibilité avec la sortie de texte Type0 / Identity-H existante.
    • Rendu le sous-ensembleur CFF pour les applications qui chargent les polices via leur propre pipeline avant de transmettre les données à HotPDF.

    2026-05-10 Version 2.36.0

    • Ajout du sous-ensemble de polices TrueType facultatif avec THotPDF.EnableFontSubsetting, ce qui réduit souvent de plus de 90 % la taille des polices intégrées dans les documents qui n'utilisent qu'un petit ensemble de glyphes.
    • Ajout de la nomenclature des polices de sous-ensemble standard PDF, tout en conservant les identifiants de glyphes de la police source pour le texte Identity-H.
    • L'intégration complète de la police a été conservée comme option par défaut pour les flux de travail qui nécessitent le programme de police complet.

    2026-05-10 Version 2.35.1

    • Correction d'un plantage d'"acquisition de police" dans Adobe Acrobat lors de l'ouverture de fichiers PDF créés avec des polices Windows substituées. HotPDF fait maintenant correspondre les noms de police PDF aux noms PostScript contenus dans les données TrueType intégrées.

    2026-05-10 Version 2.35.0

    • Ajout du support pour les mises à jour PDF incrémentielles avec `THotPDF.BeginIncrementalUpdate` et `THotPDF.SaveIncrementalUpdate`. Les octets de la source existante sont conservés et de nouveaux objets PDF sont ajoutés conformément à une révision incrémentielle.
    • Ajout de THotPDF.MarkDirty afin que les applications puissent explicitement enregistrer à nouveau les objets modifiés lors des mises à jour incrémentielles.
    • Activation des flux de travail à plusieurs signatures en conservant les plages d'octets précédemment signées tout en ajoutant des champs de signature ultérieurs ou des modifications du document.

    2026-05-10 Version 2.34.0

    • Ajout de styles de bordure pour les annotations via `THPDFPage.SetAnnotationBorderStyle`, incluant les styles plein, pointillé, biseauté, encastré et souligné.
    • Ajout d'annotations popup liées. Les nouvelles popups peuvent maintenant référencer leur annotation parente, afin que les spectateurs affichent le connecteur de commentaire attendu.
    • Ajout de THPDFPage.LastAnnotation pour faciliter la mise en forme des annotations et la création de chaînes d'annotations, sans modifier les appels existants de création d'annotations.

    2026-05-10 Version 2.33.0

    • Ajout du support pour les mécanismes de sécurité par clé publique pour le chiffrement des PDF. Les documents peuvent désormais être chiffrés pour les destinataires de certificats X.509, au lieu de se limiter aux mots de passe partagés.
    • Ajout de THotPDF.EnablePubKeyEncryption et de THotPDF.AddPubKeyRecipient pour les flux de travail de chiffrement avec clé publique et destinataire.
    • Ajout du support SHA-1 en langage Pascal pur dans HPDFCrypt, en plus des fonctions de hachage existantes.

    2026-05-10 Version 2.32.0

    • Ajout de groupes de transparence au niveau de la page avec `THPDFPage.SetTransparencyGroup` et `SetTransparencyGroupICC` pour un rendu transparent du contenu PDF plus prévisible.
    • Ajout des options DeviceGray, DeviceRGB, DeviceCMYK, de l'espace colorimétrique omis et du groupe de transparence du profil ICC.
    • Ajout de `THPDFPage.ClearTransparencyGroup` pour supprimer un groupe de transparence de page précédemment assigné.

    2026-05-09 Version 2.31.0

    • Ajout d'actions interactives pour les boutons AcroForm. Avant cette version, HotPDF pouvait placer des widgets de boutons qui s'affichaient correctement mais n'avaient aucun comportement au clic. Les boutons peuvent maintenant soumettre activement un formulaire, réinitialiser les valeurs des champs, exécuter un script JavaScript ou naviguer vers une URI.
    • Les actions SubmitForm envoient les valeurs actuelles des champs du formulaire AcroForm à une URL de serveur, ce qui permet de créer des formulaires de collecte de données basés sur PDF qui fonctionnent dans Adobe Reader et Foxit sans visionneuse web distincte.
    • ResetForm réinitialise tous les champs à leurs valeurs par défaut, éventuellement en se limitant à un ensemble de champs spécifié. Les actions JavaScript et URI suivent les mêmes restrictions de version PDF introduites dans la version v2.26.0.
    • Avant cette version, la fonction `AddPushButtonWithAction` acceptait uniquement les propriétés visuelles pour le widget bouton ; désormais, à la fois l'apparence et le comportement au clic sont entièrement contrôlés dans un seul appel.

    2026-05-09 Version 2.30.0

    • Ajout de transitions de page pour les présentations PDF en plein écran avec `THPDFPage.SetPageTransition`.
    • Ajout de THPDFPage.SetPageDuration pour permettre aux pages de présentation de passer automatiquement à la page suivante après un délai spécifié.
    • Ajout d'une gestion spécifique à la version pour les styles de transition PDF 1.5 tels que Fly, Push, Cover, Uncover et Fade.

    2026-05-09 Version 2.29.0

    • Nous avons implémenté les préférences de visualisation pour les pages PDF 1.4 en ajoutant les propriétés ViewArea et ViewClip, en complément des propriétés PrintArea et PrintClip existantes.
    • ViewArea contrôle quelle zone de la page le visualiseur utilise comme zone visible à l'écran (MediaBox, CropBox, TrimBox, BleedBox ou ArtBox). ViewClip contrôle la limite de découpage à l'écran, ce qui est important pour les fichiers PDF de relecture de conception qui contiennent des marques de débordement et de coupe qui ne doivent pas apparaître dans la vue normale.
    • Ces options sont particulièrement utiles dans les flux de travail de prévisualisation et de contrôle qualité, où la zone de recadrage affichée à l'écran doit être différente de la zone de recadrage pour l'impression. Les deux options nécessitent la version 1.4 du format PDF et sont automatiquement omises lorsque la version du format PDF cible est antérieure.

    2026-05-09 Version 2.28.0

    • Ajout de la génération optionnelle de flux d'apparence pour les formulaires AcroForm avec THotPDF.AutoFormAppearances. Les champs de texte, les champs de liste, les boutons, les cases à cocher et les boutons radio peuvent désormais être affichés de manière fiable dans les lecteurs qui ignorent l'indicateur /NeedAppearances.
    • Des ressources AcroForm par défaut ont été ajoutées pour Helvetica et ZapfDingbats lorsque les apparences automatiques sont activées.
    • Le comportement précédent d'AcroForm a été conservé en maintenant la fonctionnalité AutoFormAppearances désactivée par défaut.

    2026-05-09 Version 2.27.0

    • Amélioration de la gestion des versions de PDF pour les entrées ViewerPreferences et PageMode. Chaque valeur de préférence applique désormais sa version minimale de PDF : UseAttachments et UseOC nécessitent PDF 1.5, PrintScaling nécessite PDF 1.6, et Duplex, NumCopies et PickTrayByPDFSize nécessitent PDF 1.7.
    • Les documents générés pour les versions antérieures de PDF suppriment automatiquement les entrées de préférences du visualiseur qui ne sont pas prises en charge, ce qui évite les avertissements du visualiseur ou les interprétations erronées silencieuses dans les processeurs PDF stricts et les validateurs d'archives.
    • Lorsque THotPDF.StrictVersionLock est activé, les fichiers PDF générés, qu'ils soient conformes à la version 1.3 ou 1.4, ne contiennent jamais de champs de préférences de visionneur plus récents, ce qui garantit la compatibilité pour les flux de travail de production d'impression et d'archivage à long terme.

    2026-05-09 Version 2.26.0

    • Ajout d'une vérification de la version PDF à plusieurs API plus anciennes qui autorisaient auparavant des fonctionnalités quel que soit la version du document cible. Les types d'annotations, les actions JavaScript, les polices de type 0, les CMaps ToUnicode et les actions supplémentaires du catalogue vérifient désormais que la version du document les prend en charge avant de les écrire.
    • Les documents destinés à PDF 1.0 ou PDF 1.1 sont automatiquement mis à jour vers la version requise lorsqu'une fonctionnalité plus récente est utilisée, ce qui évite la génération silencieuse de résultats non conformes aux spécifications, sans nécessiter de modifications du code par l'appelant.
    • Lorsque THotPDF.StrictVersionLock est activé, les appels de fonctionnalités qui nécessiteraient une mise à jour de version sont refusés au lieu de promouvoir silencieusement le document, ce qui permet de prendre en charge les flux de travail qui doivent produire une sortie à une version PDF exacte.
    • Cette infrastructure de vérification de version a été étendue à ViewerPreferences et PageMode dans la version v2.27.0 et couvre toutes les principales fonctionnalités d'ici la version v2.31.0.

    2026-05-09 Version 2.25.0

    • Correction de la sortie du dictionnaire PDF pour traiter les clés "Name" comme étant sensibles à la casse, conformément à la spécification PDF. Auparavant, les noms associés qui différaient uniquement par la casse, tels que "/ca" (alpha de remplissage) et "/CA" (alpha de contour) dans un dictionnaire ExtGState, étaient incorrectement fusionnés, ce qui supprimait silencieusement une valeur.
    • Cette correction restaure le rendu correct de la transparence pour les documents qui utilisent des valeurs alpha par remplissage et par trait dans le même état graphique. Adobe Acrobat, Foxit et les lecteurs PDF intégrés aux navigateurs affichent tous le résultat corrigé comme prévu.
    • Les API de requête de dictionnaire publiques restent insensibles à la casse, de sorte que le code existant qui lit des fichiers PDF mal formés avec une casse de clé incohérente continue de fonctionner sans modification.

    2026-05-09 Version 2.24.0

    • Ajout d'une fonctionnalité de contrôle de version PDF pour les API introduites depuis la version v2.4.0, ce qui permet aux fichiers générés de rester compatibles avec la version PDF sélectionnée.
    • Ajout de THotPDF.StrictVersionLock. Lorsqu'elle est désactivée, HotPDF augmente automatiquement la version du document si nécessaire ; lorsqu'elle est activée, les appels qui nécessitent des fonctionnalités PDF plus récentes sont refusés.
    • `Updated ConfigurePDFVersion` afin que les flux XRef, les métadonnées XMP, les PDF avec balises et les options AES-256 ne puissent pas être intégrés dans les versions PDF plus anciennes.

    2026-05-09 Version 2.23.0

    • Ajout d'un flux de travail de signature numérique en trois étapes pour l'intégration de THotPDF avec les bibliothèques de signature externes PKI et CMS/PKCS#7 : création du placeholder du champ de signature, calcul de la plage d'octets et du digest à signer, puis injection de la signature CMS complétée après la signature externe.
    • La stratégie de plage d'octets garantit que le hachage signé couvre exactement les parties du fichier situées en dehors du conteneur de signature, ce qui correspond aux exigences des validateurs de signature PDF et des outils de vérification de la conformité PAdES.
    • Toutes les opérations cryptographiques, telles que la chaîne de certificats, la structure CMS et les jetons de timestamp, sont déléguées à la bibliothèque de signature de l'appelant (OpenSSL, Windows CAPI, Bouncy Castle, etc.), ce qui permet à HotPDF de rester indépendant de toute infrastructure PKI.
    • Prend en charge les documents avec plusieurs signatures : chaque signature supplémentaire est ajoutée comme une mise à jour incrémentielle, préservant les plages de bytes précédemment signées sans régénérer l'intégralité du fichier PDF.

    2026-05-09 Version 2.22.0

    • Ajout du support pour le gestionnaire de sécurité standard PDF 2.0 AES-256 V=5 R=6 via THotPDF. Utilisez UseAES256R6.
    • Ajout de primitives SHA-384 et SHA-512 en Pascal natif dans HPDFCrypt.
    • Ajout de l'outil de vérification par hachage PDF 2.0 utilisé par Acrobat DC et les flux de travail de chiffrement de type PDF/A-4.

    2026-05-09 Version 2.21.0

    • Amélioration du support des PDF étiquetés, passant d'un simple marqueur à un arbre d'accessibilité structuré pour les PDF.
    • Ajout de la gestion des rôles, de l'attribution des parents de la structure des pages et de la sortie de l'arborescence parentale afin que les validateurs PDF/UA puissent parcourir l'arborescence de la structure.
    • Amélioration de la gestion de `StructTreeRoot` pour que les appels ultérieurs à la création de PDF balisés mettent à jour la même structure de document.

    2026-05-09 Version 2.20.0

    • Ajout du support pour les paramètres /UserUnit et /Tabs au niveau de la page via THPDFPage.SetUserUnit et THPDFPage.SetTabsOrder.
    • Ajout du contenu optionnel (calques PDF) avec `THotPDF.RegisterOptionalContentGroup` et `THPDFPage.BeginOptionalContent / EndOptionalContent`.
    • Ajout d'utilitaires ExtGState pour la transparence et les modes de fusion via THotPDF.RegisterExtGState et THPDFPage.SetGraphicsState.

    2026-05-09 Version 2.19.0

    • Ajout de fonctions utilitaires pour CropBox, BleedBox, TrimBox, ArtBox et la rotation des pages, afin de faciliter les flux de travail de production de fichiers PDF.
    • Ajout de THotPDF.AddStructureElement pour la création d'arborescences de structure PDF avec rôles, liens de page et références MCID.
    • Ajout du support des motifs de remplissage et de contour pour les motifs PDF colorés ou non, permettant leur répétition.

    2026-05-09 Version 2.18.0

    • Ajout de THPDFPage.DrawInlineImage pour permettre l'écriture directe de petites images raster dans le flux de contenu d'une page.
    • Ajout de dégradés axiaux multi-points pour un rendu plus uniforme des ombrages et des transitions de couleurs dans les fichiers PDF.
    • Ajout du support pour les profils de sortie pour les flux de travail PDF/A, PDF/X et la publication avec gestion des couleurs.

    2026-05-09 Version 2.17.0

    • Ajout d'un gestionnaire de sécurité standard AES-256 (extension PDF 1.7, niveau 3) pour les documents nécessitant une protection plus forte que le paramètre par défaut AES-128. Les fichiers PDF chiffrés avec AES-256 s'ouvrent dans Adobe Acrobat 9 et versions ultérieures, Foxit Reader, Google Chrome, Apple Preview et tous les lecteurs PDF modernes.
    • Les mots de passe utilisateur et propriétaire sont dérivés à l'aide du hachage SHA-256 conformément à la spécification Adobe Extension Level 3, ce qui garantit la compatibilité avec tout déchiffreur PDF conforme sans nécessiter de support personnalisé.
    • Dans cette version, le chiffrement AES-256 est une option ; le chemin AES-128 existant reste la valeur par défaut pour une compatibilité ascendante plus large avec les versions plus anciennes d'Acrobat.
    • Dans une version ultérieure, v2.22.0, le support de PDF 2.0 avec AES-256-R6 est ajouté, intégrant un algorithme de dérivation de clé amélioré pour une sécurité maximale, compatible avec Acrobat DC et les flux de travail PDF/A-4.

    2026-05-09 Version 2.16.0

    • Ajout de six nouveaux types de commentaires pour les cas d'utilisation liés aux médias, au juridique et à l'accessibilité : Filigrane (superpositions pour l'affichage et l'impression), Effacer (marquage de régions pour la suppression de contenu), Écran (vidéo et audio intégrés), 3D (visualiseurs de modèles U3D et PRC interactifs), Média enrichi (contenu multimédia interactif) et Pop-up (bulles de commentaires liées aux commentaires parents).
    • Les annotations de filigrane prennent en charge des affichages et des impressions distincts, de sorte que les mentions "PROJET" ou "CONFIDENTIEL" peuvent apparaître à l'écran sans être imprimées, ou inversement.
    • Les annotations masquées marquent les zones de contenu à supprimer avant la distribution du document ; le flux de travail de masquage du visualiseur applique la suppression finale, tout en conservant le contenu original jusqu'à ce qu'il soit validé.
    • Tous les six types d'annotations incluent une vérification de la version PDF, de sorte que les documents destinés aux anciennes versions des normes PDF omettent automatiquement les nouveaux sous-types d'annotations et restent conformes aux spécifications.

    2026-05-09 Version 2.15.0

    • Ajout du support des polices de type 3 pour intégrer directement des définitions de glyphes vectoriels personnalisés dans la sortie PDF. Les polices de type 3 sont particulièrement adaptées aux logos d'entreprise, aux ensembles de symboles propriétaires, aux icônes de cartes et à toute notation graphique qui ne peut être exprimée à l'aide de polices standard.
    • Chaque glyphe est défini comme un flux de contenu PDF en utilisant des opérateurs de dessin standard, de sorte que les glyphes de type 3 se redimensionnent parfaitement à tous les niveaux de zoom et à toutes les résolutions d'impression sans nécessiter un fichier de police externe.
    • L'ensemble du processus, notamment l'enregistrement d'une police, la définition des glyphes individuels et la sélection de la police sur une page, est géré par les fonctions RegisterType3Font, AddType3Glyph et SetType3Font.
    • Les polices de type 3 sont rendues correctement par Adobe Reader, Foxit et tous les lecteurs PDF conformes aux spécifications, sans nécessiter l'installation de la police sur le système du lecteur.

    2026-05-09 Version 2.14.0

    • Des implémentations AES-256 et SHA-256 en Pascal pur ont été ajoutées en tant que primitives cryptographiques internes pour une protection documentaire plus robuste. Ces algorithmes sont requis par les normes de chiffrement PDF 1.7 Extension Level 3 et PDF 2.0.
    • Le nouveau code cryptographique ne nécessite ni DLL externes ni bibliothèques cryptographiques fournies par le système d'exploitation, ce qui permet à HotPDF de rester autonome sur toutes les plateformes Delphi et C++Builder prises en charge, ainsi que sur toutes les versions de Windows.
    • AES-128 reste le format de chiffrement par défaut des documents dans cette version ; les nouvelles fonctionnalités sous-tendent le gestionnaire de sécurité AES-256 ajouté dans la version v2.17.0 et le gestionnaire PDF 2.0 dans la version v2.22.0.

    2026-05-09 Version 2.13.0

    • Ajout de remplissages de dégradés axiaux (linéaires) et radiaux pour le dessin vectoriel PDF. Les dégradés vectoriels produisent des fichiers PDF nettement plus petits que les équivalents rasterisés et restent nets à n'importe quel niveau de zoom ou résolution d'impression.
    • Les deux types de dégradés prennent en charge les espaces colorimétriques DeviceGray, DeviceRGB et DeviceCMYK, couvrant ainsi l'affichage à l'écran, l'impression en RGB et les flux de travail de production en CMYK quadri.
    • Les dégradés peuvent être appliqués comme remplissages ou contours sur n'importe quel chemin de page et sont correctement rendus par Adobe Reader, Foxit, SumatraPDF et tous les lecteurs PDF modernes.

    2026-05-09 Version 2.12.0

    • Ajout de champs de signature non signés avec `THPDFPage.AddSignatureField`. Le fichier PDF généré contient un espace réservé visuel pour la signature, que les flux de travail PKI externes, les portails de signature et les bibliothèques de signature CMS/PKCS#7 peuvent remplir avec une signature cryptographique réelle.
    • Les indicateurs de signature AcroForm sont définis automatiquement chaque fois qu'au moins un champ de signature est présent, ce qui garantit la conformité du document aux spécifications sans nécessiter d'appels d'API supplémentaires.
    • Les champs de signature sont reconnus comme pouvant être signés par Adobe Acrobat, Foxit et d'autres solutions de signature PDF. Consultez la version v2.23.0 pour connaître l'ensemble du flux de travail de signature par plage d'octets.

    2026-05-09 Version 2.11.0

    • Ajout de l'infrastructure de PDF balisés nécessaire pour la conformité PDF/UA et les normes modernes d'accessibilité. Les documents balisés comportent un ordre de lecture logique et une structure sémantique que les lecteurs d'écran, les technologies d'assistance et les outils d'extraction de texte peuvent suivre.
    • THotPDF.EnableTaggedPDF active la structure arborescente du document ; THotPDF.Lang définit la langue principale du document. Les deux sont requis pour les validateurs de conformité en matière d'accessibilité.
    • Les opérateurs de contenu marqué permettent d'associer des rôles sémantiques (paragraphe, titre, figure, etc.) et des identifiants aux opérations de dessin individuelles sur la page, ce qui permet une refonte correcte et une extraction correcte par les lecteurs d'écran à partir des fichiers PDF générés.
    • Les éléments de structure et les identificateurs de contenu marqué sont suivis par page et par document, conformément à la spécification PDF pour les documents multi-pages étiquetés.

    2026-05-09 Version 2.10.0

    • Ajout du support pour les prédicteurs PNG et les prédicteurs de différentiation horizontale TIFF pour les flux d'images FlateDecode. Les prédicteurs appliquent un filtrage adaptatif par ligne avant la compression, ce qui réduit considérablement la taille du fichier pour les images photographiques et les dégradés.
    • Le prédicteur PNG optimal (mode de ligne adaptatif) et le prédicteur TIFF 2 (différenciation horizontale) sont disponibles en tant qu'assistants d'encodage autonomes pour les pipelines personnalisés d'intégration d'images.
    • Les deux modules prennent en charge les données d'image DeviceGray, DeviceRGB et DeviceCMYK, ce qui couvre les flux de travail d'affichage à l'écran et d'impression en quatre couleurs.

    2026-05-09 Version 2.9.0

    • Ajout d'un flux de métadonnées XMP en plus du dictionnaire d'informations de document traditionnel. XMP est la norme moderne pour les métadonnées intégrées aux PDF et est requise pour PDF/A, PDF/X et de nombreux flux de travail d'archivage.
    • Les métadonnées intégrées XMP sont lues par les moteurs de recherche de bureau, les systèmes de gestion des actifs numériques et les pipelines de traitement des PDF qui ne consultent plus l'ancien dictionnaire Info.
    • Les flux XMP sont laissés non compressés dans le fichier de sortie afin que les outils externes et les utilitaires en ligne de commande puissent inspecter les métadonnées sans décoder le fichier.
    • Les applications qui nécessitent un contenu de métadonnées précis peuvent fournir un paquet XMP UTF-8 entièrement personnalisé via THotPDF.CustomXMP, contournant ainsi la construction automatique.
    • Lorsque le chiffrement du document est activé, le flux XMP est chiffré par défaut avec le reste du document, ce qui permet de protéger les métadonnées.

    2026-05-09 Version 2.8.0

    • Ajout d'un flux de références croisées PDF 1.5 optionnel. Les flux de références croisées encodent la table des décalages des objets dans un format binaire compact au lieu de la grande section de texte utilisée par les tables xref traditionnelles, ce qui réduit la taille du fichier pour chaque document.
    • Les flux de références croisées sont nécessaires pour les fonctionnalités PDF 1.5, telles que les flux d'objets (introduits dans la version v2.41.0), et sont automatiquement désactivés lorsque le document cible une version de PDF inférieure à 1.5.
    • Les fichiers PDF générés avec des flux de références croisées sont traités de manière plus efficace par les lecteurs modernes, les outils d'archivage et les validateurs PDF/A.
    • La table xref de texte traditionnelle reste la valeur par défaut, ce qui garantit la compatibilité avec les lecteurs PDF anciens et les processeurs stricts.

    2026-05-09 Version 2.7.0

    • Ajout du support natif pour la couleur DeviceCMYK pour les flux de travail d'impression et PDF/X.
    • Ajout de l'enregistrement des espaces colorimétriques ICC avec `THotPDF.RegisterICCProfile`.
    • Ajout d'API génériques pour les espaces colorimétriques de remplissage et de contour, prenant en charge les profils ICC et les valeurs de couleurs arbitraires.

    2026-05-09 Version 2.6.0

    • Ajout des annotations de mise en évidence, de soulignement, de traits ondulés et de barrage.
    • Ajout des annotations Polygone, Polyline, Ink et Caret.
    • Ajout des actions de lien GoTo, GoToR et Launch pour la navigation à l'intérieur du document, entre documents et vers des fichiers externes.

    2026-05-09 Version 2.5.0

    • Ajout du support pour les formulaires AcroForm, notamment pour les champs de texte, les cases à cocher, les boutons radio, les zones de liste déroulante, les listes et les boutons-poussoir.
    • Ajout de THPDFFormFieldFlags pour permettre aux applications de configurer les options courantes des champs de formulaire sans manipulation manuelle des bits.
    • Les formulaires générés définissent maintenant l'attribut "/NeedAppearances" afin que les lecteurs PDF courants puissent afficher automatiquement les champs.

    2026-05-08 Version 2.4.0

    • Correction du chiffrement AES-128 pour les fichiers PDF. Les chaînes de caractères et les flux de données sont désormais réellement chiffrés avec AES-CBC pour une sécurité V=4 / R=4.
    • CryptKeyLength=aes128 crée désormais des fichiers PDF chiffrés que les lecteurs compatibles peuvent ouvrir avec le mot de passe utilisateur ou propriétaire configuré.
    • Ajout des fonctions utilitaires d'encodage ASCIIHexDecode, ASCII85Decode et RunLengthDecode.
    • Les bibliothèques intégrées JBIG2 et JPEG 2000 ont été mises à jour pour signaler de manière transparente les problèmes de décodage, au lieu de renvoyer des données d'image factices.

    2026-05-06 Version 2.3.23

    • Optimisation des constructions groupées de zlib-ng, libjpeg-turbo et libtiff pour les chaînes d'outils RAD Studio et Visual Studio actuelles.
    • Amélioration de l'alignement de la mémoire pour la compression native et les bibliothèques d'images sur les plateformes Delphi et C++Builder.
    • Les suites de tests de régression automatisées pour Delphi et C++Builder ont été validées sur les plateformes Win32, Win64 et Win64x.

    2026-05-05 Version 2.3.22

    • Activé la prise en charge SIMD de zlib-ng dans les versions compressées Flate 64 bits intégrées.
    • Win32 zlib-ng a été conservé sur le chemin d'objet générique stable pour assurer la compatibilité avec l'ancien ensemble d'outils.
    • Les constructions natives optimisées échouent si la compilation réussit mais qu'aucun fichier objet n'est généré.

    2026-05-05 Version 2.3.21

    • Activation de l'accélération SIMD de libjpeg-turbo dans les builds d'objets Win32, Win64 et Win64x intégrés.
    • Le support SIMD est désormais explicitement activé via un paramètre de build dans HotPDF.
    • Corrigé un problème de sortie OMF Win32 NASM qui empêchait Delphi Win32 de lier l'ensemble d'objets SIMD JPEG.
    • Corrigé un problème de régression d'image TIFF sur Win64, détecté après les reconstructions SIMD et zlib-ng.

    2026-05-05 Version 2.3.20

    • Remplacement du backend Flate intégré par zlib-ng en mode compatible avec zlib pour les flux de pages, les polices, les CMaps, les images, la sortie TIFF et les fonctions auxiliaires FlateDecode.
    • Correction des problèmes de compression de flux dense et d'importation d'images TIFF de petite taille, détectés lors de la migration vers zlib-ng.
    • Les flux de travail JPEG, basés sur libjpeg-turbo, et les flux de travail TIFF, basés sur libtiff, ont été maintenus.
    • Ajout d'une large couverture de tests de régression automatisés pour la génération de PDF dans Delphi et C++Builder, l'importation d'images, la compression, le chiffrement, les hyperliens, la configuration des pages et les flux de travail de copie/fusion/modification.

    2026-05-01 Version 2.3.19

    • Corrigé la génération du flux de page FlateDecode sur Win64 pour une sortie de code-barres dense.
    • Alignement de la compression des flux de pages et de polices Delphi modernes avec le chemin stable de la bibliothèque RTL zlib.

    2026-05-01 Version 2.3.18

    • Correction de la génération de PDF chiffrés dans C++Builder pour Win64 en corrigeant la configuration de la clé RC4, qui était basée sur la taille du pointeur.
    • Corrigé l'importation de fichiers TIFF sur les builds C++Builder pour Windows 64 bits.
    • Correction des flux de travail d'ajout de pages pour les fichiers PDF ouverts avec `LoadFromFile` afin que les pages ajoutées soient enregistrées avec des numéros d'objet sécurisés.

    2026-05-01 Version 2.3.17

    • Les démos CanvasDrawing et GraphicDraw pour C++Builder ont été mises à jour pour correspondre aux exemples de graphiques Delphi améliorés.
    • Amélioration de la démo C++Builder pour le ViewerPref, avec une interface utilisateur plus claire, une validation, une prise en charge de la sauvegarde et du chargement des paramètres prédéfinis, et une sortie dédiée pour la définition de la direction.

    2026-05-01 Version 2.3.16

    • Correction de la copie de pages pour les PDF fusionnés qui contiennent des polices CID TrueType intégrées et des tableaux de largeur imbriqués.
    • Amélioration de la correspondance des objets lors de la copie de pages à partir de plusieurs documents PDF sources, de manière séquentielle.

    2026-05-01 Version 2.3.15

    • Amélioration de la démo ViewerPref Delphi pour que les contrôles spécifiques à chaque option soient activés uniquement lorsque cela est pertinent.
    • Ajout de la gestion des erreurs de ViewerPref, de la validation du nombre de copies et du support pour la sauvegarde et le chargement de préréglages nommés.

    2026-05-01 Version 2.3.14

    • La démo PDFmerge pour Delphi a été refactorisée en un exemple autonome qui crée des fichiers PDF sources si nécessaire.
    • Améliorations de la validation de la fusion, de l'indexation des résultats et des messages d'interface utilisateur indiquant le succès ou l'échec.

    2026-05-01 Version 2.3.13

    • Les démos Delphi de CanvasDraw et GraphicDraw ont été améliorées pour produire une sortie visuelle plus claire et reproductible.
    • Amélioration de la sélection des polices TrueType dans les chemins de polices GDI, ce qui réduit les échecs lors de l'intégration causés par les polices raster de secours.
    • Correction de l'espacement des caractères lorsque la même police est utilisée dans plusieurs blocs de texte dans un seul fichier PDF.
    • Amélioration des messages d'erreur liés à l'intégration des polices, avec indication du nom de la police et de la table de caractères demandés.

    2026-05-01 Version 2.3.12

    • Amélioration de la démo CopyPage pour qu'elle puisse copier les fichiers PDF avec des structures /Pages non standard, sans nécessiter d'outil supplémentaire.
    • `CopyPage` écrit désormais une sortie compressée avec `FlateDecode`, quel que soit le chemin de copie qui réussit.
    • J'ai intégré l'exemple CopyPageFixed autonome dans la démo principale CopyPage.

    2026-05-01 Version 2.3.11

    • Les fichiers PDF générés s'ouvrent désormais avec chaque page ajustée à la hauteur de la fenêtre par défaut.
    • De nombreux noms de tailles de page prédéfinis sans préfixe ont été ajoutés pour les formats de papier bureautique, grand format, dessin, carte, pièce d'identité, photo, japonais, chinois et taïwanais, tout en conservant la compatibilité avec les noms existants préfixés par "ps".
    • Les démos de taille de page Delphi ont été refactorisées en projets LargeSize, NormalSize et SmallSize.

    2026-04-29 Version 2.3.10

    • Correction des builds de packages RAD Studio XE7 dans la couche de compatibilité TIFF.
    • Réduction des avertissements pour RAD Studio 10 Seattle et 10.1 Berlin.
    • Correction de la correspondance de la bibliothèque de construction en ligne de commande pour les versions de RAD Studio de 9.0 à 12.0.
    • Restauré les builds de packages en ligne de commande pour RAD Studio ProductVersion 9.0.
    • Correction des builds RAD Studio XE2 pour Win64 en déclarant le symbole `crt_vsprintf` requis par les stubs de compatibilité Win64.
    • Amélioration de la compatibilité avec les anciens projets, notamment en ce qui concerne les valeurs booléennes numériques dans les anciens fichiers de projet Delphi et C++Builder.

    2026-04-29 Version 2.3.9

    • Correction des builds des packages de la bibliothèque RAD Studio 10.1 Berlin en compilant les packages à partir du répertoire Lib.
    • Correction des builds de la bibliothèque Trial sur les anciennes versions de Delphi en supprimant les déclarations de variables en ligne du chemin de filigrane Trial.

    2026-04-29 Version 2.3.8

    • Supprimé un avertissement de compilateur concernant une fonction `TStream.Seek` obsolète du chemin de rappel du flux TIFF dans les versions RAD Studio 10.3 Rio.

    2026-04-29 Version 2.3.7

    • Correction de la conversion TIFF vers PDF lors de l'utilisation des fichiers d'objet libtiff 4.7.x intégrés.
    • Correction de la compilation RAD Studio Win32 du module zlib Pascal inclus, avec des paramètres de compilation plus stricts.
    • Ajout de la couverture de régression DUnitX pour la conversion TIFF vers PDF.

    2026-04-28 Version 2.3.5

    • Correction des reconstructions des packages sources pour les bibliothèques zlib, libjpeg-turbo et libtiff intégrées, en utilisant le compilateur Borland C++ Win32 classique.
    • Les fichiers d'objets tiers Win32 et Win64 ont été reconstruits et alignés pour des compilations Delphi et C++Builder plus fiables.
    • Aucune modification de l'API publique. Les projets Delphi, C++Builder et RAD Studio existants peuvent utiliser cette version comme une version de compatibilité.

    2026-04-19 Version 2.3.3

    • Amélioration de la fiabilité des projets RAD Studio en empêchant les paramètres de l'environnement INCLUDE de l'hôte d'interférer avec la compilation des ressources HotPDF.
    • Réduction des avertissements concernant les ressources en double lors de la création de packages, en particulier pour les projets RAD Studio 13.1 Florence.

    2026-04-19 Version 2.3.2

    • Les dossiers de sortie du package et du projet de démonstration suivent désormais automatiquement la version active de RAD Studio.
    • Amélioration du comportement de la construction du package HotPDF370 pour éviter que des fichiers de ressources obsolètes ne soient liés aux nouvelles ressources générées.

    2026-04-19 Version 2.3.1

    • La démo C++Builder TextOut s'exécute désormais sans modifications manuelles sur toutes les versions compatibles de RAD Studio.
    • Corrigé le comportement de reconstruction Win64x pour la démo TextOut afin que le fichier de ressources requis soit inclus avant la liaison.

    2026-04-19 Version 2.3.0

    • Ajout du support complet pour C++Builder 13.1 Florence pour les plateformes Win32, Win64 et Win64x.
    • Standardisation de la disponibilité de la surcharge de `TextOut` pour Delphi et C++Builder, tout en conservant la compatibilité avec les anciens noms de fonctions utilitaires C++Builder.
    • Nettoyé le chaînage statique Delphi Win64 en supprimant les avertissements de l'éditeur de liens précédents provenant des fichiers d'objet intégrés de zlib, libjpeg-turbo et libtiff.
    • Amélioration du package Win64x pour que les projets C++Builder puissent trouver la bibliothèque HotPDF générée via les chemins de recherche RAD Studio standard.

    2026-04-17 Version 2.2.1

    • Supprimés les avertissements du lieur Delphi Win32 provenant des bibliothèques de compression et de traitement d'images tierces incluses.
    • Amélioration de la compatibilité avec les liens statiques pour les bibliothèques zlib, JPEG et TIFF dans les versions Delphi et C++Builder.

    2026-04-14 Version 2.2.0

    • Les bibliothèques tierces intégrées ont été mises à jour vers les versions suivantes : zlib 1.3.2, libjpeg-turbo 3.1.90 et libtiff 4.7.1.
    • Modernisation des liaisons statiques Win32 et Win64 pour les bibliothèques de compression, JPEG et TIFF mises à jour.
    • Amélioration de la compatibilité des formats d'image pour les scénarios de génération de PDF qui utilisent JPEG ou TIFF en entrée.
    • Mise à jour de l'aide HTML pour qu'elle corresponde à l'API actuelle de HotPDF, aux exemples et à la structure de la bibliothèque.

    2026-04-13 Version 2.1.4

    • Corrigé la compilation Win64 pour RAD Studio XE2 à XE8.
    • Amélioration de la compatibilité des fichiers d'objets regroupés utilisés par les anciens compilateurs Delphi.
    • Supprimés les anciens fichiers de ressources de package qui pouvaient déclencher des avertissements du linker concernant les ressources en double.
    • Correction des métadonnées du projet Delphi XE3 pour le package HotPDF.

    2026-04-12 Version 2.1.3

    • J'ai étendu la démo Delphi TestNumeric pour la transformer en un test de régression pratique pour la sortie numérique PDF.
    • Ajout d'une validation plus large pour les nombres décimaux, les fractions, les entiers et du comportement de rechargement des fichiers PDF.
    • Les fichiers de sortie de débogage sont désormais facultatifs et activés via une option spécifique au moment de la compilation.
    • Mise à jour du contenu d'aide pour la journalisation de débogage et les tests de sortie numérique.

    2026-04-10 Version 2.1.2

    • Amélioration du rendu des polices intégrées dans les fichiers PDF générés pour Win32 et Win64.
    • Correction du rendu incomplet des glyphes lors du passage entre les polices intégrées, y compris les polices Windows courantes telles que Calibri.
    • La démo FontTest a été mise à jour et des fichiers PDF d'exemple ont été générés pour faciliter la vérification visuelle.
    • Mises à jour des pages d'aide HTML concernant l'intégration des polices, la sortie de texte Unicode et les exemples de polices intégrées.

    2026-04-08 Version 2.1.1

    • Mises à jour des exemples ViewerPreferences pour Delphi et C++Builder afin de les aligner avec l'API actuelle de HotPDF.
    • Ajout de la prise en charge pour les nouvelles options de préférences des lecteurs PDF.
    • Amélioration de la sortie de démonstration générée afin qu'elle reflète uniquement les paramètres de préférence du visualiseur sélectionnés dans l'interface utilisateur.
    • Mises à jour des pages d'aide HTML pour ViewerPreferences et les propriétés de document associées.